Ensure that 1-to-1 style SCTP sockets can only be connected once.

Allow implicit setup also for 1-to-1 style sockets as described
in the latest version of the socket API ID.

Approved by: re
MFC after: 1 month
This commit is contained in:
Michael Tuexen 2011-09-14 19:10:13 +00:00
parent 7cd72d8565
commit c55b70cef6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=225559
4 changed files with 32 additions and 59 deletions

View File

@ -12628,14 +12628,10 @@ sctp_lower_sosend(struct socket *so,
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
error = ENOTCONN;
goto out_unlocked;
if (stcb) {
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
}
SCTP_TCB_LOCK(stcb);
hold_tcblock = 1;
SCTP_INP_RUNLOCK(inp);
} else if (sinfo_assoc_id) {
stcb = sctp_findassociation_ep_asocid(inp, sinfo_assoc_id, 0);
@ -12700,21 +12696,12 @@ sctp_lower_sosend(struct socket *so,
}
}
if (stcb == NULL) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
error = ENOTCONN;
goto out_unlocked;
}
if (addr == NULL) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOENT);
error = ENOENT;
goto out_unlocked;
} else {
/*
* UDP style, we must go ahead and start the INIT
* process
*/
/* We must go ahead and start the INIT process */
uint32_t vrf_id;
if ((sinfo_flags & SCTP_ABORT) ||
@ -12741,6 +12728,14 @@ sctp_lower_sosend(struct socket *so,
/* Error is setup for us in the call */
goto out_unlocked;
}
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
/*
* Set the connected flag so we can queue
* data
*/
soisconnecting(so);
}
hold_tcblock = 1;
if (create_lock_applied) {
SCTP_ASOC_CREATE_UNLOCK(inp);

View File

@ -4291,6 +4291,16 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
*error = EINVAL;
return (NULL);
}
if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED)) {
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
}
}
SCTPDBG(SCTP_DEBUG_PCB3, "Allocate an association for peer:");
#ifdef SCTP_DEBUG
if (firstaddr) {

View File

@ -1541,6 +1541,11 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
/* Gak! no memory */
goto out_now;
}
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
/* Set the connected flag so we can queue data */
soisconnecting(so);
}
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
/* move to second address */
switch (sa->sa_family) {
@ -5772,15 +5777,6 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
/* Set the connected flag so we can queue data */
SOCKBUF_LOCK(&so->so_rcv);
so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
SOCKBUF_UNLOCK(&so->so_rcv);
SOCKBUF_LOCK(&so->so_snd);
so->so_snd.sb_state &= ~SBS_CANTSENDMORE;
SOCKBUF_UNLOCK(&so->so_snd);
SOCK_LOCK(so);
so->so_state &= ~SS_ISDISCONNECTING;
SOCK_UNLOCK(so);
soisconnecting(so);
}
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);

View File

@ -3622,10 +3622,14 @@ sctp_abort_notification(struct sctp_tcb *stcb, int error, int so_locked
#endif
)
{
if (stcb == NULL) {
return;
}
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
}
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
@ -3633,11 +3637,6 @@ sctp_abort_notification(struct sctp_tcb *stcb, int error, int so_locked
}
/* Tell them we lost the asoc */
sctp_report_all_outbound(stcb, 1, so_locked);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
}
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL, so_locked);
}
@ -5098,17 +5097,6 @@ sctp_sorecvmsg(struct socket *so,
*/
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
error = ECONNRESET;
/*
* You get this once if you are
* active open side
*/
if (!(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
/*
* Remove flag if on the
* active open side
*/
inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_ABORTED;
}
}
so->so_state &= ~(SS_ISCONNECTING |
SS_ISDISCONNECTING |
@ -5118,8 +5106,6 @@ sctp_sorecvmsg(struct socket *so,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
} else {
inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
}
}
goto out;
@ -5152,18 +5138,6 @@ sctp_sorecvmsg(struct socket *so,
*/
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
error = ECONNRESET;
/*
* You get this once if you
* are active open side
*/
if (!(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
/*
* Remove flag if on
* the active open
* side
*/
inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_ABORTED;
}
}
so->so_state &= ~(SS_ISCONNECTING |
SS_ISDISCONNECTING |
@ -5173,8 +5147,6 @@ sctp_sorecvmsg(struct socket *so,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
} else {
inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
}
}
goto out;