From 3bf0be6b0846f357f3d7ae7bd017f5716a293a71 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 30 Nov 2011 18:03:06 +0100 Subject: [PATCH] Add NAT-OA payloads during Quick Mode if transport mode is used. We don't parse them currently, as the Linux kernel does not need them to fix the IP header checksum. --- src/libcharon/sa/tasks/quick_mode.c | 46 +++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/libcharon/sa/tasks/quick_mode.c b/src/libcharon/sa/tasks/quick_mode.c index 3fd21aecb..472aad8c6 100644 --- a/src/libcharon/sa/tasks/quick_mode.c +++ b/src/libcharon/sa/tasks/quick_mode.c @@ -403,6 +403,34 @@ static bool get_ts(private_quick_mode_t *this, message_t *message) return TRUE; } +/** + * Add NAT-OA payloads + */ +static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message) +{ + identification_t *id; + id_payload_t *nat_oa; + host_t *src, *dst; + + src = message->get_source(message); + dst = message->get_destination(message); + + src = this->initiator ? src : dst; + dst = this->initiator ? dst : src; + + /* first NAT-OA is the initiator's address */ + id = identification_create_from_sockaddr(src->get_sockaddr(src)); + nat_oa = id_payload_create_from_identification(NAT_OA_V1, id); + message->add_payload(message, (payload_t*)nat_oa); + id->destroy(id); + + /* second NAT-OA is that of the responder */ + id = identification_create_from_sockaddr(dst->get_sockaddr(dst)); + nat_oa = id_payload_create_from_identification(NAT_OA_V1, id); + message->add_payload(message, (payload_t*)nat_oa); + id->destroy(id); +} + /** * Look up lifetimes */ @@ -457,6 +485,7 @@ METHOD(task_t, build_i, status_t, sa_payload_t *sa_payload; linked_list_t *list; proposal_t *proposal; + ipsec_mode_t mode; bool udp = FALSE; this->child_sa = child_sa_create( @@ -479,15 +508,21 @@ METHOD(task_t, build_i, status_t, } enumerator->destroy(enumerator); + mode = this->config->get_mode(this->config); if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) { udp = TRUE; + /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */ + if (mode == MODE_TRANSPORT) + { + add_nat_oa_payloads(this, message); + } } get_lifetimes(this); sa_payload = sa_payload_create_from_proposals_v1(list, this->lifetime, this->lifebytes, AUTH_NONE, - this->config->get_mode(this->config), udp); + mode, udp); list->destroy_offset(list, offsetof(proposal_t, destroy)); message->add_payload(message, &sa_payload->payload_interface); @@ -609,6 +644,7 @@ METHOD(task_t, build_r, status_t, case QM_INIT: { sa_payload_t *sa_payload; + ipsec_mode_t mode; bool udp = FALSE; this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP); @@ -619,14 +655,20 @@ METHOD(task_t, build_r, status_t, } this->proposal->set_spi(this->proposal, this->spi_r); + mode = this->config->get_mode(this->config); if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)) { udp = TRUE; + /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */ + if (mode == MODE_TRANSPORT) + { + add_nat_oa_payloads(this, message); + } } sa_payload = sa_payload_create_from_proposal_v1(this->proposal, this->lifetime, this->lifebytes, AUTH_NONE, - this->config->get_mode(this->config), udp); + mode, udp); message->add_payload(message, &sa_payload->payload_interface); if (!add_nonce(this, &this->nonce_r, message))