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