diff options
| author | Paul Mackerras <paulus@samba.org> | 2007-04-29 22:38:01 -0400 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2007-04-29 22:38:01 -0400 |
| commit | 49e1900d4cc2e7bcecb681fe60f0990bec2dcce8 (patch) | |
| tree | 253801ebf57e0a23856a2c7be129c2c178f62fdf /net/sctp/socket.c | |
| parent | 34f6d749c0a328817d5e36274e53121c1db734dc (diff) | |
| parent | b9099ff63c75216d6ca10bce5a1abcd9293c27e6 (diff) | |
Merge branch 'linux-2.6' into for-2.6.22
Diffstat (limited to 'net/sctp/socket.c')
| -rw-r--r-- | net/sctp/socket.c | 321 |
1 files changed, 295 insertions, 26 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 536298c2eda2..11938fb20395 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -627,6 +627,12 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) | |||
| 627 | retval = -EINVAL; | 627 | retval = -EINVAL; |
| 628 | goto err_bindx_rem; | 628 | goto err_bindx_rem; |
| 629 | } | 629 | } |
| 630 | |||
| 631 | if (!af->addr_valid(sa_addr, sp, NULL)) { | ||
| 632 | retval = -EADDRNOTAVAIL; | ||
| 633 | goto err_bindx_rem; | ||
| 634 | } | ||
| 635 | |||
| 630 | if (sa_addr->v4.sin_port != htons(bp->port)) { | 636 | if (sa_addr->v4.sin_port != htons(bp->port)) { |
| 631 | retval = -EINVAL; | 637 | retval = -EINVAL; |
| 632 | goto err_bindx_rem; | 638 | goto err_bindx_rem; |
| @@ -935,7 +941,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, | |||
| 935 | default: | 941 | default: |
| 936 | err = -EINVAL; | 942 | err = -EINVAL; |
| 937 | break; | 943 | break; |
| 938 | }; | 944 | } |
| 939 | 945 | ||
| 940 | out: | 946 | out: |
| 941 | kfree(kaddrs); | 947 | kfree(kaddrs); |
| @@ -2033,6 +2039,10 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
| 2033 | * SPP_HB_DEMAND - Request a user initiated heartbeat | 2039 | * SPP_HB_DEMAND - Request a user initiated heartbeat |
| 2034 | * to be made immediately. | 2040 | * to be made immediately. |
| 2035 | * | 2041 | * |
| 2042 | * SPP_HB_TIME_IS_ZERO - Specify's that the time for | ||
| 2043 | * heartbeat delayis to be set to the value of 0 | ||
| 2044 | * milliseconds. | ||
| 2045 | * | ||
| 2036 | * SPP_PMTUD_ENABLE - This field will enable PMTU | 2046 | * SPP_PMTUD_ENABLE - This field will enable PMTU |
| 2037 | * discovery upon the specified address. Note that | 2047 | * discovery upon the specified address. Note that |
| 2038 | * if the address feild is empty then all addresses | 2048 | * if the address feild is empty then all addresses |
| @@ -2075,13 +2085,30 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
| 2075 | return error; | 2085 | return error; |
| 2076 | } | 2086 | } |
| 2077 | 2087 | ||
| 2078 | if (params->spp_hbinterval) { | 2088 | /* Note that unless the spp_flag is set to SPP_HB_ENABLE the value of |
| 2079 | if (trans) { | 2089 | * this field is ignored. Note also that a value of zero indicates |
| 2080 | trans->hbinterval = msecs_to_jiffies(params->spp_hbinterval); | 2090 | * the current setting should be left unchanged. |
| 2081 | } else if (asoc) { | 2091 | */ |
| 2082 | asoc->hbinterval = msecs_to_jiffies(params->spp_hbinterval); | 2092 | if (params->spp_flags & SPP_HB_ENABLE) { |
| 2083 | } else { | 2093 | |
| 2084 | sp->hbinterval = params->spp_hbinterval; | 2094 | /* Re-zero the interval if the SPP_HB_TIME_IS_ZERO is |
| 2095 | * set. This lets us use 0 value when this flag | ||
| 2096 | * is set. | ||
| 2097 | */ | ||
| 2098 | if (params->spp_flags & SPP_HB_TIME_IS_ZERO) | ||
| 2099 | params->spp_hbinterval = 0; | ||
| 2100 | |||
| 2101 | if (params->spp_hbinterval || | ||
| 2102 | (params->spp_flags & SPP_HB_TIME_IS_ZERO)) { | ||
| 2103 | if (trans) { | ||
| 2104 | trans->hbinterval = | ||
| 2105 | msecs_to_jiffies(params->spp_hbinterval); | ||
| 2106 | } else if (asoc) { | ||
| 2107 | asoc->hbinterval = | ||
| 2108 | msecs_to_jiffies(params->spp_hbinterval); | ||
| 2109 | } else { | ||
| 2110 | sp->hbinterval = params->spp_hbinterval; | ||
| 2111 | } | ||
| 2085 | } | 2112 | } |
| 2086 | } | 2113 | } |
| 2087 | 2114 | ||
| @@ -2098,7 +2125,12 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
| 2098 | } | 2125 | } |
| 2099 | } | 2126 | } |
| 2100 | 2127 | ||
| 2101 | if (params->spp_pathmtu) { | 2128 | /* When Path MTU discovery is disabled the value specified here will |
| 2129 | * be the "fixed" path mtu (i.e. the value of the spp_flags field must | ||
| 2130 | * include the flag SPP_PMTUD_DISABLE for this field to have any | ||
| 2131 | * effect). | ||
| 2132 | */ | ||
| 2133 | if ((params->spp_flags & SPP_PMTUD_DISABLE) && params->spp_pathmtu) { | ||
| 2102 | if (trans) { | 2134 | if (trans) { |
| 2103 | trans->pathmtu = params->spp_pathmtu; | 2135 | trans->pathmtu = params->spp_pathmtu; |
| 2104 | sctp_assoc_sync_pmtu(asoc); | 2136 | sctp_assoc_sync_pmtu(asoc); |
| @@ -2129,7 +2161,11 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
| 2129 | } | 2161 | } |
| 2130 | } | 2162 | } |
| 2131 | 2163 | ||
| 2132 | if (params->spp_sackdelay) { | 2164 | /* Note that unless the spp_flag is set to SPP_SACKDELAY_ENABLE the |
| 2165 | * value of this field is ignored. Note also that a value of zero | ||
| 2166 | * indicates the current setting should be left unchanged. | ||
| 2167 | */ | ||
| 2168 | if ((params->spp_flags & SPP_SACKDELAY_ENABLE) && params->spp_sackdelay) { | ||
| 2133 | if (trans) { | 2169 | if (trans) { |
| 2134 | trans->sackdelay = | 2170 | trans->sackdelay = |
| 2135 | msecs_to_jiffies(params->spp_sackdelay); | 2171 | msecs_to_jiffies(params->spp_sackdelay); |
| @@ -2157,7 +2193,11 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
| 2157 | } | 2193 | } |
| 2158 | } | 2194 | } |
| 2159 | 2195 | ||
| 2160 | if (params->spp_pathmaxrxt) { | 2196 | /* Note that unless the spp_flag is set to SPP_PMTUD_ENABLE the value |
| 2197 | * of this field is ignored. Note also that a value of zero | ||
| 2198 | * indicates the current setting should be left unchanged. | ||
| 2199 | */ | ||
| 2200 | if ((params->spp_flags & SPP_PMTUD_ENABLE) && params->spp_pathmaxrxt) { | ||
| 2161 | if (trans) { | 2201 | if (trans) { |
| 2162 | trans->pathmaxrxt = params->spp_pathmaxrxt; | 2202 | trans->pathmaxrxt = params->spp_pathmaxrxt; |
| 2163 | } else if (asoc) { | 2203 | } else if (asoc) { |
| @@ -2249,7 +2289,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
| 2249 | return 0; | 2289 | return 0; |
| 2250 | } | 2290 | } |
| 2251 | 2291 | ||
| 2252 | /* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 2292 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) |
| 2253 | * | 2293 | * |
| 2254 | * This options will get or set the delayed ack timer. The time is set | 2294 | * This options will get or set the delayed ack timer. The time is set |
| 2255 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 2295 | * in milliseconds. If the assoc_id is 0, then this sets or gets the |
| @@ -2786,6 +2826,102 @@ static int sctp_setsockopt_context(struct sock *sk, char __user *optval, | |||
| 2786 | return 0; | 2826 | return 0; |
| 2787 | } | 2827 | } |
| 2788 | 2828 | ||
| 2829 | /* | ||
| 2830 | * 7.1.24. Get or set fragmented interleave (SCTP_FRAGMENT_INTERLEAVE) | ||
| 2831 | * | ||
| 2832 | * This options will at a minimum specify if the implementation is doing | ||
| 2833 | * fragmented interleave. Fragmented interleave, for a one to many | ||
| 2834 | * socket, is when subsequent calls to receive a message may return | ||
| 2835 | * parts of messages from different associations. Some implementations | ||
| 2836 | * may allow you to turn this value on or off. If so, when turned off, | ||
| 2837 | * no fragment interleave will occur (which will cause a head of line | ||
| 2838 | * blocking amongst multiple associations sharing the same one to many | ||
| 2839 | * socket). When this option is turned on, then each receive call may | ||
| 2840 | * come from a different association (thus the user must receive data | ||
| 2841 | * with the extended calls (e.g. sctp_recvmsg) to keep track of which | ||
| 2842 | * association each receive belongs to. | ||
| 2843 | * | ||
| 2844 | * This option takes a boolean value. A non-zero value indicates that | ||
| 2845 | * fragmented interleave is on. A value of zero indicates that | ||
| 2846 | * fragmented interleave is off. | ||
| 2847 | * | ||
| 2848 | * Note that it is important that an implementation that allows this | ||
| 2849 | * option to be turned on, have it off by default. Otherwise an unaware | ||
| 2850 | * application using the one to many model may become confused and act | ||
| 2851 | * incorrectly. | ||
| 2852 | */ | ||
| 2853 | static int sctp_setsockopt_fragment_interleave(struct sock *sk, | ||
| 2854 | char __user *optval, | ||
| 2855 | int optlen) | ||
| 2856 | { | ||
| 2857 | int val; | ||
| 2858 | |||
| 2859 | if (optlen != sizeof(int)) | ||
| 2860 | return -EINVAL; | ||
| 2861 | if (get_user(val, (int __user *)optval)) | ||
| 2862 | return -EFAULT; | ||
| 2863 | |||
| 2864 | sctp_sk(sk)->frag_interleave = (val == 0) ? 0 : 1; | ||
| 2865 | |||
| 2866 | return 0; | ||
| 2867 | } | ||
| 2868 | |||
| 2869 | /* | ||
| 2870 | * 7.1.25. Set or Get the sctp partial delivery point | ||
| 2871 | * (SCTP_PARTIAL_DELIVERY_POINT) | ||
| 2872 | * This option will set or get the SCTP partial delivery point. This | ||
| 2873 | * point is the size of a message where the partial delivery API will be | ||
| 2874 | * invoked to help free up rwnd space for the peer. Setting this to a | ||
| 2875 | * lower value will cause partial delivery's to happen more often. The | ||
| 2876 | * calls argument is an integer that sets or gets the partial delivery | ||
| 2877 | * point. | ||
| 2878 | */ | ||
| 2879 | static int sctp_setsockopt_partial_delivery_point(struct sock *sk, | ||
| 2880 | char __user *optval, | ||
| 2881 | int optlen) | ||
| 2882 | { | ||
| 2883 | u32 val; | ||
| 2884 | |||
| 2885 | if (optlen != sizeof(u32)) | ||
| 2886 | return -EINVAL; | ||
| 2887 | if (get_user(val, (int __user *)optval)) | ||
| 2888 | return -EFAULT; | ||
| 2889 | |||
| 2890 | sctp_sk(sk)->pd_point = val; | ||
| 2891 | |||
| 2892 | return 0; /* is this the right error code? */ | ||
| 2893 | } | ||
| 2894 | |||
| 2895 | /* | ||
| 2896 | * 7.1.28. Set or Get the maximum burst (SCTP_MAX_BURST) | ||
| 2897 | * | ||
| 2898 | * This option will allow a user to change the maximum burst of packets | ||
| 2899 | * that can be emitted by this association. Note that the default value | ||
| 2900 | * is 4, and some implementations may restrict this setting so that it | ||
| 2901 | * can only be lowered. | ||
| 2902 | * | ||
| 2903 | * NOTE: This text doesn't seem right. Do this on a socket basis with | ||
| 2904 | * future associations inheriting the socket value. | ||
| 2905 | */ | ||
| 2906 | static int sctp_setsockopt_maxburst(struct sock *sk, | ||
| 2907 | char __user *optval, | ||
| 2908 | int optlen) | ||
| 2909 | { | ||
| 2910 | int val; | ||
| 2911 | |||
| 2912 | if (optlen != sizeof(int)) | ||
| 2913 | return -EINVAL; | ||
| 2914 | if (get_user(val, (int __user *)optval)) | ||
| 2915 | return -EFAULT; | ||
| 2916 | |||
| 2917 | if (val < 0) | ||
| 2918 | return -EINVAL; | ||
| 2919 | |||
| 2920 | sctp_sk(sk)->max_burst = val; | ||
| 2921 | |||
| 2922 | return 0; | ||
| 2923 | } | ||
| 2924 | |||
| 2789 | /* API 6.2 setsockopt(), getsockopt() | 2925 | /* API 6.2 setsockopt(), getsockopt() |
| 2790 | * | 2926 | * |
| 2791 | * Applications use setsockopt() and getsockopt() to set or retrieve | 2927 | * Applications use setsockopt() and getsockopt() to set or retrieve |
| @@ -2865,6 +3001,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
| 2865 | case SCTP_DELAYED_ACK_TIME: | 3001 | case SCTP_DELAYED_ACK_TIME: |
| 2866 | retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen); | 3002 | retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen); |
| 2867 | break; | 3003 | break; |
| 3004 | case SCTP_PARTIAL_DELIVERY_POINT: | ||
| 3005 | retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); | ||
| 3006 | break; | ||
| 2868 | 3007 | ||
| 2869 | case SCTP_INITMSG: | 3008 | case SCTP_INITMSG: |
| 2870 | retval = sctp_setsockopt_initmsg(sk, optval, optlen); | 3009 | retval = sctp_setsockopt_initmsg(sk, optval, optlen); |
| @@ -2900,11 +3039,16 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
| 2900 | case SCTP_CONTEXT: | 3039 | case SCTP_CONTEXT: |
| 2901 | retval = sctp_setsockopt_context(sk, optval, optlen); | 3040 | retval = sctp_setsockopt_context(sk, optval, optlen); |
| 2902 | break; | 3041 | break; |
| 2903 | 3042 | case SCTP_FRAGMENT_INTERLEAVE: | |
| 3043 | retval = sctp_setsockopt_fragment_interleave(sk, optval, optlen); | ||
| 3044 | break; | ||
| 3045 | case SCTP_MAX_BURST: | ||
| 3046 | retval = sctp_setsockopt_maxburst(sk, optval, optlen); | ||
| 3047 | break; | ||
| 2904 | default: | 3048 | default: |
| 2905 | retval = -ENOPROTOOPT; | 3049 | retval = -ENOPROTOOPT; |
| 2906 | break; | 3050 | break; |
| 2907 | }; | 3051 | } |
| 2908 | 3052 | ||
| 2909 | sctp_release_sock(sk); | 3053 | sctp_release_sock(sk); |
| 2910 | 3054 | ||
| @@ -3060,6 +3204,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
| 3060 | sp->default_timetolive = 0; | 3204 | sp->default_timetolive = 0; |
| 3061 | 3205 | ||
| 3062 | sp->default_rcv_context = 0; | 3206 | sp->default_rcv_context = 0; |
| 3207 | sp->max_burst = sctp_max_burst; | ||
| 3063 | 3208 | ||
| 3064 | /* Initialize default setup parameters. These parameters | 3209 | /* Initialize default setup parameters. These parameters |
| 3065 | * can be modified with the SCTP_INITMSG socket option or | 3210 | * can be modified with the SCTP_INITMSG socket option or |
| @@ -3128,8 +3273,9 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
| 3128 | sp->pf = sctp_get_pf_specific(sk->sk_family); | 3273 | sp->pf = sctp_get_pf_specific(sk->sk_family); |
| 3129 | 3274 | ||
| 3130 | /* Control variables for partial data delivery. */ | 3275 | /* Control variables for partial data delivery. */ |
| 3131 | sp->pd_mode = 0; | 3276 | atomic_set(&sp->pd_mode, 0); |
| 3132 | skb_queue_head_init(&sp->pd_lobby); | 3277 | skb_queue_head_init(&sp->pd_lobby); |
| 3278 | sp->frag_interleave = 0; | ||
| 3133 | 3279 | ||
| 3134 | /* Create a per socket endpoint structure. Even if we | 3280 | /* Create a per socket endpoint structure. Even if we |
| 3135 | * change the data structure relationships, this may still | 3281 | * change the data structure relationships, this may still |
| @@ -3636,7 +3782,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
| 3636 | return 0; | 3782 | return 0; |
| 3637 | } | 3783 | } |
| 3638 | 3784 | ||
| 3639 | /* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 3785 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) |
| 3640 | * | 3786 | * |
| 3641 | * This options will get or set the delayed ack timer. The time is set | 3787 | * This options will get or set the delayed ack timer. The time is set |
| 3642 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 3788 | * in milliseconds. If the assoc_id is 0, then this sets or gets the |
| @@ -4530,6 +4676,77 @@ static int sctp_getsockopt_maxseg(struct sock *sk, int len, | |||
| 4530 | return 0; | 4676 | return 0; |
| 4531 | } | 4677 | } |
| 4532 | 4678 | ||
| 4679 | /* | ||
| 4680 | * 7.1.24. Get or set fragmented interleave (SCTP_FRAGMENT_INTERLEAVE) | ||
| 4681 | * (chapter and verse is quoted at sctp_setsockopt_fragment_interleave()) | ||
| 4682 | */ | ||
| 4683 | static int sctp_getsockopt_fragment_interleave(struct sock *sk, int len, | ||
| 4684 | char __user *optval, int __user *optlen) | ||
| 4685 | { | ||
| 4686 | int val; | ||
| 4687 | |||
| 4688 | if (len < sizeof(int)) | ||
| 4689 | return -EINVAL; | ||
| 4690 | |||
| 4691 | len = sizeof(int); | ||
| 4692 | |||
| 4693 | val = sctp_sk(sk)->frag_interleave; | ||
| 4694 | if (put_user(len, optlen)) | ||
| 4695 | return -EFAULT; | ||
| 4696 | if (copy_to_user(optval, &val, len)) | ||
| 4697 | return -EFAULT; | ||
| 4698 | |||
| 4699 | return 0; | ||
| 4700 | } | ||
| 4701 | |||
| 4702 | /* | ||
| 4703 | * 7.1.25. Set or Get the sctp partial delivery point | ||
| 4704 | * (chapter and verse is quoted at sctp_setsockopt_partial_delivery_point()) | ||
| 4705 | */ | ||
| 4706 | static int sctp_getsockopt_partial_delivery_point(struct sock *sk, int len, | ||
| 4707 | char __user *optval, | ||
| 4708 | int __user *optlen) | ||
| 4709 | { | ||
| 4710 | u32 val; | ||
| 4711 | |||
| 4712 | if (len < sizeof(u32)) | ||
| 4713 | return -EINVAL; | ||
| 4714 | |||
| 4715 | len = sizeof(u32); | ||
| 4716 | |||
| 4717 | val = sctp_sk(sk)->pd_point; | ||
| 4718 | if (put_user(len, optlen)) | ||
| 4719 | return -EFAULT; | ||
| 4720 | if (copy_to_user(optval, &val, len)) | ||
| 4721 | return -EFAULT; | ||
| 4722 | |||
| 4723 | return -ENOTSUPP; | ||
| 4724 | } | ||
| 4725 | |||
| 4726 | /* | ||
| 4727 | * 7.1.28. Set or Get the maximum burst (SCTP_MAX_BURST) | ||
| 4728 | * (chapter and verse is quoted at sctp_setsockopt_maxburst()) | ||
| 4729 | */ | ||
| 4730 | static int sctp_getsockopt_maxburst(struct sock *sk, int len, | ||
| 4731 | char __user *optval, | ||
| 4732 | int __user *optlen) | ||
| 4733 | { | ||
| 4734 | int val; | ||
| 4735 | |||
| 4736 | if (len < sizeof(int)) | ||
| 4737 | return -EINVAL; | ||
| 4738 | |||
| 4739 | len = sizeof(int); | ||
| 4740 | |||
| 4741 | val = sctp_sk(sk)->max_burst; | ||
| 4742 | if (put_user(len, optlen)) | ||
| 4743 | return -EFAULT; | ||
| 4744 | if (copy_to_user(optval, &val, len)) | ||
| 4745 | return -EFAULT; | ||
| 4746 | |||
| 4747 | return -ENOTSUPP; | ||
| 4748 | } | ||
| 4749 | |||
| 4533 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 4750 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
| 4534 | char __user *optval, int __user *optlen) | 4751 | char __user *optval, int __user *optlen) |
| 4535 | { | 4752 | { |
| @@ -4642,10 +4859,21 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
| 4642 | case SCTP_CONTEXT: | 4859 | case SCTP_CONTEXT: |
| 4643 | retval = sctp_getsockopt_context(sk, len, optval, optlen); | 4860 | retval = sctp_getsockopt_context(sk, len, optval, optlen); |
| 4644 | break; | 4861 | break; |
| 4862 | case SCTP_FRAGMENT_INTERLEAVE: | ||
| 4863 | retval = sctp_getsockopt_fragment_interleave(sk, len, optval, | ||
| 4864 | optlen); | ||
| 4865 | break; | ||
| 4866 | case SCTP_PARTIAL_DELIVERY_POINT: | ||
| 4867 | retval = sctp_getsockopt_partial_delivery_point(sk, len, optval, | ||
| 4868 | optlen); | ||
| 4869 | break; | ||
| 4870 | case SCTP_MAX_BURST: | ||
| 4871 | retval = sctp_getsockopt_maxburst(sk, len, optval, optlen); | ||
| 4872 | break; | ||
| 4645 | default: | 4873 | default: |
| 4646 | retval = -ENOPROTOOPT; | 4874 | retval = -ENOPROTOOPT; |
| 4647 | break; | 4875 | break; |
| 4648 | }; | 4876 | } |
| 4649 | 4877 | ||
| 4650 | sctp_release_sock(sk); | 4878 | sctp_release_sock(sk); |
| 4651 | return retval; | 4879 | return retval; |
| @@ -4970,7 +5198,8 @@ int sctp_inet_listen(struct socket *sock, int backlog) | |||
| 4970 | break; | 5198 | break; |
| 4971 | default: | 5199 | default: |
| 4972 | break; | 5200 | break; |
| 4973 | }; | 5201 | } |
| 5202 | |||
| 4974 | if (err) | 5203 | if (err) |
| 4975 | goto cleanup; | 5204 | goto cleanup; |
| 4976 | 5205 | ||
| @@ -5233,7 +5462,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, | |||
| 5233 | 5462 | ||
| 5234 | default: | 5463 | default: |
| 5235 | return -EINVAL; | 5464 | return -EINVAL; |
| 5236 | }; | 5465 | } |
| 5237 | } | 5466 | } |
| 5238 | return 0; | 5467 | return 0; |
| 5239 | } | 5468 | } |
| @@ -5638,6 +5867,36 @@ void sctp_wait_for_close(struct sock *sk, long timeout) | |||
| 5638 | finish_wait(sk->sk_sleep, &wait); | 5867 | finish_wait(sk->sk_sleep, &wait); |
| 5639 | } | 5868 | } |
| 5640 | 5869 | ||
| 5870 | static void sctp_sock_rfree_frag(struct sk_buff *skb) | ||
| 5871 | { | ||
| 5872 | struct sk_buff *frag; | ||
| 5873 | |||
| 5874 | if (!skb->data_len) | ||
| 5875 | goto done; | ||
| 5876 | |||
| 5877 | /* Don't forget the fragments. */ | ||
| 5878 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) | ||
| 5879 | sctp_sock_rfree_frag(frag); | ||
| 5880 | |||
| 5881 | done: | ||
| 5882 | sctp_sock_rfree(skb); | ||
| 5883 | } | ||
| 5884 | |||
| 5885 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) | ||
| 5886 | { | ||
| 5887 | struct sk_buff *frag; | ||
| 5888 | |||
| 5889 | if (!skb->data_len) | ||
| 5890 | goto done; | ||
| 5891 | |||
| 5892 | /* Don't forget the fragments. */ | ||
| 5893 | for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) | ||
| 5894 | sctp_skb_set_owner_r_frag(frag, sk); | ||
| 5895 | |||
| 5896 | done: | ||
| 5897 | sctp_skb_set_owner_r(skb, sk); | ||
| 5898 | } | ||
| 5899 | |||
| 5641 | /* Populate the fields of the newsk from the oldsk and migrate the assoc | 5900 | /* Populate the fields of the newsk from the oldsk and migrate the assoc |
| 5642 | * and its messages to the newsk. | 5901 | * and its messages to the newsk. |
| 5643 | */ | 5902 | */ |
| @@ -5692,10 +5951,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
| 5692 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { | 5951 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { |
| 5693 | event = sctp_skb2event(skb); | 5952 | event = sctp_skb2event(skb); |
| 5694 | if (event->asoc == assoc) { | 5953 | if (event->asoc == assoc) { |
| 5695 | sctp_sock_rfree(skb); | 5954 | sctp_sock_rfree_frag(skb); |
| 5696 | __skb_unlink(skb, &oldsk->sk_receive_queue); | 5955 | __skb_unlink(skb, &oldsk->sk_receive_queue); |
| 5697 | __skb_queue_tail(&newsk->sk_receive_queue, skb); | 5956 | __skb_queue_tail(&newsk->sk_receive_queue, skb); |
| 5698 | sctp_skb_set_owner_r(skb, newsk); | 5957 | sctp_skb_set_owner_r_frag(skb, newsk); |
| 5699 | } | 5958 | } |
| 5700 | } | 5959 | } |
| 5701 | 5960 | ||
| @@ -5706,9 +5965,9 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
| 5706 | * 3) Peeling off non-partial delivery; move pd_lobby to receive_queue. | 5965 | * 3) Peeling off non-partial delivery; move pd_lobby to receive_queue. |
| 5707 | */ | 5966 | */ |
| 5708 | skb_queue_head_init(&newsp->pd_lobby); | 5967 | skb_queue_head_init(&newsp->pd_lobby); |
| 5709 | sctp_sk(newsk)->pd_mode = assoc->ulpq.pd_mode; | 5968 | atomic_set(&sctp_sk(newsk)->pd_mode, assoc->ulpq.pd_mode); |
| 5710 | 5969 | ||
| 5711 | if (sctp_sk(oldsk)->pd_mode) { | 5970 | if (atomic_read(&sctp_sk(oldsk)->pd_mode)) { |
| 5712 | struct sk_buff_head *queue; | 5971 | struct sk_buff_head *queue; |
| 5713 | 5972 | ||
| 5714 | /* Decide which queue to move pd_lobby skbs to. */ | 5973 | /* Decide which queue to move pd_lobby skbs to. */ |
| @@ -5723,10 +5982,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
| 5723 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { | 5982 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { |
| 5724 | event = sctp_skb2event(skb); | 5983 | event = sctp_skb2event(skb); |
| 5725 | if (event->asoc == assoc) { | 5984 | if (event->asoc == assoc) { |
| 5726 | sctp_sock_rfree(skb); | 5985 | sctp_sock_rfree_frag(skb); |
| 5727 | __skb_unlink(skb, &oldsp->pd_lobby); | 5986 | __skb_unlink(skb, &oldsp->pd_lobby); |
| 5728 | __skb_queue_tail(queue, skb); | 5987 | __skb_queue_tail(queue, skb); |
| 5729 | sctp_skb_set_owner_r(skb, newsk); | 5988 | sctp_skb_set_owner_r_frag(skb, newsk); |
| 5730 | } | 5989 | } |
| 5731 | } | 5990 | } |
| 5732 | 5991 | ||
| @@ -5734,8 +5993,18 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
| 5734 | * delivery to finish. | 5993 | * delivery to finish. |
| 5735 | */ | 5994 | */ |
| 5736 | if (assoc->ulpq.pd_mode) | 5995 | if (assoc->ulpq.pd_mode) |
| 5737 | sctp_clear_pd(oldsk); | 5996 | sctp_clear_pd(oldsk, NULL); |
| 5997 | |||
| 5998 | } | ||
| 5999 | |||
| 6000 | sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) { | ||
| 6001 | sctp_sock_rfree_frag(skb); | ||
| 6002 | sctp_skb_set_owner_r_frag(skb, newsk); | ||
| 6003 | } | ||
| 5738 | 6004 | ||
| 6005 | sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) { | ||
| 6006 | sctp_sock_rfree_frag(skb); | ||
| 6007 | sctp_skb_set_owner_r_frag(skb, newsk); | ||
| 5739 | } | 6008 | } |
| 5740 | 6009 | ||
| 5741 | /* Set the type of socket to indicate that it is peeled off from the | 6010 | /* Set the type of socket to indicate that it is peeled off from the |
