• 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                 n->usage = m.usage;
340                 n->state = LOADED;
341         }
342         free(buf);
343         fclose(fp);
344 
345         return 0;
346 }
347 
348 static struct module* get_module_info(const char *module, const char *name)
349 {
350         int fd = open(module, O_RDONLY);
351         unsigned int offset, size;
352         char *map = MAP_FAILED, *strings, *dep = NULL;
353         const char **aliases = NULL;
354         int naliases = 0;
355         struct module *m = NULL;
356         struct stat s;
357 
358         if (fd < 0) {
359                 ULOG_ERR("failed to open %s\n", module);
360                 goto out;
361         }
362 
363         if (fstat(fd, &s) == -1) {
364                 ULOG_ERR("failed to stat %s\n", module);
365                 goto out;
366         }
367 
368         map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
369         if (map == MAP_FAILED) {
370                 ULOG_ERR("failed to mmap %s\n", module);
371                 goto out;
372         }
373 
374         if (elf_find_section(map, ".modinfo", &offset, &size)) {
375                 ULOG_ERR("failed to load the .modinfo section from %s\n", module);
376                 goto out;
377         }
378 
379         strings = map + offset;
380         while (true) {
381                 char *sep;
382                 int len;
383 
384                 while (!strings[0])
385                         strings++;
386                 if (strings >= map + offset + size)
387                         break;
388                 sep = strstr(strings, "=");
389                 if (!sep)
390                         break;
391                 len = sep - strings;
392                 sep++;
393                 if (!strncmp(strings, "depends=", len + 1))
394                         dep = sep;
395                 else if (!strncmp(strings, "alias=", len + 1)) {
396                         aliases = realloc(aliases, sizeof(sep) * (naliases + 1));
397                         if (!aliases) {
398                                 ULOG_ERR("out of memory\n");
399                                 goto out;
400                         }
401 
402                         aliases[naliases++] = sep;
403                 }
404                 strings = &sep[strlen(sep)];
405         }
406 
407         m = alloc_module(name, aliases, naliases, dep, s.st_size);
408 
409         if (m)
410                 m->state = SCANNED;
411 
412 out:
413         if (map != MAP_FAILED)
414                 munmap(map, s.st_size);
415 
416         if (fd >= 0)
417                 close(fd);
418 
419         free(aliases);
420 
421         return m;
422 }
423 
424 static int scan_module_folder(const char *dir)
425 {
426         int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
427         struct utsname ver;
428         char *path;
429         glob_t gl;
430         int j, rv = 0;
431 
432         uname(&ver);
433         path = alloca(strlen(dir) + sizeof("*.ko") + 1);
434         sprintf(path, "%s*.ko", dir);
435 
436         if (glob(path, gl_flags, NULL, &gl) < 0)
437                 return -1;
438 
439         for (j = 0; j < gl.gl_pathc; j++) {
440                 char *name = get_module_name(gl.gl_pathv[j]);
441                 struct module *m;
442                 char *opts;
443 
444                 if (!name)
445                         continue;
446 
447                 m = find_module(name);
448                 if (m)
449                         continue;
450 
451                 m = get_module_info(gl.gl_pathv[j], name);
452                 if (!m) {
453                         rv |= -1;
454                         continue;
455                 }
456 
457                 opts = kvlist_get(&options, name);
458                 if (!opts)
459                         continue;
460 
461                 if (*opts == '\x01')
462                         m->state = BLACKLISTED;
463                 else
464                         m->opts = strdup(opts);
465         }
466 
467         globfree(&gl);
468 
469         return rv;
470 }
471 
472 static int scan_module_folders(void)
473 {
474         int rv = 0;
475         char **p;
476 
477         if (init_module_folders())
478                 return -1;
479 
480         for (p = module_folders; *p; p++)
481                 rv |= scan_module_folder(*p);
482 
483         return rv;
484 }
485 
486 static int print_modinfo(char *module)
487 {
488         int fd = open(module, O_RDONLY);
489         unsigned int offset, size;
490         struct stat s;
491         char *map = MAP_FAILED, *strings;
492         int rv = -1;
493 
494         if (fd < 0) {
495                 ULOG_ERR("failed to open %s\n", module);
496                 goto out;
497         }
498 
499         if (fstat(fd, &s) == -1) {
500                 ULOG_ERR("failed to stat %s\n", module);
501                 goto out;
502         }
503 
504         map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
505         if (map == MAP_FAILED) {
506                 ULOG_ERR("failed to mmap %s\n", module);
507                 goto out;
508         }
509 
510         if (elf_find_section(map, ".modinfo", &offset, &size)) {
511                 ULOG_ERR("failed to load the .modinfo section from %s\n", module);
512                 goto out;
513         }
514 
515         strings = map + offset;
516         printf("module:\t\t%s\n", module);
517         while (true) {
518                 char *dup = NULL;
519                 char *sep;
520 
521                 while (!strings[0])
522                         strings++;
523                 if (strings >= map + offset + size)
524                         break;
525                 sep = strstr(strings, "=");
526                 if (!sep)
527                         break;
528                 dup = strndup(strings, sep - strings);
529                 sep++;
530                 if (strncmp(strings, "parm", 4)) {
531                         if (strlen(dup) < 7)
532                                 printf("%s:\t\t%s\n",  dup, sep);
533                         else
534                                 printf("%s:\t%s\n",  dup, sep);
535                 }
536                 strings = &sep[strlen(sep)];
537                 if (dup)
538                         free(dup);
539         }
540 
541         rv = 0;
542 
543 out:
544         if (map != MAP_FAILED)
545                 munmap(map, s.st_size);
546 
547         if (fd >= 0)
548                 close(fd);
549 
550         return rv;
551 }
552 
553 static int deps_available(struct module *m, int verbose)
554 {
555         char *dep;
556         int err = 0;
557 
558         if (!m->depends || !strcmp(m->depends, "-") || !strcmp(m->depends, ""))
559                 return 0;
560 
561         dep = m->depends;
562 
563         while (*dep) {
564                 m = find_module(dep);
565 
566                 if (verbose && !m)
567                         ULOG_ERR("missing dependency %s\n", dep);
568                 if (verbose && m && (m->state != LOADED))
569                         ULOG_ERR("dependency not loaded %s\n", dep);
570                 if (!m || (m->state != LOADED))
571                         err++;
572                 dep += strlen(dep) + 1;
573         }
574 
575         return err;
576 }
577 
578 static int insert_module(char *path, const char *options)
579 {
580         void *data = 0;
581         struct stat s;
582         int fd, ret = -1;
583 
584         if (stat(path, &s)) {
585                 ULOG_ERR("missing module %s\n", path);
586                 return ret;
587         }
588 
589         fd = open(path, O_RDONLY);
590         if (fd < 0) {
591                 ULOG_ERR("cannot open %s\n", path);
592                 return ret;
593         }
594 
595         data = malloc(s.st_size);
596         if (!data) {
597                 ULOG_ERR("out of memory\n");
598                 goto out;
599         }
600 
601         if (read(fd, data, s.st_size) == s.st_size) {
602                 ret = syscall(__NR_init_module, data, (unsigned long) s.st_size, options);
603                 if (errno == EEXIST)
604                         ret = 0;
605         }
606         else
607                 ULOG_ERR("failed to read full module %s\n", path);
608 
609 out:
610         close(fd);
611         free(data);
612 
613         return ret;
614 }
615 
616 static void load_moddeps(struct module *_m)
617 {
618         char *dep;
619         struct module *m;
620 
621         if (!strcmp(_m->depends, "-") || !strcmp(_m->depends, ""))
622                 return;
623 
624         dep = _m->depends;
625 
626         while (*dep) {
627                 m = find_module(dep);
628 
629                 if (!m)
630                         ULOG_ERR("failed to find dependency %s\n", dep);
631                 if (m && (m->state != LOADED)) {
632                         m->state = PROBE;
633                         load_moddeps(m);
634                 }
635 
636                 dep = dep + strlen(dep) + 1;
637         }
638 }
639 
640 static int load_modprobe(bool allow_load_retry)
641 {
642         int loaded, skipped, failed;
643         struct module_node *mn;
644         struct module *m;
645         bool load_retry = false;
646         static bool first_iteration = true;
647 
648         avl_for_each_element(&modules, mn, avl) {
649                 if (mn->is_alias)
650                         continue;
651                 m = mn->m;
652                 if (m->state == PROBE)
653                         load_moddeps(m);
654         }
655 
656         do {
657                 loaded = 0;
658                 skipped = 0;
659                 failed = 0;
660                 avl_for_each_element(&modules, mn, avl) {
661                         if (mn->is_alias)
662                                 continue;
663                         m = mn->m;
664                         if ((m->state == PROBE) && (!deps_available(m, 0)) && (!m->error || load_retry)) {
665                                 if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
666                                         m->state = LOADED;
667                                         m->error = 0;
668                                         loaded++;
669                                         continue;
670                                 }
671 
672                                 m->error = 1;
673                         }
674 
675                         if (m->error)
676                                 failed++;
677                         else if (m->state == PROBE)
678                                 skipped++;
679                 }
680 
681                 if (allow_load_retry) {
682                         /* if we can't load anything else let's try to load failed modules */
683                         load_retry = loaded ? (failed && !skipped) : (failed && !load_retry && !first_iteration);
684                 }
685 
686                 first_iteration = false;
687         } while (loaded || load_retry);
688 
689         return skipped + failed;
690 }
691 
692 static int print_insmod_usage(void)
693 {
694         ULOG_INFO("Usage:\n\tinsmod filename [args]\n");
695 
696         return -1;
697 }
698 
699 static int print_modprobe_usage(void)
700 {
701         ULOG_INFO(
702                 "Usage:\n"
703                 "\tmodprobe [-q] [-v] filename\n"
704                 "\tmodprobe -a [-q] [-v] filename [filename...]\n"
705         );
706 
707         return -1;
708 }
709 
710 static int print_usage(char *arg)
711 {
712         ULOG_INFO("Usage:\n\t%s module\n", arg);
713 
714         return -1;
715 }
716 
717 static int main_insmod(int argc, char **argv)
718 {
719         char *name, *cur, *options;
720         int i, ret, len;
721 
722         if (argc < 2)
723                 return print_insmod_usage();
724 
725         name = get_module_name(argv[1]);
726         if (!name) {
727                 ULOG_ERR("cannot find module - %s\n", argv[1]);
728                 return -1;
729         }
730 
731         if (scan_loaded_modules())
732                 return -1;
733 
734         if (find_module(name)) {
735                 ULOG_ERR("module is already loaded - %s\n", name);
736                 return -1;
737 
738         }
739 
740         free_modules();
741 
742         for (len = 0, i = 2; i < argc; i++)
743                 len += strlen(argv[i]) + 1;
744 
745         options = malloc(len);
746         if (!options) {
747                 ULOG_ERR("out of memory\n");
748                 ret = -1;
749                 goto err;
750         }
751 
752         options[0] = 0;
753         cur = options;
754         for (i = 2; i < argc; i++) {
755                 if (options[0]) {
756                         *cur = ' ';
757                         cur++;
758                 }
759                 cur += sprintf(cur, "%s", argv[i]);
760         }
761 
762         if (init_module_folders()) {
763                 fprintf(stderr, "Failed to find the folder holding the modules\n");
764                 ret = -1;
765                 goto err;
766         }
767 
768         if (get_module_path(argv[1])) {
769                 name = argv[1];
770         } else if (!get_module_path(name)) {
771                 fprintf(stderr, "Failed to find %s. Maybe it is a built in module ?\n", name);
772                 ret = -1;
773                 goto err;
774         }
775 
776         ret = insert_module(get_module_path(name), options);
777         if (ret)
778                 ULOG_ERR("failed to insert %s\n", get_module_path(name));
779 
780 err:
781         free(options);
782         return ret;
783 }
784 
785 static int main_rmmod(int argc, char **argv)
786 {
787         struct module *m;
788         char *name;
789         int ret;
790 
791         if (argc != 2)
792                 return print_usage("rmmod");
793 
794         if (scan_loaded_modules())
795                 return -1;
796 
797         name = get_module_name(argv[1]);
798         m = find_module(name);
799         if (!m) {
800                 ULOG_ERR("module is not loaded\n");
801                 return -1;
802         }
803         ret = syscall(__NR_delete_module, m->name, 0);
804 
805         if (ret)
806                 ULOG_ERR("unloading the module failed\n");
807 
808         free_modules();
809 
810         return ret;
811 }
812 
813 static int main_lsmod(int argc, char **argv)
814 {
815         struct module_node *mn;
816         struct module *m;
817         char *dep;
818 
819         if (scan_loaded_modules())
820                 return -1;
821 
822         avl_for_each_element(&modules, mn, avl) {
823                 if (mn->is_alias)
824                         continue;
825                 m = mn->m;
826                 if (m->state == LOADED) {
827                         printf("%-20s%8d%3d ",
828                                 m->name, m->size, m->usage);
829                         if (m->depends && strcmp(m->depends, "-") && strcmp(m->depends, "")) {
830                                 dep = m->depends;
831                                 while (*dep) {
832                                         printf("%s", dep);
833                                         dep = dep + strlen(dep) + 1;
834                                         if (*dep)
835                                                 printf(",");
836                                 }
837                         }
838                         printf("\n");
839                 }
840         }
841 
842         free_modules();
843 
844         return 0;
845 }
846 
847 static int main_modinfo(int argc, char **argv)
848 {
849         struct module *m;
850         char *name;
851 
852         if (argc != 2)
853                 return print_usage("modinfo");
854 
855         if (scan_module_folders())
856                 return -1;
857 
858         name = get_module_name(argv[1]);
859         m = find_module(name);
860         if (!m) {
861                 ULOG_ERR("cannot find module - %s\n", argv[1]);
862                 return -1;
863         }
864 
865         name = get_module_path(m->name);
866         if (!name) {
867                 ULOG_ERR("cannot find path of module - %s\n", m->name);
868                 return -1;
869         }
870 
871         print_modinfo(name);
872 
873         return 0;
874 }
875 
876 static int main_modprobe(int argc, char **argv)
877 {
878         struct module_node *mn;
879         struct module *m;
880         int exit_code = 0;
881         int load_fail;
882         int log_level = LOG_WARNING;
883         int opt;
884         bool quiet = false;
885         bool use_all = false;
886 
887         while ((opt = getopt(argc, argv, "aqv")) != -1 ) {
888                 switch (opt) {
889                         case 'a':
890                                 use_all = true;
891                                 break;
892                         case 'q': /* shhhh! */
893                                 quiet = true;
894                                 break;
895                         case 'v':
896                                 log_level = LOG_DEBUG;
897                                 break;
898                         default: /* '?' */
899                                 return print_modprobe_usage();
900                                 break;
901                         }
902         }
903 
904         if (optind >= argc)
905                 return print_modprobe_usage(); /* expected module after options */
906 
907         /* after print_modprobe_usage() so it won't be filtered out */
908         ulog_threshold(log_level);
909 
910         if (scan_module_folders())
911                 return -1;
912 
913         if (scan_loaded_modules())
914                 return -1;
915 
916         do {
917                 char *name;
918 
919                 name = get_module_name(argv[optind]);
920                 m = find_module(name);
921 
922                 if (m && m->state == BLACKLISTED) {
923                         if (!quiet)
924                                 ULOG_INFO("%s is blacklisted\n", name);
925                 } else if (m && m->state == LOADED) {
926                         if (!quiet)
927                                 ULOG_INFO("%s is already loaded\n", name);
928                 } else if (!m) {
929                         if (!quiet)
930                                 ULOG_ERR("failed to find a module named %s\n", name);
931                         exit_code = -1;
932                 } else {
933                         m->state = PROBE;
934                 }
935 
936                 optind++;
937         } while (use_all && optind < argc);
938 
939         load_fail = load_modprobe(true);
940         if (load_fail) {
941                 ULOG_ERR("%d module%s could not be probed\n",
942                          load_fail, (load_fail == 1) ? ("") : ("s"));
943 
944                 avl_for_each_element(&modules, mn, avl) {
945                         if (mn->is_alias)
946                                 continue;
947                         m = mn->m;
948                         if ((m->state == PROBE) || m->error)
949                                 ULOG_ERR("- %s\n", m->name);
950                 }
951 
952                 exit_code = -1;
953         }
954 
955         free_modules();
956 
957         return exit_code;
958 }
959 
960 static int main_loader(int argc, char **argv)
961 {
962         int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
963         char *dir = "/etc/modules.d/";
964         struct module_node *mn;
965         struct module *m;
966         glob_t gl;
967         char *path;
968         int fail, j;
969 
970         if (argc > 1)
971                 dir = argv[1];
972 
973         path = malloc(strlen(dir) + 2);
974         if (!path) {
975                 ULOG_ERR("out of memory\n");
976                 return -1;
977         }
978 
979         strcpy(path, dir);
980         strcat(path, "*");
981 
982         if (scan_module_folders()) {
983                 free (path);
984                 return -1;
985         }
986 
987         if (scan_loaded_modules()) {
988                 free (path);
989                 return -1;
990         }
991 
992         ULOG_INFO("loading kernel modules from %s\n", path);
993 
994         if (glob(path, gl_flags, NULL, &gl) < 0)
995                 goto out;
996 
997         for (j = 0; j < gl.gl_pathc; j++) {
998                 FILE *fp = fopen(gl.gl_pathv[j], "r");
999                 size_t mod_len = 0;
1000                 char *mod = NULL;
1001 
1002                 if (!fp) {
1003                         ULOG_ERR("failed to open %s\n", gl.gl_pathv[j]);
1004                         continue;
1005                 }
1006 
1007                 while (getline(&mod, &mod_len, fp) > 0) {
1008                         char *nl = strchr(mod, '\n');
1009                         struct module *m;
1010                         char *opts;
1011 
1012                         if (nl)
1013                                 *nl = '\0';
1014 
1015                         opts = strchr(mod, ' ');
1016                         if (opts)
1017                                 *opts++ = '\0';
1018 
1019                         m = find_module(get_module_name(mod));
1020                         if (!m || m->state == LOADED || m->state == BLACKLISTED)
1021                                 continue;
1022 
1023                         if (opts) {
1024                                 if (m->opts) {
1025                                         char *prev = m->opts;
1026 
1027                                         asprintf(&m->opts, "%s %s", prev, opts);
1028                                         free(prev);
1029                                 } else {
1030                                         m->opts = strdup(opts);
1031                                 }
1032                         }
1033                         m->state = PROBE;
1034                         if (basename(gl.gl_pathv[j])[0] - '' <= 9)
1035                                 load_modprobe(false);
1036 
1037                 }
1038                 free(mod);
1039                 fclose(fp);
1040         }
1041 
1042         fail = load_modprobe(true);
1043 
1044         if (fail) {
1045                 ULOG_ERR("%d module%s could not be probed\n",
1046                          fail, (fail == 1) ? ("") : ("s"));
1047 
1048                 avl_for_each_element(&modules, mn, avl) {
1049                         if (mn->is_alias)
1050                                 continue;
1051                         m = mn->m;
1052                         if ((m->state == PROBE) || (m->error))
1053                                 ULOG_ERR("- %s - %d\n", m->name, deps_available(m, 1));
1054                 }
1055         } else {
1056                 ULOG_INFO("done loading kernel modules from %s\n", path);
1057         }
1058 
1059 out:
1060         globfree(&gl);
1061         free(path);
1062 
1063         return 0;
1064 }
1065 
1066 static inline char weight(char c)
1067 {
1068         return c == '_' ? '-' : c;
1069 }
1070 
1071 static int avl_modcmp(const void *k1, const void *k2, void *ptr)
1072 {
1073         const char *s1 = k1;
1074         const char *s2 = k2;
1075 
1076         while (*s1 && (weight(*s1) == weight(*s2)))
1077         {
1078                 s1++;
1079                 s2++;
1080         }
1081 
1082         return (unsigned char)weight(*s1) - (unsigned char)weight(*s2);
1083 }
1084 
1085 static void
1086 load_options(void)
1087 {
1088         static char buf[512];
1089         char *s;
1090         FILE *f;
1091 
1092         f = fopen("/etc/modules.conf", "r");
1093         if (!f)
1094                 return;
1095 
1096         while ((s = fgets(buf, sizeof(buf), f)) != NULL) {
1097                 char *c, *cmd, *mod;
1098 
1099                 while (isspace(*s))
1100                         s++;
1101 
1102                 c = strchr(s, '#');
1103                 if (c)
1104                         *c = 0;
1105 
1106                 while (isspace(*s))
1107                         s++;
1108 
1109                 c = s + strlen(s);
1110                 while (c > s && isspace(c[-1])) {
1111                         c[-1] = 0;
1112                         c--;
1113                 }
1114 
1115                 cmd = strsep(&s, " \t");
1116                 if (!cmd || !*cmd)
1117                         continue;
1118 
1119                 while (isspace(*s))
1120                         s++;
1121 
1122                 mod = strsep(&s, " \t");
1123                 if (!mod || !*mod)
1124                         continue;
1125 
1126                 if (!strcmp(cmd, "blacklist")) {
1127                         kvlist_set(&options, mod, "\x01");
1128                         continue;
1129                 }
1130 
1131                 if (!strcmp(cmd, "options")) {
1132                         char *prev = kvlist_get(&options, mod);
1133                         char *val = NULL;
1134 
1135                         while (isspace(*s))
1136                                 s++;
1137 
1138                         if (!*s)
1139                                 continue;
1140 
1141                         if (prev && prev[0] == '\x01')
1142                                 continue;
1143 
1144                         if (!prev) {
1145                                 kvlist_set(&options, mod, s);
1146                                 continue;
1147                         }
1148 
1149                         if (asprintf(&val, "%s %s", prev, s) < 0)
1150                                 continue;
1151 
1152                         kvlist_set(&options, mod, val);
1153                         free(val);
1154                         continue;
1155                 }
1156         }
1157 }
1158 
1159 int main(int argc, char **argv)
1160 {
1161         char *exec = basename(*argv);
1162 
1163         avl_init(&modules, avl_modcmp, false, NULL);
1164         if (!strcmp(exec, "insmod"))
1165                 return main_insmod(argc, argv);
1166 
1167         if (!strcmp(exec, "rmmod"))
1168                 return main_rmmod(argc, argv);
1169 
1170         if (!strcmp(exec, "lsmod"))
1171                 return main_lsmod(argc, argv);
1172 
1173         if (!strcmp(exec, "modinfo"))
1174                 return main_modinfo(argc, argv);
1175 
1176         load_options();
1177 
1178         if (!strcmp(exec, "modprobe"))
1179                 return main_modprobe(argc, argv);
1180 
1181         ulog_open(ULOG_KMSG, LOG_USER, "kmodloader");
1182         return main_loader(argc, argv);
1183 }
1184 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt