domain: give domains a chance to probe for availability
This gives any given domain a chance to indicate that it's not actually supported on the current system. If dom_probe isn't supplied, we assume the domain is universally applicable as most of them are. Keeping fully-initialized and registered domains around that physically can't work on a large majority of FreeBSD deployments is sub-optimal and leads to errors that aren't consistent with the reality of why the socket can't be created (e.g. ESOCKTNOSUPPORT) because such scenario has to be caught upon pru_attach, at which point kicking back the more-appropriate EAFNOSUPPORT would seem weird. The initial consumer of this will be hvsock, which is only available on HyperV guests. Reviewed by: cem (earlier version), bcr (manpages) Differential Revision: https://reviews.freebsd.org/D25062
This commit is contained in:
parent
59d1661cd8
commit
239aebee61
@ -1011,6 +1011,7 @@ MLINKS+=dnv.9 dnvlist.9 \
|
||||
dnv.9 dnvlist_take_string.9
|
||||
MLINKS+=domain.9 DOMAIN_SET.9 \
|
||||
domain.9 domain_add.9 \
|
||||
domain.9 domain_init.9 \
|
||||
domain.9 pfctlinput.9 \
|
||||
domain.9 pffinddomain.9 \
|
||||
domain.9 pffindproto.9 \
|
||||
|
@ -31,6 +31,7 @@
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm domain_add ,
|
||||
.Nm domain_init ,
|
||||
.Nm pfctlinput ,
|
||||
.Nm pffinddomain ,
|
||||
.Nm pffindproto ,
|
||||
@ -45,6 +46,8 @@
|
||||
.Ft void
|
||||
.Fn domain_add "void *data"
|
||||
.Ft void
|
||||
.Fn domain_init "void *data"
|
||||
.Ft void
|
||||
.Fn pfctlinput "int cmd" "struct sockaddr *sa"
|
||||
.Ft struct domain *
|
||||
.Fn pffinddomain "int family"
|
||||
@ -65,8 +68,10 @@ and
|
||||
struct domain {
|
||||
int dom_family; /* AF_xxx */
|
||||
char *dom_name;
|
||||
int dom_flags;
|
||||
void (*dom_init) /* initialize domain data structures */
|
||||
(void);
|
||||
int (*dom_probe)(void); /* check for support (optional) */
|
||||
void (*dom_destroy) /* cleanup structures / state */
|
||||
(void);
|
||||
int (*dom_externalize) /* externalize access rights */
|
||||
@ -143,15 +148,36 @@ is not called directly, instead
|
||||
.Fn DOMAIN_SET
|
||||
is used.
|
||||
.Pp
|
||||
If the new domain has defined an initialization routine, it is called by
|
||||
.Fn domain_add ;
|
||||
If the new domain has defined a probe routine, it is called first in
|
||||
.Fn domain_add
|
||||
to determine if the domain should be supported on the current system.
|
||||
If the probe routine returns a non-0 value, then the domain will not be
|
||||
marked as supported.
|
||||
Unsupported domains do not proceed with the initialization process and are not
|
||||
discoverable by
|
||||
.Fn pffinddomain ,
|
||||
.Fn pffindtype ,
|
||||
or
|
||||
.Fn pffindproto .
|
||||
.Pp
|
||||
.Fn domain_init
|
||||
is called after
|
||||
.Fn domain_add
|
||||
during boot and for each
|
||||
.Xr vnet 9 .
|
||||
If the new domain has defined an initialization routine, it is called during
|
||||
.Fn domain_init ;
|
||||
as well, each of the protocols within the domain that have defined an
|
||||
initialization routine will have theirs called.
|
||||
Note that domain initialization cannot fail at this time.
|
||||
.Pp
|
||||
Once a domain is added it cannot be unloaded.
|
||||
Once a domain is added it cannot be completely unloaded.
|
||||
This is because there is
|
||||
no reference counting system in place to determine if there are any
|
||||
active references from sockets within that domain.
|
||||
If the domain defines a
|
||||
.Fn dom_destroy
|
||||
routine, then it will be invoked during vnet teardown.
|
||||
.Pp
|
||||
.Fn pffinddomain
|
||||
finds a domain by family.
|
||||
|
@ -172,7 +172,11 @@ domain_init(void *arg)
|
||||
{
|
||||
struct domain *dp = arg;
|
||||
struct protosw *pr;
|
||||
int flags;
|
||||
|
||||
flags = atomic_load_acq_int(&dp->dom_flags);
|
||||
if ((flags & DOMF_SUPPORTED) == 0)
|
||||
return;
|
||||
if (dp->dom_init)
|
||||
(*dp->dom_init)();
|
||||
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
|
||||
@ -200,6 +204,8 @@ vnet_domain_uninit(void *arg)
|
||||
{
|
||||
struct domain *dp = arg;
|
||||
|
||||
if ((atomic_load_acq_int(&dp->dom_flags) & DOMF_SUPPORTED) == 0)
|
||||
return;
|
||||
if (dp->dom_destroy)
|
||||
(*dp->dom_destroy)();
|
||||
}
|
||||
@ -216,6 +222,9 @@ domain_add(void *data)
|
||||
struct domain *dp;
|
||||
|
||||
dp = (struct domain *)data;
|
||||
if (dp->dom_probe != NULL && (*dp->dom_probe)() != 0)
|
||||
return;
|
||||
atomic_set_rel_int(&dp->dom_flags, DOMF_SUPPORTED);
|
||||
mtx_lock(&dom_mtx);
|
||||
dp->dom_next = domains;
|
||||
domains = dp;
|
||||
|
@ -50,8 +50,10 @@ struct rib_head;
|
||||
struct domain {
|
||||
int dom_family; /* AF_xxx */
|
||||
char *dom_name;
|
||||
int dom_flags;
|
||||
void (*dom_init) /* initialize domain data structures */
|
||||
(void);
|
||||
int (*dom_probe)(void); /* check for support (optional) */
|
||||
void (*dom_destroy) /* cleanup structures / state */
|
||||
(void);
|
||||
int (*dom_externalize) /* externalize access rights */
|
||||
@ -70,6 +72,9 @@ struct domain {
|
||||
/* af-dependent data on ifnet */
|
||||
};
|
||||
|
||||
/* dom_flags */
|
||||
#define DOMF_SUPPORTED 0x0001 /* System supports this domain. */
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern int domain_init_status;
|
||||
extern struct domain *domains;
|
||||
|
Loading…
Reference in New Issue
Block a user