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",
|
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");
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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 *, ...))
|
||||||
|
Loading…
Reference in New Issue
Block a user