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