Fix #325: allow custom modprobe command in modules-load.d plugin

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2022-12-06 14:01:20 +01:00
1 parent 3d9cbaf040
commit 3df154b798
2 files changed
+82 -31

No files matched your search

+14 -5
View File
@@ -62,7 +62,7 @@ For your convenience a set of *optional* plugins are available:
* *modules-load.so*: Scans `/etc/modules-load.d/*.conf` for modules to * *modules-load.so*: Scans `/etc/modules-load.d/*.conf` for modules to
load using `modprobe`. Each file can contain multiple lines with the load using `modprobe`. Each file can contain multiple lines with the
name of the module to load. Any line starting with the standard UNIX name of the module to load. Any line starting with the standard UNIX
comment character, `#`, is skipped. comment character, `#`, or `;`, is skipped.
Modules are loaded when entering runlevel `[2345]` using the `task` Modules are loaded when entering runlevel `[2345]` using the `task`
stanza. Each module gets a unique `name:modprobe.foo`, and stanza. Each module gets a unique `name:modprobe.foo`, and
@@ -71,11 +71,20 @@ For your convenience a set of *optional* plugins are available:
set noindex set noindex
To change the index used by the plugin:
set index 1234
**Note:** unlike the traditional .conf `module` directive, which load **Note:** unlike the traditional .conf `module` directive, which load
any listed module immediately, this plugin creates standard `taks` any listed module immediately, this plugin creates a background `task`
directives which load the module(s) in the background. As long as which load the module(s) in the background. The program is modprobe,
the `modprobe` program is found in the path, these tasks will always `/sbin/modprobe`, which you can override per .conf file:
return `[ OK ]` at boot. Check the actual status using `initctl`.
set modprobe /path/to/maybe-a-modprobe-wrapper
Since these tasks run in the background, they usually return `[ OK ]`
at boot, unless the modprobe tool does not exist. Check syslog for
warnings and the actual status of the operation using `initctl`.
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and * *netlink.so*: Listens to Linux kernel Netlink events for gateway and
interfaces. These events are then sent to the Finit service monitor interfaces. These events are then sent to the Finit service monitor
+68 -26
View File
@@ -62,62 +62,104 @@
#ifndef MODULES_LOAD_PATH #ifndef MODULES_LOAD_PATH
#define MODULES_LOAD_PATH "/etc/modules-load.d" #define MODULES_LOAD_PATH "/etc/modules-load.d"
#endif #endif
#define MODPROBE_PATH "/sbin/modprobe"
#define SERVICE_LINE \ #define SERVICE_LINE \
"cgroup.init name:modprobe.%s :%d [2345] /sbin/modprobe %s %s -- Kernel module: %s" "cgroup.init name:modprobe.%s :%d [2345] %s %s %s -- Kernel module: %s"
#define SERVICE_LINE_NOINDEX \ #define SERVICE_LINE_NOINDEX \
"cgroup.init name:modprobe.%s [2345] /sbin/modprobe %s %s -- Kernel module: %s" "cgroup.init name:modprobe.%s [2345] %s %s %s -- Kernel module: %s"
static int load_file(const char *file, int index) static int modules_load(const char *file, int index)
{ {
char module_path[PATH_MAX]; char module_path[PATH_MAX];
char line[256]; char *modprobe_path;
int num = 0; int num = 0;
char *line;
FILE *fp; FILE *fp;
strlcpy(module_path, MODULES_LOAD_PATH "/", sizeof(module_path)); strlcpy(module_path, MODULES_LOAD_PATH "/", sizeof(module_path));
strlcat(module_path, file, sizeof(module_path)); strlcat(module_path, file, sizeof(module_path));
fp = fopen(module_path, "r"); fp = fopen(module_path, "r");
if (!fp) if (!fp) {
warnx("failed opening %s for reading, skipping ...", module_path);
return 0; return 0;
}
while (fgets(line, sizeof(line), fp)) { modprobe_path = strdup(MODPROBE_PATH);
char cmd[CMD_SIZE], *mod, *args; if (!modprobe_path) {
warnx("failed allocating memory in modules-load plugin.");
fclose(fp);
return -1;
}
chomp(line); while ((line = fparseln(fp, NULL, NULL, NULL, 0))) {
char cmd[CMD_SIZE * 2], *mod, *args, *set;
/*
* fparseln() skips regular UNIX comments only.
* This is for modules-load.d(5) compat.
*/
if (line[0] == ';')
goto next;
/* trim whitespace */
mod = strip_line(line); mod = strip_line(line);
if (!mod[0]) if (!mod[0])
continue; goto next;
if (mod[0] == '#' || mod[0] == ';') /* Finit extension 'set foo bar' */
continue; if ((set = fgetval(mod, "set", "= \t"))) {
char *val = mod;
if (!strcmp(mod, "set noindex")) { if (!strcmp(set, "noindex")) {
index = 0; index = 0;
continue; free(set);
} goto next;
if (!strncmp(mod, "set index", 9)) { }
mod += 9;
args = strchr(mod, '='); if ((val = fgetval(set, "index", "= \t"))) {
if (args) /* optional */ index = atoi(val);
mod = args + 1; free(set);
index = atoi(mod); free(val);
continue; goto next;
}
if ((val = fgetval(set, "modprobe", "= \t"))) {
if (access(val, X_OK)) {
warn("%s: cannot use %s", module_path, val);
free(set);
free(val);
free(line);
goto skip;
} else {
free(modprobe_path);
modprobe_path = val;
}
free(set);
goto next;
}
/* unknown 'set' command, ignore. */
goto next;
} }
mod = strtok_r(mod, " ", &args); mod = strtok_r(mod, " ", &args);
if (!mod) if (!mod)
continue; goto next;
if (!index) if (!index)
snprintf(cmd, sizeof(cmd), SERVICE_LINE_NOINDEX, mod, mod, args, mod); snprintf(cmd, sizeof(cmd), SERVICE_LINE_NOINDEX, mod, modprobe_path, mod, args, mod);
else else
snprintf(cmd, sizeof(cmd), SERVICE_LINE, mod, index++, mod, args, mod); snprintf(cmd, sizeof(cmd), SERVICE_LINE, mod, index++, modprobe_path, mod, args, mod);
dbg("task %s", cmd);
service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL); service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL);
num++; num++;
next:
free(line);
} }
skip:
free(modprobe_path);
fclose(fp); fclose(fp);
return num; return num;
@@ -146,7 +188,7 @@ static void load(void *arg)
num = scandir(MODULES_LOAD_PATH, &dentry, module_filter, alphasort); num = scandir(MODULES_LOAD_PATH, &dentry, module_filter, alphasort);
if (num > 0) { if (num > 0) {
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
index += load_file(dentry[i]->d_name, index); index += modules_load(dentry[i]->d_name, index);
free(dentry[i]); free(dentry[i]);
} }
free(dentry); free(dentry);