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