|
|
1.1 root 1: /*
2: * Copyright (c) 1984 Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Sun Microsystems, Inc.
7: *
8: * Redistribution and use in source and binary forms are permitted provided
9: * that: (1) source distributions retain this entire copyright notice and
10: * comment, and (2) distributions including binaries display the following
11: * acknowledgement: ``This product includes software developed by the
12: * University of California, Berkeley and its contributors'' in the
13: * documentation or other materials provided with the distribution and in
14: * all advertising materials mentioning features or use of this software.
15: * Neither the name of the University nor the names of its contributors may
16: * be used to endorse or promote products derived from this software without
17: * specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: char copyright[] =
25: "@(#) Copyright (c) 1984 Regents of the University of California.\n\
26: All rights reserved.\n";
27: #endif /* not lint */
28:
29: #ifndef lint
30: static char sccsid[] = "@(#)arp.c 5.11 (Berkeley) 6/1/90";
31: #endif /* not lint */
32:
33: /*
34: * arp - display, set, and delete arp table entries
35: */
36:
37: #include <machine/pte.h>
38:
39: #include <sys/param.h>
40: #include <sys/vmmac.h>
41: #include <sys/file.h>
42: #include <sys/socket.h>
43: #include <sys/ioctl.h>
44:
45: #include <netdb.h>
46: #include <netinet/in.h>
47: #include <net/if.h>
48: #include <netinet/if_ether.h>
49:
50: #include <errno.h>
51: #include <nlist.h>
52: #include <stdio.h>
53: #include <paths.h>
54:
55: extern int errno;
56: static int kflag;
57:
58: main(argc, argv)
59: int argc;
60: char **argv;
61: {
62: int ch;
63:
64: while ((ch = getopt(argc, argv, "adsf")) != EOF)
65: switch((char)ch) {
66: case 'a': {
67: char *mem;
68:
69: if (argc > 4)
70: usage();
71: if (argc == 4) {
72: kflag = 1;
73: mem = argv[3];
74: }
75: else
76: mem = _PATH_KMEM;
77: dump((argc >= 3) ? argv[2] : _PATH_UNIX, mem);
78: exit(0);
79: }
80: case 'd':
81: if (argc != 3)
82: usage();
83: delete(argv[2]);
84: exit(0);
85: case 's':
86: if (argc < 4 || argc > 7)
87: usage();
88: exit(set(argc-2, &argv[2]) ? 1 : 0);
89: case 'f':
90: if (argc != 3)
91: usage();
92: exit (file(argv[2]) ? 1 : 0);
93: case '?':
94: default:
95: usage();
96: }
97: if (argc != 2)
98: usage();
99: get(argv[1]);
100: exit(0);
101: }
102:
103: /*
104: * Process a file to set standard arp entries
105: */
106: file(name)
107: char *name;
108: {
109: FILE *fp;
110: int i, retval;
111: char line[100], arg[5][50], *args[5];
112:
113: if ((fp = fopen(name, "r")) == NULL) {
114: fprintf(stderr, "arp: cannot open %s\n", name);
115: exit(1);
116: }
117: args[0] = &arg[0][0];
118: args[1] = &arg[1][0];
119: args[2] = &arg[2][0];
120: args[3] = &arg[3][0];
121: args[4] = &arg[4][0];
122: retval = 0;
123: while(fgets(line, 100, fp) != NULL) {
124: i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
125: arg[3], arg[4]);
126: if (i < 2) {
127: fprintf(stderr, "arp: bad line: %s\n", line);
128: retval = 1;
129: continue;
130: }
131: if (set(i, args))
132: retval = 1;
133: }
134: fclose(fp);
135: return (retval);
136: }
137:
138: /*
139: * Set an individual arp entry
140: */
141: set(argc, argv)
142: int argc;
143: char **argv;
144: {
145: struct arpreq ar;
146: struct hostent *hp;
147: struct sockaddr_in *sin;
148: u_char *ea;
149: int s;
150: char *host = argv[0], *eaddr = argv[1];
151:
152: argc -= 2;
153: argv += 2;
154: bzero((caddr_t)&ar, sizeof ar);
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: if (!(hp = gethostbyname(host))) {
160: fprintf(stderr, "arp: %s: ", host);
161: herror((char *)NULL);
162: return (1);
163: }
164: bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
165: sizeof sin->sin_addr);
166: }
167: ea = (u_char *)ar.arp_ha.sa_data;
168: if (ether_aton(eaddr, ea))
169: return (1);
170: ar.arp_flags = ATF_PERM;
171: while (argc-- > 0) {
172: if (strncmp(argv[0], "temp", 4) == 0)
173: ar.arp_flags &= ~ATF_PERM;
174: else if (strncmp(argv[0], "pub", 3) == 0)
175: ar.arp_flags |= ATF_PUBL;
176: else if (strncmp(argv[0], "trail", 5) == 0)
177: ar.arp_flags |= ATF_USETRAILERS;
178: argv++;
179: }
180:
181: s = socket(AF_INET, SOCK_DGRAM, 0);
182: if (s < 0) {
183: perror("arp: socket");
184: exit(1);
185: }
186: if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) {
187: perror(host);
188: exit(1);
189: }
190: close(s);
191: return (0);
192: }
193:
194: /*
195: * Display an individual arp entry
196: */
197: get(host)
198: char *host;
199: {
200: struct arpreq ar;
201: struct hostent *hp;
202: struct sockaddr_in *sin;
203: u_char *ea;
204: int s;
205: char *inet_ntoa();
206:
207: bzero((caddr_t)&ar, sizeof ar);
208: ar.arp_pa.sa_family = AF_INET;
209: sin = (struct sockaddr_in *)&ar.arp_pa;
210: sin->sin_family = AF_INET;
211: sin->sin_addr.s_addr = inet_addr(host);
212: if (sin->sin_addr.s_addr == -1) {
213: if (!(hp = gethostbyname(host))) {
214: fprintf(stderr, "arp: %s: ", host);
215: herror((char *)NULL);
216: exit(1);
217: }
218: bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
219: sizeof sin->sin_addr);
220: }
221: s = socket(AF_INET, SOCK_DGRAM, 0);
222: if (s < 0) {
223: perror("arp: socket");
224: exit(1);
225: }
226: if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) {
227: if (errno == ENXIO)
228: printf("%s (%s) -- no entry\n",
229: host, inet_ntoa(sin->sin_addr));
230: else
231: perror("SIOCGARP");
232: exit(1);
233: }
234: close(s);
235: ea = (u_char *)ar.arp_ha.sa_data;
236: printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
237: if (ar.arp_flags & ATF_COM)
238: ether_print(ea);
239: else
240: printf("(incomplete)");
241: if (ar.arp_flags & ATF_PERM)
242: printf(" permanent");
243: if (ar.arp_flags & ATF_PUBL)
244: printf(" published");
245: if (ar.arp_flags & ATF_USETRAILERS)
246: printf(" trailers");
247: printf("\n");
248: }
249:
250: /*
251: * Delete an arp entry
252: */
253: delete(host)
254: char *host;
255: {
256: struct arpreq ar;
257: struct hostent *hp;
258: struct sockaddr_in *sin;
259: int s;
260:
261: bzero((caddr_t)&ar, sizeof ar);
262: ar.arp_pa.sa_family = AF_INET;
263: sin = (struct sockaddr_in *)&ar.arp_pa;
264: sin->sin_family = AF_INET;
265: sin->sin_addr.s_addr = inet_addr(host);
266: if (sin->sin_addr.s_addr == -1) {
267: if (!(hp = gethostbyname(host))) {
268: fprintf(stderr, "arp: %s: ", host);
269: herror((char *)NULL);
270: exit(1);
271: }
272: bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
273: sizeof sin->sin_addr);
274: }
275: s = socket(AF_INET, SOCK_DGRAM, 0);
276: if (s < 0) {
277: perror("arp: socket");
278: exit(1);
279: }
280: if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) {
281: if (errno == ENXIO)
282: printf("%s (%s) -- no entry\n",
283: host, inet_ntoa(sin->sin_addr));
284: else
285: perror("SIOCDARP");
286: exit(1);
287: }
288: close(s);
289: printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
290: }
291:
292: struct nlist nl[] = {
293: #define X_ARPTAB 0
294: { "_arptab" },
295: #define X_ARPTAB_SIZE 1
296: { "_arptab_size" },
297: #define N_SYSMAP 2
298: { "_Sysmap" },
299: #define N_SYSSIZE 3
300: { "_Syssize" },
301: { "" },
302: };
303:
304: static struct pte *Sysmap;
305:
306: /*
307: * Dump the entire arp table
308: */
309: dump(kernel, mem)
310: char *kernel, *mem;
311: {
312: extern int h_errno;
313: struct arptab *at;
314: struct hostent *hp;
315: int bynumber, mf, arptab_size, sz;
316: char *host, *malloc();
317: off_t lseek();
318:
319: if (nlist(kernel, nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) {
320: fprintf(stderr, "arp: %s: bad namelist\n", kernel);
321: exit(1);
322: }
323: mf = open(mem, O_RDONLY);
324: if (mf < 0) {
325: fprintf(stderr, "arp: cannot open %s\n", mem);
326: exit(1);
327: }
328: if (kflag) {
329: off_t off;
330:
331: Sysmap = (struct pte *)
332: malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
333: if (!Sysmap) {
334: fputs("arp: can't get memory for Sysmap.\n", stderr);
335: exit(1);
336: }
337: off = nl[N_SYSMAP].n_value & ~KERNBASE;
338: (void)lseek(mf, off, L_SET);
339: (void)read(mf, (char *)Sysmap,
340: (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
341: }
342: klseek(mf, (long)nl[X_ARPTAB_SIZE].n_value, L_SET);
343: read(mf, &arptab_size, sizeof arptab_size);
344: if (arptab_size <= 0 || arptab_size > 1000) {
345: fprintf(stderr, "arp: %s: namelist wrong\n", kernel);
346: exit(1);
347: }
348: sz = arptab_size * sizeof (struct arptab);
349: at = (struct arptab *)malloc((u_int)sz);
350: if (at == NULL) {
351: fputs("arp: can't get memory for arptab.\n", stderr);
352: exit(1);
353: }
354: klseek(mf, (long)nl[X_ARPTAB].n_value, L_SET);
355: if (read(mf, (char *)at, sz) != sz) {
356: perror("arp: error reading arptab");
357: exit(1);
358: }
359: close(mf);
360: for (bynumber = 0; arptab_size-- > 0; at++) {
361: if (at->at_iaddr.s_addr == 0 || at->at_flags == 0)
362: continue;
363: if (bynumber == 0)
364: hp = gethostbyaddr((caddr_t)&at->at_iaddr,
365: sizeof at->at_iaddr, AF_INET);
366: else
367: hp = 0;
368: if (hp)
369: host = hp->h_name;
370: else {
371: host = "?";
372: if (h_errno == TRY_AGAIN)
373: bynumber = 1;
374: }
375: printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr));
376: if (at->at_flags & ATF_COM)
377: ether_print(at->at_enaddr);
378: else
379: printf("(incomplete)");
380: if (at->at_flags & ATF_PERM)
381: printf(" permanent");
382: if (at->at_flags & ATF_PUBL)
383: printf(" published");
384: if (at->at_flags & ATF_USETRAILERS)
385: printf(" trailers");
386: printf("\n");
387: }
388: }
389:
390: /*
391: * Seek into the kernel for a value.
392: */
393: klseek(fd, base, off)
394: int fd, off;
395: off_t base;
396: {
397: off_t lseek();
398:
399: if (kflag) { /* get kernel pte */
400: base &= ~KERNBASE;
401: base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
402: }
403: (void)lseek(fd, base, off);
404: }
405:
406: ether_print(cp)
407: u_char *cp;
408: {
409: printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
410: }
411:
412: ether_aton(a, n)
413: char *a;
414: u_char *n;
415: {
416: int i, o[6];
417:
418: i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
419: &o[3], &o[4], &o[5]);
420: if (i != 6) {
421: fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
422: return (1);
423: }
424: for (i=0; i<6; i++)
425: n[i] = o[i];
426: return (0);
427: }
428:
429: usage()
430: {
431: printf("usage: arp hostname\n");
432: printf(" arp -a [kernel] [kernel_memory]\n");
433: printf(" arp -d hostname\n");
434: printf(" arp -s hostname ether_addr [temp] [pub] [trail]\n");
435: printf(" arp -f filename\n");
436: exit(1);
437: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.