Lock down a socket, milestone 1.
o Add a mutex (sb_mtx) to struct sockbuf. This protects the data in a socket buffer. The mutex in the receive buffer also protects the data in struct socket. o Determine the lock strategy for each members in struct socket. o Lock down the following members: - so_count - so_options - so_linger - so_state o Remove *_locked() socket APIs. Make the following socket APIs touching the members above now require a locked socket: - sodisconnect() - soisconnected() - soisconnecting() - soisdisconnected() - soisdisconnecting() - sofree() - soref() - sorele() - sorwakeup() - sotryfree() - sowakeup() - sowwakeup() Reviewed by: alfred
This commit is contained in:
parent
e21fb30dce
commit
243917fe3b
@ -116,15 +116,17 @@ svr4_sys_read(td, uap)
|
||||
|
||||
if (fp->f_type == DTYPE_SOCKET) {
|
||||
so = (struct socket *)fp->f_data;
|
||||
DPRINTF(("fd %d is a socket\n", SCARG(uap, fd)));
|
||||
if (so->so_state & SS_ASYNC) {
|
||||
DPRINTF(("fd %d is an ASYNC socket!\n", SCARG(uap, fd)));
|
||||
}
|
||||
DPRINTF(("Here are its flags: 0x%x\n", so->so_state));
|
||||
#if defined(GROTTY_READ_HACK)
|
||||
SOCK_LOCK(so);
|
||||
so_state = so->so_state;
|
||||
#if defined(GROTTY_READ_HACK)
|
||||
so->so_state &= ~SS_NBIO;
|
||||
#endif
|
||||
SOCK_UNLOCK(so);
|
||||
DPRINTF(("fd %d is a socket\n", SCARG(uap, fd)));
|
||||
if (so_state & SS_ASYNC) {
|
||||
DPRINTF(("fd %d is an ASYNC socket!\n", SCARG(uap, fd)));
|
||||
}
|
||||
DPRINTF(("Here are its flags: 0x%x\n", so_state));
|
||||
}
|
||||
|
||||
rv = read(td, &ra);
|
||||
@ -140,7 +142,9 @@ svr4_sys_read(td, uap)
|
||||
|
||||
#if defined(GROTTY_READ_HACK)
|
||||
if (so) { /* We've already checked to see if this is a socket */
|
||||
SOCK_LOCK(so);
|
||||
so->so_state = so_state;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
#endif
|
||||
fdrop(fp, td);
|
||||
|
@ -29,10 +29,12 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/systm.h>
|
||||
@ -93,6 +95,7 @@ svr4_sys_ioctl(td, uap)
|
||||
char c;
|
||||
int num;
|
||||
int argsiz;
|
||||
int sostate;
|
||||
|
||||
svr4_decode_cmd(SCARG(uap, com), dir, &c, &num, &argsiz);
|
||||
|
||||
@ -113,7 +116,10 @@ svr4_sys_ioctl(td, uap)
|
||||
#if defined(DEBUG_SVR4)
|
||||
if (fp->f_type == DTYPE_SOCKET) {
|
||||
struct socket *so = (struct socket *)fp->f_data;
|
||||
DPRINTF(("<<< IN: so_state = 0x%x\n", so->so_state));
|
||||
SOCK_LOCK(so);
|
||||
sostate = so->so_state;
|
||||
SOCK_UNLOCK(so);
|
||||
DPRINTF(("<<< IN: so_state = 0x%x\n", sostate));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -158,7 +164,10 @@ svr4_sys_ioctl(td, uap)
|
||||
struct socket *so;
|
||||
|
||||
so = (struct socket *)fp->f_data;
|
||||
DPRINTF((">>> OUT: so_state = 0x%x\n", so->so_state));
|
||||
SOCK_LOCK(so);
|
||||
sostate = so->so_state;
|
||||
SOCK_UNLOCK(so);
|
||||
DPRINTF((">>> OUT: so_state = 0x%x\n", sostate));
|
||||
}
|
||||
#endif
|
||||
error = (*fun)(fp, td, retval, SCARG(uap, fd), cmd, SCARG(uap, data));
|
||||
|
@ -203,26 +203,32 @@ fifo_open(ap)
|
||||
}
|
||||
fip->fi_readers = fip->fi_writers = 0;
|
||||
wso->so_snd.sb_lowat = PIPE_BUF;
|
||||
SOCK_LOCK(rso);
|
||||
rso->so_state |= SS_CANTRCVMORE;
|
||||
SOCK_UNLOCK(rso);
|
||||
}
|
||||
if (ap->a_mode & FREAD) {
|
||||
fip->fi_readers++;
|
||||
if (fip->fi_readers == 1) {
|
||||
SOCK_LOCK(fip->fi_writesock);
|
||||
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
|
||||
if (fip->fi_writers > 0) {
|
||||
wakeup((caddr_t)&fip->fi_writers);
|
||||
sowwakeup(fip->fi_writesock);
|
||||
}
|
||||
SOCK_UNLOCK(fip->fi_writesock);
|
||||
}
|
||||
}
|
||||
if (ap->a_mode & FWRITE) {
|
||||
fip->fi_writers++;
|
||||
if (fip->fi_writers == 1) {
|
||||
SOCK_LOCK(fip->fi_readsock);
|
||||
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
|
||||
if (fip->fi_readers > 0) {
|
||||
wakeup((caddr_t)&fip->fi_readers);
|
||||
sorwakeup(fip->fi_writesock);
|
||||
}
|
||||
SOCK_UNLOCK(fip->fi_readsock);
|
||||
}
|
||||
}
|
||||
if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
|
||||
@ -282,15 +288,21 @@ fifo_read(ap)
|
||||
#endif
|
||||
if (uio->uio_resid == 0)
|
||||
return (0);
|
||||
if (ap->a_ioflag & IO_NDELAY)
|
||||
if (ap->a_ioflag & IO_NDELAY) {
|
||||
SOCK_LOCK(rso);
|
||||
rso->so_state |= SS_NBIO;
|
||||
SOCK_UNLOCK(rso);
|
||||
}
|
||||
startresid = uio->uio_resid;
|
||||
VOP_UNLOCK(ap->a_vp, 0, td);
|
||||
error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0,
|
||||
(struct mbuf **)0, (int *)0);
|
||||
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||
if (ap->a_ioflag & IO_NDELAY)
|
||||
if (ap->a_ioflag & IO_NDELAY) {
|
||||
SOCK_LOCK(rso);
|
||||
rso->so_state &= ~SS_NBIO;
|
||||
SOCK_UNLOCK(rso);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -315,14 +327,20 @@ fifo_write(ap)
|
||||
if (ap->a_uio->uio_rw != UIO_WRITE)
|
||||
panic("fifo_write mode");
|
||||
#endif
|
||||
if (ap->a_ioflag & IO_NDELAY)
|
||||
if (ap->a_ioflag & IO_NDELAY) {
|
||||
SOCK_LOCK(wso);
|
||||
wso->so_state |= SS_NBIO;
|
||||
SOCK_UNLOCK(wso);
|
||||
}
|
||||
VOP_UNLOCK(ap->a_vp, 0, td);
|
||||
error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0,
|
||||
(struct mbuf *)0, 0, td);
|
||||
vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||
if (ap->a_ioflag & IO_NDELAY)
|
||||
if (ap->a_ioflag & IO_NDELAY) {
|
||||
SOCK_LOCK(wso);
|
||||
wso->so_state &= ~SS_NBIO;
|
||||
SOCK_UNLOCK(wso);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -412,10 +430,13 @@ filt_fiforead(struct knote *kn, long hint)
|
||||
struct socket *so = (struct socket *)kn->kn_hook;
|
||||
|
||||
kn->kn_data = so->so_rcv.sb_cc;
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
kn->kn_flags |= EV_EOF;
|
||||
return (1);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
kn->kn_flags &= ~EV_EOF;
|
||||
return (kn->kn_data > 0);
|
||||
}
|
||||
@ -436,10 +457,13 @@ filt_fifowrite(struct knote *kn, long hint)
|
||||
struct socket *so = (struct socket *)kn->kn_hook;
|
||||
|
||||
kn->kn_data = sbspace(&so->so_snd);
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTSENDMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
kn->kn_flags |= EV_EOF;
|
||||
return (1);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
kn->kn_flags &= ~EV_EOF;
|
||||
return (kn->kn_data >= so->so_snd.sb_lowat);
|
||||
}
|
||||
|
@ -43,24 +43,26 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/unpcb.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <fs/portalfs/portal.h>
|
||||
|
||||
static int portal_fileid = PORTAL_ROOTFILEID+1;
|
||||
@ -182,8 +184,12 @@ portal_connect(so, so2)
|
||||
if (so->so_type != so2->so_type)
|
||||
return (EPROTOTYPE);
|
||||
|
||||
if ((so2->so_options & SO_ACCEPTCONN) == 0)
|
||||
SOCK_LOCK(so2);
|
||||
if ((so2->so_options & SO_ACCEPTCONN) == 0) {
|
||||
SOCK_UNLOCK(so2);
|
||||
return (ECONNREFUSED);
|
||||
}
|
||||
SOCK_UNLOCK(so2);
|
||||
|
||||
if ((so3 = sonewconn(so2, 0)) == 0)
|
||||
return (ECONNREFUSED);
|
||||
@ -280,14 +286,17 @@ portal_open(ap)
|
||||
* and keep polling the reference count. XXX.
|
||||
*/
|
||||
s = splnet();
|
||||
SOCK_LOCK(so);
|
||||
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
|
||||
if (fmp->pm_server->f_count == 1) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ECONNREFUSED;
|
||||
splx(s);
|
||||
goto bad;
|
||||
}
|
||||
(void) tsleep((caddr_t) &so->so_timeo, PSOCK, "portalcon", 5 * hz);
|
||||
(void) msleep((caddr_t) &so->so_timeo, SOCK_MTX(so), PSOCK, "portalcon", 5 * hz);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
|
||||
if (so->so_error) {
|
||||
|
@ -1777,19 +1777,22 @@ fgetsock(struct thread *td, int fd, struct socket **spp, u_int *fflagp)
|
||||
*spp = (struct socket *)fp->f_data;
|
||||
if (fflagp)
|
||||
*fflagp = fp->f_flag;
|
||||
SOCK_LOCK(*spp);
|
||||
soref(*spp);
|
||||
SOCK_UNLOCK(*spp);
|
||||
}
|
||||
FILEDESC_UNLOCK(td->td_proc->p_fd);
|
||||
return(error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop the reference count on the the socket and XXX release the SX lock in
|
||||
* the future. The last reference closes the socket.
|
||||
* Drop the reference count on the the socket and release the lock.
|
||||
* The last reference closes the socket. The socket must be unlocked.
|
||||
*/
|
||||
void
|
||||
fputsock(struct socket *so)
|
||||
{
|
||||
SOCK_LOCK(so);
|
||||
sorele(so);
|
||||
}
|
||||
|
||||
|
@ -104,13 +104,16 @@ soo_ioctl(fp, cmd, data, td)
|
||||
switch (cmd) {
|
||||
|
||||
case FIONBIO:
|
||||
SOCK_LOCK(so);
|
||||
if (*(int *)data)
|
||||
so->so_state |= SS_NBIO;
|
||||
else
|
||||
so->so_state &= ~SS_NBIO;
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
|
||||
case FIOASYNC:
|
||||
SOCK_LOCK(so);
|
||||
if (*(int *)data) {
|
||||
so->so_state |= SS_ASYNC;
|
||||
so->so_rcv.sb_flags |= SB_ASYNC;
|
||||
@ -120,6 +123,7 @@ soo_ioctl(fp, cmd, data, td)
|
||||
so->so_rcv.sb_flags &= ~SB_ASYNC;
|
||||
so->so_snd.sb_flags &= ~SB_ASYNC;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
|
||||
case FIONREAD:
|
||||
@ -141,7 +145,9 @@ soo_ioctl(fp, cmd, data, td)
|
||||
return (0);
|
||||
|
||||
case SIOCATMARK:
|
||||
SOCK_LOCK(so);
|
||||
*(int *)data = (so->so_state&SS_RCVATMARK) != 0;
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
@ -181,11 +187,13 @@ soo_stat(fp, ub, td)
|
||||
* If SS_CANTRCVMORE is set, but there's still data left in the
|
||||
* receive buffer, the socket is still readable.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_CANTRCVMORE) == 0 ||
|
||||
so->so_rcv.sb_cc != 0)
|
||||
ub->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
|
||||
if ((so->so_state & SS_CANTSENDMORE) == 0)
|
||||
ub->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
|
||||
SOCK_UNLOCK(so);
|
||||
ub->st_size = so->so_rcv.sb_cc;
|
||||
ub->st_uid = so->so_cred->cr_uid;
|
||||
ub->st_gid = so->so_cred->cr_gid;
|
||||
|
@ -35,11 +35,13 @@
|
||||
*/
|
||||
|
||||
#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/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/systm.h>
|
||||
#include <vm/uma.h>
|
||||
|
@ -102,71 +102,56 @@ soisconnecting(so)
|
||||
register struct socket *so;
|
||||
{
|
||||
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
|
||||
so->so_state |= SS_ISCONNECTING;
|
||||
}
|
||||
|
||||
void
|
||||
soisconnected_locked(so)
|
||||
struct socket *so;
|
||||
{
|
||||
struct socket *head = so->so_head;
|
||||
|
||||
so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
|
||||
so->so_state |= SS_ISCONNECTED;
|
||||
if (head && (so->so_state & SS_INCOMP)) {
|
||||
if ((so->so_options & SO_ACCEPTFILTER) != 0) {
|
||||
so->so_upcall = head->so_accf->so_accept_filter->accf_callback;
|
||||
so->so_upcallarg = head->so_accf->so_accept_filter_arg;
|
||||
so->so_rcv.sb_flags |= SB_UPCALL;
|
||||
so->so_options &= ~SO_ACCEPTFILTER;
|
||||
so->so_upcall(so, so->so_upcallarg, 0);
|
||||
return;
|
||||
}
|
||||
TAILQ_REMOVE(&head->so_incomp, so, so_list);
|
||||
head->so_incqlen--;
|
||||
so->so_state &= ~SS_INCOMP;
|
||||
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
|
||||
head->so_qlen++;
|
||||
so->so_state |= SS_COMP;
|
||||
sorwakeup_locked(head);
|
||||
wakeup_one(&head->so_timeo);
|
||||
} else {
|
||||
wakeup(&so->so_timeo);
|
||||
sorwakeup_locked(so);
|
||||
sowwakeup_locked(so);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
soisconnected(so)
|
||||
struct socket *so;
|
||||
{
|
||||
struct socket *head = so->so_head;
|
||||
struct socket *head;
|
||||
so_upcall_t *upcp;
|
||||
void *upcarg;
|
||||
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
head = so->so_head;
|
||||
so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
|
||||
so->so_state |= SS_ISCONNECTED;
|
||||
if (head && (so->so_state & SS_INCOMP)) {
|
||||
if ((so->so_options & SO_ACCEPTFILTER) != 0) {
|
||||
so->so_upcall = head->so_accf->so_accept_filter->accf_callback;
|
||||
so->so_upcallarg = head->so_accf->so_accept_filter_arg;
|
||||
SOCK_UNLOCK(so);
|
||||
SOCK_LOCK(head);
|
||||
upcp = head->so_accf->so_accept_filter->accf_callback;
|
||||
upcarg = head->so_accf->so_accept_filter_arg;
|
||||
SOCK_UNLOCK(head);
|
||||
SOCK_LOCK(so);
|
||||
so->so_upcall = upcp;
|
||||
so->so_upcallarg = upcarg;
|
||||
so->so_rcv.sb_flags |= SB_UPCALL;
|
||||
so->so_options &= ~SO_ACCEPTFILTER;
|
||||
so->so_upcall(so, so->so_upcallarg, 0);
|
||||
SOCK_UNLOCK(so);
|
||||
so->so_upcall(so, upcarg, 0);
|
||||
SOCK_LOCK(so);
|
||||
return;
|
||||
}
|
||||
so->so_state &= ~SS_INCOMP;
|
||||
so->so_state |= SS_COMP;
|
||||
SOCK_UNLOCK(so);
|
||||
SOCK_LOCK(head);
|
||||
TAILQ_REMOVE(&head->so_incomp, so, so_list);
|
||||
head->so_incqlen--;
|
||||
so->so_state &= ~SS_INCOMP;
|
||||
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
|
||||
head->so_qlen++;
|
||||
so->so_state |= SS_COMP;
|
||||
sorwakeup_locked(head);
|
||||
sorwakeup(head);
|
||||
wakeup_one(&head->so_timeo);
|
||||
SOCK_UNLOCK(head);
|
||||
SOCK_LOCK(so);
|
||||
} else {
|
||||
wakeup(&so->so_timeo);
|
||||
sorwakeup_locked(so);
|
||||
sowwakeup_locked(so);
|
||||
sorwakeup(so);
|
||||
sowwakeup(so);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,23 +160,12 @@ soisdisconnecting(so)
|
||||
register struct socket *so;
|
||||
{
|
||||
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
|
||||
wakeup((caddr_t)&so->so_timeo);
|
||||
sowwakeup_locked(so);
|
||||
sorwakeup_locked(so);
|
||||
}
|
||||
|
||||
void
|
||||
soisdisconnected_locked(so)
|
||||
register struct socket *so;
|
||||
{
|
||||
|
||||
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
|
||||
so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
|
||||
wakeup((caddr_t)&so->so_timeo);
|
||||
sowwakeup_locked(so);
|
||||
sorwakeup_locked(so);
|
||||
sowwakeup(so);
|
||||
sorwakeup(so);
|
||||
}
|
||||
|
||||
void
|
||||
@ -199,7 +173,12 @@ soisdisconnected(so)
|
||||
register struct socket *so;
|
||||
{
|
||||
|
||||
soisdisconnected_locked(so);
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
|
||||
so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
|
||||
wakeup((caddr_t)&so->so_timeo);
|
||||
sowwakeup(so);
|
||||
sorwakeup(so);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -224,25 +203,32 @@ sonewconn(head, connstatus)
|
||||
so = soalloc(0);
|
||||
if (so == NULL)
|
||||
return ((struct socket *)0);
|
||||
SOCK_LOCK(head);
|
||||
if ((head->so_options & SO_ACCEPTFILTER) != 0)
|
||||
connstatus = 0;
|
||||
SOCK_UNLOCK(head);
|
||||
so->so_head = head;
|
||||
so->so_type = head->so_type;
|
||||
SOCK_LOCK(so);
|
||||
so->so_options = head->so_options &~ SO_ACCEPTCONN;
|
||||
so->so_linger = head->so_linger;
|
||||
so->so_state = head->so_state | SS_NOFDREF;
|
||||
SOCK_UNLOCK(so);
|
||||
so->so_proto = head->so_proto;
|
||||
so->so_timeo = head->so_timeo;
|
||||
so->so_cred = crhold(head->so_cred);
|
||||
if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat) ||
|
||||
(*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
return ((struct socket *)0);
|
||||
}
|
||||
|
||||
if (connstatus) {
|
||||
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_COMP;
|
||||
SOCK_UNLOCK(so);
|
||||
head->so_qlen++;
|
||||
} else {
|
||||
if (head->so_incqlen >= head->so_qlimit) {
|
||||
@ -251,13 +237,19 @@ sonewconn(head, connstatus)
|
||||
(void) soabort(sp);
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_INCOMP;
|
||||
SOCK_UNLOCK(so);
|
||||
head->so_incqlen++;
|
||||
}
|
||||
if (connstatus) {
|
||||
sorwakeup_locked(head);
|
||||
SOCK_LOCK(head);
|
||||
sorwakeup(head);
|
||||
wakeup((caddr_t)&head->so_timeo);
|
||||
SOCK_UNLOCK(head);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= connstatus;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
return (so);
|
||||
}
|
||||
@ -277,8 +269,10 @@ socantsendmore(so)
|
||||
struct socket *so;
|
||||
{
|
||||
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_CANTSENDMORE;
|
||||
sowwakeup_locked(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
void
|
||||
@ -286,8 +280,10 @@ socantrcvmore(so)
|
||||
struct socket *so;
|
||||
{
|
||||
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_CANTRCVMORE;
|
||||
sorwakeup_locked(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -336,6 +332,7 @@ sowakeup(so, sb)
|
||||
register struct socket *so;
|
||||
register struct sockbuf *sb;
|
||||
{
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
|
||||
selwakeup(&sb->sb_sel);
|
||||
sb->sb_flags &= ~SB_SEL;
|
||||
@ -343,13 +340,23 @@ sowakeup(so, sb)
|
||||
sb->sb_flags &= ~SB_WAIT;
|
||||
wakeup((caddr_t)&sb->sb_cc);
|
||||
}
|
||||
if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL)
|
||||
if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) {
|
||||
SOCK_UNLOCK(so);
|
||||
pgsigio(&so->so_sigio, SIGIO, 0);
|
||||
if (sb->sb_flags & SB_UPCALL)
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
if (sb->sb_flags & SB_UPCALL) {
|
||||
SOCK_UNLOCK(so);
|
||||
(*so->so_upcall)(so, so->so_upcallarg, M_DONTWAIT);
|
||||
if (sb->sb_flags & SB_AIO)
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
if (sb->sb_flags & SB_AIO) {
|
||||
SOCK_UNLOCK(so);
|
||||
aio_swake(so, sb);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
KNOTE(&sb->sb_sel.si_note, 0);
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -959,9 +966,11 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
|
||||
xso->xso_len = sizeof *xso;
|
||||
xso->xso_so = so;
|
||||
xso->so_type = so->so_type;
|
||||
SOCK_LOCK(so);
|
||||
xso->so_options = so->so_options;
|
||||
xso->so_linger = so->so_linger;
|
||||
xso->so_state = so->so_state;
|
||||
SOCK_UNLOCK(so);
|
||||
xso->so_pcb = so->so_pcb;
|
||||
xso->xso_protocol = so->so_proto->pr_protocol;
|
||||
xso->xso_family = so->so_proto->pr_domain->dom_family;
|
||||
|
@ -82,6 +82,7 @@ static struct filterops sowrite_filtops =
|
||||
|
||||
uma_zone_t socket_zone;
|
||||
so_gen_t so_gencnt; /* generation count for sockets */
|
||||
struct mtx socq_lock;
|
||||
|
||||
MALLOC_DEFINE(M_SONAME, "soname", "socket name");
|
||||
MALLOC_DEFINE(M_PCB, "pcb", "protocol control block");
|
||||
@ -129,7 +130,8 @@ soalloc(waitok)
|
||||
/* XXX race condition for reentrant kernel */
|
||||
bzero(so, sizeof *so);
|
||||
so->so_gencnt = ++so_gencnt;
|
||||
/* sx_init(&so->so_sxlock, "socket sxlock"); */
|
||||
mtx_init(&so->so_rcv.sb_mtx, "sockbuf rcv", NULL, MTX_DEF);
|
||||
mtx_init(&so->so_snd.sb_mtx, "sockbuf snd", NULL, MTX_DEF);
|
||||
TAILQ_INIT(&so->so_aiojobq);
|
||||
++numopensockets;
|
||||
}
|
||||
@ -174,14 +176,17 @@ socreate(dom, aso, type, proto, cred, td)
|
||||
if (so == 0)
|
||||
return (ENOBUFS);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
TAILQ_INIT(&so->so_incomp);
|
||||
TAILQ_INIT(&so->so_comp);
|
||||
so->so_type = type;
|
||||
so->so_cred = crhold(cred);
|
||||
so->so_proto = prp;
|
||||
soref(so);
|
||||
SOCK_UNLOCK(so);
|
||||
error = (*prp->pr_usrreqs->pru_attach)(so, proto, td);
|
||||
if (error) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_NOFDREF;
|
||||
sorele(so);
|
||||
return (error);
|
||||
@ -208,7 +213,9 @@ static void
|
||||
sodealloc(struct socket *so)
|
||||
{
|
||||
|
||||
SOCK_LOCK(so);
|
||||
KASSERT(so->so_count == 0, ("sodealloc(): so_count %d", so->so_count));
|
||||
SOCK_UNLOCK(so);
|
||||
so->so_gencnt = ++so_gencnt;
|
||||
if (so->so_rcv.sb_hiwat)
|
||||
(void)chgsbsize(so->so_cred->cr_uidinfo,
|
||||
@ -228,7 +235,8 @@ sodealloc(struct socket *so)
|
||||
}
|
||||
#endif
|
||||
crfree(so->so_cred);
|
||||
/* sx_destroy(&so->so_sxlock); */
|
||||
mtx_destroy(&so->so_rcv.sb_mtx);
|
||||
mtx_destroy(&so->so_snd.sb_mtx);
|
||||
uma_zfree(socket_zone, so);
|
||||
--numopensockets;
|
||||
}
|
||||
@ -247,8 +255,11 @@ solisten(so, backlog, td)
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
if (TAILQ_EMPTY(&so->so_comp))
|
||||
if (TAILQ_EMPTY(&so->so_comp)) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_options |= SO_ACCEPTCONN;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
if (backlog < 0 || backlog > somaxconn)
|
||||
backlog = somaxconn;
|
||||
so->so_qlimit = backlog;
|
||||
@ -262,15 +273,21 @@ sofree(so)
|
||||
{
|
||||
struct socket *head = so->so_head;
|
||||
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
|
||||
KASSERT(so->so_count == 0, ("socket %p so_count not 0", so));
|
||||
|
||||
if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
|
||||
if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return;
|
||||
}
|
||||
if (head != NULL) {
|
||||
if (so->so_state & SS_INCOMP) {
|
||||
SOCK_UNLOCK(so);
|
||||
TAILQ_REMOVE(&head->so_incomp, so, so_list);
|
||||
head->so_incqlen--;
|
||||
} else if (so->so_state & SS_COMP) {
|
||||
SOCK_UNLOCK(so);
|
||||
/*
|
||||
* We must not decommission a socket that's
|
||||
* on the accept(2) queue. If we do, then
|
||||
@ -279,11 +296,15 @@ sofree(so)
|
||||
*/
|
||||
return;
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
panic("sofree: not queued");
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_INCOMP;
|
||||
SOCK_UNLOCK(so);
|
||||
so->so_head = NULL;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
sbrelease(&so->so_snd, so);
|
||||
sorflush(so);
|
||||
sodealloc(so);
|
||||
@ -306,9 +327,11 @@ soclose(so)
|
||||
int error = 0;
|
||||
|
||||
funsetown(&so->so_sigio);
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_ACCEPTCONN) {
|
||||
struct socket *sp, *sonext;
|
||||
|
||||
SOCK_UNLOCK(so);
|
||||
sp = TAILQ_FIRST(&so->so_incomp);
|
||||
for (; sp != NULL; sp = sonext) {
|
||||
sonext = TAILQ_NEXT(sp, so_list);
|
||||
@ -319,38 +342,49 @@ soclose(so)
|
||||
/* Dequeue from so_comp since sofree() won't do it */
|
||||
TAILQ_REMOVE(&so->so_comp, sp, so_list);
|
||||
so->so_qlen--;
|
||||
SOCK_LOCK(sp);
|
||||
sp->so_state &= ~SS_COMP;
|
||||
SOCK_UNLOCK(sp);
|
||||
sp->so_head = NULL;
|
||||
(void) soabort(sp);
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
if (so->so_pcb == 0)
|
||||
goto discard;
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
if ((so->so_state & SS_ISDISCONNECTING) == 0) {
|
||||
error = sodisconnect(so);
|
||||
if (error)
|
||||
if (error) {
|
||||
SOCK_UNLOCK(so);
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
if (so->so_options & SO_LINGER) {
|
||||
if ((so->so_state & SS_ISDISCONNECTING) &&
|
||||
(so->so_state & SS_NBIO))
|
||||
(so->so_state & SS_NBIO)) {
|
||||
SOCK_UNLOCK(so);
|
||||
goto drop;
|
||||
}
|
||||
while (so->so_state & SS_ISCONNECTED) {
|
||||
error = tsleep((caddr_t)&so->so_timeo,
|
||||
error = msleep((caddr_t)&so->so_timeo, SOCK_MTX(so),
|
||||
PSOCK | PCATCH, "soclos", so->so_linger * hz);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
drop:
|
||||
SOCK_ASSERT(so, MA_NOTOWNED);
|
||||
if (so->so_pcb) {
|
||||
int error2 = (*so->so_proto->pr_usrreqs->pru_detach)(so);
|
||||
if (error == 0)
|
||||
error = error2;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
discard:
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
if (so->so_state & SS_NOFDREF)
|
||||
panic("soclose: NOFDREF");
|
||||
so->so_state |= SS_NOFDREF;
|
||||
@ -370,6 +404,7 @@ soabort(so)
|
||||
|
||||
error = (*so->so_proto->pr_usrreqs->pru_abort)(so);
|
||||
if (error) {
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so); /* note: does not decrement the ref count */
|
||||
return error;
|
||||
}
|
||||
@ -384,9 +419,11 @@ soaccept(so, nam)
|
||||
int s = splnet();
|
||||
int error;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_NOFDREF) == 0)
|
||||
panic("soaccept: !NOFDREF");
|
||||
so->so_state &= ~SS_NOFDREF;
|
||||
SOCK_UNLOCK(so);
|
||||
error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam);
|
||||
splx(s);
|
||||
return (error);
|
||||
@ -401,8 +438,11 @@ soconnect(so, nam, td)
|
||||
int s;
|
||||
int error;
|
||||
|
||||
if (so->so_options & SO_ACCEPTCONN)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_ACCEPTCONN) {
|
||||
SOCK_UNLOCK(so);
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
s = splnet();
|
||||
/*
|
||||
* If protocol is connection-based, can only connect once.
|
||||
@ -410,12 +450,23 @@ soconnect(so, nam, td)
|
||||
* This allows user to disconnect by connecting to, e.g.,
|
||||
* a null address.
|
||||
*/
|
||||
if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
|
||||
((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
|
||||
(error = sodisconnect(so))))
|
||||
error = EISCONN;
|
||||
else
|
||||
error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, td);
|
||||
if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
|
||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EISCONN;
|
||||
goto done;
|
||||
} else {
|
||||
error = sodisconnect(so);
|
||||
if (error) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EISCONN;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, td);
|
||||
done:
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
@ -440,6 +491,7 @@ sodisconnect(so)
|
||||
int s = splnet();
|
||||
int error;
|
||||
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
error = ENOTCONN;
|
||||
goto bad;
|
||||
@ -448,7 +500,9 @@ sodisconnect(so)
|
||||
error = EALREADY;
|
||||
goto bad;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so);
|
||||
SOCK_LOCK(so);
|
||||
bad:
|
||||
splx(s);
|
||||
return (error);
|
||||
@ -507,14 +561,22 @@ sosend(so, addr, uio, top, control, flags, td)
|
||||
goto out;
|
||||
}
|
||||
|
||||
SOCK_LOCK(so);
|
||||
dontroute =
|
||||
(flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
|
||||
(so->so_proto->pr_flags & PR_ATOMIC);
|
||||
SOCK_UNLOCK(so);
|
||||
if (td)
|
||||
td->td_proc->p_stats->p_ru.ru_msgsnd++;
|
||||
if (control)
|
||||
clen = control->m_len;
|
||||
#define snderr(errno) { error = errno; splx(s); goto release; }
|
||||
#define snderr(errno) \
|
||||
do { \
|
||||
error = errno; \
|
||||
SOCK_UNLOCK(so); \
|
||||
splx(s); \
|
||||
goto release; \
|
||||
} while(0);
|
||||
|
||||
restart:
|
||||
error = sblock(&so->so_snd, SBLOCKWAIT(flags));
|
||||
@ -522,11 +584,13 @@ restart:
|
||||
goto out;
|
||||
do {
|
||||
s = splnet();
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTSENDMORE)
|
||||
snderr(EPIPE);
|
||||
if (so->so_error) {
|
||||
error = so->so_error;
|
||||
so->so_error = 0;
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
goto release;
|
||||
}
|
||||
@ -546,16 +610,21 @@ restart:
|
||||
snderr(so->so_proto->pr_flags & PR_CONNREQUIRED ?
|
||||
ENOTCONN : EDESTADDRREQ);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
space = sbspace(&so->so_snd);
|
||||
if (flags & MSG_OOB)
|
||||
space += 1024;
|
||||
if ((atomic && resid > so->so_snd.sb_hiwat) ||
|
||||
clen > so->so_snd.sb_hiwat)
|
||||
clen > so->so_snd.sb_hiwat) {
|
||||
SOCK_LOCK(so);
|
||||
snderr(EMSGSIZE);
|
||||
}
|
||||
if (space < resid + clen &&
|
||||
(atomic || space < so->so_snd.sb_lowat || space < clen)) {
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_NBIO)
|
||||
snderr(EWOULDBLOCK);
|
||||
SOCK_UNLOCK(so);
|
||||
sbunlock(&so->so_snd);
|
||||
error = sbwait(&so->so_snd);
|
||||
splx(s);
|
||||
@ -623,8 +692,11 @@ nopages:
|
||||
break;
|
||||
}
|
||||
} while (space > 0 && atomic);
|
||||
if (dontroute)
|
||||
if (dontroute) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_options |= SO_DONTROUTE;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
s = splnet(); /* XXX */
|
||||
/*
|
||||
* XXX all the SS_CANTSENDMORE checks previously
|
||||
@ -650,8 +722,11 @@ nopages:
|
||||
(resid > 0 && space > 0) ? PRUS_MORETOCOME : 0,
|
||||
top, addr, control, td);
|
||||
splx(s);
|
||||
if (dontroute)
|
||||
if (dontroute) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_options &= ~SO_DONTROUTE;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
clen = 0;
|
||||
control = 0;
|
||||
top = 0;
|
||||
@ -731,10 +806,15 @@ bad:
|
||||
}
|
||||
if (mp)
|
||||
*mp = (struct mbuf *)0;
|
||||
if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) {
|
||||
SOCK_UNLOCK(so);
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
restart:
|
||||
SOCK_ASSERT(so, MA_NOTOWNED);
|
||||
error = sblock(&so->so_rcv, SBLOCKWAIT(flags));
|
||||
if (error)
|
||||
return (error);
|
||||
@ -768,28 +848,37 @@ restart:
|
||||
so->so_error = 0;
|
||||
goto release;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
if (m)
|
||||
goto dontblock;
|
||||
else
|
||||
goto release;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
for (; m; m = m->m_next)
|
||||
if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
|
||||
m = so->so_rcv.sb_mb;
|
||||
goto dontblock;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
|
||||
(so->so_proto->pr_flags & PR_CONNREQUIRED)) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ENOTCONN;
|
||||
goto release;
|
||||
}
|
||||
if (uio->uio_resid == 0)
|
||||
if (uio->uio_resid == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
goto release;
|
||||
}
|
||||
if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EWOULDBLOCK;
|
||||
goto release;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
sbunlock(&so->so_rcv);
|
||||
error = sbwait(&so->so_rcv);
|
||||
splx(s);
|
||||
@ -859,7 +948,9 @@ dontblock:
|
||||
else
|
||||
KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER,
|
||||
("m->m_type == %d", m->m_type));
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
len = uio->uio_resid;
|
||||
if (so->so_oobmark && len > so->so_oobmark - offset)
|
||||
len = so->so_oobmark - offset;
|
||||
@ -917,7 +1008,9 @@ dontblock:
|
||||
if ((flags & MSG_PEEK) == 0) {
|
||||
so->so_oobmark -= len;
|
||||
if (so->so_oobmark == 0) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -937,8 +1030,12 @@ dontblock:
|
||||
*/
|
||||
while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
|
||||
!sosendallatonce(so) && !nextrecord) {
|
||||
if (so->so_error || so->so_state & SS_CANTRCVMORE)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_error || so->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
/*
|
||||
* Notify the protocol that some data has been
|
||||
* drained before blocking.
|
||||
@ -968,12 +1065,15 @@ dontblock:
|
||||
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
if (orig_resid == uio->uio_resid && orig_resid &&
|
||||
(flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
sbunlock(&so->so_rcv);
|
||||
splx(s);
|
||||
goto restart;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
if (flagsp)
|
||||
*flagsp |= flags;
|
||||
@ -1015,7 +1115,10 @@ sorflush(so)
|
||||
socantrcvmore(so);
|
||||
sbunlock(sb);
|
||||
asb = *sb;
|
||||
bzero((caddr_t)sb, sizeof (*sb));
|
||||
#define RANGEOF(type, start, end) (offsetof(type, end) - offsetof(type, start))
|
||||
bzero((caddr_t)&sb->sb_startzero,
|
||||
(unsigned) RANGEOF(struct sockbuf, sb_startzero, sb_endzero));
|
||||
#undef RANGEOF
|
||||
splx(s);
|
||||
if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
|
||||
(*pr->pr_domain->dom_dispose)(asb.sb_mb);
|
||||
@ -1034,10 +1137,13 @@ do_setopt_accept_filter(so, sopt)
|
||||
int error = 0;
|
||||
|
||||
/* do not set/remove accept filters on non listen sockets */
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & SO_ACCEPTCONN) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
/* removing the filter */
|
||||
if (sopt == NULL) {
|
||||
@ -1052,7 +1158,9 @@ do_setopt_accept_filter(so, sopt)
|
||||
FREE(af, M_ACCF);
|
||||
so->so_accf = NULL;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
so->so_options &= ~SO_ACCEPTFILTER;
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
/* adding a filter */
|
||||
@ -1092,7 +1200,9 @@ do_setopt_accept_filter(so, sopt)
|
||||
}
|
||||
af->so_accept_filter = afp;
|
||||
so->so_accf = af;
|
||||
SOCK_LOCK(so);
|
||||
so->so_options |= SO_ACCEPTFILTER;
|
||||
SOCK_UNLOCK(so);
|
||||
out:
|
||||
if (afap != NULL)
|
||||
FREE(afap, M_TEMP);
|
||||
@ -1164,11 +1274,13 @@ sosetopt(so, sopt)
|
||||
if (error)
|
||||
goto bad;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
so->so_linger = l.l_linger;
|
||||
if (l.l_onoff)
|
||||
so->so_options |= SO_LINGER;
|
||||
else
|
||||
so->so_options &= ~SO_LINGER;
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
|
||||
case SO_DEBUG:
|
||||
@ -1184,10 +1296,12 @@ sosetopt(so, sopt)
|
||||
sizeof optval);
|
||||
if (error)
|
||||
goto bad;
|
||||
SOCK_LOCK(so);
|
||||
if (optval)
|
||||
so->so_options |= sopt->sopt_name;
|
||||
else
|
||||
so->so_options &= ~sopt->sopt_name;
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
|
||||
case SO_SNDBUF:
|
||||
@ -1334,23 +1448,30 @@ sogetopt(so, sopt)
|
||||
switch (sopt->sopt_name) {
|
||||
#ifdef INET
|
||||
case SO_ACCEPTFILTER:
|
||||
if ((so->so_options & SO_ACCEPTCONN) == 0)
|
||||
return (EINVAL);
|
||||
MALLOC(afap, struct accept_filter_arg *, sizeof(*afap),
|
||||
M_TEMP, M_WAITOK | M_ZERO);
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & SO_ACCEPTCONN) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
FREE(afap, M_TEMP);
|
||||
return (EINVAL);
|
||||
}
|
||||
if ((so->so_options & SO_ACCEPTFILTER) != 0) {
|
||||
strcpy(afap->af_name, so->so_accf->so_accept_filter->accf_name);
|
||||
if (so->so_accf->so_accept_filter_str != NULL)
|
||||
strcpy(afap->af_arg, so->so_accf->so_accept_filter_str);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
error = sooptcopyout(sopt, afap, sizeof(*afap));
|
||||
FREE(afap, M_TEMP);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SO_LINGER:
|
||||
SOCK_LOCK(so);
|
||||
l.l_onoff = so->so_options & SO_LINGER;
|
||||
l.l_linger = so->so_linger;
|
||||
SOCK_UNLOCK(so);
|
||||
error = sooptcopyout(sopt, &l, sizeof l);
|
||||
break;
|
||||
|
||||
@ -1363,7 +1484,9 @@ sogetopt(so, sopt)
|
||||
case SO_BROADCAST:
|
||||
case SO_OOBINLINE:
|
||||
case SO_TIMESTAMP:
|
||||
SOCK_LOCK(so);
|
||||
optval = so->so_options & sopt->sopt_name;
|
||||
SOCK_UNLOCK(so);
|
||||
integer:
|
||||
error = sooptcopyout(sopt, &optval, sizeof optval);
|
||||
break;
|
||||
@ -1537,22 +1660,31 @@ sopoll(struct socket *so, int events, struct ucred *cred, struct thread *td)
|
||||
int revents = 0;
|
||||
int s = splnet();
|
||||
|
||||
if (events & (POLLIN | POLLRDNORM))
|
||||
if (events & (POLLIN | POLLRDNORM)) {
|
||||
SOCK_LOCK(so);
|
||||
if (soreadable(so))
|
||||
revents |= events & (POLLIN | POLLRDNORM);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
if (events & POLLINIGNEOF)
|
||||
if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat ||
|
||||
!TAILQ_EMPTY(&so->so_comp) || so->so_error)
|
||||
revents |= POLLINIGNEOF;
|
||||
|
||||
if (events & (POLLOUT | POLLWRNORM))
|
||||
if (events & (POLLOUT | POLLWRNORM)) {
|
||||
SOCK_LOCK(so);
|
||||
if (sowriteable(so))
|
||||
revents |= events & (POLLOUT | POLLWRNORM);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
if (events & (POLLPRI | POLLRDBAND))
|
||||
if (events & (POLLPRI | POLLRDBAND)) {
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
|
||||
revents |= events & (POLLPRI | POLLRDBAND);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
if (revents == 0) {
|
||||
if (events &
|
||||
@ -1581,10 +1713,12 @@ sokqfilter(struct file *fp, struct knote *kn)
|
||||
|
||||
switch (kn->kn_filter) {
|
||||
case EVFILT_READ:
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_ACCEPTCONN)
|
||||
kn->kn_fop = &solisten_filtops;
|
||||
else
|
||||
kn->kn_fop = &soread_filtops;
|
||||
SOCK_UNLOCK(so);
|
||||
sb = &so->so_rcv;
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
@ -1621,13 +1755,18 @@ filt_soread(struct knote *kn, long hint)
|
||||
struct socket *so = (struct socket *)kn->kn_fp->f_data;
|
||||
|
||||
kn->kn_data = so->so_rcv.sb_cc;
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
kn->kn_flags |= EV_EOF;
|
||||
kn->kn_fflags = so->so_error;
|
||||
return (1);
|
||||
}
|
||||
if (so->so_error) /* temporary udp error */
|
||||
if (so->so_error) { /* temporary udp error */
|
||||
SOCK_UNLOCK(so);
|
||||
return (1);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (kn->kn_sfflags & NOTE_LOWAT)
|
||||
return (kn->kn_data >= kn->kn_sdata);
|
||||
return (kn->kn_data >= so->so_rcv.sb_lowat);
|
||||
@ -1652,16 +1791,23 @@ filt_sowrite(struct knote *kn, long hint)
|
||||
struct socket *so = (struct socket *)kn->kn_fp->f_data;
|
||||
|
||||
kn->kn_data = sbspace(&so->so_snd);
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTSENDMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
kn->kn_flags |= EV_EOF;
|
||||
kn->kn_fflags = so->so_error;
|
||||
return (1);
|
||||
}
|
||||
if (so->so_error) /* temporary udp error */
|
||||
if (so->so_error) { /* temporary udp error */
|
||||
SOCK_UNLOCK(so);
|
||||
return (1);
|
||||
}
|
||||
if (((so->so_state & SS_ISCONNECTED) == 0) &&
|
||||
(so->so_proto->pr_flags & PR_CONNREQUIRED))
|
||||
(so->so_proto->pr_flags & PR_CONNREQUIRED)) {
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (kn->kn_sfflags & NOTE_LOWAT)
|
||||
return (kn->kn_data >= kn->kn_sdata);
|
||||
return (kn->kn_data >= so->so_snd.sb_lowat);
|
||||
|
@ -102,71 +102,56 @@ soisconnecting(so)
|
||||
register struct socket *so;
|
||||
{
|
||||
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
|
||||
so->so_state |= SS_ISCONNECTING;
|
||||
}
|
||||
|
||||
void
|
||||
soisconnected_locked(so)
|
||||
struct socket *so;
|
||||
{
|
||||
struct socket *head = so->so_head;
|
||||
|
||||
so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
|
||||
so->so_state |= SS_ISCONNECTED;
|
||||
if (head && (so->so_state & SS_INCOMP)) {
|
||||
if ((so->so_options & SO_ACCEPTFILTER) != 0) {
|
||||
so->so_upcall = head->so_accf->so_accept_filter->accf_callback;
|
||||
so->so_upcallarg = head->so_accf->so_accept_filter_arg;
|
||||
so->so_rcv.sb_flags |= SB_UPCALL;
|
||||
so->so_options &= ~SO_ACCEPTFILTER;
|
||||
so->so_upcall(so, so->so_upcallarg, 0);
|
||||
return;
|
||||
}
|
||||
TAILQ_REMOVE(&head->so_incomp, so, so_list);
|
||||
head->so_incqlen--;
|
||||
so->so_state &= ~SS_INCOMP;
|
||||
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
|
||||
head->so_qlen++;
|
||||
so->so_state |= SS_COMP;
|
||||
sorwakeup_locked(head);
|
||||
wakeup_one(&head->so_timeo);
|
||||
} else {
|
||||
wakeup(&so->so_timeo);
|
||||
sorwakeup_locked(so);
|
||||
sowwakeup_locked(so);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
soisconnected(so)
|
||||
struct socket *so;
|
||||
{
|
||||
struct socket *head = so->so_head;
|
||||
struct socket *head;
|
||||
so_upcall_t *upcp;
|
||||
void *upcarg;
|
||||
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
head = so->so_head;
|
||||
so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
|
||||
so->so_state |= SS_ISCONNECTED;
|
||||
if (head && (so->so_state & SS_INCOMP)) {
|
||||
if ((so->so_options & SO_ACCEPTFILTER) != 0) {
|
||||
so->so_upcall = head->so_accf->so_accept_filter->accf_callback;
|
||||
so->so_upcallarg = head->so_accf->so_accept_filter_arg;
|
||||
SOCK_UNLOCK(so);
|
||||
SOCK_LOCK(head);
|
||||
upcp = head->so_accf->so_accept_filter->accf_callback;
|
||||
upcarg = head->so_accf->so_accept_filter_arg;
|
||||
SOCK_UNLOCK(head);
|
||||
SOCK_LOCK(so);
|
||||
so->so_upcall = upcp;
|
||||
so->so_upcallarg = upcarg;
|
||||
so->so_rcv.sb_flags |= SB_UPCALL;
|
||||
so->so_options &= ~SO_ACCEPTFILTER;
|
||||
so->so_upcall(so, so->so_upcallarg, 0);
|
||||
SOCK_UNLOCK(so);
|
||||
so->so_upcall(so, upcarg, 0);
|
||||
SOCK_LOCK(so);
|
||||
return;
|
||||
}
|
||||
so->so_state &= ~SS_INCOMP;
|
||||
so->so_state |= SS_COMP;
|
||||
SOCK_UNLOCK(so);
|
||||
SOCK_LOCK(head);
|
||||
TAILQ_REMOVE(&head->so_incomp, so, so_list);
|
||||
head->so_incqlen--;
|
||||
so->so_state &= ~SS_INCOMP;
|
||||
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
|
||||
head->so_qlen++;
|
||||
so->so_state |= SS_COMP;
|
||||
sorwakeup_locked(head);
|
||||
sorwakeup(head);
|
||||
wakeup_one(&head->so_timeo);
|
||||
SOCK_UNLOCK(head);
|
||||
SOCK_LOCK(so);
|
||||
} else {
|
||||
wakeup(&so->so_timeo);
|
||||
sorwakeup_locked(so);
|
||||
sowwakeup_locked(so);
|
||||
sorwakeup(so);
|
||||
sowwakeup(so);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,23 +160,12 @@ soisdisconnecting(so)
|
||||
register struct socket *so;
|
||||
{
|
||||
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
|
||||
wakeup((caddr_t)&so->so_timeo);
|
||||
sowwakeup_locked(so);
|
||||
sorwakeup_locked(so);
|
||||
}
|
||||
|
||||
void
|
||||
soisdisconnected_locked(so)
|
||||
register struct socket *so;
|
||||
{
|
||||
|
||||
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
|
||||
so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
|
||||
wakeup((caddr_t)&so->so_timeo);
|
||||
sowwakeup_locked(so);
|
||||
sorwakeup_locked(so);
|
||||
sowwakeup(so);
|
||||
sorwakeup(so);
|
||||
}
|
||||
|
||||
void
|
||||
@ -199,7 +173,12 @@ soisdisconnected(so)
|
||||
register struct socket *so;
|
||||
{
|
||||
|
||||
soisdisconnected_locked(so);
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
|
||||
so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
|
||||
wakeup((caddr_t)&so->so_timeo);
|
||||
sowwakeup(so);
|
||||
sorwakeup(so);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -224,25 +203,32 @@ sonewconn(head, connstatus)
|
||||
so = soalloc(0);
|
||||
if (so == NULL)
|
||||
return ((struct socket *)0);
|
||||
SOCK_LOCK(head);
|
||||
if ((head->so_options & SO_ACCEPTFILTER) != 0)
|
||||
connstatus = 0;
|
||||
SOCK_UNLOCK(head);
|
||||
so->so_head = head;
|
||||
so->so_type = head->so_type;
|
||||
SOCK_LOCK(so);
|
||||
so->so_options = head->so_options &~ SO_ACCEPTCONN;
|
||||
so->so_linger = head->so_linger;
|
||||
so->so_state = head->so_state | SS_NOFDREF;
|
||||
SOCK_UNLOCK(so);
|
||||
so->so_proto = head->so_proto;
|
||||
so->so_timeo = head->so_timeo;
|
||||
so->so_cred = crhold(head->so_cred);
|
||||
if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat) ||
|
||||
(*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
return ((struct socket *)0);
|
||||
}
|
||||
|
||||
if (connstatus) {
|
||||
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_COMP;
|
||||
SOCK_UNLOCK(so);
|
||||
head->so_qlen++;
|
||||
} else {
|
||||
if (head->so_incqlen >= head->so_qlimit) {
|
||||
@ -251,13 +237,19 @@ sonewconn(head, connstatus)
|
||||
(void) soabort(sp);
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_INCOMP;
|
||||
SOCK_UNLOCK(so);
|
||||
head->so_incqlen++;
|
||||
}
|
||||
if (connstatus) {
|
||||
sorwakeup_locked(head);
|
||||
SOCK_LOCK(head);
|
||||
sorwakeup(head);
|
||||
wakeup((caddr_t)&head->so_timeo);
|
||||
SOCK_UNLOCK(head);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= connstatus;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
return (so);
|
||||
}
|
||||
@ -277,8 +269,10 @@ socantsendmore(so)
|
||||
struct socket *so;
|
||||
{
|
||||
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_CANTSENDMORE;
|
||||
sowwakeup_locked(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
void
|
||||
@ -286,8 +280,10 @@ socantrcvmore(so)
|
||||
struct socket *so;
|
||||
{
|
||||
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_CANTRCVMORE;
|
||||
sorwakeup_locked(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -336,6 +332,7 @@ sowakeup(so, sb)
|
||||
register struct socket *so;
|
||||
register struct sockbuf *sb;
|
||||
{
|
||||
SOCK_ASSERT(so, MA_OWNED);
|
||||
|
||||
selwakeup(&sb->sb_sel);
|
||||
sb->sb_flags &= ~SB_SEL;
|
||||
@ -343,13 +340,23 @@ sowakeup(so, sb)
|
||||
sb->sb_flags &= ~SB_WAIT;
|
||||
wakeup((caddr_t)&sb->sb_cc);
|
||||
}
|
||||
if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL)
|
||||
if ((so->so_state & SS_ASYNC) && so->so_sigio != NULL) {
|
||||
SOCK_UNLOCK(so);
|
||||
pgsigio(&so->so_sigio, SIGIO, 0);
|
||||
if (sb->sb_flags & SB_UPCALL)
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
if (sb->sb_flags & SB_UPCALL) {
|
||||
SOCK_UNLOCK(so);
|
||||
(*so->so_upcall)(so, so->so_upcallarg, M_DONTWAIT);
|
||||
if (sb->sb_flags & SB_AIO)
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
if (sb->sb_flags & SB_AIO) {
|
||||
SOCK_UNLOCK(so);
|
||||
aio_swake(so, sb);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
KNOTE(&sb->sb_sel.si_note, 0);
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -959,9 +966,11 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
|
||||
xso->xso_len = sizeof *xso;
|
||||
xso->xso_so = so;
|
||||
xso->so_type = so->so_type;
|
||||
SOCK_LOCK(so);
|
||||
xso->so_options = so->so_options;
|
||||
xso->so_linger = so->so_linger;
|
||||
xso->so_state = so->so_state;
|
||||
SOCK_UNLOCK(so);
|
||||
xso->so_pcb = so->so_pcb;
|
||||
xso->xso_protocol = so->so_proto->pr_protocol;
|
||||
xso->xso_family = so->so_proto->pr_domain->dom_family;
|
||||
|
@ -245,12 +245,15 @@ accept1(td, uap, compat)
|
||||
if (error)
|
||||
goto done2;
|
||||
s = splnet();
|
||||
SOCK_LOCK(head);
|
||||
if ((head->so_options & SO_ACCEPTCONN) == 0) {
|
||||
SOCK_UNLOCK(head);
|
||||
splx(s);
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) {
|
||||
SOCK_UNLOCK(head);
|
||||
splx(s);
|
||||
error = EWOULDBLOCK;
|
||||
goto done;
|
||||
@ -260,13 +263,16 @@ accept1(td, uap, compat)
|
||||
head->so_error = ECONNABORTED;
|
||||
break;
|
||||
}
|
||||
error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
|
||||
error = msleep((caddr_t)&head->so_timeo,
|
||||
SOCK_MTX(head), PSOCK | PCATCH,
|
||||
"accept", 0);
|
||||
if (error) {
|
||||
SOCK_UNLOCK(head);
|
||||
splx(s);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
SOCK_UNLOCK(head);
|
||||
if (head->so_error) {
|
||||
error = head->so_error;
|
||||
head->so_error = 0;
|
||||
@ -305,13 +311,17 @@ accept1(td, uap, compat)
|
||||
/* connection has been removed from the listen queue */
|
||||
KNOTE(&head->so_rcv.sb_sel.si_note, 0);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_COMP;
|
||||
SOCK_UNLOCK(so);
|
||||
so->so_head = NULL;
|
||||
if (head->so_sigio != NULL)
|
||||
fsetown(fgetown(head->so_sigio), &so->so_sigio);
|
||||
|
||||
FILE_LOCK(nfp);
|
||||
SOCK_LOCK(so);
|
||||
soref(so); /* file descriptor reference */
|
||||
SOCK_UNLOCK(so);
|
||||
nfp->f_data = (caddr_t)so; /* nfp has ref count from falloc */
|
||||
nfp->f_flag = fflag;
|
||||
nfp->f_ops = &socketops;
|
||||
@ -432,24 +442,30 @@ connect(td, uap)
|
||||
mtx_lock(&Giant);
|
||||
if ((error = fgetsock(td, uap->s, &so, NULL)) != 0)
|
||||
goto done2;
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EALREADY;
|
||||
goto done1;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
error = getsockaddr(&sa, uap->name, uap->namelen);
|
||||
if (error)
|
||||
goto done1;
|
||||
error = soconnect(so, sa, td);
|
||||
if (error)
|
||||
goto bad;
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
|
||||
SOCK_UNLOCK(so);
|
||||
FREE(sa, M_SONAME);
|
||||
error = EINPROGRESS;
|
||||
goto done1;
|
||||
}
|
||||
s = splnet();
|
||||
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
|
||||
error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, "connec", 0);
|
||||
error = msleep((caddr_t)&so->so_timeo,
|
||||
SOCK_MTX(so), PSOCK | PCATCH, "connec", 0);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
@ -457,9 +473,12 @@ connect(td, uap)
|
||||
error = so->so_error;
|
||||
so->so_error = 0;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
bad:
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
SOCK_UNLOCK(so);
|
||||
FREE(sa, M_SONAME);
|
||||
if (error == ERESTART)
|
||||
error = EINTR;
|
||||
@ -1412,10 +1431,13 @@ getpeername1(td, uap, compat)
|
||||
mtx_lock(&Giant);
|
||||
if ((error = fgetsock(td, uap->fdes, &so, NULL)) != 0)
|
||||
goto done2;
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ENOTCONN;
|
||||
goto done1;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
|
||||
if (error)
|
||||
goto done1;
|
||||
@ -1673,10 +1695,13 @@ sendfile(struct thread *td, struct sendfile_args *uap)
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ENOTCONN;
|
||||
goto done;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (uap->offset < 0) {
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
@ -1739,14 +1764,17 @@ retry_lookup:
|
||||
* Optimize the non-blocking case by looking at the socket space
|
||||
* before going to the extra work of constituting the sf_buf.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_NBIO) && sbspace(&so->so_snd) <= 0) {
|
||||
if (so->so_state & SS_CANTSENDMORE)
|
||||
error = EPIPE;
|
||||
else
|
||||
error = EAGAIN;
|
||||
SOCK_UNLOCK(so);
|
||||
sbunlock(&so->so_snd);
|
||||
goto done;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
/*
|
||||
* Attempt to look up the page.
|
||||
*
|
||||
@ -1869,6 +1897,7 @@ retry_space:
|
||||
* blocks before the pru_send (or more accurately, any blocking
|
||||
* results in a loop back to here to re-check).
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_CANTSENDMORE) || so->so_error) {
|
||||
if (so->so_state & SS_CANTSENDMORE) {
|
||||
error = EPIPE;
|
||||
@ -1876,6 +1905,7 @@ retry_space:
|
||||
error = so->so_error;
|
||||
so->so_error = 0;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
m_freem(m);
|
||||
sbunlock(&so->so_snd);
|
||||
splx(s);
|
||||
@ -1888,12 +1918,14 @@ retry_space:
|
||||
*/
|
||||
if (sbspace(&so->so_snd) < so->so_snd.sb_lowat) {
|
||||
if (so->so_state & SS_NBIO) {
|
||||
SOCK_UNLOCK(so);
|
||||
m_freem(m);
|
||||
sbunlock(&so->so_snd);
|
||||
splx(s);
|
||||
error = EAGAIN;
|
||||
goto done;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
error = sbwait(&so->so_snd);
|
||||
/*
|
||||
* An error from sbwait usually indicates that we've
|
||||
@ -1908,6 +1940,7 @@ retry_space:
|
||||
}
|
||||
goto retry_space;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, td);
|
||||
splx(s);
|
||||
if (error) {
|
||||
|
@ -104,6 +104,7 @@ uipc_abort(struct socket *so)
|
||||
return EINVAL;
|
||||
unp_drop(unp, ECONNABORTED);
|
||||
unp_detach(unp);
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
return 0;
|
||||
}
|
||||
@ -249,7 +250,9 @@ uipc_rcvd(struct socket *so, int flags)
|
||||
(void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat,
|
||||
newhiwat, RLIM_INFINITY);
|
||||
unp->unp_cc = so->so_rcv.sb_cc;
|
||||
SOCK_LOCK(so2);
|
||||
sowwakeup(so2);
|
||||
SOCK_UNLOCK(so2);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -306,7 +309,9 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
else
|
||||
from = &sun_noname;
|
||||
if (sbappendaddr(&so2->so_rcv, from, m, control)) {
|
||||
SOCK_LOCK(so2);
|
||||
sorwakeup(so2);
|
||||
SOCK_UNLOCK(so2);
|
||||
m = 0;
|
||||
control = 0;
|
||||
} else
|
||||
@ -322,7 +327,9 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
* Note: A better implementation would complain
|
||||
* if not equal to the peer's address.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
if (nam) {
|
||||
error = unp_connect(so, nam, td);
|
||||
if (error)
|
||||
@ -334,9 +341,11 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
}
|
||||
|
||||
if (so->so_state & SS_CANTSENDMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EPIPE;
|
||||
break;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (unp->unp_conn == 0)
|
||||
panic("uipc_send connected but no connection?");
|
||||
so2 = unp->unp_conn->unp_socket;
|
||||
@ -358,7 +367,9 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
(void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
|
||||
newhiwat, RLIM_INFINITY);
|
||||
unp->unp_conn->unp_cc = so2->so_rcv.sb_cc;
|
||||
SOCK_LOCK(so2);
|
||||
sorwakeup(so2);
|
||||
SOCK_UNLOCK(so2);
|
||||
m = 0;
|
||||
break;
|
||||
|
||||
@ -563,7 +574,9 @@ unp_detach(unp)
|
||||
unp_disconnect(unp);
|
||||
while (!LIST_EMPTY(&unp->unp_refs))
|
||||
unp_drop(LIST_FIRST(&unp->unp_refs), ECONNRESET);
|
||||
SOCK_LOCK(unp->unp_socket);
|
||||
soisdisconnected(unp->unp_socket);
|
||||
SOCK_UNLOCK(unp->unp_socket);
|
||||
unp->unp_socket->so_pcb = 0;
|
||||
if (unp_rights) {
|
||||
/*
|
||||
@ -697,8 +710,14 @@ unp_connect(so, nam, td)
|
||||
goto bad;
|
||||
}
|
||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
|
||||
if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
|
||||
(so3 = sonewconn(so2, 0)) == 0) {
|
||||
SOCK_LOCK(so2);
|
||||
if ((so2->so_options & SO_ACCEPTCONN) == 0) {
|
||||
SOCK_UNLOCK(so2);
|
||||
error = ECONNREFUSED;
|
||||
goto bad;
|
||||
}
|
||||
SOCK_UNLOCK(so2);
|
||||
if ((so3 = sonewconn(so2, 0)) == 0) {
|
||||
error = ECONNREFUSED;
|
||||
goto bad;
|
||||
}
|
||||
@ -756,13 +775,19 @@ unp_connect2(so, so2)
|
||||
|
||||
case SOCK_DGRAM:
|
||||
LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink);
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
|
||||
case SOCK_STREAM:
|
||||
unp2->unp_conn = unp;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
SOCK_LOCK(so2);
|
||||
soisconnected(so2);
|
||||
SOCK_UNLOCK(so2);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -784,13 +809,19 @@ unp_disconnect(unp)
|
||||
|
||||
case SOCK_DGRAM:
|
||||
LIST_REMOVE(unp, unp_reflink);
|
||||
SOCK_LOCK(unp->unp_socket);
|
||||
unp->unp_socket->so_state &= ~SS_ISCONNECTED;
|
||||
SOCK_UNLOCK(unp->unp_socket);
|
||||
break;
|
||||
|
||||
case SOCK_STREAM:
|
||||
SOCK_LOCK(unp->unp_socket);
|
||||
soisdisconnected(unp->unp_socket);
|
||||
SOCK_UNLOCK(unp->unp_socket);
|
||||
SOCK_LOCK(unp2->unp_socket);
|
||||
unp2->unp_conn = 0;
|
||||
soisdisconnected(unp2->unp_socket);
|
||||
SOCK_UNLOCK(unp2->unp_socket);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1440,8 +1440,10 @@ no_kqueue:
|
||||
*/
|
||||
so = (struct socket *)fp->f_data;
|
||||
s = splnet();
|
||||
SOCK_LOCK(so);
|
||||
if (((opcode == LIO_READ) && (!soreadable(so))) || ((opcode ==
|
||||
LIO_WRITE) && (!sowriteable(so)))) {
|
||||
SOCK_UNLOCK(so);
|
||||
TAILQ_INSERT_TAIL(&so->so_aiojobq, aiocbe, list);
|
||||
TAILQ_INSERT_TAIL(&ki->kaio_sockqueue, aiocbe, plist);
|
||||
if (opcode == LIO_READ)
|
||||
@ -1455,6 +1457,7 @@ no_kqueue:
|
||||
error = 0;
|
||||
goto done;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
@ -35,11 +35,13 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/protosw.h>
|
||||
|
||||
#include <net/raw_cb.h>
|
||||
|
||||
@ -97,6 +99,7 @@ raw_detach(rp)
|
||||
struct socket *so = rp->rcb_socket;
|
||||
|
||||
so->so_pcb = 0;
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
LIST_REMOVE(rp, list);
|
||||
#ifdef notdef
|
||||
@ -120,8 +123,12 @@ raw_disconnect(rp)
|
||||
m_freem(dtom(rp->rcb_faddr));
|
||||
rp->rcb_faddr = 0;
|
||||
#endif
|
||||
if (rp->rcb_socket->so_state & SS_NOFDREF)
|
||||
SOCK_LOCK(rp->rcb_socket);
|
||||
if (rp->rcb_socket->so_state & SS_NOFDREF) {
|
||||
SOCK_UNLOCK(rp->rcb_socket);
|
||||
raw_detach(rp);
|
||||
} else
|
||||
SOCK_UNLOCK(rp->rcb_socket);
|
||||
}
|
||||
|
||||
#ifdef notdef
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/socket.h>
|
||||
@ -105,7 +106,9 @@ raw_input(m0, proto, src, dst)
|
||||
/* should notify about lost packet */
|
||||
m_freem(n);
|
||||
else {
|
||||
SOCK_LOCK(last);
|
||||
sorwakeup(last);
|
||||
SOCK_UNLOCK(last);
|
||||
sockets++;
|
||||
}
|
||||
}
|
||||
@ -117,7 +120,9 @@ raw_input(m0, proto, src, dst)
|
||||
m, (struct mbuf *)0) == 0)
|
||||
m_freem(m);
|
||||
else {
|
||||
SOCK_LOCK(last);
|
||||
sorwakeup(last);
|
||||
SOCK_UNLOCK(last);
|
||||
sockets++;
|
||||
}
|
||||
} else
|
||||
@ -145,8 +150,11 @@ raw_uabort(struct socket *so)
|
||||
if (rp == 0)
|
||||
return EINVAL;
|
||||
raw_disconnect(rp);
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so); /* XXX huh? called after the sofree()? */
|
||||
SOCK_UNLOCK(so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -203,7 +211,9 @@ raw_udisconnect(struct socket *so)
|
||||
return ENOTCONN;
|
||||
}
|
||||
raw_disconnect(rp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -147,8 +147,10 @@ rts_attach(struct socket *so, int proto, struct thread *td)
|
||||
}
|
||||
rp->rcb_faddr = &route_src;
|
||||
route_cb.any_count++;
|
||||
soisconnected_locked(so);
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
so->so_options |= SO_USELOOPBACK;
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
@ -472,7 +474,9 @@ flush:
|
||||
/*
|
||||
* Check to see if we don't want our own messages.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & SO_USELOOPBACK) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
if (route_cb.any_count <= 1) {
|
||||
if (rtm)
|
||||
Free(rtm);
|
||||
@ -481,7 +485,8 @@ flush:
|
||||
}
|
||||
/* There is another listener, so construct message */
|
||||
rp = sotorawcb(so);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
if (rtm) {
|
||||
m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
|
||||
if (m->m_pkthdr.len < rtm->rtm_msglen) {
|
||||
|
@ -410,7 +410,9 @@ ddp_input( m, ifp, elh, phase )
|
||||
/*
|
||||
* And wake up whatever might be waiting for it
|
||||
*/
|
||||
SOCK_LOCK(ddp->ddp_socket);
|
||||
sorwakeup( ddp->ddp_socket );
|
||||
SOCK_UNLOCK(ddp->ddp_socket);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -110,8 +110,11 @@ ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
s = splnet();
|
||||
error = at_pcbconnect( ddp, nam, td );
|
||||
splx(s);
|
||||
if ( error == 0 )
|
||||
if ( error == 0 ) {
|
||||
SOCK_LOCK( so );
|
||||
soisconnected( so );
|
||||
SOCK_UNLOCK( so );
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
@ -134,7 +137,9 @@ ddp_disconnect(struct socket *so)
|
||||
at_pcbdisconnect( ddp );
|
||||
ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
|
||||
splx(s);
|
||||
SOCK_LOCK( so );
|
||||
soisdisconnected( so );
|
||||
SOCK_UNLOCK( so );
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -204,7 +209,9 @@ ddp_abort(struct socket *so)
|
||||
if ( ddp == NULL ) {
|
||||
return(EINVAL);
|
||||
}
|
||||
SOCK_LOCK( so );
|
||||
soisdisconnected( so );
|
||||
SOCK_UNLOCK( so );
|
||||
s = splnet();
|
||||
at_pcbdetach( so, ddp );
|
||||
splx(s);
|
||||
@ -440,6 +447,7 @@ at_pcballoc( struct socket *so )
|
||||
static void
|
||||
at_pcbdetach( struct socket *so, struct ddpcb *ddp)
|
||||
{
|
||||
SOCK_LOCK( so );
|
||||
soisdisconnected( so );
|
||||
so->so_pcb = 0;
|
||||
sotryfree(so);
|
||||
|
@ -110,8 +110,11 @@ ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
s = splnet();
|
||||
error = at_pcbconnect( ddp, nam, td );
|
||||
splx(s);
|
||||
if ( error == 0 )
|
||||
if ( error == 0 ) {
|
||||
SOCK_LOCK( so );
|
||||
soisconnected( so );
|
||||
SOCK_UNLOCK( so );
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
@ -134,7 +137,9 @@ ddp_disconnect(struct socket *so)
|
||||
at_pcbdisconnect( ddp );
|
||||
ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
|
||||
splx(s);
|
||||
SOCK_LOCK( so );
|
||||
soisdisconnected( so );
|
||||
SOCK_UNLOCK( so );
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -204,7 +209,9 @@ ddp_abort(struct socket *so)
|
||||
if ( ddp == NULL ) {
|
||||
return(EINVAL);
|
||||
}
|
||||
SOCK_LOCK( so );
|
||||
soisdisconnected( so );
|
||||
SOCK_UNLOCK( so );
|
||||
s = splnet();
|
||||
at_pcbdetach( so, ddp );
|
||||
splx(s);
|
||||
@ -440,6 +447,7 @@ at_pcballoc( struct socket *so )
|
||||
static void
|
||||
at_pcbdetach( struct socket *so, struct ddpcb *ddp)
|
||||
{
|
||||
SOCK_LOCK( so );
|
||||
soisdisconnected( so );
|
||||
so->so_pcb = 0;
|
||||
sotryfree(so);
|
||||
|
@ -771,19 +771,24 @@ atm_aal5_cpcs_data(tok, m)
|
||||
* Ensure that the socket is able to receive data and
|
||||
* that there's room in the socket buffer
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if (((so->so_state & SS_ISCONNECTED) == 0) ||
|
||||
(so->so_state & SS_CANTRCVMORE) ||
|
||||
(len > sbspace(&so->so_rcv))) {
|
||||
SOCK_UNLOCK(so);
|
||||
atm_sock_stat.as_indrop[atp->atp_type]++;
|
||||
KB_FREEALL(m);
|
||||
return;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
/*
|
||||
* Queue the data and notify the user
|
||||
*/
|
||||
sbappendrecord(&so->so_rcv, m);
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -835,9 +840,12 @@ atm_aal5_ctloutput(so, sopt)
|
||||
|
||||
case T_ATM_ADD_LEAF:
|
||||
case T_ATM_DROP_LEAF:
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
ATM_RETERR(ENOTCONN);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
|
||||
case T_ATM_CAUSE:
|
||||
@ -845,9 +853,12 @@ atm_aal5_ctloutput(so, sopt)
|
||||
break;
|
||||
|
||||
default:
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
SOCK_UNLOCK(so);
|
||||
ATM_RETERR(EISCONN);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -181,6 +181,7 @@ atm_sock_detach(so)
|
||||
* Break links and free control blocks
|
||||
*/
|
||||
so->so_pcb = NULL;
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
|
||||
uma_zfree(atm_pcb_zone, atp);
|
||||
@ -493,7 +494,9 @@ atm_sock_connect(so, addr, epp)
|
||||
/*
|
||||
* We're finally ready to initiate the ATM connection
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
soisconnecting(so);
|
||||
SOCK_UNLOCK(so);
|
||||
atm_sock_stat.as_connreq[atp->atp_type]++;
|
||||
err = atm_cm_connect(epp, atp, &atp->atp_attr, &atp->atp_conn);
|
||||
if (err == 0) {
|
||||
@ -501,7 +504,9 @@ atm_sock_connect(so, addr, epp)
|
||||
* Connection is setup
|
||||
*/
|
||||
atm_sock_stat.as_conncomp[atp->atp_type]++;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
} else if (err == EINPROGRESS) {
|
||||
/*
|
||||
@ -514,7 +519,9 @@ atm_sock_connect(so, addr, epp)
|
||||
* Call failed...
|
||||
*/
|
||||
atm_sock_stat.as_connfail[atp->atp_type]++;
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
return (err);
|
||||
@ -564,7 +571,9 @@ atm_sock_disconnect(so)
|
||||
atp->atp_conn = NULL;
|
||||
}
|
||||
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -661,7 +670,9 @@ atm_sock_peeraddr(so, addr)
|
||||
satm->satm_family = AF_ATM;
|
||||
satm->satm_len = sizeof(*satm);
|
||||
saddr = &satm->satm_addr.t_atm_sap_addr;
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
SOCK_UNLOCK(so);
|
||||
cvp = atp->atp_conn->co_connvc;
|
||||
saddr->SVE_tag_addr = T_ATM_PRESENT;
|
||||
if (cvp->cvc_flags & CVCF_CALLER) {
|
||||
@ -680,6 +691,7 @@ atm_sock_peeraddr(so, addr)
|
||||
else
|
||||
saddr->SVE_tag_selector = T_ATM_ABSENT;
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
saddr->SVE_tag_addr = T_ATM_ABSENT;
|
||||
saddr->SVE_tag_selector = T_ATM_ABSENT;
|
||||
saddr->address_format = T_ATM_ABSENT;
|
||||
@ -1087,10 +1099,12 @@ atm_sock_getopt(so, sopt, atp)
|
||||
* If socket is connected, return attributes for the VCC in use,
|
||||
* otherwise just return what the user has setup so far.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONNECTED)
|
||||
ap = &atp->atp_conn->co_connvc->cvc_attr;
|
||||
else
|
||||
ap = &atp->atp_attr;
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
switch (sopt->sopt_name) {
|
||||
|
||||
@ -1268,7 +1282,9 @@ atm_sock_connected(toku)
|
||||
* Connection is setup
|
||||
*/
|
||||
atm_sock_stat.as_conncomp[atp->atp_type]++;
|
||||
SOCK_LOCK(atp->atp_socket);
|
||||
soisconnected(atp->atp_socket);
|
||||
SOCK_UNLOCK(atp->atp_socket);
|
||||
}
|
||||
|
||||
|
||||
@ -1302,6 +1318,7 @@ atm_sock_cleared(toku, cause)
|
||||
/*
|
||||
* Set user error code
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
so->so_error = ECONNRESET;
|
||||
atm_sock_stat.as_connclr[atp->atp_type]++;
|
||||
@ -1320,7 +1337,9 @@ atm_sock_cleared(toku, cause)
|
||||
* Cleanup failed incoming connection setup
|
||||
*/
|
||||
if (so->so_state & SS_NOFDREF) {
|
||||
SOCK_UNLOCK(so);
|
||||
(void) atm_sock_detach(so);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
|
@ -507,7 +507,17 @@ static struct ng_type ng_ksocket_typestruct = {
|
||||
};
|
||||
NETGRAPH_INIT(ksocket, &ng_ksocket_typestruct);
|
||||
|
||||
#define ERROUT(x) do { error = (x); goto done; } while (0)
|
||||
#define ERROUT(x) \
|
||||
do { \
|
||||
error = (x); \
|
||||
goto done; \
|
||||
} while (0)
|
||||
#define ERROUT_SOCK(x) \
|
||||
do { \
|
||||
error = (x); \
|
||||
SOCK_UNLOCK(so); \
|
||||
goto done; \
|
||||
} while (0)
|
||||
|
||||
/************************************************************************
|
||||
NETGRAPH NODE STUFF
|
||||
@ -613,7 +623,9 @@ ng_ksocket_connect(hook_p hook)
|
||||
priv->so->so_upcall = ng_ksocket_incoming;
|
||||
priv->so->so_rcv.sb_flags |= SB_UPCALL;
|
||||
priv->so->so_snd.sb_flags |= SB_UPCALL;
|
||||
SOCK_LOCK(priv->so);
|
||||
priv->so->so_state |= SS_NBIO;
|
||||
SOCK_UNLOCK(priv->so);
|
||||
/*
|
||||
* --Original comment--
|
||||
* On a cloned socket we may have already received one or more
|
||||
@ -708,8 +720,10 @@ ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
ERROUT(ENXIO);
|
||||
|
||||
/* Make sure the socket is capable of accepting */
|
||||
SOCK_LOCK(so);
|
||||
if (!(so->so_options & SO_ACCEPTCONN))
|
||||
ERROUT(EINVAL);
|
||||
ERROUT_SOCK(EINVAL);
|
||||
SOCK_UNLOCK(so);
|
||||
if (priv->flags & KSF_ACCEPTING)
|
||||
ERROUT(EALREADY);
|
||||
|
||||
@ -744,18 +758,24 @@ ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
ERROUT(ENXIO);
|
||||
|
||||
/* Do connect */
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTING) != 0)
|
||||
ERROUT(EALREADY);
|
||||
ERROUT_SOCK(EALREADY);
|
||||
SOCK_UNLOCK(so);
|
||||
if ((error = soconnect(so, sa, td)) != 0) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
ERROUT(error);
|
||||
ERROUT_SOCK(error);
|
||||
}
|
||||
if ((so->so_state & SS_ISCONNECTING) != 0)
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTING) != 0) {
|
||||
/* We will notify the sender when we connect */
|
||||
priv->response_token = msg->header.token;
|
||||
raddr = priv->response_addr;
|
||||
priv->flags |= KSF_CONNECTING;
|
||||
ERROUT(EINPROGRESS);
|
||||
ERROUT_SOCK(EINPROGRESS);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -774,9 +794,11 @@ ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
|
||||
/* Get function */
|
||||
if (msg->header.cmd == NGM_KSOCKET_GETPEERNAME) {
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state
|
||||
& (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
|
||||
ERROUT(ENOTCONN);
|
||||
ERROUT_SOCK(ENOTCONN);
|
||||
SOCK_UNLOCK(so);
|
||||
func = so->so_proto->pr_usrreqs->pru_peeraddr;
|
||||
} else
|
||||
func = so->so_proto->pr_usrreqs->pru_sockaddr;
|
||||
@ -1046,11 +1068,13 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag)
|
||||
|
||||
/* Check whether a pending connect operation has completed */
|
||||
if (priv->flags & KSF_CONNECTING) {
|
||||
SOCK_LOCK(so);
|
||||
if ((error = so->so_error) != 0) {
|
||||
so->so_error = 0;
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
}
|
||||
if (!(so->so_state & SS_ISCONNECTING)) {
|
||||
SOCK_UNLOCK(so);
|
||||
NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE,
|
||||
NGM_KSOCKET_CONNECT, sizeof(int32_t), waitflag);
|
||||
if (response != NULL) {
|
||||
@ -1066,7 +1090,8 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag)
|
||||
priv->response_addr, NULL);
|
||||
}
|
||||
priv->flags &= ~KSF_CONNECTING;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
/* Check whether a pending accept operation has completed */
|
||||
@ -1096,10 +1121,14 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag)
|
||||
struct sockaddr *sa = NULL;
|
||||
meta_p meta = NULL;
|
||||
struct mbuf *n;
|
||||
int sostate;
|
||||
|
||||
/* Try to get next packet from socket */
|
||||
SOCK_LOCK(so);
|
||||
sostate = so->so_state & SS_ISCONNECTED;
|
||||
SOCK_UNLOCK(so);
|
||||
if ((error = (*so->so_proto->pr_usrreqs->pru_soreceive)
|
||||
(so, (so->so_state & SS_ISCONNECTED) ? NULL : &sa,
|
||||
(so, sostate ? NULL : &sa,
|
||||
&auio, &m, (struct mbuf **)0, &flags)) != 0)
|
||||
break;
|
||||
|
||||
@ -1146,14 +1175,17 @@ sendit: /* Forward data with optional peer sockaddr as meta info */
|
||||
* If the peer has closed the connection, forward a 0-length mbuf
|
||||
* to indicate end-of-file.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE && !(priv->flags & KSF_EOFSEEN)) {
|
||||
SOCK_UNLOCK(so);
|
||||
MGETHDR(m, waitflag, MT_DATA);
|
||||
if (m != NULL) {
|
||||
m->m_len = m->m_pkthdr.len = 0;
|
||||
NG_SEND_DATA_ONLY(error, priv->hook, m);
|
||||
}
|
||||
priv->flags |= KSF_EOFSEEN;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
@ -1172,8 +1204,12 @@ ng_ksocket_check_accept(priv_p priv)
|
||||
return error;
|
||||
}
|
||||
if (TAILQ_EMPTY(&head->so_comp)) {
|
||||
if (head->so_state & SS_CANTRCVMORE)
|
||||
SOCK_LOCK(head);
|
||||
if (head->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(head);
|
||||
return ECONNABORTED;
|
||||
}
|
||||
SOCK_UNLOCK(head);
|
||||
return EWOULDBLOCK;
|
||||
}
|
||||
return 0;
|
||||
@ -1204,8 +1240,10 @@ ng_ksocket_finish_accept(priv_p priv)
|
||||
|
||||
/* XXX KNOTE(&head->so_rcv.sb_sel.si_note, 0); */
|
||||
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_COMP;
|
||||
so->so_state |= SS_NBIO;
|
||||
SOCK_UNLOCK(so);
|
||||
so->so_head = NULL;
|
||||
|
||||
soaccept(so, &sa);
|
||||
|
@ -734,7 +734,9 @@ ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg, struct sockaddr_ng *addr)
|
||||
m_freem(mdata);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -770,9 +772,13 @@ ngs_connect(hook_p hook)
|
||||
if ((priv->datasock)
|
||||
&& (priv->datasock->ng_socket)) {
|
||||
if (NG_NODE_NUMHOOKS(node) == 1) {
|
||||
SOCK_LOCK(priv->datasock->ng_socket);
|
||||
priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
|
||||
SOCK_UNLOCK(priv->datasock->ng_socket);
|
||||
} else {
|
||||
SOCK_LOCK(priv->datasock->ng_socket);
|
||||
priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
|
||||
SOCK_UNLOCK(priv->datasock->ng_socket);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
@ -886,7 +892,9 @@ ngs_rcvdata(hook_p hook, item_p item)
|
||||
TRAP_ERROR;
|
||||
return (ENOBUFS);
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -905,9 +913,13 @@ ngs_disconnect(hook_p hook)
|
||||
if ((priv->datasock)
|
||||
&& (priv->datasock->ng_socket)) {
|
||||
if (NG_NODE_NUMHOOKS(node) == 1) {
|
||||
SOCK_LOCK(priv->datasock->ng_socket);
|
||||
priv->datasock->ng_socket->so_state |= SS_ISCONNECTED;
|
||||
SOCK_UNLOCK(priv->datasock->ng_socket);
|
||||
} else {
|
||||
SOCK_LOCK(priv->datasock->ng_socket);
|
||||
priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED;
|
||||
SOCK_UNLOCK(priv->datasock->ng_socket);
|
||||
}
|
||||
}
|
||||
|
||||
@ -932,13 +944,17 @@ ngs_shutdown(node_p node)
|
||||
struct ngpcb *const pcbp = priv->ctlsock;
|
||||
|
||||
if (dpcbp != NULL) {
|
||||
SOCK_LOCK(dpcbp->ng_socket);
|
||||
soisdisconnected(dpcbp->ng_socket);
|
||||
SOCK_UNLOCK(dpcbp->ng_socket);
|
||||
dpcbp->sockdata = NULL;
|
||||
priv->datasock = NULL;
|
||||
priv->refs--;
|
||||
}
|
||||
if (pcbp != NULL) {
|
||||
SOCK_LOCK(pcbp->ng_socket);
|
||||
soisdisconnected(pcbp->ng_socket);
|
||||
SOCK_UNLOCK(pcbp->ng_socket);
|
||||
pcbp->sockdata = NULL;
|
||||
priv->ctlsock = NULL;
|
||||
priv->refs--;
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/socketvar.h>
|
||||
@ -57,11 +59,15 @@ static void
|
||||
sohasdata(struct socket *so, void *arg, int waitflag)
|
||||
{
|
||||
|
||||
if (!soreadable(so))
|
||||
SOCK_LOCK(so);
|
||||
if (!soreadable(so)) {
|
||||
SOCK_UNLOCK(so);
|
||||
return;
|
||||
}
|
||||
|
||||
so->so_upcall = NULL;
|
||||
so->so_rcv.sb_flags &= ~SB_UPCALL;
|
||||
soisconnected_locked(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return;
|
||||
}
|
||||
|
@ -31,7 +31,9 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socketvar.h>
|
||||
@ -160,11 +162,13 @@ static void
|
||||
sohashttpget(struct socket *so, void *arg, int waitflag)
|
||||
{
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_CANTRCVMORE) == 0 && !sbfull(&so->so_rcv)) {
|
||||
struct mbuf *m;
|
||||
char *cmp;
|
||||
int cmplen, cc;
|
||||
|
||||
SOCK_UNLOCK(so);
|
||||
m = so->so_rcv.sb_mb;
|
||||
cc = so->so_rcv.sb_cc - 1;
|
||||
if (cc < 1)
|
||||
@ -197,13 +201,16 @@ sohashttpget(struct socket *so, void *arg, int waitflag)
|
||||
return;
|
||||
}
|
||||
DPRINT("mbufstrcmp bad");
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
fallout:
|
||||
DPRINT("fallout");
|
||||
SOCK_LOCK(so);
|
||||
so->so_upcall = NULL;
|
||||
so->so_rcv.sb_flags &= ~SB_UPCALL;
|
||||
soisconnected_locked(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -213,8 +220,12 @@ soparsehttpvers(struct socket *so, void *arg, int waitflag)
|
||||
struct mbuf *m, *n;
|
||||
int i, cc, spaces, inspaces;
|
||||
|
||||
if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv))
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv)) {
|
||||
SOCK_UNLOCK(so);
|
||||
goto fallout;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
m = so->so_rcv.sb_mb;
|
||||
cc = so->so_rcv.sb_cc;
|
||||
@ -283,9 +294,11 @@ readmore:
|
||||
|
||||
fallout:
|
||||
DPRINT("fallout");
|
||||
SOCK_LOCK(so);
|
||||
so->so_upcall = NULL;
|
||||
so->so_rcv.sb_flags &= ~SB_UPCALL;
|
||||
soisconnected_locked(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -300,8 +313,12 @@ soishttpconnected(struct socket *so, void *arg, int waitflag)
|
||||
int ccleft, copied;
|
||||
|
||||
DPRINT("start");
|
||||
if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv))
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv)) {
|
||||
SOCK_UNLOCK(so);
|
||||
goto gotit;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
/*
|
||||
* Walk the socketbuffer and copy the last NCHRS (3) into a, b, and c
|
||||
@ -353,8 +370,10 @@ readmore:
|
||||
return;
|
||||
|
||||
gotit:
|
||||
SOCK_LOCK(so);
|
||||
so->so_upcall = NULL;
|
||||
so->so_rcv.sb_flags &= ~SB_UPCALL;
|
||||
soisconnected_locked(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return;
|
||||
}
|
||||
|
@ -183,15 +183,20 @@ in_pcbbind(inp, nam, td)
|
||||
struct sockaddr_in *sin;
|
||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
|
||||
u_short lport = 0;
|
||||
int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
|
||||
int wild = 0, reuseport;
|
||||
int error, prison = 0;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
reuseport = (so->so_options & SO_REUSEPORT);
|
||||
SOCK_UNLOCK(so);
|
||||
if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */
|
||||
return (EADDRNOTAVAIL);
|
||||
if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
|
||||
return (EINVAL);
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
|
||||
wild = 1;
|
||||
SOCK_UNLOCK(so);
|
||||
if (nam) {
|
||||
sin = (struct sockaddr_in *)nam;
|
||||
if (nam->sa_len != sizeof (*sin))
|
||||
@ -216,8 +221,10 @@ in_pcbbind(inp, nam, td)
|
||||
* and a multicast address is bound on both
|
||||
* new and duplicated sockets.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_REUSEADDR)
|
||||
reuseport = SO_REUSEADDR|SO_REUSEPORT;
|
||||
SOCK_UNLOCK(so);
|
||||
} else if (sin->sin_addr.s_addr != INADDR_ANY) {
|
||||
sin->sin_port = 0; /* yech... */
|
||||
bzero(&sin->sin_zero, sizeof(sin->sin_zero));
|
||||
@ -237,13 +244,37 @@ in_pcbbind(inp, nam, td)
|
||||
t = in_pcblookup_local(inp->inp_pcbinfo,
|
||||
sin->sin_addr, lport,
|
||||
prison ? 0 : INPLOOKUP_WILDCARD);
|
||||
if (t &&
|
||||
(ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
|
||||
ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
|
||||
(t->inp_socket->so_options &
|
||||
SO_REUSEPORT) == 0) &&
|
||||
(so->so_cred->cr_uid !=
|
||||
t->inp_socket->so_cred->cr_uid)) {
|
||||
if (t != NULL) {
|
||||
SOCK_LOCK(t->inp_socket);
|
||||
if ((ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
|
||||
ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
|
||||
(t->inp_socket->so_options &
|
||||
SO_REUSEPORT) == 0) &&
|
||||
(so->so_cred->cr_uid !=
|
||||
t->inp_socket->so_cred->cr_uid)) {
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
#if defined(INET6)
|
||||
if (ntohl(sin->sin_addr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
ntohl(t->inp_laddr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
INP_SOCKAF(so) ==
|
||||
INP_SOCKAF(t->inp_socket))
|
||||
#endif /* defined(INET6) */
|
||||
return (EADDRINUSE);
|
||||
} else
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
}
|
||||
}
|
||||
if (prison &&
|
||||
prison_ip(td->td_ucred, 0, &sin->sin_addr.s_addr))
|
||||
return (EADDRNOTAVAIL);
|
||||
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
|
||||
lport, prison ? 0 : wild);
|
||||
if (t != NULL) {
|
||||
SOCK_LOCK(t->inp_socket);
|
||||
if ((reuseport & t->inp_socket->so_options) == 0) {
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
#if defined(INET6)
|
||||
if (ntohl(sin->sin_addr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
@ -253,24 +284,8 @@ in_pcbbind(inp, nam, td)
|
||||
INP_SOCKAF(t->inp_socket))
|
||||
#endif /* defined(INET6) */
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
}
|
||||
if (prison &&
|
||||
prison_ip(td->td_ucred, 0, &sin->sin_addr.s_addr))
|
||||
return (EADDRNOTAVAIL);
|
||||
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
|
||||
lport, prison ? 0 : wild);
|
||||
if (t &&
|
||||
(reuseport & t->inp_socket->so_options) == 0) {
|
||||
#if defined(INET6)
|
||||
if (ntohl(sin->sin_addr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
ntohl(t->inp_laddr.s_addr) !=
|
||||
INADDR_ANY ||
|
||||
INP_SOCKAF(so) ==
|
||||
INP_SOCKAF(t->inp_socket))
|
||||
#endif /* defined(INET6) */
|
||||
return (EADDRINUSE);
|
||||
} else
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
}
|
||||
}
|
||||
inp->inp_laddr = sin->sin_addr;
|
||||
@ -416,17 +431,21 @@ in_pcbladdr(inp, nam, plocal_sin)
|
||||
* destination, in case of sharing the cache with IPv6.
|
||||
*/
|
||||
ro = &inp->inp_route;
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
if (ro->ro_rt &&
|
||||
(ro->ro_dst.sa_family != AF_INET ||
|
||||
satosin(&ro->ro_dst)->sin_addr.s_addr !=
|
||||
sin->sin_addr.s_addr ||
|
||||
inp->inp_socket->so_options & SO_DONTROUTE)) {
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
RTFREE(ro->ro_rt);
|
||||
ro->ro_rt = (struct rtentry *)0;
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
}
|
||||
if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
|
||||
(ro->ro_rt == (struct rtentry *)0 ||
|
||||
ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
/* No route yet, so try to acquire one */
|
||||
bzero(&ro->ro_dst, sizeof(struct sockaddr_in));
|
||||
ro->ro_dst.sa_family = AF_INET;
|
||||
@ -434,7 +453,8 @@ in_pcbladdr(inp, nam, plocal_sin)
|
||||
((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
|
||||
sin->sin_addr;
|
||||
rtalloc(ro);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
/*
|
||||
* If we found a route, use the address
|
||||
* corresponding to the outgoing interface
|
||||
@ -548,8 +568,12 @@ in_pcbdisconnect(inp)
|
||||
inp->inp_faddr.s_addr = INADDR_ANY;
|
||||
inp->inp_fport = 0;
|
||||
in_pcbrehash(inp);
|
||||
if (inp->inp_socket->so_state & SS_NOFDREF)
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
if (inp->inp_socket->so_state & SS_NOFDREF) {
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
in_pcbdetach(inp);
|
||||
} else
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
}
|
||||
|
||||
void
|
||||
@ -565,6 +589,7 @@ in_pcbdetach(inp)
|
||||
inp->inp_gencnt = ++ipi->ipi_gencnt;
|
||||
in_pcbremlists(inp);
|
||||
so->so_pcb = 0;
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
if (inp->inp_options)
|
||||
(void)m_free(inp->inp_options);
|
||||
|
@ -228,8 +228,11 @@ divert_packet(struct mbuf *m, int incoming, int port)
|
||||
if (sbappendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc,
|
||||
m, (struct mbuf *)0) == 0)
|
||||
m_freem(m);
|
||||
else
|
||||
else {
|
||||
SOCK_LOCK(sa);
|
||||
sorwakeup(sa);
|
||||
SOCK_UNLOCK(sa);
|
||||
}
|
||||
} else {
|
||||
m_freem(m);
|
||||
ipstat.ips_noproto++;
|
||||
@ -255,6 +258,7 @@ div_output(so, m, addr, control)
|
||||
register struct ip *const ip = mtod(m, struct ip *);
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
|
||||
int error = 0;
|
||||
int soopts;
|
||||
|
||||
if (control)
|
||||
m_freem(control); /* XXX */
|
||||
@ -300,8 +304,11 @@ div_output(so, m, addr, control)
|
||||
|
||||
/* Send packet to output processing */
|
||||
ipstat.ips_rawout++; /* XXX */
|
||||
SOCK_LOCK(so);
|
||||
soopts = so->so_options & SO_DONTROUTE;
|
||||
SOCK_UNLOCK(so);
|
||||
error = ip_output(m, inp->inp_options, &inp->inp_route,
|
||||
(so->so_options & SO_DONTROUTE) |
|
||||
soopts |
|
||||
IP_ALLOWBROADCAST | IP_RAWOUTPUT,
|
||||
inp->inp_moptions);
|
||||
} else {
|
||||
@ -365,7 +372,9 @@ div_attach(struct socket *so, int proto, struct thread *td)
|
||||
inp->inp_flags |= INP_HDRINCL;
|
||||
/* The socket is always "connected" because
|
||||
we always know "where" to send the packet */
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_ISCONNECTED;
|
||||
SOCK_UNLOCK(so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -384,15 +393,21 @@ div_detach(struct socket *so)
|
||||
static int
|
||||
div_abort(struct socket *so)
|
||||
{
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return div_detach(so);
|
||||
}
|
||||
|
||||
static int
|
||||
div_disconnect(struct socket *so)
|
||||
{
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0)
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return ENOTCONN;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
return div_abort(so);
|
||||
}
|
||||
|
||||
|
@ -1837,15 +1837,18 @@ ip_savecontrol(inp, mp, ip, m)
|
||||
register struct ip *ip;
|
||||
register struct mbuf *m;
|
||||
{
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
if (inp->inp_socket->so_options & SO_TIMESTAMP) {
|
||||
struct timeval tv;
|
||||
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
microtime(&tv);
|
||||
*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
|
||||
SCM_TIMESTAMP, SOL_SOCKET);
|
||||
if (*mp)
|
||||
mp = &(*mp)->m_next;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
if (inp->inp_flags & INP_RECVDSTADDR) {
|
||||
*mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
|
||||
sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
|
||||
|
@ -1133,7 +1133,9 @@ socket_send(s, mm, src)
|
||||
if (sbappendaddr(&s->so_rcv,
|
||||
(struct sockaddr *)src,
|
||||
mm, (struct mbuf *)0) != 0) {
|
||||
SOCK_LOCK(s);
|
||||
sorwakeup(s);
|
||||
SOCK_UNLOCK(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -153,9 +153,16 @@ rip_input(m, off)
|
||||
} else
|
||||
#endif /*IPSEC*/
|
||||
if (n) {
|
||||
if (last->inp_flags & INP_CONTROLOPTS ||
|
||||
last->inp_socket->so_options & SO_TIMESTAMP)
|
||||
ip_savecontrol(last, &opts, ip, n);
|
||||
if (last->inp_flags & INP_CONTROLOPTS)
|
||||
ip_savecontrol(last, &opts, ip, n);
|
||||
else {
|
||||
SOCK_LOCK(last->inp_socket);
|
||||
if(last->inp_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
ip_savecontrol(last, &opts, ip, n);
|
||||
} else
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
}
|
||||
if (sbappendaddr(&last->inp_socket->so_rcv,
|
||||
(struct sockaddr *)&ripsrc, n,
|
||||
opts) == 0) {
|
||||
@ -163,8 +170,11 @@ rip_input(m, off)
|
||||
m_freem(n);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
} else
|
||||
} else {
|
||||
SOCK_LOCK(last->inp_socket);
|
||||
sorwakeup(last->inp_socket);
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
}
|
||||
opts = 0;
|
||||
}
|
||||
}
|
||||
@ -180,16 +190,26 @@ rip_input(m, off)
|
||||
} else
|
||||
#endif /*IPSEC*/
|
||||
if (last) {
|
||||
if (last->inp_flags & INP_CONTROLOPTS ||
|
||||
last->inp_socket->so_options & SO_TIMESTAMP)
|
||||
if (last->inp_flags & INP_CONTROLOPTS)
|
||||
ip_savecontrol(last, &opts, ip, m);
|
||||
else {
|
||||
SOCK_LOCK(last->inp_socket);
|
||||
if (last->inp_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
ip_savecontrol(last, &opts, ip, m);
|
||||
} else
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
}
|
||||
if (sbappendaddr(&last->inp_socket->so_rcv,
|
||||
(struct sockaddr *)&ripsrc, m, opts) == 0) {
|
||||
m_freem(m);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
} else
|
||||
} else {
|
||||
SOCK_LOCK(last->inp_socket);
|
||||
sorwakeup(last->inp_socket);
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
}
|
||||
} else {
|
||||
m_freem(m);
|
||||
ipstat.ips_noproto++;
|
||||
@ -209,8 +229,11 @@ rip_output(m, so, dst)
|
||||
{
|
||||
register struct ip *ip;
|
||||
register struct inpcb *inp = sotoinpcb(so);
|
||||
int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
|
||||
int flags;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
|
||||
SOCK_UNLOCK(so);
|
||||
/*
|
||||
* If the user handed us a complete IP packet, use it.
|
||||
* Otherwise, allocate an mbuf for a header and fill it in.
|
||||
@ -508,15 +531,21 @@ rip_detach(struct socket *so)
|
||||
static int
|
||||
rip_abort(struct socket *so)
|
||||
{
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return rip_detach(so);
|
||||
}
|
||||
|
||||
static int
|
||||
rip_disconnect(struct socket *so)
|
||||
{
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0)
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return ENOTCONN;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
return rip_abort(so);
|
||||
}
|
||||
|
||||
@ -552,7 +581,9 @@ rip_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
(addr->sin_family != AF_IMPLINK))
|
||||
return EAFNOSUPPORT;
|
||||
inp->inp_faddr = addr->sin_addr;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -570,13 +601,16 @@ rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
struct inpcb *inp = sotoinpcb(so);
|
||||
register u_long dst;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
SOCK_UNLOCK(so);
|
||||
if (nam) {
|
||||
m_freem(m);
|
||||
return EISCONN;
|
||||
}
|
||||
dst = inp->inp_faddr.s_addr;
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
if (nam == NULL) {
|
||||
m_freem(m);
|
||||
return ENOTCONN;
|
||||
|
@ -281,15 +281,21 @@ present:
|
||||
flags = q->tqe_th->th_flags & TH_FIN;
|
||||
nq = LIST_NEXT(q, tqe_q);
|
||||
LIST_REMOVE(q, tqe_q);
|
||||
if (so->so_state & SS_CANTRCVMORE)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
m_freem(q->tqe_m);
|
||||
else
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
sbappend(&so->so_rcv, q->tqe_m);
|
||||
}
|
||||
FREE(q, M_TSEGQ);
|
||||
q = nq;
|
||||
} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
|
||||
ND6_HINT(tp);
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return (flags);
|
||||
}
|
||||
|
||||
@ -638,6 +644,7 @@ findpcb:
|
||||
tiwin = th->th_win;
|
||||
|
||||
so = inp->inp_socket;
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
|
||||
struct in_conninfo inc;
|
||||
#ifdef TCPDEBUG
|
||||
@ -654,8 +661,11 @@ findpcb:
|
||||
}
|
||||
#endif
|
||||
/* skip if this isn't a listen socket */
|
||||
if ((so->so_options & SO_ACCEPTCONN) == 0)
|
||||
if ((so->so_options & SO_ACCEPTCONN) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
goto after_listen;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
#ifdef INET6
|
||||
inc.inc_isipv6 = isipv6;
|
||||
if (isipv6) {
|
||||
@ -868,11 +878,14 @@ findpcb:
|
||||
tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN);
|
||||
|
||||
tcpstat.tcps_connects++;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
goto trimthenstep6;
|
||||
}
|
||||
goto drop;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
after_listen:
|
||||
|
||||
/* XXX temp debugging */
|
||||
@ -1004,7 +1017,9 @@ after_listen:
|
||||
tp->t_rxtcur,
|
||||
tcp_timer_rexmt, tp);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
if (so->so_snd.sb_cc)
|
||||
(void) tcp_output(tp);
|
||||
return;
|
||||
@ -1027,7 +1042,9 @@ after_listen:
|
||||
*/
|
||||
m_adj(m, drop_hdrlen); /* delayed header drop */
|
||||
sbappend(&so->so_rcv, m);
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
if (DELAY_ACK(tp)) {
|
||||
callout_reset(tp->tt_delack, tcp_delacktime,
|
||||
tcp_timer_delack, tp);
|
||||
@ -1137,7 +1154,9 @@ after_listen:
|
||||
} else
|
||||
tp->t_flags &= ~TF_RCVD_CC;
|
||||
tcpstat.tcps_connects++;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
/* Do window scaling on this connection? */
|
||||
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
|
||||
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
|
||||
@ -1467,13 +1486,16 @@ trimthenstep6:
|
||||
* If new data are received on a connection after the
|
||||
* user processes are gone, then RST the other end.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_NOFDREF) &&
|
||||
tp->t_state > TCPS_CLOSE_WAIT && tlen) {
|
||||
SOCK_UNLOCK(so);
|
||||
tp = tcp_close(tp);
|
||||
tcpstat.tcps_rcvafterclose++;
|
||||
rstreason = BANDLIM_UNLIMITED;
|
||||
goto dropwithreset;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
/*
|
||||
* If segment ends after window, drop trailing data
|
||||
@ -1563,7 +1585,9 @@ trimthenstep6:
|
||||
case TCPS_SYN_RECEIVED:
|
||||
|
||||
tcpstat.tcps_connects++;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
/* Do window scaling? */
|
||||
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
|
||||
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
|
||||
@ -1822,7 +1846,9 @@ process_ACK:
|
||||
tp->snd_wnd -= acked;
|
||||
ourfinisacked = 0;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
tp->snd_una = th->th_ack;
|
||||
if (SEQ_LT(tp->snd_nxt, tp->snd_una))
|
||||
tp->snd_nxt = tp->snd_una;
|
||||
@ -1843,11 +1869,14 @@ process_ACK:
|
||||
* specification, but if we don't get a FIN
|
||||
* we'll hang forever.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
soisdisconnected_locked(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
callout_reset(tp->tt_2msl, tcp_maxidle,
|
||||
tcp_timer_2msl, tp);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
tp->t_state = TCPS_FIN_WAIT_2;
|
||||
}
|
||||
break;
|
||||
@ -1872,7 +1901,9 @@ process_ACK:
|
||||
else
|
||||
callout_reset(tp->tt_2msl, 2 * tcp_msl,
|
||||
tcp_timer_2msl, tp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1956,8 +1987,11 @@ step6:
|
||||
tp->rcv_up = th->th_seq + th->th_urp;
|
||||
so->so_oobmark = so->so_rcv.sb_cc +
|
||||
(tp->rcv_up - tp->rcv_nxt) - 1;
|
||||
if (so->so_oobmark == 0)
|
||||
if (so->so_oobmark == 0) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
sohasoutofband(so);
|
||||
tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
|
||||
}
|
||||
@ -1967,13 +2001,19 @@ step6:
|
||||
* but if two URG's are pending at once, some out-of-band
|
||||
* data may creep in... ick.
|
||||
*/
|
||||
if (th->th_urp <= (u_long)tlen
|
||||
if (th->th_urp <= (u_long)tlen) {
|
||||
#ifdef SO_OOBINLINE
|
||||
&& (so->so_options & SO_OOBINLINE) == 0
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & SO_OOBINLINE) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
)
|
||||
tcp_pulloutofband(so, th, m,
|
||||
drop_hdrlen); /* hdr drop is delayed */
|
||||
tcp_pulloutofband(so, th, m,
|
||||
drop_hdrlen); /* hdr drop is delayed */
|
||||
#ifdef SO_OOBINLINE
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* If no out of band data is expected,
|
||||
@ -2019,7 +2059,9 @@ dodata: /* XXX */
|
||||
tcpstat.tcps_rcvbyte += tlen;
|
||||
ND6_HINT(tp);
|
||||
sbappend(&so->so_rcv, m);
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
} else {
|
||||
thflags = tcp_reass(tp, th, &tlen, m);
|
||||
tp->t_flags |= TF_ACKNOW;
|
||||
@ -2098,7 +2140,9 @@ dodata: /* XXX */
|
||||
else
|
||||
callout_reset(tp->tt_2msl, 2 * tcp_msl,
|
||||
tcp_timer_2msl, tp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
|
||||
/*
|
||||
@ -2111,9 +2155,13 @@ dodata: /* XXX */
|
||||
}
|
||||
}
|
||||
#ifdef TCPDEBUG
|
||||
if (so->so_options & SO_DEBUG)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG) {
|
||||
SOCK_UNLOCK(so);
|
||||
tcp_trace(TA_INPUT, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -2146,9 +2194,13 @@ dropafterack:
|
||||
goto dropwithreset;
|
||||
}
|
||||
#ifdef TCPDEBUG
|
||||
if (so->so_options & SO_DEBUG)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG) {
|
||||
SOCK_UNLOCK(so);
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
m_freem(m);
|
||||
tp->t_flags |= TF_ACKNOW;
|
||||
@ -2184,9 +2236,18 @@ dropwithreset:
|
||||
goto drop;
|
||||
|
||||
#ifdef TCPDEBUG
|
||||
if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
if (tp == 0)
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
else {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
if (thflags & TH_ACK)
|
||||
/* mtod() below is safe as long as hdr dropping is delayed */
|
||||
@ -2206,9 +2267,18 @@ drop:
|
||||
* Drop space held by incoming segment and return.
|
||||
*/
|
||||
#ifdef TCPDEBUG
|
||||
if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
if (tp == 0)
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
else {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
m_freem(m);
|
||||
return;
|
||||
|
@ -126,6 +126,7 @@ tcp_output(tp)
|
||||
#ifdef INET6
|
||||
int isipv6;
|
||||
#endif
|
||||
int soopts;
|
||||
|
||||
#ifdef INET6
|
||||
isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0;
|
||||
@ -819,8 +820,12 @@ send:
|
||||
/*
|
||||
* Trace.
|
||||
*/
|
||||
if (so->so_options & SO_DEBUG)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG) {
|
||||
SOCK_UNLOCK(so);
|
||||
tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, void *), th, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -854,10 +859,13 @@ send:
|
||||
goto out;
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
SOCK_LOCK(so);
|
||||
soopts = (so->so_options & SO_DONTROUTE);
|
||||
SOCK_UNLOCK(so);
|
||||
error = ip6_output(m,
|
||||
tp->t_inpcb->in6p_outputopts,
|
||||
&tp->t_inpcb->in6p_route,
|
||||
(so->so_options & SO_DONTROUTE), NULL, NULL);
|
||||
soopts, NULL, NULL);
|
||||
} else
|
||||
#endif /* INET6 */
|
||||
{
|
||||
@ -889,8 +897,11 @@ send:
|
||||
#ifdef IPSEC
|
||||
ipsec_setsocket(m, so);
|
||||
#endif /*IPSEC*/
|
||||
SOCK_LOCK(so);
|
||||
soopts = (so->so_options & SO_DONTROUTE);
|
||||
SOCK_UNLOCK(so);
|
||||
error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
|
||||
(so->so_options & SO_DONTROUTE), 0);
|
||||
soopts, 0);
|
||||
}
|
||||
if (error) {
|
||||
|
||||
|
@ -281,15 +281,21 @@ present:
|
||||
flags = q->tqe_th->th_flags & TH_FIN;
|
||||
nq = LIST_NEXT(q, tqe_q);
|
||||
LIST_REMOVE(q, tqe_q);
|
||||
if (so->so_state & SS_CANTRCVMORE)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
m_freem(q->tqe_m);
|
||||
else
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
sbappend(&so->so_rcv, q->tqe_m);
|
||||
}
|
||||
FREE(q, M_TSEGQ);
|
||||
q = nq;
|
||||
} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
|
||||
ND6_HINT(tp);
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return (flags);
|
||||
}
|
||||
|
||||
@ -638,6 +644,7 @@ findpcb:
|
||||
tiwin = th->th_win;
|
||||
|
||||
so = inp->inp_socket;
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
|
||||
struct in_conninfo inc;
|
||||
#ifdef TCPDEBUG
|
||||
@ -654,8 +661,11 @@ findpcb:
|
||||
}
|
||||
#endif
|
||||
/* skip if this isn't a listen socket */
|
||||
if ((so->so_options & SO_ACCEPTCONN) == 0)
|
||||
if ((so->so_options & SO_ACCEPTCONN) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
goto after_listen;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
#ifdef INET6
|
||||
inc.inc_isipv6 = isipv6;
|
||||
if (isipv6) {
|
||||
@ -868,11 +878,14 @@ findpcb:
|
||||
tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN);
|
||||
|
||||
tcpstat.tcps_connects++;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
goto trimthenstep6;
|
||||
}
|
||||
goto drop;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
after_listen:
|
||||
|
||||
/* XXX temp debugging */
|
||||
@ -1004,7 +1017,9 @@ after_listen:
|
||||
tp->t_rxtcur,
|
||||
tcp_timer_rexmt, tp);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
if (so->so_snd.sb_cc)
|
||||
(void) tcp_output(tp);
|
||||
return;
|
||||
@ -1027,7 +1042,9 @@ after_listen:
|
||||
*/
|
||||
m_adj(m, drop_hdrlen); /* delayed header drop */
|
||||
sbappend(&so->so_rcv, m);
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
if (DELAY_ACK(tp)) {
|
||||
callout_reset(tp->tt_delack, tcp_delacktime,
|
||||
tcp_timer_delack, tp);
|
||||
@ -1137,7 +1154,9 @@ after_listen:
|
||||
} else
|
||||
tp->t_flags &= ~TF_RCVD_CC;
|
||||
tcpstat.tcps_connects++;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
/* Do window scaling on this connection? */
|
||||
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
|
||||
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
|
||||
@ -1467,13 +1486,16 @@ trimthenstep6:
|
||||
* If new data are received on a connection after the
|
||||
* user processes are gone, then RST the other end.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_NOFDREF) &&
|
||||
tp->t_state > TCPS_CLOSE_WAIT && tlen) {
|
||||
SOCK_UNLOCK(so);
|
||||
tp = tcp_close(tp);
|
||||
tcpstat.tcps_rcvafterclose++;
|
||||
rstreason = BANDLIM_UNLIMITED;
|
||||
goto dropwithreset;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
/*
|
||||
* If segment ends after window, drop trailing data
|
||||
@ -1563,7 +1585,9 @@ trimthenstep6:
|
||||
case TCPS_SYN_RECEIVED:
|
||||
|
||||
tcpstat.tcps_connects++;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
/* Do window scaling? */
|
||||
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
|
||||
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
|
||||
@ -1822,7 +1846,9 @@ process_ACK:
|
||||
tp->snd_wnd -= acked;
|
||||
ourfinisacked = 0;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
tp->snd_una = th->th_ack;
|
||||
if (SEQ_LT(tp->snd_nxt, tp->snd_una))
|
||||
tp->snd_nxt = tp->snd_una;
|
||||
@ -1843,11 +1869,14 @@ process_ACK:
|
||||
* specification, but if we don't get a FIN
|
||||
* we'll hang forever.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
soisdisconnected_locked(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
callout_reset(tp->tt_2msl, tcp_maxidle,
|
||||
tcp_timer_2msl, tp);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
tp->t_state = TCPS_FIN_WAIT_2;
|
||||
}
|
||||
break;
|
||||
@ -1872,7 +1901,9 @@ process_ACK:
|
||||
else
|
||||
callout_reset(tp->tt_2msl, 2 * tcp_msl,
|
||||
tcp_timer_2msl, tp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1956,8 +1987,11 @@ step6:
|
||||
tp->rcv_up = th->th_seq + th->th_urp;
|
||||
so->so_oobmark = so->so_rcv.sb_cc +
|
||||
(tp->rcv_up - tp->rcv_nxt) - 1;
|
||||
if (so->so_oobmark == 0)
|
||||
if (so->so_oobmark == 0) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
sohasoutofband(so);
|
||||
tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
|
||||
}
|
||||
@ -1967,13 +2001,19 @@ step6:
|
||||
* but if two URG's are pending at once, some out-of-band
|
||||
* data may creep in... ick.
|
||||
*/
|
||||
if (th->th_urp <= (u_long)tlen
|
||||
if (th->th_urp <= (u_long)tlen) {
|
||||
#ifdef SO_OOBINLINE
|
||||
&& (so->so_options & SO_OOBINLINE) == 0
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & SO_OOBINLINE) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
)
|
||||
tcp_pulloutofband(so, th, m,
|
||||
drop_hdrlen); /* hdr drop is delayed */
|
||||
tcp_pulloutofband(so, th, m,
|
||||
drop_hdrlen); /* hdr drop is delayed */
|
||||
#ifdef SO_OOBINLINE
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
/*
|
||||
* If no out of band data is expected,
|
||||
@ -2019,7 +2059,9 @@ dodata: /* XXX */
|
||||
tcpstat.tcps_rcvbyte += tlen;
|
||||
ND6_HINT(tp);
|
||||
sbappend(&so->so_rcv, m);
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
} else {
|
||||
thflags = tcp_reass(tp, th, &tlen, m);
|
||||
tp->t_flags |= TF_ACKNOW;
|
||||
@ -2098,7 +2140,9 @@ dodata: /* XXX */
|
||||
else
|
||||
callout_reset(tp->tt_2msl, 2 * tcp_msl,
|
||||
tcp_timer_2msl, tp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
|
||||
/*
|
||||
@ -2111,9 +2155,13 @@ dodata: /* XXX */
|
||||
}
|
||||
}
|
||||
#ifdef TCPDEBUG
|
||||
if (so->so_options & SO_DEBUG)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG) {
|
||||
SOCK_UNLOCK(so);
|
||||
tcp_trace(TA_INPUT, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -2146,9 +2194,13 @@ dropafterack:
|
||||
goto dropwithreset;
|
||||
}
|
||||
#ifdef TCPDEBUG
|
||||
if (so->so_options & SO_DEBUG)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG) {
|
||||
SOCK_UNLOCK(so);
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
m_freem(m);
|
||||
tp->t_flags |= TF_ACKNOW;
|
||||
@ -2184,9 +2236,18 @@ dropwithreset:
|
||||
goto drop;
|
||||
|
||||
#ifdef TCPDEBUG
|
||||
if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
if (tp == 0)
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
else {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
if (thflags & TH_ACK)
|
||||
/* mtod() below is safe as long as hdr dropping is delayed */
|
||||
@ -2206,9 +2267,18 @@ drop:
|
||||
* Drop space held by incoming segment and return.
|
||||
*/
|
||||
#ifdef TCPDEBUG
|
||||
if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
if (tp == 0)
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
else {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
|
||||
&tcp_savetcp, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
m_freem(m);
|
||||
return;
|
||||
|
@ -469,8 +469,16 @@ tcp_respond(tp, ipgen, th, m, ack, seq, flags)
|
||||
m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
|
||||
}
|
||||
#ifdef TCPDEBUG
|
||||
if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
if (tp == NULL)
|
||||
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
|
||||
else {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
#ifdef IPSEC
|
||||
if (ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL) != 0) {
|
||||
@ -720,7 +728,9 @@ tcp_close(tp)
|
||||
FREE(q, M_TSEGQ);
|
||||
}
|
||||
inp->inp_ppcb = NULL;
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
#ifdef INET6
|
||||
if (INP_CHECK_SOCKAF(so, AF_INET6))
|
||||
in6_pcbdetach(inp);
|
||||
@ -793,9 +803,11 @@ tcp_notify(inp, error)
|
||||
else
|
||||
tp->t_softerror = error;
|
||||
#if 0
|
||||
SOCK_LOCK(so);
|
||||
wakeup((caddr_t) &so->so_timeo);
|
||||
sorwakeup(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -39,13 +39,15 @@
|
||||
#include "opt_tcpdebug.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */
|
||||
|
||||
@ -211,9 +213,15 @@ tcp_timer_2msl(xtp)
|
||||
tp = tcp_close(tp);
|
||||
|
||||
#ifdef TCPDEBUG
|
||||
if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
if (tp != 0) {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
splx(s);
|
||||
}
|
||||
@ -243,9 +251,11 @@ tcp_timer_keep(xtp)
|
||||
tcpstat.tcps_keeptimeo++;
|
||||
if (tp->t_state < TCPS_ESTABLISHED)
|
||||
goto dropit;
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((always_keepalive ||
|
||||
tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) &&
|
||||
tp->t_state <= TCPS_CLOSING) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
if ((ticks - tp->t_rcvtime) >= tcp_keepidle + tcp_maxidle)
|
||||
goto dropit;
|
||||
/*
|
||||
@ -269,13 +279,19 @@ tcp_timer_keep(xtp)
|
||||
(void) m_free(dtom(t_template));
|
||||
}
|
||||
callout_reset(tp->tt_keep, tcp_keepintvl, tcp_timer_keep, tp);
|
||||
} else
|
||||
} else {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
callout_reset(tp->tt_keep, tcp_keepidle, tcp_timer_keep, tp);
|
||||
}
|
||||
|
||||
#ifdef TCPDEBUG
|
||||
if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
#endif
|
||||
splx(s);
|
||||
return;
|
||||
@ -285,9 +301,15 @@ dropit:
|
||||
tp = tcp_drop(tp, ETIMEDOUT);
|
||||
|
||||
#ifdef TCPDEBUG
|
||||
if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
if (tp != 0) {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
splx(s);
|
||||
}
|
||||
@ -335,9 +357,15 @@ tcp_timer_persist(xtp)
|
||||
|
||||
out:
|
||||
#ifdef TCPDEBUG
|
||||
if (tp && tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
if (tp != 0) {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
splx(s);
|
||||
}
|
||||
@ -470,9 +498,15 @@ tcp_timer_rexmt(xtp)
|
||||
|
||||
out:
|
||||
#ifdef TCPDEBUG
|
||||
if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
if (tp != 0) {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
|
||||
PRU_SLOWTIMO);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
splx(s);
|
||||
}
|
||||
|
@ -469,8 +469,16 @@ tcp_respond(tp, ipgen, th, m, ack, seq, flags)
|
||||
m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
|
||||
}
|
||||
#ifdef TCPDEBUG
|
||||
if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
if (tp == NULL)
|
||||
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
|
||||
else {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
}
|
||||
#endif
|
||||
#ifdef IPSEC
|
||||
if (ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL) != 0) {
|
||||
@ -720,7 +728,9 @@ tcp_close(tp)
|
||||
FREE(q, M_TSEGQ);
|
||||
}
|
||||
inp->inp_ppcb = NULL;
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
#ifdef INET6
|
||||
if (INP_CHECK_SOCKAF(so, AF_INET6))
|
||||
in6_pcbdetach(inp);
|
||||
@ -793,9 +803,11 @@ tcp_notify(inp, error)
|
||||
else
|
||||
tp->t_softerror = error;
|
||||
#if 0
|
||||
SOCK_LOCK(so);
|
||||
wakeup((caddr_t) &so->so_timeo);
|
||||
sorwakeup(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -103,8 +103,17 @@ static struct tcpcb *
|
||||
#ifdef TCPDEBUG
|
||||
#define TCPDEBUG0 int ostate = 0
|
||||
#define TCPDEBUG1() ostate = tp ? tp->t_state : 0
|
||||
#define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \
|
||||
tcp_trace(TA_USER, ostate, tp, 0, 0, req)
|
||||
#define TCPDEBUG2(req) \
|
||||
do { \
|
||||
if (tp != 0) { \
|
||||
SOCK_LOCK(so); \
|
||||
if (so->so_options & SO_DEBUG) { \
|
||||
SOCK_UNLOCK(so); \
|
||||
tcp_trace(TA_USER, ostate, tp, 0, 0, req); \
|
||||
} else \
|
||||
SOCK_UNLOCK(so); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define TCPDEBUG0
|
||||
#define TCPDEBUG1()
|
||||
@ -134,8 +143,10 @@ tcp_usr_attach(struct socket *so, int proto, struct thread *td)
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & SO_LINGER) && so->so_linger == 0)
|
||||
so->so_linger = TCP_LINGERTIME;
|
||||
SOCK_UNLOCK(so);
|
||||
tp = sototcpcb(so);
|
||||
out:
|
||||
TCPDEBUG2(PRU_ATTACH);
|
||||
@ -424,10 +435,13 @@ tcp_usr_accept(struct socket *so, struct sockaddr **nam)
|
||||
struct tcpcb *tp = NULL;
|
||||
TCPDEBUG0;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISDISCONNECTED) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ECONNABORTED;
|
||||
goto out;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (inp == 0) {
|
||||
splx(s);
|
||||
return (EINVAL);
|
||||
@ -448,10 +462,13 @@ tcp6_usr_accept(struct socket *so, struct sockaddr **nam)
|
||||
struct tcpcb *tp = NULL;
|
||||
TCPDEBUG0;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISDISCONNECTED) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ECONNABORTED;
|
||||
goto out;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (inp == 0) {
|
||||
splx(s);
|
||||
return (EINVAL);
|
||||
@ -654,10 +671,16 @@ tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags)
|
||||
struct tcpcb *tp;
|
||||
|
||||
COMMON_START();
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_oobmark == 0 &&
|
||||
(so->so_state & SS_RCVATMARK) == 0) ||
|
||||
so->so_options & SO_OOBINLINE ||
|
||||
tp->t_oobflags & TCPOOB_HADDATA) {
|
||||
so->so_options & SO_OOBINLINE) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (tp->t_oobflags & TCPOOB_HADDATA) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -755,7 +778,9 @@ tcp_connect(tp, nam, td)
|
||||
(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
|
||||
tp->request_r_scale++;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
soisconnecting(so);
|
||||
SOCK_UNLOCK(so);
|
||||
tcpstat.tcps_connattempt++;
|
||||
tp->t_state = TCPS_SYN_SENT;
|
||||
callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp);
|
||||
@ -841,7 +866,9 @@ tcp6_connect(tp, nam, td)
|
||||
(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
|
||||
tp->request_r_scale++;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
soisconnecting(so);
|
||||
SOCK_UNLOCK(so);
|
||||
tcpstat.tcps_connattempt++;
|
||||
tp->t_state = TCPS_SYN_SENT;
|
||||
callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp);
|
||||
@ -1039,16 +1066,21 @@ tcp_attach(so, td)
|
||||
inp->inp_vflag |= INP_IPV4;
|
||||
tp = tcp_newtcpcb(inp);
|
||||
if (tp == 0) {
|
||||
int nofd = so->so_state & SS_NOFDREF; /* XXX */
|
||||
int nofd;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
nofd = so->so_state & SS_NOFDREF; /* XXX */
|
||||
so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */
|
||||
SOCK_UNLOCK(so);
|
||||
#ifdef INET6
|
||||
if (isipv6)
|
||||
in6_pcbdetach(inp);
|
||||
else
|
||||
#endif
|
||||
in_pcbdetach(inp);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= nofd;
|
||||
SOCK_UNLOCK(so);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
tp->t_state = TCPS_CLOSED;
|
||||
@ -1071,14 +1103,19 @@ tcp_disconnect(tp)
|
||||
|
||||
if (tp->t_state < TCPS_ESTABLISHED)
|
||||
tp = tcp_close(tp);
|
||||
else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
|
||||
tp = tcp_drop(tp, 0);
|
||||
else {
|
||||
soisdisconnecting(so);
|
||||
sbflush(&so->so_rcv);
|
||||
tp = tcp_usrclosed(tp);
|
||||
if (tp)
|
||||
(void) tcp_output(tp);
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & SO_LINGER) && so->so_linger == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
tp = tcp_drop(tp, 0);
|
||||
} else {
|
||||
soisdisconnecting(so);
|
||||
SOCK_UNLOCK(so);
|
||||
sbflush(&so->so_rcv);
|
||||
tp = tcp_usrclosed(tp);
|
||||
if (tp)
|
||||
(void) tcp_output(tp);
|
||||
}
|
||||
}
|
||||
return (tp);
|
||||
}
|
||||
@ -1120,7 +1157,9 @@ tcp_usrclosed(tp)
|
||||
break;
|
||||
}
|
||||
if (tp && tp->t_state >= TCPS_FIN_WAIT_2) {
|
||||
SOCK_LOCK(tp->t_inpcb->inp_socket);
|
||||
soisdisconnected(tp->t_inpcb->inp_socket);
|
||||
SOCK_UNLOCK(tp->t_inpcb->inp_socket);
|
||||
/* To prevent the connection hanging in FIN_WAIT_2 forever. */
|
||||
if (tp->t_state == TCPS_FIN_WAIT_2)
|
||||
callout_reset(tp->tt_2msl, tcp_maxidle,
|
||||
|
@ -319,8 +319,12 @@ udp_input(m, off)
|
||||
* port. It * assumes that an application will never
|
||||
* clear these options after setting them.
|
||||
*/
|
||||
if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
|
||||
SOCK_LOCK(last->inp_socket);
|
||||
if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0) {
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
break;
|
||||
} else
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
}
|
||||
|
||||
if (last == NULL) {
|
||||
@ -384,8 +388,10 @@ udp_input(m, off)
|
||||
*/
|
||||
udp_in.sin_port = uh->uh_sport;
|
||||
udp_in.sin_addr = ip->ip_src;
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
if (inp->inp_flags & INP_CONTROLOPTS
|
||||
|| inp->inp_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
#ifdef INET6
|
||||
if (inp->inp_vflag & INP_IPV6) {
|
||||
int savedflags;
|
||||
@ -398,7 +404,8 @@ udp_input(m, off)
|
||||
} else
|
||||
#endif
|
||||
ip_savecontrol(inp, &opts, ip, m);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
m_adj(m, iphlen + sizeof(struct udphdr));
|
||||
#ifdef INET6
|
||||
if (inp->inp_vflag & INP_IPV6) {
|
||||
@ -411,7 +418,9 @@ udp_input(m, off)
|
||||
udpstat.udps_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
sorwakeup(inp->inp_socket);
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
return;
|
||||
bad:
|
||||
m_freem(m);
|
||||
@ -453,8 +462,10 @@ udp_append(last, ip, n, off)
|
||||
struct sockaddr *append_sa;
|
||||
struct mbuf *opts = 0;
|
||||
|
||||
SOCK_LOCK(last->inp_socket);
|
||||
if (last->inp_flags & INP_CONTROLOPTS ||
|
||||
last->inp_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
#ifdef INET6
|
||||
if (last->inp_vflag & INP_IPV6) {
|
||||
int savedflags;
|
||||
@ -470,7 +481,8 @@ udp_append(last, ip, n, off)
|
||||
} else
|
||||
#endif
|
||||
ip_savecontrol(last, &opts, ip, n);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
#ifdef INET6
|
||||
if (last->inp_vflag & INP_IPV6) {
|
||||
if (udp_in6.uin6_init_done == 0) {
|
||||
@ -487,8 +499,11 @@ udp_append(last, ip, n, off)
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
udpstat.udps_fullsock++;
|
||||
} else
|
||||
} else {
|
||||
SOCK_LOCK(last->inp_socket);
|
||||
sorwakeup(last->inp_socket);
|
||||
SOCK_UNLOCK(last->inp_socket);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -501,8 +516,10 @@ udp_notify(inp, errno)
|
||||
int errno;
|
||||
{
|
||||
inp->inp_socket->so_error = errno;
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
sorwakeup(inp->inp_socket);
|
||||
sowwakeup(inp->inp_socket);
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
}
|
||||
|
||||
void
|
||||
@ -678,7 +695,7 @@ udp_output(inp, m, addr, control, td)
|
||||
register int len = m->m_pkthdr.len;
|
||||
struct in_addr laddr;
|
||||
struct sockaddr_in *sin;
|
||||
int s = 0, error = 0;
|
||||
int s = 0, error = 0, soopts;
|
||||
|
||||
if (control)
|
||||
m_freem(control); /* XXX */
|
||||
@ -759,8 +776,11 @@ udp_output(inp, m, addr, control, td)
|
||||
goto release;
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
soopts = inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST);
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
error = ip_output(m, inp->inp_options, &inp->inp_route,
|
||||
(inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)),
|
||||
soopts,
|
||||
inp->inp_moptions);
|
||||
|
||||
if (addr) {
|
||||
@ -799,7 +819,9 @@ udp_abort(struct socket *so)
|
||||
inp = sotoinpcb(so);
|
||||
if (inp == 0)
|
||||
return EINVAL; /* ??? possible? panic instead? */
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
s = splnet();
|
||||
in_pcbdetach(inp);
|
||||
splx(s);
|
||||
@ -864,8 +886,11 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
|
||||
error = in_pcbconnect(inp, nam, td);
|
||||
splx(s);
|
||||
if (error == 0)
|
||||
if (error == 0) {
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -900,7 +925,9 @@ udp_disconnect(struct socket *so)
|
||||
in_pcbdisconnect(inp);
|
||||
inp->inp_laddr.s_addr = INADDR_ANY;
|
||||
splx(s);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_ISCONNECTED; /* XXX */
|
||||
SOCK_UNLOCK(so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1941,8 +1941,11 @@ icmp6_rip6_input(mp, off)
|
||||
if (opts) {
|
||||
m_freem(opts);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
sorwakeup(last->in6p_socket);
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
opts = NULL;
|
||||
}
|
||||
}
|
||||
@ -1958,8 +1961,11 @@ icmp6_rip6_input(mp, off)
|
||||
m_freem(m);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
} else
|
||||
} else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
sorwakeup(last->in6p_socket);
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
} else {
|
||||
m_freem(m);
|
||||
ip6stat.ip6s_delivered--;
|
||||
|
@ -124,14 +124,19 @@ in6_pcbbind(inp, nam, td)
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
|
||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
|
||||
u_short lport = 0;
|
||||
int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
|
||||
int wild = 0, reuseport;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
reuseport = (so->so_options & SO_REUSEPORT);
|
||||
SOCK_UNLOCK(so);
|
||||
if (!in6_ifaddr) /* XXX broken! */
|
||||
return (EADDRNOTAVAIL);
|
||||
if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
|
||||
return(EINVAL);
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
|
||||
wild = 1;
|
||||
SOCK_UNLOCK(so);
|
||||
if (nam) {
|
||||
sin6 = (struct sockaddr_in6 *)nam;
|
||||
if (nam->sa_len != sizeof(*sin6))
|
||||
@ -157,8 +162,10 @@ in6_pcbbind(inp, nam, td)
|
||||
* and a multicast address is bound on both
|
||||
* new and duplicated sockets.
|
||||
*/
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_REUSEADDR)
|
||||
reuseport = SO_REUSEADDR|SO_REUSEPORT;
|
||||
SOCK_UNLOCK(so);
|
||||
} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
struct ifaddr *ia = NULL;
|
||||
|
||||
@ -190,14 +197,19 @@ in6_pcbbind(inp, nam, td)
|
||||
t = in6_pcblookup_local(pcbinfo,
|
||||
&sin6->sin6_addr, lport,
|
||||
INPLOOKUP_WILDCARD);
|
||||
if (t &&
|
||||
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
|
||||
!IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
|
||||
(t->inp_socket->so_options &
|
||||
SO_REUSEPORT) == 0) &&
|
||||
(so->so_cred->cr_uid !=
|
||||
t->inp_socket->so_cred->cr_uid))
|
||||
return (EADDRINUSE);
|
||||
if (t != NULL) {
|
||||
SOCK_LOCK(t->inp_socket);
|
||||
if ((!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
|
||||
!IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
|
||||
(t->inp_socket->so_options &
|
||||
SO_REUSEPORT) == 0) &&
|
||||
(so->so_cred->cr_uid !=
|
||||
t->inp_socket->so_cred->cr_uid)) {
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
}
|
||||
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
struct sockaddr_in sin;
|
||||
@ -218,8 +230,14 @@ in6_pcbbind(inp, nam, td)
|
||||
}
|
||||
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
|
||||
lport, wild);
|
||||
if (t && (reuseport & t->inp_socket->so_options) == 0)
|
||||
return(EADDRINUSE);
|
||||
if (t != NULL) {
|
||||
SOCK_LOCK(t->inp_socket);
|
||||
if ((reuseport & t->inp_socket->so_options) == 0) {
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
return(EADDRINUSE);
|
||||
}
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
}
|
||||
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
struct sockaddr_in sin;
|
||||
@ -227,14 +245,19 @@ in6_pcbbind(inp, nam, td)
|
||||
in6_sin6_2_sin(&sin, sin6);
|
||||
t = in_pcblookup_local(pcbinfo, sin.sin_addr,
|
||||
lport, wild);
|
||||
if (t &&
|
||||
(reuseport & t->inp_socket->so_options)
|
||||
== 0 &&
|
||||
(ntohl(t->inp_laddr.s_addr)
|
||||
!= INADDR_ANY ||
|
||||
INP_SOCKAF(so) ==
|
||||
INP_SOCKAF(t->inp_socket)))
|
||||
return (EADDRINUSE);
|
||||
if (t != NULL) {
|
||||
SOCK_LOCK(t->inp_socket);
|
||||
if ((reuseport & t->inp_socket->so_options)
|
||||
== 0 &&
|
||||
(ntohl(t->inp_laddr.s_addr)
|
||||
!= INADDR_ANY ||
|
||||
INP_SOCKAF(so) ==
|
||||
INP_SOCKAF(t->inp_socket))) {
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
SOCK_UNLOCK(t->inp_socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
inp->in6p_laddr = sin6->sin6_addr;
|
||||
@ -589,8 +612,12 @@ in6_pcbdisconnect(inp)
|
||||
/* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
|
||||
inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
|
||||
in_pcbrehash(inp);
|
||||
if (inp->inp_socket->so_state & SS_NOFDREF)
|
||||
SOCK_LOCK(inp->inp_socket);
|
||||
if (inp->inp_socket->so_state & SS_NOFDREF) {
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
in6_pcbdetach(inp);
|
||||
} else
|
||||
SOCK_UNLOCK(inp->inp_socket);
|
||||
}
|
||||
|
||||
void
|
||||
@ -607,6 +634,7 @@ in6_pcbdetach(inp)
|
||||
inp->inp_gencnt = ++ipi->ipi_gencnt;
|
||||
in_pcbremlists(inp);
|
||||
sotoinpcb(so) = 0;
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
|
||||
if (inp->in6p_options)
|
||||
|
@ -338,9 +338,11 @@ in6_pcbsetport(laddr, inp, td)
|
||||
int count, error = 0, wild = 0;
|
||||
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
/* XXX: this is redundant when called from in6_pcbbind */
|
||||
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
|
||||
wild = INPLOOKUP_WILDCARD;
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
inp->inp_flags |= INP_ANONPORT;
|
||||
|
||||
|
@ -1147,16 +1147,19 @@ ip6_savecontrol(in6p, mp, ip6, m)
|
||||
privileged++;
|
||||
|
||||
#ifdef SO_TIMESTAMP
|
||||
SOCK_LOCK(in6p->in6p_socket);
|
||||
if ((in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0) {
|
||||
struct timeval tv;
|
||||
|
||||
SOCK_UNLOCK(in6p->in6p_socket);
|
||||
microtime(&tv);
|
||||
*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
|
||||
SCM_TIMESTAMP, SOL_SOCKET);
|
||||
if (*mp) {
|
||||
mp = &(*mp)->m_next;
|
||||
}
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(in6p->in6p_socket);
|
||||
#endif
|
||||
|
||||
/* RFC 2292 sec. 5 */
|
||||
|
@ -892,7 +892,9 @@ socket_send(s, mm, src)
|
||||
if (sbappendaddr(&s->so_rcv,
|
||||
(struct sockaddr *)src,
|
||||
mm, (struct mbuf *)0) != 0) {
|
||||
SOCK_LOCK(s);
|
||||
sorwakeup(s);
|
||||
SOCK_UNLOCK(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -182,9 +182,16 @@ rip6_input(mp, offp, proto)
|
||||
} else
|
||||
#endif /*IPSEC*/
|
||||
if (n) {
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS ||
|
||||
last->in6p_socket->so_options & SO_TIMESTAMP)
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS)
|
||||
ip6_savecontrol(last, &opts, ip6, n);
|
||||
else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
if (last->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
ip6_savecontrol(last, &opts, ip6, n);
|
||||
} else
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
/* strip intermediate headers */
|
||||
m_adj(n, *offp);
|
||||
if (sbappendaddr(&last->in6p_socket->so_rcv,
|
||||
@ -194,8 +201,11 @@ rip6_input(mp, offp, proto)
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
rip6stat.rip6s_fullsock++;
|
||||
} else
|
||||
} else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
sorwakeup(last->in6p_socket);
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
opts = NULL;
|
||||
}
|
||||
}
|
||||
@ -213,9 +223,16 @@ rip6_input(mp, offp, proto)
|
||||
} else
|
||||
#endif /*IPSEC*/
|
||||
if (last) {
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS ||
|
||||
last->in6p_socket->so_options & SO_TIMESTAMP)
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS)
|
||||
ip6_savecontrol(last, &opts, ip6, m);
|
||||
else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
if (last->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
ip6_savecontrol(last, &opts, ip6, m);
|
||||
} else
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
/* strip intermediate headers */
|
||||
m_adj(m, *offp);
|
||||
if (sbappendaddr(&last->in6p_socket->so_rcv,
|
||||
@ -224,8 +241,11 @@ rip6_input(mp, offp, proto)
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
rip6stat.rip6s_fullsock++;
|
||||
} else
|
||||
} else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
sorwakeup(last->in6p_socket);
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
} else {
|
||||
rip6stat.rip6s_nosock++;
|
||||
if (m->m_flags & M_MCAST)
|
||||
@ -591,7 +611,9 @@ rip6_detach(struct socket *so)
|
||||
static int
|
||||
rip6_abort(struct socket *so)
|
||||
{
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return rip6_detach(so);
|
||||
}
|
||||
|
||||
@ -600,8 +622,12 @@ rip6_disconnect(struct socket *so)
|
||||
{
|
||||
struct inpcb *inp = sotoinpcb(so);
|
||||
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0)
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return ENOTCONN;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
inp->in6p_faddr = in6addr_any;
|
||||
return rip6_abort(so);
|
||||
}
|
||||
@ -669,7 +695,9 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
return (error ? error : EADDRNOTAVAIL);
|
||||
inp->in6p_laddr = *in6a;
|
||||
inp->in6p_faddr = addr->sin6_addr;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -689,7 +717,9 @@ rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
struct sockaddr_in6 *dst;
|
||||
|
||||
/* always copy sockaddr to avoid overwrites */
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
SOCK_UNLOCK(so);
|
||||
if (nam) {
|
||||
m_freem(m);
|
||||
return EISCONN;
|
||||
@ -702,6 +732,7 @@ rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
sizeof(struct in6_addr));
|
||||
dst = &tmp;
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
if (nam == NULL) {
|
||||
m_freem(m);
|
||||
return ENOTCONN;
|
||||
|
@ -269,10 +269,18 @@ udp6_input(mp, offp, proto)
|
||||
* and m_copy() will copy M_PKTHDR
|
||||
* only if offset is 0.
|
||||
*/
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| last->in6p_socket->so_options & SO_TIMESTAMP)
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS)
|
||||
ip6_savecontrol(last, &opts,
|
||||
ip6, n);
|
||||
else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
if (last->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
ip6_savecontrol(last, &opts,
|
||||
ip6, n);
|
||||
} else
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
|
||||
m_adj(n, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&last->in6p_socket->so_rcv,
|
||||
@ -282,8 +290,11 @@ udp6_input(mp, offp, proto)
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
udpstat.udps_fullsock++;
|
||||
} else
|
||||
} else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
sorwakeup(last->in6p_socket);
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
opts = NULL;
|
||||
}
|
||||
}
|
||||
@ -296,9 +307,13 @@ udp6_input(mp, offp, proto)
|
||||
* port. It assumes that an application will never
|
||||
* clear these options after setting them.
|
||||
*/
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
if ((last->in6p_socket->so_options &
|
||||
(SO_REUSEPORT|SO_REUSEADDR)) == 0)
|
||||
(SO_REUSEPORT|SO_REUSEADDR)) == 0) {
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
break;
|
||||
} else
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
|
||||
if (last == NULL) {
|
||||
@ -320,9 +335,16 @@ udp6_input(mp, offp, proto)
|
||||
goto bad;
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| last->in6p_socket->so_options & SO_TIMESTAMP)
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS)
|
||||
ip6_savecontrol(last, &opts, ip6, m);
|
||||
else {
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
if (last->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
ip6_savecontrol(last, &opts, ip6, m);
|
||||
} else
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
}
|
||||
|
||||
m_adj(m, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&last->in6p_socket->so_rcv,
|
||||
@ -331,7 +353,9 @@ udp6_input(mp, offp, proto)
|
||||
udpstat.udps_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
SOCK_LOCK(last->in6p_socket);
|
||||
sorwakeup(last->in6p_socket);
|
||||
SOCK_UNLOCK(last->in6p_socket);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
/*
|
||||
@ -375,9 +399,16 @@ udp6_input(mp, offp, proto)
|
||||
*/
|
||||
init_sin6(&udp_in6, m); /* general init */
|
||||
udp_in6.sin6_port = uh->uh_sport;
|
||||
if (in6p->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| in6p->in6p_socket->so_options & SO_TIMESTAMP)
|
||||
if (in6p->in6p_flags & IN6P_CONTROLOPTS)
|
||||
ip6_savecontrol(in6p, &opts, ip6, m);
|
||||
else {
|
||||
SOCK_LOCK(in6p->in6p_socket);
|
||||
if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
SOCK_UNLOCK(in6p->in6p_socket);
|
||||
ip6_savecontrol(in6p, &opts, ip6, m);
|
||||
} else
|
||||
SOCK_UNLOCK(in6p->in6p_socket);
|
||||
}
|
||||
m_adj(m, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&in6p->in6p_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in6,
|
||||
@ -385,7 +416,9 @@ udp6_input(mp, offp, proto)
|
||||
udpstat.udps_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
SOCK_LOCK(in6p->in6p_socket);
|
||||
sorwakeup(in6p->in6p_socket);
|
||||
SOCK_UNLOCK(in6p->in6p_socket);
|
||||
return IPPROTO_DONE;
|
||||
bad:
|
||||
if (m)
|
||||
@ -509,7 +542,9 @@ udp6_abort(struct socket *so)
|
||||
inp = sotoinpcb(so);
|
||||
if (inp == 0)
|
||||
return EINVAL; /* ??? possible? panic instead? */
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
s = splnet();
|
||||
in6_pcbdetach(inp);
|
||||
splx(s);
|
||||
@ -614,7 +649,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
if (error == 0) {
|
||||
inp->inp_vflag |= INP_IPV4;
|
||||
inp->inp_vflag &= ~INP_IPV6;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@ -629,7 +666,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
inp->inp_vflag &= ~INP_IPV4;
|
||||
inp->inp_vflag |= INP_IPV6;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@ -673,7 +712,9 @@ udp6_disconnect(struct socket *so)
|
||||
in6_pcbdisconnect(inp);
|
||||
inp->in6p_laddr = in6addr_any;
|
||||
splx(s);
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_ISCONNECTED; /* XXX */
|
||||
SOCK_UNLOCK(so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -156,8 +156,12 @@ ipx_pcbconnect(ipxp, nam, td)
|
||||
*/
|
||||
ro = &ipxp->ipxp_route;
|
||||
dst = &satoipx_addr(ro->ro_dst);
|
||||
if (ipxp->ipxp_socket->so_options & SO_DONTROUTE)
|
||||
SOCK_LOCK(ipxp->ipxp_socket);
|
||||
if (ipxp->ipxp_socket->so_options & SO_DONTROUTE) {
|
||||
SOCK_UNLOCK(ipxp->ipxp_socket);
|
||||
goto flush;
|
||||
}
|
||||
SOCK_UNLOCK(ipxp->ipxp_socket);
|
||||
if (!ipx_neteq(ipxp->ipxp_lastdst, sipx->sipx_addr))
|
||||
goto flush;
|
||||
if (!ipx_hosteq(ipxp->ipxp_lastdst, sipx->sipx_addr)) {
|
||||
@ -172,15 +176,18 @@ ipx_pcbconnect(ipxp, nam, td)
|
||||
}
|
||||
}/* else cached route is ok; do nothing */
|
||||
ipxp->ipxp_lastdst = sipx->sipx_addr;
|
||||
SOCK_LOCK(ipxp->ipxp_socket);
|
||||
if ((ipxp->ipxp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
|
||||
(ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL)) {
|
||||
SOCK_UNLOCK(ipxp->ipxp_socket);
|
||||
/* No route yet, so try to acquire one */
|
||||
ro->ro_dst.sa_family = AF_IPX;
|
||||
ro->ro_dst.sa_len = sizeof(ro->ro_dst);
|
||||
*dst = sipx->sipx_addr;
|
||||
dst->x_port = 0;
|
||||
rtalloc(ro);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(ipxp->ipxp_socket);
|
||||
if (ipx_neteqnn(ipxp->ipxp_laddr.x_net, ipx_zeronet)) {
|
||||
/*
|
||||
* If route is known or can be allocated now,
|
||||
@ -257,8 +264,12 @@ ipx_pcbdisconnect(ipxp)
|
||||
{
|
||||
|
||||
ipxp->ipxp_faddr = zeroipx_addr;
|
||||
if (ipxp->ipxp_socket->so_state & SS_NOFDREF)
|
||||
SOCK_LOCK(ipxp->ipxp_socket);
|
||||
if (ipxp->ipxp_socket->so_state & SS_NOFDREF) {
|
||||
SOCK_UNLOCK(ipxp->ipxp_socket);
|
||||
ipx_pcbdetach(ipxp);
|
||||
} else
|
||||
SOCK_UNLOCK(ipxp->ipxp_socket);
|
||||
}
|
||||
|
||||
void
|
||||
@ -268,6 +279,7 @@ ipx_pcbdetach(ipxp)
|
||||
struct socket *so = ipxp->ipxp_socket;
|
||||
|
||||
so->so_pcb = 0;
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
if (ipxp->ipxp_route.ro_rt != NULL)
|
||||
rtfree(ipxp->ipxp_route.ro_rt);
|
||||
|
@ -146,7 +146,9 @@ ipx_input(m, ipxp)
|
||||
if (sbappendaddr(&ipxp->ipxp_socket->so_rcv, (struct sockaddr *)&ipx_ipx,
|
||||
m, (struct mbuf *)NULL) == 0)
|
||||
goto bad;
|
||||
SOCK_LOCK(ipxp->ipxp_socket);
|
||||
sorwakeup(ipxp->ipxp_socket);
|
||||
SOCK_UNLOCK(ipxp->ipxp_socket);
|
||||
return;
|
||||
bad:
|
||||
m_freem(m);
|
||||
@ -159,7 +161,9 @@ ipx_abort(ipxp)
|
||||
struct socket *so = ipxp->ipxp_socket;
|
||||
|
||||
ipx_pcbdisconnect(ipxp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -186,7 +190,9 @@ ipx_drop(ipxp, errno)
|
||||
}*/
|
||||
so->so_error = errno;
|
||||
ipx_pcbdisconnect(ipxp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -200,6 +206,7 @@ ipx_output(ipxp, m0)
|
||||
register struct route *ro;
|
||||
struct mbuf *m;
|
||||
struct mbuf *mprev = NULL;
|
||||
int soopts;
|
||||
|
||||
/*
|
||||
* Calculate data length.
|
||||
@ -261,9 +268,14 @@ ipx_output(ipxp, m0)
|
||||
* Output datagram.
|
||||
*/
|
||||
so = ipxp->ipxp_socket;
|
||||
if (so->so_options & SO_DONTROUTE)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DONTROUTE) {
|
||||
soopts = so->so_options & SO_BROADCAST;
|
||||
SOCK_UNLOCK(so);
|
||||
return (ipx_outputfl(m, (struct route *)NULL,
|
||||
(so->so_options & SO_BROADCAST) | IPX_ROUTETOIF));
|
||||
soopts | IPX_ROUTETOIF));
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
/*
|
||||
* Use cached route for previous datagram if
|
||||
* possible. If the previous net was the same
|
||||
@ -306,7 +318,10 @@ ipx_output(ipxp, m0)
|
||||
}
|
||||
ipxp->ipxp_lastdst = ipx->ipx_dna;
|
||||
#endif /* ancient_history */
|
||||
return (ipx_outputfl(m, ro, so->so_options & SO_BROADCAST));
|
||||
SOCK_LOCK(so);
|
||||
soopts = so->so_options & SO_BROADCAST;
|
||||
SOCK_UNLOCK(so);
|
||||
return (ipx_outputfl(m, ro, soopts));
|
||||
}
|
||||
|
||||
int
|
||||
@ -429,8 +444,11 @@ ipx_usr_abort(so)
|
||||
s = splnet();
|
||||
ipx_pcbdetach(ipxp);
|
||||
splx(s);
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -480,8 +498,11 @@ ipx_connect(so, nam, td)
|
||||
s = splnet();
|
||||
error = ipx_pcbconnect(ipxp, nam, td);
|
||||
splx(s);
|
||||
if (error == 0)
|
||||
if (error == 0) {
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -512,7 +533,9 @@ ipx_disconnect(so)
|
||||
s = splnet();
|
||||
ipx_pcbdisconnect(ipxp);
|
||||
splx(s);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -163,6 +163,7 @@ spx_input(m, ipxp)
|
||||
|
||||
so = ipxp->ipxp_socket;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG || traceallspxs) {
|
||||
ostate = cb->s_state;
|
||||
spx_savesi = *si;
|
||||
@ -170,6 +171,7 @@ spx_input(m, ipxp)
|
||||
if (so->so_options & SO_ACCEPTCONN) {
|
||||
struct spxpcb *ocb = cb;
|
||||
|
||||
SOCK_UNLOCK(so);
|
||||
so = sonewconn(so, 0);
|
||||
if (so == NULL) {
|
||||
goto drop;
|
||||
@ -193,7 +195,8 @@ spx_input(m, ipxp)
|
||||
cb->s_flags = ocb->s_flags; /* preserve sockopts */
|
||||
cb->s_flags2 = ocb->s_flags2; /* preserve sockopts */
|
||||
cb->s_state = TCPS_LISTEN;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
/*
|
||||
* Packet received on connection.
|
||||
@ -258,7 +261,9 @@ spx_input(m, ipxp)
|
||||
ipxp->ipxp_fport = si->si_sport;
|
||||
cb->s_timer[SPXT_REXMT] = 0;
|
||||
cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
cb->s_state = TCPS_ESTABLISHED;
|
||||
spxstat.spxs_accepts++;
|
||||
}
|
||||
@ -285,7 +290,9 @@ spx_input(m, ipxp)
|
||||
cb->s_dport = ipxp->ipxp_fport = si->si_sport;
|
||||
cb->s_timer[SPXT_REXMT] = 0;
|
||||
cb->s_flags |= SF_ACKNOW;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
cb->s_state = TCPS_ESTABLISHED;
|
||||
/* Use roundtrip time of connection request for initial rtt */
|
||||
if (cb->s_rtt) {
|
||||
@ -297,8 +304,12 @@ spx_input(m, ipxp)
|
||||
cb->s_rtt = 0;
|
||||
}
|
||||
}
|
||||
if (so->so_options & SO_DEBUG || traceallspxs)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG || traceallspxs) {
|
||||
SOCK_UNLOCK(so);
|
||||
spx_trace(SA_INPUT, (u_char)ostate, cb, &spx_savesi, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
m->m_len -= sizeof(struct ipx);
|
||||
m->m_pkthdr.len -= sizeof(struct ipx);
|
||||
@ -319,15 +330,23 @@ dropwithreset:
|
||||
si->si_ack = ntohs(si->si_ack);
|
||||
si->si_alo = ntohs(si->si_alo);
|
||||
m_freem(dtom(si));
|
||||
if (cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG || traceallspxs)
|
||||
SOCK_LOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
if (cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG || traceallspxs) {
|
||||
SOCK_UNLOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
spx_trace(SA_DROP, (u_char)ostate, cb, &spx_savesi, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
return;
|
||||
|
||||
drop:
|
||||
bad:
|
||||
SOCK_LOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
if (cb == 0 || cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG ||
|
||||
traceallspxs)
|
||||
traceallspxs) {
|
||||
SOCK_UNLOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
spx_trace(SA_DROP, (u_char)ostate, cb, &spx_savesi, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
@ -462,7 +481,9 @@ register struct spx *si;
|
||||
else
|
||||
break;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
cb->s_rack = si->si_ack;
|
||||
update_window:
|
||||
if (SSEQ_LT(cb->s_snxt, cb->s_rack))
|
||||
@ -501,10 +522,13 @@ update_window:
|
||||
} /* else queue this packet; */
|
||||
} else {
|
||||
/*register struct socket *so = cb->s_ipxpcb->ipxp_socket;
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state && SS_NOFDREF) {
|
||||
SOCK_UNLOCK(so);
|
||||
spx_close(cb);
|
||||
} else
|
||||
would crash system*/
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
would crash system } */
|
||||
spx_istat.notyet++;
|
||||
m_freem(dtom(si));
|
||||
return (0);
|
||||
@ -565,8 +589,11 @@ present:
|
||||
cb->s_oobflags &= ~SF_IOOB;
|
||||
if (so->so_rcv.sb_cc)
|
||||
so->so_oobmark = so->so_rcv.sb_cc;
|
||||
else
|
||||
else {
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
}
|
||||
q = q->si_prev;
|
||||
remque(q->si_next);
|
||||
@ -596,7 +623,9 @@ present:
|
||||
MCHTYPE(m, MT_OOBDATA);
|
||||
spx_newchecks[1]++;
|
||||
so->so_oobmark = 0;
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
if (packetp == 0) {
|
||||
m->m_data += SPINC;
|
||||
@ -622,8 +651,11 @@ present:
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (wakeup)
|
||||
if (wakeup) {
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1027,8 +1059,12 @@ send:
|
||||
si->si_cc |= SPX_SP;
|
||||
} else {
|
||||
cb->s_outx = 3;
|
||||
if (so->so_options & SO_DEBUG || traceallspxs)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG || traceallspxs) {
|
||||
SOCK_UNLOCK(so);
|
||||
spx_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
@ -1090,13 +1126,20 @@ send:
|
||||
si->si_sum = 0xffff;
|
||||
|
||||
cb->s_outx = 4;
|
||||
if (so->so_options & SO_DEBUG || traceallspxs)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG || traceallspxs) {
|
||||
SOCK_UNLOCK(so);
|
||||
spx_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
|
||||
if (so->so_options & SO_DONTROUTE)
|
||||
if (so->so_options & SO_DONTROUTE) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ipx_outputfl(m, (struct route *)NULL, IPX_ROUTETOIF);
|
||||
else
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ipx_outputfl(m, &cb->s_ipxpcb->ipxp_route, 0);
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
return (error);
|
||||
@ -1413,7 +1456,9 @@ spx_connect(so, nam, td)
|
||||
error = ipx_pcbconnect(ipxp, nam, td);
|
||||
if (error)
|
||||
goto spx_connect_end;
|
||||
SOCK_LOCK(so);
|
||||
soisconnecting(so);
|
||||
SOCK_UNLOCK(so);
|
||||
spxstat.spxs_connattempt++;
|
||||
cb->s_state = TCPS_SYN_SENT;
|
||||
cb->s_did = 0;
|
||||
@ -1535,12 +1580,15 @@ spx_rcvoob(so, m, flags)
|
||||
ipxp = sotoipxpcb(so);
|
||||
cb = ipxtospxpcb(ipxp);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark ||
|
||||
(so->so_state & SS_RCVATMARK)) {
|
||||
SOCK_UNLOCK(so);
|
||||
m->m_len = 1;
|
||||
*mtod(m, caddr_t) = cb->s_iobc;
|
||||
return (0);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
@ -1684,7 +1732,9 @@ spx_close(cb)
|
||||
m_free(dtom(cb->s_ipx));
|
||||
FREE(cb, M_PCB);
|
||||
ipxp->ipxp_pcb = 0;
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
ipx_pcbdetach(ipxp);
|
||||
spxstat.spxs_closed++;
|
||||
return ((struct spxpcb *)NULL);
|
||||
@ -1887,13 +1937,17 @@ spx_timers(cb, timer)
|
||||
spxstat.spxs_keeptimeo++;
|
||||
if (cb->s_state < TCPS_ESTABLISHED)
|
||||
goto dropit;
|
||||
SOCK_LOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
if (cb->s_ipxpcb->ipxp_socket->so_options & SO_KEEPALIVE) {
|
||||
SOCK_UNLOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
if (cb->s_idle >= SPXTV_MAXIDLE)
|
||||
goto dropit;
|
||||
spxstat.spxs_keepprobe++;
|
||||
spx_output(cb, (struct mbuf *)NULL);
|
||||
} else
|
||||
} else {
|
||||
SOCK_UNLOCK(cb->s_ipxpcb->ipxp_socket);
|
||||
cb->s_idle = 0;
|
||||
}
|
||||
cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
|
||||
break;
|
||||
dropit:
|
||||
|
@ -174,7 +174,9 @@ key_sendup0(rp, m, promisc)
|
||||
error = ENOBUFS;
|
||||
} else
|
||||
error = 0;
|
||||
SOCK_LOCK(rp->rcb_socket);
|
||||
sorwakeup(rp->rcb_socket);
|
||||
SOCK_UNLOCK(rp->rcb_socket);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -427,8 +429,10 @@ key_attach(struct socket *so, int proto, struct thread *td)
|
||||
key_cb.any_count++;
|
||||
kp->kp_raw.rcb_laddr = &key_src;
|
||||
kp->kp_raw.rcb_faddr = &key_dst;
|
||||
soisconnected_locked(so);
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
so->so_options |= SO_USELOOPBACK;
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
splx(s);
|
||||
return 0;
|
||||
|
@ -134,6 +134,7 @@ natm_usr_detach(struct socket *so)
|
||||
*/
|
||||
npcb_free(npcb, NPCB_DESTROY); /* drain */
|
||||
so->so_pcb = NULL;
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
out:
|
||||
splx(s);
|
||||
@ -216,7 +217,9 @@ natm_usr_connect(struct socket *so, struct sockaddr *nam, d_thread_t *p)
|
||||
}
|
||||
splx(s2);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
out:
|
||||
splx(s);
|
||||
@ -259,7 +262,9 @@ natm_usr_disconnect(struct socket *so)
|
||||
splx(s2);
|
||||
|
||||
npcb_free(npcb, NPCB_REMOVE);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
out:
|
||||
splx(s);
|
||||
@ -482,6 +487,7 @@ struct proc *p;
|
||||
|
||||
npcb_free(npcb, NPCB_DESTROY); /* drain */
|
||||
so->so_pcb = NULL;
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
|
||||
break;
|
||||
@ -552,7 +558,9 @@ struct proc *p;
|
||||
}
|
||||
splx(s2);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
break;
|
||||
|
||||
@ -579,7 +587,9 @@ struct proc *p;
|
||||
splx(s2);
|
||||
|
||||
npcb_free(npcb, NPCB_REMOVE);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
break;
|
||||
|
||||
@ -752,7 +762,9 @@ m->m_pkthdr.rcvif = NULL; /* null it out to be safe */
|
||||
natm_sookbytes += m->m_pkthdr.len;
|
||||
#endif
|
||||
sbappendrecord(&so->so_rcv, m);
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
} else {
|
||||
#ifdef NATM_STAT
|
||||
natm_sodropcnt++;
|
||||
|
@ -86,15 +86,18 @@ ncp_soconnect(struct socket *so,struct sockaddr *target, struct proc *p) {
|
||||
*/
|
||||
error = EIO;
|
||||
s = splnet();
|
||||
SOCK_LOCK(so);
|
||||
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
|
||||
(void) tsleep((caddr_t)&so->so_timeo, PSOCK, "ncpcon", 2 * hz);
|
||||
(void) msleep((caddr_t)&so->so_timeo, SOCK_MTX(so), PSOCK, "ncpcon", 2 * hz);
|
||||
if ((so->so_state & SS_ISCONNECTING) &&
|
||||
so->so_error == 0 /*&& rep &&*/) {
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (so->so_error) {
|
||||
error = so->so_error;
|
||||
so->so_error = 0;
|
||||
|
@ -97,7 +97,9 @@ idp_input(m, nsp)
|
||||
if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns,
|
||||
m, (struct mbuf *)0) == 0)
|
||||
goto bad;
|
||||
SOCK_LOCK(nsp->nsp_socket);
|
||||
sorwakeup(nsp->nsp_socket);
|
||||
SOCK_UNLOCK(nsp->nsp_socket);
|
||||
return;
|
||||
bad:
|
||||
m_freem(m);
|
||||
@ -109,7 +111,9 @@ idp_abort(nsp)
|
||||
struct socket *so = nsp->nsp_socket;
|
||||
|
||||
ns_pcbdisconnect(nsp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
/*
|
||||
* Drop connection, reporting
|
||||
@ -133,7 +137,9 @@ idp_drop(nsp, errno)
|
||||
}*/
|
||||
so->so_error = errno;
|
||||
ns_pcbdisconnect(nsp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
int noIdpRoute;
|
||||
@ -148,6 +154,7 @@ idp_output(nsp, m0)
|
||||
register struct route *ro;
|
||||
struct mbuf *mprev;
|
||||
extern int idpcksum;
|
||||
int soopts;
|
||||
|
||||
/*
|
||||
* Calculate data length.
|
||||
@ -211,9 +218,14 @@ idp_output(nsp, m0)
|
||||
* Output datagram.
|
||||
*/
|
||||
so = nsp->nsp_socket;
|
||||
if (so->so_options & SO_DONTROUTE)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DONTROUTE) {
|
||||
soopts = so->so_options & SO_BROADCAST;
|
||||
SO_UNLOCK(so);
|
||||
return (ns_output(m, (struct route *)0,
|
||||
(so->so_options & SO_BROADCAST) | NS_ROUTETOIF));
|
||||
soopts | NS_ROUTETOIF));
|
||||
}
|
||||
SO_UNLOCK(so);
|
||||
/*
|
||||
* Use cached route for previous datagram if
|
||||
* possible. If the previous net was the same
|
||||
@ -257,7 +269,10 @@ idp_output(nsp, m0)
|
||||
nsp->nsp_lastdst = idp->idp_dna;
|
||||
#endif /* ancient_history */
|
||||
if (noIdpRoute) ro = 0;
|
||||
return (ns_output(m, ro, so->so_options & SO_BROADCAST));
|
||||
SOCK_LOCK(so);
|
||||
soopts = so->so_options & SO_BROADCAST;
|
||||
SOCK_UNLOCK(so);
|
||||
return (ns_output(m, ro, soopts));
|
||||
}
|
||||
/* ARGSUSED */
|
||||
idp_ctloutput(req, so, level, name, value)
|
||||
@ -427,8 +442,11 @@ idp_usrreq(so, req, m, nam, control)
|
||||
break;
|
||||
}
|
||||
error = ns_pcbconnect(nsp, nam);
|
||||
if (error == 0)
|
||||
if (error == 0) {
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
break;
|
||||
|
||||
case PRU_CONNECT2:
|
||||
@ -445,7 +463,9 @@ idp_usrreq(so, req, m, nam, control)
|
||||
break;
|
||||
}
|
||||
ns_pcbdisconnect(nsp);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
|
||||
case PRU_SHUTDOWN:
|
||||
@ -491,8 +511,11 @@ idp_usrreq(so, req, m, nam, control)
|
||||
|
||||
case PRU_ABORT:
|
||||
ns_pcbdetach(nsp);
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so); /* XXX huh, called after sofree()? */
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
|
||||
case PRU_SOCKADDR:
|
||||
@ -546,10 +569,13 @@ idp_raw_usrreq(so, req, m, nam, control)
|
||||
|
||||
case PRU_ATTACH:
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if (!(so->so_state & SS_PRIV) || (nsp != NULL)) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
error = ns_pcballoc(so, &nsrawpcb);
|
||||
if (error)
|
||||
break;
|
||||
|
@ -107,8 +107,12 @@ ns_control(so, cmd, data, ifp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((so->so_state & SS_PRIV) == 0)
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_PRIV) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return (EPERM);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCAIFADDR:
|
||||
|
@ -94,9 +94,13 @@ ns_pcbbind(nsp, nam)
|
||||
if (lport) {
|
||||
u_short aport = ntohs(lport);
|
||||
|
||||
SOCK_LOCK(so);
|
||||
if (aport < NSPORT_RESERVED &&
|
||||
(nsp->nsp_socket->so_state & SS_PRIV) == 0)
|
||||
(nsp->nsp_socket->so_state & SS_PRIV) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
return (EACCES);
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (ns_pcblookup(&zerons_addr, lport, 0))
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
@ -148,8 +152,12 @@ ns_pcbconnect(nsp, nam)
|
||||
*/
|
||||
ro = &nsp->nsp_route;
|
||||
dst = &satons_addr(ro->ro_dst);
|
||||
if (nsp->nsp_socket->so_options & SO_DONTROUTE)
|
||||
SOCK_LOCK(nsp->nsp_socket);
|
||||
if (nsp->nsp_socket->so_options & SO_DONTROUTE) {
|
||||
SOCK_UNLOCK(nsp->nsp_socket);
|
||||
goto flush;
|
||||
}
|
||||
SOCK_UNLOCK(nsp->nsp_socket);
|
||||
if (!ns_neteq(nsp->nsp_lastdst, sns->sns_addr))
|
||||
goto flush;
|
||||
if (!ns_hosteq(nsp->nsp_lastdst, sns->sns_addr)) {
|
||||
@ -165,16 +173,19 @@ ns_pcbconnect(nsp, nam)
|
||||
}
|
||||
}/* else cached route is ok; do nothing */
|
||||
nsp->nsp_lastdst = sns->sns_addr;
|
||||
SOCK_LOCK(nsp->nsp_socket);
|
||||
if ((nsp->nsp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
|
||||
(ro->ro_rt == (struct rtentry *)0 ||
|
||||
ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
|
||||
SOCK_UNLOCK(nsp->nsp_socket);
|
||||
/* No route yet, so try to acquire one */
|
||||
ro->ro_dst.sa_family = AF_NS;
|
||||
ro->ro_dst.sa_len = sizeof(ro->ro_dst);
|
||||
*dst = sns->sns_addr;
|
||||
dst->x_port = 0;
|
||||
rtalloc(ro);
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(nsp->nsp_socket);
|
||||
if (ns_neteqnn(nsp->nsp_laddr.x_net, ns_zeronet)) {
|
||||
/*
|
||||
* If route is known or can be allocated now,
|
||||
@ -222,8 +233,12 @@ ns_pcbdisconnect(nsp)
|
||||
{
|
||||
|
||||
nsp->nsp_faddr = zerons_addr;
|
||||
if (nsp->nsp_socket->so_state & SS_NOFDREF)
|
||||
SOCK_LOCK(so);
|
||||
if (nsp->nsp_socket->so_state & SS_NOFDREF) {
|
||||
SOCK_UNLOCK(so);
|
||||
ns_pcbdetach(nsp);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
|
||||
ns_pcbdetach(nsp)
|
||||
@ -232,6 +247,7 @@ ns_pcbdetach(nsp)
|
||||
struct socket *so = nsp->nsp_socket;
|
||||
|
||||
so->so_pcb = 0;
|
||||
SOCK_LOCK(so);
|
||||
sotryfree(so);
|
||||
if (nsp->nsp_route.ro_rt)
|
||||
rtfree(nsp->nsp_route.ro_rt);
|
||||
|
@ -106,6 +106,7 @@ spp_input(m, nsp)
|
||||
si->si_alo = ntohs(si->si_alo);
|
||||
|
||||
so = nsp->nsp_socket;
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG || traceallspps) {
|
||||
ostate = cb->s_state;
|
||||
spp_savesi = *si;
|
||||
@ -113,6 +114,7 @@ spp_input(m, nsp)
|
||||
if (so->so_options & SO_ACCEPTCONN) {
|
||||
struct sppcb *ocb = cb;
|
||||
|
||||
SOCK_UNLOCK(so);
|
||||
so = sonewconn(so, 0);
|
||||
if (so == 0) {
|
||||
goto drop;
|
||||
@ -136,7 +138,8 @@ spp_input(m, nsp)
|
||||
cb->s_flags = ocb->s_flags; /* preserve sockopts */
|
||||
cb->s_flags2 = ocb->s_flags2; /* preserve sockopts */
|
||||
cb->s_state = TCPS_LISTEN;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
/*
|
||||
* Packet received on connection.
|
||||
@ -207,7 +210,9 @@ spp_input(m, nsp)
|
||||
nsp->nsp_fport = si->si_sport;
|
||||
cb->s_timer[SPPT_REXMT] = 0;
|
||||
cb->s_timer[SPPT_KEEP] = SPPTV_KEEP;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
cb->s_state = TCPS_ESTABLISHED;
|
||||
sppstat.spps_accepts++;
|
||||
}
|
||||
@ -234,7 +239,9 @@ spp_input(m, nsp)
|
||||
cb->s_dport = nsp->nsp_fport = si->si_sport;
|
||||
cb->s_timer[SPPT_REXMT] = 0;
|
||||
cb->s_flags |= SF_ACKNOW;
|
||||
SOCK_LOCK(so);
|
||||
soisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
cb->s_state = TCPS_ESTABLISHED;
|
||||
/* Use roundtrip time of connection request for initial rtt */
|
||||
if (cb->s_rtt) {
|
||||
@ -246,8 +253,12 @@ spp_input(m, nsp)
|
||||
cb->s_rtt = 0;
|
||||
}
|
||||
}
|
||||
if (so->so_options & SO_DEBUG || traceallspps)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG || traceallspps) {
|
||||
SOCK_UNLOCK(so);
|
||||
spp_trace(SA_INPUT, (u_char)ostate, cb, &spp_savesi, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
m->m_len -= sizeof (struct idp);
|
||||
m->m_pkthdr.len -= sizeof (struct idp);
|
||||
@ -268,15 +279,23 @@ dropwithreset:
|
||||
si->si_ack = ntohs(si->si_ack);
|
||||
si->si_alo = ntohs(si->si_alo);
|
||||
ns_error(dtom(si), NS_ERR_NOSOCK, 0);
|
||||
if (cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps)
|
||||
SOCK_LOCK(cb->s_nspcb->nsp_socket);
|
||||
if (cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps) {
|
||||
SOCK_UNLOCK(cb->s_nspcb->nsp_socket);
|
||||
spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(cb->s_nspcb->nsp_socket);
|
||||
return;
|
||||
|
||||
drop:
|
||||
bad:
|
||||
SOCK_LOCK(cb->s_nspcb->nsp_socket);
|
||||
if (cb == 0 || cb->s_nspcb->nsp_socket->so_options & SO_DEBUG ||
|
||||
traceallspps)
|
||||
traceallspps) {
|
||||
SOCK_UNLOCK(cb->s_nspcb->nsp_socket);
|
||||
spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(cb->s_nspcb->nsp_socket);
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
@ -410,7 +429,9 @@ register struct spidp *si;
|
||||
else
|
||||
break;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
sowwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
cb->s_rack = si->si_ack;
|
||||
update_window:
|
||||
if (SSEQ_LT(cb->s_snxt, cb->s_rack))
|
||||
@ -449,11 +470,14 @@ update_window:
|
||||
} /* else queue this packet; */
|
||||
} else {
|
||||
/*register struct socket *so = cb->s_nspcb->nsp_socket;
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state && SS_NOFDREF) {
|
||||
SOCK_UNLOCK(so);
|
||||
ns_error(dtom(si), NS_ERR_NOSOCK, 0);
|
||||
(void)spp_close(cb);
|
||||
} else
|
||||
would crash system*/
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
would crash system }*/
|
||||
spp_istat.notyet++;
|
||||
ns_error(dtom(si), NS_ERR_FULLUP, 0);
|
||||
return (0);
|
||||
@ -514,8 +538,11 @@ present:
|
||||
cb->s_oobflags &= ~SF_IOOB;
|
||||
if (so->so_rcv.sb_cc)
|
||||
so->so_oobmark = so->so_rcv.sb_cc;
|
||||
else
|
||||
else {
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
}
|
||||
q = q->si_prev;
|
||||
remque(q->si_next);
|
||||
@ -545,7 +572,9 @@ present:
|
||||
MCHTYPE(m, MT_OOBDATA);
|
||||
spp_newchecks[1]++;
|
||||
so->so_oobmark = 0;
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
if (packetp == 0) {
|
||||
m->m_data += SPINC;
|
||||
@ -571,7 +600,11 @@ present:
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (wakeup) sorwakeup(so);
|
||||
if (wakeup) {
|
||||
SOCK_LOCK(so);
|
||||
sorwakeup(so);
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1015,8 +1048,12 @@ send:
|
||||
si->si_cc |= SP_SP;
|
||||
} else {
|
||||
cb->s_outx = 3;
|
||||
if (so->so_options & SO_DEBUG || traceallspps)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG || traceallspps) {
|
||||
SOCK_UNLOCK(so);
|
||||
spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
@ -1082,13 +1119,20 @@ send:
|
||||
si->si_sum = 0xffff;
|
||||
|
||||
cb->s_outx = 4;
|
||||
if (so->so_options & SO_DEBUG || traceallspps)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_options & SO_DEBUG || traceallspps) {
|
||||
SOCK_UNLOCK(so);
|
||||
spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
|
||||
SOCK_LOCK(so);
|
||||
}
|
||||
|
||||
if (so->so_options & SO_DONTROUTE)
|
||||
if (so->so_options & SO_DONTROUTE) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ns_output(m, (struct route *)0, NS_ROUTETOIF);
|
||||
else
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ns_output(m, &cb->s_nspcb->nsp_route, 0);
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
return (error);
|
||||
@ -1369,7 +1413,9 @@ spp_usrreq(so, req, m, nam, controlp)
|
||||
error = ns_pcbconnect(nsp, nam);
|
||||
if (error)
|
||||
break;
|
||||
SOCK_LOCK(so);
|
||||
soisconnecting(so);
|
||||
SOCK_UNLOCK(so);
|
||||
sppstat.spps_connattempt++;
|
||||
cb->s_state = TCPS_SYN_SENT;
|
||||
cb->s_did = 0;
|
||||
@ -1443,12 +1489,15 @@ spp_usrreq(so, req, m, nam, controlp)
|
||||
break;
|
||||
|
||||
case PRU_RCVOOB:
|
||||
SOCK_LOCK(so);
|
||||
if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark ||
|
||||
(so->so_state & SS_RCVATMARK)) {
|
||||
SOCK_UNLOCK(so);
|
||||
m->m_len = 1;
|
||||
*mtod(m, caddr_t) = cb->s_iobc;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
||||
@ -1496,8 +1545,12 @@ spp_usrreq(so, req, m, nam, controlp)
|
||||
default:
|
||||
panic("sp_usrreq");
|
||||
}
|
||||
if (cb && (so->so_options & SO_DEBUG || traceallspps))
|
||||
SOCK_LOCK(so);
|
||||
if (cb && (so->so_options & SO_DEBUG || traceallspps)) {
|
||||
SOCK_UNLOCK(so);
|
||||
spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
release:
|
||||
if (controlp != NULL)
|
||||
m_freem(controlp);
|
||||
@ -1574,7 +1627,9 @@ spp_close(cb)
|
||||
(void) m_free(dtom(cb->s_idp));
|
||||
(void) m_free(dtom(cb));
|
||||
nsp->nsp_pcb = 0;
|
||||
SOCK_LOCK(so);
|
||||
soisdisconnected(so);
|
||||
SOCK_UNLOCK(so);
|
||||
ns_pcbdetach(nsp);
|
||||
sppstat.spps_closed++;
|
||||
return ((struct sppcb *)0);
|
||||
@ -1783,13 +1838,17 @@ spp_timers(cb, timer)
|
||||
sppstat.spps_keeptimeo++;
|
||||
if (cb->s_state < TCPS_ESTABLISHED)
|
||||
goto dropit;
|
||||
SOCK_LOCK(cb->s_nspcb->nsp_socket);
|
||||
if (cb->s_nspcb->nsp_socket->so_options & SO_KEEPALIVE) {
|
||||
SOCK_UNLOCK(cb->s_nspcb->nsp_socket);
|
||||
if (cb->s_idle >= SPPTV_MAXIDLE)
|
||||
goto dropit;
|
||||
sppstat.spps_keepprobe++;
|
||||
(void) spp_output(cb, (struct mbuf *) 0);
|
||||
} else
|
||||
} else {
|
||||
SOCK_UNLOCK(cb->s_nspcb->nsp_socket);
|
||||
cb->s_idle = 0;
|
||||
}
|
||||
cb->s_timer[SPPT_KEEP] = SPPTV_KEEP;
|
||||
break;
|
||||
dropit:
|
||||
|
@ -250,15 +250,18 @@ nb_connect_in(struct nbpcb *nbp, struct sockaddr_in *to, struct thread *td)
|
||||
if (error)
|
||||
goto bad;
|
||||
s = splnet();
|
||||
SOCK_LOCK(so);
|
||||
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
|
||||
tsleep(&so->so_timeo, PSOCK, "nbcon", 2 * hz);
|
||||
msleep(&so->so_timeo, SOCK_MTX(so), PSOCK, "nbcon", 2 * hz);
|
||||
if ((so->so_state & SS_ISCONNECTING) && so->so_error == 0 &&
|
||||
(error = nb_intr(nbp, td->td_proc)) != 0) {
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (so->so_error) {
|
||||
error = so->so_error;
|
||||
so->so_error = 0;
|
||||
@ -408,12 +411,15 @@ nbssn_recv(struct nbpcb *nbp, struct mbuf **mpp, int *lenp,
|
||||
for(;;) {
|
||||
m = NULL;
|
||||
error = nbssn_recvhdr(nbp, &len, &rpcode, MSG_DONTWAIT, td);
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state &
|
||||
(SS_ISDISCONNECTING | SS_ISDISCONNECTED | SS_CANTRCVMORE)) {
|
||||
SOCK_UNLOCK(so);
|
||||
nbp->nbp_state = NBST_CLOSED;
|
||||
NBDEBUG("session closed by peer\n");
|
||||
return ECONNRESET;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (error)
|
||||
return error;
|
||||
if (len == 0 && nbp->nbp_state != NBST_SESSION)
|
||||
@ -639,8 +645,10 @@ smb_nbst_intr(struct smb_vc *vcp)
|
||||
|
||||
if (nbp == NULL || nbp->nbp_tso == NULL)
|
||||
return;
|
||||
SOCK_LOCK(nbp->nbp_tso);
|
||||
sorwakeup(nbp->nbp_tso);
|
||||
sowwakeup(nbp->nbp_tso);
|
||||
SOCK_UNLOCK(nbp->nbp_tso);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -751,8 +751,13 @@ bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
|
||||
error = sosend(so, (struct sockaddr *) &dst,
|
||||
&auio, NULL, NULL, 0, td);
|
||||
if (error != 0) {
|
||||
int sostate;
|
||||
|
||||
SOCK_LOCK(so);
|
||||
sostate = (int)so->so_state;
|
||||
SOCK_UNLOCK(so);
|
||||
printf("bootpc_call: sosend: %d state %08x\n",
|
||||
error, (int) so->so_state);
|
||||
error, sostate);
|
||||
}
|
||||
|
||||
/* XXX: Is this needed ? */
|
||||
|
@ -230,6 +230,7 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
|
||||
* that interruptible mounts don't hang here for a long time.
|
||||
*/
|
||||
s = splnet();
|
||||
SOCK_LOCK(so);
|
||||
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
|
||||
(void) tsleep((caddr_t)&so->so_timeo, PSOCK,
|
||||
"nfscon", 2 * hz);
|
||||
@ -238,10 +239,12 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
|
||||
(error = nfs_sigintr(nmp, rep,
|
||||
(rep->r_td ? rep->r_td->td_proc : NULL))) != 0){
|
||||
so->so_state &= ~SS_ISCONNECTING;
|
||||
SOCK_UNLOCK(so);
|
||||
splx(s);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
if (so->so_error) {
|
||||
error = so->so_error;
|
||||
so->so_error = 0;
|
||||
@ -414,10 +417,14 @@ nfs_send(struct socket *so, struct sockaddr *nam, struct mbuf *top,
|
||||
rep->r_flags &= ~R_MUSTRESEND;
|
||||
soflags = rep->r_nmp->nm_soflags;
|
||||
|
||||
if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
|
||||
SOCK_LOCK(so);
|
||||
if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED)) {
|
||||
SOCK_UNLOCK(so);
|
||||
sendnam = (struct sockaddr *)0;
|
||||
else
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
sendnam = nam;
|
||||
}
|
||||
if (so->so_type == SOCK_SEQPACKET)
|
||||
flags = MSG_EOR;
|
||||
else
|
||||
@ -646,10 +653,14 @@ errout:
|
||||
} else {
|
||||
if ((so = rep->r_nmp->nm_so) == NULL)
|
||||
return (EACCES);
|
||||
if (so->so_state & SS_ISCONNECTED)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
SOCK_UNLOCK(so);
|
||||
getnam = (struct sockaddr **)0;
|
||||
else
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
getnam = aname;
|
||||
}
|
||||
auio.uio_resid = len = 1000000;
|
||||
auio.uio_td = td;
|
||||
do {
|
||||
|
@ -714,10 +714,14 @@ nfsrv_send(struct socket *so, struct sockaddr *nam, struct mbuf *top)
|
||||
int error, soflags, flags;
|
||||
|
||||
soflags = so->so_proto->pr_flags;
|
||||
if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
|
||||
SOCK_LOCK(so);
|
||||
if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED)) {
|
||||
SOCK_UNLOCK(so);
|
||||
sendnam = (struct sockaddr *)0;
|
||||
else
|
||||
} else {
|
||||
SOCK_UNLOCK(so);
|
||||
sendnam = nam;
|
||||
}
|
||||
if (so->so_type == SOCK_SEQPACKET)
|
||||
flags = MSG_EOR;
|
||||
else
|
||||
|
@ -413,10 +413,15 @@ set_object_lattr(lomac_object_t *obj, lattr_t lattr) {
|
||||
case LO_TYPE_SOCKETPAIR:
|
||||
socket = obj->lo_object.socket;
|
||||
/* KASSERT that socket peer levels are synchronized */
|
||||
if (lattr.level == LOMAC_HIGHEST_LEVEL)
|
||||
if (lattr.level == LOMAC_HIGHEST_LEVEL) {
|
||||
SOCK_LOCK(socket);
|
||||
socket->so_state &= ~SOCKET_LEVEL_LOWEST;
|
||||
else
|
||||
SOCK_UNLOCK(socket);
|
||||
} else {
|
||||
SOCK_LOCK(socket);
|
||||
socket->so_state |= SOCKET_LEVEL_LOWEST;
|
||||
SOCK_UNLOCK(socket);
|
||||
}
|
||||
#ifdef NOT_YET
|
||||
pipe = pipe->pipe_peer;
|
||||
if (pipe != NULL) {
|
||||
@ -474,8 +479,10 @@ get_object_lattr(const lomac_object_t *obj, lattr_t *lattr) {
|
||||
break;
|
||||
case LO_TYPE_SOCKETPAIR:
|
||||
socket = obj->lo_object.socket;
|
||||
SOCK_LOCK(socket);
|
||||
lattr->level = (socket->so_state & SOCKET_LEVEL_LOWEST) ?
|
||||
LOMAC_LOWEST_LEVEL : LOMAC_HIGHEST_LEVEL;
|
||||
SOCK_UNLOCK(socket);
|
||||
lattr->flags = 0;
|
||||
break;
|
||||
default:
|
||||
|
@ -245,8 +245,14 @@ lomac_local_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
|
||||
goto bad;
|
||||
}
|
||||
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
|
||||
if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
|
||||
(so3 = sonewconn(so2, 0)) == 0) {
|
||||
SOCK_LOCK(so2);
|
||||
if ((so2->so_options & SO_ACCEPTCONN) == 0) {
|
||||
SOCK_UNLOCK(so2);
|
||||
error = ECONNREFUSED;
|
||||
goto bad;
|
||||
}
|
||||
SOCK_UNLOCK(so2);
|
||||
if ((so3 = sonewconn(so2, 0)) == 0) {
|
||||
error = ECONNREFUSED;
|
||||
goto bad;
|
||||
}
|
||||
@ -345,15 +351,20 @@ lomac_local_send( struct socket *so, int flags, struct mbuf *m,
|
||||
error = ENOTCONN;
|
||||
goto out;
|
||||
}
|
||||
} else if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
if (addr != NULL) {
|
||||
error = lomac_local_connect(so, addr, td);
|
||||
if (error)
|
||||
goto out; /* XXX */
|
||||
} else {
|
||||
error = ENOTCONN;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
SOCK_LOCK(so);
|
||||
if ((so->so_state & SS_ISCONNECTED) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
if (addr != NULL) {
|
||||
error = lomac_local_connect(so, addr, td);
|
||||
if (error)
|
||||
goto out; /* XXX */
|
||||
} else {
|
||||
error = ENOTCONN;
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
}
|
||||
vp = unp->unp_vnode;
|
||||
if (vp != NULL) {
|
||||
@ -560,8 +571,12 @@ bad:
|
||||
}
|
||||
if (mp)
|
||||
*mp = (struct mbuf *)0;
|
||||
if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) {
|
||||
SOCK_UNLOCK(so);
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, 0);
|
||||
} else
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
restart:
|
||||
error = sblock(&so->so_rcv, SBLOCKWAIT(flags));
|
||||
@ -597,7 +612,9 @@ restart:
|
||||
so->so_error = 0;
|
||||
goto release;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
if (m)
|
||||
goto dontblock;
|
||||
else
|
||||
@ -606,19 +623,25 @@ restart:
|
||||
for (; m; m = m->m_next)
|
||||
if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
|
||||
m = so->so_rcv.sb_mb;
|
||||
SOCK_UNLOCK(so);
|
||||
goto dontblock;
|
||||
}
|
||||
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
|
||||
(so->so_proto->pr_flags & PR_CONNREQUIRED)) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = ENOTCONN;
|
||||
goto release;
|
||||
}
|
||||
if (uio->uio_resid == 0)
|
||||
if (uio->uio_resid == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
goto release;
|
||||
}
|
||||
if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
|
||||
SOCK_UNLOCK(so);
|
||||
error = EWOULDBLOCK;
|
||||
goto release;
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
sbunlock(&so->so_rcv);
|
||||
error = sbwait(&so->so_rcv);
|
||||
splx(s);
|
||||
@ -687,7 +710,9 @@ dontblock:
|
||||
else
|
||||
KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER,
|
||||
("receive 3"));
|
||||
SOCK_LOCK(so);
|
||||
so->so_state &= ~SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
len = uio->uio_resid;
|
||||
if (so->so_oobmark && len > so->so_oobmark - offset)
|
||||
len = so->so_oobmark - offset;
|
||||
@ -746,7 +771,9 @@ dontblock:
|
||||
if ((flags & MSG_PEEK) == 0) {
|
||||
so->so_oobmark -= len;
|
||||
if (so->so_oobmark == 0) {
|
||||
SOCK_LOCK(so);
|
||||
so->so_state |= SS_RCVATMARK;
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -766,8 +793,12 @@ dontblock:
|
||||
*/
|
||||
while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
|
||||
!sosendallatonce(so) && !nextrecord) {
|
||||
if (so->so_error || so->so_state & SS_CANTRCVMORE)
|
||||
SOCK_LOCK(so);
|
||||
if (so->so_error || so->so_state & SS_CANTRCVMORE) {
|
||||
SOCK_UNLOCK(so);
|
||||
break;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
/*
|
||||
* Notify the protocol that some data has been
|
||||
* drained before blocking.
|
||||
@ -797,12 +828,15 @@ dontblock:
|
||||
if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
|
||||
(*pr->pr_usrreqs->pru_rcvd)(so, flags);
|
||||
}
|
||||
SOCK_LOCK(so);
|
||||
if (orig_resid == uio->uio_resid && orig_resid &&
|
||||
(flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
|
||||
SOCK_UNLOCK(so);
|
||||
sbunlock(&so->so_rcv);
|
||||
splx(s);
|
||||
goto restart;
|
||||
}
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
if (flagsp)
|
||||
*flagsp |= flags;
|
||||
|
@ -38,6 +38,8 @@
|
||||
#define _SYS_SOCKETVAR_H_
|
||||
|
||||
#include <sys/queue.h> /* for TAILQ macros */
|
||||
#include <sys/_lock.h>
|
||||
#include <sys/_mutex.h>
|
||||
#include <sys/selinfo.h> /* for struct selinfo */
|
||||
|
||||
/*
|
||||
@ -48,27 +50,27 @@
|
||||
*/
|
||||
typedef u_quad_t so_gen_t;
|
||||
|
||||
struct socket;
|
||||
typedef void so_upcall_t(struct socket *, void *, int);
|
||||
|
||||
/*
|
||||
* List of locks:
|
||||
* (c) const, inited in either socreate() or sonewconn()
|
||||
* (m) sb_mtx mutex
|
||||
* (mh) the mutex of so_head
|
||||
* (mr) so_rcv.sb_mtx mutex
|
||||
* (sg) sigio_lock sx
|
||||
* (sh) sohead_lock sx
|
||||
* (sg) sigio_lock mutex
|
||||
*
|
||||
* Lock of so_rcv.sb_mtx can duplicate, provided that sohead_lock
|
||||
* is exclusively locked.
|
||||
*
|
||||
* Brackets mean that this data is not protected yet.
|
||||
* Members marked by brackets are not locked yet.
|
||||
*/
|
||||
struct socket {
|
||||
int so_count; /* reference count */
|
||||
short so_type; /* generic type, see socket.h */
|
||||
short so_options; /* from socket call, see socket.h */
|
||||
short so_linger; /* time to linger while closing */
|
||||
short so_state; /* internal state flags SS_*, below */
|
||||
caddr_t so_pcb; /* protocol control block */
|
||||
struct protosw *so_proto; /* protocol handle */
|
||||
int so_count; /* (mr) reference count */
|
||||
short so_type; /* (c) generic type, see socket.h */
|
||||
short so_options; /* (mr) from socket call, see socket.h */
|
||||
short so_linger; /* (mr) time to linger while closing */
|
||||
short so_state; /* (mr) internal state flags SS_*, below */
|
||||
caddr_t so_pcb; /* [mr] protocol control block */
|
||||
struct protosw *so_proto; /* (c) protocol handle */
|
||||
/*
|
||||
* Variables for connection queuing.
|
||||
* Socket where accepts occur is so_head in all subsidiary sockets.
|
||||
@ -80,33 +82,36 @@ struct socket {
|
||||
* We allow connections to queue up based on current queue lengths
|
||||
* and limit on number of queued connections for this socket.
|
||||
*/
|
||||
struct socket *so_head; /* back pointer to accept socket */
|
||||
TAILQ_HEAD(, socket) so_incomp; /* queue of partial unaccepted connections */
|
||||
TAILQ_HEAD(, socket) so_comp; /* queue of complete unaccepted connections */
|
||||
TAILQ_ENTRY(socket) so_list; /* list of unaccepted connections */
|
||||
short so_qlen; /* number of unaccepted connections */
|
||||
short so_incqlen; /* number of unaccepted incomplete
|
||||
struct socket *so_head; /* [mr] back pointer to accept socket */
|
||||
TAILQ_HEAD(, socket) so_incomp; /* [mr] queue of partial unaccepted connections */
|
||||
TAILQ_HEAD(, socket) so_comp; /* [mr] queue of complete unaccepted connections */
|
||||
TAILQ_ENTRY(socket) so_list; /* [mh] list of unaccepted connections */
|
||||
short so_qlen; /* [mr] number of unaccepted connections */
|
||||
short so_incqlen; /* [mr] number of unaccepted incomplete
|
||||
connections */
|
||||
short so_qlimit; /* max number queued connections */
|
||||
short so_timeo; /* connection timeout */
|
||||
u_short so_error; /* error affecting connection */
|
||||
struct sigio *so_sigio; /* [sg] information for async I/O or
|
||||
short so_qlimit; /* [mr] max number queued connections */
|
||||
short so_timeo; /* [mr] connection timeout */
|
||||
u_short so_error; /* [mr] error affecting connection */
|
||||
struct sigio *so_sigio; /* (sg) information for async I/O or
|
||||
out of band data (SIGURG) */
|
||||
u_long so_oobmark; /* chars to oob mark */
|
||||
TAILQ_HEAD(, aiocblist) so_aiojobq; /* AIO ops waiting on socket */
|
||||
u_long so_oobmark; /* [mr] chars to oob mark */
|
||||
TAILQ_HEAD(, aiocblist) so_aiojobq; /* [mr] AIO ops waiting on socket */
|
||||
/*
|
||||
* Variables for socket buffering.
|
||||
*/
|
||||
struct sockbuf {
|
||||
u_long sb_cc; /* actual chars in buffer */
|
||||
u_long sb_hiwat; /* max actual char count */
|
||||
u_long sb_mbcnt; /* chars of mbufs used */
|
||||
u_long sb_mbmax; /* max chars of mbufs to use */
|
||||
long sb_lowat; /* low water mark */
|
||||
struct mbuf *sb_mb; /* the mbuf chain */
|
||||
struct selinfo sb_sel; /* process selecting read/write */
|
||||
short sb_flags; /* flags, see below */
|
||||
short sb_timeo; /* timeout for read/write */
|
||||
#define sb_startzero sb_cc
|
||||
u_long sb_cc; /* [m] actual chars in buffer */
|
||||
u_long sb_hiwat; /* [m] max actual char count */
|
||||
u_long sb_mbcnt; /* [m] chars of mbufs used */
|
||||
u_long sb_mbmax; /* [m] max chars of mbufs to use */
|
||||
long sb_lowat; /* [m] low water mark */
|
||||
struct mbuf *sb_mb; /* [m] the mbuf chain */
|
||||
struct selinfo sb_sel; /* [m] process selecting read/write */
|
||||
short sb_flags; /* [m] flags, see below */
|
||||
short sb_timeo; /* [m] timeout for read/write */
|
||||
#define sb_endzero sb_timeo
|
||||
struct mtx sb_mtx; /* mutex of this socket buffer */
|
||||
} so_rcv, so_snd;
|
||||
#define SB_MAX (256*1024) /* default for max chars in sockbuf */
|
||||
#define SB_LOCK 0x01 /* lock on data queue */
|
||||
@ -119,19 +124,35 @@ struct socket {
|
||||
#define SB_AIO 0x80 /* AIO operations queued */
|
||||
#define SB_KNOTE 0x100 /* kernel note attached */
|
||||
|
||||
void (*so_upcall)(struct socket *, void *, int);
|
||||
void *so_upcallarg;
|
||||
struct ucred *so_cred; /* user credentials */
|
||||
so_upcall_t *so_upcall; /* [mr] */
|
||||
void *so_upcallarg; /* [mr] */
|
||||
struct ucred *so_cred; /* (c) user credentials */
|
||||
/* NB: generation count must not be first; easiest to make it last. */
|
||||
so_gen_t so_gencnt; /* generation count */
|
||||
void *so_emuldata; /* private data for emulators */
|
||||
struct so_accf {
|
||||
struct accept_filter *so_accept_filter;
|
||||
void *so_accept_filter_arg; /* saved filter args */
|
||||
char *so_accept_filter_str; /* saved user args */
|
||||
} *so_accf;
|
||||
so_gen_t so_gencnt; /* [mr] generation count */
|
||||
void *so_emuldata; /* [mr] private data for emulators */
|
||||
struct so_accf {
|
||||
struct accept_filter *so_accept_filter; /* [mr] */
|
||||
void *so_accept_filter_arg; /* [mr] saved filter args */
|
||||
char *so_accept_filter_str; /* [mr] saved user args */
|
||||
} *so_accf; /* [mr] */
|
||||
};
|
||||
|
||||
/*
|
||||
* Macros to lock a socket.
|
||||
*/
|
||||
#define SOCKBUF_LOCK(sb) mtx_lock(&(sb)->sb_mtx)
|
||||
#define SOCKBUF_TRYLOCK(sb) mtx_trylock(&(sb)->sb_mtx)
|
||||
#define SOCKBUF_UNLOCK(sb) mtx_unlock(&(sb)->sb_mtx)
|
||||
#define SOCKBUF_LOCKED(sb) mtx_owned(&(sb)->sb_mtx)
|
||||
#define SOCKBUF_ASSERT(sb, type) mtx_assert(&(sb)->sb_mtx, type)
|
||||
|
||||
#define SOCK_MTX(so) (&(so)->so_rcv.sb_mtx)
|
||||
#define SOCK_LOCK(so) SOCKBUF_LOCK(&(so)->so_rcv)
|
||||
#define SOCK_TRYLOCK(so) SOCKBUF_TRYLOCK(&(so)->so_rcv)
|
||||
#define SOCK_UNLOCK(so) SOCKBUF_UNLOCK(&(so)->so_rcv)
|
||||
#define SOCK_LOCKED(so) SOCKBUF_LOCKED(&(so)->so_rcv)
|
||||
#define SOCK_ASSERT(so, type) SOCKBUF_ASSERT(&(so)->so_rcv, type)
|
||||
|
||||
/*
|
||||
* Socket state bits.
|
||||
*/
|
||||
@ -260,39 +281,41 @@ struct xsocket {
|
||||
* still explicitly close the socket, but the last ref count will free
|
||||
* the structure.
|
||||
*/
|
||||
#define soref(so) do { \
|
||||
++(so)->so_count; \
|
||||
|
||||
#define soref(so) do { \
|
||||
SOCK_ASSERT(so, MA_OWNED); \
|
||||
++(so)->so_count; \
|
||||
} while (0)
|
||||
|
||||
#define sorele(so) do { \
|
||||
#define sorele(so) do { \
|
||||
SOCK_ASSERT(so, MA_OWNED); \
|
||||
if ((so)->so_count <= 0) \
|
||||
panic("sorele");\
|
||||
if (--(so)->so_count == 0)\
|
||||
sofree(so); \
|
||||
panic("sorele"); \
|
||||
if (--(so)->so_count == 0) \
|
||||
sofree(so); \
|
||||
else \
|
||||
SOCK_UNLOCK(so); \
|
||||
} while (0)
|
||||
|
||||
#define sotryfree(so) do { \
|
||||
#define sotryfree(so) do { \
|
||||
SOCK_ASSERT(so, MA_OWNED); \
|
||||
if ((so)->so_count == 0) \
|
||||
sofree(so); \
|
||||
sofree(so); \
|
||||
else \
|
||||
SOCK_UNLOCK(so); \
|
||||
} while(0)
|
||||
|
||||
#define sorwakeup_locked(so) do { \
|
||||
if (sb_notify(&(so)->so_rcv)) \
|
||||
sowakeup((so), &(so)->so_rcv); \
|
||||
} while (0)
|
||||
#define sorwakeup(so) do { \
|
||||
SOCK_ASSERT(so, MA_OWNED); \
|
||||
if (sb_notify(&(so)->so_rcv)) \
|
||||
sowakeup((so), &(so)->so_rcv); \
|
||||
} while (0)
|
||||
|
||||
#define sorwakeup(so) do { \
|
||||
sorwakeup_locked(so); \
|
||||
} while (0)
|
||||
|
||||
#define sowwakeup_locked(so) do { \
|
||||
if (sb_notify(&(so)->so_snd)) \
|
||||
sowakeup((so), &(so)->so_snd); \
|
||||
} while (0)
|
||||
|
||||
#define sowwakeup(so) do { \
|
||||
sowwakeup_locked(so); \
|
||||
} while (0)
|
||||
#define sowwakeup(so) do { \
|
||||
SOCK_ASSERT(so, MA_OWNED); \
|
||||
if (sb_notify(&(so)->so_snd)) \
|
||||
sowakeup((so), &(so)->so_snd); \
|
||||
} while (0)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
@ -402,14 +425,12 @@ int soconnect2(struct socket *so1, struct socket *so2);
|
||||
int socreate(int dom, struct socket **aso, int type, int proto,
|
||||
struct ucred *cred, struct thread *td);
|
||||
int sodisconnect(struct socket *so);
|
||||
void soisconnected_locked(struct socket *so);
|
||||
void sofree(struct socket *so);
|
||||
int sogetopt(struct socket *so, struct sockopt *sopt);
|
||||
void sohasoutofband(struct socket *so);
|
||||
void soisconnected(struct socket *so);
|
||||
void soisconnecting(struct socket *so);
|
||||
void soisdisconnected(struct socket *so);
|
||||
void soisdisconnected_locked(struct socket *so);
|
||||
void soisdisconnecting(struct socket *so);
|
||||
int solisten(struct socket *so, int backlog, struct thread *td);
|
||||
struct socket *
|
||||
|
Loading…
x
Reference in New Issue
Block a user