}
else
{
- ike_sa->update_hosts(ike_sa, NULL, this->new, FALSE);
+ ike_sa->update_hosts(ike_sa, NULL, this->new, 0);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
return JOB_REQUEUE_NONE;
}
METHOD(ike_sa_t, update_hosts, void,
- private_ike_sa_t *this, host_t *me, host_t *other, bool force)
+ private_ike_sa_t *this, host_t *me, host_t *other, update_hosts_flag_t flags)
{
host_t *new_me = NULL, *new_other = NULL;
bool silent = FALSE;
}
else
{
- /* update our address in any case */
- if (force && !me->equals(me, this->my_host))
+ /* update our address only if forced */
+ if ((flags & UPDATE_HOSTS_FORCE_LOCAL) && !me->equals(me, this->my_host))
{
new_me = me;
}
if (!other->equals(other, this->other_host) &&
- (force || has_condition(this, COND_NAT_THERE)))
+ ((flags & UPDATE_HOSTS_FORCE_REMOTE) || has_condition(this, COND_NAT_THERE)))
{
/* only update other's address if we are behind a static NAT,
* which we assume is the case if we are not initiator */
- if (force ||
+ if ((flags & UPDATE_HOSTS_FORCE_REMOTE) ||
(!has_condition(this, COND_NAT_HERE) ||
!has_condition(this, COND_ORIGINAL_INITIATOR)))
{
}
}
- if (new_me || new_other)
+ if (new_me || new_other || (flags & UPDATE_HOSTS_FORCE_CHILDREN))
{
enumerator_t *enumerator;
child_sa_t *child_sa;
linked_list_t *vips;
- if (!silent)
+ if ((new_me || new_other) && !silent)
{
charon->bus->ike_update(charon->bus, &this->public,
new_me ?: this->my_host,
typedef enum ike_condition_t ike_condition_t;
typedef enum ike_sa_state_t ike_sa_state_t;
typedef enum statistic_t statistic_t;
+typedef enum update_hosts_flag_t update_hosts_flag_t;
typedef struct ike_sa_t ike_sa_t;
#include <library.h>
STAT_MAX
};
+/**
+ * Flags used when updating addresses
+ */
+enum update_hosts_flag_t {
+ /** Force updating the local address (otherwise not updated if an address
+ * is already set). */
+ UPDATE_HOSTS_FORCE_LOCAL = (1<<0),
+ /** Force updating the remote address (otherwise only updated if peer is
+ * behind a NAT). */
+ UPDATE_HOSTS_FORCE_REMOTE = (1<<1),
+ /** Force updating both addresses. */
+ UPDATE_HOSTS_FORCE_ADDRS = UPDATE_HOSTS_FORCE_LOCAL|UPDATE_HOSTS_FORCE_REMOTE,
+ /** Force updating the CHILD_SAs even if no addresses changed, useful if
+ * NAT state may have changed. */
+ UPDATE_HOSTS_FORCE_CHILDREN = (1<<2),
+ /** Force updating everything. */
+ UPDATE_HOSTS_FORCE_ALL = UPDATE_HOSTS_FORCE_ADDRS|UPDATE_HOSTS_FORCE_CHILDREN,
+};
+
/**
* State of an IKE_SA.
*
void (*float_ports)(ike_sa_t *this);
/**
- * Update the IKE_SAs host.
+ * Update the IKE_SAs host and CHILD_SAs.
*
* Hosts may be NULL to use current host.
*
* @param me new local host address, or NULL
* @param other new remote host address, or NULL
- * @param force force update
+ * @param flags flags to force certain updates
*/
- void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other, bool force);
+ void (*update_hosts)(ike_sa_t *this, host_t *me, host_t *other,
+ update_hosts_flag_t flags);
/**
* Get the own identification.
}
this->ike_sa->set_statistic(this->ike_sa, STAT_INBOUND,
time_monotonic(NULL));
- this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
+ this->ike_sa->update_hosts(this->ike_sa, me, other, UPDATE_HOSTS_FORCE_ADDRS);
charon->bus->message(charon->bus, msg, TRUE, TRUE);
if (process_response(this, msg) != SUCCESS)
{
"%s.half_open_timeout", HALF_OPEN_IKE_SA_TIMEOUT,
lib->ns));
}
- this->ike_sa->update_hosts(this->ike_sa, me, other, TRUE);
+ this->ike_sa->update_hosts(this->ike_sa, me, other, UPDATE_HOSTS_FORCE_ADDRS);
charon->bus->message(charon->bus, msg, TRUE, TRUE);
if (process_request(this, msg) != SUCCESS)
{
this->ike_sa->update_hosts(this->ike_sa,
message->get_destination(message),
- message->get_source(message), TRUE);
+ message->get_source(message),
+ UPDATE_HOSTS_FORCE_ADDRS);
sa_payload = (sa_payload_t*)message->get_payload(message,
PLV1_SECURITY_ASSOCIATION);
this->ike_sa->update_hosts(this->ike_sa,
message->get_destination(message),
- message->get_source(message), TRUE);
+ message->get_source(message),
+ UPDATE_HOSTS_FORCE_ADDRS);
sa_payload = (sa_payload_t*)message->get_payload(message,
PLV1_SECURITY_ASSOCIATION);
return FAILED;
}
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
- { /* with MOBIKE, we do no implicit updates */
- this->ike_sa->update_hosts(this->ike_sa, me, other, mid == 1);
+ { /* only do implicit updates without MOBIKE, and only force
+ * updates for IKE_AUTH (ports might change due to NAT-T) */
+ this->ike_sa->update_hosts(this->ike_sa, me, other,
+ mid == 1 ? UPDATE_HOSTS_FORCE_ADDRS : 0);
}
status = handle_fragment(this, &this->responding.defrag, msg);
if (status != SUCCESS)
msg->get_exchange_type(msg) != IKE_SA_INIT)
{ /* only do updates based on verified messages (or initial ones) */
if (!this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
- { /* with MOBIKE, we do no implicit updates. we force an
- * update of the local address on IKE_SA_INIT, but never
- * for the remote address */
- this->ike_sa->update_hosts(this->ike_sa, me, NULL, mid == 0);
- this->ike_sa->update_hosts(this->ike_sa, NULL, other, FALSE);
+ { /* only do implicit updates without MOBIKE, we force an
+ * update of the local address on IKE_SA_INIT as we might
+ * not know it yet, but never for the remote address */
+ this->ike_sa->update_hosts(this->ike_sa, me, other,
+ mid == 0 ? UPDATE_HOSTS_FORCE_LOCAL : 0);
}
}
status = handle_fragment(this, &this->initiating.defrag, msg);