summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2013-05-01 00:56:35 +0200
committerFlorian Westphal <fw@strlen.de>2013-06-07 19:30:57 +0200
commit34844da8f53ec80b34ad094f2fca2519a7079ec2 (patch)
tree513e761fd914bffb8d96aade042312d5073be437 /extensions
parentf927d5fc3a6a0a8a8fb03e733a6572a934482723 (diff)
Introduce a new revision for the set match with the counters support
The revision add the support of matching the packet/byte counters if the set was defined with the extension. Also, a new flag is introduced to suppress updating the packet/byte counters if required. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libxt_set.c222
-rw-r--r--extensions/libxt_set.man41
2 files changed, 261 insertions, 2 deletions
diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c
index e0111568..2cb9e78a 100644
--- a/extensions/libxt_set.c
+++ b/extensions/libxt_set.c
@@ -289,6 +289,214 @@ set_save_v2(const void *ip, const struct xt_entry_match *match)
printf(" --return-nomatch");
}
+/* Revision 3 */
+static void
+set_help_v3(void)
+{
+ printf("set match options:\n"
+ " [!] --match-set name flags [--return-nomatch]\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_v3[] = {
+ {.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'},
+ XT_GETOPT_TABLEEND,
+};
+
+static uint64_t
+parse_counter(const char *opt)
+{
+ uintmax_t value;
+
+ if (!xtables_strtoul(opt, NULL, &value, 0, UINT64_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "Cannot parse %s as a counter value\n",
+ opt);
+ return (uint64_t)value;
+}
+
+static int
+set_parse_v3(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 '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 <set> <flag>[,<flag> */
+ 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_printv3_counter(const struct ip_set_counter_match *c, const char *name,
+ const char *sep)
+{
+ switch (c->op) {
+ case IPSET_COUNTER_EQ:
+ printf(" %s%s-eq %llu", sep, name, c->value);
+ break;
+ case IPSET_COUNTER_NE:
+ printf(" ! %s%s-eq %llu", sep, name, c->value);
+ break;
+ case IPSET_COUNTER_LT:
+ printf(" %s%s-lt %llu", sep, name, c->value);
+ break;
+ case IPSET_COUNTER_GT:
+ printf(" %s%s-gt %llu", sep, name, c->value);
+ break;
+ }
+}
+
+static void
+set_print_v3_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_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_v3(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_v3_matchinfo(info, "match-set", "");
+}
+
+static void
+set_save_v3(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_set_info_match_v3 *info = (const void *)match->data;
+
+ set_print_v3_matchinfo(info, "--match-set", "--");
+}
+
static struct xtables_match set_mt_reg[] = {
{
.name = "set",
@@ -332,6 +540,20 @@ static struct xtables_match set_mt_reg[] = {
.save = set_save_v2,
.extra_opts = set_opts_v2,
},
+ {
+ .name = "set",
+ .revision = 3,
+ .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_v3,
+ .parse = set_parse_v3,
+ .final_check = set_check_v0,
+ .print = set_print_v3,
+ .save = set_save_v3,
+ .extra_opts = set_opts_v3,
+ },
};
void _init(void)
diff --git a/extensions/libxt_set.man b/extensions/libxt_set.man
index ac60f148..7012ef2e 100644
--- a/extensions/libxt_set.man
+++ b/extensions/libxt_set.man
@@ -15,11 +15,48 @@ the set type of the specified set is single dimension (for example ipmap),
then the command will match packets for which the source address can be
found in the specified set.
.TP
-\fB\-\-return\-\-nomatch\fP
-If the \fB\-\-return\-\-nomatch\fP option is specified and the set type
+\fB\-\-return\-nomatch\fP
+If the \fB\-\-return\-nomatch\fP option is specified and the set type
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!\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
+the packet and byte counters are updated.
+.TP
+\fB!\fP \fB\-\-update\-subcounters\fP
+If the \fB\-\-update\-subcounters\fP flag is negated, then the packet and
+byte counters of the matching element in the member set of a list type of
+set won't be updated. Default the packet and byte counters are updated.
+.TP
+[\fB!\fP] \fB\-\-packets\-eq\fP \fIvalue\fP
+If the packet is matched an element in the set, match only if the
+packet counter of the element matches the given value too.
+.TP
+\fB\-\-packets\-lt\fP \fIvalue\fP
+If the packet is matched an element in the set, match only if the
+packet counter of the element is less than the given value as well.
+.TP
+\fB\-\-packets\-gt\fP \fIvalue\fP
+If the packet is matched an element in the set, match only if the
+packet counter of the element is greater than the given value as well.
+.TP
+[\fB!\fP] \fB\-bytes\-eq\fP \fIvalue\fP
+If the packet is matched an element in the set, match only if the
+byte counter of the element matches the given value too.
+.TP
+\fB\-\-bytes\-lt\fP \fIvalue\fP
+If the packet is matched an element in the set, match only if the
+byte counter of the element is less than the given value as well.
+.TP
+\fB\-\-bytes\-gt\fP \fIvalue\fP
+If the packet is matched an element in the set, match only if the
+byte counter of the element is greater than the given value as well.
+.PP
+The packet and byte counters related options and flags are ignored
+when the set was defined without counter support.
.PP
The option \fB\-\-match\-set\fP can be replaced by \fB\-\-set\fP if that does
not clash with an option of other extensions.