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