summaryrefslogtreecommitdiffstats
path: root/iptables/xtables.c
diff options
context:
space:
mode:
Diffstat (limited to 'iptables/xtables.c')
-rw-r--r--iptables/xtables.c879
1 files changed, 36 insertions, 843 deletions
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 9779bd83..5d73481c 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -36,6 +36,7 @@
#include <stdarg.h>
#include <limits.h>
#include <unistd.h>
+#include <netinet/ether.h>
#include <iptables.h>
#include <xtables.h>
#include <fcntl.h>
@@ -84,149 +85,13 @@ static struct option original_opts[] = {
{NULL},
};
-void xtables_exit_error(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
-
struct xtables_globals xtables_globals = {
.option_offset = 0,
- .program_version = PACKAGE_VERSION,
+ .program_version = PACKAGE_VERSION " (nf_tables)",
.orig_opts = original_opts,
- .exit_err = xtables_exit_error,
.compat_rev = nft_compatible_revision,
};
-static const int inverse_for_options[NUMBER_OF_OPT] =
-{
-/* -n */ 0,
-/* -s */ IPT_INV_SRCIP,
-/* -d */ IPT_INV_DSTIP,
-/* -p */ XT_INV_PROTO,
-/* -j */ 0,
-/* -v */ 0,
-/* -x */ 0,
-/* -i */ IPT_INV_VIA_IN,
-/* -o */ IPT_INV_VIA_OUT,
-/*--line*/ 0,
-/* -c */ 0,
-/* -f */ IPT_INV_FRAG,
-};
-
-#define opts xt_params->opts
-#define prog_name xt_params->program_name
-#define prog_vers xt_params->program_version
-
-static void __attribute__((noreturn))
-exit_tryhelp(int status)
-{
- if (line != -1)
- fprintf(stderr, "Error occurred at line: %d\n", line);
- fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
- prog_name, prog_name);
- xtables_free_opts(1);
- exit(status);
-}
-
-static void
-printhelp(const struct xtables_rule_match *matches)
-{
- printf("%s v%s\n\n"
-"Usage: %s -[ACD] chain rule-specification [options]\n"
-" %s -I chain [rulenum] rule-specification [options]\n"
-" %s -R chain rulenum rule-specification [options]\n"
-" %s -D chain rulenum [options]\n"
-" %s -[LS] [chain [rulenum]] [options]\n"
-" %s -[FZ] [chain] [options]\n"
-" %s -[NX] chain\n"
-" %s -E old-chain-name new-chain-name\n"
-" %s -P chain target [options]\n"
-" %s -h (print this help information)\n\n",
- prog_name, prog_vers, prog_name, prog_name,
- prog_name, prog_name, prog_name, prog_name,
- prog_name, prog_name, prog_name, prog_name);
-
- printf(
-"Commands:\n"
-"Either long or short options are allowed.\n"
-" --append -A chain Append to chain\n"
-" --check -C chain Check for the existence of a rule\n"
-" --delete -D chain Delete matching rule from chain\n"
-" --delete -D chain rulenum\n"
-" Delete rule rulenum (1 = first) from chain\n"
-" --insert -I chain [rulenum]\n"
-" Insert in chain as rulenum (default 1=first)\n"
-" --replace -R chain rulenum\n"
-" Replace rule rulenum (1 = first) in chain\n"
-" --list -L [chain [rulenum]]\n"
-" List the rules in a chain or all chains\n"
-" --list-rules -S [chain [rulenum]]\n"
-" Print the rules in a chain or all chains\n"
-" --flush -F [chain] Delete all rules in chain or all chains\n"
-" --zero -Z [chain [rulenum]]\n"
-" Zero counters in chain or all chains\n"
-" --new -N chain Create a new user-defined chain\n"
-" --delete-chain\n"
-" -X [chain] Delete a user-defined chain\n"
-" --policy -P chain target\n"
-" Change policy on chain to target\n"
-" --rename-chain\n"
-" -E old-chain new-chain\n"
-" Change chain name, (moving any references)\n"
-
-"Options:\n"
-" --ipv4 -4 Nothing (line is ignored by ip6tables-restore)\n"
-" --ipv6 -6 Error (line is ignored by iptables-restore)\n"
-"[!] --proto -p proto protocol: by number or name, eg. `tcp'\n"
-"[!] --source -s address[/mask][...]\n"
-" source specification\n"
-"[!] --destination -d address[/mask][...]\n"
-" destination specification\n"
-"[!] --in-interface -i input name[+]\n"
-" network interface name ([+] for wildcard)\n"
-" --jump -j target\n"
-" target for rule (may load target extension)\n"
-#ifdef IPT_F_GOTO
-" --goto -g chain\n"
-" jump to chain with no return\n"
-#endif
-" --match -m match\n"
-" extended match (may load extension)\n"
-" --numeric -n numeric output of addresses and ports\n"
-"[!] --out-interface -o output name[+]\n"
-" network interface name ([+] for wildcard)\n"
-" --table -t table table to manipulate (default: `filter')\n"
-" --verbose -v verbose mode\n"
-" --wait -w [seconds] maximum wait to acquire xtables lock before give up\n"
-" --wait-interval -W [usecs] wait time to try to acquire xtables lock\n"
-" default is 1 second\n"
-" --line-numbers print line numbers when listing\n"
-" --exact -x expand numbers (display exact values)\n"
-"[!] --fragment -f match second or further fragments only\n"
-" --modprobe=<command> try to insert modules using this command\n"
-" --set-counters PKTS BYTES set the counter during insert/append\n"
-"[!] --version -V print package version.\n");
-
- print_extension_helps(xtables_targets, matches);
-}
-
-void
-xtables_exit_error(enum xtables_exittype status, const char *msg, ...)
-{
- va_list args;
-
- va_start(args, msg);
- fprintf(stderr, "%s v%s (nf_tables): ", prog_name, prog_vers);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, "\n");
- if (status == PARAMETER_PROBLEM)
- exit_tryhelp(status);
- if (status == VERSION_PROBLEM)
- fprintf(stderr,
- "Perhaps iptables or your kernel needs to be upgraded.\n");
- /* On error paths, make sure that we don't leak memory */
- xtables_free_opts(1);
- exit(status);
-}
-
/*
* All functions starting with "parse" should succeed, otherwise
* the program fails.
@@ -238,189 +103,6 @@ xtables_exit_error(enum xtables_exittype status, const char *msg, ...)
/* Christophe Burki wants `-p 6' to imply `-m tcp'. */
-static void
-set_option(unsigned int *options, unsigned int option, uint8_t *invflg,
- int invert)
-{
- if (*options & option)
- xtables_error(PARAMETER_PROBLEM, "multiple -%c flags not allowed",
- opt2char(option));
- *options |= option;
-
- if (invert) {
- unsigned int i;
- for (i = 0; 1 << i != option; i++);
-
- if (!inverse_for_options[i])
- xtables_error(PARAMETER_PROBLEM,
- "cannot have ! before -%c",
- opt2char(option));
- *invflg |= inverse_for_options[i];
- }
-}
-
-static int
-add_entry(const char *chain,
- const char *table,
- struct iptables_command_state *cs,
- int rulenum, int family,
- const struct addr_mask s,
- const struct addr_mask d,
- bool verbose, struct nft_handle *h, bool append)
-{
- unsigned int i, j;
- int ret = 1;
-
- for (i = 0; i < s.naddrs; i++) {
- if (family == AF_INET) {
- cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
- cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
- for (j = 0; j < d.naddrs; j++) {
- cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
- cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
-
- if (append) {
- ret = nft_cmd_rule_append(h, chain, table,
- cs, NULL,
- verbose);
- } else {
- ret = nft_cmd_rule_insert(h, chain, table,
- cs, rulenum,
- verbose);
- }
- }
- } else if (family == AF_INET6) {
- memcpy(&cs->fw6.ipv6.src,
- &s.addr.v6[i], sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.smsk,
- &s.mask.v6[i], sizeof(struct in6_addr));
- for (j = 0; j < d.naddrs; j++) {
- memcpy(&cs->fw6.ipv6.dst,
- &d.addr.v6[j], sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.dmsk,
- &d.mask.v6[j], sizeof(struct in6_addr));
- if (append) {
- ret = nft_cmd_rule_append(h, chain, table,
- cs, NULL,
- verbose);
- } else {
- ret = nft_cmd_rule_insert(h, chain, table,
- cs, rulenum,
- verbose);
- }
- }
- }
- }
-
- return ret;
-}
-
-static int
-replace_entry(const char *chain, const char *table,
- struct iptables_command_state *cs,
- unsigned int rulenum,
- int family,
- const struct addr_mask s,
- const struct addr_mask d,
- bool verbose, struct nft_handle *h)
-{
- if (family == AF_INET) {
- cs->fw.ip.src.s_addr = s.addr.v4->s_addr;
- cs->fw.ip.dst.s_addr = d.addr.v4->s_addr;
- cs->fw.ip.smsk.s_addr = s.mask.v4->s_addr;
- cs->fw.ip.dmsk.s_addr = d.mask.v4->s_addr;
- } else if (family == AF_INET6) {
- memcpy(&cs->fw6.ipv6.src, s.addr.v6, sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.dst, d.addr.v6, sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.smsk, s.mask.v6, sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.dmsk, d.mask.v6, sizeof(struct in6_addr));
- } else
- return 1;
-
- return nft_cmd_rule_replace(h, chain, table, cs, rulenum, verbose);
-}
-
-static int
-delete_entry(const char *chain, const char *table,
- struct iptables_command_state *cs,
- int family,
- const struct addr_mask s,
- const struct addr_mask d,
- bool verbose,
- struct nft_handle *h)
-{
- unsigned int i, j;
- int ret = 1;
-
- for (i = 0; i < s.naddrs; i++) {
- if (family == AF_INET) {
- cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
- cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
- for (j = 0; j < d.naddrs; j++) {
- cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
- cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
- ret = nft_cmd_rule_delete(h, chain,
- table, cs, verbose);
- }
- } else if (family == AF_INET6) {
- memcpy(&cs->fw6.ipv6.src,
- &s.addr.v6[i], sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.smsk,
- &s.mask.v6[i], sizeof(struct in6_addr));
- for (j = 0; j < d.naddrs; j++) {
- memcpy(&cs->fw6.ipv6.dst,
- &d.addr.v6[j], sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.dmsk,
- &d.mask.v6[j], sizeof(struct in6_addr));
- ret = nft_cmd_rule_delete(h, chain,
- table, cs, verbose);
- }
- }
- }
-
- return ret;
-}
-
-static int
-check_entry(const char *chain, const char *table,
- struct iptables_command_state *cs,
- int family,
- const struct addr_mask s,
- const struct addr_mask d,
- bool verbose, struct nft_handle *h)
-{
- unsigned int i, j;
- int ret = 1;
-
- for (i = 0; i < s.naddrs; i++) {
- if (family == AF_INET) {
- cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
- cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
- for (j = 0; j < d.naddrs; j++) {
- cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
- cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
- ret = nft_cmd_rule_check(h, chain,
- table, cs, verbose);
- }
- } else if (family == AF_INET6) {
- memcpy(&cs->fw6.ipv6.src,
- &s.addr.v6[i], sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.smsk,
- &s.mask.v6[i], sizeof(struct in6_addr));
- for (j = 0; j < d.naddrs; j++) {
- memcpy(&cs->fw6.ipv6.dst,
- &d.addr.v6[j], sizeof(struct in6_addr));
- memcpy(&cs->fw6.ipv6.dmsk,
- &d.mask.v6[j], sizeof(struct in6_addr));
- ret = nft_cmd_rule_check(h, chain,
- table, cs, verbose);
- }
- }
- }
-
- return ret;
-}
-
static int
list_entries(struct nft_handle *h, const char *chain, const char *table,
int rulenum, int verbose, int numeric, int expanded,
@@ -456,540 +138,61 @@ list_rules(struct nft_handle *h, const char *chain, const char *table,
return nft_cmd_rule_list_save(h, chain, table, rulenum, counters);
}
-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 xtables_match *m;
- struct xtables_rule_match *matchp;
- bool wait_interval_set = false;
- struct timeval wait_interval;
- struct xtables_target *t;
- bool table_set = false;
- int wait = 0;
-
- memset(cs, 0, sizeof(*cs));
- cs->jumpto = "";
- cs->argv = argv;
-
- /* re-set optind to 0 in case do_command4 gets called
- * a second time */
- optind = 0;
-
- /* clear mflags in case do_command4 gets called a second time
- * (we clear the global list of all matches for security)*/
- for (m = xtables_matches; m; m = m->next)
- m->mflags = 0;
-
- for (t = xtables_targets; t; t = t->next) {
- t->tflags = 0;
- t->used = 0;
- }
-
- /* Suppress error messages: we may add new options if we
- demand-load a protocol. */
- opterr = 0;
-
- opts = xt_params->orig_opts;
- while ((cs->c = getopt_long(argc, argv,
- "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvw::W::nt:m:xc:g:46",
- opts, NULL)) != -1) {
- switch (cs->c) {
- /*
- * Command selection
- */
- case 'A':
- add_command(&p->command, CMD_APPEND, CMD_NONE,
- cs->invert);
- p->chain = optarg;
- break;
-
- case 'C':
- add_command(&p->command, CMD_CHECK, CMD_NONE,
- cs->invert);
- p->chain = optarg;
- break;
-
- case 'D':
- add_command(&p->command, CMD_DELETE, CMD_NONE,
- cs->invert);
- p->chain = optarg;
- if (xs_has_arg(argc, argv)) {
- p->rulenum = parse_rulenumber(argv[optind++]);
- p->command = CMD_DELETE_NUM;
- }
- break;
-
- case 'R':
- add_command(&p->command, CMD_REPLACE, CMD_NONE,
- cs->invert);
- p->chain = optarg;
- if (xs_has_arg(argc, argv))
- p->rulenum = parse_rulenumber(argv[optind++]);
- else
- xtables_error(PARAMETER_PROBLEM,
- "-%c requires a rule number",
- cmd2char(CMD_REPLACE));
- break;
-
- case 'I':
- add_command(&p->command, CMD_INSERT, CMD_NONE,
- cs->invert);
- p->chain = optarg;
- if (xs_has_arg(argc, argv))
- p->rulenum = parse_rulenumber(argv[optind++]);
- else
- p->rulenum = 1;
- break;
-
- case 'L':
- add_command(&p->command, CMD_LIST,
- CMD_ZERO | CMD_ZERO_NUM, cs->invert);
- if (optarg)
- p->chain = optarg;
- else if (xs_has_arg(argc, argv))
- p->chain = argv[optind++];
- if (xs_has_arg(argc, argv))
- p->rulenum = parse_rulenumber(argv[optind++]);
- break;
-
- case 'S':
- add_command(&p->command, CMD_LIST_RULES,
- CMD_ZERO|CMD_ZERO_NUM, cs->invert);
- if (optarg)
- p->chain = optarg;
- else if (xs_has_arg(argc, argv))
- p->chain = argv[optind++];
- if (xs_has_arg(argc, argv))
- p->rulenum = parse_rulenumber(argv[optind++]);
- break;
-
- case 'F':
- add_command(&p->command, CMD_FLUSH, CMD_NONE,
- cs->invert);
- if (optarg)
- p->chain = optarg;
- else if (xs_has_arg(argc, argv))
- p->chain = argv[optind++];
- break;
-
- case 'Z':
- add_command(&p->command, CMD_ZERO,
- CMD_LIST|CMD_LIST_RULES, cs->invert);
- if (optarg)
- p->chain = optarg;
- else if (xs_has_arg(argc, argv))
- p->chain = argv[optind++];
- if (xs_has_arg(argc, argv)) {
- p->rulenum = parse_rulenumber(argv[optind++]);
- p->command = CMD_ZERO_NUM;
- }
- break;
-
- case 'N':
- if (optarg && (*optarg == '-' || *optarg == '!'))
- xtables_error(PARAMETER_PROBLEM,
- "chain name not allowed to start "
- "with `%c'\n", *optarg);
- if (xtables_find_target(optarg, XTF_TRY_LOAD))
- xtables_error(PARAMETER_PROBLEM,
- "chain name may not clash "
- "with target name\n");
- add_command(&p->command, CMD_NEW_CHAIN, CMD_NONE,
- cs->invert);
- p->chain = optarg;
- break;
-
- case 'X':
- add_command(&p->command, CMD_DELETE_CHAIN, CMD_NONE,
- cs->invert);
- if (optarg)
- p->chain = optarg;
- else if (xs_has_arg(argc, argv))
- p->chain = argv[optind++];
- break;
-
- case 'E':
- add_command(&p->command, CMD_RENAME_CHAIN, CMD_NONE,
- cs->invert);
- p->chain = optarg;
- if (xs_has_arg(argc, argv))
- p->newname = argv[optind++];
- else
- xtables_error(PARAMETER_PROBLEM,
- "-%c requires old-chain-name and "
- "new-chain-name",
- cmd2char(CMD_RENAME_CHAIN));
- break;
-
- case 'P':
- add_command(&p->command, CMD_SET_POLICY, CMD_NONE,
- cs->invert);
- p->chain = optarg;
- if (xs_has_arg(argc, argv))
- p->policy = argv[optind++];
- else
- xtables_error(PARAMETER_PROBLEM,
- "-%c requires a chain and a policy",
- cmd2char(CMD_SET_POLICY));
- break;
-
- case 'h':
- if (!optarg)
- optarg = argv[optind];
-
- /* iptables -p icmp -h */
- if (!cs->matches && cs->protocol)
- xtables_find_match(cs->protocol,
- XTF_TRY_LOAD, &cs->matches);
-
- printhelp(cs->matches);
- p->command = CMD_NONE;
- return;
-
- /*
- * Option selection
- */
- case 'p':
- set_option(&cs->options, OPT_PROTOCOL,
- &args->invflags, cs->invert);
-
- /* Canonicalize into lower case */
- for (cs->protocol = optarg; *cs->protocol; cs->protocol++)
- *cs->protocol = tolower(*cs->protocol);
-
- cs->protocol = optarg;
- args->proto = xtables_parse_protocol(cs->protocol);
-
- if (args->proto == 0 &&
- (args->invflags & XT_INV_PROTO))
- xtables_error(PARAMETER_PROBLEM,
- "rule would never match protocol");
-
- /* This needs to happen here to parse extensions */
- h->ops->proto_parse(cs, args);
- break;
-
- case 's':
- set_option(&cs->options, OPT_SOURCE,
- &args->invflags, cs->invert);
- args->shostnetworkmask = optarg;
- break;
-
- case 'd':
- set_option(&cs->options, OPT_DESTINATION,
- &args->invflags, cs->invert);
- args->dhostnetworkmask = optarg;
- break;
-
-#ifdef IPT_F_GOTO
- case 'g':
- set_option(&cs->options, OPT_JUMP, &args->invflags,
- cs->invert);
- args->goto_set = true;
- cs->jumpto = xt_parse_target(optarg);
- break;
-#endif
-
- case 'j':
- set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags,
- cs->invert);
- command_jump(cs, optarg);
- break;
-
-
- case 'i':
- if (*optarg == '\0')
- xtables_error(PARAMETER_PROBLEM,
- "Empty interface is likely to be "
- "undesired");
- set_option(&cs->options, OPT_VIANAMEIN,
- &args->invflags, cs->invert);
- xtables_parse_interface(optarg,
- args->iniface,
- args->iniface_mask);
- break;
-
- case 'o':
- if (*optarg == '\0')
- xtables_error(PARAMETER_PROBLEM,
- "Empty interface is likely to be "
- "undesired");
- set_option(&cs->options, OPT_VIANAMEOUT,
- &args->invflags, cs->invert);
- xtables_parse_interface(optarg,
- args->outiface,
- args->outiface_mask);
- break;
-
- case 'f':
- if (args->family == AF_INET6) {
- xtables_error(PARAMETER_PROBLEM,
- "`-f' is not supported in IPv6, "
- "use -m frag instead");
- }
- set_option(&cs->options, OPT_FRAGMENT, &args->invflags,
- cs->invert);
- args->flags |= IPT_F_FRAG;
- break;
-
- case 'v':
- if (!p->verbose)
- set_option(&cs->options, OPT_VERBOSE,
- &args->invflags, cs->invert);
- p->verbose++;
- break;
-
- case 'm':
- command_match(cs);
- break;
-
- case 'n':
- set_option(&cs->options, OPT_NUMERIC, &args->invflags,
- cs->invert);
- break;
-
- case 't':
- if (cs->invert)
- xtables_error(PARAMETER_PROBLEM,
- "unexpected ! flag before --table");
- if (p->restore && table_set)
- xtables_error(PARAMETER_PROBLEM,
- "The -t option (seen in line %u) cannot be used in %s.\n",
- line, xt_params->program_name);
- if (!nft_table_builtin_find(h, optarg))
- xtables_error(VERSION_PROBLEM,
- "table '%s' does not exist",
- optarg);
- p->table = optarg;
- table_set = true;
- break;
-
- case 'x':
- set_option(&cs->options, OPT_EXPANDED, &args->invflags,
- cs->invert);
- break;
-
- case 'V':
- if (cs->invert)
- printf("Not %s ;-)\n", prog_vers);
- else
- printf("%s v%s (nf_tables)\n",
- prog_name, prog_vers);
- exit(0);
-
- case 'w':
- if (p->restore) {
- xtables_error(PARAMETER_PROBLEM,
- "You cannot use `-w' from "
- "iptables-restore");
- }
-
- wait = parse_wait_time(argc, argv);
- break;
-
- case 'W':
- if (p->restore) {
- xtables_error(PARAMETER_PROBLEM,
- "You cannot use `-W' from "
- "iptables-restore");
- }
-
- parse_wait_interval(argc, argv, &wait_interval);
- wait_interval_set = true;
- break;
-
- case '0':
- set_option(&cs->options, OPT_LINENUMBERS,
- &args->invflags, cs->invert);
- break;
-
- case 'M':
- xtables_modprobe_program = optarg;
- break;
-
- case 'c':
- set_option(&cs->options, OPT_COUNTERS, &args->invflags,
- cs->invert);
- args->pcnt = optarg;
- args->bcnt = strchr(args->pcnt + 1, ',');
- if (args->bcnt)
- args->bcnt++;
- if (!args->bcnt && xs_has_arg(argc, argv))
- args->bcnt = argv[optind++];
- if (!args->bcnt)
- xtables_error(PARAMETER_PROBLEM,
- "-%c requires packet and byte counter",
- opt2char(OPT_COUNTERS));
-
- if (sscanf(args->pcnt, "%llu", &args->pcnt_cnt) != 1)
- xtables_error(PARAMETER_PROBLEM,
- "-%c packet counter not numeric",
- opt2char(OPT_COUNTERS));
-
- if (sscanf(args->bcnt, "%llu", &args->bcnt_cnt) != 1)
- xtables_error(PARAMETER_PROBLEM,
- "-%c byte counter not numeric",
- opt2char(OPT_COUNTERS));
- break;
-
- case '4':
- if (args->family == AF_INET)
- break;
-
- if (p->restore && args->family == AF_INET6)
- return;
-
- exit_tryhelp(2);
-
- case '6':
- if (args->family == AF_INET6)
- break;
-
- if (p->restore && args->family == AF_INET)
- return;
-
- exit_tryhelp(2);
-
- case 1: /* non option */
- if (optarg[0] == '!' && optarg[1] == '\0') {
- if (cs->invert)
- xtables_error(PARAMETER_PROBLEM,
- "multiple consecutive ! not"
- " allowed");
- cs->invert = true;
- optarg[0] = '\0';
- continue;
- }
- fprintf(stderr, "Bad argument `%s'\n", optarg);
- exit_tryhelp(2);
-
- default:
- if (command_default(cs, &xtables_globals) == 1)
- /* cf. ip6tables.c */
- continue;
- break;
- }
- cs->invert = false;
- }
-
- if (strcmp(p->table, "nat") == 0 &&
- ((p->policy != NULL && strcmp(p->policy, "DROP") == 0) ||
- (cs->jumpto != NULL && strcmp(cs->jumpto, "DROP") == 0)))
- xtables_error(PARAMETER_PROBLEM,
- "\nThe \"nat\" table is not intended for filtering, "
- "the use of DROP is therefore inhibited.\n\n");
-
- if (!wait && wait_interval_set)
- xtables_error(PARAMETER_PROBLEM,
- "--wait-interval only makes sense with --wait\n");
-
- for (matchp = cs->matches; matchp; matchp = matchp->next)
- xtables_option_mfcall(matchp->match);
- if (cs->target != NULL)
- xtables_option_tfcall(cs->target);
-
- /* Fix me: must put inverse options checking here --MN */
-
- if (optind < argc)
- xtables_error(PARAMETER_PROBLEM,
- "unknown arguments found on commandline");
- if (!p->command)
- xtables_error(PARAMETER_PROBLEM, "no command specified");
- if (cs->invert)
- xtables_error(PARAMETER_PROBLEM,
- "nothing appropriate following !");
-
- /* Set only if required, needed by xtables-restore */
- if (h->family == AF_UNSPEC)
- h->family = args->family;
-
- h->ops->post_parse(p->command, cs, args);
-
- if (p->command == CMD_REPLACE &&
- (args->s.naddrs != 1 || args->d.naddrs != 1))
- xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
- "specify a unique address");
-
- generic_opt_check(p->command, cs->options);
-
- if (p->chain != NULL && strlen(p->chain) >= XT_EXTENSION_MAXNAMELEN)
- xtables_error(PARAMETER_PROBLEM,
- "chain name `%s' too long (must be under %u chars)",
- p->chain, XT_EXTENSION_MAXNAMELEN);
-
- if (p->command == CMD_APPEND ||
- p->command == CMD_DELETE ||
- p->command == CMD_DELETE_NUM ||
- p->command == CMD_CHECK ||
- p->command == CMD_INSERT ||
- p->command == CMD_REPLACE) {
- if (strcmp(p->chain, "PREROUTING") == 0
- || strcmp(p->chain, "INPUT") == 0) {
- /* -o not valid with incoming packets. */
- if (cs->options & OPT_VIANAMEOUT)
- xtables_error(PARAMETER_PROBLEM,
- "Can't use -%c with %s\n",
- opt2char(OPT_VIANAMEOUT),
- p->chain);
- }
-
- if (strcmp(p->chain, "POSTROUTING") == 0
- || strcmp(p->chain, "OUTPUT") == 0) {
- /* -i not valid with outgoing packets */
- if (cs->options & OPT_VIANAMEIN)
- xtables_error(PARAMETER_PROBLEM,
- "Can't use -%c with %s\n",
- opt2char(OPT_VIANAMEIN),
- p->chain);
- }
- }
-}
-
int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
bool restore)
{
int ret = 1;
- struct nft_xt_cmd_parse p = {
+ struct xt_cmd_parse p = {
.table = *table,
.restore = restore,
+ .line = line,
+ .ops = &h->ops->cmd_parse,
+ };
+ struct iptables_command_state cs = {
+ .jumpto = "",
+ .argv = argv,
};
- struct iptables_command_state cs;
struct xtables_args args = {
.family = h->family,
};
- do_parse(h, argc, argv, &p, &cs, &args);
+ if (h->ops->init_cs)
+ h->ops->init_cs(&cs);
+
+ do_parse(argc, argv, &p, &cs, &args);
+ h->verbose = p.verbose;
+ if (!nft_table_builtin_find(h, p.table))
+ xtables_error(VERSION_PROBLEM,
+ "table '%s' does not exist",
+ p.table);
switch (p.command) {
case CMD_APPEND:
- ret = add_entry(p.chain, p.table, &cs, 0, h->family,
- args.s, args.d,
- cs.options & OPT_VERBOSE, h, true);
+ ret = h->ops->add_entry(h, p.chain, p.table, &cs, &args,
+ cs.options & OPT_VERBOSE, true,
+ p.rulenum - 1);
break;
case CMD_DELETE:
- ret = delete_entry(p.chain, p.table, &cs, h->family,
- args.s, args.d,
- cs.options & OPT_VERBOSE, h);
+ ret = h->ops->delete_entry(h, p.chain, p.table, &cs, &args,
+ cs.options & OPT_VERBOSE);
break;
case CMD_DELETE_NUM:
ret = nft_cmd_rule_delete_num(h, p.chain, p.table,
p.rulenum - 1, p.verbose);
break;
case CMD_CHECK:
- ret = check_entry(p.chain, p.table, &cs, h->family,
- args.s, args.d,
- cs.options & OPT_VERBOSE, h);
+ ret = h->ops->check_entry(h, p.chain, p.table, &cs, &args,
+ cs.options & OPT_VERBOSE);
break;
case CMD_REPLACE:
- ret = replace_entry(p.chain, p.table, &cs, p.rulenum - 1,
- h->family, args.s, args.d,
- cs.options & OPT_VERBOSE, h);
+ ret = h->ops->replace_entry(h, p.chain, p.table, &cs, &args,
+ cs.options & OPT_VERBOSE,
+ p.rulenum - 1);
break;
case CMD_INSERT:
- ret = add_entry(p.chain, p.table, &cs, p.rulenum - 1,
- h->family, args.s, args.d,
- cs.options&OPT_VERBOSE, h, false);
+ ret = h->ops->add_entry(h, p.chain, p.table, &cs, &args,
+ cs.options & OPT_VERBOSE, false,
+ p.rulenum - 1);
break;
case CMD_FLUSH:
ret = nft_cmd_rule_flush(h, p.chain, p.table,
@@ -1040,8 +243,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
ret = nft_cmd_chain_user_add(h, p.chain, p.table);
break;
case CMD_DELETE_CHAIN:
- ret = nft_cmd_chain_user_del(h, p.chain, p.table,
- cs.options & OPT_VERBOSE);
+ ret = nft_cmd_chain_del(h, p.chain, p.table,
+ cs.options & OPT_VERBOSE);
break;
case CMD_RENAME_CHAIN:
ret = nft_cmd_chain_user_rename(h, p.chain, p.table, p.newname);
@@ -1054,24 +257,14 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
break;
default:
/* We should never reach this... */
- exit_tryhelp(2);
+ exit_tryhelp(2, line);
}
*table = p.table;
- nft_clear_iptables_command_state(&cs);
+ h->ops->clear_cs(&cs);
- if (h->family == AF_INET) {
- free(args.s.addr.v4);
- free(args.s.mask.v4);
- free(args.d.addr.v4);
- free(args.d.mask.v4);
- } else if (h->family == AF_INET6) {
- free(args.s.addr.v6);
- free(args.s.mask.v6);
- free(args.d.addr.v6);
- free(args.d.mask.v6);
- }
+ xtables_clear_args(&args);
xtables_free_opts(1);
return ret;