summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2011-09-14 19:10:13 +0000
committertuexen <tuexen@FreeBSD.org>2011-09-14 19:10:13 +0000
commit0e8ff918fb8c9f8e97cce19735ec7f77110d134c (patch)
treee37ede04ab1f8fd299aa01da6472fbfad8f5ec22 /sys/netinet
parent79dd2afc0bac76768a48b949de5750372af85472 (diff)
downloadFreeBSD-src-0e8ff918fb8c9f8e97cce19735ec7f77110d134c.zip
FreeBSD-src-0e8ff918fb8c9f8e97cce19735ec7f77110d134c.tar.gz
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
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/sctp_output.c29
-rw-r--r--sys/netinet/sctp_pcb.c10
-rw-r--r--sys/netinet/sctp_usrreq.c14
-rw-r--r--sys/netinet/sctputil.c38
4 files changed, 32 insertions, 59 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index c35dcac..88d0e24 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -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);
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index e397316..e5581e1 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -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) {
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index d52df50..cd69a45 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -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);
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index b13f426..54b635c 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -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 @@ restart_nosblocks:
*/
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 @@ restart_nosblocks:
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 @@ restart_nosblocks:
*/
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 @@ restart_nosblocks:
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;
OpenPOWER on IntegriCloud