Changeset View
Changeset View
Standalone View
Standalone View
sys/net/if_tuntap.c
Show First 20 Lines • Show All 322 Lines • ▼ Show 20 Lines | .cdevsw = { | ||||
.d_kqfilter = tunkqfilter, | .d_kqfilter = tunkqfilter, | ||||
.d_name = vmnetname, | .d_name = vmnetname, | ||||
}, | }, | ||||
.clone_match_fn = vmnet_clone_match, | .clone_match_fn = vmnet_clone_match, | ||||
.clone_create_fn = tun_clone_create, | .clone_create_fn = tun_clone_create, | ||||
.clone_destroy_fn = tun_clone_destroy, | .clone_destroy_fn = tun_clone_destroy, | ||||
}, | }, | ||||
}; | }; | ||||
#define NDRV nitems(tuntap_drivers) | |||||
struct tuntap_driver_cloner { | VNET_DEFINE_STATIC(struct if_clone *, tuntap_driver_cloners[NDRV]); | ||||
SLIST_ENTRY(tuntap_driver_cloner) link; | |||||
struct tuntap_driver *drv; | |||||
struct if_clone *cloner; | |||||
}; | |||||
VNET_DEFINE_STATIC(SLIST_HEAD(, tuntap_driver_cloner), tuntap_driver_cloners) = | |||||
SLIST_HEAD_INITIALIZER(tuntap_driver_cloners); | |||||
#define V_tuntap_driver_cloners VNET(tuntap_driver_cloners) | #define V_tuntap_driver_cloners VNET(tuntap_driver_cloners) | ||||
/* | /* | ||||
* Mechanism for marking a tunnel device as busy so that we can safely do some | * Mechanism for marking a tunnel device as busy so that we can safely do some | ||||
* orthogonal operations (such as operations on devices) without racing against | * orthogonal operations (such as operations on devices) without racing against | ||||
* tun_destroy. tun_destroy will wait on the condvar if we're at all busy or | * tun_destroy. tun_destroy will wait on the condvar if we're at all busy or | ||||
* open, to be woken up when the condition is alleviated. | * open, to be woken up when the condition is alleviated. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Sets unit and/or flags given the device name. Must be called with correct | * Sets unit and/or flags given the device name. Must be called with correct | ||||
* vnet context. | * vnet context. | ||||
*/ | */ | ||||
static int | static int | ||||
tuntap_name2info(const char *name, int *outunit, int *outflags) | tuntap_name2info(const char *name, int *outunit, int *outflags) | ||||
{ | { | ||||
struct tuntap_driver *drv; | struct tuntap_driver *drv; | ||||
struct tuntap_driver_cloner *drvc; | |||||
char *dname; | char *dname; | ||||
int flags, unit; | int flags, unit; | ||||
bool found; | bool found; | ||||
if (name == NULL) | if (name == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* | /* | ||||
* Needed for dev_stdclone, but dev_stdclone will not modify, it just | * Needed for dev_stdclone, but dev_stdclone will not modify, it just | ||||
* wants to be able to pass back a char * through the second param. We | * wants to be able to pass back a char * through the second param. We | ||||
* will always set that as NULL here, so we'll fake it. | * will always set that as NULL here, so we'll fake it. | ||||
*/ | */ | ||||
dname = __DECONST(char *, name); | dname = __DECONST(char *, name); | ||||
found = false; | found = false; | ||||
KASSERT(!SLIST_EMPTY(&V_tuntap_driver_cloners), | for (u_int i = 0; i < NDRV; i++) { | ||||
("tuntap_driver_cloners failed to initialize")); | drv = &tuntap_drivers[i]; | ||||
SLIST_FOREACH(drvc, &V_tuntap_driver_cloners, link) { | |||||
KASSERT(drvc->drv != NULL, | |||||
("tuntap_driver_cloners entry not properly initialized")); | |||||
drv = drvc->drv; | |||||
if (strcmp(name, drv->cdevsw.d_name) == 0) { | if (strcmp(name, drv->cdevsw.d_name) == 0) { | ||||
found = true; | found = true; | ||||
unit = -1; | unit = -1; | ||||
flags = drv->ident_flags; | flags = drv->ident_flags; | ||||
break; | break; | ||||
} | } | ||||
Show All 12 Lines | tuntap_name2info(const char *name, int *outunit, int *outflags) | ||||
if (outflags != NULL) | if (outflags != NULL) | ||||
*outflags = flags; | *outflags = flags; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Get driver information from a set of flags specified. Masks the identifying | * Get driver information from a set of flags specified. Masks the identifying | ||||
* part of the flags and compares it against all of the available | * part of the flags and compares it against all of the available | ||||
* tuntap_drivers. Must be called with correct vnet context. | * tuntap_drivers. | ||||
*/ | */ | ||||
static struct tuntap_driver * | static struct tuntap_driver * | ||||
tuntap_driver_from_flags(int tun_flags) | tuntap_driver_from_flags(int tun_flags) | ||||
{ | { | ||||
struct tuntap_driver *drv; | |||||
struct tuntap_driver_cloner *drvc; | |||||
KASSERT(!SLIST_EMPTY(&V_tuntap_driver_cloners), | for (u_int i = 0; i < NDRV; i++) | ||||
("tuntap_driver_cloners failed to initialize")); | if ((tun_flags & TUN_DRIVER_IDENT_MASK) == | ||||
SLIST_FOREACH(drvc, &V_tuntap_driver_cloners, link) { | tuntap_drivers[i].ident_flags) | ||||
KASSERT(drvc->drv != NULL, | return (&tuntap_drivers[i]); | ||||
("tuntap_driver_cloners entry not properly initialized")); | |||||
drv = drvc->drv; | |||||
if ((tun_flags & TUN_DRIVER_IDENT_MASK) == drv->ident_flags) | |||||
return (drv); | |||||
} | |||||
return (NULL); | return (NULL); | ||||
} | } | ||||
static int | static int | ||||
tun_clone_match(struct if_clone *ifc, const char *name) | tun_clone_match(struct if_clone *ifc, const char *name) | ||||
{ | { | ||||
int tunflags; | int tunflags; | ||||
▲ Show 20 Lines • Show All 185 Lines • ▼ Show 20 Lines | tun_clone_destroy(struct if_clone *ifc __unused, struct ifnet *ifp, uint32_t flags) | ||||
tun_destroy(tp); | tun_destroy(tp); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
vnet_tun_init(const void *unused __unused) | vnet_tun_init(const void *unused __unused) | ||||
{ | { | ||||
struct tuntap_driver *drv; | |||||
struct tuntap_driver_cloner *drvc; | |||||
int i; | |||||
for (i = 0; i < nitems(tuntap_drivers); ++i) { | for (u_int i = 0; i < NDRV; ++i) { | ||||
drv = &tuntap_drivers[i]; | |||||
drvc = malloc(sizeof(*drvc), M_TUN, M_WAITOK | M_ZERO); | |||||
drvc->drv = drv; | |||||
struct if_clone_addreq req = { | struct if_clone_addreq req = { | ||||
.match_f = drv->clone_match_fn, | .match_f = tuntap_drivers[i].clone_match_fn, | ||||
.create_f = drv->clone_create_fn, | .create_f = tuntap_drivers[i].clone_create_fn, | ||||
.destroy_f = drv->clone_destroy_fn, | .destroy_f = tuntap_drivers[i].clone_destroy_fn, | ||||
}; | }; | ||||
drvc->cloner = ifc_attach_cloner(drv->cdevsw.d_name, &req); | V_tuntap_driver_cloners[i] = | ||||
SLIST_INSERT_HEAD(&V_tuntap_driver_cloners, drvc, link); | ifc_attach_cloner(tuntap_drivers[i].cdevsw.d_name, &req); | ||||
}; | }; | ||||
} | } | ||||
VNET_SYSINIT(vnet_tun_init, SI_SUB_PROTO_IF, SI_ORDER_ANY, | VNET_SYSINIT(vnet_tun_init, SI_SUB_PROTO_IF, SI_ORDER_ANY, | ||||
vnet_tun_init, NULL); | vnet_tun_init, NULL); | ||||
static void | static void | ||||
vnet_tun_uninit(const void *unused __unused) | vnet_tun_uninit(const void *unused __unused) | ||||
{ | { | ||||
struct tuntap_driver_cloner *drvc; | |||||
while (!SLIST_EMPTY(&V_tuntap_driver_cloners)) { | for (u_int i = 0; i < NDRV; ++i) | ||||
drvc = SLIST_FIRST(&V_tuntap_driver_cloners); | if_clone_detach(V_tuntap_driver_cloners[i]); | ||||
SLIST_REMOVE_HEAD(&V_tuntap_driver_cloners, link); | |||||
if_clone_detach(drvc->cloner); | |||||
free(drvc, M_TUN); | |||||
} | |||||
} | } | ||||
VNET_SYSUNINIT(vnet_tun_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY, | VNET_SYSUNINIT(vnet_tun_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY, | ||||
vnet_tun_uninit, NULL); | vnet_tun_uninit, NULL); | ||||
static void | static void | ||||
tun_uninit(const void *unused __unused) | tun_uninit(const void *unused __unused) | ||||
{ | { | ||||
struct tuntap_driver *drv; | struct tuntap_driver *drv; | ||||
▲ Show 20 Lines • Show All 1,366 Lines • Show Last 20 Lines |