Hi DaveM!

This patch adds support for destination nat on connections initiated by
local processes.  This is needed in a couple of setups but not supported
by our current codebase.

Hoever, as it is a little bit expensive to hook the nat table into yet another
netfilter hook, we've made it a kernel config option.

Please apply,

diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude 
*.orig --exclude *.rej --exclude *~ 
linux-2.4.19-pre3-plain/include/linux/netfilter_ipv4/ip_nat.h 
linux-2.4.19-pre3-davem/include/linux/netfilter_ipv4/ip_nat.h
--- linux-2.4.19-pre3-plain/include/linux/netfilter_ipv4/ip_nat.h       Thu Apr 26 
00:00:28 2001
+++ linux-2.4.19-pre3-davem/include/linux/netfilter_ipv4/ip_nat.h       Thu Mar 14 
+17:16:37 2002
@@ -11,8 +11,13 @@
        IP_NAT_MANIP_DST
 };
 
+#ifndef CONFIG_IP_NF_NAT_LOCAL
 /* SRC manip occurs only on POST_ROUTING */
 #define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING)
+#else
+/* SRC manip occurs POST_ROUTING or LOCAL_IN */
+#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != 
+NF_IP_LOCAL_IN)
+#endif
 
 /* 2.3.19 (I hope) will define this in linux/netfilter_ipv4.h. */
 #ifndef SO_ORIGINAL_DST
diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude 
*.orig --exclude *.rej --exclude *~ 
linux-2.4.19-pre3-plain/net/ipv4/netfilter/Config.in 
linux-2.4.19-pre3-davem/net/ipv4/netfilter/Config.in
--- linux-2.4.19-pre3-plain/net/ipv4/netfilter/Config.in        Mon Feb 25 20:38:14 
2002
+++ linux-2.4.19-pre3-davem/net/ipv4/netfilter/Config.in        Thu Mar 14 17:16:37 
+2002
@@ -47,6 +47,7 @@
       define_bool CONFIG_IP_NF_NAT_NEEDED y
       dep_tristate '    MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE 
$CONFIG_IP_NF_NAT
       dep_tristate '    REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT 
$CONFIG_IP_NF_NAT
+      bool '    NAT of local connections' CONFIG_IP_NF_NAT_LOCAL
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
         dep_tristate '    Basic SNMP-ALG support (EXPERIMENTAL)' 
CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
       fi
diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude 
*.orig --exclude *.rej --exclude *~ 
linux-2.4.19-pre3-plain/net/ipv4/netfilter/ip_nat_core.c 
linux-2.4.19-pre3-davem/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.4.19-pre3-plain/net/ipv4/netfilter/ip_nat_core.c    Fri Dec 21 18:42:05 
2001
+++ linux-2.4.19-pre3-davem/net/ipv4/netfilter/ip_nat_core.c    Thu Mar 14 17:16:37 
+2002
@@ -314,6 +314,7 @@
                         * do_extra_mangle last time. */
                        *other_ipp = saved_ip;
 
+#ifdef CONFIG_IP_NF_NAT_LOCAL
                        if (hooknum == NF_IP_LOCAL_OUT
                            && *var_ipp != orig_dstip
                            && !do_extra_mangle(*var_ipp, other_ipp)) {
@@ -324,6 +325,7 @@
                                 * anyway. */
                                continue;
                        }
+#endif
 
                        /* Count how many others map onto this. */
                        score = count_maps(tuple->src.ip, tuple->dst.ip,
@@ -367,11 +369,13 @@
                else {
                        /* Only do extra mangle when required (breaks
                            socket binding) */
+#ifdef CONFIG_IP_NF_NAT_LOCAL
                        if (tuple->dst.ip != mr->range[0].min_ip
                            && hooknum == NF_IP_LOCAL_OUT
                            && !do_extra_mangle(mr->range[0].min_ip,
                                                &tuple->src.ip))
                                return NULL;
+#endif
                        tuple->dst.ip = mr->range[0].min_ip;
                }
        }
@@ -494,7 +498,10 @@
 static unsigned int opposite_hook[NF_IP_NUMHOOKS]
 = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
     [NF_IP_POST_ROUTING] = NF_IP_PRE_ROUTING,
-    [NF_IP_LOCAL_OUT] = NF_IP_POST_ROUTING
+#ifdef CONFIG_IP_NF_NAT_LOCAL
+    [NF_IP_LOCAL_OUT] = NF_IP_LOCAL_IN,
+    [NF_IP_LOCAL_IN] = NF_IP_LOCAL_OUT,
+#endif
 };
 
 unsigned int
diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude 
*.orig --exclude *.rej --exclude *~ 
linux-2.4.19-pre3-plain/net/ipv4/netfilter/ip_nat_rule.c 
linux-2.4.19-pre3-davem/net/ipv4/netfilter/ip_nat_rule.c
--- linux-2.4.19-pre3-plain/net/ipv4/netfilter/ip_nat_rule.c    Mon Feb 25 20:38:14 
2002
+++ linux-2.4.19-pre3-davem/net/ipv4/netfilter/ip_nat_rule.c    Thu Mar 14 17:16:37 
+2002
@@ -140,8 +140,12 @@
        struct ip_conntrack *ct;
        enum ip_conntrack_info ctinfo;
 
+#ifdef CONFIG_IP_NF_NAT_LOCAL
        IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
                     || hooknum == NF_IP_LOCAL_OUT);
+#else
+       IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING);
+#endif
 
        ct = ip_conntrack_get(*pskb, &ctinfo);
 
@@ -210,7 +214,7 @@
 
        /* Only allow these for NAT. */
        if (strcmp(tablename, "nat") != 0) {
-               DEBUGP("SNAT: wrong table %s\n", tablename);
+               DEBUGP("DNAT: wrong table %s\n", tablename);
                return 0;
        }
 
@@ -218,6 +222,14 @@
                DEBUGP("DNAT: hook mask 0x%x bad\n", hook_mask);
                return 0;
        }
+       
+#ifndef CONFIG_IP_NF_NAT_LOCAL
+       if (hook_mask & (1 << NF_IP_LOCAL_OUT)) {
+               DEBUGP("DNAT: CONFIG_IP_NF_NAT_LOCAL not enabled\n");
+               return 0;
+       }
+#endif
+
        return 1;
 }
 
diff -Nru --exclude .depend --exclude *.o --exclude *.ver --exclude .*.flags --exclude 
*.orig --exclude *.rej --exclude *~ 
linux-2.4.19-pre3-plain/net/ipv4/netfilter/ip_nat_standalone.c 
linux-2.4.19-pre3-davem/net/ipv4/netfilter/ip_nat_standalone.c
--- linux-2.4.19-pre3-plain/net/ipv4/netfilter/ip_nat_standalone.c      Mon Feb 25 
20:38:14 2002
+++ linux-2.4.19-pre3-davem/net/ipv4/netfilter/ip_nat_standalone.c      Thu Mar 14 
+17:16:37 2002
@@ -41,7 +41,8 @@
 #define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING"  \
                           : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \
                              : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT"  \
-                                : "*ERROR*")))
+                                : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN"  \
+                                   : "*ERROR*")))
 
 static unsigned int
 ip_nat_fn(unsigned int hooknum,
@@ -94,6 +95,12 @@
                }
                /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
        case IP_CT_NEW:
+#ifdef CONFIG_IP_NF_NAT_LOCAL
+               /* LOCAL_IN hook doesn't have a chain and thus doesn't care
+                * about new packets -HW */
+               if (hooknum == NF_IP_LOCAL_IN)
+                       return NF_ACCEPT;
+#endif
                info = &ct->nat.info;
 
                WRITE_LOCK(&ip_nat_lock);
@@ -204,6 +211,11 @@
 static struct nf_hook_ops ip_nat_local_out_ops
 = { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
 
+#ifdef CONFIG_IP_NF_NAT_LOCAL
+static struct nf_hook_ops ip_nat_local_in_ops
+= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_NAT_SRC };
+#endif
+
 /* Protocol registration. */
 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
 {
@@ -272,6 +284,13 @@
                printk("ip_nat_init: can't register local out hook.\n");
                goto cleanup_outops;
        }
+#ifdef CONFIG_IP_NF_NAT_LOCAL
+       ret = nf_register_hook(&ip_nat_local_in_ops);
+       if (ret < 0) {
+               printk("ip_nat_init: can't register local in hook.\n");
+               goto cleanup_localoutops;
+       }
+#endif
        if (ip_conntrack_module)
                __MOD_INC_USE_COUNT(ip_conntrack_module);
        return ret;
@@ -279,6 +298,10 @@
  cleanup:
        if (ip_conntrack_module)
                __MOD_DEC_USE_COUNT(ip_conntrack_module);
+#ifdef CONFIG_IP_NF_NAT_LOCAL
+       nf_unregister_hook(&ip_nat_local_in_ops);
+ cleanup_localoutops:
+#endif
        nf_unregister_hook(&ip_nat_local_out_ops);
  cleanup_outops:
        nf_unregister_hook(&ip_nat_out_ops);
-- 
Live long and prosper
- Harald Welte / [EMAIL PROTECTED]               http://www.gnumonks.org/
============================================================================
GCS/E/IT d- s-: a-- C+++ UL++++$ P+++ L++++$ E--- W- N++ o? K- w--- O- M+ 
V-- PS++ PE-- Y++ PGP++ t+ 5-- !X !R tv-- b+++ !DI !D G+ e* h--- r++ y+(*)

Reply via email to