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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt