16 #include <sys/syscall.h>
18 #include <sys/utsname.h>
22 #include <sys/syscall.h>
23 #include <sys/types.h>
35 #include <libubox/avl.h>
36 #include <libubox/avl-cmp.h>
37 #include <libubox/utils.h>
38 #include <libubox/ulog.h>
39 #include <libubox/kvlist.h>
40 #include <libubox/list.h>
42 #define DEF_MOD_PATH "/modules/%s/"
43 #define MOD_BUILTIN "modules.builtin"
44 #define MOD_BUILTIN_MODINFO "modules.builtin.modinfo"
46 #define MODULE_NAME_LEN (64 - sizeof(unsigned long))
52 struct list_head
list;
82 static KVLIST(options, kvlist_strlen);
93 char *s, *e, *p, path[330], ldpath[256];
96 s = getenv(
"LD_LIBRARY_PATH");
99 e += snprintf(ldpath,
sizeof(ldpath),
"%s:", s);
101 e += snprintf(e,
sizeof(ldpath) - (e - ldpath),
"/lib");
105 for (s = p = ldpath; p <= e; p++) {
106 if (*p !=
':' && *p !=
'\0')
110 snprintf(path,
sizeof(path),
"%s" DEF_MOD_PATH, s, ver.release);
112 if (!stat(path, &st) && S_ISDIR(st.st_mode)) {
116 ULOG_ERR(
"out of memory\n");
127 ULOG_ERR(
"no module folders for kernel version %s found\n", ver.release);
138 mn = avl_find_element(&
modules, name, mn,
avl);
149 avl_remove_all_elements(&
modules, mn,
avl, tmp) {
162 static char path[256];
165 if (!stat(name, &s) && S_ISREG(s.st_mode))
169 snprintf(path,
sizeof(path),
"%s%s.ko", *p, name);
170 if (!stat(path, &s) && S_ISREG(s.st_mode))
182 strncpy(name, basename(path),
sizeof(name) - 1);
184 t = strstr(name,
".ko");
191 static int elf64_find_section(
char *map,
const char *section,
unsigned int *offset,
unsigned int *size)
193 const char *secnames;
198 e = (Elf64_Ehdr *) map;
199 sh = (Elf64_Shdr *) (map + e->e_shoff);
201 secnames = map + sh[e->e_shstrndx].sh_offset;
202 for (i = 0; i < e->e_shnum; i++) {
203 if (!strcmp(section, secnames + sh[i].sh_name)) {
204 *size = sh[i].sh_size;
205 *offset = sh[i].sh_offset;
213 static int elf32_find_section(
char *map,
const char *section,
unsigned int *offset,
unsigned int *size)
215 const char *secnames;
220 e = (Elf32_Ehdr *) map;
221 sh = (Elf32_Shdr *) (map + e->e_shoff);
223 secnames = map + sh[e->e_shstrndx].sh_offset;
224 for (i = 0; i < e->e_shnum; i++) {
225 if (!strcmp(section, secnames + sh[i].sh_name)) {
226 *size = sh[i].sh_size;
227 *offset = sh[i].sh_offset;
235 static int elf_find_section(
char *map,
const char *section,
unsigned int *offset,
unsigned int *size)
237 int clazz = map[EI_CLASS];
238 int endian = map[EI_DATA];
240 #if __BYTE_ORDER == __LITTLE_ENDIAN
241 if (endian != ELFDATA2LSB)
242 #elif __BYTE_ORDER == __BIG_ENDIAN
243 if (endian != ELFDATA2MSB)
245 #error "unsupported endian"
248 ULOG_ERR(
"invalid endianess: %d\n", endian);
252 if (clazz == ELFCLASS32)
254 else if (clazz == ELFCLASS64)
257 ULOG_ERR(
"unknown elf format %d\n", clazz);
268 mn = calloc_a(
sizeof(*mn),
269 &_name, strlen(name) + 1);
271 mn->
avl.key = strcpy(_name, name);
287 m = calloc_a(
sizeof(*m),
288 &_name, strlen(
name) + 1,
308 for (i = 0; i < naliases; i++)
328 fp = fopen(
"/proc/modules",
"r");
330 ULOG_ERR(
"failed to open /proc/modules\n");
334 while (getline(&buf, &buf_len, fp) > 0) {
338 m.
name = strtok(buf,
" ");
339 m.
size = atoi(strtok(NULL,
" "));
340 m.
usage = atoi(strtok(NULL,
" "));
352 ULOG_ERR(
"Failed to allocate memory for module\n");
369 const bool is_builtin = (
module == NULL);
370 const char *mpath = NULL;
371 char *map = MAP_FAILED;
378 if (!stat(path, s) && S_ISREG(s->st_mode)) {
387 ULOG_ERR(
"cannot find modinfo path of module - %s\n",
name);
391 fd = open(mpath, O_RDONLY);
393 ULOG_ERR(
"failed to open %s\n", mpath);
397 if (fstat(fd, s) == -1) {
398 ULOG_ERR(
"failed to stat %s\n", mpath);
402 map = mmap(NULL, s->st_size, PROT_READ, MAP_PRIVATE, fd, 0);
403 if (map == MAP_FAILED) {
404 ULOG_ERR(
"failed to mmap %s\n", mpath);
412 ULOG_ERR(
"failed to load the .modinfo section from %s\n", mpath);
413 munmap(map, s->st_size);
425 const bool is_builtin = (
module == NULL);
426 unsigned int offset,
size;
427 char *map, *strings, *dep = NULL;
428 const char **aliases = NULL;
429 const char **aliasesr;
435 if (map == MAP_FAILED)
438 strings = map + offset;
440 char *end = map + offset + size;
444 while ((strings < end) && !strings[0])
449 sep = strstr(strings,
".");
452 if (strlen(name) == (sep - strings) &&
453 !strncmp(strings, name, sep - strings))
458 sep = strstr(strings,
"=");
463 if (!strncmp(strings,
"depends=", len + 1))
465 else if (!strncmp(strings,
"alias=", len + 1)) {
466 aliasesr = realloc(aliases,
sizeof(sep) * (naliases + 1));
468 ULOG_ERR(
"out of memory\n");
473 aliases[naliases++] = sep;
476 strings = &sep[strlen(sep)];
479 m =
alloc_module(name, aliases, naliases, dep, is_builtin ? 0 : s.st_size);
485 if (map != MAP_FAILED)
486 munmap(map, s.st_size);
505 snprintf(path,
sizeof(path),
"%s%s", *p,
MOD_BUILTIN);
506 fp = fopen(path,
"r");
510 if (!fstat(fileno(fp), &st) && S_ISREG(st.st_mode))
520 while (getline(&buf, &buf_len, fp) > 0) {
529 ULOG_WARN(
"found duplicate builtin module %s\n",
name);
534 ULOG_ERR(
"failed to find info for builtin module %s\n",
name);
549 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
554 path = alloca(strlen(dir) +
sizeof(
"*.ko") + 1);
555 sprintf(path,
"%s*.ko", dir);
557 if (glob(path, gl_flags, NULL, &gl) < 0)
560 for (j = 0; j < gl.gl_pathc; j++) {
610 unsigned int offset,
size;
613 char *map, *strings, *mpath;
620 if (map == MAP_FAILED)
623 strings = map + offset;
625 printf(
"name:\t\t%s\n", m->
name);
626 printf(
"filename:\t%s\n", is_builtin ?
"(builtin)" : mpath);
628 char *end = map + offset + size;
633 while ((strings < end) && !strings[0])
638 sep = strstr(strings,
".");
641 if (strlen(m->
name) == (sep - strings) &&
642 !strncmp(strings, m->
name, sep - strings))
647 sep = strstr(strings,
"=");
650 dup = strndup(strings, sep - strings);
652 if (strncmp(strings,
"parm", 4)) {
654 printf(
"%s:\t\t%s\n", dup, sep);
656 printf(
"%s:\t%s\n", dup, sep);
658 sep2 = strstr(sep,
":");
664 pname = strndup(sep, sep2 - sep);
666 pdata = strdup(sep2);
668 list_for_each_entry(p, ¶ms, list)
669 if (!strcmp(pname, p->
name))
672 if (list_entry_is_h(p, ¶ms, list)) {
673 p = alloca(
sizeof(*p));
676 list_add(&p->
list, ¶ms);
681 if (!strcmp(dup,
"parmtype"))
689 strings = &sep[strlen(sep)];
692 list_for_each_entry(p, ¶ms, list) {
693 printf(
"parm:\t\t%s", p->
name);
695 printf(
":%s", p->
desc);
697 printf(
" (%s)", p->
type);
707 if (map != MAP_FAILED)
708 munmap(map, s.st_size);
727 ULOG_ERR(
"missing dependency %s\n", dep);
729 ULOG_ERR(
"dependency not loaded %s\n", dep);
732 dep += strlen(dep) + 1;
745 ULOG_ERR(
"Path not specified\n");
749 if (stat(path, &s)) {
750 ULOG_ERR(
"missing module %s\n", path);
754 fd = open(path, O_RDONLY);
756 ULOG_ERR(
"cannot open %s\n", path);
760 data = malloc(s.st_size);
762 ULOG_ERR(
"out of memory\n");
766 if (read(fd, data, s.st_size) == s.st_size) {
767 ret = syscall(__NR_init_module, data, (
unsigned long) s.st_size, options);
772 ULOG_ERR(
"failed to read full module %s\n", path);
795 ULOG_ERR(
"failed to find dependency %s\n", dep);
801 dep = dep + strlen(dep) + 1;
807 int loaded, skipped, failed;
810 bool load_retry =
false;
811 static bool first_iteration =
true;
813 avl_for_each_element(&
modules, mn, avl) {
825 avl_for_each_element(&
modules, mn, avl) {
846 if (allow_load_retry) {
848 load_retry = loaded ? (failed && !skipped) : (failed && !load_retry && !first_iteration);
851 first_iteration =
false;
852 }
while (loaded || load_retry);
854 return skipped + failed;
859 ULOG_INFO(
"Usage:\n\tinsmod filename [args]\n");
868 "\tmodprobe [-q] [-v] filename\n"
869 "\tmodprobe -a [-q] [-v] filename [filename...]\n"
877 ULOG_INFO(
"Usage:\n\t%s module\n", arg);
884 char *
name, *cur, *options;
892 ULOG_ERR(
"cannot find module - %s\n", argv[1]);
900 ULOG_ERR(
"module is already loaded - %s\n",
name);
907 for (len = 0, i = 2; i < argc; i++)
908 len += strlen(argv[i]) + 1;
910 options = malloc(len);
912 ULOG_ERR(
"out of memory\n");
919 for (i = 2; i < argc; i++) {
924 cur += sprintf(cur,
"%s", argv[i]);
928 fprintf(stderr,
"Failed to find the folder holding the modules\n");
936 fprintf(stderr,
"Failed to find %s. Maybe it is a built in module ?\n",
name);
968 ULOG_ERR(
"module is not loaded\n");
972 ULOG_ERR(
"module is builtin\n");
975 ret = syscall(__NR_delete_module, m->
name, 0);
978 ULOG_ERR(
"unloading the module failed\n");
994 avl_for_each_element(&
modules, mn, avl) {
999 printf(
"%-20s%8d%3d ",
1005 dep = dep + strlen(dep) + 1;
1036 ULOG_ERR(
"cannot find module - %s\n", argv[1]);
1051 int log_level = LOG_WARNING;
1054 bool use_all =
false;
1056 while ((opt = getopt(argc, argv,
"aqv")) != -1 ) {
1065 log_level = LOG_DEBUG;
1077 ulog_threshold(log_level);
1096 ULOG_INFO(
"%s is blacklisted\n",
name);
1099 ULOG_INFO(
"%s is already loaded\n",
name);
1102 ULOG_INFO(
"%s is builtin\n",
name);
1105 ULOG_ERR(
"failed to find a module named %s\n",
name);
1112 }
while (use_all && optind < argc);
1116 ULOG_ERR(
"%d module%s could not be probed\n",
1117 load_fail, (load_fail == 1) ? (
"") : (
"s"));
1119 avl_for_each_element(&
modules, mn, avl) {
1124 ULOG_ERR(
"- %s\n", m->
name);
1137 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
1138 char *dir =
"/etc/modules.d/";
1143 int ret = 0, fail, j;
1148 path = malloc(strlen(dir) + 2);
1150 ULOG_ERR(
"out of memory\n");
1167 ULOG_INFO(
"loading kernel modules from %s\n", path);
1169 if (glob(path, gl_flags, NULL, &gl) < 0)
1172 for (j = 0; j < gl.gl_pathc; j++) {
1173 FILE *fp = fopen(gl.gl_pathv[j],
"r");
1178 ULOG_ERR(
"failed to open %s\n", gl.gl_pathv[j]);
1182 while (getline(&mod, &mod_len, fp) > 0) {
1183 char *nl = strchr(mod,
'\n');
1190 opts = strchr(mod,
' ');
1200 char *prev = m->
opts;
1202 fail = asprintf(&m->
opts,
"%s %s", prev,
opts);
1205 ULOG_ERR(
"out of memory for opts %s\n",
opts);
1216 if (basename(gl.gl_pathv[j])[0] -
'0' <= 9)
1227 ULOG_ERR(
"%d module%s could not be probed\n",
1228 fail, (fail == 1) ? (
"") : (
"s"));
1230 avl_for_each_element(&
modules, mn, avl) {
1238 ULOG_INFO(
"done loading kernel modules from %s\n", path);
1251 return c ==
'_' ?
'-' : c;
1256 const char *s1 = k1;
1257 const char *s2 = k2;
1265 return (
unsigned char)
weight(*s1) - (
unsigned char)
weight(*s2);
1271 static char buf[512];
1275 f = fopen(
"/etc/modules.conf",
"r");
1279 while ((s = fgets(buf,
sizeof(buf), f)) != NULL) {
1280 char *c, *cmd, *mod;
1293 while (c > s && isspace(c[-1])) {
1298 cmd = strsep(&s,
" \t");
1305 mod = strsep(&s,
" \t");
1309 if (!strcmp(cmd,
"blacklist")) {
1310 kvlist_set(&options, mod,
"\x01");
1314 if (!strcmp(cmd,
"options")) {
1315 char *prev = kvlist_get(&options, mod);
1324 if (prev && prev[0] ==
'\x01')
1328 kvlist_set(&options, mod, s);
1332 if (asprintf(&val,
"%s %s", prev, s) < 0)
1335 kvlist_set(&options, mod, val);
1346 char *exec = basename(*argv);
1349 if (!strcmp(exec,
"insmod"))
1352 if (!strcmp(exec,
"rmmod"))
1355 if (!strcmp(exec,
"lsmod"))
1358 if (!strcmp(exec,
"modinfo"))
1363 if (!strcmp(exec,
"modprobe"))
1366 ulog_open(ULOG_KMSG, LOG_USER,
"kmodloader");
static int print_insmod_usage(void)
static int main_insmod(int argc, char **argv)
static int print_usage(char *arg)
static int main_lsmod(int argc, char **argv)
static struct module_node * alloc_module_node(const char *name, struct module *m, bool is_alias)
static int scan_module_folder(const char *dir)
static struct avl_tree modules
static int elf_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
int main(int argc, char **argv)
static int print_modprobe_usage(void)
static void free_modules(void)
#define MOD_BUILTIN_MODINFO
static int elf64_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
static void load_moddeps(struct module *_m)
static KVLIST(options, kvlist_strlen)
static char * get_module_path(char *name)
static int insert_module(char *path, const char *options)
static int scan_loaded_modules(void)
static void load_options(void)
static char * mmap_modinfo(const char *module, const char *name, struct stat *s, unsigned int *offset, unsigned int *size)
static struct module * find_module(const char *name)
static char * get_module_name(char *path)
static int init_module_folders(void)
static int main_modinfo(int argc, char **argv)
static int main_rmmod(int argc, char **argv)
static struct module * alloc_module(const char *name, const char *const *aliases, int naliases, const char *depends, int size)
static struct module * get_module_info(const char *module, const char *name)
static int main_modprobe(int argc, char **argv)
static char ** module_folders
static int load_modprobe(bool allow_load_retry)
static char weight(char c)
static int deps_available(struct module *m, int verbose)
static int avl_modcmp(const void *k1, const void *k2, void *ptr)
static int scan_module_folders(void)
static int print_modinfo(const struct module *m)
static int scan_builtin_modules(void)
static int elf32_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
static void free_module(struct module *m)
static int main_loader(int argc, char **argv)
static LIST_HEAD(clients)