Don't rekey but delete CHILD_SA to resying against NATed Windows clients
authorMartin Willi <martin@revosec.ch>
Wed, 10 Aug 2011 14:59:13 +0000 (16:59 +0200)
committerMartin Willi <martin@revosec.ch>
Fri, 19 Aug 2011 07:16:17 +0000 (09:16 +0200)
src/libcharon/plugins/ha/ha_cache.c

index a7ddc28..970a8a2 100644 (file)
@@ -203,9 +203,24 @@ static status_t rekey_children(ike_sa_t *ike_sa)
        enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
        while (enumerator->enumerate(enumerator, (void**)&child_sa))
        {
-               DBG1(DBG_CFG, "resyncing CHILD_SA");
-               status = ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa),
-                                                                               child_sa->get_spi(child_sa, TRUE));
+               if (ike_sa->supports_extension(ike_sa, EXT_MS_WINDOWS) &&
+                       ike_sa->has_condition(ike_sa, COND_NAT_THERE))
+               {
+                       /* NATed Windows clients don't accept CHILD_SA rekeying, but fail
+                        * with an "invalid situation" error. We just close the CHILD_SA,
+                        * Windows will reestablish it immediately if required. */
+                       DBG1(DBG_CFG, "resyncing CHILD_SA using a delete");
+                       status = ike_sa->delete_child_sa(ike_sa,
+                                                                                        child_sa->get_protocol(child_sa),
+                                                                                        child_sa->get_spi(child_sa, TRUE));
+               }
+               else
+               {
+                       DBG1(DBG_CFG, "resyncing CHILD_SA using a rekey");
+                       status = ike_sa->rekey_child_sa(ike_sa,
+                                                                                       child_sa->get_protocol(child_sa),
+                                                                                       child_sa->get_spi(child_sa, TRUE));
+               }
                if (status == DESTROY_ME)
                {
                        break;