Multiples routing entry issues, including my recent rtalloc(9) rewrite,
led me to believe that we need a simple way to check if a (cached) route
is still valid.  So let me introduce rtvalid(9):

     The rtvalid() function checks if the route entry rt is still valid and
     can be used.  Cached entries that are no longer valid should be released
     by calling rtfree().

Currently rtvalid(9) prevent you to use a !RTF_UP route or a entry
attached to a stall ifa.  In the short term I'd like to extend it
to include the validity of next hop in order to perform ARP or NDP
resolution for RTF_GATEWAY routes. 

I did not convert all the tree yet and some conversions might be more
tricky than I though.  So I'd like to commit the function first then
commit the conversion on a case-by-case basis.  So feel free to ok some
parts of it.

Index: share/man/man9/Makefile
===================================================================
RCS file: /cvs/src/share/man/man9/Makefile,v
retrieving revision 1.238
diff -u -p -r1.238 Makefile
--- share/man/man9/Makefile     14 Aug 2015 05:25:29 -0000      1.238
+++ share/man/man9/Makefile     28 Aug 2015 10:36:02 -0000
@@ -332,7 +332,7 @@ MLINKS+=rt_timer_add.9 rt_timer_queue_cr
        rt_timer_add.9 rt_timer_queue_change.9 \
        rt_timer_add.9 rt_timer_queue_destroy.9 \
        rt_timer_add.9 rt_timer_remove_all.9
-MLINKS+=rtalloc.9 rtalloc_mpath.9 rtalloc.9 rtfree.9
+MLINKS+=rtalloc.9 rtalloc_mpath.9 rtalloc.9 rtvalid.9 rtalloc.9 rtfree.9
 MLINKS+=rtable_add.9 rtable_exists.9 rtable_add.9 rtable_get.9 \
        rtable_add.9 rtable_l2.9 rtable_add.9 rtable_l2set.9
 MLINKS+=rtlabel_id2name.9 rtlabel_name2id.9 \
Index: share/man/man9/rtalloc.9
===================================================================
RCS file: /cvs/src/share/man/man9/rtalloc.9,v
retrieving revision 1.3
diff -u -p -r1.3 rtalloc.9
--- share/man/man9/rtalloc.9    5 Dec 2014 16:55:53 -0000       1.3
+++ share/man/man9/rtalloc.9    28 Aug 2015 10:36:18 -0000
@@ -1,6 +1,6 @@
 .\" $OpenBSD: rtalloc.9,v 1.3 2014/12/05 16:55:53 schwarze Exp $
 .\"
-.\" Copyright (c) 2014 Martin Pieuchot
+.\" Copyright (c) 2014-2015 Martin Pieuchot
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
@@ -20,6 +20,7 @@
 .Sh NAME
 .Nm rtalloc ,
 .Nm rtalloc_mpath ,
+.Nm rtvalid,
 .Nm rtfree
 .Nd routing entry interface
 .Sh SYNOPSIS
@@ -30,6 +31,8 @@
 .Fn rtalloc "struct sockaddr *dst" "int flags" "unsigned int rtableid"
 .Ft struct rtentry *
 .Fn rtalloc_mpath "struct sockaddr *dst" "uint32_t *src" "unsigned int 
rtableid"
+.Ft int
+.Fn rtvalid "struct rtentry *rt"
 .Ft void
 .Fn rtfree "struct rtentry *rt"
 .Sh DESCRIPTION
@@ -65,6 +68,14 @@ but selects a multipath routing entry co
 when possible.
 .Pp
 The
+.Fn rtvalid
+function checks if the route entry
+.Fa rt
+is still valid and can be used.
+Cached entries that are no longer valid should be released by calling
+.Fn rtfree .
+.Pp
+The
 .Fn rtfree
 function releases a reference to the routing entry
 .Fa rt ,
@@ -72,9 +83,13 @@ freeing it if the reference count drops 
 .Sh CONTEXT
 .Fn rtalloc ,
 .Fn rtalloc_mpath ,
+.Fn rtvalid ,
 and
 .Fn rtfree
 can be called during autoconf, from process context, or from interrupt context.
+.Sh RETURN VALUES
+.Fn rtvalid
+returns 1 if the route entry is valid, otherwise 0.
 .Sh SEE ALSO
 .Xr route 4 ,
 .Xr rtrequest1 9
Index: sys/net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.936
diff -u -p -r1.936 pf.c
--- sys/net/pf.c        19 Aug 2015 21:22:41 -0000      1.936
+++ sys/net/pf.c        28 Aug 2015 09:40:40 -0000
@@ -2949,11 +2949,11 @@ pf_calc_mss(struct pf_addr *addr, sa_fam
 #endif /* INET6 */
        }
 
-       if (rt && rt->rt_ifp) {
+       if (rtvalid(rt)) {
                mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr);
                mss = max(tcp_mssdflt, mss);
-               rtfree(rt);
        }
+       rtfree(rt);
        mss = min(mss, offer);
        mss = max(mss, 64);             /* sanity - at least max opt space */
        return (mss);
Index: sys/net/route.c
===================================================================
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.225
diff -u -p -r1.225 route.c
--- sys/net/route.c     24 Aug 2015 22:11:33 -0000      1.225
+++ sys/net/route.c     28 Aug 2015 10:16:43 -0000
@@ -297,6 +297,25 @@ rtable_exists(u_int id)    /* verify table 
        return (1);
 }
 
+/*
+ * Returns 1 if the cached ``rt'' entry is still valid, 0 otherwise.
+ */
+int
+rtvalid(struct rtentry *rt)
+{
+       if (rt == NULL)
+               return (0);
+
+       if ((rt->rt_flags & RTF_UP) == 0)
+               return (0);
+
+       /* Routes attached to stall ifas should be freed. */
+       if (rt->rt_ifa == NULL || rt->rt_ifa->ifa_ifp == NULL)
+               return (0);
+
+       return (1);
+}
+
 struct rtentry *
 rtalloc(struct sockaddr *dst, int flags, unsigned int tableid)
 {
@@ -656,19 +675,13 @@ ifa_ifwithroute(int flags, struct sockad
        }
        if (ifa == NULL) {
                struct rtentry  *rt = rtalloc(gateway, 0, rtableid);
-               if (rt == NULL)
-                       return (NULL);
                /* The gateway must be local if the same address family. */
-               if ((rt->rt_flags & RTF_GATEWAY) &&
-                   rt_key(rt)->sa_family == dst->sa_family) {
+               if (rtvalid(rt) == 0 || ((rt->rt_flags & RTF_GATEWAY) &&
+                   rt_key(rt)->sa_family == dst->sa_family)) {
                        rtfree(rt);
                        return (NULL);
                }
                ifa = rt->rt_ifa;
-               if (ifa == NULL || ifa->ifa_ifp == NULL) {
-                       rtfree(rt);
-                       return (NULL);
-               }
                rtfree(rt);
        }
        if (ifa->ifa_addr->sa_family != dst->sa_family) {
Index: sys/net/route.h
===================================================================
RCS file: /cvs/src/sys/net/route.h,v
retrieving revision 1.110
diff -u -p -r1.110 route.h
--- sys/net/route.h     20 Aug 2015 12:39:43 -0000      1.110
+++ sys/net/route.h     28 Aug 2015 10:15:48 -0000
@@ -377,6 +377,7 @@ void                         rt_timer_queue_destroy(struct 
rt
 unsigned long           rt_timer_queue_count(struct rttimer_queue *);
 void                    rt_timer_timer(void *);
 
+int     rtvalid(struct rtentry *);
 #ifdef SMALL_KERNEL
 #define         rtalloc_mpath(dst, s, rid) rtalloc((dst), 
RT_REPORT|RT_RESOLVE, (rid))
 #else
Index: sys/netinet/in_pcb.c
===================================================================
RCS file: /cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.174
diff -u -p -r1.174 in_pcb.c
--- sys/netinet/in_pcb.c        22 Aug 2015 20:18:50 -0000      1.174
+++ sys/netinet/in_pcb.c        28 Aug 2015 09:40:40 -0000
@@ -902,7 +902,7 @@ in_selectsrc(struct in_addr **insrc, str
         * If we found a route, use the address
         * corresponding to the outgoing interface.
         */
-       if (ro->ro_rt && ro->ro_rt->rt_ifp)
+       if (rtvalid(ro->ro_rt))
                ia = ifatoia(ro->ro_rt->rt_ifa);
 
        if (ia == NULL)
Index: sys/netinet/ip_icmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.137
diff -u -p -r1.137 ip_icmp.c
--- sys/netinet/ip_icmp.c       14 Aug 2015 18:07:28 -0000      1.137
+++ sys/netinet/ip_icmp.c       28 Aug 2015 09:40:40 -0000
@@ -719,11 +719,11 @@ icmp_reflect(struct mbuf *m, struct mbuf
                sin.sin_addr = ip->ip_dst;
 
                rt = rtalloc(sintosa(&sin), 0, rtableid);
-               if (rt != NULL) {
+               if (rtvalid(rt)) {
                        if (rt->rt_flags & (RTF_LOCAL|RTF_BROADCAST))
                                ia = ifatoia(rt->rt_ifa);
-                       rtfree(rt);
                }
+               rtfree(rt);
        }
 
        /*
@@ -739,9 +739,10 @@ icmp_reflect(struct mbuf *m, struct mbuf
 
                /* keep packet in the original virtual instance */
                rt = rtalloc(sintosa(&sin), RT_REPORT|RT_RESOLVE, rtableid);
-               if (rt == NULL) {
+               if (rtvalid(rt) == 0) {
                        ipstat.ips_noroute++;
                        m_freem(m);
+                       rtfree(rt);
                        return (EHOSTUNREACH);
                }
 
@@ -925,12 +926,7 @@ icmp_mtudisc_clone(struct in_addr dst, u
        sin.sin_addr = dst;
 
        rt = rtalloc(sintosa(&sin), RT_REPORT|RT_RESOLVE, rtableid);
-       if (rt == NULL)
-               return (NULL);
-
-       /* Check if the route is actually usable */
-       if (rt->rt_flags & (RTF_REJECT | RTF_BLACKHOLE) ||
-           (rt->rt_flags & RTF_UP) == 0) {
+       if (rtvalid(rt) == 0 || (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE))) {
                rtfree(rt);
                return (NULL);
        }
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.253
diff -u -p -r1.253 ip_input.c
--- sys/netinet/ip_input.c      19 Aug 2015 15:30:25 -0000      1.253
+++ sys/netinet/ip_input.c      28 Aug 2015 09:40:40 -0000
@@ -668,13 +668,9 @@ in_ouraddr(struct mbuf *m, struct ifnet 
        sin.sin_family = AF_INET;
        sin.sin_addr = ina;
        rt = rtalloc(sintosa(&sin), 0, m->m_pkthdr.ph_rtableid);
-       if (rt != NULL) {
-               /* only use non-stale local address, check before route free */
-               if ((rt->rt_flags & (RTF_LOCAL|RTF_BROADCAST)) &&
-                   rt->rt_ifa != NULL && rt->rt_ifa->ifa_ifp != NULL)
-                       ia = ifatoia(rt->rt_ifa);
-               rtfree(rt);
-       }
+       if (rtvalid(rt) && (rt->rt_flags & (RTF_LOCAL|RTF_BROADCAST)))
+               ia = ifatoia(rt->rt_ifa);
+       rtfree(rt);
 
        if (ia == NULL) {
                struct ifaddr *ifa;
@@ -948,10 +944,8 @@ ip_slowtimo(void)
                        ip_freef(fp);
                }
        }
-       if (ipforward_rt.ro_rt) {
-               rtfree(ipforward_rt.ro_rt);
-               ipforward_rt.ro_rt = NULL;
-       }
+       rtfree(ipforward_rt.ro_rt);
+       ipforward_rt.ro_rt = NULL;
        splx(s);
 }
 
@@ -1227,11 +1221,11 @@ ip_rtaddr(struct in_addr dst, u_int rtab
 
        sin = satosin(&ipforward_rt.ro_dst);
 
-       if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
-               if (ipforward_rt.ro_rt) {
-                       rtfree(ipforward_rt.ro_rt);
-                       ipforward_rt.ro_rt = NULL;
-               }
+       if (rtvalid(ipforward_rt.ro_rt) == 0 ||
+           dst.s_addr != sin->sin_addr.s_addr) {
+               rtfree(ipforward_rt.ro_rt);
+               ipforward_rt.ro_rt = NULL;
+
                sin->sin_family = AF_INET;
                sin->sin_len = sizeof(*sin);
                sin->sin_addr = dst;
@@ -1239,8 +1233,10 @@ ip_rtaddr(struct in_addr dst, u_int rtab
                ipforward_rt.ro_rt = rtalloc(&ipforward_rt.ro_dst,
                    RT_REPORT|RT_RESOLVE, rtableid);
        }
-       if (ipforward_rt.ro_rt == 0)
+       if (rtvalid(ipforward_rt.ro_rt) == 0) {
+               rtfree(ipforward_rt.ro_rt);
                return (NULL);
+       }
        return (ifatoia(ipforward_rt.ro_rt->rt_ifa));
 }
 
@@ -1403,13 +1399,12 @@ ip_forward(struct mbuf *m, struct ifnet 
        rtableid = m->m_pkthdr.ph_rtableid;
 
        sin = satosin(&ipforward_rt.ro_dst);
-       if ((rt = ipforward_rt.ro_rt) == NULL ||
+       if (rtvalid(ipforward_rt.ro_rt) == 0 ||
            ip->ip_dst.s_addr != sin->sin_addr.s_addr ||
            rtableid != ipforward_rt.ro_tableid) {
-               if (ipforward_rt.ro_rt) {
-                       rtfree(ipforward_rt.ro_rt);
-                       ipforward_rt.ro_rt = NULL;
-               }
+               rtfree(ipforward_rt.ro_rt);
+               ipforward_rt.ro_rt = NULL;
+
                sin->sin_family = AF_INET;
                sin->sin_len = sizeof(*sin);
                sin->sin_addr = ip->ip_dst;
@@ -1417,12 +1412,13 @@ ip_forward(struct mbuf *m, struct ifnet 
 
                ipforward_rt.ro_rt = rtalloc_mpath(&ipforward_rt.ro_dst,
                    &ip->ip_src.s_addr, ipforward_rt.ro_tableid);
-               if (ipforward_rt.ro_rt == 0) {
+               if (rtvalid(ipforward_rt.ro_rt) == 0) {
+                       rtfree(ipforward_rt.ro_rt);
                        icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
                        return;
                }
-               rt = ipforward_rt.ro_rt;
        }
+       rt = ipforward_rt.ro_rt;
 
        /*
         * Save at most 68 bytes of the packet in case
Index: sys/netinet/ip_ipip.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipip.c,v
retrieving revision 1.65
diff -u -p -r1.65 ip_ipip.c
--- sys/netinet/ip_ipip.c       24 Aug 2015 22:04:06 -0000      1.65
+++ sys/netinet/ip_ipip.c       28 Aug 2015 09:40:40 -0000
@@ -315,7 +315,7 @@ ipip_input(struct mbuf *m, int iphlen, s
                }
                rt = rtalloc((struct sockaddr *)&ss, 0,
                    m->m_pkthdr.ph_rtableid);
-               if ((rt != NULL) && (rt->rt_flags & RTF_LOCAL)) {
+               if (rtvalid(rt) && (rt->rt_flags & RTF_LOCAL)) {
                        ipipstat.ipips_spoof++;
                        m_freem(m);
                        rtfree(rt);
Index: sys/netinet/ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.286
diff -u -p -r1.286 ip_output.c
--- sys/netinet/ip_output.c     16 Jul 2015 21:14:21 -0000      1.286
+++ sys/netinet/ip_output.c     28 Aug 2015 09:40:40 -0000
@@ -168,10 +168,11 @@ ip_output(struct mbuf *m0, struct mbuf *
                dst = satosin(&ro->ro_dst);
 
                /*
-                * 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 there is a cached route, check that it is to the
+                * same destination and is still valid.  If not, free
+                * it and try again.
                 */
-               if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+               if ((rtvalid(ro->ro_rt) == 0 ||
                    dst->sin_addr.s_addr != ip->ip_dst.s_addr ||
                    ro->ro_tableid != m->m_pkthdr.ph_rtableid)) {
                        rtfree(ro->ro_rt);
@@ -195,7 +196,8 @@ ip_output(struct mbuf *m0, struct mbuf *
                                ro->ro_rt = rtalloc_mpath(&ro->ro_dst,
                                    NULL, ro->ro_tableid);
 
-                       if (ro->ro_rt == NULL) {
+                       if (rtvalid(ro->ro_rt) == 0) {
+                               rtfree(ro->ro_rt);
                                ipstat.ips_noroute++;
                                error = EHOSTUNREACH;
                                goto bad;
@@ -296,10 +298,11 @@ reroute:
                dst = satosin(&ro->ro_dst);
 
                /*
-                * 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 there is a cached route, check that it is to the
+                * same destination and is still valid.  If not, free
+                * it and try again.
                 */
-               if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+               if ((rtvalid(ro->ro_rt) == 0 ||
                    dst->sin_addr.s_addr != ip->ip_dst.s_addr ||
                    ro->ro_tableid != m->m_pkthdr.ph_rtableid)) {
                        rtfree(ro->ro_rt);
@@ -323,7 +326,8 @@ reroute:
                                ro->ro_rt = rtalloc_mpath(&ro->ro_dst,
                                    &ip->ip_src.s_addr, ro->ro_tableid);
 
-                       if (ro->ro_rt == NULL) {
+                       if (rtvalid(ro->ro_rt) == 0) {
+                               rtfree(ro->ro_rt);
                                ipstat.ips_noroute++;
                                error = EHOSTUNREACH;
                                goto bad;
@@ -1495,8 +1499,9 @@ ip_setmoptions(int optname, struct ip_mo
                        sin.sin_addr = mreq->imr_multiaddr;
                        rt = rtalloc(sintosa(&sin), RT_REPORT|RT_RESOLVE,
                            rtableid);
-                       if (rt == NULL) {
+                       if (rtvalid(rt) == 0) {
                                error = EADDRNOTAVAIL;
+                               rtfree(rt);
                                break;
                        }
                        ifp = rt->rt_ifp;
Index: sys/netinet6/frag6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/frag6.c,v
retrieving revision 1.61
diff -u -p -r1.61 frag6.c
--- sys/netinet6/frag6.c        8 Jul 2015 07:31:14 -0000       1.61
+++ sys/netinet6/frag6.c        28 Aug 2015 09:40:40 -0000
@@ -183,13 +183,9 @@ frag6_input(struct mbuf **mp, int *offp,
 
        rt = rtalloc_mpath(sin6tosa(&dst), &ip6->ip6_src.s6_addr32[0],
            m->m_pkthdr.ph_rtableid);
-
-       if (rt != NULL) {
-               if (rt->rt_ifa != NULL)
-                       dstifp = ifatoia6(rt->rt_ifa)->ia_ifp;
-               rtfree(rt);
-               rt = NULL;
-       }
+       if (rtvalid(rt))
+               dstifp = ifatoia6(rt->rt_ifa)->ia_ifp;
+       rtfree(rt);
 
        /* jumbo payload can't contain a fragment header */
        if (ip6->ip6_plen == 0) {
Index: sys/netinet6/in6_src.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6_src.c,v
retrieving revision 1.51
diff -u -p -r1.51 in6_src.c
--- sys/netinet6/in6_src.c      8 Jun 2015 22:19:28 -0000       1.51
+++ sys/netinet6/in6_src.c      28 Aug 2015 10:09:13 -0000
@@ -370,15 +370,13 @@ selectroute(struct sockaddr_in6 *dstsock
                 * by that address must be a neighbor of the sending host.
                 */
                ron = &opts->ip6po_nextroute;
-               if ((ron->ro_rt &&
-                   (ron->ro_rt->rt_flags & (RTF_UP | RTF_GATEWAY)) !=
-                   RTF_UP) ||
+               if ((rtvalid(ron->ro_rt) &&
+                   (ron->ro_rt->rt_flags & RTF_GATEWAY) == 0) ||
                    !IN6_ARE_ADDR_EQUAL(&ron->ro_dst.sin6_addr,
                    &sin6_next->sin6_addr)) {
-                       if (ron->ro_rt) {
-                               rtfree(ron->ro_rt);
-                               ron->ro_rt = NULL;
-                       }
+                       rtfree(ron->ro_rt);
+                       ron->ro_rt = NULL;
+
                        ron->ro_dst = *sin6_next;
                        ron->ro_tableid = rtableid;
                }
@@ -386,12 +384,10 @@ selectroute(struct sockaddr_in6 *dstsock
                        /* multi path case? */
                        ron->ro_rt = rtalloc(sin6tosa(&ron->ro_dst),
                            RT_REPORT|RT_RESOLVE, ron->ro_tableid);
-                       if (ron->ro_rt == NULL ||
+                       if (rtvalid(ron->ro_rt) == 0 ||
                            (ron->ro_rt->rt_flags & RTF_GATEWAY)) {
-                               if (ron->ro_rt) {
-                                       rtfree(ron->ro_rt);
-                                       ron->ro_rt = NULL;
-                               }
+                               rtfree(ron->ro_rt);
+                               ron->ro_rt = NULL;
                                error = EHOSTUNREACH;
                                goto done;
                        }
@@ -419,10 +415,9 @@ selectroute(struct sockaddr_in6 *dstsock
         * cached destination, in case of sharing the cache with IPv4.
         */
        if (ro) {
-               if (ro->ro_rt &&
-                   (!(ro->ro_rt->rt_flags & RTF_UP) ||
+               if (rtvalid(ro->ro_rt) == 0 ||
                     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;
                }
@@ -447,17 +442,11 @@ selectroute(struct sockaddr_in6 *dstsock
                if (opts && opts->ip6po_nexthop)
                        goto done;
 
-               if (ro->ro_rt) {
-                       ifp = ro->ro_rt->rt_ifp;
-
-                       if (ifp == NULL) { /* can this really happen? */
-                               rtfree(ro->ro_rt);
-                               ro->ro_rt = NULL;
-                       }
-               }
-               if (ro->ro_rt == NULL)
+               if (rtvalid(ro->ro_rt)) {
+                       rt = ro->ro_rt;
+                       ifp = rt->rt_ifp;
+               } else
                        error = EHOSTUNREACH;
-               rt = ro->ro_rt;
 
                /*
                 * Check if the outgoing interface conflicts with
@@ -468,7 +457,7 @@ selectroute(struct sockaddr_in6 *dstsock
                 */
                if (opts && opts->ip6po_pktinfo &&
                    opts->ip6po_pktinfo->ipi6_ifindex) {
-                       if (!(ifp->if_flags & IFF_LOOPBACK) &&
+                       if (ifp != NULL && !(ifp->if_flags & IFF_LOOPBACK) &&
                            ifp->if_index !=
                            opts->ip6po_pktinfo->ipi6_ifindex) {
                                error = EHOSTUNREACH;
Index: sys/netinet6/ip6_forward.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_forward.c,v
retrieving revision 1.79
diff -u -p -r1.79 ip6_forward.c
--- sys/netinet6/ip6_forward.c  16 Jul 2015 21:14:21 -0000      1.79
+++ sys/netinet6/ip6_forward.c  28 Aug 2015 09:40:40 -0000
@@ -225,13 +225,11 @@ reroute:
                /*
                 * ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst
                 */
-               if (ip6_forward_rt.ro_rt == NULL ||
-                   (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0 ||
+               if (rtvalid(ip6_forward_rt.ro_rt) == 0 ||
                    ip6_forward_rt.ro_tableid != rtableid) {
-                       if (ip6_forward_rt.ro_rt) {
-                               rtfree(ip6_forward_rt.ro_rt);
-                               ip6_forward_rt.ro_rt = NULL;
-                       }
+                       rtfree(ip6_forward_rt.ro_rt);
+                       ip6_forward_rt.ro_rt = NULL;
+
                        /* this probably fails but give it a try again */
                        ip6_forward_rt.ro_tableid = rtableid;
                        ip6_forward_rt.ro_rt = rtalloc_mpath(
@@ -240,24 +238,23 @@ reroute:
                            ip6_forward_rt.ro_tableid);
                }
 
-               if (ip6_forward_rt.ro_rt == NULL) {
+               if (rtvalid(ip6_forward_rt.ro_rt) == 0) {
                        ip6stat.ip6s_noroute++;
                        /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
                        if (mcopy) {
                                icmp6_error(mcopy, ICMP6_DST_UNREACH,
                                            ICMP6_DST_UNREACH_NOROUTE, 0);
                        }
+                       rtfree(rt);
                        m_freem(m);
                        return;
                }
-       } else if (ip6_forward_rt.ro_rt == NULL ||
-          (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0 ||
+       } else if (rtvalid(ip6_forward_rt.ro_rt) == 0 ||
           !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr) ||
           ip6_forward_rt.ro_tableid != rtableid) {
-               if (ip6_forward_rt.ro_rt) {
-                       rtfree(ip6_forward_rt.ro_rt);
-                       ip6_forward_rt.ro_rt = NULL;
-               }
+               rtfree(ip6_forward_rt.ro_rt);
+               ip6_forward_rt.ro_rt = NULL;
+
                bzero(dst, sizeof(*dst));
                dst->sin6_len = sizeof(struct sockaddr_in6);
                dst->sin6_family = AF_INET6;
@@ -268,13 +265,14 @@ reroute:
                    &ip6->ip6_src.s6_addr32[0],
                    ip6_forward_rt.ro_tableid);
 
-               if (ip6_forward_rt.ro_rt == NULL) {
+               if (rtvalid(ip6_forward_rt.ro_rt) == 0) {
                        ip6stat.ip6s_noroute++;
                        /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
                        if (mcopy) {
                                icmp6_error(mcopy, ICMP6_DST_UNREACH,
                                            ICMP6_DST_UNREACH_NOROUTE, 0);
                        }
+                       rtfree(rt);
                        m_freem(m);
                        return;
                }
Index: sys/netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.144
diff -u -p -r1.144 ip6_input.c
--- sys/netinet6/ip6_input.c    16 Jul 2015 21:14:21 -0000      1.144
+++ sys/netinet6/ip6_input.c    28 Aug 2015 09:40:40 -0000
@@ -429,10 +429,9 @@ ip6_input(struct mbuf *m)
        /*
         *  Unicast check
         */
-       if (ip6_forward_rt.ro_rt != NULL &&
-           (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
+       if (rtvalid(ip6_forward_rt.ro_rt) &&
            IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
-                              &ip6_forward_rt.ro_dst.sin6_addr) &&
+                                      &ip6_forward_rt.ro_dst.sin6_addr) &&
            rtableid == ip6_forward_rt.ro_tableid)
                ip6stat.ip6s_forward_cachehit++;
        else {
@@ -459,7 +458,7 @@ ip6_input(struct mbuf *m)
         * Accept the packet if the route to the destination is marked
         * as local.
         */
-       if (ip6_forward_rt.ro_rt &&
+       if (rtvalid(ip6_forward_rt.ro_rt) &&
            ISSET(ip6_forward_rt.ro_rt->rt_flags, RTF_LOCAL)) {
                struct in6_ifaddr *ia6 =
                        ifatoia6(ip6_forward_rt.ro_rt->rt_ifa);
Index: sys/netinet6/ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.177
diff -u -p -r1.177 ip6_output.c
--- sys/netinet6/ip6_output.c   16 Jul 2015 21:14:21 -0000      1.177
+++ sys/netinet6/ip6_output.c   28 Aug 2015 09:59:27 -0000
@@ -1174,9 +1174,8 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, s
                /* The first hop and the final destination may differ. */
                struct sockaddr_in6 *sa6_dst = &ro_pmtu->ro_dst;
 
-               if (ro_pmtu->ro_rt &&
-                   ((ro_pmtu->ro_rt->rt_flags & RTF_UP) == 0 ||
-                    !IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))) {
+               if (rtvalid(ro_pmtu->ro_rt) == 0 ||
+                   !IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst)) {
                        rtfree(ro_pmtu->ro_rt);
                        ro_pmtu->ro_rt = NULL;
                }
@@ -2401,8 +2400,9 @@ ip6_setmoptions(int optname, struct ip6_
                        dst->sin6_addr = mreq->ipv6mr_multiaddr;
                        ro.ro_rt = rtalloc(sin6tosa(&ro.ro_dst),
                            RT_REPORT|RT_RESOLVE, ro.ro_tableid);
-                       if (ro.ro_rt == NULL) {
+                       if (rtvalid(ro.ro_rt) == 0) {
                                error = EADDRNOTAVAIL;
+                               rtfree(ro.ro_rt);
                                break;
                        }
                        ifp = ro.ro_rt->rt_ifp;
Index: sys/netinet6/nd6_nbr.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6_nbr.c,v
retrieving revision 1.92
diff -u -p -r1.92 nd6_nbr.c
--- sys/netinet6/nd6_nbr.c      24 Aug 2015 15:58:35 -0000      1.92
+++ sys/netinet6/nd6_nbr.c      28 Aug 2015 09:40:40 -0000
@@ -232,7 +232,7 @@ nd6_ns_input(struct mbuf *m, int off, in
                tsin6.sin6_addr = taddr6;
 
                rt = rtalloc(sin6tosa(&tsin6), 0, m->m_pkthdr.ph_rtableid);
-               if (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
+               if (rtvalid(rt) && (rt->rt_flags & RTF_ANNOUNCE) &&
                    rt->rt_gateway->sa_family == AF_LINK) {
                        /*
                         * proxy NDP for single entry
@@ -245,8 +245,7 @@ nd6_ns_input(struct mbuf *m, int off, in
                                router = 0;     /* XXX */
                        }
                }
-               if (rt)
-                       rtfree(rt);
+               rtfree(rt);
        }
        if (!ifa) {
                /*

Reply via email to