diff --git a/server/include/checks.h b/server/include/checks.h index b9df6731f..b4089554e 100644 --- a/server/include/checks.h +++ b/server/include/checks.h @@ -34,6 +34,14 @@ int check_kernel_cmdline(); */ int check_kernel_version(); +/** Checks if a kernel module is loaded + * + * @param module the name of the module + * @retval 0 Module is loaded. + * @reval <>0 Module is not loaded. + */ +int check_kernel_module(char *module); + /** Check if program is running with super user (root) privileges. * * diff --git a/server/include/config.h b/server/include/config.h index 7cc6031fc..5a54b960e 100644 --- a/server/include/config.h +++ b/server/include/config.h @@ -36,12 +36,15 @@ #define IPPROTO_S2SS 137 #define ETH_P_S2SS 0xBABE +#define SYSFS_PATH "/sys" +#define PROCFS_PATH "/proc" + /* Checks */ #define KERNEL_VERSION_MAJ 3 #define KERNEL_VERSION_MIN 4 #ifndef LICENSE_VALID - #define LICENSE_VALID 0 + #define LICENSE_VALID 0 #endif #define LICENSE_CHECKS \ { { "/sys/class/dmi/id/product_uuid", "5002E503-4904-EB05-7406-0C0700080009" }, \ diff --git a/server/include/utils.h b/server/include/utils.h index 461a49bb6..2b1d53be9 100644 --- a/server/include/utils.h +++ b/server/include/utils.h @@ -103,9 +103,6 @@ cpu_set_t to_cpu_set(int set); /** Allocate and initialize memory. */ void * alloc(size_t bytes); -/** A system(2) emulator with popen / pclose(2) and proper output handling */ -int system2(const char* cmd, ...); - /** Call quit() in the main thread. */ void die(); diff --git a/server/src/checks.c b/server/src/checks.c index b52c2f235..764238d99 100644 --- a/server/src/checks.c +++ b/server/src/checks.c @@ -36,14 +36,14 @@ int check_kernel_version() int check_kernel_rtpreempt() { - return access("/sys/kernel/realtime", R_OK); + return access(SYSFS_PATH "/kernel/realtime", R_OK); } int check_kernel_cmdline() { char cmd[512]; - FILE *f = fopen("/proc/cmdline", "r"); + FILE *f = fopen(PROCFS_PATH "/cmdline", "r"); if (!f) return -1; @@ -53,6 +53,29 @@ int check_kernel_cmdline() return strstr(cmd, "isolcpus=") ? 0 : -1; } +int check_kernel_module(char *module) +{ + FILE *f; + int ret = -1; + char *line = NULL; + size_t len = 0; + + if (!(f = fopen(PROCFS_PATH "/modules", "r"))) + return -1; + + while (getline(&line, &len, f) >= 0) { + if (strstr(line, module) == line) { + ret = 0; + break; + } + } + + free(line); + fclose(f); + + return ret; +} + int check_root() { return getuid(); diff --git a/server/src/gtfpga.c b/server/src/gtfpga.c index 1a07e1beb..4f5c50103 100644 --- a/server/src/gtfpga.c +++ b/server/src/gtfpga.c @@ -17,8 +17,7 @@ #include "gtfpga.h" #include "utils.h" #include "timing.h" - -#define SYSFS_PATH "/sys/bus/pci" +#include "checks.h" static struct pci_access *pacc; @@ -122,20 +121,16 @@ static int gtfpga_load_driver(struct pci_dev *d) { FILE *f; char slot[16]; - int ret; + + if (check_kernel_module("uio_pci_generic")) + error("Missing kernel module: uio_pci_generic"); /* Prepare slot identifier */ snprintf(slot, sizeof(slot), "%04x:%02x:%02x.%x", d->domain, d->bus, d->dev, d->func); - /* Load uio_pci_generic module */ - ret = system2("modprobe uio_pci_generic"); - if (ret) - serror("Failed to load module"); - /* Add new ID to uio_pci_generic */ - f = fopen(SYSFS_PATH "/drivers/uio_pci_generic/new_id", "w"); - if (!f) + if (!(f = fopen(SYSFS_PATH "/bus/pci/drivers/uio_pci_generic/new_id", "w"))) serror("Failed to add PCI id to uio_pci_generic driver"); debug(5, "Adding ID to uio_pci_generic module: %04x %04x", d->vendor_id, d->device_id); diff --git a/server/src/if.c b/server/src/if.c index 28125c253..034824b62 100644 --- a/server/src/if.c +++ b/server/src/if.c @@ -21,6 +21,7 @@ #include "nl.h" #include "socket.h" #include "utils.h" +#include "checks.h" /** Linked list of interfaces. */ struct list interfaces; @@ -71,6 +72,14 @@ int if_start(struct interface *i, int affinity) if (mark == 0) return 0; + /* Check if all kernel modules are loaded */ + if (check_kernel_module("sch_prio")) + error("Missing kernel module: sch_prio"); + if (check_kernel_module("sch_netem")) + error("Missing kernel module: sch_netem"); + if (check_kernel_module("cls_fw")) + error("Missing kernel module: cls_fw"); + /* Replace root qdisc */ if ((ret = tc_prio(i, &i->tc_qdisc, TC_HANDLE(1, 0), TC_H_ROOT, mark))) ;//error("Failed to setup priority queuing discipline: %s", nl_geterror(ret)); diff --git a/server/src/utils.c b/server/src/utils.c index 5b5598a0a..9ff54159f 100644 --- a/server/src/utils.c +++ b/server/src/utils.c @@ -119,29 +119,3 @@ void * alloc(size_t bytes) return p; } - -/** @todo: Proper way: create additional pipe for stderr in child process */ -int system2(const char *cmd, ...) -{ - va_list ap; - char buf[1024]; - - va_start(ap, cmd); - vsnprintf(buf, sizeof(buf), cmd, ap); - va_end(ap); - - strap(buf, sizeof(buf), " 2>&1", sizeof(buf)); /* redirect stderr to stdout */ - - debug(1, "System: %s", buf); - - FILE *f = popen(buf, "r"); - if (f == NULL) - serror("Failed to execute: '%s'", cmd); - - while (!feof(f) && fgets(buf, sizeof(buf), f) != NULL) { INDENT - strtok(buf, "\n"); /* strip trailing newline */ - info(buf); - } - - return pclose(f); -}