From: Martin Willi Date: Wed, 14 Mar 2007 11:07:12 +0000 (-0000) Subject: cleaned up and fixed DPD handling code X-Git-Tag: 4.1.0~67 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=edfabed069bb827d61f38be79e331f508666f3f4;p=thirdparty%2Fstrongswan.git cleaned up and fixed DPD handling code --- diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index b8bfed5a6d..a3dbaa4f7c 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -407,99 +407,6 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other) iterator->destroy(iterator); } -/** - * Implementation of ike_sa_t.retransmit. - */ -static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) -{ - this->time.outbound = time(NULL); - if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS) - { - connection_t *connection = NULL; - policy_t *policy; - linked_list_t *my_ts, *other_ts; - child_sa_t* child_sa; - dpd_action_t action; - job_t *job; - - DBG2(DBG_IKE, "dead peer detected, handling CHILD_SAs dpd action"); - - /* check for childrens with dpdaction = hold */ - while(this->child_sas->remove_first(this->child_sas, - (void**)&child_sa) == SUCCESS) - { - /* get the policy which belongs to this CHILD */ - my_ts = child_sa->get_my_traffic_selectors(child_sa); - other_ts = child_sa->get_other_traffic_selectors(child_sa); - policy = charon->policies->get_policy(charon->policies, - this->my_id, this->other_id, - my_ts, other_ts, - this->my_host, this->other_host); - if (policy == NULL) - { - DBG1(DBG_IKE, "no policy for CHILD to handle DPD"); - continue; - } - - action = policy->get_dpd_action(policy); - /* get a connection for further actions */ - if (connection == NULL && - (action == DPD_ROUTE || action == DPD_RESTART)) - { - connection = charon->connections->get_connection_by_hosts( - charon->connections, - this->my_host, this->other_host); - if (connection == NULL) - { - SIG(IKE_UP_FAILED, "no connection found to handle DPD"); - break; - } - } - - DBG1(DBG_IKE, "dpd action for %s is %N", - policy->get_name(policy), dpd_action_names, action); - - switch (action) - { - case DPD_ROUTE: - connection->get_ref(connection); - job = (job_t*)route_job_create(connection, policy, TRUE); - charon->job_queue->add(charon->job_queue, job); - break; - case DPD_RESTART: - connection->get_ref(connection); - job = (job_t*)initiate_job_create(connection, policy); - charon->job_queue->add(charon->job_queue, job); - break; - default: - policy->destroy(policy); - break; - } - child_sa->destroy(child_sa); - } - - /* send a proper signal to brief interested bus listeners */ - switch (this->state) - { - case IKE_CONNECTING: - SIG(IKE_UP_FAILED, "establishing IKE_SA failed, peer not responding"); - break; - case IKE_REKEYING: - SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed, peer not responding"); - break; - case IKE_DELETING: - SIG(IKE_DOWN_FAILED, "proper IKE_SA delete failed, peer not responding"); - break; - default: - break; - } - - DESTROY_IF(connection); - return DESTROY_ME; - } - return SUCCESS; -} - /** * Implementation of ike_sa_t.generate */ @@ -916,6 +823,119 @@ static status_t unroute(private_ike_sa_t *this, policy_t *policy) return SUCCESS; } +/** + * Implementation of ike_sa_t.retransmit. + */ +static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id) +{ + this->time.outbound = time(NULL); + if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS) + { + policy_t *policy; + child_sa_t* child_sa; + linked_list_t *to_route, *to_restart; + iterator_t *iterator; + + /* send a proper signal to brief interested bus listeners */ + switch (this->state) + { + case IKE_CONNECTING: + SIG(IKE_UP_FAILED, "establishing IKE_SA failed, peer not responding"); + break; + case IKE_REKEYING: + SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed, peer not responding"); + break; + case IKE_DELETING: + SIG(IKE_DOWN_FAILED, "proper IKE_SA delete failed, peer not responding"); + break; + default: + break; + } + + /* summarize how we have to handle each child */ + to_route = linked_list_create(); + to_restart = linked_list_create(); + iterator = this->child_sas->create_iterator(this->child_sas, TRUE); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + policy = child_sa->get_policy(child_sa); + + if (child_sa->get_state(child_sa) == CHILD_ROUTED) + { + /* reroute routed CHILD_SAs */ + to_route->insert_last(to_route, policy); + } + else + { + /* use DPD action for established CHILD_SAs */ + switch (policy->get_dpd_action(policy)) + { + case DPD_ROUTE: + to_route->insert_last(to_route, policy); + break; + case DPD_RESTART: + to_restart->insert_last(to_restart, policy); + break; + default: + break; + } + } + } + iterator->destroy(iterator); + + /* create a new IKE_SA if we have to route or to restart */ + if (to_route->get_count(to_route) || to_restart->get_count(to_restart)) + { + ike_sa_id_t *other_id; + private_ike_sa_t *new; + task_t *task; + + other_id = ike_sa_id_create(0, 0, TRUE); + new = (private_ike_sa_t*)charon->ike_sa_manager->checkout( + charon->ike_sa_manager, other_id); + other_id->destroy(other_id); + + apply_config(new, this->connection, this->policy); + /* use actual used host, not the wildcarded one in connection */ + new->other_host->destroy(new->other_host); + new->other_host = this->other_host->clone(this->other_host); + + /* install routes */ + while (to_route->remove_last(to_route, (void**)&policy) == SUCCESS) + { + route(new, new->connection, policy); + } + + /* restart children */ + if (to_restart->get_count(to_restart)) + { + task = (task_t*)ike_init_create(&new->public, TRUE, NULL); + new->task_manager->queue_task(new->task_manager, task); + task = (task_t*)ike_natd_create(&new->public, TRUE); + new->task_manager->queue_task(new->task_manager, task); + task = (task_t*)ike_cert_create(&new->public, TRUE); + new->task_manager->queue_task(new->task_manager, task); + task = (task_t*)ike_config_create(&new->public, new->policy); + new->task_manager->queue_task(new->task_manager, task); + task = (task_t*)ike_auth_create(&new->public, TRUE); + new->task_manager->queue_task(new->task_manager, task); + + while (to_restart->remove_last(to_restart, (void**)&policy) == SUCCESS) + { + task = (task_t*)child_create_create(&new->public, policy); + new->task_manager->queue_task(new->task_manager, task); + } + new->task_manager->initiate(new->task_manager); + } + charon->ike_sa_manager->checkin(charon->ike_sa_manager, &new->public); + } + to_route->destroy(to_route); + to_restart->destroy(to_restart); + return DESTROY_ME; + } + return SUCCESS; +} + /** * Implementation of ike_sa_t.send_dpd */ diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c index 4c6a199e42..be35cea973 100644 --- a/src/charon/sa/task_manager.c +++ b/src/charon/sa/task_manager.c @@ -739,7 +739,7 @@ static void destroy(private_task_manager_t *this) SIG(IKE_UP_FAILED, "establishing IKE_SA failed"); break; case IKE_DELETE: - SIG(IKE_DOWN_FAILED, "deleting IKE_SA properly failed"); + SIG(IKE_DOWN_FAILED, "IKE_SA deleted"); break; case IKE_REKEY: SIG(IKE_REKEY_FAILED, "rekeying IKE_SA failed");