Commit 5e8f3f70 authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller

sctp: simplify sctp listening code

sctp_inet_listen() call is split between UDP and TCP style.  Looking
at the code, the two functions are almost the same and can be
merged into a single helper.  This also fixes a bug that was
fixed in the UDP function, but missed in the TCP function.
Signed-off-by: default avatarVlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3bcb1255
...@@ -5843,37 +5843,28 @@ static int sctp_get_port(struct sock *sk, unsigned short snum) ...@@ -5843,37 +5843,28 @@ static int sctp_get_port(struct sock *sk, unsigned short snum)
} }
/* /*
* 3.1.3 listen() - UDP Style Syntax * Move a socket to LISTENING state.
*
* By default, new associations are not accepted for UDP style sockets.
* An application uses listen() to mark a socket as being able to
* accept new associations.
*/ */
SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog)
{ {
struct sctp_sock *sp = sctp_sk(sk); struct sctp_sock *sp = sctp_sk(sk);
struct sctp_endpoint *ep = sp->ep; struct sctp_endpoint *ep = sp->ep;
struct crypto_hash *tfm = NULL;
/* Only UDP style sockets that are not peeled off are allowed to /* Allocate HMAC for generating cookie. */
* listen(). if (!sctp_sk(sk)->hmac && sctp_hmac_alg) {
*/ tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
if (!sctp_style(sk, UDP)) if (IS_ERR(tfm)) {
return -EINVAL; if (net_ratelimit()) {
printk(KERN_INFO
/* If backlog is zero, disable listening. */ "SCTP: failed to load transform for %s: %ld\n",
if (!backlog) { sctp_hmac_alg, PTR_ERR(tfm));
if (sctp_sstate(sk, CLOSED)) }
return 0; return -ENOSYS;
}
sctp_unhash_endpoint(ep); sctp_sk(sk)->hmac = tfm;
sk->sk_state = SCTP_SS_CLOSED;
return 0;
} }
/* Return if we are already listening. */
if (sctp_sstate(sk, LISTENING))
return 0;
/* /*
* If a bind() or sctp_bindx() is not called prior to a listen() * If a bind() or sctp_bindx() is not called prior to a listen()
* call that allows new associations to be accepted, the system * call that allows new associations to be accepted, the system
...@@ -5884,7 +5875,6 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) ...@@ -5884,7 +5875,6 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
* extensions draft, but follows the practice as seen in TCP * extensions draft, but follows the practice as seen in TCP
* sockets. * sockets.
* *
* Additionally, turn off fastreuse flag since we are not listening
*/ */
sk->sk_state = SCTP_SS_LISTENING; sk->sk_state = SCTP_SS_LISTENING;
if (!ep->base.bind_addr.port) { if (!ep->base.bind_addr.port) {
...@@ -5895,113 +5885,71 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) ...@@ -5895,113 +5885,71 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
sk->sk_state = SCTP_SS_CLOSED; sk->sk_state = SCTP_SS_CLOSED;
return -EADDRINUSE; return -EADDRINUSE;
} }
sctp_sk(sk)->bind_hash->fastreuse = 0;
} }
sctp_hash_endpoint(ep);
return 0;
}
/*
* 4.1.3 listen() - TCP Style Syntax
*
* Applications uses listen() to ready the SCTP endpoint for accepting
* inbound associations.
*/
SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
{
struct sctp_sock *sp = sctp_sk(sk);
struct sctp_endpoint *ep = sp->ep;
/* If backlog is zero, disable listening. */
if (!backlog) {
if (sctp_sstate(sk, CLOSED))
return 0;
sctp_unhash_endpoint(ep);
sk->sk_state = SCTP_SS_CLOSED;
return 0;
}
if (sctp_sstate(sk, LISTENING))
return 0;
/*
* If a bind() or sctp_bindx() is not called prior to a listen()
* call that allows new associations to be accepted, the system
* picks an ephemeral port and will choose an address set equivalent
* to binding with a wildcard address.
*
* This is not currently spelled out in the SCTP sockets
* extensions draft, but follows the practice as seen in TCP
* sockets.
*/
sk->sk_state = SCTP_SS_LISTENING;
if (!ep->base.bind_addr.port) {
if (sctp_autobind(sk))
return -EAGAIN;
} else
sctp_sk(sk)->bind_hash->fastreuse = 0;
sk->sk_max_ack_backlog = backlog; sk->sk_max_ack_backlog = backlog;
sctp_hash_endpoint(ep); sctp_hash_endpoint(ep);
return 0; return 0;
} }
/* /*
* 4.1.3 / 5.1.3 listen()
*
* By default, new associations are not accepted for UDP style sockets.
* An application uses listen() to mark a socket as being able to
* accept new associations.
*
* On TCP style sockets, applications use listen() to ready the SCTP
* endpoint for accepting inbound associations.
*
* On both types of endpoints a backlog of '0' disables listening.
*
* Move a socket to LISTENING state. * Move a socket to LISTENING state.
*/ */
int sctp_inet_listen(struct socket *sock, int backlog) int sctp_inet_listen(struct socket *sock, int backlog)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct crypto_hash *tfm = NULL; struct sctp_endpoint *ep = sctp_sk(sk)->ep;
int err = -EINVAL; int err = -EINVAL;
if (unlikely(backlog < 0)) if (unlikely(backlog < 0))
goto out; return err;
sctp_lock_sock(sk); sctp_lock_sock(sk);
/* Peeled-off sockets are not allowed to listen(). */
if (sctp_style(sk, UDP_HIGH_BANDWIDTH))
goto out;
if (sock->state != SS_UNCONNECTED) if (sock->state != SS_UNCONNECTED)
goto out; goto out;
/* Allocate HMAC for generating cookie. */ /* If backlog is zero, disable listening. */
if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { if (!backlog) {
tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); if (sctp_sstate(sk, CLOSED))
if (IS_ERR(tfm)) {
if (net_ratelimit()) {
printk(KERN_INFO
"SCTP: failed to load transform for %s: %ld\n",
sctp_hmac_alg, PTR_ERR(tfm));
}
err = -ENOSYS;
goto out; goto out;
}
}
switch (sock->type) { err = 0;
case SOCK_SEQPACKET: sctp_unhash_endpoint(ep);
err = sctp_seqpacket_listen(sk, backlog); sk->sk_state = SCTP_SS_CLOSED;
break; if (sk->sk_reuse)
case SOCK_STREAM: sctp_sk(sk)->bind_hash->fastreuse = 1;
err = sctp_stream_listen(sk, backlog); goto out;
break;
default:
break;
} }
if (err) /* If we are already listening, just update the backlog */
goto cleanup; if (sctp_sstate(sk, LISTENING))
sk->sk_max_ack_backlog = backlog;
else {
err = sctp_listen_start(sk, backlog);
if (err)
goto out;
}
/* Store away the transform reference. */ err = 0;
if (!sctp_sk(sk)->hmac)
sctp_sk(sk)->hmac = tfm;
out: out:
sctp_release_sock(sk); sctp_release_sock(sk);
return err; return err;
cleanup:
crypto_free_hash(tfm);
goto out;
} }
/* /*
......
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