Don't unset IKE_SA on bus before we released virtual IPs and attributes
[strongswan.git] / src / libcharon / sa / ike_sa.c
index ea15ff2..d7a9076 100644 (file)
@@ -285,7 +285,7 @@ static time_t get_use_time(private_ike_sa_t* this, bool inbound)
        enumerator = this->child_sas->create_enumerator(this->child_sas);
        while (enumerator->enumerate(enumerator, &child_sa))
        {
-               child_sa->get_usestats(child_sa, inbound, &current, NULL);
+               child_sa->get_usestats(child_sa, inbound, &current, NULL, NULL);
                use_time = max(use_time, current);
        }
        enumerator->destroy(enumerator);
@@ -776,6 +776,10 @@ METHOD(ike_sa_t, clear_virtual_ips, void,
        linked_list_t *vips = local ? this->my_vips : this->other_vips;
        host_t *vip;
 
+       if (!local && vips->get_count(vips))
+       {
+               charon->bus->assign_vips(charon->bus, &this->public, FALSE);
+       }
        while (vips->remove_first(vips, (void**)&vip) == SUCCESS)
        {
                if (local)
@@ -900,7 +904,7 @@ METHOD(ike_sa_t, update_hosts, void,
        else
        {
                /* update our address in any case */
-               if (!me->equals(me, this->my_host))
+               if (force && !me->equals(me, this->my_host))
                {
                        set_my_host(this, me->clone(me));
                        update = TRUE;
@@ -909,7 +913,8 @@ METHOD(ike_sa_t, update_hosts, void,
                if (!other->equals(other, this->other_host))
                {
                        /* update others address if we are NOT NATed */
-                       if (force || !has_condition(this, COND_NAT_HERE))
+                       if ((has_condition(this, COND_NAT_THERE) &&
+                                !has_condition(this, COND_NAT_HERE)) || force )
                        {
                                set_other_host(this, other->clone(other));
                                update = TRUE;
@@ -1444,6 +1449,10 @@ METHOD(ike_sa_t, delete_, status_t,
                        }
                        /* FALL */
                case IKE_ESTABLISHED:
+                       if (time_monotonic(NULL) >= this->stats[STAT_DELETE])
+                       {       /* IKE_SA hard lifetime hit */
+                               charon->bus->alert(charon->bus, ALERT_IKE_SA_EXPIRED);
+                       }
                        this->task_manager->queue_ike_delete(this->task_manager);
                        return this->task_manager->initiate(this->task_manager);
                case IKE_CREATED:
@@ -2085,21 +2094,15 @@ METHOD(ike_sa_t, destroy, void,
                free(entry->data.ptr);
                free(entry);
        }
-       this->attributes->destroy(this->attributes);
-
-       this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy));
-
-       /* unset SA after here to avoid usage by the listeners */
-       charon->bus->set_sa(charon->bus, NULL);
-
-       DESTROY_IF(this->keymat);
-
        while (this->my_vips->remove_last(this->my_vips, (void**)&vip) == SUCCESS)
        {
                hydra->kernel_interface->del_ip(hydra->kernel_interface, vip, -1, TRUE);
                vip->destroy(vip);
        }
-       this->my_vips->destroy(this->my_vips);
+       if (this->other_vips->get_count(this->other_vips))
+       {
+               charon->bus->assign_vips(charon->bus, &this->public, FALSE);
+       }
        while (this->other_vips->remove_last(this->other_vips,
                                                                                 (void**)&vip) == SUCCESS)
        {
@@ -2116,6 +2119,14 @@ METHOD(ike_sa_t, destroy, void,
                }
                vip->destroy(vip);
        }
+
+       /* unset SA after here to avoid usage by the listeners */
+       charon->bus->set_sa(charon->bus, NULL);
+
+       this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy));
+       DESTROY_IF(this->keymat);
+       this->attributes->destroy(this->attributes);
+       this->my_vips->destroy(this->my_vips);
        this->other_vips->destroy(this->other_vips);
        this->peer_addresses->destroy_offset(this->peer_addresses,
                                                                                 offsetof(host_t, destroy));