Commit 99ab9689 authored by Sridhar Samudrala's avatar Sridhar Samudrala

[SCTP] shutdown() support for TCP-style sockets.

parent 9c841195
...@@ -520,6 +520,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -520,6 +520,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newsk->family = PF_INET6; newsk->family = PF_INET6;
newsk->protocol = IPPROTO_SCTP; newsk->protocol = IPPROTO_SCTP;
newsk->backlog_rcv = sk->prot->backlog_rcv; newsk->backlog_rcv = sk->prot->backlog_rcv;
newsk->shutdown = sk->shutdown;
newsctp6sk = (struct sctp6_sock *)newsk; newsctp6sk = (struct sctp6_sock *)newsk;
newsctp6sk->pinet6 = &newsctp6sk->inet6; newsctp6sk->pinet6 = &newsctp6sk->inet6;
......
...@@ -515,6 +515,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, ...@@ -515,6 +515,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
newsk->prot = sk->prot; newsk->prot = sk->prot;
newsk->no_check = sk->no_check; newsk->no_check = sk->no_check;
newsk->reuse = sk->reuse; newsk->reuse = sk->reuse;
newsk->shutdown = sk->shutdown;
newsk->destruct = inet_sock_destruct; newsk->destruct = inet_sock_destruct;
newsk->zapped = 0; newsk->zapped = 0;
......
...@@ -617,8 +617,23 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, struct sctp_association *as ...@@ -617,8 +617,23 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, struct sctp_association *as
asoc->state = state; asoc->state = state;
asoc->state_timestamp = jiffies; asoc->state_timestamp = jiffies;
if (SCTP_SOCKET_TCP == sp->type) {
/* Change the sk->state of a TCP-style socket that has
* sucessfully completed a connect() call.
*/
if ((SCTP_STATE_ESTABLISHED == asoc->state) &&
(SCTP_SS_CLOSED == sk->state))
sk->state = SCTP_SS_ESTABLISHED;
/* Set the RCV_SHUTDOWN flag when a SHUTDOWN is received. */
if (SCTP_STATE_SHUTDOWN_RECEIVED == asoc->state)
sk->shutdown |= RCV_SHUTDOWN;
}
if ((SCTP_STATE_ESTABLISHED == asoc->state) || if ((SCTP_STATE_ESTABLISHED == asoc->state) ||
(SCTP_STATE_CLOSED == asoc->state)) { (SCTP_STATE_CLOSED == asoc->state) ||
(SCTP_STATE_SHUTDOWN_RECEIVED == asoc->state)) {
/* Wake up any processes waiting in the asoc's wait queue in /* Wake up any processes waiting in the asoc's wait queue in
* sctp_wait_for_connect() or sctp_wait_for_sndbuf(). * sctp_wait_for_connect() or sctp_wait_for_sndbuf().
*/ */
...@@ -634,13 +649,6 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, struct sctp_association *as ...@@ -634,13 +649,6 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, struct sctp_association *as
if (SCTP_SOCKET_UDP != sp->type) if (SCTP_SOCKET_UDP != sp->type)
sk->state_change(sk); sk->state_change(sk);
} }
/* Change the sk->state of a TCP-style socket that has sucessfully
* completed a connect() call.
*/
if ((SCTP_STATE_ESTABLISHED == asoc->state) &&
(SCTP_SOCKET_TCP == sp->type) && (SCTP_SS_CLOSED == sk->state))
sk->state = SCTP_SS_ESTABLISHED;
} }
/* These three macros allow us to pull the debugging code out of the /* These three macros allow us to pull the debugging code out of the
......
...@@ -1864,11 +1864,38 @@ SCTP_STATIC int sctp_destroy_sock(struct sock *sk) ...@@ -1864,11 +1864,38 @@ SCTP_STATIC int sctp_destroy_sock(struct sock *sk)
return 0; return 0;
} }
/* FIXME: Comments needed. */ /* API 4.1.7 shutdown() - TCP Style Syntax
* int shutdown(int socket, int how);
*
* sd - the socket descriptor of the association to be closed.
* how - Specifies the type of shutdown. The values are
* as follows:
* SHUT_RD
* Disables further receive operations. No SCTP
* protocol action is taken.
* SHUT_WR
* Disables further send operations, and initiates
* the SCTP shutdown sequence.
* SHUT_RDWR
* Disables further send and receive operations
* and initiates the SCTP shutdown sequence.
*/
SCTP_STATIC void sctp_shutdown(struct sock *sk, int how) SCTP_STATIC void sctp_shutdown(struct sock *sk, int how)
{ {
/* UDP-style sockets do not support shutdown. */ struct sctp_endpoint *ep;
/* STUB */ struct sctp_association *asoc;
if (SCTP_SOCKET_TCP != sctp_sk(sk)->type)
return;
if (how & SEND_SHUTDOWN) {
ep = sctp_sk(sk)->ep;
if (!list_empty(&ep->asocs)) {
asoc = list_entry(ep->asocs.next,
struct sctp_association, asocs);
sctp_primitive_SHUTDOWN(asoc, NULL);
}
}
} }
/* 7.2.1 Association Status (SCTP_STATUS) /* 7.2.1 Association Status (SCTP_STATUS)
...@@ -3145,6 +3172,9 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, ...@@ -3145,6 +3172,9 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
if (skb) if (skb)
return skb; return skb;
if (sk->shutdown & RCV_SHUTDOWN)
break;
/* User doesn't want to wait. */ /* User doesn't want to wait. */
error = -EAGAIN; error = -EAGAIN;
if (!timeo) if (!timeo)
...@@ -3379,6 +3409,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p) ...@@ -3379,6 +3409,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
__set_current_state(TASK_INTERRUPTIBLE); __set_current_state(TASK_INTERRUPTIBLE);
if (!*timeo_p) if (!*timeo_p)
goto do_nonblock; goto do_nonblock;
if (sk->shutdown & RCV_SHUTDOWN)
break;
if (sk->err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING || if (sk->err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING ||
asoc->base.dead) asoc->base.dead)
goto do_error; goto do_error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment