From: Tobias Brunner Date: Fri, 15 Jan 2021 15:09:59 +0000 (+0100) Subject: ike-sa-manager: Add a method to register/check out new IKE_SAs X-Git-Tag: 5.9.2rc1~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5d97af58942325018550c338cd02a683009bfcbe;p=thirdparty%2Fstrongswan.git ike-sa-manager: Add a method to register/check out new IKE_SAs This way, jobs for new IKE_SAs (created via create_new()) may be scheduled/queued before checkin() is called. If they run before that happens, they will now correctly block in checkout() instead of doing nothing because the IKE_SA was not found. --- diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index b7df1d809b..9fec03348b 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -1277,6 +1277,17 @@ METHOD(ike_sa_manager_t, create_new, ike_sa_t*, return ike_sa; } +METHOD(ike_sa_manager_t, checkout_new, void, + private_ike_sa_manager_t *this, ike_sa_t *ike_sa) +{ + u_int segment; + entry_t *entry; + + segment = create_and_put_entry(this, ike_sa, &entry); + entry->checked_out = thread_current(); + unlock_single_segment(this, segment); +} + /** * Get the message ID or message hash to detect early retransmissions */ @@ -1491,10 +1502,7 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, { /* IKE_SA reuse disabled by config (not possible for IKEv1) */ ike_sa = create_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE); ike_sa->set_peer_cfg(ike_sa, peer_cfg); - - segment = create_and_put_entry(this, ike_sa, &entry); - entry->checked_out = thread_current(); - unlock_single_segment(this, segment); + checkout_new(this, ike_sa); charon->bus->set_sa(charon->bus, ike_sa); goto out; } @@ -1566,10 +1574,7 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*, { ike_sa = create_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE); ike_sa->set_peer_cfg(ike_sa, peer_cfg); - - segment = create_and_put_entry(this, ike_sa, &entry); - entry->checked_out = thread_current(); - unlock_single_segment(this, segment); + checkout_new(this, ike_sa); } charon->bus->set_sa(charon->bus, ike_sa); @@ -2468,6 +2473,7 @@ ike_sa_manager_t *ike_sa_manager_create() INIT(this, .public = { .create_new = _create_new, + .checkout_new = _checkout_new, .checkout = _checkout, .checkout_by_message = _checkout_by_message, .checkout_by_config = _checkout_by_config, diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h index 5695c9433f..b68ec7c142 100644 --- a/src/libcharon/sa/ike_sa_manager.h +++ b/src/libcharon/sa/ike_sa_manager.h @@ -59,6 +59,22 @@ struct ike_sa_manager_t { ike_sa_t *(*create_new)(ike_sa_manager_t* this, ike_version_t version, bool initiator); + /** + * Register/checkout an IKE_SA created with create_new(). + * + * This may be used shortly before calling checkin() for unregistered SAs + * created via create_new() to avoid race conditions so e.g. jobs may + * find the SA and block on it until checkin() is called. + * + * @note There is no check that verifies that the IKE_SA is not yet + * registered. + * + * @note The IKE_SA on the bus is not changed by this method. + * + * @param ike_sa IKE_SA to register + */ + void (*checkout_new)(ike_sa_manager_t* this, ike_sa_t *ike_sa); + /** * Checkout an existing IKE_SA. *