netfilter: xtables: connlimit revision 1
Jan Engelhardt [Tue, 18 Jan 2011 16:32:40 +0000 (17:32 +0100)]
This adds destination address-based selection. The old "inverse"
member is overloaded (memory-wise) with a new "flags" variable,
similar to how J.Park did it with xt_string rev 1. Since revision¬†0
userspace only sets flag 0x1, no great changes are made to explicitly
test for different revisions.

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>

Documentation/feature-removal-schedule.txt
include/linux/netfilter/xt_connlimit.h
net/netfilter/xt_connlimit.c

index 22f1081..45cc804 100644 (file)
@@ -576,3 +576,10 @@ Why:       The functions have been superceded by cancel_delayed_work_sync()
 Who:   Tejun Heo <tj@kernel.org>
 
 ----------------------------
+
+What:  xt_connlimit rev 0
+When:  2012
+Who:   Jan Engelhardt <jengelh@medozas.de>
+Files: net/netfilter/xt_connlimit.c
+
+----------------------------
index 7e3284b..8884efc 100644 (file)
@@ -3,6 +3,11 @@
 
 struct xt_connlimit_data;
 
+enum {
+       XT_CONNLIMIT_INVERT = 1 << 0,
+       XT_CONNLIMIT_DADDR  = 1 << 1,
+};
+
 struct xt_connlimit_info {
        union {
                union nf_inet_addr mask;
@@ -14,6 +19,13 @@ struct xt_connlimit_info {
 #endif
        };
        unsigned int limit, inverse;
+       union {
+               /* revision 0 */
+               unsigned int inverse;
+
+               /* revision 1 */
+               __u32 flags;
+       };
 
        /* Used internally by the kernel */
        struct xt_connlimit_data *data __attribute__((aligned(8)));
index 452bc16..7fd3fd5 100644 (file)
@@ -193,10 +193,12 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
        if (par->family == NFPROTO_IPV6) {
                const struct ipv6hdr *iph = ipv6_hdr(skb);
-               memcpy(&addr.ip6, &iph->saddr, sizeof(iph->saddr));
+               memcpy(&addr.ip6, (info->flags & XT_CONNLIMIT_DADDR) ?
+                      &iph->daddr : &iph->saddr, sizeof(addr.ip6));
        } else {
                const struct iphdr *iph = ip_hdr(skb);
-               addr.ip = iph->saddr;
+               addr.ip = (info->flags & XT_CONNLIMIT_DADDR) ?
+                         iph->daddr : iph->saddr;
        }
 
        spin_lock_bh(&info->data->lock);
@@ -208,7 +210,8 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
                /* kmalloc failed, drop it entirely */
                goto hotdrop;
 
-       return (connections > info->limit) ^ info->inverse;
+       return (connections > info->limit) ^
+              !!(info->flags & XT_CONNLIMIT_INVERT);
 
  hotdrop:
        par->hotdrop = true;
@@ -266,25 +269,38 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
        kfree(info->data);
 }
 
-static struct xt_match connlimit_mt_reg __read_mostly = {
-       .name       = "connlimit",
-       .revision   = 0,
-       .family     = NFPROTO_UNSPEC,
-       .checkentry = connlimit_mt_check,
-       .match      = connlimit_mt,
-       .matchsize  = sizeof(struct xt_connlimit_info),
-       .destroy    = connlimit_mt_destroy,
-       .me         = THIS_MODULE,
+static struct xt_match connlimit_mt_reg[] __read_mostly = {
+       {
+               .name       = "connlimit",
+               .revision   = 0,
+               .family     = NFPROTO_UNSPEC,
+               .checkentry = connlimit_mt_check,
+               .match      = connlimit_mt,
+               .matchsize  = sizeof(struct xt_connlimit_info),
+               .destroy    = connlimit_mt_destroy,
+               .me         = THIS_MODULE,
+       },
+       {
+               .name       = "connlimit",
+               .revision   = 1,
+               .family     = NFPROTO_UNSPEC,
+               .checkentry = connlimit_mt_check,
+               .match      = connlimit_mt,
+               .matchsize  = sizeof(struct xt_connlimit_info),
+               .destroy    = connlimit_mt_destroy,
+               .me         = THIS_MODULE,
+       },
 };
 
 static int __init connlimit_mt_init(void)
 {
-       return xt_register_match(&connlimit_mt_reg);
+       return xt_register_matches(connlimit_mt_reg,
+              ARRAY_SIZE(connlimit_mt_reg));
 }
 
 static void __exit connlimit_mt_exit(void)
 {
-       xt_unregister_match(&connlimit_mt_reg);
+       xt_unregister_matches(connlimit_mt_reg, ARRAY_SIZE(connlimit_mt_reg));
 }
 
 module_init(connlimit_mt_init);