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:
parent
1533bed05b
commit
86b032af6c
@ -76,6 +76,8 @@ dump_interface_status()
|
||||
}
|
||||
fprintf(fp, " interface status: %s\n",
|
||||
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, " carrier detection: %s\n",
|
||||
ifinfo->mediareqok ? "available" : "unavailable");
|
||||
|
@ -35,7 +35,10 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
@ -70,6 +73,9 @@ int rssock;
|
||||
|
||||
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
|
||||
sockopen()
|
||||
{
|
||||
@ -233,6 +239,7 @@ rtsol_input(int s)
|
||||
struct cmsghdr *cm;
|
||||
struct in6_pktinfo *pi = NULL;
|
||||
struct ifinfo *ifi = NULL;
|
||||
struct nd_router_advert *nd_ra;
|
||||
u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
|
||||
|
||||
/* get message */
|
||||
@ -330,6 +337,23 @@ rtsol_input(int s)
|
||||
INET6_ADDRSTRLEN),
|
||||
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++;
|
||||
|
||||
switch(ifi->state) {
|
||||
@ -343,3 +367,106 @@ rtsol_input(int s)
|
||||
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);
|
||||
}
|
||||
|
@ -40,15 +40,19 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl dDfm1
|
||||
.Op Fl O Ar script-name
|
||||
.Ar interface ...
|
||||
.Nm
|
||||
.Op Fl dDfm1
|
||||
.Op Fl O Ar script-name
|
||||
.Fl a
|
||||
.Nm rtsol
|
||||
.Op Fl dD
|
||||
.Op Fl O Ar script-name
|
||||
.Ar interface ...
|
||||
.Nm rtsol
|
||||
.Op Fl dD
|
||||
.Op Fl O Ar script-name
|
||||
.Fl a
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
@ -128,6 +132,21 @@ When sending a Router Solicitation on an interface,
|
||||
.Nm
|
||||
includes a Source Link-layer address option if the interface
|
||||
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
|
||||
Upon receipt of signal
|
||||
.Dv SIGUSR1 ,
|
||||
@ -178,6 +197,20 @@ Transmit Router Solicitation packets until at least one valid Router
|
||||
Advertisement packet has arrived on each
|
||||
.Ar interface ,
|
||||
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
|
||||
.Sh DIAGNOSTICS
|
||||
.Ex -std rtsold rtsol
|
||||
|
@ -57,6 +57,7 @@ struct ifinfo *iflist;
|
||||
struct timeval tm_max = {0x7fffffff, 0x7fffffff};
|
||||
int aflag = 0;
|
||||
int dflag = 0;
|
||||
char *otherconf_script;
|
||||
static int log_upto = 999;
|
||||
static int fflag = 0;
|
||||
|
||||
@ -126,9 +127,9 @@ main(argc, argv)
|
||||
if (argv0 && argv0[strlen(argv0) - 1] != 'd') {
|
||||
fflag = 1;
|
||||
once = 1;
|
||||
opts = "adD";
|
||||
opts = "adDO:";
|
||||
} else
|
||||
opts = "adDfm1";
|
||||
opts = "adDfm1O:";
|
||||
|
||||
while ((ch = getopt(argc, argv, opts)) != -1) {
|
||||
switch (ch) {
|
||||
@ -150,6 +151,9 @@ main(argc, argv)
|
||||
case '1':
|
||||
once = 1;
|
||||
break;
|
||||
case 'O':
|
||||
otherconf_script = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(argv0);
|
||||
/*NOTREACHED*/
|
||||
@ -196,6 +200,11 @@ main(argc, argv)
|
||||
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
|
||||
/* random value initilization */
|
||||
srandom((u_long)time(NULL));
|
||||
@ -524,6 +533,13 @@ rtsol_check_timer()
|
||||
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)
|
||||
defrouter_probe(ifinfo->sdl->sdl_index);
|
||||
break;
|
||||
|
@ -40,6 +40,8 @@ struct ifinfo {
|
||||
int probeinterval; /* interval of probe timer(if necessary) */
|
||||
int probetimer; /* rest of probe timer */
|
||||
int mediareqok; /* wheter the IF supports SIOCGIFMEDIA */
|
||||
int otherconfig; /* need a separate protocol for the "other"
|
||||
* configuration */
|
||||
int state;
|
||||
int probes;
|
||||
int dadcount;
|
||||
@ -63,6 +65,7 @@ struct ifinfo {
|
||||
/* rtsold.c */
|
||||
extern struct timeval tm_max;
|
||||
extern int dflag;
|
||||
extern char *otherconf_script;
|
||||
struct ifinfo *find_ifinfo __P((int ifindex));
|
||||
void rtsol_timer_update __P((struct ifinfo *ifinfo));
|
||||
extern void warnmsg __P((int, const char *, const char *, ...))
|
||||
|
Loading…
Reference in New Issue
Block a user