From: Tobias Brunner Date: Tue, 27 Oct 2020 18:06:21 +0000 (+0100) Subject: ike-sa: Add flags to force updating hosts/CHILD_SAs X-Git-Tag: 5.9.2dr2~28^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=51c7cf9a04c61f655032b7fc53e801c160426f74;p=thirdparty%2Fstrongswan.git ike-sa: Add flags to force updating hosts/CHILD_SAs This allows more fine grained control over what's updated and does not require multiple calls of the method. Plus we'll be able to use it in the ike-mobike task. --- diff --git a/src/libcharon/processing/jobs/update_sa_job.c b/src/libcharon/processing/jobs/update_sa_job.c index dfb85f6905..6fe211357a 100644 --- a/src/libcharon/processing/jobs/update_sa_job.c +++ b/src/libcharon/processing/jobs/update_sa_job.c @@ -76,7 +76,7 @@ METHOD(job_t, execute, job_requeue_t, } 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; diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index b8fdcbb07d..24fb4cd23b 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -1114,7 +1114,7 @@ METHOD(ike_sa_t, float_ports, void, } 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; @@ -1138,18 +1138,18 @@ METHOD(ike_sa_t, update_hosts, void, } 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))) { @@ -1158,13 +1158,13 @@ METHOD(ike_sa_t, update_hosts, void, } } - 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, diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index b965a49c97..f15455930a 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -28,6 +28,7 @@ typedef enum ike_extension_t ike_extension_t; 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 @@ -264,6 +265,25 @@ enum statistic_t { 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. * @@ -454,15 +474,16 @@ struct ike_sa_t { 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. diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c index 2a8bcfae7f..f49a8eb8ed 100644 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -1408,7 +1408,7 @@ METHOD(task_manager_t, process_message, status_t, } 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) { @@ -1528,7 +1528,7 @@ METHOD(task_manager_t, process_message, status_t, "%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) { diff --git a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c index 7314f8872e..c38276c9c9 100644 --- a/src/libcharon/sa/ikev1/tasks/aggressive_mode.c +++ b/src/libcharon/sa/ikev1/tasks/aggressive_mode.c @@ -384,7 +384,8 @@ METHOD(task_t, process_r, status_t, 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); diff --git a/src/libcharon/sa/ikev1/tasks/main_mode.c b/src/libcharon/sa/ikev1/tasks/main_mode.c index c1d12046fe..35e860f090 100644 --- a/src/libcharon/sa/ikev1/tasks/main_mode.c +++ b/src/libcharon/sa/ikev1/tasks/main_mode.c @@ -376,7 +376,8 @@ METHOD(task_t, process_r, status_t, 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); diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index 64d95f5819..9a3c1cae3e 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -1649,8 +1649,10 @@ METHOD(task_manager_t, process_message, status_t, 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) @@ -1718,11 +1720,11 @@ METHOD(task_manager_t, process_message, status_t, 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);