diff -ur linux-source-2.6.20-voyage-ori/net/ipv4/netfilter/iptable_tproxy.c linux-source-2.6.20-voyage-sam1/net/ipv4/netfilter/iptable_tproxy.c
--- linux-source-2.6.20-voyage-ori/net/ipv4/netfilter/iptable_tproxy.c	2008-02-27 14:46:53.000000000 +0100
+++ linux-source-2.6.20-voyage-sam1/net/ipv4/netfilter/iptable_tproxy.c	2008-02-27 14:33:25.000000000 +0100
@@ -24,6 +24,7 @@
 #include <linux/time.h>
 #include <net/tcp.h>
 #include <net/udp.h>
+#include <net/icmp.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
 #include <net/inet_timewait_sock.h>
@@ -700,6 +701,68 @@
 	return NF_ACCEPT;
 }
 
+#ifdef CONFIG_IP_NF_TPROXY_ICMP
+/* redirect incoming packet to the appropriate ip (ICMP specific) */
+static int
+ip_tproxy_setup_nat_icmp(struct sk_buff **pskb, int hooknum, struct ip_tproxy_sockref *sr)
+{
+	enum ip_nat_manip_type manip_type;
+	struct sk_buff *skb = *pskb;
+	struct ip_conntrack_tuple tuple;
+
+	/* free the original conntrack entry, and assign the fake one */
+	nf_conntrack_put(skb->nfct);
+	skb->nfct = &ip_tproxy_fake_ct.ct_general;
+	skb->nfctinfo = IP_CT_NEW;
+	nf_conntrack_get(skb->nfct);
+
+	/* fill tuple structure with new information */
+	tuple.dst.protonum = skb->nh.iph->protocol;
+
+	/* printk(KERN_NOTICE "IP_TPROXY: ip_tproxy_setup_nat_icmp() - handling ICMP packet now\n"); */
+	if (hooknum == NF_IP_POST_ROUTING) {
+		/* in POSTROUTING we perform an SNAT to the foreign address */
+		tuple.src.ip = sr->faddr;
+		tuple.src.u.icmp.id	= skb->h.icmph->un.echo.id;
+		manip_type = IP_NAT_MANIP_SRC;
+	} else if (hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT) {
+		/* in PREROUTING and LOCAL_OUT we perform a DNAT to our socket address */
+		tuple.dst.ip		= sr->laddr;
+		tuple.dst.u.icmp.type	= skb->h.icmph->type;
+		tuple.dst.u.icmp.code	= skb->h.icmph->code;
+		manip_type = IP_NAT_MANIP_DST;
+
+#ifdef CONFIG_IP_NF_TPROXY_ICMP_IPV4_PAYLOAD
+		/* change data if IP header is here as payload */
+		if(pskb_may_pull(skb, sizeof(struct iphdr)) && skb->data != NULL
+			&& (skb->len >= (sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeof(struct iphdr))))	/* check for added payload */
+		{
+			struct iphdr *iph;
+
+			iph   = (struct iphdr *)(skb->data + sizeof(struct iphdr) + sizeof(struct icmphdr));
+
+			if(!skb_make_writable(pskb, (sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeof(struct iphdr))))
+				DEBUGP(KERN_DEBUG "IP_TPROXY: ip_tproxy_setup_nat_icmp(): failed to rewrite packet payload\n");
+			/* test if ipv4 header is complete & rewrite it */
+			else if(!(iph->ihl < 5) && iph->version == 4) {
+					nf_csum_replace4(&iph->check, iph->saddr, sr->laddr);	/* update csum - cause its needed */
+					iph->saddr	= sr->laddr;
+			}
+		}
+#endif
+	} else
+		return NF_DROP;
+
+	/* manipulate packet "by hand" */
+	if (unlikely(!ip_nat_manip_pkt(skb->nh.iph->protocol, pskb, 0, &tuple, manip_type))) {
+		DEBUGP(KERN_DEBUG "IP_TPROXY: ip_tproxy_setup_nat_icmp(): failed to rewrite packet header\n");
+		return NF_DROP;
+	}
+
+	return NF_ACCEPT;
+}
+#endif
+
 /* setup NAT for the packet */
 int
 ip_tproxy_setup_nat(struct sk_buff **pskb, int hooknum, struct ip_tproxy_sockref *sr, unsigned int flags)
@@ -712,6 +775,10 @@
 		return ip_tproxy_setup_nat_bidir(ct, hooknum, sr, flags);
 	} else if (sr->proto == IPPROTO_UDP)
 		return ip_tproxy_setup_nat_unidir(pskb, hooknum, sr);
+#ifdef CONFIG_IP_NF_TPROXY_ICMP
+	else if (sr->proto == IPPROTO_ICMP)
+		return ip_tproxy_setup_nat_icmp(pskb, hooknum, sr);
+#endif
 
 	return NF_DROP;
 }
diff -ur linux-source-2.6.20-voyage-ori/net/ipv4/netfilter/ipt_TPROXY.c linux-source-2.6.20-voyage-sam1/net/ipv4/netfilter/ipt_TPROXY.c
--- linux-source-2.6.20-voyage-ori/net/ipv4/netfilter/ipt_TPROXY.c	2008-02-27 14:46:53.000000000 +0100
+++ linux-source-2.6.20-voyage-sam1/net/ipv4/netfilter/ipt_TPROXY.c	2008-02-27 14:26:29.000000000 +0100
@@ -63,9 +63,16 @@
 	u16 *ports, _ports[2];
 	struct iphdr *iph = (*pskb)->nh.iph;
 
+#ifdef CONFIG_IP_NF_TPROXY_ICMP
+	/* TCP/UDP/ICMP only */
+	if ((iph->protocol != IPPROTO_TCP) &&
+	    (iph->protocol != IPPROTO_UDP) &&
+	    (iph->protocol != IPPROTO_ICMP))
+#else
 	/* TCP/UDP only */
 	if ((iph->protocol != IPPROTO_TCP) &&
 	    (iph->protocol != IPPROTO_UDP))
+#endif
 		return NF_ACCEPT;
 
 	/* get ports */
diff -ur linux-source-2.6.20-voyage-ori/net/ipv4/netfilter/Kconfig linux-source-2.6.20-voyage-sam1/net/ipv4/netfilter/Kconfig
--- linux-source-2.6.20-voyage-ori/net/ipv4/netfilter/Kconfig	2008-02-27 14:46:53.000000000 +0100
+++ linux-source-2.6.20-voyage-sam1/net/ipv4/netfilter/Kconfig	2008-03-05 13:59:58.000000000 +0100
@@ -221,6 +221,51 @@
 
 	  To compile it as a module, choose M here.  If unsure, say Y.
 
+if IP_NF_TPROXY
+
+config IP_NF_TPROXY_ICMP
+	bool "ICMP protocol support"
+	depends on IP_NF_TPROXY && IP_NF_TARGET_TPROXY
+	help
+	  This option adds a ICMP protocol support for TPROXY.
+
+	  ICMP support by securecoms.com, implemented by Sam <sam@scomd.net>.
+	  If unsure, say N.
+
+if IP_NF_TPROXY_ICMP
+
+config IP_NF_TPROXY_ICMP_IPV4_PAYLOAD
+	bool "ICMP IPv4 payload rewrite support"
+	depends on IP_NF_TPROXY && IP_NF_TARGET_TPROXY
+	help
+	  This option enables rewrite of IPv4 packets carried as payload
+	  of (i.e., Destination Unreachable) ICMP packets, and allows
+	  destination computer to correctly handle i.e., Fragmentation
+	  Needed information and adjust PMTU accordingly.
+
+	  Example: 
+
+          In combination with u32 match, one can build rule to redirect Fragmentation
+	  Needed ICMP packet from specific port (in ICMP payload) to destination
+	  computer.
+
+	  iptables -t tproxy -A PREROUTING -p icmp --icmp-type fragmentation-needed \
+			-m u32 --u32 "48&0xffff=80" -j TPROXY --on-ip 10.10.10.10 --on-port 0
+
+	  In case you are proxying all communication to port 80 on a network, this
+	  will redirect ICMP Fragmentation Needed packets sent as a response to
+	  connection from proxy server to remote port 80 and modify their payload
+	  so local kernel can handle these packets and adjust PMTU accordingly.
+	  This also obsoletes need to disable PMTU discovery (a.k.a disabling
+	  DontFragment bit), because from now it will work correctly !
+
+	  ICMP support by securecoms.com, implemented by Sam <sam@scomd.net>.
+	  If unsure, say N.
+
+endif
+
+endif
+
 config IP_NF_MATCH_TPROXY
 	tristate "tproxy match support"
 	depends on IP_NF_TPROXY

