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>
This commit is contained in:
		
					parent
					
						
							
								161c8d2f50
							
						
					
				
			
			
				commit
				
					
						e89c209581
					
				
			
		
					 1 changed files with 107 additions and 23 deletions
				
			
		|  | @ -2778,33 +2778,78 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int op | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) |  * 8.1.16.  Get or Set the Maximum Fragmentation Size (SCTP_MAXSEG) | ||||||
|  * |  * This option will get or set the maximum size to put in any outgoing | ||||||
|  * This socket option specifies the maximum size to put in any outgoing |  * SCTP DATA chunk.  If a message is larger than this size it will be | ||||||
|  * SCTP chunk.  If a message is larger than this size it will be |  | ||||||
|  * fragmented by SCTP into the specified size.  Note that the underlying |  * fragmented by SCTP into the specified size.  Note that the underlying | ||||||
|  * SCTP implementation may fragment into smaller sized chunks when the |  * SCTP implementation may fragment into smaller sized chunks when the | ||||||
|  * PMTU of the underlying association is smaller than the value set by |  * PMTU of the underlying association is smaller than the value set by | ||||||
|  * the user. |  * the user.  The default value for this option is '0' which indicates | ||||||
|  |  * the user is NOT limiting fragmentation and only the PMTU will effect | ||||||
|  |  * SCTP's choice of DATA chunk size.  Note also that values set larger | ||||||
|  |  * than the maximum size of an IP datagram will effectively let SCTP | ||||||
|  |  * control fragmentation (i.e. the same as setting this option to 0). | ||||||
|  |  * | ||||||
|  |  * The following structure is used to access and modify this parameter: | ||||||
|  |  * | ||||||
|  |  * struct sctp_assoc_value { | ||||||
|  |  *   sctp_assoc_t assoc_id; | ||||||
|  |  *   uint32_t assoc_value; | ||||||
|  |  * }; | ||||||
|  |  * | ||||||
|  |  * assoc_id:  This parameter is ignored for one-to-one style sockets. | ||||||
|  |  *    For one-to-many style sockets this parameter indicates which | ||||||
|  |  *    association the user is performing an action upon.  Note that if | ||||||
|  |  *    this field's value is zero then the endpoints default value is | ||||||
|  |  *    changed (effecting future associations only). | ||||||
|  |  * assoc_value:  This parameter specifies the maximum size in bytes. | ||||||
|  */ |  */ | ||||||
| static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen) | static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen) | ||||||
| { | { | ||||||
|  | 	struct sctp_assoc_value params; | ||||||
| 	struct sctp_association *asoc; | 	struct sctp_association *asoc; | ||||||
| 	struct sctp_sock *sp = sctp_sk(sk); | 	struct sctp_sock *sp = sctp_sk(sk); | ||||||
| 	int val; | 	int val; | ||||||
| 
 | 
 | ||||||
| 	if (optlen < sizeof(int)) | 	if (optlen == sizeof(int)) { | ||||||
| 		return -EINVAL; | 		printk(KERN_WARNING | ||||||
| 	if (get_user(val, (int __user *)optval)) | 		   "SCTP: Use of int in maxseg socket option deprecated\n"); | ||||||
|  | 		printk(KERN_WARNING | ||||||
|  | 		   "SCTP: Use struct sctp_assoc_value instead\n"); | ||||||
|  | 		if (copy_from_user(&val, optval, optlen)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
|  | 		params.assoc_id = 0; | ||||||
|  | 	} else if (optlen == sizeof(struct sctp_assoc_value)) { | ||||||
|  | 		if (copy_from_user(¶ms, optval, optlen)) | ||||||
|  | 			return -EFAULT; | ||||||
|  | 		val = params.assoc_value; | ||||||
|  | 	} else | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
| 	if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) | 	if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	asoc = sctp_id2assoc(sk, params.assoc_id); | ||||||
|  | 	if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (asoc) { | ||||||
|  | 		if (val == 0) { | ||||||
|  | 			val = asoc->pathmtu; | ||||||
|  | 			val -= sp->pf->af->net_header_len; | ||||||
|  | 			val -= sizeof(struct sctphdr) + | ||||||
|  | 					sizeof(struct sctp_data_chunk); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		asoc->frag_point = val; | ||||||
|  | 	} else { | ||||||
| 		sp->user_frag = val; | 		sp->user_frag = val; | ||||||
| 
 | 
 | ||||||
| 		/* Update the frag_point of the existing associations. */ | 		/* Update the frag_point of the existing associations. */ | ||||||
| 		list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | 		list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||||||
| 			asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); | 			asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -5100,30 +5145,69 @@ static int sctp_getsockopt_context(struct sock *sk, int len, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG) |  * 8.1.16.  Get or Set the Maximum Fragmentation Size (SCTP_MAXSEG) | ||||||
|  * |  * This option will get or set the maximum size to put in any outgoing | ||||||
|  * This socket option specifies the maximum size to put in any outgoing |  * SCTP DATA chunk.  If a message is larger than this size it will be | ||||||
|  * SCTP chunk.  If a message is larger than this size it will be |  | ||||||
|  * fragmented by SCTP into the specified size.  Note that the underlying |  * fragmented by SCTP into the specified size.  Note that the underlying | ||||||
|  * SCTP implementation may fragment into smaller sized chunks when the |  * SCTP implementation may fragment into smaller sized chunks when the | ||||||
|  * PMTU of the underlying association is smaller than the value set by |  * PMTU of the underlying association is smaller than the value set by | ||||||
|  * the user. |  * the user.  The default value for this option is '0' which indicates | ||||||
|  |  * the user is NOT limiting fragmentation and only the PMTU will effect | ||||||
|  |  * SCTP's choice of DATA chunk size.  Note also that values set larger | ||||||
|  |  * than the maximum size of an IP datagram will effectively let SCTP | ||||||
|  |  * control fragmentation (i.e. the same as setting this option to 0). | ||||||
|  |  * | ||||||
|  |  * The following structure is used to access and modify this parameter: | ||||||
|  |  * | ||||||
|  |  * struct sctp_assoc_value { | ||||||
|  |  *   sctp_assoc_t assoc_id; | ||||||
|  |  *   uint32_t assoc_value; | ||||||
|  |  * }; | ||||||
|  |  * | ||||||
|  |  * assoc_id:  This parameter is ignored for one-to-one style sockets. | ||||||
|  |  *    For one-to-many style sockets this parameter indicates which | ||||||
|  |  *    association the user is performing an action upon.  Note that if | ||||||
|  |  *    this field's value is zero then the endpoints default value is | ||||||
|  |  *    changed (effecting future associations only). | ||||||
|  |  * assoc_value:  This parameter specifies the maximum size in bytes. | ||||||
|  */ |  */ | ||||||
| static int sctp_getsockopt_maxseg(struct sock *sk, int len, | static int sctp_getsockopt_maxseg(struct sock *sk, int len, | ||||||
| 				  char __user *optval, int __user *optlen) | 				  char __user *optval, int __user *optlen) | ||||||
| { | { | ||||||
| 	int val; | 	struct sctp_assoc_value params; | ||||||
|  | 	struct sctp_association *asoc; | ||||||
| 
 | 
 | ||||||
| 	if (len < sizeof(int)) | 	if (len == sizeof(int)) { | ||||||
|  | 		printk(KERN_WARNING | ||||||
|  | 		   "SCTP: Use of int in maxseg socket option deprecated\n"); | ||||||
|  | 		printk(KERN_WARNING | ||||||
|  | 		   "SCTP: Use struct sctp_assoc_value instead\n"); | ||||||
|  | 		params.assoc_id = 0; | ||||||
|  | 	} else if (len >= sizeof(struct sctp_assoc_value)) { | ||||||
|  | 		len = sizeof(struct sctp_assoc_value); | ||||||
|  | 		if (copy_from_user(¶ms, optval, sizeof(params))) | ||||||
|  | 			return -EFAULT; | ||||||
|  | 	} else | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	len = sizeof(int); | 	asoc = sctp_id2assoc(sk, params.assoc_id); | ||||||
|  | 	if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (asoc) | ||||||
|  | 		params.assoc_value = asoc->frag_point; | ||||||
|  | 	else | ||||||
|  | 		params.assoc_value = sctp_sk(sk)->user_frag; | ||||||
| 
 | 
 | ||||||
| 	val = sctp_sk(sk)->user_frag; |  | ||||||
| 	if (put_user(len, optlen)) | 	if (put_user(len, optlen)) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 	if (copy_to_user(optval, &val, len)) | 	if (len == sizeof(int)) { | ||||||
|  | 		if (copy_to_user(optval, ¶ms.assoc_value, len)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
|  | 	} else { | ||||||
|  | 		if (copy_to_user(optval, ¶ms, len)) | ||||||
|  | 			return -EFAULT; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Wei Yongjun
				Wei Yongjun