Skip to content

Commit

Permalink
netfilter: ipset: set match: add support to match the counters
Browse files Browse the repository at this point in the history
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: Jozsef Kadlecsik <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
  • Loading branch information
Jozsef Kadlecsik authored and ummakynes committed Apr 29, 2013
1 parent de76303 commit 6e01781
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 9 deletions.
9 changes: 7 additions & 2 deletions include/linux/netfilter/ipset/ip_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
31 changes: 27 additions & 4 deletions include/uapi/linux/netfilter/ipset/ip_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,28 @@ 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),
IPSET_FLAG_BIT_LIST_SETNAME = 1,
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),
Expand All @@ -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 */
Expand Down Expand Up @@ -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,
};

Expand All @@ -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 */

Expand Down
9 changes: 9 additions & 0 deletions include/uapi/linux/netfilter/xt_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -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*/
2 changes: 1 addition & 1 deletion net/netfilter/ipset/ip_set_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions net/netfilter/ipset/ip_set_list_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}
}
Expand Down
70 changes: 70 additions & 0 deletions net/netfilter/xt_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
ADT_OPT(opt, par->family, info->match_set.dim,
info->match_set.flags, 0, UINT_MAX);

if (opt.flags & IPSET_RETURN_NOMATCH)
opt.cmdflags |= IPSET_FLAG_RETURN_NOMATCH;

return match_set(info->match_set.index, skb, par, &opt,
info->match_set.flags & IPSET_INV_MATCH);
}
Expand Down Expand Up @@ -317,6 +320,52 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
#define set_target_v2_checkentry set_target_v1_checkentry
#define set_target_v2_destroy set_target_v1_destroy

/* Revision 3 match */

static bool
match_counter(u64 counter, const struct ip_set_counter_match *info)
{
switch (info->op) {
case IPSET_COUNTER_NONE:
return true;
case IPSET_COUNTER_EQ:
return counter == info->value;
case IPSET_COUNTER_NE:
return counter != info->value;
case IPSET_COUNTER_LT:
return counter < info->value;
case IPSET_COUNTER_GT:
return counter > info->value;
}
return false;
}

static bool
set_match_v3(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_set_info_match_v3 *info = par->matchinfo;
ADT_OPT(opt, par->family, info->match_set.dim,
info->match_set.flags, info->flags, UINT_MAX);
int ret;

if (info->packets.op != IPSET_COUNTER_NONE ||
info->bytes.op != IPSET_COUNTER_NONE)
opt.cmdflags |= IPSET_FLAG_MATCH_COUNTERS;

ret = match_set(info->match_set.index, skb, par, &opt,
info->match_set.flags & IPSET_INV_MATCH);

if (!(ret && opt.cmdflags & IPSET_FLAG_MATCH_COUNTERS))
return ret;

if (!match_counter(opt.ext.packets, &info->packets))
return 0;
return match_counter(opt.ext.bytes, &info->bytes);
}

#define set_match_v3_checkentry set_match_v1_checkentry
#define set_match_v3_destroy set_match_v1_destroy

static struct xt_match set_matches[] __read_mostly = {
{
.name = "set",
Expand Down Expand Up @@ -369,6 +418,27 @@ static struct xt_match set_matches[] __read_mostly = {
.destroy = set_match_v1_destroy,
.me = THIS_MODULE
},
/* counters support: update, match */
{
.name = "set",
.family = NFPROTO_IPV4,
.revision = 3,
.match = set_match_v3,
.matchsize = sizeof(struct xt_set_info_match_v3),
.checkentry = set_match_v3_checkentry,
.destroy = set_match_v3_destroy,
.me = THIS_MODULE
},
{
.name = "set",
.family = NFPROTO_IPV6,
.revision = 3,
.match = set_match_v3,
.matchsize = sizeof(struct xt_set_info_match_v3),
.checkentry = set_match_v3_checkentry,
.destroy = set_match_v3_destroy,
.me = THIS_MODULE
},
};

static struct xt_target set_targets[] __read_mostly = {
Expand Down

0 comments on commit 6e01781

Please sign in to comment.