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
[-- Attachment #1 --]
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
[-- Attachment #2 --]
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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010316201916.A20185>
