|
@@ -2530,8 +2530,32 @@ static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, int o
|
|
|
|
|
|
/* Set the values to the specific association */
|
|
|
if (asoc) {
|
|
|
- if (assocparams.sasoc_asocmaxrxt != 0)
|
|
|
+ if (assocparams.sasoc_asocmaxrxt != 0) {
|
|
|
+ __u32 path_sum = 0;
|
|
|
+ int paths = 0;
|
|
|
+ struct list_head *pos;
|
|
|
+ struct sctp_transport *peer_addr;
|
|
|
+
|
|
|
+ list_for_each(pos, &asoc->peer.transport_addr_list) {
|
|
|
+ peer_addr = list_entry(pos,
|
|
|
+ struct sctp_transport,
|
|
|
+ transports);
|
|
|
+ path_sum += peer_addr->pathmaxrxt;
|
|
|
+ paths++;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Only validate asocmaxrxt if we have more then
|
|
|
+ * one path/transport. We do this because path
|
|
|
+ * retransmissions are only counted when we have more
|
|
|
+ * then one path.
|
|
|
+ */
|
|
|
+ if (paths > 1 &&
|
|
|
+ assocparams.sasoc_asocmaxrxt > path_sum)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
asoc->max_retrans = assocparams.sasoc_asocmaxrxt;
|
|
|
+ }
|
|
|
+
|
|
|
if (assocparams.sasoc_cookie_life != 0) {
|
|
|
asoc->cookie_life.tv_sec =
|
|
|
assocparams.sasoc_cookie_life / 1000;
|