116255Skarels #ifndef lint 2*26314Skarels static char *sccsid = "@(#)arp.c 5.2 (Berkeley) 02/21/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; 6325788Skarels 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]; 7325788Skarels args[4] = &arg[4][0]; 7416255Skarels while(fgets(line, 100, fp) != NULL) { 7525788Skarels i = sscanf(line, "%s %s %s %s", arg[0], arg[1], arg[2], arg[3], 7625788Skarels 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 bzero((caddr_t)&ar, sizeof ar); 10216255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 103*26314Skarels sin->sin_family = AF_INET; 104*26314Skarels sin->sin_addr.s_addr = inet_addr(host); 105*26314Skarels if (sin->sin_addr.s_addr == -1) { 106*26314Skarels hp = gethostbyname(host); 107*26314Skarels if (hp == NULL) { 108*26314Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 109*26314Skarels return; 110*26314Skarels } 111*26314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 112*26314Skarels sizeof sin->sin_addr); 113*26314Skarels } 11421393Skarels ea = (u_char *)ar.arp_ha.sa_data; 11516255Skarels if (ether_aton(eaddr, ea)) 11616255Skarels return; 11716255Skarels ar.arp_flags = ATF_PERM; 118*26314Skarels while (argc-- > 0) { 11916255Skarels if (strncmp(argv[0], "temp", 4) == 0) 12016255Skarels ar.arp_flags &= ~ATF_PERM; 12116255Skarels if (strncmp(argv[0], "pub", 3) == 0) 12216255Skarels ar.arp_flags |= ATF_PUBL; 12325788Skarels if (strncmp(argv[0], "trail", 5) == 0) 12425788Skarels ar.arp_flags |= ATF_USETRAILERS; 12516255Skarels argv++; 12616255Skarels } 12716255Skarels 12816255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 12916255Skarels if (s < 0) { 13016255Skarels perror("arp: socket"); 13116255Skarels exit(1); 13216255Skarels } 13316255Skarels if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 13416255Skarels perror(host); 13516255Skarels exit(1); 13616255Skarels } 13716255Skarels close(s); 13816255Skarels } 13916255Skarels 14016255Skarels 14116255Skarels /* 14216255Skarels * Display an individual arp entry 14316255Skarels */ 14416255Skarels get(host) 14516255Skarels char *host; 14616255Skarels { 14716255Skarels struct arpreq ar; 14816255Skarels struct hostent *hp; 14916255Skarels struct sockaddr_in *sin; 15021393Skarels u_char *ea; 15116255Skarels int s; 15216255Skarels 15316255Skarels bzero((caddr_t)&ar, sizeof ar); 15416255Skarels ar.arp_pa.sa_family = AF_INET; 15516255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 156*26314Skarels sin->sin_family = AF_INET; 157*26314Skarels sin->sin_addr.s_addr = inet_addr(host); 158*26314Skarels if (sin->sin_addr.s_addr == -1) { 159*26314Skarels hp = gethostbyname(host); 160*26314Skarels if (hp == NULL) { 161*26314Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 162*26314Skarels exit(1); 163*26314Skarels } 164*26314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 165*26314Skarels sizeof sin->sin_addr); 166*26314Skarels } 16716255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 16816255Skarels if (s < 0) { 16916255Skarels perror("arp: socket"); 17016255Skarels exit(1); 17116255Skarels } 17216255Skarels if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 17316255Skarels if (errno == ENXIO) 17416255Skarels printf("%s (%s) -- no entry\n", 17516255Skarels host, inet_ntoa(sin->sin_addr)); 17616255Skarels else 17716255Skarels perror("SIOCGARP"); 17816255Skarels exit(1); 17916255Skarels } 18016255Skarels close(s); 18121393Skarels ea = (u_char *)ar.arp_ha.sa_data; 18216255Skarels printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 18316255Skarels if (ar.arp_flags & ATF_COM) 18416255Skarels ether_print(ea); 18516255Skarels else 18616255Skarels printf("(incomplete)"); 18725788Skarels if (ar.arp_flags & ATF_PERM) printf(" permanent"); 18816255Skarels if (ar.arp_flags & ATF_PUBL) printf(" published"); 18925788Skarels if (ar.arp_flags & ATF_USETRAILERS) printf(" trailers"); 19016255Skarels printf("\n"); 19116255Skarels } 19216255Skarels 19316255Skarels /* 19416255Skarels * Delete an arp entry 19516255Skarels */ 19616255Skarels delete(host) 19716255Skarels char *host; 19816255Skarels { 19916255Skarels struct arpreq ar; 20016255Skarels struct hostent *hp; 20116255Skarels struct sockaddr_in *sin; 20216255Skarels int s; 20316255Skarels 20416255Skarels bzero((caddr_t)&ar, sizeof ar); 20516255Skarels ar.arp_pa.sa_family = AF_INET; 20616255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 207*26314Skarels sin->sin_family = AF_INET; 208*26314Skarels sin->sin_addr.s_addr = inet_addr(host); 209*26314Skarels if (sin->sin_addr.s_addr == -1) { 210*26314Skarels hp = gethostbyname(host); 211*26314Skarels if (hp == NULL) { 212*26314Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 213*26314Skarels exit(1); 214*26314Skarels } 215*26314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 216*26314Skarels sizeof sin->sin_addr); 217*26314Skarels } 21816255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 21916255Skarels if (s < 0) { 22016255Skarels perror("arp: socket"); 22116255Skarels exit(1); 22216255Skarels } 22316255Skarels if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 22416255Skarels if (errno == ENXIO) 22516255Skarels printf("%s (%s) -- no entry\n", 22616255Skarels host, inet_ntoa(sin->sin_addr)); 22716255Skarels else 22816255Skarels perror("SIOCDARP"); 22916255Skarels exit(1); 23016255Skarels } 23116255Skarels close(s); 23216255Skarels printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 23316255Skarels } 23416255Skarels 23516255Skarels struct nlist nl[] = { 23616255Skarels #define X_ARPTAB 0 23716255Skarels { "_arptab" }, 23816255Skarels #define X_ARPTAB_SIZE 1 23916255Skarels { "_arptab_size" }, 24016255Skarels { "" }, 24116255Skarels }; 24216255Skarels 24316255Skarels /* 24416255Skarels * Dump the entire arp table 24516255Skarels */ 24616255Skarels dump(kernel, mem) 24716255Skarels char *kernel, *mem; 24816255Skarels { 24916255Skarels int mf, arptab_size, sz; 25016255Skarels struct arptab *at; 25116255Skarels struct hostent *hp; 25216255Skarels char *host; 253*26314Skarels int bynumber = 0; 25416255Skarels 25516255Skarels nlist(kernel, nl); 25616255Skarels if(nl[X_ARPTAB_SIZE].n_type == 0) { 25716255Skarels fprintf(stderr, "arp: %s: bad namelist\n", kernel); 25816255Skarels exit(1); 25916255Skarels } 26016255Skarels mf = open(mem, 0); 26116255Skarels if(mf < 0) { 26216255Skarels fprintf(fprintf, "arp: cannot open %s\n", mem); 26316255Skarels exit(1); 26416255Skarels } 26516255Skarels lseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, 0); 26616255Skarels read(mf, &arptab_size, sizeof arptab_size); 26716255Skarels if (arptab_size <=0 || arptab_size > 1000) { 26816255Skarels fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 26916255Skarels exit(1); 27016255Skarels } 27116255Skarels sz = arptab_size * sizeof (struct arptab); 27216255Skarels at = (struct arptab *)malloc(sz); 27316255Skarels if (at == NULL) { 27416255Skarels fprintf(stderr, "arp: can't get memory for arptab\n"); 27516255Skarels exit(1); 27616255Skarels } 27716255Skarels lseek(mf, (long)nl[X_ARPTAB].n_value, 0); 27816255Skarels if (read(mf, (char *)at, sz) != sz) { 27916255Skarels perror("arp: error reading arptab"); 28016255Skarels exit(1); 28116255Skarels } 28216255Skarels close(mf); 28316255Skarels for (; arptab_size-- > 0; at++) { 28416255Skarels if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 28516255Skarels continue; 286*26314Skarels if (bynumber == 0) 287*26314Skarels hp = gethostbyaddr((caddr_t)&at->at_iaddr, 288*26314Skarels sizeof at->at_iaddr, AF_INET); 289*26314Skarels else 290*26314Skarels hp = 0; 29116255Skarels if (hp) 29216255Skarels host = hp->h_name; 293*26314Skarels else { 29416255Skarels host = "?"; 295*26314Skarels if (h_errno == TRY_AGAIN) 296*26314Skarels bynumber = 1; 297*26314Skarels } 29816255Skarels printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 29916255Skarels if (at->at_flags & ATF_COM) 30021393Skarels ether_print(at->at_enaddr); 30116255Skarels else 30216255Skarels printf("(incomplete)"); 30325788Skarels if (at->at_flags & ATF_PERM) printf(" permanent"); 30416255Skarels if (at->at_flags & ATF_PUBL) printf(" published"); 30525788Skarels if (at->at_flags & ATF_USETRAILERS) printf(" trailers"); 30616255Skarels printf("\n"); 30716255Skarels } 30816255Skarels } 30916255Skarels 31021393Skarels ether_print(cp) 31121393Skarels u_char *cp; 31216255Skarels { 31316255Skarels printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 31416255Skarels } 31516255Skarels 31616255Skarels ether_aton(a, n) 31716255Skarels char *a; 31821393Skarels u_char *n; 31916255Skarels { 32016255Skarels int i, o[6]; 32116255Skarels 32216255Skarels i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 32316255Skarels &o[3], &o[4], &o[5]); 32416255Skarels if (i != 6) { 32516255Skarels fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 32616255Skarels return (1); 32716255Skarels } 32816255Skarels for (i=0; i<6; i++) 32921393Skarels n[i] = o[i]; 33016255Skarels return (0); 33116255Skarels } 33216255Skarels 33316255Skarels usage() 33416255Skarels { 33516255Skarels printf("Usage: arp hostname\n"); 33616255Skarels printf(" arp -a [/vmunix] [/dev/kmem]\n"); 33716255Skarels printf(" arp -d hostname\n"); 33816255Skarels printf(" arp -s hostname ether_addr [temp] [pub]\n"); 33916255Skarels printf(" arp -f filename\n"); 34016255Skarels } 341