1*16255Skarels #ifndef lint 2*16255Skarels static char *sccsid = "@(#)arp.c 1.1 (Berkeley) 03/30/84"; 3*16255Skarels #endif 4*16255Skarels 5*16255Skarels /* 6*16255Skarels * arp - display, set, and delete arp table entries 7*16255Skarels */ 8*16255Skarels 9*16255Skarels #include <stdio.h> 10*16255Skarels #include <sys/types.h> 11*16255Skarels #include <sys/socket.h> 12*16255Skarels #include <netinet/in.h> 13*16255Skarels #include <sys/ioctl.h> 14*16255Skarels #include <errno.h> 15*16255Skarels #include <netdb.h> 16*16255Skarels #include <nlist.h> 17*16255Skarels #include <net/if.h> 18*16255Skarels #include <netinet/if_ether.h> 19*16255Skarels 20*16255Skarels extern int errno; 21*16255Skarels 22*16255Skarels main(argc, argv) 23*16255Skarels char **argv; 24*16255Skarels { 25*16255Skarels if (argc >= 2 && strcmp(argv[1], "-a") == 0) { 26*16255Skarels char *kernel = "/vmunix", *mem = "/dev/kmem"; 27*16255Skarels 28*16255Skarels if (argc >= 3) 29*16255Skarels kernel = argv[2]; 30*16255Skarels if (argc >= 4) 31*16255Skarels mem = argv[3]; 32*16255Skarels dump(kernel, mem); 33*16255Skarels exit(0); 34*16255Skarels } 35*16255Skarels if (argc == 2) { 36*16255Skarels get(argv[1]); 37*16255Skarels exit(0); 38*16255Skarels } 39*16255Skarels if (argc >= 4 && strcmp(argv[1], "-s") == 0) { 40*16255Skarels set(argc-2, &argv[2]); 41*16255Skarels exit(0); 42*16255Skarels } 43*16255Skarels if (argc == 3 && strcmp(argv[1], "-d") == 0) { 44*16255Skarels delete(argv[2]); 45*16255Skarels exit(0); 46*16255Skarels } 47*16255Skarels if (argc == 3 && strcmp(argv[1], "-f") == 0) { 48*16255Skarels file(argv[2]); 49*16255Skarels exit(0); 50*16255Skarels } 51*16255Skarels usage(); 52*16255Skarels exit(1); 53*16255Skarels } 54*16255Skarels 55*16255Skarels /* 56*16255Skarels * Process a file to set standard arp entries 57*16255Skarels */ 58*16255Skarels file(name) 59*16255Skarels char *name; 60*16255Skarels { 61*16255Skarels FILE *fp; 62*16255Skarels int i; 63*16255Skarels char line[100], arg[4][50], *args[4]; 64*16255Skarels 65*16255Skarels if ((fp = fopen(name, "r")) == NULL) { 66*16255Skarels fprintf(stderr, "arp: cannot open %s\n", name); 67*16255Skarels exit(1); 68*16255Skarels } 69*16255Skarels args[0] = &arg[0][0]; 70*16255Skarels args[1] = &arg[1][0]; 71*16255Skarels args[2] = &arg[2][0]; 72*16255Skarels args[3] = &arg[3][0]; 73*16255Skarels while(fgets(line, 100, fp) != NULL) { 74*16255Skarels i = sscanf(line, "%s %s %s %s", arg[0], arg[1], arg[2], arg[3]); 75*16255Skarels if (i < 2) { 76*16255Skarels fprintf(stderr, "arp: bad line: %s\n", line); 77*16255Skarels continue; 78*16255Skarels } 79*16255Skarels set(i, args); 80*16255Skarels } 81*16255Skarels fclose(fp); 82*16255Skarels } 83*16255Skarels 84*16255Skarels /* 85*16255Skarels * Set an individual arp entry 86*16255Skarels */ 87*16255Skarels set(argc, argv) 88*16255Skarels char **argv; 89*16255Skarels { 90*16255Skarels struct arpreq ar; 91*16255Skarels struct hostent *hp; 92*16255Skarels struct sockaddr_in *sin; 93*16255Skarels struct ether_addr *ea; 94*16255Skarels int s; 95*16255Skarels char *host = argv[0], *eaddr = argv[1]; 96*16255Skarels 97*16255Skarels argc -= 2; 98*16255Skarels argv += 2; 99*16255Skarels hp = gethostbyname(host); 100*16255Skarels if (hp == NULL) { 101*16255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 102*16255Skarels return (1); 103*16255Skarels } 104*16255Skarels bzero((caddr_t)&ar, sizeof ar); 105*16255Skarels ar.arp_pa.sa_family = AF_INET; 106*16255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 107*16255Skarels sin->sin_addr = *(struct in_addr *)hp->h_addr; 108*16255Skarels ea = (struct ether_addr *)ar.arp_ha.sa_data; 109*16255Skarels if (ether_aton(eaddr, ea)) 110*16255Skarels return; 111*16255Skarels ar.arp_flags = ATF_PERM; 112*16255Skarels while(argc-- > 0) { 113*16255Skarels if (strncmp(argv[0], "temp", 4) == 0) 114*16255Skarels ar.arp_flags &= ~ATF_PERM; 115*16255Skarels if (strncmp(argv[0], "pub", 3) == 0) 116*16255Skarels ar.arp_flags |= ATF_PUBL; 117*16255Skarels argv++; 118*16255Skarels } 119*16255Skarels 120*16255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 121*16255Skarels if (s < 0) { 122*16255Skarels perror("arp: socket"); 123*16255Skarels exit(1); 124*16255Skarels } 125*16255Skarels if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) { 126*16255Skarels perror(host); 127*16255Skarels exit(1); 128*16255Skarels } 129*16255Skarels close(s); 130*16255Skarels } 131*16255Skarels 132*16255Skarels 133*16255Skarels /* 134*16255Skarels * Display an individual arp entry 135*16255Skarels */ 136*16255Skarels get(host) 137*16255Skarels char *host; 138*16255Skarels { 139*16255Skarels struct arpreq ar; 140*16255Skarels struct hostent *hp; 141*16255Skarels struct sockaddr_in *sin; 142*16255Skarels struct ether_addr *ea; 143*16255Skarels int s; 144*16255Skarels 145*16255Skarels hp = gethostbyname(host); 146*16255Skarels if (hp == NULL) { 147*16255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 148*16255Skarels exit(1); 149*16255Skarels } 150*16255Skarels bzero((caddr_t)&ar, sizeof ar); 151*16255Skarels ar.arp_pa.sa_family = AF_INET; 152*16255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 153*16255Skarels sin->sin_addr = *(struct in_addr *)hp->h_addr; 154*16255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 155*16255Skarels if (s < 0) { 156*16255Skarels perror("arp: socket"); 157*16255Skarels exit(1); 158*16255Skarels } 159*16255Skarels if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 160*16255Skarels if (errno == ENXIO) 161*16255Skarels printf("%s (%s) -- no entry\n", 162*16255Skarels host, inet_ntoa(sin->sin_addr)); 163*16255Skarels else 164*16255Skarels perror("SIOCGARP"); 165*16255Skarels exit(1); 166*16255Skarels } 167*16255Skarels close(s); 168*16255Skarels ea = (struct ether_addr *)ar.arp_ha.sa_data; 169*16255Skarels printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 170*16255Skarels if (ar.arp_flags & ATF_COM) 171*16255Skarels ether_print(ea); 172*16255Skarels else 173*16255Skarels printf("(incomplete)"); 174*16255Skarels if (!(ar.arp_flags & ATF_PERM)) printf(" temporary"); 175*16255Skarels if (ar.arp_flags & ATF_PUBL) printf(" published"); 176*16255Skarels printf("\n"); 177*16255Skarels } 178*16255Skarels 179*16255Skarels /* 180*16255Skarels * Delete an arp entry 181*16255Skarels */ 182*16255Skarels delete(host) 183*16255Skarels char *host; 184*16255Skarels { 185*16255Skarels struct arpreq ar; 186*16255Skarels struct hostent *hp; 187*16255Skarels struct sockaddr_in *sin; 188*16255Skarels int s; 189*16255Skarels 190*16255Skarels hp = gethostbyname(host); 191*16255Skarels if (hp == NULL) { 192*16255Skarels fprintf(stderr, "arp: %s: unknown host\n", host); 193*16255Skarels exit(1); 194*16255Skarels } 195*16255Skarels bzero((caddr_t)&ar, sizeof ar); 196*16255Skarels ar.arp_pa.sa_family = AF_INET; 197*16255Skarels sin = (struct sockaddr_in *)&ar.arp_pa; 198*16255Skarels sin->sin_addr = *(struct in_addr *)hp->h_addr; 199*16255Skarels s = socket(AF_INET, SOCK_DGRAM, 0); 200*16255Skarels if (s < 0) { 201*16255Skarels perror("arp: socket"); 202*16255Skarels exit(1); 203*16255Skarels } 204*16255Skarels if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) { 205*16255Skarels if (errno == ENXIO) 206*16255Skarels printf("%s (%s) -- no entry\n", 207*16255Skarels host, inet_ntoa(sin->sin_addr)); 208*16255Skarels else 209*16255Skarels perror("SIOCDARP"); 210*16255Skarels exit(1); 211*16255Skarels } 212*16255Skarels close(s); 213*16255Skarels printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 214*16255Skarels } 215*16255Skarels 216*16255Skarels struct nlist nl[] = { 217*16255Skarels #define X_ARPTAB 0 218*16255Skarels { "_arptab" }, 219*16255Skarels #define X_ARPTAB_SIZE 1 220*16255Skarels { "_arptab_size" }, 221*16255Skarels { "" }, 222*16255Skarels }; 223*16255Skarels 224*16255Skarels /* 225*16255Skarels * Dump the entire arp table 226*16255Skarels */ 227*16255Skarels dump(kernel, mem) 228*16255Skarels char *kernel, *mem; 229*16255Skarels { 230*16255Skarels int mf, arptab_size, sz; 231*16255Skarels struct arptab *at; 232*16255Skarels struct hostent *hp; 233*16255Skarels char *host; 234*16255Skarels 235*16255Skarels nlist(kernel, nl); 236*16255Skarels if(nl[X_ARPTAB_SIZE].n_type == 0) { 237*16255Skarels fprintf(stderr, "arp: %s: bad namelist\n", kernel); 238*16255Skarels exit(1); 239*16255Skarels } 240*16255Skarels mf = open(mem, 0); 241*16255Skarels if(mf < 0) { 242*16255Skarels fprintf(fprintf, "arp: cannot open %s\n", mem); 243*16255Skarels exit(1); 244*16255Skarels } 245*16255Skarels lseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, 0); 246*16255Skarels read(mf, &arptab_size, sizeof arptab_size); 247*16255Skarels if (arptab_size <=0 || arptab_size > 1000) { 248*16255Skarels fprintf(stderr, "arp: %s: namelist wrong\n", kernel); 249*16255Skarels exit(1); 250*16255Skarels } 251*16255Skarels sz = arptab_size * sizeof (struct arptab); 252*16255Skarels at = (struct arptab *)malloc(sz); 253*16255Skarels if (at == NULL) { 254*16255Skarels fprintf(stderr, "arp: can't get memory for arptab\n"); 255*16255Skarels exit(1); 256*16255Skarels } 257*16255Skarels lseek(mf, (long)nl[X_ARPTAB].n_value, 0); 258*16255Skarels if (read(mf, (char *)at, sz) != sz) { 259*16255Skarels perror("arp: error reading arptab"); 260*16255Skarels exit(1); 261*16255Skarels } 262*16255Skarels close(mf); 263*16255Skarels for (; arptab_size-- > 0; at++) { 264*16255Skarels if (at->at_iaddr.s_addr == 0 || at->at_flags == 0) 265*16255Skarels continue; 266*16255Skarels hp = gethostbyaddr((caddr_t)&at->at_iaddr, sizeof at->at_iaddr, 267*16255Skarels AF_INET); 268*16255Skarels if (hp) 269*16255Skarels host = hp->h_name; 270*16255Skarels else 271*16255Skarels host = "?"; 272*16255Skarels printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr)); 273*16255Skarels if (at->at_flags & ATF_COM) 274*16255Skarels ether_print(&at->at_enaddr); 275*16255Skarels else 276*16255Skarels printf("(incomplete)"); 277*16255Skarels if (!(at->at_flags & ATF_PERM)) printf(" temporary"); 278*16255Skarels if (at->at_flags & ATF_PUBL) printf(" published"); 279*16255Skarels printf("\n"); 280*16255Skarels } 281*16255Skarels } 282*16255Skarels 283*16255Skarels ether_print(ea) 284*16255Skarels struct ether_addr *ea; 285*16255Skarels { 286*16255Skarels u_char *cp = &ea->ether_addr_octet[0]; 287*16255Skarels 288*16255Skarels printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 289*16255Skarels } 290*16255Skarels 291*16255Skarels ether_aton(a, n) 292*16255Skarels char *a; 293*16255Skarels struct ether_addr *n; 294*16255Skarels { 295*16255Skarels int i, o[6]; 296*16255Skarels 297*16255Skarels i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 298*16255Skarels &o[3], &o[4], &o[5]); 299*16255Skarels if (i != 6) { 300*16255Skarels fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); 301*16255Skarels return (1); 302*16255Skarels } 303*16255Skarels for (i=0; i<6; i++) 304*16255Skarels n->ether_addr_octet[i] = o[i]; 305*16255Skarels return (0); 306*16255Skarels } 307*16255Skarels 308*16255Skarels usage() 309*16255Skarels { 310*16255Skarels printf("Usage: arp hostname\n"); 311*16255Skarels printf(" arp -a [/vmunix] [/dev/kmem]\n"); 312*16255Skarels printf(" arp -d hostname\n"); 313*16255Skarels printf(" arp -s hostname ether_addr [temp] [pub]\n"); 314*16255Skarels printf(" arp -f filename\n"); 315*16255Skarels } 316