use MOBIKE enabled DPD if we are NATed

update SAs if we detect changes in NAT mappings
This commit is contained in:
Martin Willi
2008-10-06 13:37:04 +00:00
parent 0592212f23
commit 9d9a772ee1
6 changed files with 113 additions and 4 deletions
+40 -1
View File
@@ -254,6 +254,11 @@ struct private_ike_sa_t {
*/ */
linked_list_t *additional_addresses; linked_list_t *additional_addresses;
/**
* previously value of received DESTINATION_IP hash
*/
chunk_t nat_detection_dest;
/** /**
* number pending UPDATE_SA_ADDRESS (MOBIKE) * number pending UPDATE_SA_ADDRESS (MOBIKE)
*/ */
@@ -626,8 +631,20 @@ static status_t send_dpd(private_ike_sa_t *this)
{ {
/* to long ago, initiate dead peer detection */ /* to long ago, initiate dead peer detection */
task_t *task; 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; diff = 0;
DBG1(DBG_IKE, "sending DPD request"); DBG1(DBG_IKE, "sending DPD request");
@@ -818,6 +835,25 @@ static iterator_t* create_additional_address_iterator(private_ike_sa_t *this)
this->additional_addresses, TRUE); 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. * 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); DESTROY_IF(this->server_reflexive_host);
chunk_free(&this->connect_id); chunk_free(&this->connect_id);
#endif /* ME */ #endif /* ME */
free(this->nat_detection_dest.ptr);
DESTROY_IF(this->my_host); DESTROY_IF(this->my_host);
DESTROY_IF(this->other_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.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.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.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.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit;
this->public.delete = (status_t (*)(ike_sa_t*))delete_; this->public.delete = (status_t (*)(ike_sa_t*))delete_;
this->public.destroy = (void (*)(ike_sa_t*))destroy; 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->other_virtual_ip = NULL;
this->dns_servers = linked_list_create(); this->dns_servers = linked_list_create();
this->additional_addresses = linked_list_create(); this->additional_addresses = linked_list_create();
this->nat_detection_dest = chunk_empty;
this->pending_updates = 0; this->pending_updates = 0;
this->keyingtry = 0; this->keyingtry = 0;
this->ike_initiator = FALSE; this->ike_initiator = FALSE;
+8
View File
@@ -406,6 +406,14 @@ struct ike_sa_t {
*/ */
iterator_t* (*create_additional_address_iterator)(ike_sa_t *this); 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. * Enable an extension the peer supports.
* *
+23 -1
View File
@@ -434,7 +434,7 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message)
return SUCCESS; return SUCCESS;
} }
if (this->cookie2.ptr) if (this->cookie2.ptr)
{ /* check cookie if we included none */ { /* check cookie if we included one */
chunk_t cookie2; chunk_t cookie2;
cookie2 = this->cookie2; cookie2 = this->cookie2;
@@ -455,6 +455,13 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message)
if (this->natd) if (this->natd)
{ {
this->natd->task.process(&this->natd->task, message); 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) if (this->update)
{ {
@@ -506,6 +513,20 @@ static void roam(private_ike_mobike_t *this, bool address)
this->ike_sa->get_pending_updates(this->ike_sa) + 1); this->ike_sa->get_pending_updates(this->ike_sa) + 1);
} }
/**
* 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. * Implementation of ike_mobike_t.is_probing.
*/ */
@@ -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); private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t);
this->public.roam = (void(*)(ike_mobike_t*,bool))roam; 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.transmit = (void(*)(ike_mobike_t*,packet_t*))transmit;
this->public.is_probing = (bool(*)(ike_mobike_t*))is_probing; this->public.is_probing = (bool(*)(ike_mobike_t*))is_probing;
this->public.task.get_type = (task_type_t(*)(task_t*))get_type; this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
+5
View File
@@ -54,6 +54,11 @@ struct ike_mobike_t {
*/ */
void (*roam)(ike_mobike_t *this, bool address); 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. * Transmision hook, called by task manager.
* *
+27 -1
View File
@@ -72,6 +72,11 @@ struct private_ike_natd_t {
* Have we found a matching destination address NAT hash? * Have we found a matching destination address NAT hash?
*/ */
bool dst_matched; 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: case NAT_DETECTION_DESTINATION_IP:
{ {
this->dst_seen = TRUE; this->dst_seen = TRUE;
hash = notify->get_notification_data(notify);
if (!this->dst_matched) if (!this->dst_matched)
{ {
hash = notify->get_notification_data(notify);
DBG3(DBG_IKE, "received dst_hash %B", &hash); DBG3(DBG_IKE, "received dst_hash %B", &hash);
if (chunk_equals(hash, dst_hash)) if (chunk_equals(hash, dst_hash))
{ {
this->dst_matched = TRUE; 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; break;
} }
case NAT_DETECTION_SOURCE_IP: 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->dst_seen = FALSE;
this->src_matched = FALSE; this->src_matched = FALSE;
this->dst_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.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->ike_sa = ike_sa;
this->initiator = initiator; this->initiator = initiator;
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); 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->dst_seen = FALSE;
this->src_matched = FALSE; this->src_matched = FALSE;
this->dst_matched = FALSE; this->dst_matched = FALSE;
this->mapping_changed = FALSE;
return &this->public; return &this->public;
} }
+9
View File
@@ -38,6 +38,15 @@ struct ike_natd_t {
* Implements the task_t interface * Implements the task_t interface
*/ */
task_t task; 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);
}; };
/** /**