kmodloader: added -a arg to modprobe
[oweals/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 }