summaryrefslogtreecommitdiff
path: root/src/charon/sa/tasks/ike_natd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/tasks/ike_natd.c')
-rw-r--r--src/charon/sa/tasks/ike_natd.c78
1 files changed, 48 insertions, 30 deletions
diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c
index 50b5d652b..84a28d024 100644
--- a/src/charon/sa/tasks/ike_natd.c
+++ b/src/charon/sa/tasks/ike_natd.c
@@ -203,14 +203,12 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
if (this->src_seen && this->dst_seen)
{
- if (!this->dst_matched)
- {
- this->ike_sa->enable_natt(this->ike_sa, TRUE);
- }
- if (!this->src_matched)
- {
- this->ike_sa->enable_natt(this->ike_sa, FALSE);
- }
+ this->ike_sa->enable_extension(this->ike_sa, EXT_NATT);
+
+ this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE,
+ !this->dst_matched);
+ this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE,
+ !this->src_matched);
}
}
@@ -220,8 +218,11 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
static status_t process_i(private_ike_natd_t *this, message_t *message)
{
process_payloads(this, message);
-
- if (this->ike_sa->is_natt_enabled(this->ike_sa))
+
+ /* if peer supports NAT-T, we switch to port 4500 even
+ * if no NAT is detected. MOBIKE requires this. */
+ if (message->get_exchange_type(message) == IKE_SA_INIT &&
+ this->ike_sa->supports_extension(this->ike_sa, EXT_NATT))
{
host_t *me, *other;
@@ -240,33 +241,49 @@ static status_t process_i(private_ike_natd_t *this, message_t *message)
static status_t build_i(private_ike_natd_t *this, message_t *message)
{
notify_payload_t *notify;
- linked_list_t *list;
+ iterator_t *iterator;
host_t *host;
- /* include one notify if our address is defined, all addresses otherwise */
+ /* destination is always set */
+ host = this->ike_sa->get_other_host(this->ike_sa);
+ notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host);
+ message->add_payload(message, (payload_t*)notify);
+
+ /* source may be any, we have 3 possibilities to get our source address:
+ * 1. It is defined in the config => use the one of the IKE_SA
+ * 2. We do a routing lookup in the kernel interface
+ * 3. Include all possbile addresses
+ */
host = this->ike_sa->get_my_host(this->ike_sa);
- if (host->is_anyaddr(host))
+ if (!host->is_anyaddr(host))
+ { /* 1. */
+ notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
+ message->add_payload(message, (payload_t*)notify);
+ }
+ else
{
- /* TODO: we could get the src address from netlink!? */
- list = charon->kernel_interface->create_address_list(charon->kernel_interface);
- while (list->remove_first(list, (void**)&host) == SUCCESS)
- {
+ host = charon->kernel_interface->get_source_addr(
+ charon->kernel_interface,
+ this->ike_sa->get_other_host(this->ike_sa));
+ if (host)
+ { /* 2. */
+ host->set_port(host, IKEV2_UDP_PORT);
notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
- host->destroy(host);
message->add_payload(message, (payload_t*)notify);
+ host->destroy(host);
+ }
+ else
+ { /* 3. */
+ iterator = charon->kernel_interface->create_address_iterator(
+ charon->kernel_interface);
+ while (iterator->iterate(iterator, (void**)&host))
+ {
+ notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
+ message->add_payload(message, (payload_t*)notify);
+ }
+ iterator->destroy(iterator);
}
- list->destroy(list);
- }
- else
- {
- notify = build_natd_payload(this, NAT_DETECTION_SOURCE_IP, host);
- message->add_payload(message, (payload_t*)notify);
}
-
- host = this->ike_sa->get_other_host(this->ike_sa);
- notify = build_natd_payload(this, NAT_DETECTION_DESTINATION_IP, host);
- message->add_payload(message, (payload_t*)notify);
-
return NEED_MORE;
}
@@ -279,7 +296,8 @@ static status_t build_r(private_ike_natd_t *this, message_t *message)
host_t *me, *other;
/* only add notifies on successfull responses. */
- if (message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
+ if (message->get_exchange_type(message) == IKE_SA_INIT &&
+ message->get_payload(message, SECURITY_ASSOCIATION) == NULL)
{
return SUCCESS;
}