From 60e7f66931a5cf268d356fd11532245e057267ac Mon Sep 17 00:00:00 2001 From: "Bjoern A. Zeeb" Date: Tue, 25 Aug 2020 16:09:23 +0000 Subject: [PATCH] rtsol(d): add script for "M bit" While we do support the "O bit" running a script (usually to start a dhcpv6 client) we have no options for setups which set the "M bit" for, e.g., static address assignment as in EC2. Duplicate most of the "O bit" logic to also start a script for the "M bit" with the one difference: if the "M bit" is set we will not start the script for the "O bit" as well (per RFC 4861, Section 4.2). Reviewed by: hrs, markj MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D26099 --- usr.sbin/rtsold/dump.c | 2 ++ usr.sbin/rtsold/rtsol.c | 25 ++++++++++++++++++++++--- usr.sbin/rtsold/rtsold.8 | 22 +++++++++++++++++++++- usr.sbin/rtsold/rtsold.c | 28 +++++++++++++++++++++------- usr.sbin/rtsold/rtsold.h | 3 +++ 5 files changed, 69 insertions(+), 11 deletions(-) diff --git a/usr.sbin/rtsold/dump.c b/usr.sbin/rtsold/dump.c index daaefc6bc88..65b4f979bd4 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 06f860e3984..cbdc12f84c0 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 05133d8720b..e30a07f3a3f 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 2c1199a29bf..1d560546331 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 ab8d5ae5d97..1342ad87703 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; -- 2.45.0