diff options
Diffstat (limited to 'xtables.c')
-rw-r--r-- | xtables.c | 86 |
1 files changed, 85 insertions, 1 deletions
@@ -16,14 +16,27 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#include <dlfcn.h> #include <errno.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> #include <iptables_common.h> #include <xtables.h> +#ifndef PROC_SYS_MODPROBE +#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" +#endif + +/* the path to command to load kernel module */ +const char *modprobe = NULL; + void *fw_calloc(size_t count, size_t size) { void *p; @@ -47,3 +60,74 @@ void *fw_malloc(size_t size) return p; } + +static char *get_modprobe(void) +{ + int procfile; + char *ret; + +#define PROCFILE_BUFSIZ 1024 + procfile = open(PROC_SYS_MODPROBE, O_RDONLY); + if (procfile < 0) + return NULL; + + ret = (char *) malloc(PROCFILE_BUFSIZ); + if (ret) { + memset(ret, 0, PROCFILE_BUFSIZ); + switch (read(procfile, ret, PROCFILE_BUFSIZ)) { + case -1: goto fail; + case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */ + } + if (ret[strlen(ret)-1]=='\n') + ret[strlen(ret)-1]=0; + close(procfile); + return ret; + } + fail: + free(ret); + close(procfile); + return NULL; +} + +int xtables_insmod(const char *modname, const char *modprobe, int quiet) +{ + char *buf = NULL; + char *argv[4]; + int status; + + /* If they don't explicitly set it, read out of kernel */ + if (!modprobe) { + buf = get_modprobe(); + if (!buf) + return -1; + modprobe = buf; + } + + switch (fork()) { + case 0: + argv[0] = (char *)modprobe; + argv[1] = (char *)modname; + if (quiet) { + argv[2] = "-q"; + argv[3] = NULL; + } else { + argv[2] = NULL; + argv[3] = NULL; + } + execv(argv[0], argv); + + /* not usually reached */ + exit(1); + case -1: + return -1; + + default: /* parent */ + wait(&status); + } + + free(buf); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + return 0; + return -1; +} + |