diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 5 | ||||
-rw-r--r-- | net/sctp/output.c | 6 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 6 | ||||
-rw-r--r-- | net/sctp/probe.c | 17 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 12 | ||||
-rw-r--r-- | net/sctp/socket.c | 36 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 76 | ||||
-rw-r--r-- | net/sctp/transport.c | 2 |
8 files changed, 126 insertions, 34 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 68a27f9796d2..31ed008c8e13 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -154,8 +154,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
154 | 154 | ||
155 | asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; | 155 | asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; |
156 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; | 156 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; |
157 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = | 157 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ; |
158 | min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ; | ||
159 | 158 | ||
160 | /* Initializes the timers */ | 159 | /* Initializes the timers */ |
161 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) | 160 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) |
@@ -291,8 +290,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
291 | asoc->peer.ipv6_address = 1; | 290 | asoc->peer.ipv6_address = 1; |
292 | INIT_LIST_HEAD(&asoc->asocs); | 291 | INIT_LIST_HEAD(&asoc->asocs); |
293 | 292 | ||
294 | asoc->autoclose = sp->autoclose; | ||
295 | |||
296 | asoc->default_stream = sp->default_stream; | 293 | asoc->default_stream = sp->default_stream; |
297 | asoc->default_ppid = sp->default_ppid; | 294 | asoc->default_ppid = sp->default_ppid; |
298 | asoc->default_flags = sp->default_flags; | 295 | asoc->default_flags = sp->default_flags; |
diff --git a/net/sctp/output.c b/net/sctp/output.c index e650978daf27..0fb140f8f088 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -474,10 +474,11 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
474 | * for a given destination transport address. | 474 | * for a given destination transport address. |
475 | */ | 475 | */ |
476 | 476 | ||
477 | if (!tp->rto_pending) { | 477 | if (!chunk->resent && !tp->rto_pending) { |
478 | chunk->rtt_in_progress = 1; | 478 | chunk->rtt_in_progress = 1; |
479 | tp->rto_pending = 1; | 479 | tp->rto_pending = 1; |
480 | } | 480 | } |
481 | |||
481 | has_data = 1; | 482 | has_data = 1; |
482 | } | 483 | } |
483 | 484 | ||
@@ -580,7 +581,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
580 | unsigned long timeout; | 581 | unsigned long timeout; |
581 | 582 | ||
582 | /* Restart the AUTOCLOSE timer when sending data. */ | 583 | /* Restart the AUTOCLOSE timer when sending data. */ |
583 | if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) { | 584 | if (sctp_state(asoc, ESTABLISHED) && |
585 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { | ||
584 | timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; | 586 | timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; |
585 | timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; | 587 | timeout = asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]; |
586 | 588 | ||
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 94df75877869..f51ba985a36e 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -446,6 +446,8 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
446 | transport->rto_pending = 0; | 446 | transport->rto_pending = 0; |
447 | } | 447 | } |
448 | 448 | ||
449 | chunk->resent = 1; | ||
450 | |||
449 | /* Move the chunk to the retransmit queue. The chunks | 451 | /* Move the chunk to the retransmit queue. The chunks |
450 | * on the retransmit queue are always kept in order. | 452 | * on the retransmit queue are always kept in order. |
451 | */ | 453 | */ |
@@ -1375,6 +1377,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1375 | * instance). | 1377 | * instance). |
1376 | */ | 1378 | */ |
1377 | if (!tchunk->tsn_gap_acked && | 1379 | if (!tchunk->tsn_gap_acked && |
1380 | !tchunk->resent && | ||
1378 | tchunk->rtt_in_progress) { | 1381 | tchunk->rtt_in_progress) { |
1379 | tchunk->rtt_in_progress = 0; | 1382 | tchunk->rtt_in_progress = 0; |
1380 | rtt = jiffies - tchunk->sent_at; | 1383 | rtt = jiffies - tchunk->sent_at; |
@@ -1391,7 +1394,8 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1391 | */ | 1394 | */ |
1392 | if (!tchunk->tsn_gap_acked) { | 1395 | if (!tchunk->tsn_gap_acked) { |
1393 | tchunk->tsn_gap_acked = 1; | 1396 | tchunk->tsn_gap_acked = 1; |
1394 | *highest_new_tsn_in_sack = tsn; | 1397 | if (TSN_lt(*highest_new_tsn_in_sack, tsn)) |
1398 | *highest_new_tsn_in_sack = tsn; | ||
1395 | bytes_acked += sctp_data_size(tchunk); | 1399 | bytes_acked += sctp_data_size(tchunk); |
1396 | if (!tchunk->transport) | 1400 | if (!tchunk->transport) |
1397 | migrate_bytes += sctp_data_size(tchunk); | 1401 | migrate_bytes += sctp_data_size(tchunk); |
diff --git a/net/sctp/probe.c b/net/sctp/probe.c index 53c452efb40b..5e68b94ee640 100644 --- a/net/sctp/probe.c +++ b/net/sctp/probe.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <net/sctp/sctp.h> | 38 | #include <net/sctp/sctp.h> |
39 | #include <net/sctp/sm.h> | 39 | #include <net/sctp/sm.h> |
40 | 40 | ||
41 | MODULE_SOFTDEP("pre: sctp"); | ||
41 | MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>"); | 42 | MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>"); |
42 | MODULE_DESCRIPTION("SCTP snooper"); | 43 | MODULE_DESCRIPTION("SCTP snooper"); |
43 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
@@ -182,6 +183,20 @@ static struct jprobe sctp_recv_probe = { | |||
182 | .entry = jsctp_sf_eat_sack, | 183 | .entry = jsctp_sf_eat_sack, |
183 | }; | 184 | }; |
184 | 185 | ||
186 | static __init int sctp_setup_jprobe(void) | ||
187 | { | ||
188 | int ret = register_jprobe(&sctp_recv_probe); | ||
189 | |||
190 | if (ret) { | ||
191 | if (request_module("sctp")) | ||
192 | goto out; | ||
193 | ret = register_jprobe(&sctp_recv_probe); | ||
194 | } | ||
195 | |||
196 | out: | ||
197 | return ret; | ||
198 | } | ||
199 | |||
185 | static __init int sctpprobe_init(void) | 200 | static __init int sctpprobe_init(void) |
186 | { | 201 | { |
187 | int ret = -ENOMEM; | 202 | int ret = -ENOMEM; |
@@ -202,7 +217,7 @@ static __init int sctpprobe_init(void) | |||
202 | &sctpprobe_fops)) | 217 | &sctpprobe_fops)) |
203 | goto free_kfifo; | 218 | goto free_kfifo; |
204 | 219 | ||
205 | ret = register_jprobe(&sctp_recv_probe); | 220 | ret = sctp_setup_jprobe(); |
206 | if (ret) | 221 | if (ret) |
207 | goto remove_proc; | 222 | goto remove_proc; |
208 | 223 | ||
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index dfe3f36ff2aa..a26065be7289 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -820,7 +820,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, | |||
820 | SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); | 820 | SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); |
821 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 821 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
822 | 822 | ||
823 | if (new_asoc->autoclose) | 823 | if (new_asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
824 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 824 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
825 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 825 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
826 | 826 | ||
@@ -908,7 +908,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(struct net *net, | |||
908 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); | 908 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); |
909 | SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); | 909 | SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); |
910 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 910 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
911 | if (asoc->autoclose) | 911 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
912 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 912 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
913 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 913 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
914 | 914 | ||
@@ -2970,7 +2970,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net, | |||
2970 | if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) | 2970 | if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM) |
2971 | force = SCTP_FORCE(); | 2971 | force = SCTP_FORCE(); |
2972 | 2972 | ||
2973 | if (asoc->autoclose) { | 2973 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { |
2974 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 2974 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
2975 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 2975 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
2976 | } | 2976 | } |
@@ -3878,7 +3878,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net, | |||
3878 | SCTP_CHUNK(chunk)); | 3878 | SCTP_CHUNK(chunk)); |
3879 | 3879 | ||
3880 | /* Count this as receiving DATA. */ | 3880 | /* Count this as receiving DATA. */ |
3881 | if (asoc->autoclose) { | 3881 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) { |
3882 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 3882 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
3883 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 3883 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
3884 | } | 3884 | } |
@@ -5267,7 +5267,7 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( | |||
5267 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 5267 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
5268 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 5268 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
5269 | 5269 | ||
5270 | if (asoc->autoclose) | 5270 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
5271 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5271 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
5272 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 5272 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
5273 | 5273 | ||
@@ -5346,7 +5346,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack( | |||
5346 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 5346 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
5347 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); | 5347 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); |
5348 | 5348 | ||
5349 | if (asoc->autoclose) | 5349 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE]) |
5350 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5350 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
5351 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 5351 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
5352 | 5352 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 72046b9729a8..42b709c95cf3 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2196,6 +2196,7 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
2196 | unsigned int optlen) | 2196 | unsigned int optlen) |
2197 | { | 2197 | { |
2198 | struct sctp_sock *sp = sctp_sk(sk); | 2198 | struct sctp_sock *sp = sctp_sk(sk); |
2199 | struct net *net = sock_net(sk); | ||
2199 | 2200 | ||
2200 | /* Applicable to UDP-style socket only */ | 2201 | /* Applicable to UDP-style socket only */ |
2201 | if (sctp_style(sk, TCP)) | 2202 | if (sctp_style(sk, TCP)) |
@@ -2205,6 +2206,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, | |||
2205 | if (copy_from_user(&sp->autoclose, optval, optlen)) | 2206 | if (copy_from_user(&sp->autoclose, optval, optlen)) |
2206 | return -EFAULT; | 2207 | return -EFAULT; |
2207 | 2208 | ||
2209 | if (sp->autoclose > net->sctp.max_autoclose) | ||
2210 | sp->autoclose = net->sctp.max_autoclose; | ||
2211 | |||
2208 | return 0; | 2212 | return 0; |
2209 | } | 2213 | } |
2210 | 2214 | ||
@@ -2811,6 +2815,8 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne | |||
2811 | { | 2815 | { |
2812 | struct sctp_rtoinfo rtoinfo; | 2816 | struct sctp_rtoinfo rtoinfo; |
2813 | struct sctp_association *asoc; | 2817 | struct sctp_association *asoc; |
2818 | unsigned long rto_min, rto_max; | ||
2819 | struct sctp_sock *sp = sctp_sk(sk); | ||
2814 | 2820 | ||
2815 | if (optlen != sizeof (struct sctp_rtoinfo)) | 2821 | if (optlen != sizeof (struct sctp_rtoinfo)) |
2816 | return -EINVAL; | 2822 | return -EINVAL; |
@@ -2824,26 +2830,36 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigne | |||
2824 | if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) | 2830 | if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP)) |
2825 | return -EINVAL; | 2831 | return -EINVAL; |
2826 | 2832 | ||
2833 | rto_max = rtoinfo.srto_max; | ||
2834 | rto_min = rtoinfo.srto_min; | ||
2835 | |||
2836 | if (rto_max) | ||
2837 | rto_max = asoc ? msecs_to_jiffies(rto_max) : rto_max; | ||
2838 | else | ||
2839 | rto_max = asoc ? asoc->rto_max : sp->rtoinfo.srto_max; | ||
2840 | |||
2841 | if (rto_min) | ||
2842 | rto_min = asoc ? msecs_to_jiffies(rto_min) : rto_min; | ||
2843 | else | ||
2844 | rto_min = asoc ? asoc->rto_min : sp->rtoinfo.srto_min; | ||
2845 | |||
2846 | if (rto_min > rto_max) | ||
2847 | return -EINVAL; | ||
2848 | |||
2827 | if (asoc) { | 2849 | if (asoc) { |
2828 | if (rtoinfo.srto_initial != 0) | 2850 | if (rtoinfo.srto_initial != 0) |
2829 | asoc->rto_initial = | 2851 | asoc->rto_initial = |
2830 | msecs_to_jiffies(rtoinfo.srto_initial); | 2852 | msecs_to_jiffies(rtoinfo.srto_initial); |
2831 | if (rtoinfo.srto_max != 0) | 2853 | asoc->rto_max = rto_max; |
2832 | asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max); | 2854 | asoc->rto_min = rto_min; |
2833 | if (rtoinfo.srto_min != 0) | ||
2834 | asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min); | ||
2835 | } else { | 2855 | } else { |
2836 | /* If there is no association or the association-id = 0 | 2856 | /* If there is no association or the association-id = 0 |
2837 | * set the values to the endpoint. | 2857 | * set the values to the endpoint. |
2838 | */ | 2858 | */ |
2839 | struct sctp_sock *sp = sctp_sk(sk); | ||
2840 | |||
2841 | if (rtoinfo.srto_initial != 0) | 2859 | if (rtoinfo.srto_initial != 0) |
2842 | sp->rtoinfo.srto_initial = rtoinfo.srto_initial; | 2860 | sp->rtoinfo.srto_initial = rtoinfo.srto_initial; |
2843 | if (rtoinfo.srto_max != 0) | 2861 | sp->rtoinfo.srto_max = rto_max; |
2844 | sp->rtoinfo.srto_max = rtoinfo.srto_max; | 2862 | sp->rtoinfo.srto_min = rto_min; |
2845 | if (rtoinfo.srto_min != 0) | ||
2846 | sp->rtoinfo.srto_min = rtoinfo.srto_min; | ||
2847 | } | 2863 | } |
2848 | 2864 | ||
2849 | return 0; | 2865 | return 0; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 6b36561a1b3b..b0565afb61c7 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -56,11 +56,16 @@ extern long sysctl_sctp_mem[3]; | |||
56 | extern int sysctl_sctp_rmem[3]; | 56 | extern int sysctl_sctp_rmem[3]; |
57 | extern int sysctl_sctp_wmem[3]; | 57 | extern int sysctl_sctp_wmem[3]; |
58 | 58 | ||
59 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | 59 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, |
60 | int write, | 60 | void __user *buffer, size_t *lenp, |
61 | loff_t *ppos); | ||
62 | static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, | ||
63 | void __user *buffer, size_t *lenp, | ||
64 | loff_t *ppos); | ||
65 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | ||
61 | void __user *buffer, size_t *lenp, | 66 | void __user *buffer, size_t *lenp, |
62 | |||
63 | loff_t *ppos); | 67 | loff_t *ppos); |
68 | |||
64 | static struct ctl_table sctp_table[] = { | 69 | static struct ctl_table sctp_table[] = { |
65 | { | 70 | { |
66 | .procname = "sctp_mem", | 71 | .procname = "sctp_mem", |
@@ -102,17 +107,17 @@ static struct ctl_table sctp_net_table[] = { | |||
102 | .data = &init_net.sctp.rto_min, | 107 | .data = &init_net.sctp.rto_min, |
103 | .maxlen = sizeof(unsigned int), | 108 | .maxlen = sizeof(unsigned int), |
104 | .mode = 0644, | 109 | .mode = 0644, |
105 | .proc_handler = proc_dointvec_minmax, | 110 | .proc_handler = proc_sctp_do_rto_min, |
106 | .extra1 = &one, | 111 | .extra1 = &one, |
107 | .extra2 = &timer_max | 112 | .extra2 = &init_net.sctp.rto_max |
108 | }, | 113 | }, |
109 | { | 114 | { |
110 | .procname = "rto_max", | 115 | .procname = "rto_max", |
111 | .data = &init_net.sctp.rto_max, | 116 | .data = &init_net.sctp.rto_max, |
112 | .maxlen = sizeof(unsigned int), | 117 | .maxlen = sizeof(unsigned int), |
113 | .mode = 0644, | 118 | .mode = 0644, |
114 | .proc_handler = proc_dointvec_minmax, | 119 | .proc_handler = proc_sctp_do_rto_max, |
115 | .extra1 = &one, | 120 | .extra1 = &init_net.sctp.rto_min, |
116 | .extra2 = &timer_max | 121 | .extra2 = &timer_max |
117 | }, | 122 | }, |
118 | { | 123 | { |
@@ -294,8 +299,7 @@ static struct ctl_table sctp_net_table[] = { | |||
294 | { /* sentinel */ } | 299 | { /* sentinel */ } |
295 | }; | 300 | }; |
296 | 301 | ||
297 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | 302 | static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, |
298 | int write, | ||
299 | void __user *buffer, size_t *lenp, | 303 | void __user *buffer, size_t *lenp, |
300 | loff_t *ppos) | 304 | loff_t *ppos) |
301 | { | 305 | { |
@@ -342,6 +346,60 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, | |||
342 | return ret; | 346 | return ret; |
343 | } | 347 | } |
344 | 348 | ||
349 | static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, | ||
350 | void __user *buffer, size_t *lenp, | ||
351 | loff_t *ppos) | ||
352 | { | ||
353 | struct net *net = current->nsproxy->net_ns; | ||
354 | int new_value; | ||
355 | struct ctl_table tbl; | ||
356 | unsigned int min = *(unsigned int *) ctl->extra1; | ||
357 | unsigned int max = *(unsigned int *) ctl->extra2; | ||
358 | int ret; | ||
359 | |||
360 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
361 | tbl.maxlen = sizeof(unsigned int); | ||
362 | |||
363 | if (write) | ||
364 | tbl.data = &new_value; | ||
365 | else | ||
366 | tbl.data = &net->sctp.rto_min; | ||
367 | ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); | ||
368 | if (write) { | ||
369 | if (ret || new_value > max || new_value < min) | ||
370 | return -EINVAL; | ||
371 | net->sctp.rto_min = new_value; | ||
372 | } | ||
373 | return ret; | ||
374 | } | ||
375 | |||
376 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | ||
377 | void __user *buffer, size_t *lenp, | ||
378 | loff_t *ppos) | ||
379 | { | ||
380 | struct net *net = current->nsproxy->net_ns; | ||
381 | int new_value; | ||
382 | struct ctl_table tbl; | ||
383 | unsigned int min = *(unsigned int *) ctl->extra1; | ||
384 | unsigned int max = *(unsigned int *) ctl->extra2; | ||
385 | int ret; | ||
386 | |||
387 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
388 | tbl.maxlen = sizeof(unsigned int); | ||
389 | |||
390 | if (write) | ||
391 | tbl.data = &new_value; | ||
392 | else | ||
393 | tbl.data = &net->sctp.rto_max; | ||
394 | ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); | ||
395 | if (write) { | ||
396 | if (ret || new_value > max || new_value < min) | ||
397 | return -EINVAL; | ||
398 | net->sctp.rto_max = new_value; | ||
399 | } | ||
400 | return ret; | ||
401 | } | ||
402 | |||
345 | int sctp_sysctl_net_register(struct net *net) | 403 | int sctp_sysctl_net_register(struct net *net) |
346 | { | 404 | { |
347 | struct ctl_table *table; | 405 | struct ctl_table *table; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index e332efb124cc..efc46ffed1fd 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -573,7 +573,7 @@ void sctp_transport_burst_limited(struct sctp_transport *t) | |||
573 | u32 old_cwnd = t->cwnd; | 573 | u32 old_cwnd = t->cwnd; |
574 | u32 max_burst_bytes; | 574 | u32 max_burst_bytes; |
575 | 575 | ||
576 | if (t->burst_limited) | 576 | if (t->burst_limited || asoc->max_burst == 0) |
577 | return; | 577 | return; |
578 | 578 | ||
579 | max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu); | 579 | max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu); |