aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2021-08-27 00:39:48 +0000
committerLaurent Bercot <ska@appnovation.com>2021-08-27 00:39:48 +0000
commitb61ab0373a724d38e059655d561b5fb3dcb2aff6 (patch)
tree389a18205e8e5f316285365a4244d3253dbd4dc8 /src
parent7d30371be2837dafa3f09c2ea23b9cc9054ebadc (diff)
downloadmdevd-b61ab0373a724d38e059655d561b5fb3dcb2aff6.tar.gz
Add -O nlgroups for netlink rebroadcast
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src')
-rw-r--r--src/mdevd/mdevd.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/src/mdevd/mdevd.c b/src/mdevd/mdevd.c
index 3e73393..a486a9a 100644
--- a/src/mdevd/mdevd.c
+++ b/src/mdevd/mdevd.c
@@ -42,7 +42,7 @@
#include <mdevd/config.h>
-#define USAGE "mdevd [ -v verbosity ] [ -D notif ] [ -o outputfd ] [ -b kbufsz ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ] [ -F fwbase ] [ -C ]"
+#define USAGE "mdevd [ -v verbosity ] [ -D notif ] [ -o outputfd ] [ -O nlgroups ] [ -b kbufsz ] [ -f conffile ] [ -n ] [ -s slashsys ] [ -d slashdev ] [ -F fwbase ] [ -C ]"
#define dieusage() strerr_dieusage(100, USAGE)
#define CONFBUFSIZE 8192
@@ -56,7 +56,6 @@
static int dryrun = 0 ;
static int cont = 1 ;
static pid_t pid = 0 ;
-static unsigned int outputfd = 0 ;
static unsigned int verbosity = 1 ;
static char const *slashsys = "/sys" ;
static char const *fwbase = "/lib/firmware" ;
@@ -219,6 +218,19 @@ static inline int netlink_init (unsigned int kbufsz)
return -1 ;
}
+static inline int rebc_init (unsigned int groups)
+{
+ struct sockaddr_nl nl = { .nl_family = AF_NETLINK, .nl_pad = 0, .nl_groups = groups & ~1U, .nl_pid = 0 } ;
+ int fd = socket_internal(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT, O_CLOEXEC) ;
+ if (fd == -1) return -1 ;
+ if (connect(fd, (struct sockaddr *)&nl, sizeof nl) == -1)
+ {
+ fd_close(fd) ;
+ return -1 ;
+ }
+ return fd ;
+}
+
static inline size_t netlink_read (int fd, char *s)
{
struct sockaddr_nl nl;
@@ -290,6 +302,7 @@ static inline int uevent_read (int fd, struct uevent_s *event)
}
+
/* mdev.conf parsing. See PARSING.txt for details. */
/* The first pass is simple. The goal is just to compute scriptlen and envmatchlen. */
@@ -966,9 +979,9 @@ static inline int handle_signals (void)
switch (c)
{
case -1 : strerr_diefu1sys(111, "selfpipe_read") ;
- case SIGTERM :
- case SIGHUP : cont = c == SIGHUP ;
case 0 : return e ;
+ case SIGTERM : cont = 0 ; break ;
+ case SIGHUP : cont = 1 ; break ;
case SIGCHLD :
if (!pid) wait_reap() ;
else
@@ -996,7 +1009,7 @@ static inline int handle_event (int fd, struct uevent_s *event, scriptelem const
return 1 ;
}
-static void output_event (struct uevent_s *event)
+static int output_event (unsigned int outputfd, struct uevent_s *event)
{
static char const c = 0 ;
struct iovec v[2] = { { .iov_base = event->buf, .iov_len = event->len }, { .iov_base = (char *)&c, .iov_len = 1 } } ;
@@ -1005,9 +1018,16 @@ static void output_event (struct uevent_s *event)
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, outputfd)] = 0 ;
fd_close(outputfd) ;
- outputfd = 0 ;
strerr_warnwu3sys("write to descriptor ", fmt, " (closing it)") ;
+ return 0 ;
}
+ return 1 ;
+}
+
+static void rebc_event (int fd, struct uevent_s const *event)
+{
+ if (fd_send(fd, event->buf, event->len, 0) == -1)
+ strerr_warnwu1sys("rebroadcast uevent") ;
}
int main (int argc, char const *const *argv)
@@ -1018,12 +1038,14 @@ int main (int argc, char const *const *argv)
unsigned int kbufsz = 512288 ;
char const *slashdev = "/dev" ;
int docoldplug = 0 ;
+ unsigned int outputfd = 0 ;
+ unsigned int rebc = 0 ;
PROG = "mdevd" ;
{
subgetopt l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "nv:D:o:b:f:s:d:F:C", &l) ;
+ int opt = subgetopt_r(argc, argv, "nv:D:o:O:b:f:s:d:F:C", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -1031,6 +1053,7 @@ int main (int argc, char const *const *argv)
case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ;
case 'D' : if (!uint0_scan(l.arg, &notif)) dieusage() ; break ;
case 'o' : if (!uint0_scan(l.arg, &outputfd)) dieusage() ; break ;
+ case 'O' : if (!uint0_scan(l.arg, &rebc)) dieusage() ; break ;
case 'b' : if (!uint0_scan(l.arg, &kbufsz)) dieusage() ; break ;
case 'f' : configfile = l.arg ; break ;
case 's' : slashsys = l.arg ; break ;
@@ -1063,7 +1086,6 @@ int main (int argc, char const *const *argv)
if (ndelay_on(outputfd) < 0) strerr_diefu1sys(111, "set output fd non-blocking") ;
if (coe(outputfd) < 0) strerr_diefu1sys(111, "set output fd close-on-exec") ;
}
-
{
struct stat st ;
if (stat("/", &st) < 0) strerr_diefu1sys(111, "stat /") ;
@@ -1073,6 +1095,13 @@ int main (int argc, char const *const *argv)
x[1].fd = netlink_init(kbufsz) ;
if (x[1].fd < 0) strerr_diefu1sys(111, "init netlink") ;
+ if (rebc)
+ {
+ int fd = rebc_init(rebc) ;
+ if (fd == -1) strerr_diefu2sys(111, "init netlink", " rebroadcast socket") ;
+ rebc = fd ;
+ }
+
x[0].fd = selfpipe_init() ;
if (x[0].fd < 0) strerr_diefu1sys(111, "init selfpipe") ;
if (!sig_altignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ;
@@ -1133,11 +1162,17 @@ int main (int argc, char const *const *argv)
{
if (iopause_stamp(x, 1 + (!pid && cont == 2), 0, 0) < 0) strerr_diefu1sys(111, "iopause") ;
if (x[0].revents & IOPAUSE_READ)
- if (handle_signals() && outputfd)
- output_event(&event) ;
+ if (handle_signals())
+ {
+ if (outputfd && !output_event(outputfd, &event)) outputfd = 0 ;
+ if (rebc) rebc_event(rebc, &event) ;
+ }
if (!pid && cont == 2 && x[1].revents & IOPAUSE_READ)
- if (handle_event(x[1].fd, &event, script, scriptlen, storage, envmatch) && !pid && outputfd)
- output_event(&event) ;
+ if (handle_event(x[1].fd, &event, script, scriptlen, storage, envmatch) && !pid)
+ {
+ if (outputfd && !output_event(outputfd, &event)) outputfd = 0 ;
+ if (rebc) rebc_event(rebc, &event) ;
+ }
}
script_free(script, scriptlen, envmatch, envmatchlen) ;