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