|
@@ -3140,9 +3140,9 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
|
|
|
*/
|
|
|
static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
|
|
|
{
|
|
|
+ struct sctp_sock *sp = sctp_sk(sk);
|
|
|
struct sctp_assoc_value params;
|
|
|
struct sctp_association *asoc;
|
|
|
- struct sctp_sock *sp = sctp_sk(sk);
|
|
|
int val;
|
|
|
|
|
|
if (optlen == sizeof(int)) {
|
|
@@ -3158,26 +3158,35 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
|
|
|
if (copy_from_user(¶ms, optval, optlen))
|
|
|
return -EFAULT;
|
|
|
val = params.assoc_value;
|
|
|
- } else
|
|
|
+ } else {
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
- if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)))
|
|
|
- return -EINVAL;
|
|
|
+ if (val) {
|
|
|
+ int min_len, max_len;
|
|
|
|
|
|
- asoc = sctp_id2assoc(sk, params.assoc_id);
|
|
|
- if (!asoc && params.assoc_id && sctp_style(sk, UDP))
|
|
|
- return -EINVAL;
|
|
|
+ min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len;
|
|
|
+ min_len -= sizeof(struct sctphdr) +
|
|
|
+ sizeof(struct sctp_data_chunk);
|
|
|
+
|
|
|
+ max_len = SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_data_chunk);
|
|
|
|
|
|
+ if (val < min_len || val > max_len)
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ asoc = sctp_id2assoc(sk, params.assoc_id);
|
|
|
if (asoc) {
|
|
|
if (val == 0) {
|
|
|
- val = asoc->pathmtu;
|
|
|
- val -= sp->pf->af->net_header_len;
|
|
|
+ val = asoc->pathmtu - sp->pf->af->net_header_len;
|
|
|
val -= sizeof(struct sctphdr) +
|
|
|
- sizeof(struct sctp_data_chunk);
|
|
|
+ sizeof(struct sctp_data_chunk);
|
|
|
}
|
|
|
asoc->user_frag = val;
|
|
|
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);
|
|
|
} else {
|
|
|
+ if (params.assoc_id && sctp_style(sk, UDP))
|
|
|
+ return -EINVAL;
|
|
|
sp->user_frag = val;
|
|
|
}
|
|
|
|