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