diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2005-01-16 22:01:26 -0800 |
---|---|---|
committer | David S. Miller <davem@nuts.davemloft.net> | 2005-01-16 22:01:26 -0800 |
commit | 8d5f3377d48c74df38990688f09e773887ba4eb5 (patch) | |
tree | 25465714cf5b26bd8ad9cddd402d6e42b6eb3c09 /net/ipv4/netfilter/ip_nat_proto_tcp.c | |
parent | cd79564003e1b16ebc4090d3a2055e30e08898fc (diff) | |
download | history-8d5f3377d48c74df38990688f09e773887ba4eb5.tar.gz |
[NETFILTER]: Remove manip array from conntrack entry
Original patch and multo bugfixes by Krisztian Kovacs.
Now NAT has been simplified, there is only one place to NAT each
packet. That means we can intuit what to do by looking at the
difference between this packet and the reply we expect, getting rid of
the manips[] array in the connection tracking structure, which is 72
bytes. Rework NAT to be based on 'change this packet to make src/dst
look like this tuple'.
1) Each protocol's manip_pkt takes a 'struct ip_conntrack_manip',
which is half (the source half) of a tuple. Hand the whole desired
tuple to the NAT code and have it use the 'maniptype' arg to decide
what part to copy.
2) Krisztian points out that we don't need the NAT lock to read the
NAT information (or the tuples) as they never change once set, and
while being set we have exclusive access. A lock is only needed to
deal with only remaining NAT list: the bysource hash.
3) We don't need to rehash for the bysource hash: it depends on the
incoming packet, which we can't change.
4) Many NAT functions only need the maniptype they are to perform, not
the actual hook, which makes the code clearer.
5) New status bits to indicate what NAT needs to be done. We can
always figure it out by inverting the tuple we expect in the other
direction and comparing it, but this is faster.
6) Rename 'do_bindings' to 'nat_packet'.
7) ICMP handing is vastly simplified: we unconditionally change to
look the way we want.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/netfilter/ip_nat_proto_tcp.c')
-rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_tcp.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c index fb21a0875fa44..694838c0acd0d 100644 --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -85,14 +85,14 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple, static int tcp_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff, - const struct ip_conntrack_manip *manip, + const struct ip_conntrack_tuple *tuple, enum ip_nat_manip_type maniptype) { struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); struct tcphdr *hdr; unsigned int hdroff = iphdroff + iph->ihl*4; - u32 oldip, oldsrc = iph->saddr, olddst = iph->daddr; - u16 *portptr, oldport; + u32 oldip, newip; + u16 *portptr, newport, oldport; int hdrsize = 8; /* TCP connection tracking guarantees this much */ /* this could be a inner header returned in icmp packet; in such @@ -104,27 +104,32 @@ tcp_manip_pkt(struct sk_buff **pskb, if (!skb_ip_make_writable(pskb, hdroff + hdrsize)) return 0; - hdr = (void *)(*pskb)->data + hdroff; + iph = (struct iphdr *)((*pskb)->data + iphdroff); + hdr = (struct tcphdr *)((*pskb)->data + iph->ihl*4); if (maniptype == IP_NAT_MANIP_SRC) { /* Get rid of src ip and src pt */ - oldip = oldsrc; + oldip = iph->saddr; + newip = tuple->src.ip; + newport = tuple->src.u.tcp.port; portptr = &hdr->source; } else { /* Get rid of dst ip and dst pt */ - oldip = olddst; + oldip = iph->daddr; + newip = tuple->dst.ip; + newport = tuple->dst.u.tcp.port; portptr = &hdr->dest; } oldport = *portptr; - *portptr = manip->u.tcp.port; + *portptr = newport; if (hdrsize < sizeof(*hdr)) return 1; - hdr->check = ip_nat_cheat_check(~oldip, manip->ip, + hdr->check = ip_nat_cheat_check(~oldip, newip, ip_nat_cheat_check(oldport ^ 0xFFFF, - manip->u.tcp.port, + newport, hdr->check)); return 1; } |