• source navigation  • diff markup  • identifier search  • freetext search  • 

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt