From patchwork Sat Jun 29 21:33:13 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mr Dash Four X-Patchwork-Id: 255794 X-Patchwork-Delegate: kadlec@blackhole.kfki.hu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3DFCC2C02B0 for ; Sun, 30 Jun 2013 07:33:24 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751214Ab3F2VdX (ORCPT ); Sat, 29 Jun 2013 17:33:23 -0400 Received: from mail-wi0-f175.google.com ([209.85.212.175]:44698 "EHLO mail-wi0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750901Ab3F2VdW (ORCPT ); Sat, 29 Jun 2013 17:33:22 -0400 Received: by mail-wi0-f175.google.com with SMTP id m6so1941140wiv.8 for ; Sat, 29 Jun 2013 14:33:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-type:content-transfer-encoding; bh=3ZOdFbaOOrW30SKHp2D5iSCWeiYnzpnHps4vVNi6h1A=; b=Wvrm9UQmEAFLK2PAHLwLvX+UGGkgRa9xvPJUHqMBRpJFXywvEJ+lge2wpSBnikhNTp jsyqpOq18RwMgvA8xgLP1TutvxIHWeajWMbE3Jo75RMSHL4DmhT7ITgo2R1GF49cKre/ KAd68uYwqAHRLq/5WiGsyHxbsYK5VvLTGnpp3ekvJqRqMlw9LCnq+ulsgCU/32+OKEpw A97G/vQNScXi8/OYp8I3z0X8joH0Y6dZ4jKfDqTjLg/U9uuyMIZFhC5F/LAKUu9u+0EQ bsmrit9DJIbT2w04SZdcNKKrNAJxRrECEeBRLQ4OMao2RQHyyf2a2XJLfShvv/KBjLhQ hsGA== X-Received: by 10.180.8.106 with SMTP id q10mr1078685wia.21.1372541601521; Sat, 29 Jun 2013 14:33:21 -0700 (PDT) Received: from [10.68.68.173] (cpc2-gill1-0-0-cust32.20-1.cable.virginmedia.com. [77.100.109.33]) by mx.google.com with ESMTPSA id b9sm6415144wik.5.2013.06.29.14.33.19 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 29 Jun 2013 14:33:20 -0700 (PDT) Message-ID: <51CF5299.5070700@googlemail.com> Date: Sat, 29 Jun 2013 22:33:13 +0100 From: Dash Four User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.23) Gecko/20090812 Thunderbird/2.0.0.23 MIME-Version: 1.0 To: Jozsef Kadlecsik CC: Pablo Neira Ayuso , Netfilter Core Team Subject: [PATCH v3 5/5] iptables (userspace): add set match "inner" flag support References: <35b6c01e2fda99f15993c76aea9078e4336fb68a.1372540306.git.mr.dash.four@googlemail.com> In-Reply-To: <35b6c01e2fda99f15993c76aea9078e4336fb68a.1372540306.git.mr.dash.four@googlemail.com> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch adds "inner" flag support for the set match in iptables. Revision history: v1 * initial revision Signed-off-by: Dash Four --- extensions/libxt_set.c | 199 +++++++++++++++++++++++++++++++++ extensions/libxt_set.man | 10 ++ include/linux/netfilter/ipset/ip_set.h | 2 + 3 files changed, 211 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c index 2cb9e78..3b20c94 100644 --- a/extensions/libxt_set.c +++ b/extensions/libxt_set.c @@ -497,6 +497,191 @@ set_save_v3(const void *ip, const struct xt_entry_match *match) set_print_v3_matchinfo(info, "--match-set", "--"); } +/* Revision 4 - add --inner flag */ +static void +set_help_v4(void) +{ + printf("set match options:\n" + " [!] --match-set name flags [--return-nomatch] [--inner]\n" + " [! --update-counters] [! --update-subcounters]\n" + " [[!] --packets-eq value | --packets-lt value | --packets-gt value\n" + " [[!] --bytes-eq value | --bytes-lt value | --bytes-gt value\n" + " 'name' is the set name from to match,\n" + " 'flags' are the comma separated list of\n" + " 'src' and 'dst' specifications.\n"); +} + +static const struct option set_opts_v4[] = { + {.name = "match-set", .has_arg = true, .val = '1'}, + {.name = "set", .has_arg = true, .val = '2'}, + {.name = "return-nomatch", .has_arg = false, .val = '3'}, + {.name = "update-counters", .has_arg = false, .val = '4'}, + {.name = "packets-eq", .has_arg = true, .val = '5'}, + {.name = "packets-lt", .has_arg = true, .val = '6'}, + {.name = "packets-gt", .has_arg = true, .val = '7'}, + {.name = "bytes-eq", .has_arg = true, .val = '8'}, + {.name = "bytes-lt", .has_arg = true, .val = '9'}, + {.name = "bytes-gt", .has_arg = true, .val = '0'}, + {.name = "update-subcounters", .has_arg = false, .val = 'a'}, + {.name = "inner", .has_arg = false, .val = 'b'}, + XT_GETOPT_TABLEEND, +}; + +static int +set_parse_v4(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct xt_set_info_match_v3 *info = + (struct xt_set_info_match_v3 *) (*match)->data; + + switch (c) { + case 'b': + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--inner flag cannot be inverted\n"); + info->flags |= IPSET_FLAG_INNER; + break; + case 'a': + if (invert) + info->flags |= IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE; + break; + case '0': + if (info->bytes.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --bytes-[eq|lt|gt]" + " is allowed\n"); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--bytes-gt option cannot be inverted\n"); + info->bytes.op = IPSET_COUNTER_GT; + info->bytes.value = parse_counter(optarg); + break; + case '9': + if (info->bytes.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --bytes-[eq|lt|gt]" + " is allowed\n"); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--bytes-lt option cannot be inverted\n"); + info->bytes.op = IPSET_COUNTER_LT; + info->bytes.value = parse_counter(optarg); + break; + case '8': + if (info->bytes.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --bytes-[eq|lt|gt]" + " is allowed\n"); + info->bytes.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; + info->bytes.value = parse_counter(optarg); + break; + case '7': + if (info->packets.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --packets-[eq|lt|gt]" + " is allowed\n"); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--packets-gt option cannot be inverted\n"); + info->packets.op = IPSET_COUNTER_GT; + info->packets.value = parse_counter(optarg); + break; + case '6': + if (info->packets.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --packets-[eq|lt|gt]" + " is allowed\n"); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--packets-lt option cannot be inverted\n"); + info->packets.op = IPSET_COUNTER_LT; + info->packets.value = parse_counter(optarg); + break; + case '5': + if (info->packets.op != IPSET_COUNTER_NONE) + xtables_error(PARAMETER_PROBLEM, + "only one of the --packets-[eq|lt|gt]" + " is allowed\n"); + info->packets.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; + info->packets.value = parse_counter(optarg); + break; + case '4': + if (invert) + info->flags |= IPSET_FLAG_SKIP_COUNTER_UPDATE; + break; + case '3': + if (invert) + xtables_error(PARAMETER_PROBLEM, + "--return-nomatch flag cannot be inverted\n"); + info->flags |= IPSET_FLAG_RETURN_NOMATCH; + break; + case '2': + fprintf(stderr, + "--set option deprecated, please use --match-set\n"); + case '1': /* --match-set [, */ + if (info->match_set.dim) + xtables_error(PARAMETER_PROBLEM, + "--match-set can be specified only once"); + if (invert) + info->match_set.flags |= IPSET_INV_MATCH; + + if (!argv[optind] + || argv[optind][0] == '-' + || argv[optind][0] == '!') + xtables_error(PARAMETER_PROBLEM, + "--match-set requires two args."); + + if (strlen(optarg) > IPSET_MAXNAMELEN - 1) + xtables_error(PARAMETER_PROBLEM, + "setname `%s' too long, max %d characters.", + optarg, IPSET_MAXNAMELEN - 1); + + get_set_byname(optarg, &info->match_set); + parse_dirs(argv[optind], &info->match_set); + DEBUGP("parse: set index %u\n", info->match_set.index); + optind++; + + *flags = 1; + break; + } + + return 1; +} + +static void +set_print_v4_matchinfo(const struct xt_set_info_match_v3 *info, + const char *opt, const char *sep) +{ + print_match(opt, &info->match_set); + if (info->flags & IPSET_FLAG_RETURN_NOMATCH) + printf(" %sreturn-nomatch", sep); + if (info->flags & IPSET_FLAG_INNER) + printf(" %sinner", sep); + if ((info->flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) + printf(" ! %supdate-counters", sep); + if ((info->flags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)) + printf(" ! %supdate-subcounters", sep); + set_printv3_counter(&info->packets, "packets", sep); + set_printv3_counter(&info->bytes, "bytes", sep); +} + +/* Prints out the matchinfo. */ +static void +set_print_v4(const void *ip, const struct xt_entry_match *match, int numeric) +{ + const struct xt_set_info_match_v3 *info = (const void *)match->data; + + set_print_v4_matchinfo(info, "match-set", ""); +} + +static void +set_save_v4(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_set_info_match_v3 *info = (const void *)match->data; + + set_print_v4_matchinfo(info, "--match-set", "--"); +} + static struct xtables_match set_mt_reg[] = { { .name = "set", @@ -554,6 +739,20 @@ static struct xtables_match set_mt_reg[] = { .save = set_save_v3, .extra_opts = set_opts_v3, }, + { + .name = "set", + .revision = 4, + .version = XTABLES_VERSION, + .family = NFPROTO_UNSPEC, + .size = XT_ALIGN(sizeof(struct xt_set_info_match_v3)), + .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v3)), + .help = set_help_v4, + .parse = set_parse_v4, + .final_check = set_check_v0, + .print = set_print_v4, + .save = set_save_v4, + .extra_opts = set_opts_v4, + }, }; void _init(void) diff --git a/extensions/libxt_set.man b/extensions/libxt_set.man index 7012ef2..21e443c 100644 --- a/extensions/libxt_set.man +++ b/extensions/libxt_set.man @@ -21,6 +21,16 @@ supports the \fBnomatch\fP flag, then the matching is reversed: a match with an element flagged with \fBnomatch\fP returns \fBtrue\fP, while a match with a plain element returns \fBfalse\fP. .TP +\fB\-\-inner\fP +Please note that this option will only produce matches in the event of +the following ICMPv4 and ICMPv6 messages: \fBdestination-unreachable\fP +(ICMPv4 code 3 and ICMPv6 code 1), \fBsource-quench\fP (ICMPv4 code 4), +\fBtime-exceeded\fP (ICMPv4 code 11 and ICMPv6 code 3) and +\fBpacket-too-big\fP (ICMPv6 code 2). If the \fB\-\-inner\fP option is +specified, then element matching is based on the properties +(source/destination IP address, protocol, port and so on) of the original +(inner) connection, which produced the above ICMP[v6] type messages. +.TP \fB!\fP \fB\-\-update\-counters\fP If the \fB\-\-update\-counters\fP flag is negated, then the packet and byte counters of the matching element in the set won't be updated. Default diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h index eb9123e..1b3d9cb 100644 --- a/include/linux/netfilter/ipset/ip_set.h +++ b/include/linux/netfilter/ipset/ip_set.h @@ -161,6 +161,8 @@ enum ipset_cmd_flags { (1 << IPSET_FLAG_BIT_SKIP_SUBCOUNTER_UPDATE), IPSET_FLAG_BIT_MATCH_COUNTERS = 5, IPSET_FLAG_MATCH_COUNTERS = (1 << IPSET_FLAG_BIT_MATCH_COUNTERS), + IPSET_FLAG_BIT_INNER = 6, + IPSET_FLAG_INNER = (1 << IPSET_FLAG_BIT_INNER), IPSET_FLAG_BIT_RETURN_NOMATCH = 7, IPSET_FLAG_RETURN_NOMATCH = (1 << IPSET_FLAG_BIT_RETURN_NOMATCH), IPSET_FLAG_CMD_MAX = 15,