DNS resolving of ike_cfg hosts dynamically on demand
authorMartin Willi <martin@strongswan.org>
Fri, 6 Jun 2008 15:05:54 +0000 (15:05 -0000)
committerMartin Willi <martin@strongswan.org>
Fri, 6 Jun 2008 15:05:54 +0000 (15:05 -0000)
14 files changed:
src/charon/config/backend_manager.c
src/charon/config/ike_cfg.c
src/charon/config/ike_cfg.h
src/charon/plugins/medcli/medcli_config.c
src/charon/plugins/medsrv/medsrv_config.c
src/charon/plugins/sql/sql_config.c
src/charon/plugins/stroke/stroke_config.c
src/charon/plugins/stroke/stroke_list.c
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa_manager.c
src/charon/sa/tasks/ike_init.c
src/libstrongswan/utils/host.c
src/libstrongswan/utils/host.h
src/libstrongswan/utils/leak_detective.c

index 7b2ddca..41c26e1 100644 (file)
@@ -138,9 +138,13 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
        while (enumerator->enumerate(enumerator, (void**)&current))
        {
                prio = MATCH_NONE;
-               my_candidate = current->get_my_host(current);
-               other_candidate = current->get_other_host(current);
                
+               my_candidate = host_create_from_dns(current->get_my_addr(current),
+                                                                                       me->get_family(me), 0);
+               if (!my_candidate)
+               {
+                       continue;
+               }
                if (my_candidate->ip_equals(my_candidate, me))
                {
                        prio += MATCH_ME;
@@ -149,6 +153,14 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
                {
                        prio += MATCH_ANY;
                }
+               my_candidate->destroy(my_candidate);
+               
+               other_candidate = host_create_from_dns(current->get_other_addr(current),
+                                                                                          other->get_family(other), 0);
+               if (!other_candidate)
+               {
+                       continue;
+               }
                if (other_candidate->ip_equals(other_candidate, other))
                {
                        prio += MATCH_OTHER;
@@ -157,9 +169,11 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this,
                {
                        prio += MATCH_ANY;
                }
+               other_candidate->destroy(other_candidate);
                
-               DBG2(DBG_CFG, "  candidate: %H...%H, prio %d",
-                        my_candidate, other_candidate, prio);
+               DBG2(DBG_CFG, "  candidate: %s...%s, prio %d", 
+                        current->get_my_addr(current), current->get_other_addr(current),
+                        prio);
                
                /* we require at least two MATCH_ANY */
                if (prio > best)
index b92cb98..36f8414 100644 (file)
@@ -41,12 +41,12 @@ struct private_ike_cfg_t {
        /**
         * Address of local host
         */
-       host_t *my_host;
+       char *me;
 
        /**
         * Address of remote host
         */     
-       host_t *other_host;
+       char *other;
        
        /**
         * should we send a certificate request?
@@ -81,19 +81,19 @@ static bool force_encap_meth(private_ike_cfg_t *this)
 }
 
 /**
- * Implementation of ike_cfg_t.get_my_host.
+ * Implementation of ike_cfg_t.get_my_addr.
  */
-static host_t *get_my_host (private_ike_cfg_t *this)
+static char *get_my_addr(private_ike_cfg_t *this)
 {
-       return this->my_host;
+       return this->me;
 }
 
 /**
- * Implementation of ike_cfg_t.get_other_host.
+ * Implementation of ike_cfg_t.get_other_addr.
  */
-static host_t *get_other_host (private_ike_cfg_t *this)
+static char *get_other_addr(private_ike_cfg_t *this)
 {
-       return this->other_host;
+       return this->other;
 }
 
 /**
@@ -219,8 +219,8 @@ static bool equals(private_ike_cfg_t *this, private_ike_cfg_t *other)
        return (eq &&
                this->certreq == other->certreq &&
                this->force_encap == other->force_encap &&
-               this->my_host->equals(this->my_host, other->my_host) &&
-               this->other_host->equals(this->other_host, other->other_host));
+               streq(this->me, other->me) &&
+               streq(this->other, other->other));
 }
 
 /**
@@ -241,8 +241,8 @@ static void destroy(private_ike_cfg_t *this)
        {
                this->proposals->destroy_offset(this->proposals,
                                                                                offsetof(proposal_t, destroy));
-               this->my_host->destroy(this->my_host);
-               this->other_host->destroy(this->other_host);
+               free(this->me);
+               free(this->other);
                free(this);
        }
 }
@@ -251,15 +251,15 @@ static void destroy(private_ike_cfg_t *this)
  * Described in header.
  */
 ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
-                                                 host_t *my_host, host_t *other_host)
+                                                 char *me, char *other)
 {
        private_ike_cfg_t *this = malloc_thing(private_ike_cfg_t);
        
        /* public functions */
        this->public.send_certreq = (bool(*)(ike_cfg_t*))send_certreq;
        this->public.force_encap = (bool (*) (ike_cfg_t *))force_encap_meth;
-       this->public.get_my_host = (host_t*(*)(ike_cfg_t*))get_my_host;
-       this->public.get_other_host = (host_t*(*)(ike_cfg_t*))get_other_host;
+       this->public.get_my_addr = (char*(*)(ike_cfg_t*))get_my_addr;
+       this->public.get_other_addr = (char*(*)(ike_cfg_t*))get_other_addr;
        this->public.add_proposal = (void(*)(ike_cfg_t*, proposal_t*)) add_proposal;
        this->public.get_proposals = (linked_list_t*(*)(ike_cfg_t*))get_proposals;
        this->public.select_proposal = (proposal_t*(*)(ike_cfg_t*,linked_list_t*))select_proposal;
@@ -272,9 +272,8 @@ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap,
        this->refcount = 1;
        this->certreq = certreq;
        this->force_encap = force_encap;
-       this->my_host = my_host;
-       this->other_host = other_host;
-       
+       this->me = strdup(me);
+       this->other = strdup(other);
        this->proposals = linked_list_create();
        
        return &this->public;
index d1cae00..e84246b 100644 (file)
@@ -43,16 +43,16 @@ struct ike_cfg_t {
        /**
         * Get own address.
         * 
-        * @return              host information as host_t object
+        * @return              string of address/DNS name
         */
-       host_t* (*get_my_host) (ike_cfg_t *this);
+       char* (*get_my_addr) (ike_cfg_t *this);
 
        /**
         * Get peers address.
         * 
-        * @return              host information as host_t object
+        * @return              string of address/DNS name
         */
-       host_t* (*get_other_host) (ike_cfg_t *this);
+       char* (*get_other_addr) (ike_cfg_t *this);
        
        /**
         * Adds a proposal to the list.
@@ -136,11 +136,11 @@ struct ike_cfg_t {
  * @param name                 ike_cfg identifier
  * @param certreq              TRUE to send a certificate request
  * @param force_encap  enforce UDP encapsulation by faking NATD notify
- * @param my_host              host_t representing local address
- * @param other_host   host_t representing remote address
+ * @param me                   address/DNS name of local peer
+ * @param other                        address/DNS name of remote peer
  * @return                             ike_cfg_t object.
  */
 ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, 
-                                                 host_t *my_host, host_t *other_host);
+                                                 char *me, char *other);
 
 #endif /* IKE_CFG_H_ @} */
index dff6c3d..8a56bfe 100644 (file)
@@ -100,7 +100,6 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam
        child_cfg_t *child_cfg;
        chunk_t me, other;
        char *address, *local_net, *remote_net;
-       host_t *med;
        
        /* query mediation server config:
         * - build ike_cfg/peer_cfg for mediation connection on-the-fly 
@@ -114,14 +113,7 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam
                DESTROY_IF(e);
                return NULL;
        }
-       med = host_create_from_string(address, 500);
-       if (!med)
-       {
-               e->destroy(e);
-               return NULL;
-       }
-       ike_cfg = ike_cfg_create(FALSE, FALSE,
-                                                        host_create_from_string("0.0.0.0", 500), med);
+       ike_cfg = ike_cfg_create(FALSE, FALSE, "0.0.0.0", address);
        ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        DBG1(DBG_CFG, "mediation server id: %B", &other);
        med_cfg = peer_cfg_create(
@@ -313,8 +305,7 @@ medcli_config_t *medcli_config_create(database_t *db)
        this->rekey = lib->settings->get_int(lib->settings,
                                                                                 "medclient.rekey", 20) * 60;
        this->dpd = lib->settings->get_int(lib->settings, "medclient.dpd", 300);
-       this->ike = ike_cfg_create(FALSE, FALSE, host_create_any(AF_INET),
-                                                          host_create_any(AF_INET));
+       this->ike = ike_cfg_create(FALSE, FALSE, "0.0.0.0", "0.0.0.0");
        this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
        
        return &this->public;
index 8439c20..04cb569 100644 (file)
@@ -139,8 +139,7 @@ medsrv_config_t *medsrv_config_create(database_t *db)
        this->rekey = lib->settings->get_int(lib->settings,
                                                                                 "medmanager.rekey", 20) * 60;
        this->dpd = lib->settings->get_int(lib->settings, "medmanager.dpd", 300);
-       this->ike = ike_cfg_create(FALSE, FALSE, host_create_any(AF_INET),
-                                                          host_create_any(AF_INET));
+       this->ike = ike_cfg_create(FALSE, FALSE, "0.0.0.0", "0.0.0.0");
        this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE));
        
        return &this->public;
index 06fd298..7a2e96f 100644 (file)
@@ -179,34 +179,9 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
        
        while (e->enumerate(e, &certreq, &force_encap, &local, &remote))
        {
-               host_t *me, *other;
                ike_cfg_t *ike_cfg;
                
-               me = host_create_from_string(local, 500);
-               if (!me)
-               {
-                       continue;
-               }
-               if (my_host && !me->is_anyaddr(me) &&
-                       !me->ip_equals(me, my_host))
-               {
-                       me->destroy(me);
-                       continue;
-               }
-               other = host_create_from_string(remote, 500);
-               if (!other)
-               {
-                       me->destroy(me);
-                       continue;
-               }
-               if (other_host && !other->is_anyaddr(other) &&
-                       !other->ip_equals(other, other_host))
-               {
-                       me->destroy(me);
-                       other->destroy(other);
-                       continue;
-               }
-               ike_cfg = ike_cfg_create(certreq, force_encap, me, other);
+               ike_cfg = ike_cfg_create(certreq, force_encap, local, remote);
                /* TODO: read proposal from db */
                ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
                return ike_cfg;
index af19675..0069191 100644 (file)
@@ -139,20 +139,8 @@ static void ike_data_destroy(ike_data_t *data)
  */
 static bool ike_filter(ike_data_t *data, peer_cfg_t **in, ike_cfg_t **out)
 {
-       ike_cfg_t *ike_cfg;
-       host_t *me, *other;
-       
-       ike_cfg = (*in)->get_ike_cfg(*in);
-       
-       me = ike_cfg->get_my_host(ike_cfg);
-       other = ike_cfg->get_other_host(ike_cfg);
-       if ((!data->me || me->is_anyaddr(me) || me->ip_equals(me, data->me)) &&
-               (!data->other || other->is_anyaddr(other) || other->ip_equals(other, data->other)))
-       {
-               *out = ike_cfg;
-               return TRUE;
-       }
-       return FALSE;
+       *out = (*in)->get_ike_cfg(*in);
+       return TRUE;
 }
 
 /**
@@ -296,58 +284,50 @@ static void add_proposals(private_stroke_config_t *this, char *string,
  */
 static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg)
 {
-       host_t *me = NULL, *other = NULL, *tmp;
        stroke_end_t tmp_end;
        ike_cfg_t *ike_cfg;
        char *interface;
-
-       if (msg->add_conn.me.address)
-       {
-               me = host_create_from_string(msg->add_conn.me.address, IKEV2_UDP_PORT);
-       }
-       if (!me)
-       {
-               DBG1(DBG_CFG, "invalid left host: %s", msg->add_conn.me.address);
-               return NULL;
-       }
-       if (msg->add_conn.other.address)
-       {
-               other = host_create_from_string(msg->add_conn.other.address, IKEV2_UDP_PORT);
-       }
-       if (!other)
-       {
-               DBG1(DBG_CFG, "invalid right host: %s", msg->add_conn.other.address);
-               me->destroy(me);
-               return NULL;
-       }
-       interface = charon->kernel_interface->get_interface(
-                                                                                       charon->kernel_interface, other);
-       if (interface)
-       {
-               DBG2(DBG_CFG, "left is other host, swapping ends");
-               tmp = me;
-               me = other;
-               other = tmp;
-               tmp_end = msg->add_conn.me;
-               msg->add_conn.me = msg->add_conn.other;
-               msg->add_conn.other = tmp_end;
-               free(interface);
-       }
-       else
+       host_t *host;
+       
+       host = host_create_from_dns(msg->add_conn.other.address, 0, 0);
+       if (host)
        {
                interface = charon->kernel_interface->get_interface(
-                                                                                               charon->kernel_interface, me);
-               if (!interface)
+                                                                                               charon->kernel_interface, host);
+               host->destroy(host);
+               if (interface)
                {
-                       DBG1(DBG_CFG, "left nor right host is our side, assuming left=local");
+                       DBG2(DBG_CFG, "left is other host, swapping ends");
+                       tmp_end = msg->add_conn.me;
+                       msg->add_conn.me = msg->add_conn.other;
+                       msg->add_conn.other = tmp_end;
+                       free(interface);
                }
                else
                {
-                       free(interface);
+                       host = host_create_from_dns(msg->add_conn.me.address, 0, 0);
+                       if (host)
+                       {
+                               interface = charon->kernel_interface->get_interface(
+                                                                                               charon->kernel_interface, host);
+                               host->destroy(host);
+                               if (!interface)
+                               {
+                                       DBG1(DBG_CFG, "left nor right host is our side, "
+                                                "assuming left=local");
+                               }
+                               else
+                               {
+                                       free(interface);
+                               }
+                               
+                       }
                }
        }
        ike_cfg = ike_cfg_create(msg->add_conn.other.sendcert != CERT_NEVER_SEND,
-                                                        msg->add_conn.force_encap, me, other);
+                                                        msg->add_conn.force_encap,
+                                                        msg->add_conn.me.address,
+                                                        msg->add_conn.other.address);
        add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL);
        return ike_cfg;                                  
 }
@@ -485,8 +465,14 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
                        }
                        else
                        {
-                               host_t* my_host = ike_cfg->get_my_host(ike_cfg);
-                               vip = host_create_any(my_host->get_family(my_host));
+                               if (strchr(ike_cfg->get_my_addr(ike_cfg), ':'))
+                               {
+                                       vip = host_create_any(AF_INET6);
+                               }
+                               else
+                               {
+                                       vip = host_create_any(AF_INET);
+                               }
                        }
                }
        }
@@ -777,9 +763,9 @@ static void add(private_stroke_config_t *this, stroke_msg_t *msg)
        else
        {
                /* add config to backend */
-               DBG1(DBG_CFG, "added configuration '%s': %H[%D]...%H[%D]", msg->add_conn.name,
-                        ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg),
-                        ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg));
+               DBG1(DBG_CFG, "added configuration '%s': %s[%D]...%s[%D]", msg->add_conn.name,
+                        ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg),
+                        ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg));
                this->mutex->lock(this->mutex);
                this->list->insert_last(this->list, peer_cfg);
                this->mutex->unlock(this->mutex);
index db9d829..4f06024 100644 (file)
@@ -229,9 +229,9 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
                        }
                        
                        ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
-                       fprintf(out, "%12s:  %H[%D]...%H[%D]\n", peer_cfg->get_name(peer_cfg),
-                                       ike_cfg->get_my_host(ike_cfg), peer_cfg->get_my_id(peer_cfg),
-                                       ike_cfg->get_other_host(ike_cfg), peer_cfg->get_other_id(peer_cfg));
+                       fprintf(out, "%12s:  %s[%D]...%s[%D]\n", peer_cfg->get_name(peer_cfg),
+                                       ike_cfg->get_my_addr(ike_cfg), peer_cfg->get_my_id(peer_cfg),
+                                       ike_cfg->get_other_addr(ike_cfg), peer_cfg->get_other_id(peer_cfg));
                        /* TODO: list CAs and groups */
                        children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                        while (children->enumerate(children, &child_cfg))
index e19b7be..6dfc42d 100644 (file)
@@ -410,18 +410,6 @@ static void set_peer_cfg(private_ike_sa_t *this, peer_cfg_t *peer_cfg)
                this->ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
                this->ike_cfg->get_ref(this->ike_cfg);
        }
-       
-       /* apply values, so we are ready to initate/acquire */
-       if (this->my_host->is_anyaddr(this->my_host))
-       {
-               host_t *me = this->ike_cfg->get_my_host(this->ike_cfg);
-               set_my_host(this, me->clone(me));
-       }
-       if (this->other_host->is_anyaddr(this->other_host))
-       {
-               host_t *other = this->ike_cfg->get_other_host(this->ike_cfg);
-               set_other_host(this, other->clone(other));
-       }
        /* apply IDs if they are not already set */
        if (this->my_id->contains_wildcards(this->my_id))
        {
@@ -1042,6 +1030,28 @@ static status_t initiate_mediated(private_ike_sa_t *this, host_t *me, host_t *ot
 #endif /* ME */
 
 /**
+ * Resolve DNS host in configuration
+ */
+static void resolve_hosts(private_ike_sa_t *this)
+{
+       host_t *host;
+       
+       host = host_create_from_dns(this->ike_cfg->get_my_addr(this->ike_cfg), 0, 
+                                                               IKEV2_UDP_PORT);
+       if (host)
+       {
+               set_my_host(this, host);
+       }
+       host = host_create_from_dns(this->ike_cfg->get_other_addr(this->ike_cfg),
+                                                               this->my_host->get_family(this->my_host),
+                                                               IKEV2_UDP_PORT);
+       if (host)
+       {
+               set_other_host(this, host);
+       }
+}
+
+/**
  * Initiates a CHILD_SA using the appropriate reqid
  */
 static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_cfg, u_int32_t reqid)
@@ -1050,6 +1060,8 @@ static status_t initiate_with_reqid(private_ike_sa_t *this, child_cfg_t *child_c
        
        if (this->state == IKE_CREATED)
        {
+               resolve_hosts(this);
+               
                if (this->other_host->is_anyaddr(this->other_host)
 #ifdef ME
                        && !this->peer_cfg->get_mediated_by(this->peer_cfg)
@@ -2516,8 +2528,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        /* initialize private fields */
        this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
        this->child_sas = linked_list_create();
-       this->my_host = host_create_any(AF_INET);
-       this->other_host = host_create_any(AF_INET);
+       this->my_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT);
+       this->other_host = host_create_from_string("0.0.0.0", IKEV2_UDP_PORT);
        this->my_id = identification_create_from_encoding(ID_ANY, chunk_empty);
        this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
        this->extensions = 0;
index 5c84cf0..d9983d8 100644 (file)
@@ -497,64 +497,70 @@ static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
        ike_cfg_t *ike_cfg;
        
        ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
-       my_host = ike_cfg->get_my_host(ike_cfg);
-       other_host =  ike_cfg->get_other_host(ike_cfg);
        my_id = peer_cfg->get_my_id(peer_cfg);
        other_id = peer_cfg->get_other_id(peer_cfg);
+       my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0);
+       other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0);
        
        pthread_mutex_lock(&(this->mutex));
        
-       enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
-       while (enumerator->enumerate(enumerator, &entry))
+       if (my_host && other_host)
        {
-               identification_t *found_my_id, *found_other_id;
-               host_t *found_my_host, *found_other_host;
-               
-               if (!wait_for_entry(this, entry))
+               enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
+               while (enumerator->enumerate(enumerator, &entry))
                {
-                       continue;
-               }
+                       identification_t *found_my_id, *found_other_id;
+                       host_t *found_my_host, *found_other_host;
                
-               if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
-               {
-                       /* skip IKE_SA which are not useable */
-                       continue;
-               }
+                       if (!wait_for_entry(this, entry))
+                       {
+                               continue;
+                       }
                
-               found_my_id = entry->ike_sa->get_my_id(entry->ike_sa);
-               found_other_id = entry->ike_sa->get_other_id(entry->ike_sa);
-               found_my_host = entry->ike_sa->get_my_host(entry->ike_sa);
-               found_other_host = entry->ike_sa->get_other_host(entry->ike_sa);
+                       if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
+                       {
+                               /* skip IKE_SA which are not useable */
+                               continue;
+                       }
                
-               if (found_my_id->get_type(found_my_id) == ID_ANY &&
-                       found_other_id->get_type(found_other_id) == ID_ANY)
-               {
-                       /* IKE_SA has no IDs yet, so we can't use it */
-                       continue;
-               }
-               DBG2(DBG_MGR, "candidate IKE_SA for \n\t%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]",
-                        my_host, my_id, other_host, other_id,
-                        found_my_host, found_my_id, found_other_host, found_other_id);
-               /* compare ID and hosts. Supplied ID may contain wildcards, and IP
-                * may be %any. */
-               if ((my_host->is_anyaddr(my_host) ||
-                        my_host->ip_equals(my_host, found_my_host)) &&
-                       (other_host->is_anyaddr(other_host) ||
-                        other_host->ip_equals(other_host, found_other_host)) &&
-                       found_my_id->matches(found_my_id, my_id) &&
-                       found_other_id->matches(found_other_id, other_id) &&
-                       streq(peer_cfg->get_name(peer_cfg),
-                                 entry->ike_sa->get_name(entry->ike_sa)))
-               {
-                       /* looks good, we take this one */
-                       DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]",
-                                my_host, my_id, other_host, other_id);
-                       entry->checked_out = TRUE;
-                       ike_sa = entry->ike_sa;
-                       break;
+                       found_my_id = entry->ike_sa->get_my_id(entry->ike_sa);
+                       found_other_id = entry->ike_sa->get_other_id(entry->ike_sa);
+                       found_my_host = entry->ike_sa->get_my_host(entry->ike_sa);
+                       found_other_host = entry->ike_sa->get_other_host(entry->ike_sa);
+               
+                       if (found_my_id->get_type(found_my_id) == ID_ANY &&
+                               found_other_id->get_type(found_other_id) == ID_ANY)
+                       {
+                               /* IKE_SA has no IDs yet, so we can't use it */
+                               continue;
+                       }
+                       DBG2(DBG_MGR, "candidate IKE_SA for \n\t"
+                                "%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]",
+                                my_host, my_id, other_host, other_id,
+                                found_my_host, found_my_id, found_other_host, found_other_id);
+                       /* compare ID and hosts. Supplied ID may contain wildcards, and IP
+                        * may be %any. */
+                       if ((my_host->is_anyaddr(my_host) ||
+                                my_host->ip_equals(my_host, found_my_host)) &&
+                               (other_host->is_anyaddr(other_host) ||
+                                other_host->ip_equals(other_host, found_other_host)) &&
+                               found_my_id->matches(found_my_id, my_id) &&
+                               found_other_id->matches(found_other_id, other_id) &&
+                               streq(peer_cfg->get_name(peer_cfg),
+                                         entry->ike_sa->get_name(entry->ike_sa)))
+                       {
+                               /* looks good, we take this one */
+                               DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]",
+                                        my_host, my_id, other_host, other_id);
+                               entry->checked_out = TRUE;
+                               ike_sa = entry->ike_sa;
+                               break;
+                       }
                }
+               enumerator->destroy(enumerator);
        }
-       enumerator->destroy(enumerator);
+       DESTROY_IF(my_host);
+       DESTROY_IF(other_host);
        
        if (!ike_sa)
        {
index 8cb706a..0bf8523 100644 (file)
@@ -223,7 +223,7 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
        this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
        SIG(IKE_UP_START, "initiating IKE_SA '%s' to %H",
                this->ike_sa->get_name(this->ike_sa),
-               this->config->get_other_host(this->config));
+               this->ike_sa->get_other_host(this->ike_sa));
        this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
        
        if (this->retry++ >= MAX_RETRIES)
index a2fa579..b60d532 100644 (file)
  * $Id$
  */
 
+#define _GNU_SOURCE
+#include <netdb.h>
 #include <string.h>
 #include <printf.h>
 
 #include "host.h"
 
+#include <debug.h>
 
 typedef struct private_host_t private_host_t;
 
@@ -451,6 +454,56 @@ host_t *host_create_from_string(char *string, u_int16_t port)
 /*
  * Described in header.
  */
+host_t *host_create_from_dns(char *string, int af, u_int16_t port)
+{
+       private_host_t *this;
+       struct hostent host, *ptr;
+       char buf[512];
+       int err, ret;
+       
+       if (af)
+       {       
+               ret = gethostbyname2_r(string, af, &host, buf, sizeof(buf), &ptr, &err);
+       }
+       else
+       {
+               ret = gethostbyname_r(string, &host, buf, sizeof(buf), &ptr, &err);
+       }
+       if (ret != 0)
+       {
+               DBG1("resolving '%s' failed: %s", string, hstrerror(err));
+               return NULL;
+       }
+       if (ptr == NULL)
+       {
+               DBG1("resolving '%s' failed", string);
+       }
+       this = host_create_empty();
+       this->address.sa_family = host.h_addrtype;
+       switch (af)
+       {
+               case AF_INET:
+                       memcpy(&this->address4.sin_addr.s_addr,
+                                  host.h_addr_list[0], host.h_length);
+                       this->address4.sin_port = htons(port);
+                       this->socklen = sizeof(struct sockaddr_in);
+                       break;
+               case AF_INET6:
+                       memcpy(&this->address6.sin6_addr.s6_addr,
+                                  host.h_addr_list[0], host.h_length);
+                       this->address6.sin6_port = htons(port);
+                       this->socklen = sizeof(struct sockaddr_in6);
+                       break;
+               default:
+                       free(this);
+                       return NULL;
+       }
+       return &this->public;
+}
+
+/*
+ * Described in header.
+ */
 host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
 {
        private_host_t *this = host_create_empty();
index fd2fe01..6a1d824 100644 (file)
@@ -160,6 +160,16 @@ struct host_t {
 host_t *host_create_from_string(char *string, u_int16_t port);
 
 /**
+ * Constructor to create a host_t from a DNS name.
+ *
+ * @param string               hostname to resolve
+ * @param family               family to prefer, 0 for first match
+ * @param port                 port number
+ * @return                             host_t, NULL lookup failed
+ */
+host_t *host_create_from_dns(char *string, int family, u_int16_t port);
+
+/**
  * Constructor to create a host_t object from an address chunk
  *
  * @param family               Address family, such as AF_INET or AF_INET6
index 789c149..a28cac3 100644 (file)
@@ -250,6 +250,8 @@ char *whitelist[] = {
        "getprotobynumber",
        "getservbyport",
        "getservbyname",
+       "gethostbyname_r",
+       "gethostbyname2_r",
        "getpwnam_r",
        "getgrnam_r",
        "register_printf_function",