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