diff options
-rw-r--r-- | src/charon/config/connections/local_connection_store.c | 2 | ||||
-rw-r--r-- | src/charon/config/policies/policy.c | 25 | ||||
-rw-r--r-- | src/charon/config/policies/policy.h | 36 | ||||
-rw-r--r-- | src/charon/sa/child_sa.c | 5 | ||||
-rw-r--r-- | src/charon/sa/child_sa.h | 8 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 91 | ||||
-rw-r--r-- | src/charon/sa/transactions/ike_auth.c | 7 | ||||
-rwxr-xr-x | src/charon/threads/stroke_interface.c | 2 | ||||
-rw-r--r-- | src/starter/starterstroke.c | 2 | ||||
-rw-r--r-- | src/stroke/stroke.c | 2 | ||||
-rw-r--r-- | src/stroke/stroke.h | 2 |
11 files changed, 156 insertions, 26 deletions
diff --git a/src/charon/config/connections/local_connection_store.c b/src/charon/config/connections/local_connection_store.c index 024754ee7..72265b5f0 100644 --- a/src/charon/config/connections/local_connection_store.c +++ b/src/charon/config/connections/local_connection_store.c @@ -126,7 +126,7 @@ static connection_t *get_connection_by_hosts(private_local_connection_store_t *t host_t *found_my_host = found->get_my_host(found); host_t *found_other_host = found->get_other_host(found); - this->logger->log(this->logger, CONTROL, + this->logger->log(this->logger, CONTROL|LEVEL1, "found matching connection \"%s\": %s...%s (prio=%d)", found->get_name(found), found_my_host->get_string(found_my_host), diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c index 71fadbdfa..f64447a52 100644 --- a/src/charon/config/policies/policy.c +++ b/src/charon/config/policies/policy.c @@ -31,6 +31,13 @@ #include <utils/identification.h> #include <utils/logger_manager.h> +mapping_t dpd_action_m[] = { + {DPD_CLEAR, "DPD_CLEAR"}, + {DPD_ROUTE, "DPD_ROUTE"}, + {DPD_RESTART, "DPD_RESTART"}, + {MAPPING_END, NULL}, +}; + typedef struct private_policy_t private_policy_t; /** @@ -110,9 +117,9 @@ struct private_policy_t { u_int32_t jitter; /** - * Should the SA get ROUTED when peer detected as dead? + * What to do with an SA when other peer seams to be dead? */ - bool dpd_route; + bool dpd_action; /** * logger @@ -334,6 +341,15 @@ static char* get_updown(private_policy_t *this) } /** + * Implements policy_t.get_dpd_action + */ +static dpd_action_t get_dpd_action(private_policy_t *this) +{ + return this->dpd_action; +} + + +/** * Implementation of policy_t.add_my_traffic_selector */ static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector) @@ -446,7 +462,7 @@ static void destroy(private_policy_t *this) */ policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id, u_int32_t hard_lifetime, u_int32_t soft_lifetime, - u_int32_t jitter, char *updown, bool dpd_route) + u_int32_t jitter, char *updown, dpd_action_t dpd_action) { private_policy_t *this = malloc_thing(private_policy_t); @@ -465,6 +481,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal; this->public.add_authorities = (void(*)(policy_t*,identification_t*, identification_t*))add_authorities; this->public.get_updown = (char*(*)(policy_t*))get_updown; + this->public.get_dpd_action = (dpd_action_t(*)(policy_t*))get_dpd_action; this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime; this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime; this->public.get_ref = (void(*)(policy_t*))get_ref; @@ -478,7 +495,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o this->soft_lifetime = soft_lifetime; this->jitter = jitter; this->updown = (updown == NULL) ? NULL : strdup(updown); - this->dpd_route = dpd_route; + this->dpd_action = dpd_action; /* initialize private members*/ this->refcount = 1; diff --git a/src/charon/config/policies/policy.h b/src/charon/config/policies/policy.h index 9505e53fd..18e6ad0fc 100644 --- a/src/charon/config/policies/policy.h +++ b/src/charon/config/policies/policy.h @@ -31,6 +31,30 @@ #include <encoding/payloads/auth_payload.h> +typedef enum dpd_action_t dpd_action_t; + +/** + * @brief Actions to take when a peer does not respond (dead peer detected). + * + * These values are the same as in pluto/starter, so do not modify them! + * + * @ingroup config + */ +enum dpd_action_t { + /** remove CHILD_SA without replacement */ + DPD_CLEAR = 1, + /** route the CHILD_SA to resetup when needed */ + DPD_ROUTE = 2, + /** restart CHILD_SA in a new IKE_SA, immediately */ + DPD_RESTART = 3, +}; + +/** + * String mappings for dpd_action_t + */ +mapping_t dpd_action_m[]; + + typedef struct policy_t policy_t; /** @@ -202,6 +226,14 @@ struct policy_t { * @return path to updown script */ char* (*get_updown) (policy_t *this); + + /** + * @brief What should be done with a CHILD_SA, when other peer does not respond. + * + * @param this calling object + * @return dpd action + */ + dpd_action_t (*get_dpd_action) (policy_t *this); /** * @brief Get the lifetime of a policy, before rekeying starts. @@ -264,7 +296,7 @@ struct policy_t { * @param soft_lifetime lifetime before rekeying an SA * @param jitter range of randomization time * @param updown updown script to execute on up/down event - * @param dpd_route should the connection go to routed state if DPD detected? + * @param dpd_action what to to with a CHILD_SA when other peer does not respond * @return policy_t object * * @ingroup config @@ -272,6 +304,6 @@ struct policy_t { policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id, u_int32_t hard_lifetime, u_int32_t soft_lifetime, - u_int32_t jitter, char *updown, bool dpd_route); + u_int32_t jitter, char *updown, dpd_action_t dpd_action); #endif /* POLICY_H_ */ diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index 2e8155678..8a7e64ac4 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -157,6 +157,11 @@ struct private_child_sa_t { * Specifies if NAT traversal is used */ bool use_natt; + + /** + * Specifies if CHILD_SA goes to ROUTED state if DPD detected + */ + bool stays_routed; /** * CHILD_SAs own logger diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h index abba8e4a0..5129ffe6a 100644 --- a/src/charon/sa/child_sa.h +++ b/src/charon/sa/child_sa.h @@ -197,8 +197,8 @@ struct child_sa_t { * @param other_diff differences to apply for other * @return SUCCESS or FAILED */ - status_t (*update_hosts) (child_sa_t *this, host_t *new_me, host_t *new_other, - host_diff_t my_diff, host_diff_t other_diff); + status_t (*update_hosts)(child_sa_t *this, host_t *new_me, host_t *new_other, + host_diff_t my_diff, host_diff_t other_diff); /** * @brief Install the policies using some traffic selectors. @@ -211,7 +211,9 @@ struct child_sa_t { * @param other_ts traffic selectors for remote site * @return SUCCESS or FAILED */ - status_t (*add_policies) (child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list); + status_t (*add_policies)(child_sa_t *this, + linked_list_t *my_ts_list, + linked_list_t *other_ts_list); /** * @brief Get the traffic selectors of added policies of local host. diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 6488cc20c..c5d3a63cd 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -55,6 +55,8 @@ #include <queues/jobs/send_dpd_job.h> #include <queues/jobs/send_keepalive_job.h> #include <queues/jobs/rekey_ike_sa_job.h> +#include <queues/jobs/route_job.h> +#include <queues/jobs/initiate_job.h> /** * String mappings for ike_sa_state_t. @@ -426,6 +428,80 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other) } /** + * called when the peer is not responding anymore + */ +static void dpd_detected(private_ike_sa_t *this) +{ + /* check for childrens with dpdaction=hold */ + 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; + + this->logger->log(this->logger, CONTROL|LEVEL1, + "dead peer detected, handling CHILD_SAs dpd action"); + + 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) + { + this->logger->log(this->logger, ERROR, + "no policy found for this CHILD_SA"); + 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) + { + this->logger->log(this->logger, ERROR, + "no connection found for this IKE_SA"); + break; + } + } + + this->logger->log(this->logger, CONTROL, "dpd action for %s is %s", + policy->get_name(policy), + mapping_find(dpd_action_m, 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); + } + DESTROY_IF(connection); +} + +/** * send a request and schedule retransmission */ static status_t transmit_request(private_ike_sa_t *this) @@ -439,20 +515,16 @@ static status_t transmit_request(private_ike_sa_t *this) transaction_t *transaction = this->transaction_out; u_int32_t message_id; - - this->logger->log(this->logger, CONTROL, - "transmitting request"); - transmitted = transaction->requested(transaction); timeout = charon->configuration->get_retransmit_timeout(charon->configuration, transmitted, this->retrans_sequences); if (timeout == 0) { - /* giving up. TODO: check for childrens with dpdaction=hold */ this->logger->log(this->logger, ERROR, "giving up after %d retransmits, deleting IKE_SA", transmitted - 1); + dpd_detected(this); return DESTROY_ME; } @@ -502,8 +574,6 @@ static status_t retransmit_request(private_ike_sa_t *this, u_int32_t message_id) if (this->transaction_out == NULL || this->transaction_out->get_message_id(this->transaction_out) != message_id) { - if (this->transaction_out) - printf("trans_out->mid = %d, mid = %d\n", this->transaction_out->get_message_id(this->transaction_out), message_id); /* no retransmit necessary, transaction did already complete */ return SUCCESS; } @@ -925,7 +995,7 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) { if (current->get_reqid(current) == reqid) { - iterator->remove(iterator); + //iterator->remove(iterator); child_sa = current; break; } @@ -945,7 +1015,7 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid) this->my_id, this->other_id, my_ts, other_ts, this->my_host, this->other_host); - child_sa->destroy(child_sa); + //child_sa->destroy(child_sa); if (policy == NULL) { this->logger->log(this->logger, ERROR, @@ -1128,7 +1198,8 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t return FAILED; } - child_sa = child_sa_create(0, this->my_host, this->other_host, 0, 0, FALSE); + child_sa = child_sa_create(0, this->my_host, this->other_host, + 0, 0, FALSE); child_sa->set_name(child_sa, policy->get_name(policy)); my_ts = policy->get_my_traffic_selectors(policy, this->my_host); other_ts = policy->get_other_traffic_selectors(policy, this->other_host); diff --git a/src/charon/sa/transactions/ike_auth.c b/src/charon/sa/transactions/ike_auth.c index 1d15daebb..0632fe421 100644 --- a/src/charon/sa/transactions/ike_auth.c +++ b/src/charon/sa/transactions/ike_auth.c @@ -312,12 +312,15 @@ static status_t get_request(private_ike_auth_t *this, message_t **result) linked_list_t *proposal_list; sa_payload_t *sa_payload; u_int32_t soft_lifetime, hard_lifetime; + bool enable_natt; proposal_list = this->policy->get_proposals(this->policy); soft_lifetime = this->policy->get_soft_lifetime(this->policy); hard_lifetime = this->policy->get_hard_lifetime(this->policy); - this->child_sa = child_sa_create(this->reqid, me, other, soft_lifetime, hard_lifetime, - this->ike_sa->is_natt_enabled(this->ike_sa)); + enable_natt = this->ike_sa->is_natt_enabled(this->ike_sa); + this->child_sa = child_sa_create(this->reqid, me, other, + soft_lifetime, hard_lifetime, + enable_natt); this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy)); if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS) { diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index 55a3b79c3..b8bdd5a99 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -412,7 +412,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) msg->add_conn.rekey.ipsec_lifetime, msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin, msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100, - msg->add_conn.me.updown, msg->add_conn.dpd.route); + msg->add_conn.me.updown, msg->add_conn.dpd.action); policy->add_my_traffic_selector(policy, my_ts); policy->add_other_traffic_selector(policy, other_ts); policy->add_authorities(policy, my_ca, other_ca); diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index 32866be05..e54931ad5 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -181,7 +181,7 @@ int starter_stroke_add_conn(starter_conn_t *conn) msg.add_conn.algorithms.ike = push_string(&msg, conn->ike); msg.add_conn.algorithms.esp = push_string(&msg, conn->esp); msg.add_conn.dpd.delay = conn->dpd_delay; - msg.add_conn.dpd.route = conn->dpd_action == DPD_ACTION_HOLD ? 1 : 0; + msg.add_conn.dpd.action = conn->dpd_action; starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->right); starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->left); diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index 03a5ca245..6ca07a8e5 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -117,7 +117,7 @@ static int add_connection(char *name, msg.add_conn.algorithms.esp = NULL; msg.add_conn.dpd.delay = 0; - msg.add_conn.dpd.route = 0; + msg.add_conn.dpd.action = 1; msg.add_conn.me.id = push_string(&msg, my_id); msg.add_conn.me.address = push_string(&msg, my_addr); diff --git a/src/stroke/stroke.h b/src/stroke/stroke.h index 320284229..39a529c60 100644 --- a/src/stroke/stroke.h +++ b/src/stroke/stroke.h @@ -147,7 +147,7 @@ struct stroke_msg_t { } rekey; struct { time_t delay; - bool route; + int action; } dpd; stroke_end_t me, other; } add_conn; |