|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.