gre(4) calculates the route to the destination of the tunnel and chaches
the route. It uses a very "special" algorithm for the lookup that tends to
break more often then hitting the problems which the algorithm tries to
circumvent. To be more precise gre(4) fiddles with the endpoint address
looking up an address +/-1 of the real IP. This is done to allow a gre(4)
tunnel where destination IP of the tunnel is equvalent with the
destination IP on the gre interface. For example:
gre0: flags=9011<UP,POINTOPOINT,LINK0,MULTICAST> mtu 1476
        priority: 0
        groups: gre
        physical address inet 192.168.254.109 --> 192.168.254.101
        inet6 fe80::20a:e4ff:fe39:5583%gre0 ->  prefixlen 64 scopeid 0x9
        inet 10.0.0.2 --> 192.168.254.101 netmask 0xffffffff

Both destinations are 192.168.254.101. Now this is all nice but a IMO
uncommon case and the code breaks in some cases (e.g. when the tunnel
endpoint is directly reachable).

So the following diff removes this special handling. Btw. the inner IP
address can be set to almost anything without causing issues. How many
people do need this strange feature?
-- 
:wq Claudio

Index: if_gre.c
===================================================================
RCS file: /cvs/src/sys/net/if_gre.c,v
retrieving revision 1.51
diff -u -p -r1.51 if_gre.c
--- if_gre.c    3 Jul 2010 04:44:51 -0000       1.51
+++ if_gre.c    22 Sep 2010 04:51:43 -0000
@@ -675,29 +675,13 @@ void
 gre_compute_route(struct gre_softc *sc)
 {
        struct route *ro;
-       u_int32_t a, b, c;
 
        ro = &sc->route;
 
        bzero(ro, sizeof(struct route));
-       ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sc->g_dst;
        ro->ro_dst.sa_family = AF_INET;
        ro->ro_dst.sa_len = sizeof(ro->ro_dst);
-
-       /*
-        * toggle last bit, so our interface is not found, but a less
-        * specific route. I'd rather like to specify a shorter mask,
-        * but this is not possible. Should work though. XXX
-        * there is a simpler way ...
-        */
-       if ((sc->sc_if.if_flags & IFF_LINK1) == 0) {
-               a = ntohl(sc->g_dst.s_addr);
-               b = a & 0x01;
-               c = a & 0xfffffffe;
-               b = b ^ 0x01;
-               a = b | c;
-               ((struct sockaddr_in *) &ro->ro_dst)->sin_addr.s_addr = 
htonl(a);
-       }
+       ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sc->g_dst;
 
        ro->ro_rt = rtalloc1(&ro->ro_dst, RT_REPORT | RT_NOCLONING,
            sc->g_rtableid);
@@ -714,13 +698,6 @@ gre_compute_route(struct gre_softc *sc)
                ro->ro_rt = NULL;
                return;
        }
-
-       /*
-        * now change it back - else ip_output will just drop
-        * the route and search one to this interface ...
-        */
-       if ((sc->sc_if.if_flags & IFF_LINK1) == 0)
-               ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sc->g_dst;
 }
 
 /*

Reply via email to