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_udp.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_udp.c')
-rw-r--r-- | net/ipv4/netfilter/ip_nat_proto_udp.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index 3c492530863c1..c669e3b5f5d0d 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -84,34 +84,40 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple, static int udp_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 udphdr *hdr; unsigned int hdroff = iphdroff + iph->ihl*4; - u32 oldip, oldsrc = iph->saddr, olddst = iph->daddr; - u16 *portptr; + u32 oldip, newip; + u16 *portptr, newport; if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr))) return 0; - hdr = (void *)(*pskb)->data + hdroff; + iph = (struct iphdr *)((*pskb)->data + iphdroff); + hdr = (struct udphdr *)((*pskb)->data + hdroff); + 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.udp.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.udp.port; portptr = &hdr->dest; } if (hdr->check) /* 0 is a special case meaning no checksum */ - hdr->check = ip_nat_cheat_check(~oldip, manip->ip, + hdr->check = ip_nat_cheat_check(~oldip, newip, ip_nat_cheat_check(*portptr ^ 0xFFFF, - manip->u.udp.port, + newport, hdr->check)); - *portptr = manip->u.udp.port; + *portptr = newport; return 1; } |