#include <sys/param.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socketvar.h>
#include <sys/socketops.h>
#include <sys/systm.h>
#include <vm/vm_zone.h>
#include <sys/thread2.h>
static void domaininit (void *);
SYSINIT(domain, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, domaininit, NULL);
struct domainlist domains;
#define PR_NOTSUPP(pr, label) \
if (pr->pr_ ## label == NULL) \
pr->pr_ ## label = pr_generic_notsupp;
#define PRU_NOTSUPP(pu, label) \
if (pu->pru_ ## label == NULL) \
pu->pru_ ## label = pr_generic_notsupp;
static void
net_init_domain(struct domain *dp)
{
struct protosw *pr;
struct pr_usrreqs *pu;
crit_enter();
if (dp->dom_init)
(*dp->dom_init)();
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
pu = pr->pr_usrreqs;
if (pu == NULL) {
panic("domaininit: %ssw[%ld] has no usrreqs!",
dp->dom_name, (long)(pr - dp->dom_protosw));
}
PR_NOTSUPP(pr, ctloutput);
PRU_NOTSUPP(pu, accept);
PRU_NOTSUPP(pu, bind);
PRU_NOTSUPP(pu, connect);
PRU_NOTSUPP(pu, connect2);
PRU_NOTSUPP(pu, control);
PRU_NOTSUPP(pu, disconnect);
PRU_NOTSUPP(pu, listen);
PRU_NOTSUPP(pu, peeraddr);
PRU_NOTSUPP(pu, rcvd);
PRU_NOTSUPP(pu, rcvoob);
PRU_NOTSUPP(pu, shutdown);
PRU_NOTSUPP(pu, sockaddr);
if (pu->pru_sense == NULL)
pu->pru_sense = pru_sense_null;
if (pu->pru_sosend == NULL)
pu->pru_sosend = pru_sosend_notsupp;
if (pu->pru_soreceive == NULL)
pu->pru_soreceive = pru_soreceive_notsupp;
if (pr->pr_init)
(*pr->pr_init)();
}
max_hdr = max_linkhdr + max_protohdr;
max_datalen = MHLEN - max_hdr;
crit_exit();
}
void
net_add_domain(void *data)
{
struct domain *dp = data;
crit_enter();
SLIST_INSERT_HEAD(&domains, dp, dom_next);
crit_exit();
net_init_domain(dp);
}
static void
domaininit(void *dummy)
{
if (max_linkhdr < 20)
max_linkhdr = 20;
}
struct protosw *
pffindtype(int family, int type)
{
struct domain *dp;
struct protosw *pr;
SLIST_FOREACH(dp, &domains, dom_next)
if (dp->dom_family == family)
goto found;
return (NULL);
found:
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
if (pr->pr_type && pr->pr_type == type)
return (pr);
return (NULL);
}
struct protosw *
pffindproto(int family, int protocol, int type)
{
struct domain *dp;
struct protosw *pr;
struct protosw *maybe = NULL;
if (family == 0)
return (NULL);
SLIST_FOREACH(dp, &domains, dom_next)
if (dp->dom_family == family)
goto found;
return (NULL);
found:
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
return (pr);
if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
pr->pr_protocol == 0 && maybe == NULL)
maybe = pr;
}
return (maybe);
}
void
kpfctlinput(int cmd, struct sockaddr *sa)
{
struct domain *dp;
struct protosw *pr;
SLIST_FOREACH(dp, &domains, dom_next) {
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
so_pr_ctlinput(pr, cmd, sa, NULL);
}
}
void
kpfctlinput_direct(int cmd, struct sockaddr *sa)
{
struct domain *dp;
struct protosw *pr;
SLIST_FOREACH(dp, &domains, dom_next) {
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
so_pr_ctlinput_direct(pr, cmd, sa, NULL);
}
}
void
kpfctlinput2(int cmd, struct sockaddr *sa, void *ctlparam)
{
struct domain *dp;
struct protosw *pr;
if (!sa)
return;
SLIST_FOREACH(dp, &domains, dom_next) {
if (dp->dom_family != sa->sa_family)
continue;
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
so_pr_ctlinput(pr, cmd, sa, ctlparam);
}
}