static int check_module_inuse(struct kmod_module *mod) { struct kmod_list *holders; if (kmod_module_get_initstate(mod) == -ENOENT) { ERR("Module %s is not currently loaded\n", kmod_module_get_name(mod)); return -ENOENT; } holders = kmod_module_get_holders(mod); if (holders != NULL) { struct kmod_list *itr; ERR("Module %s is in use by:", kmod_module_get_name(mod)); kmod_list_foreach(itr, holders) { struct kmod_module *hm = kmod_module_get_module(itr); fprintf(stderr, " %s", kmod_module_get_name(hm)); kmod_module_unref(hm); } fputc('\n', stderr); kmod_module_unref_list(holders); return -EBUSY; } if (kmod_module_get_refcnt(mod) != 0) { ERR("Module %s is in use\n", kmod_module_get_name(mod)); return -EBUSY; } return 0; }
static bool insmod_recursion_has_loop(struct kmod_module *mod, struct array *recursion) { unsigned int i; /* * Don't check every time to not impact normal use cases. If the * recursion hits INSMOD_RECURSION_STEP, then search loop in * @recursion. */ if ((recursion->count + 1) % INSMOD_RECURSION_STEP != 0) return false; for (i = 0; i < recursion->count; i++) { if (recursion->array[i] != mod) continue; ERR("Dependency loop detected while inserting '%s'. Operation aborted.\n", kmod_module_get_name(mod)); for (; i < recursion->count; i++) ERR("\t%s\n", kmod_module_get_name(recursion->array[i])); return true; } return false; }
static int load_module(struct udev *udev, const char *alias) { struct kmod_list *list = NULL; struct kmod_list *l; int err; err = kmod_module_new_from_lookup(ctx, alias, &list); if (err < 0) return err; if (list == NULL) log_debug("no module matches '%s'", alias); kmod_list_foreach(l, list) { struct kmod_module *mod = kmod_module_get_module(l); err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); if (err == KMOD_PROBE_APPLY_BLACKLIST) log_debug("module '%s' is blacklisted", kmod_module_get_name(mod)); else if (err == 0) log_debug("inserted '%s'", kmod_module_get_name(mod)); else log_debug("failed to insert '%s'", kmod_module_get_name(mod)); kmod_module_unref(mod); } kmod_module_unref_list(list); return err; }
static int do_lsmod(int argc, char *argv[]) { struct kmod_ctx *ctx; const char *null_config = NULL; struct kmod_list *list, *itr; int err; if (argc != 1) { fprintf(stderr, "Usage: %s\n", argv[0]); return EXIT_FAILURE; } ctx = kmod_new(NULL, &null_config); if (ctx == NULL) { fputs("Error: kmod_new() failed!\n", stderr); return EXIT_FAILURE; } err = kmod_module_new_from_loaded(ctx, &list); if (err < 0) { fprintf(stderr, "Error: could not get list of modules: %s\n", strerror(-err)); kmod_unref(ctx); return EXIT_FAILURE; } puts("Module Size Used by"); kmod_list_foreach(itr, list) { struct kmod_module *mod = kmod_module_get_module(itr); const char *name = kmod_module_get_name(mod); int use_count = kmod_module_get_refcnt(mod); long size = kmod_module_get_size(mod); struct kmod_list *holders, *hitr; int first = 1; printf("%-19s %8ld %d ", name, size, use_count); holders = kmod_module_get_holders(mod); kmod_list_foreach(hitr, holders) { struct kmod_module *hm = kmod_module_get_module(hitr); if (!first) putchar(','); else first = 0; fputs(kmod_module_get_name(hm), stdout); kmod_module_unref(hm); } putchar('\n'); kmod_module_unref_list(holders); kmod_module_unref(mod); } kmod_module_unref_list(list); kmod_unref(ctx); return EXIT_SUCCESS; }
static int load_module(struct kmod_ctx *ctx, const char *m) { const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; struct kmod_list *itr, *modlist = NULL; int r = 0; log_debug("load: %s", m); r = kmod_module_new_from_lookup(ctx, m, &modlist); if (r < 0) { log_error("Failed to lookup alias '%s': %s", m, strerror(-r)); return r; } if (!modlist) { log_error("Failed to find module '%s'", m); return -ENOENT; } kmod_list_foreach(itr, modlist) { struct kmod_module *mod; int state, err; mod = kmod_module_get_module(itr); state = kmod_module_get_initstate(mod); switch (state) { case KMOD_MODULE_BUILTIN: log_info("Module '%s' is builtin", kmod_module_get_name(mod)); break; case KMOD_MODULE_LIVE: log_debug("Module '%s' is already loaded", kmod_module_get_name(mod)); break; default: err = kmod_module_probe_insert_module(mod, probe_flags, NULL, NULL, NULL, NULL); if (err == 0) log_info("Inserted module '%s'", kmod_module_get_name(mod)); else if (err == KMOD_PROBE_APPLY_BLACKLIST) log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); else { log_error("Failed to insert '%s': %s", kmod_module_get_name(mod), strerror(-err)); r = err; } } kmod_module_unref(mod); } kmod_module_unref_list(modlist); return r; }
static int loaded_1(const struct test *t) { struct kmod_ctx *ctx; const char *null_config = NULL; struct kmod_list *list, *itr; int err; ctx = kmod_new(NULL, &null_config); if (ctx == NULL) exit(EXIT_FAILURE); err = kmod_module_new_from_loaded(ctx, &list); if (err < 0) { fprintf(stderr, "%s\n", strerror(-err)); kmod_unref(ctx); exit(EXIT_FAILURE); } printf("Module Size Used by\n"); kmod_list_foreach(itr, list) { struct kmod_module *mod = kmod_module_get_module(itr); const char *name = kmod_module_get_name(mod); int use_count = kmod_module_get_refcnt(mod); long size = kmod_module_get_size(mod); struct kmod_list *holders, *hitr; int first = 1; printf("%-19s %8ld %d ", name, size, use_count); holders = kmod_module_get_holders(mod); kmod_list_foreach(hitr, holders) { struct kmod_module *hm = kmod_module_get_module(hitr); if (!first) putchar(','); else first = 0; fputs(kmod_module_get_name(hm), stdout); kmod_module_unref(hm); } putchar('\n'); kmod_module_unref_list(holders); kmod_module_unref(mod); } kmod_module_unref_list(list); kmod_unref(ctx); return EXIT_SUCCESS; }
int kmod_setup(void) { unsigned i; struct kmod_ctx *ctx = NULL; struct kmod_module *mod; int err; for (i = 0; i < ELEMENTSOF(kmod_table); i += 2) { if (access(kmod_table[i+1], F_OK) >= 0) continue; log_debug("Your kernel apparently lacks built-in %s support. Might be a good idea to compile it in. " "We'll now try to work around this by loading the module...", kmod_table[i]); if (!ctx) { ctx = kmod_new(NULL, NULL); if (!ctx) { log_error("Failed to allocate memory for kmod"); return -ENOMEM; } kmod_set_log_fn(ctx, systemd_kmod_log, NULL); kmod_load_resources(ctx); } err = kmod_module_new_from_name(ctx, kmod_table[i], &mod); if (err < 0) { log_error("Failed to load module '%s'", kmod_table[i]); continue; } err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); if (err == 0) log_info("Inserted module '%s'", kmod_module_get_name(mod)); else if (err == KMOD_PROBE_APPLY_BLACKLIST) log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); else log_error("Failed to insert '%s'", kmod_module_get_name(mod)); kmod_module_unref(mod); } if (ctx) kmod_unref(ctx); return 0; }
int check(char *kmod_name){ int ret = 0, err; struct kmod_ctx *ctx; struct kmod_module *mod; struct kmod_list *list, *itr; const char *null_config = NULL; printf("Checking if %s is loaded...\n", kmod_name); ctx = kmod_new(NULL, &null_config); if(ctx == NULL){ ret = -1; printf("Unexpected error...\n"); }else{ err = kmod_module_new_from_loaded(ctx, &list); if(err < 0){ ret = -1; printf("Error: %s\n", strerror(-err)); }else{ ret = 0; kmod_list_foreach(itr, list){ mod = kmod_module_get_module(itr); if(strcmp(kmod_module_get_name(mod), kmod_name) == 0){ ret = 1; } kmod_module_unref(mod); } kmod_module_unref_list(list); } }
std::vector<std::string> modalias_resolve_modules(struct kmod_ctx *ctx, const std::string &modalias) { struct kmod_list *l = nullptr, *list = nullptr, *filtered = nullptr; std::vector<std::string> modules; int err = kmod_module_new_from_lookup(ctx, modalias.c_str(), &list); if (err < 0) goto exit; // No module found... if (list == nullptr) goto exit; // filter through blacklist err = kmod_module_apply_filter(ctx, KMOD_FILTER_BLACKLIST, list, &filtered); kmod_module_unref_list(list); if (err <0) goto exit; list = filtered; kmod_list_foreach(l, list) { struct kmod_module *mod = kmod_module_get_module(l); const char *str = kmod_module_get_name(mod); if (modules.empty() || modules.back() != str) modules.push_back(str); kmod_module_unref(mod); if (err < 0) break; } kmod_module_unref_list(list); exit: return modules; }
static int from_name(const struct test *t) { static const char *modnames[] = { "ext4", "balbalbalbbalbalbalbalbalbalbal", "snd-hda-intel", "snd-timer", "iTCO_wdt", NULL, }; const char **p; struct kmod_ctx *ctx; struct kmod_module *mod; const char *null_config = NULL; int err; ctx = kmod_new(NULL, &null_config); if (ctx == NULL) exit(1); for (p = modnames; p != NULL; p++) { err = kmod_module_new_from_name(ctx, *p, &mod); if (err < 0) exit(0); printf("modname: %s\n", kmod_module_get_name(mod)); kmod_module_unref(mod); } kmod_unref(ctx); return 0; }
static int from_alias(const struct test *t) { static const char *modnames[] = { "ext4.*", NULL, }; const char **p; struct kmod_ctx *ctx; int err; ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(1); for (p = modnames; p != NULL; p++) { struct kmod_list *l, *list = NULL; err = kmod_module_new_from_lookup(ctx, *p, &list); if (err < 0) exit(0); kmod_list_foreach(l, list) { struct kmod_module *m; m = kmod_module_get_module(l); printf("modname: %s\n", kmod_module_get_name(m)); kmod_module_unref(m); } kmod_module_unref_list(list); } kmod_unref(ctx); return 0; }
static int blacklist_1(const struct test *t) { struct kmod_ctx *ctx; struct kmod_list *list = NULL, *l, *filtered; struct kmod_module *mod; int err; size_t len = 0; const char *names[] = { "pcspkr", "pcspkr2", "floppy", "ext4", NULL }; const char **name; ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(1); for(name = names; *name; name++) { err = kmod_module_new_from_name(ctx, *name, &mod); if (err < 0) goto fail_lookup; list = kmod_list_append(list, mod); } err = kmod_module_apply_filter(ctx, KMOD_FILTER_BLACKLIST, list, &filtered); if (err < 0) { ERR("Could not filter: %s\n", strerror(-err)); goto fail; } if (filtered == NULL) { ERR("All modules were filtered out!\n"); goto fail; } kmod_list_foreach(l, filtered) { const char *modname; mod = kmod_module_get_module(l); modname = kmod_module_get_name(mod); if (strcmp("pcspkr", modname) == 0 || strcmp("floppy", modname) == 0) goto fail; len++; kmod_module_unref(mod); } if (len != 2) goto fail; kmod_module_unref_list(filtered); kmod_module_unref_list(list); kmod_unref(ctx); return 0; fail: kmod_module_unref_list(list); fail_lookup: kmod_unref(ctx); return 1; }
/** * Attempts to load a module. * * @param module_name The filename of the module to be loaded * @param driver The name of the driver to be loaded * @return 1 if the driver is succesfully loaded, 0 otherwise */ int module_load(char *module_name, char *driver) { int err = 0; int flags = KMOD_PROBE_IGNORE_LOADED; struct kmod_list *l, *list = NULL; if (module_is_loaded(driver) == 0) { /* the module has not loaded yet, try to load it */ bb_log(LOG_INFO, "Loading driver '%s' (module '%s')\n", driver, module_name); err = kmod_module_new_from_lookup(bb_status.kmod_ctx, module_name, &list); if (err < 0) { bb_log(LOG_DEBUG, "kmod_module_new_from_lookup(%s) failed (err: %d).\n", module_name, err); return 0; } if (list == NULL) { bb_log(LOG_ERR, "Module '%s' not found.\n", module_name); return 0; } kmod_list_foreach(l, list) { struct kmod_module *mod = kmod_module_get_module(l); bb_log(LOG_DEBUG, "Loading module '%s'.\n", kmod_module_get_name(mod)); err = kmod_module_probe_insert_module(mod, flags, NULL, NULL, NULL, 0); if (err < 0) { bb_log(LOG_DEBUG, "kmod_module_probe_insert_module(%s) failed (err: %d).\n", kmod_module_get_name(mod), err); } kmod_module_unref(mod); if (err < 0) { break; } } kmod_module_unref_list(list); }
static int check_module_inuse(struct kmod_module *mod) { struct kmod_list *holders; int state, ret; state = kmod_module_get_initstate(mod); if (state == KMOD_MODULE_BUILTIN) { ERR("Module %s is builtin.\n", kmod_module_get_name(mod)); return -ENOENT; } else if (state < 0) { ERR("Module %s is not currently loaded\n", kmod_module_get_name(mod)); return -ENOENT; } holders = kmod_module_get_holders(mod); if (holders != NULL) { struct kmod_list *itr; ERR("Module %s is in use by:", kmod_module_get_name(mod)); kmod_list_foreach(itr, holders) { struct kmod_module *hm = kmod_module_get_module(itr); fprintf(stderr, " %s", kmod_module_get_name(hm)); kmod_module_unref(hm); } fputc('\n', stderr); kmod_module_unref_list(holders); return -EBUSY; } ret = kmod_module_get_refcnt(mod); if (ret > 0) { ERR("Module %s is in use\n", kmod_module_get_name(mod)); return -EBUSY; } else if (ret == -ENOENT) { ERR("Module unloading is not supported\n"); } return ret; }
static int command_do(struct kmod_module *module, const char *type, const char *command, const char *cmdline_opts) { const char *modname = kmod_module_get_name(module); char *p, *cmd = NULL; size_t cmdlen, cmdline_opts_len, varlen; int ret = 0; if (cmdline_opts == NULL) cmdline_opts = ""; cmdline_opts_len = strlen(cmdline_opts); cmd = strdup(command); if (cmd == NULL) return -ENOMEM; cmdlen = strlen(cmd); varlen = sizeof("$CMDLINE_OPTS") - 1; while ((p = strstr(cmd, "$CMDLINE_OPTS")) != NULL) { size_t prefixlen = p - cmd; size_t suffixlen = cmdlen - prefixlen - varlen; size_t slen = cmdlen - varlen + cmdline_opts_len; char *suffix = p + varlen; char *s = malloc(slen + 1); if (s == NULL) { free(cmd); return -ENOMEM; } memcpy(s, cmd, p - cmd); memcpy(s + prefixlen, cmdline_opts, cmdline_opts_len); memcpy(s + prefixlen + cmdline_opts_len, suffix, suffixlen); s[slen] = '\0'; free(cmd); cmd = s; cmdlen = slen; } SHOW("%s %s\n", type, cmd); if (dry_run) goto end; setenv("MODPROBE_MODULE", modname, 1); ret = system(cmd); unsetenv("MODPROBE_MODULE"); if (ret == -1 || WEXITSTATUS(ret)) { LOG("Error running %s command for %s\n", type, modname); if (ret != -1) ret = -WEXITSTATUS(ret); } end: free(cmd); return ret; }
static int insmod_do_insert_module(struct kmod_module *mod, const char *opts) { int flags = 0, err; SHOW("insmod %s %s\n", kmod_module_get_path(mod), opts ? opts : ""); if (dry_run) return 0; if (strip_modversion || force) flags |= KMOD_INSERT_FORCE_MODVERSION; if (strip_vermagic || force) flags |= KMOD_INSERT_FORCE_VERMAGIC; err = kmod_module_insert_module(mod, flags, opts); switch (err) { case -EEXIST: /* * We checked for EEXIST with an earlier call to * retrieve the initstate, but to avoid a race * condition, we don't make any assumptions and handle * the error again here */ if (!first_time) err = 0; else ERR("Module %s already in kernel.\n", kmod_module_get_name(mod)); break; case -EPERM: ERR("could not insert '%s': %s\n", kmod_module_get_name(mod), strerror(-err)); break; } return err; }
static int rmmod_do_remove_module(struct kmod_module *mod) { const char *modname = kmod_module_get_name(mod); int flags = 0, err; SHOW("rmmod %s\n", kmod_module_get_name(mod)); if (dry_run) return 0; if (force) flags |= KMOD_REMOVE_FORCE; err = kmod_module_remove_module(mod, flags); if (err == -EEXIST) { if (!first_time) err = 0; else LOG("Module %s is not in kernel.\n", modname); } return err; }
static noreturn int test_dependencies(const struct test *t) { struct kmod_ctx *ctx; struct kmod_module *mod = NULL; struct kmod_list *list, *l; int err; size_t len = 0; int fooa = 0, foob = 0, fooc = 0; ctx = kmod_new(NULL, NULL); if (ctx == NULL) exit(EXIT_FAILURE); err = kmod_module_new_from_name(ctx, "mod-foo", &mod); if (err < 0 || mod == NULL) { kmod_unref(ctx); exit(EXIT_FAILURE); } list = kmod_module_get_dependencies(mod); kmod_list_foreach(l, list) { struct kmod_module *m = kmod_module_get_module(l); const char *name = kmod_module_get_name(m); if (streq(name, "mod_foo_a")) fooa = 1; if (streq(name, "mod_foo_b")) foob = 1; else if (streq(name, "mod_foo_c")) fooc = 1; fprintf(stderr, "name=%s", name); kmod_module_unref(m); len++; } /* fooa, foob, fooc */ if (len != 3 || !fooa || !foob || !fooc) exit(EXIT_FAILURE); kmod_module_unref_list(list); kmod_module_unref(mod); kmod_unref(ctx); exit(EXIT_SUCCESS); }
/** * @attention 本注释得到了"核高基"科技重大专项2012年课题 * “开源操作系统内核分析和安全性评估 * (课题编号:2012ZX01039-004)”的资助。 * * @copyright 注释添加单位:清华大学——03任务 * (Linux内核相关通用基础软件包分析) * * @author 注释添加人员: 李明 * (电子邮件 <*****@*****.**>) * * @date 注释添加日期: 2013-6-1 * * @note 注释详细内容: * * @brief 测试模块的 kmod_module_get_dependencies 是否工作正确 * 其中需要调用到 libkmod 模块中的以下接口 * - kmod_new() * - kmod_module_new_from_name() * - kmod_module_get_dependencies() * - kmod_list_foreach() * - kmod_module_get_module() * - kmod_module_get_name() * - kmod_module_unref_list() * - kmod_module_unref() * - kmod_unref() */ static int test_dependencies(const struct test *t) { struct kmod_ctx *ctx; struct kmod_module *mod; struct kmod_list *list, *l; int err; size_t len = 0; int crc16 = 0, mbcache = 0, jbd2 = 0; ctx = kmod_new(NULL, NULL); if (ctx == NULL) return EXIT_FAILURE; err = kmod_module_new_from_name(ctx, "ext4", &mod); if (err < 0) { kmod_unref(ctx); return EXIT_FAILURE; } list = kmod_module_get_dependencies(mod); kmod_list_foreach(l, list) { struct kmod_module *m = kmod_module_get_module(l); const char *name = kmod_module_get_name(m); if (strcmp(name, "crc16") == 0) crc16 = 1; if (strcmp(name, "mbcache") == 0) mbcache = 1; else if (strcmp(name, "jbd2") == 0) jbd2 = 1; kmod_module_unref(m); len++; } /* crc16, mbcache, jbd2 */ if (len != 3 || !crc16 || !mbcache || !jbd2) return EXIT_FAILURE; kmod_module_unref_list(list); kmod_module_unref(mod); kmod_unref(ctx); return EXIT_SUCCESS; }
static int load_module(struct kmod_ctx *ctx, const char *m) { struct kmod_list *itr, *modlist = NULL; const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; const char *options = "luns=8 iSerialNumber=1234000 ro=1"; int r = 0; r = kmod_module_new_from_lookup(ctx, m, &modlist); if (r < 0) { printf("ERROR: Failed to lookup alias '%s': %s\n", m, strerror(-r)); } if (!modlist) { printf("ERROR: Failed to find module '%s'\n", m); return -ENOENT; } kmod_list_foreach(itr, modlist) { struct kmod_module *mod; int state, err; mod = kmod_module_get_module(itr); state = kmod_module_get_initstate(mod); switch (state) { case KMOD_MODULE_BUILTIN: printf("Module '%s' is builtin\n", kmod_module_get_name(mod)); break; case KMOD_MODULE_LIVE: printf("Module '%s' is already loaded\n", kmod_module_get_name(mod)); //printf("Unloading module '%s'...\n", kmod_module_get_name(mod)); //err = kmod_module_remove_module(mod, KMOD_REMOVE_FORCE); //if (err == 0) //{ // printf("Successfully removed module '%s'\n", kmod_module_get_name(mod)); // r = EAGAIN; //} //else //{ // printf("ERROR: Module '%s' can't be removed\n", kmod_module_get_name(mod)); // r = err; //} break; default: err = kmod_module_probe_insert_module(mod, probe_flags, options, NULL, NULL, NULL); if (err == 0) printf("Inserted module '%s'\n", kmod_module_get_name(mod)); else if (err == KMOD_PROBE_APPLY_BLACKLIST) printf("Module '%s' is blacklisted\n", kmod_module_get_name(mod)); else { printf("ERROR: Failed to insert '%s': %s\n", kmod_module_get_name(mod), strerror(-err)); r = err; } } kmod_module_unref(mod); } kmod_module_unref_list(modlist); return r; }
static int rmmod_do_module(struct kmod_module *mod, bool do_dependencies) { const char *modname = kmod_module_get_name(mod); struct kmod_list *pre = NULL, *post = NULL; const char *cmd = NULL; int err; if (!ignore_commands) { err = kmod_module_get_softdeps(mod, &pre, &post); if (err < 0) { WRN("could not get softdeps of '%s': %s\n", modname, strerror(-err)); return err; } cmd = kmod_module_get_remove_commands(mod); } if (cmd == NULL && !ignore_loaded) { int state = kmod_module_get_initstate(mod); if (state < 0) { LOG ("Module %s not found.\n", modname); err = -ENOENT; goto error; } else if (state == KMOD_MODULE_BUILTIN) { LOG("Module %s is builtin.\n", modname); err = -ENOENT; goto error; } else if (state != KMOD_MODULE_LIVE) { if (first_time) { LOG("Module %s is not in kernel.\n", modname); err = -ENOENT; goto error; } else { err = 0; goto error; } } } rmmod_do_deps_list(post, false); if (do_dependencies && remove_dependencies) { struct kmod_list *deps = kmod_module_get_dependencies(mod); err = rmmod_do_deps_list(deps, true); if (err < 0) goto error; } if (!ignore_loaded) { int usage = kmod_module_get_refcnt(mod); if (usage > 0) { if (!quiet_inuse) LOG("Module %s is in use.\n", modname); err = -EBUSY; goto error; } } if (cmd == NULL) err = rmmod_do_remove_module(mod); else err = command_do(mod, "remove", cmd, NULL); if (err < 0) goto error; rmmod_do_deps_list(pre, false); error: kmod_module_unref_list(pre); kmod_module_unref_list(post); return err; }
int kmod_setup(void) { #ifdef HAVE_KMOD static const struct { const char *module; const char *path; bool warn_if_unavailable:1; bool warn_if_module:1; bool (*condition_fn)(void); } kmod_table[] = { /* auto-loading on use doesn't work before udev is up */ { "autofs4", "/sys/class/misc/autofs", true, false, NULL }, /* early configure of ::1 on the loopback device */ { "ipv6", "/sys/module/ipv6", false, true, NULL }, /* this should never be a module */ { "unix", "/proc/net/unix", true, true, NULL }, /* IPC is needed before we bring up any other services */ { "kdbus", "/sys/fs/kdbus", false, false, is_kdbus_wanted }, #ifdef HAVE_LIBIPTC /* netfilter is needed by networkd, nspawn among others, and cannot be autoloaded */ { "ip_tables", "/proc/net/ip_tables_names", false, false, NULL }, #endif }; struct kmod_ctx *ctx = NULL; unsigned int i; int r; if (have_effective_cap(CAP_SYS_MODULE) == 0) return 0; for (i = 0; i < ELEMENTSOF(kmod_table); i++) { struct kmod_module *mod; if (kmod_table[i].path && access(kmod_table[i].path, F_OK) >= 0) continue; if (kmod_table[i].condition_fn && !kmod_table[i].condition_fn()) continue; if (kmod_table[i].warn_if_module) log_debug("Your kernel apparently lacks built-in %s support. Might be " "a good idea to compile it in. We'll now try to work around " "this by loading the module...", kmod_table[i].module); if (!ctx) { ctx = kmod_new(NULL, NULL); if (!ctx) return log_oom(); kmod_set_log_fn(ctx, systemd_kmod_log, NULL); kmod_load_resources(ctx); } r = kmod_module_new_from_name(ctx, kmod_table[i].module, &mod); if (r < 0) { log_error("Failed to lookup module '%s'", kmod_table[i].module); continue; } r = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); if (r == 0) log_debug("Inserted module '%s'", kmod_module_get_name(mod)); else if (r == KMOD_PROBE_APPLY_BLACKLIST) log_info("Module '%s' is blacklisted", kmod_module_get_name(mod)); else { bool print_warning = kmod_table[i].warn_if_unavailable || (r < 0 && r != -ENOENT); log_full_errno(print_warning ? LOG_WARNING : LOG_DEBUG, r, "Failed to insert module '%s': %m", kmod_module_get_name(mod)); } kmod_module_unref(mod); } if (ctx) kmod_unref(ctx); #endif return 0; }
static int modinfo_do(struct kmod_module *mod) { struct kmod_list *l, *list = NULL; struct param *params = NULL; int err; if (field != NULL && strcmp(field, "filename") == 0) { printf("%s%c", kmod_module_get_path(mod), separator); return 0; } else if (field == NULL) { printf("%-16s%s%c", "filename:", kmod_module_get_path(mod), separator); } err = kmod_module_get_info(mod, &list); if (err < 0) { LOG("could not get modinfo from '%s': %s\n", kmod_module_get_name(mod), strerror(-err)); return err; } if (field != NULL && strcmp(field, "parm") == 0) { err = modinfo_params_do(list); goto end; } kmod_list_foreach(l, list) { const char *key = kmod_module_info_get_key(l); const char *value = kmod_module_info_get_value(l); int keylen; if (field != NULL) { if (strcmp(field, key) != 0) continue; /* filtered output contains no key, just value */ printf("%s%c", value, separator); continue; } if (strcmp(key, "parm") == 0 || strcmp(key, "parmtype") == 0) { err = process_parm(key, value, ¶ms); if (err < 0) goto end; continue; } if (separator == '\0') { printf("%s=%s%c", key, value, separator); continue; } keylen = strlen(key); printf("%s:%-*s%s%c", key, 15 - keylen, "", value, separator); } if (field != NULL) goto end; while (params != NULL) { struct param *p = params; params = p->next; if (p->param == NULL) printf("%-16s%.*s:%.*s%c", "parm:", p->namelen, p->name, p->typelen, p->type, separator); else if (p->type != NULL) printf("%-16s%.*s:%.*s (%.*s)%c", "parm:", p->namelen, p->name, p->paramlen, p->param, p->typelen, p->type, separator); else printf("%-16s%.*s:%.*s%c", "parm:", p->namelen, p->name, p->paramlen, p->param, separator); free(p); } end: while (params != NULL) { void *tmp = params; params = params->next; free(tmp); } kmod_module_info_free_list(list); return err; }