removed -N from usage, since it does not work correct (Debian Bug #50266)
[oss-qm-packages.git] / arp.c
blob97b59dea9c951232bdcd9fc36a0f6d05cd611fd1
1 /*
2 * arp This file contains an implementation of the command
3 * that maintains the kernel's ARP cache. It is derived
4 * from Berkeley UNIX arp(8), but cleaner and with sup-
5 * port for devices other than Ethernet.
7 * NET-TOOLS A collection of programs that form the base set of the
8 * NET-3 Networking Distribution for the LINUX operating
9 * system.
11 * Version: $Id: arp.c,v 1.18 2000/11/06 19:48:49 pb Exp $
13 * Maintainer: Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de>
15 * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
17 * Changes:
18 * (based on work from Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>)
19 * Alan Cox : modified for NET3
20 * Andrew Tridgell : proxy arp netmasks
21 * Bernd Eckenfels : -n option
22 * Bernd Eckenfels : Use only /proc for display
23 * {1.60} Bernd Eckenfels : new arpcode (-i) for 1.3.42 but works
24 * with 1.2.x, too
25 * {1.61} Bernd Eckenfels : more verbose messages
26 * {1.62} Bernd Eckenfels : check -t for hw adresses and try to
27 * explain EINVAL (jeff)
28 *970125 {1.63} Bernd Eckenfels : -a print hardwarename instead of tiltle
29 *970201 {1.64} Bernd Eckenfels : net-features.h support
30 *970203 {1.65} Bernd Eckenfels : "#define" in "#if",
31 * -H|-A additional to -t|-p
32 *970214 {1.66} Bernd Eckenfels : Fix optarg required for -H and -A
33 *970412 {1.67} Bernd Eckenfels : device=""; is default
34 *970514 {1.68} Bernd Eckenfels : -N and -D
35 *970517 {1.69} Bernd Eckenfels : usage() fixed
36 *970622 {1.70} Bernd Eckenfels : arp -d priv
37 *970106 {1.80} Bernd Eckenfels : new syntax without -D and with "dev <If>",
38 * ATF_MAGIC, ATF_DONTPUB support.
39 * Typo fix (Debian Bug#5728 Giuliano Procida)
40 *970803 {1.81} Bernd Eckenfels : removed junk comment line 1
41 *970925 {1.82} Bernd Eckenfels : include fix for libc6
42 *980213 (1.83) Phil Blundell: set ATF_COM on new entries
43 *980629 (1.84) Arnaldo Carvalho de Melo: gettext instead of catgets
44 *990101 {1.85} Bernd Eckenfels fixed usage and return codes
45 *990105 (1.86) Phil Blundell: don't ignore EINVAL in arp_set
46 *991121 (1.87) Bernd Eckenfels: yes --device has a mandatory arg
48 * This program is free software; you can redistribute it
49 * and/or modify it under the terms of the GNU General
50 * Public License as published by the Free Software
51 * Foundation; either version 2 of the License, or (at
52 * your option) any later version.
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <sys/ioctl.h>
57 #include <net/if.h>
58 /* #include <linux/netdevice.h> */
59 /* #include <linux/if_arp.h> */
60 #include <net/if_arp.h>
61 #include <stdlib.h>
62 #include <stdio.h>
63 #include <errno.h>
64 #include <ctype.h>
65 #include <fcntl.h>
66 #include <string.h>
67 #include <getopt.h>
68 #include <unistd.h>
69 #include "net-support.h"
70 #include "pathnames.h"
71 #include "version.h"
72 #include "config.h"
73 #include "intl.h"
74 #include "util.h"
76 #define DFLT_AF "inet"
77 #define DFLT_HW "ether"
79 #define FEATURE_ARP
80 #include "lib/net-features.h"
82 char *Release = RELEASE, *Version = "arp 1.87 (1999-11-21)";
84 int opt_n = 0; /* do not resolve addresses */
85 int opt_N = 0; /* use symbolic names */
86 int opt_v = 0; /* debugging output flag */
87 int opt_D = 0; /* HW-address is devicename */
88 int opt_e = 0; /* 0=BSD output, 1=new linux */
89 int opt_a = 0; /* all entries, substring match */
90 struct aftype *ap; /* current address family */
91 struct hwtype *hw; /* current hardware type */
92 int sockfd = 0; /* active socket descriptor */
93 int hw_set = 0; /* flag if hw-type was set (-H) */
94 char device[16] = ""; /* current device */
95 static void usage(void);
97 /* Delete an entry from the ARP cache. */
98 static int arp_del(char **args)
100 char host[128];
101 struct arpreq req;
102 struct sockaddr sa;
103 int flags = 0;
104 int err;
106 memset((char *) &req, 0, sizeof(req));
108 /* Resolve the host name. */
109 if (*args == NULL) {
110 fprintf(stderr, _("arp: need host name\n"));
111 return (-1);
113 safe_strncpy(host, *args, (sizeof host));
114 if (ap->input(0, host, &sa) < 0) {
115 ap->herror(host);
116 return (-1);
118 /* If a host has more than one address, use the correct one! */
119 memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
121 if (hw_set)
122 req.arp_ha.sa_family = hw->type;
124 req.arp_flags = ATF_PERM;
125 args++;
126 while (*args != NULL) {
127 if (opt_v)
128 fprintf(stderr, "args=%s\n", *args);
129 if (!strcmp(*args, "pub")) {
130 flags |= 1;
131 args++;
132 continue;
134 if (!strcmp(*args, "priv")) {
135 flags |= 2;
136 args++;
137 continue;
139 if (!strcmp(*args, "temp")) {
140 req.arp_flags &= ~ATF_PERM;
141 args++;
142 continue;
144 if (!strcmp(*args, "trail")) {
145 req.arp_flags |= ATF_USETRAILERS;
146 args++;
147 continue;
149 if (!strcmp(*args, "dontpub")) {
150 #ifdef HAVE_ATF_DONTPUB
151 req.arp_flags |= ATF_DONTPUB;
152 #else
153 ENOSUPP("arp", "ATF_DONTPUB");
154 #endif
155 args++;
156 continue;
158 if (!strcmp(*args, "auto")) {
159 #ifdef HAVE_ATF_MAGIC
160 req.arp_flags |= ATF_MAGIC;
161 #else
162 ENOSUPP("arp", "ATF_MAGIC");
163 #endif
164 args++;
165 continue;
167 if (!strcmp(*args, "dev")) {
168 if (*++args == NULL)
169 usage();
170 safe_strncpy(device, *args, sizeof(device));
171 args++;
172 continue;
174 if (!strcmp(*args, "netmask")) {
175 if (*++args == NULL)
176 usage();
177 if (strcmp(*args, "255.255.255.255") != 0) {
178 strcpy(host, *args);
179 if (ap->input(0, host, &sa) < 0) {
180 ap->herror(host);
181 return (-1);
183 memcpy((char *) &req.arp_netmask, (char *) &sa,
184 sizeof(struct sockaddr));
185 req.arp_flags |= ATF_NETMASK;
187 args++;
188 continue;
190 usage();
192 if (flags == 0)
193 flags = 3;
195 strcpy(req.arp_dev, device);
197 err = -1;
199 /* Call the kernel. */
200 if (flags & 2) {
201 if (opt_v)
202 fprintf(stderr, "arp: SIOCDARP(nopub)\n");
203 if ((err = ioctl(sockfd, SIOCDARP, &req) < 0)) {
204 if (errno == ENXIO) {
205 if (flags & 1)
206 goto nopub;
207 printf(_("No ARP entry for %s\n"), host);
208 return (-1);
210 perror("SIOCDARP(priv)");
211 return (-1);
214 if ((flags & 1) && (err)) {
215 nopub:
216 req.arp_flags |= ATF_PUBL;
217 if (opt_v)
218 fprintf(stderr, "arp: SIOCDARP(pub)\n");
219 if (ioctl(sockfd, SIOCDARP, &req) < 0) {
220 if (errno == ENXIO) {
221 printf(_("No ARP entry for %s\n"), host);
222 return (-1);
224 perror("SIOCDARP(pub)");
225 return (-1);
228 return (0);
231 /* Get the hardware address to a specified interface name */
232 static int arp_getdevhw(char *ifname, struct sockaddr *sa, struct hwtype *hw)
234 struct ifreq ifr;
235 struct hwtype *xhw;
237 strcpy(ifr.ifr_name, ifname);
238 if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
239 fprintf(stderr, _("arp: cant get HW-Address for `%s': %s.\n"), ifname, strerror(errno));
240 return (-1);
242 if (hw && (ifr.ifr_hwaddr.sa_family != hw->type)) {
243 fprintf(stderr, _("arp: protocol type mismatch.\n"));
244 return (-1);
246 memcpy((char *) sa, (char *) &(ifr.ifr_hwaddr), sizeof(struct sockaddr));
248 if (opt_v) {
249 if (!(xhw = get_hwntype(ifr.ifr_hwaddr.sa_family)) || (xhw->print == 0)) {
250 xhw = get_hwntype(-1);
252 fprintf(stderr, _("arp: device `%s' has HW address %s `%s'.\n"), ifname, xhw->name, xhw->print((char *)&ifr.ifr_hwaddr.sa_data));
254 return (0);
257 /* Set an entry in the ARP cache. */
258 static int arp_set(char **args)
260 char host[128];
261 struct arpreq req;
262 struct sockaddr sa;
263 int flags;
265 memset((char *) &req, 0, sizeof(req));
267 /* Resolve the host name. */
268 if (*args == NULL) {
269 fprintf(stderr, _("arp: need host name\n"));
270 return (-1);
272 safe_strncpy(host, *args++, (sizeof host));
273 if (ap->input(0, host, &sa) < 0) {
274 ap->herror(host);
275 return (-1);
277 /* If a host has more than one address, use the correct one! */
278 memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
280 /* Fetch the hardware address. */
281 if (*args == NULL) {
282 fprintf(stderr, _("arp: need hardware address\n"));
283 return (-1);
285 if (opt_D) {
286 if (arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL) < 0)
287 return (-1);
288 } else {
289 if (hw->input(*args++, &req.arp_ha) < 0) {
290 fprintf(stderr, _("arp: invalid hardware address\n"));
291 return (-1);
295 /* Check out any modifiers. */
296 flags = ATF_PERM | ATF_COM;
297 while (*args != NULL) {
298 if (!strcmp(*args, "temp")) {
299 flags &= ~ATF_PERM;
300 args++;
301 continue;
303 if (!strcmp(*args, "pub")) {
304 flags |= ATF_PUBL;
305 args++;
306 continue;
308 if (!strcmp(*args, "priv")) {
309 flags &= ~ATF_PUBL;
310 args++;
311 continue;
313 if (!strcmp(*args, "trail")) {
314 flags |= ATF_USETRAILERS;
315 args++;
316 continue;
318 if (!strcmp(*args, "dontpub")) {
319 #ifdef HAVE_ATF_DONTPUB
320 flags |= ATF_DONTPUB;
321 #else
322 ENOSUPP("arp", "ATF_DONTPUB");
323 #endif
324 args++;
325 continue;
327 if (!strcmp(*args, "auto")) {
328 #ifdef HAVE_ATF_MAGIC
329 flags |= ATF_MAGIC;
330 #else
331 ENOSUPP("arp", "ATF_MAGIC");
332 #endif
333 args++;
334 continue;
336 if (!strcmp(*args, "dev")) {
337 if (*++args == NULL)
338 usage();
339 safe_strncpy(device, *args, sizeof(device));
340 args++;
341 continue;
343 if (!strcmp(*args, "netmask")) {
344 if (*++args == NULL)
345 usage();
346 if (strcmp(*args, "255.255.255.255") != 0) {
347 strcpy(host, *args);
348 if (ap->input(0, host, &sa) < 0) {
349 ap->herror(host);
350 return (-1);
352 memcpy((char *) &req.arp_netmask, (char *) &sa,
353 sizeof(struct sockaddr));
354 flags |= ATF_NETMASK;
356 args++;
357 continue;
359 usage();
362 /* Fill in the remainder of the request. */
363 req.arp_flags = flags;
365 strcpy(req.arp_dev, device);
367 /* Call the kernel. */
368 if (opt_v)
369 fprintf(stderr, "arp: SIOCSARP()\n");
370 if (ioctl(sockfd, SIOCSARP, &req) < 0) {
371 perror("SIOCSARP");
372 return (-1);
374 return (0);
378 /* Process an EtherFile */
379 static int arp_file(char *name)
381 char buff[1024];
382 char *sp, *args[32];
383 int linenr, argc;
384 FILE *fp;
386 if ((fp = fopen(name, "r")) == NULL) {
387 fprintf(stderr, _("arp: cannot open etherfile %s !\n"), name);
388 return (-1);
390 /* Read the lines in the file. */
391 linenr = 0;
392 while (fgets(buff, sizeof(buff), fp) != (char *) NULL) {
393 linenr++;
394 if (opt_v == 1)
395 fprintf(stderr, ">> %s", buff);
396 if ((sp = strchr(buff, '\n')) != (char *) NULL)
397 *sp = '\0';
398 if (buff[0] == '#' || buff[0] == '\0')
399 continue;
401 argc = getargs(buff, args);
402 if (argc < 2) {
403 fprintf(stderr, _("arp: format error on line %u of etherfile %s !\n"),
404 linenr, name);
405 continue;
407 if (strchr (args[0], ':') != NULL) {
408 /* We have a correct ethers file, switch hw adress and hostname
409 for arp */
410 char *cp;
411 cp = args[1];
412 args[1] = args[0];
413 args[0] = cp;
415 if (arp_set(args) != 0)
416 fprintf(stderr, _("arp: cannot set entry on line %u of etherfile %s !\n"),
417 linenr, name);
420 (void) fclose(fp);
421 return (0);
425 /* Print the contents of an ARP request block. */
426 static void arp_disp_2(char *name, int type, int arp_flags, char *hwa, char *mask, char *dev)
428 static int title = 0;
429 struct hwtype *xhw;
430 char flags[10];
432 xhw = get_hwntype(type);
433 if (xhw == NULL)
434 xhw = get_hwtype(DFLT_HW);
436 if (title++ == 0) {
437 printf(_("Address\t\t\tHWtype\tHWaddress\t Flags Mask\t\t Iface\n"));
439 /* Setup the flags. */
440 flags[0] = '\0';
441 if (arp_flags & ATF_COM)
442 strcat(flags, "C");
443 if (arp_flags & ATF_PERM)
444 strcat(flags, "M");
445 if (arp_flags & ATF_PUBL)
446 strcat(flags, "P");
447 #ifdef HAVE_ATF_MAGIC
448 if (arp_flags & ATF_MAGIC)
449 strcat(flags, "A");
450 #endif
451 #ifdef HAVE_ATF_DONTPUB
452 if (arp_flags & ATF_DONTPUB)
453 strcat(flags, "!");
454 #endif
455 if (arp_flags & ATF_USETRAILERS)
456 strcat(flags, "T");
458 if (!(arp_flags & ATF_NETMASK))
459 mask = "";
461 printf("%-23.23s\t", name);
463 if (!(arp_flags & ATF_COM)) {
464 if (arp_flags & ATF_PUBL)
465 printf("%-8.8s%-20.20s", "*", "*");
466 else
467 printf("%-8.8s%-20.20s", "", _("(incomplete)"));
468 } else {
469 printf("%-8.8s%-20.20s", xhw->name, hwa);
472 printf("%-6.6s%-15.15s %s\n", flags, mask, dev);
475 /* Print the contents of an ARP request block. */
476 static void arp_disp(char *name, char *ip, int type, int arp_flags, char *hwa, char *mask, char *dev)
478 struct hwtype *xhw;
480 xhw = get_hwntype(type);
481 if (xhw == NULL)
482 xhw = get_hwtype(DFLT_HW);
484 printf(_("%s (%s) at "), name, ip);
486 if (!(arp_flags & ATF_COM)) {
487 if (arp_flags & ATF_PUBL)
488 printf("* ");
489 else
490 printf(_("<incomplete> "));
491 } else {
492 printf("%s [%s] ", hwa, xhw->name);
495 if (arp_flags & ATF_NETMASK)
496 printf(_("netmask %s "), mask);
498 if (arp_flags & ATF_PERM)
499 printf("PERM ");
500 if (arp_flags & ATF_PUBL)
501 printf("PUP ");
502 #ifdef HAVE_ATF_MAGIC
503 if (arp_flags & ATF_MAGIC)
504 printf("AUTO ");
505 #endif
506 #ifdef HAVE_ATF_DONTPUB
507 if (arp_flags & ATF_DONTPUB)
508 printf("DONTPUB ");
509 #endif
510 if (arp_flags & ATF_USETRAILERS)
511 printf("TRAIL ");
513 printf(_("on %s\n"), dev);
517 /* Display the contents of the ARP cache in the kernel. */
518 static int arp_show(char *name)
520 char host[100];
521 struct sockaddr sa;
522 char ip[100];
523 char hwa[100];
524 char mask[100];
525 char line[200];
526 char dev[100];
527 int type, flags;
528 FILE *fp;
529 char *hostname;
530 int num, entries = 0, showed = 0;
532 host[0] = '\0';
534 if (name != NULL) {
535 /* Resolve the host name. */
536 safe_strncpy(host, name, (sizeof host));
537 if (ap->input(0, host, &sa) < 0) {
538 ap->herror(host);
539 return (-1);
541 safe_strncpy(host, ap->sprint(&sa, 1), sizeof(host));
543 /* Open the PROCps kernel table. */
544 if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) {
545 perror(_PATH_PROCNET_ARP);
546 return (-1);
548 /* Bypass header -- read until newline */
549 if (fgets(line, sizeof(line), fp) != (char *) NULL) {
550 strcpy(mask, "-");
551 strcpy(dev, "-");
552 /* Read the ARP cache entries. */
553 for (; fgets(line, sizeof(line), fp);) {
554 num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s\n",
555 ip, &type, &flags, hwa, mask, dev);
556 if (num < 4)
557 break;
559 entries++;
560 /* if the user specified hw-type differs, skip it */
561 if (hw_set && (type != hw->type))
562 continue;
564 /* if the user specified address differs, skip it */
565 if (host[0] && strcmp(ip, host))
566 continue;
568 /* if the user specified device differs, skip it */
569 if (device[0] && strcmp(dev, device))
570 continue;
572 showed++;
573 /* This IS ugly but it works -be */
574 if (opt_n)
575 hostname = "?";
576 else {
577 if (ap->input(0, ip, &sa) < 0)
578 hostname = ip;
579 else
580 hostname = ap->sprint(&sa, opt_n | 0x8000);
581 if (strcmp(hostname, ip) == 0)
582 hostname = "?";
585 if (opt_e)
586 arp_disp_2(hostname[0] == '?' ? ip : hostname, type, flags, hwa, mask, dev);
587 else
588 arp_disp(hostname, ip, type, flags, hwa, mask, dev);
591 if (opt_v)
592 printf(_("Entries: %d\tSkipped: %d\tFound: %d\n"), entries, entries - showed, showed);
594 if (!showed) {
595 if (host[0] && !opt_a)
596 printf(_("%s (%s) -- no entry\n"), name, host);
597 else if (hw_set || host[0] || device[0]) {
598 printf(_("arp: in %d entries no match found.\n"), entries);
601 (void) fclose(fp);
602 return (0);
605 static void version(void)
607 fprintf(stderr, "%s\n%s\n%s\n", Release, Version, Features);
608 exit(E_VERSION);
611 static void usage(void)
613 fprintf(stderr, _("Usage:\n arp [-vn] [<HW>] [-i <if>] [-a] [<hostname>] <-Display ARP cache\n"));
614 fprintf(stderr, _(" arp [-v] [-i <if>] -d <hostname> [pub][nopub] <-Delete ARP entry\n"));
615 fprintf(stderr, _(" arp [-vnD] [<HW>] [-i <if>] -f [<filename>] <-Add entry from file\n"));
616 fprintf(stderr, _(" arp [-v] [<HW>] [-i <if>] -s <hostname> <hwaddr> [temp][nopub] <-Add entry\n"));
617 fprintf(stderr, _(" arp [-v] [<HW>] [-i <if>] -s <hostname> <hwaddr> [netmask <nm>] pub <-''-\n"));
618 fprintf(stderr, _(" arp [-v] [<HW>] [-i <if>] -Ds <hostname> <if> [netmask <nm>] pub <-''-\n\n"));
620 fprintf(stderr, _(" -a display (all) hosts in alternative (BSD) style\n"));
621 fprintf(stderr, _(" -s, --set set a new ARP entry\n"));
622 fprintf(stderr, _(" -d, --delete delete a specified entry\n"));
623 fprintf(stderr, _(" -v, --verbose be verbose\n"));
624 fprintf(stderr, _(" -n, --numeric don't resolve names\n"));
625 fprintf(stderr, _(" -i, --device specify network interface (e.g. eth0)\n"));
626 fprintf(stderr, _(" -D, --use-device read <hwaddr> from given device\n"));
627 fprintf(stderr, _(" -A, -p, --protocol specify protocol family\n"));
628 fprintf(stderr, _(" -f, --file read new entries from file or from /etc/ethers\n\n"));
630 fprintf(stderr, _(" <HW>=Use '-H <hw>' to specify hardware address type. Default: %s\n"), DFLT_HW);
631 fprintf(stderr, _(" List of possible hardware types (which support ARP):\n"));
632 print_hwlist(1); /* 1 = ARPable */
633 exit(E_USAGE);
636 int main(int argc, char **argv)
638 int i, lop, what;
639 struct option longopts[] =
641 {"verbose", 0, 0, 'v'},
642 {"version", 0, 0, 'V'},
643 {"all", 0, 0, 'a'},
644 {"delete", 0, 0, 'd'},
645 {"file", 0, 0, 'f'},
646 {"numeric", 0, 0, 'n'},
647 {"set", 0, 0, 's'},
648 {"protocol", 1, 0, 'A'},
649 {"hw-type", 1, 0, 'H'},
650 {"device", 1, 0, 'i'},
651 {"help", 0, 0, 'h'},
652 {"use-device", 0, 0, 'D'},
653 {"symbolic", 0, 0, 'N'},
654 {NULL, 0, 0, 0}
657 #if I18N
658 bindtextdomain("net-tools", "/usr/share/locale");
659 textdomain("net-tools");
660 #endif
662 /* Initialize variables... */
663 if ((hw = get_hwtype(DFLT_HW)) == NULL) {
664 fprintf(stderr, _("%s: hardware type not supported!\n"), DFLT_HW);
665 return (-1);
667 if ((ap = get_aftype(DFLT_AF)) == NULL) {
668 fprintf(stderr, _("%s: address family not supported!\n"), DFLT_AF);
669 return (-1);
671 what = 0;
673 /* Fetch the command-line arguments. */
674 /* opterr = 0; */
675 while ((i = getopt_long(argc, argv, "A:H:adfp:nsei:t:vh?DNV", longopts, &lop)) != EOF)
676 switch (i) {
677 case 'a':
678 what = 1;
679 opt_a = 1;
680 break;
681 case 'f':
682 what = 2;
683 break;
684 case 'd':
685 what = 3;
686 break;
687 case 's':
688 what = 4;
689 break;
692 case 'e':
693 opt_e = 1;
694 break;
695 case 'n':
696 opt_n = FLAG_NUM;
697 break;
698 case 'D':
699 opt_D = 1;
700 break;
701 case 'N':
702 opt_N = FLAG_SYM;
703 fprintf(stderr, _("arp: -N not yet supported.\n"));
704 break;
705 case 'v':
706 opt_v = 1;
707 break;
709 case 'A':
710 case 'p':
711 ap = get_aftype(optarg);
712 if (ap == NULL) {
713 fprintf(stderr, _("arp: %s: unknown address family.\n"),
714 optarg);
715 exit(-1);
717 break;
718 case 'H':
719 case 't':
720 hw = get_hwtype(optarg);
721 if (hw == NULL) {
722 fprintf(stderr, _("arp: %s: unknown hardware type.\n"),
723 optarg);
724 exit(-1);
726 hw_set = 1;
727 break;
728 case 'i':
729 safe_strncpy(device, optarg, sizeof(device));
730 break;
732 case 'V':
733 version();
734 case '?':
735 case 'h':
736 default:
737 usage();
740 if (ap->af != AF_INET) {
741 fprintf(stderr, _("arp: %s: kernel only supports 'inet'.\n"),
742 ap->name);
743 exit(-1);
746 /* If not hw type specified get default */
747 if(hw_set==0)
748 if ((hw = get_hwtype(DFLT_HW)) == NULL) {
749 fprintf(stderr, _("%s: hardware type not supported!\n"), DFLT_HW);
750 return (-1);
753 if (hw->alen <= 0) {
754 fprintf(stderr, _("arp: %s: hardware type without ARP support.\n"),
755 hw->name);
756 exit(-1);
758 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
759 perror("socket");
760 exit(-1);
762 /* Now see what we have to do here... */
763 switch (what) {
764 case 0:
765 opt_e = 1;
766 what = arp_show(argv[optind]);
767 break;
769 case 1: /* show an ARP entry in the cache */
770 what = arp_show(argv[optind]);
771 break;
773 case 2: /* process an EtherFile */
774 what = arp_file(argv[optind] ? argv[optind] : "/etc/ethers");
775 break;
777 case 3: /* delete an ARP entry from the cache */
778 what = arp_del(&argv[optind]);
779 break;
781 case 4: /* set an ARP entry in the cache */
782 what = arp_set(&argv[optind]);
783 break;
785 default:
786 usage();
789 exit(what);