summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2008-06-10 04:49:12 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2008-06-10 04:49:12 +0000
commit1ddab6ee3578889fbe7ba8f39e65ade5a7cd10b9 (patch)
tree65a240f4ec224f32500be32ff0507d4c48255446 /usr.sbin
parent753ee0d376f55c458981efc73ade5b952fb6347d (diff)
add the -O option to run an external script when the "other
configuration" flag is found in the RA message. it basically means "here is your IPv6 address, but run something like DHCPv6 to get more information". so the main purpose is to run a dhcpv6 client to get DNS etc. Merged from KAME ok rainer@
Diffstat (limited to 'usr.sbin')
-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 *, ...)