diff options
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 206 |
1 files changed, 173 insertions, 33 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a1b904529d5e..b14a8f33e42d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -114,7 +114,7 @@ extern int sysctl_sctp_wmem[3]; | |||
114 | 114 | ||
115 | static int sctp_memory_pressure; | 115 | static int sctp_memory_pressure; |
116 | static atomic_t sctp_memory_allocated; | 116 | static atomic_t sctp_memory_allocated; |
117 | static atomic_t sctp_sockets_allocated; | 117 | struct percpu_counter sctp_sockets_allocated; |
118 | 118 | ||
119 | static void sctp_enter_memory_pressure(struct sock *sk) | 119 | static void sctp_enter_memory_pressure(struct sock *sk) |
120 | { | 120 | { |
@@ -2404,9 +2404,9 @@ static int sctp_setsockopt_delayed_ack(struct sock *sk, | |||
2404 | if (params.sack_delay == 0 && params.sack_freq == 0) | 2404 | if (params.sack_delay == 0 && params.sack_freq == 0) |
2405 | return 0; | 2405 | return 0; |
2406 | } else if (optlen == sizeof(struct sctp_assoc_value)) { | 2406 | } else if (optlen == sizeof(struct sctp_assoc_value)) { |
2407 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | 2407 | printk(KERN_WARNING "SCTP: Use of struct sctp_assoc_value " |
2408 | "in delayed_ack socket option deprecated\n"); | 2408 | "in delayed_ack socket option deprecated\n"); |
2409 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | 2409 | printk(KERN_WARNING "SCTP: Use struct sctp_sack_info instead\n"); |
2410 | if (copy_from_user(¶ms, optval, optlen)) | 2410 | if (copy_from_user(¶ms, optval, optlen)) |
2411 | return -EFAULT; | 2411 | return -EFAULT; |
2412 | 2412 | ||
@@ -2778,32 +2778,77 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int op | |||
2778 | } | 2778 | } |
2779 | 2779 | ||
2780 | /* | 2780 | /* |
2781 | * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) | 2781 | * 8.1.16. Get or Set the Maximum Fragmentation Size (SCTP_MAXSEG) |
2782 | * | 2782 | * This option will get or set the maximum size to put in any outgoing |
2783 | * This socket option specifies the maximum size to put in any outgoing | 2783 | * SCTP DATA chunk. If a message is larger than this size it will be |
2784 | * SCTP chunk. If a message is larger than this size it will be | ||
2785 | * fragmented by SCTP into the specified size. Note that the underlying | 2784 | * fragmented by SCTP into the specified size. Note that the underlying |
2786 | * SCTP implementation may fragment into smaller sized chunks when the | 2785 | * SCTP implementation may fragment into smaller sized chunks when the |
2787 | * PMTU of the underlying association is smaller than the value set by | 2786 | * PMTU of the underlying association is smaller than the value set by |
2788 | * the user. | 2787 | * the user. The default value for this option is '0' which indicates |
2788 | * the user is NOT limiting fragmentation and only the PMTU will effect | ||
2789 | * SCTP's choice of DATA chunk size. Note also that values set larger | ||
2790 | * than the maximum size of an IP datagram will effectively let SCTP | ||
2791 | * control fragmentation (i.e. the same as setting this option to 0). | ||
2792 | * | ||
2793 | * The following structure is used to access and modify this parameter: | ||
2794 | * | ||
2795 | * struct sctp_assoc_value { | ||
2796 | * sctp_assoc_t assoc_id; | ||
2797 | * uint32_t assoc_value; | ||
2798 | * }; | ||
2799 | * | ||
2800 | * assoc_id: This parameter is ignored for one-to-one style sockets. | ||
2801 | * For one-to-many style sockets this parameter indicates which | ||
2802 | * association the user is performing an action upon. Note that if | ||
2803 | * this field's value is zero then the endpoints default value is | ||
2804 | * changed (effecting future associations only). | ||
2805 | * assoc_value: This parameter specifies the maximum size in bytes. | ||
2789 | */ | 2806 | */ |
2790 | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen) | 2807 | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen) |
2791 | { | 2808 | { |
2809 | struct sctp_assoc_value params; | ||
2792 | struct sctp_association *asoc; | 2810 | struct sctp_association *asoc; |
2793 | struct sctp_sock *sp = sctp_sk(sk); | 2811 | struct sctp_sock *sp = sctp_sk(sk); |
2794 | int val; | 2812 | int val; |
2795 | 2813 | ||
2796 | if (optlen < sizeof(int)) | 2814 | if (optlen == sizeof(int)) { |
2815 | printk(KERN_WARNING | ||
2816 | "SCTP: Use of int in maxseg socket option deprecated\n"); | ||
2817 | printk(KERN_WARNING | ||
2818 | "SCTP: Use struct sctp_assoc_value instead\n"); | ||
2819 | if (copy_from_user(&val, optval, optlen)) | ||
2820 | return -EFAULT; | ||
2821 | params.assoc_id = 0; | ||
2822 | } else if (optlen == sizeof(struct sctp_assoc_value)) { | ||
2823 | if (copy_from_user(¶ms, optval, optlen)) | ||
2824 | return -EFAULT; | ||
2825 | val = params.assoc_value; | ||
2826 | } else | ||
2797 | return -EINVAL; | 2827 | return -EINVAL; |
2798 | if (get_user(val, (int __user *)optval)) | 2828 | |
2799 | return -EFAULT; | ||
2800 | if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) | 2829 | if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) |
2801 | return -EINVAL; | 2830 | return -EINVAL; |
2802 | sp->user_frag = val; | ||
2803 | 2831 | ||
2804 | /* Update the frag_point of the existing associations. */ | 2832 | asoc = sctp_id2assoc(sk, params.assoc_id); |
2805 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | 2833 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) |
2806 | asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); | 2834 | return -EINVAL; |
2835 | |||
2836 | if (asoc) { | ||
2837 | if (val == 0) { | ||
2838 | val = asoc->pathmtu; | ||
2839 | val -= sp->pf->af->net_header_len; | ||
2840 | val -= sizeof(struct sctphdr) + | ||
2841 | sizeof(struct sctp_data_chunk); | ||
2842 | } | ||
2843 | |||
2844 | asoc->frag_point = val; | ||
2845 | } else { | ||
2846 | sp->user_frag = val; | ||
2847 | |||
2848 | /* Update the frag_point of the existing associations. */ | ||
2849 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||
2850 | asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); | ||
2851 | } | ||
2807 | } | 2852 | } |
2808 | 2853 | ||
2809 | return 0; | 2854 | return 0; |
@@ -2965,14 +3010,21 @@ static int sctp_setsockopt_fragment_interleave(struct sock *sk, | |||
2965 | } | 3010 | } |
2966 | 3011 | ||
2967 | /* | 3012 | /* |
2968 | * 7.1.25. Set or Get the sctp partial delivery point | 3013 | * 8.1.21. Set or Get the SCTP Partial Delivery Point |
2969 | * (SCTP_PARTIAL_DELIVERY_POINT) | 3014 | * (SCTP_PARTIAL_DELIVERY_POINT) |
3015 | * | ||
2970 | * This option will set or get the SCTP partial delivery point. This | 3016 | * This option will set or get the SCTP partial delivery point. This |
2971 | * point is the size of a message where the partial delivery API will be | 3017 | * point is the size of a message where the partial delivery API will be |
2972 | * invoked to help free up rwnd space for the peer. Setting this to a | 3018 | * invoked to help free up rwnd space for the peer. Setting this to a |
2973 | * lower value will cause partial delivery's to happen more often. The | 3019 | * lower value will cause partial deliveries to happen more often. The |
2974 | * calls argument is an integer that sets or gets the partial delivery | 3020 | * calls argument is an integer that sets or gets the partial delivery |
2975 | * point. | 3021 | * point. Note also that the call will fail if the user attempts to set |
3022 | * this value larger than the socket receive buffer size. | ||
3023 | * | ||
3024 | * Note that any single message having a length smaller than or equal to | ||
3025 | * the SCTP partial delivery point will be delivered in one single read | ||
3026 | * call as long as the user provided buffer is large enough to hold the | ||
3027 | * message. | ||
2976 | */ | 3028 | */ |
2977 | static int sctp_setsockopt_partial_delivery_point(struct sock *sk, | 3029 | static int sctp_setsockopt_partial_delivery_point(struct sock *sk, |
2978 | char __user *optval, | 3030 | char __user *optval, |
@@ -2985,6 +3037,12 @@ static int sctp_setsockopt_partial_delivery_point(struct sock *sk, | |||
2985 | if (get_user(val, (int __user *)optval)) | 3037 | if (get_user(val, (int __user *)optval)) |
2986 | return -EFAULT; | 3038 | return -EFAULT; |
2987 | 3039 | ||
3040 | /* Note: We double the receive buffer from what the user sets | ||
3041 | * it to be, also initial rwnd is based on rcvbuf/2. | ||
3042 | */ | ||
3043 | if (val > (sk->sk_rcvbuf >> 1)) | ||
3044 | return -EINVAL; | ||
3045 | |||
2988 | sctp_sk(sk)->pd_point = val; | 3046 | sctp_sk(sk)->pd_point = val; |
2989 | 3047 | ||
2990 | return 0; /* is this the right error code? */ | 3048 | return 0; /* is this the right error code? */ |
@@ -3613,7 +3671,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3613 | sp->hmac = NULL; | 3671 | sp->hmac = NULL; |
3614 | 3672 | ||
3615 | SCTP_DBG_OBJCNT_INC(sock); | 3673 | SCTP_DBG_OBJCNT_INC(sock); |
3616 | atomic_inc(&sctp_sockets_allocated); | 3674 | percpu_counter_inc(&sctp_sockets_allocated); |
3675 | |||
3676 | local_bh_disable(); | ||
3677 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | ||
3678 | local_bh_enable(); | ||
3679 | |||
3617 | return 0; | 3680 | return 0; |
3618 | } | 3681 | } |
3619 | 3682 | ||
@@ -3627,7 +3690,10 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) | |||
3627 | /* Release our hold on the endpoint. */ | 3690 | /* Release our hold on the endpoint. */ |
3628 | ep = sctp_sk(sk)->ep; | 3691 | ep = sctp_sk(sk)->ep; |
3629 | sctp_endpoint_free(ep); | 3692 | sctp_endpoint_free(ep); |
3630 | atomic_dec(&sctp_sockets_allocated); | 3693 | percpu_counter_dec(&sctp_sockets_allocated); |
3694 | local_bh_disable(); | ||
3695 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | ||
3696 | local_bh_enable(); | ||
3631 | } | 3697 | } |
3632 | 3698 | ||
3633 | /* API 4.1.7 shutdown() - TCP Style Syntax | 3699 | /* API 4.1.7 shutdown() - TCP Style Syntax |
@@ -4168,9 +4234,9 @@ static int sctp_getsockopt_delayed_ack(struct sock *sk, int len, | |||
4168 | if (copy_from_user(¶ms, optval, len)) | 4234 | if (copy_from_user(¶ms, optval, len)) |
4169 | return -EFAULT; | 4235 | return -EFAULT; |
4170 | } else if (len == sizeof(struct sctp_assoc_value)) { | 4236 | } else if (len == sizeof(struct sctp_assoc_value)) { |
4171 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | 4237 | printk(KERN_WARNING "SCTP: Use of struct sctp_assoc_value " |
4172 | "in delayed_ack socket option deprecated\n"); | 4238 | "in delayed_ack socket option deprecated\n"); |
4173 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | 4239 | printk(KERN_WARNING "SCTP: Use struct sctp_sack_info instead\n"); |
4174 | if (copy_from_user(¶ms, optval, len)) | 4240 | if (copy_from_user(¶ms, optval, len)) |
4175 | return -EFAULT; | 4241 | return -EFAULT; |
4176 | } else | 4242 | } else |
@@ -5092,30 +5158,69 @@ static int sctp_getsockopt_context(struct sock *sk, int len, | |||
5092 | } | 5158 | } |
5093 | 5159 | ||
5094 | /* | 5160 | /* |
5095 | * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) | 5161 | * 8.1.16. Get or Set the Maximum Fragmentation Size (SCTP_MAXSEG) |
5096 | * | 5162 | * This option will get or set the maximum size to put in any outgoing |
5097 | * This socket option specifies the maximum size to put in any outgoing | 5163 | * SCTP DATA chunk. If a message is larger than this size it will be |
5098 | * SCTP chunk. If a message is larger than this size it will be | ||
5099 | * fragmented by SCTP into the specified size. Note that the underlying | 5164 | * fragmented by SCTP into the specified size. Note that the underlying |
5100 | * SCTP implementation may fragment into smaller sized chunks when the | 5165 | * SCTP implementation may fragment into smaller sized chunks when the |
5101 | * PMTU of the underlying association is smaller than the value set by | 5166 | * PMTU of the underlying association is smaller than the value set by |
5102 | * the user. | 5167 | * the user. The default value for this option is '0' which indicates |
5168 | * the user is NOT limiting fragmentation and only the PMTU will effect | ||
5169 | * SCTP's choice of DATA chunk size. Note also that values set larger | ||
5170 | * than the maximum size of an IP datagram will effectively let SCTP | ||
5171 | * control fragmentation (i.e. the same as setting this option to 0). | ||
5172 | * | ||
5173 | * The following structure is used to access and modify this parameter: | ||
5174 | * | ||
5175 | * struct sctp_assoc_value { | ||
5176 | * sctp_assoc_t assoc_id; | ||
5177 | * uint32_t assoc_value; | ||
5178 | * }; | ||
5179 | * | ||
5180 | * assoc_id: This parameter is ignored for one-to-one style sockets. | ||
5181 | * For one-to-many style sockets this parameter indicates which | ||
5182 | * association the user is performing an action upon. Note that if | ||
5183 | * this field's value is zero then the endpoints default value is | ||
5184 | * changed (effecting future associations only). | ||
5185 | * assoc_value: This parameter specifies the maximum size in bytes. | ||
5103 | */ | 5186 | */ |
5104 | static int sctp_getsockopt_maxseg(struct sock *sk, int len, | 5187 | static int sctp_getsockopt_maxseg(struct sock *sk, int len, |
5105 | char __user *optval, int __user *optlen) | 5188 | char __user *optval, int __user *optlen) |
5106 | { | 5189 | { |
5107 | int val; | 5190 | struct sctp_assoc_value params; |
5191 | struct sctp_association *asoc; | ||
5108 | 5192 | ||
5109 | if (len < sizeof(int)) | 5193 | if (len == sizeof(int)) { |
5194 | printk(KERN_WARNING | ||
5195 | "SCTP: Use of int in maxseg socket option deprecated\n"); | ||
5196 | printk(KERN_WARNING | ||
5197 | "SCTP: Use struct sctp_assoc_value instead\n"); | ||
5198 | params.assoc_id = 0; | ||
5199 | } else if (len >= sizeof(struct sctp_assoc_value)) { | ||
5200 | len = sizeof(struct sctp_assoc_value); | ||
5201 | if (copy_from_user(¶ms, optval, sizeof(params))) | ||
5202 | return -EFAULT; | ||
5203 | } else | ||
5110 | return -EINVAL; | 5204 | return -EINVAL; |
5111 | 5205 | ||
5112 | len = sizeof(int); | 5206 | asoc = sctp_id2assoc(sk, params.assoc_id); |
5207 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | ||
5208 | return -EINVAL; | ||
5209 | |||
5210 | if (asoc) | ||
5211 | params.assoc_value = asoc->frag_point; | ||
5212 | else | ||
5213 | params.assoc_value = sctp_sk(sk)->user_frag; | ||
5113 | 5214 | ||
5114 | val = sctp_sk(sk)->user_frag; | ||
5115 | if (put_user(len, optlen)) | 5215 | if (put_user(len, optlen)) |
5116 | return -EFAULT; | 5216 | return -EFAULT; |
5117 | if (copy_to_user(optval, &val, len)) | 5217 | if (len == sizeof(int)) { |
5118 | return -EFAULT; | 5218 | if (copy_to_user(optval, ¶ms.assoc_value, len)) |
5219 | return -EFAULT; | ||
5220 | } else { | ||
5221 | if (copy_to_user(optval, ¶ms, len)) | ||
5222 | return -EFAULT; | ||
5223 | } | ||
5119 | 5224 | ||
5120 | return 0; | 5225 | return 0; |
5121 | } | 5226 | } |
@@ -5368,6 +5473,38 @@ num: | |||
5368 | return 0; | 5473 | return 0; |
5369 | } | 5474 | } |
5370 | 5475 | ||
5476 | /* | ||
5477 | * 8.2.5. Get the Current Number of Associations (SCTP_GET_ASSOC_NUMBER) | ||
5478 | * This option gets the current number of associations that are attached | ||
5479 | * to a one-to-many style socket. The option value is an uint32_t. | ||
5480 | */ | ||
5481 | static int sctp_getsockopt_assoc_number(struct sock *sk, int len, | ||
5482 | char __user *optval, int __user *optlen) | ||
5483 | { | ||
5484 | struct sctp_sock *sp = sctp_sk(sk); | ||
5485 | struct sctp_association *asoc; | ||
5486 | u32 val = 0; | ||
5487 | |||
5488 | if (sctp_style(sk, TCP)) | ||
5489 | return -EOPNOTSUPP; | ||
5490 | |||
5491 | if (len < sizeof(u32)) | ||
5492 | return -EINVAL; | ||
5493 | |||
5494 | len = sizeof(u32); | ||
5495 | |||
5496 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||
5497 | val++; | ||
5498 | } | ||
5499 | |||
5500 | if (put_user(len, optlen)) | ||
5501 | return -EFAULT; | ||
5502 | if (copy_to_user(optval, &val, len)) | ||
5503 | return -EFAULT; | ||
5504 | |||
5505 | return 0; | ||
5506 | } | ||
5507 | |||
5371 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 5508 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
5372 | char __user *optval, int __user *optlen) | 5509 | char __user *optval, int __user *optlen) |
5373 | { | 5510 | { |
@@ -5510,6 +5647,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5510 | retval = sctp_getsockopt_local_auth_chunks(sk, len, optval, | 5647 | retval = sctp_getsockopt_local_auth_chunks(sk, len, optval, |
5511 | optlen); | 5648 | optlen); |
5512 | break; | 5649 | break; |
5650 | case SCTP_GET_ASSOC_NUMBER: | ||
5651 | retval = sctp_getsockopt_assoc_number(sk, len, optval, optlen); | ||
5652 | break; | ||
5513 | default: | 5653 | default: |
5514 | retval = -ENOPROTOOPT; | 5654 | retval = -ENOPROTOOPT; |
5515 | break; | 5655 | break; |