ip6tables-restore.c revision 5065afa11159f4d8cfad672ac01f2958379fad4b
12f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó/* Code to restore the iptables state, from file by ip6tables-save.
22f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * Author:  Andras Kis-Szabo <kisza@sch.bme.hu>
32f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó *
42f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * based on iptables-restore
52f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * Authors:
62f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * 	Harald Welte <laforge@gnumonks.org>
72f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó * 	Rusty Russell <rusty@linuxcare.com.au>
80c4188f446e7c0ed07076c69d1d7f336a92efc8bAndrás Kis-Szabó * This code is distributed under the terms of GNU GPL v2
92f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó *
105065afa11159f4d8cfad672ac01f2958379fad4bMartin Josefsson * $Id: ip6tables-restore.c,v 1.15 2004/01/31 19:28:13 gandalf Exp $
112f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó */
122f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
132f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <getopt.h>
142f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <sys/errno.h>
152f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <string.h>
162f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <stdio.h>
172f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include <stdlib.h>
182f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include "ip6tables.h"
192f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#include "libiptc/libip6tc.h"
202f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
212f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#ifdef DEBUG
222f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
232f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#else
242f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#define DEBUGP(x, args...)
252f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó#endif
262f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
272f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóstatic int binary = 0, counters = 0, verbose = 0, noflush = 0;
282f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
292f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó/* Keeping track of external matches and targets.  */
302f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóstatic struct option options[] = {
312f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	{ "binary", 0, 0, 'b' },
322f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	{ "counters", 0, 0, 'c' },
33ec7897120d739896eff4f9b2c5a1de15364382b7Martin Josefsson	{ "verbose", 0, 0, 'v' },
342f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	{ "help", 0, 0, 'h' },
352f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	{ "noflush", 0, 0, 'n'},
3658918654563975e7bf3a6ec26af92a3bc222c229Harald Welte	{ "modprobe", 1, 0, 'M'},
372f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	{ 0 }
382f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó};
392f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
402f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóstatic void print_usage(const char *name, const char *version) __attribute__((noreturn));
412f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
422f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóstatic void print_usage(const char *name, const char *version)
432f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó{
442f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-h]\n"
452f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			"	   [ --binary ]\n"
462f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			"	   [ --counters ]\n"
472f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			"	   [ --verbose ]\n"
482f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			"	   [ --help ]\n"
4958918654563975e7bf3a6ec26af92a3bc222c229Harald Welte			"	   [ --noflush ]\n"
5058918654563975e7bf3a6ec26af92a3bc222c229Harald Welte		        "          [ --modprobe=<command>]\n", name);
512f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
522f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	exit(1);
532f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó}
542f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
5558918654563975e7bf3a6ec26af92a3bc222c229Harald Welteip6tc_handle_t create_handle(const char *tablename, const char* modprobe)
562f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó{
572f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	ip6tc_handle_t handle;
582f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
592f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	handle = ip6tc_init(tablename);
6058918654563975e7bf3a6ec26af92a3bc222c229Harald Welte
6158918654563975e7bf3a6ec26af92a3bc222c229Harald Welte	if (!handle) {
6297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó		/* try to insmod the module if iptc_init failed */
6397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó		ip6tables_insmod("ip6_tables", modprobe);
6497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó		handle = ip6tc_init(tablename);
6558918654563975e7bf3a6ec26af92a3bc222c229Harald Welte	}
6658918654563975e7bf3a6ec26af92a3bc222c229Harald Welte
672f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	if (!handle) {
682f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		exit_error(PARAMETER_PROBLEM, "%s: unable to initialize"
692f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			"table '%s'\n", program_name, tablename);
702f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		exit(1);
712f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
722f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	return handle;
732f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó}
742f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
752f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóint parse_counters(char *string, struct ip6t_counters *ctr)
762f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó{
772f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	return (sscanf(string, "[%llu:%llu]", &ctr->pcnt, &ctr->bcnt) == 2);
782f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó}
792f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
80885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte/* global new argv and argc */
81885c6eb5ec8a186c77a4710808374dd612e82b20Harald Weltestatic char *newargv[255];
82885c6eb5ec8a186c77a4710808374dd612e82b20Harald Weltestatic int newargc;
83885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
84885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte/* function adding one argument to newargv, updating newargc
8597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó * returns true if argument added, false otherwise */
86885c6eb5ec8a186c77a4710808374dd612e82b20Harald Weltestatic int add_argv(char *what) {
8797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó	DEBUGP("add_argv: %s\n", what);
8897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó	if (what && ((newargc + 1) < sizeof(newargv)/sizeof(char *))) {
8997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó		newargv[newargc] = strdup(what);
9097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó		newargc++;
9197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó		return 1;
9297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó	} else
9397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó		return 0;
94885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte}
95885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
96885c6eb5ec8a186c77a4710808374dd612e82b20Harald Weltestatic void free_argv(void) {
9797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó	int i;
98885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
9997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó	for (i = 0; i < newargc; i++)
10097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó		free(newargv[i]);
101885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte}
102885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
1032f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabóint main(int argc, char *argv[])
1042f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó{
105841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson	ip6tc_handle_t handle = NULL;
1062f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	char buffer[10240];
1072f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	int c;
1082f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	char curtable[IP6T_TABLE_MAXNAMELEN + 1];
1092f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	FILE *in;
11058918654563975e7bf3a6ec26af92a3bc222c229Harald Welte	const char *modprobe = 0;
111a8658ca43fba82f7761f774f4daeb29b3e335053Harald Welte	int in_table = 0;
1122f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1132f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	program_name = "ip6tables-restore";
11480fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte	program_version = IPTABLES_VERSION;
115a8658ca43fba82f7761f774f4daeb29b3e335053Harald Welte	line = 0;
1162f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1173efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte#ifdef NO_SHARED_LIBS
1183efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte	init_extensions();
1193efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte#endif
1203efb6ead2e51fe1eca55bcb2b06afb4dc4b8cb7cHarald Welte
12158918654563975e7bf3a6ec26af92a3bc222c229Harald Welte	while ((c = getopt_long(argc, argv, "bcvhnM:", options, NULL)) != -1) {
1222f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		switch (c) {
1232f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			case 'b':
1242f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				binary = 1;
1252f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				break;
1262f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			case 'c':
1272f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				counters = 1;
1282f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				break;
12997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			case 'v':
13097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				verbose = 1;
13197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				break;
1322f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			case 'h':
1332f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				print_usage("ip6tables-restore",
13480fe35d6339b53a12ddaec41885613e4e37ed031Harald Welte					    IPTABLES_VERSION);
1352f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				break;
1362f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			case 'n':
1372f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				noflush = 1;
1382f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				break;
13958918654563975e7bf3a6ec26af92a3bc222c229Harald Welte			case 'M':
14058918654563975e7bf3a6ec26af92a3bc222c229Harald Welte				modprobe = optarg;
14158918654563975e7bf3a6ec26af92a3bc222c229Harald Welte				break;
1422f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		}
1432f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
1442f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1452f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	if (optind == argc - 1) {
1462f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		in = fopen(argv[optind], "r");
1472f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		if (!in) {
1482f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			fprintf(stderr, "Can't open %s: %s", argv[optind],
1492f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				strerror(errno));
1502f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			exit(1);
1512f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		}
1522f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
1532f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	else if (optind < argc) {
1542f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		fprintf(stderr, "Unknown arguments found on commandline");
1552f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		exit(1);
1562f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
1572f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	else in = stdin;
15897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
1592f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	/* Grab standard input. */
1602f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	while (fgets(buffer, sizeof(buffer), in)) {
1612f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		int ret;
1622f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1632f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		line++;
1645065afa11159f4d8cfad672ac01f2958379fad4bMartin Josefsson		if (buffer[0] == '\n')
1655065afa11159f4d8cfad672ac01f2958379fad4bMartin Josefsson			continue;
1662f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		else if (buffer[0] == '#') {
1672f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (verbose) fputs(buffer, stdout);
1682f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			continue;
169a8658ca43fba82f7761f774f4daeb29b3e335053Harald Welte		} else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
1702f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			DEBUGP("Calling commit\n");
1712f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			ret = ip6tc_commit(&handle);
172a8658ca43fba82f7761f774f4daeb29b3e335053Harald Welte			in_table = 0;
173a8658ca43fba82f7761f774f4daeb29b3e335053Harald Welte		} else if ((buffer[0] == '*') && (!in_table)) {
1742f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			/* New table */
1752f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			char *table;
1762f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1772f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			table = strtok(buffer+1, " \t\n");
1782f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			DEBUGP("line %u, table '%s'\n", line, table);
1792f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (!table) {
1802f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				exit_error(PARAMETER_PROBLEM,
1812f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					"%s: line %u table name invalid\n",
1822f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					program_name, line);
1832f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				exit(1);
1842f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			}
1852f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			strncpy(curtable, table, IP6T_TABLE_MAXNAMELEN);
186073df8feb0a8c4023ce40138e519ac9b341b1ca2Karsten Desler			curtable[IP6T_TABLE_MAXNAMELEN] = '\0';
1872f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
188841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson			if (handle)
189841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson				ip6tc_free(&handle);
190841e4aed2349046eb2c0b1375139c06569a93bd0Martin Josefsson
19158918654563975e7bf3a6ec26af92a3bc222c229Harald Welte			handle = create_handle(table, modprobe);
1922f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (noflush == 0) {
1932f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				DEBUGP("Cleaning all chains of table '%s'\n",
1942f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					table);
1952f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				for_each_chain(flush_entries, verbose, 1,
1962f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						&handle);
1972f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
1982f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				DEBUGP("Deleting all user-defined chains "
1992f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				       "of table '%s'\n", table);
2002f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				for_each_chain(delete_chain, verbose, 0,
2012f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						&handle) ;
2022f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			}
2032f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2042f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			ret = 1;
205a8658ca43fba82f7761f774f4daeb29b3e335053Harald Welte			in_table = 1;
2062f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
207a8658ca43fba82f7761f774f4daeb29b3e335053Harald Welte		} else if ((buffer[0] == ':') && (in_table)) {
2082f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			/* New chain. */
2092f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			char *policy, *chain;
2102f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2112f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			chain = strtok(buffer+1, " \t\n");
2122f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			DEBUGP("line %u, chain '%s'\n", line, chain);
2132f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (!chain) {
2142f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				exit_error(PARAMETER_PROBLEM,
2152f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					   "%s: line %u chain name invalid\n",
2162f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					   program_name, line);
2172f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				exit(1);
2182f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			}
2192f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
220885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte			if (!ip6tc_builtin(chain, handle)) {
22197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				DEBUGP("Creating new chain '%s'\n", chain);
222885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte				if (!ip6tc_create_chain(chain, &handle))
22397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					exit_error(PARAMETER_PROBLEM,
22497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						   "error creating chain "
22597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						   "'%s':%s\n", chain,
22697fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						   strerror(errno));
227885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte			}
2282f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2292f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			policy = strtok(NULL, " \t\n");
2302f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			DEBUGP("line %u, policy '%s'\n", line, policy);
2312f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (!policy) {
2322f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				exit_error(PARAMETER_PROBLEM,
2332f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					   "%s: line %u policy invalid\n",
2342f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					   program_name, line);
2352f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				exit(1);
2362f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			}
2372f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2382f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (strcmp(policy, "-") != 0) {
2392f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				struct ip6t_counters count;
2402f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2412f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				if (counters) {
2422f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					char *ctrs;
2432f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					ctrs = strtok(NULL, " \t\n");
2442f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2452f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					parse_counters(ctrs, &count);
2462f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2472f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				} else {
2482f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					memset(&count, 0,
2492f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					       sizeof(struct ip6t_counters));
2502f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				}
2512f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2522f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				DEBUGP("Setting policy of chain %s to %s\n",
2532f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					chain, policy);
2542f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2552f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				if (!ip6tc_set_policy(chain, policy, &count,
2562f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						     &handle))
2572f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					exit_error(OTHER_PROBLEM,
2582f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						"Can't set policy `%s'"
2592f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						" on `%s' line %u: %s\n",
2602f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						chain, policy, line,
2612f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						ip6tc_strerror(errno));
2622f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			}
2632f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2642f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			ret = 1;
2652f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
266a8658ca43fba82f7761f774f4daeb29b3e335053Harald Welte		} else if (in_table) {
267885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte			int a;
2682f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			char *ptr = buffer;
2692f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			char *pcnt = NULL;
2702f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			char *bcnt = NULL;
27197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			char *parsestart;
272885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
27397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			/* the parser */
27497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			char *param_start, *curchar;
27597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			int quote_open;
276885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
27797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			/* reset the newargv */
27897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			newargc = 0;
2792f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
2802f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (buffer[0] == '[') {
28197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				/* we have counters in our input */
2822f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				ptr = strchr(buffer, ']');
2832f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				if (!ptr)
2842f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					exit_error(PARAMETER_PROBLEM,
2852f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						   "Bad line %u: need ]\n",
2862f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó						   line);
2872f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
288885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte				pcnt = strtok(buffer+1, ":");
28997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				if (!pcnt)
29097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					exit_error(PARAMETER_PROBLEM,
29197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						   "Bad line %u: need :\n",
29297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						   line);
2932f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
294885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte				bcnt = strtok(NULL, "]");
29597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				if (!bcnt)
29697fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					exit_error(PARAMETER_PROBLEM,
29797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						   "Bad line %u: need ]\n",
29897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						   line);
299885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
30097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				/* start command parsing after counter */
30197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				parsestart = ptr + 1;
30297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			} else {
30397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				/* start command parsing at start of line */
30497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				parsestart = buffer;
30597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			}
30697fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
30797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			add_argv(argv[0]);
30897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			add_argv("-t");
30997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			add_argv((char *) &curtable);
31097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
3112f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			if (counters && pcnt && bcnt) {
31297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				add_argv("--set-counters");
31397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				add_argv((char *) pcnt);
31497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				add_argv((char *) bcnt);
3152f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			}
316bb41f8879f5743d683ff3e66ef440b7b7bb5f6d2Harald Welte
31797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			/* After fighting with strtok enough, here's now
31897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			 * a 'real' parser. According to Rusty I'm now no
31997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			 * longer a real hacker, but I can live with that */
32097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
32197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			quote_open = 0;
32297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			param_start = parsestart;
32397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
32497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			for (curchar = parsestart; *curchar; curchar++) {
32597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				if (*curchar == '"') {
32629cdbd047cdc757aec98db308114c1c250ae0d22Michael Rash					/* quote_open cannot be true if there
32729cdbd047cdc757aec98db308114c1c250ae0d22Michael Rash					 * was no previous character.  Thus,
32829cdbd047cdc757aec98db308114c1c250ae0d22Michael Rash					 * curchar-1 has to be within bounds */
32929cdbd047cdc757aec98db308114c1c250ae0d22Michael Rash					if (quote_open &&
33029cdbd047cdc757aec98db308114c1c250ae0d22Michael Rash					    *(curchar-1) != '\\') {
33197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						quote_open = 0;
33297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						*curchar = ' ';
33397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					} else {
33497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						quote_open = 1;
33597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						param_start++;
33697fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					}
33797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				}
33897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				if (*curchar == ' '
33997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				    || *curchar == '\t'
34097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				    || * curchar == '\n') {
34197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					char param_buffer[1024];
34297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					int param_len = curchar-param_start;
34397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
34497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					if (quote_open)
34597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						continue;
34697fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
34797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					if (!param_len) {
34897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						/* two spaces? */
34997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						param_start++;
35097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						continue;
35197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					}
35297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
35397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					/* end of one parameter */
35497fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					strncpy(param_buffer, param_start,
35597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó						param_len);
35697fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					*(param_buffer+param_len) = '\0';
35797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó
35897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					/* check if table name specified */
35948a6f900fa25a4dd2d9b39cff4bf1ab83356d967Harald Welte					if (!strncmp(param_buffer, "-t", 3)
36048a6f900fa25a4dd2d9b39cff4bf1ab83356d967Harald Welte                                            || !strncmp(param_buffer, "--table", 8)) {
361bb41f8879f5743d683ff3e66ef440b7b7bb5f6d2Harald Welte						exit_error(PARAMETER_PROBLEM,
362bb41f8879f5743d683ff3e66ef440b7b7bb5f6d2Harald Welte						   "Line %u seems to have a "
363bb41f8879f5743d683ff3e66ef440b7b7bb5f6d2Harald Welte						   "-t table option.\n", line);
364bb41f8879f5743d683ff3e66ef440b7b7bb5f6d2Harald Welte						exit(1);
365bb41f8879f5743d683ff3e66ef440b7b7bb5f6d2Harald Welte					}
366bb41f8879f5743d683ff3e66ef440b7b7bb5f6d2Harald Welte
36797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					add_argv(param_buffer);
36897fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					param_start += param_len + 1;
36997fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				} else {
37097fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					/* regular character, skip */
37197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				}
37297fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			}
373885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
374885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte			DEBUGP("calling do_command6(%u, argv, &%s, handle):\n",
37597fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó				newargc, curtable);
376885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
37797fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			for (a = 0; a < newargc; a++)
3782f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó				DEBUGP("argv[%u]: %s\n", a, newargv[a]);
3792f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
380885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte			ret = do_command6(newargc, newargv,
38197fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó					 &newargv[2], &handle);
382885c6eb5ec8a186c77a4710808374dd612e82b20Harald Welte
38397fd91a58e7978338451471cfc2cd5ead3b22f26András Kis-Szabó			free_argv();
3842f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		}
3852f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		if (!ret) {
3862f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			fprintf(stderr, "%s: line %u failed\n",
3872f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó					program_name, line);
3882f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó			exit(1);
3892f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó		}
3902f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	}
3912f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó
3922f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó	return 0;
3932f52379841217e55201fbc93872be9a21fa5d443András Kis-Szabó}
394