From d13b60c9ddb48e651b92f13579e236c530658176 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 13 Apr 2014 11:05:15 +0200 Subject: nft: xtables-restore: add generic parsing infrastructure This allows us to reuse the xtables-restore parser code in the translation infrastructure. Signed-off-by: Pablo Neira Ayuso --- iptables/nft-shared.h | 35 ++++++ iptables/xtables-restore.c | 269 +++++++++++++++++++++++++++------------------ 2 files changed, 195 insertions(+), 109 deletions(-) (limited to 'iptables') diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h index 03784ccc..56d75f82 100644 --- a/iptables/nft-shared.h +++ b/iptables/nft-shared.h @@ -232,4 +232,39 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], struct nft_xt_cmd_parse *p, struct iptables_command_state *cs, struct xtables_args *args); +struct nft_xt_restore_parse { + FILE *in; + int testing; + const char *tablename; +}; + +struct nftnl_chain_list; + +struct nft_xt_restore_cb { + void (*table_new)(struct nft_handle *h, const char *table); + struct nftnl_chain_list *(*chain_list)(struct nft_handle *h); + int (*chains_purge)(struct nft_handle *h, const char *table, + struct nftnl_chain_list *clist); + void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable, + const char *chain); + int (*chain_set)(struct nft_handle *h, const char *table, + const char *chain, const char *policy, + const struct xt_counters *counters); + int (*chain_user_add)(struct nft_handle *h, const char *chain, + const char *table); + + int (*rule_flush)(struct nft_handle *h, const char *chain, const char *table); + + int (*do_command)(struct nft_handle *h, int argc, char *argv[], + char **table, bool restore); + + int (*commit)(struct nft_handle *h); + int (*abort)(struct nft_handle *h); +}; + +void xtables_restore_parse(struct nft_handle *h, + struct nft_xt_restore_parse *p, + struct nft_xt_restore_cb *cb, + int argc, char *argv[]); + #endif diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c index 7a7ee066..cb60cce1 100644 --- a/iptables/xtables-restore.c +++ b/iptables/xtables-restore.c @@ -159,107 +159,64 @@ static void add_param_to_argv(char *parsestart) } } +static struct nftnl_chain_list *get_chain_list(struct nft_handle *h) +{ + struct nftnl_chain_list *chain_list; + + chain_list = nft_chain_dump(h); + if (chain_list == NULL) + xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n"); + + return chain_list; +} + +static void chain_delete(struct nftnl_chain_list *clist, const char *curtable, + const char *chain) +{ + struct nftnl_chain *chain_obj; + + chain_obj = nft_chain_list_find(clist, curtable, chain); + /* This chain has been found, delete from list. Later + * on, unvisited chains will be purged out. + */ + if (chain_obj != NULL) + nftnl_chain_list_del(chain_obj); +} + +struct nft_xt_restore_cb restore_cb = { + .chain_list = get_chain_list, + .commit = nft_commit, + .abort = nft_abort, + .chains_purge = nft_table_purge_chains, + .rule_flush = nft_rule_flush, + .chain_del = chain_delete, + .do_command = do_commandx, + .chain_set = nft_chain_set, + .chain_user_add = nft_chain_user_add, +}; + static const struct xtc_ops xtc_ops = { .strerror = nft_strerror, }; -static int -xtables_restore_main(int family, const char *progname, int argc, char *argv[]) +void xtables_restore_parse(struct nft_handle *h, + struct nft_xt_restore_parse *p, + struct nft_xt_restore_cb *cb, + int argc, char *argv[]) { - struct nft_handle h = { - .family = family, - .restore = true, - }; char buffer[10240]; - int c; + int in_table = 0; char curtable[XT_TABLE_MAXNAMELEN + 1]; - FILE *in; - int in_table = 0, testing = 0; - const char *tablename = NULL; const struct xtc_ops *ops = &xtc_ops; - struct nftnl_chain_list *chain_list; - struct nftnl_chain *chain_obj; + struct nftnl_chain_list *chain_list = NULL; line = 0; - xtables_globals.program_name = progname; - c = xtables_init_all(&xtables_globals, family); - if (c < 0) { - fprintf(stderr, "%s/%s Failed to initialize xtables\n", - xtables_globals.program_name, - xtables_globals.program_version); - exit(1); - } -#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) - init_extensions(); - init_extensions4(); -#endif - - if (nft_init(&h, xtables_ipv4) < 0) { - fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", - xtables_globals.program_name, - xtables_globals.program_version, - strerror(errno)); - exit(EXIT_FAILURE); - } - - while ((c = getopt_long(argc, argv, "bcvthnM:T:46", options, NULL)) != -1) { - switch (c) { - case 'b': - fprintf(stderr, "-b/--binary option is not implemented\n"); - break; - case 'c': - counters = 1; - break; - case 'v': - verbose = 1; - break; - case 't': - testing = 1; - break; - case 'h': - print_usage("xtables-restore", - IPTABLES_VERSION); - break; - case 'n': - noflush = 1; - break; - case 'M': - xtables_modprobe_program = optarg; - break; - case 'T': - tablename = optarg; - break; - case '4': - h.family = AF_INET; - break; - case '6': - h.family = AF_INET6; - xtables_set_nfproto(AF_INET6); - break; - } - } - - if (optind == argc - 1) { - in = fopen(argv[optind], "re"); - if (!in) { - fprintf(stderr, "Can't open %s: %s\n", argv[optind], - strerror(errno)); - exit(1); - } - } - else if (optind < argc) { - fprintf(stderr, "Unknown arguments found on commandline\n"); - exit(1); - } - else in = stdin; - - chain_list = nft_chain_dump(&h); - if (chain_list == NULL) - xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n"); + if (cb->chain_list) + chain_list = cb->chain_list(h); /* Grab standard input. */ - while (fgets(buffer, sizeof(buffer), in)) { + while (fgets(buffer, sizeof(buffer), p->in)) { int ret = 0; line++; @@ -270,22 +227,24 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) fputs(buffer, stdout); continue; } else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) { - if (!testing) { + if (!p->testing) { /* Commit per table, although we support * global commit at once, stick by now to * the existing behaviour. */ DEBUGP("Calling commit\n"); - ret = nft_commit(&h); + if (cb->commit) + ret = cb->commit(h); } else { DEBUGP("Not calling commit, testing\n"); - ret = nft_abort(&h); + if (cb->abort) + ret = cb->abort(h); } in_table = 0; /* Purge out unused chains in this table */ - if (!testing) - nft_table_purge_chains(&h, curtable, chain_list); + if (!p->testing && cb->chains_purge) + cb->chains_purge(h, curtable, chain_list); } else if ((buffer[0] == '*') && (!in_table)) { /* New table */ @@ -302,18 +261,22 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) strncpy(curtable, table, XT_TABLE_MAXNAMELEN); curtable[XT_TABLE_MAXNAMELEN] = '\0'; - if (tablename && (strcmp(tablename, table) != 0)) + if (p->tablename && (strcmp(p->tablename, table) != 0)) continue; if (noflush == 0) { DEBUGP("Cleaning all chains of table '%s'\n", table); - nft_rule_flush(&h, NULL, table); + if (cb->rule_flush) + cb->rule_flush(h, NULL, table); } ret = 1; in_table = 1; + if (cb->table_new) + cb->table_new(h, table); + } else if ((buffer[0] == ':') && (in_table)) { /* New chain. */ char *policy, *chain = NULL; @@ -328,13 +291,8 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) exit(1); } - chain_obj = nft_chain_list_find(chain_list, - curtable, chain); - /* This chain has been found, delete from list. Later - * on, unvisited chains will be purged out. - */ - if (chain_obj != NULL) - nftnl_chain_list_del(chain_obj); + if (cb->chain_del) + cb->chain_del(chain_list, curtable, chain); if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN) xtables_error(PARAMETER_PROBLEM, @@ -362,7 +320,8 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) "for chain '%s'\n", chain); } - if (nft_chain_set(&h, curtable, chain, policy, &count) < 0) { + if (cb->chain_set && + cb->chain_set(h, curtable, chain, policy, &count) < 0) { xtables_error(OTHER_PROBLEM, "Can't set policy `%s'" " on `%s' line %u: %s\n", @@ -374,7 +333,8 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) ret = 1; } else { - if (nft_chain_user_add(&h, chain, curtable) < 0) { + if (cb->chain_user_add && + cb->chain_user_add(h, chain, curtable) < 0) { if (errno == EEXIST) continue; @@ -441,10 +401,14 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) for (a = 0; a < newargc; a++) DEBUGP("argv[%u]: %s\n", a, newargv[a]); - ret = do_commandx(&h, newargc, newargv, - &newargv[2], true); + ret = cb->do_command(h, newargc, newargv, + &newargv[2], true); if (ret < 0) { - ret = nft_abort(&h); + if (cb->abort) + ret = cb->abort(h); + else + ret = 0; + if (ret < 0) { fprintf(stderr, "failed to abort " "commit operation\n"); @@ -455,7 +419,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) free_argv(); fflush(stdout); } - if (tablename && (strcmp(tablename, curtable) != 0)) + if (p->tablename && (strcmp(p->tablename, curtable) != 0)) continue; if (!ret) { fprintf(stderr, "%s: line %u failed\n", @@ -468,8 +432,95 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) xt_params->program_name, line + 1); exit(1); } +} + +static int +xtables_restore_main(int family, const char *progname, int argc, char *argv[]) +{ + struct nft_handle h = { + .family = family, + .restore = true, + }; + int c; + struct nft_xt_restore_parse p = {}; + + line = 0; + + xtables_globals.program_name = progname; + c = xtables_init_all(&xtables_globals, family); + if (c < 0) { + fprintf(stderr, "%s/%s Failed to initialize xtables\n", + xtables_globals.program_name, + xtables_globals.program_version); + exit(1); + } +#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS) + init_extensions(); + init_extensions4(); +#endif + + if (nft_init(&h, xtables_ipv4) < 0) { + fprintf(stderr, "%s/%s Failed to initialize nft: %s\n", + xtables_globals.program_name, + xtables_globals.program_version, + strerror(errno)); + exit(EXIT_FAILURE); + } + + while ((c = getopt_long(argc, argv, "bcvthnM:T:46", options, NULL)) != -1) { + switch (c) { + case 'b': + fprintf(stderr, "-b/--binary option is not implemented\n"); + break; + case 'c': + counters = 1; + break; + case 'v': + verbose = 1; + break; + case 't': + p.testing = 1; + break; + case 'h': + print_usage("xtables-restore", + IPTABLES_VERSION); + break; + case 'n': + noflush = 1; + break; + case 'M': + xtables_modprobe_program = optarg; + break; + case 'T': + p.tablename = optarg; + break; + case '4': + h.family = AF_INET; + break; + case '6': + h.family = AF_INET6; + xtables_set_nfproto(AF_INET6); + break; + } + } + + if (optind == argc - 1) { + p.in = fopen(argv[optind], "re"); + if (!p.in) { + fprintf(stderr, "Can't open %s: %s\n", argv[optind], + strerror(errno)); + exit(1); + } + } else if (optind < argc) { + fprintf(stderr, "Unknown arguments found on commandline\n"); + exit(1); + } else { + p.in = stdin; + } + + xtables_restore_parse(&h, &p, &restore_cb, argc, argv); - fclose(in); + fclose(p.in); return 0; } -- cgit v1.2.3