Replace outdated NLS support with GNU gettext (patch from
[platform/upstream/net-tools.git] / arp.c
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.
6  *
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.
10  *
11  * Version:     arp 1.83 (1998-02-13)
12  *
13  * Maintainer:  Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de>
14  *
15  * Author:      Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
16  *
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  *
45  *
46  *              This program is free software; you can redistribute it
47  *              and/or  modify it under  the terms of  the GNU General
48  *              Public  License as  published  by  the  Free  Software
49  *              Foundation;  either  version 2 of the License, or  (at
50  *              your option) any later version.
51  */
52 #include <sys/types.h>
53 #include <sys/socket.h>
54 #include <sys/ioctl.h>
55 #include <net/if.h>
56 /* #include <linux/netdevice.h> */
57 /* #include <linux/if_arp.h>    */
58 #include <net/if_arp.h>
59 #include <stdlib.h>
60 #include <stdio.h>
61 #include <errno.h>
62 #include <ctype.h>
63 #include <fcntl.h>
64 #include <string.h>
65 #include <getopt.h>
66 #include <unistd.h>
67 #include "net-support.h"
68 #include "pathnames.h"
69 #include "version.h"
70 #include "config.h"
71 #include "intl.h"
72
73 #define DFLT_AF "inet"
74 #define DFLT_HW "ether"
75
76 #define FEATURE_ARP
77 #include "lib/net-features.h"
78
79 char *Release = RELEASE,
80      *Version = "arp 1.84 (1998-06-29)";
81
82 int opt_n = 0;                          /* do not resolve addresses     */
83 int opt_N = 0;                          /* use symbolic names           */
84 int opt_v = 0;                          /* debugging output flag        */
85 int opt_D = 0;                          /* HW-address is devicename     */
86 int opt_e = 0;                          /* 0=BSD output, 1=new linux    */
87 int opt_a = 0;                          /* all entries, substring match */
88 struct aftype *ap;                      /* current address family       */
89 struct hwtype *hw;                      /* current hardware type        */
90 int sockfd=0;                           /* active socket descriptor     */
91 int hw_set = 0;                         /* flag if hw-type was set (-H) */
92 char device[16]="";                     /* current device               */
93 static void usage(void);
94
95 /* Delete an entry from the ARP cache. */
96 static int
97 arp_del(char **args)
98 {
99   char host[128];
100   struct arpreq req;
101   struct sockaddr sa;
102   int flags=0;
103   int err;
104
105   memset((char *) &req, 0, sizeof(req));
106
107   /* Resolve the host name. */
108   if (*args == NULL) {
109         fprintf(stderr, _("arp: need host name\n"));
110         return(-1);
111   }
112   host[(sizeof host)-1] = 0;
113   strncpy(host, *args, (sizeof host)-1);
114   if (ap->input(0, host, &sa) < 0) {
115         ap->herror(host);
116         return(-1);
117   }
118
119   /* If a host has more than one address, use the correct one! */
120   memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
121
122   if (hw_set) 
123         req.arp_ha.sa_family=hw->type;
124   
125   req.arp_flags=ATF_PERM;
126   args++;
127   while (*args != NULL) {
128         if (opt_v) fprintf(stderr,"args=%s\n",*args);
129         if (! strcmp(*args, "pub")) {
130                 flags |= 1;
131                 args++;
132                 continue;
133         }
134         if (! strcmp(*args, "priv")) {
135                 flags |= 2;
136                 args++;
137                 continue;
138         }
139         if (! strcmp(*args, "temp")) {
140                 req.arp_flags &= ~ATF_PERM;
141                 args++;
142                 continue;
143         }
144         if (! strcmp(*args, "trail")) {
145                 req.arp_flags |= ATF_USETRAILERS;
146                 args++;
147                 continue;
148         }
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;
157         }
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;
166         }
167         if (! strcmp(*args, "dev")) {
168                 if (*++args == NULL) usage();
169                 strncpy(device,*args,sizeof(device)-1);
170                 device[sizeof(device)-1]='\0';
171                 args++;
172                 continue;
173         }
174         if (! strcmp(*args, "netmask")) {
175                 if (*++args == NULL) usage();
176                 if (strcmp(*args,"255.255.255.255") != 0) {
177                         strcpy(host, *args);
178                         if (ap->input(0, host, &sa) < 0) {
179                                 ap->herror(host);
180                                 return(-1);
181                         }
182                         memcpy((char *) &req.arp_netmask, (char *) &sa,
183                         sizeof(struct sockaddr));
184                         req.arp_flags |= ATF_NETMASK;
185                 }
186                 args++;
187                 continue;
188         }
189         usage();
190   }
191   if (flags == 0)
192         flags = 3;
193
194   strcpy(req.arp_dev,device);
195
196   err = -1;
197
198   /* Call the kernel. */
199   if (flags & 2) {
200         if (opt_v)  fprintf(stderr,"arp: SIOCDARP(nopub)\n");
201         if ((err = ioctl(sockfd, SIOCDARP, &req) < 0)) {
202                 if (errno == ENXIO) {
203                         if (flags & 1)
204                                 goto nopub;
205                         printf(_("No ARP entry for %s\n"), host);
206                         return(-1);
207                 }
208                 perror("SIOCDARP(priv)");
209                 return(-1);
210         }
211   }
212   if ((flags & 1) && (err)) {
213 nopub:
214         req.arp_flags |= ATF_PUBL;
215         if (opt_v)  fprintf(stderr,"arp: SIOCDARP(pub)\n");
216         if (ioctl(sockfd, SIOCDARP, &req) < 0) {
217                 if (errno == ENXIO) {
218                         printf(_("No ARP entry for %s\n"), host);
219                         return(-1);
220                 }
221                 perror("SIOCDARP(pub)");
222                 return(-1);
223         }
224   }
225
226   return(0);
227 }
228
229 /* Get the hardware address to a specified interface name */
230 static int
231 arp_getdevhw(char *ifname, struct sockaddr *sa, struct hwtype *hw)
232 {
233   struct ifreq ifr;
234   struct hwtype *xhw;
235
236   strcpy(ifr.ifr_name, ifname);
237   if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
238       fprintf(stderr,"arp: cant get HW-Address for `%s': %s.\n", ifname, strerror(errno));
239       return(-1);
240   }
241   if (hw && (ifr.ifr_hwaddr.sa_family!=hw->type)) {
242       fprintf(stderr,"arp: protocol type missmatch.\n");
243       return(-1);
244   }
245   memcpy((char *)sa, (char *)&(ifr.ifr_hwaddr), sizeof(struct sockaddr));
246
247   if (opt_v) {
248       if (!(xhw = get_hwntype(ifr.ifr_hwaddr.sa_family)) || (xhw->sprint==0)) {
249         xhw = get_hwntype(-1);
250       }
251       fprintf(stderr, "arp: device `%s' has HW address %s `%s'.\n",ifname, xhw->name, xhw->sprint(&ifr.ifr_hwaddr));
252   }
253   return(0);
254 }
255
256 /* Set an entry in the ARP cache. */
257 static int
258 arp_set(char **args)
259 {
260   char host[128];
261   struct arpreq req;
262   struct sockaddr sa;
263   int flags;
264
265   memset((char *) &req, 0, sizeof(req));
266
267   /* Resolve the host name. */
268   if (*args == NULL) {
269         fprintf(stderr, _("arp: need host name\n"));
270         return(-1);
271   }
272   host[(sizeof host)-1] = 0; 
273   strncpy(host, *args++, (sizeof host)-1);
274   if (ap->input(0, host, &sa) < 0) {
275         ap->herror(host);
276         return(-1);
277   }
278
279   /* If a host has more than one address, use the correct one! */
280   memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
281
282   /* Fetch the hardware address. */
283   if (*args == NULL) {
284         fprintf(stderr, _("arp: need hardware address\n"));
285         return(-1);
286   }
287
288   if (opt_D) {
289     if (arp_getdevhw(*args++, &req.arp_ha, hw_set?hw:NULL) < 0)
290       return(-1);
291   } else {
292     if (hw->input(*args++, &req.arp_ha) < 0) {
293         fprintf(stderr, _("arp: invalid hardware address\n"));
294         return(-1);
295     }
296   }
297   
298   /* Check out any modifiers. */
299   flags = ATF_PERM | ATF_COM;
300   while (*args != NULL) {
301         if (! strcmp(*args, "temp")) {
302                 flags &= ~ATF_PERM;
303                 args++;
304                 continue;
305         }
306         if (! strcmp(*args, "pub")) {
307                 flags |= ATF_PUBL;
308                 args++;
309                 continue;
310         }
311         if (! strcmp(*args, "priv")) {
312                 flags &= ~ATF_PUBL;
313                 args++;
314                 continue;
315         }
316         if (! strcmp(*args, "trail")) {
317                 flags |= ATF_USETRAILERS;
318                 args++;
319                 continue;
320         }
321         if (! strcmp(*args, "dontpub")) { 
322 #ifdef HAVE_ATF_DONTPUB
323                 flags |= ATF_DONTPUB;
324 #else
325                 ENOSUPP("arp", "ATF_DONTPUB");
326 #endif
327                 args++;
328                 continue;
329         }
330                 
331         if (! strcmp(*args, "auto")) {
332 #ifdef HAVE_ATF_MAGIC
333                 flags |= ATF_MAGIC;
334 #else
335                 ENOSUPP("arp", "ATF_MAGIC");
336 #endif
337                 args++;
338                 continue;
339         }
340         if (! strcmp(*args, "dev")) {
341                 if (*++args == NULL) usage();
342                 strncpy(device,*args,sizeof(device)-1);
343                 device[sizeof(device)-1]='\0';
344                 args++;
345                 continue;
346         }
347
348         if (! strcmp(*args, "netmask")) {
349                 if (*++args == NULL) usage();
350                 if (strcmp(*args,"255.255.255.255") != 0) {
351                         strcpy(host, *args);
352                         if (ap->input(0, host, &sa) < 0) {
353                                 ap->herror(host);
354                                 return(-1);
355                         }
356                         memcpy((char *) &req.arp_netmask, (char *) &sa,
357                                 sizeof(struct sockaddr));
358                         flags |= ATF_NETMASK;
359                 }
360                 args++;
361                 continue;
362         }
363         usage();
364   }
365
366   /* Fill in the remainder of the request. */
367   req.arp_flags = flags;
368
369   strcpy(req.arp_dev,device);
370
371   /* Call the kernel. */
372   if (opt_v)  fprintf(stderr,"arp: SIOCSARP()\n");
373   if (ioctl(sockfd, SIOCSARP, &req) < 0) {
374         if (errno != EINVAL) {
375                 perror("SIOCSARP");
376                 return(-1);
377         }
378   }
379
380   return(0);
381 }
382
383
384 /* Process an EtherFile */
385 static int
386 arp_file(char *name)
387 {
388   char buff[1024];
389   char *sp, *args[32];
390   int linenr, argc;
391   FILE *fp;
392
393   if ((fp = fopen(name, "r")) == NULL) {
394         fprintf(stderr, _("arp: cannot open etherfile %s !\n"), name);
395         return(-1);
396   }
397
398   /* Read the lines in the file. */
399   linenr = 0;
400   while (fgets(buff, sizeof(buff), fp) != (char *)NULL) {
401         linenr++;
402         if (opt_v == 1) fprintf(stderr, ">> %s", buff);
403         if ((sp = strchr(buff, '\n')) != (char *)NULL) *sp = '\0';
404         if (buff[0] == '#' || buff[0] == '\0') continue;
405
406         argc = getargs(buff, args);
407         if (argc < 2) {
408                 fprintf(stderr, _("arp: format error on line %u of etherfile %s !\n"),
409                         linenr, name);
410                 continue;
411         }
412
413         if (arp_set(args) != 0)
414                 fprintf(stderr, _("arp: cannot set entry on line %u of etherfile %s !\n"),
415                         linenr, name);
416   }
417
418   (void) fclose(fp);
419   return(0);
420 }
421
422
423 /* Print the contents of an ARP request block. */
424 static void
425 arp_disp_2(char *name,int type,int arp_flags,char *hwa,char *mask,char *dev)
426 {
427   static int title = 0;
428   struct hwtype *xhw;
429   char flags[10];
430   
431   xhw = get_hwntype(type);
432   if (xhw == NULL) 
433     xhw = get_hwtype(DFLT_HW);
434     
435   if (title++ == 0) {
436     printf(_("Address\t\t\tHWtype\tHWaddress\t    Flags Mask\t\t  Iface\n"));
437   }
438   /* Setup the flags. */
439   flags[0] = '\0';
440   if (arp_flags & ATF_COM) strcat(flags, "C");
441   if (arp_flags & ATF_PERM) strcat(flags, "M");
442   if (arp_flags & ATF_PUBL) strcat(flags, "P");
443 #ifdef HAVE_ATF_MAGIC
444   if (arp_flags & ATF_MAGIC) strcat(flags, "A");
445 #endif
446 #ifdef HAVE_ATF_DONTPUB
447   if (arp_flags & ATF_DONTPUB) strcat(flags, "!");
448 #endif
449   if (arp_flags & ATF_USETRAILERS) strcat(flags, "T");
450
451   if (!(arp_flags & ATF_NETMASK)) mask="";
452
453   printf("%-23.23s\t", name);
454
455   if (!(arp_flags & ATF_COM)) {
456         if (arp_flags & ATF_PUBL)
457                 printf("%-8.8s%-20.20s","*","*");
458         else
459                 printf("%-8.8s%-20.20s","","(incomplete)");
460   } else {
461         printf("%-8.8s%-20.20s", xhw->name, hwa);
462   }
463
464   printf("%-6.6s%-15.15s %s\n", flags,mask,dev);
465 }
466
467 /* Print the contents of an ARP request block. */
468 static void
469 arp_disp(char *name, char *ip, int type,int arp_flags,char *hwa,char *mask,char *dev)
470 {
471   struct hwtype *xhw;
472   
473   xhw = get_hwntype(type);
474   if (xhw == NULL) 
475     xhw = get_hwtype(DFLT_HW);
476     
477
478
479   printf("%s (%s) at ", name, ip);
480
481   if (!(arp_flags & ATF_COM)) {
482         if (arp_flags & ATF_PUBL)
483                 printf("* ");
484         else
485                 printf("<incomplete> ");
486   } else {
487         printf("%s [%s] ", hwa, xhw->name);
488   }
489   
490   if (arp_flags & ATF_NETMASK)
491         printf("netmask %s ", mask);
492   
493   if (arp_flags & ATF_PERM) printf("PERM ");
494   if (arp_flags & ATF_PUBL) printf("PUP ");
495 #ifdef HAVE_ATF_MAGIC
496   if (arp_flags & ATF_MAGIC) printf("AUTO ");
497 #endif
498 #ifdef HAVE_ATF_DONTPUB
499   if (arp_flags & ATF_DONTPUB) printf("DONTPUB ");
500 #endif
501   if (arp_flags & ATF_USETRAILERS) printf("TRAIL ");
502
503   printf("on %s\n", dev);
504 }
505
506
507 /* Display the contents of the ARP cache in the kernel. */
508 static int
509 arp_show(char *name)
510 {
511   char host[100];
512   struct sockaddr sa;
513   char ip[100];
514   char hwa[100];
515   char mask[100];
516   char line[200];
517   char dev[100];
518   int type,flags;
519   FILE *fp;
520   char *hostname;
521   int num,entries=0,showed=0;
522
523   host[0]='\0';
524   
525   if (name != NULL) {
526         /* Resolve the host name. */
527           host[(sizeof host)-1] = 0;
528         strncpy(host, name, (sizeof host)-1);
529         if (ap->input(0, host, &sa) < 0) {
530                 ap->herror(host);
531                 return(-1);
532         }
533         strcpy(host,ap->sprint(&sa, 1));
534   }
535   
536   /* Open the PROCps kernel table. */
537   if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) {
538         perror(_PATH_PROCNET_ARP);
539         return(-1);
540   }
541
542   /* Bypass header -- read until newline */
543   if (fgets(line, sizeof(line), fp) != (char *)NULL) {
544         strcpy(mask,"-");
545         strcpy(dev,"-");
546         /* Read the ARP cache entries. */
547         for(;fgets(line,sizeof(line),fp);)
548         {
549                 num=sscanf(line,"%s 0x%x 0x%x %100s %100s %100s\n",
550                                                ip,&type,&flags,hwa,mask,dev);
551                 if(num<4)
552                         break;
553                 
554                 entries++;      
555                 /* if the user specified hw-type differs, skip it */
556                 if (hw_set && (type != hw->type))
557                         continue;
558                         
559                 /* if the user specified address differs, skip it */
560                 if (host[0] && strcmp(ip,host))
561                         continue;
562                 
563                 /* if the user specified device differs, skip it */
564                 if (device[0] && strcmp(dev,device))
565                         continue;
566
567                 showed++;
568                 /* This IS ugly but it works -be */
569                 if (opt_n)
570                         hostname="?";
571                 else {
572                         if (ap->input(0, ip,&sa) < 0)
573                                 hostname=ip;
574                         else
575                                 hostname = ap->sprint(&sa, opt_n | 0x8000);
576                         if (strcmp(hostname, ip)==0)
577                                 hostname="?";
578                 }
579
580                 if (opt_e)
581                         arp_disp_2(hostname[0]=='?'?ip:hostname,type,flags,hwa,mask,dev);
582                 else
583                         arp_disp(hostname,ip,type,flags,hwa,mask,dev);
584         }
585   }
586   if (opt_v)
587         printf(_("Entries: %d\tSkipped: %d\tFound: %d\n"),entries,entries-showed,showed);
588   
589   if (!showed) {
590         if (host[0] && !opt_a)
591                 printf("%s (%s) -- no entry\n", name, host);
592         else if (hw_set || host[0] || device[0]) {
593                 printf(_("arp: in %d entries no match found.\n"),entries);
594         }
595   }
596   (void) fclose(fp);
597   return(0);
598 }
599
600 static void
601 version(void)
602 {
603   fprintf(stderr, "%s\n%s\n%s\n",Release,Version,Features);
604   exit(-1);
605 }
606
607 static void
608 usage(void)
609 {
610   fprintf(stderr, _("Usage: arp [-vn] [-H type] [-i if] -a [hostname]\n"));
611   fprintf(stderr, _("       arp [-v] [-i if] -d hostname [pub][nopub]\n"));
612   fprintf(stderr, _("       arp [-v] [-H type] [-i if] -s  hostname hw_addr [temp][nopub]\n"));
613   fprintf(stderr, _("       arp [-v] [-H type] [-i if] -s  hostname hw_addr [netmask nm] pub\n"));
614   fprintf(stderr, _("       arp [-v] [-H type] [-i if] -Ds hostname if [netmask nm] pub\n"));
615   fprintf(stderr, _("       arp [-vnD] [-H type] [-i if] -f filename\n"));
616   exit(-1);
617 }
618
619 int
620 main(int argc, char **argv)
621 {
622   int i, lop, what;
623   struct option longopts[]=
624   {
625         {"verbose",     0,      0,      'v'},
626         {"version",     0,      0,      'V'},
627         {"all",         0,      0,      'a'},
628         {"delete",      0,      0,      'd'},
629         {"file",        0,      0,      'f'},
630         {"numeric",     0,      0,      'n'},
631         {"set",         0,      0,      's'},
632         {"protocol",    1,      0,      'A'},
633         {"hw-type",     1,      0,      'H'},
634         {"device",      0,      0,      'i'},
635         {"help",        0,      0,      'h'},
636         {"use-device",  0,      0,      'D'},
637         {"symbolic",    0,      0,      'N'},
638         {NULL,          0,      0,      0}
639   };    
640              
641 #if I18N
642   bindtextdomain("net-tools", "/usr/share/locale");
643   textdomain("net-tools");
644 #endif
645
646   /* Initialize variables... */
647   if ((hw = get_hwtype(DFLT_HW)) == NULL) {
648         fprintf(stderr, _("%s: hardware type not supported!\n"), DFLT_HW);
649         return(-1);
650   }
651   if ((ap = get_aftype(DFLT_AF)) == NULL) {
652         fprintf(stderr, _("%s: address family not supported!\n"), DFLT_AF);
653         return(-1);
654   }
655   what = 0;
656
657   /* Fetch the command-line arguments. */
658   /* opterr = 0; */
659   while ((i = getopt_long(argc, argv, "A:H:adfp:nsei:t:vh?DNV",longopts, &lop)) != EOF) switch(i) {
660         case 'a':
661                 what = 1;
662                 opt_a = 1;
663                 break;
664         case 'f':
665                 what = 2;
666                 break;
667         case 'd':
668                 what = 3;
669                 break;
670         case 's':
671                 what = 4;
672                 break;
673
674
675         case 'e':
676                 opt_e = 1;
677                 break;
678         case 'n':
679                 opt_n = FLAG_NUM;
680                 break;
681         case 'D':
682                 opt_D = 1;
683                 break;
684         case 'N':
685                 opt_N = FLAG_SYM;
686                 fprintf(stderr,"arp: -N not yet supported.\n");
687                 break;
688         case 'v':
689                 opt_v = 1;
690                 break;
691
692         case 'A':
693         case 'p':
694                 ap = get_aftype(optarg);
695                 if (ap == NULL) {
696                         fprintf(stderr, _("arp: %s: unknown address family.\n"),
697                                 optarg);
698                         exit(-1);
699                 }
700                 break;
701         case 'H':
702         case 't':
703                 hw = get_hwtype(optarg);
704                 if (hw == NULL) {
705                         fprintf(stderr, _("arp: %s: unknown hardware type.\n"),
706                                 optarg);
707                         exit(-1);
708                 }
709                 hw_set = 1;
710                 break;
711         case 'i':
712                 strncpy(device,optarg,sizeof(device)-1);
713                 device[sizeof(device)-1]='\0';
714                 break;
715
716         case 'V':
717                 version();
718         case '?':
719         case 'h':
720         default:
721                 usage();
722   }
723
724   if (ap->af != AF_INET) {
725         fprintf(stderr, _("arp: %s: kernel only supports 'inet'.\n"),
726                         ap->name);
727         exit(-1);
728   }
729   if (hw->alen <= 0) {
730         fprintf(stderr, _("arp: %s: hardware type without ARP support.\n"),
731                         hw->name);
732         exit(-1);
733   }
734   if ((sockfd = socket(AF_INET,SOCK_DGRAM,0)) <0)
735   {
736         perror("socket");
737         exit(-1);
738   }
739
740   /* Now see what we have to do here... */
741   switch(what) {
742         case 0:
743                 opt_e = 1;
744                 what = arp_show(argv[optind]);
745                 break;
746                 
747         case 1:         /* show an ARP entry in the cache */
748                 what = arp_show(argv[optind]);
749                 break;
750
751         case 2:         /* process an EtherFile */
752                 what = arp_file(argv[optind]);
753                 break;
754
755         case 3:         /* delete an ARP entry from the cache */
756                 what = arp_del(&argv[optind]);
757                 break;
758
759         case 4:         /* set an ARP entry in the cache */
760                 what = arp_set(&argv[optind]);
761                 break;
762
763         default:
764                 usage();
765   }
766
767   exit(what);
768 }