blob: 9ebc5775b92df7b88ffdd9dd64620cce857da8f9 [file] [log] [blame]
/* Code to restore the iptables state, from file by ip6tables-save.
* Author: Andras Kis-Szabo <kisza@sch.bme.hu>
*
* based on iptables-restore
* Authors:
* Harald Welte <laforge@gnumonks.org>
* Rusty Russell <rusty@linuxcare.com.au>
*
*/
#include <getopt.h>
#include <sys/errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "ip6tables.h"
#include "libiptc/libip6tc.h"
#ifdef DEBUG
#define DEBUGP(x, args...) fprintf(stderr, x, ## args)
#else
#define DEBUGP(x, args...)
#endif
extern int for_each_chain(int (*fn)(const ip6t_chainlabel, int, ip6tc_handle_t *), int verbose, int builtinstoo, ip6tc_handle_t *handle);
extern int flush_entries(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
extern int delete_chain(const ip6t_chainlabel chain, int verbose, ip6tc_handle_t *handle);
static int binary = 0, counters = 0, verbose = 0, noflush = 0;
/* Keeping track of external matches and targets. */
static struct option options[] = {
{ "binary", 0, 0, 'b' },
{ "counters", 0, 0, 'c' },
/* { "verbose", 1, 0, 'v' }, */
{ "help", 0, 0, 'h' },
{ "noflush", 0, 0, 'n'},
{ 0 }
};
static void print_usage(const char *name, const char *version) __attribute__((noreturn));
static void print_usage(const char *name, const char *version)
{
fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-h]\n"
" [ --binary ]\n"
" [ --counters ]\n"
" [ --verbose ]\n"
" [ --help ]\n"
" [ --noflush ]\n", name);
exit(1);
}
ip6tc_handle_t create_handle(const char *tablename)
{
ip6tc_handle_t handle;
handle = ip6tc_init(tablename);
if (!handle) {
exit_error(PARAMETER_PROBLEM, "%s: unable to initialize"
"table '%s'\n", program_name, tablename);
exit(1);
}
return handle;
}
int parse_counters(char *string, struct ip6t_counters *ctr)
{
return (sscanf(string, "[%llu:%llu]", &ctr->pcnt, &ctr->bcnt) == 2);
}
int main(int argc, char *argv[])
{
ip6tc_handle_t handle;
char buffer[10240];
unsigned int line = 0;
int c;
char curtable[IP6T_TABLE_MAXNAMELEN + 1];
char curchain[IP6T_FUNCTION_MAXNAMELEN + 1];
FILE *in;
program_name = "ip6tables-restore";
program_version = NETFILTER_VERSION;
while ((c = getopt_long(argc, argv, "bcvhn", options, NULL)) != -1) {
switch (c) {
case 'b':
binary = 1;
break;
case 'c':
counters = 1;
break;
case 'h':
print_usage("ip6tables-restore",
NETFILTER_VERSION);
break;
case 'n':
noflush = 1;
break;
}
}
if (optind == argc - 1) {
in = fopen(argv[optind], "r");
if (!in) {
fprintf(stderr, "Can't open %s: %s", argv[optind],
strerror(errno));
exit(1);
}
}
else if (optind < argc) {
fprintf(stderr, "Unknown arguments found on commandline");
exit(1);
}
else in = stdin;
/*
handle = iptc_init("filter");
if (!handle)
exit_error(VERSION_PROBLEM,
"can't initialize iptables-restore: %s",
iptc_strerror(errno));
if (!clean_slate(&handle))
exit_error(OTHER_PROBLEM, "Deleting old chains: %s",
iptc_strerror(errno));
*/
/* Grab standard input. */
while (fgets(buffer, sizeof(buffer), in)) {
int ret;
line++;
if (buffer[0] == '\n') continue;
else if (buffer[0] == '#') {
if (verbose) fputs(buffer, stdout);
continue;
} else if (strcmp(buffer, "COMMIT\n") == 0) {
DEBUGP("Calling commit\n");
ret = ip6tc_commit(&handle);
} else if (buffer[0] == '*') {
/* New table */
char *table;
table = strtok(buffer+1, " \t\n");
DEBUGP("line %u, table '%s'\n", line, table);
if (!table) {
exit_error(PARAMETER_PROBLEM,
"%s: line %u table name invalid\n",
program_name, line);
exit(1);
}
strncpy(curtable, table, IP6T_TABLE_MAXNAMELEN);
handle = create_handle(table);
if (noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n",
table);
for_each_chain(flush_entries, verbose, 1,
&handle);
DEBUGP("Deleting all user-defined chains "
"of table '%s'\n", table);
for_each_chain(delete_chain, verbose, 0,
&handle) ;
}
ret = 1;
} else if (buffer[0] == ':') {
/* New chain. */
char *policy, *chain;
chain = strtok(buffer+1, " \t\n");
DEBUGP("line %u, chain '%s'\n", line, chain);
if (!chain) {
exit_error(PARAMETER_PROBLEM,
"%s: line %u chain name invalid\n",
program_name, line);
exit(1);
}
strncpy(curchain, chain, IP6T_FUNCTION_MAXNAMELEN);
/* why the f... does iptc_builtin not work here ? */
/* FIXME: abort if chain creation fails --RR */
// if (!iptc_builtin(curchain, &handle)) {
DEBUGP("Creating new chain '%s'\n", curchain);
if (!ip6tc_create_chain(curchain, &handle))
DEBUGP("unable to create chain '%s':%s\n", curchain,
strerror(errno));
// }
policy = strtok(NULL, " \t\n");
DEBUGP("line %u, policy '%s'\n", line, policy);
if (!policy) {
exit_error(PARAMETER_PROBLEM,
"%s: line %u policy invalid\n",
program_name, line);
exit(1);
}
if (strcmp(policy, "-") != 0) {
struct ip6t_counters count;
if (counters) {
char *ctrs;
ctrs = strtok(NULL, " \t\n");
parse_counters(ctrs, &count);
} else {
memset(&count, 0,
sizeof(struct ip6t_counters));
}
DEBUGP("Setting policy of chain %s to %s\n",
chain, policy);
if (!ip6tc_set_policy(chain, policy, &count,
&handle))
exit_error(OTHER_PROBLEM,
"Can't set policy `%s'"
" on `%s' line %u: %s\n",
chain, policy, line,
ip6tc_strerror(errno));
}
ret = 1;
} else {
char *newargv[1024];
int i,a, argvsize;
char *ptr = buffer;
char *pcnt = NULL;
char *bcnt = NULL;
if (buffer[0] == '[') {
ptr = strchr(buffer, ']');
if (!ptr)
exit_error(PARAMETER_PROBLEM,
"Bad line %u: need ]\n",
line);
pcnt = strtok(buffer+1, ":");
bcnt = strtok(NULL, "]");
}
newargv[0] = argv[0];
newargv[1] = "-t";
newargv[2] = (char *) &curtable;
newargv[3] = "-A";
newargv[4] = (char *) &curchain;
argvsize = 5;
if (counters && pcnt && bcnt) {
newargv[5] = "--set-counters";
newargv[6] = (char *) pcnt;
newargv[7] = (char *) bcnt;
argvsize = 8;
}
// strtok initcialize!
if ( buffer[0]!='[' )
{
if (!(newargv[argvsize] = strtok(buffer, " \t\n")))
goto ImLaMeR;
//break;
argvsize++;
}
/* strtok: a function only a coder could love */
for (i = argvsize; i < sizeof(newargv)/sizeof(char *);
i++) {
if (!(newargv[i] = strtok(NULL, " \t\n")))
break;
ptr = NULL;
}
ImLaMeR: if (i == sizeof(newargv)/sizeof(char *)) {
fprintf(stderr,
"%s: line %u too many arguments\n",
program_name, line);
exit(1);
}
DEBUGP("===>calling do_command6(%u, argv, &%s, handle):\n",
i, curtable);
for (a = 0; a <= i; a++)
DEBUGP("argv[%u]: %s\n", a, newargv[a]);
ret = do_command6(i, newargv, &newargv[2], &handle);
}
if (!ret) {
fprintf(stderr, "%s: line %u failed\n",
program_name, line);
exit(1);
}
}
return 0;
}