Use different loglevels
[project/ubox.git] / kmodloader.c
1 /*
2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15 #define _GNU_SOURCE
16 #include <sys/syscall.h>
17 #include <sys/mman.h>
18 #include <sys/utsname.h>
19
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/syscall.h>
23 #include <sys/types.h>
24 #include <values.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <syslog.h>
31 #include <libgen.h>
32 #include <glob.h>
33 #include <elf.h>
34
35 #include <libubox/avl.h>
36 #include <libubox/avl-cmp.h>
37 #include <libubox/utils.h>
38
39 #define DEF_MOD_PATH "/lib/modules/%s/"
40
41 #define INFO(fmt, ...) do { \
42 syslog(LOG_INFO, fmt, ## __VA_ARGS__); \
43 printf("kmod: "fmt, ## __VA_ARGS__); \
44 } while (0)
45 #define ERROR(fmt, ...) do { \
46 syslog(LOG_ERR, fmt, ## __VA_ARGS__); \
47 fprintf(stderr,"kmod: "fmt, ## __VA_ARGS__); \
48 } while (0)
49 #define DEBUG(fmt, ...) do { \
50 syslog(LOG_DEBUG, fmt, ## __VA_ARGS__); \
51 } while (0)
52
53
54 enum {
55 SCANNED,
56 PROBE,
57 LOADED,
58 };
59
60 struct module {
61 struct avl_node avl;
62
63 char *name;
64 char *depends;
65 char *opts;
66
67 int size;
68 int usage;
69 int state;
70 int error;
71 };
72
73 static struct avl_tree modules;
74 static char *prefix = "";
75
76 static struct module *find_module(const char *name)
77 {
78 struct module *m;
79 return avl_find_element(&modules, name, m, avl);
80 }
81
82 static void free_modules(void)
83 {
84 struct module *m, *tmp;
85
86 avl_remove_all_elements(&modules, m, avl, tmp)
87 free(m);
88 }
89
90 static char* get_module_path(char *name)
91 {
92 static char path[256];
93 struct utsname ver;
94 struct stat s;
95
96 if (!stat(name, &s))
97 return name;
98
99 uname(&ver);
100 snprintf(path, 256, "%s" DEF_MOD_PATH "%s.ko", prefix, ver.release, name);
101
102 if (!stat(path, &s))
103 return path;
104
105 return NULL;
106 }
107
108 static char* get_module_name(char *path)
109 {
110 static char name[32];
111 char *t;
112
113 strncpy(name, basename(path), sizeof(name));
114
115 t = strstr(name, ".ko");
116 if (t)
117 *t = '\0';
118
119 return name;
120 }
121
122 static int elf64_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
123 {
124 const char *secnames;
125 Elf64_Ehdr *e;
126 Elf64_Shdr *sh;
127 int i;
128
129 e = (Elf64_Ehdr *) map;
130 sh = (Elf64_Shdr *) (map + e->e_shoff);
131
132 secnames = map + sh[e->e_shstrndx].sh_offset;
133 for (i = 0; i < e->e_shnum; i++) {
134 if (!strcmp(section, secnames + sh[i].sh_name)) {
135 *size = sh[i].sh_size;
136 *offset = sh[i].sh_offset;
137 return 0;
138 }
139 }
140
141 return -1;
142 }
143
144 static int elf32_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
145 {
146 const char *secnames;
147 Elf32_Ehdr *e;
148 Elf32_Shdr *sh;
149 int i;
150
151 e = (Elf32_Ehdr *) map;
152 sh = (Elf32_Shdr *) (map + e->e_shoff);
153
154 secnames = map + sh[e->e_shstrndx].sh_offset;
155 for (i = 0; i < e->e_shnum; i++) {
156 if (!strcmp(section, secnames + sh[i].sh_name)) {
157 *size = sh[i].sh_size;
158 *offset = sh[i].sh_offset;
159 return 0;
160 }
161 }
162
163 return -1;
164 }
165
166 static int elf_find_section(char *map, const char *section, unsigned int *offset, unsigned int *size)
167 {
168 int clazz = map[EI_CLASS];
169
170 if (clazz == ELFCLASS32)
171 return elf32_find_section(map, section, offset, size);
172 else if (clazz == ELFCLASS64)
173 return elf64_find_section(map, section, offset, size);
174
175 ERROR("unknown elf format %d\n", clazz);
176
177 return -1;
178 }
179
180 static struct module *
181 alloc_module(const char *name, const char *depends, int size)
182 {
183 struct module *m;
184 char *_name, *_dep;
185
186 m = calloc_a(sizeof(*m),
187 &_name, strlen(name) + 1,
188 &_dep, depends ? strlen(depends) + 2 : 0);
189 if (!m)
190 return NULL;
191
192 m->avl.key = m->name = strcpy(_name, name);
193 m->opts = 0;
194
195 if (depends) {
196 m->depends = strcpy(_dep, depends);
197 while (*_dep) {
198 if (*_dep == ',')
199 *_dep = '\0';
200 _dep++;
201 }
202 }
203
204 m->size = size;
205 avl_insert(&modules, &m->avl);
206
207 return m;
208 }
209
210 static int scan_loaded_modules(void)
211 {
212 size_t buf_len = 0;
213 char *buf = NULL;
214 FILE *fp;
215
216 fp = fopen("/proc/modules", "r");
217 if (!fp) {
218 ERROR("failed to open /proc/modules\n");
219 return -1;
220 }
221
222 while (getline(&buf, &buf_len, fp) > 0) {
223 struct module m;
224 struct module *n;
225
226 m.name = strtok(buf, " ");
227 m.size = atoi(strtok(NULL, " "));
228 m.usage = atoi(strtok(NULL, " "));
229 m.depends = strtok(NULL, " ");
230
231 if (!m.name || !m.depends)
232 continue;
233
234 n = alloc_module(m.name, m.depends, m.size);
235 n->usage = m.usage;
236 n->state = LOADED;
237 }
238 free(buf);
239 fclose(fp);
240
241 return 0;
242 }
243
244 static struct module* get_module_info(const char *module, const char *name)
245 {
246 int fd = open(module, O_RDONLY);
247 unsigned int offset, size;
248 char *map, *strings, *dep = NULL;
249 struct module *m;
250 struct stat s;
251
252 if (!fd) {
253 ERROR("failed to open %s\n", module);
254 return NULL;
255 }
256
257 if (fstat(fd, &s) == -1) {
258 ERROR("failed to stat %s\n", module);
259 return NULL;
260 }
261
262 map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
263 if (map == MAP_FAILED) {
264 ERROR("failed to mmap %s\n", module);
265 return NULL;
266 }
267
268 if (elf_find_section(map, ".modinfo", &offset, &size)) {
269 ERROR("failed to load the .modinfo section from %s\n", module);
270 return NULL;
271 }
272
273 strings = map + offset;
274 while (strings && (strings < map + offset + size)) {
275 char *sep;
276 int len;
277
278 while (!strings[0])
279 strings++;
280 sep = strstr(strings, "=");
281 if (!sep)
282 break;
283 len = sep - strings;
284 sep++;
285 if (!strncmp(strings, "depends=", len + 1))
286 dep = sep;
287 strings = &sep[strlen(sep)];
288 }
289
290 m = alloc_module(name, dep, s.st_size);
291 if (!m)
292 return NULL;
293
294 m->state = SCANNED;
295
296 return m;
297 }
298
299 static int scan_module_folder(void)
300 {
301 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
302 struct utsname ver;
303 char *path;
304 glob_t gl;
305 int j;
306
307 uname(&ver);
308 path = alloca(sizeof(DEF_MOD_PATH "*.ko") + strlen(prefix) + strlen(ver.release) + 1);
309 sprintf(path, "%s" DEF_MOD_PATH "*.ko", prefix, ver.release);
310
311 if (glob(path, gl_flags, NULL, &gl) < 0)
312 return -1;
313
314 for (j = 0; j < gl.gl_pathc; j++) {
315 char *name = get_module_name(gl.gl_pathv[j]);
316 struct module *m;
317
318 if (!name)
319 continue;
320
321 m = find_module(name);
322 if (!m)
323 get_module_info(gl.gl_pathv[j], name);
324 }
325
326 globfree(&gl);
327
328 return 0;
329 }
330
331 static int print_modinfo(char *module)
332 {
333 int fd = open(module, O_RDONLY);
334 unsigned int offset, size;
335 struct stat s;
336 char *map, *strings;
337
338 if (!fd) {
339 ERROR("failed to open %s\n", module);
340 return -1;
341 }
342
343 if (fstat(fd, &s) == -1) {
344 ERROR("failed to stat %s\n", module);
345 return -1;
346 }
347
348 map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
349 if (map == MAP_FAILED) {
350 ERROR("failed to mmap %s\n", module);
351 return -1;
352 }
353
354 if (elf_find_section(map, ".modinfo", &offset, &size)) {
355 ERROR("failed to load the .modinfo section from %s\n", module);
356 return -1;
357 }
358
359 strings = map + offset;
360 printf("module:\t\t%s\n", module);
361 while (strings && (strings < map + offset + size)) {
362 char *dup = NULL;
363 char *sep;
364
365 while (!strings[0])
366 strings++;
367 sep = strstr(strings, "=");
368 if (!sep)
369 break;
370 dup = strndup(strings, sep - strings);
371 sep++;
372 if (strncmp(strings, "parm", 4)) {
373 if (strlen(dup) < 7)
374 printf("%s:\t\t%s\n", dup, sep);
375 else
376 printf("%s:\t%s\n", dup, sep);
377 }
378 strings = &sep[strlen(sep)];
379 if (dup)
380 free(dup);
381 }
382
383 return 0;
384 }
385
386 static int deps_available(struct module *m, int verbose)
387 {
388 char *dep;
389 int err = 0;
390
391 if (!strcmp(m->depends, "-") || !strcmp(m->depends, ""))
392 return 0;
393
394 dep = m->depends;
395
396 while (*dep) {
397 m = find_module(dep);
398
399 if (verbose && !m)
400 ERROR("missing dependency %s\n", dep);
401 if (verbose && m && (m->state != LOADED))
402 ERROR("dependency not loaded %s\n", dep);
403 if (!m || (m->state != LOADED))
404 err++;
405 dep += strlen(dep) + 1;
406 }
407
408 return err;
409 }
410
411 static int insert_module(char *path, const char *options)
412 {
413 void *data = 0;
414 struct stat s;
415 int fd, ret = -1;
416
417 if (stat(path, &s)) {
418 ERROR("missing module %s\n", path);
419 return ret;
420 }
421
422 fd = open(path, O_RDONLY);
423 if (!fd) {
424 ERROR("cannot open %s\n", path);
425 return ret;
426 }
427
428 data = malloc(s.st_size);
429 if (read(fd, data, s.st_size) == s.st_size)
430 ret = syscall(__NR_init_module, data, (unsigned long) s.st_size, options);
431 else
432 ERROR("failed to read full module %s\n", path);
433
434 close(fd);
435 free(data);
436
437 return ret;
438 }
439
440 static void load_moddeps(struct module *_m)
441 {
442 char *dep;
443 struct module *m;
444
445 if (!strcmp(_m->depends, "-") || !strcmp(_m->depends, ""))
446 return;
447
448 dep = _m->depends;
449
450 while (*dep) {
451 m = find_module(dep);
452
453 if (!m)
454 ERROR("failed to find dependency %s\n", dep);
455 if (m && (m->state != LOADED)) {
456 m->state = PROBE;
457 load_moddeps(m);
458 }
459
460 dep = dep + strlen(dep) + 1;
461 }
462 }
463
464 static int iterations = 0;
465 static int load_modprobe(void)
466 {
467 int loaded, todo;
468 struct module *m;
469
470 avl_for_each_element(&modules, m, avl)
471 if (m->state == PROBE)
472 load_moddeps(m);
473
474 do {
475 loaded = 0;
476 todo = 0;
477 avl_for_each_element(&modules, m, avl) {
478 if ((m->state == PROBE) && (!deps_available(m, 0))) {
479 if (!insert_module(get_module_path(m->name), (m->opts) ? (m->opts) : (""))) {
480 m->state = LOADED;
481 m->error = 0;
482 loaded++;
483 continue;
484 }
485 m->error = 1;
486 }
487
488 if ((m->state == PROBE) || m->error)
489 todo++;
490 }
491 iterations++;
492 } while (loaded);
493
494 return todo;
495 }
496
497 static int print_insmod_usage(void)
498 {
499 INFO("Usage:\n\tinsmod filename [args]\n");
500
501 return -1;
502 }
503
504 static int print_usage(char *arg)
505 {
506 INFO("Usage:\n\t%s module\n", arg);
507
508 return -1;
509 }
510
511 static int main_insmod(int argc, char **argv)
512 {
513 char *name, *cur, *options;
514 int i, ret, len;
515
516 if (argc < 2)
517 return print_insmod_usage();
518
519 name = get_module_name(argv[1]);
520 if (!name) {
521 ERROR("cannot find module - %s\n", argv[1]);
522 return -1;
523 }
524
525 if (scan_loaded_modules())
526 return -1;
527
528 if (find_module(name)) {
529 ERROR("module is already loaded - %s\n", name);
530 return -1;
531
532 }
533
534 free_modules();
535
536 for (len = 0, i = 2; i < argc; i++)
537 len += strlen(argv[i]) + 1;
538
539 options = malloc(len);
540 options[0] = 0;
541 cur = options;
542 for (i = 2; i < argc; i++) {
543 if (options[0]) {
544 *cur = ' ';
545 cur++;
546 }
547 cur += sprintf(cur, "%s", argv[i]);
548 }
549
550 if (get_module_path(argv[1])) {
551 name = argv[1];
552 } else if (!get_module_path(name)) {
553 fprintf(stderr, "Failed to find %s. Maybe it is a built in module ?\n", name);
554 return -1;
555 }
556
557 ret = insert_module(get_module_path(name), options);
558 free(options);
559
560 if (ret)
561 ERROR("failed to insert %s\n", get_module_path(name));
562
563 return ret;
564 }
565
566 static int main_rmmod(int argc, char **argv)
567 {
568 struct module *m;
569 char *name;
570 int ret;
571
572 if (argc != 2)
573 return print_usage("rmmod");
574
575 if (scan_loaded_modules())
576 return -1;
577
578 name = get_module_name(argv[1]);
579 m = find_module(name);
580 if (!m) {
581 ERROR("module is not loaded\n");
582 return -1;
583 }
584 ret = syscall(__NR_delete_module, m->name, 0);
585
586 if (ret)
587 ERROR("unloading the module failed\n");
588
589 free_modules();
590
591 return ret;
592 }
593
594 static int main_lsmod(int argc, char **argv)
595 {
596 struct module *m;
597
598 if (scan_loaded_modules())
599 return -1;
600
601 avl_for_each_element(&modules, m, avl)
602 if (m->state == LOADED)
603 printf("%-20s%8d%3d %s\n",
604 m->name, m->size, m->usage,
605 (*m->depends == '-') ? ("") : (m->depends));
606
607 free_modules();
608
609 return 0;
610 }
611
612 static int main_modinfo(int argc, char **argv)
613 {
614 struct module *m;
615 char *name;
616
617 if (argc != 2)
618 return print_usage("modinfo");
619
620 if (scan_module_folder())
621 return -1;
622
623 name = get_module_name(argv[1]);
624 m = find_module(name);
625 if (!m) {
626 ERROR("cannot find module - %s\n", argv[1]);
627 return -1;
628 }
629
630 name = get_module_path(m->name);
631 if (!name) {
632 ERROR("cannot find path of module - %s\n", m->name);
633 return -1;
634 }
635
636 print_modinfo(name);
637
638 return 0;
639 }
640
641 static int main_modprobe(int argc, char **argv)
642 {
643 struct module *m;
644 char *name;
645
646 if (argc != 2)
647 return print_usage("modprobe");
648
649 if (scan_loaded_modules())
650 return -1;
651
652 if (scan_module_folder())
653 return -1;
654
655 name = get_module_name(argv[1]);
656 m = find_module(name);
657 if (m && m->state == LOADED) {
658 ERROR("%s is already loaded\n", name);
659 return -1;
660 } else if (!m) {
661 ERROR("failed to find a module named %s\n", name);
662 } else {
663 int fail;
664
665 m->state = PROBE;
666
667 fail = load_modprobe();
668
669 if (fail) {
670 ERROR("%d module%s could not be probed\n",
671 fail, (fail == 1) ? ("") : ("s"));
672
673 avl_for_each_element(&modules, m, avl)
674 if ((m->state == PROBE) || m->error)
675 ERROR("- %s\n", m->name);
676 }
677 }
678
679 free_modules();
680
681 return 0;
682 }
683
684 static int main_loader(int argc, char **argv)
685 {
686 int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
687 char *dir = "/etc/modules.d/*";
688 struct module *m;
689 glob_t gl;
690 char *path;
691 int fail, j;
692
693 if (argc > 1)
694 dir = argv[1];
695
696 if (argc > 2)
697 prefix = argv[2];
698
699 path = malloc(strlen(dir) + 2);
700 strcpy(path, dir);
701 strcat(path, "*");
702
703 if (scan_loaded_modules())
704 return -1;
705
706 if (scan_module_folder())
707 return -1;
708
709 syslog(0, "kmodloader: loading kernel modules from %s\n", path);
710
711 if (glob(path, gl_flags, NULL, &gl) < 0)
712 goto out;
713
714 for (j = 0; j < gl.gl_pathc; j++) {
715 FILE *fp = fopen(gl.gl_pathv[j], "r");
716 size_t mod_len = 0;
717 char *mod = NULL;
718
719 if (!fp) {
720 ERROR("failed to open %s\n", gl.gl_pathv[j]);
721 continue;
722 }
723
724 while (getline(&mod, &mod_len, fp) > 0) {
725 char *nl = strchr(mod, '\n');
726 struct module *m;
727 char *opts;
728
729 if (nl)
730 *nl = '\0';
731
732 opts = strchr(mod, ' ');
733 if (opts)
734 *opts++ = '\0';
735
736 m = find_module(get_module_name(mod));
737 if (!m || (m->state == LOADED))
738 continue;
739
740 if (opts)
741 m->opts = strdup(opts);
742 m->state = PROBE;
743 if (basename(gl.gl_pathv[j])[0] - '0' <= 9)
744 load_modprobe();
745
746 }
747 free(mod);
748 fclose(fp);
749 }
750
751 fail = load_modprobe();
752 DEBUG("ran %d iterations\n", iterations);
753
754 if (fail) {
755 ERROR("%d module%s could not be probed\n",
756 fail, (fail == 1) ? ("") : ("s"));
757
758 avl_for_each_element(&modules, m, avl)
759 if ((m->state == PROBE) || (m->error))
760 ERROR("- %s - %d\n", m->name, deps_available(m, 1));
761 }
762
763 out:
764 globfree(&gl);
765 free(path);
766
767 return 0;
768 }
769
770 static int avl_modcmp(const void *k1, const void *k2, void *ptr)
771 {
772 const char *s1 = k1;
773 const char *s2 = k2;
774
775 while (*s1 && ((*s1 == *s2) ||
776 ((*s1 == '_') && (*s2 == '-')) ||
777 ((*s1 == '-') && (*s2 == '_'))))
778 {
779 s1++;
780 s2++;
781 }
782
783 return *(const unsigned char *)s1 - *(const unsigned char *)s2;
784 }
785
786 int main(int argc, char **argv)
787 {
788 char *exec = basename(*argv);
789
790 avl_init(&modules, avl_modcmp, false, NULL);
791 if (!strcmp(exec, "insmod"))
792 return main_insmod(argc, argv);
793
794 if (!strcmp(exec, "rmmod"))
795 return main_rmmod(argc, argv);
796
797 if (!strcmp(exec, "lsmod"))
798 return main_lsmod(argc, argv);
799
800 if (!strcmp(exec, "modinfo"))
801 return main_modinfo(argc, argv);
802
803 if (!strcmp(exec, "modprobe"))
804 return main_modprobe(argc, argv);
805
806 return main_loader(argc, argv);
807 }