Fix warnings when compiling for Windows.
[tinc] / src / net_socket.c
index 979e84b..a696127 100644 (file)
@@ -1,7 +1,7 @@
 /*
     net_socket.c -- Handle various kinds of sockets.
     Copyright (C) 1998-2005 Ivo Timmermans,
-                  2000-2017 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2018 Guus Sliepen <guus@tinc-vpn.org>
                   2006      Scott Lamb <slamb@slamb.org>
                   2009      Florian Forster <octo@verplant.org>
 
@@ -22,6 +22,7 @@
 
 #include "system.h"
 
+#include "address_cache.h"
 #include "conf.h"
 #include "connection.h"
 #include "control_common.h"
@@ -40,7 +41,8 @@ int maxtimeout = 900;
 int seconds_till_retry = 5;
 int udp_rcvbuf = 1024 * 1024;
 int udp_sndbuf = 1024 * 1024;
-int max_connection_burst = 100;
+int max_connection_burst = 10;
+int fwmark;
 
 listen_socket_t listen_socket[MAXSOCKETS];
 int listen_sockets;
@@ -58,14 +60,14 @@ static void configure_tcp(connection_t *c) {
        int flags = fcntl(c->socket, F_GETFL);
 
        if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "fcntl for %s: %s", c->hostname, strerror(errno));
+               logger(DEBUG_ALWAYS, LOG_ERR, "fcntl for %s fd %d: %s", c->hostname, c->socket, strerror(errno));
        }
 
 #elif defined(WIN32)
        unsigned long arg = 1;
 
        if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno));
+               logger(DEBUG_ALWAYS, LOG_ERR, "ioctlsocket for %s fd %d: %s", c->hostname, c->socket, sockstrerror(sockerrno));
        }
 
 #endif
@@ -84,6 +86,14 @@ static void configure_tcp(connection_t *c) {
        option = IPTOS_LOWDELAY;
        setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof(option));
 #endif
+
+#if defined(SO_MARK)
+
+       if(fwmark) {
+               setsockopt(c->socket, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
+       }
+
+#endif
 }
 
 static bool bind_to_interface(int sd) {
@@ -112,6 +122,7 @@ static bool bind_to_interface(int sd) {
        }
 
 #else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
+       (void)sd;
        logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "BindToInterface");
 #endif
 
@@ -183,6 +194,14 @@ int setup_listen_socket(const sockaddr_t *sa) {
 
 #else
 #warning IPV6_V6ONLY not defined
+#endif
+
+#if defined(SO_MARK)
+
+       if(fwmark) {
+               setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
+       }
+
 #endif
 
        if(get_config_string
@@ -192,6 +211,7 @@ int setup_listen_socket(const sockaddr_t *sa) {
 
                memset(&ifr, 0, sizeof(ifr));
                strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
+               ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
 
                if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) {
                        closesocket(nfd);
@@ -315,6 +335,14 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
                setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
        }
 
+#endif
+
+#if defined(SO_MARK)
+
+       if(fwmark) {
+               setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
+       }
+
 #endif
 
        if(!bind_to_interface(nfd)) {
@@ -360,7 +388,7 @@ void finish_connecting(connection_t *c) {
        send_id(c);
 }
 
-static void do_outgoing_pipe(connection_t *c, char *command) {
+static void do_outgoing_pipe(connection_t *c, const char *command) {
 #ifndef HAVE_MINGW
        int fd[2];
 
@@ -408,6 +436,8 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
 
        exit(result);
 #else
+       (void)c;
+       (void)command;
        logger(DEBUG_ALWAYS, LOG_ERR, "Proxy type exec not supported on this platform!");
        return;
 #endif
@@ -491,73 +521,26 @@ static void handle_meta_io(void *data, int flags) {
        }
 }
 
-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;
+       const sockaddr_t *sa;
        struct addrinfo *proxyai = NULL;
        int result;
 
 begin:
+       sa = get_recent_address(outgoing->address_cache);
 
-       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);
-                       return false;
-               }
-
-               get_config_string(outgoing->cfg, &address);
-
-               space = strchr(address, ' ');
-
-               if(space) {
-                       port = xstrdup(space + 1);
-                       *space = 0;
-               } else {
-                       if(!get_config_string(lookup_config(outgoing->config_tree, "Port"), &port)) {
-                               port = xstrdup("655");
-                       }
-               }
-
-               outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
-               free(address);
-               free(port);
-
-               outgoing->aip = outgoing->ai;
-               outgoing->cfg = lookup_config_next(outgoing->config_tree, outgoing->cfg);
-       }
-
-       if(!outgoing->aip) {
-               if(outgoing->ai) {
-                       freeaddrinfo(outgoing->ai);
-               }
-
-               outgoing->ai = NULL;
-
-               if(outgoing->kai) {
-                       free_known_addresses(outgoing->kai);
-               }
-
-               outgoing->kai = NULL;
-
-               goto begin;
+       if(!sa) {
+               logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->node->name);
+               retry_outgoing(outgoing);
+               return false;
        }
 
        connection_t *c = new_connection();
        c->outgoing = outgoing;
-
-       memcpy(&c->address, outgoing->aip->ai_addr, outgoing->aip->ai_addrlen);
-       outgoing->aip = outgoing->aip->ai_next;
-
+       memcpy(&c->address, sa, SALEN(sa->sa));
        c->hostname = sockaddr2hostname(&c->address);
 
-       logger(DEBUG_CONNECTIONS, LOG_INFO, "Trying to connect to %s (%s)", outgoing->name, c->hostname);
+       logger(DEBUG_CONNECTIONS, LOG_INFO, "Trying to connect to %s (%s)", outgoing->node->name, c->hostname);
 
        if(!proxytype) {
                c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
@@ -617,7 +600,7 @@ begin:
        }
 
        if(result == -1 && !sockinprogress(sockerrno)) {
-               logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not connect to %s (%s): %s", outgoing->name, c->hostname, sockstrerror(sockerrno));
+               logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not connect to %s (%s): %s", outgoing->node->name, c->hostname, sockstrerror(sockerrno));
                free_connection(c);
 
                goto begin;
@@ -627,7 +610,7 @@ begin:
 
        c->last_ping_time = time(NULL);
        c->status.connecting = true;
-       c->name = xstrdup(outgoing->name);
+       c->name = xstrdup(outgoing->node->name);
 #ifndef DISABLE_LEGACY
        c->outcipher = myself->connection->outcipher;
        c->outdigest = myself->connection->outdigest;
@@ -643,50 +626,14 @@ begin:
        return true;
 }
 
-// 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) {
-                       continue;
-               }
-
-               bool found = false;
-
-               for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
-                       if(!sockaddrcmp(&e->reverse->address, (sockaddr_t *)aip->ai_addr)) {
-                               found = true;
-                               break;
-                       }
-               }
-
-               if(found) {
-                       continue;
-               }
-
-               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;
-}
-
 void setup_outgoing_connection(outgoing_t *outgoing, bool verbose) {
+       (void)verbose;
        timeout_del(&outgoing->ev);
 
-       node_t *n = lookup_node(outgoing->name);
+       node_t *n = outgoing->node;
 
-       if(n && n->connection) {
-               logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", outgoing->name);
+       if(n->connection) {
+               logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", n->name);
 
                if(!n->connection->outgoing) {
                        n->connection->outgoing = outgoing;
@@ -696,19 +643,8 @@ void setup_outgoing_connection(outgoing_t *outgoing, bool verbose) {
                }
        }
 
-       init_configuration(&outgoing->config_tree);
-       read_host_config(outgoing->config_tree, outgoing->name, verbose);
-       outgoing->cfg = lookup_config(outgoing->config_tree, "Address");
-
-       if(!outgoing->cfg) {
-               if(n) {
-                       outgoing->aip = outgoing->kai = get_known_addresses(n);
-               }
-
-               if(!outgoing->kai) {
-                       logger(verbose ? DEBUG_ALWAYS : DEBUG_CONNECTIONS, LOG_DEBUG, "No address known for %s", outgoing->name);
-                       goto remove;
-               }
+       if(!outgoing->address_cache) {
+               outgoing->address_cache = open_address_cache(n);
        }
 
        do_outgoing_connection(outgoing);
@@ -723,6 +659,7 @@ remove:
   new connection
 */
 void handle_new_meta_connection(void *data, int flags) {
+       (void)flags;
        listen_socket_t *l = data;
        connection_t *c;
        sockaddr_t sa;
@@ -741,12 +678,6 @@ void handle_new_meta_connection(void *data, int flags) {
        // Check if we get many connections from the same host
 
        static sockaddr_t prev_sa;
-       static int tarpit = -1;
-
-       if(tarpit >= 0) {
-               closesocket(tarpit);
-               tarpit = -1;
-       }
 
        if(!sockaddrcmp_noport(&sa, &prev_sa)) {
                static int samehost_burst;
@@ -762,7 +693,7 @@ void handle_new_meta_connection(void *data, int flags) {
                samehost_burst++;
 
                if(samehost_burst > max_connection_burst) {
-                       tarpit = fd;
+                       tarpit(fd);
                        return;
                }
        }
@@ -785,7 +716,7 @@ void handle_new_meta_connection(void *data, int flags) {
 
        if(connection_burst >= max_connection_burst) {
                connection_burst = max_connection_burst;
-               tarpit = fd;
+               tarpit(fd);
                return;
        }
 
@@ -814,7 +745,6 @@ void handle_new_meta_connection(void *data, int flags) {
        connection_add(c);
 
        c->allow_request = ID;
-       send_id(c);
 }
 
 #ifndef HAVE_MINGW
@@ -822,6 +752,7 @@ void handle_new_meta_connection(void *data, int flags) {
   accept a new UNIX socket connection
 */
 void handle_new_unix_connection(void *data, int flags) {
+       (void)flags;
        io_t *io = data;
        connection_t *c;
        sockaddr_t sa;
@@ -851,28 +782,14 @@ void handle_new_unix_connection(void *data, int flags) {
        connection_add(c);
 
        c->allow_request = ID;
-
-       send_id(c);
 }
 #endif
 
 static void free_outgoing(outgoing_t *outgoing) {
        timeout_del(&outgoing->ev);
 
-       if(outgoing->ai) {
-               freeaddrinfo(outgoing->ai);
-       }
-
-       if(outgoing->kai) {
-               free_known_addresses(outgoing->kai);
-       }
-
-       if(outgoing->config_tree) {
-               exit_configuration(&outgoing->config_tree);
-       }
-
-       if(outgoing->name) {
-               free(outgoing->name);
+       if(outgoing->address_cache) {
+               close_address_cache(outgoing->address_cache);
        }
 
        free(outgoing);
@@ -911,7 +828,7 @@ void try_outgoing_connections(void) {
                bool found = false;
 
                for list_each(outgoing_t, outgoing, outgoing_list) {
-                       if(!strcmp(outgoing->name, name)) {
+                       if(!strcmp(outgoing->node->name, name)) {
                                found = true;
                                outgoing->timeout = 0;
                                break;
@@ -920,7 +837,15 @@ void try_outgoing_connections(void) {
 
                if(!found) {
                        outgoing_t *outgoing = xzalloc(sizeof(*outgoing));
-                       outgoing->name = name;
+                       node_t *n = lookup_node(name);
+
+                       if(!n) {
+                               n = new_node();
+                               n->name = xstrdup(name);
+                               node_add(n);
+                       }
+
+                       outgoing->node = n;
                        list_insert_tail(outgoing_list, outgoing);
                        setup_outgoing_connection(outgoing, true);
                }