diff options
author | Martin Willi <martin@strongswan.org> | 2008-10-06 13:37:04 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2008-10-06 13:37:04 +0000 |
commit | 9d9a772ee1f5b356224a26508139720399e21818 (patch) | |
tree | 890c4b24b4afeef2bfb2da0582181322565570c0 | |
parent | 0592212f237852b68b97bea59300f1296fc61401 (diff) | |
download | strongswan-9d9a772ee1f5b356224a26508139720399e21818.tar.bz2 strongswan-9d9a772ee1f5b356224a26508139720399e21818.tar.xz |
use MOBIKE enabled DPD if we are NATed
update SAs if we detect changes in NAT mappings
-rw-r--r-- | src/charon/sa/ike_sa.c | 43 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.h | 8 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.c | 24 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.h | 5 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_natd.c | 28 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_natd.h | 9 |
6 files changed, 113 insertions, 4 deletions
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 415112731..351e28282 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -255,6 +255,11 @@ struct private_ike_sa_t { linked_list_t *additional_addresses; /** + * previously value of received DESTINATION_IP hash + */ + chunk_t nat_detection_dest; + + /** * number pending UPDATE_SA_ADDRESS (MOBIKE) */ u_int32_t pending_updates; @@ -626,8 +631,20 @@ static status_t send_dpd(private_ike_sa_t *this) { /* to long ago, initiate dead peer detection */ task_t *task; + ike_mobike_t *mobike; - task = (task_t*)ike_dpd_create(TRUE); + if (supports_extension(this, EXT_MOBIKE) && + has_condition(this, COND_NAT_HERE)) + { + /* use mobike enabled DPD to detect NAT mapping changes */ + mobike = ike_mobike_create(&this->public, TRUE); + mobike->dpd(mobike); + task = &mobike->task; + } + else + { + task = (task_t*)ike_dpd_create(TRUE); + } diff = 0; DBG1(DBG_IKE, "sending DPD request"); @@ -817,7 +834,26 @@ static iterator_t* create_additional_address_iterator(private_ike_sa_t *this) return this->additional_addresses->create_iterator( this->additional_addresses, TRUE); } - + +/** + * Implementation of ike_sa_t.has_mapping_changed + */ +static bool has_mapping_changed(private_ike_sa_t *this, chunk_t hash) +{ + if (this->nat_detection_dest.ptr == NULL) + { + this->nat_detection_dest = chunk_clone(hash); + return FALSE; + } + if (chunk_equals(hash, this->nat_detection_dest)) + { + return FALSE; + } + free(this->nat_detection_dest.ptr); + this->nat_detection_dest = chunk_clone(hash); + return TRUE; +} + /** * Implementation of ike_sa_t.set_pending_updates. */ @@ -2498,6 +2534,7 @@ static void destroy(private_ike_sa_t *this) DESTROY_IF(this->server_reflexive_host); chunk_free(&this->connect_id); #endif /* ME */ + free(this->nat_detection_dest.ptr); DESTROY_IF(this->my_host); DESTROY_IF(this->other_host); @@ -2559,6 +2596,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.is_ike_initiator = (bool (*)(ike_sa_t*))is_ike_initiator; this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator; this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address; + this->public.has_mapping_changed = (bool(*)(ike_sa_t*, chunk_t hash))has_mapping_changed; this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit; this->public.delete = (status_t (*)(ike_sa_t*))delete_; this->public.destroy = (void (*)(ike_sa_t*))destroy; @@ -2638,6 +2676,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->other_virtual_ip = NULL; this->dns_servers = linked_list_create(); this->additional_addresses = linked_list_create(); + this->nat_detection_dest = chunk_empty; this->pending_updates = 0; this->keyingtry = 0; this->ike_initiator = FALSE; diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index e45d18cea..3cd9e00f0 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -407,6 +407,14 @@ struct ike_sa_t { iterator_t* (*create_additional_address_iterator)(ike_sa_t *this); /** + * Check if mappings have changed on a NAT for our source address. + * + * @param hash received DESTINATION_IP hash + * @return TRUE if mappings have changed + */ + bool (*has_mapping_changed)(ike_sa_t *this, chunk_t hash); + + /** * Enable an extension the peer supports. * * If support for an IKE extension is detected, this method is called diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c index 4b8e8ceb0..450149f1c 100644 --- a/src/charon/sa/tasks/ike_mobike.c +++ b/src/charon/sa/tasks/ike_mobike.c @@ -434,7 +434,7 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) return SUCCESS; } if (this->cookie2.ptr) - { /* check cookie if we included none */ + { /* check cookie if we included one */ chunk_t cookie2; cookie2 = this->cookie2; @@ -455,6 +455,13 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) if (this->natd) { this->natd->task.process(&this->natd->task, message); + if (this->natd->has_mapping_changed(this->natd)) + { + /* force an update if mappings have changed */ + this->update = this->check = TRUE; + DBG1(DBG_IKE, "detected changes in NAT mappings, " + "initiating MOBIKE update"); + } } if (this->update) { @@ -507,6 +514,20 @@ static void roam(private_ike_mobike_t *this, bool address) } /** + * Implementation of ike_mobike_t.dpd + */ +static void dpd(private_ike_mobike_t *this) +{ + if (!this->natd) + { + this->natd = ike_natd_create(this->ike_sa, this->initiator); + } + this->address = FALSE; + this->ike_sa->set_pending_updates(this->ike_sa, + this->ike_sa->get_pending_updates(this->ike_sa) + 1); +} + +/** * Implementation of ike_mobike_t.is_probing. */ static bool is_probing(private_ike_mobike_t *this) @@ -556,6 +577,7 @@ ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator) private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t); this->public.roam = (void(*)(ike_mobike_t*,bool))roam; + this->public.dpd = (void(*)(ike_mobike_t*))dpd; this->public.transmit = (void(*)(ike_mobike_t*,packet_t*))transmit; this->public.is_probing = (bool(*)(ike_mobike_t*))is_probing; this->public.task.get_type = (task_type_t(*)(task_t*))get_type; diff --git a/src/charon/sa/tasks/ike_mobike.h b/src/charon/sa/tasks/ike_mobike.h index 7325f5a6f..81bdd0f74 100644 --- a/src/charon/sa/tasks/ike_mobike.h +++ b/src/charon/sa/tasks/ike_mobike.h @@ -55,6 +55,11 @@ struct ike_mobike_t { void (*roam)(ike_mobike_t *this, bool address); /** + * Use the task for a DPD check which detects changes in NAT mappings. + */ + void (*dpd)(ike_mobike_t *this); + + /** * Transmision hook, called by task manager. * * The task manager calls this hook whenever it transmits a packet. It diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c index 34c040c65..de0cfce1b 100644 --- a/src/charon/sa/tasks/ike_natd.c +++ b/src/charon/sa/tasks/ike_natd.c @@ -72,6 +72,11 @@ struct private_ike_natd_t { * Have we found a matching destination address NAT hash? */ bool dst_matched; + + /** + * whether NAT mappings for our NATed address has changed + */ + bool mapping_changed; }; @@ -192,15 +197,24 @@ static void process_payloads(private_ike_natd_t *this, message_t *message) case NAT_DETECTION_DESTINATION_IP: { this->dst_seen = TRUE; + hash = notify->get_notification_data(notify); if (!this->dst_matched) { - hash = notify->get_notification_data(notify); DBG3(DBG_IKE, "received dst_hash %B", &hash); if (chunk_equals(hash, dst_hash)) { this->dst_matched = TRUE; } } + /* RFC4555 says we should also compare against IKE_SA_INIT + * NATD payloads, but this does not work: We are running + * there at port 500, but use 4500 afterwards... */ + if (message->get_exchange_type(message) == INFORMATIONAL && + this->initiator && !this->dst_matched) + { + this->mapping_changed = this->ike_sa->has_mapping_changed( + this->ike_sa, hash); + } break; } case NAT_DETECTION_SOURCE_IP: @@ -415,6 +429,15 @@ static void migrate(private_ike_natd_t *this, ike_sa_t *ike_sa) this->dst_seen = FALSE; this->src_matched = FALSE; this->dst_matched = FALSE; + this->mapping_changed = FALSE; +} + +/** + * Implementation of ike_natd_t.has_mapping_changed + */ +static bool has_mapping_changed(private_ike_natd_t *this) +{ + return this->mapping_changed; } /** @@ -448,6 +471,8 @@ ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator) this->public.task.process = (status_t(*)(task_t*,message_t*))process_r; } + this->public.has_mapping_changed = (bool(*)(ike_natd_t*))has_mapping_changed; + this->ike_sa = ike_sa; this->initiator = initiator; this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); @@ -455,6 +480,7 @@ ike_natd_t *ike_natd_create(ike_sa_t *ike_sa, bool initiator) this->dst_seen = FALSE; this->src_matched = FALSE; this->dst_matched = FALSE; + this->mapping_changed = FALSE; return &this->public; } diff --git a/src/charon/sa/tasks/ike_natd.h b/src/charon/sa/tasks/ike_natd.h index 793408797..cb132d0c2 100644 --- a/src/charon/sa/tasks/ike_natd.h +++ b/src/charon/sa/tasks/ike_natd.h @@ -38,6 +38,15 @@ struct ike_natd_t { * Implements the task_t interface */ task_t task; + + /** + * Check if the NAT mapping has changed for our address. + * + * MOBIKE uses NAT payloads in DPD to detect changes in the NAT mappings. + * + * @return TRUE if mappings have changed + */ + bool (*has_mapping_changed)(ike_natd_t *this); }; /** |