diff -ur v2.6.0-test1/linux/net/ipv4/ip_nat_dumb.c linux/net/ipv4/ip_nat_dumb.c
--- v2.6.0-test1/linux/net/ipv4/ip_nat_dumb.c	Sat Jul 26 16:38:42 2003
+++ linux/net/ipv4/ip_nat_dumb.c	Sun Jul 27 18:32:43 2003
@@ -52,6 +52,13 @@
 	u32 osaddr = iph->saddr;
 	u16	check;
 
+#ifdef CONFIG_NETFILTER
+#ifdef IP_NF_NAT_NEEDED
+	if (skb->nfct)
+		return 0;
+#endif
+#endif
+
 	IPCB(skb)->flags |= IPSKB_TRANSLATED;
 
 	/* Rewrite IP header */
diff -ur v2.6.0-test1/linux/net/ipv4/netfilter/ip_fw_compat.c linux/net/ipv4/netfilter/ip_fw_compat.c
--- v2.6.0-test1/linux/net/ipv4/netfilter/ip_fw_compat.c	Sat Jul 26 16:38:42 2003
+++ linux/net/ipv4/netfilter/ip_fw_compat.c	Sun Jul 27 18:32:43 2003
@@ -54,6 +54,7 @@
       const struct net_device *out,
       int (*okfn)(struct sk_buff *))
 {
+	struct rtable *rt;
 	int ret = FW_BLOCK;
 	u_int16_t redirpt;
 
@@ -85,6 +86,9 @@
                    demasqueraded: if so, skip forward chain. */
 		if ((*pskb)->nfct)
 			ret = FW_ACCEPT;
+		else if (rt = (struct rtable *) (*pskb)->dst,
+			 rt->rt_flags & RTCF_MASQ)
+			ret = FW_MASQUERADE;
 		else ret = fwops->fw_forward(fwops, PF_INET,
 					     (struct net_device *)out,
 					     &redirpt, pskb);
diff -ur v2.6.0-test1/linux/net/ipv4/netfilter/ip_fw_compat_masq.c linux/net/ipv4/netfilter/ip_fw_compat_masq.c
--- v2.6.0-test1/linux/net/ipv4/netfilter/ip_fw_compat_masq.c	Sat Jul 26 16:38:42 2003
+++ linux/net/ipv4/netfilter/ip_fw_compat_masq.c	Sun Jul 27 18:32:43 2003
@@ -68,19 +68,28 @@
 	/* Setup the masquerade, if not already */
 	if (!info->initialized) {
 		u_int32_t newsrc;
-		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = (*pskb)->nh.iph->daddr } } };
-		struct rtable *rt;
+		struct rtable *rt = (struct rtable *) (*pskb)->dst;
+		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = (*pskb)->nh.iph->daddr,
+							 .tos = RT_TOS((*pskb)->nh.iph->tos) } },
+				    .oif = rt->u.dst.dev->ifindex,
+		};
 		struct ip_nat_multi_range range;
 
+		if (rt->rt_flags & RTCF_MASQ && (newsrc = rt->rt_src_map))
+			goto have_src;
+
 		/* Pass 0 instead of saddr, since it's going to be changed
 		   anyway. */
 		if (ip_route_output_key(&rt, &fl) != 0) {
+			WRITE_UNLOCK(&ip_nat_lock);
 			DEBUGP("ipnat_rule_masquerade: Can't reroute.\n");
 			return NF_DROP;
 		}
-		newsrc = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
-					  RT_SCOPE_UNIVERSE);
+		newsrc = rt->rt_src;
 		ip_rt_put(rt);
+
+		have_src:
+
 		range = ((struct ip_nat_multi_range)
 			 { 1,
 			   {{IP_NAT_RANGE_MAP_IPS|IP_NAT_RANGE_PROTO_SPECIFIED,
diff -ur v2.6.0-test1/linux/net/ipv4/netfilter/ip_nat_rule.c linux/net/ipv4/netfilter/ip_nat_rule.c
--- v2.6.0-test1/linux/net/ipv4/netfilter/ip_nat_rule.c	Sat Jul 26 16:38:43 2003
+++ linux/net/ipv4/netfilter/ip_nat_rule.c	Sun Jul 27 18:29:30 2003
@@ -255,6 +255,46 @@
 	return ip_nat_setup_info(conntrack, &mr, hooknum);
 }
 
+#ifdef CONFIG_IP_ROUTE_NAT
+
+static inline unsigned int
+alloc_rtmasq_binding(struct ip_conntrack *conntrack,
+		   struct ip_nat_info *info,
+		   struct sk_buff *skb)
+{
+	/* Force range to this IP; let proto decide mapping for
+	   per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
+	*/
+	struct rtable *rt = (struct rtable *) skb->dst;
+	struct ip_nat_multi_range mr
+		= { 1, { { IP_NAT_RANGE_MAP_IPS, 0, 0, { 0 }, { 0 } } } };
+
+	if (rt->rt_src_map) {
+		mr.range[0].min_ip = mr.range[0].max_ip = rt->rt_src_map;
+	} else {
+		struct flowi fl = {
+			.nl_u	= { .ip4_u = {
+					.daddr = rt->rt_dst,
+					.tos =  RT_TOS(skb->nh.iph->tos)|RTO_CONN,
+#ifdef CONFIG_IP_ROUTE_FWMARK
+					.fwmark = skb->nfmark,
+#endif
+			} },
+			.oif = rt->u.dst.dev->ifindex,
+		};
+
+		if (ip_route_output_key(&rt, &fl) != 0)
+			return NF_DROP;
+		mr.range[0].min_ip = mr.range[0].max_ip = rt->rt_src;
+		ip_rt_put(rt);
+	}
+	DEBUGP("Allocating RTMASQ binding for %p (%u.%u.%u.%u)\n", conntrack,
+	       NIPQUAD(mr.range[0].min_ip));
+	return ip_nat_setup_info(conntrack, &mr, NF_IP_POST_ROUTING);
+}
+
+#endif
+
 int ip_nat_rule_find(struct sk_buff **pskb,
 		     unsigned int hooknum,
 		     const struct net_device *in,
@@ -264,6 +304,15 @@
 {
 	int ret;
 
+#ifdef CONFIG_IP_ROUTE_NAT
+	{
+		struct rtable *rt = (struct rtable *) (*pskb)->dst;
+
+		if (rt && rt->rt_flags & RTCF_MASQ &&
+		    hooknum == NF_IP_POST_ROUTING)
+			return alloc_rtmasq_binding(ct, info, *pskb);
+	}
+#endif
 	ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL);
 
 	if (ret == NF_ACCEPT) {
