[NETFILTER]: Add NAT support for nf_conntrack

Add NAT support for nf_conntrack. Joint work of Jozsef Kadlecsik,
Yasuyuki Kozakai, Martin Josefsson and myself.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jozsef Kadlecsik
2006-12-02 22:07:13 -08:00
committed by David S. Miller
parent d2483ddefd
commit 5b1158e909
29 changed files with 2668 additions and 60 deletions

View File

@@ -579,7 +579,8 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
/* FIXME: protect helper list per RCU */
read_lock_bh(&nf_conntrack_lock);
helper = __nf_ct_helper_find(repl);
if (helper)
/* NAT might want to assign a helper later */
if (helper || features & NF_CT_F_NAT)
features |= NF_CT_F_HELP;
read_unlock_bh(&nf_conntrack_lock);
@@ -850,6 +851,26 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
orig->dst.protonum));
}
/* Alter reply tuple (maybe alter helper). This is for NAT, and is
implicitly racy: see __nf_conntrack_confirm */
void nf_conntrack_alter_reply(struct nf_conn *ct,
const struct nf_conntrack_tuple *newreply)
{
struct nf_conn_help *help = nfct_help(ct);
write_lock_bh(&nf_conntrack_lock);
/* Should be unconfirmed, so not in hash table yet */
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
DEBUGP("Altering reply tuple of %p to ", ct);
NF_CT_DUMP_TUPLE(newreply);
ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
if (!ct->master && help && help->expecting == 0)
help->helper = __nf_ct_helper_find(newreply);
write_unlock_bh(&nf_conntrack_lock);
}
/* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */
void __nf_ct_refresh_acct(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,

View File

@@ -39,7 +39,11 @@
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <linux/netfilter_ipv4/ip_nat_protocol.h>
#include <net/netfilter/nf_conntrack_tuple.h>
#ifdef CONFIG_NF_NAT_NEEDED
#include <net/netfilter/nf_nat_core.h>
#include <net/netfilter/nf_nat_protocol.h>
#endif
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
@@ -430,7 +434,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
restart:
list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
h = (struct nf_conntrack_tuple_hash *) i;
if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
continue;
ct = nf_ct_tuplehash_to_ctrack(h);
/* Dump entries of a given L3 protocol number.
@@ -556,28 +560,28 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple,
return 0;
}
#ifdef CONFIG_IP_NF_NAT_NEEDED
#ifdef CONFIG_NF_NAT_NEEDED
static const size_t cta_min_protonat[CTA_PROTONAT_MAX] = {
[CTA_PROTONAT_PORT_MIN-1] = sizeof(u_int16_t),
[CTA_PROTONAT_PORT_MAX-1] = sizeof(u_int16_t),
};
static int ctnetlink_parse_nat_proto(struct nfattr *attr,
static int nfnetlink_parse_nat_proto(struct nfattr *attr,
const struct nf_conn *ct,
struct ip_nat_range *range)
struct nf_nat_range *range)
{
struct nfattr *tb[CTA_PROTONAT_MAX];
struct ip_nat_protocol *npt;
struct nf_nat_protocol *npt;
nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
return -EINVAL;
npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
npt = nf_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
if (!npt->nfattr_to_range) {
ip_nat_proto_put(npt);
nf_nat_proto_put(npt);
return 0;
}
@@ -585,7 +589,7 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr,
if (npt->nfattr_to_range(tb, range) > 0)
range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
ip_nat_proto_put(npt);
nf_nat_proto_put(npt);
return 0;
}
@@ -596,8 +600,8 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = {
};
static inline int
ctnetlink_parse_nat(struct nfattr *nat,
const struct nf_conn *ct, struct ip_nat_range *range)
nfnetlink_parse_nat(struct nfattr *nat,
const struct nf_conn *ct, struct nf_nat_range *range)
{
struct nfattr *tb[CTA_NAT_MAX];
int err;
@@ -623,7 +627,7 @@ ctnetlink_parse_nat(struct nfattr *nat,
if (!tb[CTA_NAT_PROTO-1])
return 0;
err = ctnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range);
err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO-1], ct, range);
if (err < 0)
return err;
@@ -798,35 +802,35 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
return -EINVAL;
if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
#ifndef CONFIG_IP_NF_NAT_NEEDED
#ifndef CONFIG_NF_NAT_NEEDED
return -EINVAL;
#else
struct ip_nat_range range;
struct nf_nat_range range;
if (cda[CTA_NAT_DST-1]) {
if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
if (nfnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
&range) < 0)
return -EINVAL;
if (ip_nat_initialized(ct,
if (nf_nat_initialized(ct,
HOOK2MANIP(NF_IP_PRE_ROUTING)))
return -EEXIST;
ip_nat_setup_info(ct, &range, hooknum);
nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
}
if (cda[CTA_NAT_SRC-1]) {
if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
if (nfnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
&range) < 0)
return -EINVAL;
if (ip_nat_initialized(ct,
if (nf_nat_initialized(ct,
HOOK2MANIP(NF_IP_POST_ROUTING)))
return -EEXIST;
ip_nat_setup_info(ct, &range, hooknum);
nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
}
#endif
}
/* Be careful here, modifying NAT bits can screw up things,
* so don't let users modify them directly if they don't pass
* ip_nat_range. */
* nf_nat_range. */
ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
return 0;
}

View File

@@ -730,7 +730,7 @@ static int tcp_in_window(struct ip_ct_tcp *state,
return res;
}
#ifdef CONFIG_IP_NF_NAT_NEEDED
#ifdef CONFIG_NF_NAT_NEEDED
/* Update sender->td_end after NAT successfully mangled the packet */
/* Caller must linearize skb at tcp header. */
void nf_conntrack_tcp_update(struct sk_buff *skb,

View File

@@ -530,8 +530,11 @@ EXPORT_SYMBOL(nf_conntrack_lock);
EXPORT_SYMBOL(nf_conntrack_hash);
EXPORT_SYMBOL(nf_conntrack_untracked);
EXPORT_SYMBOL_GPL(nf_conntrack_find_get);
#ifdef CONFIG_IP_NF_NAT_NEEDED
#ifdef CONFIG_NF_NAT_NEEDED
EXPORT_SYMBOL(nf_conntrack_tcp_update);
EXPORT_SYMBOL(nf_conntrack_register_cache);
EXPORT_SYMBOL(nf_conntrack_unregister_cache);
EXPORT_SYMBOL(nf_conntrack_alter_reply);
#endif
EXPORT_SYMBOL(__nf_conntrack_confirm);
EXPORT_SYMBOL(nf_ct_get_tuple);