Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_socket.c
Show First 20 Lines • Show All 517 Lines • ▼ Show 20 Lines | if (prp == NULL) { | ||||
/* No support for domain. */ | /* No support for domain. */ | ||||
if (pffinddomain(dom) == NULL) | if (pffinddomain(dom) == NULL) | ||||
return (EAFNOSUPPORT); | return (EAFNOSUPPORT); | ||||
/* No support for socket type. */ | /* No support for socket type. */ | ||||
if (proto == 0 && type != 0) | if (proto == 0 && type != 0) | ||||
return (EPROTOTYPE); | return (EPROTOTYPE); | ||||
return (EPROTONOSUPPORT); | return (EPROTONOSUPPORT); | ||||
} | } | ||||
if (prp->pr_usrreqs->pru_attach == NULL || | |||||
prp->pr_usrreqs->pru_attach == pru_attach_notsupp) | |||||
return (EPROTONOSUPPORT); | |||||
MPASS(prp->pr_attach); | |||||
if (IN_CAPABILITY_MODE(td) && (prp->pr_flags & PR_CAPATTACH) == 0) | if (IN_CAPABILITY_MODE(td) && (prp->pr_flags & PR_CAPATTACH) == 0) | ||||
return (ECAPMODE); | return (ECAPMODE); | ||||
if (prison_check_af(cred, prp->pr_domain->dom_family) != 0) | if (prison_check_af(cred, prp->pr_domain->dom_family) != 0) | ||||
return (EPROTONOSUPPORT); | return (EPROTONOSUPPORT); | ||||
if (prp->pr_type != type) | if (prp->pr_type != type) | ||||
return (EPROTOTYPE); | return (EPROTOTYPE); | ||||
Show All 21 Lines | if ((prp->pr_flags & PR_SOCKBUF) == 0) { | ||||
so->so_snd.sb_mtx = &so->so_snd_mtx; | so->so_snd.sb_mtx = &so->so_snd_mtx; | ||||
so->so_rcv.sb_mtx = &so->so_rcv_mtx; | so->so_rcv.sb_mtx = &so->so_rcv_mtx; | ||||
} | } | ||||
/* | /* | ||||
* Auto-sizing of socket buffers is managed by the protocols and | * Auto-sizing of socket buffers is managed by the protocols and | ||||
* the appropriate flags must be set in the pru_attach function. | * the appropriate flags must be set in the pru_attach function. | ||||
*/ | */ | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
error = (*prp->pr_usrreqs->pru_attach)(so, proto, td); | error = prp->pr_attach(so, proto, td); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
if (error) { | if (error) { | ||||
sodealloc(so); | sodealloc(so); | ||||
return (error); | return (error); | ||||
} | } | ||||
soref(so); | soref(so); | ||||
*aso = so; | *aso = so; | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 208 Lines • ▼ Show 20 Lines | |||||
struct socket * | struct socket * | ||||
sonewconn(struct socket *head, int connstatus) | sonewconn(struct socket *head, int connstatus) | ||||
{ | { | ||||
struct socket *so; | struct socket *so; | ||||
if ((so = solisten_clone(head)) == NULL) | if ((so = solisten_clone(head)) == NULL) | ||||
return (NULL); | return (NULL); | ||||
if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) { | if (so->so_proto->pr_attach(so, 0, NULL) != 0) { | ||||
sodealloc(so); | sodealloc(so); | ||||
log(LOG_DEBUG, "%s: pcb %p: pru_attach() failed\n", | log(LOG_DEBUG, "%s: pcb %p: pr_attach() failed\n", | ||||
__func__, head->so_pcb); | __func__, head->so_pcb); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
solisten_enqueue(so, connstatus); | solisten_enqueue(so, connstatus); | ||||
return (so); | return (so); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | knlist_init(&so->so_wrsel.si_note, so, so_wrknl_lock, so_wrknl_unlock, | ||||
so_wrknl_assert_lock); | so_wrknl_assert_lock); | ||||
VNET_SO_ASSERT(head); | VNET_SO_ASSERT(head); | ||||
if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) { | if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) { | ||||
sodealloc(so); | sodealloc(so); | ||||
log(LOG_DEBUG, "%s: pcb %p: soreserve() failed\n", | log(LOG_DEBUG, "%s: pcb %p: soreserve() failed\n", | ||||
__func__, head->so_pcb); | __func__, head->so_pcb); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) { | if ((*so->so_proto->pr_attach)(so, 0, NULL)) { | ||||
sodealloc(so); | sodealloc(so); | ||||
log(LOG_DEBUG, "%s: pcb %p: pru_attach() failed\n", | log(LOG_DEBUG, "%s: pcb %p: pru_attach() failed\n", | ||||
__func__, head->so_pcb); | __func__, head->so_pcb); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
so->so_rcv.sb_lowat = head->so_rcv.sb_lowat; | so->so_rcv.sb_lowat = head->so_rcv.sb_lowat; | ||||
so->so_snd.sb_lowat = head->so_snd.sb_lowat; | so->so_snd.sb_lowat = head->so_snd.sb_lowat; | ||||
so->so_rcv.sb_timeo = head->so_rcv.sb_timeo; | so->so_rcv.sb_timeo = head->so_rcv.sb_timeo; | ||||
so->so_snd.sb_timeo = head->so_snd.sb_timeo; | so->so_snd.sb_timeo = head->so_snd.sb_timeo; | ||||
so->so_rcv.sb_flags |= head->so_rcv.sb_flags & SB_AUTOSIZE; | so->so_rcv.sb_flags |= head->so_rcv.sb_flags & SB_AUTOSIZE; | ||||
so->so_snd.sb_flags |= head->so_snd.sb_flags & SB_AUTOSIZE; | so->so_snd.sb_flags |= head->so_snd.sb_flags & SB_AUTOSIZE; | ||||
soref(so); | soref(so); | ||||
return (so); | return (so); | ||||
} | } | ||||
#endif /* SCTP */ | #endif /* SCTP */ | ||||
int | int | ||||
sobind(struct socket *so, struct sockaddr *nam, struct thread *td) | sobind(struct socket *so, struct sockaddr *nam, struct thread *td) | ||||
{ | { | ||||
int error; | int error; | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, td); | error = so->so_proto->pr_bind(so, nam, td); | ||||
Lint: Possible Spelling Mistake: Possible spelling error. You wrote 'nam', but did you mean 'name'? | |||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
sobindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) | sobindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td) | ||||
{ | { | ||||
int error; | int error; | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
error = (*so->so_proto->pr_usrreqs->pru_bindat)(fd, so, nam, td); | error = so->so_proto->pr_bindat(fd, so, nam, td); | ||||
Lint: Possible Spelling Mistake Possible spelling error. You wrote 'nam', but did you mean 'name'? Lint: Possible Spelling Mistake: Possible spelling error. You wrote 'nam', but did you mean 'name'? | |||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* solisten() transitions a socket from a non-listening state to a listening | * solisten() transitions a socket from a non-listening state to a listening | ||||
* state, but can also be used to update the listen queue depth on an | * state, but can also be used to update the listen queue depth on an | ||||
* existing listen socket. The protocol will call back into the sockets | * existing listen socket. The protocol will call back into the sockets | ||||
* layer using solisten_proto_check() and solisten_proto() to check and set | * layer using solisten_proto_check() and solisten_proto() to check and set | ||||
* socket-layer listen state. Call backs are used so that the protocol can | * socket-layer listen state. Call backs are used so that the protocol can | ||||
* acquire both protocol and socket layer locks in whatever order is required | * acquire both protocol and socket layer locks in whatever order is required | ||||
* by the protocol. | * by the protocol. | ||||
* | * | ||||
* Protocol implementors are advised to hold the socket lock across the | * Protocol implementors are advised to hold the socket lock across the | ||||
* socket-layer test and set to avoid races at the socket layer. | * socket-layer test and set to avoid races at the socket layer. | ||||
*/ | */ | ||||
int | int | ||||
solisten(struct socket *so, int backlog, struct thread *td) | solisten(struct socket *so, int backlog, struct thread *td) | ||||
{ | { | ||||
int error; | int error; | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
error = (*so->so_proto->pr_usrreqs->pru_listen)(so, backlog, td); | error = so->so_proto->pr_listen(so, backlog, td); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Prepare for a call to solisten_proto(). Acquire all socket buffer locks in | * Prepare for a call to solisten_proto(). Acquire all socket buffer locks in | ||||
* order to interlock with socket I/O. | * order to interlock with socket I/O. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 208 Lines • ▼ Show 20 Lines | sofree(struct socket *so) | ||||
if (so->so_dtor != NULL) | if (so->so_dtor != NULL) | ||||
so->so_dtor(so); | so->so_dtor(so); | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
if ((pr->pr_flags & PR_RIGHTS) && !SOLISTENING(so)) { | if ((pr->pr_flags & PR_RIGHTS) && !SOLISTENING(so)) { | ||||
MPASS(pr->pr_domain->dom_dispose != NULL); | MPASS(pr->pr_domain->dom_dispose != NULL); | ||||
(*pr->pr_domain->dom_dispose)(so); | (*pr->pr_domain->dom_dispose)(so); | ||||
} | } | ||||
if (pr->pr_usrreqs->pru_detach != NULL) | if (pr->pr_detach != NULL) | ||||
(*pr->pr_usrreqs->pru_detach)(so); | pr->pr_detach(so); | ||||
/* | /* | ||||
* From this point on, we assume that no other references to this | * From this point on, we assume that no other references to this | ||||
* socket exist anywhere else in the stack. Therefore, no locks need | * socket exist anywhere else in the stack. Therefore, no locks need | ||||
* to be acquired or held. | * to be acquired or held. | ||||
*/ | */ | ||||
if (!(pr->pr_flags & PR_SOCKBUF) && !SOLISTENING(so)) { | if (!(pr->pr_flags & PR_SOCKBUF) && !SOLISTENING(so)) { | ||||
sbdestroy(so, SO_SND); | sbdestroy(so, SO_SND); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | if ((so->so_options & SO_LINGER) != 0 && so->so_linger != 0) { | ||||
so->so_linger * hz); | so->so_linger * hz); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
drop: | drop: | ||||
if (so->so_proto->pr_usrreqs->pru_close != NULL) | if (so->so_proto->pr_close != NULL) | ||||
(*so->so_proto->pr_usrreqs->pru_close)(so); | so->so_proto->pr_close(so); | ||||
SOCK_LOCK(so); | SOCK_LOCK(so); | ||||
if ((listening = SOLISTENING(so))) { | if ((listening = SOLISTENING(so))) { | ||||
struct socket *sp; | struct socket *sp; | ||||
TAILQ_INIT(&lqueue); | TAILQ_INIT(&lqueue); | ||||
TAILQ_SWAP(&lqueue, &so->sol_incomp, socket, so_list); | TAILQ_SWAP(&lqueue, &so->sol_incomp, socket, so_list); | ||||
TAILQ_CONCAT(&lqueue, &so->sol_comp, so_list); | TAILQ_CONCAT(&lqueue, &so->sol_comp, so_list); | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
* descriptor and protocol, we asserted that none of them are being held. | * descriptor and protocol, we asserted that none of them are being held. | ||||
*/ | */ | ||||
void | void | ||||
soabort(struct socket *so) | soabort(struct socket *so) | ||||
{ | { | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
if (so->so_proto->pr_usrreqs->pru_abort != NULL) | if (so->so_proto->pr_abort != NULL) | ||||
(*so->so_proto->pr_usrreqs->pru_abort)(so); | so->so_proto->pr_abort(so); | ||||
SOCK_LOCK(so); | SOCK_LOCK(so); | ||||
sorele_locked(so); | sorele_locked(so); | ||||
} | } | ||||
int | int | ||||
soaccept(struct socket *so, struct sockaddr **nam) | soaccept(struct socket *so, struct sockaddr **nam) | ||||
{ | { | ||||
int error; | int error; | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam); | error = so->so_proto->pr_accept(so, nam); | ||||
Lint: Possible Spelling Mistake Possible spelling error. You wrote 'nam', but did you mean 'name'? Lint: Possible Spelling Mistake: Possible spelling error. You wrote 'nam', but did you mean 'name'? | |||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
soconnect(struct socket *so, struct sockaddr *nam, struct thread *td) | soconnect(struct socket *so, struct sockaddr *nam, struct thread *td) | ||||
{ | { | ||||
Show All 17 Lines | if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && | ||||
error = EISCONN; | error = EISCONN; | ||||
} else { | } else { | ||||
/* | /* | ||||
* Prevent accumulated error from previous connection from | * Prevent accumulated error from previous connection from | ||||
* biting us. | * biting us. | ||||
*/ | */ | ||||
so->so_error = 0; | so->so_error = 0; | ||||
if (fd == AT_FDCWD) { | if (fd == AT_FDCWD) { | ||||
error = (*so->so_proto->pr_usrreqs->pru_connect)(so, | error = so->so_proto->pr_connect(so, nam, td); | ||||
Lint: Possible Spelling Mistake Possible spelling error. You wrote 'nam', but did you mean 'name'? Lint: Possible Spelling Mistake: Possible spelling error. You wrote 'nam', but did you mean 'name'? | |||||
nam, td); | |||||
} else { | } else { | ||||
error = (*so->so_proto->pr_usrreqs->pru_connectat)(fd, | error = so->so_proto->pr_connectat(fd, so, nam, td); | ||||
Lint: Possible Spelling Mistake Possible spelling error. You wrote 'nam', but did you mean 'name'? Lint: Possible Spelling Mistake: Possible spelling error. You wrote 'nam', but did you mean 'name'? | |||||
so, nam, td); | |||||
} | } | ||||
} | } | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
soconnect2(struct socket *so1, struct socket *so2) | soconnect2(struct socket *so1, struct socket *so2) | ||||
{ | { | ||||
int error; | int error; | ||||
CURVNET_SET(so1->so_vnet); | CURVNET_SET(so1->so_vnet); | ||||
error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2); | error = so1->so_proto->pr_connect2(so1, so2); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
sodisconnect(struct socket *so) | sodisconnect(struct socket *so) | ||||
{ | { | ||||
int error; | int error; | ||||
if ((so->so_state & SS_ISCONNECTED) == 0) | if ((so->so_state & SS_ISCONNECTED) == 0) | ||||
return (ENOTCONN); | return (ENOTCONN); | ||||
if (so->so_state & SS_ISDISCONNECTING) | if (so->so_state & SS_ISDISCONNECTING) | ||||
return (EALREADY); | return (EALREADY); | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so); | error = so->so_proto->pr_disconnect(so); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, | sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, | ||||
struct mbuf *top, struct mbuf *control, int flags, struct thread *td) | struct mbuf *top, struct mbuf *control, int flags, struct thread *td) | ||||
{ | { | ||||
long space; | long space; | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, | ||||
* XXX all the SBS_CANTSENDMORE checks previously done could be out | * XXX all the SBS_CANTSENDMORE checks previously done could be out | ||||
* of date. We could have received a reset packet in an interrupt or | * of date. We could have received a reset packet in an interrupt or | ||||
* maybe we slept while doing page faults in uiomove() etc. We could | * maybe we slept while doing page faults in uiomove() etc. We could | ||||
* probably recheck again inside the locking protection here, but | * probably recheck again inside the locking protection here, but | ||||
* there are probably other places that this also happens. We must | * there are probably other places that this also happens. We must | ||||
* rethink this. | * rethink this. | ||||
*/ | */ | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
error = (*so->so_proto->pr_usrreqs->pru_send)(so, | error = so->so_proto->pr_send(so, (flags & MSG_OOB) ? PRUS_OOB : | ||||
(flags & MSG_OOB) ? PRUS_OOB : | |||||
/* | /* | ||||
* If the user set MSG_EOF, the protocol understands this flag and | * If the user set MSG_EOF, the protocol understands this flag and | ||||
* nothing left to send then use PRU_SEND_EOF instead of PRU_SEND. | * nothing left to send then use PRU_SEND_EOF instead of PRU_SEND. | ||||
*/ | */ | ||||
((flags & MSG_EOF) && | ((flags & MSG_EOF) && | ||||
(so->so_proto->pr_flags & PR_IMPLOPCL) && | (so->so_proto->pr_flags & PR_IMPLOPCL) && | ||||
(resid <= 0)) ? | (resid <= 0)) ? | ||||
PRUS_EOF : | PRUS_EOF : | ||||
Show All 33 Lines | |||||
int | int | ||||
sosend_generic(struct socket *so, struct sockaddr *addr, struct uio *uio, | sosend_generic(struct socket *so, struct sockaddr *addr, struct uio *uio, | ||||
struct mbuf *top, struct mbuf *control, int flags, struct thread *td) | struct mbuf *top, struct mbuf *control, int flags, struct thread *td) | ||||
{ | { | ||||
long space; | long space; | ||||
ssize_t resid; | ssize_t resid; | ||||
int clen = 0, error, dontroute; | int clen = 0, error, dontroute; | ||||
int atomic = sosendallatonce(so) || top; | int atomic = sosendallatonce(so) || top; | ||||
int pru_flag; | int pr_send_flag; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
struct ktls_session *tls; | struct ktls_session *tls; | ||||
int tls_enq_cnt, tls_pruflag; | int tls_enq_cnt, tls_send_flag; | ||||
uint8_t tls_rtype; | uint8_t tls_rtype; | ||||
tls = NULL; | tls = NULL; | ||||
tls_rtype = TLS_RLTYPE_APP; | tls_rtype = TLS_RLTYPE_APP; | ||||
#endif | #endif | ||||
if (uio != NULL) | if (uio != NULL) | ||||
resid = uio->uio_resid; | resid = uio->uio_resid; | ||||
else if ((top->m_flags & M_PKTHDR) != 0) | else if ((top->m_flags & M_PKTHDR) != 0) | ||||
Show All 23 Lines | #endif | ||||
if (control != NULL) | if (control != NULL) | ||||
clen = control->m_len; | clen = control->m_len; | ||||
error = SOCK_IO_SEND_LOCK(so, SBLOCKWAIT(flags)); | error = SOCK_IO_SEND_LOCK(so, SBLOCKWAIT(flags)); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
tls_pruflag = 0; | tls_send_flag = 0; | ||||
tls = ktls_hold(so->so_snd.sb_tls_info); | tls = ktls_hold(so->so_snd.sb_tls_info); | ||||
if (tls != NULL) { | if (tls != NULL) { | ||||
if (tls->mode == TCP_TLS_MODE_SW) | if (tls->mode == TCP_TLS_MODE_SW) | ||||
tls_pruflag = PRUS_NOTREADY; | tls_send_flag = PRUS_NOTREADY; | ||||
if (control != NULL) { | if (control != NULL) { | ||||
struct cmsghdr *cm = mtod(control, struct cmsghdr *); | struct cmsghdr *cm = mtod(control, struct cmsghdr *); | ||||
if (clen >= sizeof(*cm) && | if (clen >= sizeof(*cm) && | ||||
cm->cmsg_type == TLS_SET_RECORD_TYPE) { | cm->cmsg_type == TLS_SET_RECORD_TYPE) { | ||||
tls_rtype = *((uint8_t *)CMSG_DATA(cm)); | tls_rtype = *((uint8_t *)CMSG_DATA(cm)); | ||||
clen = 0; | clen = 0; | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | #endif | ||||
* while doing page faults in uiomove() etc. We | * while doing page faults in uiomove() etc. We | ||||
* could probably recheck again inside the locking | * could probably recheck again inside the locking | ||||
* protection here, but there are probably other | * protection here, but there are probably other | ||||
* places that this also happens. We must rethink | * places that this also happens. We must rethink | ||||
* this. | * this. | ||||
*/ | */ | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
pru_flag = (flags & MSG_OOB) ? PRUS_OOB : | pr_send_flag = (flags & MSG_OOB) ? PRUS_OOB : | ||||
/* | /* | ||||
* If the user set MSG_EOF, the protocol understands | * If the user set MSG_EOF, the protocol understands | ||||
* this flag and nothing left to send then use | * this flag and nothing left to send then use | ||||
* PRU_SEND_EOF instead of PRU_SEND. | * PRU_SEND_EOF instead of PRU_SEND. | ||||
*/ | */ | ||||
((flags & MSG_EOF) && | ((flags & MSG_EOF) && | ||||
(so->so_proto->pr_flags & PR_IMPLOPCL) && | (so->so_proto->pr_flags & PR_IMPLOPCL) && | ||||
(resid <= 0)) ? | (resid <= 0)) ? | ||||
PRUS_EOF : | PRUS_EOF : | ||||
/* If there is more to send set PRUS_MORETOCOME. */ | /* If there is more to send set PRUS_MORETOCOME. */ | ||||
(flags & MSG_MORETOCOME) || | (flags & MSG_MORETOCOME) || | ||||
(resid > 0 && space > 0) ? PRUS_MORETOCOME : 0; | (resid > 0 && space > 0) ? PRUS_MORETOCOME : 0; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
pru_flag |= tls_pruflag; | pr_send_flag |= tls_send_flag; | ||||
#endif | #endif | ||||
error = (*so->so_proto->pr_usrreqs->pru_send)(so, | error = so->so_proto->pr_send(so, pr_send_flag, top, | ||||
pru_flag, top, addr, control, td); | addr, control, td); | ||||
if (dontroute) { | if (dontroute) { | ||||
SOCK_LOCK(so); | SOCK_LOCK(so); | ||||
so->so_options &= ~SO_DONTROUTE; | so->so_options &= ~SO_DONTROUTE; | ||||
SOCK_UNLOCK(so); | SOCK_UNLOCK(so); | ||||
} | } | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
Show All 31 Lines | |||||
int | int | ||||
sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, | sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, | ||||
struct mbuf *top, struct mbuf *control, int flags, struct thread *td) | struct mbuf *top, struct mbuf *control, int flags, struct thread *td) | ||||
{ | { | ||||
int error; | int error; | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
error = so->so_proto->pr_usrreqs->pru_sosend(so, addr, uio, | error = so->so_proto->pr_sosend(so, addr, uio, | ||||
top, control, flags, td); | top, control, flags, td); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* The part of soreceive() that implements reading non-inline out-of-band | * The part of soreceive() that implements reading non-inline out-of-band | ||||
* data from a socket. For more complete comments, see soreceive(), from | * data from a socket. For more complete comments, see soreceive(), from | ||||
* which this code originated. | * which this code originated. | ||||
* | * | ||||
* Note that soreceive_rcvoob(), unlike the remainder of soreceive(), is | * Note that soreceive_rcvoob(), unlike the remainder of soreceive(), is | ||||
* unable to return an mbuf chain to the caller. | * unable to return an mbuf chain to the caller. | ||||
*/ | */ | ||||
static int | static int | ||||
soreceive_rcvoob(struct socket *so, struct uio *uio, int flags) | soreceive_rcvoob(struct socket *so, struct uio *uio, int flags) | ||||
{ | { | ||||
struct protosw *pr = so->so_proto; | struct protosw *pr = so->so_proto; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
int error; | int error; | ||||
KASSERT(flags & MSG_OOB, ("soreceive_rcvoob: (flags & MSG_OOB) == 0")); | KASSERT(flags & MSG_OOB, ("soreceive_rcvoob: (flags & MSG_OOB) == 0")); | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
m = m_get(M_WAITOK, MT_DATA); | m = m_get(M_WAITOK, MT_DATA); | ||||
error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK); | error = pr->pr_rcvoob(so, m, flags & MSG_PEEK); | ||||
if (error) | if (error) | ||||
goto bad; | goto bad; | ||||
do { | do { | ||||
error = uiomove(mtod(m, void *), | error = uiomove(mtod(m, void *), | ||||
(int) min(uio->uio_resid, m->m_len), uio); | (int) min(uio->uio_resid, m->m_len), uio); | ||||
m = m_free(m); | m = m_free(m); | ||||
} while (uio->uio_resid && error == 0 && m); | } while (uio->uio_resid && error == 0 && m); | ||||
bad: | bad: | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | if (flagsp != NULL) { | ||||
flags = 0; | flags = 0; | ||||
if (flags & MSG_OOB) | if (flags & MSG_OOB) | ||||
return (soreceive_rcvoob(so, uio, flags)); | return (soreceive_rcvoob(so, uio, flags)); | ||||
if (mp != NULL) | if (mp != NULL) | ||||
*mp = NULL; | *mp = NULL; | ||||
if ((pr->pr_flags & PR_WANTRCVD) && (so->so_state & SS_ISCONFIRMING) | if ((pr->pr_flags & PR_WANTRCVD) && (so->so_state & SS_ISCONFIRMING) | ||||
&& uio->uio_resid) { | && uio->uio_resid) { | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
(*pr->pr_usrreqs->pru_rcvd)(so, 0); | pr->pr_rcvd(so, 0); | ||||
} | } | ||||
error = SOCK_IO_RECV_LOCK(so, SBLOCKWAIT(flags)); | error = SOCK_IO_RECV_LOCK(so, SBLOCKWAIT(flags)); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
restart: | restart: | ||||
SOCKBUF_LOCK(&so->so_rcv); | SOCKBUF_LOCK(&so->so_rcv); | ||||
▲ Show 20 Lines • Show All 372 Lines • ▼ Show 20 Lines | while (flags & MSG_WAITALL && m == NULL && uio->uio_resid > 0 && | ||||
break; | break; | ||||
/* | /* | ||||
* Notify the protocol that some data has been | * Notify the protocol that some data has been | ||||
* drained before blocking. | * drained before blocking. | ||||
*/ | */ | ||||
if (pr->pr_flags & PR_WANTRCVD) { | if (pr->pr_flags & PR_WANTRCVD) { | ||||
SOCKBUF_UNLOCK(&so->so_rcv); | SOCKBUF_UNLOCK(&so->so_rcv); | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
(*pr->pr_usrreqs->pru_rcvd)(so, flags); | pr->pr_rcvd(so, flags); | ||||
SOCKBUF_LOCK(&so->so_rcv); | SOCKBUF_LOCK(&so->so_rcv); | ||||
} | } | ||||
SBLASTRECORDCHK(&so->so_rcv); | SBLASTRECORDCHK(&so->so_rcv); | ||||
SBLASTMBUFCHK(&so->so_rcv); | SBLASTMBUFCHK(&so->so_rcv); | ||||
/* | /* | ||||
* We could receive some data while was notifying | * We could receive some data while was notifying | ||||
* the protocol. Skip blocking in this case. | * the protocol. Skip blocking in this case. | ||||
*/ | */ | ||||
Show All 38 Lines | if ((flags & MSG_PEEK) == 0) { | ||||
* If soreceive() is being done from the socket callback, | * If soreceive() is being done from the socket callback, | ||||
* then don't need to generate ACK to peer to update window, | * then don't need to generate ACK to peer to update window, | ||||
* since ACK will be generated on return to TCP. | * since ACK will be generated on return to TCP. | ||||
*/ | */ | ||||
if (!(flags & MSG_SOCALLBCK) && | if (!(flags & MSG_SOCALLBCK) && | ||||
(pr->pr_flags & PR_WANTRCVD)) { | (pr->pr_flags & PR_WANTRCVD)) { | ||||
SOCKBUF_UNLOCK(&so->so_rcv); | SOCKBUF_UNLOCK(&so->so_rcv); | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
(*pr->pr_usrreqs->pru_rcvd)(so, flags); | pr->pr_rcvd(so, flags); | ||||
SOCKBUF_LOCK(&so->so_rcv); | SOCKBUF_LOCK(&so->so_rcv); | ||||
} | } | ||||
} | } | ||||
SOCKBUF_LOCK_ASSERT(&so->so_rcv); | SOCKBUF_LOCK_ASSERT(&so->so_rcv); | ||||
if (orig_resid == uio->uio_resid && orig_resid && | if (orig_resid == uio->uio_resid && orig_resid && | ||||
(flags & MSG_EOR) == 0 && (so->so_rcv.sb_state & SBS_CANTRCVMORE) == 0) { | (flags & MSG_EOR) == 0 && (so->so_rcv.sb_state & SBS_CANTRCVMORE) == 0) { | ||||
SOCKBUF_UNLOCK(&so->so_rcv); | SOCKBUF_UNLOCK(&so->so_rcv); | ||||
goto restart; | goto restart; | ||||
▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | if (len > 0) | ||||
sbdrop_locked(sb, len); | sbdrop_locked(sb, len); | ||||
/* Notify protocol that we drained some data. */ | /* Notify protocol that we drained some data. */ | ||||
if ((so->so_proto->pr_flags & PR_WANTRCVD) && | if ((so->so_proto->pr_flags & PR_WANTRCVD) && | ||||
(((flags & MSG_WAITALL) && uio->uio_resid > 0) || | (((flags & MSG_WAITALL) && uio->uio_resid > 0) || | ||||
!(flags & MSG_SOCALLBCK))) { | !(flags & MSG_SOCALLBCK))) { | ||||
SOCKBUF_UNLOCK(sb); | SOCKBUF_UNLOCK(sb); | ||||
VNET_SO_ASSERT(so); | VNET_SO_ASSERT(so); | ||||
(*so->so_proto->pr_usrreqs->pru_rcvd)(so, flags); | so->so_proto->pr_rcvd(so, flags); | ||||
SOCKBUF_LOCK(sb); | SOCKBUF_LOCK(sb); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* For MSG_WAITALL we may have to loop again and wait for | * For MSG_WAITALL we may have to loop again and wait for | ||||
* more data to come in. | * more data to come in. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, | soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, | ||||
struct mbuf **mp0, struct mbuf **controlp, int *flagsp) | struct mbuf **mp0, struct mbuf **controlp, int *flagsp) | ||||
{ | { | ||||
int error; | int error; | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
error = (so->so_proto->pr_usrreqs->pru_soreceive(so, psa, uio, | error = so->so_proto->pr_soreceive(so, psa, uio, mp0, controlp, flagsp); | ||||
mp0, controlp, flagsp)); | |||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
soshutdown(struct socket *so, int how) | soshutdown(struct socket *so, int how) | ||||
{ | { | ||||
struct protosw *pr; | struct protosw *pr; | ||||
Show All 30 Lines | if (how != SHUT_WR) { | ||||
SOCK_UNLOCK(so); | SOCK_UNLOCK(so); | ||||
} | } | ||||
goto done; | goto done; | ||||
} | } | ||||
SOCK_UNLOCK(so); | SOCK_UNLOCK(so); | ||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
pr = so->so_proto; | pr = so->so_proto; | ||||
if (pr->pr_usrreqs->pru_flush != NULL) | if (pr->pr_flush != NULL) | ||||
(*pr->pr_usrreqs->pru_flush)(so, how); | pr->pr_flush(so, how); | ||||
if (how != SHUT_WR) | if (how != SHUT_WR) | ||||
sorflush(so); | sorflush(so); | ||||
if (how != SHUT_RD) { | if (how != SHUT_RD) { | ||||
error = (*pr->pr_usrreqs->pru_shutdown)(so); | error = pr->pr_shutdown(so); | ||||
wakeup(&so->so_timeo); | wakeup(&so->so_timeo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return ((error == 0 && soerror_enotconn) ? ENOTCONN : error); | return ((error == 0 && soerror_enotconn) ? ENOTCONN : error); | ||||
} | } | ||||
wakeup(&so->so_timeo); | wakeup(&so->so_timeo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
done: | done: | ||||
▲ Show 20 Lines • Show All 654 Lines • ▼ Show 20 Lines | |||||
sopoll(struct socket *so, int events, struct ucred *active_cred, | sopoll(struct socket *so, int events, struct ucred *active_cred, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
/* | /* | ||||
* We do not need to set or assert curvnet as long as everyone uses | * We do not need to set or assert curvnet as long as everyone uses | ||||
* sopoll_generic(). | * sopoll_generic(). | ||||
*/ | */ | ||||
return (so->so_proto->pr_usrreqs->pru_sopoll(so, events, active_cred, | return (so->so_proto->pr_sopoll(so, events, active_cred, td)); | ||||
td)); | |||||
} | } | ||||
int | int | ||||
sopoll_generic(struct socket *so, int events, struct ucred *active_cred, | sopoll_generic(struct socket *so, int events, struct ucred *active_cred, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
int revents; | int revents; | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | soo_kqfilter(struct file *fp, struct knote *kn) | ||||
} else { | } else { | ||||
SOCK_BUF_LOCK(so, which); | SOCK_BUF_LOCK(so, which); | ||||
knlist_add(knl, kn, 1); | knlist_add(knl, kn, 1); | ||||
sb->sb_flags |= SB_KNOTE; | sb->sb_flags |= SB_KNOTE; | ||||
SOCK_BUF_UNLOCK(so, which); | SOCK_BUF_UNLOCK(so, which); | ||||
} | } | ||||
SOCK_UNLOCK(so); | SOCK_UNLOCK(so); | ||||
return (0); | return (0); | ||||
} | |||||
/* | |||||
* Some routines that return EOPNOTSUPP for entry points that are not | |||||
* supported by a protocol. Fill in as needed. | |||||
*/ | |||||
int | |||||
pru_accept_notsupp(struct socket *so, struct sockaddr **nam) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_aio_queue_notsupp(struct socket *so, struct kaiocb *job) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_attach_notsupp(struct socket *so, int proto, struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_bind_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_bindat_notsupp(int fd, struct socket *so, struct sockaddr *nam, | |||||
struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_connect_notsupp(struct socket *so, struct sockaddr *nam, struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_connectat_notsupp(int fd, struct socket *so, struct sockaddr *nam, | |||||
struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_connect2_notsupp(struct socket *so1, struct socket *so2) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_control_notsupp(struct socket *so, u_long cmd, void *data, | |||||
struct ifnet *ifp, struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_disconnect_notsupp(struct socket *so) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_listen_notsupp(struct socket *so, int backlog, struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_peeraddr_notsupp(struct socket *so, struct sockaddr **nam) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_rcvd_notsupp(struct socket *so, int flags) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_send_notsupp(struct socket *so, int flags, struct mbuf *m, | |||||
struct sockaddr *addr, struct mbuf *control, struct thread *td) | |||||
{ | |||||
if (control != NULL) | |||||
m_freem(control); | |||||
if ((flags & PRUS_NOTREADY) == 0) | |||||
m_freem(m); | |||||
return (EOPNOTSUPP); | |||||
} | |||||
int | |||||
pru_ready_notsupp(struct socket *so, struct mbuf *m, int count) | |||||
{ | |||||
return (EOPNOTSUPP); | |||||
} | |||||
/* | |||||
* This isn't really a ``null'' operation, but it's the default one and | |||||
* doesn't do anything destructive. | |||||
*/ | |||||
int | |||||
pru_sense_null(struct socket *so, struct stat *sb) | |||||
{ | |||||
sb->st_blksize = so->so_snd.sb_hiwat; | |||||
return 0; | |||||
} | |||||
int | |||||
pru_shutdown_notsupp(struct socket *so) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_sockaddr_notsupp(struct socket *so, struct sockaddr **nam) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_sosend_notsupp(struct socket *so, struct sockaddr *addr, struct uio *uio, | |||||
struct mbuf *top, struct mbuf *control, int flags, struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_soreceive_notsupp(struct socket *so, struct sockaddr **paddr, | |||||
struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | |||||
int | |||||
pru_sopoll_notsupp(struct socket *so, int events, struct ucred *cred, | |||||
struct thread *td) | |||||
{ | |||||
return EOPNOTSUPP; | |||||
} | } | ||||
static void | static void | ||||
filt_sordetach(struct knote *kn) | filt_sordetach(struct knote *kn) | ||||
{ | { | ||||
struct socket *so = kn->kn_fp->f_data; | struct socket *so = kn->kn_fp->f_data; | ||||
so_rdknl_lock(so); | so_rdknl_lock(so); | ||||
▲ Show 20 Lines • Show All 655 Lines • Show Last 20 Lines |
Possible spelling error. You wrote 'nam', but did you mean 'name'?