int so_pru_attach_fast(struct socket *so, int proto, struct pru_attach_info *ai) { struct netmsg_pru_attach *msg; int error; error = so->so_proto->pr_usrreqs->pru_preattach(so, proto, ai); if (error) return error; msg = kmalloc(sizeof(*msg), M_LWKTMSG, M_WAITOK | M_NULLOK); if (msg == NULL) { /* * Fail to allocate message; fallback to * synchronized pru_attach. */ return so_pru_attach(so, proto, NULL /* postattach */); } netmsg_init(&msg->base, so, &netisr_afree_rport, 0, so->so_proto->pr_usrreqs->pru_attach); msg->nm_proto = proto; msg->nm_ai = NULL; /* postattach */ lwkt_sendmsg(so->so_port, &msg->base.lmsg); return 0; }
int socreate(int dom, struct socket **aso, int type, int proto, struct thread *td) { struct proc *p = td->td_proc; struct protosw *prp; struct socket *so; struct pru_attach_info ai; int error; if (proto) prp = pffindproto(dom, proto, type); else prp = pffindtype(dom, type); if (prp == 0 || prp->pr_usrreqs->pru_attach == 0) return (EPROTONOSUPPORT); if (p->p_ucred->cr_prison && jail_socket_unixiproute_only && prp->pr_domain->dom_family != PF_LOCAL && prp->pr_domain->dom_family != PF_INET && prp->pr_domain->dom_family != PF_INET6 && prp->pr_domain->dom_family != PF_ROUTE) { return (EPROTONOSUPPORT); } if (prp->pr_type != type) return (EPROTOTYPE); so = soalloc(p != 0); if (so == NULL) return (ENOBUFS); /* * Callers of socreate() presumably will connect up a descriptor * and call soclose() if they cannot. This represents our so_refs * (which should be 1) from soalloc(). */ soclrstate(so, SS_NOFDREF); /* * Set a default port for protocol processing. No action will occur * on the socket on this port until an inpcb is attached to it and * is able to match incoming packets, or until the socket becomes * available to userland. * * We normally default the socket to the protocol thread on cpu 0. * If PR_SYNC_PORT is set (unix domain sockets) there is no protocol * thread and all pr_*()/pru_*() calls are executed synchronously. */ if (prp->pr_flags & PR_SYNC_PORT) so->so_port = &netisr_sync_port; else so->so_port = cpu_portfn(0); TAILQ_INIT(&so->so_incomp); TAILQ_INIT(&so->so_comp); so->so_type = type; so->so_cred = crhold(p->p_ucred); so->so_proto = prp; ai.sb_rlimit = &p->p_rlimit[RLIMIT_SBSIZE]; ai.p_ucred = p->p_ucred; ai.fd_rdir = p->p_fd->fd_rdir; /* * Auto-sizing of socket buffers is managed by the protocols and * the appropriate flags must be set in the pru_attach function. */ error = so_pru_attach(so, proto, &ai); if (error) { sosetstate(so, SS_NOFDREF); sofree(so); /* from soalloc */ return error; } /* * NOTE: Returns referenced socket. */ *aso = so; return (0); }