diff options
Diffstat (limited to 'net/sctp/sm_sideeffect.c')
-rw-r--r-- | net/sctp/sm_sideeffect.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 4c5bed9af4e3..eb1f42f45fdd 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -397,6 +397,41 @@ out_unlock: | |||
397 | sctp_transport_put(transport); | 397 | sctp_transport_put(transport); |
398 | } | 398 | } |
399 | 399 | ||
400 | /* Handle the timeout of the ICMP protocol unreachable timer. Trigger | ||
401 | * the correct state machine transition that will close the association. | ||
402 | */ | ||
403 | void sctp_generate_proto_unreach_event(unsigned long data) | ||
404 | { | ||
405 | struct sctp_transport *transport = (struct sctp_transport *) data; | ||
406 | struct sctp_association *asoc = transport->asoc; | ||
407 | |||
408 | sctp_bh_lock_sock(asoc->base.sk); | ||
409 | if (sock_owned_by_user(asoc->base.sk)) { | ||
410 | SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__); | ||
411 | |||
412 | /* Try again later. */ | ||
413 | if (!mod_timer(&transport->proto_unreach_timer, | ||
414 | jiffies + (HZ/20))) | ||
415 | sctp_association_hold(asoc); | ||
416 | goto out_unlock; | ||
417 | } | ||
418 | |||
419 | /* Is this structure just waiting around for us to actually | ||
420 | * get destroyed? | ||
421 | */ | ||
422 | if (asoc->base.dead) | ||
423 | goto out_unlock; | ||
424 | |||
425 | sctp_do_sm(SCTP_EVENT_T_OTHER, | ||
426 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | ||
427 | asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); | ||
428 | |||
429 | out_unlock: | ||
430 | sctp_bh_unlock_sock(asoc->base.sk); | ||
431 | sctp_association_put(asoc); | ||
432 | } | ||
433 | |||
434 | |||
400 | /* Inject a SACK Timeout event into the state machine. */ | 435 | /* Inject a SACK Timeout event into the state machine. */ |
401 | static void sctp_generate_sack_event(unsigned long data) | 436 | static void sctp_generate_sack_event(unsigned long data) |
402 | { | 437 | { |
@@ -962,6 +997,29 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc, | |||
962 | } | 997 | } |
963 | 998 | ||
964 | 999 | ||
1000 | /* Sent the next ASCONF packet currently stored in the association. | ||
1001 | * This happens after the ASCONF_ACK was succeffully processed. | ||
1002 | */ | ||
1003 | static void sctp_cmd_send_asconf(struct sctp_association *asoc) | ||
1004 | { | ||
1005 | /* Send the next asconf chunk from the addip chunk | ||
1006 | * queue. | ||
1007 | */ | ||
1008 | if (!list_empty(&asoc->addip_chunk_list)) { | ||
1009 | struct list_head *entry = asoc->addip_chunk_list.next; | ||
1010 | struct sctp_chunk *asconf = list_entry(entry, | ||
1011 | struct sctp_chunk, list); | ||
1012 | list_del_init(entry); | ||
1013 | |||
1014 | /* Hold the chunk until an ASCONF_ACK is received. */ | ||
1015 | sctp_chunk_hold(asconf); | ||
1016 | if (sctp_primitive_ASCONF(asoc, asconf)) | ||
1017 | sctp_chunk_free(asconf); | ||
1018 | else | ||
1019 | asoc->addip_last_asconf = asconf; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
965 | 1023 | ||
966 | /* These three macros allow us to pull the debugging code out of the | 1024 | /* These three macros allow us to pull the debugging code out of the |
967 | * main flow of sctp_do_sm() to keep attention focused on the real | 1025 | * main flow of sctp_do_sm() to keep attention focused on the real |
@@ -1617,6 +1675,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1617 | } | 1675 | } |
1618 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); | 1676 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); |
1619 | break; | 1677 | break; |
1678 | case SCTP_CMD_SEND_NEXT_ASCONF: | ||
1679 | sctp_cmd_send_asconf(asoc); | ||
1680 | break; | ||
1620 | default: | 1681 | default: |
1621 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1682 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
1622 | cmd->verb, cmd->obj.ptr); | 1683 | cmd->verb, cmd->obj.ptr); |