This makes handling such IKE_SAs more specifically compared to keeping them
in state IKE_CONNECTING or IKE_ESTABLISHED (which we did when we lost a
collision - even triggering the ike_updown event), or using IKE_REKEYING for
them, which would also be ambiguous.
For instance, we can now reject anything but DELETES for such SAs.
As the static plugin that creates and destroys the default sender was
not initialized because of the missing socket the daemon won't destroy
our sender. Test cases will eventually have to flush the IKE_SA manager to
satisfy the leak detective. However, in case of a test failure and if there
are IKE_SAs in the manager the daemon will flush the SAs when deinitializing,
which will cause deletes to get sent. This crashes if the sender is already
destroyed.
In case listeners on the stack are triggered while cleaning up after a
test failed (e.g. via ike_sa_manager_t::flush) remaining listeners defined on
the stack would cause a segmentation fault.
Moving to the new SA only after receiving the DELETE for the old SA was
not ideal as it rendered the new SA unusable (because it simply didn't
exist in the manager) if the DELETE was delayed/got dropped.
This happens if the peer deletes the redundant SA before we are able to
handle the response. The deleted SA will be in state CHILD_INSTALLED but
we don't want to trigger the child_updown() event for it or recreate it.
Generally, we will not find the CHILD_SA by searching for it with the
outbound SPI (the initiator of the DELETE sent its inbound SPI) - and if
we found a CHILD_SA it would most likely be the wrong one (one in which
we used the same inbound SPI as the peer used for the one it deletes).
And we don't actually want to destroy the CHILD_SA at this point as we
know we already initiated a DELETE ourselves, which means that task
still has a reference to it and will destroy the CHILD_SA when it
receives the response from the other peer.
libcharon_deinit() already calls all the functions we called manually.
Unloading the plugins will not work if charon->initialize() is called
as charon's static plugin features would already be unloaded before the
destroyed members are accessed in destroy() to flush them.
If a called script interacts with the daemon or one of its plugins
another thread might have to acquire the write lock (e.g. to configure a
fallback or set a value). Holding the read lock prevents that, potentially
resulting in a deadlock.