diff options
author | 2001-07-23 18:42:32 +0000 | |
---|---|---|
committer | 2001-07-23 18:42:32 +0000 | |
commit | e66b2787848770e3eff3a503f5ceeb5880a1c05d (patch) | |
tree | 08697943532aaa4261b9c09d488e459f1e00a094 | |
parent | no zero size xstrdup() error; ok markus@ (diff) | |
download | wireguard-openbsd-e66b2787848770e3eff3a503f5ceeb5880a1c05d.tar.xz wireguard-openbsd-e66b2787848770e3eff3a503f5ceeb5880a1c05d.zip |
sync with latest kame. do not print yet-to-be-initialized interface.
-rw-r--r-- | usr.sbin/ndp/ndp.c | 279 |
1 files changed, 246 insertions, 33 deletions
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c index c8aedbad3d3..93a4ebf85de 100644 --- a/usr.sbin/ndp/ndp.c +++ b/usr.sbin/ndp/ndp.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ndp.c,v 1.10 2001/03/21 15:32:27 itojun Exp $ */ -/* $KAME: ndp.c,v 1.62 2001/03/21 15:26:32 itojun Exp $ */ +/* $OpenBSD: ndp.c,v 1.11 2001/07/23 18:42:32 itojun Exp $ */ +/* $KAME: ndp.c,v 1.69 2001/07/23 14:46:31 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -115,6 +115,7 @@ #include <stdlib.h> #include <fcntl.h> #include <unistd.h> +#include <err.h> #include "gmt2local.h" #ifndef NI_WITHSCOPEID @@ -166,6 +167,15 @@ static char *sec2str __P((time_t t)); static char *ether_str __P((struct sockaddr_dl *sdl)); 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 main(argc, argv) int argc; @@ -177,7 +187,7 @@ main(argc, argv) pid = getpid(); thiszone = gmt2local(0); - while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != EOF) + while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != -1) switch ((char)ch) { case 'a': aflag = 1; @@ -334,8 +344,8 @@ getsocket() if (s < 0) { s = socket(PF_ROUTE, SOCK_RAW, 0); if (s < 0) { - perror("ndp: socket"); - exit(1); + err(1, "ndp: socket"); + /* NOTREACHED */ } } } @@ -400,8 +410,8 @@ set(argc, argv) argv++; } if (rtmsg(RTM_GET) < 0) { - perror(host); - return (1); + errx(1, "RTM_GET(%s) failed", host); + /* NOTREACHED */ } sin = (struct sockaddr_in6 *)(rtm + 1); sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin6_len) + (char *)sin); @@ -499,8 +509,8 @@ delete(host) } #endif if (rtmsg(RTM_GET) < 0) { - perror(host); - return (1); + errx(1, "RTM_GET(%s) failed", host); + /* NOTREACHED */ } sin = (struct sockaddr_in6 *)(rtm + 1); sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin6_len) + (char *)sin); @@ -597,6 +607,23 @@ again:; rtm = (struct rt_msghdr *)next; sin = (struct sockaddr_in6 *)(rtm + 1); sdl = (struct sockaddr_dl *)((char *)sin + ROUNDUP(sin->sin6_len)); + + /* + * Some OSes can produce a route that has the LINK flag but + * has a non-AF_LINK gateway (e.g. fe80::xx%lo0 on FreeBSD + * and BSD/OS, where xx is not the interface identifier on + * lo0). Such routes entry would annoy getnbrinfo() below, + * so we skip them. + * XXX: such routes should have the GATEWAY flag, not the + * LINK flag. However, there is rotten routing software + * that advertises all routes that have the GATEWAY flag. + * Thus, KAME kernel intentionally does not set the LINK flag. + * What is to be fixed is not ndp, but such routing software + * (and the kernel workaround)... + */ + if (sdl->sdl_family != AF_LINK) + continue; + if (addr) { if (!IN6_ARE_ADDR_EQUAL(addr, &sin->sin6_addr)) continue; @@ -857,8 +884,8 @@ doit: rtm->rtm_type = cmd; if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { if (errno != ESRCH || cmd != RTM_DELETE) { - perror("writing to routing socket"); - return (-1); + err(1, "writing to routing socket"); + /* NOTREACHED */ } } do { @@ -884,14 +911,14 @@ ifinfo(argc, argv) #endif if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - perror("ndp: socket"); - exit(1); + err(1, "socket"); + /* NOTREACHED */ } bzero(&nd, sizeof(nd)); strcpy(nd.ifname, ifname); if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { - perror("ioctl (SIOCGIFINFO_IN6)"); - exit(1); + err(1, "ioctl(SIOCGIFINFO_IN6)"); + /* NOTREACHED */ } #define ND nd.ndi newflags = ND.flags; @@ -917,12 +944,17 @@ ifinfo(argc, argv) ND.flags = newflags; if (ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd) < 0) { - perror("ioctl(SIOCSIFINFO_FLAGS)"); - exit(1); + err(1, "ioctl(SIOCSIFINFO_FLAGS)"); + /* NOTREACHED */ } #undef SETFLAG } + if (!ND.linkmtu) { + errx(1, "%s: not initialized yet", ifname); + /* NOTREACHED */ + } + printf("linkmtu=%d", ND.linkmtu); printf(", curhlim=%d", ND.chlim); printf(", basereachable=%ds%dms", @@ -966,25 +998,76 @@ ifinfo(argc, argv) close(s); } +#ifndef ND_RA_FLAG_RTPREF_MASK /* XXX: just for compilation on *BSD release */ +#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */ +#endif + void rtrlist() { +#ifdef ICMPV6CTL_ND6_DRLIST + int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_DRLIST }; + char *buf; + struct in6_defrouter *p, *ep; + size_t l; + struct timeval time; + + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) { + err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)"); + /*NOTREACHED*/ + } + buf = malloc(l); + if (!buf) { + errx(1, "not enough core"); + /*NOTREACHED*/ + } + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { + err(1, "sysctl(ICMPV6CTL_ND6_DRLIST)"); + /*NOTREACHED*/ + } + + ep = (struct in6_defrouter *)(buf + l); + for (p = (struct in6_defrouter *)buf; p < ep; p++) { + int rtpref; + + if (getnameinfo((struct sockaddr *)&p->rtaddr, + p->rtaddr.sin6_len, host_buf, sizeof(host_buf), NULL, 0, + NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0)) != 0) + strlcpy(host_buf, "?", sizeof(host_buf)); + + printf("%s if=%s", host_buf, + if_indextoname(p->if_index, ifix_buf)); + printf(", flags=%s%s", + p->flags & ND_RA_FLAG_MANAGED ? "M" : "", + p->flags & ND_RA_FLAG_OTHER ? "O" : ""); + rtpref = ((p->flags & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff; + printf(", pref=%s", rtpref_str[rtpref]); + + gettimeofday(&time, 0); + if (p->expire == 0) + printf(", expire=Never\n"); + else + printf(", expire=%s\n", + sec2str(p->expire - time.tv_sec)); + } + free(buf); +#else struct in6_drlist dr; int s, i; struct timeval time; if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - perror("ndp: socket"); - exit(1); + err(1, "socket"); + /* NOTREACHED */ } bzero(&dr, sizeof(dr)); strcpy(dr.ifname, "lo0"); /* dummy */ if (ioctl(s, SIOCGDRLST_IN6, (caddr_t)&dr) < 0) { - perror("ioctl (SIOCGDRLST_IN6)"); - exit(1); + err(1, "ioctl(SIOCGDRLST_IN6)"); + /* NOTREACHED */ } #define DR dr.defrouter[i] - for (i = 0 ; DR.if_index && i < PRLSTSIZ ; i++) { + for (i = 0 ; DR.if_index && i < DRLSTSIZ ; i++) { struct sockaddr_in6 sin6; bzero(&sin6, sizeof(sin6)); @@ -1009,11 +1092,128 @@ rtrlist() } #undef DR close(s); +#endif } void plist() { +#ifdef ICMPV6CTL_ND6_PRLIST + int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_PRLIST }; + char *buf; + struct in6_prefix *p, *ep, *n; + struct sockaddr_in6 *advrtr; + size_t l; + struct timeval time; +#ifdef NI_WITHSCOPEID + const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; + int ninflags = (nflag ? NI_NUMERICHOST : 0) | NI_WITHSCOPEID; +#else + const int niflags = NI_NUMERICHOST; + int ninflags = nflag ? NI_NUMERICHOST : 0; +#endif + char namebuf[NI_MAXHOST]; + + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) { + err(1, "sysctl(ICMPV6CTL_ND6_PRLIST)"); + /*NOTREACHED*/ + } + buf = malloc(l); + if (!buf) { + errx(1, "not enough core"); + /*NOTREACHED*/ + } + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { + err(1, "sysctl(ICMPV6CTL_ND6_PRLIST)"); + /*NOTREACHED*/ + } + + ep = (struct in6_prefix *)(buf + l); + for (p = (struct in6_prefix *)buf; p < ep; p = n) { + advrtr = (struct sockaddr_in6 *)(p + 1); + n = (struct in6_prefix *)&advrtr[p->advrtrs]; + + if (getnameinfo((struct sockaddr *)&p->prefix, + p->prefix.sin6_len, namebuf, sizeof(namebuf), + NULL, 0, niflags) != 0) + strlcpy(namebuf, "?", sizeof(namebuf)); + printf("%s/%d if=%s\n", namebuf, p->prefixlen, + if_indextoname(p->if_index, ifix_buf)); + + gettimeofday(&time, 0); + /* + * meaning of fields, especially flags, is very different + * by origin. notify the difference to the users. + */ + printf("flags=%s%s%s%s%s", + p->raflags.onlink ? "L" : "", + p->raflags.autonomous ? "A" : "", + (p->flags & NDPRF_ONLINK) != 0 ? "O" : "", + (p->flags & NDPRF_DETACHED) != 0 ? "D" : "", +#ifdef NDPRF_HOME + (p->flags & NDPRF_HOME) != 0 ? "H" : "" +#else + "" +#endif + ); + if (p->vltime == ND6_INFINITE_LIFETIME) + printf(" vltime=infinity"); + else + printf(" vltime=%ld", (long)p->vltime); + if (p->pltime == ND6_INFINITE_LIFETIME) + printf(", pltime=infinity"); + else + printf(", pltime=%ld", (long)p->pltime); + if (p->expire == 0) + printf(", expire=Never"); + else if (p->expire >= time.tv_sec) + printf(", expire=%s", + sec2str(p->expire - time.tv_sec)); + else + printf(", expired"); + printf(", ref=%d", p->refcnt); + printf("\n"); + /* + * "advertising router" list is meaningful only if the prefix + * information is from RA. + */ + if (p->advrtrs) { + int j; + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)(p + 1); + printf(" advertised by\n"); + for (j = 0; j < p->advrtrs; j++) { + struct in6_nbrinfo *nbi; + + if (getnameinfo((struct sockaddr *)sin6, + sin6->sin6_len, namebuf, sizeof(namebuf), + NULL, 0, ninflags) != 0) + strlcpy(namebuf, "?", sizeof(namebuf)); + printf(" %s", namebuf); + + nbi = getnbrinfo(&sin6->sin6_addr, p->if_index, + 0); + if (nbi) { + switch(nbi->state) { + case ND6_LLINFO_REACHABLE: + case ND6_LLINFO_STALE: + case ND6_LLINFO_DELAY: + case ND6_LLINFO_PROBE: + printf(" (reachable)\n"); + break; + default: + printf(" (unreachable)\n"); + } + } else + printf(" (no neighbor state)\n"); + sin6++; + } + } else + printf(" No advertising router\n"); + } + free(buf); +#else struct in6_prlist pr; int s, i; struct timeval time; @@ -1021,14 +1221,14 @@ plist() gettimeofday(&time, 0); if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - perror("ndp: socket"); - exit(1); + err(1, "socket"); + /* NOTREACHED */ } bzero(&pr, sizeof(pr)); strcpy(pr.ifname, "lo0"); /* dummy */ if (ioctl(s, SIOCGPRLST_IN6, (caddr_t)&pr) < 0) { - perror("ioctl (SIOCGPRLST_IN6)"); - exit(1); + err(1, "ioctl(SIOCGPRLST_IN6)"); + /* NOTREACHED */ } #define PR pr.prefix[i] for (i = 0; PR.if_index && i < PRLSTSIZ ; i++) { @@ -1078,13 +1278,22 @@ plist() * meaning of fields, especially flags, is very different * by origin. notify the difference to the users. */ - printf(" %s", PR.origin == PR_ORIG_RA ? "" : "advertise: "); +#if 0 + printf(" %s", + PR.origin == PR_ORIG_RA ? "" : "advertise: "); +#endif #ifdef NDPRF_ONLINK - printf("flags=%s%s%s%s", + printf("flags=%s%s%s%s%s", PR.raflags.onlink ? "L" : "", PR.raflags.autonomous ? "A" : "", (PR.flags & NDPRF_ONLINK) != 0 ? "O" : "", - (PR.flags & NDPRF_DETACHED) != 0 ? "D" : ""); + (PR.flags & NDPRF_DETACHED) != 0 ? "D" : "", +#ifdef NDPRF_HOME + (PR.flags & NDPRF_HOME) != 0 ? "H" : "" +#else + "" +#endif + ); #else printf("flags=%s%s", PR.raflags.onlink ? "L" : "", @@ -1108,6 +1317,7 @@ plist() #ifdef NDPRF_ONLINK printf(", ref=%d", PR.refcnt); #endif +#if 0 switch (PR.origin) { case PR_ORIG_RA: printf(", origin=RA"); @@ -1125,12 +1335,14 @@ plist() printf(", origin=?"); break; } +#endif printf("\n"); /* * "advertising router" list is meaningful only if the prefix * information is from RA. */ - if (PR.origin != PR_ORIG_RA) + if (0 && /* prefix origin is almost obsolted */ + PR.origin != PR_ORIG_RA) ; else if (PR.advrtrs) { int j; @@ -1174,6 +1386,7 @@ plist() } #undef PR close(s); +#endif } void @@ -1214,7 +1427,7 @@ harmonize_rtr() err(1, "socket"); strcpy(dummyif, "lo0"); /* dummy */ if (ioctl(s, SIOCSNDFLUSH_IN6, (caddr_t)&dummyif) < 0) - err(1, "ioctl (SIOCSNDFLUSH_IN6)"); + err(1, "ioctl(SIOCSNDFLUSH_IN6)"); close(s); } @@ -1241,7 +1454,7 @@ setdefif(ifname) ndifreq.ifindex = ifindex; if (ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq) < 0) - err(1, "ioctl (SIOCSDEFIFACE_IN6)"); + err(1, "ioctl(SIOCSDEFIFACE_IN6)"); close(s); } @@ -1259,7 +1472,7 @@ getdefif() strcpy(ndifreq.ifname, "lo0"); /* dummy */ if (ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq) < 0) - err(1, "ioctl (SIOCGDEFIFACE_IN6)"); + err(1, "ioctl(SIOCGDEFIFACE_IN6)"); if (ndifreq.ifindex == 0) printf("No default interface.\n"); |