From owner-freebsd-net@FreeBSD.ORG Thu Nov 11 20:24:02 2004 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id B936E16A4CE; Thu, 11 Nov 2004 20:24:02 +0000 (GMT) Received: from moutng.kundenserver.de (moutng.kundenserver.de [212.227.126.177]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1AE4B43D48; Thu, 11 Nov 2004 20:24:02 +0000 (GMT) (envelope-from max@love2party.net) Received: from [212.227.126.209] (helo=mrelayng.kundenserver.de) by moutng.kundenserver.de with esmtp (Exim 3.35 #1) id 1CSLU9-00018w-00; Thu, 11 Nov 2004 21:24:01 +0100 Received: from [84.128.130.223] (helo=donor.laier.local) by mrelayng.kundenserver.de with asmtp (TLSv1:RC4-MD5:128) (Exim 3.35 #1) id 1CSLU8-0007bw-00; Thu, 11 Nov 2004 21:24:01 +0100 From: Max Laier To: freebsd-arch@freebsd.org Date: Thu, 11 Nov 2004 21:24:05 +0100 User-Agent: KMail/1.7.1 MIME-Version: 1.0 Content-Type: multipart/signed; boundary="nextPart4509686.Ad4VYY4PBk"; protocol="application/pgp-signature"; micalg=pgp-sha1 Content-Transfer-Encoding: 7bit Message-Id: <200411112124.12616.max@love2party.net> X-Provags-ID: kundenserver.de abuse@kundenserver.de auth:61c499deaeeba3ba5be80f48ecc83056 cc: freebsd-net@freebsd.org Subject: in.c autoadding prefix route X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Nov 2004 20:24:02 -0000 --nextPart4509686.Ad4VYY4PBk Content-Type: multipart/mixed; boundary="Boundary-01=_np8kBd92qNtmEHy" Content-Transfer-Encoding: 7bit Content-Disposition: inline --Boundary-01=_np8kBd92qNtmEHy Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline All, I know I have sent this a couple of times before, but never got anywhere. T= his=20 time I am set to commit! The attached patch (http://people.freebsd.org/~mlaier/in.c.patch) derived f= rom=20 WIDE via OpenBSD in.c, rev 1.21 improves the handling of automatic prefix=20 routes. Right now you can't have two legs into the same network. If you want to, yo= u=20 must give on of the interfaces a host address only (netmask /32). This way = it=20 is not possible to hand over the route if one of the interfaces is=20 "removed" (however this is done in the special case). The patch allows to add more than on IPv4 address with the same prefix. In = the=20 case that there is a route already, we leave it alone and add the new addre= ss=20 without the IFA_ROUTE flag. When we remove an address later on, that has a= =20 route associated, we try to find an alternative address to use for the rout= e=20 and hand it over. This is required for CARP, but should be helpful for other situations as we= ll. Any objections? I also plan to merge this back to RELENG_5 after some time. I don't see thi= s=20 breaking assumptions (it was an error case before) - please tell me if you= =20 see something. =2D-=20 /"\ Best regards, | mlaier@freebsd.org \ / Max Laier | ICQ #67774661 X http://pf4freebsd.love2party.net/ | mlaier@EFnet / \ ASCII Ribbon Campaign | Against HTML Mail and News --Boundary-01=_np8kBd92qNtmEHy Content-Type: text/x-diff; charset="us-ascii"; name="in.c.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="in.c.patch" =2D-- ../dist/sys/netinet/in.c Sat Nov 6 21:01:08 2004 +++ sys/netinet/in.c Mon Nov 8 02:05:17 2004 @@ -1,4 +1,32 @@ /* + * Copyright (C) 2001 WIDE Project. All rights reserved. + *=20 + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + *=20 + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP= OSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENT= IAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STR= ICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY W= AY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* * Copyright (c) 1982, 1986, 1991, 1993 * The Regents of the University of California. All rights reserved. * @@ -55,6 +83,8 @@ static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t, struct ifnet *, struct thread *); =20 +static int in_addprefix(struct in_ifaddr *, int); +static int in_scrubprefix(struct in_ifaddr *); static void in_socktrim(struct sockaddr_in *); static int in_ifinit(struct ifnet *, struct in_ifaddr *, struct sockaddr_in *, int); @@ -654,14 +684,7 @@ register struct ifnet *ifp; register struct in_ifaddr *ia; { =2D =2D if ((ia->ia_flags & IFA_ROUTE) =3D=3D 0) =2D return; =2D if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) =2D rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); =2D else =2D rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); =2D ia->ia_flags &=3D ~IFA_ROUTE; + in_scrubprefix(ia); } =20 /* @@ -743,26 +766,7 @@ return (0); flags |=3D RTF_HOST; } =2D =2D /*- =2D * Don't add host routes for interface addresses of =2D * 0.0.0.0 --> 0.255.255.255 netmask 255.0.0.0. This makes it =2D * possible to assign several such address pairs with consistent =2D * results (no host route) and is required by BOOTP. =2D * =2D * XXX: This is ugly ! There should be a way for the caller to =2D * say that they don't want a host route. =2D */ =2D if (ia->ia_addr.sin_addr.s_addr !=3D INADDR_ANY || =2D ia->ia_netmask !=3D IN_CLASSA_NET || =2D ia->ia_dstaddr.sin_addr.s_addr !=3D htonl(IN_CLASSA_HOST)) { =2D if ((error =3D rtinit(&ia->ia_ifa, (int)RTM_ADD, flags)) !=3D 0) { =2D ia->ia_addr =3D oldaddr; =2D return (error); =2D } =2D ia->ia_flags |=3D IFA_ROUTE; =2D } =2D + error =3D in_addprefix(ia, flags); /* * If the interface supports multicast, join the "all hosts" * multicast group on that interface. @@ -776,6 +780,118 @@ return (error); } =20 +#define rtinitflags(x) \ + ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) !=3D 0) \ + ? RTF_HOST : 0) +/* + * add a route to prefix ("connected route" in cisco terminology). + * does nothing if there's some interface address with the same prefix alr= eady. + */ +static int +in_addprefix(target, flags) + struct in_ifaddr *target; + int flags; +{ + struct in_ifaddr *ia; + struct in_addr prefix, mask, p; + int error; + + if ((flags & RTF_HOST) !=3D 0) + prefix =3D target->ia_dstaddr.sin_addr; + else { + prefix =3D target->ia_addr.sin_addr; + mask =3D target->ia_sockmask.sin_addr; + prefix.s_addr &=3D mask.s_addr; + } + + TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { + if (rtinitflags(ia)) + p =3D ia->ia_dstaddr.sin_addr; + else { + p =3D ia->ia_addr.sin_addr; + p.s_addr &=3D ia->ia_sockmask.sin_addr.s_addr; + } + + if (prefix.s_addr !=3D p.s_addr) + continue; + + /* + * if we got a matching prefix route inserted by other + * interface adderss, we don't need to bother + */ + if (ia->ia_flags & IFA_ROUTE) + return 0; + } + + /* + * noone seem to have prefix route. insert it. + */ + error =3D rtinit(&target->ia_ifa, (int)RTM_ADD, flags); + if (!error) + target->ia_flags |=3D IFA_ROUTE; + return error; +} + +/* + * remove a route to prefix ("connected route" in cisco terminology). + * re-installs the route by using another interface address, if there's one + * with the same prefix (otherwise we lose the route mistakenly). + */ +static int +in_scrubprefix(target) + struct in_ifaddr *target; +{ + struct in_ifaddr *ia; + struct in_addr prefix, mask, p; + int error; + + if ((target->ia_flags & IFA_ROUTE) =3D=3D 0) + return 0; + + if (rtinitflags(target)) + prefix =3D target->ia_dstaddr.sin_addr; + else { + prefix =3D target->ia_addr.sin_addr; + mask =3D target->ia_sockmask.sin_addr; + prefix.s_addr &=3D mask.s_addr; + } + + TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { + if (rtinitflags(ia)) + p =3D ia->ia_dstaddr.sin_addr; + else { + p =3D ia->ia_addr.sin_addr; + p.s_addr &=3D ia->ia_sockmask.sin_addr.s_addr; + } + + if (prefix.s_addr !=3D p.s_addr) + continue; + + /* + * if we got a matching prefix route, move IFA_ROUTE to him + */ + if ((ia->ia_flags & IFA_ROUTE) =3D=3D 0) { + rtinit(&(target->ia_ifa), (int)RTM_DELETE, + rtinitflags(target)); + target->ia_flags &=3D ~IFA_ROUTE; + + error =3D rtinit(&ia->ia_ifa, (int)RTM_ADD, + rtinitflags(ia) | RTF_UP); + if (error =3D=3D 0) + ia->ia_flags |=3D IFA_ROUTE; + return error; + } + } + + /* + * noone seem to have prefix route. remove it. + */ + rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target)); + target->ia_flags &=3D ~IFA_ROUTE; + return 0; +} + +#undef rtinitflags =20 /* * Return 1 if the address might be a local broadcast address. --Boundary-01=_np8kBd92qNtmEHy-- --nextPart4509686.Ad4VYY4PBk Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.6 (FreeBSD) iD8DBQBBk8psXyyEoT62BG0RAmutAJ9z6WB3K1FYiXIDsa/gGY/QjISOYACggWA3 o3PCXKZ60jN3t6bk6VWdkXk= =DccO -----END PGP SIGNATURE----- --nextPart4509686.Ad4VYY4PBk--