source: trunk/minix/commands/simple/arp.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 9.1 KB
Line 
1/*
2arp.c
3
4Created: Jan 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
5
6Manipulate ARP table
7*/
8
9#define _POSIX_C_SOURCE 2
10#define _MINIX_SOURCE
11
12#include <errno.h>
13#include <fcntl.h>
14#include <stdarg.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19
20#include <sys/ioctl.h>
21
22#include <net/netlib.h>
23#include <net/gen/ether.h>
24#include <net/gen/if_ether.h>
25#include <net/gen/in.h>
26#include <net/gen/inet.h>
27#include <net/gen/ip_io.h>
28#include <net/gen/netdb.h>
29#include <net/gen/socket.h>
30
31#include <net/gen/arp_io.h>
32
33char *progname;
34static int ipfd= -1;
35static int do_setuid= 0;
36
37static void do_open(char *devname);
38static void show_one(char *hostname, int do_num);
39static void show_all(int do_num);
40static void print_one(ipaddr_t ipaddr, nwio_arp_t *arpp, int do_num);
41static void delete_all(void);
42static void delete(char *hostname);
43static void do_set(char *hostname, char *ethername, int temp, int pub,
44 int optdelete);
45static ipaddr_t nametoipaddr(char *hostname);
46static void fatal(char *fmt, ...);
47static void usage(void);
48
49int main(int argc, char *argv[])
50{
51 int c;
52 char *hostname, *ethername;
53 int do_temp, do_pub;
54 int a_flag, d_flag, n_flag, s_flag, S_flag;
55 char *I_arg;
56
57 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
58
59 a_flag= d_flag= n_flag= s_flag= S_flag= 0;
60 I_arg= NULL;
61 while(c= getopt(argc, argv, "adnsS?I:"), c != -1)
62 {
63 switch(c)
64 {
65 case '?': usage();
66 case 'a': a_flag= 1; break;
67 case 'd': d_flag= 1; break;
68 case 'n': n_flag= 1; break;
69 case 's': s_flag= 1; break;
70 case 'S': S_flag= 1; break;
71 case 'I': I_arg= optarg; break;
72 default: fatal("getopt failed: '%c'", c);
73 }
74 }
75
76 hostname= NULL; /* lint */
77 ethername= NULL; /* lint */
78 do_temp= do_pub= 0; /* lint */
79
80 if (n_flag + d_flag + s_flag + S_flag > 1)
81 usage();
82 if (s_flag || S_flag)
83 {
84 if (optind >= argc) usage();
85 hostname= argv[optind++];
86
87 if (optind >= argc) usage();
88 ethername= argv[optind++];
89
90 do_temp= do_pub= 0;
91 while (optind < argc)
92 {
93 if (strcasecmp(argv[optind], "temp") == 0)
94 {
95 do_temp= 1;
96 optind++;
97 continue;
98 }
99 if (strcasecmp(argv[optind], "pub") == 0)
100 {
101 do_pub= 1;
102 optind++;
103 continue;
104 }
105 usage();
106 }
107 }
108 else if (d_flag)
109 {
110 if (!a_flag)
111 {
112 if (optind >= argc)
113 usage();
114 hostname= argv[optind++];
115 if (optind != argc)
116 usage();
117 }
118 }
119 else if (a_flag)
120 {
121 if (optind != argc)
122 usage();
123 do_setuid= 1;
124 }
125 else
126 {
127 if (optind >= argc)
128 usage();
129 hostname= argv[optind++];
130 if (optind != argc)
131 usage();
132 do_setuid= 1;
133 }
134
135 do_open(I_arg);
136 if (d_flag)
137 {
138 if (a_flag)
139 delete_all();
140 else
141 delete(hostname);
142 }
143 else if (s_flag || S_flag)
144 do_set(hostname, ethername, do_temp, do_pub, S_flag);
145 else if (a_flag)
146 show_all(n_flag);
147 else
148 show_one(hostname, n_flag);
149 exit(0);
150}
151
152static void do_open(char *devname)
153{
154 size_t l;
155 char *check;
156
157 if (do_setuid && devname)
158 {
159 /* Only strings that consist of IP_DEVICE optionally
160 * followed by a number are allowed.
161 */
162 l= strlen(IP_DEVICE);
163 if (strncmp(devname, IP_DEVICE, l) != 0)
164 do_setuid= 0;
165 else if (strlen(devname) == l)
166 ; /* OK */
167 else
168 {
169 strtoul(devname+l, &check, 10);
170 if (check[0] != '\0')
171 do_setuid= 0;
172 }
173 }
174 if (!devname)
175 devname= IP_DEVICE;
176 if (!do_setuid)
177 {
178 setuid(getuid());
179 setgid(getgid());
180 }
181 ipfd= open(devname, O_RDWR);
182 if (ipfd == -1)
183 fatal("unable to open '%s': %s", devname, strerror(errno));
184}
185
186static void show_one(char *hostname, int do_num)
187{
188 int r;
189 ipaddr_t ipaddr;
190 nwio_arp_t arp;
191
192 ipaddr= nametoipaddr(hostname);
193
194 arp.nwa_ipaddr= ipaddr;
195 r= ioctl(ipfd, NWIOARPGIP, &arp);
196 if (r == -1 && errno == ENOENT)
197 {
198 print_one(ipaddr, NULL, do_num);
199 exit(1);
200 }
201 if (r == -1)
202 fatal("NWIOARPGIP failed: %s", strerror(errno));
203 print_one(ipaddr, &arp, do_num);
204}
205
206static void show_all(int do_num)
207{
208 int ind, max, i, r;
209 nwio_arp_t *arptab;
210 nwio_arp_t arp;
211
212 /* First get all entries */
213 max= 10;
214 ind= 0;
215 arptab= malloc(max * sizeof(*arptab));
216 if (arptab == NULL)
217 {
218 fatal("out of memory, can't get %d bytes",
219 max*sizeof(*arptab));
220 }
221 arp.nwa_entno= 0;
222 for (;;)
223 {
224 if (ind == max)
225 {
226 max *= 2;
227 arptab= realloc(arptab, max * sizeof(*arptab));
228 if (!arptab)
229 {
230 fatal("out of memory, can't get %d bytes",
231 max*sizeof(*arptab));
232 }
233 }
234 r= ioctl(ipfd, NWIOARPGNEXT, &arp);
235 if (r == -1 && errno == ENOENT)
236 break;
237 if (r == -1)
238 fatal("NWIOARPGNEXT failed: %s", strerror(errno));
239 arptab[ind]= arp;
240 ind++;
241 }
242
243 for (i= 0; i<ind; i++)
244 print_one(0, &arptab[i], do_num);
245}
246
247static void print_one(ipaddr_t ipaddr, nwio_arp_t *arpp, int do_num)
248{
249 u32_t flags;
250 struct hostent *he;
251
252 if (arpp)
253 ipaddr= arpp->nwa_ipaddr;
254 if (!do_num)
255 he= gethostbyaddr((char *)&ipaddr, sizeof(ipaddr), AF_INET);
256 else
257 he= NULL;
258 if (he)
259 printf("%s (%s)", he->h_name, inet_ntoa(ipaddr));
260 else
261 printf("%s", inet_ntoa(ipaddr));
262 if (!arpp)
263 {
264 printf(" -- no entry\n");
265 return;
266 }
267 flags= arpp->nwa_flags;
268 if (flags & NWAF_INCOMPLETE)
269 printf(" is incomplete");
270 else if (flags & NWAF_DEAD)
271 printf(" is dead");
272 else
273 {
274 printf(" is at %s", ether_ntoa(&arpp->nwa_ethaddr));
275 if (flags & NWAF_PERM)
276 printf(" permanent");
277 if (flags & NWAF_PUB)
278 printf(" published");
279 }
280 printf("\n");
281}
282
283static void delete_all(void)
284{
285 int ind, max, i, r;
286 nwio_arp_t *arptab;
287 nwio_arp_t arp;
288
289 /* First get all entries */
290 max= 10;
291 ind= 0;
292 arptab= malloc(max * sizeof(*arptab));
293 if (arptab == NULL)
294 {
295 fatal("out of memory, can't get %d bytes",
296 max*sizeof(*arptab));
297 }
298 arp.nwa_entno= 0;
299 for (;;)
300 {
301 if (ind == max)
302 {
303 max *= 2;
304 arptab= realloc(arptab, max * sizeof(*arptab));
305 if (arptab == NULL)
306 {
307 fatal("out of memory, can't get %d bytes",
308 max*sizeof(*arptab));
309 }
310 }
311 r= ioctl(ipfd, NWIOARPGNEXT, &arp);
312 if (r == -1 && errno == ENOENT)
313 break;
314 if (r == -1)
315 fatal("NWIOARPGNEXT failed: %s", strerror(errno));
316 arptab[ind]= arp;
317 ind++;
318 }
319
320 for (i= 0; i<ind; i++)
321 {
322 r= ioctl(ipfd, NWIOARPDIP, &arptab[i]);
323 if (r == 0)
324 continue;
325 if (errno == EINVAL || errno == ENOENT)
326 {
327 /* Entry is incomplete of entry is already deleted */
328 continue;
329 }
330 fatal("unable to delete host %s: %s",
331 inet_ntoa(arptab[i].nwa_ipaddr), strerror(errno));
332 }
333}
334
335static void delete(char *hostname)
336{
337 int r;
338 ipaddr_t ipaddr;
339 nwio_arp_t arp;
340
341 ipaddr= nametoipaddr(hostname);
342 arp.nwa_ipaddr= ipaddr;
343 r= ioctl(ipfd, NWIOARPDIP, &arp);
344 if (r == 0)
345 return;
346 if (errno == ENOENT)
347 {
348 print_one(ipaddr, NULL, 0);
349 exit(1);
350 }
351 fatal("unable to delete host %s: %s", inet_ntoa(ipaddr),
352 errno == EINVAL ? "entry is incomplete" : strerror(errno));
353}
354
355static void do_set(char *hostname, char *ethername, int temp, int pub,
356 int optdelete)
357{
358 int r;
359 ipaddr_t ipaddr;
360 ether_addr_t *eap;
361 ether_addr_t ethaddr;
362 nwio_arp_t arp;
363 nwio_ipconf_t ipconf;
364
365 ipaddr= nametoipaddr(hostname);
366 if (pub && strcasecmp(ethername, "auto") == 0)
367 {
368 r= ioctl(ipfd, NWIOGIPCONF, &ipconf);
369 if (r == -1)
370 fatal("NWIOGIPCONF failed: %s", strerror(errno));
371 arp.nwa_ipaddr= ipconf.nwic_ipaddr;
372 r= ioctl(ipfd, NWIOARPGIP, &arp);
373 if (r == -1)
374 fatal("NWIOARPGIP failed: %s", strerror(errno));
375 ethaddr= arp.nwa_ethaddr;
376 }
377 else if (eap= ether_aton(ethername), eap != NULL)
378 ethaddr= *eap;
379 else if (ether_hostton(ethername, &ethaddr) != 0)
380 {
381 fatal("unable to parse ethernet address '%s'",
382 ethername);
383 }
384
385 if (optdelete)
386 {
387 arp.nwa_ipaddr= ipaddr;
388 r= ioctl(ipfd, NWIOARPDIP, &arp);
389 if (r == -1 && errno != ENOENT)
390 {
391 fatal("unable to delete entry for host %s: %s",
392 inet_ntoa(ipaddr),
393 errno == EINVAL ? "incomplete entry" :
394 strerror(errno));
395 }
396 }
397
398 arp.nwa_ipaddr= ipaddr;
399 arp.nwa_ethaddr= ethaddr;
400 arp.nwa_flags= 0;
401 if (pub)
402 arp.nwa_flags |= NWAF_PUB;
403 if (!temp)
404 arp.nwa_flags |= NWAF_PERM;
405 r= ioctl(ipfd, NWIOARPSIP, &arp);
406 if (r == -1)
407 {
408 fatal("unable to set arp entry: %s",
409 errno == EEXIST ? "entry exists" : strerror(errno));
410 }
411}
412
413static ipaddr_t nametoipaddr(char *hostname)
414{
415 ipaddr_t ipaddr;
416 struct hostent *he;
417
418 if (inet_aton(hostname, &ipaddr) == 0)
419 {
420 he= gethostbyname(hostname);
421 if (!he)
422 fatal("unknown hostname '%s'", hostname);
423 if (he->h_addrtype != AF_INET ||
424 he->h_length != sizeof(ipaddr))
425 {
426 fatal("strange host '%s': addrtype %d, length %d",
427 he->h_addrtype, he->h_length);
428 }
429 memcpy(&ipaddr, he->h_addr, sizeof(ipaddr));
430 }
431 return ipaddr;
432}
433
434#if 0
435static char *ether_ntoa(struct ether_addr *eap)
436{
437 static char buf[]= "xx:xx:xx:xx:xx:xx";
438
439 sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
440 eap->ea_addr[0], eap->ea_addr[1],
441 eap->ea_addr[2], eap->ea_addr[3],
442 eap->ea_addr[4], eap->ea_addr[5]);
443 return buf;
444}
445#endif
446
447static void fatal(char *fmt, ...)
448{
449 va_list ap;
450
451 va_start(ap, fmt);
452 fprintf(stderr, "%s: ", progname);
453 vfprintf(stderr, fmt, ap);
454 fprintf(stderr, "\n");
455 va_end(ap);
456
457 exit(1);
458}
459
460static void usage(void)
461{
462 fprintf(stderr, "Usage:\tarp [-I ip-dev] [-n] hostname\n"
463 "\tarp [-I ip-dev] [-n] -a\n"
464 "\tarp [-I ip-dev] -d hostname\n"
465 "\tarp [-I ip-dev] -d -a\n"
466 "\tarp [-I ip-dev] -s hostname ether-addr [temp] [pub]\n"
467 "\tarp [-I ip-dev] -S hostname ether-addr [temp] [pub]\n");
468 exit(1);
469}
470
471/*
472 * $PchId: arp.c,v 1.3 2005/01/31 22:31:45 philip Exp $
473 */
Note: See TracBrowser for help on using the repository browser.