diff --git a/usr.sbin/rtsold/dump.c b/usr.sbin/rtsold/dump.c index daaefc6bc88d..65b4f979bd43 100644 --- a/usr.sbin/rtsold/dump.c +++ b/usr.sbin/rtsold/dump.c @@ -84,6 +84,8 @@ rtsold_dump(FILE *fp) } fprintf(fp, " interface status: %s\n", ifi->active > 0 ? "active" : "inactive"); + fprintf(fp, " managed config: %s\n", + ifi->managedconfig ? "on" : "off"); fprintf(fp, " other config: %s\n", ifi->otherconfig ? "on" : "off"); fprintf(fp, " rtsold status: %s\n", ifstatstr[ifi->state]); diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c index 06f860e3984e..cbdc12f84c03 100644 --- a/usr.sbin/rtsold/rtsol.c +++ b/usr.sbin/rtsold/rtsol.c @@ -79,6 +79,7 @@ static int ra_opt_rdnss_dispatch(struct ifinfo *, struct rainfo *, struct script_msg_head_t *, struct script_msg_head_t *); static char *make_rsid(const char *, const char *, struct rainfo *); +#define _ARGS_MANAGED managedconf_script, ifi->ifname #define _ARGS_OTHER otherconf_script, ifi->ifname #define _ARGS_RESADD resolvconf_script, "-a", rsid #define _ARGS_RESDEL resolvconf_script, "-d", rsid @@ -290,19 +291,37 @@ rtsol_input(int sock) nd_ra = (struct nd_router_advert *)icp; + /* + * Process the "M bit." + * If the value of ManagedConfigFlag changes from FALSE to TRUE, the + * host should invoke the stateful autoconfiguration protocol, + * requesting information. + * [RFC 4861 Section 4.2] + * XXX ??? [draft-ietf-v6ops-dhcpv6-slaac-problem-07] + */ + if (((nd_ra->nd_ra_flags_reserved) & ND_RA_FLAG_MANAGED) && + !ifi->managedconfig) { + warnmsg(LOG_DEBUG, __func__, + "ManagedConfigFlag on %s is turned on", ifi->ifname); + ifi->managedconfig = 1; + CALL_SCRIPT(MANAGED, NULL); + } + /* * 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] + * requesting information unless the "M bit" was set as well in + * which case the "O bit" is redundant. + * [RFC 4861 Section 4.2] */ 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(OTHER, NULL); + if (!ifi->managedconfig) + CALL_SCRIPT(OTHER, NULL); } clock_gettime(CLOCK_MONOTONIC_FAST, &now); newent_rai = 0; diff --git a/usr.sbin/rtsold/rtsold.8 b/usr.sbin/rtsold/rtsold.8 index 05133d8720b1..e30a07f3a3fe 100644 --- a/usr.sbin/rtsold/rtsold.8 +++ b/usr.sbin/rtsold/rtsold.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 14, 2011 +.Dd August 19, 2020 .Dt RTSOLD 8 .Os .\" @@ -40,23 +40,27 @@ .Sh SYNOPSIS .Nm .Op Fl dDfFmu1 +.Op Fl M Ar script-name .Op Fl O Ar script-name .Op Fl p Ar pidfile .Op Fl R Ar script-name .Ar interface ... .Nm .Op Fl dDfFmu1 +.Op Fl M Ar script-name .Op Fl O Ar script-name .Op Fl p Ar pidfile .Op Fl R Ar script-name .Fl a .Nm rtsol .Op Fl dDu +.Op Fl M Ar script-name .Op Fl O Ar script-name .Op Fl R Ar script-name .Ar interface ... .Nm rtsol .Op Fl dDu +.Op Fl M Ar script-name .Op Fl O Ar script-name .Op Fl R Ar script-name .Fl a @@ -208,6 +212,20 @@ Transmit Router Solicitation packets until at least one valid Router Advertisement packet has arrived on each .Ar interface , then exit. +.It Fl M Ar script-name +Specifies a supplement script file to handle the Managed 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 managed +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 . .It Fl O Ar script-name Specifies a supplement script file to handle the Other Configuration flag of the router advertisement. @@ -218,6 +236,8 @@ will invoke with a single argument of the receiving interface name, expecting the script will then start a protocol for the other configuration. +The script will not be run if the Managed Configuration flag in the +router advertisement is also TRUE. .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 diff --git a/usr.sbin/rtsold/rtsold.c b/usr.sbin/rtsold/rtsold.c index 2c1199a29bf3..1d5605463314 100644 --- a/usr.sbin/rtsold/rtsold.c +++ b/usr.sbin/rtsold/rtsold.c @@ -80,6 +80,7 @@ int aflag = 0; int dflag = 0; int uflag = 0; +const char *managedconf_script; const char *otherconf_script; const char *resolvconf_script = "/sbin/resolvconf"; @@ -124,11 +125,11 @@ main(int argc, char **argv) progname = basename(argv[0]); if (strcmp(progname, "rtsold") == 0) { - opts = "adDfFm1O:p:R:u"; + opts = "adDfFm1M:O:p:R:u"; once = 0; pidfilepath = NULL; } else { - opts = "adDFO:R:u"; + opts = "adDFM:O:R:u"; fflag = 1; once = 1; } @@ -156,6 +157,9 @@ main(int argc, char **argv) case '1': once = 1; break; + case 'M': + managedconf_script = optarg; + break; case 'O': otherconf_script = optarg; break; @@ -190,6 +194,9 @@ main(int argc, char **argv) else log_upto = LOG_NOTICE; + if (managedconf_script != NULL && *managedconf_script != '/') + errx(1, "configuration script (%s) must be an absolute path", + managedconf_script); if (otherconf_script != NULL && *otherconf_script != '/') errx(1, "configuration script (%s) must be an absolute path", otherconf_script); @@ -324,9 +331,11 @@ static int init_capabilities(void) { #ifdef WITH_CASPER - const char *const scripts[2] = { resolvconf_script, otherconf_script }; + const char *const scripts[] = + { resolvconf_script, managedconf_script, otherconf_script }; cap_channel_t *capcasper; nvlist_t *limits; + int count; capcasper = cap_init(); if (capcasper == NULL) @@ -339,9 +348,12 @@ init_capabilities(void) capscript = cap_service_open(capcasper, "rtsold.script"); if (capscript == NULL) return (-1); + count = 0; + for (size_t i = 0; i < nitems(scripts); i++) + if (scripts[i] != NULL) + count++; limits = nvlist_create(0); - nvlist_add_string_array(limits, "scripts", scripts, - otherconf_script != NULL ? 2 : 1); + nvlist_add_string_array(limits, "scripts", scripts, count); if (cap_limit_set(capscript, limits) != 0) return (-1); @@ -597,10 +609,12 @@ rtsol_check_timer(void) /* * If we need a probe, clear the previous - * status wrt the "other" configuration. + * status wrt the "managed/other" configuration. */ - if (probe) + if (probe) { + ifi->managedconfig = 0; ifi->otherconfig = 0; + } if (probe && mobile_node) { error = cap_probe_defrouters(capsendmsg, ifi); diff --git a/usr.sbin/rtsold/rtsold.h b/usr.sbin/rtsold/rtsold.h index ab8d5ae5d971..1342ad87703b 100644 --- a/usr.sbin/rtsold/rtsold.h +++ b/usr.sbin/rtsold/rtsold.h @@ -71,6 +71,8 @@ struct ifinfo { int probeinterval; /* interval of probe timer (if necessary) */ int probetimer; /* rest of probe timer */ int mediareqok; /* whether the IF supports SIOCGIFMEDIA */ + int managedconfig; /* need a separate protocol for the "managed" + * configuration */ int otherconfig; /* need a separate protocol for the "other" * configuration */ int state; @@ -156,6 +158,7 @@ extern int dflag; extern int aflag; extern int Fflag; extern int uflag; +extern const char *managedconf_script; extern const char *otherconf_script; extern const char *resolvconf_script; extern struct cap_channel *capllflags, *capscript, *capsendmsg, *capsyslog;