git: 476babaea7a3 - main - rtsol: introduce an 'always' script

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 02 May 2023 16:07:50 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=476babaea7a32ef215e6a3791eed267252f93d79

commit 476babaea7a32ef215e6a3791eed267252f93d79
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2023-05-02 08:45:01 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2023-05-02 16:07:36 +0000

    rtsol: introduce an 'always' script
    
    In addition to the 'M' and 'O' scripts (for when 'Managed' and 'Other'
    flags are set) also introduce an 'always' script that is called for any
    router advertisement (so even if M and O are not set).
    
    This is primarly useful for systems like pfSense that wish to be
    informed of routers for further system configuration.
    
    See also https://redmine.pfsense.org/issues/14072
    
    Reviewed by:    melifaro
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D39931
---
 usr.sbin/rtsold/rtsol.c  | 12 ++++++++++++
 usr.sbin/rtsold/rtsold.8 | 18 +++++++++++++++++-
 usr.sbin/rtsold/rtsold.c | 19 ++++++++++++++++---
 usr.sbin/rtsold/rtsold.h |  2 ++
 4 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c
index 646dd092cb0c..e15b9f202468 100644
--- a/usr.sbin/rtsold/rtsol.c
+++ b/usr.sbin/rtsold/rtsol.c
@@ -81,6 +81,7 @@ static char *make_rsid(const char *, const char *, struct rainfo *);
 
 #define	_ARGS_MANAGED	managedconf_script, ifi->ifname, rasender
 #define	_ARGS_OTHER	otherconf_script, ifi->ifname, rasender
+#define	_ARGS_ALWAYS	alwaysconf_script, ifi->ifname, rasender
 #define	_ARGS_RESADD	resolvconf_script, "-a", rsid
 #define	_ARGS_RESDEL	resolvconf_script, "-d", rsid
 
@@ -327,6 +328,17 @@ rtsol_input(int sock)
 		if (!ifi->managedconfig)
 			CALL_SCRIPT(OTHER, NULL);
 	}
+
+	/*
+	 * "Always" script.
+	 */
+	if (!ifi->alwaysconfig) {
+		const char *rasender = inet_ntop(AF_INET6, &from.sin6_addr,
+		    ntopbuf, sizeof(ntopbuf));
+		ifi->alwaysconfig = 1;
+		CALL_SCRIPT(ALWAYS, NULL);
+	}
+
 	clock_gettime(CLOCK_MONOTONIC_FAST, &now);
 	newent_rai = 0;
 	rai = find_rainfo(ifi, &from);
diff --git a/usr.sbin/rtsold/rtsold.8 b/usr.sbin/rtsold/rtsold.8
index 992d3a0f784d..cc5505a7de5c 100644
--- a/usr.sbin/rtsold/rtsold.8
+++ b/usr.sbin/rtsold/rtsold.8
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 15, 2021
+.Dd May 2, 2023
 .Dt RTSOLD 8
 .Os
 .\"
@@ -42,6 +42,7 @@
 .Op Fl dDfFimu1
 .Op Fl M Ar script-name
 .Op Fl O Ar script-name
+.Op Fl A Ar script-name
 .Op Fl p Ar pidfile
 .Op Fl R Ar script-name
 .Ar interface ...
@@ -49,6 +50,7 @@
 .Op Fl dDfFimu1
 .Op Fl M Ar script-name
 .Op Fl O Ar script-name
+.Op Fl A Ar script-name
 .Op Fl p Ar pidfile
 .Op Fl R Ar script-name
 .Fl a
@@ -56,12 +58,14 @@
 .Op Fl dDiu
 .Op Fl M Ar script-name
 .Op Fl O Ar script-name
+.Op Fl A Ar script-name
 .Op Fl R Ar script-name
 .Ar interface ...
 .Nm rtsol
 .Op Fl dDiu
 .Op Fl M Ar script-name
 .Op Fl O Ar script-name
+.Op Fl A Ar script-name
 .Op Fl R Ar script-name
 .Fl a
 .\"
@@ -250,6 +254,18 @@ router advertisement is also TRUE.
 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 A Ar script-name
+Specifies a supplement script file to always be called for the router
+advertisement.
+.Nm
+will invoke
+.Ar script-name
+with a first argument of the receiving interface name
+and a second argument of the sending router address.
+.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 p Ar pidfile
 Writes the process ID of
 .Nm
diff --git a/usr.sbin/rtsold/rtsold.c b/usr.sbin/rtsold/rtsold.c
index f1ba3b07c879..3da2a225307b 100644
--- a/usr.sbin/rtsold/rtsold.c
+++ b/usr.sbin/rtsold/rtsold.c
@@ -82,6 +82,7 @@ int uflag = 0;
 
 const char *managedconf_script;
 const char *otherconf_script;
+const char *alwaysconf_script;
 const char *resolvconf_script = "/sbin/resolvconf";
 
 cap_channel_t *capllflags, *capscript, *capsendmsg, *capsyslog;
@@ -126,11 +127,11 @@ main(int argc, char **argv)
 
 	progname = basename(argv[0]);
 	if (strcmp(progname, "rtsold") == 0) {
-		opts = "adDfFim1M:O:p:R:u";
+		opts = "adDfFim1M:O:A:p:R:u";
 		once = 0;
 		pidfilepath = NULL;
 	} else {
-		opts = "adDFiM:O:R:u";
+		opts = "adDFiM:O:A:R:u";
 		fflag = 1;
 		once = 1;
 	}
@@ -167,6 +168,9 @@ main(int argc, char **argv)
 		case 'O':
 			otherconf_script = optarg;
 			break;
+		case 'A':
+			alwaysconf_script = optarg;
+			break;
 		case 'p':
 			pidfilepath = optarg;
 			break;
@@ -204,6 +208,9 @@ main(int argc, char **argv)
 	if (otherconf_script != NULL && *otherconf_script != '/')
 		errx(1, "configuration script (%s) must be an absolute path",
 		    otherconf_script);
+	if (alwaysconf_script != NULL && *alwaysconf_script != '/')
+		errx(1, "configuration script (%s) must be an absolute path",
+		    alwaysconf_script);
 	if (*resolvconf_script != '/')
 		errx(1, "configuration script (%s) must be an absolute path",
 		    resolvconf_script);
@@ -336,7 +343,8 @@ init_capabilities(void)
 {
 #ifdef WITH_CASPER
 	const char *const scripts[] =
-	    { resolvconf_script, managedconf_script, otherconf_script };
+	    { resolvconf_script, managedconf_script, otherconf_script,
+	    alwaysconf_script };
 	cap_channel_t *capcasper;
 	nvlist_t *limits;
 
@@ -616,6 +624,7 @@ rtsol_check_timer(void)
 				if (probe) {
 					ifi->managedconfig = 0;
 					ifi->otherconfig = 0;
+					ifi->alwaysconfig = 0;
 				}
 				if (probe && mobile_node) {
 					error = cap_probe_defrouters(capsendmsg,
@@ -786,13 +795,17 @@ usage(const char *progname)
 
 	if (strcmp(progname, "rtsold") == 0) {
 		fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] "
+		    "[-M script-name ] [-A script-name ] "
 		    "[-p pidfile] [-R script-name] interface ...\n");
 		fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] "
+		    "[-M script-name ] [-A script-name ] "
 		    "[-p pidfile] [-R script-name] -a\n");
 	} else {
 		fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] "
+		    "[-M script-name ] [-A script-name ] "
 		    "[-p pidfile] [-R script-name] interface ...\n");
 		fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] "
+		    "[-M script-name ] [-A script-name ] "
 		    "[-p pidfile] [-R script-name] -a\n");
 	}
 	exit(1);
diff --git a/usr.sbin/rtsold/rtsold.h b/usr.sbin/rtsold/rtsold.h
index 1342ad87703b..6b8db8466e62 100644
--- a/usr.sbin/rtsold/rtsold.h
+++ b/usr.sbin/rtsold/rtsold.h
@@ -75,6 +75,7 @@ struct ifinfo {
 				 * configuration */
 	int otherconfig;	/* need a separate protocol for the "other"
 				 * configuration */
+	int alwaysconfig;	/* Have we called the 'always' script? */
 	int state;
 	int probes;
 	int dadcount;
@@ -160,6 +161,7 @@ extern int Fflag;
 extern int uflag;
 extern const char *managedconf_script;
 extern const char *otherconf_script;
+extern const char *alwaysconf_script;
 extern const char *resolvconf_script;
 extern struct cap_channel *capllflags, *capscript, *capsendmsg, *capsyslog;