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