diff options
author | ume <ume@FreeBSD.org> | 2003-11-13 16:02:44 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2003-11-13 16:02:44 +0000 |
commit | 59af8d55c7f5cc534f1685da36373c3445ef7954 (patch) | |
tree | 3e0528436ece4d58e7b145e6ab35ea51b175f8dc /usr.sbin/ndp/ndp.c | |
parent | 650f540b8d6f1e889ef3f8bd86211668f13343dc (diff) | |
download | FreeBSD-src-59af8d55c7f5cc534f1685da36373c3445ef7954.zip FreeBSD-src-59af8d55c7f5cc534f1685da36373c3445ef7954.tar.gz |
- make command line argument parsing POSIX compliant. comment from
deraadt NOTE: -I needs to take an arg (there's no way we can take no
arg/an arg with a single option)
- sscanf overrun
- no variable name on prototype.
- u_int32_t may not be u_long.
- skipped non-host route when printing neighbor cache entries.
- valid and preferred lifetimes are unsigned.
- wording.
Obtained from: KAME
Diffstat (limited to 'usr.sbin/ndp/ndp.c')
-rw-r--r-- | usr.sbin/ndp/ndp.c | 300 |
1 files changed, 172 insertions, 128 deletions
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c index bd55ef7..a761f96 100644 --- a/usr.sbin/ndp/ndp.c +++ b/usr.sbin/ndp/ndp.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: ndp.c,v 1.65 2001/05/08 04:36:34 itojun Exp $ */ +/* $KAME: ndp.c,v 1.104 2003/06/27 07:48:39 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -111,6 +111,7 @@ #include <stdlib.h> #include <fcntl.h> #include <unistd.h> +#include <err.h> #include "gmt2local.h" /* packing rule for routing socket */ @@ -119,7 +120,6 @@ #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) static pid_t pid; -static int cflag; static int nflag; static int tflag; static int32_t thiszone; /* time difference with gmt */ @@ -136,14 +136,13 @@ void getsocket __P((void)); int set __P((int, char **)); void get __P((char *)); int delete __P((char *)); -void dump __P((struct in6_addr *)); -static struct in6_nbrinfo *getnbrinfo __P((struct in6_addr *addr, - int ifindex, int)); +void dump __P((struct in6_addr *, int)); +static struct in6_nbrinfo *getnbrinfo __P((struct in6_addr *, int, int)); static char *ether_str __P((struct sockaddr_dl *)); int ndp_ether_aton __P((char *, u_char *)); void usage __P((void)); int rtmsg __P((int)); -void ifinfo __P((int, char **)); +void ifinfo __P((char *, int, char **)); void rtrlist __P((void)); void plist __P((void)); void pfx_flush __P((void)); @@ -154,16 +153,21 @@ void harmonize_rtr __P((void)); static void getdefif __P((void)); static void setdefif __P((char *)); #endif -static char *sec2str __P((time_t t)); -static char *ether_str __P((struct sockaddr_dl *sdl)); +static char *sec2str __P((time_t)); +static char *ether_str __P((struct sockaddr_dl *)); static void ts_print __P((const struct timeval *)); +#ifdef ICMPV6CTL_ND6_DRLIST static char *rtpref_str[] = { "medium", /* 00 */ "high", /* 01 */ "rsv", /* 10 */ "low" /* 11 */ }; +#endif + +int mode = 0; +char *arg = NULL; int main(argc, argv) @@ -171,76 +175,54 @@ main(argc, argv) char **argv; { int ch; - int aflag = 0, dflag = 0, sflag = 0, Hflag = 0, - pflag = 0, rflag = 0, Pflag = 0, Rflag = 0; pid = getpid(); thiszone = gmt2local(0); - while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != -1) + while ((ch = getopt(argc, argv, "acd:f:Ii:nprstA:HPR")) != -1) switch (ch) { case 'a': - aflag = 1; - break; case 'c': - cflag = 1; + case 'p': + case 'r': + case 'H': + case 'P': + case 'R': + case 's': + case 'I': + if (mode) { + usage(); + /*NOTREACHED*/ + } + mode = ch; + arg = NULL; break; case 'd': - dflag = 1; - break; - case 'I': -#ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */ - if (argc > 2) - setdefif(argv[2]); - getdefif(); /* always call it to print the result */ - exit(0); -#else - errx(1, "not supported yet"); - /*NOTREACHED*/ -#endif + case 'f': case 'i' : - argc -= optind; - argv += optind; - if (argc < 1) + if (mode) { usage(); - ifinfo(argc, argv); - exit(0); + /*NOTREACHED*/ + } + mode = ch; + arg = optarg; + break; case 'n': nflag = 1; - continue; - case 'p': - pflag = 1; - break; - case 'f' : - if (argc != 3) - usage(); - file(argv[2]); - exit(0); - case 'l' : - /* obsolete, ignored */ - break; - case 'r' : - rflag = 1; - break; - case 's': - sflag = 1; break; case 't': tflag = 1; break; case 'A': - aflag = 1; + if (mode) { + usage(); + /*NOTREACHED*/ + } + mode = 'a'; repeat = atoi(optarg); - if (repeat < 0) + if (repeat < 0) { usage(); - break; - case 'H' : - Hflag = 1; - break; - case 'P': - Pflag = 1; - break; - case 'R': - Rflag = 1; + /*NOTREACHED*/ + } break; default: usage(); @@ -249,45 +231,90 @@ main(argc, argv) argc -= optind; argv += optind; - if (aflag || cflag) { - dump(0); - exit(0); - } - if (dflag) { - if (argc != 1) + switch (mode) { + case 'a': + case 'c': + if (argc != 0) { usage(); - delete(argv[0]); - exit(0); - } - if (pflag) { + /*NOTREACHED*/ + } + dump(0, mode == 'c'); + break; + case 'd': + if (argc != 0) { + usage(); + /*NOTREACHED*/ + } + delete(arg); + break; + case 'I': +#ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */ + if (argc > 1) { + usage(); + /*NOTREACHED*/ + } else if (argc == 1) { + if (strcmp(*argv, "delete") == 0 || + if_nametoindex(*argv)) + setdefif(*argv); + else + errx(1, "invalid interface %s", *argv); + } + getdefif(); /* always call it to print the result */ + break; +#else + errx(1, "not supported yet"); + /*NOTREACHED*/ +#endif + case 'p': + if (argc != 0) { + usage(); + /*NOTREACHED*/ + } plist(); - exit(0); - } - if (rflag) { + break; + case 'i': + ifinfo(arg, argc, argv); + break; + case 'r': + if (argc != 0) { + usage(); + /*NOTREACHED*/ + } rtrlist(); - exit(0); - } - if (sflag) { + break; + case 's': if (argc < 2 || argc > 4) usage(); exit(set(argc, argv) ? 1 : 0); - } - if (Hflag) { + case 'H': + if (argc != 0) { + usage(); + /*NOTREACHED*/ + } harmonize_rtr(); - exit(0); - } - if (Pflag) { + break; + case 'P': + if (argc != 0) { + usage(); + /*NOTREACHED*/ + } pfx_flush(); - exit(0); - } - if (Rflag) { + break; + case 'R': + if (argc != 0) { + usage(); + /*NOTREACHED*/ + } rtr_flush(); - exit(0); + break; + case 0: + if (argc != 1) { + usage(); + /*NOTREACHED*/ + } + get(argv[0]); + break; } - - if (argc != 1) - usage(); - get(argv[0]); exit(0); } @@ -313,8 +340,8 @@ file(name) args[4] = &arg[4][0]; retval = 0; while (fgets(line, 100, fp) != NULL) { - i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], - arg[3], arg[4]); + i = sscanf(line, "%49s %49s %49s %49s %49s", + arg[0], arg[1], arg[2], arg[3], arg[4]); if (i < 2) { fprintf(stderr, "ndp: bad line: %s\n", line); retval = 1; @@ -408,10 +435,12 @@ set(argc, argv) if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) { if (sdl->sdl_family == AF_LINK && (rtm->rtm_flags & RTF_LLINFO) && - !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) { - case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: - case IFT_ISO88024: case IFT_ISO88025: - goto overwrite; + !(rtm->rtm_flags & RTF_GATEWAY)) { + switch (sdl->sdl_type) { + case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: + case IFT_ISO88024: case IFT_ISO88025: + goto overwrite; + } } /* * IPv4 arp command retries with sin_other = SIN_PROXY here. @@ -457,7 +486,7 @@ get(host) htons(((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id); } #endif - dump(&sin->sin6_addr); + dump(&sin->sin6_addr, 0); if (found_entry == 0) { getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf, sizeof(host_buf), NULL ,0, @@ -541,7 +570,7 @@ delete: return 0; } -#define W_ADDR 31 +#define W_ADDR 36 #define W_LL 17 #define W_IF 6 @@ -549,8 +578,9 @@ delete: * Dump the entire neighbor cache */ void -dump(addr) +dump(addr, cflag) struct in6_addr *addr; + int cflag; { int mib[6]; size_t needed; @@ -569,9 +599,9 @@ dump(addr) /* Print header */ if (!tflag && !cflag) - printf("%-*.*s %-*.*s %*.*s %-9.9s %2s %4s %4s\n", + printf("%-*.*s %-*.*s %*.*s %-9.9s %1s %5s\n", W_ADDR, W_ADDR, "Neighbor", W_LL, W_LL, "Linklayer Address", - W_IF, W_IF, "Netif", "Expire", "St", "Flgs", "Prbs"); + W_IF, W_IF, "Netif", "Expire", "S", "Flags"); again:; mib[0] = CTL_NET; @@ -614,6 +644,9 @@ again:; if (sdl->sdl_family != AF_LINK) continue; + if (!(rtm->rtm_flags & RTF_HOST)) + continue; + if (addr) { if (!IN6_ARE_ADDR_EQUAL(addr, &sin->sin6_addr)) continue; @@ -632,10 +665,13 @@ again:; } getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf, sizeof(host_buf), NULL, 0, (nflag ? NI_NUMERICHOST : 0)); - if (cflag == 1) { + if (cflag) { #ifdef RTF_WASCLONED if (rtm->rtm_flags & RTF_WASCLONED) delete(host_buf); +#elif defined(RTF_CLONED) + if (rtm->rtm_flags & RTF_CLONED) + delete(host_buf); #else delete(host_buf); #endif @@ -707,7 +743,6 @@ again:; warnx("failed to get neighbor information"); printf(" "); } - putchar(' '); /* * other flags. R: router, P: proxy, W: ?? @@ -719,16 +754,22 @@ again:; } else { sin = (struct sockaddr_in6 *) (sdl->sdl_len + (char *)sdl); +#if 0 /* W and P are mystery even for us */ snprintf(flgbuf, sizeof(flgbuf), "%s%s%s%s", isrouter ? "R" : "", !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr) ? "P" : "", (sin->sin6_len != sizeof(struct sockaddr_in6)) ? "W" : "", (rtm->rtm_flags & RTF_ANNOUNCE) ? "p" : ""); +#else + snprintf(flgbuf, sizeof(flgbuf), "%s%s", + isrouter ? "R" : "", + (rtm->rtm_flags & RTF_ANNOUNCE) ? "p" : ""); +#endif } - printf(" %-4.4s", flgbuf); + printf(" %s", flgbuf); if (prbs) - printf(" %4d", prbs); + printf(" %d", prbs); printf("\n"); } @@ -806,22 +847,16 @@ ndp_ether_aton(a, n) void usage() { - printf("usage: ndp hostname\n"); - printf(" ndp -a[nt]\n"); + printf("usage: ndp [-nt] hostname\n"); + printf(" ndp [-nt] -a | -c | -p | -r | -H | -P | -R\n"); printf(" ndp [-nt] -A wait\n"); - printf(" ndp -c[nt]\n"); - printf(" ndp -d[nt] hostname\n"); - printf(" ndp -f[nt] filename\n"); - printf(" ndp -i interface [flags...]\n"); + printf(" ndp [-nt] -d hostname\n"); + printf(" ndp [-nt] -f filename\n"); + printf(" ndp [-nt] -i interface [flags...]\n"); #ifdef SIOCSDEFIFACE_IN6 - printf(" ndp -I [interface|delete]\n"); + printf(" ndp [-nt] -I [interface|delete]\n"); #endif - printf(" ndp -p\n"); - printf(" ndp -r\n"); - printf(" ndp -s hostname ether_addr [temp] [proxy]\n"); - printf(" ndp -H\n"); - printf(" ndp -P\n"); - printf(" ndp -R\n"); + printf(" ndp [-nt] -s nodename etheraddr [temp] [proxy]\n"); exit(1); } @@ -848,8 +883,10 @@ rtmsg(cmd) exit(1); case RTM_ADD: rtm->rtm_addrs |= RTA_GATEWAY; - rtm->rtm_rmx.rmx_expire = expire_time; - rtm->rtm_inits = RTV_EXPIRE; + if (expire_time) { + rtm->rtm_rmx.rmx_expire = expire_time; + rtm->rtm_inits = RTV_EXPIRE; + } rtm->rtm_flags |= (RTF_HOST | RTF_STATIC); if (rtm->rtm_flags & RTF_ANNOUNCE) { rtm->rtm_flags &= ~RTF_HOST; @@ -889,13 +926,13 @@ doit: } void -ifinfo(argc, argv) +ifinfo(ifname, argc, argv) + char *ifname; int argc; char **argv; { struct in6_ndireq nd; int i, s; - char *ifname = argv[0]; u_int32_t newflags; #ifdef IPV6CTL_USETEMPADDR u_int8_t nullbuf[8]; @@ -910,10 +947,10 @@ ifinfo(argc, argv) if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { err(1, "ioctl(SIOCGIFINFO_IN6)"); /* NOTREACHED */ - } + } #define ND nd.ndi newflags = ND.flags; - for (i = 1; i < argc; i++) { + for (i = 0; i < argc; i++) { int clear = 0; char *cp = argv[i]; @@ -935,6 +972,9 @@ ifinfo(argc, argv) #ifdef ND6_IFF_ACCEPT_RTADV SETFLAG("accept_rtadv", ND6_IFF_ACCEPT_RTADV); #endif +#ifdef ND6_IFF_PREFER_SOURCE + SETFLAG("prefer_source", ND6_IFF_PREFER_SOURCE); +#endif ND.flags = newflags; if (ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd) < 0) { @@ -990,7 +1030,11 @@ ifinfo(argc, argv) if ((ND.flags & ND6_IFF_ACCEPT_RTADV)) printf("accept_rtadv "); #endif -} +#ifdef ND6_IFF_PREFER_SOURCE + if ((ND.flags & ND6_IFF_PREFER_SOURCE)) + printf("prefer_source "); +#endif + } putc('\n', stdout); #undef ND @@ -1153,11 +1197,11 @@ plist() if (p->vltime == ND6_INFINITE_LIFETIME) printf(" vltime=infinity"); else - printf(" vltime=%ld", (long)p->vltime); + printf(" vltime=%lu", (unsigned long)p->vltime); if (p->pltime == ND6_INFINITE_LIFETIME) printf(", pltime=infinity"); else - printf(", pltime=%ld", (long)p->pltime); + printf(", pltime=%lu", (unsigned long)p->pltime); if (p->expire == 0) printf(", expire=Never"); else if (p->expire >= time.tv_sec) @@ -1175,7 +1219,7 @@ plist() int j; struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)(p + 1); + sin6 = advrtr; printf(" advertised by\n"); for (j = 0; j < p->advrtrs; j++) { struct in6_nbrinfo *nbi; @@ -1293,11 +1337,11 @@ plist() if (PR.vltime == ND6_INFINITE_LIFETIME) printf(" vltime=infinity"); else - printf(" vltime=%ld", (long)PR.vltime); + printf(" vltime=%lu", PR.vltime); if (PR.pltime == ND6_INFINITE_LIFETIME) printf(", pltime=infinity"); else - printf(", pltime=%ld", (long)PR.pltime); + printf(", pltime=%lu", PR.pltime); if (PR.expire == 0) printf(", expire=Never"); else if (PR.expire >= time.tv_sec) |