diff options
Diffstat (limited to 'usr.sbin/rtsold')
-rw-r--r-- | usr.sbin/rtsold/dump.c | 6 | ||||
-rw-r--r-- | usr.sbin/rtsold/rtsol.c | 135 | ||||
-rw-r--r-- | usr.sbin/rtsold/rtsold.8 | 33 | ||||
-rw-r--r-- | usr.sbin/rtsold/rtsold.c | 39 | ||||
-rw-r--r-- | usr.sbin/rtsold/rtsold.h | 5 |
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 *, ...) |