summaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_nat_dumb.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-09-19 19:15:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-09-19 19:15:08 +0000
commit03ba4131783cc9e872f8bb26a03f15bc11f27564 (patch)
tree88db8dba75ae06ba3bad08e42c5e52efc162535c /net/ipv4/ip_nat_dumb.c
parent257730f99381dd26e10b832fce4c94cae7ac1176 (diff)
- Merge with Linux 2.1.121.
- Bugfixes.
Diffstat (limited to 'net/ipv4/ip_nat_dumb.c')
-rw-r--r--net/ipv4/ip_nat_dumb.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/net/ipv4/ip_nat_dumb.c b/net/ipv4/ip_nat_dumb.c
index 07a7afc23..c48ea9263 100644
--- a/net/ipv4/ip_nat_dumb.c
+++ b/net/ipv4/ip_nat_dumb.c
@@ -5,7 +5,7 @@
*
* Dumb Network Address Translation.
*
- * Version: $Id: ip_nat_dumb.c,v 1.3 1998/03/15 03:31:44 davem Exp $
+ * Version: $Id: ip_nat_dumb.c,v 1.4 1998/08/26 12:03:49 davem Exp $
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
@@ -17,11 +17,12 @@
* Fixes:
* Rani Assaf : A zero checksum is a special case
* only in UDP
+ * Rani Assaf : Added ICMP messages rewriting
+ *
*
* NOTE: It is just working model of real NAT.
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/sched.h>
@@ -36,9 +37,6 @@
#include <linux/udp.h>
#include <linux/firewall.h>
#include <linux/ip_fw.h>
-#ifdef CONFIG_IP_MASQUERADE
-#include <net/ip_masq.h>
-#endif
#include <net/checksum.h>
#include <linux/route.h>
#include <net/route.h>
@@ -68,20 +66,48 @@ ip_do_nat(struct sk_buff *skb)
switch(iph->protocol) {
case IPPROTO_TCP:
- cksum = (u16*)&((struct tcphdr*)(((char*)iph) + iph->ihl*4))->check;
+ cksum = (u16*)&((struct tcphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
+ if ((u8*)(cksum+1) > skb->tail)
+ goto truncated;
check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, ~(*cksum));
*cksum = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
break;
case IPPROTO_UDP:
- cksum = (u16*)&((struct udphdr*)(((char*)iph) + iph->ihl*4))->check;
+ cksum = (u16*)&((struct udphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
+ if ((u8*)(cksum+1) > skb->tail)
+ goto truncated;
if ((check = *cksum) != 0) {
check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, ~check);
check = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
*cksum = check ? : 0xFFFF;
}
+ break;
+ case IPPROTO_ICMP:
+ {
+ struct icmphdr *icmph = (struct icmphdr*)((char*)iph + (iph->ihl<<2));
+ struct iphdr *ciph;
+
+ if ((icmph->type != ICMP_DEST_UNREACH) &&
+ (icmph->type != ICMP_TIME_EXCEEDED) &&
+ (icmph->type != ICMP_PARAMETERPROB)) break;
+
+ ciph = (struct iphdr *) (icmph + 1);
+
+ if ((u8*)(ciph+1) > skb->tail)
+ goto truncated;
+
+ if (rt->rt_flags&RTCF_DNAT && ciph->saddr == odaddr)
+ ciph->saddr = iph->daddr;
+ if (rt->rt_flags&RTCF_SNAT && ciph->daddr == osaddr)
+ ciph->daddr = iph->saddr;
+ break;
+ }
default:
break;
}
}
return 0;
+
+truncated:
+ return -EINVAL;
}