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 * 842791Sbostic * %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*50476Sbostic static char sccsid[] = "@(#)arp.c 5.11.1.1 (Berkeley) 07/22/91"; 1934918Sbostic #endif /* not lint */ 2034918Sbostic 2116255Skarels /* 2216255Skarels * arp - display, set, and delete arp table entries 2316255Skarels */ 2416255Skarels 2533624Sbostic #include <sys/param.h> 2633624Sbostic #include <sys/file.h> 2716255Skarels #include <sys/socket.h> 28*50476Sbostic #include <sys/ioctl.h> 2933624Sbostic 30*50476Sbostic #include <netdb.h> 31*50476Sbostic #include <netinet/in.h> 3250132Ssklower #include <net/if.h> 3316255Skarels #include <netinet/if_ether.h> 3416255Skarels 3533624Sbostic #include <errno.h> 3633624Sbostic #include <nlist.h> 37*50476Sbostic #include <kvm.h> 3833624Sbostic #include <stdio.h> 3937961Sbostic #include <paths.h> 4033624Sbostic 4116255Skarels extern int errno; 4216255Skarels 4316255Skarels main(argc, argv) 4433624Sbostic int argc; 4516255Skarels char **argv; 4616255Skarels { 4733624Sbostic int ch; 4816255Skarels 49*50476Sbostic while ((ch = getopt(argc, argv, "adsf")) != EOF) 5033624Sbostic switch((char)ch) { 51*50476Sbostic case 'a': { 52*50476Sbostic char *mem = 0; 53*50476Sbostic 54*50476Sbostic if (argc > 4) 55*50476Sbostic usage(); 56*50476Sbostic if (argc == 4) { 57*50476Sbostic mem = argv[3]; 58*50476Sbostic } 59*50476Sbostic dump((argc >= 3) ? argv[2] : _PATH_UNIX, mem); 6033624Sbostic exit(0); 61*50476Sbostic } 6233624Sbostic case 'd': 63*50476Sbostic if (argc != 3) 6433624Sbostic usage(); 65*50476Sbostic delete(argv[2]); 6633624Sbostic exit(0); 6733624Sbostic case 's': 6833624Sbostic if (argc < 4 || argc > 7) 6933624Sbostic usage(); 7033624Sbostic exit(set(argc-2, &argv[2]) ? 1 : 0); 71*50476Sbostic case 'f': 72*50476Sbostic if (argc != 3) 73*50476Sbostic usage(); 74*50476Sbostic exit (file(argv[2]) ? 1 : 0); 7533624Sbostic case '?': 7633624Sbostic default: 7733624Sbostic usage(); 7833624Sbostic } 7933624Sbostic if (argc != 2) 8033624Sbostic usage(); 8133624Sbostic get(argv[1]); 8233624Sbostic exit(0); 8316255Skarels } 8416255Skarels 8516255Skarels /* 8616255Skarels * Process a file to set standard arp entries 8716255Skarels */ 8816255Skarels file(name) 8916255Skarels char *name; 9016255Skarels { 9116255Skarels FILE *fp; 9233624Sbostic int i, retval; 9325788Skarels char line[100], arg[5][50], *args[5]; 9416255Skarels 9516255Skarels if ((fp = fopen(name, "r")) == NULL) { 9616255Skarels fprintf(stderr, "arp: cannot open %s\n", name); 9716255Skarels exit(1); 9816255Skarels } 9916255Skarels args[0] = &arg[0][0]; 10016255Skarels args[1] = &arg[1][0]; 10116255Skarels args[2] = &arg[2][0]; 10216255Skarels args[3] = &arg[3][0]; 10325788Skarels args[4] = &arg[4][0]; 10432643Smckusick retval = 0; 10516255Skarels while(fgets(line, 100, fp) != NULL) { 10632643Smckusick i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], 10732643Smckusick arg[3], arg[4]); 10816255Skarels if (i < 2) { 10916255Skarels fprintf(stderr, "arp: bad line: %s\n", line); 11032643Smckusick retval = 1; 11116255Skarels continue; 11216255Skarels } 11332643Smckusick if (set(i, args)) 11432643Smckusick retval = 1; 11516255Skarels } 11616255Skarels fclose(fp); 11732643Smckusick return (retval); 11816255Skarels } 11916255Skarels 12016255Skarels /* 12116255Skarels * Set an individual arp entry 12216255Skarels */ 12316255Skarels set(argc, argv) 12433624Sbostic int argc; 12516255Skarels char **argv; 12616255Skarels { 127*50476Sbostic struct arpreq ar; 12816255Skarels struct hostent *hp; 129*50476Sbostic struct sockaddr_in *sin; 13021393Skarels u_char *ea; 131*50476Sbostic int s; 13216255Skarels char *host = argv[0], *eaddr = argv[1]; 13316255Skarels 13416255Skarels argc -= 2; 13516255Skarels argv += 2; 136*50476Sbostic bzero((caddr_t)&ar, sizeof ar); 137*50476Sbostic sin = (struct sockaddr_in *)&ar.arp_pa; 138*50476Sbostic sin->sin_family = AF_INET; 13926314Skarels sin->sin_addr.s_addr = inet_addr(host); 14026314Skarels if (sin->sin_addr.s_addr == -1) { 14135778Sbostic if (!(hp = gethostbyname(host))) { 14235778Sbostic fprintf(stderr, "arp: %s: ", host); 14335778Sbostic herror((char *)NULL); 14432643Smckusick return (1); 14526314Skarels } 14626314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 14726314Skarels sizeof sin->sin_addr); 14826314Skarels } 149*50476Sbostic ea = (u_char *)ar.arp_ha.sa_data; 150*50476Sbostic if (ether_aton(eaddr, ea)) 151*50476Sbostic return (1); 152*50476Sbostic ar.arp_flags = ATF_PERM; 15326314Skarels while (argc-- > 0) { 154*50476Sbostic if (strncmp(argv[0], "temp", 4) == 0) 155*50476Sbostic ar.arp_flags &= ~ATF_PERM; 15633624Sbostic else if (strncmp(argv[0], "pub", 3) == 0) 157*50476Sbostic ar.arp_flags |= ATF_PUBL; 15833624Sbostic else if (strncmp(argv[0], "trail", 5) == 0) 159*50476Sbostic ar.arp_flags |= ATF_USETRAILERS; 16016255Skarels argv++; 16116255Skarels } 162*50476Sbostic 163*50476Sbostic s = socket(AF_INET, SOCK_DGRAM, 0); 164*50476Sbostic if (s < 0) { 165*50476Sbostic perror("arp: socket"); 166*50476Sbostic exit(1); 167*50476Sbostic } 168*50476Sbostic if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 16916255Skarels perror(host); 170*50476Sbostic exit(1); 17116255Skarels } 172*50476Sbostic close(s); 173*50476Sbostic return (0); 17416255Skarels } 17516255Skarels 17616255Skarels /* 17716255Skarels * Display an individual arp entry 17816255Skarels */ 17916255Skarels get(host) 18016255Skarels char *host; 18116255Skarels { 182*50476Sbostic struct arpreq ar; 18316255Skarels struct hostent *hp; 184*50476Sbostic struct sockaddr_in *sin; 18521393Skarels u_char *ea; 186*50476Sbostic int s; 18733624Sbostic char *inet_ntoa(); 18816255Skarels 189*50476Sbostic bzero((caddr_t)&ar, sizeof ar); 190*50476Sbostic ar.arp_pa.sa_family = AF_INET; 191*50476Sbostic sin = (struct sockaddr_in *)&ar.arp_pa; 192*50476Sbostic sin->sin_family = AF_INET; 19326314Skarels sin->sin_addr.s_addr = inet_addr(host); 19426314Skarels if (sin->sin_addr.s_addr == -1) { 19535778Sbostic if (!(hp = gethostbyname(host))) { 19635778Sbostic fprintf(stderr, "arp: %s: ", host); 19735778Sbostic herror((char *)NULL); 19826314Skarels exit(1); 19926314Skarels } 20026314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 20126314Skarels sizeof sin->sin_addr); 20226314Skarels } 203*50476Sbostic s = socket(AF_INET, SOCK_DGRAM, 0); 204*50476Sbostic if (s < 0) { 205*50476Sbostic perror("arp: socket"); 20633624Sbostic exit(1); 20733624Sbostic } 208*50476Sbostic if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 209*50476Sbostic if (errno == ENXIO) 210*50476Sbostic printf("%s (%s) -- no entry\n", 211*50476Sbostic host, inet_ntoa(sin->sin_addr)); 212*50476Sbostic else 213*50476Sbostic perror("SIOCGARP"); 214*50476Sbostic exit(1); 215*50476Sbostic } 216*50476Sbostic close(s); 217*50476Sbostic ea = (u_char *)ar.arp_ha.sa_data; 218*50476Sbostic printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 219*50476Sbostic if (ar.arp_flags & ATF_COM) 220*50476Sbostic ether_print(ea); 221*50476Sbostic else 222*50476Sbostic printf("(incomplete)"); 223*50476Sbostic if (ar.arp_flags & ATF_PERM) 224*50476Sbostic printf(" permanent"); 225*50476Sbostic if (ar.arp_flags & ATF_PUBL) 226*50476Sbostic printf(" published"); 227*50476Sbostic if (ar.arp_flags & ATF_USETRAILERS) 228*50476Sbostic printf(" trailers"); 229*50476Sbostic printf("\n"); 23016255Skarels } 23116255Skarels 23216255Skarels /* 23316255Skarels * Delete an arp entry 23416255Skarels */ 235*50476Sbostic delete(host) 23616255Skarels char *host; 23716255Skarels { 238*50476Sbostic struct arpreq ar; 23916255Skarels struct hostent *hp; 240*50476Sbostic struct sockaddr_in *sin; 241*50476Sbostic int s; 24216255Skarels 243*50476Sbostic bzero((caddr_t)&ar, sizeof ar); 244*50476Sbostic ar.arp_pa.sa_family = AF_INET; 245*50476Sbostic sin = (struct sockaddr_in *)&ar.arp_pa; 246*50476Sbostic sin->sin_family = AF_INET; 24726314Skarels sin->sin_addr.s_addr = inet_addr(host); 24826314Skarels if (sin->sin_addr.s_addr == -1) { 24935778Sbostic if (!(hp = gethostbyname(host))) { 25035778Sbostic fprintf(stderr, "arp: %s: ", host); 25135778Sbostic herror((char *)NULL); 252*50476Sbostic exit(1); 25326314Skarels } 25426314Skarels bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 25526314Skarels sizeof sin->sin_addr); 25626314Skarels } 257*50476Sbostic s = socket(AF_INET, SOCK_DGRAM, 0); 258*50476Sbostic if (s < 0) { 259*50476Sbostic perror("arp: socket"); 260*50476Sbostic exit(1); 26133624Sbostic } 262*50476Sbostic if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 263*50476Sbostic if (errno == ENXIO) 264*50476Sbostic printf("%s (%s) -- no entry\n", 265*50476Sbostic host, inet_ntoa(sin->sin_addr)); 266*50476Sbostic else 267*50476Sbostic perror("SIOCDARP"); 268*50476Sbostic exit(1); 26916255Skarels } 270*50476Sbostic close(s); 271*50476Sbostic printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 27216255Skarels } 27316255Skarels 274*50476Sbostic struct nlist nl[] = { 275*50476Sbostic #define X_ARPTAB 0 276*50476Sbostic { "_arptab" }, 277*50476Sbostic #define X_ARPTAB_SIZE 1 278*50476Sbostic { "_arptab_size" }, 279*50476Sbostic { "" }, 280*50476Sbostic }; 281*50476Sbostic 28216255Skarels /* 28316255Skarels * Dump the entire arp table 28416255Skarels */ 285*50476Sbostic dump(kernel, mem) 286*50476Sbostic char *kernel, *mem; 28716255Skarels { 28833624Sbostic extern int h_errno; 289*50476Sbostic struct arptab *at; 29016255Skarels struct hostent *hp; 291*50476Sbostic int bynumber, mf, arptab_size, sz; 292*50476Sbostic char *host, *malloc(); 293*50476Sbostic off_t lseek(); 29416255Skarels 295*50476Sbostic if (kvm_openfiles(kernel, mem, NULL) == -1) { 296*50476Sbostic fprintf(stderr, "arp: kvm_openfiles: %s\n", kvm_geterr()); 297*50476Sbostic exit(1); 298*50476Sbostic } 299*50476Sbostic if (kvm_nlist(nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) { 300*50476Sbostic fprintf(stderr, "arp: %s: bad namelist\n", kernel); 301*50476Sbostic exit(1); 302*50476Sbostic } 303*50476Sbostic if (kvm_read((void *)(nl[X_ARPTAB_SIZE].n_value), 304*50476Sbostic &arptab_size, sizeof arptab_size) == -1 || 305*50476Sbostic arptab_size <= 0 || arptab_size > 1000) { 306*50476Sbostic fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 307*50476Sbostic exit(1); 308*50476Sbostic } 309*50476Sbostic sz = arptab_size * sizeof (struct arptab); 310*50476Sbostic at = (struct arptab *)malloc((u_int)sz); 311*50476Sbostic if (at == NULL) { 312*50476Sbostic fputs("arp: can't get memory for arptab.\n", stderr); 313*50476Sbostic exit(1); 314*50476Sbostic } 315*50476Sbostic if (kvm_read((void *)(nl[X_ARPTAB].n_value), (char *)at, sz) == -1) { 316*50476Sbostic perror("arp: error reading arptab"); 317*50476Sbostic exit(1); 318*50476Sbostic } 319*50476Sbostic for (bynumber = 0; arptab_size-- > 0; at++) { 320*50476Sbostic if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 321*50476Sbostic continue; 322*50476Sbostic if (bynumber == 0) 323*50476Sbostic hp = gethostbyaddr((caddr_t)&at->at_iaddr, 324*50476Sbostic sizeof at->at_iaddr, AF_INET); 32526314Skarels else 32626314Skarels hp = 0; 32716255Skarels if (hp) 32816255Skarels host = hp->h_name; 32926314Skarels else { 33016255Skarels host = "?"; 33126314Skarels if (h_errno == TRY_AGAIN) 332*50476Sbostic bynumber = 1; 33326314Skarels } 334*50476Sbostic printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 335*50476Sbostic if (at->at_flags & ATF_COM) 336*50476Sbostic ether_print(at->at_enaddr); 33716255Skarels else 33816255Skarels printf("(incomplete)"); 339*50476Sbostic if (at->at_flags & ATF_PERM) 34033624Sbostic printf(" permanent"); 341*50476Sbostic if (at->at_flags & ATF_PUBL) 342*50476Sbostic printf(" published"); 343*50476Sbostic if (at->at_flags & ATF_USETRAILERS) 34433624Sbostic printf(" trailers"); 34516255Skarels printf("\n"); 34616255Skarels } 34716255Skarels } 34816255Skarels 34921393Skarels ether_print(cp) 35021393Skarels u_char *cp; 35116255Skarels { 35216255Skarels printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 35316255Skarels } 35416255Skarels 35516255Skarels ether_aton(a, n) 35616255Skarels char *a; 35721393Skarels u_char *n; 35816255Skarels { 35916255Skarels int i, o[6]; 36016255Skarels 36116255Skarels i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 36216255Skarels &o[3], &o[4], &o[5]); 36316255Skarels if (i != 6) { 36416255Skarels fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 36516255Skarels return (1); 36616255Skarels } 36716255Skarels for (i=0; i<6; i++) 36821393Skarels n[i] = o[i]; 36916255Skarels return (0); 37016255Skarels } 37116255Skarels 37216255Skarels usage() 37316255Skarels { 37433624Sbostic printf("usage: arp hostname\n"); 37537961Sbostic printf(" arp -a [kernel] [kernel_memory]\n"); 37616255Skarels printf(" arp -d hostname\n"); 37732643Smckusick printf(" arp -s hostname ether_addr [temp] [pub] [trail]\n"); 37816255Skarels printf(" arp -f filename\n"); 37933624Sbostic exit(1); 38016255Skarels } 381