Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Mar 2001 20:19:16 +0200
From:      Ruslan Ermilov <ru@FreeBSD.org>
To:        net@FreeBSD.org
Cc:        Garrett Wollman <wollman@FreeBSD.org>
Subject:   Reading Stevens, playing routing games
Message-ID:  <20010316201916.A20185@sunbay.com>

next in thread | raw e-mail | index | archive | help

--ew6BAiZeqk4r7MaW
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi!

First of all, I would like to commit the attached patch; it removes
duplicate code.  Please review.

Also, I found a nasty bug in IP routing.  The new route added may not
take immediate effect for routing decisions, because ip_forward() may
use the cached route (rt_forwarding).


DEMO (only relevant routes are shown).

Step 1.  On a router, add a route to the network (192.168.1).

: # route add -net 192.168.1 gateway
: add net 192.168.1: gateway gateway
: 
: # netstat -rn
: Routing tables
: 
: Internet:
: Destination        Gateway            Flags     Refs     Use     Netif Expire
: 192.168.1          gateway            UGSc        0        0      rl0

Step 2.  From some other host for which this machine is the default router,
         run ``traceroute -m 2 -n 192.168.1.1''.  Observe, on the router,
         that the reference count grown on the 192.168.1 route.

: # netstat -rn
: Routing tables
: 
: Internet:
: Destination        Gateway            Flags     Refs     Use     Netif Expire
: 192.168.1          gateway            UGSc        1        3      rl0

Step 3.  Add RTF_REJECT host route to the destination:

: # route add 192.168.1.1 -iface lo0 -reject
: add host 192.168.1.1: gateway lo0
: # netstat -rn
: Routing tables
: 
: Internet:
: Destination        Gateway            Flags     Refs     Use     Netif Expire
: 192.168.1          gateway            UGSc        1        3      rl0
: 192.168.1.1        lo0                UHRS        0        0      lo0

Step 4.  The fun begins.  What you would expect if you run traceroute to
         192.168.1.1 again?  Obviously host route should take precedence
         over network route, and I expected ICMP Destination Unreachable.
         But... what's a hell? the new route did not take immediate effect,
         traceroute succeeded (192.168.1.1 still has zero refcound and use):

: # netstat -rn
: Routing tables
: 
: Internet:
: Destination        Gateway            Flags     Refs     Use     Netif Expire
: 192.168.1          gateway            UGSc        1        6      rl0
: 192.168.1.1        lo0                UHRS        0        0      lo0

Step 5.  The fun continues.  From another host, run traceroute to another
         destination (to help router change rt_forward.ro_dst).
         traceroute -m 2 -n 192.168.1.2:

: # netstat -rn
: Routing tables
: 
: Internet:
: Destination        Gateway            Flags     Refs     Use     Netif Expire
: 192.168.1          gateway            UGSc        1        9      rl0
: 192.168.1.1        lo0                UHRS        0        0      lo0

Step 6.  Run traceroute again to 192.168.1.1.  The fun ends.


The solution I found so far is to unstaticize the ``rt_forward'', and
invalidate the rt_forward.ro_rt in in_addroute() (in_rmx.c).  Any better
ideas?


Cheers,
-- 
Ruslan Ermilov		Oracle Developer/DBA,
ru@sunbay.com		Sunbay Software AG,
ru@FreeBSD.org		FreeBSD committer,
+380.652.512.251	Simferopol, Ukraine

http://www.FreeBSD.org	The Power To Serve
http://www.oracle.com	Enabling The Information Age

--ew6BAiZeqk4r7MaW
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=p

Index: ip_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.162
diff -u -p -r1.162 ip_input.c
--- ip_input.c	2001/03/08 19:03:26	1.162
+++ ip_input.c	2001/03/16 17:34:30
@@ -1507,7 +1507,6 @@ ip_forward(m, srcrt)
 	int srcrt;
 {
 	register struct ip *ip = mtod(m, struct ip *);
-	register struct sockaddr_in *sin;
 	register struct rtentry *rt;
 	int error, type = 0, code = 0;
 	struct mbuf *mcopy;
@@ -1543,24 +1542,11 @@ ip_forward(m, srcrt)
 	}
 #endif
 
-	sin = (struct sockaddr_in *)&ipforward_rt.ro_dst;
-	if ((rt = ipforward_rt.ro_rt) == 0 ||
-	    ip->ip_dst.s_addr != sin->sin_addr.s_addr) {
-		if (ipforward_rt.ro_rt) {
-			RTFREE(ipforward_rt.ro_rt);
-			ipforward_rt.ro_rt = 0;
-		}
-		sin->sin_family = AF_INET;
-		sin->sin_len = sizeof(*sin);
-		sin->sin_addr = ip->ip_dst;
-
-		rtalloc_ign(&ipforward_rt, RTF_PRCLONING);
-		if (ipforward_rt.ro_rt == 0) {
-			icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
-			return;
-		}
+	if (ip_rtaddr(ip->ip_dst) == 0) {
+		icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
+		return;
+	} else
 		rt = ipforward_rt.ro_rt;
-	}
 
 	/*
 	 * Save the IP header and at most 8 bytes of the payload,

--ew6BAiZeqk4r7MaW--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010316201916.A20185>