|
@@ -2778,32 +2778,77 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int op
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG)
|
|
|
|
- *
|
|
|
|
- * This socket option specifies the maximum size to put in any outgoing
|
|
|
|
- * SCTP chunk. If a message is larger than this size it will be
|
|
|
|
|
|
+ * 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
|
|
|
|
+ * SCTP DATA 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)) {
|
|
|
|
+ printk(KERN_WARNING
|
|
|
|
+ "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;
|
|
|
|
+ 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;
|
|
return -EINVAL;
|
|
- if (get_user(val, (int __user *)optval))
|
|
|
|
- return -EFAULT;
|
|
|
|
|
|
+
|
|
if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)))
|
|
if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
- sp->user_frag = val;
|
|
|
|
|
|
|
|
- /* Update the frag_point of the existing associations. */
|
|
|
|
- list_for_each_entry(asoc, &(sp->ep->asocs), asocs) {
|
|
|
|
- asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
|
|
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ /* Update the frag_point of the existing associations. */
|
|
|
|
+ list_for_each_entry(asoc, &(sp->ep->asocs), asocs) {
|
|
|
|
+ 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)
|
|
|
|
- *
|
|
|
|
- * This socket option specifies the maximum size to put in any outgoing
|
|
|
|
- * SCTP chunk. If a message is larger than this size it will be
|
|
|
|
|
|
+ * 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
|
|
|
|
+ * SCTP DATA 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))
|
|
|
|
- return -EFAULT;
|
|
|
|
|
|
+ if (len == sizeof(int)) {
|
|
|
|
+ if (copy_to_user(optval, ¶ms.assoc_value, len))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+ } else {
|
|
|
|
+ if (copy_to_user(optval, ¶ms, len))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|