summaryrefslogtreecommitdiff
path: root/usr.sbin/rtsold
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/rtsold')
-rw-r--r--usr.sbin/rtsold/dump.c6
-rw-r--r--usr.sbin/rtsold/rtsol.c135
-rw-r--r--usr.sbin/rtsold/rtsold.833
-rw-r--r--usr.sbin/rtsold/rtsold.c39
-rw-r--r--usr.sbin/rtsold/rtsold.h5
5 files changed, 206 insertions, 12 deletions
diff --git a/usr.sbin/rtsold/dump.c b/usr.sbin/rtsold/dump.c
index f8ac5e31474..2c70fb218d9 100644
--- a/usr.sbin/rtsold/dump.c
+++ b/usr.sbin/rtsold/dump.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dump.c,v 1.11 2003/10/05 15:29:28 deraadt Exp $ */
+/* $OpenBSD: dump.c,v 1.12 2008/06/10 04:49:11 reyk Exp $ */
/* $KAME: dump.c,v 1.10 2002/05/31 10:10:03 itojun Exp $ */
/*
@@ -74,6 +74,10 @@ dump_interface_status(void)
}
fprintf(fp, " interface status: %s\n",
ifinfo->active > 0 ? "active" : "inactive");
+#ifndef SMALL
+ fprintf(fp, " other config: %s\n",
+ ifinfo->otherconfig ? "on" : "off");
+#endif
fprintf(fp, " rtsold status: %s\n", ifstatstr[ifinfo->state]);
fprintf(fp, " carrier detection: %s\n",
ifinfo->mediareqok ? "available" : "unavailable");
diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c
index 1cab663b690..3e31bbfc13e 100644
--- a/usr.sbin/rtsold/rtsol.c
+++ b/usr.sbin/rtsold/rtsol.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsol.c,v 1.14 2008/03/24 16:11:05 deraadt Exp $ */
+/* $OpenBSD: rtsol.c,v 1.15 2008/06/10 04:49:11 reyk Exp $ */
/* $KAME: rtsol.c,v 1.15 2002/05/31 10:10:03 itojun Exp $ */
/*
@@ -35,6 +35,7 @@
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/queue.h>
+#include <sys/stat.h>
#include <net/if.h>
#include <net/route.h>
@@ -55,6 +56,8 @@
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
+#include <fcntl.h>
+
#include "rtsold.h"
#define ALLROUTER "ff02::2"
@@ -69,6 +72,11 @@ int rssock;
static struct sockaddr_in6 sin6_allrouters = {sizeof(sin6_allrouters), AF_INET6};
+#ifndef SMALL
+void call_script(char *, char *);
+int safefile(const char *);
+#endif
+
int
sockopen(void)
{
@@ -214,6 +222,9 @@ rtsol_input(int s)
struct icmp6_hdr *icp;
struct cmsghdr *cm;
ssize_t i;
+#ifndef SMALL
+ struct nd_router_advert *nd_ra;
+#endif
/* get message */
if ((i = recvmsg(s, &rcvmhdr, 0)) < 0) {
@@ -308,6 +319,25 @@ rtsol_input(int s)
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, INET6_ADDRSTRLEN),
ifi->ifname, ifi->state);
+#ifndef SMALL
+ 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);
+ }
+#endif
+
ifi->racnt++;
switch (ifi->state) {
@@ -321,3 +351,106 @@ rtsol_input(int s)
break;
}
}
+
+#ifndef SMALL
+void
+call_script(char *scriptpath, char *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) != 0) {
+ 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(1);
+ }
+
+ return;
+}
+
+int
+safefile(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);
+}
+#endif
diff --git a/usr.sbin/rtsold/rtsold.8 b/usr.sbin/rtsold/rtsold.8
index d474db78618..d2a79b0d7fe 100644
--- a/usr.sbin/rtsold/rtsold.8
+++ b/usr.sbin/rtsold/rtsold.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: rtsold.8,v 1.24 2007/05/31 19:20:29 jmc Exp $
+.\" $OpenBSD: rtsold.8,v 1.25 2008/06/10 04:49:11 reyk Exp $
.\" $KAME: rtsold.8,v 1.17 2001/07/09 22:30:37 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd $Mdocdate: May 31 2007 $
+.Dd $Mdocdate: June 10 2008 $
.Dt RTSOLD 8
.Os
.\"
@@ -39,6 +39,7 @@
.Sh SYNOPSIS
.Nm rtsold
.Op Fl 1DdFfm
+.Op Fl O Ar script-name
.Ar interface ...
.Nm rtsold
.Op Fl 1DdFfm
@@ -46,6 +47,7 @@
.Pp
.Nm rtsol
.Op Fl DdF
+.Op Fl O Ar script-name
.Ar interface ...
.Nm rtsol
.Op Fl DdF
@@ -138,6 +140,20 @@ When sending a Router Solicitation on an interface,
includes a Source Link-layer address option if the interface
has a link-layer address.
.Pp
+.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 Other Configuration
+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 ,
.Nm
@@ -199,6 +215,19 @@ Moreover, if the option is specified,
periodically sends Router Solicitation on an interface that does not support
.Dv SIOCGIFMEDIA
ioctl.
+.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
.Pp
.Ex -std rtsold
diff --git a/usr.sbin/rtsold/rtsold.c b/usr.sbin/rtsold/rtsold.c
index a711cd27741..6b282788929 100644
--- a/usr.sbin/rtsold/rtsold.c
+++ b/usr.sbin/rtsold/rtsold.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsold.c,v 1.41 2008/04/13 00:22:17 djm Exp $ */
+/* $OpenBSD: rtsold.c,v 1.42 2008/06/10 04:49:11 reyk Exp $ */
/* $KAME: rtsold.c,v 1.75 2004/01/03 00:00:07 itojun Exp $ */
/*
@@ -65,6 +65,8 @@ static int Fflag = 0; /* force setting sysctl parameters */
int aflag = 0;
int dflag = 0;
+char *otherconf_script;
+
/* protocol constants */
#define MAX_RTR_SOLICITATION_DELAY 1 /* second */
#define RTR_SOLICITATION_INTERVAL 4 /* seconds */
@@ -117,9 +119,9 @@ main(int argc, char *argv[])
if (argv0 && argv0[0] != '\0' && argv0[strlen(argv0) - 1] != 'd') {
fflag = 1;
once = 1;
- opts = "adDF";
+ opts = "adDFO:";
} else
- opts = "adDfFm1";
+ opts = "adDfFm1O:";
while ((ch = getopt(argc, argv, opts)) != -1) {
switch (ch) {
@@ -144,6 +146,11 @@ main(int argc, char *argv[])
case '1':
once = 1;
break;
+#ifndef SMALL
+ case 'O':
+ otherconf_script = optarg;
+ break;
+#endif
default:
usage(argv0);
/*NOTREACHED*/
@@ -173,6 +180,13 @@ main(int argc, char *argv[])
setlogmask(LOG_UPTO(log_upto));
}
+#ifndef SMALL
+ if (otherconf_script && *otherconf_script != '/') {
+ errx(1, "configuration script (%s) must be an absolute path",
+ otherconf_script);
+ }
+#endif
+
if (Fflag) {
setinet6sysctl(IPV6CTL_ACCEPT_RTADV, 1);
setinet6sysctl(IPV6CTL_FORWARDING, 0);
@@ -507,6 +521,15 @@ rtsol_check_timer(void)
ifinfo->state = IFS_PROBE;
}
+#ifndef SMALL
+ /*
+ * If we need a probe, clear the previous
+ * status wrt the "other" configuration.
+ */
+ if (probe)
+ ifinfo->otherconfig = 0;
+#endif
+
if (probe && mobile_node)
defrouter_probe(ifinfo);
break;
@@ -637,11 +660,13 @@ static void
usage(char *progname)
{
if (progname && progname[0] != '\0' && progname[strlen(progname) - 1] != 'd') {
- fprintf(stderr, "usage: rtsol [-DdF] interface ...\n");
- fprintf(stderr, "usage: rtsol [-DdF] -a\n");
+ fprintf(stderr, "usage: rtsol [-DdF] [-O script] "
+ "interface ...\n");
+ fprintf(stderr, "usage: rtsol [-DdF] [-O script] -a\n");
} else {
- fprintf(stderr, "usage: rtsold [-1DdFfm] interface ...\n");
- fprintf(stderr, "usage: rtsold [-1DdFfm] -a\n");
+ fprintf(stderr, "usage: rtsold [-1DdFfm] [-O script] "
+ "interface ...\n");
+ fprintf(stderr, "usage: rtsold [-1DdFfm] [-O script] -a\n");
}
exit(1);
}
diff --git a/usr.sbin/rtsold/rtsold.h b/usr.sbin/rtsold/rtsold.h
index 95c883b9f8b..653098ecd00 100644
--- a/usr.sbin/rtsold/rtsold.h
+++ b/usr.sbin/rtsold/rtsold.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsold.h,v 1.11 2004/01/05 20:32:50 itojun Exp $ */
+/* $OpenBSD: rtsold.h,v 1.12 2008/06/10 04:49:11 reyk Exp $ */
/* $KAME: rtsold.h,v 1.14 2002/05/31 10:10:03 itojun Exp $ */
/*
@@ -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(int ifindex);
void rtsol_timer_update(struct ifinfo *);
extern void warnmsg(int, const char *, const char *, ...)