Check all Address statements when making outgoing connections.
[tinc] / src / address_cache.c
index 552e1f2..b6d48d0 100644 (file)
@@ -85,14 +85,16 @@ void add_recent_address(address_cache_t *cache, const sockaddr_t *sa) {
        unsigned int pos = find_cached(cache, sa);
 
        // It's in the first spot, so nothing to do
-       if (pos == 0) {
+       if(pos == 0) {
                return;
        }
 
        // Shift everything, move/add the address to the first slot
        if(pos == NOT_CACHED) {
-               if(cache->data.used < MAX_CACHED_ADDRESSES)
+               if(cache->data.used < MAX_CACHED_ADDRESSES) {
                        cache->data.used++;
+               }
+
                pos = cache->data.used - 1;
        }
 
@@ -106,7 +108,6 @@ void add_recent_address(address_cache_t *cache, const sockaddr_t *sa) {
        FILE *fp = fopen(fname, "wb");
 
        if(fp) {
-               fprintf(stderr, "Writing cache to %s\n", fname);
                fwrite(&cache->data, sizeof(cache->data), 1, fp);
                fclose(fp);
        }
@@ -126,13 +127,13 @@ const sockaddr_t *get_recent_address(address_cache_t *cache) {
 
                if(cache->ai) {
                        if(cache->aip) {
-                               sockaddr_t *sa = (sockaddr_t *)cache->aip;
+                               sockaddr_t *sa = (sockaddr_t *)cache->aip->ai_addr;
+                               cache->aip = cache->aip->ai_next;
 
                                if(find_cached(cache, sa) != NOT_CACHED) {
                                        continue;
                                }
 
-                               cache->aip = cache->aip->ai_next;
                                return sa;
                        } else {
                                free_known_addresses(cache->ai);
@@ -150,7 +151,7 @@ const sockaddr_t *get_recent_address(address_cache_t *cache) {
                cache->cfg = lookup_config(cache->config_tree, "Address");
        }
 
-       while(cache->cfg && !cache->ai) {
+       while(cache->cfg && !cache->aip) {
                char *address, *port;
 
                get_config_string(cache->cfg, &address);
@@ -166,23 +167,48 @@ const sockaddr_t *get_recent_address(address_cache_t *cache) {
                        }
                }
 
+               if(cache->ai) {
+                       free_known_addresses(cache->ai);
+               }
+
                cache->aip = cache->ai = str2addrinfo(address, port, SOCK_STREAM);
+
+               if(cache->ai) {
+                       struct addrinfo *ai = NULL;
+
+                       for(; cache->aip; cache->aip = cache->aip->ai_next) {
+                               struct addrinfo *oai = ai;
+
+                               ai = xzalloc(sizeof(*ai));
+                               ai->ai_family = cache->aip->ai_family;
+                               ai->ai_socktype = cache->aip->ai_socktype;
+                               ai->ai_protocol = cache->aip->ai_protocol;
+                               ai->ai_addrlen = cache->aip->ai_addrlen;
+                               ai->ai_addr = xmalloc(ai->ai_addrlen);
+                               memcpy(ai->ai_addr, cache->aip->ai_addr, ai->ai_addrlen);
+                               ai->ai_next = oai;
+                       }
+
+                       freeaddrinfo(cache->ai);
+                       cache->aip = cache->ai = ai;
+               }
+
                free(address);
                free(port);
 
                cache->cfg = lookup_config_next(cache->config_tree, cache->cfg);
        }
 
-       if(cache->aip) {
-               sockaddr_t *sa = (sockaddr_t *)cache->aip->ai_addr;
-               cache->aip = cache->aip->ai_next;
+       if(cache->ai) {
+               if(cache->aip) {
+                       sockaddr_t *sa = (sockaddr_t *)cache->aip->ai_addr;
 
-               if(!cache->aip) {
-                       freeaddrinfo(cache->aip);
-                       cache->aip = NULL;
+                       cache->aip = cache->aip->ai_next;
+                       return sa;
+               } else {
+                       free_known_addresses(cache->ai);
+                       cache->ai = NULL;
                }
-
-               return sa;
        }
 
        // We're all out of addresses.
@@ -232,11 +258,7 @@ void reset_address_cache(address_cache_t *cache, const sockaddr_t *sa) {
        }
 
        if(cache->ai) {
-               if(cache->tried == cache->data.used) {
-                       free_known_addresses(cache->ai);
-               } else {
-                       freeaddrinfo(cache->ai);
-               }
+               free_known_addresses(cache->ai);
        }
 
        cache->config_tree = NULL;
@@ -252,11 +274,7 @@ void close_address_cache(address_cache_t *cache) {
        }
 
        if(cache->ai) {
-               if(cache->tried == cache->data.used) {
-                       free_known_addresses(cache->ai);
-               } else {
-                       freeaddrinfo(cache->ai);
-               }
+               free_known_addresses(cache->ai);
        }
 
        free(cache);