diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-04-06 03:02:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-06 03:02:57 -0400 |
commit | f541ae326fa120fa5c57433e4d9a133df212ce41 (patch) | |
tree | bdbd94ec72cfc601118051cb35e8617d55510177 /net/sctp/socket.c | |
parent | e255357764f92afcafafbd4879b222b8c752065a (diff) | |
parent | 0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff) |
Merge branch 'linus' into perfcounters/core-v2
Merge reason: we have gathered quite a few conflicts, need to merge upstream
Conflicts:
arch/powerpc/kernel/Makefile
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/hardirq.h
arch/x86/include/asm/unistd_32.h
arch/x86/include/asm/unistd_64.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/irq.c
arch/x86/kernel/syscall_table_32.S
arch/x86/mm/iomap_32.c
include/linux/sched.h
kernel/Makefile
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 216 |
1 files changed, 100 insertions, 116 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ff0a8f88de04..5fb3a8c9792e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -3069,9 +3069,6 @@ static int sctp_setsockopt_maxburst(struct sock *sk, | |||
3069 | int val; | 3069 | int val; |
3070 | int assoc_id = 0; | 3070 | int assoc_id = 0; |
3071 | 3071 | ||
3072 | if (optlen < sizeof(int)) | ||
3073 | return -EINVAL; | ||
3074 | |||
3075 | if (optlen == sizeof(int)) { | 3072 | if (optlen == sizeof(int)) { |
3076 | printk(KERN_WARNING | 3073 | printk(KERN_WARNING |
3077 | "SCTP: Use of int in max_burst socket option deprecated\n"); | 3074 | "SCTP: Use of int in max_burst socket option deprecated\n"); |
@@ -3939,7 +3936,6 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, | |||
3939 | { | 3936 | { |
3940 | struct sock *sk = asoc->base.sk; | 3937 | struct sock *sk = asoc->base.sk; |
3941 | struct socket *sock; | 3938 | struct socket *sock; |
3942 | struct inet_sock *inetsk; | ||
3943 | struct sctp_af *af; | 3939 | struct sctp_af *af; |
3944 | int err = 0; | 3940 | int err = 0; |
3945 | 3941 | ||
@@ -3954,18 +3950,18 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, | |||
3954 | if (err < 0) | 3950 | if (err < 0) |
3955 | return err; | 3951 | return err; |
3956 | 3952 | ||
3957 | /* Populate the fields of the newsk from the oldsk and migrate the | 3953 | sctp_copy_sock(sock->sk, sk, asoc); |
3958 | * asoc to the newsk. | ||
3959 | */ | ||
3960 | sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); | ||
3961 | 3954 | ||
3962 | /* Make peeled-off sockets more like 1-1 accepted sockets. | 3955 | /* Make peeled-off sockets more like 1-1 accepted sockets. |
3963 | * Set the daddr and initialize id to something more random | 3956 | * Set the daddr and initialize id to something more random |
3964 | */ | 3957 | */ |
3965 | af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); | 3958 | af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); |
3966 | af->to_sk_daddr(&asoc->peer.primary_addr, sk); | 3959 | af->to_sk_daddr(&asoc->peer.primary_addr, sk); |
3967 | inetsk = inet_sk(sock->sk); | 3960 | |
3968 | inetsk->id = asoc->next_tsn ^ jiffies; | 3961 | /* Populate the fields of the newsk from the oldsk and migrate the |
3962 | * asoc to the newsk. | ||
3963 | */ | ||
3964 | sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); | ||
3969 | 3965 | ||
3970 | *sockp = sock; | 3966 | *sockp = sock; |
3971 | 3967 | ||
@@ -5284,16 +5280,14 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, | |||
5284 | struct sctp_sock *sp; | 5280 | struct sctp_sock *sp; |
5285 | struct sctp_association *asoc; | 5281 | struct sctp_association *asoc; |
5286 | 5282 | ||
5287 | if (len < sizeof(int)) | ||
5288 | return -EINVAL; | ||
5289 | |||
5290 | if (len == sizeof(int)) { | 5283 | if (len == sizeof(int)) { |
5291 | printk(KERN_WARNING | 5284 | printk(KERN_WARNING |
5292 | "SCTP: Use of int in max_burst socket option deprecated\n"); | 5285 | "SCTP: Use of int in max_burst socket option deprecated\n"); |
5293 | printk(KERN_WARNING | 5286 | printk(KERN_WARNING |
5294 | "SCTP: Use struct sctp_assoc_value instead\n"); | 5287 | "SCTP: Use struct sctp_assoc_value instead\n"); |
5295 | params.assoc_id = 0; | 5288 | params.assoc_id = 0; |
5296 | } else if (len == sizeof (struct sctp_assoc_value)) { | 5289 | } else if (len >= sizeof(struct sctp_assoc_value)) { |
5290 | len = sizeof(struct sctp_assoc_value); | ||
5297 | if (copy_from_user(¶ms, optval, len)) | 5291 | if (copy_from_user(¶ms, optval, len)) |
5298 | return -EFAULT; | 5292 | return -EFAULT; |
5299 | } else | 5293 | } else |
@@ -5849,37 +5843,28 @@ static int sctp_get_port(struct sock *sk, unsigned short snum) | |||
5849 | } | 5843 | } |
5850 | 5844 | ||
5851 | /* | 5845 | /* |
5852 | * 3.1.3 listen() - UDP Style Syntax | 5846 | * Move a socket to LISTENING state. |
5853 | * | ||
5854 | * By default, new associations are not accepted for UDP style sockets. | ||
5855 | * An application uses listen() to mark a socket as being able to | ||
5856 | * accept new associations. | ||
5857 | */ | 5847 | */ |
5858 | SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | 5848 | SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog) |
5859 | { | 5849 | { |
5860 | struct sctp_sock *sp = sctp_sk(sk); | 5850 | struct sctp_sock *sp = sctp_sk(sk); |
5861 | struct sctp_endpoint *ep = sp->ep; | 5851 | struct sctp_endpoint *ep = sp->ep; |
5852 | struct crypto_hash *tfm = NULL; | ||
5862 | 5853 | ||
5863 | /* Only UDP style sockets that are not peeled off are allowed to | 5854 | /* Allocate HMAC for generating cookie. */ |
5864 | * listen(). | 5855 | if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { |
5865 | */ | 5856 | tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); |
5866 | if (!sctp_style(sk, UDP)) | 5857 | if (IS_ERR(tfm)) { |
5867 | return -EINVAL; | 5858 | if (net_ratelimit()) { |
5868 | 5859 | printk(KERN_INFO | |
5869 | /* If backlog is zero, disable listening. */ | 5860 | "SCTP: failed to load transform for %s: %ld\n", |
5870 | if (!backlog) { | 5861 | sctp_hmac_alg, PTR_ERR(tfm)); |
5871 | if (sctp_sstate(sk, CLOSED)) | 5862 | } |
5872 | return 0; | 5863 | return -ENOSYS; |
5873 | 5864 | } | |
5874 | sctp_unhash_endpoint(ep); | 5865 | sctp_sk(sk)->hmac = tfm; |
5875 | sk->sk_state = SCTP_SS_CLOSED; | ||
5876 | return 0; | ||
5877 | } | 5866 | } |
5878 | 5867 | ||
5879 | /* Return if we are already listening. */ | ||
5880 | if (sctp_sstate(sk, LISTENING)) | ||
5881 | return 0; | ||
5882 | |||
5883 | /* | 5868 | /* |
5884 | * 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() |
5885 | * call that allows new associations to be accepted, the system | 5870 | * call that allows new associations to be accepted, the system |
@@ -5890,7 +5875,6 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | |||
5890 | * extensions draft, but follows the practice as seen in TCP | 5875 | * extensions draft, but follows the practice as seen in TCP |
5891 | * sockets. | 5876 | * sockets. |
5892 | * | 5877 | * |
5893 | * Additionally, turn off fastreuse flag since we are not listening | ||
5894 | */ | 5878 | */ |
5895 | sk->sk_state = SCTP_SS_LISTENING; | 5879 | sk->sk_state = SCTP_SS_LISTENING; |
5896 | if (!ep->base.bind_addr.port) { | 5880 | if (!ep->base.bind_addr.port) { |
@@ -5901,113 +5885,71 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) | |||
5901 | sk->sk_state = SCTP_SS_CLOSED; | 5885 | sk->sk_state = SCTP_SS_CLOSED; |
5902 | return -EADDRINUSE; | 5886 | return -EADDRINUSE; |
5903 | } | 5887 | } |
5904 | sctp_sk(sk)->bind_hash->fastreuse = 0; | ||
5905 | } | 5888 | } |
5906 | 5889 | ||
5907 | sctp_hash_endpoint(ep); | ||
5908 | return 0; | ||
5909 | } | ||
5910 | |||
5911 | /* | ||
5912 | * 4.1.3 listen() - TCP Style Syntax | ||
5913 | * | ||
5914 | * Applications uses listen() to ready the SCTP endpoint for accepting | ||
5915 | * inbound associations. | ||
5916 | */ | ||
5917 | SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) | ||
5918 | { | ||
5919 | struct sctp_sock *sp = sctp_sk(sk); | ||
5920 | struct sctp_endpoint *ep = sp->ep; | ||
5921 | |||
5922 | /* If backlog is zero, disable listening. */ | ||
5923 | if (!backlog) { | ||
5924 | if (sctp_sstate(sk, CLOSED)) | ||
5925 | return 0; | ||
5926 | |||
5927 | sctp_unhash_endpoint(ep); | ||
5928 | sk->sk_state = SCTP_SS_CLOSED; | ||
5929 | return 0; | ||
5930 | } | ||
5931 | |||
5932 | if (sctp_sstate(sk, LISTENING)) | ||
5933 | return 0; | ||
5934 | |||
5935 | /* | ||
5936 | * If a bind() or sctp_bindx() is not called prior to a listen() | ||
5937 | * call that allows new associations to be accepted, the system | ||
5938 | * picks an ephemeral port and will choose an address set equivalent | ||
5939 | * to binding with a wildcard address. | ||
5940 | * | ||
5941 | * This is not currently spelled out in the SCTP sockets | ||
5942 | * extensions draft, but follows the practice as seen in TCP | ||
5943 | * sockets. | ||
5944 | */ | ||
5945 | sk->sk_state = SCTP_SS_LISTENING; | ||
5946 | if (!ep->base.bind_addr.port) { | ||
5947 | if (sctp_autobind(sk)) | ||
5948 | return -EAGAIN; | ||
5949 | } else | ||
5950 | sctp_sk(sk)->bind_hash->fastreuse = 0; | ||
5951 | |||
5952 | sk->sk_max_ack_backlog = backlog; | 5890 | sk->sk_max_ack_backlog = backlog; |
5953 | sctp_hash_endpoint(ep); | 5891 | sctp_hash_endpoint(ep); |
5954 | return 0; | 5892 | return 0; |
5955 | } | 5893 | } |
5956 | 5894 | ||
5957 | /* | 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 | * | ||
5958 | * Move a socket to LISTENING state. | 5907 | * Move a socket to LISTENING state. |
5959 | */ | 5908 | */ |
5960 | int sctp_inet_listen(struct socket *sock, int backlog) | 5909 | int sctp_inet_listen(struct socket *sock, int backlog) |
5961 | { | 5910 | { |
5962 | struct sock *sk = sock->sk; | 5911 | struct sock *sk = sock->sk; |
5963 | struct crypto_hash *tfm = NULL; | 5912 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
5964 | int err = -EINVAL; | 5913 | int err = -EINVAL; |
5965 | 5914 | ||
5966 | if (unlikely(backlog < 0)) | 5915 | if (unlikely(backlog < 0)) |
5967 | goto out; | 5916 | return err; |
5968 | 5917 | ||
5969 | sctp_lock_sock(sk); | 5918 | sctp_lock_sock(sk); |
5970 | 5919 | ||
5920 | /* Peeled-off sockets are not allowed to listen(). */ | ||
5921 | if (sctp_style(sk, UDP_HIGH_BANDWIDTH)) | ||
5922 | goto out; | ||
5923 | |||
5971 | if (sock->state != SS_UNCONNECTED) | 5924 | if (sock->state != SS_UNCONNECTED) |
5972 | goto out; | 5925 | goto out; |
5973 | 5926 | ||
5974 | /* Allocate HMAC for generating cookie. */ | 5927 | /* If backlog is zero, disable listening. */ |
5975 | if (!sctp_sk(sk)->hmac && sctp_hmac_alg) { | 5928 | if (!backlog) { |
5976 | tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); | 5929 | if (sctp_sstate(sk, CLOSED)) |
5977 | if (IS_ERR(tfm)) { | ||
5978 | if (net_ratelimit()) { | ||
5979 | printk(KERN_INFO | ||
5980 | "SCTP: failed to load transform for %s: %ld\n", | ||
5981 | sctp_hmac_alg, PTR_ERR(tfm)); | ||
5982 | } | ||
5983 | err = -ENOSYS; | ||
5984 | goto out; | 5930 | goto out; |
5985 | } | ||
5986 | } | ||
5987 | 5931 | ||
5988 | switch (sock->type) { | 5932 | err = 0; |
5989 | case SOCK_SEQPACKET: | 5933 | sctp_unhash_endpoint(ep); |
5990 | err = sctp_seqpacket_listen(sk, backlog); | 5934 | sk->sk_state = SCTP_SS_CLOSED; |
5991 | break; | 5935 | if (sk->sk_reuse) |
5992 | case SOCK_STREAM: | 5936 | sctp_sk(sk)->bind_hash->fastreuse = 1; |
5993 | err = sctp_stream_listen(sk, backlog); | 5937 | goto out; |
5994 | break; | ||
5995 | default: | ||
5996 | break; | ||
5997 | } | 5938 | } |
5998 | 5939 | ||
5999 | if (err) | 5940 | /* If we are already listening, just update the backlog */ |
6000 | 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 | } | ||
6001 | 5948 | ||
6002 | /* Store away the transform reference. */ | 5949 | err = 0; |
6003 | if (!sctp_sk(sk)->hmac) | ||
6004 | sctp_sk(sk)->hmac = tfm; | ||
6005 | out: | 5950 | out: |
6006 | sctp_release_sock(sk); | 5951 | sctp_release_sock(sk); |
6007 | return err; | 5952 | return err; |
6008 | cleanup: | ||
6009 | crypto_free_hash(tfm); | ||
6010 | goto out; | ||
6011 | } | 5953 | } |
6012 | 5954 | ||
6013 | /* | 5955 | /* |
@@ -6700,6 +6642,48 @@ done: | |||
6700 | sctp_skb_set_owner_r(skb, sk); | 6642 | sctp_skb_set_owner_r(skb, sk); |
6701 | } | 6643 | } |
6702 | 6644 | ||
6645 | void sctp_copy_sock(struct sock *newsk, struct sock *sk, | ||
6646 | struct sctp_association *asoc) | ||
6647 | { | ||
6648 | struct inet_sock *inet = inet_sk(sk); | ||
6649 | struct inet_sock *newinet = inet_sk(newsk); | ||
6650 | |||
6651 | newsk->sk_type = sk->sk_type; | ||
6652 | newsk->sk_bound_dev_if = sk->sk_bound_dev_if; | ||
6653 | newsk->sk_flags = sk->sk_flags; | ||
6654 | newsk->sk_no_check = sk->sk_no_check; | ||
6655 | newsk->sk_reuse = sk->sk_reuse; | ||
6656 | |||
6657 | newsk->sk_shutdown = sk->sk_shutdown; | ||
6658 | newsk->sk_destruct = inet_sock_destruct; | ||
6659 | newsk->sk_family = sk->sk_family; | ||
6660 | newsk->sk_protocol = IPPROTO_SCTP; | ||
6661 | newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | ||
6662 | newsk->sk_sndbuf = sk->sk_sndbuf; | ||
6663 | newsk->sk_rcvbuf = sk->sk_rcvbuf; | ||
6664 | newsk->sk_lingertime = sk->sk_lingertime; | ||
6665 | newsk->sk_rcvtimeo = sk->sk_rcvtimeo; | ||
6666 | newsk->sk_sndtimeo = sk->sk_sndtimeo; | ||
6667 | |||
6668 | newinet = inet_sk(newsk); | ||
6669 | |||
6670 | /* Initialize sk's sport, dport, rcv_saddr and daddr for | ||
6671 | * getsockname() and getpeername() | ||
6672 | */ | ||
6673 | newinet->sport = inet->sport; | ||
6674 | newinet->saddr = inet->saddr; | ||
6675 | newinet->rcv_saddr = inet->rcv_saddr; | ||
6676 | newinet->dport = htons(asoc->peer.port); | ||
6677 | newinet->pmtudisc = inet->pmtudisc; | ||
6678 | newinet->id = asoc->next_tsn ^ jiffies; | ||
6679 | |||
6680 | newinet->uc_ttl = inet->uc_ttl; | ||
6681 | newinet->mc_loop = 1; | ||
6682 | newinet->mc_ttl = 1; | ||
6683 | newinet->mc_index = 0; | ||
6684 | newinet->mc_list = NULL; | ||
6685 | } | ||
6686 | |||
6703 | /* Populate the fields of the newsk from the oldsk and migrate the assoc | 6687 | /* Populate the fields of the newsk from the oldsk and migrate the assoc |
6704 | * and its messages to the newsk. | 6688 | * and its messages to the newsk. |
6705 | */ | 6689 | */ |