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)

Obtained from: KAME
Reviewd by: ume, gnn
MFC after: 2 weeks
This commit is contained in:
SUZUKI Shinsuke 2005-10-19 15:05:42 +00:00
parent 273ae68f43
commit b9204379a1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=151468
6 changed files with 112 additions and 10 deletions

View File

@ -361,6 +361,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

@ -1441,6 +1441,34 @@ nd6_ioctl(cmd, data, ifp)
ND = *ND_IFINFO(ifp);
ND.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 = ND.flags;
break;

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
@ -196,6 +197,18 @@ For more details about the entire algorithm of source address
selection, see the
.Pa IMPLEMENTATION
file supplied with the KAME kit.
.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

@ -965,6 +965,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("nud", ND6_IFF_PERFORMNUD);
#ifdef ND6_IFF_ACCEPT_RTADV
SETFLAG("accept_rtadv", ND6_IFF_ACCEPT_RTADV);
@ -972,13 +993,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) {
@ -986,6 +1011,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;