summaryrefslogtreecommitdiffstats
path: root/xtables.c
diff options
context:
space:
mode:
Diffstat (limited to 'xtables.c')
-rw-r--r--xtables.c86
1 files changed, 85 insertions, 1 deletions
diff --git a/xtables.c b/xtables.c
index 667656a..1b65b95 100644
--- a/xtables.c
+++ b/xtables.c
@@ -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;
+}
+