Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6e01781d authored by Jozsef Kadlecsik's avatar Jozsef Kadlecsik Committed by Pablo Neira Ayuso
Browse files

netfilter: ipset: set match: add support to match the counters



The new revision of the set match supports to match the counters
and to suppress updating the counters at matching too.

At the set:list types, the updating of the subcounters can be
suppressed as well.

Signed-off-by: default avatarJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent de76303c
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ struct ip_set;

typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
			   const struct ip_set_ext *ext,
			   struct ip_set_ext *mext, u32 flags);
			   struct ip_set_ext *mext, u32 cmdflags);

/* Kernel API function options */
struct ip_set_adt_opt {
@@ -217,10 +217,15 @@ ip_set_update_counter(struct ip_set_counter *counter,
		      const struct ip_set_ext *ext,
		      struct ip_set_ext *mext, u32 flags)
{
	if (ext->packets != ULLONG_MAX) {
	if (ext->packets != ULLONG_MAX &&
	    !(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) {
		ip_set_add_bytes(ext->bytes, counter);
		ip_set_add_packets(ext->packets, counter);
	}
	if (flags & IPSET_FLAG_MATCH_COUNTERS) {
		mext->packets = ip_set_get_packets(counter);
		mext->bytes = ip_set_get_bytes(counter);
	}
}

static inline bool
+27 −4
Original line number Diff line number Diff line
@@ -145,7 +145,7 @@ enum ipset_errno {
	IPSET_ERR_TYPE_SPECIFIC = 4352,
};

/* Flags at command level */
/* Flags at command level or match/target flags, lower half of cmdattrs*/
enum ipset_cmd_flags {
	IPSET_FLAG_BIT_EXIST	= 0,
	IPSET_FLAG_EXIST	= (1 << IPSET_FLAG_BIT_EXIST),
@@ -153,10 +153,20 @@ enum ipset_cmd_flags {
	IPSET_FLAG_LIST_SETNAME	= (1 << IPSET_FLAG_BIT_LIST_SETNAME),
	IPSET_FLAG_BIT_LIST_HEADER = 2,
	IPSET_FLAG_LIST_HEADER	= (1 << IPSET_FLAG_BIT_LIST_HEADER),
	IPSET_FLAG_CMD_MAX = 15,	/* Lower half */
	IPSET_FLAG_BIT_SKIP_COUNTER_UPDATE = 3,
	IPSET_FLAG_SKIP_COUNTER_UPDATE =
		(1 << IPSET_FLAG_BIT_SKIP_COUNTER_UPDATE),
	IPSET_FLAG_BIT_SKIP_SUBCOUNTER_UPDATE = 4,
	IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE =
		(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_RETURN_NOMATCH = 7,
	IPSET_FLAG_RETURN_NOMATCH = (1 << IPSET_FLAG_BIT_RETURN_NOMATCH),
	IPSET_FLAG_CMD_MAX = 15,
};

/* Flags at CADT attribute level */
/* Flags at CADT attribute level, upper half of cmdattrs */
enum ipset_cadt_flags {
	IPSET_FLAG_BIT_BEFORE	= 0,
	IPSET_FLAG_BEFORE	= (1 << IPSET_FLAG_BIT_BEFORE),
@@ -166,7 +176,7 @@ enum ipset_cadt_flags {
	IPSET_FLAG_NOMATCH	= (1 << IPSET_FLAG_BIT_NOMATCH),
	IPSET_FLAG_BIT_WITH_COUNTERS = 3,
	IPSET_FLAG_WITH_COUNTERS = (1 << IPSET_FLAG_BIT_WITH_COUNTERS),
	IPSET_FLAG_CADT_MAX	= 15,	/* Upper half */
	IPSET_FLAG_CADT_MAX	= 15,
};

/* Commands with settype-specific attributes */
@@ -195,6 +205,7 @@ enum ip_set_dim {
	 * If changed, new revision of iptables match/target is required.
	 */
	IPSET_DIM_MAX = 6,
	/* Backward compatibility: set match revision 2 */
	IPSET_BIT_RETURN_NOMATCH = 7,
};

@@ -207,6 +218,18 @@ enum ip_set_kopt {
	IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH),
};

enum {
	IPSET_COUNTER_NONE = 0,
	IPSET_COUNTER_EQ,
	IPSET_COUNTER_NE,
	IPSET_COUNTER_LT,
	IPSET_COUNTER_GT,
};

struct ip_set_counter_match {
	__u8 op;
	__u64 value;
};

/* Interface to iptables/ip6tables */

+9 −0
Original line number Diff line number Diff line
@@ -62,4 +62,13 @@ struct xt_set_info_target_v2 {
	__u32 timeout;
};

/* Revision 3 match */

struct xt_set_info_match_v3 {
	struct xt_set_info match_set;
	struct ip_set_counter_match packets;
	struct ip_set_counter_match bytes;
	__u32 flags;
};

#endif /*_XT_SET_H*/
+1 −1
Original line number Diff line number Diff line
@@ -413,7 +413,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
		ret = 1;
	} else {
		/* --return-nomatch: invert matched element */
		if ((opt->flags & IPSET_RETURN_NOMATCH) &&
		if ((opt->cmdflags & IPSET_FLAG_RETURN_NOMATCH) &&
		    (set->type->features & IPSET_TYPE_NOMATCH) &&
		    (ret > 0 || ret == -ENOTEMPTY))
			ret = -ret;
+6 −2
Original line number Diff line number Diff line
@@ -84,9 +84,13 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
{
	struct list_set *map = set->data;
	struct set_elem *e;
	u32 i;
	u32 i, cmdflags = opt->cmdflags;
	int ret;

	/* Don't lookup sub-counters at all */
	opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS;
	if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)
		opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE;
	for (i = 0; i < map->size; i++) {
		e = list_set_elem(map, i);
		if (e->id == IPSET_INVALID_ID)
@@ -99,7 +103,7 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
			if (SET_WITH_COUNTER(set))
				ip_set_update_counter(ext_counter(e, map),
						      ext, &opt->ext,
						      opt->cmdflags);
						      cmdflags);
			return ret;
		}
	}
Loading