summaryrefslogtreecommitdiffstats
path: root/iptables
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2021-09-27 16:59:49 +0200
committerPhil Sutter <phil@nwl.cc>2021-10-20 11:32:54 +0200
commit0af80a91b0a98891d3cbc891a7377281b4080035 (patch)
tree75bb9416ae047dc947fd0dd35f850bc55f7b73f9 /iptables
parent142cf72442760ae8fc377bbfb54a913baf84742e (diff)
nft: Merge xtables-arp-standalone.c into xtables-standalone.cHEADmaster
By declaring the relevant family_ops callbacks for arptables, the code becomes ready to just use do_commandx() instead of a dedicated parser. As a side-effect, this enables a bunch of new features in arptables-nft: * Support '-C' command * Support '-S' command * Support rule indexes just like xtables, e.g. in '-I' or '-R' commands * Reject chain names starting with '!' * Support '-c N,M' counter syntax Since arptables still accepts intrapositioned negations, add code to cover that but print a warning like iptables did 12 years ago prior to removing the functionality. Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'iptables')
-rw-r--r--iptables/Makefile.am2
-rw-r--r--iptables/nft-arp.c95
-rw-r--r--iptables/xtables-arp-standalone.c63
-rw-r--r--iptables/xtables-arp.c638
-rw-r--r--iptables/xtables-restore.c2
-rw-r--r--iptables/xtables-standalone.c19
-rw-r--r--iptables/xtables.c98
7 files changed, 218 insertions, 699 deletions
diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index f7895210..0258264c 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -37,7 +37,7 @@ xtables_nft_multi_SOURCES += xtables-save.c xtables-restore.c \
xtables-standalone.c xtables.c nft.c \
nft-shared.c nft-ipv4.c nft-ipv6.c nft-arp.c \
xtables-monitor.c nft-cache.c \
- xtables-arp-standalone.c xtables-arp.c \
+ xtables-arp.c \
nft-bridge.c nft-cmd.c nft-chain.c \
xtables-eb-standalone.c xtables-eb.c \
xtables-eb-translate.c \
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index b37ffbb5..32eb91ad 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -617,7 +617,8 @@ static void nft_arp_post_parse(int command,
cs->arp.counters.pcnt = args->pcnt_cnt;
cs->arp.counters.bcnt = args->bcnt_cnt;
- if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND)) {
+ if (command & (CMD_REPLACE | CMD_INSERT |
+ CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
if (!(cs->options & OPT_DESTINATION))
args->dhostnetworkmask = "0.0.0.0/0";
if (!(cs->options & OPT_SOURCE))
@@ -702,6 +703,94 @@ static void nft_arp_init_cs(struct iptables_command_state *cs)
cs->arp.arp.arhrd_mask = 65535;
}
+static int
+nft_arp_add_entry(struct nft_handle *h,
+ const char *chain, const char *table,
+ struct iptables_command_state *cs,
+ struct xtables_args *args, bool verbose,
+ bool append, int rulenum)
+{
+ unsigned int i, j;
+ int ret = 1;
+
+ for (i = 0; i < args->s.naddrs; i++) {
+ cs->arp.arp.src.s_addr = args->s.addr.v4[i].s_addr;
+ cs->arp.arp.smsk.s_addr = args->s.mask.v4[i].s_addr;
+ for (j = 0; j < args->d.naddrs; j++) {
+ cs->arp.arp.tgt.s_addr = args->d.addr.v4[j].s_addr;
+ cs->arp.arp.tmsk.s_addr = args->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);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int
+nft_arp_delete_entry(struct nft_handle *h,
+ const char *chain, const char *table,
+ struct iptables_command_state *cs,
+ struct xtables_args *args, bool verbose)
+{
+ unsigned int i, j;
+ int ret = 1;
+
+ for (i = 0; i < args->s.naddrs; i++) {
+ cs->arp.arp.src.s_addr = args->s.addr.v4[i].s_addr;
+ cs->arp.arp.smsk.s_addr = args->s.mask.v4[i].s_addr;
+ for (j = 0; j < args->d.naddrs; j++) {
+ cs->arp.arp.tgt.s_addr = args->d.addr.v4[j].s_addr;
+ cs->arp.arp.tmsk.s_addr = args->d.mask.v4[j].s_addr;
+ ret = nft_cmd_rule_delete(h, chain, table, cs, verbose);
+ }
+ }
+
+ return ret;
+}
+
+static int
+nft_arp_check_entry(struct nft_handle *h,
+ const char *chain, const char *table,
+ struct iptables_command_state *cs,
+ struct xtables_args *args, bool verbose)
+{
+ unsigned int i, j;
+ int ret = 1;
+
+ for (i = 0; i < args->s.naddrs; i++) {
+ cs->arp.arp.src.s_addr = args->s.addr.v4[i].s_addr;
+ cs->arp.arp.smsk.s_addr = args->s.mask.v4[i].s_addr;
+ for (j = 0; j < args->d.naddrs; j++) {
+ cs->arp.arp.tgt.s_addr = args->d.addr.v4[j].s_addr;
+ cs->arp.arp.tmsk.s_addr = args->d.mask.v4[j].s_addr;
+ ret = nft_cmd_rule_check(h, chain, table, cs, verbose);
+ }
+ }
+
+ return ret;
+}
+
+static int
+nft_arp_replace_entry(struct nft_handle *h,
+ const char *chain, const char *table,
+ struct iptables_command_state *cs,
+ struct xtables_args *args, bool verbose,
+ int rulenum)
+{
+ cs->arp.arp.src.s_addr = args->s.addr.v4->s_addr;
+ cs->arp.arp.tgt.s_addr = args->d.addr.v4->s_addr;
+ cs->arp.arp.smsk.s_addr = args->s.mask.v4->s_addr;
+ cs->arp.arp.tmsk.s_addr = args->d.mask.v4->s_addr;
+
+ return nft_cmd_rule_replace(h, chain, table, cs, rulenum, verbose);
+}
+
struct nft_family_ops nft_family_ops_arp = {
.add = nft_arp_add,
.is_same = nft_arp_is_same,
@@ -718,4 +807,8 @@ struct nft_family_ops nft_family_ops_arp = {
.init_cs = nft_arp_init_cs,
.clear_cs = nft_clear_iptables_command_state,
.parse_target = nft_ipv46_parse_target,
+ .add_entry = nft_arp_add_entry,
+ .delete_entry = nft_arp_delete_entry,
+ .check_entry = nft_arp_check_entry,
+ .replace_entry = nft_arp_replace_entry,
};
diff --git a/iptables/xtables-arp-standalone.c b/iptables/xtables-arp-standalone.c
deleted file mode 100644
index 82db3f38..00000000
--- a/iptables/xtables-arp-standalone.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Author: Paul.Russell@rustcorp.com.au and mneuling@radlogic.com.au
- *
- * 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>
- *
- * arptables -- IP firewall administration for kernels with
- * firewall table (aimed for the 2.3 kernels)
- *
- * See the accompanying manual page arptables(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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <xtables.h>
-#include "nft.h"
-#include <linux/netfilter_arp/arp_tables.h>
-
-#include "xtables-multi.h"
-
-int xtables_arp_main(int argc, char *argv[])
-{
- int ret;
- char *table = "filter";
- struct nft_handle h;
-
- nft_init_arp(&h, "arptables");
-
- ret = do_commandarp(&h, argc, argv, &table, false);
- if (ret)
- ret = nft_commit(&h);
-
- nft_fini(&h);
- xtables_fini();
-
- if (!ret)
- fprintf(stderr, "arptables: %s\n", nft_strerror(errno));
-
- exit(!ret);
-}
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index de7c3817..cca19438 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -30,35 +30,23 @@
#include "config.h"
#include <getopt.h>
#include <string.h>
-#include <netdb.h>
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include <inttypes.h>
-#include <dlfcn.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <net/if.h>
-#include <netinet/ether.h>
-#include <iptables.h>
#include <xtables.h>
#include "xshared.h"
#include "nft.h"
#include "nft-arp.h"
-#include <linux/netfilter_arp/arp_tables.h>
static struct option original_opts[] = {
{ "append", 1, 0, 'A' },
{ "delete", 1, 0, 'D' },
+ { "check", 1, 0, 'C'},
{ "insert", 1, 0, 'I' },
{ "replace", 1, 0, 'R' },
{ "list", 2, 0, 'L' },
+ { "list-rules", 2, 0, 'S'},
{ "flush", 2, 0, 'F' },
{ "zero", 2, 0, 'Z' },
{ "new-chain", 1, 0, 'N' },
@@ -101,7 +89,7 @@ static void printhelp(const struct xtables_rule_match *m);
struct xtables_globals arptables_globals = {
.option_offset = 0,
.program_version = PACKAGE_VERSION,
- .optstring = OPTSTRING_COMMON "R:S::" "h::l:nv" /* "m:" */,
+ .optstring = OPTSTRING_COMMON "C:R:S::" "h::l:nv" /* "m:" */,
.orig_opts = original_opts,
.exit_err = xtables_exit_error,
.compat_rev = nft_compatible_revision,
@@ -109,25 +97,18 @@ struct xtables_globals arptables_globals = {
};
static void
-exit_tryhelp(int status)
-{
- fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
- arptables_globals.program_name,
- arptables_globals.program_version);
- exit(status);
-}
-
-static void
printhelp(const struct xtables_rule_match *m)
{
struct xtables_target *t = NULL;
int i;
printf("%s v%s\n\n"
-"Usage: %s -[AD] chain rule-specification [options]\n"
-" %s -[RI] chain rulenum rule-specification [options]\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 -[LFZ] [chain] [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"
@@ -141,11 +122,14 @@ printhelp(const struct xtables_rule_match *m)
arptables_globals.program_name,
arptables_globals.program_name,
arptables_globals.program_name,
+ arptables_globals.program_name,
+ arptables_globals.program_name,
arptables_globals.program_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"
@@ -153,9 +137,13 @@ printhelp(const struct xtables_rule_match *m)
" 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] List the rules in a chain or all chains\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] Zero counters 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"
@@ -210,134 +198,6 @@ printhelp(const struct xtables_rule_match *m)
}
}
-static int
-check_inverse(const char option[], int *invert, int *optidx, int argc)
-{
- if (option && strcmp(option, "!") == 0) {
- if (*invert)
- xtables_error(PARAMETER_PROBLEM,
- "Multiple `!' flags not allowed");
- *invert = true;
- if (optidx) {
- *optidx = *optidx+1;
- if (argc && *optidx > argc)
- xtables_error(PARAMETER_PROBLEM,
- "no argument following `!'");
- }
-
- return true;
- }
- return false;
-}
-
-static int
-list_entries(struct nft_handle *h, const char *chain, const char *table,
- int rulenum, int verbose, int numeric, int expanded,
- int linenumbers)
-{
- unsigned int format;
-
- format = FMT_OPTIONS;
- if (!verbose)
- format |= FMT_NOCOUNTS;
- else
- format |= FMT_VIA;
-
- if (numeric)
- format |= FMT_NUMERIC;
-
- if (!expanded)
- format |= FMT_KILOMEGAGIGA;
-
- if (linenumbers)
- format |= FMT_LINENUMBERS;
-
- return nft_cmd_rule_list(h, chain, table, rulenum, format);
-}
-
-static int
-append_entry(struct nft_handle *h,
- const char *chain,
- const char *table,
- struct iptables_command_state *cs,
- int rulenum,
- unsigned int nsaddrs,
- const struct in_addr saddrs[],
- const struct in_addr smasks[],
- unsigned int ndaddrs,
- const struct in_addr daddrs[],
- const struct in_addr dmasks[],
- bool verbose, bool append)
-{
- unsigned int i, j;
- int ret = 1;
-
- for (i = 0; i < nsaddrs; i++) {
- cs->arp.arp.src.s_addr = saddrs[i].s_addr;
- cs->arp.arp.smsk.s_addr = smasks[i].s_addr;
- for (j = 0; j < ndaddrs; j++) {
- cs->arp.arp.tgt.s_addr = daddrs[j].s_addr;
- cs->arp.arp.tmsk.s_addr = dmasks[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);
- }
- }
- }
-
- return ret;
-}
-
-static int
-replace_entry(const char *chain,
- const char *table,
- struct iptables_command_state *cs,
- unsigned int rulenum,
- const struct in_addr *saddr,
- const struct in_addr *smask,
- const struct in_addr *daddr,
- const struct in_addr *dmask,
- bool verbose, struct nft_handle *h)
-{
- cs->arp.arp.src.s_addr = saddr->s_addr;
- cs->arp.arp.tgt.s_addr = daddr->s_addr;
- cs->arp.arp.smsk.s_addr = smask->s_addr;
- cs->arp.arp.tmsk.s_addr = dmask->s_addr;
-
- 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,
- unsigned int nsaddrs,
- const struct in_addr saddrs[],
- const struct in_addr smasks[],
- unsigned int ndaddrs,
- const struct in_addr daddrs[],
- const struct in_addr dmasks[],
- bool verbose, struct nft_handle *h)
-{
- unsigned int i, j;
- int ret = 1;
-
- for (i = 0; i < nsaddrs; i++) {
- cs->arp.arp.src.s_addr = saddrs[i].s_addr;
- cs->arp.arp.smsk.s_addr = smasks[i].s_addr;
- for (j = 0; j < ndaddrs; j++) {
- cs->arp.arp.tgt.s_addr = daddrs[j].s_addr;
- cs->arp.arp.tmsk.s_addr = dmasks[j].s_addr;
- ret = nft_cmd_rule_delete(h, chain, table, cs, verbose);
- }
- }
-
- return ret;
-}
-
int nft_init_arp(struct nft_handle *h, const char *pname)
{
arptables_globals.program_name = pname;
@@ -358,467 +218,3 @@ int nft_init_arp(struct nft_handle *h, const char *pname)
return 0;
}
-
-int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
- bool restore)
-{
- struct iptables_command_state cs = {
- .jumpto = "",
- .arp.arp = {
- .arhln = 6,
- .arhln_mask = 255,
- .arhrd = htons(ARPHRD_ETHER),
- .arhrd_mask = 65535,
- },
- };
- struct nft_xt_cmd_parse p = {
- .table = *table,
- };
- struct xtables_args args = {
- .family = h->family,
- };
- int invert = 0;
- int ret = 1;
- struct xtables_target *t;
-
- /* re-set optind to 0 in case do_command gets called
- * a second time */
- optind = 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, xt_params->optstring,
- opts, NULL)) != -1) {
- switch (cs.c) {
- /*
- * Command selection
- */
- case 'A':
- add_command(&p.command, CMD_APPEND, CMD_NONE,
- invert);
- p.chain = optarg;
- break;
-
- case 'D':
- add_command(&p.command, CMD_DELETE, CMD_NONE,
- 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,
- 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,
- 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,
- invert);
- if (optarg) p.chain = optarg;
- else if (xs_has_arg(argc, argv))
- p.chain = argv[optind++];
- break;
-
- case 'F':
- add_command(&p.command, CMD_FLUSH, CMD_NONE,
- 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,
- invert);
- if (optarg) p.chain = optarg;
- else if (xs_has_arg(argc, argv))
- p.chain = argv[optind++];
- break;
-
- case 'N':
- if (optarg && *optarg == '-')
- xtables_error(PARAMETER_PROBLEM,
- "chain name not allowed to start "
- "with `-'\n");
- 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,
- invert);
- p.chain = optarg;
- break;
-
- case 'X':
- add_command(&p.command, CMD_DELETE_CHAIN, CMD_NONE,
- 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,
- 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,
- 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];
-
- xt_params->print_help(NULL);
- p.command = CMD_NONE;
- break;
- case 's':
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_SOURCE, &args.invflags,
- invert);
- args.shostnetworkmask = argv[optind-1];
- break;
-
- case 'd':
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_DESTINATION, &args.invflags,
- invert);
- args.dhostnetworkmask = argv[optind-1];
- break;
-
- case 2:/* src-mac */
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_S_MAC, &args.invflags,
- invert);
- args.src_mac = argv[optind - 1];
- break;
-
- case 3:/* dst-mac */
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_D_MAC, &args.invflags,
- invert);
- args.dst_mac = argv[optind - 1];
- break;
-
- case 'l':/* hardware length */
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_H_LENGTH, &args.invflags,
- invert);
- args.arp_hlen = argv[optind - 1];
- break;
-
- case 8: /* was never supported, not even in arptables-legacy */
- xtables_error(PARAMETER_PROBLEM, "not supported");
- case 4:/* opcode */
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_OPCODE, &args.invflags,
- invert);
- args.arp_opcode = argv[optind - 1];
- break;
-
- case 5:/* h-type */
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_H_TYPE, &args.invflags,
- invert);
- args.arp_htype = argv[optind - 1];
- break;
-
- case 6:/* proto-type */
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_P_TYPE, &args.invflags,
- invert);
- args.arp_ptype = argv[optind - 1];
- break;
-
- case 'j':
- set_option(&cs.options, OPT_JUMP, &args.invflags,
- invert);
- command_jump(&cs, optarg);
- break;
-
- case 'i':
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_VIANAMEIN, &args.invflags,
- invert);
- xtables_parse_interface(argv[optind-1],
- args.iniface,
- args.iniface_mask);
- break;
-
- case 'o':
- check_inverse(optarg, &invert, &optind, argc);
- set_option(&cs.options, OPT_VIANAMEOUT, &args.invflags,
- invert);
- xtables_parse_interface(argv[optind-1],
- args.outiface,
- args.outiface_mask);
- break;
-
- case 'v':
- if (!p.verbose)
- set_option(&cs.options, OPT_VERBOSE,
- &args.invflags, invert);
- p.verbose++;
- break;
-
- case 'm': /* ignored by arptables-legacy */
- break;
- case 'n':
- set_option(&cs.options, OPT_NUMERIC, &args.invflags,
- invert);
- break;
-
- case 't':
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "unexpected ! flag before --table");
- /* ignore this option.
- * arptables-legacy parses it, but libarptc doesn't use it.
- * arptables only has a 'filter' table anyway.
- */
- break;
-
- case 'V':
- if (invert)
- printf("Not %s ;-)\n", arptables_globals.program_version);
- else
- printf("%s v%s (nf_tables)\n",
- arptables_globals.program_name,
- arptables_globals.program_version);
- exit(0);
-
- case '0':
- set_option(&cs.options, OPT_LINENUMBERS, &args.invflags,
- invert);
- break;
-
- case 'M':
- //modprobe = optarg;
- break;
-
- case 'c':
-
- set_option(&cs.options, OPT_COUNTERS, &args.invflags,
- invert);
- args.pcnt = optarg;
- if (xs_has_arg(argc, argv))
- args.bcnt = argv[optind++];
- else
- xtables_error(PARAMETER_PROBLEM,
- "-%c requires packet and byte counter",
- opt2char(OPT_COUNTERS));
-
- if (sscanf(args.pcnt, "%llu", &cs.arp.counters.pcnt) != 1)
- xtables_error(PARAMETER_PROBLEM,
- "-%c packet counter not numeric",
- opt2char(OPT_COUNTERS));
-
- if (sscanf(args.bcnt, "%llu", &cs.arp.counters.bcnt) != 1)
- xtables_error(PARAMETER_PROBLEM,
- "-%c byte counter not numeric",
- opt2char(OPT_COUNTERS));
-
- break;
-
-
- case 1: /* non option */
- if (optarg[0] == '!' && optarg[1] == '\0') {
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "multiple consecutive ! not"
- " allowed");
- invert = true;
- optarg[0] = '\0';
- continue;
- }
- printf("Bad argument `%s'\n", optarg);
- exit_tryhelp(2);
-
- default:
- if (cs.target) {
- xtables_option_tpcall(cs.c, argv,
- invert, cs.target, &cs.arp);
- }
- break;
- }
- invert = false;
- }
-
- if (cs.target)
- xtables_option_tfcall(cs.target);
-
- if (optind < argc)
- xtables_error(PARAMETER_PROBLEM,
- "unknown arguments found on commandline");
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "nothing appropriate following !");
-
- 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");
-
- if (p.chain && strlen(p.chain) > ARPT_FUNCTION_MAXNAMELEN)
- xtables_error(PARAMETER_PROBLEM,
- "chain name `%s' too long (must be under %i chars)",
- p.chain, ARPT_FUNCTION_MAXNAMELEN);
-
- if (p.command == CMD_APPEND
- || p.command == CMD_DELETE
- || 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);
- }
- }
-
- switch (p.command) {
- case CMD_APPEND:
- ret = append_entry(h, p.chain, p.table, &cs, 0,
- args.s.naddrs, args.s.addr.v4, args.s.mask.v4,
- args.d.naddrs, args.d.addr.v4, args.d.mask.v4,
- cs.options&OPT_VERBOSE, true);
- break;
- case CMD_DELETE:
- ret = delete_entry(p.chain, p.table, &cs,
- args.s.naddrs, args.s.addr.v4, args.s.mask.v4,
- args.d.naddrs, args.d.addr.v4, args.d.mask.v4,
- cs.options&OPT_VERBOSE, h);
- break;
- case CMD_DELETE_NUM:
- ret = nft_cmd_rule_delete_num(h, p.chain, p.table, p.rulenum - 1, p.verbose);
- break;
- case CMD_REPLACE:
- ret = replace_entry(p.chain, p.table, &cs, p.rulenum - 1,
- args.s.addr.v4, args.s.mask.v4, args.d.addr.v4, args.d.mask.v4,
- cs.options&OPT_VERBOSE, h);
- break;
- case CMD_INSERT:
- ret = append_entry(h, p.chain, p.table, &cs, p.rulenum - 1,
- args.s.naddrs, args.s.addr.v4, args.s.mask.v4,
- args.d.naddrs, args.d.addr.v4, args.d.mask.v4,
- cs.options&OPT_VERBOSE, false);
- break;
- case CMD_LIST:
- ret = list_entries(h, p.chain, p.table,
- p.rulenum,
- cs.options&OPT_VERBOSE,
- cs.options&OPT_NUMERIC,
- /*cs.options&OPT_EXPANDED*/0,
- cs.options&OPT_LINENUMBERS);
- break;
- case CMD_FLUSH:
- ret = nft_cmd_rule_flush(h, p.chain, p.table, cs.options & OPT_VERBOSE);
- break;
- case CMD_ZERO:
- ret = nft_cmd_chain_zero_counters(h, p.chain, p.table,
- cs.options & OPT_VERBOSE);
- break;
- case CMD_LIST|CMD_ZERO:
- ret = list_entries(h, p.chain, p.table, p.rulenum,
- cs.options&OPT_VERBOSE,
- cs.options&OPT_NUMERIC,
- /*cs.options&OPT_EXPANDED*/0,
- cs.options&OPT_LINENUMBERS);
- if (ret)
- ret = nft_cmd_chain_zero_counters(h, p.chain, p.table,
- cs.options & OPT_VERBOSE);
- break;
- case CMD_NEW_CHAIN:
- ret = nft_cmd_chain_user_add(h, p.chain, p.table);
- break;
- case CMD_DELETE_CHAIN:
- 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);
- break;
- case CMD_SET_POLICY:
- ret = nft_cmd_chain_set(h, p.table, p.chain, p.policy, NULL);
- if (ret < 0)
- xtables_error(PARAMETER_PROBLEM, "Wrong policy `%s'\n",
- p.policy);
- break;
- case CMD_NONE:
- break;
- default:
- /* We should never reach this... */
- exit_tryhelp(2);
- }
-
- free(args.s.addr.v4);
- free(args.s.mask.v4);
- free(args.d.addr.v4);
- free(args.d.mask.v4);
-
- nft_clear_iptables_command_state(&cs);
- xtables_free_opts(1);
-
-/* if (p.verbose > 1)
- dump_entries(*handle);*/
-
- return ret;
-}
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 86dcede3..aa8b397f 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -451,7 +451,7 @@ int xtables_eb_restore_main(int argc, char *argv[])
static const struct nft_xt_restore_cb arp_restore_cb = {
.commit = nft_commit,
.table_flush = nft_cmd_table_flush,
- .do_command = do_commandarp,
+ .do_command = do_commandx,
.chain_set = nft_cmd_chain_set,
.chain_restore = nft_cmd_chain_restore,
};
diff --git a/iptables/xtables-standalone.c b/iptables/xtables-standalone.c
index 19d663b0..5482a856 100644
--- a/iptables/xtables-standalone.c
+++ b/iptables/xtables-standalone.c
@@ -68,9 +68,17 @@ xtables_main(int family, const char *progname, int argc, char *argv[])
}
xt_params->program_name = progname;
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
- init_extensions();
- init_extensions4();
- init_extensions6();
+ switch (family) {
+ case NFPROTO_IPV4:
+ case NFPROTO_IPV6:
+ init_extensions();
+ init_extensions4();
+ init_extensions6();
+ break;
+ case NFPROTO_ARP:
+ init_extensionsa();
+ break;
+ }
#endif
if (nft_init(&h, family) < 0) {
@@ -107,3 +115,8 @@ int xtables_ip6_main(int argc, char *argv[])
{
return xtables_main(NFPROTO_IPV6, "ip6tables", argc, argv);
}
+
+int xtables_arp_main(int argc, char *argv[])
+{
+ return xtables_main(NFPROTO_ARP, "arptables", argc, argv);
+}
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 075506f0..5c69af7e 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -36,11 +36,13 @@
#include <stdarg.h>
#include <limits.h>
#include <unistd.h>
+#include <netinet/ether.h>
#include <iptables.h>
#include <xtables.h>
#include <fcntl.h>
#include "xshared.h"
#include "nft-shared.h"
+#include "nft-arp.h"
#include "nft.h"
static struct option original_opts[] = {
@@ -273,6 +275,34 @@ static void check_empty_interface(struct nft_handle *h, const char *arg)
fprintf(stderr, "%s", msg);
}
+static void check_inverse(struct nft_handle *h, const char option[],
+ bool *invert, int *optidx, int argc)
+{
+ switch (h->family) {
+ case NFPROTO_ARP:
+ break;
+ default:
+ return;
+ }
+
+ if (!option || strcmp(option, "!"))
+ return;
+
+ fprintf(stderr, "Using intrapositioned negation (`--option ! this`) "
+ "is deprecated in favor of extrapositioned (`! --option this`).\n");
+
+ if (*invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Multiple `!' flags not allowed");
+ *invert = true;
+ if (optidx) {
+ *optidx = *optidx + 1;
+ if (argc && *optidx > argc)
+ xtables_error(PARAMETER_PROBLEM,
+ "no argument following `!'");
+ }
+}
+
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)
@@ -458,14 +488,16 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
* Option selection
*/
case 'p':
+ check_inverse(h, optarg, &invert, &optind, argc);
set_option(&cs->options, OPT_PROTOCOL,
&args->invflags, invert);
/* Canonicalize into lower case */
- for (cs->protocol = optarg; *cs->protocol; cs->protocol++)
+ for (cs->protocol = argv[optind - 1];
+ *cs->protocol; cs->protocol++)
*cs->protocol = tolower(*cs->protocol);
- cs->protocol = optarg;
+ cs->protocol = argv[optind - 1];
args->proto = xtables_parse_protocol(cs->protocol);
if (args->proto == 0 &&
@@ -474,19 +506,22 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
"rule would never match protocol");
/* This needs to happen here to parse extensions */
- h->ops->proto_parse(cs, args);
+ if (h->ops->proto_parse)
+ h->ops->proto_parse(cs, args);
break;
case 's':
+ check_inverse(h, optarg, &invert, &optind, argc);
set_option(&cs->options, OPT_SOURCE,
&args->invflags, invert);
- args->shostnetworkmask = optarg;
+ args->shostnetworkmask = argv[optind - 1];
break;
case 'd':
+ check_inverse(h, optarg, &invert, &optind, argc);
set_option(&cs->options, OPT_DESTINATION,
&args->invflags, invert);
- args->dhostnetworkmask = optarg;
+ args->dhostnetworkmask = argv[optind - 1];
break;
#ifdef IPT_F_GOTO
@@ -498,27 +533,72 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
break;
#endif
+ case 2:/* src-mac */
+ check_inverse(h, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_S_MAC, &args->invflags,
+ invert);
+ args->src_mac = argv[optind - 1];
+ break;
+
+ case 3:/* dst-mac */
+ check_inverse(h, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_D_MAC, &args->invflags,
+ invert);
+ args->dst_mac = argv[optind - 1];
+ break;
+
+ case 'l':/* hardware length */
+ check_inverse(h, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_H_LENGTH, &args->invflags,
+ invert);
+ args->arp_hlen = argv[optind - 1];
+ break;
+
+ case 8: /* was never supported, not even in arptables-legacy */
+ xtables_error(PARAMETER_PROBLEM, "not supported");
+ case 4:/* opcode */
+ check_inverse(h, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_OPCODE, &args->invflags,
+ invert);
+ args->arp_opcode = argv[optind - 1];
+ break;
+
+ case 5:/* h-type */
+ check_inverse(h, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_H_TYPE, &args->invflags,
+ invert);
+ args->arp_htype = argv[optind - 1];
+ break;
+
+ case 6:/* proto-type */
+ check_inverse(h, optarg, &invert, &optind, argc);
+ set_option(&cs->options, OPT_P_TYPE, &args->invflags,
+ invert);
+ args->arp_ptype = argv[optind - 1];
+ break;
+
case 'j':
set_option(&cs->options, OPT_JUMP, &args->invflags,
invert);
- command_jump(cs, optarg);
+ command_jump(cs, argv[optind - 1]);
break;
-
case 'i':
check_empty_interface(h, optarg);
+ check_inverse(h, optarg, &invert, &optind, argc);
set_option(&cs->options, OPT_VIANAMEIN,
&args->invflags, invert);
- xtables_parse_interface(optarg,
+ xtables_parse_interface(argv[optind - 1],
args->iniface,
args->iniface_mask);
break;
case 'o':
check_empty_interface(h, optarg);
+ check_inverse(h, optarg, &invert, &optind, argc);
set_option(&cs->options, OPT_VIANAMEOUT,
&args->invflags, invert);
- xtables_parse_interface(optarg,
+ xtables_parse_interface(argv[optind - 1],
args->outiface,
args->outiface_mask);
break;