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