116255Skarels #ifndef lint 2*33624Sbostic static char *sccsid = "@(#)arp.c 5.5 (Berkeley) 03/01/88"; 316255Skarels #endif 416255Skarels 516255Skarels /* 616255Skarels * arp - display, set, and delete arp table entries 716255Skarels */ 816255Skarels 9*33624Sbostic #include <machine/pte.h> 10*33624Sbostic 11*33624Sbostic #include <sys/param.h> 12*33624Sbostic #include <sys/vmmac.h> 13*33624Sbostic #include <sys/file.h> 1416255Skarels #include <sys/socket.h> 1516255Skarels #include <sys/ioctl.h> 16*33624Sbostic 1716255Skarels #include <netdb.h> 18*33624Sbostic #include <netinet/in.h> 1916255Skarels #include <net/if.h> 2016255Skarels #include <netinet/if_ether.h> 2116255Skarels 22*33624Sbostic #include <errno.h> 23*33624Sbostic #include <nlist.h> 24*33624Sbostic #include <stdio.h> 25*33624Sbostic 2616255Skarels extern int errno; 27*33624Sbostic static int kflag; 2816255Skarels 2916255Skarels main(argc, argv) 30*33624Sbostic int argc; 3116255Skarels char **argv; 3216255Skarels { 33*33624Sbostic int ch; 3416255Skarels 35*33624Sbostic while ((ch = getopt(argc, argv, "adsf")) != EOF) 36*33624Sbostic switch((char)ch) { 37*33624Sbostic case 'a': { 38*33624Sbostic char *mem; 39*33624Sbostic 40*33624Sbostic if (argc > 4) 41*33624Sbostic usage(); 42*33624Sbostic if (argc == 4) { 43*33624Sbostic kflag = 1; 44*33624Sbostic mem = argv[3]; 45*33624Sbostic } 46*33624Sbostic else 47*33624Sbostic mem = "/dev/kmem"; 48*33624Sbostic dump((argc >= 3) ? argv[2] : "/vmunix", mem); 49*33624Sbostic exit(0); 50*33624Sbostic } 51*33624Sbostic case 'd': 52*33624Sbostic if (argc != 3) 53*33624Sbostic usage(); 54*33624Sbostic delete(argv[2]); 55*33624Sbostic exit(0); 56*33624Sbostic case 's': 57*33624Sbostic if (argc < 4 || argc > 7) 58*33624Sbostic usage(); 59*33624Sbostic exit(set(argc-2, &argv[2]) ? 1 : 0); 60*33624Sbostic case 'f': 61*33624Sbostic if (argc != 3) 62*33624Sbostic usage(); 63*33624Sbostic exit (file(argv[2]) ? 1 : 0); 64*33624Sbostic case '?': 65*33624Sbostic default: 66*33624Sbostic usage(); 67*33624Sbostic } 68*33624Sbostic if (argc != 2) 69*33624Sbostic usage(); 70*33624Sbostic get(argv[1]); 71*33624Sbostic exit(0); 7216255Skarels } 7316255Skarels 7416255Skarels /* 7516255Skarels * Process a file to set standard arp entries 7616255Skarels */ 7716255Skarels file(name) 7816255Skarels char *name; 7916255Skarels { 8016255Skarels FILE *fp; 81*33624Sbostic int i, retval; 8225788Skarels char line[100], arg[5][50], *args[5]; 8316255Skarels 8416255Skarels if ((fp = fopen(name, "r")) == NULL) { 8516255Skarels fprintf(stderr, "arp: cannot open %s\n", name); 8616255Skarels exit(1); 8716255Skarels } 8816255Skarels args[0] = &arg[0][0]; 8916255Skarels args[1] = &arg[1][0]; 9016255Skarels args[2] = &arg[2][0]; 9116255Skarels args[3] = &arg[3][0]; 9225788Skarels args[4] = &arg[4][0]; 9332643Smckusick retval = 0; 9416255Skarels while(fgets(line, 100, fp) != NULL) { 9532643Smckusick i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], 9632643Smckusick arg[3], arg[4]); 9716255Skarels if (i < 2) { 9816255Skarels fprintf(stderr, "arp: bad line: %s\n", line); 9932643Smckusick retval = 1; 10016255Skarels continue; 10116255Skarels } 10232643Smckusick if (set(i, args)) 10332643Smckusick retval = 1; 10416255Skarels } 10516255Skarels fclose(fp); 10632643Smckusick return (retval); 10716255Skarels } 10816255Skarels 10916255Skarels /* 11016255Skarels * Set an individual arp entry 11116255Skarels */ 11216255Skarels set(argc, argv) 113*33624Sbostic int argc; 11416255Skarels char **argv; 11516255Skarels { 11616255Skarels struct arpreq ar; 11716255Skarels struct hostent *hp; 11816255Skarels struct sockaddr_in *sin; 11921393Skarels u_char *ea; 12016255Skarels int s; 12116255Skarels char *host = argv[0], *eaddr = argv[1]; 12216255Skarels 12316255Skarels argc -= 2; 12416255Skarels argv += 2; 12516255Skarels bzero((caddr_t)&ar, sizeof ar); 12616255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 12726314Skarels sin->sin_family = AF_INET; 12826314Skarels sin->sin_addr.s_addr = inet_addr(host); 12926314Skarels if (sin->sin_addr.s_addr == -1) { 13026314Skarels hp = gethostbyname(host); 13126314Skarels if (hp == NULL) { 13226314Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 13332643Smckusick return (1); 13426314Skarels } 13526314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 13626314Skarels sizeof sin->sin_addr); 13726314Skarels } 13821393Skarels ea = (u_char *)ar.arp_ha.sa_data; 13916255Skarels if (ether_aton(eaddr, ea)) 14032643Smckusick return (1); 14116255Skarels ar.arp_flags = ATF_PERM; 14226314Skarels while (argc-- > 0) { 14316255Skarels if (strncmp(argv[0], "temp", 4) == 0) 14416255Skarels ar.arp_flags &= ~ATF_PERM; 145*33624Sbostic else if (strncmp(argv[0], "pub", 3) == 0) 14616255Skarels ar.arp_flags |= ATF_PUBL; 147*33624Sbostic else if (strncmp(argv[0], "trail", 5) == 0) 14825788Skarels ar.arp_flags |= ATF_USETRAILERS; 14916255Skarels argv++; 15016255Skarels } 15116255Skarels 15216255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 15316255Skarels if (s < 0) { 154*33624Sbostic perror("arp: socket"); 155*33624Sbostic exit(1); 156*33624Sbostic } 15716255Skarels if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 15816255Skarels perror(host); 15916255Skarels exit(1); 16016255Skarels } 16116255Skarels close(s); 16232643Smckusick return (0); 16316255Skarels } 16416255Skarels 16516255Skarels /* 16616255Skarels * Display an individual arp entry 16716255Skarels */ 16816255Skarels get(host) 16916255Skarels char *host; 17016255Skarels { 17116255Skarels struct arpreq ar; 17216255Skarels struct hostent *hp; 17316255Skarels struct sockaddr_in *sin; 17421393Skarels u_char *ea; 17516255Skarels int s; 176*33624Sbostic char *inet_ntoa(); 17716255Skarels 17816255Skarels bzero((caddr_t)&ar, sizeof ar); 17916255Skarels ar.arp_pa.sa_family = AF_INET; 18016255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 18126314Skarels sin->sin_family = AF_INET; 18226314Skarels sin->sin_addr.s_addr = inet_addr(host); 18326314Skarels if (sin->sin_addr.s_addr == -1) { 18426314Skarels hp = gethostbyname(host); 18526314Skarels if (hp == NULL) { 18626314Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 18726314Skarels exit(1); 18826314Skarels } 18926314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 19026314Skarels sizeof sin->sin_addr); 19126314Skarels } 19216255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 19316255Skarels if (s < 0) { 194*33624Sbostic perror("arp: socket"); 195*33624Sbostic exit(1); 196*33624Sbostic } 19716255Skarels if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 19816255Skarels if (errno == ENXIO) 19916255Skarels printf("%s (%s) -- no entry\n", 20016255Skarels host, inet_ntoa(sin->sin_addr)); 20116255Skarels else 20216255Skarels perror("SIOCGARP"); 20316255Skarels exit(1); 20416255Skarels } 20516255Skarels close(s); 20621393Skarels ea = (u_char *)ar.arp_ha.sa_data; 20716255Skarels printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 20816255Skarels if (ar.arp_flags & ATF_COM) 20916255Skarels ether_print(ea); 21016255Skarels else 21116255Skarels printf("(incomplete)"); 212*33624Sbostic if (ar.arp_flags & ATF_PERM) 213*33624Sbostic printf(" permanent"); 214*33624Sbostic if (ar.arp_flags & ATF_PUBL) 215*33624Sbostic printf(" published"); 216*33624Sbostic if (ar.arp_flags & ATF_USETRAILERS) 217*33624Sbostic printf(" trailers"); 21816255Skarels printf("\n"); 21916255Skarels } 22016255Skarels 22116255Skarels /* 22216255Skarels * Delete an arp entry 22316255Skarels */ 22416255Skarels delete(host) 22516255Skarels char *host; 22616255Skarels { 22716255Skarels struct arpreq ar; 22816255Skarels struct hostent *hp; 22916255Skarels struct sockaddr_in *sin; 23016255Skarels int s; 23116255Skarels 23216255Skarels bzero((caddr_t)&ar, sizeof ar); 23316255Skarels ar.arp_pa.sa_family = AF_INET; 23416255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 23526314Skarels sin->sin_family = AF_INET; 23626314Skarels sin->sin_addr.s_addr = inet_addr(host); 23726314Skarels if (sin->sin_addr.s_addr == -1) { 23826314Skarels hp = gethostbyname(host); 23926314Skarels if (hp == NULL) { 24026314Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 24126314Skarels exit(1); 24226314Skarels } 24326314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 24426314Skarels sizeof sin->sin_addr); 24526314Skarels } 24616255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 24716255Skarels if (s < 0) { 248*33624Sbostic perror("arp: socket"); 249*33624Sbostic exit(1); 250*33624Sbostic } 25116255Skarels if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 25216255Skarels if (errno == ENXIO) 25316255Skarels printf("%s (%s) -- no entry\n", 25416255Skarels host, inet_ntoa(sin->sin_addr)); 25516255Skarels else 25616255Skarels perror("SIOCDARP"); 25716255Skarels exit(1); 25816255Skarels } 25916255Skarels close(s); 26016255Skarels printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 26116255Skarels } 26216255Skarels 26316255Skarels struct nlist nl[] = { 26416255Skarels #define X_ARPTAB 0 26516255Skarels { "_arptab" }, 26616255Skarels #define X_ARPTAB_SIZE 1 26716255Skarels { "_arptab_size" }, 268*33624Sbostic #define N_SYSMAP 2 269*33624Sbostic { "_Sysmap" }, 270*33624Sbostic #define N_SYSSIZE 3 271*33624Sbostic { "_Syssize" }, 27216255Skarels { "" }, 27316255Skarels }; 27416255Skarels 275*33624Sbostic static struct pte *Sysmap; 276*33624Sbostic 27716255Skarels /* 27816255Skarels * Dump the entire arp table 27916255Skarels */ 28016255Skarels dump(kernel, mem) 28116255Skarels char *kernel, *mem; 28216255Skarels { 283*33624Sbostic extern int h_errno; 28416255Skarels struct arptab *at; 28516255Skarels struct hostent *hp; 286*33624Sbostic int bynumber, mf, arptab_size, sz; 287*33624Sbostic char *host, *malloc(); 288*33624Sbostic off_t lseek(); 28916255Skarels 290*33624Sbostic if (nlist(kernel, nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) { 29116255Skarels fprintf(stderr, "arp: %s: bad namelist\n", kernel); 29216255Skarels exit(1); 29316255Skarels } 294*33624Sbostic mf = open(mem, O_RDONLY); 295*33624Sbostic if (mf < 0) { 29616255Skarels fprintf(fprintf, "arp: cannot open %s\n", mem); 29716255Skarels exit(1); 29816255Skarels } 299*33624Sbostic if (kflag) { 300*33624Sbostic off_t off; 301*33624Sbostic 302*33624Sbostic Sysmap = (struct pte *) 303*33624Sbostic malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 304*33624Sbostic if (!Sysmap) { 305*33624Sbostic fputs("arp: can't get memory for Sysmap.\n", stderr); 306*33624Sbostic exit(1); 307*33624Sbostic } 308*33624Sbostic off = nl[N_SYSMAP].n_value & ~KERNBASE; 309*33624Sbostic (void)lseek(mf, off, L_SET); 310*33624Sbostic (void)read(mf, (char *)Sysmap, 311*33624Sbostic (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 312*33624Sbostic } 313*33624Sbostic klseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, L_SET); 31416255Skarels read(mf, &arptab_size, sizeof arptab_size); 315*33624Sbostic if (arptab_size <= 0 || arptab_size > 1000) { 31616255Skarels fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 31716255Skarels exit(1); 31816255Skarels } 31916255Skarels sz = arptab_size * sizeof (struct arptab); 320*33624Sbostic at = (struct arptab *)malloc((u_int)sz); 32116255Skarels if (at == NULL) { 322*33624Sbostic fputs("arp: can't get memory for arptab.\n", stderr); 32316255Skarels exit(1); 32416255Skarels } 325*33624Sbostic klseek(mf, (long)nl[X_ARPTAB].n_value, L_SET); 32616255Skarels if (read(mf, (char *)at, sz) != sz) { 32716255Skarels perror("arp: error reading arptab"); 32816255Skarels exit(1); 32916255Skarels } 33016255Skarels close(mf); 331*33624Sbostic for (bynumber = 0; arptab_size-- > 0; at++) { 33216255Skarels if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 33316255Skarels continue; 33426314Skarels if (bynumber == 0) 33526314Skarels hp = gethostbyaddr((caddr_t)&at->at_iaddr, 33626314Skarels sizeof at->at_iaddr, AF_INET); 33726314Skarels else 33826314Skarels hp = 0; 33916255Skarels if (hp) 34016255Skarels host = hp->h_name; 34126314Skarels else { 34216255Skarels host = "?"; 34326314Skarels if (h_errno == TRY_AGAIN) 34426314Skarels bynumber = 1; 34526314Skarels } 34616255Skarels printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 34716255Skarels if (at->at_flags & ATF_COM) 34821393Skarels ether_print(at->at_enaddr); 34916255Skarels else 35016255Skarels printf("(incomplete)"); 351*33624Sbostic if (at->at_flags & ATF_PERM) 352*33624Sbostic printf(" permanent"); 353*33624Sbostic if (at->at_flags & ATF_PUBL) 354*33624Sbostic printf(" published"); 355*33624Sbostic if (at->at_flags & ATF_USETRAILERS) 356*33624Sbostic printf(" trailers"); 35716255Skarels printf("\n"); 35816255Skarels } 35916255Skarels } 36016255Skarels 361*33624Sbostic /* 362*33624Sbostic * Seek into the kernel for a value. 363*33624Sbostic */ 364*33624Sbostic klseek(fd, base, off) 365*33624Sbostic int fd, off; 366*33624Sbostic off_t base; 367*33624Sbostic { 368*33624Sbostic off_t lseek(); 369*33624Sbostic 370*33624Sbostic if (kflag) { /* get kernel pte */ 371*33624Sbostic base &= ~KERNBASE; 372*33624Sbostic base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); 373*33624Sbostic } 374*33624Sbostic (void)lseek(fd, base, off); 375*33624Sbostic } 376*33624Sbostic 37721393Skarels ether_print(cp) 37821393Skarels u_char *cp; 37916255Skarels { 38016255Skarels printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 38116255Skarels } 38216255Skarels 38316255Skarels ether_aton(a, n) 38416255Skarels char *a; 38521393Skarels u_char *n; 38616255Skarels { 38716255Skarels int i, o[6]; 38816255Skarels 38916255Skarels i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 39016255Skarels &o[3], &o[4], &o[5]); 39116255Skarels if (i != 6) { 39216255Skarels fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 39316255Skarels return (1); 39416255Skarels } 39516255Skarels for (i=0; i<6; i++) 39621393Skarels n[i] = o[i]; 39716255Skarels return (0); 39816255Skarels } 39916255Skarels 40016255Skarels usage() 40116255Skarels { 402*33624Sbostic printf("usage: arp hostname\n"); 40316255Skarels printf(" arp -a [/vmunix] [/dev/kmem]\n"); 40416255Skarels printf(" arp -d hostname\n"); 40532643Smckusick printf(" arp -s hostname ether_addr [temp] [pub] [trail]\n"); 40616255Skarels printf(" arp -f filename\n"); 407*33624Sbostic exit(1); 40816255Skarels } 409