📄 arpd.c
字号:
/* * arpd.c -- * * A program to reply to ARP and RARP requests. This program * only translates between Internet and Ethernet addresses. See * RFC826 for details of the ARP protocol, and RFC903 for details * of the RARP protocol. * * Copyright 1989 Regents of the University of California * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <net/if_arp.h>#include <netinet/in.h>#include <sys/file.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/time.h>#include <net/if.h>#include <netinet/if_ether.h>#include <bstring.h>int arpverbose = 0;extern u_long proxyaddr;/* * The ARP/RARP packet size is defined below. Because of structure * alignment differences between machines, it isn't safe to use * sizeof with the structure. */#define ARP_PACKET_SIZE 42static int FindArpReply(unsigned long dstipaddr, u_char* etherdst);extern unsigned long FindGateway(unsigned long);struct ether_addr { unsigned char ether_addr_octet[6];};extern struct ether_addr *ether_aton(char *s);/* *---------------------------------------------------------------------- * * ArpRequest -- * * Handle an ARP request. * * Results: * None. * * Side effects: * A response is transmitted for the ARP request. * *---------------------------------------------------------------------- */intArpRequest(void *pin, int pinlen, void *pout, int *poutlen){ struct { struct ether_header hdr; struct ether_arp arp; } packet; int bytesRead, etherType, protocolType, hardwareType, arpOp; unsigned long senderAddr, targetAddr; u_char eaddr[6]; /* * Read and validate the ARP packet. */ bytesRead = (sizeof(packet) > pinlen) ? pinlen : sizeof(packet); bcopy(pin, &packet, bytesRead); if (bytesRead < 0) { printf("arpd couldn't read ARP packet: %d\n", errno); return 0; } if (bytesRead < ARP_PACKET_SIZE) { if (arpverbose) printf("arpd got short ARP packet: only %d bytes\n", bytesRead); return 0; } etherType = ntohs(packet.hdr.ether_type); if (etherType != ETHERTYPE_ARP) { if (arpverbose) printf("arpd got ARP packet with ether_type 0x%x\n", etherType); return 0; } arpOp = ntohs(packet.arp.ea_hdr.ar_op); if (arpOp != ARPOP_REQUEST) { if (arpverbose) { printf("arpd got ARP packet with unknown op %d\n", arpOp); } return 0; } hardwareType = ntohs(packet.arp.ea_hdr.ar_hrd); if (hardwareType != ARPHRD_ETHER) { if (arpverbose) { printf("arpd got ARP packet with unknown hardware type 0x%x\n", hardwareType); } return 0; } protocolType = ntohs(packet.arp.ea_hdr.ar_pro); if (protocolType != ETHERTYPE_IP) { if (arpverbose) { printf("arpd got ARP packet with unknown protocol type 0x%x\n", protocolType); } return 0; } bcopy((void *) packet.arp.arp_spa, (void *) &senderAddr, sizeof(senderAddr)); bcopy((void *) packet.arp.arp_tpa, (void *) &targetAddr, sizeof(targetAddr)); if(arpverbose) { printf("ARP request: address 0x%x\n", targetAddr); }#ifdef SIM_PROXY if(targetAddr == senderAddr) return(0);#endif if(!FindArpReply(targetAddr, eaddr)) return 0; if(arpverbose) { char *c; c = eaddr; printf("ARP request: address 0x%x, hardware %x:%x:%x:%x:%x:%x\n", targetAddr, c[0],c[1],c[2],c[3],c[4],c[5]); } /* * Reverse sender and target fields, and respond with the appropriate * Ethernet address. No need to fill in the source in the packet * header: the kernel automatically overwrites it. */ bcopy((void *) &targetAddr, (void *) packet.arp.arp_spa, sizeof(targetAddr)); bcopy((void *) &senderAddr, (void *) packet.arp.arp_tpa, sizeof(senderAddr)); bcopy((void *) &packet.arp.arp_sha, (void *) &packet.arp.arp_tha, 6); bcopy((void *) &eaddr, (void *) &packet.arp.arp_sha, 6); packet.arp.ea_hdr.ar_op = htons(ARPOP_REPLY); bcopy((void *) &packet.hdr.ether_shost, (void *) &packet.hdr.ether_dhost, 6); bcopy((void *) &packet, pout, ARP_PACKET_SIZE); (*poutlen) = ARP_PACKET_SIZE; return 1;}static intFindArpReply(unsigned long dstipaddr, u_char *etherdst){ FILE *pfd; unsigned int gateway; int found; gateway = FindGateway(dstipaddr); if (gateway == (unsigned int ) -1) { return 0; }#ifdef sparc pfd = popen("/etc/arp -a", "r");#endif#ifdef sgi pfd = popen("/usr/etc/arp -a", "r");#endif if (pfd == (FILE *) NULL) { return 0; } found = 0; while(1) { unsigned int ip1,ip2,ip3,ip4,e1,e2,e3,e4,e5,e6; struct in_addr *ia = (struct in_addr *) &gateway; int n; char name[256], eaddrstring[32]; n = fscanf(pfd, "%s (%d.%d.%d.%d) at %s\n", name, &ip1,&ip2,&ip3,&ip4, eaddrstring); if (n < 0) break; if (n != 6) continue;#ifdef sparc if ( (ip1 == ia->S_un.S_un_b.s_b1) && (ip2 == ia->S_un.S_un_b.s_b2) && (ip3 == ia->S_un.S_un_b.s_b3) && (ip4 == ia->S_un.S_un_b.s_b4) ) { u_char *e = ether_aton(eaddrstring); if (e != NULL) { *etherdst = *e; found = 1; } break; }#endif /* sparc */#ifdef sgi if ( ((( ip1*256+ip2)*256+ip3)*256+ip4) == ia->s_addr){ struct ether_addr *e = ether_aton(eaddrstring); if (e != NULL) { bcopy((void *)e, etherdst, 6); found = 1; printf("arp -a found: %s\n",eaddrstring); } break; } #endif /* sgi */ } pclose(pfd); return found;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -