diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 3 | ||||
-rw-r--r-- | net/sctp/input.c | 27 | ||||
-rw-r--r-- | net/sctp/output.c | 7 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 34 | ||||
-rw-r--r-- | net/sctp/proc.c | 141 | ||||
-rw-r--r-- | net/sctp/protocol.c | 5 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 44 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 16 | ||||
-rw-r--r-- | net/sctp/socket.c | 321 |
9 files changed, 461 insertions, 137 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 024c3ebd9661..35b6a023a6d0 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. |
@@ -624,6 +626,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
624 | * association configured value. | 626 | * association configured value. |
625 | */ | 627 | */ |
626 | peer->sackdelay = asoc->sackdelay; | 628 | peer->sackdelay = asoc->sackdelay; |
629 | peer->sackfreq = asoc->sackfreq; | ||
627 | 630 | ||
628 | /* Enable/disable heartbeat, SACK delay, and path MTU discovery | 631 | /* Enable/disable heartbeat, SACK delay, and path MTU discovery |
629 | * based on association setting. | 632 | * based on association setting. |
diff --git a/net/sctp/input.c b/net/sctp/input.c index ca6b022b1df2..d354a23972d4 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -430,6 +430,9 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
430 | struct sock *sk = NULL; | 430 | struct sock *sk = NULL; |
431 | struct sctp_association *asoc; | 431 | struct sctp_association *asoc; |
432 | struct sctp_transport *transport = NULL; | 432 | struct sctp_transport *transport = NULL; |
433 | struct sctp_init_chunk *chunkhdr; | ||
434 | __u32 vtag = ntohl(sctphdr->vtag); | ||
435 | int len = skb->len - ((void *)sctphdr - (void *)skb->data); | ||
433 | 436 | ||
434 | *app = NULL; *tpp = NULL; | 437 | *app = NULL; *tpp = NULL; |
435 | 438 | ||
@@ -451,8 +454,28 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
451 | 454 | ||
452 | sk = asoc->base.sk; | 455 | sk = asoc->base.sk; |
453 | 456 | ||
454 | if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) { | 457 | /* RFC 4960, Appendix C. ICMP Handling |
455 | ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); | 458 | * |
459 | * ICMP6) An implementation MUST validate that the Verification Tag | ||
460 | * contained in the ICMP message matches the Verification Tag of | ||
461 | * the peer. If the Verification Tag is not 0 and does NOT | ||
462 | * match, discard the ICMP message. If it is 0 and the ICMP | ||
463 | * message contains enough bytes to verify that the chunk type is | ||
464 | * an INIT chunk and that the Initiate Tag matches the tag of the | ||
465 | * peer, continue with ICMP7. If the ICMP message is too short | ||
466 | * or the chunk type or the Initiate Tag does not match, silently | ||
467 | * discard the packet. | ||
468 | */ | ||
469 | if (vtag == 0) { | ||
470 | chunkhdr = (struct sctp_init_chunk *)((void *)sctphdr | ||
471 | + sizeof(struct sctphdr)); | ||
472 | if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t) | ||
473 | + sizeof(__be32) || | ||
474 | chunkhdr->chunk_hdr.type != SCTP_CID_INIT || | ||
475 | ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) { | ||
476 | goto out; | ||
477 | } | ||
478 | } else if (vtag != asoc->c.peer_vtag) { | ||
456 | goto out; | 479 | goto out; |
457 | } | 480 | } |
458 | 481 | ||
diff --git a/net/sctp/output.c b/net/sctp/output.c index 6d45bae93b46..abcd00dc05eb 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -157,7 +157,8 @@ void sctp_packet_free(struct sctp_packet *packet) | |||
157 | * packet can be sent only after receiving the COOKIE_ACK. | 157 | * packet can be sent only after receiving the COOKIE_ACK. |
158 | */ | 158 | */ |
159 | sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, | 159 | sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, |
160 | struct sctp_chunk *chunk) | 160 | struct sctp_chunk *chunk, |
161 | int one_packet) | ||
161 | { | 162 | { |
162 | sctp_xmit_t retval; | 163 | sctp_xmit_t retval; |
163 | int error = 0; | 164 | int error = 0; |
@@ -175,7 +176,9 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, | |||
175 | /* If we have an empty packet, then we can NOT ever | 176 | /* If we have an empty packet, then we can NOT ever |
176 | * return PMTU_FULL. | 177 | * return PMTU_FULL. |
177 | */ | 178 | */ |
178 | retval = sctp_packet_append_chunk(packet, chunk); | 179 | if (!one_packet) |
180 | retval = sctp_packet_append_chunk(packet, | ||
181 | chunk); | ||
179 | } | 182 | } |
180 | break; | 183 | break; |
181 | 184 | ||
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index ace6770e9048..70ead8dc3485 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -702,6 +702,7 @@ int sctp_outq_uncork(struct sctp_outq *q) | |||
702 | return error; | 702 | return error; |
703 | } | 703 | } |
704 | 704 | ||
705 | |||
705 | /* | 706 | /* |
706 | * Try to flush an outqueue. | 707 | * Try to flush an outqueue. |
707 | * | 708 | * |
@@ -725,6 +726,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
725 | sctp_xmit_t status; | 726 | sctp_xmit_t status; |
726 | int error = 0; | 727 | int error = 0; |
727 | int start_timer = 0; | 728 | int start_timer = 0; |
729 | int one_packet = 0; | ||
728 | 730 | ||
729 | /* These transports have chunks to send. */ | 731 | /* These transports have chunks to send. */ |
730 | struct list_head transport_list; | 732 | struct list_head transport_list; |
@@ -830,20 +832,33 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
830 | if (sctp_test_T_bit(chunk)) { | 832 | if (sctp_test_T_bit(chunk)) { |
831 | packet->vtag = asoc->c.my_vtag; | 833 | packet->vtag = asoc->c.my_vtag; |
832 | } | 834 | } |
833 | case SCTP_CID_SACK: | 835 | /* The following chunks are "response" chunks, i.e. |
834 | case SCTP_CID_HEARTBEAT: | 836 | * they are generated in response to something we |
837 | * received. If we are sending these, then we can | ||
838 | * send only 1 packet containing these chunks. | ||
839 | */ | ||
835 | case SCTP_CID_HEARTBEAT_ACK: | 840 | case SCTP_CID_HEARTBEAT_ACK: |
836 | case SCTP_CID_SHUTDOWN: | ||
837 | case SCTP_CID_SHUTDOWN_ACK: | 841 | case SCTP_CID_SHUTDOWN_ACK: |
838 | case SCTP_CID_ERROR: | ||
839 | case SCTP_CID_COOKIE_ECHO: | ||
840 | case SCTP_CID_COOKIE_ACK: | 842 | case SCTP_CID_COOKIE_ACK: |
841 | case SCTP_CID_ECN_ECNE: | 843 | case SCTP_CID_COOKIE_ECHO: |
844 | case SCTP_CID_ERROR: | ||
842 | case SCTP_CID_ECN_CWR: | 845 | case SCTP_CID_ECN_CWR: |
843 | case SCTP_CID_ASCONF: | ||
844 | case SCTP_CID_ASCONF_ACK: | 846 | case SCTP_CID_ASCONF_ACK: |
847 | one_packet = 1; | ||
848 | /* Fall throught */ | ||
849 | |||
850 | case SCTP_CID_SACK: | ||
851 | case SCTP_CID_HEARTBEAT: | ||
852 | case SCTP_CID_SHUTDOWN: | ||
853 | case SCTP_CID_ECN_ECNE: | ||
854 | case SCTP_CID_ASCONF: | ||
845 | case SCTP_CID_FWD_TSN: | 855 | case SCTP_CID_FWD_TSN: |
846 | sctp_packet_transmit_chunk(packet, chunk); | 856 | status = sctp_packet_transmit_chunk(packet, chunk, |
857 | one_packet); | ||
858 | if (status != SCTP_XMIT_OK) { | ||
859 | /* put the chunk back */ | ||
860 | list_add(&chunk->list, &q->control_chunk_list); | ||
861 | } | ||
847 | break; | 862 | break; |
848 | 863 | ||
849 | default: | 864 | default: |
@@ -974,7 +989,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
974 | atomic_read(&chunk->skb->users) : -1); | 989 | atomic_read(&chunk->skb->users) : -1); |
975 | 990 | ||
976 | /* Add the chunk to the packet. */ | 991 | /* Add the chunk to the packet. */ |
977 | status = sctp_packet_transmit_chunk(packet, chunk); | 992 | status = sctp_packet_transmit_chunk(packet, chunk, 0); |
978 | 993 | ||
979 | switch (status) { | 994 | switch (status) { |
980 | case SCTP_XMIT_PMTU_FULL: | 995 | case SCTP_XMIT_PMTU_FULL: |
@@ -1239,7 +1254,6 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1239 | * Make sure the empty queue handler will get run later. | 1254 | * Make sure the empty queue handler will get run later. |
1240 | */ | 1255 | */ |
1241 | q->empty = (list_empty(&q->out_chunk_list) && | 1256 | q->empty = (list_empty(&q->out_chunk_list) && |
1242 | list_empty(&q->control_chunk_list) && | ||
1243 | list_empty(&q->retransmit)); | 1257 | list_empty(&q->retransmit)); |
1244 | if (!q->empty) | 1258 | if (!q->empty) |
1245 | goto finish; | 1259 | goto finish; |
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 9258dfe784ae..98c6a882016a 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -113,9 +113,13 @@ static __init int sctp_proc_init(void) | |||
113 | goto out_eps_proc_init; | 113 | goto out_eps_proc_init; |
114 | if (sctp_assocs_proc_init()) | 114 | if (sctp_assocs_proc_init()) |
115 | goto out_assocs_proc_init; | 115 | goto out_assocs_proc_init; |
116 | if (sctp_remaddr_proc_init()) | ||
117 | goto out_remaddr_proc_init; | ||
116 | 118 | ||
117 | return 0; | 119 | return 0; |
118 | 120 | ||
121 | out_remaddr_proc_init: | ||
122 | sctp_assocs_proc_exit(); | ||
119 | out_assocs_proc_init: | 123 | out_assocs_proc_init: |
120 | sctp_eps_proc_exit(); | 124 | sctp_eps_proc_exit(); |
121 | out_eps_proc_init: | 125 | out_eps_proc_init: |
@@ -138,6 +142,7 @@ static void sctp_proc_exit(void) | |||
138 | sctp_snmp_proc_exit(); | 142 | sctp_snmp_proc_exit(); |
139 | sctp_eps_proc_exit(); | 143 | sctp_eps_proc_exit(); |
140 | sctp_assocs_proc_exit(); | 144 | sctp_assocs_proc_exit(); |
145 | sctp_remaddr_proc_exit(); | ||
141 | 146 | ||
142 | if (proc_net_sctp) { | 147 | if (proc_net_sctp) { |
143 | proc_net_sctp = NULL; | 148 | proc_net_sctp = NULL; |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 23a9f1a95b7d..9732c797e8ed 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 | ||
@@ -655,7 +664,7 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, | |||
655 | struct sctp_association *asoc, | 664 | struct sctp_association *asoc, |
656 | struct sctp_sackhdr *sackh) | 665 | struct sctp_sackhdr *sackh) |
657 | { | 666 | { |
658 | int err; | 667 | int err = 0; |
659 | 668 | ||
660 | if (sctp_outq_sack(&asoc->outqueue, sackh)) { | 669 | if (sctp_outq_sack(&asoc->outqueue, sackh)) { |
661 | /* There are no more TSNs awaiting SACK. */ | 670 | /* There are no more TSNs awaiting SACK. */ |
@@ -663,11 +672,6 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, | |||
663 | SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), | 672 | SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), |
664 | asoc->state, asoc->ep, asoc, NULL, | 673 | asoc->state, asoc->ep, asoc, NULL, |
665 | GFP_ATOMIC); | 674 | GFP_ATOMIC); |
666 | } else { | ||
667 | /* Windows may have opened, so we need | ||
668 | * to check if we have DATA to transmit | ||
669 | */ | ||
670 | err = sctp_outq_flush(&asoc->outqueue, 0); | ||
671 | } | 675 | } |
672 | 676 | ||
673 | return err; | 677 | return err; |
@@ -1472,8 +1476,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1472 | break; | 1476 | break; |
1473 | 1477 | ||
1474 | case SCTP_CMD_DISCARD_PACKET: | 1478 | case SCTP_CMD_DISCARD_PACKET: |
1475 | /* We need to discard the whole packet. */ | 1479 | /* We need to discard the whole packet. |
1480 | * Uncork the queue since there might be | ||
1481 | * responses pending | ||
1482 | */ | ||
1476 | chunk->pdiscard = 1; | 1483 | chunk->pdiscard = 1; |
1484 | if (asoc) { | ||
1485 | sctp_outq_uncork(&asoc->outqueue); | ||
1486 | local_cork = 0; | ||
1487 | } | ||
1477 | break; | 1488 | break; |
1478 | 1489 | ||
1479 | case SCTP_CMD_RTO_PENDING: | 1490 | case SCTP_CMD_RTO_PENDING: |
@@ -1544,8 +1555,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1544 | } | 1555 | } |
1545 | 1556 | ||
1546 | out: | 1557 | out: |
1547 | if (local_cork) | 1558 | /* If this is in response to a received chunk, wait until |
1548 | sctp_outq_uncork(&asoc->outqueue); | 1559 | * we are done with the packet to open the queue so that we don't |
1560 | * send multiple packets in response to a single request. | ||
1561 | */ | ||
1562 | if (asoc && SCTP_EVENT_T_CHUNK == event_type && chunk) { | ||
1563 | if (chunk->end_of_packet || chunk->singleton) | ||
1564 | sctp_outq_uncork(&asoc->outqueue); | ||
1565 | } else if (local_cork) | ||
1566 | sctp_outq_uncork(&asoc->outqueue); | ||
1549 | return error; | 1567 | return error; |
1550 | nomem: | 1568 | nomem: |
1551 | error = -ENOMEM; | 1569 | error = -ENOMEM; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index fcdb45d1071b..8848d329aa2c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -795,8 +795,6 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
795 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 795 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
796 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 796 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
797 | 797 | ||
798 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
799 | |||
800 | /* This will send the COOKIE ACK */ | 798 | /* This will send the COOKIE ACK */ |
801 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 799 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
802 | 800 | ||
@@ -883,7 +881,6 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep, | |||
883 | if (asoc->autoclose) | 881 | if (asoc->autoclose) |
884 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 882 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
885 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 883 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
886 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
887 | 884 | ||
888 | /* It may also notify its ULP about the successful | 885 | /* It may also notify its ULP about the successful |
889 | * establishment of the association with a Communication Up | 886 | * establishment of the association with a Communication Up |
@@ -1781,7 +1778,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, | |||
1781 | goto nomem; | 1778 | goto nomem; |
1782 | 1779 | ||
1783 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 1780 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
1784 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
1785 | 1781 | ||
1786 | /* RFC 2960 5.1 Normal Establishment of an Association | 1782 | /* RFC 2960 5.1 Normal Establishment of an Association |
1787 | * | 1783 | * |
@@ -1898,12 +1894,13 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
1898 | 1894 | ||
1899 | } | 1895 | } |
1900 | } | 1896 | } |
1901 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
1902 | 1897 | ||
1903 | repl = sctp_make_cookie_ack(new_asoc, chunk); | 1898 | repl = sctp_make_cookie_ack(new_asoc, chunk); |
1904 | if (!repl) | 1899 | if (!repl) |
1905 | goto nomem; | 1900 | goto nomem; |
1906 | 1901 | ||
1902 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
1903 | |||
1907 | if (ev) | 1904 | if (ev) |
1908 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | 1905 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, |
1909 | SCTP_ULPEVENT(ev)); | 1906 | SCTP_ULPEVENT(ev)); |
@@ -1911,9 +1908,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
1911 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, | 1908 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, |
1912 | SCTP_ULPEVENT(ai_ev)); | 1909 | SCTP_ULPEVENT(ai_ev)); |
1913 | 1910 | ||
1914 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
1915 | sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); | ||
1916 | |||
1917 | return SCTP_DISPOSITION_CONSUME; | 1911 | return SCTP_DISPOSITION_CONSUME; |
1918 | 1912 | ||
1919 | nomem: | 1913 | nomem: |
@@ -3970,9 +3964,6 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
3970 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3964 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
3971 | break; | 3965 | break; |
3972 | case SCTP_CID_ACTION_DISCARD_ERR: | 3966 | case SCTP_CID_ACTION_DISCARD_ERR: |
3973 | /* Discard the packet. */ | ||
3974 | sctp_sf_pdiscard(ep, asoc, type, arg, commands); | ||
3975 | |||
3976 | /* Generate an ERROR chunk as response. */ | 3967 | /* Generate an ERROR chunk as response. */ |
3977 | hdr = unk_chunk->chunk_hdr; | 3968 | hdr = unk_chunk->chunk_hdr; |
3978 | err_chunk = sctp_make_op_error(asoc, unk_chunk, | 3969 | err_chunk = sctp_make_op_error(asoc, unk_chunk, |
@@ -3982,6 +3973,9 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
3982 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 3973 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
3983 | SCTP_CHUNK(err_chunk)); | 3974 | SCTP_CHUNK(err_chunk)); |
3984 | } | 3975 | } |
3976 | |||
3977 | /* Discard the packet. */ | ||
3978 | sctp_sf_pdiscard(ep, asoc, type, arg, commands); | ||
3985 | return SCTP_DISPOSITION_CONSUME; | 3979 | return SCTP_DISPOSITION_CONSUME; |
3986 | break; | 3980 | break; |
3987 | case SCTP_CID_ACTION_SKIP: | 3981 | case SCTP_CID_ACTION_SKIP: |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 0dbcde6758ea..df5572c39f0c 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; |
@@ -3497,7 +3588,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3497 | } | 3588 | } |
3498 | 3589 | ||
3499 | /* Cleanup any SCTP per socket resources. */ | 3590 | /* Cleanup any SCTP per socket resources. */ |
3500 | SCTP_STATIC int sctp_destroy_sock(struct sock *sk) | 3591 | SCTP_STATIC void sctp_destroy_sock(struct sock *sk) |
3501 | { | 3592 | { |
3502 | struct sctp_endpoint *ep; | 3593 | struct sctp_endpoint *ep; |
3503 | 3594 | ||
@@ -3507,7 +3598,6 @@ SCTP_STATIC int sctp_destroy_sock(struct sock *sk) | |||
3507 | ep = sctp_sk(sk)->ep; | 3598 | ep = sctp_sk(sk)->ep; |
3508 | sctp_endpoint_free(ep); | 3599 | sctp_endpoint_free(ep); |
3509 | atomic_dec(&sctp_sockets_allocated); | 3600 | atomic_dec(&sctp_sockets_allocated); |
3510 | return 0; | ||
3511 | } | 3601 | } |
3512 | 3602 | ||
3513 | /* API 4.1.7 shutdown() - TCP Style Syntax | 3603 | /* API 4.1.7 shutdown() - TCP Style Syntax |
@@ -3999,70 +4089,91 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
3999 | return 0; | 4089 | return 0; |
4000 | } | 4090 | } |
4001 | 4091 | ||
4002 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 4092 | /* |
4003 | * | 4093 | * 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 | 4094 | * |
4005 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 4095 | * This option will effect the way delayed acks are performed. This |
4006 | * endpoints default delayed ack timer value. If the assoc_id field is | 4096 | * option allows you to get or set the delayed ack time, in |
4007 | * non-zero, then the set or get effects the specified association. | 4097 | * milliseconds. It also allows changing the delayed ack frequency. |
4008 | * | 4098 | * Changing the frequency to 1 disables the delayed sack algorithm. If |
4009 | * struct sctp_assoc_value { | 4099 | * the assoc_id is 0, then this sets or gets the endpoints default |
4010 | * sctp_assoc_t assoc_id; | 4100 | * values. If the assoc_id field is non-zero, then the set or get |
4011 | * uint32_t assoc_value; | 4101 | * effects the specified association for the one to many model (the |
4012 | * }; | 4102 | * assoc_id field is ignored by the one to one model). Note that if |
4103 | * sack_delay or sack_freq are 0 when setting this option, then the | ||
4104 | * current values will remain unchanged. | ||
4105 | * | ||
4106 | * struct sctp_sack_info { | ||
4107 | * sctp_assoc_t sack_assoc_id; | ||
4108 | * uint32_t sack_delay; | ||
4109 | * uint32_t sack_freq; | ||
4110 | * }; | ||
4013 | * | 4111 | * |
4014 | * assoc_id - This parameter, indicates which association the | 4112 | * sack_assoc_id - This parameter, indicates which association the user |
4015 | * user is preforming an action upon. Note that if | 4113 | * is performing an action upon. Note that if this field's value is |
4016 | * this field's value is zero then the endpoints | 4114 | * zero then the endpoints default value is changed (effecting future |
4017 | * default value is changed (effecting future | 4115 | * associations only). |
4018 | * associations only). | ||
4019 | * | 4116 | * |
4020 | * assoc_value - This parameter contains the number of milliseconds | 4117 | * sack_delay - This parameter contains the number of milliseconds that |
4021 | * that the user is requesting the delayed ACK timer | 4118 | * the user is requesting the delayed ACK timer be set to. Note that |
4022 | * be set to. Note that this value is defined in | 4119 | * this value is defined in the standard to be between 200 and 500 |
4023 | * the standard to be between 200 and 500 milliseconds. | 4120 | * milliseconds. |
4024 | * | 4121 | * |
4025 | * Note: a value of zero will leave the value alone, | 4122 | * sack_freq - This parameter contains the number of packets that must |
4026 | * but disable SACK delay. A non-zero value will also | 4123 | * be received before a sack is sent without waiting for the delay |
4027 | * enable SACK delay. | 4124 | * timer to expire. The default value for this is 2, setting this |
4125 | * value to 1 will disable the delayed sack algorithm. | ||
4028 | */ | 4126 | */ |
4029 | static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len, | 4127 | static int sctp_getsockopt_delayed_ack(struct sock *sk, int len, |
4030 | char __user *optval, | 4128 | char __user *optval, |
4031 | int __user *optlen) | 4129 | int __user *optlen) |
4032 | { | 4130 | { |
4033 | struct sctp_assoc_value params; | 4131 | struct sctp_sack_info params; |
4034 | struct sctp_association *asoc = NULL; | 4132 | struct sctp_association *asoc = NULL; |
4035 | struct sctp_sock *sp = sctp_sk(sk); | 4133 | struct sctp_sock *sp = sctp_sk(sk); |
4036 | 4134 | ||
4037 | if (len < sizeof(struct sctp_assoc_value)) | 4135 | if (len >= sizeof(struct sctp_sack_info)) { |
4038 | return - EINVAL; | 4136 | len = sizeof(struct sctp_sack_info); |
4039 | |||
4040 | len = sizeof(struct sctp_assoc_value); | ||
4041 | 4137 | ||
4042 | if (copy_from_user(¶ms, optval, len)) | 4138 | if (copy_from_user(¶ms, optval, len)) |
4043 | return -EFAULT; | 4139 | return -EFAULT; |
4140 | } else if (len == sizeof(struct sctp_assoc_value)) { | ||
4141 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | ||
4142 | "in delayed_ack socket option deprecated\n"); | ||
4143 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | ||
4144 | if (copy_from_user(¶ms, optval, len)) | ||
4145 | return -EFAULT; | ||
4146 | } else | ||
4147 | return - EINVAL; | ||
4044 | 4148 | ||
4045 | /* Get association, if assoc_id != 0 and the socket is a one | 4149 | /* 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 | 4150 | * to many style socket, and an association was not found, then |
4047 | * the id was invalid. | 4151 | * the id was invalid. |
4048 | */ | 4152 | */ |
4049 | asoc = sctp_id2assoc(sk, params.assoc_id); | 4153 | asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
4050 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | 4154 | if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
4051 | return -EINVAL; | 4155 | return -EINVAL; |
4052 | 4156 | ||
4053 | if (asoc) { | 4157 | if (asoc) { |
4054 | /* Fetch association values. */ | 4158 | /* Fetch association values. */ |
4055 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) | 4159 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) { |
4056 | params.assoc_value = jiffies_to_msecs( | 4160 | params.sack_delay = jiffies_to_msecs( |
4057 | asoc->sackdelay); | 4161 | asoc->sackdelay); |
4058 | else | 4162 | params.sack_freq = asoc->sackfreq; |
4059 | params.assoc_value = 0; | 4163 | |
4164 | } else { | ||
4165 | params.sack_delay = 0; | ||
4166 | params.sack_freq = 1; | ||
4167 | } | ||
4060 | } else { | 4168 | } else { |
4061 | /* Fetch socket values. */ | 4169 | /* Fetch socket values. */ |
4062 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) | 4170 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) { |
4063 | params.assoc_value = sp->sackdelay; | 4171 | params.sack_delay = sp->sackdelay; |
4064 | else | 4172 | params.sack_freq = sp->sackfreq; |
4065 | params.assoc_value = 0; | 4173 | } else { |
4174 | params.sack_delay = 0; | ||
4175 | params.sack_freq = 1; | ||
4176 | } | ||
4066 | } | 4177 | } |
4067 | 4178 | ||
4068 | if (copy_to_user(optval, ¶ms, len)) | 4179 | if (copy_to_user(optval, ¶ms, len)) |
@@ -4112,6 +4223,8 @@ static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len, | |||
4112 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) | 4223 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) |
4113 | return -EFAULT; | 4224 | return -EFAULT; |
4114 | 4225 | ||
4226 | printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_NUM_OLD " | ||
4227 | "socket option deprecated\n"); | ||
4115 | /* For UDP-style sockets, id specifies the association to query. */ | 4228 | /* For UDP-style sockets, id specifies the association to query. */ |
4116 | asoc = sctp_id2assoc(sk, id); | 4229 | asoc = sctp_id2assoc(sk, id); |
4117 | if (!asoc) | 4230 | if (!asoc) |
@@ -4151,6 +4264,9 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, | |||
4151 | 4264 | ||
4152 | if (getaddrs.addr_num <= 0) return -EINVAL; | 4265 | if (getaddrs.addr_num <= 0) return -EINVAL; |
4153 | 4266 | ||
4267 | printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_OLD " | ||
4268 | "socket option deprecated\n"); | ||
4269 | |||
4154 | /* For UDP-style sockets, id specifies the association to query. */ | 4270 | /* For UDP-style sockets, id specifies the association to query. */ |
4155 | asoc = sctp_id2assoc(sk, getaddrs.assoc_id); | 4271 | asoc = sctp_id2assoc(sk, getaddrs.assoc_id); |
4156 | if (!asoc) | 4272 | if (!asoc) |
@@ -4244,6 +4360,9 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, | |||
4244 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) | 4360 | if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) |
4245 | return -EFAULT; | 4361 | return -EFAULT; |
4246 | 4362 | ||
4363 | printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_NUM_OLD " | ||
4364 | "socket option deprecated\n"); | ||
4365 | |||
4247 | /* | 4366 | /* |
4248 | * For UDP-style sockets, id specifies the association to query. | 4367 | * For UDP-style sockets, id specifies the association to query. |
4249 | * If the id field is set to the value '0' then the locally bound | 4368 | * If the id field is set to the value '0' then the locally bound |
@@ -4404,6 +4523,10 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, | |||
4404 | if (getaddrs.addr_num <= 0 || | 4523 | if (getaddrs.addr_num <= 0 || |
4405 | getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr))) | 4524 | getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr))) |
4406 | return -EINVAL; | 4525 | return -EINVAL; |
4526 | |||
4527 | printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_OLD " | ||
4528 | "socket option deprecated\n"); | ||
4529 | |||
4407 | /* | 4530 | /* |
4408 | * For UDP-style sockets, id specifies the association to query. | 4531 | * For UDP-style sockets, id specifies the association to query. |
4409 | * If the id field is set to the value '0' then the locally bound | 4532 | * If the id field is set to the value '0' then the locally bound |
@@ -5220,8 +5343,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5220 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, | 5343 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, |
5221 | optlen); | 5344 | optlen); |
5222 | break; | 5345 | break; |
5223 | case SCTP_DELAYED_ACK_TIME: | 5346 | case SCTP_DELAYED_ACK: |
5224 | retval = sctp_getsockopt_delayed_ack_time(sk, len, optval, | 5347 | retval = sctp_getsockopt_delayed_ack(sk, len, optval, |
5225 | optlen); | 5348 | optlen); |
5226 | break; | 5349 | break; |
5227 | case SCTP_INITMSG: | 5350 | case SCTP_INITMSG: |