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
.\" SUCH DAMAGE.
.\"
.\" $NetBSD: ndp.8,v 1.3 1999/09/03 03:54:47 itojun Exp $
.\" KAME Id: ndp.8,v 1.1.1.1 1999/08/08 23:30:48 itojun Exp
.\" $NetBSD: ndp.8,v 1.4 1999/12/13 15:30:25 itojun Exp $
.\" KAME Id: ndp.8,v 1.4 1999/12/13 11:07:41 jinmei Exp
.\"
.Dd May 17, 1998
.Dt NDP 8
@ -39,10 +39,10 @@
.Sh SYNOPSIS
.Nm ndp
.Fl a
.Op Fl nt
.Op Fl ntl
.Nm ndp
.Fl A Ar wait
.Op Fl nt
.Op Fl ntl
.Nm ndp
.Fl c
.Op Fl nt
@ -57,6 +57,9 @@
.Nm ndp
.Fl H
.Nm ndp
.Fl I
.Op delete \(ba Ar interface
.Nm ndp
.Fl i
.Ar interface
.Nm ndp
@ -98,8 +101,21 @@ Parse the file specified by
.It Fl H
Harmonize consistency between the routing table and the default router
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
.Ar interface
view ND information for specified interface.
.It Fl l
Do not truncate numeric IPv6 address.
.It Fl n
Do not try to resolve numeric address to hostname.
.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.
@ -115,6 +115,10 @@
#include <unistd.h>
#include "gmt2local.h"
#ifndef NI_WITHSCOPEID
#define NI_WITHSCOPEID 0
#endif
/* packing rule for routing socket */
#define ROUNDUP(a) \
((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 int s = -1;
static int repeat = 0;
static int lflag = 0;
char ntop_buf[INET6_ADDRSTRLEN]; /* inet_ntop() */
char host_buf[NI_MAXHOST]; /* getnameinfo() */
char ifix_buf[IFNAMSIZ]; /* if_indextoname() */
int main __P((int, char **));
@ -139,7 +145,8 @@ 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));
static struct in6_nbrinfo *getnbrinfo __P((struct in6_addr *addr,
int ifindex, int));
static char *ether_str __P((struct sockaddr_dl *));
int ndp_ether_aton __P((char *, u_char *));
void usage __P((void));
@ -150,6 +157,10 @@ void plist __P((void));
void pfx_flush __P((void));
void rtr_flush __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 *ether_str __P((struct sockaddr_dl *sdl));
static void ts_print __P((const struct timeval *));
@ -167,7 +178,7 @@ main(argc, argv)
pid = getpid();
thiszone = gmt2local(0);
while ((ch = getopt(argc, argv, "acndfiprstA:HPR")) != EOF)
while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != EOF)
switch ((char)ch) {
case 'a':
aflag = 1;
@ -179,6 +190,16 @@ main(argc, argv)
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 'i' :
if (argc != 3)
usage();
@ -195,6 +216,9 @@ main(argc, argv)
usage();
file(argv[2]);
exit(0);
case 'l' :
lflag = 1;
break;
case 'r' :
rflag = 1;
break;
@ -417,9 +441,10 @@ get(host)
sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
dump(&sin->sin6_addr);
if (found_entry == 0) {
printf("%s (%s) -- no entry\n",
host, inet_ntop(AF_INET6, &sin->sin6_addr, ntop_buf,
sizeof(ntop_buf)));
getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf,
sizeof(host_buf), NULL ,0,
NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0));
printf("%s (%s) -- no entry\n", host, host_buf);
exit(1);
}
}
@ -431,7 +456,7 @@ int
delete(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;
struct sockaddr_dl *sdl;
struct addrinfo hints, *res;
@ -470,10 +495,14 @@ delete:
printf("cannot locate %s\n", host);
return (1);
}
if (rtmsg(RTM_DELETE) == 0)
printf("%s (%s) deleted\n", host,
inet_ntop(AF_INET6, &sin->sin6_addr, ntop_buf,
sizeof(ntop_buf)));
if (rtmsg(RTM_DELETE) == 0) {
getnameinfo((struct sockaddr *)sin,
sin->sin6_len, host_buf,
sizeof(host_buf), NULL, 0,
NI_WITHSCOPEID | (nflag ? NI_NUMERICHOST : 0));
printf("%s (%s) deleted\n", host, host_buf);
}
return 0;
}
@ -486,18 +515,19 @@ dump(addr)
{
int mib[6];
size_t needed;
char *host, *lim, *buf, *next;
char *lim, *buf, *next;
struct rt_msghdr *rtm;
struct sockaddr_in6 *sin;
struct sockaddr_dl *sdl;
extern int h_errno;
struct hostent *hp;
struct in6_nbrinfo *nbi;
struct timeval time;
int addrwidth;
char flgbuf[8];
/* Print header */
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",
"St", "Flgs", "Prbs");
@ -536,30 +566,36 @@ again:;
ntop_buf, sizeof(ntop_buf)));
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);
if (tflag)
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),
if_indextoname(sdl->sdl_index, ifix_buf));
/* Print neighbor discovery specific informations */
putchar(' ');
nbi = getnbrinfo(&sin->sin6_addr, sdl->sdl_index);
nbi = getnbrinfo(&sin->sin6_addr, sdl->sdl_index, 1);
if (nbi) {
if (nbi->expire > time.tv_sec) {
printf(" %-9.9s",
@ -604,29 +640,26 @@ again:;
warnx("failed to get neighbor information");
printf(" ");
}
/* other flags */
putchar(' ');
{
u_char flgbuf[8], *p = flgbuf;
flgbuf[0] = '\0';
if (isrouter)
p += sprintf((char *)p, "R");
#ifndef RADISH
if (rtm->rtm_addrs & RTA_NETMASK) {
/*
* other flags. R: router, P: proxy, W: ??
*/
if ((rtm->rtm_addrs & RTA_NETMASK) == 0) {
snprintf(flgbuf, sizeof(flgbuf), "%s",
isrouter ? "R" : "");
} else {
sin = (struct sockaddr_in6 *)
(sdl->sdl_len + (char *)sdl);
if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
p += sprintf((char *)p, "P");
if (sin->sin6_len != sizeof(struct sockaddr_in6))
p += sprintf((char *)p, "W");
}
#endif /*RADISH*/
printf("%4s", flgbuf);
snprintf(flgbuf, sizeof(flgbuf), "%s%s%s",
isrouter ? "R" : "",
!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr)
? "P" : "",
(sin->sin6_len != sizeof(struct sockaddr_in6))
? "W" : "");
}
printf(" %-4.4s", flgbuf);
putchar(' ');
if (prbs)
printf(" %4d", prbs);
@ -641,9 +674,10 @@ again:;
}
static struct in6_nbrinfo *
getnbrinfo(addr, ifindex)
getnbrinfo(addr, ifindex, warning)
struct in6_addr *addr;
int ifindex;
int warning;
{
static struct in6_nbrinfo nbi;
int s;
@ -655,6 +689,7 @@ getnbrinfo(addr, ifindex)
if_indextoname(ifindex, nbi.ifname);
nbi.addr = *addr;
if (ioctl(s, SIOCGNBRINFO_IN6, (caddr_t)&nbi) < 0) {
if (warning)
warn("ioctl");
close(s);
return(NULL);
@ -705,12 +740,15 @@ void
usage()
{
printf("usage: ndp hostname\n");
printf(" ndp -a[nt]\n");
printf(" ndp [-nt] -A wait\n");
printf(" ndp -a[ntl]\n");
printf(" ndp [-ntl] -A wait\n");
printf(" ndp -c[nt]\n");
printf(" ndp -d[nt] hostname\n");
printf(" ndp -f[nt] filename\n");
printf(" ndp -i interface\n");
#ifdef SIOCSDEFIFACE_IN6
printf(" ndp -I [interface|delete]\n");
#endif
printf(" ndp -p\n");
printf(" ndp -r\n");
printf(" ndp -s hostname ether_addr [temp]\n");
@ -825,8 +863,17 @@ rtrlist()
}
#define DR dr.defrouter[i]
for (i = 0 ; DR.if_index && i < PRLSTSIZ ; i++) {
printf("%s if=%s", inet_ntop(AF_INET6, &DR.rtaddr,
ntop_buf, sizeof(ntop_buf)),
struct sockaddr_in6 sin6;
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));
printf(", flags=%s%s",
DR.flags & ND_RA_FLAG_MANAGED ? "M" : "",
@ -890,10 +937,36 @@ plist()
int j;
printf(" advertised by\n");
for (j = 0; j < PR.advrtrs; j++) {
printf(" %s\n",
inet_ntop(AF_INET6, &PR.advrtr[j],
ntop_buf,
sizeof(ntop_buf)));
struct sockaddr_in6 sin6;
struct in6_nbrinfo *nbi;
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)
printf(" and %d routers\n",
@ -930,6 +1003,8 @@ rtr_flush()
strcpy(dummyif, "lo0"); /* dummy */
if (ioctl(s, SIOCSRTRFLUSH_IN6, (caddr_t)&dummyif) < 0)
err(1, "ioctl(SIOCSRTRFLUSH_IN6)");
close(s);
}
void
@ -938,17 +1013,70 @@ harmonize_rtr()
char dummyif[IFNAMSIZ+8];
int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
perror("ndp: socket");
exit(1);
}
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
strcpy(dummyif, "lo0"); /* dummy */
if (ioctl(s, SIOCSNDFLUSH_IN6, (caddr_t)&dummyif) < 0) {
perror("ioctl (SIOCSNDFLUSH_IN6)");
exit(1);
if (ioctl(s, SIOCSNDFLUSH_IN6, (caddr_t)&dummyif) < 0)
err(1, "ioctl (SIOCSNDFLUSH_IN6)");
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 *
sec2str(total)
time_t total;