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, ¶ms, list) 685 if (!strcmp(pname, p->name)) 686 break; 687 688 if (list_entry_is_h(p, ¶ms, list)) { 689 p = alloca(sizeof(*p)); 690 p->name = pname; 691 p->desc = p->type = NULL; 692 list_add(&p->list, ¶ms); 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, ¶ms, 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