MFC: added an ioctl option in kernel so that ndp/rtadvd can change some NDP-related kernel variables based on their configurations (RFC2461 p.43 6.2.1 mandates this for IPv6 routers)

Revision  Changes    Path
  1.56      +1 -0      src/sys/netinet6/in6.c
  1.26      +1 -0      src/sys/netinet6/in6_var.h
  1.57      +28 -0     src/sys/netinet6/nd6.c
  1.17      +21 -8     src/usr.sbin/ndp/ndp.8
  1.17      +31 -2     src/usr.sbin/ndp/ndp.c
  1.25      +30 -0     src/usr.sbin/rtadvd/config.c
This commit is contained in:
suz 2005-11-05 10:50:09 +00:00
parent d3ffc1647d
commit 038918b0d7
6 changed files with 114 additions and 10 deletions

View File

@ -364,6 +364,7 @@ in6_control(so, cmd, data, ifp, td)
/* FALLTHROUGH */
case OSIOCGIFINFO_IN6:
case SIOCGIFINFO_IN6:
case SIOCSIFINFO_IN6:
case SIOCGDRLST_IN6:
case SIOCGPRLST_IN6:
case SIOCGNBRINFO_IN6:

View File

@ -404,6 +404,7 @@ struct in6_rrenumreq {
#define OSIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ondireq)
#endif
#define SIOCGIFINFO_IN6 _IOWR('i', 108, struct in6_ndireq)
#define SIOCSIFINFO_IN6 _IOWR('i', 109, struct in6_ndireq)
#define SIOCSNDFLUSH_IN6 _IOWR('i', 77, struct in6_ifreq)
#define SIOCGNBRINFO_IN6 _IOWR('i', 78, struct in6_nbrinfo)
#define SIOCSPFXFLUSH_IN6 _IOWR('i', 79, struct in6_ifreq)

View File

@ -1426,6 +1426,7 @@ nd6_ioctl(cmd, data, ifp)
break;
case OSIOCGIFINFO_IN6:
#define ND ndi->ndi
/* XXX: old ndp(8) assumes a positive value for linkmtu. */
bzero(&ndi->ndi, sizeof(ndi->ndi));
ndi->ndi.linkmtu = IN6_LINKMTU(ifp);
@ -1441,9 +1442,38 @@ nd6_ioctl(cmd, data, ifp)
ndi->ndi = *ND_IFINFO(ifp);
ndi->ndi.linkmtu = IN6_LINKMTU(ifp);
break;
case SIOCSIFINFO_IN6:
/*
* used to change host variables from userland.
* intented for a use on router to reflect RA configurations.
*/
/* 0 means 'unspecified' */
if (ND.linkmtu != 0) {
if (ND.linkmtu < IPV6_MMTU ||
ND.linkmtu > IN6_LINKMTU(ifp)) {
error = EINVAL;
break;
}
ND_IFINFO(ifp)->linkmtu = ND.linkmtu;
}
if (ND.basereachable != 0) {
int obasereachable = ND_IFINFO(ifp)->basereachable;
ND_IFINFO(ifp)->basereachable = ND.basereachable;
if (ND.basereachable != obasereachable)
ND_IFINFO(ifp)->reachable =
ND_COMPUTE_RTIME(ND.basereachable);
}
if (ND.retrans != 0)
ND_IFINFO(ifp)->retrans = ND.retrans;
if (ND.chlim != 0)
ND_IFINFO(ifp)->chlim = ND.chlim;
/* FALLTHROUGH */
case SIOCSIFINFO_FLAGS:
ND_IFINFO(ifp)->flags = ndi->ndi.flags;
break;
#undef ND
case SIOCSNDFLUSH_IN6: /* XXX: the ioctl name is confusing... */
/* flush default router list */
/*

View File

@ -63,7 +63,7 @@
.Op Fl nt
.Fl i
.Ar interface
.Op Ar flags ...
.Op Ar expressions ...
.Nm
.Op Fl nt
.Fl I Op Ar interface | Li delete
@ -153,19 +153,20 @@ The
will be used as the default.
.It Fl I Li delete
The current default interface will be deleted from the kernel.
.It Fl i Ar interface Op Ar flags ...
.It Fl i Ar interface Op Ar expressions ...
View ND information for the specified interface.
If additional arguments
.Ar flags
.Ar expressions
are given,
.Nm
sets or clears the specified flags for the interface.
Each flag should be separated by white spaces or tab characters.
Possible flags are as follows.
All of the flags can begin with the
sets or clears the flags or variables for the interface as specified in
the expression.
Each expression should be separated by white spaces or tab characters.
Possible expressions are as follows.
Some of the expressions can begin with the
special character
.Ql - ,
which means the flag should be cleared.
which means the flag specified in the expression should be cleared.
Note that you need
.Fl -
before
@ -209,6 +210,18 @@ a certain failure of Duplicate Address Detection.
While the flag can be set or cleared by hand with the
.Nm
command, it is not generally advisable to modify this flag manually.
.It Xo
.Ic basereachable=(number)
.Xc
Specify the BaseReachbleTimer on the interface in millisecond.
.It Xo
.Ic retrans=(number)
.Xc
Specify the RetransTimer on the interface in millisecond.
.It Xo
.Ic curhlim=(number)
.Xc
Specify the Cur Hop Limit on the interface.
.El
.It Fl n
Do not try to resolve numeric addresses to hostnames.

View File

@ -969,6 +969,27 @@ ifinfo(ifname, argc, argv)
newflags |= (f);\
}\
} while (0)
/*
* XXX: this macro is not 100% correct, in that it matches "nud" against
* "nudbogus". But we just let it go since this is minor.
*/
#define SETVALUE(f, v) \
do { \
char *valptr; \
unsigned long newval; \
v = 0; /* unspecified */ \
if (strncmp(cp, f, strlen(f)) == 0) { \
valptr = strchr(cp, '='); \
if (valptr == NULL) \
err(1, "syntax error in %s field", (f)); \
errno = 0; \
newval = strtoul(++valptr, NULL, 0); \
if (errno) \
err(1, "syntax error in %s's value", (f)); \
v = newval; \
} \
} while (0)
SETFLAG("disabled", ND6_IFF_IFDISABLED);
SETFLAG("nud", ND6_IFF_PERFORMNUD);
#ifdef ND6_IFF_ACCEPT_RTADV
@ -977,13 +998,17 @@ ifinfo(ifname, argc, argv)
#ifdef ND6_IFF_PREFER_SOURCE
SETFLAG("prefer_source", ND6_IFF_PREFER_SOURCE);
#endif
SETVALUE("basereachable", ND.basereachable);
SETVALUE("retrans", ND.retrans);
SETVALUE("curhlim", ND.chlim);
ND.flags = newflags;
if (ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd) < 0) {
err(1, "ioctl(SIOCSIFINFO_FLAGS)");
if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd) < 0) {
err(1, "ioctl(SIOCSIFINFO_IN6)");
/* NOTREACHED */
}
#undef SETFLAG
#undef SETVALUE
}
if (!ND.initialized) {
@ -991,6 +1016,10 @@ ifinfo(ifname, argc, argv)
/* NOTREACHED */
}
if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) {
err(1, "ioctl(SIOCGIFINFO_IN6)");
/* NOTREACHED */
}
printf("linkmtu=%d", ND.linkmtu);
printf(", maxmtu=%d", ND.maxmtu);
printf(", curhlim=%d", ND.chlim);

View File

@ -46,6 +46,7 @@
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet/icmp6.h>
#include <netinet6/nd6.h>
#include <arpa/inet.h>
@ -407,6 +408,35 @@ getconfig(intface)
exit(1);
}
#ifdef SIOCSIFINFO_IN6
{
struct in6_ndireq ndi;
int s;
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
syslog(LOG_ERR, "<%s> socket: %s", __func__,
strerror(errno));
exit(1);
}
memset(&ndi, 0, sizeof(ndi));
strncpy(ndi.ifname, intface, IFNAMSIZ);
if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&ndi) < 0) {
syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %s",
__func__, intface, strerror(errno));
}
/* reflect the RA info to the host variables in kernel */
ndi.ndi.chlim = tmp->hoplimit;
ndi.ndi.retrans = tmp->retranstimer;
ndi.ndi.basereachable = tmp->reachabletime;
if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&ndi) < 0) {
syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %s",
__func__, intface, strerror(errno));
}
close(s);
}
#endif
/* route information */
#ifdef ROUTEINFO
tmp->routes = 0;