From owner-freebsd-net Tue Jul 17 23:43:47 2001 Delivered-To: freebsd-net@freebsd.org Received: from shuttle.wide.toshiba.co.jp (shuttle.wide.toshiba.co.jp [202.249.10.124]) by hub.freebsd.org (Postfix) with ESMTP id A272037B401 for ; Tue, 17 Jul 2001 23:43:41 -0700 (PDT) (envelope-from jinmei@isl.rdc.toshiba.co.jp) Received: from localhost ([3ffe:501:4819:2000:f4b9:a9c3:3362:c191]) by shuttle.wide.toshiba.co.jp (8.9.1+3.1W/8.9.1) with ESMTP id PAA00912 for ; Wed, 18 Jul 2001 15:45:39 +0900 (JST) Date: Wed, 18 Jul 2001 15:43:41 +0900 Message-ID: From: JINMEI Tatuya / =?ISO-2022-JP?B?GyRCP0BMQEMjOkgbKEI=?= To: freebsd-net@FreeBSD.ORG Subject: avoiding unnecessary route deletion in rt_fixchange() User-Agent: Wanderlust/2.5.8 (Smooth) Emacs/21.0 Mule/5.0 (SAKAKI) Organization: Research & Development Center, Toshiba Corp., Kawasaki, Japan. MIME-Version: 1.0 (generated by SEMI 1.13.7 - "Awazu") Content-Type: text/plain; charset=US-ASCII X-Dispatcher: imput version 980905(IM100) Lines: 103 Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org As commented in defined in sys/net/route.c, rt_fixchange() has a bad effect, which would cause unnecessary route deletion: * Unfortunately, this has the obnoxious * property of also triggering for insertion /above/ a pre-existing network * route and clones. Sigh. This may be fixed some day. The effect has been even worse, because recent versions of route.c set the parent rtentry for cloned routes from an interface-direct route. For example, suppose that we have an interface "ne0" that has an IPv4 subnet "10.0.0.0/24". Then we may have a cloned route like 10.0.0.1 on the interface, whose parent route is 10.0.0.0/24 (to the interface ne0). Now, when we add the default route (i.e. 0.0.0.0/0), rt_fixchange() will remove the cloned route 10.0.0.1. The (bad) effect also prevents rt_setgate from configuring rt_gwroute, which would not be an intended behavior. As suggested in the comments to rt_fixchange(), we need stricter check in the function, to prevent unintentional route deletion. The attached is a proposed fix to this problem (for FreeBSD4-STABLE). Please review it, and merge it to the repository if acceptable. This fix will also solve the "IPV6 panic?" problem which was recently reported in this list. Thanks, JINMEI, Tatuya Communication Platform Lab. Corporate R&D Center, Toshiba Corp. jinmei@isl.rdc.toshiba.co.jp *** route.c.orig Wed Jul 18 15:13:18 2001 --- route.c Wed Jul 18 15:18:15 2001 *************** *** 726,734 **** * network route and (cloned) host routes. For this reason, a simple check * of rt->rt_parent is insufficient; each candidate route must be tested * against the (mask, value) of the new route (passed as before in vp) ! * to see if the new route matches it. Unfortunately, this has the obnoxious ! * property of also triggering for insertion /above/ a pre-existing network ! * route and clones. Sigh. This may be fixed some day. * * XXX - it may be possible to do fixdelete() for changes and reserve this * routine just for adds. I'm not sure why I thought it was necessary to do --- 726,732 ---- * network route and (cloned) host routes. For this reason, a simple check * of rt->rt_parent is insufficient; each candidate route must be tested * against the (mask, value) of the new route (passed as before in vp) ! * to see if the new route matches it. * * XXX - it may be possible to do fixdelete() for changes and reserve this * routine just for adds. I'm not sure why I thought it was necessary to do *************** *** 747,754 **** struct rtfc_arg *ap = vp; struct rtentry *rt0 = ap->rt0; struct radix_node_head *rnh = ap->rnh; ! u_char *xk1, *xm1, *xk2; ! int i, len; #ifdef DEBUG if (rtfcdebug) --- 745,752 ---- struct rtfc_arg *ap = vp; struct rtentry *rt0 = ap->rt0; struct radix_node_head *rnh = ap->rnh; ! u_char *xk1, *xm1, *xk2, *xmp; ! int i, len, mlen; #ifdef DEBUG if (rtfcdebug) *************** *** 781,786 **** --- 779,806 ---- xk1 = (u_char *)rt_key(rt0); xm1 = (u_char *)rt_mask(rt0); xk2 = (u_char *)rt_key(rt); + + /* avoid applying a less specific route */ + xmp = (u_char *)rt_mask(rt->rt_parent); + mlen = ((struct sockaddr *)rt_key(rt->rt_parent))->sa_len; + if (mlen > ((struct sockaddr *)rt_key(rt0))->sa_len) { + #ifdef DEBUG + if (rtfcdebug) + printf("rt_fixchange: inserting a less " + "specific route\n"); + #endif + return 0; + } + for (i = rnh->rnh_treetop->rn_offset; i < mlen; i++) { + if ((xmp[i] & ~(xmp[i] ^ xm1[i])) != xmp[i]) { + #ifdef DEBUG + if (rtfcdebug) + printf("rt_fixchange: inserting a less " + "specific route\n"); + #endif + return 0; + } + } for (i = rnh->rnh_treetop->rn_offset; i < len; i++) { if ((xk2[i] & xm1[i]) != xk1[i]) { To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message