diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 3 | ||||
-rw-r--r-- | net/sctp/proc.c | 141 | ||||
-rw-r--r-- | net/sctp/protocol.c | 3 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 17 | ||||
-rw-r--r-- | net/sctp/socket.c | 306 |
5 files changed, 369 insertions, 101 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 532634861db1..d5cc731b6798 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -136,6 +136,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
136 | 136 | ||
137 | /* Set association default SACK delay */ | 137 | /* Set association default SACK delay */ |
138 | asoc->sackdelay = msecs_to_jiffies(sp->sackdelay); | 138 | asoc->sackdelay = msecs_to_jiffies(sp->sackdelay); |
139 | asoc->sackfreq = sp->sackfreq; | ||
139 | 140 | ||
140 | /* Set the association default flags controlling | 141 | /* Set the association default flags controlling |
141 | * Heartbeat, SACK delay, and Path MTU Discovery. | 142 | * Heartbeat, SACK delay, and Path MTU Discovery. |
@@ -261,6 +262,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
261 | * already received one packet.] | 262 | * already received one packet.] |
262 | */ | 263 | */ |
263 | asoc->peer.sack_needed = 1; | 264 | asoc->peer.sack_needed = 1; |
265 | asoc->peer.sack_cnt = 0; | ||
264 | 266 | ||
265 | /* Assume that the peer will tell us if he recognizes ASCONF | 267 | /* Assume that the peer will tell us if he recognizes ASCONF |
266 | * as part of INIT exchange. | 268 | * as part of INIT exchange. |
@@ -615,6 +617,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
615 | * association configured value. | 617 | * association configured value. |
616 | */ | 618 | */ |
617 | peer->sackdelay = asoc->sackdelay; | 619 | peer->sackdelay = asoc->sackdelay; |
620 | peer->sackfreq = asoc->sackfreq; | ||
618 | 621 | ||
619 | /* Enable/disable heartbeat, SACK delay, and path MTU discovery | 622 | /* Enable/disable heartbeat, SACK delay, and path MTU discovery |
620 | * based on association setting. | 623 | * based on association setting. |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 0aba759cb9b7..5dd89831eceb 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -383,3 +383,144 @@ void sctp_assocs_proc_exit(void) | |||
383 | { | 383 | { |
384 | remove_proc_entry("assocs", proc_net_sctp); | 384 | remove_proc_entry("assocs", proc_net_sctp); |
385 | } | 385 | } |
386 | |||
387 | static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) | ||
388 | { | ||
389 | if (*pos >= sctp_assoc_hashsize) | ||
390 | return NULL; | ||
391 | |||
392 | if (*pos < 0) | ||
393 | *pos = 0; | ||
394 | |||
395 | if (*pos == 0) | ||
396 | seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " | ||
397 | "REM_ADDR_RTX START\n"); | ||
398 | |||
399 | return (void *)pos; | ||
400 | } | ||
401 | |||
402 | static void *sctp_remaddr_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
403 | { | ||
404 | if (++*pos >= sctp_assoc_hashsize) | ||
405 | return NULL; | ||
406 | |||
407 | return pos; | ||
408 | } | ||
409 | |||
410 | static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v) | ||
411 | { | ||
412 | return; | ||
413 | } | ||
414 | |||
415 | static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) | ||
416 | { | ||
417 | struct sctp_hashbucket *head; | ||
418 | struct sctp_ep_common *epb; | ||
419 | struct sctp_association *assoc; | ||
420 | struct hlist_node *node; | ||
421 | struct sctp_transport *tsp; | ||
422 | int hash = *(loff_t *)v; | ||
423 | |||
424 | if (hash >= sctp_assoc_hashsize) | ||
425 | return -ENOMEM; | ||
426 | |||
427 | head = &sctp_assoc_hashtable[hash]; | ||
428 | sctp_local_bh_disable(); | ||
429 | read_lock(&head->lock); | ||
430 | sctp_for_each_hentry(epb, node, &head->chain) { | ||
431 | assoc = sctp_assoc(epb); | ||
432 | list_for_each_entry(tsp, &assoc->peer.transport_addr_list, | ||
433 | transports) { | ||
434 | /* | ||
435 | * The remote address (ADDR) | ||
436 | */ | ||
437 | tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr); | ||
438 | seq_printf(seq, " "); | ||
439 | |||
440 | /* | ||
441 | * The association ID (ASSOC_ID) | ||
442 | */ | ||
443 | seq_printf(seq, "%d ", tsp->asoc->assoc_id); | ||
444 | |||
445 | /* | ||
446 | * If the Heartbeat is active (HB_ACT) | ||
447 | * Note: 1 = Active, 0 = Inactive | ||
448 | */ | ||
449 | seq_printf(seq, "%d ", timer_pending(&tsp->hb_timer)); | ||
450 | |||
451 | /* | ||
452 | * Retransmit time out (RTO) | ||
453 | */ | ||
454 | seq_printf(seq, "%lu ", tsp->rto); | ||
455 | |||
456 | /* | ||
457 | * Maximum path retransmit count (PATH_MAX_RTX) | ||
458 | */ | ||
459 | seq_printf(seq, "%d ", tsp->pathmaxrxt); | ||
460 | |||
461 | /* | ||
462 | * remote address retransmit count (REM_ADDR_RTX) | ||
463 | * Note: We don't have a way to tally this at the moment | ||
464 | * so lets just leave it as zero for the moment | ||
465 | */ | ||
466 | seq_printf(seq, "0 "); | ||
467 | |||
468 | /* | ||
469 | * remote address start time (START). This is also not | ||
470 | * currently implemented, but we can record it with a | ||
471 | * jiffies marker in a subsequent patch | ||
472 | */ | ||
473 | seq_printf(seq, "0"); | ||
474 | |||
475 | seq_printf(seq, "\n"); | ||
476 | } | ||
477 | } | ||
478 | |||
479 | read_unlock(&head->lock); | ||
480 | sctp_local_bh_enable(); | ||
481 | |||
482 | return 0; | ||
483 | |||
484 | } | ||
485 | |||
486 | static const struct seq_operations sctp_remaddr_ops = { | ||
487 | .start = sctp_remaddr_seq_start, | ||
488 | .next = sctp_remaddr_seq_next, | ||
489 | .stop = sctp_remaddr_seq_stop, | ||
490 | .show = sctp_remaddr_seq_show, | ||
491 | }; | ||
492 | |||
493 | /* Cleanup the proc fs entry for 'remaddr' object. */ | ||
494 | void sctp_remaddr_proc_exit(void) | ||
495 | { | ||
496 | remove_proc_entry("remaddr", proc_net_sctp); | ||
497 | } | ||
498 | |||
499 | static int sctp_remaddr_seq_open(struct inode *inode, struct file *file) | ||
500 | { | ||
501 | return seq_open(file, &sctp_remaddr_ops); | ||
502 | } | ||
503 | |||
504 | static const struct file_operations sctp_remaddr_seq_fops = { | ||
505 | .open = sctp_remaddr_seq_open, | ||
506 | .read = seq_read, | ||
507 | .llseek = seq_lseek, | ||
508 | .release = seq_release, | ||
509 | }; | ||
510 | |||
511 | int __init sctp_remaddr_proc_init(void) | ||
512 | { | ||
513 | struct proc_dir_entry *p; | ||
514 | |||
515 | p = create_proc_entry("remaddr", S_IRUGO, proc_net_sctp); | ||
516 | if (!p) | ||
517 | return -ENOMEM; | ||
518 | p->proc_fops = &sctp_remaddr_seq_fops; | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | void sctp_assoc_proc_exit(void) | ||
524 | { | ||
525 | remove_proc_entry("remaddr", proc_net_sctp); | ||
526 | } | ||
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index b435a193c5df..d6af466091d2 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -113,6 +113,8 @@ static __init int sctp_proc_init(void) | |||
113 | goto out_nomem; | 113 | goto out_nomem; |
114 | if (sctp_assocs_proc_init()) | 114 | if (sctp_assocs_proc_init()) |
115 | goto out_nomem; | 115 | goto out_nomem; |
116 | if (sctp_remaddr_proc_init()) | ||
117 | goto out_nomem; | ||
116 | 118 | ||
117 | return 0; | 119 | return 0; |
118 | 120 | ||
@@ -129,6 +131,7 @@ static void sctp_proc_exit(void) | |||
129 | sctp_snmp_proc_exit(); | 131 | sctp_snmp_proc_exit(); |
130 | sctp_eps_proc_exit(); | 132 | sctp_eps_proc_exit(); |
131 | sctp_assocs_proc_exit(); | 133 | sctp_assocs_proc_exit(); |
134 | sctp_remaddr_proc_exit(); | ||
132 | 135 | ||
133 | if (proc_net_sctp) { | 136 | if (proc_net_sctp) { |
134 | proc_net_sctp = NULL; | 137 | proc_net_sctp = NULL; |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 23a9f1a95b7d..b083312c725a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -190,20 +190,28 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force, | |||
190 | * unacknowledged DATA chunk. ... | 190 | * unacknowledged DATA chunk. ... |
191 | */ | 191 | */ |
192 | if (!asoc->peer.sack_needed) { | 192 | if (!asoc->peer.sack_needed) { |
193 | /* We will need a SACK for the next packet. */ | 193 | asoc->peer.sack_cnt++; |
194 | asoc->peer.sack_needed = 1; | ||
195 | 194 | ||
196 | /* Set the SACK delay timeout based on the | 195 | /* Set the SACK delay timeout based on the |
197 | * SACK delay for the last transport | 196 | * SACK delay for the last transport |
198 | * data was received from, or the default | 197 | * data was received from, or the default |
199 | * for the association. | 198 | * for the association. |
200 | */ | 199 | */ |
201 | if (trans) | 200 | if (trans) { |
201 | /* We will need a SACK for the next packet. */ | ||
202 | if (asoc->peer.sack_cnt >= trans->sackfreq - 1) | ||
203 | asoc->peer.sack_needed = 1; | ||
204 | |||
202 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = | 205 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = |
203 | trans->sackdelay; | 206 | trans->sackdelay; |
204 | else | 207 | } else { |
208 | /* We will need a SACK for the next packet. */ | ||
209 | if (asoc->peer.sack_cnt >= asoc->sackfreq - 1) | ||
210 | asoc->peer.sack_needed = 1; | ||
211 | |||
205 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = | 212 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = |
206 | asoc->sackdelay; | 213 | asoc->sackdelay; |
214 | } | ||
207 | 215 | ||
208 | /* Restart the SACK timer. */ | 216 | /* Restart the SACK timer. */ |
209 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 217 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
@@ -216,6 +224,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force, | |||
216 | goto nomem; | 224 | goto nomem; |
217 | 225 | ||
218 | asoc->peer.sack_needed = 0; | 226 | asoc->peer.sack_needed = 0; |
227 | asoc->peer.sack_cnt = 0; | ||
219 | 228 | ||
220 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack)); | 229 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack)); |
221 | 230 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e7e3baf7009e..253e5ea7e1e8 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -956,7 +956,8 @@ out: | |||
956 | */ | 956 | */ |
957 | static int __sctp_connect(struct sock* sk, | 957 | static int __sctp_connect(struct sock* sk, |
958 | struct sockaddr *kaddrs, | 958 | struct sockaddr *kaddrs, |
959 | int addrs_size) | 959 | int addrs_size, |
960 | sctp_assoc_t *assoc_id) | ||
960 | { | 961 | { |
961 | struct sctp_sock *sp; | 962 | struct sctp_sock *sp; |
962 | struct sctp_endpoint *ep; | 963 | struct sctp_endpoint *ep; |
@@ -1111,6 +1112,8 @@ static int __sctp_connect(struct sock* sk, | |||
1111 | timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); | 1112 | timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); |
1112 | 1113 | ||
1113 | err = sctp_wait_for_connect(asoc, &timeo); | 1114 | err = sctp_wait_for_connect(asoc, &timeo); |
1115 | if (!err && assoc_id) | ||
1116 | *assoc_id = asoc->assoc_id; | ||
1114 | 1117 | ||
1115 | /* Don't free association on exit. */ | 1118 | /* Don't free association on exit. */ |
1116 | asoc = NULL; | 1119 | asoc = NULL; |
@@ -1128,7 +1131,8 @@ out_free: | |||
1128 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() | 1131 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() |
1129 | * | 1132 | * |
1130 | * API 8.9 | 1133 | * API 8.9 |
1131 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt); | 1134 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt, |
1135 | * sctp_assoc_t *asoc); | ||
1132 | * | 1136 | * |
1133 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. | 1137 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. |
1134 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 | 1138 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 |
@@ -1144,8 +1148,10 @@ out_free: | |||
1144 | * representation is termed a "packed array" of addresses). The caller | 1148 | * representation is termed a "packed array" of addresses). The caller |
1145 | * specifies the number of addresses in the array with addrcnt. | 1149 | * specifies the number of addresses in the array with addrcnt. |
1146 | * | 1150 | * |
1147 | * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns | 1151 | * On success, sctp_connectx() returns 0. It also sets the assoc_id to |
1148 | * -1, and sets errno to the appropriate error code. | 1152 | * the association id of the new association. On failure, sctp_connectx() |
1153 | * returns -1, and sets errno to the appropriate error code. The assoc_id | ||
1154 | * is not touched by the kernel. | ||
1149 | * | 1155 | * |
1150 | * For SCTP, the port given in each socket address must be the same, or | 1156 | * For SCTP, the port given in each socket address must be the same, or |
1151 | * sctp_connectx() will fail, setting errno to EINVAL. | 1157 | * sctp_connectx() will fail, setting errno to EINVAL. |
@@ -1182,11 +1188,12 @@ out_free: | |||
1182 | * addrs The pointer to the addresses in user land | 1188 | * addrs The pointer to the addresses in user land |
1183 | * addrssize Size of the addrs buffer | 1189 | * addrssize Size of the addrs buffer |
1184 | * | 1190 | * |
1185 | * Returns 0 if ok, <0 errno code on error. | 1191 | * Returns >=0 if ok, <0 errno code on error. |
1186 | */ | 1192 | */ |
1187 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | 1193 | SCTP_STATIC int __sctp_setsockopt_connectx(struct sock* sk, |
1188 | struct sockaddr __user *addrs, | 1194 | struct sockaddr __user *addrs, |
1189 | int addrs_size) | 1195 | int addrs_size, |
1196 | sctp_assoc_t *assoc_id) | ||
1190 | { | 1197 | { |
1191 | int err = 0; | 1198 | int err = 0; |
1192 | struct sockaddr *kaddrs; | 1199 | struct sockaddr *kaddrs; |
@@ -1209,13 +1216,46 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | |||
1209 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | 1216 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { |
1210 | err = -EFAULT; | 1217 | err = -EFAULT; |
1211 | } else { | 1218 | } else { |
1212 | err = __sctp_connect(sk, kaddrs, addrs_size); | 1219 | err = __sctp_connect(sk, kaddrs, addrs_size, assoc_id); |
1213 | } | 1220 | } |
1214 | 1221 | ||
1215 | kfree(kaddrs); | 1222 | kfree(kaddrs); |
1223 | |||
1216 | return err; | 1224 | return err; |
1217 | } | 1225 | } |
1218 | 1226 | ||
1227 | /* | ||
1228 | * This is an older interface. It's kept for backward compatibility | ||
1229 | * to the option that doesn't provide association id. | ||
1230 | */ | ||
1231 | SCTP_STATIC int sctp_setsockopt_connectx_old(struct sock* sk, | ||
1232 | struct sockaddr __user *addrs, | ||
1233 | int addrs_size) | ||
1234 | { | ||
1235 | return __sctp_setsockopt_connectx(sk, addrs, addrs_size, NULL); | ||
1236 | } | ||
1237 | |||
1238 | /* | ||
1239 | * New interface for the API. The since the API is done with a socket | ||
1240 | * option, to make it simple we feed back the association id is as a return | ||
1241 | * indication to the call. Error is always negative and association id is | ||
1242 | * always positive. | ||
1243 | */ | ||
1244 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | ||
1245 | struct sockaddr __user *addrs, | ||
1246 | int addrs_size) | ||
1247 | { | ||
1248 | sctp_assoc_t assoc_id = 0; | ||
1249 | int err = 0; | ||
1250 | |||
1251 | err = __sctp_setsockopt_connectx(sk, addrs, addrs_size, &assoc_id); | ||
1252 | |||
1253 | if (err) | ||
1254 | return err; | ||
1255 | else | ||
1256 | return assoc_id; | ||
1257 | } | ||
1258 | |||
1219 | /* API 3.1.4 close() - UDP Style Syntax | 1259 | /* API 3.1.4 close() - UDP Style Syntax |
1220 | * Applications use close() to perform graceful shutdown (as described in | 1260 | * Applications use close() to perform graceful shutdown (as described in |
1221 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1261 | * Section 10.1 of [SCTP]) on ALL the associations currently represented |
@@ -2305,74 +2345,98 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
2305 | return 0; | 2345 | return 0; |
2306 | } | 2346 | } |
2307 | 2347 | ||
2308 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 2348 | /* |
2309 | * | 2349 | * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK) |
2310 | * This options will get or set the delayed ack timer. The time is set | 2350 | * |
2311 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 2351 | * This option will effect the way delayed acks are performed. This |
2312 | * endpoints default delayed ack timer value. If the assoc_id field is | 2352 | * option allows you to get or set the delayed ack time, in |
2313 | * non-zero, then the set or get effects the specified association. | 2353 | * milliseconds. It also allows changing the delayed ack frequency. |
2314 | * | 2354 | * Changing the frequency to 1 disables the delayed sack algorithm. If |
2315 | * struct sctp_assoc_value { | 2355 | * the assoc_id is 0, then this sets or gets the endpoints default |
2316 | * sctp_assoc_t assoc_id; | 2356 | * values. If the assoc_id field is non-zero, then the set or get |
2317 | * uint32_t assoc_value; | 2357 | * effects the specified association for the one to many model (the |
2318 | * }; | 2358 | * assoc_id field is ignored by the one to one model). Note that if |
2359 | * sack_delay or sack_freq are 0 when setting this option, then the | ||
2360 | * current values will remain unchanged. | ||
2361 | * | ||
2362 | * struct sctp_sack_info { | ||
2363 | * sctp_assoc_t sack_assoc_id; | ||
2364 | * uint32_t sack_delay; | ||
2365 | * uint32_t sack_freq; | ||
2366 | * }; | ||
2319 | * | 2367 | * |
2320 | * assoc_id - This parameter, indicates which association the | 2368 | * sack_assoc_id - This parameter, indicates which association the user |
2321 | * user is preforming an action upon. Note that if | 2369 | * is performing an action upon. Note that if this field's value is |
2322 | * this field's value is zero then the endpoints | 2370 | * zero then the endpoints default value is changed (effecting future |
2323 | * default value is changed (effecting future | 2371 | * associations only). |
2324 | * associations only). | ||
2325 | * | 2372 | * |
2326 | * assoc_value - This parameter contains the number of milliseconds | 2373 | * sack_delay - This parameter contains the number of milliseconds that |
2327 | * that the user is requesting the delayed ACK timer | 2374 | * the user is requesting the delayed ACK timer be set to. Note that |
2328 | * be set to. Note that this value is defined in | 2375 | * this value is defined in the standard to be between 200 and 500 |
2329 | * the standard to be between 200 and 500 milliseconds. | 2376 | * milliseconds. |
2330 | * | 2377 | * |
2331 | * Note: a value of zero will leave the value alone, | 2378 | * sack_freq - This parameter contains the number of packets that must |
2332 | * but disable SACK delay. A non-zero value will also | 2379 | * be received before a sack is sent without waiting for the delay |
2333 | * enable SACK delay. | 2380 | * timer to expire. The default value for this is 2, setting this |
2381 | * value to 1 will disable the delayed sack algorithm. | ||
2334 | */ | 2382 | */ |
2335 | 2383 | ||
2336 | static int sctp_setsockopt_delayed_ack_time(struct sock *sk, | 2384 | static int sctp_setsockopt_delayed_ack(struct sock *sk, |
2337 | char __user *optval, int optlen) | 2385 | char __user *optval, int optlen) |
2338 | { | 2386 | { |
2339 | struct sctp_assoc_value params; | 2387 | struct sctp_sack_info params; |
2340 | struct sctp_transport *trans = NULL; | 2388 | struct sctp_transport *trans = NULL; |
2341 | struct sctp_association *asoc = NULL; | 2389 | struct sctp_association *asoc = NULL; |
2342 | struct sctp_sock *sp = sctp_sk(sk); | 2390 | struct sctp_sock *sp = sctp_sk(sk); |
2343 | 2391 | ||
2344 | if (optlen != sizeof(struct sctp_assoc_value)) | 2392 | if (optlen == sizeof(struct sctp_sack_info)) { |
2345 | return - EINVAL; | 2393 | if (copy_from_user(¶ms, optval, optlen)) |
2394 | return -EFAULT; | ||
2346 | 2395 | ||
2347 | if (copy_from_user(¶ms, optval, optlen)) | 2396 | if (params.sack_delay == 0 && params.sack_freq == 0) |
2348 | return -EFAULT; | 2397 | return 0; |
2398 | } else if (optlen == sizeof(struct sctp_assoc_value)) { | ||
2399 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | ||
2400 | "in delayed_ack socket option deprecated\n"); | ||
2401 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | ||
2402 | if (copy_from_user(¶ms, optval, optlen)) | ||
2403 | return -EFAULT; | ||
2404 | |||
2405 | if (params.sack_delay == 0) | ||
2406 | params.sack_freq = 1; | ||
2407 | else | ||
2408 | params.sack_freq = 0; | ||
2409 | } else | ||
2410 | return - EINVAL; | ||
2349 | 2411 | ||
2350 | /* Validate value parameter. */ | 2412 | /* Validate value parameter. */ |
2351 | if (params.assoc_value > 500) | 2413 | if (params.sack_delay > 500) |
2352 | return -EINVAL; | 2414 | return -EINVAL; |
2353 | 2415 | ||
2354 | /* Get association, if assoc_id != 0 and the socket is a one | 2416 | /* Get association, if sack_assoc_id != 0 and the socket is a one |
2355 | * to many style socket, and an association was not found, then | 2417 | * to many style socket, and an association was not found, then |
2356 | * the id was invalid. | 2418 | * the id was invalid. |
2357 | */ | 2419 | */ |
2358 | asoc = sctp_id2assoc(sk, params.assoc_id); | 2420 | asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
2359 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | 2421 | if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
2360 | return -EINVAL; | 2422 | return -EINVAL; |
2361 | 2423 | ||
2362 | if (params.assoc_value) { | 2424 | if (params.sack_delay) { |
2363 | if (asoc) { | 2425 | if (asoc) { |
2364 | asoc->sackdelay = | 2426 | asoc->sackdelay = |
2365 | msecs_to_jiffies(params.assoc_value); | 2427 | msecs_to_jiffies(params.sack_delay); |
2366 | asoc->param_flags = | 2428 | asoc->param_flags = |
2367 | (asoc->param_flags & ~SPP_SACKDELAY) | | 2429 | (asoc->param_flags & ~SPP_SACKDELAY) | |
2368 | SPP_SACKDELAY_ENABLE; | 2430 | SPP_SACKDELAY_ENABLE; |
2369 | } else { | 2431 | } else { |
2370 | sp->sackdelay = params.assoc_value; | 2432 | sp->sackdelay = params.sack_delay; |
2371 | sp->param_flags = | 2433 | sp->param_flags = |
2372 | (sp->param_flags & ~SPP_SACKDELAY) | | 2434 | (sp->param_flags & ~SPP_SACKDELAY) | |
2373 | SPP_SACKDELAY_ENABLE; | 2435 | SPP_SACKDELAY_ENABLE; |
2374 | } | 2436 | } |
2375 | } else { | 2437 | } |
2438 | |||
2439 | if (params.sack_freq == 1) { | ||
2376 | if (asoc) { | 2440 | if (asoc) { |
2377 | asoc->param_flags = | 2441 | asoc->param_flags = |
2378 | (asoc->param_flags & ~SPP_SACKDELAY) | | 2442 | (asoc->param_flags & ~SPP_SACKDELAY) | |
@@ -2382,22 +2446,40 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk, | |||
2382 | (sp->param_flags & ~SPP_SACKDELAY) | | 2446 | (sp->param_flags & ~SPP_SACKDELAY) | |
2383 | SPP_SACKDELAY_DISABLE; | 2447 | SPP_SACKDELAY_DISABLE; |
2384 | } | 2448 | } |
2449 | } else if (params.sack_freq > 1) { | ||
2450 | if (asoc) { | ||
2451 | asoc->sackfreq = params.sack_freq; | ||
2452 | asoc->param_flags = | ||
2453 | (asoc->param_flags & ~SPP_SACKDELAY) | | ||
2454 | SPP_SACKDELAY_ENABLE; | ||
2455 | } else { | ||
2456 | sp->sackfreq = params.sack_freq; | ||
2457 | sp->param_flags = | ||
2458 | (sp->param_flags & ~SPP_SACKDELAY) | | ||
2459 | SPP_SACKDELAY_ENABLE; | ||
2460 | } | ||
2385 | } | 2461 | } |
2386 | 2462 | ||
2387 | /* If change is for association, also apply to each transport. */ | 2463 | /* If change is for association, also apply to each transport. */ |
2388 | if (asoc) { | 2464 | if (asoc) { |
2389 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, | 2465 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, |
2390 | transports) { | 2466 | transports) { |
2391 | if (params.assoc_value) { | 2467 | if (params.sack_delay) { |
2392 | trans->sackdelay = | 2468 | trans->sackdelay = |
2393 | msecs_to_jiffies(params.assoc_value); | 2469 | msecs_to_jiffies(params.sack_delay); |
2394 | trans->param_flags = | 2470 | trans->param_flags = |
2395 | (trans->param_flags & ~SPP_SACKDELAY) | | 2471 | (trans->param_flags & ~SPP_SACKDELAY) | |
2396 | SPP_SACKDELAY_ENABLE; | 2472 | SPP_SACKDELAY_ENABLE; |
2397 | } else { | 2473 | } |
2474 | if (params.sack_freq == 1) { | ||
2398 | trans->param_flags = | 2475 | trans->param_flags = |
2399 | (trans->param_flags & ~SPP_SACKDELAY) | | 2476 | (trans->param_flags & ~SPP_SACKDELAY) | |
2400 | SPP_SACKDELAY_DISABLE; | 2477 | SPP_SACKDELAY_DISABLE; |
2478 | } else if (params.sack_freq > 1) { | ||
2479 | trans->sackfreq = params.sack_freq; | ||
2480 | trans->param_flags = | ||
2481 | (trans->param_flags & ~SPP_SACKDELAY) | | ||
2482 | SPP_SACKDELAY_ENABLE; | ||
2401 | } | 2483 | } |
2402 | } | 2484 | } |
2403 | } | 2485 | } |
@@ -3164,10 +3246,18 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3164 | optlen, SCTP_BINDX_REM_ADDR); | 3246 | optlen, SCTP_BINDX_REM_ADDR); |
3165 | break; | 3247 | break; |
3166 | 3248 | ||
3249 | case SCTP_SOCKOPT_CONNECTX_OLD: | ||
3250 | /* 'optlen' is the size of the addresses buffer. */ | ||
3251 | retval = sctp_setsockopt_connectx_old(sk, | ||
3252 | (struct sockaddr __user *)optval, | ||
3253 | optlen); | ||
3254 | break; | ||
3255 | |||
3167 | case SCTP_SOCKOPT_CONNECTX: | 3256 | case SCTP_SOCKOPT_CONNECTX: |
3168 | /* 'optlen' is the size of the addresses buffer. */ | 3257 | /* 'optlen' is the size of the addresses buffer. */ |
3169 | retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval, | 3258 | retval = sctp_setsockopt_connectx(sk, |
3170 | optlen); | 3259 | (struct sockaddr __user *)optval, |
3260 | optlen); | ||
3171 | break; | 3261 | break; |
3172 | 3262 | ||
3173 | case SCTP_DISABLE_FRAGMENTS: | 3263 | case SCTP_DISABLE_FRAGMENTS: |
@@ -3186,8 +3276,8 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3186 | retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); | 3276 | retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); |
3187 | break; | 3277 | break; |
3188 | 3278 | ||
3189 | case SCTP_DELAYED_ACK_TIME: | 3279 | case SCTP_DELAYED_ACK: |
3190 | retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen); | 3280 | retval = sctp_setsockopt_delayed_ack(sk, optval, optlen); |
3191 | break; | 3281 | break; |
3192 | case SCTP_PARTIAL_DELIVERY_POINT: | 3282 | case SCTP_PARTIAL_DELIVERY_POINT: |
3193 | retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); | 3283 | retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); |
@@ -3294,7 +3384,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, | |||
3294 | /* Pass correct addr len to common routine (so it knows there | 3384 | /* Pass correct addr len to common routine (so it knows there |
3295 | * is only one address being passed. | 3385 | * is only one address being passed. |
3296 | */ | 3386 | */ |
3297 | err = __sctp_connect(sk, addr, af->sockaddr_len); | 3387 | err = __sctp_connect(sk, addr, af->sockaddr_len, NULL); |
3298 | } | 3388 | } |
3299 | 3389 | ||
3300 | sctp_release_sock(sk); | 3390 | sctp_release_sock(sk); |
@@ -3446,6 +3536,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3446 | sp->pathmaxrxt = sctp_max_retrans_path; | 3536 | sp->pathmaxrxt = sctp_max_retrans_path; |
3447 | sp->pathmtu = 0; // allow default discovery | 3537 | sp->pathmtu = 0; // allow default discovery |
3448 | sp->sackdelay = sctp_sack_timeout; | 3538 | sp->sackdelay = sctp_sack_timeout; |
3539 | sp->sackfreq = 2; | ||
3449 | sp->param_flags = SPP_HB_ENABLE | | 3540 | sp->param_flags = SPP_HB_ENABLE | |
3450 | SPP_PMTUD_ENABLE | | 3541 | SPP_PMTUD_ENABLE | |
3451 | SPP_SACKDELAY_ENABLE; | 3542 | SPP_SACKDELAY_ENABLE; |
@@ -3999,70 +4090,91 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
3999 | return 0; | 4090 | return 0; |
4000 | } | 4091 | } |
4001 | 4092 | ||
4002 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 4093 | /* |
4003 | * | 4094 | * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK) |
4004 | * This options will get or set the delayed ack timer. The time is set | 4095 | * |
4005 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 4096 | * This option will effect the way delayed acks are performed. This |
4006 | * endpoints default delayed ack timer value. If the assoc_id field is | 4097 | * option allows you to get or set the delayed ack time, in |
4007 | * non-zero, then the set or get effects the specified association. | 4098 | * milliseconds. It also allows changing the delayed ack frequency. |
4008 | * | 4099 | * Changing the frequency to 1 disables the delayed sack algorithm. If |
4009 | * struct sctp_assoc_value { | 4100 | * the assoc_id is 0, then this sets or gets the endpoints default |
4010 | * sctp_assoc_t assoc_id; | 4101 | * values. If the assoc_id field is non-zero, then the set or get |
4011 | * uint32_t assoc_value; | 4102 | * effects the specified association for the one to many model (the |
4012 | * }; | 4103 | * assoc_id field is ignored by the one to one model). Note that if |
4104 | * sack_delay or sack_freq are 0 when setting this option, then the | ||
4105 | * current values will remain unchanged. | ||
4106 | * | ||
4107 | * struct sctp_sack_info { | ||
4108 | * sctp_assoc_t sack_assoc_id; | ||
4109 | * uint32_t sack_delay; | ||
4110 | * uint32_t sack_freq; | ||
4111 | * }; | ||
4013 | * | 4112 | * |
4014 | * assoc_id - This parameter, indicates which association the | 4113 | * sack_assoc_id - This parameter, indicates which association the user |
4015 | * user is preforming an action upon. Note that if | 4114 | * is performing an action upon. Note that if this field's value is |
4016 | * this field's value is zero then the endpoints | 4115 | * zero then the endpoints default value is changed (effecting future |
4017 | * default value is changed (effecting future | 4116 | * associations only). |
4018 | * associations only). | ||
4019 | * | 4117 | * |
4020 | * assoc_value - This parameter contains the number of milliseconds | 4118 | * sack_delay - This parameter contains the number of milliseconds that |
4021 | * that the user is requesting the delayed ACK timer | 4119 | * the user is requesting the delayed ACK timer be set to. Note that |
4022 | * be set to. Note that this value is defined in | 4120 | * this value is defined in the standard to be between 200 and 500 |
4023 | * the standard to be between 200 and 500 milliseconds. | 4121 | * milliseconds. |
4024 | * | 4122 | * |
4025 | * Note: a value of zero will leave the value alone, | 4123 | * sack_freq - This parameter contains the number of packets that must |
4026 | * but disable SACK delay. A non-zero value will also | 4124 | * be received before a sack is sent without waiting for the delay |
4027 | * enable SACK delay. | 4125 | * timer to expire. The default value for this is 2, setting this |
4126 | * value to 1 will disable the delayed sack algorithm. | ||
4028 | */ | 4127 | */ |
4029 | static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len, | 4128 | static int sctp_getsockopt_delayed_ack(struct sock *sk, int len, |
4030 | char __user *optval, | 4129 | char __user *optval, |
4031 | int __user *optlen) | 4130 | int __user *optlen) |
4032 | { | 4131 | { |
4033 | struct sctp_assoc_value params; | 4132 | struct sctp_sack_info params; |
4034 | struct sctp_association *asoc = NULL; | 4133 | struct sctp_association *asoc = NULL; |
4035 | struct sctp_sock *sp = sctp_sk(sk); | 4134 | struct sctp_sock *sp = sctp_sk(sk); |
4036 | 4135 | ||
4037 | if (len < sizeof(struct sctp_assoc_value)) | 4136 | if (len >= sizeof(struct sctp_sack_info)) { |
4038 | return - EINVAL; | 4137 | len = sizeof(struct sctp_sack_info); |
4039 | |||
4040 | len = sizeof(struct sctp_assoc_value); | ||
4041 | 4138 | ||
4042 | if (copy_from_user(¶ms, optval, len)) | 4139 | if (copy_from_user(¶ms, optval, len)) |
4043 | return -EFAULT; | 4140 | return -EFAULT; |
4141 | } else if (len == sizeof(struct sctp_assoc_value)) { | ||
4142 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | ||
4143 | "in delayed_ack socket option deprecated\n"); | ||
4144 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | ||
4145 | if (copy_from_user(¶ms, optval, len)) | ||
4146 | return -EFAULT; | ||
4147 | } else | ||
4148 | return - EINVAL; | ||
4044 | 4149 | ||
4045 | /* Get association, if assoc_id != 0 and the socket is a one | 4150 | /* Get association, if sack_assoc_id != 0 and the socket is a one |
4046 | * to many style socket, and an association was not found, then | 4151 | * to many style socket, and an association was not found, then |
4047 | * the id was invalid. | 4152 | * the id was invalid. |
4048 | */ | 4153 | */ |
4049 | asoc = sctp_id2assoc(sk, params.assoc_id); | 4154 | asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
4050 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | 4155 | if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
4051 | return -EINVAL; | 4156 | return -EINVAL; |
4052 | 4157 | ||
4053 | if (asoc) { | 4158 | if (asoc) { |
4054 | /* Fetch association values. */ | 4159 | /* Fetch association values. */ |
4055 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) | 4160 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) { |
4056 | params.assoc_value = jiffies_to_msecs( | 4161 | params.sack_delay = jiffies_to_msecs( |
4057 | asoc->sackdelay); | 4162 | asoc->sackdelay); |
4058 | else | 4163 | params.sack_freq = asoc->sackfreq; |
4059 | params.assoc_value = 0; | 4164 | |
4165 | } else { | ||
4166 | params.sack_delay = 0; | ||
4167 | params.sack_freq = 1; | ||
4168 | } | ||
4060 | } else { | 4169 | } else { |
4061 | /* Fetch socket values. */ | 4170 | /* Fetch socket values. */ |
4062 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) | 4171 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) { |
4063 | params.assoc_value = sp->sackdelay; | 4172 | params.sack_delay = sp->sackdelay; |
4064 | else | 4173 | params.sack_freq = sp->sackfreq; |
4065 | params.assoc_value = 0; | 4174 | } else { |
4175 | params.sack_delay = 0; | ||
4176 | params.sack_freq = 1; | ||
4177 | } | ||
4066 | } | 4178 | } |
4067 | 4179 | ||
4068 | if (copy_to_user(optval, ¶ms, len)) | 4180 | if (copy_to_user(optval, ¶ms, len)) |
@@ -5218,8 +5330,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5218 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, | 5330 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, |
5219 | optlen); | 5331 | optlen); |
5220 | break; | 5332 | break; |
5221 | case SCTP_DELAYED_ACK_TIME: | 5333 | case SCTP_DELAYED_ACK: |
5222 | retval = sctp_getsockopt_delayed_ack_time(sk, len, optval, | 5334 | retval = sctp_getsockopt_delayed_ack(sk, len, optval, |
5223 | optlen); | 5335 | optlen); |
5224 | break; | 5336 | break; |
5225 | case SCTP_INITMSG: | 5337 | case SCTP_INITMSG: |