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)