diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2009-03-12 05:49:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-13 14:37:56 -0400 |
commit | 5e8f3f703ae4e4af65e2695e486b3cd198328863 (patch) | |
tree | 1927b01e884dbd5ddb1d4586ac08e4a14e0601eb /net/sctp/socket.c | |
parent | 3bcb1255bae39cae1b4d2660f2b5a6ab2f404c10 (diff) |
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: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 152 |
1 files changed, 50 insertions, 102 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index bbd3cd238d7f..5fb3a8c9792e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -5843,37 +5843,28 @@ static int sctp_get_port(struct sock *sk, unsigned short snum) | |||
5843 | } | 5843 | } |
5844 | 5844 | ||
5845 | /* | 5845 | /* |
5846 | * 3.1.3 listen() - UDP Style Syntax | 5846 | * Move a socket to LISTENING state. |
5847 | * | ||
5848 | * By default, new associations are not accepted for UDP style sockets. | ||
5849 | * An application uses listen() to mark a socket as being able to | ||
5850 | * accept new associations. | ||
5851 | */ | 5847 | */ |
5852 | SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | 5848 | SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog) |
5853 | { | 5849 | { |
5854 | struct sctp_sock *sp = sctp_sk(sk); | 5850 | struct sctp_sock *sp = sctp_sk(sk); |
5855 | struct sctp_endpoint *ep = sp->ep; | 5851 | struct sctp_endpoint *ep = sp->ep; |
5852 | struct crypto_hash *tfm = NULL; | ||
5856 | 5853 | ||
5857 | /* Only UDP style sockets that are not peeled off are allowed to | 5854 | /* Allocate HMAC for generating cookie. */ |
5858 | * listen(). | 5855 | if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { |
5859 | */ | 5856 | tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); |
5860 | if (!sctp_style(sk, UDP)) | 5857 | if (IS_ERR(tfm)) { |
5861 | return -EINVAL; | 5858 | if (net_ratelimit()) { |
5862 | 5859 | printk(KERN_INFO | |
5863 | /* If backlog is zero, disable listening. */ | 5860 | "SCTP: failed to load transform for %s: %ld\n", |
5864 | if (!backlog) { | 5861 | sctp_hmac_alg, PTR_ERR(tfm)); |
5865 | if (sctp_sstate(sk, CLOSED)) | 5862 | } |
5866 | return 0; | 5863 | return -ENOSYS; |
5867 | 5864 | } | |
5868 | sctp_unhash_endpoint(ep); | 5865 | sctp_sk(sk)->hmac = tfm; |
5869 | sk->sk_state = SCTP_SS_CLOSED; | ||
5870 | return 0; | ||
5871 | } | 5866 | } |
5872 | 5867 | ||
5873 | /* Return if we are already listening. */ | ||
5874 | if (sctp_sstate(sk, LISTENING)) | ||
5875 | return 0; | ||
5876 | |||
5877 | /* | 5868 | /* |
5878 | * If a bind() or sctp_bindx() is not called prior to a listen() | 5869 | * If a bind() or sctp_bindx() is not called prior to a listen() |
5879 | * call that allows new associations to be accepted, the system | 5870 | * 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 | * extensions draft, but follows the practice as seen in TCP | 5875 | * extensions draft, but follows the practice as seen in TCP |
5885 | * sockets. | 5876 | * sockets. |
5886 | * | 5877 | * |
5887 | * Additionally, turn off fastreuse flag since we are not listening | ||
5888 | */ | 5878 | */ |
5889 | sk->sk_state = SCTP_SS_LISTENING; | 5879 | sk->sk_state = SCTP_SS_LISTENING; |
5890 | if (!ep->base.bind_addr.port) { | 5880 | if (!ep->base.bind_addr.port) { |
@@ -5895,113 +5885,71 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | |||
5895 | sk->sk_state = SCTP_SS_CLOSED; | 5885 | sk->sk_state = SCTP_SS_CLOSED; |
5896 | return -EADDRINUSE; | 5886 | return -EADDRINUSE; |
5897 | } | 5887 | } |
5898 | sctp_sk(sk)->bind_hash->fastreuse = 0; | ||
5899 | } | 5888 | } |
5900 | 5889 | ||
5901 | sctp_hash_endpoint(ep); | ||
5902 | return 0; | ||
5903 | } | ||
5904 | |||
5905 | /* | ||
5906 | * 4.1.3 listen() - TCP Style Syntax | ||
5907 | * | ||
5908 | * Applications uses listen() to ready the SCTP endpoint for accepting | ||
5909 | * inbound associations. | ||
5910 | */ | ||
5911 | SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) | ||
5912 | { | ||
5913 | struct sctp_sock *sp = sctp_sk(sk); | ||
5914 | struct sctp_endpoint *ep = sp->ep; | ||
5915 | |||
5916 | /* If backlog is zero, disable listening. */ | ||
5917 | if (!backlog) { | ||
5918 | if (sctp_sstate(sk, CLOSED)) | ||
5919 | return 0; | ||
5920 | |||
5921 | sctp_unhash_endpoint(ep); | ||
5922 | sk->sk_state = SCTP_SS_CLOSED; | ||
5923 | return 0; | ||
5924 | } | ||
5925 | |||
5926 | if (sctp_sstate(sk, LISTENING)) | ||
5927 | return 0; | ||
5928 | |||
5929 | /* | ||
5930 | * If a bind() or sctp_bindx() is not called prior to a listen() | ||
5931 | * call that allows new associations to be accepted, the system | ||
5932 | * picks an ephemeral port and will choose an address set equivalent | ||
5933 | * to binding with a wildcard address. | ||
5934 | * | ||
5935 | * This is not currently spelled out in the SCTP sockets | ||
5936 | * extensions draft, but follows the practice as seen in TCP | ||
5937 | * sockets. | ||
5938 | */ | ||
5939 | sk->sk_state = SCTP_SS_LISTENING; | ||
5940 | if (!ep->base.bind_addr.port) { | ||
5941 | if (sctp_autobind(sk)) | ||
5942 | return -EAGAIN; | ||
5943 | } else | ||
5944 | sctp_sk(sk)->bind_hash->fastreuse = 0; | ||
5945 | |||
5946 | sk->sk_max_ack_backlog = backlog; | 5890 | sk->sk_max_ack_backlog = backlog; |
5947 | sctp_hash_endpoint(ep); | 5891 | sctp_hash_endpoint(ep); |
5948 | return 0; | 5892 | return 0; |
5949 | } | 5893 | } |
5950 | 5894 | ||
5951 | /* | 5895 | /* |
5896 | * 4.1.3 / 5.1.3 listen() | ||
5897 | * | ||
5898 | * By default, new associations are not accepted for UDP style sockets. | ||
5899 | * An application uses listen() to mark a socket as being able to | ||
5900 | * accept new associations. | ||
5901 | * | ||
5902 | * On TCP style sockets, applications use listen() to ready the SCTP | ||
5903 | * endpoint for accepting inbound associations. | ||
5904 | * | ||
5905 | * On both types of endpoints a backlog of '0' disables listening. | ||
5906 | * | ||
5952 | * Move a socket to LISTENING state. | 5907 | * Move a socket to LISTENING state. |
5953 | */ | 5908 | */ |
5954 | int sctp_inet_listen(struct socket *sock, int backlog) | 5909 | int sctp_inet_listen(struct socket *sock, int backlog) |
5955 | { | 5910 | { |
5956 | struct sock *sk = sock->sk; | 5911 | struct sock *sk = sock->sk; |
5957 | struct crypto_hash *tfm = NULL; | 5912 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
5958 | int err = -EINVAL; | 5913 | int err = -EINVAL; |
5959 | 5914 | ||
5960 | if (unlikely(backlog < 0)) | 5915 | if (unlikely(backlog < 0)) |
5961 | goto out; | 5916 | return err; |
5962 | 5917 | ||
5963 | sctp_lock_sock(sk); | 5918 | sctp_lock_sock(sk); |
5964 | 5919 | ||
5920 | /* Peeled-off sockets are not allowed to listen(). */ | ||
5921 | if (sctp_style(sk, UDP_HIGH_BANDWIDTH)) | ||
5922 | goto out; | ||
5923 | |||
5965 | if (sock->state != SS_UNCONNECTED) | 5924 | if (sock->state != SS_UNCONNECTED) |
5966 | goto out; | 5925 | goto out; |
5967 | 5926 | ||
5968 | /* Allocate HMAC for generating cookie. */ | 5927 | /* If backlog is zero, disable listening. */ |
5969 | if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { | 5928 | if (!backlog) { |
5970 | tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); | 5929 | if (sctp_sstate(sk, CLOSED)) |
5971 | if (IS_ERR(tfm)) { | ||
5972 | if (net_ratelimit()) { | ||
5973 | printk(KERN_INFO | ||
5974 | "SCTP: failed to load transform for %s: %ld\n", | ||
5975 | sctp_hmac_alg, PTR_ERR(tfm)); | ||
5976 | } | ||
5977 | err = -ENOSYS; | ||
5978 | goto out; | 5930 | goto out; |
5979 | } | ||
5980 | } | ||
5981 | 5931 | ||
5982 | switch (sock->type) { | 5932 | err = 0; |
5983 | case SOCK_SEQPACKET: | 5933 | sctp_unhash_endpoint(ep); |
5984 | err = sctp_seqpacket_listen(sk, backlog); | 5934 | sk->sk_state = SCTP_SS_CLOSED; |
5985 | break; | 5935 | if (sk->sk_reuse) |
5986 | case SOCK_STREAM: | 5936 | sctp_sk(sk)->bind_hash->fastreuse = 1; |
5987 | err = sctp_stream_listen(sk, backlog); | 5937 | goto out; |
5988 | break; | ||
5989 | default: | ||
5990 | break; | ||
5991 | } | 5938 | } |
5992 | 5939 | ||
5993 | if (err) | 5940 | /* If we are already listening, just update the backlog */ |
5994 | goto cleanup; | 5941 | if (sctp_sstate(sk, LISTENING)) |
5942 | sk->sk_max_ack_backlog = backlog; | ||
5943 | else { | ||
5944 | err = sctp_listen_start(sk, backlog); | ||
5945 | if (err) | ||
5946 | goto out; | ||
5947 | } | ||
5995 | 5948 | ||
5996 | /* Store away the transform reference. */ | 5949 | err = 0; |
5997 | if (!sctp_sk(sk)->hmac) | ||
5998 | sctp_sk(sk)->hmac = tfm; | ||
5999 | out: | 5950 | out: |
6000 | sctp_release_sock(sk); | 5951 | sctp_release_sock(sk); |
6001 | return err; | 5952 | return err; |
6002 | cleanup: | ||
6003 | crypto_free_hash(tfm); | ||
6004 | goto out; | ||
6005 | } | 5953 | } |
6006 | 5954 | ||
6007 | /* | 5955 | /* |