134918Sbostic /* 234918Sbostic * Copyright (c) 1984 Regents of the University of California. 334918Sbostic * All rights reserved. 434918Sbostic * 534918Sbostic * This code is derived from software contributed to Berkeley by 634918Sbostic * Sun Microsystems, Inc. 734918Sbostic * 8*42791Sbostic * %sccs.include.redist.c% 934918Sbostic */ 1034918Sbostic 1116255Skarels #ifndef lint 1234918Sbostic char copyright[] = 1334918Sbostic "@(#) Copyright (c) 1984 Regents of the University of California.\n\ 1434918Sbostic All rights reserved.\n"; 1534918Sbostic #endif /* not lint */ 1616255Skarels 1734918Sbostic #ifndef lint 18*42791Sbostic static char sccsid[] = "@(#)arp.c 5.11 (Berkeley) 06/01/90"; 1934918Sbostic #endif /* not lint */ 2034918Sbostic 2116255Skarels /* 2216255Skarels * arp - display, set, and delete arp table entries 2316255Skarels */ 2416255Skarels 2533624Sbostic #include <machine/pte.h> 2633624Sbostic 2733624Sbostic #include <sys/param.h> 2833624Sbostic #include <sys/vmmac.h> 2933624Sbostic #include <sys/file.h> 3016255Skarels #include <sys/socket.h> 3116255Skarels #include <sys/ioctl.h> 3233624Sbostic 3316255Skarels #include <netdb.h> 3433624Sbostic #include <netinet/in.h> 3516255Skarels #include <net/if.h> 3616255Skarels #include <netinet/if_ether.h> 3716255Skarels 3833624Sbostic #include <errno.h> 3933624Sbostic #include <nlist.h> 4033624Sbostic #include <stdio.h> 4137961Sbostic #include <paths.h> 4233624Sbostic 4316255Skarels extern int errno; 4433624Sbostic static int kflag; 4516255Skarels 4616255Skarels main(argc, argv) 4733624Sbostic int argc; 4816255Skarels char **argv; 4916255Skarels { 5033624Sbostic int ch; 5116255Skarels 5233624Sbostic while ((ch = getopt(argc, argv, "adsf")) != EOF) 5333624Sbostic switch((char)ch) { 5433624Sbostic case 'a': { 5533624Sbostic char *mem; 5633624Sbostic 5733624Sbostic if (argc > 4) 5833624Sbostic usage(); 5933624Sbostic if (argc == 4) { 6033624Sbostic kflag = 1; 6133624Sbostic mem = argv[3]; 6233624Sbostic } 6333624Sbostic else 6437255Sbostic mem = _PATH_KMEM; 6537961Sbostic dump((argc >= 3) ? argv[2] : _PATH_UNIX, mem); 6633624Sbostic exit(0); 6733624Sbostic } 6833624Sbostic case 'd': 6933624Sbostic if (argc != 3) 7033624Sbostic usage(); 7133624Sbostic delete(argv[2]); 7233624Sbostic exit(0); 7333624Sbostic case 's': 7433624Sbostic if (argc < 4 || argc > 7) 7533624Sbostic usage(); 7633624Sbostic exit(set(argc-2, &argv[2]) ? 1 : 0); 7733624Sbostic case 'f': 7833624Sbostic if (argc != 3) 7933624Sbostic usage(); 8033624Sbostic exit (file(argv[2]) ? 1 : 0); 8133624Sbostic case '?': 8233624Sbostic default: 8333624Sbostic usage(); 8433624Sbostic } 8533624Sbostic if (argc != 2) 8633624Sbostic usage(); 8733624Sbostic get(argv[1]); 8833624Sbostic exit(0); 8916255Skarels } 9016255Skarels 9116255Skarels /* 9216255Skarels * Process a file to set standard arp entries 9316255Skarels */ 9416255Skarels file(name) 9516255Skarels char *name; 9616255Skarels { 9716255Skarels FILE *fp; 9833624Sbostic int i, retval; 9925788Skarels char line[100], arg[5][50], *args[5]; 10016255Skarels 10116255Skarels if ((fp = fopen(name, "r")) == NULL) { 10216255Skarels fprintf(stderr, "arp: cannot open %s\n", name); 10316255Skarels exit(1); 10416255Skarels } 10516255Skarels args[0] = &arg[0][0]; 10616255Skarels args[1] = &arg[1][0]; 10716255Skarels args[2] = &arg[2][0]; 10816255Skarels args[3] = &arg[3][0]; 10925788Skarels args[4] = &arg[4][0]; 11032643Smckusick retval = 0; 11116255Skarels while(fgets(line, 100, fp) != NULL) { 11232643Smckusick i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], 11332643Smckusick arg[3], arg[4]); 11416255Skarels if (i < 2) { 11516255Skarels fprintf(stderr, "arp: bad line: %s\n", line); 11632643Smckusick retval = 1; 11716255Skarels continue; 11816255Skarels } 11932643Smckusick if (set(i, args)) 12032643Smckusick retval = 1; 12116255Skarels } 12216255Skarels fclose(fp); 12332643Smckusick return (retval); 12416255Skarels } 12516255Skarels 12616255Skarels /* 12716255Skarels * Set an individual arp entry 12816255Skarels */ 12916255Skarels set(argc, argv) 13033624Sbostic int argc; 13116255Skarels char **argv; 13216255Skarels { 13316255Skarels struct arpreq ar; 13416255Skarels struct hostent *hp; 13516255Skarels struct sockaddr_in *sin; 13621393Skarels u_char *ea; 13716255Skarels int s; 13816255Skarels char *host = argv[0], *eaddr = argv[1]; 13916255Skarels 14016255Skarels argc -= 2; 14116255Skarels argv += 2; 14216255Skarels bzero((caddr_t)&ar, sizeof ar); 14316255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 14426314Skarels sin->sin_family = AF_INET; 14526314Skarels sin->sin_addr.s_addr = inet_addr(host); 14626314Skarels if (sin->sin_addr.s_addr == -1) { 14735778Sbostic if (!(hp = gethostbyname(host))) { 14835778Sbostic fprintf(stderr, "arp: %s: ", host); 14935778Sbostic herror((char *)NULL); 15032643Smckusick return (1); 15126314Skarels } 15226314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 15326314Skarels sizeof sin->sin_addr); 15426314Skarels } 15521393Skarels ea = (u_char *)ar.arp_ha.sa_data; 15616255Skarels if (ether_aton(eaddr, ea)) 15732643Smckusick return (1); 15816255Skarels ar.arp_flags = ATF_PERM; 15926314Skarels while (argc-- > 0) { 16016255Skarels if (strncmp(argv[0], "temp", 4) == 0) 16116255Skarels ar.arp_flags &= ~ATF_PERM; 16233624Sbostic else if (strncmp(argv[0], "pub", 3) == 0) 16316255Skarels ar.arp_flags |= ATF_PUBL; 16433624Sbostic else if (strncmp(argv[0], "trail", 5) == 0) 16525788Skarels ar.arp_flags |= ATF_USETRAILERS; 16616255Skarels argv++; 16716255Skarels } 16816255Skarels 16916255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 17016255Skarels if (s < 0) { 17133624Sbostic perror("arp: socket"); 17233624Sbostic exit(1); 17333624Sbostic } 17416255Skarels if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 17516255Skarels perror(host); 17616255Skarels exit(1); 17716255Skarels } 17816255Skarels close(s); 17932643Smckusick return (0); 18016255Skarels } 18116255Skarels 18216255Skarels /* 18316255Skarels * Display an individual arp entry 18416255Skarels */ 18516255Skarels get(host) 18616255Skarels char *host; 18716255Skarels { 18816255Skarels struct arpreq ar; 18916255Skarels struct hostent *hp; 19016255Skarels struct sockaddr_in *sin; 19121393Skarels u_char *ea; 19216255Skarels int s; 19333624Sbostic char *inet_ntoa(); 19416255Skarels 19516255Skarels bzero((caddr_t)&ar, sizeof ar); 19616255Skarels ar.arp_pa.sa_family = AF_INET; 19716255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 19826314Skarels sin->sin_family = AF_INET; 19926314Skarels sin->sin_addr.s_addr = inet_addr(host); 20026314Skarels if (sin->sin_addr.s_addr == -1) { 20135778Sbostic if (!(hp = gethostbyname(host))) { 20235778Sbostic fprintf(stderr, "arp: %s: ", host); 20335778Sbostic herror((char *)NULL); 20426314Skarels exit(1); 20526314Skarels } 20626314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 20726314Skarels sizeof sin->sin_addr); 20826314Skarels } 20916255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 21016255Skarels if (s < 0) { 21133624Sbostic perror("arp: socket"); 21233624Sbostic exit(1); 21333624Sbostic } 21416255Skarels if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 21516255Skarels if (errno == ENXIO) 21616255Skarels printf("%s (%s) -- no entry\n", 21716255Skarels host, inet_ntoa(sin->sin_addr)); 21816255Skarels else 21916255Skarels perror("SIOCGARP"); 22016255Skarels exit(1); 22116255Skarels } 22216255Skarels close(s); 22321393Skarels ea = (u_char *)ar.arp_ha.sa_data; 22416255Skarels printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 22516255Skarels if (ar.arp_flags & ATF_COM) 22616255Skarels ether_print(ea); 22716255Skarels else 22816255Skarels printf("(incomplete)"); 22933624Sbostic if (ar.arp_flags & ATF_PERM) 23033624Sbostic printf(" permanent"); 23133624Sbostic if (ar.arp_flags & ATF_PUBL) 23233624Sbostic printf(" published"); 23333624Sbostic if (ar.arp_flags & ATF_USETRAILERS) 23433624Sbostic printf(" trailers"); 23516255Skarels printf("\n"); 23616255Skarels } 23716255Skarels 23816255Skarels /* 23916255Skarels * Delete an arp entry 24016255Skarels */ 24116255Skarels delete(host) 24216255Skarels char *host; 24316255Skarels { 24416255Skarels struct arpreq ar; 24516255Skarels struct hostent *hp; 24616255Skarels struct sockaddr_in *sin; 24716255Skarels int s; 24816255Skarels 24916255Skarels bzero((caddr_t)&ar, sizeof ar); 25016255Skarels ar.arp_pa.sa_family = AF_INET; 25116255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 25226314Skarels sin->sin_family = AF_INET; 25326314Skarels sin->sin_addr.s_addr = inet_addr(host); 25426314Skarels if (sin->sin_addr.s_addr == -1) { 25535778Sbostic if (!(hp = gethostbyname(host))) { 25635778Sbostic fprintf(stderr, "arp: %s: ", host); 25735778Sbostic herror((char *)NULL); 25826314Skarels exit(1); 25926314Skarels } 26026314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 26126314Skarels sizeof sin->sin_addr); 26226314Skarels } 26316255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 26416255Skarels if (s < 0) { 26533624Sbostic perror("arp: socket"); 26633624Sbostic exit(1); 26733624Sbostic } 26816255Skarels if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 26916255Skarels if (errno == ENXIO) 27016255Skarels printf("%s (%s) -- no entry\n", 27116255Skarels host, inet_ntoa(sin->sin_addr)); 27216255Skarels else 27316255Skarels perror("SIOCDARP"); 27416255Skarels exit(1); 27516255Skarels } 27616255Skarels close(s); 27716255Skarels printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 27816255Skarels } 27916255Skarels 28016255Skarels struct nlist nl[] = { 28116255Skarels #define X_ARPTAB 0 28216255Skarels { "_arptab" }, 28316255Skarels #define X_ARPTAB_SIZE 1 28416255Skarels { "_arptab_size" }, 28533624Sbostic #define N_SYSMAP 2 28633624Sbostic { "_Sysmap" }, 28733624Sbostic #define N_SYSSIZE 3 28833624Sbostic { "_Syssize" }, 28916255Skarels { "" }, 29016255Skarels }; 29116255Skarels 29233624Sbostic static struct pte *Sysmap; 29333624Sbostic 29416255Skarels /* 29516255Skarels * Dump the entire arp table 29616255Skarels */ 29716255Skarels dump(kernel, mem) 29816255Skarels char *kernel, *mem; 29916255Skarels { 30033624Sbostic extern int h_errno; 30116255Skarels struct arptab *at; 30216255Skarels struct hostent *hp; 30333624Sbostic int bynumber, mf, arptab_size, sz; 30433624Sbostic char *host, *malloc(); 30533624Sbostic off_t lseek(); 30616255Skarels 30733624Sbostic if (nlist(kernel, nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) { 30816255Skarels fprintf(stderr, "arp: %s: bad namelist\n", kernel); 30916255Skarels exit(1); 31016255Skarels } 31133624Sbostic mf = open(mem, O_RDONLY); 31233624Sbostic if (mf < 0) { 31335377Sbostic fprintf(stderr, "arp: cannot open %s\n", mem); 31416255Skarels exit(1); 31516255Skarels } 31633624Sbostic if (kflag) { 31733624Sbostic off_t off; 31833624Sbostic 31933624Sbostic Sysmap = (struct pte *) 32033624Sbostic malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 32133624Sbostic if (!Sysmap) { 32233624Sbostic fputs("arp: can't get memory for Sysmap.\n", stderr); 32333624Sbostic exit(1); 32433624Sbostic } 32533624Sbostic off = nl[N_SYSMAP].n_value & ~KERNBASE; 32633624Sbostic (void)lseek(mf, off, L_SET); 32733624Sbostic (void)read(mf, (char *)Sysmap, 32833624Sbostic (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 32933624Sbostic } 33033624Sbostic klseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, L_SET); 33116255Skarels read(mf, &arptab_size, sizeof arptab_size); 33233624Sbostic if (arptab_size <= 0 || arptab_size > 1000) { 33316255Skarels fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 33416255Skarels exit(1); 33516255Skarels } 33616255Skarels sz = arptab_size * sizeof (struct arptab); 33733624Sbostic at = (struct arptab *)malloc((u_int)sz); 33816255Skarels if (at == NULL) { 33933624Sbostic fputs("arp: can't get memory for arptab.\n", stderr); 34016255Skarels exit(1); 34116255Skarels } 34233624Sbostic klseek(mf, (long)nl[X_ARPTAB].n_value, L_SET); 34316255Skarels if (read(mf, (char *)at, sz) != sz) { 34416255Skarels perror("arp: error reading arptab"); 34516255Skarels exit(1); 34616255Skarels } 34716255Skarels close(mf); 34833624Sbostic for (bynumber = 0; arptab_size-- > 0; at++) { 34916255Skarels if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 35016255Skarels continue; 35126314Skarels if (bynumber == 0) 35226314Skarels hp = gethostbyaddr((caddr_t)&at->at_iaddr, 35326314Skarels sizeof at->at_iaddr, AF_INET); 35426314Skarels else 35526314Skarels hp = 0; 35616255Skarels if (hp) 35716255Skarels host = hp->h_name; 35826314Skarels else { 35916255Skarels host = "?"; 36026314Skarels if (h_errno == TRY_AGAIN) 36126314Skarels bynumber = 1; 36226314Skarels } 36316255Skarels printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 36416255Skarels if (at->at_flags & ATF_COM) 36521393Skarels ether_print(at->at_enaddr); 36616255Skarels else 36716255Skarels printf("(incomplete)"); 36833624Sbostic if (at->at_flags & ATF_PERM) 36933624Sbostic printf(" permanent"); 37033624Sbostic if (at->at_flags & ATF_PUBL) 37133624Sbostic printf(" published"); 37233624Sbostic if (at->at_flags & ATF_USETRAILERS) 37333624Sbostic printf(" trailers"); 37416255Skarels printf("\n"); 37516255Skarels } 37616255Skarels } 37716255Skarels 37833624Sbostic /* 37933624Sbostic * Seek into the kernel for a value. 38033624Sbostic */ 38133624Sbostic klseek(fd, base, off) 38233624Sbostic int fd, off; 38333624Sbostic off_t base; 38433624Sbostic { 38533624Sbostic off_t lseek(); 38633624Sbostic 38733624Sbostic if (kflag) { /* get kernel pte */ 38833624Sbostic base &= ~KERNBASE; 38933624Sbostic base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); 39033624Sbostic } 39133624Sbostic (void)lseek(fd, base, off); 39233624Sbostic } 39333624Sbostic 39421393Skarels ether_print(cp) 39521393Skarels u_char *cp; 39616255Skarels { 39716255Skarels printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 39816255Skarels } 39916255Skarels 40016255Skarels ether_aton(a, n) 40116255Skarels char *a; 40221393Skarels u_char *n; 40316255Skarels { 40416255Skarels int i, o[6]; 40516255Skarels 40616255Skarels i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 40716255Skarels &o[3], &o[4], &o[5]); 40816255Skarels if (i != 6) { 40916255Skarels fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 41016255Skarels return (1); 41116255Skarels } 41216255Skarels for (i=0; i<6; i++) 41321393Skarels n[i] = o[i]; 41416255Skarels return (0); 41516255Skarels } 41616255Skarels 41716255Skarels usage() 41816255Skarels { 41933624Sbostic printf("usage: arp hostname\n"); 42037961Sbostic printf(" arp -a [kernel] [kernel_memory]\n"); 42116255Skarels printf(" arp -d hostname\n"); 42232643Smckusick printf(" arp -s hostname ether_addr [temp] [pub] [trail]\n"); 42316255Skarels printf(" arp -f filename\n"); 42433624Sbostic exit(1); 42516255Skarels } 426