if (asoc->user_frag)
                frag = min_t(int, frag, asoc->user_frag);
 
-       frag = SCTP_TRUNC4(min_t(int, frag, SCTP_MAX_CHUNK_LEN));
+       frag = SCTP_TRUNC4(min_t(int, frag, SCTP_MAX_CHUNK_LEN -
+                                           sizeof(struct sctp_data_chunk)));
 
        return frag;
 }
 
  */
 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)) {
                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;
        }