diff options
author | Martin Willi <martin@strongswan.org> | 2007-06-26 13:04:13 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2007-06-26 13:04:13 +0000 |
commit | 2b3100b5d075d0146570174dd70fa9e9ff775479 (patch) | |
tree | b9c5d1898da751901cae6dfae1352a636aed77a4 | |
parent | 361712fe37cddd7f056e6316a5baca125d08aa8c (diff) | |
download | strongswan-2b3100b5d075d0146570174dd70fa9e9ff775479.tar.bz2 strongswan-2b3100b5d075d0146570174dd70fa9e9ff775479.tar.xz |
simple roaming of the client works (not MOBIKE conform yet!)
-rw-r--r-- | src/charon/kernel/kernel_interface.c | 47 | ||||
-rw-r--r-- | src/charon/kernel/kernel_interface.h | 17 | ||||
-rw-r--r-- | src/charon/sa/child_sa.c | 154 | ||||
-rw-r--r-- | src/charon/sa/child_sa.h | 17 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 288 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.h | 11 | ||||
-rw-r--r-- | src/charon/sa/task_manager.c | 2 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.c | 17 |
8 files changed, 250 insertions, 303 deletions
diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index bf5479bfe..76b488eee 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -1393,10 +1393,10 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest) msg = (struct rtmsg*)NLMSG_DATA(hdr); msg->rtm_family = dest->get_family(dest); msg->rtm_dst_len = msg->rtm_family == AF_INET ? 32 : 128; - msg->rtm_table = RT_TABLE_UNSPEC; - msg->rtm_protocol = RTPROT_UNSPEC; + msg->rtm_table = RT_TABLE_MAIN; + msg->rtm_protocol = RTPROT_STATIC; msg->rtm_type = RTN_UNICAST; - msg->rtm_scope = RT_SCOPE_HOST; + msg->rtm_scope = RT_SCOPE_UNIVERSE; chunk = dest->get_address(dest); add_attribute(hdr, RTA_DST, chunk, sizeof(request)); @@ -1443,12 +1443,11 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest) break; } free(out); - if (source) + if (source == NULL) { - return source; + DBG2(DBG_KNL, "no route found to %H", dest); } - DBG2(DBG_KNL, "no route found to %H", dest); - return NULL; + return source; } /** @@ -1784,10 +1783,9 @@ static status_t add_sa(private_kernel_interface_t *this, * Implementation of kernel_interface_t.update_sa. */ static status_t update_sa(private_kernel_interface_t *this, - host_t *dst, u_int32_t spi, - protocol_id_t protocol, - host_t *new_src, host_t *new_dst, - host_diff_t src_changes, host_diff_t dst_changes) + u_int32_t spi, protocol_id_t protocol, + host_t *src, host_t *dst, + host_t *new_src, host_t *new_dst) { unsigned char request[BUFFER_SIZE]; struct nlmsghdr *hdr, *out = NULL; @@ -1797,8 +1795,9 @@ static status_t update_sa(private_kernel_interface_t *this, memset(&request, 0, sizeof(request)); - DBG2(DBG_KNL, "querying SAD entry with SPI 0x%x", spi); + DBG2(DBG_KNL, "querying SAD entry with SPI 0x%x for update", spi); + /* query the exisiting SA first */ hdr = (struct nlmsghdr*)request; hdr->nlmsg_flags = NLM_F_REQUEST; hdr->nlmsg_type = XFRM_MSG_GETSA; @@ -1838,31 +1837,33 @@ static status_t update_sa(private_kernel_interface_t *this, break; } } - if (sa == NULL) + if (sa == NULL || + this->public.del_sa(&this->public, dst, spi, protocol) != SUCCESS) { DBG1(DBG_KNL, "unable to update SAD entry with SPI 0x%x", spi); free(out); return FAILED; } - DBG2(DBG_KNL, "updating SAD entry with SPI 0x%x", spi); + DBG2(DBG_KNL, "updating SAD entry with SPI 0x%x from %#H..%#H to %#H..%#H", + spi, src, dst, new_src, new_dst); + /* update the values in the queried SA */ hdr = out; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - hdr->nlmsg_type = XFRM_MSG_UPDSA; + hdr->nlmsg_type = XFRM_MSG_NEWSA; - if (src_changes & HOST_DIFF_ADDR) + if (!src->ip_equals(src, new_src)) { host2xfrm(new_src, &sa->saddr); } - - if (dst_changes & HOST_DIFF_ADDR) + if (!dst->ip_equals(dst, new_dst)) { - hdr->nlmsg_type = XFRM_MSG_NEWSA; host2xfrm(new_dst, &sa->id.daddr); } - if (src_changes & HOST_DIFF_PORT || dst_changes & HOST_DIFF_PORT) + if (src->get_port(src) != new_src->get_port(new_src) || + dst->get_port(dst) != new_dst->get_port(new_dst)) { struct rtattr *rtattr = XFRM_RTA(hdr, struct xfrm_usersa_info); size_t rtsize = XFRM_PAYLOAD(hdr, struct xfrm_usersa_info); @@ -1887,10 +1888,6 @@ static status_t update_sa(private_kernel_interface_t *this, } free(out); - if (dst_changes & HOST_DIFF_ADDR) - { - return this->public.del_sa(&this->public, dst, spi, protocol); - } return SUCCESS; } @@ -2318,7 +2315,7 @@ kernel_interface_t *kernel_interface_create() /* public functions */ this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_t,algorithm_t*,algorithm_t*,prf_plus_t*,natt_conf_t*,mode_t,bool))add_sa; - this->public.update_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_diff_t,host_diff_t))update_sa; + this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,host_t*,host_t*,host_t*,host_t*))update_sa; this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t*))query_sa; this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa; this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,traffic_selector_t*,traffic_selector_t*,policy_dir_t,protocol_id_t,u_int32_t,bool,mode_t,bool))add_policy; diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h index 62acb45bd..d3d3c9b70 100644 --- a/src/charon/kernel/kernel_interface.h +++ b/src/charon/kernel/kernel_interface.h @@ -145,21 +145,20 @@ struct kernel_interface_t { * create a new SA and delete the old one. * * @param this calling object - * @param dst destination address for this SA * @param spi SPI of the SA * @param protocol protocol for this SA (ESP/AH) - * @param new_src new source address for this SA - * @param new_dst new destination address for this SA - * @param src_changes changes in src - * @param dst_changes changes in dst + * @param src current source address + * @param dst current destination address + * @param new_src new source address + * @param new_dst new destination address * @return * - SUCCESS * - FAILED if kernel comm failed */ - status_t (*update_sa)(kernel_interface_t *this, host_t *dst, u_int32_t spi, - protocol_id_t protocol, - host_t *new_src, host_t *new_dst, - host_diff_t src_changes, host_diff_t dst_changes); + status_t (*update_sa)(kernel_interface_t *this, + u_int32_t spi, protocol_id_t protocol, + host_t *src, host_t *dst, + host_t *new_src, host_t *new_dst); /** * @brief Query the use time of an SA. diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index 1e7b6cb2c..e5cddf04f 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -782,139 +782,79 @@ static status_t get_use_time(private_child_sa_t *this, bool inbound, time_t *use } /** - * Update the host adress/port of a SA - */ -static status_t update_sa_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other, - int my_changes, int other_changes, bool mine) -{ - host_t *src, *dst, *new_src, *new_dst; - int src_changes, dst_changes; - status_t status; - u_int32_t spi; - - if (mine) - { - src = this->other.addr; - dst = this->me.addr; - new_src = new_other; - new_dst = new_me; - src_changes = other_changes; - dst_changes = my_changes; - spi = this->other.spi; - } - else - { - src = this->me.addr; - dst = this->other.addr; - new_src = new_me; - new_dst = new_other; - src_changes = my_changes; - dst_changes = other_changes; - spi = this->me.spi; - } - - DBG2(DBG_CHD, "updating %N SA 0x%x, from %#H..#H to %#H..%#H", - protocol_id_names, this->protocol, ntohl(spi), src, dst, new_src, new_dst); - - status = charon->kernel_interface->update_sa(charon->kernel_interface, - dst, spi, this->protocol, - new_src, new_dst, - src_changes, dst_changes); - - if (status != SUCCESS) - { - return FAILED; - } - return SUCCESS; -} - -/** - * Update the host adress/port of a policy - */ -static status_t update_policy_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other) -{ - iterator_t *iterator; - sa_policy_t *policy; - status_t status; - /* we always use high priorities, as hosts getting updated are INSTALLED */ - - iterator = this->policies->create_iterator(this->policies, TRUE); - while (iterator->iterate(iterator, (void**)&policy)) - { - status = charon->kernel_interface->add_policy( - charon->kernel_interface, - new_me, new_other, - policy->my_ts, policy->other_ts, - POLICY_OUT, this->protocol, this->reqid, TRUE, this->mode, TRUE); - - status |= charon->kernel_interface->add_policy( - charon->kernel_interface, - new_other, new_me, - policy->other_ts, policy->my_ts, - POLICY_IN, this->protocol, this->reqid, TRUE, this->mode, TRUE); - - status |= charon->kernel_interface->add_policy( - charon->kernel_interface, - new_other, new_me, - policy->other_ts, policy->my_ts, - POLICY_FWD, this->protocol, this->reqid, TRUE, this->mode, TRUE); - - if (status != SUCCESS) - { - iterator->destroy(iterator); - return FAILED; - } - } - iterator->destroy(iterator); - - return SUCCESS; -} - -/** * Implementation of child_sa_t.update_hosts. */ -static status_t update_hosts(private_child_sa_t *this, host_t *new_me, host_t *new_other, - host_diff_t my_changes, host_diff_t other_changes) +static status_t update_hosts(private_child_sa_t *this, host_t *me, host_t *other) { - if (!my_changes && !other_changes) + /* anything changed at all? */ + if (me->equals(me, this->me.addr) && other->equals(other, this->other.addr)) { return SUCCESS; } - + /* update our (initator) SAs */ - if (update_sa_hosts(this, new_me, new_other, my_changes, other_changes, TRUE) != SUCCESS) + if (charon->kernel_interface->update_sa( + charon->kernel_interface, this->me.spi, this->protocol, + this->other.addr, this->me.addr, other, me) != SUCCESS) { return FAILED; } /* update his (responder) SAs */ - if (update_sa_hosts(this, new_me, new_other, my_changes, other_changes, FALSE) != SUCCESS) + if (charon->kernel_interface->update_sa( + charon->kernel_interface, this->other.spi, this->protocol, + this->me.addr, this->other.addr, me, other) != SUCCESS) { return FAILED; } /* update policies */ - if (my_changes & HOST_DIFF_ADDR || other_changes & HOST_DIFF_ADDR) + if (!me->ip_equals(me, this->me.addr) || + !other->ip_equals(other, this->other.addr)) { - if (update_policy_hosts(this, new_me, new_other) != SUCCESS) + iterator_t *iterator; + sa_policy_t *policy; + status_t status; + + /* always use high priorities, as hosts getting updated are INSTALLED */ + iterator = this->policies->create_iterator(this->policies, TRUE); + while (iterator->iterate(iterator, (void**)&policy)) { - return FAILED; + status = charon->kernel_interface->add_policy( + charon->kernel_interface, me, other, + policy->my_ts, policy->other_ts, POLICY_OUT, + this->protocol, this->reqid, TRUE, this->mode, TRUE); + + status |= charon->kernel_interface->add_policy( + charon->kernel_interface, other, me, + policy->other_ts, policy->my_ts, POLICY_IN, + this->protocol, this->reqid, TRUE, this->mode, TRUE); + + status |= charon->kernel_interface->add_policy( + charon->kernel_interface, other, me, + policy->other_ts, policy->my_ts, POLICY_FWD, + this->protocol, this->reqid, TRUE, this->mode, TRUE); + + if (status != SUCCESS) + { + iterator->destroy(iterator); + return FAILED; + } } + iterator->destroy(iterator); } - /* update hosts */ - if (my_changes) + /* finally apply hosts */ + if (!me->equals(me, this->me.addr)) { this->me.addr->destroy(this->me.addr); - this->me.addr = new_me->clone(new_me); + this->me.addr = me->clone(me); } - - if (other_changes) + if (other->equals(other, this->other.addr)) { this->other.addr->destroy(this->other.addr); - this->other.addr = new_other->clone(new_other); - } - + this->other.addr = other->clone(other); + } return SUCCESS; } @@ -1011,7 +951,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc; this->public.add = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))add; this->public.update = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))update; - this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))update_hosts; + this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*))update_hosts; this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,mode_t))add_policies; this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors; this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time; diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h index cf5f3e7d7..0118df49f 100644 --- a/src/charon/sa/child_sa.h +++ b/src/charon/sa/child_sa.h @@ -200,19 +200,16 @@ struct child_sa_t { prf_plus_t *prf_plus); /** - * @brief Update the hosts in the kernel SAs and policies + * @brief Update the hosts in the kernel SAs and policies. * - * @warning only call this after update() has been called. + * The CHILD must be INSTALLED to do this update. * - * @param this calling object - * @param new_me the new local host - * @param new_other the new remote host - * @param my_diff differences to apply for me - * @param other_diff differences to apply for other - * @return SUCCESS or FAILED + * @param this calling object + * @param me the new local host + * @param other the new remote host + * @return SUCCESS or FAILED */ - status_t (*update_hosts)(child_sa_t *this, host_t *new_me, host_t *new_other, - host_diff_t my_diff, host_diff_t other_diff); + status_t (*update_hosts)(child_sa_t *this, host_t *me, host_t *other); /** * @brief Install the policies using some traffic selectors. diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 5406cb70e..1d6b8ec01 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -386,6 +386,40 @@ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg) } /** + * Implementation of ike_sa_t.send_keepalive + */ +static void send_keepalive(private_ike_sa_t *this) +{ + send_keepalive_job_t *job; + time_t last_out, now, diff; + + last_out = get_use_time(this, FALSE); + now = time(NULL); + + diff = now - last_out; + + if (diff >= KEEPALIVE_INTERVAL) + { + packet_t *packet; + chunk_t data; + + packet = packet_create(); + packet->set_source(packet, this->my_host->clone(this->my_host)); + packet->set_destination(packet, this->other_host->clone(this->other_host)); + data.ptr = malloc(1); + data.ptr[0] = 0xFF; + data.len = 1; + packet->set_data(packet, data); + charon->sender->send(charon->sender, packet); + DBG1(DBG_IKE, "sending keep alive"); + diff = 0; + } + job = send_keepalive_job_create(this->ike_sa_id); + charon->scheduler->schedule_job(charon->scheduler, (job_t*)job, + (KEEPALIVE_INTERVAL - diff) * 1000); +} + +/** * Implementation of ike_sa_t.get_ike_cfg */ static ike_cfg_t *get_ike_cfg(private_ike_sa_t *this) @@ -401,6 +435,74 @@ static void set_ike_cfg(private_ike_sa_t *this, ike_cfg_t *ike_cfg) ike_cfg->get_ref(ike_cfg); this->ike_cfg = ike_cfg; } +/** + * Implementation of ike_sa_t.enable_extension. + */ +static void enable_extension(private_ike_sa_t *this, ike_extension_t extension) +{ + this->extensions |= extension; +} + +/** + * Implementation of ike_sa_t.has_extension. + */ +static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension) +{ + return (this->extensions & extension) != FALSE; +} + +/** + * Implementation of ike_sa_t.has_condition. + */ +static bool has_condition(private_ike_sa_t *this, ike_condition_t condition) +{ + return (this->conditions & condition) != FALSE; +} + +/** + * Implementation of ike_sa_t.enable_condition. + */ +static void set_condition(private_ike_sa_t *this, ike_condition_t condition, + bool enable) +{ + if (has_condition(this, condition) != enable) + { + if (enable) + { + switch (condition) + { + case COND_STALE: + DBG1(DBG_IKE, "no route to %H, setting IKE_SA to stale", + this->other_host); + break; + case COND_NAT_HERE: + DBG1(DBG_IKE, "local host is behind NAT, sending keep alives"); + this->conditions |= COND_NAT_ANY; + send_keepalive(this); + break; + case COND_NAT_THERE: + DBG1(DBG_IKE, "remote host is behind NAT"); + this->conditions |= COND_NAT_ANY; + break; + default: + break; + } + this->conditions |= condition; + } + else + { + switch (condition) + { + case COND_STALE: + DBG1(DBG_IKE, "new route to %H found", this->other_host); + break; + default: + break; + } + this->conditions &= ~condition; + } + } +} /** * Implementation of ike_sa_t.send_dpd @@ -451,40 +553,6 @@ static status_t send_dpd(private_ike_sa_t *this) } /** - * Implementation of ike_sa_t.send_keepalive - */ -static void send_keepalive(private_ike_sa_t *this) -{ - send_keepalive_job_t *job; - time_t last_out, now, diff; - - last_out = get_use_time(this, FALSE); - now = time(NULL); - - diff = now - last_out; - - if (diff >= KEEPALIVE_INTERVAL) - { - packet_t *packet; - chunk_t data; - - packet = packet_create(); - packet->set_source(packet, this->my_host->clone(this->my_host)); - packet->set_destination(packet, this->other_host->clone(this->other_host)); - data.ptr = malloc(1); - data.ptr[0] = 0xFF; - data.len = 1; - packet->set_data(packet, data); - charon->sender->send(charon->sender, packet); - DBG1(DBG_IKE, "sending keep alive"); - diff = 0; - } - job = send_keepalive_job_create(this->ike_sa_id); - charon->scheduler->schedule_job(charon->scheduler, (job_t*)job, - (KEEPALIVE_INTERVAL - diff) * 1000); -} - -/** * Implementation of ike_sa_t.get_state. */ static ike_sa_state_t get_state(private_ike_sa_t *this) @@ -577,63 +645,60 @@ static void reset(private_ike_sa_t *this) */ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other) { - iterator_t *iterator = NULL; - child_sa_t *child_sa = NULL; - host_diff_t my_diff, other_diff; + bool update = FALSE; - if (this->my_host->is_anyaddr(this->my_host) || - this->other_host->is_anyaddr(this->other_host)) + if (me == NULL) { - /* on first received message */ - this->my_host->destroy(this->my_host); - this->my_host = me->clone(me); - this->other_host->destroy(this->other_host); - this->other_host = other->clone(other); - return; + me = this->my_host; } - - my_diff = me->get_differences(me, this->my_host); - other_diff = other->get_differences(other, this->other_host); - - if (!my_diff && !other_diff) + if (other == NULL) { - return; + other = this->other_host; } - if (my_diff) - { - this->my_host->destroy(this->my_host); - this->my_host = me->clone(me); - } - - if (!(this->conditions & COND_NAT_THERE)) + /* apply hosts on first received message */ + if (this->my_host->is_anyaddr(this->my_host) || + this->other_host->is_anyaddr(this->other_host)) { - /* update without restrictions if we are not NATted */ - if (other_diff) - { - this->other_host->destroy(this->other_host); - this->other_host = other->clone(other); - } + set_my_host(this, me->clone(me)); + set_other_host(this, other->clone(other)); + update = TRUE; } else { - /* if we are natted, only port may change */ - if (other_diff & HOST_DIFF_ADDR) + /* update our address in any case */ + if (!me->equals(me, this->my_host)) { - return; + set_my_host(this, me->clone(me)); + update = TRUE; } - else if (other_diff & HOST_DIFF_PORT) + + if (!other->equals(other, this->other_host)) { - this->other_host->set_port(this->other_host, other->get_port(other)); + /* update others adress if we are NOT NATed, + * and allow port changes if we are NATed */ + if (!has_condition(this, COND_NAT_HERE) || + other->ip_equals(other, this->other_host)) + { + set_other_host(this, other->clone(other)); + update = TRUE; + } } } - iterator = this->child_sas->create_iterator(this->child_sas, TRUE); - while (iterator->iterate(iterator, (void**)&child_sa)) + + /* update all associated CHILD_SAs, if required */ + if (update) { - child_sa->update_hosts(child_sa, this->my_host, this->other_host, - my_diff, other_diff); + iterator_t *iterator; + child_sa_t *child_sa; + + iterator = this->child_sas->create_iterator(this->child_sas, TRUE); + while (iterator->iterate(iterator, (void**)&child_sa)) + { + child_sa->update_hosts(child_sa, this->my_host, this->other_host); + } + iterator->destroy(iterator); } - iterator->destroy(iterator); } /** @@ -1249,75 +1314,6 @@ static host_t* get_virtual_ip(private_ike_sa_t *this, bool local) } /** - * Implementation of ike_sa_t.enable_extension. - */ -static void enable_extension(private_ike_sa_t *this, ike_extension_t extension) -{ - this->extensions |= extension; -} - -/** - * Implementation of ike_sa_t.has_extension. - */ -static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension) -{ - return (this->extensions & extension) != FALSE; -} - -/** - * Implementation of ike_sa_t.has_condition. - */ -static bool has_condition(private_ike_sa_t *this, ike_condition_t condition) -{ - return (this->conditions & condition) != FALSE; -} - -/** - * Implementation of ike_sa_t.enable_condition. - */ -static void set_condition(private_ike_sa_t *this, ike_condition_t condition, - bool enable) -{ - if (has_condition(this, condition) != enable) - { - if (enable) - { - switch (condition) - { - case COND_STALE: - DBG1(DBG_IKE, "no route to %H, setting IKE_SA to stale", - this->other_host); - break; - case COND_NAT_HERE: - DBG1(DBG_IKE, "local host is behind NAT, sending keep alives"); - this->conditions |= COND_NAT_ANY; - send_keepalive(this); - break; - case COND_NAT_THERE: - DBG1(DBG_IKE, "remote host is behind NAT"); - this->conditions |= COND_NAT_ANY; - break; - default: - break; - } - this->conditions |= condition; - } - else - { - switch (condition) - { - case COND_STALE: - DBG1(DBG_IKE, "new route to %H found", this->other_host); - break; - default: - break; - } - this->conditions &= ~condition; - } - } -} - -/** * Implementation of ike_sa_t.add_additional_address. */ static void add_additional_address(private_ike_sa_t *this, host_t *host) @@ -1682,7 +1678,7 @@ static status_t roam(private_ike_sa_t *this) me = charon->kernel_interface->get_source_addr(charon->kernel_interface, this->other_host); - if (me && me->ip_equals(me, this->my_virtual_ip)) + if (me && this->my_virtual_ip && me->ip_equals(me, this->my_virtual_ip)) { /* do not roam to the virtual IP of this IKE_SA */ me->destroy(me); me = NULL; @@ -1704,11 +1700,13 @@ static status_t roam(private_ike_sa_t *this) /* our attachement changed, update if we have mobike */ if (supports_extension(this, EXT_MOBIKE)) { + DBG1(DBG_IKE, "requesting address change using MOBIKE"); mobike = ike_mobike_create(&this->public, TRUE); mobike->roam(mobike, me, NULL); this->task_manager->queue_task(this->task_manager, (task_t*)mobike); return this->task_manager->initiate(this->task_manager); } + DBG1(DBG_IKE, "reestablishing IKE_SA due address change"); /* reestablish if not */ set_my_host(this, me); return reestablish(this); @@ -1736,6 +1734,7 @@ static status_t roam(private_ike_sa_t *this) if (me) { /* good, we have a new route. Use MOBIKE to update */ + set_condition(this, COND_STALE, FALSE); iterator->destroy(iterator); me->set_port(me, this->my_host->get_port(this->my_host)); other->set_port(other, this->other_host->get_port(this->other_host)); @@ -2006,6 +2005,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->public.set_my_host = (void (*)(ike_sa_t*,host_t*)) set_my_host; this->public.get_other_host = (host_t* (*)(ike_sa_t*)) get_other_host; this->public.set_other_host = (void (*)(ike_sa_t*,host_t*)) set_other_host; + this->public.update_hosts = (void(*)(ike_sa_t*, host_t *me, host_t *other))update_hosts; this->public.get_my_id = (identification_t* (*)(ike_sa_t*)) get_my_id; this->public.set_my_id = (void (*)(ike_sa_t*,identification_t*)) set_my_id; this->public.get_other_id = (identification_t* (*)(ike_sa_t*)) get_other_id; diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index f4ca5ae69..b7eceedd2 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -283,6 +283,17 @@ struct ike_sa_t { void (*set_other_host) (ike_sa_t *this, host_t *other); /** + * @brief Update the IKE_SAs host. + * + * Hosts may be NULL to use current host. + * + * @param this calling object + * @param me new local host address, or NULL + * @param other new remote host address, or NULL + */ + void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other); + + /** * @brief Get the own identification. * * @param this calling object diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c index fc2a13061..6d77e3be8 100644 --- a/src/charon/sa/task_manager.c +++ b/src/charon/sa/task_manager.c @@ -355,6 +355,8 @@ static status_t build_request(private_task_manager_t *this) case IKE_REKEY: exchange = CREATE_CHILD_SA; break; + case IKE_MOBIKE: + exchange = INFORMATIONAL; default: continue; } diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c index a7f5fb6d6..43ede2e57 100644 --- a/src/charon/sa/tasks/ike_mobike.c +++ b/src/charon/sa/tasks/ike_mobike.c @@ -208,14 +208,7 @@ static status_t build_i(private_ike_mobike_t *this, message_t *message) /* TODO: NAT discovery */ /* set new addresses */ - if (this->me) - { - this->ike_sa->set_my_host(this->ike_sa, this->me->clone(this->me)); - } - if (this->other) - { - this->ike_sa->set_other_host(this->ike_sa, this->other->clone(this->other)); - } + this->ike_sa->update_hosts(this->ike_sa, this->me, this->other); } return NEED_MORE; @@ -251,6 +244,10 @@ static status_t build_r(private_ike_mobike_t *this, message_t *message) } return SUCCESS; } + else if (message->get_exchange_type(message) == INFORMATIONAL) + { + return SUCCESS; + } return NEED_MORE; } @@ -265,6 +262,10 @@ static status_t process_i(private_ike_mobike_t *this, message_t *message) process_payloads(this, message); return SUCCESS; } + else if (message->get_exchange_type(message) == INFORMATIONAL) + { + return SUCCESS; + } return NEED_MORE; } |