- Virtualize interface cloner for gre(4). This fixes a panic when destroying
a vnet jail which has a gre(4) interface. - Make net.link.gre.max_nesting vnet-local.
This commit is contained in:
parent
a7f5886ec7
commit
89c58b73e0
@ -102,15 +102,16 @@ struct mtag_gre_nesting {
|
||||
* gre_mtx protects all global variables in if_gre.c.
|
||||
* XXX: gre_softc data not protected yet.
|
||||
*/
|
||||
struct mtx gre_mtx;
|
||||
VNET_DEFINE(struct mtx, gre_mtx);
|
||||
VNET_DEFINE(struct gre_softc_head, gre_softc_list);
|
||||
|
||||
static const char grename[] = "gre";
|
||||
static MALLOC_DEFINE(M_GRE, grename, "Generic Routing Encapsulation");
|
||||
|
||||
struct gre_softc_head gre_softc_list;
|
||||
|
||||
static int gre_clone_create(struct if_clone *, int, caddr_t);
|
||||
static void gre_clone_destroy(struct ifnet *);
|
||||
static struct if_clone *gre_cloner;
|
||||
static VNET_DEFINE(struct if_clone *, gre_cloner);
|
||||
#define V_gre_cloner VNET(gre_cloner)
|
||||
|
||||
static int gre_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static int gre_output(struct ifnet *, struct mbuf *,
|
||||
@ -118,8 +119,6 @@ static int gre_output(struct ifnet *, struct mbuf *,
|
||||
|
||||
static int gre_compute_route(struct gre_softc *sc);
|
||||
|
||||
static void greattach(void);
|
||||
|
||||
#ifdef INET
|
||||
extern struct domain inetdomain;
|
||||
static const struct protosw in_gre_protosw = {
|
||||
@ -160,26 +159,34 @@ static SYSCTL_NODE(_net_link, IFT_TUNNEL, gre, CTLFLAG_RW, 0,
|
||||
*/
|
||||
#define MAX_GRE_NEST 1
|
||||
#endif
|
||||
static int max_gre_nesting = MAX_GRE_NEST;
|
||||
SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW,
|
||||
&max_gre_nesting, 0, "Max nested tunnels");
|
||||
static VNET_DEFINE(int, max_gre_nesting) = MAX_GRE_NEST;
|
||||
#define V_max_gre_nesting VNET(max_gre_nesting)
|
||||
SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET,
|
||||
&VNET_NAME(max_gre_nesting), 0, "Max nested tunnels");
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
greattach(void)
|
||||
vnet_gre_init(const void *unused __unused)
|
||||
{
|
||||
|
||||
mtx_init(&gre_mtx, "gre_mtx", NULL, MTX_DEF);
|
||||
LIST_INIT(&gre_softc_list);
|
||||
gre_cloner = if_clone_simple(grename, gre_clone_create,
|
||||
LIST_INIT(&V_gre_softc_list);
|
||||
GRE_LIST_LOCK_INIT();
|
||||
V_gre_cloner = if_clone_simple(grename, gre_clone_create,
|
||||
gre_clone_destroy, 0);
|
||||
}
|
||||
VNET_SYSINIT(vnet_gre_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
|
||||
vnet_gre_init, NULL);
|
||||
|
||||
static void
|
||||
vnet_gre_uninit(const void *unused __unused)
|
||||
{
|
||||
|
||||
if_clone_detach(V_gre_cloner);
|
||||
GRE_LIST_LOCK_DESTROY();
|
||||
}
|
||||
VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
|
||||
vnet_gre_uninit, NULL);
|
||||
|
||||
static int
|
||||
gre_clone_create(ifc, unit, params)
|
||||
struct if_clone *ifc;
|
||||
int unit;
|
||||
caddr_t params;
|
||||
gre_clone_create(struct if_clone *ifc, int unit, caddr_t params)
|
||||
{
|
||||
struct gre_softc *sc;
|
||||
|
||||
@ -210,21 +217,20 @@ gre_clone_create(ifc, unit, params)
|
||||
sc->key = 0;
|
||||
if_attach(GRE2IFP(sc));
|
||||
bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
|
||||
mtx_lock(&gre_mtx);
|
||||
LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
|
||||
mtx_unlock(&gre_mtx);
|
||||
GRE_LIST_LOCK();
|
||||
LIST_INSERT_HEAD(&V_gre_softc_list, sc, sc_list);
|
||||
GRE_LIST_UNLOCK();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
gre_clone_destroy(ifp)
|
||||
struct ifnet *ifp;
|
||||
gre_clone_destroy(struct ifnet *ifp)
|
||||
{
|
||||
struct gre_softc *sc = ifp->if_softc;
|
||||
|
||||
mtx_lock(&gre_mtx);
|
||||
GRE_LIST_LOCK();
|
||||
LIST_REMOVE(sc, sc_list);
|
||||
mtx_unlock(&gre_mtx);
|
||||
GRE_LIST_UNLOCK();
|
||||
|
||||
#ifdef INET
|
||||
if (sc->encap != NULL)
|
||||
@ -269,7 +275,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
||||
|
||||
gt = (struct mtag_gre_nesting *)(mtag + 1);
|
||||
gt->count++;
|
||||
if (gt->count > min(gt->max,max_gre_nesting)) {
|
||||
if (gt->count > min(gt->max, V_max_gre_nesting)) {
|
||||
printf("%s: hit maximum recursion limit %u on %s\n",
|
||||
__func__, gt->count - 1, ifp->if_xname);
|
||||
m_freem(m);
|
||||
@ -301,7 +307,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
|
||||
* Note: the sysctl does not actually check for saneness, so we
|
||||
* limit the maximum numbers of possible recursions here.
|
||||
*/
|
||||
max = imin(max_gre_nesting, 256);
|
||||
max = imin(V_max_gre_nesting, 256);
|
||||
/* If someone sets the sysctl <= 0, we want at least 1. */
|
||||
max = imax(max, 1);
|
||||
len = sizeof(struct mtag_gre_nesting) +
|
||||
@ -909,16 +915,12 @@ gremodevent(module_t mod, int type, void *data)
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
greattach();
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
if_clone_detach(gre_cloner);
|
||||
mtx_destroy(&gre_mtx);
|
||||
break;
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static moduledata_t gre_mod = {
|
||||
|
@ -176,8 +176,16 @@ struct mobip_h {
|
||||
|
||||
#ifdef _KERNEL
|
||||
LIST_HEAD(gre_softc_head, gre_softc);
|
||||
extern struct mtx gre_mtx;
|
||||
extern struct gre_softc_head gre_softc_list;
|
||||
VNET_DECLARE(struct gre_softc_head, gre_softc_list);
|
||||
#define V_gre_softc_list VNET(gre_softc_list)
|
||||
|
||||
VNET_DECLARE(struct mtx, gre_mtx);
|
||||
#define V_gre_mtx VNET(gre_mtx)
|
||||
#define GRE_LIST_LOCK_INIT(x) mtx_init(&V_gre_mtx, "gre_mtx", NULL, \
|
||||
MTX_DEF)
|
||||
#define GRE_LIST_LOCK_DESTROY(x) mtx_destroy(&V_gre_mtx)
|
||||
#define GRE_LIST_LOCK(x) mtx_lock(&V_gre_mtx)
|
||||
#define GRE_LIST_UNLOCK(x) mtx_unlock(&V_gre_mtx)
|
||||
|
||||
u_int16_t gre_in_cksum(u_int16_t *, u_int);
|
||||
#endif /* _KERNEL */
|
||||
|
@ -315,18 +315,18 @@ gre_lookup(struct mbuf *m, u_int8_t proto)
|
||||
struct ip *ip = mtod(m, struct ip *);
|
||||
struct gre_softc *sc;
|
||||
|
||||
mtx_lock(&gre_mtx);
|
||||
for (sc = LIST_FIRST(&gre_softc_list); sc != NULL;
|
||||
GRE_LIST_LOCK();
|
||||
for (sc = LIST_FIRST(&V_gre_softc_list); sc != NULL;
|
||||
sc = LIST_NEXT(sc, sc_list)) {
|
||||
if ((sc->g_dst.s_addr == ip->ip_src.s_addr) &&
|
||||
(sc->g_src.s_addr == ip->ip_dst.s_addr) &&
|
||||
(sc->g_proto == proto) &&
|
||||
((GRE2IFP(sc)->if_flags & IFF_UP) != 0)) {
|
||||
mtx_unlock(&gre_mtx);
|
||||
GRE_LIST_UNLOCK();
|
||||
return (sc);
|
||||
}
|
||||
}
|
||||
mtx_unlock(&gre_mtx);
|
||||
GRE_LIST_UNLOCK();
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user