From: mpi Date: Mon, 5 May 2014 11:44:33 +0000 (+0000) Subject: Use a custom ifa_rtrequest function for point-to-point interfaces X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=7da1c79582926d7bf5db9de050dc83d671827eff;p=openbsd Use a custom ifa_rtrequest function for point-to-point interfaces instead of relying on hacks in nd6_rtrequest() to add a route to loopback for each address configured on such interfaces. While here document that abusing lo0 for local traffic is not safe for interfaces in a non-default rdomain. Tested by claudio@, jca@ and sthen@, ok sthen@ --- diff --git a/sys/net/if.c b/sys/net/if.c index 5f35a6d5a37..95709aec76a 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.286 2014/04/22 12:35:00 mpi Exp $ */ +/* $OpenBSD: if.c,v 1.287 2014/05/05 11:44:33 mpi Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -989,6 +989,71 @@ link_rtrequest(int cmd, struct rtentry *rt) } } +/* + * Default action when installing a local route on a point-to-point + * interface. + */ +void +p2p_rtrequest(int req, struct rtentry *rt) +{ + struct ifnet *ifp = rt->rt_ifp; + struct ifaddr *ifa, *lo0ifa; + + switch (req) { + case RTM_ADD: + /* + * XXX Here we abuse RTF_LLINFO to add a route to + * loopback. We do that to always have a route + * pointing to our address. + */ + if ((rt->rt_flags & RTF_LLINFO) == 0) + break; + + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (memcmp(rt_key(rt), ifa->ifa_addr, + rt_key(rt)->sa_len) == 0) + break; + } + + if (ifa == NULL) + break; + + /* + * XXX Since lo0 is in the default rdomain we should not + * (ab)use it for any route related to an interface of a + * different rdomain. + */ + TAILQ_FOREACH(lo0ifa, &lo0ifp->if_addrlist, ifa_list) + if (lo0ifa->ifa_addr->sa_family == + ifa->ifa_addr->sa_family) + break; + + if (lo0ifa == NULL) + break; + + rt_setgate(rt, rt_key(rt), lo0ifa->ifa_addr, ifp->if_rdomain); + rt->rt_ifp = lo0ifp; + rt->rt_flags &= ~RTF_LLINFO; + + /* + * make sure to set rt->rt_ifa to the interface + * address we are using, otherwise we will have trouble + * with source address selection. + */ + if (ifa != rt->rt_ifa) { + ifafree(rt->rt_ifa); + ifa->ifa_refcnt++; + rt->rt_ifa = ifa; + } + break; + case RTM_DELETE: + case RTM_RESOLVE: + default: + break; + } +} + + /* * Bring down all interfaces */ diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index ec0ba137193..264e83c6325 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_gif.c,v 1.66 2014/04/21 12:22:25 henning Exp $ */ +/* $OpenBSD: if_gif.c,v 1.67 2014/05/05 11:44:33 mpi Exp $ */ /* $KAME: if_gif.c,v 1.43 2001/02/20 08:51:07 itojun Exp $ */ /* @@ -354,7 +354,8 @@ int gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct gif_softc *sc = (struct gif_softc*)ifp; - struct ifreq *ifr = (struct ifreq*)data; + struct ifreq *ifr = (struct ifreq *)data; + struct ifaddr *ifa = (struct ifaddr *)data; int error = 0, size; struct sockaddr *dst, *src; struct sockaddr *sa; @@ -363,6 +364,7 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch (cmd) { case SIOCSIFADDR: + ifa->ifa_rtrequest = p2p_rtrequest; break; case SIOCSIFDSTADDR: diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index e42391092e9..3e58bc1ef08 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_gre.c,v 1.67 2014/04/21 12:22:25 henning Exp $ */ +/* $OpenBSD: if_gre.c,v 1.68 2014/05/05 11:44:33 mpi Exp $ */ /* $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -441,7 +441,8 @@ int gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { - struct ifreq *ifr = (struct ifreq *) data; + struct ifreq *ifr = (struct ifreq *)data; + struct ifaddr *ifa = (struct ifaddr *)data; struct if_laddrreq *lifr = (struct if_laddrreq *)data; struct ifkalivereq *ikar = (struct ifkalivereq *)data; struct gre_softc *sc = ifp->if_softc; @@ -455,6 +456,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch(cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; + ifa->ifa_rtrequest = p2p_rtrequest; break; case SIOCSIFDSTADDR: break; diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c index ab1dad08965..5cb44e75ac4 100644 --- a/sys/net/if_ppp.c +++ b/sys/net/if_ppp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ppp.c,v 1.73 2014/04/19 12:08:10 henning Exp $ */ +/* $OpenBSD: if_ppp.c,v 1.74 2014/05/05 11:44:33 mpi Exp $ */ /* $NetBSD: if_ppp.c,v 1.39 1997/05/17 21:11:59 christos Exp $ */ /* @@ -619,6 +619,7 @@ pppsioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCSIFADDR: if (ifa->ifa_addr->sa_family != AF_INET) error = EAFNOSUPPORT; + ifa->ifa_rtrequest = p2p_rtrequest; break; case SIOCSIFDSTADDR: diff --git a/sys/net/if_pppx.c b/sys/net/if_pppx.c index 37a971504ef..66b2a836043 100644 --- a/sys/net/if_pppx.c +++ b/sys/net/if_pppx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pppx.c,v 1.29 2014/04/08 04:26:53 miod Exp $ */ +/* $OpenBSD: if_pppx.c,v 1.30 2014/05/05 11:44:33 mpi Exp $ */ /* * Copyright (c) 2010 Claudio Jeker @@ -1094,10 +1094,14 @@ pppx_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) { struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc; struct ifreq *ifr = (struct ifreq *)addr; + struct ifaddr *ifa = (struct ifaddr *)addr; int error = 0; switch (cmd) { case SIOCSIFADDR: + ifa->ifa_rtrequest = p2p_rtrequest; + break; + case SIOCSIFFLAGS: break; diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c index d3b5f0ee462..afbced7c8c7 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_spppsubr.c,v 1.122 2014/05/02 10:40:26 jca Exp $ */ +/* $OpenBSD: if_spppsubr.c,v 1.123 2014/05/05 11:44:33 mpi Exp $ */ /* * Synchronous PPP/Cisco link level subroutines. * Keepalive protocol implemented in both Cisco and PPP modes. @@ -996,7 +996,8 @@ sppp_pick(struct ifnet *ifp) int sppp_ioctl(struct ifnet *ifp, u_long cmd, void *data) { - struct ifreq *ifr = (struct ifreq*) data; + struct ifreq *ifr = data; + struct ifaddr *ifa = data; struct sppp *sp = (struct sppp*) ifp; int s, rv, going_up, going_down, newmode; @@ -1009,6 +1010,7 @@ sppp_ioctl(struct ifnet *ifp, u_long cmd, void *data) case SIOCSIFADDR: if_up(ifp); + ifa->ifa_rtrequest = p2p_rtrequest; /* FALLTHROUGH */ case SIOCSIFFLAGS: diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 3e9a6500972..7d705463df4 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tun.c,v 1.124 2014/04/22 14:41:03 mpi Exp $ */ +/* $OpenBSD: if_tun.c,v 1.125 2014/05/05 11:44:33 mpi Exp $ */ /* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */ /* @@ -469,6 +469,7 @@ tun_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct tun_softc *tp = (struct tun_softc *)(ifp->if_softc); struct ifreq *ifr = (struct ifreq *)data; + struct ifaddr *ifa = (struct ifaddr *)data; int error = 0, s; s = splnet(); @@ -477,16 +478,19 @@ tun_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCSIFADDR: tuninit(tp); TUNDEBUG(("%s: address set\n", ifp->if_xname)); - if (tp->tun_flags & TUN_LAYER2) - switch (((struct ifaddr *)data)->ifa_addr->sa_family) { + if (tp->tun_flags & TUN_LAYER2) { + switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: - arp_ifinit(&tp->arpcom, (struct ifaddr *)data); + arp_ifinit(&tp->arpcom, ifa); break; #endif default: break; } + } else { + ifa->ifa_rtrequest = p2p_rtrequest; + } break; case SIOCSIFDSTADDR: tuninit(tp); diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 34061ae5862..0277f9d0234 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_var.h,v 1.9 2014/04/23 09:30:57 mpi Exp $ */ +/* $OpenBSD: if_var.h,v 1.10 2014/05/05 11:44:33 mpi Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -428,6 +428,7 @@ struct ifaddr *ifa_ifwithnet(struct sockaddr *, u_int); struct ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *); void ifafree(struct ifaddr *); void link_rtrequest(int, struct rtentry *); +void p2p_rtrequest(int, struct rtentry *); void if_clone_attach(struct if_clone *); void if_clone_detach(struct if_clone *); diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 4286eaee5a9..2e8c294dd9d 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ether.c,v 1.125 2014/04/14 09:06:42 mpi Exp $ */ +/* $OpenBSD: if_ether.c,v 1.126 2014/05/05 11:44:33 mpi Exp $ */ /* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */ /* @@ -254,6 +254,12 @@ arp_rtrequest(int req, struct rtentry *rt) SDL(gate)->sdl_alen = ETHER_ADDR_LEN; memcpy(LLADDR(SDL(gate)), ((struct arpcom *)ifp)->ac_enaddr, ETHER_ADDR_LEN); + + /* + * XXX Since lo0 is in the default rdomain we + * should not (ab)use it for any route related + * to an interface of a different rdomain. + */ if (useloopback) rt->rt_ifp = lo0ifp; /* diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 4dcdf1d2f84..300abd63c3c 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6.c,v 1.135 2014/04/10 13:47:21 mpi Exp $ */ +/* $OpenBSD: in6.c,v 1.136 2014/05/05 11:44:33 mpi Exp $ */ /* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */ /* @@ -1369,7 +1369,8 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia6, int newhost) ifacount++; } - if ((ifacount <= 1 || ifp->if_type == IFT_CARP) && ifp->if_ioctl && + if ((ifacount <= 1 || ifp->if_type == IFT_CARP || + (ifp->if_flags & IFF_POINTOPOINT)) && ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia6))) { splx(s); return (error); @@ -1398,7 +1399,9 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia6, int newhost) /* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */ if (newhost) { /* set the rtrequest function to create llinfo */ - ia6->ia_ifa.ifa_rtrequest = nd6_rtrequest; + if ((ifp->if_flags & IFF_POINTOPOINT) == 0) + ia6->ia_ifa.ifa_rtrequest = nd6_rtrequest; + rt_ifa_addloop(&(ia6->ia_ifa)); } diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 70faed0b066..71a1aec6222 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.c,v 1.114 2014/04/14 09:06:42 mpi Exp $ */ +/* $OpenBSD: nd6.c,v 1.115 2014/05/05 11:44:33 mpi Exp $ */ /* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */ /* @@ -1157,8 +1157,14 @@ nd6_rtrequest(int req, struct rtentry *rt) memcpy(LLADDR(SDL(gate)), macp, ifp->if_addrlen); SDL(gate)->sdl_alen = ifp->if_addrlen; } + + /* + * XXX Since lo0 is in the default rdomain we + * should not (ab)use it for any route related + * to an interface of a different rdomain. + */ if (nd6_useloopback) { - rt->rt_ifp = lo0ifp; /*XXX*/ + rt->rt_ifp = lo0ifp; /* * Make sure rt_ifa be equal to the ifaddr * corresponding to the address.