]> err.no Git - linux-2.6/blobdiff - net/ipv4/netfilter/ip_conntrack_netlink.c
[NETFILTER] ctnetlink: return -EINVAL if size is wrong
[linux-2.6] / net / ipv4 / netfilter / ip_conntrack_netlink.c
index 82a65043a8ef6a0c1b900a2ef5f282a12e7428ee..cfc5487e627acf7d6d76e3108ee9f46721d8d5a2 100644 (file)
 #include <linux/netlink.h>
 #include <linux/spinlock.h>
 #include <linux/notifier.h>
-#include <linux/rtnetlink.h>
 
 #include <linux/netfilter.h>
-#include <linux/netfilter_ipv4.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
@@ -58,14 +55,17 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb,
                            const struct ip_conntrack_tuple *tuple)
 {
        struct ip_conntrack_protocol *proto;
+       int ret = 0;
 
        NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
 
        proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
-       if (proto && proto->tuple_to_nfattr)
-               return proto->tuple_to_nfattr(skb, tuple);
+       if (likely(proto && proto->tuple_to_nfattr)) {
+               ret = proto->tuple_to_nfattr(skb, tuple);
+               ip_conntrack_proto_put(proto);
+       }
 
-       return 0;
+       return ret;
 
 nfattr_failure:
        return -1;
@@ -175,7 +175,7 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct,
 {
        enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
        struct nfattr *nest_count = NFA_NEST(skb, type);
-       u_int64_t tmp;
+       u_int32_t tmp;
 
        tmp = htonl(ct->counters[dir].packets);
        NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
@@ -479,9 +479,7 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple)
 
        DEBUGP("entered %s\n", __FUNCTION__);
 
-       
-       if (nfattr_parse_nested(tb, CTA_IP_MAX, attr) < 0)
-               goto nfattr_failure;
+       nfattr_parse_nested(tb, CTA_IP_MAX, attr);
 
        if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
                return -EINVAL;
@@ -497,9 +495,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple)
        DEBUGP("leaving\n");
 
        return 0;
-
-nfattr_failure:
-       return -1;
 }
 
 static const int cta_min_proto[CTA_PROTO_MAX] = {
@@ -521,8 +516,7 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr,
 
        DEBUGP("entered %s\n", __FUNCTION__);
 
-       if (nfattr_parse_nested(tb, CTA_PROTO_MAX, attr) < 0)
-               goto nfattr_failure;
+       nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
 
        if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
                return -EINVAL;
@@ -539,9 +533,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr,
        }
        
        return ret;
-
-nfattr_failure:
-       return -1;
 }
 
 static inline int
@@ -555,8 +546,7 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple,
 
        memset(tuple, 0, sizeof(*tuple));
 
-       if (nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]) < 0)
-               goto nfattr_failure;
+       nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
 
        if (!tb[CTA_TUPLE_IP-1])
                return -EINVAL;
@@ -583,9 +573,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple,
        DEBUGP("leaving\n");
 
        return 0;
-
-nfattr_failure:
-       return -1;
 }
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
@@ -603,11 +590,10 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
 
        DEBUGP("entered %s\n", __FUNCTION__);
 
-       if (nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr) < 0)
-               goto nfattr_failure;
+       nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
 
        if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
-               goto nfattr_failure;
+               return -EINVAL;
 
        npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
        if (!npt)
@@ -626,9 +612,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
 
        DEBUGP("leaving\n");
        return 0;
-
-nfattr_failure:
-       return -1;
 }
 
 static inline int
@@ -642,8 +625,7 @@ ctnetlink_parse_nat(struct nfattr *cda[],
 
        memset(range, 0, sizeof(*range));
        
-       if (nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]) < 0)
-               goto nfattr_failure;
+       nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]);
 
        if (tb[CTA_NAT_MINIP-1])
                range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]);
@@ -665,9 +647,6 @@ ctnetlink_parse_nat(struct nfattr *cda[],
 
        DEBUGP("leaving\n");
        return 0;
-
-nfattr_failure:
-       return -1;
 }
 #endif
 
@@ -678,8 +657,7 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
 
        DEBUGP("entered %s\n", __FUNCTION__);
 
-       if (nfattr_parse_nested(tb, CTA_HELP_MAX, attr) < 0)
-               goto nfattr_failure;
+       nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
 
        if (!tb[CTA_HELP_NAME-1])
                return -EINVAL;
@@ -687,9 +665,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
        *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]);
 
        return 0;
-
-nfattr_failure:
-       return -1;
 }
 
 static int
@@ -804,7 +779,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
        ct = tuplehash_to_ctrack(h);
 
        err = -ENOMEM;
-       skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
+       skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
        if (!skb2) {
                ip_conntrack_put(ct);
                return -ENOMEM;
@@ -957,8 +932,7 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[])
        u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
        int err = 0;
 
-       if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0)
-               goto nfattr_failure;
+       nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
 
        proto = ip_conntrack_proto_find_get(npt);
        if (!proto)
@@ -969,9 +943,6 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[])
        ip_conntrack_proto_put(proto); 
 
        return err;
-
-nfattr_failure:
-       return -ENOMEM;
 }
 
 static int
@@ -1005,6 +976,11 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[])
                        return err;
        }
 
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+       if (cda[CTA_MARK-1])
+               ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+#endif
+
        DEBUGP("all done\n");
        return 0;
 }
@@ -1048,6 +1024,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
        if (ct->helper)
                ip_conntrack_helper_put(ct->helper);
 
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+       if (cda[CTA_MARK-1])
+               ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+#endif
+
        DEBUGP("conntrack with id %u inserted\n", ct->id);
        return 0;
 
@@ -1554,6 +1535,8 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = {
        .cb                             = ctnl_exp_cb,
 };
 
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
+
 static int __init ctnetlink_init(void)
 {
        int ret;