kmodloader.c 22 KB

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