inet_sk(sk)->dport = htons(asoc->peer.port);
af = sctp_get_af_specific(to.sa.sa_family);
af->to_sk_daddr(&to, sk);
- sk->sk_err = 0;
timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
err = sctp_wait_for_connect(asoc, &timeo);
ep = sctp_sk(sk)->ep;
- /* Walk all associations on an endpoint. */
+ /* Walk all associations on a socket, not on an endpoint. */
list_for_each_safe(pos, temp, &ep->asocs) {
asoc = list_entry(pos, struct sctp_association, asocs);
if (sctp_state(asoc, CLOSED)) {
sctp_unhash_established(asoc);
sctp_association_free(asoc);
- continue;
- }
- }
- if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
- struct sctp_chunk *chunk;
+ } else if (sock_flag(sk, SOCK_LINGER) &&
+ !sk->sk_lingertime) {
+ struct sctp_chunk *chunk;
- chunk = sctp_make_abort_user(asoc, NULL, 0);
- if (chunk)
- sctp_primitive_ABORT(asoc, chunk);
+ chunk = sctp_make_abort_user(asoc, NULL, 0);
+ if (chunk)
+ sctp_primitive_ABORT(asoc, chunk);
+ } else
+ sctp_primitive_SHUTDOWN(asoc, NULL);
} else
sctp_primitive_SHUTDOWN(asoc, NULL);
}
/* Is there any exceptional events? */
if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
mask |= POLLERR;
- if (sk->sk_shutdown & RCV_SHUTDOWN)
- mask |= POLLRDHUP;
if (sk->sk_shutdown == SHUTDOWN_MASK)
mask |= POLLHUP;
*/
sctp_release_sock(sk);
current_timeo = schedule_timeout(current_timeo);
- BUG_ON(sk != asoc->base.sk);
sctp_lock_sock(sk);
*timeo_p = current_timeo;
*/
newsp->type = type;
- /* Mark the new socket "in-use" by the user so that any packets
- * that may arrive on the association after we've moved it are
- * queued to the backlog. This prevents a potential race between
- * backlog processing on the old socket and new-packet processing
- * on the new socket.
- */
- sctp_lock_sock(newsk);
+ spin_lock_bh(&oldsk->sk_lock.slock);
+ /* Migrate the backlog from oldsk to newsk. */
+ sctp_backlog_migrate(assoc, oldsk, newsk);
+ /* Migrate the association to the new socket. */
sctp_assoc_migrate(assoc, newsk);
+ spin_unlock_bh(&oldsk->sk_lock.slock);
/* If the association on the newsk is already closed before accept()
* is called, set RCV_SHUTDOWN flag.
newsk->sk_shutdown |= RCV_SHUTDOWN;
newsk->sk_state = SCTP_SS_ESTABLISHED;
- sctp_release_sock(newsk);
}
/* This proto struct describes the ULP interface for SCTP. */