|
@@ -28,11 +28,8 @@
|
|
|
#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;
|
|
@@ -827,7 +802,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
|
|
|
free:
|
|
|
kfree_skb(skb2);
|
|
|
out:
|
|
|
- return -1;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static inline int
|
|
@@ -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;
|
|
|
|
|
@@ -1312,6 +1293,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
|
|
|
if (!exp)
|
|
|
return -ENOENT;
|
|
|
|
|
|
+ if (cda[CTA_EXPECT_ID-1]) {
|
|
|
+ u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
|
|
|
+ if (exp->id != ntohl(id)) {
|
|
|
+ ip_conntrack_expect_put(exp);
|
|
|
+ return -ENOENT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
err = -ENOMEM;
|
|
|
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
|
|
if (!skb2)
|
|
@@ -1554,6 +1543,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;
|