Use rtisivalid(9) to check if the given (cached) route can be used.
authormpi <mpi@openbsd.org>
Tue, 13 Oct 2015 10:16:17 +0000 (10:16 +0000)
committermpi <mpi@openbsd.org>
Tue, 13 Oct 2015 10:16:17 +0000 (10:16 +0000)
Note that after calling rtalloc(9) we only check if a route has been
returned or not and do not check for its validity.  This cannot be
improved without a massive refactoring.

The kernel currently *do* use !RTF_UP route due to a mismatch between
the value of ifp->if_link_state and the IFF_UP|IFF_RUNNING code.

I'd explain the RTF_UP flag as follow:

.  If a cached route entry w/o RTF_UP is passed to ip{6,}_output(),
.  call rtalloc(9) to see if a better entry is present in the tree.

This is enough to support MPATH and route cache invalidation.

ok bluhm@

sys/netinet/ip_output.c
sys/netinet6/in6_src.c

index 24ecc1b..11af574 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_output.c,v 1.300 2015/10/07 14:52:45 deraadt Exp $ */
+/*     $OpenBSD: ip_output.c,v 1.301 2015/10/13 10:16:17 mpi Exp $     */
 /*     $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $  */
 
 /*
@@ -170,9 +170,9 @@ reroute:
         * If there is a cached route, check that it is to the same
         * destination and is still up.  If not, free it and try again.
         */
-       if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+       if (!rtisvalid(ro->ro_rt) ||
            dst->sin_addr.s_addr != ip->ip_dst.s_addr ||
-           ro->ro_tableid != m->m_pkthdr.ph_rtableid)) {
+           ro->ro_tableid != m->m_pkthdr.ph_rtableid) {
                rtfree(ro->ro_rt);
                ro->ro_rt = NULL;
        }
index 8ab08e2..bbb916e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in6_src.c,v 1.62 2015/09/18 14:26:22 mpi Exp $        */
+/*     $OpenBSD: in6_src.c,v 1.63 2015/10/13 10:16:17 mpi Exp $        */
 /*     $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 itojun Exp $        */
 
 /*
@@ -252,13 +252,12 @@ in6_selectsrc(struct in6_addr **in6src, struct sockaddr_in6 *dstsock,
         * our src addr is taken from the i/f, else punt.
         */
        if (ro) {
-               if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
-                   !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst))) {
+               if (!rtisvalid(ro->ro_rt) ||
+                   !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) {
                        rtfree(ro->ro_rt);
                        ro->ro_rt = NULL;
                }
-               if (ro->ro_rt == (struct rtentry *)0 ||
-                   ro->ro_rt->rt_ifp == (struct ifnet *)0) {
+               if (ro->ro_rt == NULL) {
                        struct sockaddr_in6 *sa6;
 
                        /* No route yet, so try to acquire one */
@@ -368,10 +367,9 @@ in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
         * cached destination, in case of sharing the cache with IPv4.
         */
        if (ro) {
-               if (ro->ro_rt &&
-                   (!(ro->ro_rt->rt_flags & RTF_UP) ||
+               if (!rtisvalid(ro->ro_rt) ||
                     sin6tosa(&ro->ro_dst)->sa_family != AF_INET6 ||
-                    !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst))) {
+                    !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) {
                        rtfree(ro->ro_rt);
                        ro->ro_rt = NULL;
                }