Search
j0ke.net Open Build Service
>
Projects
>
ha
:
firewall
>
iptables
> iptables-batch.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File iptables-batch.patch of Package iptables
--- Makefile.am +++ Makefile.am @@ -31,6 +31,11 @@ iptables_save_LDFLAGS = ${iptables_LDFLAGS} iptables_save_LDADD = ${iptables_LDADD} +iptables_batch_SOURCES = iptables-batch.c iptables.c xtables.c +iptables_batch_CFLAGS = ${AM_CFLAGS} +iptables_batch_LDFLAGS = ${iptables_LDFLAGS} +iptables_batch_LDADD = ${iptables_LDADD} + # iptables-multi, semi-static iptables_static_SOURCES = ${iptables_multi_SOURCES} iptables_static_CFLAGS = ${iptables_multi_CFLAGS} -DNO_SHARED_LIBS=1 @@ -58,6 +63,11 @@ ip6tables_save_LDFLAGS = ${ip6tables_LDFLAGS} ip6tables_save_LDADD = ${ip6tables_LDADD} +ip6tables_batch_SOURCES = iptables-batch.c ip6tables.c xtables.c +ip6tables_batch_CFLAGS = ${AM_CFLAGS} -DIP6T +ip6tables_batch_LDFLAGS = ${iptables_LDFLAGS} +ip6tables_batch_LDADD = ${iptables_LDADD} + # iptables-multi, semi-static ip6tables_static_SOURCES = ${ip6tables_multi_SOURCES} ip6tables_static_CFLAGS = ${ip6tables_multi_CFLAGS} -DNO_SHARED_LIBS=1 @@ -82,8 +92,8 @@ sbin_PROGRAMS += iptables-static ip6tables-static endif if ENABLE_SHARED -sbin_PROGRAMS += iptables iptables-multi iptables-restore iptables-save \ - ip6tables ip6tables-multi ip6tables-restore ip6tables-save +sbin_PROGRAMS += iptables iptables-multi iptables-restore iptables-save iptables-batch \ + ip6tables ip6tables-multi ip6tables-restore ip6tables-save ip6tables-batch endif iptables.8: ${srcdir}/iptables.8.in extensions/matches4.man extensions/targets4.man --- iptables-batch.c +++ iptables-batch.c @@ -0,0 +1,450 @@ +/* + * Author: Ludwig Nussel <ludwig.nussel@suse.de> + * + * Based on the ipchains code by Paul Russell and Michael Neuling + * + * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>: + * Paul 'Rusty' Russell <rusty@rustcorp.com.au> + * Marc Boucher <marc+nf@mbsi.ca> + * James Morris <jmorris@intercode.com.au> + * Harald Welte <laforge@gnumonks.org> + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> + * + * iptables-batch -- iptables batch processor + * + * See the accompanying manual page iptables(8) for information + * about proper usage of this program. + * + * 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. + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include <xtables.h> +#ifdef IP6T +#include <ip6tables.h> +#else +#include <iptables.h> +#endif + +static char* errstr = NULL; + +static unsigned current_line = 0; + +static char* +skipspace(char* ptr) +{ + while(*ptr && isspace(*ptr)) + ++ptr; + return ptr; +} + +static char* +getliteral(char** ptr) +{ + char* start = *ptr; + char* p = start; + + while(*p && !isspace(*p)) + ++p; + + if(*p) + { + *p = '\0'; + ++p; + } + + *ptr = p; + return start; +} + +static char* +getstring(char** ptr) +{ + char* start = *ptr+1; // skip leading " + char* p = start; + char* o = start; + int backslash = 0; + int done = 0; + + while(*p && !done) + { + if(backslash) + { + backslash = 0; + // no escapes supported, just eat the backslash + *o++ = *p++; + } + else if(*p == '\\') + { + backslash = 1; + p++; + } + else if(*p == '"') + { + done = 1; + } + else + { + *o++ = *p++; + } + } + + if(done) + { + *o = '\0'; + *p = '\0'; + ++p; + *ptr = p; + } + else + { + errstr = "missing \" at end of string"; + start = NULL; + } + return start; +} + +// this is just a very basic method, not 100% shell compatible +static char* +getword(char** ptr) +{ + *ptr = skipspace(*ptr); + if(**ptr == '"') + return getstring(ptr); + return getliteral(ptr); +} + +// destructive +static int +tokenize(int* argc, char* argv[], size_t nargvsize, char* line) +{ + char* ptr = skipspace(line); + int ret = 0; + char* word; + + while(ptr && *ptr) + { + if(*ptr == '#') + break; + if(*argc >= nargvsize) + { + errstr = "too many arguments"; + ret = -1; + break; + } + word = getword(&ptr); + if(!word) + { + ret = -1; + break; + } + argv[(*argc)++] = word; + ++ret; + } + return ret; +} + +#ifdef DEBUG +static void +dumpargv(int argc, char* argv[]) +{ + int i; + for(i=0; i < argc; ++i) + { + printf("%s\"%s\"",i?" ":"", argv[i]); + } + puts(""); +} +#endif + +struct table_handle +{ + char* name; +#ifdef IP6T + ip6tc_handle_t handle; +#else + iptc_handle_t handle; +#endif +}; + +static struct table_handle* tables = NULL; +static unsigned num_tables; +struct table_handle* current_table; + +static void +alloc_tables(void) +{ + tables = realloc(tables, sizeof(struct table_handle) * num_tables); +} + +static void +set_current_table(const char* name) +{ + unsigned i; + + if(!strcmp(name, current_table->name)) // same as last time? + return; + + for(i = 0; i < num_tables; ++i) // find already known table + { + if(!strcmp(name, tables[i].name)) + { + current_table = &tables[i]; + return; + } + } + + // table name not known, create new + i = num_tables++; + alloc_tables(); + current_table = &tables[i]; + current_table->name = strdup(name); + current_table->handle = NULL; +} + +static int +find_table(int argc, char* argv[]) +{ + int i; + for(i = 0; i < argc; ++i) + { + if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--table")) + { + ++i; + if(i >= argc) + { + fprintf(stderr, "line %d: missing table name after %s\n", + current_line, argv[i]); + return 0; + } + set_current_table(argv[i]); + return 1; + } + } + + // no -t specified + set_current_table("filter"); + + return 1; +} + +static int +do_iptables(int argc, char* argv[]) +{ + char *table = "filter"; + int ret = 0; + + if(!find_table(argc, argv)) + return 0; + +#ifdef IP6T + ret = do_command6(argc, argv, &table, ¤t_table->handle); + + if (!ret) + { + fprintf(stderr, "line %d: %s\n", current_line, ip6tc_strerror(errno)); + } + else + { + if(!table || strcmp(table, current_table->name)) + { + fprintf(stderr, "line %d: expected table %s, got %s\n", + current_line, current_table->name, table); + exit(1); + } + } +#else + ret = do_command(argc, argv, &table, ¤t_table->handle); + + if (!ret) + { + fprintf(stderr, "line %d: %s\n", current_line, iptc_strerror(errno)); + } + else + { + if(!table || strcmp(table, current_table->name)) + { + fprintf(stderr, "line %d: expected table %s, got %s\n", + current_line, current_table->name, table); + exit(1); + } + } +#endif + + return ret; +} + +static int +do_commit(void) +{ + unsigned i; + int ret = 1; + + for(i = 0; i < num_tables; ++i) + { + if(tables[i].handle) + { +#ifdef IP6T + if(!ip6tc_commit(&tables[i].handle)) + { + fprintf(stderr, "commit failed on table %s: %s\n", tables[i].name, ip6tc_strerror(errno)); + ret = 0; + } +#else + if(!iptc_commit(&tables[i].handle)) + { + fprintf(stderr, "commit failed on table %s: %s\n", tables[i].name, iptc_strerror(errno)); + ret = 0; + } +#endif + } + } + + return ret; +} + +static void +help(void) +{ + fprintf(stderr, "Usage: %s [FILE]\n\n", program_name); + puts("Read iptables commands from FILE, commit them at EOF\n"); + puts("In addition to normal iptables calls the commands"); + puts("'commit' and 'exit' are understood."); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + int ret = 1; + int numtok; + size_t llen = 0; + char* line = NULL; + ssize_t r = -1; + int nargc = 0; + char* nargv[256]; + FILE* fp = stdin; + +#ifdef IP6T + program_name = "ip6tables-batch"; +#else + program_name = "iptables-batch"; +#endif + lib_dir = getenv("XTABLES_LIBDIR"); + if (!lib_dir) + lib_dir = XTABLES_LIBDIR; + program_version = XTABLES_VERSION; + +#ifdef NO_SHARED_LIBS + init_extensions(); +#endif + if(argc > 1) + { + if(!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) + { + help(); + } + else if(strcmp(argv[1], "-")) + { + fp = fopen(argv[1], "r"); + if(!fp) + { + perror("fopen"); + exit(1); + } + } + } + + num_tables = 4; + alloc_tables(); + tables[0].name = "filter"; + tables[0].handle = NULL; + tables[1].name = "mangle"; + tables[1].handle = NULL; + tables[2].name = "nat"; + tables[2].handle = NULL; + tables[3].name = "raw"; + tables[3].handle = NULL; + current_table = &tables[0]; + + while((r = getline(&line, &llen, fp)) != -1) + { + if(llen < 1 || !*line) + continue; + if(line[strlen(line)-1] == '\n') + line[strlen(line) -1 ] = '\0'; + + ++current_line; + nargc = 0; + errstr = NULL; + numtok = tokenize(&nargc, nargv, (sizeof(nargv)/sizeof(nargv[0])), line); + if(numtok == -1) + { + } + else if (numtok == 0) + { + continue; + } + else if(nargc < 1) + { + errstr = "insufficient number of arguments"; + } + + if(errstr) + { + fprintf(stderr, "parse error in line %d: %s\n", current_line, errstr); + ret = 0; + break; + } + +#ifdef DEBUG + dumpargv(nargc, nargv); +#endif + +#ifdef IP6T + if(!strcmp(nargv[0], "ip6tables")) +#else + if(!strcmp(nargv[0], "iptables")) +#endif + { + ret = do_iptables(nargc, nargv); + if(!ret) break; + } + else if(!strcmp(nargv[0], "exit")) + { + break; + } + else if(!strcmp(nargv[0], "commit")) + { + ret = do_commit(); + if(!ret) break; + } + else + { + fprintf(stderr, "line %d: invalid command '%s'\n", current_line, nargv[0]); + } + } + + if(ret) + ret = do_commit(); + + exit(!ret); +}