diff options
author | Phil Blundell <philb@gnu.org> | 1998-02-08 19:38:50 +0000 |
---|---|---|
committer | Phil Blundell <philb@gnu.org> | 1998-02-08 19:38:50 +0000 |
commit | 1d873f2e84fe35afe99fe05fd2e5f1bb1c51470d (patch) | |
tree | 2628d723cf995ff551213fe4e679f2634632893a /arp.c | |
parent | b1279cc68c387980090293ccba91afc5afaeabef (diff) | |
download | net-tools-1d873f2e84fe35afe99fe05fd2e5f1bb1c51470d.tar.gz net-tools-1d873f2e84fe35afe99fe05fd2e5f1bb1c51470d.tar.bz2 net-tools-1d873f2e84fe35afe99fe05fd2e5f1bb1c51470d.zip |
Various ifconfig cleanups and new arp.
Diffstat (limited to 'arp.c')
-rw-r--r-- | arp.c | 421 |
1 files changed, 318 insertions, 103 deletions
@@ -8,13 +8,14 @@ * NET-3 Networking Distribution for the LINUX operating * system. * - * Version: arp 1.69 (1996-05-17) + * Version: arp 1.82 (1997-09-25) * * Maintainer: Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de> * * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * * Changes: + * (based on work from Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>) * Alan Cox : modified for NET3 * Andrew Tridgell : proxy arp netmasks * Bernd Eckenfels : -n option @@ -24,14 +25,21 @@ * {1.61} Bernd Eckenfels : more verbose messages * {1.62} Bernd Eckenfels : check -t for hw adresses and try to * explain EINVAL (jeff) - *960125 {1.63} Bernd Eckenfels : -a print hardwarename instead of tiltle - *960201 {1.64} Bernd Eckenfels : net-features.h support - *960203 {1.65} Bernd Eckenfels : "#define" in "#if", + *970125 {1.63} Bernd Eckenfels : -a print hardwarename instead of tiltle + *970201 {1.64} Bernd Eckenfels : net-features.h support + *970203 {1.65} Bernd Eckenfels : "#define" in "#if", * -H|-A additional to -t|-p - *960214 {1.66} Bernd Eckenfels : Fix optarg required for -H and -A - *960412 {1.67} Bernd Eckenfels : device=""; is default - *960514 {1.68} Bernd Eckenfels : -N and -D - *960517 {1.69} Bernd Eckenfels : usage() fixed + *970214 {1.66} Bernd Eckenfels : Fix optarg required for -H and -A + *970412 {1.67} Bernd Eckenfels : device=""; is default + *970514 {1.68} Bernd Eckenfels : -N and -D + *970517 {1.69} Bernd Eckenfels : usage() fixed + *970622 {1.70} Bernd Eckenfels : arp -d priv + *970106 {1.80} Bernd Eckenfels : new syntax without -D and with "dev <If>", + * ATF_MAGIC, ATF_DONTPUB support. + * Typo fix (Debian Bug#5728 Giuliano Procida) + *970803 {1.81} Bernd Eckenfels : removed junk comment line 1 + *970925 {1.82} Bernd Eckenfels : include fix for libc6 + * * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General @@ -43,6 +51,8 @@ #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> +/* #include <linux/netdevice.h> */ +/* #include <linux/if_arp.h> */ #include <net/if_arp.h> #include <stdlib.h> #include <stdio.h> @@ -66,12 +76,14 @@ char *Release = RELEASE, - *Version = "arp 1.69 (1996-05-17)"; + *Version = "arp 1.82 (1997-09-25)"; int opt_n = 0; /* do not resolve addresses */ int opt_N = 0; /* use symbolic names */ int opt_v = 0; /* debugging output flag */ int opt_D = 0; /* HW-address is devicename */ +int opt_e = 0; /* 0=BSD output, 1=new linux */ +int opt_a = 0; /* all entries, substring match */ struct aftype *ap; /* current address family */ struct hwtype *hw; /* current hardware type */ int sockfd=0; /* active socket descriptor */ @@ -86,6 +98,7 @@ arp_del(char **args) char host[128]; struct arpreq req; struct sockaddr sa; + int flags=0; #if HAVE_NEW_SIOCSARP struct arpreq_old old_req; #endif @@ -106,40 +119,133 @@ arp_del(char **args) /* If a host has more than one address, use the correct one! */ memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr)); - req.arp_flags=0; + if (hw_set) + req.arp_ha.sa_family=hw->type; - if (args[1]) { - if (strcmp(args[1],"pub")==0) - req.arp_flags|=ATF_PUBL; - else - usage(); + req.arp_flags=ATF_PERM; + args++; + while (*args != NULL) { + if (opt_v) fprintf(stderr,"args=%s\n",*args); + if (! strcmp(*args, "pub")) { + flags |= 1; + args++; + continue; + } + if (! strcmp(*args, "priv")) { + flags |= 2; + args++; + continue; + } + if (! strcmp(*args, "temp")) { + req.arp_flags &= ~ATF_PERM; + args++; + continue; + } + if (! strcmp(*args, "trail")) { + req.arp_flags |= ATF_USETRAILERS; + args++; + continue; + } + if (! strcmp(*args, "dontpub")) { +#ifdef HAVE_ATF_DONTPUB + req.arp_flags |= ATF_DONTPUB; +#else + ENOSUPP("arp", "ATF_DONTPUB"); +#endif + args++; + continue; + } + if (! strcmp(*args, "auto")) { +#ifdef HAVE_ATF_MAGIC + req.arp_flags |= ATF_MAGIC; +#else + ENOSUPP("arp", "ATF_MAGIC"); +#endif + args++; + continue; + } + if (! strcmp(*args, "dev")) { + if (*++args == NULL) usage(); + strncpy(device,*args,sizeof(device)-1); + device[sizeof(device)-1]='\0'; + args++; + continue; + } + if (! strcmp(*args, "netmask")) { + if (*++args == NULL) usage(); + if (strcmp(*args,"255.255.255.255") != 0) { + strcpy(host, *args); + if (ap->input(0, host, &sa) < 0) { + ap->herror(host); + return(-1); + } + memcpy((char *) &req.arp_netmask, (char *) &sa, + sizeof(struct sockaddr)); + req.arp_flags |= ATF_NETMASK; + } + args++; + continue; + } + usage(); } - + if (flags == 0) + flags = 3; + #if HAVE_NEW_SIOCSARP strcpy(req.arp_dev,device); - memcpy((char *)&old_req,(char *)&req,sizeof(old_req)); /* Call the kernel. */ - if (opt_v) fprintf(stderr,"arp: SIOCDARP()\n"); - if (ioctl(sockfd, SIOCDARP, &req) < 0) { - if (errno == EINVAL) { - if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP()\n"); - if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) { - if (errno != ENXIO) { - perror("OLD_SIOCSARP"); - return(-1); + if (flags & 2) { + if (opt_v) fprintf(stderr,"arp: SIOCDARP(nopub)\n"); + if (ioctl(sockfd, SIOCDARP, &req) < 0) { + if (errno == EINVAL) { + if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP(priv)\n"); + memcpy((char *)&old_req,(char *)&req,sizeof(old_req)); + if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) { + if (errno != ENXIO) { + perror("OLD_SIOCSARP(priv)"); + return(-1); + } + } else { + return(0); } - } else { - return(0); } - } - if (errno == ENXIO) { - printf(NLS_CATGETS(catfd, arpSet, arp_no_arp, - "No ARP entry for %s\n"), host); + if (errno == ENXIO) { + if (flags & 1) + goto nopub; + printf(NLS_CATGETS(catfd, arpSet, arp_no_arp, + "No ARP entry for %s\n"), host); + return(-1); + } + perror("SIOCDARP(priv)"); return(-1); - } - perror("SIOCDARP"); - return(-1); + } + } + if (flags & 1) { +nopub: + req.arp_flags |= ATF_PUBL; + if (opt_v) fprintf(stderr,"arp: SIOCDARP(pub)\n"); + if (ioctl(sockfd, SIOCDARP, &req) < 0) { + if (errno == EINVAL) { + if (opt_v) fprintf(stderr,"arp: OLD_SIOCDARP(pub)\n"); + memcpy((char *)&old_req,(char *)&req,sizeof(old_req)); + if (ioctl(sockfd, OLD_SIOCDARP, &old_req) < 0) { + if (errno != ENXIO) { + perror("OLD_SIOCSARP(pub)"); + return(-1); + } + } else { + return(0); + } + } + if (errno == ENXIO) { + printf(NLS_CATGETS(catfd, arpSet, arp_no_arp, + "No ARP entry for %s\n"), host); + return(-1); + } + perror("SIOCDARP(pub)"); + return(-1); + } } #else /* Call the kernel. */ @@ -227,30 +333,70 @@ arp_set(char **args) /* Check out any modifiers. */ flags = ATF_PERM; while (*args != NULL) { - if (! strcmp(*args, "temp")) flags &= ~ATF_PERM; - if (! strcmp(*args, "pub")) flags |= ATF_PUBL; -/* if (! strcmp(*args, "rarp")) flags |= ATF_RARP;*/ - if (! strcmp(*args, "trail")) flags |= ATF_USETRAILERS; - if (! strcmp(*args, "netmask")) - { - if (*++args == NULL) usage(); - if (strcmp(*args,"255.255.255.255") != 0) - { - strcpy(host, *args); - if (ap->input(0, host, &sa) < 0) { - ap->herror(host); - return(-1); - } - memcpy((char *) &req.arp_netmask, (char *) &sa, - sizeof(struct sockaddr)); - flags |= ATF_NETMASK; - } - } - args++; - } + if (! strcmp(*args, "temp")) { + flags &= ~ATF_PERM; + args++; + continue; + } + if (! strcmp(*args, "pub")) { + flags |= ATF_PUBL; + args++; + continue; + } + if (! strcmp(*args, "priv")) { + flags &= ~ATF_PUBL; + args++; + continue; + } + if (! strcmp(*args, "trail")) { + flags |= ATF_USETRAILERS; + args++; + continue; + } + if (! strcmp(*args, "dontpub")) { +#ifdef HAVE_ATF_DONTPUB + flags |= ATF_DONTPUB; +#else + ENOSUPP("arp", "ATF_DONTPUB"); +#endif + args++; + continue; + } + + if (! strcmp(*args, "auto")) { +#ifdef HAVE_ATF_MAGIC + flags |= ATF_MAGIC; +#else + ENOSUPP("arp", "ATF_MAGIC"); +#endif + args++; + continue; + } + if (! strcmp(*args, "dev")) { + if (*++args == NULL) usage(); + strncpy(device,*args,sizeof(device)-1); + device[sizeof(device)-1]='\0'; + args++; + continue; + } - if ((flags & ATF_NETMASK) && !(flags & ATF_PUBL)) - usage(); + if (! strcmp(*args, "netmask")) { + if (*++args == NULL) usage(); + if (strcmp(*args,"255.255.255.255") != 0) { + strcpy(host, *args); + if (ap->input(0, host, &sa) < 0) { + ap->herror(host); + return(-1); + } + memcpy((char *) &req.arp_netmask, (char *) &sa, + sizeof(struct sockaddr)); + flags |= ATF_NETMASK; + } + args++; + continue; + } + usage(); + } /* Fill in the remainder of the request. */ req.arp_flags = flags; @@ -275,10 +421,10 @@ arp_set(char **args) perror("SIOCSARP and OLD_SIOCSARP"); if (flags & ATF_PUBL) fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_einv_pub, - "Probably destination is reached via ARP Interface. See arp(8)\n")); + "Probably route to destination points to interface. See arp(8)\n")); else fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_einv_nopub, - "Probably destination is on different Interface. See arp(8)\n")); + "No ARP Support or route to destination points to other interface. See arp(8)\n")); return(-1); } } @@ -339,23 +485,15 @@ arp_file(char *name) /* Print the contents of an ARP request block. */ static void -arp_disp_2(char *ip,int type,int arp_flags,char *hwa,char *mask,char *dev) +arp_disp_2(char *name,int type,int arp_flags,char *hwa,char *mask,char *dev) { static int title = 0; struct hwtype *xhw; - struct aftype *xap; - char *sp; - struct sockaddr sap; - char flags[6]; + char flags[10]; xhw = get_hwntype(type); if (xhw == NULL) - xhw = get_hwtype("ether"); -/* - * xap = get_afntype(req->arp_pa.sa_family); - * if (xap == NULL) - */ - xap = get_aftype("inet"); + xhw = get_hwtype(DFLT_HW); if (title++ == 0) { printf(NLS_CATGETS(catfd, arpSet, arp_address, @@ -366,17 +504,67 @@ arp_disp_2(char *ip,int type,int arp_flags,char *hwa,char *mask,char *dev) if (arp_flags & ATF_COM) strcat(flags, "C"); if (arp_flags & ATF_PERM) strcat(flags, "M"); if (arp_flags & ATF_PUBL) strcat(flags, "P"); -/* if (arp_flags & ATF_RARP) strcat(flags, "R");*/ +#ifdef HAVE_ATF_MAGIC + if (arp_flags & ATF_MAGIC) strcat(flags, "A"); +#endif +#ifdef HAVE_ATF_DONTPUB + if (arp_flags & ATF_DONTPUB) strcat(flags, "!"); +#endif if (arp_flags & ATF_USETRAILERS) strcat(flags, "T"); - /* This IS ugly but it works -be */ - if (xap->input(0, ip,&sap) < 0) - sp=ip; - else - sp = xap->sprint(&sap, opt_n); + if (!(arp_flags & ATF_NETMASK)) mask=""; + + printf("%-23.23s\t", name); + + if (!(arp_flags & ATF_COM)) { + if (arp_flags & ATF_PUBL) + printf("%-8.8s%-20.20s","*","*"); + else + printf("%-8.8s%-20.20s","","(incomplete)"); + } else { + printf("%-8.8s%-20.20s", xhw->name, hwa); + } + + printf("%-6.6s%-15.15s %s\n", flags,mask,dev); +} + +/* Print the contents of an ARP request block. */ +static void +arp_disp(char *name, char *ip, int type,int arp_flags,char *hwa,char *mask,char *dev) +{ + struct hwtype *xhw; + + xhw = get_hwntype(type); + if (xhw == NULL) + xhw = get_hwtype(DFLT_HW); + + + + printf("%s (%s) at ", name, ip); + + if (!(arp_flags & ATF_COM)) { + if (arp_flags & ATF_PUBL) + printf("* "); + else + printf("<incomplete> "); + } else { + printf("%s [%s] ", hwa, xhw->name); + } - printf("%-23.23s\t%-8.8s", sp, xhw->name); - printf("%-20.20s%-6.6s%-15.15s %s\n", hwa, flags,mask,dev); + if (arp_flags & ATF_NETMASK) + printf("netmask %s ", mask); + + if (arp_flags & ATF_PERM) printf("PERM "); + if (arp_flags & ATF_PUBL) printf("PUP "); +#ifdef HAVE_ATF_MAGIC + if (arp_flags & ATF_MAGIC) printf("AUTO "); +#endif +#ifdef HAVE_ATF_DONTPUB + if (arp_flags & ATF_DONTPUB) printf("DONTPUB "); +#endif + if (arp_flags & ATF_USETRAILERS) printf("TRAIL "); + + printf("on %s\n", dev); } @@ -393,6 +581,7 @@ arp_show(char *name) char dev[100]; int type,flags; FILE *fp; + char *hostname; int num,entries=0,showed=0; host[0]='\0'; @@ -437,17 +626,38 @@ arp_show(char *name) /* if the user specified device differs, skip it */ if (device[0] && strcmp(dev,device)) continue; - showed++; - arp_disp_2(ip,type,flags,hwa,mask,dev); + + showed++; + /* This IS ugly but it works -be */ + if (opt_n) + hostname="?"; + else { + if (ap->input(0, ip,&sa) < 0) + hostname=ip; + else + hostname = ap->sprint(&sa, opt_n | 0x8000); + if (strcmp(hostname, ip)==0) + hostname="?"; + } + + if (opt_e) + arp_disp_2(hostname[0]=='?'?ip:hostname,type,flags,hwa,mask,dev); + else + arp_disp(hostname,ip,type,flags,hwa,mask,dev); } } if (opt_v) printf(NLS_CATGETS(catfd, arpSet, arp_sum, - "Entries: %d\tSkiped: %d\tFound: %d\n"),entries,entries-showed,showed); + "Entries: %d\tSkipped: %d\tFound: %d\n"),entries,entries-showed,showed); - if (!showed && (hw_set || host[0] || device[0])) - printf(NLS_CATGETS(catfd, arpSet, arp_none, - "arp: in %d entries no match found.\n"),entries); + if (!showed) { + if (host[0] && !opt_a) + printf("%s (%s) -- no entry\n", name, host); + else if (hw_set || host[0] || device[0]) { + printf(NLS_CATGETS(catfd, arpSet, arp_none, + "arp: in %d entries no match found.\n"),entries); + } + } (void) fclose(fp); return(0); } @@ -466,9 +676,9 @@ usage(void) fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage1, "Usage: arp [-vn] [-H type] [-i if] -a [hostname]\n")); fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage2, - " arp [-v] [-i if] -d hostname [pub]\n")); + " arp [-v] [-i if] -d hostname [pub][nopub]\n")); fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage3, - " arp [-v] [-H type] [-i if] -s hostname hw_addr [temp]\n")); + " arp [-v] [-H type] [-i if] -s hostname hw_addr [temp][nopub]\n")); fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage4, " arp [-v] [-H type] [-i if] -s hostname hw_addr [netmask nm] pub\n")); fprintf(stderr, NLS_CATGETS(catfd, arpSet, arp_usage5, @@ -487,7 +697,7 @@ main(int argc, char **argv) { {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, - {"display", 0, 0, 'a'}, + {"all", 0, 0, 'a'}, {"delete", 0, 0, 'd'}, {"file", 0, 0, 'f'}, {"numeric", 0, 0, 'n'}, @@ -519,23 +729,29 @@ main(int argc, char **argv) NLS_CATCLOSE(catfd) return(-1); } - what = -1; + what = 0; /* Fetch the command-line arguments. */ /* opterr = 0; */ - while ((i = getopt_long(argc, argv, "A:H:adfp:nsi:t:vh?DNV",longopts, &lop)) != EOF) switch(i) { + while ((i = getopt_long(argc, argv, "A:H:adfp:nsei:t:vh?DNV",longopts, &lop)) != EOF) switch(i) { case 'a': what = 1; + opt_a = 1; + break; + case 'f': + what = 2; break; - case 'd': what = 3; break; - - case 'f': - what = 2; + case 's': + what = 4; break; + + case 'e': + opt_e = 1; + break; case 'n': opt_n = FLAG_NUM; break; @@ -546,6 +762,10 @@ main(int argc, char **argv) opt_N = FLAG_SYM; fprintf(stderr,"arp: -N not yet supported.\n"); break; + case 'v': + opt_v = 1; + break; + case 'A': case 'p': ap = get_aftype(optarg); @@ -557,11 +777,6 @@ main(int argc, char **argv) exit(-1); } break; - - case 's': - what = 4; - break; - case 'H': case 't': hw = get_hwtype(optarg); @@ -579,13 +794,8 @@ main(int argc, char **argv) device[sizeof(device)-1]='\0'; break; - case 'v': - opt_v = 1; - break; - case 'V': version(); - case '?': case 'h': default: @@ -615,6 +825,11 @@ main(int argc, char **argv) /* Now see what we have to do here... */ switch(what) { + case 0: + opt_e = 1; + what = arp_show(argv[optind]); + break; + case 1: /* show an ARP entry in the cache */ what = arp_show(argv[optind]); break; |