Make sure returning ifp from in6_select* functions psref-ed
To this end, callers need to pass struct psref to the functions and the fuctions acquire a reference of ifp with it. In some cases, we can simply use if_get_byindex, however, in other cases (say rt->rt_ifp and ia->ifa_ifp), we have no MP-safe way for now. In order to take a reference anyway we use non MP-safe function if_acquire_NOMPSAFE for the latter cases. They should be fixed in the future somehow.
This commit is contained in:
parent
f7107c248e
commit
4badfc204a
14
sys/net/if.c
14
sys/net/if.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if.c,v 1.343 2016/06/20 08:30:58 knakahara Exp $ */
|
||||
/* $NetBSD: if.c,v 1.344 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
|
||||
@ -90,7 +90,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.343 2016/06/20 08:30:58 knakahara Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.344 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_inet.h"
|
||||
@ -2193,6 +2193,9 @@ void
|
||||
if_put(const struct ifnet *ifp, struct psref *psref)
|
||||
{
|
||||
|
||||
if (ifp == NULL)
|
||||
return;
|
||||
|
||||
psref_release(psref, &ifp->if_psref, ifnet_psref_class);
|
||||
}
|
||||
|
||||
@ -2223,14 +2226,15 @@ if_get_byindex(u_int idx, struct psref *psref)
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX unsafe
|
||||
* XXX it's safe only if the passed ifp is guaranteed to not be freed,
|
||||
* for example the ifp is already held or some other object is held which
|
||||
* guarantes the ifp to not be freed indirectly.
|
||||
*/
|
||||
void
|
||||
if_acquire_unsafe(struct ifnet *ifp, struct psref *psref)
|
||||
if_acquire_NOMPSAFE(struct ifnet *ifp, struct psref *psref)
|
||||
{
|
||||
|
||||
KASSERT(ifp->if_index != 0);
|
||||
KASSERT(if_byindex(ifp->if_index) != NULL);
|
||||
psref_acquire(psref, &ifp->if_psref, ifnet_psref_class);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: if.h,v 1.213 2016/06/21 03:28:27 ozaki-r Exp $ */
|
||||
/* $NetBSD: if.h,v 1.214 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
|
||||
@ -952,7 +952,7 @@ struct ifnet *if_get(const char *, struct psref *);
|
||||
ifnet_t *if_byindex(u_int);
|
||||
ifnet_t *if_get_byindex(u_int, struct psref *);
|
||||
void if_put(const struct ifnet *, struct psref *);
|
||||
void if_acquire_unsafe(struct ifnet *, struct psref *);
|
||||
void if_acquire_NOMPSAFE(struct ifnet *, struct psref *);
|
||||
|
||||
static inline if_index_t
|
||||
if_get_index(const struct ifnet *ifp)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: icmp6.c,v 1.188 2016/06/10 13:31:44 ozaki-r Exp $ */
|
||||
/* $NetBSD: icmp6.c,v 1.189 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.188 2016/06/10 13:31:44 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.189 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
@ -2091,7 +2091,7 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
||||
sockaddr_in6_init(&sin6, &ip6->ip6_dst, 0, 0, 0);
|
||||
|
||||
memset(&ro, 0, sizeof(ro));
|
||||
src = in6_selectsrc(&sin6, NULL, NULL, &ro, NULL, NULL, &e);
|
||||
src = in6_selectsrc(&sin6, NULL, NULL, &ro, NULL, NULL, NULL, &e);
|
||||
rtcache_free(&ro);
|
||||
if (src == NULL) {
|
||||
nd6log(LOG_DEBUG,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6_pcb.c,v 1.144 2016/06/21 03:28:27 ozaki-r Exp $ */
|
||||
/* $NetBSD: in6_pcb.c,v 1.145 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.144 2016/06/21 03:28:27 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.145 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
@ -438,6 +438,8 @@ in6_pcbconnect(void *v, struct sockaddr_in6 *sin6, struct lwp *l)
|
||||
#endif
|
||||
struct sockaddr_in6 tmp;
|
||||
struct vestigial_inpcb vestige;
|
||||
struct psref psref;
|
||||
int bound;
|
||||
|
||||
(void)&in6a; /* XXX fool gcc */
|
||||
|
||||
@ -478,6 +480,7 @@ in6_pcbconnect(void *v, struct sockaddr_in6 *sin6, struct lwp *l)
|
||||
tmp = *sin6;
|
||||
sin6 = &tmp;
|
||||
|
||||
bound = curlwp_bind();
|
||||
/* Source address selection. */
|
||||
if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr) &&
|
||||
in6p->in6p_laddr.s6_addr32[3] == 0) {
|
||||
@ -512,23 +515,29 @@ in6_pcbconnect(void *v, struct sockaddr_in6 *sin6, struct lwp *l)
|
||||
in6a = in6_selectsrc(sin6, in6p->in6p_outputopts,
|
||||
in6p->in6p_moptions,
|
||||
&in6p->in6p_route,
|
||||
&in6p->in6p_laddr, &ifp, &error);
|
||||
&in6p->in6p_laddr, &ifp, &psref, &error);
|
||||
if (ifp && scope_ambiguous &&
|
||||
(error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) {
|
||||
if_put(ifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return(error);
|
||||
}
|
||||
|
||||
if (in6a == NULL) {
|
||||
if_put(ifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
if (error == 0)
|
||||
error = EADDRNOTAVAIL;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifp != NULL)
|
||||
if (ifp != NULL) {
|
||||
in6p->in6p_ip6.ip6_hlim = (u_int8_t)in6_selecthlim(in6p, ifp);
|
||||
else
|
||||
if_put(ifp, &psref);
|
||||
} else
|
||||
in6p->in6p_ip6.ip6_hlim = (u_int8_t)in6_selecthlim_rt(in6p);
|
||||
curlwp_bindx(bound);
|
||||
|
||||
if (in6_pcblookup_connect(in6p->in6p_table, &sin6->sin6_addr,
|
||||
sin6->sin6_port,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6_src.c,v 1.61 2016/06/21 03:28:27 ozaki-r Exp $ */
|
||||
/* $NetBSD: in6_src.c,v 1.62 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $KAME: in6_src.c,v 1.159 2005/10/19 01:40:32 t-momose Exp $ */
|
||||
|
||||
/*
|
||||
@ -66,7 +66,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.61 2016/06/21 03:28:27 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.62 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
@ -123,10 +123,10 @@ struct in6_addrpolicy defaultaddrpolicy;
|
||||
int ip6_prefer_tempaddr = 0;
|
||||
|
||||
static int selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
|
||||
struct ip6_moptions *, struct route *, struct ifnet **,
|
||||
struct ip6_moptions *, struct route *, struct ifnet **, struct psref *,
|
||||
struct rtentry **, int, int);
|
||||
static int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *,
|
||||
struct ip6_moptions *, struct route *, struct ifnet **);
|
||||
struct ip6_moptions *, struct route *, struct ifnet **, struct psref *);
|
||||
|
||||
static struct in6_addrpolicy *lookup_addrsel_policy(struct sockaddr_in6 *);
|
||||
|
||||
@ -174,7 +174,7 @@ static struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *);
|
||||
struct in6_addr *
|
||||
in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
struct ip6_moptions *mopts, struct route *ro, struct in6_addr *laddr,
|
||||
struct ifnet **ifpp, int *errorp)
|
||||
struct ifnet **ifpp, struct psref *psref, int *errorp)
|
||||
{
|
||||
struct in6_addr dst;
|
||||
struct ifnet *ifp = NULL;
|
||||
@ -188,6 +188,13 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
#if defined(MIP6) && NMIP > 0
|
||||
u_int8_t ip6po_usecoa = 0;
|
||||
#endif /* MIP6 && NMIP > 0 */
|
||||
struct psref local_psref;
|
||||
struct in6_addr *ret_ia = NULL;
|
||||
int bound = curlwp_bind();
|
||||
#define PSREF (psref == NULL) ? &local_psref : psref
|
||||
|
||||
KASSERT((ifpp != NULL && psref != NULL) ||
|
||||
(ifpp == NULL && psref == NULL));
|
||||
|
||||
dst = dstsock->sin6_addr; /* make a copy for local operation */
|
||||
*errorp = 0;
|
||||
@ -201,8 +208,8 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
* to this function (e.g., for identifying the appropriate scope zone
|
||||
* ID).
|
||||
*/
|
||||
error = in6_selectif(dstsock, opts, mopts, ro, &ifp);
|
||||
if (ifpp)
|
||||
error = in6_selectif(dstsock, opts, mopts, ro, &ifp, PSREF);
|
||||
if (ifpp != NULL)
|
||||
*ifpp = ifp;
|
||||
|
||||
/*
|
||||
@ -230,19 +237,20 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
if (ifp) {
|
||||
*errorp = in6_setscope(&srcsock.sin6_addr, ifp, NULL);
|
||||
if (*errorp != 0)
|
||||
return (NULL);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ia6 = (struct in6_ifaddr *)ifa_ifwithaddr((struct sockaddr *)(&srcsock));
|
||||
if (ia6 == NULL ||
|
||||
(ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
|
||||
*errorp = EADDRNOTAVAIL;
|
||||
return (NULL);
|
||||
goto exit;
|
||||
}
|
||||
pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */
|
||||
if (ifpp)
|
||||
*ifpp = ifp;
|
||||
return (&ia6->ia_addr.sin6_addr);
|
||||
ret_ia = &ia6->ia_addr.sin6_addr;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -250,8 +258,10 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
* care at the moment whether in6_selectif() succeeded above, even
|
||||
* though it would eventually cause an error.
|
||||
*/
|
||||
if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
|
||||
return (laddr);
|
||||
if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr)) {
|
||||
ret_ia = laddr;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* The outgoing interface is crucial in the general selection procedure
|
||||
@ -259,7 +269,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
*/
|
||||
if (ifp == NULL) {
|
||||
*errorp = error;
|
||||
return (NULL);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -281,7 +291,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
|
||||
*errorp = in6_setscope(&dst, ifp, &odstzone);
|
||||
if (*errorp != 0)
|
||||
return (NULL);
|
||||
goto exit;
|
||||
|
||||
for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
|
||||
int new_scope = -1, new_matchlen = -1;
|
||||
@ -544,10 +554,16 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
|
||||
if ((ia = ia_best) == NULL) {
|
||||
*errorp = EADDRNOTAVAIL;
|
||||
return (NULL);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return (&ia->ia_addr.sin6_addr);
|
||||
ret_ia = &ia->ia_addr.sin6_addr;
|
||||
exit:
|
||||
if (ifpp == NULL)
|
||||
if_put(ifp, PSREF);
|
||||
curlwp_bindx(bound);
|
||||
return ret_ia;
|
||||
#undef PSREF
|
||||
}
|
||||
#undef REPLACE
|
||||
#undef BREAK
|
||||
@ -556,7 +572,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
static int
|
||||
selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp,
|
||||
struct rtentry **retrt, int clone, int norouteok)
|
||||
struct psref *psref, struct rtentry **retrt, int clone, int norouteok)
|
||||
{
|
||||
int error = 0;
|
||||
struct ifnet *ifp = NULL;
|
||||
@ -564,6 +580,11 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
struct sockaddr_in6 *sin6_next;
|
||||
struct in6_pktinfo *pi = NULL;
|
||||
struct in6_addr *dst;
|
||||
struct psref local_psref;
|
||||
#define PSREF ((psref == NULL) ? &local_psref : psref)
|
||||
|
||||
KASSERT((retifp != NULL && psref != NULL) ||
|
||||
(retifp == NULL && psref == NULL));
|
||||
|
||||
dst = &dstsock->sin6_addr;
|
||||
|
||||
@ -583,7 +604,7 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
/* If the caller specify the outgoing interface explicitly, use it. */
|
||||
if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) {
|
||||
/* XXX boundary check is assumed to be already done. */
|
||||
ifp = if_byindex(pi->ipi6_ifindex);
|
||||
ifp = if_get_byindex(pi->ipi6_ifindex, PSREF);
|
||||
if (ifp != NULL &&
|
||||
(norouteok || retrt == NULL ||
|
||||
IN6_IS_ADDR_MULTICAST(dst))) {
|
||||
@ -592,8 +613,11 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
* multicast.
|
||||
*/
|
||||
goto done;
|
||||
} else
|
||||
} else {
|
||||
if_put(ifp, PSREF);
|
||||
ifp = NULL;
|
||||
goto getroute;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -601,8 +625,7 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
* interface for the address is specified by the caller, use it.
|
||||
*/
|
||||
if (IN6_IS_ADDR_MULTICAST(dst) && mopts != NULL) {
|
||||
/* XXX not MP-safe yet */
|
||||
ifp = if_byindex(mopts->im6o_multicast_if_index);
|
||||
ifp = if_get_byindex(mopts->im6o_multicast_if_index, PSREF);
|
||||
if (ifp != NULL)
|
||||
goto done; /* we do not need a route for multicast. */
|
||||
}
|
||||
@ -636,6 +659,8 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
goto done;
|
||||
}
|
||||
ifp = rt->rt_ifp;
|
||||
if (ifp != NULL)
|
||||
if_acquire_NOMPSAFE(ifp, PSREF);
|
||||
|
||||
/*
|
||||
* When cloning is required, try to allocate a route to the
|
||||
@ -671,8 +696,12 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
|
||||
if (rt == NULL)
|
||||
error = EHOSTUNREACH;
|
||||
else
|
||||
else {
|
||||
if_put(ifp, PSREF);
|
||||
ifp = rt->rt_ifp;
|
||||
if (ifp != NULL)
|
||||
if_acquire_NOMPSAFE(ifp, PSREF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the outgoing interface conflicts with
|
||||
@ -705,21 +734,28 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
|
||||
if (retifp != NULL)
|
||||
*retifp = ifp;
|
||||
else
|
||||
if_put(ifp, PSREF);
|
||||
if (retrt != NULL)
|
||||
*retrt = rt; /* rt may be NULL */
|
||||
|
||||
return (error);
|
||||
#undef PSREF
|
||||
}
|
||||
|
||||
static int
|
||||
in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp)
|
||||
struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp,
|
||||
struct psref *psref)
|
||||
{
|
||||
int error, clone;
|
||||
struct rtentry *rt = NULL;
|
||||
|
||||
KASSERT(retifp != NULL);
|
||||
*retifp = NULL;
|
||||
|
||||
clone = IN6_IS_ADDR_MULTICAST(&dstsock->sin6_addr) ? 0 : 1;
|
||||
if ((error = selectroute(dstsock, opts, mopts, ro, retifp,
|
||||
if ((error = selectroute(dstsock, opts, mopts, ro, retifp, psref,
|
||||
&rt, clone, 1)) != 0) {
|
||||
return (error);
|
||||
}
|
||||
@ -751,8 +787,12 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
* destination address (which should probably be one of our own
|
||||
* addresses.)
|
||||
*/
|
||||
if (rt && rt->rt_ifa && rt->rt_ifa->ifa_ifp)
|
||||
if (rt && rt->rt_ifa && rt->rt_ifa->ifa_ifp &&
|
||||
rt->rt_ifa->ifa_ifp != *retifp) {
|
||||
if_put(*retifp, psref);
|
||||
*retifp = rt->rt_ifa->ifa_ifp;
|
||||
if_acquire_NOMPSAFE(*retifp, psref);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -764,9 +804,9 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
int
|
||||
in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
||||
struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp,
|
||||
struct rtentry **retrt, int clone)
|
||||
struct psref *psref, struct rtentry **retrt, int clone)
|
||||
{
|
||||
return selectroute(dstsock, opts, mopts, ro, retifp,
|
||||
return selectroute(dstsock, opts, mopts, ro, retifp, psref,
|
||||
retrt, clone, 0);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ip6_output.c,v 1.169 2016/06/21 10:21:04 ozaki-r Exp $ */
|
||||
/* $NetBSD: ip6_output.c,v 1.170 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.169 2016/06/21 10:21:04 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.170 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
@ -163,7 +163,7 @@ ip6_output(
|
||||
)
|
||||
{
|
||||
struct ip6_hdr *ip6, *mhip6;
|
||||
struct ifnet *ifp, *origifp;
|
||||
struct ifnet *ifp, *origifp = NULL;
|
||||
struct mbuf *m = m0;
|
||||
int hlen, tlen, len, off;
|
||||
bool tso;
|
||||
@ -185,6 +185,9 @@ ip6_output(
|
||||
#ifdef IPSEC
|
||||
struct secpolicy *sp = NULL;
|
||||
#endif
|
||||
struct psref psref, psref_ia;
|
||||
int bound = curlwp_bind();
|
||||
bool release_psref_ia = false;
|
||||
|
||||
memset(&ip6route, 0, sizeof(ip6route));
|
||||
|
||||
@ -488,8 +491,9 @@ ip6_output(
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
|
||||
sockaddr_in6_init(&dst_sa, &ip6->ip6_dst, 0, 0, 0);
|
||||
ifp = NULL;
|
||||
if ((error = in6_selectroute(&dst_sa, opt, im6o, ro,
|
||||
&ifp, &rt, 0)) != 0) {
|
||||
&ifp, &psref, &rt, 0)) != 0) {
|
||||
if (ifp != NULL)
|
||||
in6_ifstat_inc(ifp, ifs6_out_discard);
|
||||
goto bad;
|
||||
@ -522,9 +526,11 @@ ip6_output(
|
||||
* destination addresses. We should use ia_ifp to support the
|
||||
* case of sending packets to an address of our own.
|
||||
*/
|
||||
if (ia != NULL && ia->ia_ifp)
|
||||
if (ia != NULL && ia->ia_ifp) {
|
||||
origifp = ia->ia_ifp;
|
||||
else
|
||||
if_acquire_NOMPSAFE(origifp, &psref_ia);
|
||||
release_psref_ia = true;
|
||||
} else
|
||||
origifp = ifp;
|
||||
|
||||
src0 = ip6->ip6_src;
|
||||
@ -976,6 +982,10 @@ done:
|
||||
KEY_FREESP(&sp);
|
||||
#endif /* IPSEC */
|
||||
|
||||
if_put(ifp, &psref);
|
||||
if (release_psref_ia)
|
||||
if_put(origifp, &psref_ia);
|
||||
curlwp_bindx(bound);
|
||||
|
||||
return (error);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ip6_var.h,v 1.66 2016/06/21 03:28:27 ozaki-r Exp $ */
|
||||
/* $NetBSD: ip6_var.h,v 1.67 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -397,10 +397,10 @@ struct route;
|
||||
|
||||
struct in6_addr *in6_selectsrc(struct sockaddr_in6 *,
|
||||
struct ip6_pktopts *, struct ip6_moptions *, struct route *,
|
||||
struct in6_addr *, struct ifnet **, int *);
|
||||
struct in6_addr *, struct ifnet **, struct psref *, int *);
|
||||
int in6_selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
|
||||
struct ip6_moptions *, struct route *, struct ifnet **,
|
||||
struct rtentry **, int);
|
||||
struct psref *, struct rtentry **, int);
|
||||
int ip6_get_membership(const struct sockopt *, struct ifnet **, void *,
|
||||
size_t);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nd6_nbr.c,v 1.120 2016/06/21 03:28:27 ozaki-r Exp $ */
|
||||
/* $NetBSD: nd6_nbr.c,v 1.121 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.120 2016/06/21 03:28:27 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.121 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
@ -454,7 +454,7 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
|
||||
sockaddr_in6_init(&dst_sa, &ip6->ip6_dst, 0, 0, 0);
|
||||
|
||||
src = in6_selectsrc(&dst_sa, NULL,
|
||||
NULL, &ro, NULL, NULL, &error);
|
||||
NULL, &ro, NULL, NULL, NULL, &error);
|
||||
if (src == NULL) {
|
||||
nd6log(LOG_DEBUG, "source can't be "
|
||||
"determined: dst=%s, error=%d\n",
|
||||
@ -944,7 +944,7 @@ nd6_na_output(
|
||||
/*
|
||||
* Select a source whose scope is the same as that of the dest.
|
||||
*/
|
||||
src = in6_selectsrc(satosin6(dst), NULL, NULL, &ro, NULL, NULL, &error);
|
||||
src = in6_selectsrc(satosin6(dst), NULL, NULL, &ro, NULL, NULL, NULL, &error);
|
||||
if (src == NULL) {
|
||||
nd6log(LOG_DEBUG, "source can't be "
|
||||
"determined: dst=%s, error=%d\n",
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: raw_ip6.c,v 1.145 2016/06/16 02:38:40 ozaki-r Exp $ */
|
||||
/* $NetBSD: raw_ip6.c,v 1.146 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.145 2016/06/16 02:38:40 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.146 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ipsec.h"
|
||||
@ -388,6 +388,7 @@ rip6_output(struct mbuf *m, struct socket * const so,
|
||||
int scope_ambiguous = 0;
|
||||
struct in6_addr *in6a;
|
||||
int bound = curlwp_bind();
|
||||
struct psref psref;
|
||||
|
||||
in6p = sotoin6pcb(so);
|
||||
|
||||
@ -448,7 +449,7 @@ rip6_output(struct mbuf *m, struct socket * const so,
|
||||
* Source address selection.
|
||||
*/
|
||||
if ((in6a = in6_selectsrc(dstsock, optp, in6p->in6p_moptions,
|
||||
&in6p->in6p_route, &in6p->in6p_laddr, &oifp, &error)) == 0) {
|
||||
&in6p->in6p_route, &in6p->in6p_laddr, &oifp, &psref, &error)) == 0) {
|
||||
if (error == 0)
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
@ -478,6 +479,9 @@ rip6_output(struct mbuf *m, struct socket * const so,
|
||||
ip6->ip6_nxt = in6p->in6p_ip6.ip6_nxt;
|
||||
ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
|
||||
|
||||
if_put(oifp, &psref);
|
||||
oifp = NULL;
|
||||
|
||||
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
|
||||
in6p->in6p_cksum != -1) {
|
||||
int off;
|
||||
@ -534,6 +538,7 @@ rip6_output(struct mbuf *m, struct socket * const so,
|
||||
ip6_clearpktopts(&opt, -1);
|
||||
m_freem(control);
|
||||
}
|
||||
if_put(oifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
}
|
||||
@ -715,6 +720,8 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
|
||||
struct ifnet *ifp = NULL;
|
||||
int scope_ambiguous = 0;
|
||||
int error = 0;
|
||||
struct psref psref;
|
||||
int bound;
|
||||
|
||||
KASSERT(solocked(so));
|
||||
KASSERT(in6p != NULL);
|
||||
@ -738,10 +745,11 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
|
||||
if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
|
||||
return error;
|
||||
|
||||
bound = curlwp_bind();
|
||||
/* Source address selection. XXX: need pcblookup? */
|
||||
in6a = in6_selectsrc(addr, in6p->in6p_outputopts,
|
||||
in6p->in6p_moptions, &in6p->in6p_route,
|
||||
&in6p->in6p_laddr, &ifp, &error);
|
||||
&in6p->in6p_laddr, &ifp, &psref, &error);
|
||||
if (in6a == NULL) {
|
||||
if (error == 0)
|
||||
error = EADDRNOTAVAIL;
|
||||
@ -756,6 +764,8 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
|
||||
in6p->in6p_faddr = addr->sin6_addr;
|
||||
soisconnected(so);
|
||||
out:
|
||||
if_put(ifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: udp6_output.c,v 1.51 2016/06/10 13:31:44 ozaki-r Exp $ */
|
||||
/* $NetBSD: udp6_output.c,v 1.52 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.51 2016/06/10 13:31:44 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.52 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
@ -226,14 +226,19 @@ udp6_output(struct in6pcb * const in6p, struct mbuf *m,
|
||||
}
|
||||
|
||||
if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
|
||||
struct psref psref;
|
||||
|
||||
laddr = in6_selectsrc(sin6, optp,
|
||||
in6p->in6p_moptions,
|
||||
&in6p->in6p_route,
|
||||
&in6p->in6p_laddr, &oifp, &error);
|
||||
&in6p->in6p_laddr, &oifp, &psref, &error);
|
||||
if (oifp && scope_ambiguous &&
|
||||
(error = in6_setscope(&sin6->sin6_addr,
|
||||
oifp, NULL)))
|
||||
oifp, NULL))) {
|
||||
if_put(oifp, &psref);
|
||||
goto release;
|
||||
}
|
||||
if_put(oifp, &psref);
|
||||
} else {
|
||||
/*
|
||||
* XXX: freebsd[34] does not have in_selectsrc, but
|
||||
|
Loading…
Reference in New Issue
Block a user