This does two things.  Prevent a NULL dereference in ip6_getpmtu() that
was introduced during the rdomain support addition.

Make use of if_get() instead of rt_ifp.

ok?

Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.199
diff -u -p -r1.199 ip6_output.c
--- netinet6/ip6_output.c       11 Nov 2015 10:23:23 -0000      1.199
+++ netinet6/ip6_output.c       19 Nov 2015 12:23:38 -0000
@@ -128,8 +128,8 @@ int ip6_insertfraghdr(struct mbuf *, str
        struct ip6_frag **);
 int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t);
 int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
-int ip6_getpmtu(struct route_in6 *, struct route_in6 *,
-       struct ifnet *, struct in6_addr *, u_long *, int *);
+int ip6_getpmtu(struct route_in6 *, struct route_in6 *, struct ifnet *,
+    unsigned int, struct in6_addr *, u_long *, int *);
 int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
 static __inline u_int16_t __attribute__((__unused__))
     in6_cksum_phdr(const struct in6_addr *, const struct in6_addr *,
@@ -646,8 +646,8 @@ reroute:
        }
 
        /* Determine path MTU. */
-       if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu,
-           &alwaysfrag)) != 0)
+       if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, ro->ro_tableid, &finaldst,
+           &mtu, &alwaysfrag)) != 0)
                goto bad;
 
        /*
@@ -1111,8 +1111,8 @@ ip6_insertfraghdr(struct mbuf *m0, struc
 }
 
 int
-ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
-    struct ifnet *ifp, struct in6_addr *dst, u_long *mtup, int *alwaysfragp)
+ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro, struct ifnet 
*ifp0,
+    unsigned int rtableid, struct in6_addr *dst, u_long *mtup, int 
*alwaysfragp)
 {
        u_int32_t mtu = 0;
        int alwaysfrag = 0;
@@ -1123,14 +1123,14 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, s
                struct sockaddr_in6 *sa6_dst = &ro_pmtu->ro_dst;
 
                if (!rtisvalid(ro_pmtu->ro_rt) ||
-                   (ro_pmtu->ro_tableid != ifp->if_rdomain) ||
+                   (ro_pmtu->ro_tableid != rtableid) ||
                     !IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst)) {
                        rtfree(ro_pmtu->ro_rt);
                        ro_pmtu->ro_rt = NULL;
                }
                if (ro_pmtu->ro_rt == NULL) {
                        bzero(ro_pmtu, sizeof(*ro_pmtu));
-                       ro_pmtu->ro_tableid = ifp->if_rdomain;
+                       ro_pmtu->ro_tableid = rtableid;
                        sa6_dst->sin6_family = AF_INET6;
                        sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
                        sa6_dst->sin6_addr = *dst;
@@ -1140,8 +1140,13 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, s
                }
        }
        if (ro_pmtu->ro_rt) {
-               if (ifp == NULL)
-                       ifp = ro_pmtu->ro_rt->rt_ifp;
+               struct ifnet *ifp;
+
+               if (ifp0 == NULL)
+                       ifp = if_get(ro_pmtu->ro_rt->rt_ifidx);
+               else
+                       ifp = ifp0;
+
                mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
                if (mtu == 0)
                        mtu = ifp->if_mtu;
@@ -1169,8 +1174,11 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, s
                        if (!(ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU))
                                ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu;
                }
-       } else if (ifp) {
-               mtu = ifp->if_mtu;
+
+               if (ifp0 == NULL)
+                       if_put(ifp);
+       } else if (ifp0) {
+               mtu = ifp0->if_mtu;
        } else
                error = EHOSTUNREACH; /* XXX */
 
@@ -1623,7 +1631,8 @@ do { \
                                 * the outgoing interface.
                                 */
                                error = ip6_getpmtu(ro, NULL, NULL,
-                                   &inp->inp_faddr6, &pmtu, NULL);
+                                   inp->inp_rtableid, &inp->inp_faddr6, &pmtu,
+                                   NULL);
                                if (error)
                                        break;
                                if (pmtu > IPV6_MAXPACKET)

Reply via email to