0afc79560693e9a67bf0ca74a0dfd934b5387e75
[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 int rv = -1;
315 FILE *fp;
316
317 fp = fopen("/proc/modules", "r");
318 if (!fp) {
319 ULOG_ERR("failed to open /proc/modules\n");
320 goto out;
321 }
322
323 while (getline(&buf, &buf_len, fp) > 0) {
324 struct module m;
325 struct module *n;
326
327 m.name = strtok(buf, " ");
328 m.size = atoi(strtok(NULL, " "));
329 m.usage = atoi(strtok(NULL, " "));
330 m.depends = strtok(NULL, " ");
331
332 if (!m.name || !m.depends)
333 continue;
334
335 n = find_module(m.name);
336 if (!n) {
337 /* possibly a module outside /lib/modules/<ver>/ */
338 n = alloc_module(m.name, NULL, 0, m.depends, m.size);
339 }
340 if (!n) {
341 ULOG_ERR("Failed to allocate memory for module\n");
342 goto out;
343 }
344
345 n->usage = m.usage;
346 n->state = LOADED;
347 }
348 rv = 0;
349 out:
350 free(buf);
351 fclose(fp);
352
353 return rv;
354 }
355
356 static struct module* get_module_info(const char *module, const char *name)
357 {
358 int fd = open(module, O_RDONLY);
359 unsigned int offset, size;
360 char *map = MAP_FAILED, *strings, *dep = NULL;
361 const char **aliases = NULL;
362 const char **aliasesr;
363 int naliases = 0;
364 struct module *m = NULL;
365 struct stat s;
366
367 if (fd < 0) {
368 ULOG_ERR("failed to open %s\n", module);
369 goto out;
370 }
371
372 if (fstat(fd, &s) == -1) {
373 ULOG_ERR("failed to stat %s\n", module);
374 goto out;
375 }
376
377 map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
378 if (map == MAP_FAILED) {
379 ULOG_ERR("failed to mmap %s\n", module);
380 goto out;
381 }
382
383 if (elf_find_section(map, ".modinfo", &offset, &size)) {
384 ULOG_ERR("failed to load the .modinfo section from %s\n", module);
385 goto out;
386 }
387
388 strings = map + offset;
389 while (true) {
390 char *sep;
391 int len;
392
393 while (!strings[0])
394 strings++;
395 if (strings >= map + offset + size)
396 break;
397 sep = strstr(strings, "=");
398 if (!sep)
399 break;
400 len = sep - strings;
401 sep++;
402 if (!strncmp(strings, "depends=", len + 1))
403 dep = sep;
404 else if (!strncmp(strings, "alias=", len + 1)) {
405 aliasesr = realloc(aliases, sizeof(sep) * (naliases + 1));
406 if (!aliasesr) {
407 ULOG_ERR("out of memory\n");
408 goto out;
409 }
410
411 aliases = aliasesr;
412 aliases[naliases++] = sep;
413 }
414 strings = &sep[strlen(sep)];
415 }
416
417 m = alloc_module(name, aliases, naliases, dep, s.st_size);
418
419 if (m)
420 m->state = SCANNED;
421
422 out:
423 if (map != MAP_FAILED)
424 munmap(map, s.st_size);
425
426 if (fd >= 0)
427 close(fd);
428
429 free(aliases);
430
431 return m;
432 }
433
434 static int scan_module_folder(const char *dir)
435 {
436 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
437 char *path;
438 glob_t gl;
439 int j, rv = 0;
440
441 path = alloca(strlen(dir) + sizeof("*.ko") + 1);
442 sprintf(path, "%s*.ko", dir);
443
444 if (glob(path, gl_flags, NULL, &gl) < 0)
445 return -1;
446
447 for (j = 0; j < gl.gl_pathc; j++) {
448 char *name = get_module_name(gl.gl_pathv[j]);
449 struct module *m;
450 char *opts;
451
452 if (!name)
453 continue;
454
455 m = find_module(name);
456 if (m)
457 continue;
458
459 m = get_module_info(gl.gl_pathv[j], name);
460 if (!m) {
461 rv |= -1;
462 continue;
463 }
464
465 opts = kvlist_get(&options, name);
466 if (!opts)
467 continue;
468
469 if (*opts == '\x01')
470 m->state = BLACKLISTED;
471 else
472 m->opts = strdup(opts);
473 }
474
475 globfree(&gl);
476
477 return rv;
478 }
479
480 static int scan_module_folders(void)
481 {
482 int rv = 0;
483 char **p;
484
485 if (init_module_folders())
486 return -1;
487
488 for (p = module_folders; *p; p++)
489 rv |= scan_module_folder(*p);
490
491 return rv;
492 }
493
494 static int print_modinfo(char *module)
495 {
496 int fd = open(module, O_RDONLY);
497 unsigned int offset, size;
498 struct stat s;
499 char *map = MAP_FAILED, *strings;
500 int rv = -1;
501
502 if (fd < 0) {
503 ULOG_ERR("failed to open %s\n", module);
504 goto out;
505 }
506
507 if (fstat(fd, &s) == -1) {
508 ULOG_ERR("failed to stat %s\n", module);
509 goto out;
510 }
511
512 map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
513 if (map == MAP_FAILED) {
514 ULOG_ERR("failed to mmap %s\n", module);
515 goto out;
516 }
517
518 if (elf_find_section(map, ".modinfo", &offset, &size)) {
519 ULOG_ERR("failed to load the .modinfo section from %s\n", module);
520 goto out;
521 }
522
523 strings = map + offset;
524 printf("module:\t\t%s\n", module);
525 while (true) {
526 char *dup = NULL;
527 char *sep;
528
529 while (!strings[0])
530 strings++;
531 if (strings >= map + offset + size)
532 break;
533 sep = strstr(strings, "=");
534 if (!sep)
535 break;
536 dup = strndup(strings, sep - strings);
537 sep++;
538 if (strncmp(strings, "parm", 4)) {
539 if (strlen(dup) < 7)
540 printf("%s:\t\t%s\n", dup, sep);
541 else
542 printf("%s:\t%s\n", dup, sep);
543 }
544 strings = &sep[strlen(sep)];
545 if (dup)
546 free(dup);
547 }
548
549 rv = 0;
550
551 out:
552 if (map != MAP_FAILED)
553 munmap(map, s.st_size);
554
555 if (fd >= 0)
556 close(fd);
557
558 return rv;
559 }
560
561 static int deps_available(struct module *m, int verbose)
562 {
563 char *dep;
564 int err = 0;
565
566 if (!m->depends || !strcmp(m->depends, "-") || !strcmp(m->depends, ""))
567 return 0;
568
569 dep = m->depends;
570
571 while (*dep) {
572 m = find_module(dep);
573
574 if (verbose && !m)
575 ULOG_ERR("missing dependency %s\n", dep);
576 if (verbose && m && (m->state != LOADED))
577 ULOG_ERR("dependency not loaded %s\n", dep);
578 if (!m || (m->state != LOADED))
579 err++;
580 dep += strlen(dep) + 1;
581 }
582
583 return err;
584 }
585
586 static int insert_module(char *path, const char *options)
587 {
588 void *data = 0;
589 struct stat s;
590 int fd, ret = -1;
591
592 if (!path) {
593 ULOG_ERR("Path not specified\n");
594 return ret;
595 }
596
597 if (stat(path, &s)) {
598 ULOG_ERR("missing module %s\n", path);
599 return ret;
600 }
601
602 fd = open(path, O_RDONLY);
603 if (fd < 0) {
604 ULOG_ERR("cannot open %s\n", path);
605 return ret;
606 }
607
608 data = malloc(s.st_size);
609 if (!data) {
610 ULOG_ERR("out of memory\n");
611 goto out;
612 }
613
614 if (read(fd, data, s.st_size) == s.st_size) {
615 ret = syscall(__NR_init_module, data, (unsigned long) s.st_size, options);
616 if (errno == EEXIST)
617 ret = 0;
618 }
619 else
620 ULOG_ERR("failed to read full module %s\n", path);
621
622 out:
623 close(fd);
624 free(data);
625
626 return ret;
627 }
628
629 static void load_moddeps(struct module *_m)
630 {
631 char *dep;
632 struct module *m;
633
634 if (!strcmp(_m->depends, "-") || !strcmp(_m->depends, ""))
635 return;
636
637 dep = _m->depends;
638
639 while (*dep) {
640 m = find_module(dep);
641
642 if (!m)
643 ULOG_ERR("failed to find dependency %s\n", dep);
644 if (m && (m->state != LOADED)) {
645 m->state = PROBE;
646 load_moddeps(m);
647 }
648
649 dep = dep + strlen(dep) + 1;
650 }
651 }
652
653 static int load_modprobe(bool allow_load_retry)
654 {
655 int loaded, skipped, failed;
656 struct module_node *mn;
657 struct module *m;
658 bool load_retry = false;
659 static bool first_iteration = true;
660
661 avl_for_each_element(&modules, mn, avl) {
662 if (mn->is_alias)
663 continue;
664 m = mn->m;
665 if (m->state == PROBE)
666 load_moddeps(m);
667 }
668
669 do {
670 loaded = 0;
671 skipped = 0;
672 failed = 0;
673 avl_for_each_element(&modules, mn, avl) {
674 if (mn->is_alias)
675 continue;
676 m = mn->m;
677 if ((m->state == PROBE) && (!deps_available(m, 0)) && (!m->error || load_retry)) {
678 if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
679 m->state = LOADED;
680 m->error = 0;
681 loaded++;
682 continue;
683 }
684
685 m->error = 1;
686 }
687
688 if (m->error)
689 failed++;
690 else if (m->state == PROBE)
691 skipped++;
692 }
693
694 if (allow_load_retry) {
695 /* if we can't load anything else let's try to load failed modules */
696 load_retry = loaded ? (failed && !skipped) : (failed && !load_retry && !first_iteration);
697 }
698
699 first_iteration = false;
700 } while (loaded || load_retry);
701
702 return skipped + failed;
703 }
704
705 static int print_insmod_usage(void)
706 {
707 ULOG_INFO("Usage:\n\tinsmod filename [args]\n");
708
709 return -1;
710 }
711
712 static int print_modprobe_usage(void)
713 {
714 ULOG_INFO(
715 "Usage:\n"
716 "\tmodprobe [-q] [-v] filename\n"
717 "\tmodprobe -a [-q] [-v] filename [filename...]\n"
718 );
719
720 return -1;
721 }
722
723 static int print_usage(char *arg)
724 {
725 ULOG_INFO("Usage:\n\t%s module\n", arg);
726
727 return -1;
728 }
729
730 static int main_insmod(int argc, char **argv)
731 {
732 char *name, *cur, *options;
733 int i, ret, len;
734
735 if (argc < 2)
736 return print_insmod_usage();
737
738 name = get_module_name(argv[1]);
739 if (!name) {
740 ULOG_ERR("cannot find module - %s\n", argv[1]);
741 return -1;
742 }
743
744 if (scan_loaded_modules())
745 return -1;
746
747 if (find_module(name)) {
748 ULOG_ERR("module is already loaded - %s\n", name);
749 return -1;
750
751 }
752
753 free_modules();
754
755 for (len = 0, i = 2; i < argc; i++)
756 len += strlen(argv[i]) + 1;
757
758 options = malloc(len);
759 if (!options) {
760 ULOG_ERR("out of memory\n");
761 ret = -1;
762 goto err;
763 }
764
765 options[0] = 0;
766 cur = options;
767 for (i = 2; i < argc; i++) {
768 if (options[0]) {
769 *cur = ' ';
770 cur++;
771 }
772 cur += sprintf(cur, "%s", argv[i]);
773 }
774
775 if (init_module_folders()) {
776 fprintf(stderr, "Failed to find the folder holding the modules\n");
777 ret = -1;
778 goto err;
779 }
780
781 if (get_module_path(argv[1])) {
782 name = argv[1];
783 } else if (!get_module_path(name)) {
784 fprintf(stderr, "Failed to find %s. Maybe it is a built in module ?\n", name);
785 ret = -1;
786 goto err;
787 }
788
789 ret = insert_module(get_module_path(name), options);
790 if (ret)
791 ULOG_ERR("failed to insert %s\n", get_module_path(name));
792
793 err:
794 free(options);
795 return ret;
796 }
797
798 static int main_rmmod(int argc, char **argv)
799 {
800 struct module *m;
801 char *name;
802 int ret;
803
804 if (argc != 2)
805 return print_usage("rmmod");
806
807 if (scan_loaded_modules())
808 return -1;
809
810 name = get_module_name(argv[1]);
811 m = find_module(name);
812 if (!m) {
813 ULOG_ERR("module is not loaded\n");
814 return -1;
815 }
816 ret = syscall(__NR_delete_module, m->name, 0);
817
818 if (ret)
819 ULOG_ERR("unloading the module failed\n");
820
821 free_modules();
822
823 return ret;
824 }
825
826 static int main_lsmod(int argc, char **argv)
827 {
828 struct module_node *mn;
829 struct module *m;
830 char *dep;
831
832 if (scan_loaded_modules())
833 return -1;
834
835 avl_for_each_element(&modules, mn, avl) {
836 if (mn->is_alias)
837 continue;
838 m = mn->m;
839 if (m->state == LOADED) {
840 printf("%-20s%8d%3d ",
841 m->name, m->size, m->usage);
842 if (m->depends && strcmp(m->depends, "-") && strcmp(m->depends, "")) {
843 dep = m->depends;
844 while (*dep) {
845 printf("%s", dep);
846 dep = dep + strlen(dep) + 1;
847 if (*dep)
848 printf(",");
849 }
850 }
851 printf("\n");
852 }
853 }
854
855 free_modules();
856
857 return 0;
858 }
859
860 static int main_modinfo(int argc, char **argv)
861 {
862 struct module *m;
863 char *name;
864
865 if (argc != 2)
866 return print_usage("modinfo");
867
868 if (scan_module_folders())
869 return -1;
870
871 name = get_module_name(argv[1]);
872 m = find_module(name);
873 if (!m) {
874 ULOG_ERR("cannot find module - %s\n", argv[1]);
875 return -1;
876 }
877
878 name = get_module_path(m->name);
879 if (!name) {
880 ULOG_ERR("cannot find path of module - %s\n", m->name);
881 return -1;
882 }
883
884 print_modinfo(name);
885
886 return 0;
887 }
888
889 static int main_modprobe(int argc, char **argv)
890 {
891 struct module_node *mn;
892 struct module *m;
893 int exit_code = 0;
894 int load_fail;
895 int log_level = LOG_WARNING;
896 int opt;
897 bool quiet = false;
898 bool use_all = false;
899
900 while ((opt = getopt(argc, argv, "aqv")) != -1 ) {
901 switch (opt) {
902 case 'a':
903 use_all = true;
904 break;
905 case 'q': /* shhhh! */
906 quiet = true;
907 break;
908 case 'v':
909 log_level = LOG_DEBUG;
910 break;
911 default: /* '?' */
912 return print_modprobe_usage();
913 break;
914 }
915 }
916
917 if (optind >= argc)
918 return print_modprobe_usage(); /* expected module after options */
919
920 /* after print_modprobe_usage() so it won't be filtered out */
921 ulog_threshold(log_level);
922
923 if (scan_module_folders())
924 return -1;
925
926 if (scan_loaded_modules())
927 return -1;
928
929 do {
930 char *name;
931
932 name = get_module_name(argv[optind]);
933 m = find_module(name);
934
935 if (m && m->state == BLACKLISTED) {
936 if (!quiet)
937 ULOG_INFO("%s is blacklisted\n", name);
938 } else if (m && m->state == LOADED) {
939 if (!quiet)
940 ULOG_INFO("%s is already loaded\n", name);
941 } else if (!m) {
942 if (!quiet)
943 ULOG_ERR("failed to find a module named %s\n", name);
944 exit_code = -1;
945 } else {
946 m->state = PROBE;
947 }
948
949 optind++;
950 } while (use_all && optind < argc);
951
952 load_fail = load_modprobe(true);
953 if (load_fail) {
954 ULOG_ERR("%d module%s could not be probed\n",
955 load_fail, (load_fail == 1) ? ("") : ("s"));
956
957 avl_for_each_element(&modules, mn, avl) {
958 if (mn->is_alias)
959 continue;
960 m = mn->m;
961 if ((m->state == PROBE) || m->error)
962 ULOG_ERR("- %s\n", m->name);
963 }
964
965 exit_code = -1;
966 }
967
968 free_modules();
969
970 return exit_code;
971 }
972
973 static int main_loader(int argc, char **argv)
974 {
975 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
976 char *dir = "/etc/modules.d/";
977 struct module_node *mn;
978 struct module *m;
979 glob_t gl;
980 char *path;
981 int ret = 0, fail, j;
982
983 if (argc > 1)
984 dir = argv[1];
985
986 path = malloc(strlen(dir) + 2);
987 if (!path) {
988 ULOG_ERR("out of memory\n");
989 return -1;
990 }
991
992 strcpy(path, dir);
993 strcat(path, "*");
994
995 if (scan_module_folders()) {
996 ret = -1;
997 goto free_path;
998 }
999
1000 if (scan_loaded_modules()) {
1001 ret = -1;
1002 goto free_path;
1003 }
1004
1005 ULOG_INFO("loading kernel modules from %s\n", path);
1006
1007 if (glob(path, gl_flags, NULL, &gl) < 0)
1008 goto out;
1009
1010 for (j = 0; j < gl.gl_pathc; j++) {
1011 FILE *fp = fopen(gl.gl_pathv[j], "r");
1012 size_t mod_len = 0;
1013 char *mod = NULL;
1014
1015 if (!fp) {
1016 ULOG_ERR("failed to open %s\n", gl.gl_pathv[j]);
1017 continue;
1018 }
1019
1020 while (getline(&mod, &mod_len, fp) > 0) {
1021 char *nl = strchr(mod, '\n');
1022 struct module *m;
1023 char *opts;
1024
1025 if (nl)
1026 *nl = '\0';
1027
1028 opts = strchr(mod, ' ');
1029 if (opts)
1030 *opts++ = '\0';
1031
1032 m = find_module(get_module_name(mod));
1033 if (!m || m->state == LOADED || m->state == BLACKLISTED)
1034 continue;
1035
1036 if (opts) {
1037 if (m->opts) {
1038 char *prev = m->opts;
1039
1040 fail = asprintf(&m->opts, "%s %s", prev, opts);
1041 free(prev);
1042 if (fail < 0) {
1043 ULOG_ERR("out of memory for opts %s\n", opts);
1044 free(mod);
1045 fclose(fp);
1046 ret = -1;
1047 goto out;
1048 }
1049 } else {
1050 m->opts = strdup(opts);
1051 }
1052 }
1053 m->state = PROBE;
1054 if (basename(gl.gl_pathv[j])[0] - '0' <= 9)
1055 load_modprobe(false);
1056
1057 }
1058 free(mod);
1059 fclose(fp);
1060 }
1061
1062 fail = load_modprobe(true);
1063
1064 if (fail) {
1065 ULOG_ERR("%d module%s could not be probed\n",
1066 fail, (fail == 1) ? ("") : ("s"));
1067
1068 avl_for_each_element(&modules, mn, avl) {
1069 if (mn->is_alias)
1070 continue;
1071 m = mn->m;
1072 if ((m->state == PROBE) || (m->error))
1073 ULOG_ERR("- %s - %d\n", m->name, deps_available(m, 1));
1074 }
1075 } else {
1076 ULOG_INFO("done loading kernel modules from %s\n", path);
1077 }
1078
1079 out:
1080 globfree(&gl);
1081 free_path:
1082 free(path);
1083
1084 return ret;
1085 }
1086
1087 static inline char weight(char c)
1088 {
1089 return c == '_' ? '-' : c;
1090 }
1091
1092 static int avl_modcmp(const void *k1, const void *k2, void *ptr)
1093 {
1094 const char *s1 = k1;
1095 const char *s2 = k2;
1096
1097 while (*s1 && (weight(*s1) == weight(*s2)))
1098 {
1099 s1++;
1100 s2++;
1101 }
1102
1103 return (unsigned char)weight(*s1) - (unsigned char)weight(*s2);
1104 }
1105
1106 static void
1107 load_options(void)
1108 {
1109 static char buf[512];
1110 char *s;
1111 FILE *f;
1112
1113 f = fopen("/etc/modules.conf", "r");
1114 if (!f)
1115 return;
1116
1117 while ((s = fgets(buf, sizeof(buf), f)) != NULL) {
1118 char *c, *cmd, *mod;
1119
1120 while (isspace(*s))
1121 s++;
1122
1123 c = strchr(s, '#');
1124 if (c)
1125 *c = 0;
1126
1127 while (isspace(*s))
1128 s++;
1129
1130 c = s + strlen(s);
1131 while (c > s && isspace(c[-1])) {
1132 c[-1] = 0;
1133 c--;
1134 }
1135
1136 cmd = strsep(&s, " \t");
1137 if (!cmd || !*cmd)
1138 continue;
1139
1140 while (isspace(*s))
1141 s++;
1142
1143 mod = strsep(&s, " \t");
1144 if (!mod || !*mod)
1145 continue;
1146
1147 if (!strcmp(cmd, "blacklist")) {
1148 kvlist_set(&options, mod, "\x01");
1149 continue;
1150 }
1151
1152 if (!strcmp(cmd, "options")) {
1153 char *prev = kvlist_get(&options, mod);
1154 char *val = NULL;
1155
1156 while (isspace(*s))
1157 s++;
1158
1159 if (!*s)
1160 continue;
1161
1162 if (prev && prev[0] == '\x01')
1163 continue;
1164
1165 if (!prev) {
1166 kvlist_set(&options, mod, s);
1167 continue;
1168 }
1169
1170 if (asprintf(&val, "%s %s", prev, s) < 0)
1171 continue;
1172
1173 kvlist_set(&options, mod, val);
1174 free(val);
1175 continue;
1176 }
1177 }
1178
1179 fclose(f);
1180 }
1181
1182 int main(int argc, char **argv)
1183 {
1184 char *exec = basename(*argv);
1185
1186 avl_init(&modules, avl_modcmp, false, NULL);
1187 if (!strcmp(exec, "insmod"))
1188 return main_insmod(argc, argv);
1189
1190 if (!strcmp(exec, "rmmod"))
1191 return main_rmmod(argc, argv);
1192
1193 if (!strcmp(exec, "lsmod"))
1194 return main_lsmod(argc, argv);
1195
1196 if (!strcmp(exec, "modinfo"))
1197 return main_modinfo(argc, argv);
1198
1199 load_options();
1200
1201 if (!strcmp(exec, "modprobe"))
1202 return main_modprobe(argc, argv);
1203
1204 ulog_open(ULOG_KMSG, LOG_USER, "kmodloader");
1205 return main_loader(argc, argv);
1206 }