add -I and -l. cleanup on screen formatting.

(sync with latest KAME)
This commit is contained in:
itojun 1999-12-13 15:30:25 +00:00
parent 5979fc87e0
commit 644cf51b1e
2 changed files with 216 additions and 72 deletions

View File

@ -25,8 +25,8 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" $NetBSD: ndp.8,v 1.3 1999/09/03 03:54:47 itojun Exp $ .\" $NetBSD: ndp.8,v 1.4 1999/12/13 15:30:25 itojun Exp $
.\" KAME Id: ndp.8,v 1.1.1.1 1999/08/08 23:30:48 itojun Exp .\" KAME Id: ndp.8,v 1.4 1999/12/13 11:07:41 jinmei Exp
.\" .\"
.Dd May 17, 1998 .Dd May 17, 1998
.Dt NDP 8 .Dt NDP 8
@ -39,10 +39,10 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm ndp .Nm ndp
.Fl a .Fl a
.Op Fl nt .Op Fl ntl
.Nm ndp .Nm ndp
.Fl A Ar wait .Fl A Ar wait
.Op Fl nt .Op Fl ntl
.Nm ndp .Nm ndp
.Fl c .Fl c
.Op Fl nt .Op Fl nt
@ -57,6 +57,9 @@
.Nm ndp .Nm ndp
.Fl H .Fl H
.Nm ndp .Nm ndp
.Fl I
.Op delete \(ba Ar interface
.Nm ndp
.Fl i .Fl i
.Ar interface .Ar interface
.Nm ndp .Nm ndp
@ -98,8 +101,21 @@ Parse the file specified by
.It Fl H .It Fl H
Harmonize consistency between the routing table and the default router Harmonize consistency between the routing table and the default router
list; install the top entry of the list into the kernel routing table. list; install the top entry of the list into the kernel routing table.
.It Fl I Op delete \(ba Ar interface
Shows or specifies the default interface used as the default route when
there is no default router. If no argument is given to the option,
the current deafult interface will be shown.
If an
.Ar interface
is specified, the interface will be used as the default.
If a special keyword
.Ic delete
is specified, the current default interface will be deleted from the kernel.
.It Fl i .It Fl i
.Ar interface
view ND information for specified interface. view ND information for specified interface.
.It Fl l
Do not truncate numeric IPv6 address.
.It Fl n .It Fl n
Do not try to resolve numeric address to hostname. Do not try to resolve numeric address to hostname.
.It Fl p .It Fl p

View File

@ -1,4 +1,4 @@
/* $NetBSD: ndp.c,v 1.3 1999/09/03 03:54:47 itojun Exp $ */ /* $NetBSD: ndp.c,v 1.4 1999/12/13 15:30:25 itojun Exp $ */
/* /*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@ -115,6 +115,10 @@
#include <unistd.h> #include <unistd.h>
#include "gmt2local.h" #include "gmt2local.h"
#ifndef NI_WITHSCOPEID
#define NI_WITHSCOPEID 0
#endif
/* packing rule for routing socket */ /* packing rule for routing socket */
#define ROUNDUP(a) \ #define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
@ -128,8 +132,10 @@ static int tflag;
static int32_t thiszone; /* time difference with gmt */ static int32_t thiszone; /* time difference with gmt */
static int s = -1; static int s = -1;
static int repeat = 0; static int repeat = 0;
static int lflag = 0;
char ntop_buf[INET6_ADDRSTRLEN]; /* inet_ntop() */ char ntop_buf[INET6_ADDRSTRLEN]; /* inet_ntop() */
char host_buf[NI_MAXHOST]; /* getnameinfo() */
char ifix_buf[IFNAMSIZ]; /* if_indextoname() */ char ifix_buf[IFNAMSIZ]; /* if_indextoname() */
int main __P((int, char **)); int main __P((int, char **));
@ -139,7 +145,8 @@ int set __P((int, char **));
void get __P((char *)); void get __P((char *));
int delete __P((char *)); int delete __P((char *));
void dump __P((struct in6_addr *)); void dump __P((struct in6_addr *));
static struct in6_nbrinfo *getnbrinfo __P((struct in6_addr *addr, int ifindex)); static struct in6_nbrinfo *getnbrinfo __P((struct in6_addr *addr,
int ifindex, int));
static char *ether_str __P((struct sockaddr_dl *)); static char *ether_str __P((struct sockaddr_dl *));
int ndp_ether_aton __P((char *, u_char *)); int ndp_ether_aton __P((char *, u_char *));
void usage __P((void)); void usage __P((void));
@ -150,6 +157,10 @@ void plist __P((void));
void pfx_flush __P((void)); void pfx_flush __P((void));
void rtr_flush __P((void)); void rtr_flush __P((void));
void harmonize_rtr __P((void)); void harmonize_rtr __P((void));
#ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */
static void getdefif __P((void));
static void setdefif __P((char *));
#endif
static char *sec2str __P((time_t t)); static char *sec2str __P((time_t t));
static char *ether_str __P((struct sockaddr_dl *sdl)); static char *ether_str __P((struct sockaddr_dl *sdl));
static void ts_print __P((const struct timeval *)); static void ts_print __P((const struct timeval *));
@ -167,7 +178,7 @@ main(argc, argv)
pid = getpid(); pid = getpid();
thiszone = gmt2local(0); thiszone = gmt2local(0);
while ((ch = getopt(argc, argv, "acndfiprstA:HPR")) != EOF) while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != EOF)
switch ((char)ch) { switch ((char)ch) {
case 'a': case 'a':
aflag = 1; aflag = 1;
@ -179,6 +190,16 @@ main(argc, argv)
case 'd': case 'd':
dflag = 1; dflag = 1;
break; 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 'i' : case 'i' :
if (argc != 3) if (argc != 3)
usage(); usage();
@ -195,6 +216,9 @@ main(argc, argv)
usage(); usage();
file(argv[2]); file(argv[2]);
exit(0); exit(0);
case 'l' :
lflag = 1;
break;
case 'r' : case 'r' :
rflag = 1; rflag = 1;
break; break;
@ -417,9 +441,10 @@ get(host)
sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
dump(&sin->sin6_addr); dump(&sin->sin6_addr);
if (found_entry == 0) { if (found_entry == 0) {
printf("%s (%s) -- no entry\n", getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf,
host, inet_ntop(AF_INET6, &sin->sin6_addr, ntop_buf, sizeof(host_buf), NULL ,0,
sizeof(ntop_buf))); NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0));
printf("%s (%s) -- no entry\n", host, host_buf);
exit(1); exit(1);
} }
} }
@ -431,7 +456,7 @@ int
delete(host) delete(host)
char *host; char *host;
{ {
register struct sockaddr_in6 *sin = &sin_m; struct sockaddr_in6 *sin = &sin_m;
register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
struct sockaddr_dl *sdl; struct sockaddr_dl *sdl;
struct addrinfo hints, *res; struct addrinfo hints, *res;
@ -470,10 +495,14 @@ delete:
printf("cannot locate %s\n", host); printf("cannot locate %s\n", host);
return (1); return (1);
} }
if (rtmsg(RTM_DELETE) == 0) if (rtmsg(RTM_DELETE) == 0) {
printf("%s (%s) deleted\n", host, getnameinfo((struct sockaddr *)sin,
inet_ntop(AF_INET6, &sin->sin6_addr, ntop_buf, sin->sin6_len, host_buf,
sizeof(ntop_buf))); sizeof(host_buf), NULL, 0,
NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0));
printf("%s (%s) deleted\n", host, host_buf);
}
return 0; return 0;
} }
@ -486,18 +515,19 @@ dump(addr)
{ {
int mib[6]; int mib[6];
size_t needed; size_t needed;
char *host, *lim, *buf, *next; char *lim, *buf, *next;
struct rt_msghdr *rtm; struct rt_msghdr *rtm;
struct sockaddr_in6 *sin; struct sockaddr_in6 *sin;
struct sockaddr_dl *sdl; struct sockaddr_dl *sdl;
extern int h_errno; extern int h_errno;
struct hostent *hp;
struct in6_nbrinfo *nbi; struct in6_nbrinfo *nbi;
struct timeval time; struct timeval time;
int addrwidth;
char flgbuf[8];
/* Print header */ /* Print header */
if (!tflag) if (!tflag)
printf("%-29.29s %-18.18s %6.6s %-9.9s %2s %4s %4s\n", printf("%-31.31s %-17.17s %6.6s %-9.9s %2s %4s %4s\n",
"Neighbor", "Linklayer Address", "Netif", "Expire", "Neighbor", "Linklayer Address", "Netif", "Expire",
"St", "Flgs", "Prbs"); "St", "Flgs", "Prbs");
@ -533,33 +563,39 @@ again:;
continue; continue;
if (fflag == 1) { if (fflag == 1) {
delete((char *)inet_ntop(AF_INET6, &sin->sin6_addr, delete((char *)inet_ntop(AF_INET6, &sin->sin6_addr,
ntop_buf, sizeof(ntop_buf))); ntop_buf, sizeof(ntop_buf)));
continue; continue;
} }
host = NULL;
if (nflag == 0) {
hp = gethostbyaddr((char *)&sin->sin6_addr,
sizeof(struct in6_addr), AF_INET6);
if (hp)
host = hp->h_name;
}
if (host == NULL) {
inet_ntop(AF_INET6, &sin->sin6_addr,
ntop_buf, sizeof(ntop_buf));
host = ntop_buf;
}
if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&sin->sin6_addr)) {
/* XXX: should scope id be filled in the kernel? */
if (sin->sin6_scope_id == 0)
sin->sin6_scope_id = sdl->sdl_index;
/* XXX: KAME specific hack; removed the embedded id */
*(u_int16_t *)&sin->sin6_addr.s6_addr[2] = 0;
}
getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf,
sizeof(host_buf), NULL, 0,
NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0));
gettimeofday(&time, 0); gettimeofday(&time, 0);
if (tflag) if (tflag)
ts_print(&time); ts_print(&time);
printf("%-29.29s %-18.18s %6.6s", host, if (lflag) {
addrwidth = strlen(host_buf);
if (addrwidth < 31)
addrwidth = 31;
} else
addrwidth = 31;
printf("%-*.*s %-17.17s %6.6s", addrwidth, addrwidth, host_buf,
ether_str(sdl), ether_str(sdl),
if_indextoname(sdl->sdl_index, ifix_buf)); if_indextoname(sdl->sdl_index, ifix_buf));
/* Print neighbor discovery specific informations */ /* Print neighbor discovery specific informations */
putchar(' '); nbi = getnbrinfo(&sin->sin6_addr, sdl->sdl_index, 1);
nbi = getnbrinfo(&sin->sin6_addr, sdl->sdl_index);
if (nbi) { if (nbi) {
if (nbi->expire > time.tv_sec) { if (nbi->expire > time.tv_sec) {
printf(" %-9.9s", printf(" %-9.9s",
@ -604,31 +640,28 @@ again:;
warnx("failed to get neighbor information"); warnx("failed to get neighbor information");
printf(" "); printf(" ");
} }
/* other flags */
putchar(' '); putchar(' ');
{
u_char flgbuf[8], *p = flgbuf;
flgbuf[0] = '\0'; /*
if (isrouter) * other flags. R: router, P: proxy, W: ??
p += sprintf((char *)p, "R"); */
#ifndef RADISH if ((rtm->rtm_addrs & RTA_NETMASK) == 0) {
if (rtm->rtm_addrs & RTA_NETMASK) { snprintf(flgbuf, sizeof(flgbuf), "%s",
sin = (struct sockaddr_in6 *) isrouter ? "R" : "");
(sdl->sdl_len + (char *)sdl); } else {
if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr)) sin = (struct sockaddr_in6 *)
p += sprintf((char *)p, "P"); (sdl->sdl_len + (char *)sdl);
if (sin->sin6_len != sizeof(struct sockaddr_in6)) snprintf(flgbuf, sizeof(flgbuf), "%s%s%s",
p += sprintf((char *)p, "W"); isrouter ? "R" : "",
} !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr)
#endif /*RADISH*/ ? "P" : "",
printf("%4s", flgbuf); (sin->sin6_len != sizeof(struct sockaddr_in6))
? "W" : "");
} }
printf(" %-4.4s", flgbuf);
putchar(' ');
if (prbs) if (prbs)
printf("% 4d", prbs); printf(" %4d", prbs);
printf("\n"); printf("\n");
} }
@ -641,9 +674,10 @@ again:;
} }
static struct in6_nbrinfo * static struct in6_nbrinfo *
getnbrinfo(addr, ifindex) getnbrinfo(addr, ifindex, warning)
struct in6_addr *addr; struct in6_addr *addr;
int ifindex; int ifindex;
int warning;
{ {
static struct in6_nbrinfo nbi; static struct in6_nbrinfo nbi;
int s; int s;
@ -655,7 +689,8 @@ getnbrinfo(addr, ifindex)
if_indextoname(ifindex, nbi.ifname); if_indextoname(ifindex, nbi.ifname);
nbi.addr = *addr; nbi.addr = *addr;
if (ioctl(s, SIOCGNBRINFO_IN6, (caddr_t)&nbi) < 0) { if (ioctl(s, SIOCGNBRINFO_IN6, (caddr_t)&nbi) < 0) {
warn("ioctl"); if (warning)
warn("ioctl");
close(s); close(s);
return(NULL); return(NULL);
} }
@ -705,12 +740,15 @@ void
usage() usage()
{ {
printf("usage: ndp hostname\n"); printf("usage: ndp hostname\n");
printf(" ndp -a[nt]\n"); printf(" ndp -a[ntl]\n");
printf(" ndp [-nt] -A wait\n"); printf(" ndp [-ntl] -A wait\n");
printf(" ndp -c[nt]\n"); printf(" ndp -c[nt]\n");
printf(" ndp -d[nt] hostname\n"); printf(" ndp -d[nt] hostname\n");
printf(" ndp -f[nt] filename\n"); printf(" ndp -f[nt] filename\n");
printf(" ndp -i interface\n"); printf(" ndp -i interface\n");
#ifdef SIOCSDEFIFACE_IN6
printf(" ndp -I [interface|delete]\n");
#endif
printf(" ndp -p\n"); printf(" ndp -p\n");
printf(" ndp -r\n"); printf(" ndp -r\n");
printf(" ndp -s hostname ether_addr [temp]\n"); printf(" ndp -s hostname ether_addr [temp]\n");
@ -825,8 +863,17 @@ rtrlist()
} }
#define DR dr.defrouter[i] #define DR dr.defrouter[i]
for (i = 0 ; DR.if_index && i < PRLSTSIZ ; i++) { for (i = 0 ; DR.if_index && i < PRLSTSIZ ; i++) {
printf("%s if=%s", inet_ntop(AF_INET6, &DR.rtaddr, struct sockaddr_in6 sin6;
ntop_buf, sizeof(ntop_buf)),
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
sin6.sin6_addr = DR.rtaddr;
getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, host_buf,
sizeof(host_buf), NULL, 0,
NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0));
printf("%s if=%s", host_buf,
if_indextoname(DR.if_index, ifix_buf)); if_indextoname(DR.if_index, ifix_buf));
printf(", flags=%s%s", printf(", flags=%s%s",
DR.flags & ND_RA_FLAG_MANAGED ? "M" : "", DR.flags & ND_RA_FLAG_MANAGED ? "M" : "",
@ -890,10 +937,36 @@ plist()
int j; int j;
printf(" advertised by\n"); printf(" advertised by\n");
for (j = 0; j < PR.advrtrs; j++) { for (j = 0; j < PR.advrtrs; j++) {
printf(" %s\n", struct sockaddr_in6 sin6;
inet_ntop(AF_INET6, &PR.advrtr[j], struct in6_nbrinfo *nbi;
ntop_buf,
sizeof(ntop_buf))); bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
sin6.sin6_addr = PR.advrtr[j];
sin6.sin6_scope_id = PR.if_index; /* XXX */
getnameinfo((struct sockaddr *)&sin6,
sin6.sin6_len, host_buf,
sizeof(host_buf), NULL, 0,
NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0));
printf(" %s", host_buf);
nbi = getnbrinfo(&sin6.sin6_addr, PR.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");
} }
if (PR.advrtrs > DRLSTSIZ) if (PR.advrtrs > DRLSTSIZ)
printf(" and %d routers\n", printf(" and %d routers\n",
@ -930,6 +1003,8 @@ rtr_flush()
strcpy(dummyif, "lo0"); /* dummy */ strcpy(dummyif, "lo0"); /* dummy */
if (ioctl(s, SIOCSRTRFLUSH_IN6, (caddr_t)&dummyif) < 0) if (ioctl(s, SIOCSRTRFLUSH_IN6, (caddr_t)&dummyif) < 0)
err(1, "ioctl(SIOCSRTRFLUSH_IN6)"); err(1, "ioctl(SIOCSRTRFLUSH_IN6)");
close(s);
} }
void void
@ -938,17 +1013,70 @@ harmonize_rtr()
char dummyif[IFNAMSIZ+8]; char dummyif[IFNAMSIZ+8];
int s; int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
perror("ndp: socket"); err(1, "socket");
exit(1);
}
strcpy(dummyif, "lo0"); /* dummy */ strcpy(dummyif, "lo0"); /* dummy */
if (ioctl(s, SIOCSNDFLUSH_IN6, (caddr_t)&dummyif) < 0) { if (ioctl(s, SIOCSNDFLUSH_IN6, (caddr_t)&dummyif) < 0)
perror("ioctl (SIOCSNDFLUSH_IN6)"); err(1, "ioctl (SIOCSNDFLUSH_IN6)");
exit(1);
} close(s);
} }
#ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */
static void
setdefif(ifname)
char *ifname;
{
struct in6_ndifreq ndifreq;
unsigned int ifindex;
if (strcasecmp(ifname, "delete") == 0)
ifindex = 0;
else {
if ((ifindex = if_nametoindex(ifname)) == 0)
err(1, "failed to resolve i/f index for %s", ifname);
}
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
strcpy(ndifreq.ifname, "lo0"); /* dummy */
ndifreq.ifindex = ifindex;
if (ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq) < 0)
err(1, "ioctl (SIOCSDEFIFACE_IN6)");
close(s);
}
static void
getdefif()
{
struct in6_ndifreq ndifreq;
char ifname[IFNAMSIZ+8];
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
memset(&ndifreq, 0, sizeof(ndifreq));
strcpy(ndifreq.ifname, "lo0"); /* dummy */
if (ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq) < 0)
err(1, "ioctl (SIOCGDEFIFACE_IN6)");
if (ndifreq.ifindex == 0)
printf("No default interface.\n");
else {
if ((if_indextoname(ndifreq.ifindex, ifname)) == NULL)
err(1, "failed to resolve ifname for index %lu",
ndifreq.ifindex);
printf("ND default interface = %s\n", ifname);
}
close(s);
}
#endif
static char * static char *
sec2str(total) sec2str(total)
time_t total; time_t total;