aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Yongjun <yjwei@cn.fujitsu.com>2008-12-25 19:54:58 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-25 19:54:58 -0500
commite89c2095815d82eaa9fb85eff42f8b65b67a59cf (patch)
treea6ee89692051c0fa1328b8b79c3b9d7b44dbeab5
parent161c8d2f50109b44b664eaf23831ea1587979a61 (diff)
sctp: Bring SCTP_MAXSEG socket option into ietf API extension compliance
Brings maxseg socket option set/get into line with the latest ietf socket extensions API draft, while maintaining backwards compatibility. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sctp/socket.c130
1 files changed, 107 insertions, 23 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index a2de585888d0..0738843876a1 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -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 */
2790static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen) 2807static 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(&params, 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;
@@ -5100,30 +5145,69 @@ static int sctp_getsockopt_context(struct sock *sk, int len,
5100} 5145}
5101 5146
5102/* 5147/*
5103 * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) 5148 * 8.1.16. Get or Set the Maximum Fragmentation Size (SCTP_MAXSEG)
5104 * 5149 * This option will get or set the maximum size to put in any outgoing
5105 * This socket option specifies the maximum size to put in any outgoing 5150 * SCTP DATA chunk. If a message is larger than this size it will be
5106 * SCTP chunk. If a message is larger than this size it will be
5107 * fragmented by SCTP into the specified size. Note that the underlying 5151 * fragmented by SCTP into the specified size. Note that the underlying
5108 * SCTP implementation may fragment into smaller sized chunks when the 5152 * SCTP implementation may fragment into smaller sized chunks when the
5109 * PMTU of the underlying association is smaller than the value set by 5153 * PMTU of the underlying association is smaller than the value set by
5110 * the user. 5154 * the user. The default value for this option is '0' which indicates
5155 * the user is NOT limiting fragmentation and only the PMTU will effect
5156 * SCTP's choice of DATA chunk size. Note also that values set larger
5157 * than the maximum size of an IP datagram will effectively let SCTP
5158 * control fragmentation (i.e. the same as setting this option to 0).
5159 *
5160 * The following structure is used to access and modify this parameter:
5161 *
5162 * struct sctp_assoc_value {
5163 * sctp_assoc_t assoc_id;
5164 * uint32_t assoc_value;
5165 * };
5166 *
5167 * assoc_id: This parameter is ignored for one-to-one style sockets.
5168 * For one-to-many style sockets this parameter indicates which
5169 * association the user is performing an action upon. Note that if
5170 * this field's value is zero then the endpoints default value is
5171 * changed (effecting future associations only).
5172 * assoc_value: This parameter specifies the maximum size in bytes.
5111 */ 5173 */
5112static int sctp_getsockopt_maxseg(struct sock *sk, int len, 5174static int sctp_getsockopt_maxseg(struct sock *sk, int len,
5113 char __user *optval, int __user *optlen) 5175 char __user *optval, int __user *optlen)
5114{ 5176{
5115 int val; 5177 struct sctp_assoc_value params;
5178 struct sctp_association *asoc;
5116 5179
5117 if (len < sizeof(int)) 5180 if (len == sizeof(int)) {
5181 printk(KERN_WARNING
5182 "SCTP: Use of int in maxseg socket option deprecated\n");
5183 printk(KERN_WARNING
5184 "SCTP: Use struct sctp_assoc_value instead\n");
5185 params.assoc_id = 0;
5186 } else if (len >= sizeof(struct sctp_assoc_value)) {
5187 len = sizeof(struct sctp_assoc_value);
5188 if (copy_from_user(&params, optval, sizeof(params)))
5189 return -EFAULT;
5190 } else
5118 return -EINVAL; 5191 return -EINVAL;
5119 5192
5120 len = sizeof(int); 5193 asoc = sctp_id2assoc(sk, params.assoc_id);
5194 if (!asoc && params.assoc_id && sctp_style(sk, UDP))
5195 return -EINVAL;
5196
5197 if (asoc)
5198 params.assoc_value = asoc->frag_point;
5199 else
5200 params.assoc_value = sctp_sk(sk)->user_frag;
5121 5201
5122 val = sctp_sk(sk)->user_frag;
5123 if (put_user(len, optlen)) 5202 if (put_user(len, optlen))
5124 return -EFAULT; 5203 return -EFAULT;
5125 if (copy_to_user(optval, &val, len)) 5204 if (len == sizeof(int)) {
5126 return -EFAULT; 5205 if (copy_to_user(optval, &params.assoc_value, len))
5206 return -EFAULT;
5207 } else {
5208 if (copy_to_user(optval, &params, len))
5209 return -EFAULT;
5210 }
5127 5211
5128 return 0; 5212 return 0;
5129} 5213}