]> Pileus Git - ~andy/linux/blobdiff - net/netfilter/xt_set.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[~andy/linux] / net / netfilter / xt_set.c
index 636c5199ff357fb5e2f67f1e6940042bc40dd2b6..31790e789e224f8fb758ee87e62f8dd8908e81dd 100644 (file)
@@ -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);
 }
@@ -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",
@@ -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 = {