From 98984a8c623b592ddfb3b30ac92615422849eab3 Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Wed, 19 Jan 2005 21:09:05 +0000 Subject: add ebtablesu scheme, along with general cleanup --- userspace/ebtables2/ebtablesd.c | 367 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 367 insertions(+) create mode 100644 userspace/ebtables2/ebtablesd.c (limited to 'userspace/ebtables2/ebtablesd.c') diff --git a/userspace/ebtables2/ebtablesd.c b/userspace/ebtables2/ebtablesd.c new file mode 100644 index 0000000..1f60791 --- /dev/null +++ b/userspace/ebtables2/ebtablesd.c @@ -0,0 +1,367 @@ +/* + * ebtablesd.c, January 2005 + * + * Author: Bart De Schuymer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "include/ebtables_u.h" + +#define OPT_KERNELDATA 0x800 /* Also defined in ebtables.c */ + +static struct ebt_u_replace replace[3]; +#define OPEN_METHOD_FILE 1 +#define OPEN_METHOD_KERNEL 2 +static int open_method[3]; +void ebt_early_init_once(); + +static void sigpipe_handler(int sig) +{ +} + +int main(int argc_, char *argv_[]) +{ + char *argv[EBTD_ARGC_MAX], *args[4], name[] = "mkdir", + mkdir_option[] = "-p", mkdir_dir[] = EBTD_PIPE_DIR, + cmdline[EBTD_CMDLINE_MAXLN]; + int readfd, stop = 0, base = 0, offset = 0, n = 0, ret = 0; + + /* Make sure the pipe directory exists */ + args[0] = name; + args[1] = mkdir_option; + args[2] = mkdir_dir; + args[3] = NULL; + switch (fork()) { + case 0: + execvp(args[0], args); + + /* Not usually reached */ + exit(0); + case -1: + return -1; + + default: /* Parent */ + wait(NULL); + } + + if (mkfifo(EBTD_PIPE, 0600) < 0 && errno != EEXIST) { + printf("Error creating FIFO " EBTD_PIPE "\n"); + ret = -1; + goto do_exit; + } + + if ((readfd = open(EBTD_PIPE, O_RDONLY | O_NONBLOCK, 0)) == -1) { + perror("open"); + ret = -1; + goto do_exit; + } + + if (signal(SIGPIPE, sigpipe_handler) == SIG_ERR) { + perror("signal"); + ret = -1; + goto do_exit; + } + + ebt_silent = 1; + + strcpy(replace[0].name, "filter"); + strcpy(replace[1].name, "nat"); + strcpy(replace[2].name, "broute"); + + ebt_early_init_once(); + + while (!stop) { + int n2, i, argc, table_nr, ntot; + + /* base == 0 */ + ntot = read(readfd, cmdline+offset, EBTD_CMDLINE_MAXLN-offset-1); + if (ntot <= 0) + continue; + ntot += offset; +continue_read: + /* Change all ' ' into '\0'. This implies that the user is not + * allowed to use spaces (that don't distinguish options or + * commands) in her rules. This comes down to not allowing spaces + * in options like the string of --ulog-prefix (use '_' instead). + */ + for (; offset < ntot; n++, offset++) { + if (cmdline[offset] == ' ') + cmdline[offset] = '\0'; + if (cmdline[offset] == '\n') { + cmdline[offset] = '\0'; + break; + } + } + if (n == 0) { + if (offset == ntot) { + /* The ntot bytes were parsed and ended with '\n' */ + base = 0; + offset = 0; + continue; + } + offset++; + base = offset; + n = 0; + goto continue_read; + } + if (offset == ntot) { /* The ntot bytes were parsed but no complete rule is yet specified */ + if (base == 0) { + ebt_print_error("ebtablesd: the maximum command line length is %d", EBTD_CMDLINE_MAXLN-1); + goto write_msg; + } + memmove(cmdline, cmdline+base+offset, ntot-offset); + offset -= base; + offset++; + base = 0; + continue; + } + + table_nr = 0; + n2 = 0; + argc = 0; + while (n2 < n && argc < EBTD_ARGC_MAX) { + argv[argc++] = cmdline + base + n2; + n2 += strlen(cmdline + base + n2) + 1; + } + offset++; /* Move past the '\n' */ + base = offset; + + if (argc > EBTD_ARGC_MAX) { + ebt_print_error("ebtablesd: maximum %d arguments " + "allowed", EBTD_ARGC_MAX - 1); + goto write_msg; + } + if (argc == 1) { + ebt_print_error("ebtablesd: no arguments"); + goto write_msg; + } + + /* Parse the options */ + if (!strcmp(argv[1], "-t")) { + if (argc < 3) { + ebt_print_error("ebtablesd: -t but no table"); + goto write_msg; + } + for (i = 0; i < 3; i++) + if (!strcmp(replace[i].name, argv[2])) + break; + if (i == 3) { + ebt_print_error("ebtablesd: table '%s' was " + "not recognized", argv[2]); + goto write_msg; + } + table_nr = i; + } else if (!strcmp(argv[1], "free")) { + if (argc != 3) { + ebt_print_error("ebtablesd: command free " + "needs exactly one argument"); + goto write_msg; + } + for (i = 0; i < 3; i++) + if (!strcmp(replace[i].name, argv[2])) + break; + if (i == 3) { + ebt_print_error("ebtablesd: table '%s' was " + "not recognized", argv[2]); + goto write_msg; + } + if (!(replace[i].flags & OPT_KERNELDATA)) { + ebt_print_error("ebtablesd: table %s has not " + "been opened"); + goto write_msg; + } + ebt_cleanup_replace(&replace[i]); + replace[i].flags &= ~OPT_KERNELDATA; + goto write_msg; + } else if (!strcmp(argv[1], "open")) { + if (argc != 3) { + ebt_print_error("ebtablesd: command open " + "needs exactly one argument"); + goto write_msg; + } + + for (i = 0; i < 3; i++) + if (!strcmp(replace[i].name, argv[2])) + break; + if (i == 3) { + ebt_print_error("ebtablesd: table '%s' was " + "not recognized", argv[2]); + goto write_msg; + } + if (replace[i].flags & OPT_KERNELDATA) { + ebt_print_error("ebtablesd: table %s needs to " + "be freed before it can be " + "opened"); + goto write_msg; + } + if (!ebt_get_kernel_table(&replace[i], 0)) { + replace[i].flags |= OPT_KERNELDATA; + open_method[i] = OPEN_METHOD_KERNEL; + } + goto write_msg; + } else if (!strcmp(argv[1], "fopen")) { + struct ebt_u_replace tmp; + + memset(&tmp, 0, sizeof(tmp)); + if (argc != 4) { + ebt_print_error("ebtablesd: command fopen " + "needs exactly two arguments"); + goto write_msg; + } + + for (i = 0; i < 3; i++) + if (!strcmp(replace[i].name, argv[2])) + break; + if (i == 3) { + ebt_print_error("ebtablesd: table '%s' was " + "not recognized", argv[2]); + goto write_msg; + } + if (replace[i].flags & OPT_KERNELDATA) { + ebt_print_error("ebtablesd: table %s needs to " + "be freed before it can be " + "opened"); + goto write_msg; + } + tmp.filename = (char *)malloc(strlen(argv[3]) + 1); + if (!tmp.filename) { + ebt_print_error("Out of memory"); + goto write_msg; + } + strcpy(tmp.filename, argv[3]); + strcpy(tmp.name, "filter"); + tmp.command = 'L'; /* Make sure retrieve_from_file() + * doesn't complain about wrong + * table name */ + + ebt_get_kernel_table(&tmp, 0); + free(tmp.filename); + tmp.filename = NULL; + if (ebt_errormsg[0] != '\0') + goto write_msg; + + if (strcmp(tmp.name, argv[2])) { + ebt_print_error("ebtablesd: opened file with " + "wrong table name '%s'", tmp.name); + ebt_cleanup_replace(&tmp); + goto write_msg; + } + replace[i] = tmp; + replace[i].command = '\0'; + replace[i].flags |= OPT_KERNELDATA; + open_method[i] = OPEN_METHOD_FILE; + goto write_msg; + } else if (!strcmp(argv[1], "commit")) { + if (argc != 3) { + ebt_print_error("ebtablesd: command commit " + "needs exactly one argument"); + goto write_msg; + } + + for (i = 0; i < 3; i++) + if (!strcmp(replace[i].name, argv[2])) + break; + if (i == 3) { + ebt_print_error("ebtablesd: table '%s' was " + "not recognized", argv[2]); + goto write_msg; + } + if (!(replace[i].flags & OPT_KERNELDATA)) { + ebt_print_error("ebtablesd: table %s has not " + "been opened"); + goto write_msg; + } + /* The counters from the kernel are useless if we + * didn't start from a kernel table */ + if (open_method[i] == OPEN_METHOD_FILE) + replace[i].num_counters = 0; + ebt_deliver_table(&replace[i]); + if (ebt_errormsg[0] == '\0' && open_method[i] == OPEN_METHOD_KERNEL) + ebt_deliver_counters(&replace[i], EXEC_STYLE_DAEMON); + goto write_msg; + } else if (!strcmp(argv[1], "fcommit")) { + if (argc != 4) { + ebt_print_error("ebtablesd: command commit " + "needs exactly two argument"); + goto write_msg; + } + + for (i = 0; i < 3; i++) + if (!strcmp(replace[i].name, argv[2])) + break; + if (i == 3) { + ebt_print_error("ebtablesd: table '%s' was " + "not recognized", argv[2]); + goto write_msg; + } + if (!(replace[i].flags & OPT_KERNELDATA)) { + ebt_print_error("ebtablesd: table %s has not " + "been opened"); + goto write_msg; + } + replace[i].filename = (char *)malloc(strlen(argv[3]) + 1); + if (!replace[i].filename) { + ebt_print_error("Out of memory"); + goto write_msg; + } + strcpy(replace[i].filename, argv[3]); + ebt_deliver_table(&replace[i]); + if (ebt_errormsg[0] == '\0' && open_method[i] == OPEN_METHOD_KERNEL) + ebt_deliver_counters(&replace[i], EXEC_STYLE_DAEMON); + free(replace[i].filename); + replace[i].filename = NULL; + goto write_msg; + }else if (!strcmp(argv[1], "quit")) { + if (argc != 2) { + ebt_print_error("ebtablesd: command quit does " + "not take any arguments"); + goto write_msg; + } + stop = 1; + goto write_msg; + } + if (!(replace[table_nr].flags & OPT_KERNELDATA)) { + ebt_print_error("ebtablesd: table %s has not been " + "opened", replace[table_nr].name); + goto write_msg; + } + optind = 1; +printf("jak: ntot = %d, offset = %d, base = %d\n", ntot, offset, base); + do_command(argc, argv, EXEC_STYLE_DAEMON, &replace[table_nr]); + ebt_reinit_extensions(); +write_msg: +#ifndef SILENT_DAEMON + if (ebt_errormsg[0] != '\0') + printf("%s\n", ebt_errormsg); +#endif + ebt_errormsg[0]= '\0'; + n = 0; + goto continue_read; + } +do_exit: + unlink(EBTD_PIPE); + + return 0; +} -- cgit v1.2.3