sctp: Fix SCTP_MAXSEG socket option to comply to spec.
We had a bug that we never stored the user-defined value for MAXSEG when setting the value on an association. Thus future PMTU events ended up re-writing the frag point and increasing it past user limit. Additionally, when setting the option on the socket/endpoint, we effect all current associations, which is against spec. Now, we store the user 'maxseg' value along with the computed 'frag_point'. We inherit 'maxseg' from the socket at association creation and use it as an upper limit for 'frag_point' when its set. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
This commit is contained in:
@ -112,6 +112,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
|
||||
asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000)
|
||||
* 1000;
|
||||
asoc->frag_point = 0;
|
||||
asoc->user_frag = sp->user_frag;
|
||||
|
||||
/* Set the association max_retrans and RTO values from the
|
||||
* socket values.
|
||||
@ -674,7 +675,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
|
||||
"%d\n", asoc, asoc->pathmtu);
|
||||
peer->pmtu_pending = 0;
|
||||
|
||||
asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
|
||||
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);
|
||||
|
||||
/* The asoc->peer.port might not be meaningful yet, but
|
||||
* initialize the packet structure anyway.
|
||||
@ -1330,9 +1331,8 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
|
||||
}
|
||||
|
||||
if (pmtu) {
|
||||
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
|
||||
asoc->pathmtu = pmtu;
|
||||
asoc->frag_point = sctp_frag_point(sp, pmtu);
|
||||
asoc->frag_point = sctp_frag_point(asoc, pmtu);
|
||||
}
|
||||
|
||||
SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n",
|
||||
|
@ -2243,7 +2243,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
|
||||
sctp_assoc_sync_pmtu(asoc);
|
||||
} else if (asoc) {
|
||||
asoc->pathmtu = params->spp_pathmtu;
|
||||
sctp_frag_point(sp, params->spp_pathmtu);
|
||||
sctp_frag_point(asoc, params->spp_pathmtu);
|
||||
} else {
|
||||
sp->pathmtu = params->spp_pathmtu;
|
||||
}
|
||||
@ -2880,15 +2880,10 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
|
||||
val -= sizeof(struct sctphdr) +
|
||||
sizeof(struct sctp_data_chunk);
|
||||
}
|
||||
|
||||
asoc->frag_point = val;
|
||||
asoc->user_frag = val;
|
||||
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);
|
||||
} 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;
|
||||
|
Reference in New Issue
Block a user