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