summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-11-29 15:12:37 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-11-29 15:12:37 +0000
commit9547a57ed80dbdd0da6df9e5add41a9e95df518c (patch)
tree1e592361fda19523b92c22db2293b89d3da7c876 /sys
parent5dbceb517258f5cf48b4c23bc8350c2f0e47daec (diff)
Use if_get() rather than dereferencing rt_ifp in ip6_getpmtu().
While here fix a NULL dereference introduced by the support for multiple rdomains. It seems that this code path is never run... With input from David Hill, ok florian@
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet6/ip6_output.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index c14909eb0fa..5c1ff3b9ec6 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_output.c,v 1.199 2015/11/11 10:23:23 mpi Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.200 2015/11/29 15:12:36 mpi Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@@ -128,8 +128,8 @@ int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int,
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, struct mbuf *m, int hlen,
}
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, struct route_in6 *ro,
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,15 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
}
}
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);
+ if (ifp == NULL)
+ return (EHOSTUNREACH);
+ } else
+ ifp = ifp0;
+
mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
if (mtu == 0)
mtu = ifp->if_mtu;
@@ -1169,8 +1176,11 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
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 +1633,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)