diff options
Diffstat (limited to 'src/charon/sa/tasks/ike_natd.c')
-rw-r--r-- | src/charon/sa/tasks/ike_natd.c | 78 |
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; } |