let gif(4) promise softint(9) contract (2/2) : ip_encap side
The last commit does not care encaptab. This commit fixes encaptab race which is used not only gif(4).
This commit is contained in:
parent
d81cd78ed7
commit
b71542e5bc
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_gif.c,v 1.114 2016/07/04 04:14:47 knakahara Exp $ */
|
/* $NetBSD: if_gif.c,v 1.115 2016/07/04 04:17:25 knakahara Exp $ */
|
||||||
/* $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $ */
|
/* $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.114 2016/07/04 04:14:47 knakahara Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.115 2016/07/04 04:17:25 knakahara Exp $");
|
||||||
|
|
||||||
#ifdef _KERNEL_OPT
|
#ifdef _KERNEL_OPT
|
||||||
#include "opt_inet.h"
|
#include "opt_inet.h"
|
||||||
|
@ -110,9 +110,6 @@ static int gif_encap_attach(struct gif_softc *);
|
||||||
static int gif_encap_detach(struct gif_softc *);
|
static int gif_encap_detach(struct gif_softc *);
|
||||||
static void gif_encap_pause(struct gif_softc *);
|
static void gif_encap_pause(struct gif_softc *);
|
||||||
|
|
||||||
static void gif_list_lock_enter(void);
|
|
||||||
static void gif_list_lock_exit(void);
|
|
||||||
|
|
||||||
static struct if_clone gif_cloner =
|
static struct if_clone gif_cloner =
|
||||||
IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
|
IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy);
|
||||||
|
|
||||||
|
@ -812,7 +809,7 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
s = splsoftnet();
|
s = splsoftnet();
|
||||||
gif_list_lock_enter();
|
encap_lock_enter();
|
||||||
|
|
||||||
LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
|
LIST_FOREACH(sc2, &gif_softc_list, gif_list) {
|
||||||
if (sc2 == sc)
|
if (sc2 == sc)
|
||||||
|
@ -823,7 +820,7 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
|
||||||
if (sockaddr_cmp(sc2->gif_pdst, dst) == 0 &&
|
if (sockaddr_cmp(sc2->gif_pdst, dst) == 0 &&
|
||||||
sockaddr_cmp(sc2->gif_psrc, src) == 0) {
|
sockaddr_cmp(sc2->gif_psrc, src) == 0) {
|
||||||
/* continue to use the old configureation. */
|
/* continue to use the old configureation. */
|
||||||
gif_list_lock_exit();
|
encap_lock_exit();
|
||||||
splx(s);
|
splx(s);
|
||||||
return EADDRNOTAVAIL;
|
return EADDRNOTAVAIL;
|
||||||
}
|
}
|
||||||
|
@ -832,13 +829,13 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((nsrc = sockaddr_dup(src, M_WAITOK)) == NULL) {
|
if ((nsrc = sockaddr_dup(src, M_WAITOK)) == NULL) {
|
||||||
gif_list_lock_exit();
|
encap_lock_exit();
|
||||||
splx(s);
|
splx(s);
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
if ((ndst = sockaddr_dup(dst, M_WAITOK)) == NULL) {
|
if ((ndst = sockaddr_dup(dst, M_WAITOK)) == NULL) {
|
||||||
sockaddr_free(nsrc);
|
sockaddr_free(nsrc);
|
||||||
gif_list_lock_exit();
|
encap_lock_exit();
|
||||||
splx(s);
|
splx(s);
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -889,7 +886,7 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
|
||||||
else
|
else
|
||||||
ifp->if_flags &= ~IFF_RUNNING;
|
ifp->if_flags &= ~IFF_RUNNING;
|
||||||
|
|
||||||
gif_list_lock_exit();
|
encap_lock_exit();
|
||||||
splx(s);
|
splx(s);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -901,7 +898,7 @@ gif_delete_tunnel(struct ifnet *ifp)
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
s = splsoftnet();
|
s = splsoftnet();
|
||||||
gif_list_lock_enter();
|
encap_lock_enter();
|
||||||
|
|
||||||
gif_encap_pause(sc);
|
gif_encap_pause(sc);
|
||||||
if (sc->gif_psrc) {
|
if (sc->gif_psrc) {
|
||||||
|
@ -925,26 +922,6 @@ gif_delete_tunnel(struct ifnet *ifp)
|
||||||
else
|
else
|
||||||
ifp->if_flags &= ~IFF_RUNNING;
|
ifp->if_flags &= ~IFF_RUNNING;
|
||||||
|
|
||||||
gif_list_lock_exit();
|
encap_lock_exit();
|
||||||
splx(s);
|
splx(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gif_list_lock_enter(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* XXX future work
|
|
||||||
* should change interruptable lock.
|
|
||||||
*/
|
|
||||||
KERNEL_LOCK(1, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gif_list_lock_exit(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* XXX future work
|
|
||||||
* should change interruptable lock.
|
|
||||||
*/
|
|
||||||
KERNEL_UNLOCK_ONE(NULL);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_stf.c,v 1.91 2016/06/22 07:48:17 ozaki-r Exp $ */
|
/* $NetBSD: if_stf.c,v 1.92 2016/07/04 04:17:25 knakahara Exp $ */
|
||||||
/* $KAME: if_stf.c,v 1.62 2001/06/07 22:32:16 itojun Exp $ */
|
/* $KAME: if_stf.c,v 1.62 2001/06/07 22:32:16 itojun Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.91 2016/06/22 07:48:17 ozaki-r Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.92 2016/07/04 04:17:25 knakahara Exp $");
|
||||||
|
|
||||||
#ifdef _KERNEL_OPT
|
#ifdef _KERNEL_OPT
|
||||||
#include "opt_inet.h"
|
#include "opt_inet.h"
|
||||||
|
@ -191,17 +191,20 @@ stf_clone_create(struct if_clone *ifc, int unit)
|
||||||
{
|
{
|
||||||
struct stf_softc *sc;
|
struct stf_softc *sc;
|
||||||
|
|
||||||
|
sc = malloc(sizeof(struct stf_softc), M_DEVBUF, M_WAIT|M_ZERO);
|
||||||
|
if_initname(&sc->sc_if, ifc->ifc_name, unit);
|
||||||
|
|
||||||
|
encap_lock_enter();
|
||||||
if (LIST_FIRST(&stf_softc_list) != NULL) {
|
if (LIST_FIRST(&stf_softc_list) != NULL) {
|
||||||
/* Only one stf interface is allowed. */
|
/* Only one stf interface is allowed. */
|
||||||
|
encap_lock_exit();
|
||||||
|
free(sc, M_DEVBUF);
|
||||||
return (EEXIST);
|
return (EEXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = malloc(sizeof(struct stf_softc), M_DEVBUF, M_WAIT|M_ZERO);
|
|
||||||
|
|
||||||
if_initname(&sc->sc_if, ifc->ifc_name, unit);
|
|
||||||
|
|
||||||
sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6,
|
sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6,
|
||||||
stf_encapcheck, &in_stf_encapsw, sc);
|
stf_encapcheck, &in_stf_encapsw, sc);
|
||||||
|
encap_lock_exit();
|
||||||
if (sc->encap_cookie == NULL) {
|
if (sc->encap_cookie == NULL) {
|
||||||
printf("%s: unable to attach encap\n", if_name(&sc->sc_if));
|
printf("%s: unable to attach encap\n", if_name(&sc->sc_if));
|
||||||
free(sc, M_DEVBUF);
|
free(sc, M_DEVBUF);
|
||||||
|
@ -226,8 +229,10 @@ stf_clone_destroy(struct ifnet *ifp)
|
||||||
{
|
{
|
||||||
struct stf_softc *sc = (void *) ifp;
|
struct stf_softc *sc = (void *) ifp;
|
||||||
|
|
||||||
|
encap_lock_enter();
|
||||||
LIST_REMOVE(sc, sc_list);
|
LIST_REMOVE(sc, sc_list);
|
||||||
encap_detach(sc->encap_cookie);
|
encap_detach(sc->encap_cookie);
|
||||||
|
encap_lock_exit();
|
||||||
bpf_detach(ifp);
|
bpf_detach(ifp);
|
||||||
if_detach(ifp);
|
if_detach(ifp);
|
||||||
rtcache_free(&sc->sc_ro);
|
rtcache_free(&sc->sc_ro);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: ip_encap.c,v 1.53 2016/04/26 08:44:44 ozaki-r Exp $ */
|
/* $NetBSD: ip_encap.c,v 1.54 2016/07/04 04:17:25 knakahara Exp $ */
|
||||||
/* $KAME: ip_encap.c,v 1.73 2001/10/02 08:30:58 itojun Exp $ */
|
/* $KAME: ip_encap.c,v 1.73 2001/10/02 08:30:58 itojun Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.53 2016/04/26 08:44:44 ozaki-r Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.54 2016/07/04 04:17:25 knakahara Exp $");
|
||||||
|
|
||||||
#ifdef _KERNEL_OPT
|
#ifdef _KERNEL_OPT
|
||||||
#include "opt_mrouting.h"
|
#include "opt_mrouting.h"
|
||||||
|
@ -82,6 +82,8 @@ __KERNEL_RCSID(0, "$NetBSD: ip_encap.c,v 1.53 2016/04/26 08:44:44 ozaki-r Exp $"
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/kmem.h>
|
#include <sys/kmem.h>
|
||||||
|
#include <sys/once.h>
|
||||||
|
#include <sys/rwlock.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
||||||
|
@ -124,6 +126,12 @@ LIST_HEAD(, encaptab) encaptab = LIST_HEAD_INITIALIZER(&encaptab);
|
||||||
|
|
||||||
struct radix_node_head *encap_head[2]; /* 0 for AF_INET, 1 for AF_INET6 */
|
struct radix_node_head *encap_head[2]; /* 0 for AF_INET, 1 for AF_INET6 */
|
||||||
|
|
||||||
|
static ONCE_DECL(encap_init_control);
|
||||||
|
|
||||||
|
static krwlock_t encap_whole_lock __cacheline_aligned;
|
||||||
|
|
||||||
|
static int encap_init_once(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
encap_init(void)
|
encap_init(void)
|
||||||
{
|
{
|
||||||
|
@ -166,6 +174,7 @@ encap4_lookup(struct mbuf *m, int off, int proto, enum direction dir)
|
||||||
struct radix_node *rn;
|
struct radix_node *rn;
|
||||||
|
|
||||||
KASSERT(m->m_len >= sizeof(*ip));
|
KASSERT(m->m_len >= sizeof(*ip));
|
||||||
|
KASSERT(rw_read_held(&encap_whole_lock));
|
||||||
|
|
||||||
ip = mtod(m, struct ip *);
|
ip = mtod(m, struct ip *);
|
||||||
|
|
||||||
|
@ -246,6 +255,7 @@ encap4_input(struct mbuf *m, ...)
|
||||||
proto = va_arg(ap, int);
|
proto = va_arg(ap, int);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
rw_enter(&encap_whole_lock, RW_READER);
|
||||||
match = encap4_lookup(m, off, proto, INBOUND);
|
match = encap4_lookup(m, off, proto, INBOUND);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
|
@ -253,11 +263,15 @@ encap4_input(struct mbuf *m, ...)
|
||||||
esw = match->esw;
|
esw = match->esw;
|
||||||
if (esw && esw->encapsw4.pr_input) {
|
if (esw && esw->encapsw4.pr_input) {
|
||||||
encap_fillarg(m, match);
|
encap_fillarg(m, match);
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
(*esw->encapsw4.pr_input)(m, off, proto);
|
(*esw->encapsw4.pr_input)(m, off, proto);
|
||||||
} else
|
} else {
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
|
|
||||||
/* last resort: inject to raw socket */
|
/* last resort: inject to raw socket */
|
||||||
rip_input(m, off, proto);
|
rip_input(m, off, proto);
|
||||||
|
@ -276,6 +290,7 @@ encap6_lookup(struct mbuf *m, int off, int proto, enum direction dir)
|
||||||
struct radix_node *rn;
|
struct radix_node *rn;
|
||||||
|
|
||||||
KASSERT(m->m_len >= sizeof(*ip6));
|
KASSERT(m->m_len >= sizeof(*ip6));
|
||||||
|
KASSERT(rw_read_held(&encap_whole_lock));
|
||||||
|
|
||||||
ip6 = mtod(m, struct ip6_hdr *);
|
ip6 = mtod(m, struct ip6_hdr *);
|
||||||
|
|
||||||
|
@ -330,6 +345,7 @@ encap6_input(struct mbuf **mp, int *offp, int proto)
|
||||||
const struct encapsw *esw;
|
const struct encapsw *esw;
|
||||||
struct encaptab *match;
|
struct encaptab *match;
|
||||||
|
|
||||||
|
rw_enter(&encap_whole_lock, RW_READER);
|
||||||
match = encap6_lookup(m, *offp, proto, INBOUND);
|
match = encap6_lookup(m, *offp, proto, INBOUND);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
|
@ -337,24 +353,33 @@ encap6_input(struct mbuf **mp, int *offp, int proto)
|
||||||
esw = match->esw;
|
esw = match->esw;
|
||||||
if (esw && esw->encapsw6.pr_input) {
|
if (esw && esw->encapsw6.pr_input) {
|
||||||
encap_fillarg(m, match);
|
encap_fillarg(m, match);
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
return (*esw->encapsw6.pr_input)(mp, offp, proto);
|
return (*esw->encapsw6.pr_input)(mp, offp, proto);
|
||||||
} else {
|
} else {
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
return IPPROTO_DONE;
|
return IPPROTO_DONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
|
|
||||||
/* last resort: inject to raw socket */
|
/* last resort: inject to raw socket */
|
||||||
return rip6_input(mp, offp, proto);
|
return rip6_input(mp, offp, proto);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX
|
||||||
|
* The encaptab list and the rnh radix tree must be manipulated atomically.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
encap_add(struct encaptab *ep)
|
encap_add(struct encaptab *ep)
|
||||||
{
|
{
|
||||||
struct radix_node_head *rnh = encap_rnh(ep->af);
|
struct radix_node_head *rnh = encap_rnh(ep->af);
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
|
KASSERT(rw_write_held(&encap_whole_lock));
|
||||||
|
|
||||||
LIST_INSERT_HEAD(&encaptab, ep, chain);
|
LIST_INSERT_HEAD(&encaptab, ep, chain);
|
||||||
if (!ep->func && rnh) {
|
if (!ep->func && rnh) {
|
||||||
if (!rnh->rnh_addaddr((void *)ep->addrpack,
|
if (!rnh->rnh_addaddr((void *)ep->addrpack,
|
||||||
|
@ -370,12 +395,18 @@ encap_add(struct encaptab *ep)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX
|
||||||
|
* The encaptab list and the rnh radix tree must be manipulated atomically.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
encap_remove(struct encaptab *ep)
|
encap_remove(struct encaptab *ep)
|
||||||
{
|
{
|
||||||
struct radix_node_head *rnh = encap_rnh(ep->af);
|
struct radix_node_head *rnh = encap_rnh(ep->af);
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
|
KASSERT(rw_write_held(&encap_whole_lock));
|
||||||
|
|
||||||
LIST_REMOVE(ep, chain);
|
LIST_REMOVE(ep, chain);
|
||||||
if (!ep->func && rnh) {
|
if (!ep->func && rnh) {
|
||||||
if (!rnh->rnh_deladdr((void *)ep->addrpack,
|
if (!rnh->rnh_deladdr((void *)ep->addrpack,
|
||||||
|
@ -420,6 +451,15 @@ encap_afcheck(int af, const struct sockaddr *sp, const struct sockaddr *dp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
encap_init_once(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
rw_init(&encap_whole_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sp (src ptr) is always my side, and dp (dst ptr) is always remote side.
|
* sp (src ptr) is always my side, and dp (dst ptr) is always remote side.
|
||||||
* length of mask (sm and dm) is assumed to be same as sp/dp.
|
* length of mask (sm and dm) is assumed to be same as sp/dp.
|
||||||
|
@ -440,6 +480,8 @@ encap_attach(int af, int proto,
|
||||||
struct ip_pack6 *pack6;
|
struct ip_pack6 *pack6;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
RUN_ONCE(&encap_init_control, encap_init_once);
|
||||||
|
|
||||||
s = splsoftnet();
|
s = splsoftnet();
|
||||||
/* sanity check on args */
|
/* sanity check on args */
|
||||||
error = encap_afcheck(af, sp, dp);
|
error = encap_afcheck(af, sp, dp);
|
||||||
|
@ -535,7 +577,9 @@ encap_attach(int af, int proto,
|
||||||
ep->esw = esw;
|
ep->esw = esw;
|
||||||
ep->arg = arg;
|
ep->arg = arg;
|
||||||
|
|
||||||
|
rw_enter(&encap_whole_lock, RW_WRITER);
|
||||||
error = encap_add(ep);
|
error = encap_add(ep);
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
if (error)
|
if (error)
|
||||||
goto gc;
|
goto gc;
|
||||||
|
|
||||||
|
@ -564,6 +608,8 @@ encap_attach_func(int af, int proto,
|
||||||
int error;
|
int error;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
|
RUN_ONCE(&encap_init_control, encap_init_once);
|
||||||
|
|
||||||
s = splsoftnet();
|
s = splsoftnet();
|
||||||
/* sanity check on args */
|
/* sanity check on args */
|
||||||
if (!func) {
|
if (!func) {
|
||||||
|
@ -588,7 +634,9 @@ encap_attach_func(int af, int proto,
|
||||||
ep->esw = esw;
|
ep->esw = esw;
|
||||||
ep->arg = arg;
|
ep->arg = arg;
|
||||||
|
|
||||||
|
rw_enter(&encap_whole_lock, RW_WRITER);
|
||||||
error = encap_add(ep);
|
error = encap_add(ep);
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
if (error)
|
if (error)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -644,9 +692,11 @@ encap6_ctlinput(int cmd, const struct sockaddr *sa, void *d0)
|
||||||
/*
|
/*
|
||||||
* Check to see if we have a valid encap configuration.
|
* Check to see if we have a valid encap configuration.
|
||||||
*/
|
*/
|
||||||
|
rw_enter(&encap_whole_lock, RW_READER);
|
||||||
match = encap6_lookup(m, off, nxt, OUTBOUND);
|
match = encap6_lookup(m, off, nxt, OUTBOUND);
|
||||||
if (match)
|
if (match)
|
||||||
valid++;
|
valid++;
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Depending on the value of "valid" and routing table
|
* Depending on the value of "valid" and routing table
|
||||||
|
@ -664,6 +714,7 @@ encap6_ctlinput(int cmd, const struct sockaddr *sa, void *d0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* inform all listeners */
|
/* inform all listeners */
|
||||||
|
rw_enter(&encap_whole_lock, RW_READER);
|
||||||
LIST_FOREACH(ep, &encaptab, chain) {
|
LIST_FOREACH(ep, &encaptab, chain) {
|
||||||
if (ep->af != AF_INET6)
|
if (ep->af != AF_INET6)
|
||||||
continue;
|
continue;
|
||||||
|
@ -678,6 +729,7 @@ encap6_ctlinput(int cmd, const struct sockaddr *sa, void *d0)
|
||||||
(*esw->encapsw6.pr_ctlinput)(cmd, sa, d, ep->arg);
|
(*esw->encapsw6.pr_ctlinput)(cmd, sa, d, ep->arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
|
|
||||||
rip6_ctlinput(cmd, sa, d0);
|
rip6_ctlinput(cmd, sa, d0);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -691,11 +743,14 @@ encap_detach(const struct encaptab *cookie)
|
||||||
struct encaptab *p, *np;
|
struct encaptab *p, *np;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
rw_enter(&encap_whole_lock, RW_WRITER);
|
||||||
LIST_FOREACH_SAFE(p, &encaptab, chain, np) {
|
LIST_FOREACH_SAFE(p, &encaptab, chain, np) {
|
||||||
if (p == ep) {
|
if (p == ep) {
|
||||||
error = encap_remove(p);
|
error = encap_remove(p);
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (!ep->func) {
|
if (!ep->func) {
|
||||||
kmem_free(p->addrpack, ep->addrpack->sa_len);
|
kmem_free(p->addrpack, ep->addrpack->sa_len);
|
||||||
kmem_free(p->maskpack, ep->maskpack->sa_len);
|
kmem_free(p->maskpack, ep->maskpack->sa_len);
|
||||||
|
@ -704,6 +759,7 @@ encap_detach(const struct encaptab *cookie)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rw_exit(&encap_whole_lock);
|
||||||
|
|
||||||
return ENOENT;
|
return ENOENT;
|
||||||
}
|
}
|
||||||
|
@ -747,6 +803,8 @@ encap_fillarg(struct mbuf *m, const struct encaptab *ep)
|
||||||
{
|
{
|
||||||
struct m_tag *mtag;
|
struct m_tag *mtag;
|
||||||
|
|
||||||
|
KASSERT(rw_read_held(&encap_whole_lock));
|
||||||
|
|
||||||
mtag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT);
|
mtag = m_tag_get(PACKET_TAG_ENCAP, sizeof(void *), M_NOWAIT);
|
||||||
if (mtag) {
|
if (mtag) {
|
||||||
*(void **)(mtag + 1) = ep->arg;
|
*(void **)(mtag + 1) = ep->arg;
|
||||||
|
@ -768,3 +826,23 @@ encap_getarg(struct mbuf *m)
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encap_lock_enter(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* XXX future work
|
||||||
|
* change interruptable lock.
|
||||||
|
*/
|
||||||
|
KERNEL_LOCK(1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
encap_lock_exit(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* XXX future work
|
||||||
|
* change interruptable lock
|
||||||
|
*/
|
||||||
|
KERNEL_UNLOCK_ONE(NULL);
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: ip_encap.h,v 1.19 2016/02/29 01:29:15 knakahara Exp $ */
|
/* $NetBSD: ip_encap.h,v 1.20 2016/07/04 04:17:25 knakahara Exp $ */
|
||||||
/* $KAME: ip_encap.h,v 1.7 2000/03/25 07:23:37 sumikawa Exp $ */
|
/* $KAME: ip_encap.h,v 1.7 2000/03/25 07:23:37 sumikawa Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,6 +106,9 @@ void *encap6_ctlinput(int, const struct sockaddr *, void *);
|
||||||
int encap_detach(const struct encaptab *);
|
int encap_detach(const struct encaptab *);
|
||||||
void *encap_getarg(struct mbuf *);
|
void *encap_getarg(struct mbuf *);
|
||||||
|
|
||||||
|
void encap_lock_enter(void);
|
||||||
|
void encap_lock_exit(void);
|
||||||
|
|
||||||
#define ENCAP_PR_WRAP_CTLINPUT(name) \
|
#define ENCAP_PR_WRAP_CTLINPUT(name) \
|
||||||
static void * \
|
static void * \
|
||||||
name##_wrapper(int a, const struct sockaddr *b, void *c, void *d) \
|
name##_wrapper(int a, const struct sockaddr *b, void *c, void *d) \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: ip_mroute.c,v 1.141 2016/06/21 03:28:27 ozaki-r Exp $ */
|
/* $NetBSD: ip_mroute.c,v 1.142 2016/07/04 04:17:25 knakahara Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1992, 1993
|
* Copyright (c) 1992, 1993
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: ip_mroute.c,v 1.141 2016/06/21 03:28:27 ozaki-r Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: ip_mroute.c,v 1.142 2016/07/04 04:17:25 knakahara Exp $");
|
||||||
|
|
||||||
#ifdef _KERNEL_OPT
|
#ifdef _KERNEL_OPT
|
||||||
#include "opt_inet.h"
|
#include "opt_inet.h"
|
||||||
|
@ -832,8 +832,10 @@ add_vif(struct vifctl *vifcp)
|
||||||
* this requires both radix tree lookup and then a
|
* this requires both radix tree lookup and then a
|
||||||
* function to check, and this is not supported yet.
|
* function to check, and this is not supported yet.
|
||||||
*/
|
*/
|
||||||
|
encap_lock_enter();
|
||||||
vifp->v_encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV4,
|
vifp->v_encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV4,
|
||||||
vif_encapcheck, &vif_encapsw, vifp);
|
vif_encapcheck, &vif_encapsw, vifp);
|
||||||
|
encap_lock_exit();
|
||||||
if (!vifp->v_encap_cookie)
|
if (!vifp->v_encap_cookie)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
|
@ -929,7 +931,9 @@ reset_vif(struct vif *vifp)
|
||||||
callout_stop(&vifp->v_repq_ch);
|
callout_stop(&vifp->v_repq_ch);
|
||||||
|
|
||||||
/* detach this vif from decapsulator dispatch table */
|
/* detach this vif from decapsulator dispatch table */
|
||||||
|
encap_lock_enter();
|
||||||
encap_detach(vifp->v_encap_cookie);
|
encap_detach(vifp->v_encap_cookie);
|
||||||
|
encap_lock_exit();
|
||||||
vifp->v_encap_cookie = NULL;
|
vifp->v_encap_cookie = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: xform_ipip.c,v 1.39 2016/06/10 13:31:44 ozaki-r Exp $ */
|
/* $NetBSD: xform_ipip.c,v 1.40 2016/07/04 04:17:25 knakahara Exp $ */
|
||||||
/* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */
|
/* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */
|
||||||
/* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
|
/* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.39 2016/06/10 13:31:44 ozaki-r Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.40 2016/07/04 04:17:25 knakahara Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IP-inside-IP processing
|
* IP-inside-IP processing
|
||||||
|
@ -725,6 +725,8 @@ ipe4_attach(void)
|
||||||
xform_register(&ipe4_xformsw);
|
xform_register(&ipe4_xformsw);
|
||||||
/* attach to encapsulation framework */
|
/* attach to encapsulation framework */
|
||||||
/* XXX save return cookie for detach on module remove */
|
/* XXX save return cookie for detach on module remove */
|
||||||
|
encap_lock_enter();
|
||||||
|
/* ipe4_encapsw and ipe4_encapsw must be added atomically */
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
(void) encap_attach_func(AF_INET, -1,
|
(void) encap_attach_func(AF_INET, -1,
|
||||||
ipe4_encapcheck, &ipe4_encapsw, NULL);
|
ipe4_encapcheck, &ipe4_encapsw, NULL);
|
||||||
|
@ -733,6 +735,7 @@ ipe4_attach(void)
|
||||||
(void) encap_attach_func(AF_INET6, -1,
|
(void) encap_attach_func(AF_INET6, -1,
|
||||||
ipe4_encapcheck, &ipe4_encapsw6, NULL);
|
ipe4_encapcheck, &ipe4_encapsw6, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
encap_lock_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SYSINIT
|
#ifdef SYSINIT
|
||||||
|
|
Loading…
Reference in New Issue