/*
net_socket.c -- Handle various kinds of sockets.
Copyright (C) 1998-2005 Ivo Timmermans,
- 2000-2014 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2016 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;
}
#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(IPPROTO_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
+ option = IPTOS_LOWDELAY;
+ setsockopt(c->socket, IPPROTO_IP, IP_TOS, (void *)&option, sizeof option);
#endif
-#if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
+#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY)
option = IPTOS_LOWDELAY;
- setsockopt(c->socket, SOL_IP, IP_TOS, (void *)&option, sizeof option);
+ setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof option);
#endif
}
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
#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) {
}
#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) {
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);
if(outgoing->ai)
freeaddrinfo(outgoing->ai);
outgoing->ai = NULL;
+
+ if(outgoing->kai)
+ free_known_addresses(outgoing->kai);
+ outgoing->kai = NULL;
+
goto 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);
} else if(proxytype == PROXY_EXEC) {
result = 0;
} else {
+ if(!proxyai)
+ abort();
result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen);
freeaddrinfo(proxyai);
}
/* Now that there is a working socket, fill in the rest and register this connection. */
+ c->last_ping_time = time(NULL);
c->status.connecting = true;
c->name = xstrdup(outgoing->name);
#ifndef DISABLE_LEGACY
// 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)
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;
if(n && n->connection) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", outgoing->name);
-
- n->connection->outgoing = outgoing;
- return;
+ if(!n->connection->outgoing) {
+ n->connection->outgoing = outgoing;
+ return;
+ } else {
+ goto remove;
+ }
}
init_configuration(&outgoing->config_tree);
if(!outgoing->cfg) {
if(n)
- outgoing->aip = outgoing->ai = get_known_addresses(n);
- if(!outgoing->ai) {
- logger(DEBUG_ALWAYS, LOG_ERR, "No address known for %s", outgoing->name);
- return;
+ 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;
}
}
do_outgoing_connection(outgoing);
+ return;
+
+remove:
+ list_delete(outgoing_list, outgoing);
}
/*
if(outgoing->ai)
freeaddrinfo(outgoing->ai);
+ if(outgoing->kai)
+ free_known_addresses(outgoing->kai);
+
if(outgoing->config_tree)
exit_configuration(&outgoing->config_tree);