Process the "O bit."

If the value of OtherConfigFlag changes from FALSE to TRUE, the
host should invoke the stateful autoconfiguration protocol,
requesting information.
[RFC 2462 Section 5.5.3]

Obtained from:	KAME
MFC after:	1 week
This commit is contained in:
Hajimu UMEMOTO 2003-08-08 16:42:37 +00:00
parent 1533bed05b
commit 86b032af6c
5 changed files with 183 additions and 2 deletions

View File

@ -76,6 +76,8 @@ dump_interface_status()
} }
fprintf(fp, " interface status: %s\n", fprintf(fp, " interface status: %s\n",
ifinfo->active > 0 ? "active" : "inactive"); ifinfo->active > 0 ? "active" : "inactive");
fprintf(fp, " other config: %s\n",
ifinfo->otherconfig ? "on" : "off");
fprintf(fp, " rtsold status: %s\n", ifstatstr[ifinfo->state]); fprintf(fp, " rtsold status: %s\n", ifstatstr[ifinfo->state]);
fprintf(fp, " carrier detection: %s\n", fprintf(fp, " carrier detection: %s\n",
ifinfo->mediareqok ? "available" : "unavailable"); ifinfo->mediareqok ? "available" : "unavailable");

View File

@ -35,7 +35,10 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/time.h> #include <sys/time.h>
#include <fcntl.h>
#include <sys/queue.h> #include <sys/queue.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <net/if.h> #include <net/if.h>
#include <net/route.h> #include <net/route.h>
@ -70,6 +73,9 @@ int rssock;
static struct sockaddr_in6 sin6_allrouters = {sizeof(sin6_allrouters), AF_INET6}; static struct sockaddr_in6 sin6_allrouters = {sizeof(sin6_allrouters), AF_INET6};
static void call_script __P((char *, char *));
static int safefile __P((const char *));
int int
sockopen() sockopen()
{ {
@ -233,6 +239,7 @@ rtsol_input(int s)
struct cmsghdr *cm; struct cmsghdr *cm;
struct in6_pktinfo *pi = NULL; struct in6_pktinfo *pi = NULL;
struct ifinfo *ifi = NULL; struct ifinfo *ifi = NULL;
struct nd_router_advert *nd_ra;
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
/* get message */ /* get message */
@ -330,6 +337,23 @@ rtsol_input(int s)
INET6_ADDRSTRLEN), INET6_ADDRSTRLEN),
ifi->ifname, ifi->state); ifi->ifname, ifi->state);
nd_ra = (struct nd_router_advert *)icp;
/*
* Process the "O bit."
* If the value of OtherConfigFlag changes from FALSE to TRUE, the
* host should invoke the stateful autoconfiguration protocol,
* requesting information.
* [RFC 2462 Section 5.5.3]
*/
if (((nd_ra->nd_ra_flags_reserved) & ND_RA_FLAG_OTHER) &&
!ifi->otherconfig) {
warnmsg(LOG_DEBUG, __func__,
"OtherConfigFlag on %s is turned on", ifi->ifname);
ifi->otherconfig = 1;
call_script(otherconf_script, ifi->ifname);
}
ifi->racnt++; ifi->racnt++;
switch(ifi->state) { switch(ifi->state) {
@ -343,3 +367,106 @@ rtsol_input(int s)
break; break;
} }
} }
static void
call_script(scriptpath, ifname)
char *scriptpath, *ifname;
{
pid_t pid, wpid;
if (scriptpath == NULL)
return;
/* launch the script */
pid = fork();
if (pid < 0) {
warnmsg(LOG_ERR, __func__,
"failed to fork: %s", strerror(errno));
return;
} else if (pid) {
int wstatus;
do {
wpid = wait(&wstatus);
} while (wpid != pid && wpid > 0);
if (wpid < 0)
warnmsg(LOG_ERR, __func__,
"wait: %s", strerror(errno));
else {
warnmsg(LOG_DEBUG, __func__,
"script \"%s\" terminated", scriptpath);
}
} else {
char *argv[3];
int fd;
argv[0] = scriptpath;
argv[1] = ifname;
argv[2] = NULL;
if (safefile(scriptpath)) {
warnmsg(LOG_ERR, __func__,
"script \"%s\" cannot be executed safely",
scriptpath);
exit(1);
}
if ((fd = open("/dev/null", O_RDWR)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > STDERR_FILENO)
close(fd);
}
execv(scriptpath, argv);
warnmsg(LOG_ERR, __func__, "child: exec failed: %s",
strerror(errno));
exit(0);
}
return;
}
static int
safefile(path)
const char *path;
{
struct stat s;
uid_t myuid;
/* no setuid */
if (getuid() != geteuid()) {
warnmsg(LOG_NOTICE, __func__,
"setuid'ed execution not allowed\n");
return (-1);
}
if (lstat(path, &s) != 0) {
warnmsg(LOG_NOTICE, __func__, "lstat failed: %s",
strerror(errno));
return (-1);
}
/* the file must be owned by the running uid */
myuid = getuid();
if (s.st_uid != myuid) {
warnmsg(LOG_NOTICE, __func__,
"%s has invalid owner uid\n", path);
return (-1);
}
switch (s.st_mode & S_IFMT) {
case S_IFREG:
break;
default:
warnmsg(LOG_NOTICE, __func__,
"%s is an invalid file type 0x%o\n",
path, (s.st_mode & S_IFMT));
return (-1);
}
return (0);
}

View File

@ -40,15 +40,19 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl dDfm1 .Op Fl dDfm1
.Op Fl O Ar script-name
.Ar interface ... .Ar interface ...
.Nm .Nm
.Op Fl dDfm1 .Op Fl dDfm1
.Op Fl O Ar script-name
.Fl a .Fl a
.Nm rtsol .Nm rtsol
.Op Fl dD .Op Fl dD
.Op Fl O Ar script-name
.Ar interface ... .Ar interface ...
.Nm rtsol .Nm rtsol
.Op Fl dD .Op Fl dD
.Op Fl O Ar script-name
.Fl a .Fl a
.\" .\"
.Sh DESCRIPTION .Sh DESCRIPTION
@ -128,6 +132,21 @@ When sending a Router Solicitation on an interface,
.Nm .Nm
includes a Source Link-layer address option if the interface includes a Source Link-layer address option if the interface
has a link-layer address. has a link-layer address.
.Lp
.Nm
manages a per-interface parameter to detect if a separate protocol is
needed for configuration parameters other than host's addresses.
At the invocation time, the flag is FALSE, and becomes TRUE when
the daemon receives a router advertisement with the OtherConfig flag
being set.
A script file can be specified to deal with the case
.Pq see below .
When
.Nm
start resending router solicitation messages by one of the conditions
events,
the daemon resets the parameter because the event may indicate a
change on the attached link.
.Pp .Pp
Upon receipt of signal Upon receipt of signal
.Dv SIGUSR1 , .Dv SIGUSR1 ,
@ -178,6 +197,20 @@ Transmit Router Solicitation packets until at least one valid Router
Advertisement packet has arrived on each Advertisement packet has arrived on each
.Ar interface , .Ar interface ,
then exit. then exit.
.It Fl O Ar script-name
Specifies a supplement script file to handle the Other Configuration
flag of the router advertisement.
When the flag changes from FALSE to TRUE,
.Nm
will invoke
.Ar script-name
with a single argument of the receiving interface name,
expecting the script will then start a protocol for the other
configuration.
.Ar script-name
must be the absolute path from root to the script file, be a regular
file, and be created by the same owner who runs
.Nm .
.El .El
.Sh DIAGNOSTICS .Sh DIAGNOSTICS
.Ex -std rtsold rtsol .Ex -std rtsold rtsol

View File

@ -57,6 +57,7 @@ struct ifinfo *iflist;
struct timeval tm_max = {0x7fffffff, 0x7fffffff}; struct timeval tm_max = {0x7fffffff, 0x7fffffff};
int aflag = 0; int aflag = 0;
int dflag = 0; int dflag = 0;
char *otherconf_script;
static int log_upto = 999; static int log_upto = 999;
static int fflag = 0; static int fflag = 0;
@ -126,9 +127,9 @@ main(argc, argv)
if (argv0 && argv0[strlen(argv0) - 1] != 'd') { if (argv0 && argv0[strlen(argv0) - 1] != 'd') {
fflag = 1; fflag = 1;
once = 1; once = 1;
opts = "adD"; opts = "adDO:";
} else } else
opts = "adDfm1"; opts = "adDfm1O:";
while ((ch = getopt(argc, argv, opts)) != -1) { while ((ch = getopt(argc, argv, opts)) != -1) {
switch (ch) { switch (ch) {
@ -150,6 +151,9 @@ main(argc, argv)
case '1': case '1':
once = 1; once = 1;
break; break;
case 'O':
otherconf_script = optarg;
break;
default: default:
usage(argv0); usage(argv0);
/*NOTREACHED*/ /*NOTREACHED*/
@ -196,6 +200,11 @@ main(argc, argv)
setlogmask(LOG_UPTO(log_upto)); setlogmask(LOG_UPTO(log_upto));
} }
if (otherconf_script && *otherconf_script != '/') {
errx(1, "configuration script (%s) must be an absolute path",
otherconf_script);
}
#ifndef HAVE_ARC4RANDOM #ifndef HAVE_ARC4RANDOM
/* random value initilization */ /* random value initilization */
srandom((u_long)time(NULL)); srandom((u_long)time(NULL));
@ -524,6 +533,13 @@ rtsol_check_timer()
ifinfo->state = IFS_PROBE; ifinfo->state = IFS_PROBE;
} }
/*
* If we need a probe, clear the previous
* status wrt the "other" configuration.
*/
if (probe)
ifinfo->otherconfig = 0;
if (probe && mobile_node) if (probe && mobile_node)
defrouter_probe(ifinfo->sdl->sdl_index); defrouter_probe(ifinfo->sdl->sdl_index);
break; break;

View File

@ -40,6 +40,8 @@ struct ifinfo {
int probeinterval; /* interval of probe timer(if necessary) */ int probeinterval; /* interval of probe timer(if necessary) */
int probetimer; /* rest of probe timer */ int probetimer; /* rest of probe timer */
int mediareqok; /* wheter the IF supports SIOCGIFMEDIA */ int mediareqok; /* wheter the IF supports SIOCGIFMEDIA */
int otherconfig; /* need a separate protocol for the "other"
* configuration */
int state; int state;
int probes; int probes;
int dadcount; int dadcount;
@ -63,6 +65,7 @@ struct ifinfo {
/* rtsold.c */ /* rtsold.c */
extern struct timeval tm_max; extern struct timeval tm_max;
extern int dflag; extern int dflag;
extern char *otherconf_script;
struct ifinfo *find_ifinfo __P((int ifindex)); struct ifinfo *find_ifinfo __P((int ifindex));
void rtsol_timer_update __P((struct ifinfo *ifinfo)); void rtsol_timer_update __P((struct ifinfo *ifinfo));
extern void warnmsg __P((int, const char *, const char *, ...)) extern void warnmsg __P((int, const char *, const char *, ...))