netdev
[Top] [All Lists]

[PATCH] 1 serial, 3 netfilter -- Re: [2 bugs] iptable_nat module makes a

To: Rusty Russell <rusty@xxxxxxxxxxxxxxxx>
Subject: [PATCH] 1 serial, 3 netfilter -- Re: [2 bugs] iptable_nat module makes a black hole for GRE packets, iptables only plays with ICMP/UDP/TCP
From: David Ford <david@xxxxxxxxxxxxxx>
Date: Sun, 04 Jun 2000 18:12:18 -0700
Cc: alan@xxxxxxxxxxxxxxxxxxx, netdev@xxxxxxxxxxx
Organization: Talon Technology, Intl.
References: <20000604175726.B06318154@halfway>
Reply-to: Blu3Viper <david+validemail@xxxxxxxxxxxxxx>
Sender: owner-netdev@xxxxxxxxxxx
Ok, I massaged your patch around Rusty, and now everything netfilter/GRE
looks like it's doing ok.  Somehow my wireless stuff broke but I'll look at
that separately.

Attached is a conglomerate patch for:

        o SNAT happens
        o iptables is friendly with GRE packet routing and target LOG
        o OOPS in serial.c pnp guessing (temp fix)

For reference, this is how things look:


(T1 service) --------[ eth0 ]---[ greN ]
     |
  (inet)
     |
(cable modem) -------[ eth0 ]---[ greN ]
                        |
                        +-------[ eth1 ]-------(hub)
                        |
                        +-------[ eth2 ]-------(wireless pcmcia)


Everything from the lower set is tunneled to the upper set.  Now that
everyone is playing nicely (except wireless :P), generic traffic such as http
can be NAT'd instead of consuming tunnel bandwidth :)

Thankyou muchly for the help in this Rusty, you've no idea what a relaxing
day this is going to be.

-d

Rusty Russell wrote:

> In message <393A7A41.6ED4C7CB@xxxxxxxxxxxxxx> you write:
> > Alan first.  Alan, please remove "GRE is broken" from the todo list.
> > Replace it with "iptable_nat module breaks GRE" and add "iptables
> > generally doesn't handle protocols outside the top 3".
>
> Belay that.  These are the same `feature': entunnelled GRE packets
> don't go through LOCAL_OUT.  I didn't do that originally because I
> wasn't sure what the best policy for tunnels.

--
"The difference between 'involvement' and 'commitment' is like an
eggs-and-ham breakfast: the chicken was 'involved' - the pig was
'committed'."


diff -ruN linux/drivers/char/serial.c linux-fix/drivers/char/serial.c
--- linux/drivers/char/serial.c Sun Jun  4 17:10:55 2000
+++ linux-fix/drivers/char/serial.c     Sun Jun  4 17:31:52 2000
@@ -119,6 +119,7 @@
 #undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
 #undef SERIAL_DEBUG_PCI
 #undef SERIAL_DEBUG_AUTOCONF
+#define SERIAL_DEBUG_PNP
 
 /* Sanity checks */
 
@@ -3345,7 +3346,7 @@
 }
 
 /*
- * This routine detect the IRQ of a serial port by clearing OUT2 when
+ * This routine detects the IRQ of a serial port by clearing OUT2 when
  * no UART interrupt are requested (IER = 0) (*GPL*). This seems to work at
  * each time, as long as no other device permanently request the IRQ.
  * If no IRQ is detected, or multiple IRQ appear, this function returns 0.
@@ -3457,7 +3458,7 @@
  * 16550, and why not?  Startech doesn't seem to even acknowledge its
  * existence.)
  * 
- * What evil have men's minds wrought...
+ * What evil have mens' minds wrought...
  */
 static void autoconfig_startech_uarts(struct async_struct *info,
                                      struct serial_state *state,
@@ -4900,9 +4901,14 @@
        struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
        struct isapnp_resources *resa;
 
-       if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
-          !(check_compatible_id(dev)))
-              return 1;
+       printk("Checking resource inside serial_pnp_guess_board, %08lx (%s)\n", 
res, dev->bus->name);
+       
+       if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
+               !(check_compatible_id(dev)))
+                       return 1;
+
+       if (!res)
+               return 0;
 
        if (res->next)
               return 1;
@@ -4959,8 +4965,9 @@
                            board.device == ISAPNP_DEVICE(0x1021)))
                               board.flags |= SPCI_FL_NO_SHIRQ;
               } else {
-                      if (serial_pnp_guess_board(dev, &board))
+                      if (serial_pnp_guess_board(dev, &board)) {
                               continue;
+                              }
               }
               
               if (board.flags & SPCI_FL_NO_SHIRQ)
diff -ruN linux/net/ipv4/ip_gre.c linux-fix/net/ipv4/ip_gre.c
--- linux/net/ipv4/ip_gre.c     Mon May 22 09:50:55 2000
+++ linux-fix/net/ipv4/ip_gre.c Sun Jun  4 15:16:37 2000
@@ -35,6 +35,7 @@
 #include <net/ipip.h>
 #include <net/arp.h>
 #include <net/checksum.h>
+#include <linux/netfilter_ipv4.h>
 
 #ifdef CONFIG_IPV6
 #include <net/ipv6.h>
@@ -529,6 +530,52 @@
 #endif
 }
 
+#ifdef CONFIG_NETFILTER
+/* To preserve the cute illusion that a locally-generated packet can
+       be mangled before routing, we actually reroute if a hook altered
+       the packet. -RR */
+static int route_me_harder(struct sk_buff *skb)
+{
+       struct iphdr *iph = skb->nh.iph;
+       struct rtable *rt;
+
+       if (ip_route_output(&rt, iph->daddr, iph->saddr,
+                               RT_TOS(iph->tos) | RTO_CONN,
+                               skb->sk ? skb->sk->bound_dev_if : 0)) {
+                printk("route_me_harder: No more route.\n");
+                return -EINVAL;
+       }
+
+       /* Drop old route. */
+       dst_release(skb->dst);
+
+       skb->dst = &rt->u.dst;
+       return 0;
+}
+#endif
+
+/* Do route recalc if netfilter changes skb. */
+static inline int
+send_maybe_reroute(struct sk_buff *skb)
+{
+       struct ip_tunnel *tunnel = (struct ip_tunnel*)skb->dev->priv;
+       struct net_device_stats *stats = &tunnel->stat;
+
+#ifdef CONFIG_NETFILTER
+       if (skb->nfcache & NFC_ALTERED) {
+               if (route_me_harder(skb) != 0) {
+                       kfree_skb(skb);
+                       return -EINVAL;
+               }
+       }
+#endif
+       stats->tx_bytes += skb->len;
+       stats->tx_packets++;
+       ip_send(skb);
+       tunnel->recursion--;
+       return 0;
+}
+
 int ipgre_rcv(struct sk_buff *skb, unsigned short len)
 {
        struct iphdr *iph = skb->nh.iph;
@@ -827,12 +874,8 @@
        skb->nfct = NULL;
 #endif
 
-       stats->tx_bytes += skb->len;
-       stats->tx_packets++;
-       ip_send(skb);
-       tunnel->recursion--;
-       return 0;
-
+       return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+                                                       send_maybe_reroute);
 tx_error_icmp:
        dst_link_failure(skb);
 
diff -ruN linux/net/ipv4/netfilter/ip_nat_core.c 
linux-fix/net/ipv4/netfilter/ip_nat_core.c
--- linux/net/ipv4/netfilter/ip_nat_core.c      Fri Mar 17 10:56:20 2000
+++ linux-fix/net/ipv4/netfilter/ip_nat_core.c  Sun Jun  4 14:25:26 2000
@@ -269,7 +269,7 @@
                unsigned int score;
                struct ip_conntrack_tuple tuple;
        } best = { NULL,  0xFFFFFFFF };
-       u_int32_t *var_ipp, *other_ipp, saved_ip;
+       u_int32_t *var_ipp, *other_ipp, saved_ip, orig_dstip;
 
        if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
                var_ipp = &tuple->src.ip;
@@ -280,6 +280,9 @@
                saved_ip = tuple->src.ip;
                other_ipp = &tuple->src.ip;
        }
+       /* Don't do do_extra_mangle unless neccessary (overrides
+               explicit socket bindings, for example) */
+       orig_dstip = tuple->dst.ip;
 
        IP_NF_ASSERT(mr->rangesize >= 1);
        for (i = 0; i < mr->rangesize; i++) {
@@ -306,7 +309,8 @@
                        *other_ipp = saved_ip;
 
                        if (hooknum == NF_IP_LOCAL_OUT
-                           && !do_extra_mangle(*var_ipp, other_ipp)) {
+                               && *var_ipp != orig_dstip
+                          && !do_extra_mangle(*var_ipp, other_ipp)) {
                                DEBUGP("Range %u %u.%u.%u.%u rt failed!\n",
                                       i, IP_PARTS(*var_ipp));
                                /* Can't route?  This whole range part is
diff -ruN linux/scripts/lxdialog/Makefile linux-fix/scripts/lxdialog/Makefile
--- linux/scripts/lxdialog/Makefile     Sun Jun  4 17:10:56 2000
+++ linux-fix/scripts/lxdialog/Makefile Sun Jun  4 00:04:02 2000
@@ -10,7 +10,7 @@
 ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
         HOSTCFLAGS += -DCURSES_LOC="<ncurses.h>"
 else
-       HOSTCFLAGS += -DCURSES_LOC="<curses.h>"
+       HOSTCFLAGS += -I/usr/local/include -DCURSES_LOC="<curses.h>"
 endif
 endif
 endif
<Prev in Thread] Current Thread [Next in Thread>