* (C) 2001 by Jay Schulist <jschlst@samba.org>
* (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
*
* I've reworked this stuff to use attributes instead of conntrack
* structures. 5.44 am. I need more tea. --pablo 05/07/11.
static inline int
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
- const struct nf_conntrack_tuple *tuple)
+ const struct nf_conntrack_tuple *tuple,
+ struct nf_conntrack_protocol *proto)
{
- struct nf_conntrack_protocol *proto;
int ret = 0;
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
- /* If no protocol helper is found, this function will return the
- * generic protocol helper, so proto won't *ever* be NULL */
- proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
if (likely(proto->tuple_to_nfattr))
ret = proto->tuple_to_nfattr(skb, tuple);
- nf_ct_proto_put(proto);
+ NFA_NEST_END(skb, nest_parms);
return ret;
}
static inline int
-ctnetlink_dump_tuples(struct sk_buff *skb,
- const struct nf_conntrack_tuple *tuple)
+ctnetlink_dump_tuples_ip(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple,
+ struct nf_conntrack_l3proto *l3proto)
{
- struct nfattr *nest_parms;
- struct nf_conntrack_l3proto *l3proto;
int ret = 0;
-
- l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
-
- nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+
if (likely(l3proto->tuple_to_nfattr))
ret = l3proto->tuple_to_nfattr(skb, tuple);
+
NFA_NEST_END(skb, nest_parms);
+ return ret;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_tuples(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple)
+{
+ int ret;
+ struct nf_conntrack_l3proto *l3proto;
+ struct nf_conntrack_protocol *proto;
+
+ l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
+ ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
nf_ct_l3proto_put(l3proto);
if (unlikely(ret < 0))
return ret;
- nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
- ret = ctnetlink_dump_tuples_proto(skb, tuple);
- NFA_NEST_END(skb, nest_parms);
+ proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+ ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
+ nf_ct_proto_put(proto);
return ret;
-
-nfattr_failure:
- return -1;
}
static inline int
};
static inline int
-ctnetlink_parse_nat(struct nfattr *cda[],
+ctnetlink_parse_nat(struct nfattr *nat,
const struct nf_conn *ct, struct ip_nat_range *range)
{
struct nfattr *tb[CTA_NAT_MAX];
memset(range, 0, sizeof(*range));
- nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]);
+ nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
return -EINVAL;
/* ASSURED bit can only be set */
return -EINVAL;
- if (cda[CTA_NAT-1]) {
+ if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
#ifndef CONFIG_IP_NF_NAT_NEEDED
return -EINVAL;
#else
- unsigned int hooknum;
struct ip_nat_range range;
- if (ctnetlink_parse_nat(cda, ct, &range) < 0)
- return -EINVAL;
-
- DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n",
- NIPQUAD(range.min_ip), NIPQUAD(range.max_ip),
- htons(range.min.all), htons(range.max.all));
-
- /* This is tricky but it works. ip_nat_setup_info needs the
- * hook number as parameter, so let's do the correct
- * conversion and run away */
- if (status & IPS_SRC_NAT_DONE)
- hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */
- else if (status & IPS_DST_NAT_DONE)
- hooknum = NF_IP_PRE_ROUTING; /* IP_NAT_MANIP_DST */
- else
- return -EINVAL; /* Missing NAT flags */
-
- DEBUGP("NAT status: %lu\n",
- status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
-
- if (ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
- return -EEXIST;
- ip_nat_setup_info(ct, &range, hooknum);
-
- DEBUGP("NAT status after setup_info: %lu\n",
- ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
+ if (cda[CTA_NAT_DST-1]) {
+ if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
+ &range) < 0)
+ return -EINVAL;
+ if (ip_nat_initialized(ct,
+ HOOK2MANIP(NF_IP_PRE_ROUTING)))
+ return -EEXIST;
+ ip_nat_setup_info(ct, &range, hooknum);
+ }
+ if (cda[CTA_NAT_SRC-1]) {
+ if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
+ &range) < 0)
+ return -EINVAL;
+ if (ip_nat_initialized(ct,
+ HOOK2MANIP(NF_IP_POST_ROUTING)))
+ return -EEXIST;
+ ip_nat_setup_info(ct, &range, hooknum);
+ }
#endif
}
return err;
}
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK-1])
ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
#endif
return err;
}
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+#if defined(CONFIG_NF_CONNTRACK_MARK)
if (cda[CTA_MARK-1])
ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
#endif
/* implicit 'else' */
/* we only allow nat config for new conntracks */
- if (cda[CTA_NAT-1]) {
+ if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
err = -EINVAL;
goto out_unlock;
}
return -1;
}
+static inline int
+ctnetlink_exp_dump_mask(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *mask)
+{
+ int ret;
+ struct nf_conntrack_l3proto *l3proto;
+ struct nf_conntrack_protocol *proto;
+ struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+
+ l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
+ ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
+ nf_ct_l3proto_put(l3proto);
+
+ if (unlikely(ret < 0))
+ goto nfattr_failure;
+
+ proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+ ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
+ nf_ct_proto_put(proto);
+ if (unlikely(ret < 0))
+ goto nfattr_failure;
+
+ NFA_NEST_END(skb, nest_parms);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
static inline int
ctnetlink_exp_dump_expect(struct sk_buff *skb,
const struct nf_conntrack_expect *exp)
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
goto nfattr_failure;
- if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
+ if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
goto nfattr_failure;
if (ctnetlink_exp_dump_tuple(skb,
&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
printk("ctnetlink: unregistering from nfnetlink.\n");
#ifdef CONFIG_NF_CONNTRACK_EVENTS
- nf_conntrack_unregister_notifier(&ctnl_notifier_exp);
+ nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
nf_conntrack_unregister_notifier(&ctnl_notifier);
#endif