diff -ur v2.4.20-routes9/linux/net/ipv4/ip_nat_dumb.c linux/net/ipv4/ip_nat_dumb.c --- v2.4.20-routes9/linux/net/ipv4/ip_nat_dumb.c Thu Mar 6 00:26:28 2003 +++ linux/net/ipv4/ip_nat_dumb.c Thu Mar 6 00:27:32 2003 @@ -52,6 +52,13 @@ u32 osaddr = iph->saddr; u16 check; +#ifdef CONFIG_NETFILTER +#ifdef CONFIG_IP_NF_NAT_NEEDED + if (skb->nfct) + return 0; +#endif +#endif + IPCB(skb)->flags |= IPSKB_TRANSLATED; /* Rewrite IP header */ diff -ur v2.4.20-routes9/linux/net/ipv4/netfilter/ip_fw_compat.c linux/net/ipv4/netfilter/ip_fw_compat.c --- v2.4.20-routes9/linux/net/ipv4/netfilter/ip_fw_compat.c Sun Mar 31 06:18:26 2002 +++ linux/net/ipv4/netfilter/ip_fw_compat.c Thu Mar 6 00:27:32 2003 @@ -76,6 +76,7 @@ const struct net_device *out, int (*okfn)(struct sk_buff *)) { + struct rtable *rt; int ret = FW_BLOCK; u_int16_t redirpt; @@ -117,6 +118,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, (*pskb)->nh.raw, &redirpt, pskb); diff -ur v2.4.20-routes9/linux/net/ipv4/netfilter/ip_fw_compat_masq.c linux/net/ipv4/netfilter/ip_fw_compat_masq.c --- v2.4.20-routes9/linux/net/ipv4/netfilter/ip_fw_compat_masq.c Thu Mar 6 00:26:28 2003 +++ linux/net/ipv4/netfilter/ip_fw_compat_masq.c Thu Mar 6 00:32:19 2003 @@ -78,6 +78,10 @@ struct ip_nat_multi_range range; skb_rt = (struct rtable *) (*pskb)->dst; + rt = skb_rt; + if (rt->rt_flags & RTCF_MASQ && (newsrc = rt->rt_src_map)) + goto have_src; + skb_dev = skb_rt->u.dst.dev; /* Pass 0 instead of saddr, since it's going to be changed anyway. */ @@ -90,6 +94,9 @@ } 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.4.20-routes9/linux/net/ipv4/netfilter/ip_nat_rule.c linux/net/ipv4/netfilter/ip_nat_rule.c --- v2.4.20-routes9/linux/net/ipv4/netfilter/ip_nat_rule.c Fri Nov 29 03:00:19 2002 +++ linux/net/ipv4/netfilter/ip_nat_rule.c Thu Mar 6 00:44:57 2003 @@ -252,6 +252,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 rt_key key = { + dst: rt->rt_dst, + src: 0, + oif: rt->u.dst.dev->ifindex, + gw: rt->rt_gateway, + tos: RT_TOS(skb->nh.iph->tos)|RTO_CONN, +#ifdef CONFIG_IP_ROUTE_FWMARK + fwmark: skb->nfmark, +#endif + }; + + if (ip_route_output_key(&rt, &key) != 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, @@ -260,6 +300,16 @@ struct ip_nat_info *info) { 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);