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