kmodloader: support loadable module parameters in modinfo
[project/ubox.git] / kmodloader.c
1 /*
2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15 #define _GNU_SOURCE
16 #include <sys/syscall.h>
17 #include <sys/mman.h>
18 #include <sys/utsname.h>
19
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/syscall.h>
23 #include <sys/types.h>
24 #include <values.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <libgen.h>
31 #include <glob.h>
32 #include <elf.h>
33 #include <ctype.h>
34
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>
41
42 #define DEF_MOD_PATH "/modules/%s/"
43 /* duplicated from in-kernel include/linux/module.h */
44 #define MODULE_NAME_LEN (64 - sizeof(unsigned long))
45
46 struct param {
47 char *name;
48 char *desc;
49 char *type;
50 struct list_head list;
51 };
52
53 enum {
54 SCANNED,
55 PROBE,
56 LOADED,
57 BLACKLISTED,
58 };
59
60 struct module {
61 char *name;
62 char *depends;
63 char *opts;
64
65 int size;
66 int usage;
67 int state;
68 int error;
69 int refcnt; /* number of references from module_node.m */
70 };
71
72 struct module_node {
73 struct avl_node avl;
74 struct module *m;
75 bool is_alias;
76 };
77
78 static struct avl_tree modules;
79 static KVLIST(options, kvlist_strlen);
80
81 static char **module_folders = NULL;
82
83 static void free_module(struct module *m);
84
85 static int init_module_folders(void)
86 {
87 int n = 0;
88 struct stat st;
89 struct utsname ver;
90 char *s, *e, *p, path[330], ldpath[256];
91
92 e = ldpath;
93 s = getenv("LD_LIBRARY_PATH");
94
95 if (s)
96 e += snprintf(ldpath, sizeof(ldpath), "%s:", s);
97
98 e += snprintf(e, sizeof(ldpath) - (e - ldpath), "/lib");
99
100 uname(&ver);
101
102 for (s = p = ldpath; p <= e; p++) {
103 if (*p != ':' && *p != '\0')
104 continue;
105
106 *p = 0;
107 snprintf(path, sizeof(path), "%s" DEF_MOD_PATH, s, ver.release);
108
109 if (!stat(path, &st) && S_ISDIR(st.st_mode)) {
110 module_folders = realloc(module_folders, sizeof(p) * (n + 2));
111
112 if (!module_folders) {
113 ULOG_ERR("out of memory\n");
114 return -1;
115 }
116
117 module_folders[n++] = strdup(path);
118 }
119
120 s = p + 1;
121 }
122
123 if (!module_folders) {
124 ULOG_ERR("no module folders for kernel version %s found\n", ver.release);
125 return -1;
126 }
127
128 module_folders[n] = NULL;
129 return 0;
130 }
131
132 static struct module *find_module(const char *name)
133 {
134 struct module_node *mn;
135 mn = avl_find_element(&modules, name, mn, avl);
136 if (mn)
137 return mn->m;
138 else
139 return NULL;
140 }
141
142 static void free_modules(void)
143 {
144 struct module_node *mn, *tmp;
145
146 avl_remove_all_elements(&modules, mn, avl, tmp) {
147 struct module *m = mn->m;
148
149 m->refcnt -= 1;
150 if (m->refcnt == 0)
151 free_module(m);
152 free(mn);
153 }
154 }
155
156 static char* get_module_path(char *name)
157 {
158 char **p;
159 static char path[256];
160 struct stat s;
161
162 if (!stat(name, &s) && S_ISREG(s.st_mode))
163 return name;
164
165 for (p = module_folders; *p; p++) {
166 snprintf(path, sizeof(path), "%s%s.ko", *p, name);
167 if (!stat(path, &s) && S_ISREG(s.st_mode))
168 return path;
169 }
170
171 return NULL;
172 }
173
174 static char* get_module_name(char *path)
175 {
176 static char name[MODULE_NAME_LEN];
177 char *t;
178
179 strncpy(name, basename(path), sizeof(name) - 1);
180
181 t = strstr(name, ".ko");
182 if (t)
183 *t = '\0';
184
185 return name;
186 }
187
188 static int elf64_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
189 {
190 const char *secnames;
191 Elf64_Ehdr *e;
192 Elf64_Shdr *sh;
193 int i;
194
195 e = (Elf64_Ehdr *) map;
196 sh = (Elf64_Shdr *) (map + e->e_shoff);
197
198 secnames = map + sh[e->e_shstrndx].sh_offset;
199 for (i = 0; i < e->e_shnum; i++) {
200 if (!strcmp(section, secnames + sh[i].sh_name)) {
201 *size = sh[i].sh_size;
202 *offset = sh[i].sh_offset;
203 return 0;
204 }
205 }
206
207 return -1;
208 }
209
210 static int elf32_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
211 {
212 const char *secnames;
213 Elf32_Ehdr *e;
214 Elf32_Shdr *sh;
215 int i;
216
217 e = (Elf32_Ehdr *) map;
218 sh = (Elf32_Shdr *) (map + e->e_shoff);
219
220 secnames = map + sh[e->e_shstrndx].sh_offset;
221 for (i = 0; i < e->e_shnum; i++) {
222 if (!strcmp(section, secnames + sh[i].sh_name)) {
223 *size = sh[i].sh_size;
224 *offset = sh[i].sh_offset;
225 return 0;
226 }
227 }
228
229 return -1;
230 }
231
232 static int elf_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
233 {
234 int clazz = map[EI_CLASS];
235 int endian = map[EI_DATA];
236
237 #if __BYTE_ORDER == __LITTLE_ENDIAN
238 if (endian != ELFDATA2LSB)
239 #elif __BYTE_ORDER == __BIG_ENDIAN
240 if (endian != ELFDATA2MSB)
241 #else
242 #error "unsupported endian"
243 #endif
244 {
245 ULOG_ERR("invalid endianess: %d\n", endian);
246 return -1;
247 }
248
249 if (clazz == ELFCLASS32)
250 return elf32_find_section(map, section, offset, size);
251 else if (clazz == ELFCLASS64)
252 return elf64_find_section(map, section, offset, size);
253
254 ULOG_ERR("unknown elf format %d\n", clazz);
255
256 return -1;
257 }
258
259 static struct module_node *
260 alloc_module_node(const char *name, struct module *m, bool is_alias)
261 {
262 struct module_node *mn;
263 char *_name;
264
265 mn = calloc_a(sizeof(*mn),
266 &_name, strlen(name) + 1);
267 if (mn) {
268 mn->avl.key = strcpy(_name, name);
269 mn->m = m;
270 mn->is_alias = is_alias;
271 avl_insert(&modules, &mn->avl);
272 m->refcnt += 1;
273 }
274 return mn;
275 }
276
277 static struct module *
278 alloc_module(const char *name, const char * const *aliases, int naliases, const char *depends, int size)
279 {
280 struct module *m;
281 char *_name, *_dep;
282 int i;
283
284 m = calloc_a(sizeof(*m),
285 &_name, strlen(name) + 1,
286 &_dep, depends ? strlen(depends) + 2 : 0);
287 if (!m)
288 return NULL;
289
290 m->name = strcpy(_name, name);
291 m->opts = 0;
292
293 if (depends) {
294 m->depends = strcpy(_dep, depends);
295 while (*_dep) {
296 if (*_dep == ',')
297 *_dep = '\0';
298 _dep++;
299 }
300 }
301 m->size = size;
302
303 m->refcnt = 0;
304 alloc_module_node(m->name, m, false);
305 for (i = 0; i < naliases; i++)
306 alloc_module_node(aliases[i], m, true);
307
308 return m;
309 }
310
311 static void free_module(struct module *m)
312 {
313 if (m->opts)
314 free(m->opts);
315 free(m);
316 }
317
318 static int scan_loaded_modules(void)
319 {
320 size_t buf_len = 0;
321 char *buf = NULL;
322 int rv = -1;
323 FILE *fp;
324
325 fp = fopen("/proc/modules", "r");
326 if (!fp) {
327 ULOG_ERR("failed to open /proc/modules\n");
328 goto out;
329 }
330
331 while (getline(&buf, &buf_len, fp) > 0) {
332 struct module m;
333 struct module *n;
334
335 m.name = strtok(buf, " ");
336 m.size = atoi(strtok(NULL, " "));
337 m.usage = atoi(strtok(NULL, " "));
338 m.depends = strtok(NULL, " ");
339
340 if (!m.name || !m.depends)
341 continue;
342
343 n = find_module(m.name);
344 if (!n) {
345 /* possibly a module outside /lib/modules/<ver>/ */
346 n = alloc_module(m.name, NULL, 0, m.depends, m.size);
347 }
348 if (!n) {
349 ULOG_ERR("Failed to allocate memory for module\n");
350 goto out;
351 }
352
353 n->usage = m.usage;
354 n->state = LOADED;
355 }
356 rv = 0;
357 out:
358 free(buf);
359 fclose(fp);
360
361 return rv;
362 }
363
364 static struct module* get_module_info(const char *module, const char *name)
365 {
366 int fd = open(module, O_RDONLY);
367 unsigned int offset, size;
368 char *map = MAP_FAILED, *strings, *dep = NULL;
369 const char **aliases = NULL;
370 const char **aliasesr;
371 int naliases = 0;
372 struct module *m = NULL;
373 struct stat s;
374
375 if (fd < 0) {
376 ULOG_ERR("failed to open %s\n", module);
377 goto out;
378 }
379
380 if (fstat(fd, &s) == -1) {
381 ULOG_ERR("failed to stat %s\n", module);
382 goto out;
383 }
384
385 map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
386 if (map == MAP_FAILED) {
387 ULOG_ERR("failed to mmap %s\n", module);
388 goto out;
389 }
390
391 if (elf_find_section(map, ".modinfo", &offset, &size)) {
392 ULOG_ERR("failed to load the .modinfo section from %s\n", module);
393 goto out;
394 }
395
396 strings = map + offset;
397 while (true) {
398 char *sep;
399 int len;
400
401 while (!strings[0])
402 strings++;
403 if (strings >= map + offset + size)
404 break;
405 sep = strstr(strings, "=");
406 if (!sep)
407 break;
408 len = sep - strings;
409 sep++;
410 if (!strncmp(strings, "depends=", len + 1))
411 dep = sep;
412 else if (!strncmp(strings, "alias=", len + 1)) {
413 aliasesr = realloc(aliases, sizeof(sep) * (naliases + 1));
414 if (!aliasesr) {
415 ULOG_ERR("out of memory\n");
416 goto out;
417 }
418
419 aliases = aliasesr;
420 aliases[naliases++] = sep;
421 }
422 strings = &sep[strlen(sep)];
423 }
424
425 m = alloc_module(name, aliases, naliases, dep, s.st_size);
426
427 if (m)
428 m->state = SCANNED;
429
430 out:
431 if (map != MAP_FAILED)
432 munmap(map, s.st_size);
433
434 if (fd >= 0)
435 close(fd);
436
437 free(aliases);
438
439 return m;
440 }
441
442 static int scan_module_folder(const char *dir)
443 {
444 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
445 char *path;
446 glob_t gl;
447 int j, rv = 0;
448
449 path = alloca(strlen(dir) + sizeof("*.ko") + 1);
450 sprintf(path, "%s*.ko", dir);
451
452 if (glob(path, gl_flags, NULL, &gl) < 0)
453 return -1;
454
455 for (j = 0; j < gl.gl_pathc; j++) {
456 char *name = get_module_name(gl.gl_pathv[j]);
457 struct module *m;
458 char *opts;
459
460 if (!name)
461 continue;
462
463 m = find_module(name);
464 if (m)
465 continue;
466
467 m = get_module_info(gl.gl_pathv[j], name);
468 if (!m) {
469 rv |= -1;
470 continue;
471 }
472
473 opts = kvlist_get(&options, name);
474 if (!opts)
475 continue;
476
477 if (*opts == '\x01')
478 m->state = BLACKLISTED;
479 else
480 m->opts = strdup(opts);
481 }
482
483 globfree(&gl);
484
485 return rv;
486 }
487
488 static int scan_module_folders(void)
489 {
490 int rv = 0;
491 char **p;
492
493 if (init_module_folders())
494 return -1;
495
496 for (p = module_folders; *p; p++)
497 rv |= scan_module_folder(*p);
498
499 return rv;
500 }
501
502 static int print_modinfo(char *module)
503 {
504 int fd = open(module, O_RDONLY);
505 unsigned int offset, size;
506 struct param *p;
507 struct stat s;
508 char *map = MAP_FAILED, *strings;
509 int rv = -1;
510
511 LIST_HEAD(params);
512
513 if (fd < 0) {
514 ULOG_ERR("failed to open %s\n", module);
515 goto out;
516 }
517
518 if (fstat(fd, &s) == -1) {
519 ULOG_ERR("failed to stat %s\n", module);
520 goto out;
521 }
522
523 map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
524 if (map == MAP_FAILED) {
525 ULOG_ERR("failed to mmap %s\n", module);
526 goto out;
527 }
528
529 if (elf_find_section(map, ".modinfo", &offset, &size)) {
530 ULOG_ERR("failed to load the .modinfo section from %s\n", module);
531 goto out;
532 }
533
534 strings = map + offset;
535 printf("module:\t\t%s\n", module);
536 while (true) {
537 char *pname, *pdata;
538 char *dup = NULL;
539 char *sep, *sep2;
540
541 while (!strings[0])
542 strings++;
543 if (strings >= map + offset + size)
544 break;
545 sep = strstr(strings, "=");
546 if (!sep)
547 break;
548 dup = strndup(strings, sep - strings);
549 sep++;
550 if (strncmp(strings, "parm", 4)) {
551 if (strlen(dup) < 7)
552 printf("%s:\t\t%s\n", dup, sep);
553 else
554 printf("%s:\t%s\n", dup, sep);
555 } else {
556 sep2 = strstr(sep, ":");
557 if (!sep2)
558 break;
559 pname = strndup(sep, sep2 - sep);
560 sep2++;
561 pdata = strdup(sep2);
562
563 list_for_each_entry(p, &params, list)
564 if (!strcmp(pname, p->name))
565 break;
566
567 if (list_entry_is_h(p, &params, list)) {
568 p = alloca(sizeof(*p));
569 p->name = pname;
570 p->desc = p->type = NULL;
571 list_add(&p->list, &params);
572 } else {
573 free(pname);
574 }
575
576 if (!strcmp(dup, "parmtype"))
577 p->type = pdata;
578 else
579 p->desc = pdata;
580 }
581 strings = &sep[strlen(sep)];
582 if (dup)
583 free(dup);
584 }
585
586 list_for_each_entry(p, &params, list) {
587 printf("parm:\t\t%s", p->name);
588 if (p->desc)
589 printf(":%s", p->desc);
590 if (p->type)
591 printf(" (%s)", p->type);
592 printf("\n");
593 free(p->name);
594 free(p->desc);
595 free(p->type);
596 }
597
598 rv = 0;
599
600 out:
601 if (map != MAP_FAILED)
602 munmap(map, s.st_size);
603
604 if (fd >= 0)
605 close(fd);
606
607 return rv;
608 }
609
610 static int deps_available(struct module *m, int verbose)
611 {
612 char *dep;
613 int err = 0;
614
615 if (!m->depends || !strcmp(m->depends, "-") || !strcmp(m->depends, ""))
616 return 0;
617
618 dep = m->depends;
619
620 while (*dep) {
621 m = find_module(dep);
622
623 if (verbose && !m)
624 ULOG_ERR("missing dependency %s\n", dep);
625 if (verbose && m && (m->state != LOADED))
626 ULOG_ERR("dependency not loaded %s\n", dep);
627 if (!m || (m->state != LOADED))
628 err++;
629 dep += strlen(dep) + 1;
630 }
631
632 return err;
633 }
634
635 static int insert_module(char *path, const char *options)
636 {
637 void *data = 0;
638 struct stat s;
639 int fd, ret = -1;
640
641 if (!path) {
642 ULOG_ERR("Path not specified\n");
643 return ret;
644 }
645
646 if (stat(path, &s)) {
647 ULOG_ERR("missing module %s\n", path);
648 return ret;
649 }
650
651 fd = open(path, O_RDONLY);
652 if (fd < 0) {
653 ULOG_ERR("cannot open %s\n", path);
654 return ret;
655 }
656
657 data = malloc(s.st_size);
658 if (!data) {
659 ULOG_ERR("out of memory\n");
660 goto out;
661 }
662
663 if (read(fd, data, s.st_size) == s.st_size) {
664 ret = syscall(__NR_init_module, data, (unsigned long) s.st_size, options);
665 if (errno == EEXIST)
666 ret = 0;
667 }
668 else
669 ULOG_ERR("failed to read full module %s\n", path);
670
671 out:
672 close(fd);
673 free(data);
674
675 return ret;
676 }
677
678 static void load_moddeps(struct module *_m)
679 {
680 char *dep;
681 struct module *m;
682
683 if (!strcmp(_m->depends, "-") || !strcmp(_m->depends, ""))
684 return;
685
686 dep = _m->depends;
687
688 while (*dep) {
689 m = find_module(dep);
690
691 if (!m)
692 ULOG_ERR("failed to find dependency %s\n", dep);
693 if (m && (m->state != LOADED)) {
694 m->state = PROBE;
695 load_moddeps(m);
696 }
697
698 dep = dep + strlen(dep) + 1;
699 }
700 }
701
702 static int load_modprobe(bool allow_load_retry)
703 {
704 int loaded, skipped, failed;
705 struct module_node *mn;
706 struct module *m;
707 bool load_retry = false;
708 static bool first_iteration = true;
709
710 avl_for_each_element(&modules, mn, avl) {
711 if (mn->is_alias)
712 continue;
713 m = mn->m;
714 if (m->state == PROBE)
715 load_moddeps(m);
716 }
717
718 do {
719 loaded = 0;
720 skipped = 0;
721 failed = 0;
722 avl_for_each_element(&modules, mn, avl) {
723 if (mn->is_alias)
724 continue;
725 m = mn->m;
726 if ((m->state == PROBE) && (!deps_available(m, 0)) && (!m->error || load_retry)) {
727 if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
728 m->state = LOADED;
729 m->error = 0;
730 loaded++;
731 continue;
732 }
733
734 m->error = 1;
735 }
736
737 if (m->error)
738 failed++;
739 else if (m->state == PROBE)
740 skipped++;
741 }
742
743 if (allow_load_retry) {
744 /* if we can't load anything else let's try to load failed modules */
745 load_retry = loaded ? (failed && !skipped) : (failed && !load_retry && !first_iteration);
746 }
747
748 first_iteration = false;
749 } while (loaded || load_retry);
750
751 return skipped + failed;
752 }
753
754 static int print_insmod_usage(void)
755 {
756 ULOG_INFO("Usage:\n\tinsmod filename [args]\n");
757
758 return -1;
759 }
760
761 static int print_modprobe_usage(void)
762 {
763 ULOG_INFO(
764 "Usage:\n"
765 "\tmodprobe [-q] [-v] filename\n"
766 "\tmodprobe -a [-q] [-v] filename [filename...]\n"
767 );
768
769 return -1;
770 }
771
772 static int print_usage(char *arg)
773 {
774 ULOG_INFO("Usage:\n\t%s module\n", arg);
775
776 return -1;
777 }
778
779 static int main_insmod(int argc, char **argv)
780 {
781 char *name, *cur, *options;
782 int i, ret, len;
783
784 if (argc < 2)
785 return print_insmod_usage();
786
787 name = get_module_name(argv[1]);
788 if (!name) {
789 ULOG_ERR("cannot find module - %s\n", argv[1]);
790 return -1;
791 }
792
793 if (scan_loaded_modules())
794 return -1;
795
796 if (find_module(name)) {
797 ULOG_ERR("module is already loaded - %s\n", name);
798 return -1;
799
800 }
801
802 free_modules();
803
804 for (len = 0, i = 2; i < argc; i++)
805 len += strlen(argv[i]) + 1;
806
807 options = malloc(len);
808 if (!options) {
809 ULOG_ERR("out of memory\n");
810 ret = -1;
811 goto err;
812 }
813
814 options[0] = 0;
815 cur = options;
816 for (i = 2; i < argc; i++) {
817 if (options[0]) {
818 *cur = ' ';
819 cur++;
820 }
821 cur += sprintf(cur, "%s", argv[i]);
822 }
823
824 if (init_module_folders()) {
825 fprintf(stderr, "Failed to find the folder holding the modules\n");
826 ret = -1;
827 goto err;
828 }
829
830 if (get_module_path(argv[1])) {
831 name = argv[1];
832 } else if (!get_module_path(name)) {
833 fprintf(stderr, "Failed to find %s. Maybe it is a built in module ?\n", name);
834 ret = -1;
835 goto err;
836 }
837
838 ret = insert_module(get_module_path(name), options);
839 if (ret)
840 ULOG_ERR("failed to insert %s\n", get_module_path(name));
841
842 err:
843 free(options);
844 return ret;
845 }
846
847 static int main_rmmod(int argc, char **argv)
848 {
849 struct module *m;
850 char *name;
851 int ret;
852
853 if (argc != 2)
854 return print_usage("rmmod");
855
856 if (scan_loaded_modules())
857 return -1;
858
859 name = get_module_name(argv[1]);
860 m = find_module(name);
861 if (!m) {
862 ULOG_ERR("module is not loaded\n");
863 return -1;
864 }
865 ret = syscall(__NR_delete_module, m->name, 0);
866
867 if (ret)
868 ULOG_ERR("unloading the module failed\n");
869
870 free_modules();
871
872 return ret;
873 }
874
875 static int main_lsmod(int argc, char **argv)
876 {
877 struct module_node *mn;
878 struct module *m;
879 char *dep;
880
881 if (scan_loaded_modules())
882 return -1;
883
884 avl_for_each_element(&modules, mn, avl) {
885 if (mn->is_alias)
886 continue;
887 m = mn->m;
888 if (m->state == LOADED) {
889 printf("%-20s%8d%3d ",
890 m->name, m->size, m->usage);
891 if (m->depends && strcmp(m->depends, "-") && strcmp(m->depends, "")) {
892 dep = m->depends;
893 while (*dep) {
894 printf("%s", dep);
895 dep = dep + strlen(dep) + 1;
896 if (*dep)
897 printf(",");
898 }
899 }
900 printf("\n");
901 }
902 }
903
904 free_modules();
905
906 return 0;
907 }
908
909 static int main_modinfo(int argc, char **argv)
910 {
911 struct module *m;
912 char *name;
913
914 if (argc != 2)
915 return print_usage("modinfo");
916
917 if (scan_module_folders())
918 return -1;
919
920 name = get_module_name(argv[1]);
921 m = find_module(name);
922 if (!m) {
923 ULOG_ERR("cannot find module - %s\n", argv[1]);
924 return -1;
925 }
926
927 name = get_module_path(m->name);
928 if (!name) {
929 ULOG_ERR("cannot find path of module - %s\n", m->name);
930 return -1;
931 }
932
933 print_modinfo(name);
934
935 return 0;
936 }
937
938 static int main_modprobe(int argc, char **argv)
939 {
940 struct module_node *mn;
941 struct module *m;
942 int exit_code = 0;
943 int load_fail;
944 int log_level = LOG_WARNING;
945 int opt;
946 bool quiet = false;
947 bool use_all = false;
948
949 while ((opt = getopt(argc, argv, "aqv")) != -1 ) {
950 switch (opt) {
951 case 'a':
952 use_all = true;
953 break;
954 case 'q': /* shhhh! */
955 quiet = true;
956 break;
957 case 'v':
958 log_level = LOG_DEBUG;
959 break;
960 default: /* '?' */
961 return print_modprobe_usage();
962 break;
963 }
964 }
965
966 if (optind >= argc)
967 return print_modprobe_usage(); /* expected module after options */
968
969 /* after print_modprobe_usage() so it won't be filtered out */
970 ulog_threshold(log_level);
971
972 if (scan_module_folders())
973 return -1;
974
975 if (scan_loaded_modules())
976 return -1;
977
978 do {
979 char *name;
980
981 name = get_module_name(argv[optind]);
982 m = find_module(name);
983
984 if (m && m->state == BLACKLISTED) {
985 if (!quiet)
986 ULOG_INFO("%s is blacklisted\n", name);
987 } else if (m && m->state == LOADED) {
988 if (!quiet)
989 ULOG_INFO("%s is already loaded\n", name);
990 } else if (!m) {
991 if (!quiet)
992 ULOG_ERR("failed to find a module named %s\n", name);
993 exit_code = -1;
994 } else {
995 m->state = PROBE;
996 }
997
998 optind++;
999 } while (use_all && optind < argc);
1000
1001 load_fail = load_modprobe(true);
1002 if (load_fail) {
1003 ULOG_ERR("%d module%s could not be probed\n",
1004 load_fail, (load_fail == 1) ? ("") : ("s"));
1005
1006 avl_for_each_element(&modules, mn, avl) {
1007 if (mn->is_alias)
1008 continue;
1009 m = mn->m;
1010 if ((m->state == PROBE) || m->error)
1011 ULOG_ERR("- %s\n", m->name);
1012 }
1013
1014 exit_code = -1;
1015 }
1016
1017 free_modules();
1018
1019 return exit_code;
1020 }
1021
1022 static int main_loader(int argc, char **argv)
1023 {
1024 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
1025 char *dir = "/etc/modules.d/";
1026 struct module_node *mn;
1027 struct module *m;
1028 glob_t gl;
1029 char *path;
1030 int ret = 0, fail, j;
1031
1032 if (argc > 1)
1033 dir = argv[1];
1034
1035 path = malloc(strlen(dir) + 2);
1036 if (!path) {
1037 ULOG_ERR("out of memory\n");
1038 return -1;
1039 }
1040
1041 strcpy(path, dir);
1042 strcat(path, "*");
1043
1044 if (scan_module_folders()) {
1045 ret = -1;
1046 goto free_path;
1047 }
1048
1049 if (scan_loaded_modules()) {
1050 ret = -1;
1051 goto free_path;
1052 }
1053
1054 ULOG_INFO("loading kernel modules from %s\n", path);
1055
1056 if (glob(path, gl_flags, NULL, &gl) < 0)
1057 goto out;
1058
1059 for (j = 0; j < gl.gl_pathc; j++) {
1060 FILE *fp = fopen(gl.gl_pathv[j], "r");
1061 size_t mod_len = 0;
1062 char *mod = NULL;
1063
1064 if (!fp) {
1065 ULOG_ERR("failed to open %s\n", gl.gl_pathv[j]);
1066 continue;
1067 }
1068
1069 while (getline(&mod, &mod_len, fp) > 0) {
1070 char *nl = strchr(mod, '\n');
1071 struct module *m;
1072 char *opts;
1073
1074 if (nl)
1075 *nl = '\0';
1076
1077 opts = strchr(mod, ' ');
1078 if (opts)
1079 *opts++ = '\0';
1080
1081 m = find_module(get_module_name(mod));
1082 if (!m || m->state == LOADED || m->state == BLACKLISTED)
1083 continue;
1084
1085 if (opts) {
1086 if (m->opts) {
1087 char *prev = m->opts;
1088
1089 fail = asprintf(&m->opts, "%s %s", prev, opts);
1090 free(prev);
1091 if (fail < 0) {
1092 ULOG_ERR("out of memory for opts %s\n", opts);
1093 free(mod);
1094 fclose(fp);
1095 ret = -1;
1096 goto out;
1097 }
1098 } else {
1099 m->opts = strdup(opts);
1100 }
1101 }
1102 m->state = PROBE;
1103 if (basename(gl.gl_pathv[j])[0] - '0' <= 9)
1104 load_modprobe(false);
1105
1106 }
1107 free(mod);
1108 fclose(fp);
1109 }
1110
1111 fail = load_modprobe(true);
1112
1113 if (fail) {
1114 ULOG_ERR("%d module%s could not be probed\n",
1115 fail, (fail == 1) ? ("") : ("s"));
1116
1117 avl_for_each_element(&modules, mn, avl) {
1118 if (mn->is_alias)
1119 continue;
1120 m = mn->m;
1121 if ((m->state == PROBE) || (m->error))
1122 ULOG_ERR("- %s - %d\n", m->name, deps_available(m, 1));
1123 }
1124 } else {
1125 ULOG_INFO("done loading kernel modules from %s\n", path);
1126 }
1127
1128 out:
1129 globfree(&gl);
1130 free_path:
1131 free(path);
1132
1133 return ret;
1134 }
1135
1136 static inline char weight(char c)
1137 {
1138 return c == '_' ? '-' : c;
1139 }
1140
1141 static int avl_modcmp(const void *k1, const void *k2, void *ptr)
1142 {
1143 const char *s1 = k1;
1144 const char *s2 = k2;
1145
1146 while (*s1 && (weight(*s1) == weight(*s2)))
1147 {
1148 s1++;
1149 s2++;
1150 }
1151
1152 return (unsigned char)weight(*s1) - (unsigned char)weight(*s2);
1153 }
1154
1155 static void
1156 load_options(void)
1157 {
1158 static char buf[512];
1159 char *s;
1160 FILE *f;
1161
1162 f = fopen("/etc/modules.conf", "r");
1163 if (!f)
1164 return;
1165
1166 while ((s = fgets(buf, sizeof(buf), f)) != NULL) {
1167 char *c, *cmd, *mod;
1168
1169 while (isspace(*s))
1170 s++;
1171
1172 c = strchr(s, '#');
1173 if (c)
1174 *c = 0;
1175
1176 while (isspace(*s))
1177 s++;
1178
1179 c = s + strlen(s);
1180 while (c > s && isspace(c[-1])) {
1181 c[-1] = 0;
1182 c--;
1183 }
1184
1185 cmd = strsep(&s, " \t");
1186 if (!cmd || !*cmd)
1187 continue;
1188
1189 while (isspace(*s))
1190 s++;
1191
1192 mod = strsep(&s, " \t");
1193 if (!mod || !*mod)
1194 continue;
1195
1196 if (!strcmp(cmd, "blacklist")) {
1197 kvlist_set(&options, mod, "\x01");
1198 continue;
1199 }
1200
1201 if (!strcmp(cmd, "options")) {
1202 char *prev = kvlist_get(&options, mod);
1203 char *val = NULL;
1204
1205 while (isspace(*s))
1206 s++;
1207
1208 if (!*s)
1209 continue;
1210
1211 if (prev && prev[0] == '\x01')
1212 continue;
1213
1214 if (!prev) {
1215 kvlist_set(&options, mod, s);
1216 continue;
1217 }
1218
1219 if (asprintf(&val, "%s %s", prev, s) < 0)
1220 continue;
1221
1222 kvlist_set(&options, mod, val);
1223 free(val);
1224 continue;
1225 }
1226 }
1227
1228 fclose(f);
1229 }
1230
1231 int main(int argc, char **argv)
1232 {
1233 char *exec = basename(*argv);
1234
1235 avl_init(&modules, avl_modcmp, false, NULL);
1236 if (!strcmp(exec, "insmod"))
1237 return main_insmod(argc, argv);
1238
1239 if (!strcmp(exec, "rmmod"))
1240 return main_rmmod(argc, argv);
1241
1242 if (!strcmp(exec, "lsmod"))
1243 return main_lsmod(argc, argv);
1244
1245 if (!strcmp(exec, "modinfo"))
1246 return main_modinfo(argc, argv);
1247
1248 load_options();
1249
1250 if (!strcmp(exec, "modprobe"))
1251 return main_modprobe(argc, argv);
1252
1253 ulog_open(ULOG_KMSG, LOG_USER, "kmodloader");
1254 return main_loader(argc, argv);
1255 }