more posix-compliant arg parsing. sync with kame. help from deraadt

This commit is contained in:
itojun 2002-06-03 03:34:36 +00:00
parent ad4cab117d
commit 016477e967
2 changed files with 199 additions and 140 deletions

View File

@ -1,5 +1,5 @@
.\" $NetBSD: ndp.8,v 1.15 2002/05/29 08:51:28 wiz Exp $
.\" $KAME: ndp.8,v 1.19 2002/05/29 07:34:01 itojun Exp $
.\" $NetBSD: ndp.8,v 1.16 2002/06/03 03:34:36 itojun Exp $
.\" $KAME: ndp.8,v 1.25 2002/06/03 03:30:16 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@ -38,27 +38,26 @@
.\"
.Sh SYNOPSIS
.Nm ndp
.Op Fl nt
.Fl a
.Op Fl nt
.Nm ndp
.Op Fl nt
.Fl A Ar wait
.Op Fl nt
.Nm ndp
.Op Fl nt
.Fl c
.Op Fl nt
.Nm ndp
.Fl d
.Op Fl nt
.Ar hostname
.Fl d Ar hostname
.Nm ndp
.Fl f
.Op Fl nt
.Ar filename
.Fl f Ar filename
.Nm ndp
.Fl H
.Nm ndp
.Fl I
.Op delete \(ba Ar interface
.Fl I Ar interface
.Nm ndp
.Fl I Li delete
.Nm ndp
.Fl i
.Ar interface
@ -72,10 +71,8 @@
.Nm ndp
.Fl R
.Nm ndp
.Fl s
.Op Fl nt
.Ar nodename
.Ar ether_addr
.Fl s Ar nodename ether_addr
.Op Li temp
.Op Li proxy
.\"
@ -83,12 +80,12 @@
The
.Nm
command manipulates the address mapping table
used by Neighbor Discovery Protocol (NDP).
used by the Neighbor Discovery Protocol (NDP).
.Bl -tag -width Ds
.It Fl a
Dump the currently existing NDP entries.
The following information will be printed:
.Bl -tag -width Ds
.Bl -tag -width NeighborXX
.It Neighbor
IPv6 address of the neighbor.
.It Linklayer Address
@ -99,17 +96,32 @@ when the address is not available.
.It Netif
Network interface associated with the neighbor cache entry.
.It Expire
The time until the expiry of the entry.
The time until expiry of the entry.
The entry could become
.Dq Li permanent
when it will never expire.
.Dq Li permanent ,
in which case it will never expire.
.It S
State of the neighbor cache entry, in a single letter.
They are:
Nostate, Waitdelete, Incomplete, Reachable, Stale, Delay and Probe.
.Dq Li ?
indicates unknown state, which should never happen.
.It Flgs
State of the neighbor cache entry, as a single letter:
.Bl -tag -width indent -compact
.Pp
.It N
Nostate
.It W
Waitdelete
.It I
Incomplete
.It R
Reachable
.It S
Stale
.It D
Deay
.It P
Probe
.It ?
Unknown state (should never happen).
.El
.It Flags
Flags on the neighbor cache entry, in a single letter.
They are: Router, proxy neighbor advertisement
.Pq Dq p .
@ -133,17 +145,17 @@ 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
.It Fl I 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 default interface will be shown.
If an
If a valid
.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.
If
.Ar interface
is not a valid interface name, the current setting will be presented.
.It Fl I Li delete
The current default interface will be deleted from the kernel.
.It Fl i Ar interface Op Ar flags ...
View ND information for the specified interface.
If additional arguments
@ -158,6 +170,7 @@ special character
.Ql - ,
which means the flag should be cleared.
.\"
.Pp
.Bl -tag -width Ds -compact
.It Xo
.Ic nud
@ -165,9 +178,31 @@ which means the flag should be cleared.
turn on or off NUD (Neighbor Unreachability Detection) on the
interface.
NUD is usually turned on by default.
.It Xo
.Ic accept_rtadv
.Xc
specify whether or not to accept Router Advertisement messages
received on the
.Ar interface .
Note that the kernel does not accept Router Advertisement messages
unless the
.Li net.inet6.ip6.accept_rtadv
variable is non-0, even if the flag is on.
This flag is set to 1 by default.
.It Xo
.Ic prefer_source
.Xc
prefer addresses on the
.Ar interface
as candidates of the source address for outgoing packets.
The default value of this flag is off.
For more details about the entire algorithm of source address
selection, see the
.Pa IMPLEMENTATION
file supplied with the KAME kit.
.El
.It Fl n
Do not try to resolve numeric address to hostname.
Do not try to resolve numeric addresses to hostnames.
.It Fl p
Show prefix list.
.It Fl P
@ -188,8 +223,8 @@ responding to requests for
.Ar hostname
even though the host address is not its own.
.It Fl t
Print timestamp on each entries,
to make it possible to merge output with
Print timestamp on each entry,
making it possible to merge output with
.Xr tcpdump 8 .
Most useful when used with
.Fl A .

View File

@ -1,5 +1,5 @@
/* $NetBSD: ndp.c,v 1.21 2002/06/02 23:43:21 itojun Exp $ */
/* $KAME: ndp.c,v 1.91 2002/06/02 15:22:07 itojun Exp $ */
/* $NetBSD: ndp.c,v 1.22 2002/06/03 03:34:36 itojun Exp $ */
/* $KAME: ndp.c,v 1.97 2002/06/03 03:31:25 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@ -117,7 +117,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 */
@ -134,13 +133,13 @@ void getsocket __P((void));
int set __P((int, char **));
void get __P((char *));
int delete __P((char *));
void dump __P((struct in6_addr *));
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));
@ -164,82 +163,63 @@ static char *rtpref_str[] = {
};
#endif
int mode = 0;
char *arg = NULL;
int
main(argc, argv)
int argc;
char **argv;
{
int ch;
int aflag = 0, dflag = 0, sflag = 0, Hflag = 0;
int pflag = 0, rflag = 0, Pflag = 0, Rflag = 0;
pid = getpid();
thiszone = gmt2local(0);
while ((ch = getopt(argc, argv, "acndfIilprstA:HPR")) != -1)
switch ((char)ch) {
while ((ch = getopt(argc, argv, "acd:f:I:i: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':
if (mode) {
usage();
/*NOTREACHED*/
}
mode = ch;
arg = NULL;
break;
case 'd':
dflag = 1;
break;
case 'f':
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' :
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;
repeat = atoi(optarg);
if (repeat < 0)
if (mode) {
usage();
break;
case 'H' :
Hflag = 1;
break;
case 'P':
Pflag = 1;
break;
case 'R':
Rflag = 1;
/*NOTREACHED*/
}
mode = 'a';
repeat = atoi(optarg);
if (repeat < 0) {
usage();
/*NOTREACHED*/
}
break;
default:
usage();
@ -248,45 +228,86 @@ 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 != 0) {
usage();
/*NOTREACHED*/
}
if (strcmp(arg, "default") == 0 || if_nametoindex(arg))
setdefif(arg);
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);
}
@ -407,10 +428,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.
@ -456,7 +479,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,
@ -548,8 +571,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;
@ -568,9 +592,9 @@ dump(addr)
/* Print header */
if (!tflag && !cflag)
printf("%-*.*s %-*.*s %*.*s %-9.9s %1s %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", "S", "Flgs");
W_IF, W_IF, "Netif", "Expire", "S", "Flags");
again:;
mib[0] = CTL_NET;
@ -633,9 +657,8 @@ again:;
#endif
}
getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf,
sizeof(host_buf), NULL, 0,
(nflag ? NI_NUMERICHOST : 0));
if (cflag == 1) {
sizeof(host_buf), NULL, 0, (nflag ? NI_NUMERICHOST : 0));
if (cflag) {
#ifdef RTF_WASCLONED
if (rtm->rtm_flags & RTF_WASCLONED)
delete(host_buf);
@ -817,14 +840,15 @@ void
usage()
{
printf("usage: ndp hostname\n");
printf(" ndp -a[nt]\n");
printf(" ndp [-nt] -a\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 [-nt]- c\n");
printf(" ndp [-nt] -d hostname\n");
printf(" ndp [-nt] -f filename\n");
printf(" ndp -i interface [flags...]\n");
#ifdef SIOCSDEFIFACE_IN6
printf(" ndp -I [interface|delete]\n");
printf(" ndp -I interface\n");
printf(" ndp -I delete\n");
#endif
printf(" ndp -p\n");
printf(" ndp -r\n");
@ -901,13 +925,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];
@ -925,7 +949,7 @@ ifinfo(argc, argv)
}
#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];