116255Skarels #ifndef lint 2*25788Skarels static char *sccsid = "@(#)arp.c 1.4 (Berkeley) 01/09/86"; 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; 63*25788Skarels char line[100], arg[5][50], *args[5]; 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]; 73*25788Skarels args[4] = &arg[4][0]; 7416255Skarels while(fgets(line, 100, fp) != NULL) { 75*25788Skarels i = sscanf(line, "%s %s %s %s", arg[0], arg[1], arg[2], arg[3], 76*25788Skarels arg[4]); 7716255Skarels if (i < 2) { 7816255Skarels fprintf(stderr, "arp: bad line: %s\n", line); 7916255Skarels continue; 8016255Skarels } 8116255Skarels set(i, args); 8216255Skarels } 8316255Skarels fclose(fp); 8416255Skarels } 8516255Skarels 8616255Skarels /* 8716255Skarels * Set an individual arp entry 8816255Skarels */ 8916255Skarels set(argc, argv) 9016255Skarels char **argv; 9116255Skarels { 9216255Skarels struct arpreq ar; 9316255Skarels struct hostent *hp; 9416255Skarels struct sockaddr_in *sin; 9521393Skarels u_char *ea; 9616255Skarels int s; 9716255Skarels char *host = argv[0], *eaddr = argv[1]; 9816255Skarels 9916255Skarels argc -= 2; 10016255Skarels argv += 2; 10116255Skarels hp = gethostbyname(host); 10216255Skarels if (hp == NULL) { 10316255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 10425122Sbloom return; 10516255Skarels } 10616255Skarels bzero((caddr_t)&ar, sizeof ar); 10716255Skarels ar.arp_pa.sa_family = AF_INET; 10816255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 10925122Sbloom bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, sizeof sin->sin_addr); 11021393Skarels ea = (u_char *)ar.arp_ha.sa_data; 11116255Skarels if (ether_aton(eaddr, ea)) 11216255Skarels return; 11316255Skarels ar.arp_flags = ATF_PERM; 11416255Skarels while(argc-- > 0) { 11516255Skarels if (strncmp(argv[0], "temp", 4) == 0) 11616255Skarels ar.arp_flags &= ~ATF_PERM; 11716255Skarels if (strncmp(argv[0], "pub", 3) == 0) 11816255Skarels ar.arp_flags |= ATF_PUBL; 119*25788Skarels if (strncmp(argv[0], "trail", 5) == 0) 120*25788Skarels ar.arp_flags |= ATF_USETRAILERS; 12116255Skarels argv++; 12216255Skarels } 12316255Skarels 12416255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 12516255Skarels if (s < 0) { 12616255Skarels perror("arp: socket"); 12716255Skarels exit(1); 12816255Skarels } 12916255Skarels if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 13016255Skarels perror(host); 13116255Skarels exit(1); 13216255Skarels } 13316255Skarels close(s); 13416255Skarels } 13516255Skarels 13616255Skarels 13716255Skarels /* 13816255Skarels * Display an individual arp entry 13916255Skarels */ 14016255Skarels get(host) 14116255Skarels char *host; 14216255Skarels { 14316255Skarels struct arpreq ar; 14416255Skarels struct hostent *hp; 14516255Skarels struct sockaddr_in *sin; 14621393Skarels u_char *ea; 14716255Skarels int s; 14816255Skarels 14916255Skarels hp = gethostbyname(host); 15016255Skarels if (hp == NULL) { 15116255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 15216255Skarels exit(1); 15316255Skarels } 15416255Skarels bzero((caddr_t)&ar, sizeof ar); 15516255Skarels ar.arp_pa.sa_family = AF_INET; 15616255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 15716255Skarels sin->sin_addr = *(struct in_addr *)hp->h_addr; 15816255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 15916255Skarels if (s < 0) { 16016255Skarels perror("arp: socket"); 16116255Skarels exit(1); 16216255Skarels } 16316255Skarels if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 16416255Skarels if (errno == ENXIO) 16516255Skarels printf("%s (%s) -- no entry\n", 16616255Skarels host, inet_ntoa(sin->sin_addr)); 16716255Skarels else 16816255Skarels perror("SIOCGARP"); 16916255Skarels exit(1); 17016255Skarels } 17116255Skarels close(s); 17221393Skarels ea = (u_char *)ar.arp_ha.sa_data; 17316255Skarels printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 17416255Skarels if (ar.arp_flags & ATF_COM) 17516255Skarels ether_print(ea); 17616255Skarels else 17716255Skarels printf("(incomplete)"); 178*25788Skarels if (ar.arp_flags & ATF_PERM) printf(" permanent"); 17916255Skarels if (ar.arp_flags & ATF_PUBL) printf(" published"); 180*25788Skarels if (ar.arp_flags & ATF_USETRAILERS) printf(" trailers"); 18116255Skarels printf("\n"); 18216255Skarels } 18316255Skarels 18416255Skarels /* 18516255Skarels * Delete an arp entry 18616255Skarels */ 18716255Skarels delete(host) 18816255Skarels char *host; 18916255Skarels { 19016255Skarels struct arpreq ar; 19116255Skarels struct hostent *hp; 19216255Skarels struct sockaddr_in *sin; 19316255Skarels int s; 19416255Skarels 19516255Skarels hp = gethostbyname(host); 19616255Skarels if (hp == NULL) { 19716255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 19816255Skarels exit(1); 19916255Skarels } 20016255Skarels bzero((caddr_t)&ar, sizeof ar); 20116255Skarels ar.arp_pa.sa_family = AF_INET; 20216255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 20325122Sbloom bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, sizeof sin->sin_addr); 20416255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 20516255Skarels if (s < 0) { 20616255Skarels perror("arp: socket"); 20716255Skarels exit(1); 20816255Skarels } 20916255Skarels if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 21016255Skarels if (errno == ENXIO) 21116255Skarels printf("%s (%s) -- no entry\n", 21216255Skarels host, inet_ntoa(sin->sin_addr)); 21316255Skarels else 21416255Skarels perror("SIOCDARP"); 21516255Skarels exit(1); 21616255Skarels } 21716255Skarels close(s); 21816255Skarels printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 21916255Skarels } 22016255Skarels 22116255Skarels struct nlist nl[] = { 22216255Skarels #define X_ARPTAB 0 22316255Skarels { "_arptab" }, 22416255Skarels #define X_ARPTAB_SIZE 1 22516255Skarels { "_arptab_size" }, 22616255Skarels { "" }, 22716255Skarels }; 22816255Skarels 22916255Skarels /* 23016255Skarels * Dump the entire arp table 23116255Skarels */ 23216255Skarels dump(kernel, mem) 23316255Skarels char *kernel, *mem; 23416255Skarels { 23516255Skarels int mf, arptab_size, sz; 23616255Skarels struct arptab *at; 23716255Skarels struct hostent *hp; 23816255Skarels char *host; 23916255Skarels 24016255Skarels nlist(kernel, nl); 24116255Skarels if(nl[X_ARPTAB_SIZE].n_type == 0) { 24216255Skarels fprintf(stderr, "arp: %s: bad namelist\n", kernel); 24316255Skarels exit(1); 24416255Skarels } 24516255Skarels mf = open(mem, 0); 24616255Skarels if(mf < 0) { 24716255Skarels fprintf(fprintf, "arp: cannot open %s\n", mem); 24816255Skarels exit(1); 24916255Skarels } 25016255Skarels lseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, 0); 25116255Skarels read(mf, &arptab_size, sizeof arptab_size); 25216255Skarels if (arptab_size <=0 || arptab_size > 1000) { 25316255Skarels fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 25416255Skarels exit(1); 25516255Skarels } 25616255Skarels sz = arptab_size * sizeof (struct arptab); 25716255Skarels at = (struct arptab *)malloc(sz); 25816255Skarels if (at == NULL) { 25916255Skarels fprintf(stderr, "arp: can't get memory for arptab\n"); 26016255Skarels exit(1); 26116255Skarels } 26216255Skarels lseek(mf, (long)nl[X_ARPTAB].n_value, 0); 26316255Skarels if (read(mf, (char *)at, sz) != sz) { 26416255Skarels perror("arp: error reading arptab"); 26516255Skarels exit(1); 26616255Skarels } 26716255Skarels close(mf); 26816255Skarels for (; arptab_size-- > 0; at++) { 26916255Skarels if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 27016255Skarels continue; 27116255Skarels hp = gethostbyaddr((caddr_t)&at->at_iaddr, sizeof at->at_iaddr, 27216255Skarels AF_INET); 27316255Skarels if (hp) 27416255Skarels host = hp->h_name; 27516255Skarels else 27616255Skarels host = "?"; 27716255Skarels printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 27816255Skarels if (at->at_flags & ATF_COM) 27921393Skarels ether_print(at->at_enaddr); 28016255Skarels else 28116255Skarels printf("(incomplete)"); 282*25788Skarels if (at->at_flags & ATF_PERM) printf(" permanent"); 28316255Skarels if (at->at_flags & ATF_PUBL) printf(" published"); 284*25788Skarels if (at->at_flags & ATF_USETRAILERS) printf(" trailers"); 28516255Skarels printf("\n"); 28616255Skarels } 28716255Skarels } 28816255Skarels 28921393Skarels ether_print(cp) 29021393Skarels u_char *cp; 29116255Skarels { 29216255Skarels printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 29316255Skarels } 29416255Skarels 29516255Skarels ether_aton(a, n) 29616255Skarels char *a; 29721393Skarels u_char *n; 29816255Skarels { 29916255Skarels int i, o[6]; 30016255Skarels 30116255Skarels i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 30216255Skarels &o[3], &o[4], &o[5]); 30316255Skarels if (i != 6) { 30416255Skarels fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 30516255Skarels return (1); 30616255Skarels } 30716255Skarels for (i=0; i<6; i++) 30821393Skarels n[i] = o[i]; 30916255Skarels return (0); 31016255Skarels } 31116255Skarels 31216255Skarels usage() 31316255Skarels { 31416255Skarels printf("Usage: arp hostname\n"); 31516255Skarels printf(" arp -a [/vmunix] [/dev/kmem]\n"); 31616255Skarels printf(" arp -d hostname\n"); 31716255Skarels printf(" arp -s hostname ether_addr [temp] [pub]\n"); 31816255Skarels printf(" arp -f filename\n"); 31916255Skarels } 320