From owner-freebsd-net Fri Mar 16 10:19:28 2001 Delivered-To: freebsd-net@freebsd.org Received: from whale.sunbay.crimea.ua (whale.sunbay.crimea.ua [212.110.138.65]) by hub.freebsd.org (Postfix) with ESMTP id 6F8A237B719; Fri, 16 Mar 2001 10:19:19 -0800 (PST) (envelope-from ru@whale.sunbay.crimea.ua) Received: (from ru@localhost) by whale.sunbay.crimea.ua (8.11.2/8.11.2) id f2GIJGa23052; Fri, 16 Mar 2001 20:19:16 +0200 (EET) (envelope-from ru) Date: Fri, 16 Mar 2001 20:19:16 +0200 From: Ruslan Ermilov To: net@FreeBSD.org Cc: Garrett Wollman Subject: Reading Stevens, playing routing games Message-ID: <20010316201916.A20185@sunbay.com> Mail-Followup-To: net@FreeBSD.org, Garrett Wollman Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="ew6BAiZeqk4r7MaW" Content-Disposition: inline User-Agent: Mutt/1.2.5i Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org --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