All of lore.kernel.org
 help / color / mirror / Atom feed
* iptables-batch 2nd try
@ 2005-04-21 12:20 Ludwig Nussel
  2005-04-24 16:21 ` Patrick McHardy
  0 siblings, 1 reply; 7+ messages in thread
From: Ludwig Nussel @ 2005-04-21 12:20 UTC (permalink / raw)
  To: netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 10241 bytes --]

Hi,

Another attempt, this time the commits for the tables are done at
the end like with iptables-restore. The purpose of this exercise is
to speed up an existing shell script (SuSEfirewall2) by writing
iptables calls into a file and run iptables-batch at the end instead of
fork/exec all the time. The script doesn't need to be changed much
for that, one basically just needs to redefine iptables as shell
function. If iptables-batch is not available the script can
transparently fall back to individual iptables calls.

cu
Ludwig

Index: iptables-1.3.1/iptables-batch.c
===================================================================
--- /dev/null
+++ iptables-1.3.1/iptables-batch.c
@@ -0,0 +1,443 @@
+/*
+ * 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 -- IP firewall administration for kernels with
+ *	firewall table (aimed for the 2.3 kernels)
+ *
+ *	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>
+
+#ifdef IP6T_LIB_DIR
+#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;
+}
+
+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_LIB_DIR
+	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()
+{
+	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_LIB_DIR
+	ret = do_command6(argc, argv, &table, &current_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, &current_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()
+{
+	unsigned i;
+	int ret = 1;
+
+	for(i = 0; i < num_tables; ++i)
+	{
+		if(tables[i].handle)
+		{
+#ifdef IP6T_LIB_DIR
+			ret &= ip6tc_commit(&tables[i].handle);
+#else
+			ret &= iptc_commit(&tables[i].handle);
+#endif
+		}
+	}
+
+	return ret;
+}
+
+static void
+help()
+{
+	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;
+	size_t llen = 0;
+	char* line = NULL;
+	ssize_t r = -1;
+	int nargc = 0;
+	char* nargv[256];
+	FILE* fp = stdin;
+
+#ifdef IP6T_LIB_DIR
+	program_name = "ip6tables-batch";
+
+	lib_dir = getenv("IP6TABLES_LIB_DIR");
+	if (!lib_dir)
+		lib_dir = IP6T_LIB_DIR;
+#else
+	program_name = "iptables-batch";
+
+	lib_dir = getenv("IPTABLES_LIB_DIR");
+	if (!lib_dir)
+		lib_dir = IPT_LIB_DIR;
+#endif
+	program_version = IPTABLES_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 = 3;
+	alloc_tables();
+	tables[0].name = strdup("filter");
+	tables[0].handle = NULL;
+	tables[1].name = strdup("mangle");
+	tables[1].handle = NULL;
+	tables[2].name = strdup("nat");
+	tables[2].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;
+		ret = tokenize(&nargc, nargv, (sizeof(nargv)/sizeof(nargv[0])), line);
+		if(ret == -1)
+		{
+		}
+		else if (ret == 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_LIB_DIR
+		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);
+}
Index: iptables-1.3.1/Makefile
===================================================================
--- iptables-1.3.1.orig/Makefile
+++ iptables-1.3.1/Makefile
@@ -130,6 +130,12 @@ iptables: iptables-standalone.c iptables
 	$(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
 endif
 
+iptables-batch: iptables-batch.c iptables.o $(STATIC_LIBS) libiptc/libiptc.a
+	$(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+ip6tables-batch: iptables-batch.c ip6tables.o $(STATIC6_LIBS) libiptc/libiptc.a
+	$(CC) $(CFLAGS) -DIP6T_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
 $(DESTDIR)$(BINDIR)/iptables: iptables
 	@[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
 	cp $< $@

-- 
 (o_   Ludwig Nussel
 //\   SUSE LINUX Products GmbH, Development
 V_/_  http://www.suse.de/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: iptables-batch 2nd try
  2005-04-21 12:20 iptables-batch 2nd try Ludwig Nussel
@ 2005-04-24 16:21 ` Patrick McHardy
  2005-04-27 12:58   ` Ludwig Nussel
  0 siblings, 1 reply; 7+ messages in thread
From: Patrick McHardy @ 2005-04-24 16:21 UTC (permalink / raw)
  To: Ludwig Nussel; +Cc: netfilter-devel

Ludwig Nussel wrote:
> Hi,
> 
> Another attempt, this time the commits for the tables are done at
> the end like with iptables-restore. The purpose of this exercise is
> to speed up an existing shell script (SuSEfirewall2) by writing
> iptables calls into a file and run iptables-batch at the end instead of
> fork/exec all the time. The script doesn't need to be changed much
> for that, one basically just needs to redefine iptables as shell
> function. If iptables-batch is not available the script can
> transparently fall back to individual iptables calls.

Sounds reasonable, but I'm not very familiar with the iptables code,
so I'll wait for others to comment before applying it.

> +	num_tables = 3;
> +	alloc_tables();
> +	tables[0].name = strdup("filter");
> +	tables[0].handle = NULL;
> +	tables[1].name = strdup("mangle");
> +	tables[1].handle = NULL;
> +	tables[2].name = strdup("nat");
> +	tables[2].handle = NULL;
> +	current_table = &tables[0];

The raw table is missing.

Regards
Patrick

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: iptables-batch 2nd try
  2005-04-24 16:21 ` Patrick McHardy
@ 2005-04-27 12:58   ` Ludwig Nussel
  2005-05-06 11:41     ` Harald Welte
  0 siblings, 1 reply; 7+ messages in thread
From: Ludwig Nussel @ 2005-04-27 12:58 UTC (permalink / raw)
  To: netfilter-devel

Patrick McHardy wrote:
> Ludwig Nussel wrote:
> [...]
> >+	num_tables = 3;
> >+	alloc_tables();
> >+	tables[0].name = strdup("filter");
> >+	tables[0].handle = NULL;
> >+	tables[1].name = strdup("mangle");
> >+	tables[1].handle = NULL;
> >+	tables[2].name = strdup("nat");
> >+	tables[2].handle = NULL;
> >+	current_table = &tables[0];
> 
> The raw table is missing.

Entries for missing tables are allocated when need. Doesn't hurt to
have it though. Here is an updated patch. I also removed the strdup.
It's not needed, the memory is not freed manually anyways.

Index: iptables-1.3.1/iptables-batch.c
===================================================================
--- /dev/null
+++ iptables-1.3.1/iptables-batch.c
@@ -0,0 +1,454 @@
+/*
+ * 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 -- IP firewall administration for kernels with
+ *	firewall table (aimed for the 2.3 kernels)
+ *
+ *	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>
+
+#ifdef IP6T_LIB_DIR
+#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;
+}
+
+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_LIB_DIR
+	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()
+{
+	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_LIB_DIR
+	ret = do_command6(argc, argv, &table, &current_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, &current_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()
+{
+	unsigned i;
+	int ret = 1;
+
+	for(i = 0; i < num_tables; ++i)
+	{
+		if(tables[i].handle)
+		{
+#ifdef IP6T_LIB_DIR
+			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()
+{
+	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_LIB_DIR
+	program_name = "ip6tables-batch";
+
+	lib_dir = getenv("IP6TABLES_LIB_DIR");
+	if (!lib_dir)
+		lib_dir = IP6T_LIB_DIR;
+#else
+	program_name = "iptables-batch";
+
+	lib_dir = getenv("IPTABLES_LIB_DIR");
+	if (!lib_dir)
+		lib_dir = IPT_LIB_DIR;
+#endif
+	program_version = IPTABLES_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_LIB_DIR
+		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);
+}
Index: iptables-1.3.1/Makefile
===================================================================
--- iptables-1.3.1.orig/Makefile
+++ iptables-1.3.1/Makefile
@@ -130,6 +130,12 @@ iptables: iptables-standalone.c iptables
 	$(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
 endif
 
+iptables-batch: iptables-batch.c iptables.o $(STATIC_LIBS) libiptc/libiptc.a
+	$(CC) $(CFLAGS) -DIPT_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+ip6tables-batch: iptables-batch.c ip6tables.o $(STATIC6_LIBS) libiptc/libiptc.a
+	$(CC) $(CFLAGS) -DIP6T_LIB_DIR=\"$(IPT_LIBDIR)\" $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
 $(DESTDIR)$(BINDIR)/iptables: iptables
 	@[ -d $(DESTDIR)$(BINDIR) ] || mkdir -p $(DESTDIR)$(BINDIR)
 	cp $< $@

cu
Ludwig

-- 
 (o_   Ludwig Nussel
 //\   SUSE LINUX Products GmbH, Development
 V_/_  http://www.suse.de/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: iptables-batch 2nd try
  2005-04-27 12:58   ` Ludwig Nussel
@ 2005-05-06 11:41     ` Harald Welte
  2005-05-09  8:56       ` Ludwig Nussel
  0 siblings, 1 reply; 7+ messages in thread
From: Harald Welte @ 2005-05-06 11:41 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Ludwig Nussel

[-- Attachment #1: Type: text/plain, Size: 1826 bytes --]

Hi Ludwig!

Sorry for my delayed response.

On Wed, Apr 27, 2005 at 02:58:08PM +0200, Ludwig Nussel wrote:
> + *	iptables -- IP firewall administration for kernels with
> + *	firewall table (aimed for the 2.3 kernels)
> + *
> + *	See the accompanying manual page iptables(8) for information
> + *	about proper usage of this program.

well those two comments are no longer valid, that's for sure ;)
> +	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);

So why don't you put some simple parser/converter in front of
iptables-restore?  I mean, iptables-restore does pretty much the same,
just that it expects the input format to be something different than a
shell script.

Those differences should be quite easy to convert (probably even in some
shell or perl script).  Basically all you need to do is to remove the
"iptables" from the beginning of the command, and add the COMMIT line at
the end.  Even though "-P" and "-N" are not used.

Please correct me if I'm missing something completely.

My main objective is that the functionality between iptables-restore and
iptables-batch is pretty much the same.  I think either a converter
before iptables-restore, or modifications to iptables-restore would be a
better way.

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: iptables-batch 2nd try
  2005-05-06 11:41     ` Harald Welte
@ 2005-05-09  8:56       ` Ludwig Nussel
  2005-05-09  9:02         ` Harald Welte
  0 siblings, 1 reply; 7+ messages in thread
From: Ludwig Nussel @ 2005-05-09  8:56 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Harald Welte

Harald Welte wrote:
> On Wed, Apr 27, 2005 at 02:58:08PM +0200, Ludwig Nussel wrote:
> ...
> > +	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);
> 
> So why don't you put some simple parser/converter in front of
> iptables-restore?  I mean, iptables-restore does pretty much the same,
> just that it expects the input format to be something different than a
> shell script.
> 
> Those differences should be quite easy to convert (probably even in some
> shell or perl script).  Basically all you need to do is to remove the
> "iptables" from the beginning of the command, and add the COMMIT line at
> the end.  Even though "-P" and "-N" are not used.

That was my first approach but the startup costs for perl are too
high. So you'd need to write the converter in e.g. C. But then it
doesn't make much sense to print text that is parsed by
iptables-restore again when you can just do the appropriate calls
yourself. The disadvantage is that you need to build iptables-batch
inside iptables since there doesn't seem to be an external library.

> My main objective is that the functionality between iptables-restore and
> iptables-batch is pretty much the same.  I think either a converter
> before iptables-restore, or modifications to iptables-restore would be a
> better way.

There isn't much code to share between iptables-restore and
iptables-batch. Although the functionality is similar they work
differently.

cu
Ludwig

-- 
 (o_   Ludwig Nussel
 //\   SUSE LINUX Products GmbH, Development
 V_/_  http://www.suse.de/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: iptables-batch 2nd try
  2005-05-09  8:56       ` Ludwig Nussel
@ 2005-05-09  9:02         ` Harald Welte
  2005-05-09  9:45           ` Ludwig Nussel
  0 siblings, 1 reply; 7+ messages in thread
From: Harald Welte @ 2005-05-09  9:02 UTC (permalink / raw)
  To: netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 998 bytes --]

On Mon, May 09, 2005 at 10:56:03AM +0200, Ludwig Nussel wrote:
> 
> > My main objective is that the functionality between iptables-restore and
> > iptables-batch is pretty much the same.  I think either a converter
> > before iptables-restore, or modifications to iptables-restore would be a
> > better way.
> 
> There isn't much code to share between iptables-restore and
> iptables-batch. Although the functionality is similar they work
> differently.
 
The question would then rather be: why is there no code share since the
functionality is similar? ;)

I'm honestly interested in the technical reasons.  

-- 
- Harald Welte <laforge@netfilter.org>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: iptables-batch 2nd try
  2005-05-09  9:02         ` Harald Welte
@ 2005-05-09  9:45           ` Ludwig Nussel
  0 siblings, 0 replies; 7+ messages in thread
From: Ludwig Nussel @ 2005-05-09  9:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Harald Welte

Harald Welte wrote:
> On Mon, May 09, 2005 at 10:56:03AM +0200, Ludwig Nussel wrote:
> > 
> > > My main objective is that the functionality between iptables-restore and
> > > iptables-batch is pretty much the same.  I think either a converter
> > > before iptables-restore, or modifications to iptables-restore would be a
> > > better way.
> > 
> > There isn't much code to share between iptables-restore and
> > iptables-batch. Although the functionality is similar they work
> > differently.
>  
> The question would then rather be: why is there no code share since the
> functionality is similar? ;)

Hmm. Both read a file line by line and split it into words.

iptables-batch then searches for -t to select the correct handle
that is passed to do_command(). Allocation of the handle is left to
do_command(). At EOF (or when reading "commit") it calls
iptc_commit() on each handle. That's it. If you want to flush tables
you have to add "iptables -F" lines yourself.

iptables-restore has a special syntax for manually creating a single
handle, creating chains and set their policy and for setting
counters. One needs to COMMIT before switching to another table. A
global setting determines whether all tables are flushed when a
handle for them is allocated.

So IMHO all that can be shared are some lines initialization
(getenv(), init_extensions()) and maybe the tokenizer. All the other
code would need to be inside a if(batch) {...} else if (restore){...}

cu
Ludwig

-- 
 (o_   Ludwig Nussel
 //\   SUSE LINUX Products GmbH, Development
 V_/_  http://www.suse.de/

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-05-09  9:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-04-21 12:20 iptables-batch 2nd try Ludwig Nussel
2005-04-24 16:21 ` Patrick McHardy
2005-04-27 12:58   ` Ludwig Nussel
2005-05-06 11:41     ` Harald Welte
2005-05-09  8:56       ` Ludwig Nussel
2005-05-09  9:02         ` Harald Welte
2005-05-09  9:45           ` Ludwig Nussel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.