From patchwork Fri Aug 10 15:07:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Sutter X-Patchwork-Id: 956283 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=nwl.cc Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41n7lz5RRLz9ryt for ; Sat, 11 Aug 2018 01:07:59 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727771AbeHJRiO (ORCPT ); Fri, 10 Aug 2018 13:38:14 -0400 Received: from orbyte.nwl.cc ([151.80.46.58]:53526 "EHLO orbyte.nwl.cc" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727404AbeHJRiO (ORCPT ); Fri, 10 Aug 2018 13:38:14 -0400 Received: from localhost ([::1]:40570 helo=tatos) by orbyte.nwl.cc with esmtp (Exim 4.90_1) (envelope-from ) id 1fo91C-0007CV-71; Fri, 10 Aug 2018 17:07:58 +0200 From: Phil Sutter To: Pablo Neira Ayuso Cc: Florian Westphal , netfilter-devel@vger.kernel.org Subject: [iptables PATCH 1/3] xtables: Use native nftables limit expression Date: Fri, 10 Aug 2018 17:07:35 +0200 Message-Id: <20180810150737.16959-2-phil@nwl.cc> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810150737.16959-1-phil@nwl.cc> References: <20180810150737.16959-1-phil@nwl.cc> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org The original issue was that for a rule with limit match added by ebtables-nft, the kernel might attempt to use xt_limit instead of ebt_limit (and fail due to that). This happens if xt_limit.ko is loaded but ebt_limit.ko is not, because the kernel prefers the family-independent variants. There are multiple ways to avoid above issue, but using neither xt_limit nor ebt_limit with nft-variants should be the most effective one. Therefore translate a created limit match in userspace into native nftables code before sending it to kernel and do the reverse translation when listing rules. Apart from the translation routines, this requires slight adjustment of nft_is_expr_compatible() since neither xt_limit nor ebt_limit support byte-based limits or inverted limit match. Signed-off-by: Phil Sutter --- iptables/nft-shared.c | 46 +++++++++++++++++++++++++++++++++++++ iptables/nft.c | 53 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 95 insertions(+), 4 deletions(-) diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c index 5b55c7c0a7052..871037d21a7a6 100644 --- a/iptables/nft-shared.c +++ b/iptables/nft-shared.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -549,6 +550,49 @@ void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e) ops->parse_immediate(jumpto, nft_goto, data); } +static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e) +{ + __u32 burst = nftnl_expr_get_u32(e, NFTNL_EXPR_LIMIT_BURST); + __u64 unit = nftnl_expr_get_u64(e, NFTNL_EXPR_LIMIT_UNIT); + __u64 rate = nftnl_expr_get_u64(e, NFTNL_EXPR_LIMIT_RATE); + struct xtables_rule_match **matches; + struct xtables_match *match; + struct nft_family_ops *ops; + struct xt_rateinfo *rinfo; + size_t size; + + switch (ctx->family) { + case NFPROTO_IPV4: + case NFPROTO_IPV6: + case NFPROTO_BRIDGE: + matches = &ctx->cs->matches; + break; + default: + fprintf(stderr, "BUG: nft_parse_match() unknown family %d\n", + ctx->family); + exit(EXIT_FAILURE); + } + + match = xtables_find_match("limit", XTF_TRY_LOAD, matches); + if (match == NULL) + return; + + size = XT_ALIGN(sizeof(struct xt_entry_match)) + match->size; + match->m = xtables_calloc(1, size); + match->m->u.match_size = size; + strcpy(match->m->u.user.name, match->name); + match->m->u.user.revision = match->revision; + xs_init_match(match); + + rinfo = (void *)match->m->data; + rinfo->avg = XT_LIMIT_SCALE * unit / rate; + rinfo->burst = burst; + + ops = nft_family_ops_lookup(ctx->family); + if (ops->parse_match != NULL) + ops->parse_match(match, ctx->cs); +} + void nft_rule_to_iptables_command_state(const struct nftnl_rule *r, struct iptables_command_state *cs) { @@ -586,6 +630,8 @@ void nft_rule_to_iptables_command_state(const struct nftnl_rule *r, nft_parse_match(&ctx, expr); else if (strcmp(name, "target") == 0) nft_parse_target(&ctx, expr); + else if (strcmp(name, "limit") == 0) + nft_parse_limit(&ctx, expr); expr = nftnl_expr_iter_next(iter); } diff --git a/iptables/nft.c b/iptables/nft.c index 120039ed6aac8..8c0746dd94b87 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -38,6 +38,8 @@ #include #include +#include + #include #include #include @@ -896,11 +898,50 @@ static int __add_match(struct nftnl_expr *e, struct xt_entry_match *m) return 0; } +static int add_nft_limit(struct nftnl_rule *r, struct xt_entry_match *m) +{ + struct xt_rateinfo *rinfo = (void *)m->data; + static const uint32_t mult[] = { + XT_LIMIT_SCALE*24*60*60, /* day */ + XT_LIMIT_SCALE*60*60, /* hour */ + XT_LIMIT_SCALE*60, /* min */ + XT_LIMIT_SCALE, /* sec */ + }; + struct nftnl_expr *expr; + int i; + + expr = nftnl_expr_alloc("limit"); + if (!expr) + return -ENOMEM; + + for (i = 1; i < ARRAY_SIZE(mult); i++) { + if (rinfo->avg > mult[i] || + mult[i] / rinfo->avg < mult[i] % rinfo->avg) + break; + } + + nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_TYPE, NFT_LIMIT_PKTS); + nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_FLAGS, 0); + + nftnl_expr_set_u64(expr, NFTNL_EXPR_LIMIT_RATE, + mult[i - 1] / rinfo->avg); + nftnl_expr_set_u64(expr, NFTNL_EXPR_LIMIT_UNIT, + mult[i - 1] / XT_LIMIT_SCALE); + + nftnl_expr_set_u32(expr, NFTNL_EXPR_LIMIT_BURST, rinfo->burst); + + nftnl_rule_add_expr(r, expr); + return 0; +} + int add_match(struct nftnl_rule *r, struct xt_entry_match *m) { struct nftnl_expr *expr; int ret; + if (!strcmp(m->u.user.name, "limit")) + return add_nft_limit(r, m); + expr = nftnl_expr_alloc("match"); if (expr == NULL) return -ENOMEM; @@ -2996,8 +3037,9 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = { }; -static int nft_is_expr_compatible(const char *name) +static int nft_is_expr_compatible(const struct nftnl_expr *expr) { + const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME); int i; for (i = 0; i < NFT_COMPAT_EXPR_MAX; i++) { @@ -3005,6 +3047,11 @@ static int nft_is_expr_compatible(const char *name) return 0; } + if (!strcmp(name, "limit") && + nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_TYPE) == NFT_LIMIT_PKTS && + nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_FLAGS) == 0) + return 0; + return 1; } @@ -3020,9 +3067,7 @@ static bool nft_is_rule_compatible(struct nftnl_rule *rule) expr = nftnl_expr_iter_next(iter); while (expr != NULL) { - const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME); - - if (nft_is_expr_compatible(name) == 0) { + if (nft_is_expr_compatible(expr) == 0) { expr = nftnl_expr_iter_next(iter); continue; } From patchwork Fri Aug 10 15:07:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Sutter X-Patchwork-Id: 956282 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=nwl.cc Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41n7lt4Xbzz9ryt for ; Sat, 11 Aug 2018 01:07:54 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727738AbeHJRiJ (ORCPT ); Fri, 10 Aug 2018 13:38:09 -0400 Received: from orbyte.nwl.cc ([151.80.46.58]:53518 "EHLO orbyte.nwl.cc" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727404AbeHJRiJ (ORCPT ); Fri, 10 Aug 2018 13:38:09 -0400 Received: from localhost ([::1]:40562 helo=tatos) by orbyte.nwl.cc with esmtp (Exim 4.90_1) (envelope-from ) id 1fo916-0007CB-RP; Fri, 10 Aug 2018 17:07:52 +0200 From: Phil Sutter To: Pablo Neira Ayuso Cc: Florian Westphal , netfilter-devel@vger.kernel.org Subject: [iptables PATCH 2/3] ebtables: Merge libebt_limit.c into libxt_limit.c Date: Fri, 10 Aug 2018 17:07:36 +0200 Message-Id: <20180810150737.16959-3-phil@nwl.cc> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810150737.16959-1-phil@nwl.cc> References: <20180810150737.16959-1-phil@nwl.cc> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Both extensions were very similar already, but now that they both are translated into native nftables code, their actual difference (i.e. match size) doesn't matter anymore. This change comes with one caveat: Since ebtables limit match is not in its own file anymore, match preloading automatically also loads the NFPROTO_UNSPEC limit match. This is not a problem per se since match lookup will prefer the family-specific one, but when parsing unknown options, a match without 'parse' callback is encountered. Therefore do_commandeb() has to check existence of that callback prior to dereferencing it. Signed-off-by: Phil Sutter --- extensions/libebt_limit.c | 205 ------------------ extensions/libxt_limit.c | 102 +++++++-- .../ebtables/0002-ebtables-save-restore_0 | 6 +- .../ebtables/0003-ebtables-restore-defaults_0 | 4 +- iptables/xtables-eb.c | 5 +- 5 files changed, 97 insertions(+), 225 deletions(-) delete mode 100644 extensions/libebt_limit.c diff --git a/extensions/libebt_limit.c b/extensions/libebt_limit.c deleted file mode 100644 index e8da2a150e6e1..0000000000000 --- a/extensions/libebt_limit.c +++ /dev/null @@ -1,205 +0,0 @@ -/* ebt_limit - * - * Authors: - * Tom Marshall - * - * Mostly copied from iptables' limit match. - * - * September, 2003 - * - * Translated to use libxtables for ebtables-compat in 2015 by - * Arturo Borrero Gonzalez - */ - -#include -#include -#include -#include -#include -#include -#include -#include "iptables/nft.h" -#include "iptables/nft-bridge.h" - -#define EBT_LIMIT_AVG "3/hour" -#define EBT_LIMIT_BURST 5 - -#define FLAG_LIMIT 0x01 -#define FLAG_LIMIT_BURST 0x02 -#define ARG_LIMIT '1' -#define ARG_LIMIT_BURST '2' - -static const struct option brlimit_opts[] = -{ - { .name = "limit", .has_arg = true, .val = ARG_LIMIT }, - { .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST }, - XT_GETOPT_TABLEEND, -}; - -static void brlimit_print_help(void) -{ - printf( -"limit options:\n" -"--limit avg : max average match rate: default "EBT_LIMIT_AVG"\n" -" [Packets per second unless followed by \n" -" /sec /minute /hour /day postfixes]\n" -"--limit-burst number : number to match in a burst, -1 < number < 10001,\n" -" default %u\n", EBT_LIMIT_BURST); -} - -static int parse_rate(const char *rate, uint32_t *val) -{ - const char *delim; - uint32_t r; - uint32_t mult = 1; /* Seconds by default. */ - - delim = strchr(rate, '/'); - if (delim) { - if (strlen(delim+1) == 0) - return 0; - - if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0) - mult = 1; - else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0) - mult = 60; - else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0) - mult = 60*60; - else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0) - mult = 24*60*60; - else - return 0; - } - r = atoi(rate); - if (!r) - return 0; - - /* This would get mapped to infinite (1/day is minimum they - can specify, so we're ok at that end). */ - if (r / mult > EBT_LIMIT_SCALE) - return 0; - - *val = EBT_LIMIT_SCALE * mult / r; - return 1; -} - -static void brlimit_init(struct xt_entry_match *match) -{ - struct ebt_limit_info *r = (struct ebt_limit_info *)match->data; - - parse_rate(EBT_LIMIT_AVG, &r->avg); - r->burst = EBT_LIMIT_BURST; -} - -static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - struct ebt_limit_info *r = (struct ebt_limit_info *)(*match)->data; - uintmax_t num; - - switch (c) { - case ARG_LIMIT: - EBT_CHECK_OPTION(flags, FLAG_LIMIT); - if (invert) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --limit"); - if (!parse_rate(optarg, &r->avg)) - xtables_error(PARAMETER_PROBLEM, - "bad rate `%s'", optarg); - break; - case ARG_LIMIT_BURST: - EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST); - if (invert) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --limit-burst"); - if (!xtables_strtoul(optarg, NULL, &num, 0, 10000)) - xtables_error(PARAMETER_PROBLEM, - "bad --limit-burst `%s'", optarg); - r->burst = num; - break; - default: - return 0; - } - - return 1; -} - -struct rates -{ - const char *name; - uint32_t mult; -}; - -static struct rates g_rates[] = -{ - { "day", EBT_LIMIT_SCALE*24*60*60 }, - { "hour", EBT_LIMIT_SCALE*60*60 }, - { "minute", EBT_LIMIT_SCALE*60 }, - { "second", EBT_LIMIT_SCALE } -}; - -static void print_rate(uint32_t period) -{ - unsigned int i; - - for (i = 1; i < sizeof(g_rates)/sizeof(struct rates); i++) - if (period > g_rates[i].mult || - g_rates[i].mult/period < g_rates[i].mult%period) - break; - - printf("%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name); -} - -static void brlimit_print(const void *ip, const struct xt_entry_match *match, - int numeric) -{ - struct ebt_limit_info *r = (struct ebt_limit_info *)match->data; - - printf("--limit "); - print_rate(r->avg); - printf("--limit-burst %u ", r->burst); -} - -static void print_rate_xlate(struct xt_xlate *xl, uint32_t period) -{ - unsigned int i; - - for (i = 1; i < sizeof(g_rates)/sizeof(struct rates); i++) - if (period > g_rates[i].mult || - g_rates[i].mult/period < g_rates[i].mult%period) - break; - - xt_xlate_add(xl, "%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name); -} - -static int brlimit_xlate(struct xt_xlate *xl, - const struct xt_xlate_mt_params *params) -{ - const struct ebt_limit_info *r = (const void *)params->match->data; - - xt_xlate_add(xl, "limit rate "); - print_rate_xlate(xl, r->avg); - if (r->burst != 0) - xt_xlate_add(xl, "burst %u packets ", r->burst); - - return 1; -} - -static struct xtables_match brlimit_match = { - .name = "limit", - .revision = 0, - .version = XTABLES_VERSION, - .family = NFPROTO_BRIDGE, - .size = XT_ALIGN(sizeof(struct ebt_limit_info)), - .userspacesize = offsetof(struct ebt_limit_info, prev), - .init = brlimit_init, - .help = brlimit_print_help, - .parse = brlimit_parse, - .print = brlimit_print, - .xlate = brlimit_xlate, - .extra_opts = brlimit_opts, -}; - -void _init(void) -{ - xtables_register_match(&brlimit_match); -} diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c index c8ddca8778400..124bda2902eb7 100644 --- a/extensions/libxt_limit.c +++ b/extensions/libxt_limit.c @@ -6,6 +6,8 @@ #define _BSD_SOURCE 1 #define _DEFAULT_SOURCE 1 #define _ISOC99_SOURCE 1 +#include +#include #include #include #include @@ -13,6 +15,8 @@ #include #include #include +#include "iptables/nft.h" +#include "iptables/nft-bridge.h" #define XT_LIMIT_AVG "3/hour" #define XT_LIMIT_BURST 5 @@ -191,22 +195,92 @@ static int limit_xlate(struct xt_xlate *xl, return 1; } -static struct xtables_match limit_match = { - .family = NFPROTO_UNSPEC, - .name = "limit", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct xt_rateinfo)), - .userspacesize = offsetof(struct xt_rateinfo, prev), - .help = limit_help, - .init = limit_init, - .x6_parse = limit_parse, - .print = limit_print, - .save = limit_save, - .x6_options = limit_opts, - .xlate = limit_xlate, +#define FLAG_LIMIT 0x01 +#define FLAG_LIMIT_BURST 0x02 +#define ARG_LIMIT '1' +#define ARG_LIMIT_BURST '2' + +static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct xt_rateinfo *r = (struct xt_rateinfo *)(*match)->data; + uintmax_t num; + + switch (c) { + case ARG_LIMIT: + EBT_CHECK_OPTION(flags, FLAG_LIMIT); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --limit"); + if (!parse_rate(optarg, &r->avg)) + xtables_error(PARAMETER_PROBLEM, + "bad rate `%s'", optarg); + break; + case ARG_LIMIT_BURST: + EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --limit-burst"); + if (!xtables_strtoul(optarg, NULL, &num, 0, 10000)) + xtables_error(PARAMETER_PROBLEM, + "bad --limit-burst `%s'", optarg); + r->burst = num; + break; + default: + return 0; + } + + return 1; +} + +static void brlimit_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct xt_rateinfo *r = (struct xt_rateinfo *)match->data; + + printf("--limit"); + print_rate(r->avg); + printf(" --limit-burst %u ", r->burst); +} + +static const struct option brlimit_opts[] = +{ + { .name = "limit", .has_arg = true, .val = ARG_LIMIT }, + { .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST }, + XT_GETOPT_TABLEEND, +}; + +static struct xtables_match limit_match[] = { + { + .family = NFPROTO_UNSPEC, + .name = "limit", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_rateinfo)), + .userspacesize = offsetof(struct xt_rateinfo, prev), + .help = limit_help, + .init = limit_init, + .x6_parse = limit_parse, + .print = limit_print, + .save = limit_save, + .x6_options = limit_opts, + .xlate = limit_xlate, + }, + { + .family = NFPROTO_BRIDGE, + .name = "limit", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_rateinfo)), + .userspacesize = offsetof(struct xt_rateinfo, prev), + .help = limit_help, + .init = limit_init, + .parse = brlimit_parse, + .print = brlimit_print, + .extra_opts = brlimit_opts, + .xlate = limit_xlate, + }, }; void _init(void) { - xtables_register_match(&limit_match); + xtables_register_matches(limit_match, ARRAY_SIZE(limit_match)); } diff --git a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 index 1de76840a8432..eeb7d83574e9d 100755 --- a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 +++ b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 @@ -84,15 +84,15 @@ DUMP='*filter -A foo -p IPv6 --ip6-src feed:babe::1 -j ACCEPT -A foo -p IPv6 --ip6-dst feed:babe::/64 -j ACCEPT -A foo -p IPv6 --ip6-proto tcp -j ACCEPT --A foo --limit 100/second --limit-burst 42 -j ACCEPT +-A foo --limit 100/sec --limit-burst 42 -j ACCEPT -A foo --log-level notice --log-prefix "" -j CONTINUE -A foo -j mark --mark-set 0x23 --mark-target ACCEPT -A foo --nflog-group 1 -j CONTINUE -A foo --pkttype-type multicast -j ACCEPT -A foo --stp-type config -j ACCEPT --A foo --802_3-sap 0x23 --limit 100/second --limit-burst 5 -j ACCEPT +-A foo --802_3-sap 0x23 --limit 100/sec --limit-burst 5 -j ACCEPT -A foo --pkttype-type multicast --log-level notice --log-prefix "" -j CONTINUE --A foo --pkttype-type multicast --limit 100/second --limit-burst 5 -j ACCEPT +-A foo --pkttype-type multicast --limit 100/sec --limit-burst 5 -j ACCEPT *nat :PREROUTING ACCEPT diff --git a/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 b/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 index d82bae549212f..c858054764d70 100755 --- a/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 +++ b/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 @@ -22,8 +22,8 @@ EXPECT='*filter :INPUT ACCEPT :FORWARD ACCEPT :OUTPUT ACCEPT --A FORWARD --limit 100/second --limit-burst 42 -j ACCEPT --A FORWARD --limit 1000/second --limit-burst 5 -j ACCEPT +-A FORWARD --limit 100/sec --limit-burst 42 -j ACCEPT +-A FORWARD --limit 1000/sec --limit-burst 5 -j ACCEPT -A FORWARD --log-level notice --log-prefix "foobar" -j CONTINUE -A FORWARD --log-level notice --log-prefix "" -j CONTINUE ' diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c index 798c027c134ac..a46b9e5a9113b 100644 --- a/iptables/xtables-eb.c +++ b/iptables/xtables-eb.c @@ -1199,7 +1199,10 @@ print_zero: /* Is it a match_option? */ for (m = xtables_matches; m; m = m->next) { - if (m->parse(c - m->option_offset, argv, ebt_check_inverse2(optarg, argc, argv), &m->mflags, NULL, &m->m)) { + if (m->parse && + m->parse(c - m->option_offset, argv, + ebt_check_inverse2(optarg, argc, argv), + &m->mflags, NULL, &m->m)) { ebt_add_match(m, &cs); goto check_extension; } From patchwork Fri Aug 10 15:07:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Sutter X-Patchwork-Id: 956281 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=nwl.cc Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41n7lp50Xjz9ryt for ; Sat, 11 Aug 2018 01:07:50 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727563AbeHJRiE (ORCPT ); Fri, 10 Aug 2018 13:38:04 -0400 Received: from orbyte.nwl.cc ([151.80.46.58]:53510 "EHLO orbyte.nwl.cc" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727404AbeHJRiE (ORCPT ); Fri, 10 Aug 2018 13:38:04 -0400 Received: from localhost ([::1]:40554 helo=tatos) by orbyte.nwl.cc with esmtp (Exim 4.90_1) (envelope-from ) id 1fo911-0007Bn-GP; Fri, 10 Aug 2018 17:07:47 +0200 From: Phil Sutter To: Pablo Neira Ayuso Cc: Florian Westphal , netfilter-devel@vger.kernel.org Subject: [iptables PATCH 3/3] arptables: Drop extensions/libxt_mangle.c Date: Fri, 10 Aug 2018 17:07:37 +0200 Message-Id: <20180810150737.16959-4-phil@nwl.cc> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180810150737.16959-1-phil@nwl.cc> References: <20180810150737.16959-1-phil@nwl.cc> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This was merely an outdated duplicate of extensions/libarpt_mangle.c. Signed-off-by: Phil Sutter --- extensions/libxt_mangle.c | 396 -------------------------------------- 1 file changed, 396 deletions(-) delete mode 100644 extensions/libxt_mangle.c diff --git a/extensions/libxt_mangle.c b/extensions/libxt_mangle.c deleted file mode 100644 index 360742b6f4a21..0000000000000 --- a/extensions/libxt_mangle.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * 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. - * - * Authors: - * Libarptc code from: Bart De Schuymer - * Port to libxtables: Tomasz Bursztyka - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static void mangle_help(void) -{ - printf( -"mangle target options:\n" -"--mangle-ip-s IP address\n" -"--mangle-ip-d IP address\n" -"--mangle-mac-s MAC address\n" -"--mangle-mac-d MAC address\n" -"--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n" - ); -} - -enum { - MANGLE_IPS = 0, - MANGLE_IPT = 1, - MANGLE_DEVS = 2, - MANGLE_DEVT = 3, - MANGLE_TARGET = 4, -}; - -static const struct xt_option_entry mangle_opts[] = { - { .name = "mangle-ip-s", .id = MANGLE_IPS, .type = XTTYPE_STRING }, - { .name = "mangle-ip-d", .id = MANGLE_IPT, .type = XTTYPE_STRING }, - { .name = "mangle-mac-s", .id = MANGLE_DEVS, .type = XTTYPE_STRING }, - { .name = "mangle-mac-d", .id = MANGLE_DEVT, .type = XTTYPE_STRING }, - { .name = "mangle-target", .id = MANGLE_TARGET, - .type = XTTYPE_STRING }, - XTOPT_TABLEEND, -}; - - -static struct in_addr *network_to_addr(const char *name) -{ - struct netent *net; - static struct in_addr addr; - - if ((net = getnetbyname(name)) != NULL) { - if (net->n_addrtype != AF_INET) - return (struct in_addr *) NULL; - addr.s_addr = htonl((unsigned long) net->n_net); - return &addr; - } - - return (struct in_addr *) NULL; -} - -static void inaddrcpy(struct in_addr *dst, struct in_addr *src) -{ - dst->s_addr = src->s_addr; -} - -static struct in_addr *host_to_addr(const char *name, unsigned int *naddr) -{ - struct in_addr *addr; - struct addrinfo hints; - struct addrinfo *res, *p; - int err; - unsigned int i; - - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_RAW; - - *naddr = 0; - err = getaddrinfo(name, NULL, &hints, &res); - if (err != 0) - return NULL; - else { - for (p = res; p != NULL; p = p->ai_next) - (*naddr)++; - addr = xtables_calloc(*naddr, sizeof(struct in_addr)); - for (i = 0, p = res; p != NULL; p = p->ai_next) - memcpy(&addr[i++], - &((const struct sockaddr_in *)p->ai_addr)->sin_addr, - sizeof(struct in_addr)); - freeaddrinfo(res); - return addr; - } - - return (struct in_addr *) NULL; -} - -static int string_to_number(const char *s, unsigned int min, - unsigned int max, unsigned int *ret) -{ - long number; - char *end; - - /* Handle hex, octal, etc. */ - errno = 0; - number = strtol(s, &end, 0); - if (*end == '\0' && end != s) { - /* we parsed a number, let's see if we want this */ - if (errno != ERANGE && min <= number && number <= max) { - *ret = number; - return 0; - } - } - return -1; -} - -static struct in_addr *dotted_to_addr(const char *dotted) -{ - static struct in_addr addr; - unsigned char *addrp; - char *p, *q; - unsigned int onebyte; - int i; - char buf[20]; - - /* copy dotted string, because we need to modify it */ - strncpy(buf, dotted, sizeof(buf) - 1); - addrp = (unsigned char *) &(addr.s_addr); - - p = buf; - for (i = 0; i < 3; i++) { - if ((q = strchr(p, '.')) == NULL) - return (struct in_addr *) NULL; - - *q = '\0'; - if (string_to_number(p, 0, 255, &onebyte) == -1) - return (struct in_addr *) NULL; - - addrp[i] = (unsigned char) onebyte; - p = q + 1; - } - - /* we've checked 3 bytes, now we check the last one */ - if (string_to_number(p, 0, 255, &onebyte) == -1) - return (struct in_addr *) NULL; - - addrp[3] = (unsigned char) onebyte; - - return &addr; -} - -static struct in_addr *parse_hostnetwork(const char *name, - unsigned int *naddrs) -{ - struct in_addr *addrp, *addrptmp; - - if ((addrptmp = dotted_to_addr(name)) != NULL || - (addrptmp = network_to_addr(name)) != NULL) { - addrp = xtables_malloc(sizeof(struct in_addr)); - inaddrcpy(addrp, addrptmp); - *naddrs = 1; - return addrp; - } - if ((addrp = host_to_addr(name, naddrs)) != NULL) - return addrp; - - xtables_error(PARAMETER_PROBLEM, "host/network `%s' not found", name); -} - -static void mangle_parse(struct xt_option_call *cb) -{ - const struct arpt_entry *e = cb->xt_entry; - struct arpt_mangle *mangle = cb->data; - struct in_addr *ipaddr; - struct ether_addr *macaddr; - - /* mangle target is by default "ACCEPT". Setting it here, - * since original arpt_mangle.c init() no longer exists*/ - mangle->target = NF_ACCEPT; - - xtables_option_parse(cb); - switch (cb->entry->id) { - case MANGLE_IPS: -/* - if (e->arp.arpln_mask == 0) - xtables_error(PARAMETER_PROBLEM, "no pln defined"); - - if (e->arp.invflags & ARPT_INV_ARPPLN) - xtables_error(PARAMETER_PROBLEM, - "! pln not allowed for --mangle-ip-s"); -*/ -/* - if (e->arp.arpln != 4) - xtables_error(PARAMETER_PROBLEM, "only pln=4 supported"); -*/ - { - unsigned int nr; - ipaddr = parse_hostnetwork(cb->arg, &nr); - } - mangle->u_s.src_ip.s_addr = ipaddr->s_addr; - free(ipaddr); - mangle->flags |= ARPT_MANGLE_SIP; - break; - case MANGLE_IPT: -/* - if (e->arp.arpln_mask == 0) - xtables_error(PARAMETER_PROBLEM, "no pln defined"); - - if (e->arp.invflags & ARPT_INV_ARPPLN) - xtables_error(PARAMETER_PROBLEM, - "! pln not allowed for --mangle-ip-d"); -*/ -/* - if (e->arp.arpln != 4) - xtables_error(PARAMETER_PROBLEM, "only pln=4 supported"); -*/ - { - unsigned int nr; - ipaddr = parse_hostnetwork(cb->arg, &nr); - } - mangle->u_t.tgt_ip.s_addr = ipaddr->s_addr; - free(ipaddr); - mangle->flags |= ARPT_MANGLE_TIP; - break; - case MANGLE_DEVS: - if (e->arp.arhln_mask == 0) - xtables_error(PARAMETER_PROBLEM, - "no --h-length defined"); - if (e->arp.invflags & ARPT_INV_ARPHLN) - xtables_error(PARAMETER_PROBLEM, - "! --h-length not allowed for " - "--mangle-mac-s"); - if (e->arp.arhln != 6) - xtables_error(PARAMETER_PROBLEM, - "only --h-length 6 supported"); - macaddr = ether_aton(cb->arg); - if (macaddr == NULL) - xtables_error(PARAMETER_PROBLEM, "invalid source MAC"); - memcpy(mangle->src_devaddr, macaddr, e->arp.arhln); - mangle->flags |= ARPT_MANGLE_SDEV; - break; - case MANGLE_DEVT: - if (e->arp.arhln_mask == 0) - xtables_error(PARAMETER_PROBLEM, - "no --h-length defined"); - if (e->arp.invflags & ARPT_INV_ARPHLN) - xtables_error(PARAMETER_PROBLEM, - "! hln not allowed for --mangle-mac-d"); - if (e->arp.arhln != 6) - xtables_error(PARAMETER_PROBLEM, - "only --h-length 6 supported"); - macaddr = ether_aton(cb->arg); - if (macaddr == NULL) - xtables_error(PARAMETER_PROBLEM, "invalid target MAC"); - memcpy(mangle->tgt_devaddr, macaddr, e->arp.arhln); - mangle->flags |= ARPT_MANGLE_TDEV; - break; - case MANGLE_TARGET: - if (!strcmp(cb->arg, "DROP")) - mangle->target = NF_DROP; - else if (!strcmp(cb->arg, "ACCEPT")) - mangle->target = NF_ACCEPT; - else if (!strcmp(cb->arg, "CONTINUE")) - mangle->target = ARPT_CONTINUE; - else - xtables_error(PARAMETER_PROBLEM, - "bad target for --mangle-target"); - break; - } -} - -static void mangle_fcheck(struct xt_fcheck_call *cb) -{ -} - -static char *addr_to_dotted(const struct in_addr *addrp) -{ - static char buf[20]; - const unsigned char *bytep; - - bytep = (const unsigned char *) &(addrp->s_addr); - sprintf(buf, "%d.%d.%d.%d", bytep[0], bytep[1], bytep[2], bytep[3]); - return buf; -} - -static char *addr_to_host(const struct in_addr *addr) -{ - struct hostent *host; - - if ((host = gethostbyaddr((char *) addr, - sizeof(struct in_addr), AF_INET)) != NULL) - return (char *) host->h_name; - - return (char *) NULL; -} - -static char *addr_to_network(const struct in_addr *addr) -{ - struct netent *net; - - if ((net = getnetbyaddr((long) ntohl(addr->s_addr), AF_INET)) != NULL) - return (char *) net->n_name; - - return (char *) NULL; -} - -static char *addr_to_anyname(const struct in_addr *addr) -{ - char *name; - - if ((name = addr_to_host(addr)) != NULL || - (name = addr_to_network(addr)) != NULL) - return name; - - return addr_to_dotted(addr); -} - -static void print_mac(const unsigned char *mac, int l) -{ - int j; - - for (j = 0; j < l; j++) - printf("%02x%s", mac[j], - (j==l-1) ? "" : ":"); -} - -static void mangle_print(const void *ip, const struct xt_entry_target *target, - int numeric) -{ - const struct arpt_mangle *m = (const void *)target; - char buf[100]; - - if (m->flags & ARPT_MANGLE_SIP) { - if (numeric) - sprintf(buf, "%s", addr_to_dotted(&(m->u_s.src_ip))); - else - sprintf(buf, "%s", addr_to_anyname(&(m->u_s.src_ip))); - printf("--mangle-ip-s %s ", buf); - } - if (m->flags & ARPT_MANGLE_SDEV) { - printf("--mangle-mac-s "); - print_mac((unsigned char *)m->src_devaddr, 6); - printf(" "); - } - if (m->flags & ARPT_MANGLE_TIP) { - if (numeric) - sprintf(buf, "%s", addr_to_dotted(&(m->u_t.tgt_ip))); - else - sprintf(buf, "%s", addr_to_anyname(&(m->u_t.tgt_ip))); - printf("--mangle-ip-d %s ", buf); - } - if (m->flags & ARPT_MANGLE_TDEV) { - printf("--mangle-mac-d "); - print_mac((unsigned char *)m->tgt_devaddr, 6); - printf(" "); - } - if (m->target != NF_ACCEPT) { - printf("--mangle-target "); - if (m->target == NF_DROP) - printf("DROP "); - else - printf("CONTINUE "); - } -} - -static void mangle_save(const void *ip, const struct xt_entry_target *target) -{ -} - -static struct xtables_target mangle_tg_reg = { - .family = NFPROTO_ARP, - .name = "mangle", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct arpt_mangle)), - .userspacesize = XT_ALIGN(sizeof(struct arpt_mangle)), - .help = mangle_help, - .x6_parse = mangle_parse, - .x6_fcheck = mangle_fcheck, - .print = mangle_print, - .save = mangle_save, - .x6_options = mangle_opts, -}; - -void _init(void) -{ - xtables_register_target(&mangle_tg_reg); -}