Releasing 1.1pre15.
[tinc] / src / net_socket.c
index 8983d28..ac6b840 100644 (file)
@@ -1,7 +1,7 @@
 /*
     net_socket.c -- Handle various kinds of sockets.
     Copyright (C) 1998-2005 Ivo Timmermans,
-                  2000-2016 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2017 Guus Sliepen <guus@tinc-vpn.org>
                   2006      Scott Lamb <slamb@slamb.org>
                   2009      Florian Forster <octo@verplant.org>
 
 #include "utils.h"
 #include "xalloc.h"
 
-/* Needed on Mac OS/X */
-#ifndef SOL_TCP
-#define SOL_TCP IPPROTO_TCP
-#endif
-
 int addressfamily = AF_UNSPEC;
 int maxtimeout = 900;
 int seconds_till_retry = 5;
@@ -73,14 +68,14 @@ static void configure_tcp(connection_t *c) {
        }
 #endif
 
-#if defined(SOL_TCP) && defined(TCP_NODELAY)
+#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
        option = 1;
-       setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, sizeof option);
+       setsockopt(c->socket, IPPROTO_TCP, TCP_NODELAY, (void *)&option, sizeof option);
 #endif
 
-#if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
+#if defined(IPPROTO_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
        option = IPTOS_LOWDELAY;
-       setsockopt(c->socket, SOL_IP, IP_TOS, (void *)&option, sizeof option);
+       setsockopt(c->socket, IPPROTO_IP, IP_TOS, (void *)&option, sizeof option);
 #endif
 
 #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY)
@@ -168,9 +163,9 @@ int setup_listen_socket(const sockaddr_t *sa) {
        option = 1;
        setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
 
-#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
+#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
        if(sa->sa.sa_family == AF_INET6)
-               setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
+               setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
 #endif
 
        if(get_config_string
@@ -266,10 +261,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
 #define IP_DONTFRAGMENT IP_DONTFRAG
 #endif
 
-#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
+#if defined(IPPROTO_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
        if(myself->options & OPTION_PMTU_DISCOVERY) {
                option = IP_PMTUDISC_DO;
-               setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
+               setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
        }
 #elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
        if(myself->options & OPTION_PMTU_DISCOVERY) {
@@ -278,10 +273,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
        }
 #endif
 
-#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
+#if defined(IPPROTO_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
        if(myself->options & OPTION_PMTU_DISCOVERY) {
                option = IPV6_PMTUDISC_DO;
-               setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
+               setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
        }
 #elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
        if(myself->options & OPTION_PMTU_DISCOVERY) {
@@ -387,7 +382,7 @@ static void handle_meta_write(connection_t *c) {
                if(!sockerrno || sockerrno == EPIPE) {
                        logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname);
                } else if(sockwouldblock(sockerrno)) {
-                       logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname);
+                       logger(DEBUG_META, LOG_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname);
                        return;
                } else {
                        logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, sockstrerror(sockerrno));
@@ -446,13 +441,20 @@ static void handle_meta_io(void *data, int flags) {
                handle_meta_connection_data(c);
 }
 
+static void free_known_addresses(struct addrinfo *ai) {
+       for(struct addrinfo *aip = ai, *next; aip; aip = next) {
+               next = aip->ai_next;
+               free(aip);
+       }
+}
+
 bool do_outgoing_connection(outgoing_t *outgoing) {
        char *address, *port, *space;
        struct addrinfo *proxyai = NULL;
        int result;
 
 begin:
-       if(!outgoing->ai) {
+       if(!outgoing->ai && !outgoing->kai) {
                if(!outgoing->cfg) {
                        logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->name);
                        retry_outgoing(outgoing);
@@ -482,6 +484,11 @@ begin:
                if(outgoing->ai)
                        freeaddrinfo(outgoing->ai);
                outgoing->ai = NULL;
+
+               if(outgoing->kai)
+                       free_known_addresses(outgoing->kai);
+               outgoing->kai = NULL;
+
                goto begin;
        }
 
@@ -522,10 +529,10 @@ begin:
 #endif
 
        if(proxytype != PROXY_EXEC) {
-#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
+#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
                int option = 1;
                if(c->address.sa.sa_family == AF_INET6)
-                       setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
+                       setsockopt(c->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
 #endif
 
                bind_to_interface(c->socket);
@@ -539,6 +546,8 @@ begin:
        } else if(proxytype == PROXY_EXEC) {
                result = 0;
        } else {
+               if(!proxyai)
+                       abort();
                result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen);
                freeaddrinfo(proxyai);
        }
@@ -573,6 +582,7 @@ begin:
 // Find edges pointing to this node, and use them to build a list of unique, known addresses.
 static struct addrinfo *get_known_addresses(node_t *n) {
        struct addrinfo *ai = NULL;
+       struct addrinfo *oai = NULL;
 
        for splay_each(edge_t, e, n->edge_tree) {
                if(!e->reverse)
@@ -588,16 +598,15 @@ static struct addrinfo *get_known_addresses(node_t *n) {
                if(found)
                        continue;
 
-               struct addrinfo *nai = xzalloc(sizeof *nai);
-               if(ai)
-                       ai->ai_next = nai;
-               ai = nai;
+               oai = ai;
+               ai = xzalloc(sizeof *ai);
                ai->ai_family = e->reverse->address.sa.sa_family;
                ai->ai_socktype = SOCK_STREAM;
                ai->ai_protocol = IPPROTO_TCP;
                ai->ai_addrlen = SALEN(e->reverse->address.sa);
                ai->ai_addr = xmalloc(ai->ai_addrlen);
                memcpy(ai->ai_addr, &e->reverse->address, ai->ai_addrlen);
+               ai->ai_next = oai;
        }
 
        return ai;
@@ -624,8 +633,8 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
 
        if(!outgoing->cfg) {
                if(n)
-                       outgoing->aip = outgoing->ai = get_known_addresses(n);
-               if(!outgoing->ai) {
+                       outgoing->aip = outgoing->kai = get_known_addresses(n);
+               if(!outgoing->kai) {
                        logger(DEBUG_ALWAYS, LOG_DEBUG, "No address known for %s", outgoing->name);
                        goto remove;
                }
@@ -780,6 +789,9 @@ static void free_outgoing(outgoing_t *outgoing) {
        if(outgoing->ai)
                freeaddrinfo(outgoing->ai);
 
+       if(outgoing->kai)
+               free_known_addresses(outgoing->kai);
+
        if(outgoing->config_tree)
                exit_configuration(&outgoing->config_tree);