From c853103ac6550cf6f77e144a215c0c61e06c5703 Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Fri, 14 Jun 2002 21:55:29 +0000 Subject: Try to autoload ebtables kernel module when needed. --- ebtables.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/ebtables.c b/ebtables.c index dddb623..061ed4d 100644 --- a/ebtables.c +++ b/ebtables.c @@ -34,11 +34,22 @@ #include #include #include "include/ebtables_u.h" +#include +#include +#include +#include +#include +#include +#include // here are the number-name correspondences kept for the ethernet // frame type field #define PROTOCOLFILE "/etc/ethertypes" +#ifndef PROC_SYS_MODPROBE +#define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" +#endif + #define DATABASEHOOKNR NF_BR_NUMHOOKS #define DATABASEHOOKNAME "DB" @@ -79,6 +90,7 @@ static struct option ebt_original_options[] = { { "destination" , required_argument, 0, 'd' }, { "dst" , required_argument, 0, 'd' }, { "table" , required_argument, 0, 't' }, + { "modprobe" , required_argument, 0, 'M' }, { 0 } }; @@ -326,6 +338,69 @@ void register_table(struct ebt_u_table *t) tables = t; } +// blatently stolen (again) from iptables.c userspace program +// find out where the modprobe utility is located +static char *get_modprobe(void) +{ + int procfile; + char *ret; + + procfile = open(PROC_SYS_MODPROBE, O_RDONLY); + if (procfile < 0) + return NULL; + + ret = malloc(1024); + if (ret) { + switch (read(procfile, ret, 1024)) { + case -1: goto fail; + case 1024: 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; +} + +// I hate stealing, really... Lets call it a tribute. +int ebtables_insmod(const char *modname, const char *modprobe) +{ + char *buf = NULL; + char *argv[3]; + + /* 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; + argv[2] = NULL; + execv(argv[0], argv); + + /* not usually reached */ + exit(0); + case -1: + return -1; + + default: /* parent */ + wait(NULL); + } + + free(buf); + return 0; +} + + // used to parse /etc/etherproto int disregard_whitespace(char *buffer, FILE *ifp) { @@ -631,6 +706,7 @@ void print_help() "--out-if -o [!] name : network output interface name\n" "--logical-in [!] name : logical bridge input interface name\n" "--logical-out [!] name : logical bridge output interface name\n" +"--modprobe -M : try to insert modules using this command\n" "--version -V : print package version\n" "\n" , prog_name, @@ -1206,6 +1282,7 @@ int main(int argc, char *argv[]) struct ebt_u_watcher *w; struct ebt_u_match_list *m_l; struct ebt_u_watcher_list *w_l; + const char *modprobe = NULL; // initialize the table name, OPT_ flags, selected hook and command strcpy(replace.name, "filter"); @@ -1221,7 +1298,7 @@ int main(int argc, char *argv[]) // getopt saves the day while ((c = getopt_long(argc, argv, - "-A:D:I:L::Z::F::P:Vhi:o:j:p:b:s:d:t:", ebt_options, NULL)) != -1) { + "-A:D:I:L::Z::F::P:Vhi:o:j:p:b:s:d:t:M:", ebt_options, NULL)) != -1) { switch (c) { case 'A': // add a rule @@ -1312,6 +1389,10 @@ int main(int argc, char *argv[]) printf("%s, %s\n", prog_name, prog_version); exit(0); + case 'M': // modprobe + modprobe = optarg; + break; + case 'h': // help if (replace.flags & OPT_COMMAND) print_error("Multiple commands not allowed"); @@ -1600,7 +1681,12 @@ int main(int argc, char *argv[]) new_entry->ethproto = htons(new_entry->ethproto); // get the kernel's information - get_table(&replace); + if (get_table(&replace)) { + ebtables_insmod("ebtables", modprobe); + if (get_table(&replace)) + print_error("can't initialize ebtables table %s", + replace.name); + } // check if selected_hook is a valid_hook if (replace.selected_hook >= 0 && !(replace.valid_hooks & (1 << replace.selected_hook))) -- cgit v1.2.3