116255Skarels #ifndef lint 2*21393Skarels static char *sccsid = "@(#)arp.c 1.2 (Berkeley) 05/30/85"; 316255Skarels #endif 416255Skarels 516255Skarels /* 616255Skarels * arp - display, set, and delete arp table entries 716255Skarels */ 816255Skarels 916255Skarels #include <stdio.h> 1016255Skarels #include <sys/types.h> 1116255Skarels #include <sys/socket.h> 1216255Skarels #include <netinet/in.h> 1316255Skarels #include <sys/ioctl.h> 1416255Skarels #include <errno.h> 1516255Skarels #include <netdb.h> 1616255Skarels #include <nlist.h> 1716255Skarels #include <net/if.h> 1816255Skarels #include <netinet/if_ether.h> 1916255Skarels 2016255Skarels extern int errno; 2116255Skarels 2216255Skarels main(argc, argv) 2316255Skarels char **argv; 2416255Skarels { 2516255Skarels if (argc >= 2 && strcmp(argv[1], "-a") == 0) { 2616255Skarels char *kernel = "/vmunix", *mem = "/dev/kmem"; 2716255Skarels 2816255Skarels if (argc >= 3) 2916255Skarels kernel = argv[2]; 3016255Skarels if (argc >= 4) 3116255Skarels mem = argv[3]; 3216255Skarels dump(kernel, mem); 3316255Skarels exit(0); 3416255Skarels } 3516255Skarels if (argc == 2) { 3616255Skarels get(argv[1]); 3716255Skarels exit(0); 3816255Skarels } 3916255Skarels if (argc >= 4 && strcmp(argv[1], "-s") == 0) { 4016255Skarels set(argc-2, &argv[2]); 4116255Skarels exit(0); 4216255Skarels } 4316255Skarels if (argc == 3 && strcmp(argv[1], "-d") == 0) { 4416255Skarels delete(argv[2]); 4516255Skarels exit(0); 4616255Skarels } 4716255Skarels if (argc == 3 && strcmp(argv[1], "-f") == 0) { 4816255Skarels file(argv[2]); 4916255Skarels exit(0); 5016255Skarels } 5116255Skarels usage(); 5216255Skarels exit(1); 5316255Skarels } 5416255Skarels 5516255Skarels /* 5616255Skarels * Process a file to set standard arp entries 5716255Skarels */ 5816255Skarels file(name) 5916255Skarels char *name; 6016255Skarels { 6116255Skarels FILE *fp; 6216255Skarels int i; 6316255Skarels char line[100], arg[4][50], *args[4]; 6416255Skarels 6516255Skarels if ((fp = fopen(name, "r")) == NULL) { 6616255Skarels fprintf(stderr, "arp: cannot open %s\n", name); 6716255Skarels exit(1); 6816255Skarels } 6916255Skarels args[0] = &arg[0][0]; 7016255Skarels args[1] = &arg[1][0]; 7116255Skarels args[2] = &arg[2][0]; 7216255Skarels args[3] = &arg[3][0]; 7316255Skarels while(fgets(line, 100, fp) != NULL) { 7416255Skarels i = sscanf(line, "%s %s %s %s", arg[0], arg[1], arg[2], arg[3]); 7516255Skarels if (i < 2) { 7616255Skarels fprintf(stderr, "arp: bad line: %s\n", line); 7716255Skarels continue; 7816255Skarels } 7916255Skarels set(i, args); 8016255Skarels } 8116255Skarels fclose(fp); 8216255Skarels } 8316255Skarels 8416255Skarels /* 8516255Skarels * Set an individual arp entry 8616255Skarels */ 8716255Skarels set(argc, argv) 8816255Skarels char **argv; 8916255Skarels { 9016255Skarels struct arpreq ar; 9116255Skarels struct hostent *hp; 9216255Skarels struct sockaddr_in *sin; 93*21393Skarels u_char *ea; 9416255Skarels int s; 9516255Skarels char *host = argv[0], *eaddr = argv[1]; 9616255Skarels 9716255Skarels argc -= 2; 9816255Skarels argv += 2; 9916255Skarels hp = gethostbyname(host); 10016255Skarels if (hp == NULL) { 10116255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 10216255Skarels return (1); 10316255Skarels } 10416255Skarels bzero((caddr_t)&ar, sizeof ar); 10516255Skarels ar.arp_pa.sa_family = AF_INET; 10616255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 10716255Skarels sin->sin_addr = *(struct in_addr *)hp->h_addr; 108*21393Skarels ea = (u_char *)ar.arp_ha.sa_data; 10916255Skarels if (ether_aton(eaddr, ea)) 11016255Skarels return; 11116255Skarels ar.arp_flags = ATF_PERM; 11216255Skarels while(argc-- > 0) { 11316255Skarels if (strncmp(argv[0], "temp", 4) == 0) 11416255Skarels ar.arp_flags &= ~ATF_PERM; 11516255Skarels if (strncmp(argv[0], "pub", 3) == 0) 11616255Skarels ar.arp_flags |= ATF_PUBL; 11716255Skarels argv++; 11816255Skarels } 11916255Skarels 12016255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 12116255Skarels if (s < 0) { 12216255Skarels perror("arp: socket"); 12316255Skarels exit(1); 12416255Skarels } 12516255Skarels if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 12616255Skarels perror(host); 12716255Skarels exit(1); 12816255Skarels } 12916255Skarels close(s); 13016255Skarels } 13116255Skarels 13216255Skarels 13316255Skarels /* 13416255Skarels * Display an individual arp entry 13516255Skarels */ 13616255Skarels get(host) 13716255Skarels char *host; 13816255Skarels { 13916255Skarels struct arpreq ar; 14016255Skarels struct hostent *hp; 14116255Skarels struct sockaddr_in *sin; 142*21393Skarels u_char *ea; 14316255Skarels int s; 14416255Skarels 14516255Skarels hp = gethostbyname(host); 14616255Skarels if (hp == NULL) { 14716255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 14816255Skarels exit(1); 14916255Skarels } 15016255Skarels bzero((caddr_t)&ar, sizeof ar); 15116255Skarels ar.arp_pa.sa_family = AF_INET; 15216255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 15316255Skarels sin->sin_addr = *(struct in_addr *)hp->h_addr; 15416255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 15516255Skarels if (s < 0) { 15616255Skarels perror("arp: socket"); 15716255Skarels exit(1); 15816255Skarels } 15916255Skarels if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 16016255Skarels if (errno == ENXIO) 16116255Skarels printf("%s (%s) -- no entry\n", 16216255Skarels host, inet_ntoa(sin->sin_addr)); 16316255Skarels else 16416255Skarels perror("SIOCGARP"); 16516255Skarels exit(1); 16616255Skarels } 16716255Skarels close(s); 168*21393Skarels ea = (u_char *)ar.arp_ha.sa_data; 16916255Skarels printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 17016255Skarels if (ar.arp_flags & ATF_COM) 17116255Skarels ether_print(ea); 17216255Skarels else 17316255Skarels printf("(incomplete)"); 17416255Skarels if (!(ar.arp_flags & ATF_PERM)) printf(" temporary"); 17516255Skarels if (ar.arp_flags & ATF_PUBL) printf(" published"); 17616255Skarels printf("\n"); 17716255Skarels } 17816255Skarels 17916255Skarels /* 18016255Skarels * Delete an arp entry 18116255Skarels */ 18216255Skarels delete(host) 18316255Skarels char *host; 18416255Skarels { 18516255Skarels struct arpreq ar; 18616255Skarels struct hostent *hp; 18716255Skarels struct sockaddr_in *sin; 18816255Skarels int s; 18916255Skarels 19016255Skarels hp = gethostbyname(host); 19116255Skarels if (hp == NULL) { 19216255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 19316255Skarels exit(1); 19416255Skarels } 19516255Skarels bzero((caddr_t)&ar, sizeof ar); 19616255Skarels ar.arp_pa.sa_family = AF_INET; 19716255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 19816255Skarels sin->sin_addr = *(struct in_addr *)hp->h_addr; 19916255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 20016255Skarels if (s < 0) { 20116255Skarels perror("arp: socket"); 20216255Skarels exit(1); 20316255Skarels } 20416255Skarels if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 20516255Skarels if (errno == ENXIO) 20616255Skarels printf("%s (%s) -- no entry\n", 20716255Skarels host, inet_ntoa(sin->sin_addr)); 20816255Skarels else 20916255Skarels perror("SIOCDARP"); 21016255Skarels exit(1); 21116255Skarels } 21216255Skarels close(s); 21316255Skarels printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 21416255Skarels } 21516255Skarels 21616255Skarels struct nlist nl[] = { 21716255Skarels #define X_ARPTAB 0 21816255Skarels { "_arptab" }, 21916255Skarels #define X_ARPTAB_SIZE 1 22016255Skarels { "_arptab_size" }, 22116255Skarels { "" }, 22216255Skarels }; 22316255Skarels 22416255Skarels /* 22516255Skarels * Dump the entire arp table 22616255Skarels */ 22716255Skarels dump(kernel, mem) 22816255Skarels char *kernel, *mem; 22916255Skarels { 23016255Skarels int mf, arptab_size, sz; 23116255Skarels struct arptab *at; 23216255Skarels struct hostent *hp; 23316255Skarels char *host; 23416255Skarels 23516255Skarels nlist(kernel, nl); 23616255Skarels if(nl[X_ARPTAB_SIZE].n_type == 0) { 23716255Skarels fprintf(stderr, "arp: %s: bad namelist\n", kernel); 23816255Skarels exit(1); 23916255Skarels } 24016255Skarels mf = open(mem, 0); 24116255Skarels if(mf < 0) { 24216255Skarels fprintf(fprintf, "arp: cannot open %s\n", mem); 24316255Skarels exit(1); 24416255Skarels } 24516255Skarels lseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, 0); 24616255Skarels read(mf, &arptab_size, sizeof arptab_size); 24716255Skarels if (arptab_size <=0 || arptab_size > 1000) { 24816255Skarels fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 24916255Skarels exit(1); 25016255Skarels } 25116255Skarels sz = arptab_size * sizeof (struct arptab); 25216255Skarels at = (struct arptab *)malloc(sz); 25316255Skarels if (at == NULL) { 25416255Skarels fprintf(stderr, "arp: can't get memory for arptab\n"); 25516255Skarels exit(1); 25616255Skarels } 25716255Skarels lseek(mf, (long)nl[X_ARPTAB].n_value, 0); 25816255Skarels if (read(mf, (char *)at, sz) != sz) { 25916255Skarels perror("arp: error reading arptab"); 26016255Skarels exit(1); 26116255Skarels } 26216255Skarels close(mf); 26316255Skarels for (; arptab_size-- > 0; at++) { 26416255Skarels if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 26516255Skarels continue; 26616255Skarels hp = gethostbyaddr((caddr_t)&at->at_iaddr, sizeof at->at_iaddr, 26716255Skarels AF_INET); 26816255Skarels if (hp) 26916255Skarels host = hp->h_name; 27016255Skarels else 27116255Skarels host = "?"; 27216255Skarels printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 27316255Skarels if (at->at_flags & ATF_COM) 274*21393Skarels ether_print(at->at_enaddr); 27516255Skarels else 27616255Skarels printf("(incomplete)"); 27716255Skarels if (!(at->at_flags & ATF_PERM)) printf(" temporary"); 27816255Skarels if (at->at_flags & ATF_PUBL) printf(" published"); 27916255Skarels printf("\n"); 28016255Skarels } 28116255Skarels } 28216255Skarels 283*21393Skarels ether_print(cp) 284*21393Skarels u_char *cp; 28516255Skarels { 28616255Skarels printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 28716255Skarels } 28816255Skarels 28916255Skarels ether_aton(a, n) 29016255Skarels char *a; 291*21393Skarels u_char *n; 29216255Skarels { 29316255Skarels int i, o[6]; 29416255Skarels 29516255Skarels i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 29616255Skarels &o[3], &o[4], &o[5]); 29716255Skarels if (i != 6) { 29816255Skarels fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 29916255Skarels return (1); 30016255Skarels } 30116255Skarels for (i=0; i<6; i++) 302*21393Skarels n[i] = o[i]; 30316255Skarels return (0); 30416255Skarels } 30516255Skarels 30616255Skarels usage() 30716255Skarels { 30816255Skarels printf("Usage: arp hostname\n"); 30916255Skarels printf(" arp -a [/vmunix] [/dev/kmem]\n"); 31016255Skarels printf(" arp -d hostname\n"); 31116255Skarels printf(" arp -s hostname ether_addr [temp] [pub]\n"); 31216255Skarels printf(" arp -f filename\n"); 31316255Skarels } 314