Virtualize interface cloner for gif(4). This fixes a panic when destroying
a vnet jail which has a gif(4) interface.
This commit is contained in:
parent
ee0bd4b909
commit
a7f5886ec7
@ -92,13 +92,20 @@
|
||||
static const char gifname[] = "gif";
|
||||
|
||||
/*
|
||||
* gif_mtx protects the global gif_softc_list.
|
||||
* gif_mtx protects a per-vnet gif_softc_list.
|
||||
*/
|
||||
static struct mtx gif_mtx;
|
||||
static VNET_DEFINE(struct mtx, gif_mtx);
|
||||
#define V_gif_mtx VNET(gif_mtx)
|
||||
static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
|
||||
static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list);
|
||||
#define V_gif_softc_list VNET(gif_softc_list)
|
||||
|
||||
#define GIF_LIST_LOCK_INIT(x) mtx_init(&V_gif_mtx, "gif_mtx", \
|
||||
NULL, MTX_DEF)
|
||||
#define GIF_LIST_LOCK_DESTROY(x) mtx_destroy(&V_gif_mtx)
|
||||
#define GIF_LIST_LOCK(x) mtx_lock(&V_gif_mtx)
|
||||
#define GIF_LIST_UNLOCK(x) mtx_unlock(&V_gif_mtx)
|
||||
|
||||
void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
|
||||
void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
|
||||
void (*ng_gif_attach_p)(struct ifnet *ifp);
|
||||
@ -107,7 +114,8 @@ void (*ng_gif_detach_p)(struct ifnet *ifp);
|
||||
static void gif_start(struct ifnet *);
|
||||
static int gif_clone_create(struct if_clone *, int, caddr_t);
|
||||
static void gif_clone_destroy(struct ifnet *);
|
||||
static struct if_clone *gif_cloner;
|
||||
static VNET_DEFINE(struct if_clone *, gif_cloner);
|
||||
#define V_gif_cloner VNET(gif_cloner)
|
||||
|
||||
static int gifmodevent(module_t, int, void *);
|
||||
|
||||
@ -189,9 +197,9 @@ gif_clone_create(struct if_clone *ifc, int unit, caddr_t params)
|
||||
if (ng_gif_attach_p != NULL)
|
||||
(*ng_gif_attach_p)(GIF2IFP(sc));
|
||||
|
||||
mtx_lock(&gif_mtx);
|
||||
GIF_LIST_LOCK();
|
||||
LIST_INSERT_HEAD(&V_gif_softc_list, sc, gif_list);
|
||||
mtx_unlock(&gif_mtx);
|
||||
GIF_LIST_UNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -204,9 +212,9 @@ gif_clone_destroy(struct ifnet *ifp)
|
||||
#endif
|
||||
struct gif_softc *sc = ifp->if_softc;
|
||||
|
||||
mtx_lock(&gif_mtx);
|
||||
GIF_LIST_LOCK();
|
||||
LIST_REMOVE(sc, gif_list);
|
||||
mtx_unlock(&gif_mtx);
|
||||
GIF_LIST_UNLOCK();
|
||||
|
||||
gif_delete_tunnel(ifp);
|
||||
#ifdef INET6
|
||||
@ -238,9 +246,22 @@ vnet_gif_init(const void *unused __unused)
|
||||
{
|
||||
|
||||
LIST_INIT(&V_gif_softc_list);
|
||||
GIF_LIST_LOCK_INIT();
|
||||
V_gif_cloner = if_clone_simple(gifname, gif_clone_create,
|
||||
gif_clone_destroy, 0);
|
||||
}
|
||||
VNET_SYSINIT(vnet_gif_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, vnet_gif_init,
|
||||
NULL);
|
||||
VNET_SYSINIT(vnet_gif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
|
||||
vnet_gif_init, NULL);
|
||||
|
||||
static void
|
||||
vnet_gif_uninit(const void *unused __unused)
|
||||
{
|
||||
|
||||
if_clone_detach(V_gif_cloner);
|
||||
GIF_LIST_LOCK_DESTROY();
|
||||
}
|
||||
VNET_SYSUNINIT(vnet_gif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
|
||||
vnet_gif_uninit, NULL);
|
||||
|
||||
static int
|
||||
gifmodevent(module_t mod, int type, void *data)
|
||||
@ -248,19 +269,12 @@ gifmodevent(module_t mod, int type, void *data)
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF);
|
||||
gif_cloner = if_clone_simple(gifname, gif_clone_create,
|
||||
gif_clone_destroy, 0);
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
if_clone_detach(gif_cloner);
|
||||
mtx_destroy(&gif_mtx);
|
||||
break;
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static moduledata_t gif_mod = {
|
||||
@ -364,7 +378,7 @@ gif_start(struct ifnet *ifp)
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (sc->gif_psrc->sa_family == AF_INET6)
|
||||
m->m_pkthdr.len -= GIF_HDR_LEN6;
|
||||
m->m_pkthdr.len -= GIF_HDR_LEN6;
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
@ -373,6 +387,7 @@ gif_start(struct ifnet *ifp)
|
||||
*/
|
||||
af = m->m_pkthdr.csum_data;
|
||||
|
||||
/* override to IPPROTO_ETHERIP for bridged traffic */
|
||||
if (ifp->if_bridge)
|
||||
af = AF_LINK;
|
||||
|
||||
@ -381,7 +396,6 @@ gif_start(struct ifnet *ifp)
|
||||
|
||||
/* Done by IFQ_HANDOFF */
|
||||
/* if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);*/
|
||||
/* override to IPPROTO_ETHERIP for bridged traffic */
|
||||
|
||||
M_SETFIB(m, sc->gif_fibnum);
|
||||
/* inner AF-specific encapsulation */
|
||||
@ -904,7 +918,7 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
|
||||
struct sockaddr *osrc, *odst, *sa;
|
||||
int error = 0;
|
||||
|
||||
mtx_lock(&gif_mtx);
|
||||
GIF_LIST_LOCK();
|
||||
LIST_FOREACH(sc2, &V_gif_softc_list, gif_list) {
|
||||
if (sc2 == sc)
|
||||
continue;
|
||||
@ -924,13 +938,13 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
|
||||
bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
|
||||
bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
|
||||
error = EADDRNOTAVAIL;
|
||||
mtx_unlock(&gif_mtx);
|
||||
GIF_LIST_UNLOCK();
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* XXX both end must be valid? (I mean, not 0.0.0.0) */
|
||||
}
|
||||
mtx_unlock(&gif_mtx);
|
||||
GIF_LIST_UNLOCK();
|
||||
|
||||
/* XXX we can detach from both, but be polite just in case */
|
||||
if (sc->gif_psrc)
|
||||
|
Loading…
x
Reference in New Issue
Block a user