📄 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. */#ifndef lintstatic char rcsid[] = "$Header: /hive/cvsroot/simulation/apps/unix/ethersim/sun/arpd.c,v 1.3 1997/02/03 20:24:17 verghese Exp $ SPRITE (Berkeley)";#endif not lint#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>int arpverbose = 0;/* * 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, struct ether_addr *etherdst);extern unsigned long FindGateway(unsigned long);/* *---------------------------------------------------------------------- * * ArpRequest -- * * Handle an ARP request. * * Results: * None. * * Side effects: * A response is transmitted for the ARP request. * *---------------------------------------------------------------------- */intArpRequest(pin, pinlen, pout, poutlen) 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; struct ether_addr eaddr; /* * 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((char *) packet.arp.arp_spa, (char *) &senderAddr, sizeof(senderAddr)); bcopy((char *) packet.arp.arp_tpa, (char *) &targetAddr, sizeof(targetAddr)); if(!FindArpReply(targetAddr, &eaddr)) { /* * If we do not find the address in the arp cache, * do a ping of the address using a "system" call * This way we will find it the next time, maybe */ char buf[128]; struct in_addr *in = (struct in_addr *)&targetAddr; strcpy(buf, "/usr/etc/ping "); strcat(buf, inet_ntoa(*in)); strcat(buf, " &"); if (arpverbose) printf("%#x not in arp cache, doing %s\n", targetAddr, buf); system(buf); return 0; } /* * 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((char *) &targetAddr, (char *) packet.arp.arp_spa, sizeof(targetAddr)); bcopy((char *) &senderAddr, (char *) packet.arp.arp_tpa, sizeof(senderAddr)); bcopy((char *) &packet.arp.arp_sha, (char *) &packet.arp.arp_tha, sizeof(struct ether_addr)); bcopy((char *) &eaddr, (char *) &packet.arp.arp_sha, sizeof(struct ether_addr)); packet.arp.ea_hdr.ar_op = htons(ARPOP_REPLY); bcopy((char *) &packet.hdr.ether_shost, (char *) &packet.hdr.ether_dhost, sizeof(struct ether_addr)); bcopy((char *) &packet, pout, ARP_PACKET_SIZE); (*poutlen) = ARP_PACKET_SIZE; return 1;}static intFindArpReply(dstipaddr, etherdst) unsigned long dstipaddr; struct ether_addr *etherdst;{ FILE *pfd; unsigned int gateway; int found; gateway = FindGateway(dstipaddr); if (gateway == (unsigned int ) -1) { return 0; } pfd = popen("/usr/etc/arp -a", "r"); 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]; char line[1024]; extern int verbose; if (fgets(line, sizeof(line), pfd) == 0) break; if (verbose) { fprintf(stderr, "arp request result: %s", line); } n = sscanf(line, "%s (%d.%d.%d.%d) at %s\n", name, &ip1,&ip2,&ip3,&ip4, eaddrstring); if (verbose) { fprintf(stderr, "n=%d name=%s\n", n, name); } if (n < 0) break; if (n != 6) continue; 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)) { struct ether_addr *e = ether_aton(eaddrstring); if (verbose) {#define A(x) (e->ether_addr_octet[x]) fprintf(stderr, "ARP entry found %s %d.%d.%d.%d %s %x:%x:%x:%x:%x:%x\n", name, ip1, ip2, ip3, ip4, eaddrstring, A(1), A(2), A(3), A(4), A(5), A(6)); } if (e != NULL) { *etherdst = *e; found = 1; } break; } } pclose(pfd); return found;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -