Skip to content

Commit f68b2e0

Browse files
author
Vlad Yasevich
committed
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 <[email protected]>
1 parent cb95ea3 commit f68b2e0

File tree

4 files changed

+11
-14
lines changed

4 files changed

+11
-14
lines changed

include/net/sctp/sctp.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,15 +486,16 @@ static inline __s32 sctp_jitter(__u32 rto)
486486
}
487487

488488
/* Break down data chunks at this point. */
489-
static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu)
489+
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
490490
{
491+
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
491492
int frag = pmtu;
492493

493494
frag -= sp->pf->af->net_header_len;
494495
frag -= sizeof(struct sctphdr) + sizeof(struct sctp_data_chunk);
495496

496-
if (sp->user_frag)
497-
frag = min_t(int, frag, sp->user_frag);
497+
if (asoc->user_frag)
498+
frag = min_t(int, frag, asoc->user_frag);
498499

499500
frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN);
500501

include/net/sctp/structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,7 @@ struct sctp_association {
17631763

17641764
/* The message size at which SCTP fragmentation will occur. */
17651765
__u32 frag_point;
1766+
__u32 user_frag;
17661767

17671768
/* Counter used to count INIT errors. */
17681769
int init_err_counter;

net/sctp/associola.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
112112
asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000)
113113
* 1000;
114114
asoc->frag_point = 0;
115+
asoc->user_frag = sp->user_frag;
115116

116117
/* Set the association max_retrans and RTO values from the
117118
* socket values.
@@ -674,7 +675,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
674675
"%d\n", asoc, asoc->pathmtu);
675676
peer->pmtu_pending = 0;
676677

677-
asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
678+
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);
678679

679680
/* The asoc->peer.port might not be meaningful yet, but
680681
* initialize the packet structure anyway.
@@ -1330,9 +1331,8 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
13301331
}
13311332

13321333
if (pmtu) {
1333-
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
13341334
asoc->pathmtu = pmtu;
1335-
asoc->frag_point = sctp_frag_point(sp, pmtu);
1335+
asoc->frag_point = sctp_frag_point(asoc, pmtu);
13361336
}
13371337

13381338
SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n",

net/sctp/socket.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,7 +2243,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
22432243
sctp_assoc_sync_pmtu(asoc);
22442244
} else if (asoc) {
22452245
asoc->pathmtu = params->spp_pathmtu;
2246-
sctp_frag_point(sp, params->spp_pathmtu);
2246+
sctp_frag_point(asoc, params->spp_pathmtu);
22472247
} else {
22482248
sp->pathmtu = params->spp_pathmtu;
22492249
}
@@ -2880,15 +2880,10 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
28802880
val -= sizeof(struct sctphdr) +
28812881
sizeof(struct sctp_data_chunk);
28822882
}
2883-
2884-
asoc->frag_point = val;
2883+
asoc->user_frag = val;
2884+
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);
28852885
} else {
28862886
sp->user_frag = val;
2887-
2888-
/* Update the frag_point of the existing associations. */
2889-
list_for_each_entry(asoc, &(sp->ep->asocs), asocs) {
2890-
asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
2891-
}
28922887
}
28932888

28942889
return 0;

0 commit comments

Comments
 (0)