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)