sctp: simplify sctp listening code
authorVlad Yasevich <vladislav.yasevich@hp.com>
Thu, 12 Mar 2009 09:49:17 +0000 (09:49 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 13 Mar 2009 18:37:56 +0000 (11:37 -0700)
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: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sctp/socket.c

index bbd3cd238d7ffca87e34429862f5a2e31d3f952c..5fb3a8c9792e741dac08902a0f8b7cc1f43dc872 100644 (file)
@@ -5843,37 +5843,28 @@ static int sctp_get_port(struct sock *sk, unsigned short snum)
 }
 
 /*
- * 3.1.3 listen() - UDP Style Syntax
- *
- *   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.
+ *  Move a socket to LISTENING state.
  */
-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_endpoint *ep = sp->ep;
+       struct crypto_hash *tfm = NULL;
 
-       /* Only UDP style sockets that are not peeled off are allowed to
-        * listen().
-        */
-       if (!sctp_style(sk, UDP))
-               return -EINVAL;
-
-       /* 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;
+       /* Allocate HMAC for generating cookie. */
+       if (!sctp_sk(sk)->hmac && sctp_hmac_alg) {
+               tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
+               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));
+                       }
+                       return -ENOSYS;
+               }
+               sctp_sk(sk)->hmac = tfm;
        }
 
-       /* 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()
         * 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)
         * extensions draft, but follows the practice as seen in TCP
         * sockets.
         *
-        * Additionally, turn off fastreuse flag since we are not listening
         */
        sk->sk_state = SCTP_SS_LISTENING;
        if (!ep->base.bind_addr.port) {
@@ -5895,113 +5885,71 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
                        sk->sk_state = SCTP_SS_CLOSED;
                        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;
        sctp_hash_endpoint(ep);
        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.
  */
 int sctp_inet_listen(struct socket *sock, int backlog)
 {
        struct sock *sk = sock->sk;
-       struct crypto_hash *tfm = NULL;
+       struct sctp_endpoint *ep = sctp_sk(sk)->ep;
        int err = -EINVAL;
 
        if (unlikely(backlog < 0))
-               goto out;
+               return err;
 
        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)
                goto out;
 
-       /* Allocate HMAC for generating cookie. */
-       if (!sctp_sk(sk)->hmac && sctp_hmac_alg) {
-               tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
-               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;
+       /* If backlog is zero, disable listening. */
+       if (!backlog) {
+               if (sctp_sstate(sk, CLOSED))
                        goto out;
-               }
-       }
 
-       switch (sock->type) {
-       case SOCK_SEQPACKET:
-               err = sctp_seqpacket_listen(sk, backlog);
-               break;
-       case SOCK_STREAM:
-               err = sctp_stream_listen(sk, backlog);
-               break;
-       default:
-               break;
+               err = 0;
+               sctp_unhash_endpoint(ep);
+               sk->sk_state = SCTP_SS_CLOSED;
+               if (sk->sk_reuse)
+                       sctp_sk(sk)->bind_hash->fastreuse = 1;
+               goto out;
        }
 
-       if (err)
-               goto cleanup;
+       /* If we are already listening, just update the backlog */
+       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. */
-       if (!sctp_sk(sk)->hmac)
-               sctp_sk(sk)->hmac = tfm;
+       err = 0;
 out:
        sctp_release_sock(sk);
        return err;
-cleanup:
-       crypto_free_hash(tfm);
-       goto out;
 }
 
 /*