patch-2.1.120 linux/net/ipv4/ip_nat_dumb.c
Next file: linux/net/ipv4/ip_options.c
Previous file: linux/net/ipv4/ip_input.c
Back to the patch index
Back to the overall index
- Lines: 84
- Date:
Mon Aug 31 10:32:19 1998
- Orig file:
v2.1.119/linux/net/ipv4/ip_nat_dumb.c
- Orig date:
Tue Mar 17 22:18:16 1998
diff -u --recursive --new-file v2.1.119/linux/net/ipv4/ip_nat_dumb.c linux/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 @@
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;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov