From 261d1eac1c5bbe6c87aa707566f290e611169432 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 5 Jun 2009 16:14:31 +0200 Subject: [PATCH 01/32] Properly set HMAC length for incoming packets. --- src/protocol_key.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/protocol_key.c b/src/protocol_key.c index 64225fd2..41479148 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -154,6 +154,7 @@ bool send_ans_key(node_t *to) to->incipher = myself->incipher; to->inkeylength = myself->inkeylength; to->indigest = myself->indigest; + to->inmaclength = myself->inmaclength; to->incompression = myself->incompression; // Allocate memory for key From 36f8e4da8b1708474505f5a1fa8cf1ba848921de Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 11 Jun 2009 18:36:08 +0200 Subject: [PATCH 02/32] Don't try to send MTU probes to unreachable nodes. If there is an outstanding MTU probe event for a node which is not reachable anymore, a UDP packet would be sent to that node, which caused a key request to be sent to that node, which triggered a NULL pointer dereference. Probes and other UDP packets to unreachable nodes are now dropped. --- src/meta.c | 5 +++++ src/net_packet.c | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/meta.c b/src/meta.c index a32d4137..b59f15b0 100644 --- a/src/meta.c +++ b/src/meta.c @@ -41,6 +41,11 @@ bool send_meta(connection_t *c, const char *buffer, int length) cp(); + if(!c) { + logger(LOG_ERR, _("send_meta() called with NULL pointer!")); + abort(); + } + ifdebug(META) logger(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length, c->name, c->hostname); diff --git a/src/net_packet.c b/src/net_packet.c index 40d94518..9f612751 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -70,6 +70,11 @@ void send_mtu_probe(node_t *n) n->mtuprobes++; n->mtuevent = NULL; + if(!n->status.reachable) { + ifdebug(TRAFFIC) logger(LOG_INFO, _("Trying to send MTU probe to unreachable node %s (%s)"), n->name, n->hostname); + return; + } + if(n->mtuprobes >= 10 && !n->minmtu) { ifdebug(TRAFFIC) logger(LOG_INFO, _("No response to MTU probes from %s (%s)"), n->name, n->hostname); return; @@ -328,6 +333,11 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) cp(); + if(!n->status.reachable) { + ifdebug(TRAFFIC) logger(LOG_INFO, _("Trying to send UDP packet to unreachable node %s (%s)"), n->name, n->hostname); + return; + } + /* Make sure we have a valid key */ if(!n->status.validkey) { From df4add94a4a6461758b218a9ad257efc735062fe Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 11 Jun 2009 19:07:54 +0200 Subject: [PATCH 03/32] Remove pending MTU probe events when a node's reachability status changes. --- src/graph.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/graph.c b/src/graph.c index 87bb2204..85643585 100644 --- a/src/graph.c +++ b/src/graph.c @@ -264,6 +264,11 @@ void sssp_bfs(void) n->minmtu = 0; n->mtuprobes = 0; + if(n->mtuevent) { + event_del(n->mtuevent); + n->mtuevent = NULL; + } + asprintf(&envp[0], "NETNAME=%s", netname ? : ""); asprintf(&envp[1], "DEVICE=%s", device ? : ""); asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); From 66be914d35cb7e7ea4dd4aed68ae9e41addd9f70 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 11 Jun 2009 19:26:34 +0200 Subject: [PATCH 04/32] Do not log errors when recvfrom() returns EAGAIN or EINTR. Although we select() before we call recvfrom(), it sometimes happens that select() tells us we can read but a subsequent read fails anyway. This is harmless. --- src/net_packet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/net_packet.c b/src/net_packet.c index 9f612751..5e503f58 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -552,7 +552,8 @@ void handle_incoming_vpn_data(int sock) pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); if(pkt.len < 0) { - logger(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); + if(errno != EAGAIN && errno != EINTR) + logger(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); return; } From de029ce46056e02908b5390da9b71a6a59133f26 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 11 Jun 2009 19:39:25 +0200 Subject: [PATCH 05/32] Change level of some debug messages, zero pointer after freeing hostname. --- src/net_packet.c | 2 +- src/node.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/net_packet.c b/src/net_packet.c index 5e503f58..31c44771 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -71,7 +71,7 @@ void send_mtu_probe(node_t *n) n->mtuevent = NULL; if(!n->status.reachable) { - ifdebug(TRAFFIC) logger(LOG_INFO, _("Trying to send MTU probe to unreachable node %s (%s)"), n->name, n->hostname); + logger(LOG_DEBUG, _("Trying to send MTU probe to unreachable node %s (%s)"), n->name, n->hostname); return; } diff --git a/src/node.c b/src/node.c index 9d359253..a4ef78f2 100644 --- a/src/node.c +++ b/src/node.c @@ -176,10 +176,11 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) n->hostname = sockaddr2hostname(&n->address); avl_delete(node_udp_tree, n); avl_insert(node_udp_tree, n); - logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); + ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); } else { memset(&n->address, 0, sizeof n->address); - logger(LOG_DEBUG, "UDP address of %s cleared", n->name); + n->hostname = 0; + ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s cleared", n->name); } } From 5a7fc58012da10b96073804994777255463d1b8d Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 8 Sep 2009 16:35:28 +0200 Subject: [PATCH 06/32] Always remove a node from the UDP tree before freeing it. Valgrind caught tinc reading free'd memory during a purge(). This was caused by first removing it from the main node tree, which will already call free_node(), and then removing it from the UDP tree. This might cause spurious segmentation faults. --- src/node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node.c b/src/node.c index a4ef78f2..f2bb3990 100644 --- a/src/node.c +++ b/src/node.c @@ -137,8 +137,8 @@ void node_del(node_t *n) edge_del(e); } - avl_delete(node_tree, n); avl_delete(node_udp_tree, n); + avl_delete(node_tree, n); } node_t *lookup_node(char *name) From 63fe89e9eb8ef9077bfe3cd416c86820715eb33b Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Sat, 5 Sep 2009 17:24:41 +0400 Subject: [PATCH 07/32] Remove extra semicolon in my definition of setpriority() --- src/tincd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tincd.c b/src/tincd.c index bec16cd3..da3c33fa 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -485,7 +485,7 @@ static bool drop_privs() { } #ifdef HAVE_MINGW -# define setpriority(level) SetPriorityClass(GetCurrentProcess(), level); +# define setpriority(level) SetPriorityClass(GetCurrentProcess(), level) #else # define NORMAL_PRIORITY_CLASS 0 # define BELOW_NORMAL_PRIORITY_CLASS 10 From 5e0efd53e797a2b5468b91b41b6122f3b942efb2 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 8 Sep 2009 18:16:58 +0200 Subject: [PATCH 08/32] Add xasprintf() and xvasprintf(). These functions wrap asprintf() and vasprintf(), and check the return value. If the function failed, tinc will exit with an error message, similar to xmalloc() and friends. --- lib/dropin.c | 25 +++++++++++++++++-------- lib/dropin.h | 1 + lib/xalloc.h | 3 +++ lib/xmalloc.c | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/lib/dropin.c b/lib/dropin.c index a3c28b04..23d2b136 100644 --- a/lib/dropin.c +++ b/lib/dropin.c @@ -125,27 +125,36 @@ char *get_current_dir_name(void) #endif #ifndef HAVE_ASPRINTF -int asprintf(char **buf, const char *fmt, ...) +int asprintf(char **buf, const char *fmt, ...) { + int result; + va_list ap; + va_start(ap, fmt); + result = vasprintf(buf, fmt, ap); + va_end(ap); + return result; +} + +int vasprintf(char **buf, const char *fmt, va_list ap) { { int status; - va_list ap; + va_list aq; int len; len = 4096; *buf = xmalloc(len); - va_start(ap, fmt); - status = vsnprintf(*buf, len, fmt, ap); - va_end(ap); + va_copy(aq, ap); + status = vsnprintf(*buf, len, fmt, aq); + va_end(aq); if(status >= 0) *buf = xrealloc(*buf, status + 1); if(status > len - 1) { len = status; - va_start(ap, fmt); - status = vsnprintf(*buf, len, fmt, ap); - va_end(ap); + va_copy(aq, ap); + status = vsnprintf(*buf, len, fmt, aq); + va_end(aq); } return status; diff --git a/lib/dropin.h b/lib/dropin.h index eabc4c4d..72109c84 100644 --- a/lib/dropin.h +++ b/lib/dropin.h @@ -36,6 +36,7 @@ extern char *get_current_dir_name(void); #ifndef HAVE_ASPRINTF extern int asprintf(char **, const char *, ...); +extern int vasprintf(char **, const char *, va_list ap); #endif #ifndef HAVE_GETNAMEINFO diff --git a/lib/xalloc.h b/lib/xalloc.h index 7cb486a2..51f99bdf 100644 --- a/lib/xalloc.h +++ b/lib/xalloc.h @@ -24,3 +24,6 @@ void *xcalloc PARAMS ((size_t n, size_t s)); void *xrealloc PARAMS ((void *p, size_t n)) __attribute__ ((__malloc__)); char *xstrdup PARAMS ((const char *s)) __attribute__ ((__malloc__)); + +extern int xasprintf(char **strp, const char *fmt, ...); +extern int xvasprintf(char **strp, const char *fmt, va_list ap); diff --git a/lib/xmalloc.c b/lib/xmalloc.c index d02f41b9..51356e46 100644 --- a/lib/xmalloc.c +++ b/lib/xmalloc.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #if STDC_HEADERS # include @@ -138,3 +140,21 @@ xcalloc (n, s) } #endif /* NOT_USED */ + +int xasprintf(char **strp, const char *fmt, ...) { + int result; + va_list ap; + va_start(ap, fmt); + result = xvasprintf(strp, fmt, ap); + va_end(ap); + return result; +} + +int xvasprintf(char **strp, const char *fmt, va_list ap) { + int result = vasprintf(strp, fmt, ap); + if(result < 0) { + fprintf(stderr, "vasprintf() failed: %s\n", strerror(errno)); + exit(xalloc_exit_failure); + } + return result; +} From 3e55dc77f4ba19fd9e79f3d5ce9d28bb6b05019e Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 8 Sep 2009 18:18:16 +0200 Subject: [PATCH 09/32] Check the return value of fscanf() when reading a PID file. --- lib/pidfile.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pidfile.c b/lib/pidfile.c index 426cbf39..dd6788a6 100644 --- a/lib/pidfile.c +++ b/lib/pidfile.c @@ -37,11 +37,12 @@ pid_t read_pid (char *pidfile) { FILE *f; - long pid = 0; + long pid; if (!(f=fopen(pidfile,"r"))) return 0; - fscanf(f,"%ld", &pid); + if(fscanf(f,"%ld", &pid) != 1) + pid = 0; fclose(f); return pid; } From 73d77dd416b87b7c4e9b6aa450f64846235cd2b4 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 8 Sep 2009 18:18:36 +0200 Subject: [PATCH 10/32] Replace asprintf() by xasprintf(). --- src/conf.c | 4 ++-- src/connection.c | 2 +- src/graph.c | 17 +++++++++-------- src/net.c | 2 +- src/net_setup.c | 28 ++++++++++++++-------------- src/net_socket.c | 2 +- src/netutl.c | 4 ++-- src/process.c | 4 ++-- src/protocol.c | 2 +- src/solaris/device.c | 2 +- src/subnet.c | 12 ++++++------ src/tincd.c | 22 +++++++++++----------- src/uml_socket/device.c | 2 +- 13 files changed, 52 insertions(+), 51 deletions(-) diff --git a/src/conf.c b/src/conf.c index ce776804..d8a8d832 100644 --- a/src/conf.c +++ b/src/conf.c @@ -417,7 +417,7 @@ bool read_server_config() cp(); - asprintf(&fname, "%s/tinc.conf", confbase); + xasprintf(&fname, "%s/tinc.conf", confbase); x = read_config_file(config_tree, fname); if(x == -1) { /* System error: complain */ @@ -469,7 +469,7 @@ FILE *ask_and_open(const char *filename, const char *what) char *p; directory = get_current_dir_name(); - asprintf(&p, "%s/%s", directory, fn); + xasprintf(&p, "%s/%s", directory, fn); free(fn); free(directory); fn = p; diff --git a/src/connection.c b/src/connection.c index 9fd4002b..a2a188a6 100644 --- a/src/connection.c +++ b/src/connection.c @@ -158,7 +158,7 @@ bool read_connection_config(connection_t *c) cp(); - asprintf(&fname, "%s/hosts/%s", confbase, c->name); + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); x = read_config_file(c->config_tree, fname); free(fname); diff --git a/src/graph.c b/src/graph.c index 85643585..a267f052 100644 --- a/src/graph.c +++ b/src/graph.c @@ -57,6 +57,7 @@ #include "process.h" #include "subnet.h" #include "utils.h" +#include "xalloc.h" static bool graph_changed = true; @@ -269,18 +270,18 @@ void sssp_bfs(void) n->mtuevent = NULL; } - asprintf(&envp[0], "NETNAME=%s", netname ? : ""); - asprintf(&envp[1], "DEVICE=%s", device ? : ""); - asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); - asprintf(&envp[3], "NODE=%s", n->name); + xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[3], "NODE=%s", n->name); sockaddr2str(&n->address, &address, &port); - asprintf(&envp[4], "REMOTEADDRESS=%s", address); - asprintf(&envp[5], "REMOTEPORT=%s", port); + xasprintf(&envp[4], "REMOTEADDRESS=%s", address); + xasprintf(&envp[5], "REMOTEPORT=%s", port); envp[6] = NULL; execute_script(n->status.reachable ? "host-up" : "host-down", envp); - asprintf(&name, + xasprintf(&name, n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", n->name); execute_script(name, envp); @@ -331,7 +332,7 @@ void dump_graph(void) if(filename[0] == '|') { file = popen(filename + 1, "w"); } else { - asprintf(&tmpname, "%s.new", filename); + xasprintf(&tmpname, "%s.new", filename); file = fopen(tmpname, "w"); } diff --git a/src/net.c b/src/net.c index 7f17252d..4a2af954 100644 --- a/src/net.c +++ b/src/net.c @@ -466,7 +466,7 @@ int main_loop(void) for(node = connection_tree->head; node; node = node->next) { c = node->data; - asprintf(&fname, "%s/hosts/%s", confbase, c->name); + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); if(stat(fname, &s) || s.st_mtime > last_config_check) terminate_connection(c, c->status.active); free(fname); diff --git a/src/net_setup.c b/src/net_setup.c index 94e25b62..4eef68ed 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -113,7 +113,7 @@ bool read_rsa_public_key(connection_t *c) /* Else, check if a harnessed public key is in the config file */ - asprintf(&fname, "%s/hosts/%s", confbase, c->name); + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); fp = fopen(fname, "r"); if(fp) { @@ -128,7 +128,7 @@ bool read_rsa_public_key(connection_t *c) /* Try again with PEM_read_RSA_PUBKEY. */ - asprintf(&fname, "%s/hosts/%s", confbase, c->name); + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); fp = fopen(fname, "r"); if(fp) { @@ -171,7 +171,7 @@ bool read_rsa_private_key(void) } if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) - asprintf(&fname, "%s/rsa_key.priv", confbase); + xasprintf(&fname, "%s/rsa_key.priv", confbase); fp = fopen(fname, "r"); @@ -228,8 +228,8 @@ bool setup_myself(void) myself->connection = new_connection(); init_configuration(&myself->connection->config_tree); - asprintf(&myself->hostname, _("MYSELF")); - asprintf(&myself->connection->hostname, _("MYSELF")); + xasprintf(&myself->hostname, _("MYSELF")); + xasprintf(&myself->connection->hostname, _("MYSELF")); myself->connection->options = 0; myself->connection->protocol_version = PROT_CURRENT; @@ -257,7 +257,7 @@ bool setup_myself(void) return false; if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport)) - asprintf(&myport, "655"); + xasprintf(&myport, "655"); /* Read in all the subnets specified in the host configuration file */ @@ -433,10 +433,10 @@ bool setup_myself(void) return false; /* Run tinc-up script to further initialize the tap interface */ - asprintf(&envp[0], "NETNAME=%s", netname ? : ""); - asprintf(&envp[1], "DEVICE=%s", device ? : ""); - asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); - asprintf(&envp[3], "NAME=%s", myself->name); + xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[3], "NAME=%s", myself->name); envp[4] = NULL; execute_script("tinc-up", envp); @@ -571,10 +571,10 @@ void close_network_connections(void) close(listen_socket[i].udp); } - asprintf(&envp[0], "NETNAME=%s", netname ? : ""); - asprintf(&envp[1], "DEVICE=%s", device ? : ""); - asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); - asprintf(&envp[3], "NAME=%s", myself->name); + xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[3], "NAME=%s", myself->name); envp[4] = NULL; exit_requests(); diff --git a/src/net_socket.c b/src/net_socket.c index 865df786..8df9f380 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -367,7 +367,7 @@ begin: get_config_string(c->outgoing->cfg, &address); if(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) - asprintf(&port, "655"); + xasprintf(&port, "655"); c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); free(address); diff --git a/src/netutl.c b/src/netutl.c index 20648605..909441e1 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -128,7 +128,7 @@ char *sockaddr2hostname(const sockaddr_t *sa) cp(); if(sa->sa.sa_family == AF_UNKNOWN) { - asprintf(&str, _("%s port %s"), sa->unknown.address, sa->unknown.port); + xasprintf(&str, _("%s port %s"), sa->unknown.address, sa->unknown.port); return str; } @@ -139,7 +139,7 @@ char *sockaddr2hostname(const sockaddr_t *sa) gai_strerror(err)); } - asprintf(&str, _("%s port %s"), address, port); + xasprintf(&str, _("%s port %s"), address, port); return str; } diff --git a/src/process.c b/src/process.c index c2940bc5..28bba02d 100644 --- a/src/process.c +++ b/src/process.c @@ -371,9 +371,9 @@ bool execute_script(const char *name, char **envp) cp(); #ifndef HAVE_MINGW - len = asprintf(&scriptname, "\"%s/%s\"", confbase, name); + len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name); #else - len = asprintf(&scriptname, "\"%s/%s.bat\"", confbase, name); + len = xasprintf(&scriptname, "\"%s/%s.bat\"", confbase, name); #endif if(len < 0) return false; diff --git a/src/protocol.c b/src/protocol.c index 2e93cff4..85133954 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -75,7 +75,7 @@ bool send_request(connection_t *c, const char *format, ...) cp(); - /* Use vsnprintf instead of vasprintf: faster, no memory + /* Use vsnprintf instead of vxasprintf: faster, no memory fragmentation, cleanup is automatic, and there is a limit on the input buffer anyway */ diff --git a/src/solaris/device.c b/src/solaris/device.c index 748b5459..f76bbbd5 100644 --- a/src/solaris/device.c +++ b/src/solaris/device.c @@ -100,7 +100,7 @@ bool setup_device(void) } if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) - asprintf(&iface, "tun%d", ppa); + xasprintf(&iface, "tun%d", ppa); device_info = _("Solaris tun device"); diff --git a/src/subnet.c b/src/subnet.c index 9547829f..334729db 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -480,15 +480,15 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) { char netstr[MAXNETSTR + 7] = "SUBNET="; char *name, *address, *port; - asprintf(&envp[0], "NETNAME=%s", netname ? : ""); - asprintf(&envp[1], "DEVICE=%s", device ? : ""); - asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); - asprintf(&envp[3], "NODE=%s", owner->name); + xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[3], "NODE=%s", owner->name); if(owner != myself) { sockaddr2str(&owner->address, &address, &port); - asprintf(&envp[4], "REMOTEADDRESS=%s", address); - asprintf(&envp[5], "REMOTEPORT=%s", port); + xasprintf(&envp[4], "REMOTEADDRESS=%s", address); + xasprintf(&envp[5], "REMOTEPORT=%s", port); envp[6] = netstr; envp[7] = NULL; } else { diff --git a/src/tincd.c b/src/tincd.c index da3c33fa..a13e2661 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -337,7 +337,7 @@ static bool keygen(int bits) } else fprintf(stderr, _("Done.\n")); - asprintf(&filename, "%s/rsa_key.priv", confbase); + xasprintf(&filename, "%s/rsa_key.priv", confbase); f = ask_and_open(filename, _("private RSA key")); if(!f) @@ -356,9 +356,9 @@ static bool keygen(int bits) free(filename); if(name) - asprintf(&filename, "%s/hosts/%s", confbase, name); + xasprintf(&filename, "%s/hosts/%s", confbase, name); else - asprintf(&filename, "%s/rsa_key.pub", confbase); + xasprintf(&filename, "%s/rsa_key.pub", confbase); f = ask_and_open(filename, _("public RSA key")); @@ -389,7 +389,7 @@ static void make_names(void) #endif if(netname) - asprintf(&identname, "tinc.%s", netname); + xasprintf(&identname, "tinc.%s", netname); else identname = xstrdup("tinc"); @@ -397,12 +397,12 @@ static void make_names(void) if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) { if(!RegQueryValueEx(key, NULL, 0, 0, installdir, &len)) { if(!logfilename) - asprintf(&logfilename, "%s/log/%s.log", identname); + xasprintf(&logfilename, "%s/log/%s.log", identname); if(!confbase) { if(netname) - asprintf(&confbase, "%s/%s", installdir, netname); + xasprintf(&confbase, "%s/%s", installdir, netname); else - asprintf(&confbase, "%s", installdir); + xasprintf(&confbase, "%s", installdir); } } RegCloseKey(key); @@ -412,19 +412,19 @@ static void make_names(void) #endif if(!pidfilename) - asprintf(&pidfilename, LOCALSTATEDIR "/run/%s.pid", identname); + xasprintf(&pidfilename, LOCALSTATEDIR "/run/%s.pid", identname); if(!logfilename) - asprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname); + xasprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname); if(netname) { if(!confbase) - asprintf(&confbase, CONFDIR "/tinc/%s", netname); + xasprintf(&confbase, CONFDIR "/tinc/%s", netname); else logger(LOG_INFO, _("Both netname and configuration directory given, using the latter...")); } else { if(!confbase) - asprintf(&confbase, CONFDIR "/tinc"); + xasprintf(&confbase, CONFDIR "/tinc"); } } diff --git a/src/uml_socket/device.c b/src/uml_socket/device.c index 62a6f2eb..de0b4a55 100644 --- a/src/uml_socket/device.c +++ b/src/uml_socket/device.c @@ -71,7 +71,7 @@ bool setup_device(void) cp(); if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - asprintf(&device, LOCALSTATEDIR "/run/%s.umlsocket", identname); + xasprintf(&device, LOCALSTATEDIR "/run/%s.umlsocket", identname); get_config_string(lookup_config(config_tree, "Interface"), &iface); From f52ea0a7eb0383cc2a5f41db1bf24c39424fdb04 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 8 Sep 2009 18:21:52 +0200 Subject: [PATCH 11/32] UNIX signal numbers start at 1. --- src/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/process.c b/src/process.c index 28bba02d..d07ce7db 100644 --- a/src/process.c +++ b/src/process.c @@ -587,7 +587,7 @@ void setup_signals(void) /* Set a default signal handler for every signal, errors will be ignored. */ - for(i = 0; i < NSIG; i++) { + for(i = 1; i < NSIG; i++) { if(!do_detach) act.sa_handler = SIG_DFL; else From 9b394bc887695da6db74f4b9796b4823e553f8cc Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 8 Sep 2009 21:45:24 +0200 Subject: [PATCH 12/32] Ensure tinc compiles with gcc -std=c99. We use a lot of C99 features already, but also some extensions which are not in the standard. --- configure.in | 2 +- src/connection.c | 4 ++-- src/connection.h | 25 +++++++++++-------------- src/net.c | 2 +- src/node.h | 19 ++++++++----------- 5 files changed, 23 insertions(+), 29 deletions(-) diff --git a/configure.in b/configure.in index 3cb6a4de..964dd27a 100644 --- a/configure.in +++ b/configure.in @@ -21,7 +21,7 @@ AC_DEFINE([__USE_BSD], 1, [Enable BSD extensions]) ALL_LINGUAS="nl" dnl Checks for programs. -AC_PROG_CC +AC_PROG_CC_C99 AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S diff --git a/src/connection.c b/src/connection.c index a2a188a6..430e1c14 100644 --- a/src/connection.c +++ b/src/connection.c @@ -37,7 +37,7 @@ connection_t *broadcast; static int connection_compare(const connection_t *a, const connection_t *b) { - return (void *)a - (void *)b; + return a - b; } void init_connections(void) @@ -144,7 +144,7 @@ void dump_connections(void) for(node = connection_tree->head; node; node = node->next) { c = node->data; logger(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x outbuf %d/%d/%d"), - c->name, c->hostname, c->options, c->socket, c->status.value, + c->name, c->hostname, c->options, c->socket, *(uint32_t *)&c->status, c->outbufsize, c->outbufstart, c->outbuflen); } diff --git a/src/connection.h b/src/connection.h index 087d8f00..8948d4fa 100644 --- a/src/connection.h +++ b/src/connection.h @@ -32,20 +32,17 @@ #define OPTION_TCPONLY 0x0002 #define OPTION_PMTU_DISCOVERY 0x0004 -typedef union connection_status_t { - struct { - int pinged:1; /* sent ping */ - int active:1; /* 1 if active.. */ - int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ - int termreq:1; /* the termination of this connection was requested */ - int remove:1; /* Set to 1 if you want this connection removed */ - int timeout:1; /* 1 if gotten timeout */ - int encryptout:1; /* 1 if we can encrypt outgoing traffic */ - int decryptin:1; /* 1 if we have to decrypt incoming traffic */ - int mst:1; /* 1 if this connection is part of a minimum spanning tree */ - int unused:23; - }; - uint32_t value; +typedef struct connection_status_t { + int pinged:1; /* sent ping */ + int active:1; /* 1 if active.. */ + int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ + int termreq:1; /* the termination of this connection was requested */ + int remove:1; /* Set to 1 if you want this connection removed */ + int timeout:1; /* 1 if gotten timeout */ + int encryptout:1; /* 1 if we can encrypt outgoing traffic */ + int decryptin:1; /* 1 if we have to decrypt incoming traffic */ + int mst:1; /* 1 if this connection is part of a minimum spanning tree */ + int unused:23; } connection_status_t; #include "edge.h" diff --git a/src/net.c b/src/net.c index 4a2af954..910e86dd 100644 --- a/src/net.c +++ b/src/net.c @@ -251,7 +251,7 @@ static void check_dead_connections(void) } else { if(c->status.remove) { logger(LOG_WARNING, _("Old connection_t for %s (%s) status %04x still lingering, deleting..."), - c->name, c->hostname, c->status.value); + c->name, c->hostname, *(uint32_t *)&c->status); connection_del(c); continue; } diff --git a/src/node.h b/src/node.h index 4321c008..528716de 100644 --- a/src/node.h +++ b/src/node.h @@ -29,17 +29,14 @@ #include "list.h" #include "subnet.h" -typedef union node_status_t { - struct { - int unused_active:1; /* 1 if active (not used for nodes) */ - int validkey:1; /* 1 if we currently have a valid key for him */ - int waitingforkey:1; /* 1 if we already sent out a request */ - int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ - int reachable:1; /* 1 if this node is reachable in the graph */ - int indirect:1; /* 1 if this node is not directly reachable by us */ - int unused:26; - }; - uint32_t value; +typedef struct node_status_t { + int unused_active:1; /* 1 if active (not used for nodes) */ + int validkey:1; /* 1 if we currently have a valid key for him */ + int waitingforkey:1; /* 1 if we already sent out a request */ + int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ + int reachable:1; /* 1 if this node is reachable in the graph */ + int indirect:1; /* 1 if this node is not directly reachable by us */ + int unused:26; } node_status_t; typedef struct node_t { From 81afa26e4ad53bea00da18a7666f63d33cf3f588 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Wed, 9 Sep 2009 12:04:08 +0200 Subject: [PATCH 13/32] Convert bitfields to integers in a safe way. This is commit eb391c52eed46f3f03b404553df417851fc0cb90 redone, but without the non-standard anonymous union. --- lib/utils.c | 7 +++++++ lib/utils.h | 2 ++ src/connection.c | 2 +- src/net.c | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index 56bcb0b1..02b7b344 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -100,3 +100,10 @@ const char *winerror(int err) { } #endif +unsigned int bitfield_to_int(void *bitfield, size_t size) { + unsigned int value = 0; + if(size > sizeof value) + size = sizeof value; + memcpy(&value, bitfield, size); + return value; +} diff --git a/lib/utils.h b/lib/utils.h index 04c4ddbd..ce726482 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -43,4 +43,6 @@ extern const char *winerror(int); #define strerror(x) ((x)>0?strerror(x):winerror(GetLastError())) #endif +extern unsigned int bitfield_to_int(void *bitfield, size_t size); + #endif /* __TINC_UTILS_H__ */ diff --git a/src/connection.c b/src/connection.c index 430e1c14..66eb0596 100644 --- a/src/connection.c +++ b/src/connection.c @@ -144,7 +144,7 @@ void dump_connections(void) for(node = connection_tree->head; node; node = node->next) { c = node->data; logger(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x outbuf %d/%d/%d"), - c->name, c->hostname, c->options, c->socket, *(uint32_t *)&c->status, + c->name, c->hostname, c->options, c->socket, bitfield_to_int(&c->status, sizeof c->status), c->outbufsize, c->outbufstart, c->outbuflen); } diff --git a/src/net.c b/src/net.c index 910e86dd..3cf1773d 100644 --- a/src/net.c +++ b/src/net.c @@ -251,7 +251,7 @@ static void check_dead_connections(void) } else { if(c->status.remove) { logger(LOG_WARNING, _("Old connection_t for %s (%s) status %04x still lingering, deleting..."), - c->name, c->hostname, *(uint32_t *)&c->status); + c->name, c->hostname, bitfield_to_int(&c->status, sizeof c->status)); connection_del(c); continue; } From dd6226062c2356d2a3679e2c7972be71233cb9de Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Wed, 9 Sep 2009 13:23:16 +0200 Subject: [PATCH 14/32] Add the GPL license to the repository. Tinc is licensed under the GPL version 2 or later. To ensure autoconf does not install the wrong license if COPYING is missing, we have to put the right one in place. --- COPYING | 289 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 COPYING diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..2ecad8df --- /dev/null +++ b/COPYING @@ -0,0 +1,289 @@ +Copyright (C) 1998-2009 Ivo Timmermans, Guus Sliepen and others. +See the AUTHORS file for a complete list. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS From ff946d0423fe547ea42bb11acfb3035c3b8aee4e Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Wed, 9 Sep 2009 14:51:36 +0200 Subject: [PATCH 15/32] Another safe bitfield conversion. --- src/node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node.c b/src/node.c index f2bb3990..0c9033ca 100644 --- a/src/node.c +++ b/src/node.c @@ -198,7 +198,7 @@ void dump_nodes(void) logger(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s pmtu %d (min %d max %d)"), n->name, n->hostname, n->outcipher ? n->outcipher->nid : 0, n->outdigest ? n->outdigest->type : 0, n->outmaclength, n->outcompression, - n->options, *(uint32_t *)&n->status, n->nexthop ? n->nexthop->name : "-", + n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-", n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu); } From 4a5d42178cc0954efba8b24058da9c70cc77c35a Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 10 Sep 2009 19:32:54 +0200 Subject: [PATCH 16/32] Add support for iPhones and recent iPods. This is a slightly modified patch from Grzegorz Dymarek that allows tinc to use the tunemu device, which allows tinc to be compiled for iPhones and recent iPods. To enable support for tunemu, the --enable-tunemu option has to be used when running the configure script. --- THANKS | 1 + configure.in | 9 ++ src/Makefile.am | 10 +- src/bsd/device.c | 74 ++++++++- src/bsd/tunemu.c | 386 +++++++++++++++++++++++++++++++++++++++++++++++ src/bsd/tunemu.h | 32 ++++ 6 files changed, 503 insertions(+), 9 deletions(-) create mode 100644 src/bsd/tunemu.c create mode 100644 src/bsd/tunemu.h diff --git a/THANKS b/THANKS index 2daa8f16..ed57da59 100644 --- a/THANKS +++ b/THANKS @@ -8,6 +8,7 @@ We would like to thank the following people for their contributions to tinc: * Cris van Pelt * Enrique Zanardi * Flynn Marquardt +* Grzegorz Dymarek * Hans Bayle * Ivo van Dong * James MacLean diff --git a/configure.in b/configure.in index 964dd27a..eff93a08 100644 --- a/configure.in +++ b/configure.in @@ -75,6 +75,15 @@ case $host_os in ;; esac +AC_ARG_ENABLE(tunemu, + AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]), + [ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu]) + tunemu=true + ] +) + +AM_CONDITIONAL(TUNEMU, test "$tunemu" = true) + AC_CACHE_SAVE if test -d /sw/include ; then diff --git a/src/Makefile.am b/src/Makefile.am index 10f07af5..501fdf66 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,6 +9,10 @@ tincd_SOURCES = conf.c connection.c edge.c event.c graph.c logger.c meta.c net.c net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \ protocol_key.c protocol_subnet.c route.c subnet.c tincd.c +if TUNEMU +tincd_SOURCES += bsd/tunemu.c +endif + nodist_tincd_SOURCES = device.c DEFAULT_INCLUDES = @@ -16,10 +20,14 @@ DEFAULT_INCLUDES = INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h logger.h meta.h net.h netutl.h node.h process.h \ - protocol.h route.h subnet.h + protocol.h route.h subnet.h bsd/tunemu.h LIBS = @LIBS@ @LIBINTL@ +if TUNEMU +LIBS += -lpcap +endif + tincd_LDADD = \ $(top_builddir)/lib/libvpn.a diff --git a/src/bsd/device.c b/src/bsd/device.c index 2e8908af..fe85d10f 100644 --- a/src/bsd/device.c +++ b/src/bsd/device.c @@ -29,12 +29,19 @@ #include "utils.h" #include "xalloc.h" +#ifdef HAVE_TUNEMU +#include "bsd/tunemu.h" +#endif + #define DEFAULT_DEVICE "/dev/tun0" typedef enum device_type { DEVICE_TYPE_TUN, DEVICE_TYPE_TUNIFHEAD, DEVICE_TYPE_TAP, +#ifdef HAVE_TUNEMU + DEVICE_TYPE_TUNEMU, +#endif } device_type_t; int device_fd = -1; @@ -43,7 +50,9 @@ char *iface = NULL; static char *device_info = NULL; static int device_total_in = 0; static int device_total_out = 0; -#if defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) +#if defined(TUNEMU) +static device_type_t device_type = DEVICE_TYPE_TUNEMU; +#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD; #else static device_type_t device_type = DEVICE_TYPE_TUN; @@ -60,14 +69,13 @@ bool setup_device(void) { if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) iface = xstrdup(rindex(device, '/') ? rindex(device, '/') + 1 : device); - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { - logger(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return false; - } - if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { if(!strcasecmp(type, "tun")) /* use default */; +#ifdef HAVE_TUNEMU + else if(!strcasecmp(type, "tunemu")) + device_type = DEVICE_TYPE_TUNEMU; +#endif else if(!strcasecmp(type, "tunnohead")) device_type = DEVICE_TYPE_TUN; else if(!strcasecmp(type, "tunifhead")) @@ -83,6 +91,23 @@ bool setup_device(void) { device_type = DEVICE_TYPE_TAP; } + switch(device_type) { +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: { + char dynamic_name[256] = ""; + device_fd = tunemu_open(dynamic_name); + } + break; +#endif + default: + device_fd = open(device, O_RDWR | O_NONBLOCK); + } + + if(device_fd < 0) { + logger(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return false; + } + switch(device_type) { default: device_type = DEVICE_TYPE_TUN; @@ -129,6 +154,11 @@ bool setup_device(void) { overwrite_mac = true; device_info = _("Generic BSD tap device"); break; +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: + device_info = _("BSD tunemu device"); + break; +#endif } logger(LOG_INFO, _("%s is a %s"), device, device_info); @@ -139,7 +169,15 @@ bool setup_device(void) { void close_device(void) { cp(); - close(device_fd); + switch(device_type) { +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: + tunemu_close(device_fd); + break; +#endif + default: + close(device_fd); + } free(device); free(iface); @@ -152,7 +190,16 @@ bool read_packet(vpn_packet_t *packet) { switch(device_type) { case DEVICE_TYPE_TUN: - if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) { +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: + if(device_type == DEVICE_TYPE_TUNEMU) + lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14); + else +#else + lenin = read(device_fd, packet->data + 14, MTU - 14); +#endif + + if(lenin <= 0) { logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); return false; @@ -228,6 +275,7 @@ bool read_packet(vpn_packet_t *packet) { ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); + logger(LOG_INFO, "E:fd_read"); return true; } @@ -284,6 +332,16 @@ bool write_packet(vpn_packet_t *packet) } break; +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: + if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) { + logger(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, + device, strerror(errno)); + return false; + } + break; +#endif + default: return false; } diff --git a/src/bsd/tunemu.c b/src/bsd/tunemu.c new file mode 100644 index 00000000..f532b04f --- /dev/null +++ b/src/bsd/tunemu.c @@ -0,0 +1,386 @@ +/* + * tunemu - Tun device emulation for Darwin + * Copyright (C) 2009 Friedrich Schöller + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "tunemu.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PPPPROTO_CTL 1 + +#define PPP_IP 0x21 +#define PPP_IPV6 0x57 + +#define SC_LOOP_TRAFFIC 0x00000200 + +#define PPPIOCNEWUNIT _IOWR('t', 62, int) +#define PPPIOCSFLAGS _IOW('t', 89, int) +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) +#define PPPIOCATTCHAN _IOW('t', 56, int) +#define PPPIOCGCHAN _IOR('t', 55, int) +#define PPPIOCCONNECT _IOW('t', 58, int) +#define PPPIOCGUNIT _IOR('t', 86, int) + +struct sockaddr_ppp +{ + u_int8_t ppp_len; + u_int8_t ppp_family; + u_int16_t ppp_proto; + u_int32_t ppp_cookie; +}; + +enum NPmode +{ + NPMODE_PASS, + NPMODE_DROP, + NPMODE_ERROR, + NPMODE_QUEUE +}; + +struct npioctl +{ + int protocol; + enum NPmode mode; +}; + +#define PPP_KEXT_PATH "/System/Library/Extensions/PPP.kext" + +#define ERROR_BUFFER_SIZE 1024 + +char tunemu_error[ERROR_BUFFER_SIZE]; + +static int pcap_use_count = 0; +static pcap_t *pcap = NULL; + +static int data_buffer_length = 0; +static char *data_buffer = NULL; + +static void tun_error(char *format, ...) +{ + va_list vl; + va_start(vl, format); + vsnprintf(tunemu_error, ERROR_BUFFER_SIZE, format, vl); + va_end(vl); +} + +static void tun_noerror() +{ + *tunemu_error = 0; +} + +static void closeall() +{ + int fd = getdtablesize(); + while (fd--) + close(fd); + + open("/dev/null", O_RDWR, 0); + dup(0); + dup(0); +} + +static int ppp_load_kext() +{ + int pid = fork(); + if (pid < 0) + { + tun_error("fork for ppp kext: %s", strerror(errno)); + return -1; + } + + if (pid == 0) + { + closeall(); + execle("/sbin/kextload", "kextload", PPP_KEXT_PATH, NULL, NULL); + exit(1); + } + + int status; + while (waitpid(pid, &status, 0) < 0) + { + if (errno == EINTR) + continue; + + tun_error("waitpid for ppp kext: %s", strerror(errno)); + return -1; + } + + if (WEXITSTATUS(status) != 0) + { + tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH); + return -1; + } + + tun_noerror(); + return 0; +} + +static int ppp_new_instance() +{ + // create ppp socket + int ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL); + if (ppp_sockfd < 0) + { + if (ppp_load_kext() < 0) + return -1; + + ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL); + if (ppp_sockfd < 0) + { + tun_error("creating ppp socket: %s", strerror(errno)); + return -1; + } + } + + // connect to ppp procotol + struct sockaddr_ppp pppaddr; + pppaddr.ppp_len = sizeof(struct sockaddr_ppp); + pppaddr.ppp_family = AF_PPP; + pppaddr.ppp_proto = PPPPROTO_CTL; + pppaddr.ppp_cookie = 0; + if (connect(ppp_sockfd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0) + { + tun_error("connecting ppp socket: %s", strerror(errno)); + close(ppp_sockfd); + return -1; + } + + tun_noerror(); + return ppp_sockfd; +} + +static int ppp_new_unit(int *unit_number) +{ + int fd = ppp_new_instance(); + if (fd < 0) + return -1; + + // create ppp unit + if (ioctl(fd, PPPIOCNEWUNIT, unit_number) < 0) + { + tun_error("creating ppp unit: %s", strerror(errno)); + close(fd); + return -1; + } + + tun_noerror(); + return fd; +} + +static int ppp_setup_unit(int unit_fd) +{ + // send traffic to program + int flags = SC_LOOP_TRAFFIC; + if (ioctl(unit_fd, PPPIOCSFLAGS, &flags) < 0) + { + tun_error("setting ppp loopback mode: %s", strerror(errno)); + return -1; + } + + // allow packets + struct npioctl npi; + npi.protocol = PPP_IP; + npi.mode = NPMODE_PASS; + if (ioctl(unit_fd, PPPIOCSNPMODE, &npi) < 0) + { + tun_error("starting ppp unit: %s", strerror(errno)); + return -1; + } + + tun_noerror(); + return 0; +} + +static int open_pcap() +{ + if (pcap != NULL) + { + pcap_use_count++; + return 0; + } + + char errbuf[PCAP_ERRBUF_SIZE]; + pcap = pcap_open_live("lo0", BUFSIZ, 0, 1, errbuf); + pcap_use_count = 1; + + if (pcap == NULL) + { + tun_error("opening pcap: %s", errbuf); + return -1; + } + + tun_noerror(); + return 0; +} + +static void close_pcap() +{ + if (pcap == NULL) + return; + + pcap_use_count--; + if (pcap_use_count == 0) + { + pcap_close(pcap); + pcap = NULL; + } +} + +static void allocate_data_buffer(int size) +{ + if (data_buffer_length < size) + { + free(data_buffer); + data_buffer_length = size; + data_buffer = malloc(data_buffer_length); + } +} + +static void make_device_name(tunemu_device device, int unit_number) +{ + snprintf(device, sizeof(tunemu_device), "ppp%d", unit_number); +} + +static int check_device_name(tunemu_device device) +{ + if (strlen(device) < 4) + return -1; + + int unit_number = atoi(device + 3); + if (unit_number < 0 || unit_number > 999) + return -1; + + tunemu_device compare; + make_device_name(compare, unit_number); + + if (strcmp(device, compare) != 0) + return -1; + + return 0; +} + +int tunemu_open(tunemu_device device) +{ + int ppp_unit_number = -1; + if (device[0] != 0) + { + if (check_device_name(device) < 0) + { + tun_error("invalid device name \"%s\"", device); + return -1; + } + + ppp_unit_number = atoi(device + 3); + } + + int ppp_unit_fd = ppp_new_unit(&ppp_unit_number); + if (ppp_unit_fd < 0) + return -1; + + if (ppp_setup_unit(ppp_unit_fd) < 0) + { + close(ppp_unit_fd); + return -1; + } + + if (open_pcap() < 0) + { + close(ppp_unit_fd); + return -1; + } + + make_device_name(device, ppp_unit_number); + + return ppp_unit_fd; +} + +int tunemu_close(int ppp_sockfd) +{ + int ret = close(ppp_sockfd); + + if (ret == 0) + close_pcap(); + + return ret; +} + +int tunemu_read(int ppp_sockfd, char *buffer, int length) +{ + allocate_data_buffer(length + 2); + + length = read(ppp_sockfd, data_buffer, length + 2); + if (length < 0) + { + tun_error("reading packet: %s", strerror(errno)); + return length; + } + tun_noerror(); + + length -= 2; + if (length < 0) + return 0; + + memcpy(buffer, data_buffer + 2, length); + + return length; +} + +int tunemu_write(int ppp_sockfd, char *buffer, int length) +{ + allocate_data_buffer(length + 4); + + data_buffer[0] = 0x02; + data_buffer[1] = 0x00; + data_buffer[2] = 0x00; + data_buffer[3] = 0x00; + + memcpy(data_buffer + 4, buffer, length); + + if (pcap == NULL) + { + tun_error("pcap not open"); + return -1; + } + + length = pcap_inject(pcap, data_buffer, length + 4); + if (length < 0) + { + tun_error("injecting packet: %s", pcap_geterr(pcap)); + return length; + } + tun_noerror(); + + length -= 4; + if (length < 0) + return 0; + + return length; +} diff --git a/src/bsd/tunemu.h b/src/bsd/tunemu.h new file mode 100644 index 00000000..42b1785b --- /dev/null +++ b/src/bsd/tunemu.h @@ -0,0 +1,32 @@ +/* + * tunemu - Tun device emulation for Darwin + * Copyright (C) 2009 Friedrich Schöller + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef TUNEMU_H +#define TUNEMU_H + +typedef char tunemu_device[7]; + +extern char tunemu_error[]; + +int tunemu_open(tunemu_device dev); +int tunemu_close(int fd); +int tunemu_read(int fd, char *buffer, int length); +int tunemu_write(int fd, char *buffer, int length); + +#endif From a60a0a1f1357508063ee565d672c39898a787e33 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 10 Sep 2009 19:51:08 +0200 Subject: [PATCH 17/32] Don't stat() on iPhone/iPod. Grzegorz Dymarek noted that tinc segfaults at the stat() call in execute_script() on the iPhone. We can omit the stat() call for the moment, the subsequent call to system() will fail with just a warning. --- src/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/process.c b/src/process.c index d07ce7db..f03f12a4 100644 --- a/src/process.c +++ b/src/process.c @@ -380,12 +380,14 @@ bool execute_script(const char *name, char **envp) scriptname[len - 1] = '\0'; +#ifndef HAVE_TUNEMU /* First check if there is a script */ if(stat(scriptname + 1, &s)) { free(scriptname); return true; } +#endif ifdebug(STATUS) logger(LOG_INFO, _("Executing script %s"), name); From 052ff8b2c598358d1c5febaa9f9f5fc5d384cfd3 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 12 Sep 2009 13:34:11 +0200 Subject: [PATCH 18/32] Put Subnet weight in a separate environment variable. Commit 5674bba5c54c1aee3a4ac5b3aba6b3ebded91bbc introduced weighted Subnets, but the weight was included in the SUBNET variable passed to subnet-up/down scripts. This makes it harder to use in those scripts. The weight is now stripped from the SUBNET variable and put in the WEIGHT variabel. --- src/subnet.c | 55 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/src/subnet.c b/src/subnet.c index 334729db..140b6145 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -476,9 +476,12 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) void subnet_update(node_t *owner, subnet_t *subnet, bool up) { avl_node_t *node; int i; - char *envp[8]; - char netstr[MAXNETSTR + 7] = "SUBNET="; + char *envp[9] = {0}; + char netstr[MAXNETSTR]; char *name, *address, *port; + char empty[] = ""; + + // Prepare environment variables to be passed to the script xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); xasprintf(&envp[1], "DEVICE=%s", device ? : ""); @@ -487,13 +490,9 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) { if(owner != myself) { sockaddr2str(&owner->address, &address, &port); - xasprintf(&envp[4], "REMOTEADDRESS=%s", address); - xasprintf(&envp[5], "REMOTEPORT=%s", port); - envp[6] = netstr; - envp[7] = NULL; - } else { - envp[4] = netstr; - envp[5] = NULL; + // 4 and 5 are reserved for SUBNET and WEIGHT + xasprintf(&envp[6], "REMOTEADDRESS=%s", address); + xasprintf(&envp[7], "REMOTEPORT=%s", port); } name = up ? "subnet-up" : "subnet-down"; @@ -501,22 +500,44 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) { if(!subnet) { for(node = owner->subnet_tree->head; node; node = node->next) { subnet = node->data; - if(!net2str(netstr + 7, sizeof netstr - 7, subnet)) + if(!net2str(netstr, sizeof netstr, subnet)) continue; + // Strip the weight from the subnet, and put it in its own environment variable + char *weight = strchr(netstr + 7, '#'); + if(weight) + *weight++ = 0; + else + weight = empty; + + // Prepare the SUBNET and WEIGHT variables + if(envp[4]) + free(envp[4]); + if(envp[5]) + free(envp[5]); + xasprintf(&envp[4], "SUBNET=%s", netstr); + xasprintf(&envp[5], "WEIGHT=%s", weight); + execute_script(name, envp); } } else { - if(net2str(netstr + 7, sizeof netstr - 7, subnet)) + if(net2str(netstr + 7, sizeof netstr - 7, subnet)) { + // Strip the weight from the subnet, and put it in its own environment variable + char *weight = strchr(netstr + 7, '#'); + if(weight) + *weight++ = 0; + else + weight = empty; + + // Prepare the SUBNET and WEIGHT variables + xasprintf(&envp[4], "SUBNET=%s", netstr); + xasprintf(&envp[5], "WEIGHT=%s", weight); + execute_script(name, envp); + } } - for(i = 0; i < (owner != myself ? 6 : 4); i++) + for(i = 0; envp[i] && i < 9; i++) free(envp[i]); - - if(owner != myself) { - free(address); - free(port); - } } void dump_subnets(void) From 7242868b64f9d6f62b6c5bbf1526eb632ed9a4d6 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 12 Sep 2009 13:40:32 +0200 Subject: [PATCH 19/32] Allow PMTUDiscovery in switch and hub modes again. PMTUDiscovery was disabled in commit d5b56bbba56480b5565ffb38496175a7c1df60ac because tinc did not handle packets larger than the path MTU in switch and hub modes. We now allow it again in preparation of proper support, but default to off. --- src/net_setup.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/net_setup.c b/src/net_setup.c index 4eef68ed..d45cb1bb 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -306,9 +306,12 @@ bool setup_myself(void) } else routing_mode = RMODE_ROUTER; - if(routing_mode == RMODE_ROUTER) - if(!get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice) || choice) - myself->options |= OPTION_PMTU_DISCOVERY; + // Enable PMTUDiscovery by default if we are in router mode. + + choice = routing_mode == RMODE_ROUTER; + get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice); + if(choice) + myself->options |= OPTION_PMTU_DISCOVERY; get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); From 9915f2abbedb7f1aa2b9e2f81d52ddcfca60e82d Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 12 Sep 2009 14:19:36 +0200 Subject: [PATCH 20/32] Handle unicast packets larger than PMTU in switch mode. If PMTUDiscovery is enabled, and we see a unicast packet that is larger than the path MTU in switch mode, treat it just like we would do in router mode. --- src/route.c | 110 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 36 deletions(-) diff --git a/src/route.c b/src/route.c index e79fae51..d748db16 100644 --- a/src/route.c +++ b/src/route.c @@ -94,6 +94,13 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) { } else return true; } + +static void swap_mac_addresses(vpn_packet_t *packet) { + mac_t tmp; + memcpy(&tmp, &packet->data[0], sizeof tmp); + memcpy(&packet->data[0], &packet->data[6], sizeof tmp); + memcpy(&packet->data[6], &tmp, sizeof tmp); +} static void learn_mac(mac_t *address) { @@ -160,40 +167,6 @@ void age_subnets(void) } } -static void route_mac(node_t *source, vpn_packet_t *packet) -{ - subnet_t *subnet; - mac_t dest; - - cp(); - - - /* Learn source address */ - - if(source == myself) { - mac_t src; - memcpy(&src, &packet->data[6], sizeof src); - learn_mac(&src); - } - - /* Lookup destination address */ - - memcpy(&dest, &packet->data[0], sizeof dest); - subnet = lookup_subnet_mac(&dest); - - if(!subnet) { - broadcast_packet(source, packet); - return; - } - - if(subnet->owner == source) { - ifdebug(TRAFFIC) logger(LOG_WARNING, _("Packet looping back to %s (%s)!"), source->name, source->hostname); - return; - } - - send_packet(subnet->owner, packet); -} - /* RFC 792 */ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) @@ -210,6 +183,10 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t cp(); + /* Swap Ethernet source and destination addresses */ + + swap_mac_addresses(packet); + /* Copy headers from packet into properly aligned structs on the stack */ memcpy(&ip, packet->data + ether_size, ip_size); @@ -406,6 +383,10 @@ static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t cp(); + /* Swap Ethernet source and destination addresses */ + + swap_mac_addresses(packet); + /* Copy headers from packet to structs on the stack */ memcpy(&ip6, packet->data + ether_size, ip6_size); @@ -743,6 +724,64 @@ static void route_arp(node_t *source, vpn_packet_t *packet) send_packet(source, packet); } +static void route_mac(node_t *source, vpn_packet_t *packet) +{ + subnet_t *subnet; + mac_t dest; + + cp(); + + + /* Learn source address */ + + if(source == myself) { + mac_t src; + memcpy(&src, &packet->data[6], sizeof src); + learn_mac(&src); + } + + /* Lookup destination address */ + + memcpy(&dest, &packet->data[0], sizeof dest); + subnet = lookup_subnet_mac(&dest); + + if(!subnet) { + broadcast_packet(source, packet); + return; + } + + if(subnet->owner == source) { + ifdebug(TRAFFIC) logger(LOG_WARNING, _("Packet looping back to %s (%s)!"), source->name, source->hostname); + return; + } + + // Handle packets larger than PMTU + + node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; + + if(via && packet->len > via->mtu && via != myself) { + ifdebug(TRAFFIC) logger(LOG_INFO, _("Packet for %s (%s) length %d larger than MTU %d"), subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); + uint16_t type = packet->data[12] << 8 | packet->data[13]; + if(type == ETH_P_IP) { + if(packet->data[20] & 0x40) { + packet->len = via->mtu; + route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); + } else { + fragment_ipv4_packet(via, packet); + } + } else if(type == ETH_P_IPV6) { + packet->len = via->mtu; + route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0); + } else + ifdebug(TRAFFIC) logger(LOG_INFO, _("Large packet of unhandled type %hx dropped"), type); + + return; + } + + send_packet(subnet->owner, packet); +} + + void route(node_t *source, vpn_packet_t *packet) { cp(); @@ -753,9 +792,8 @@ void route(node_t *source, vpn_packet_t *packet) switch (routing_mode) { case RMODE_ROUTER: { - uint16_t type; + uint16_t type = packet->data[12] << 8 | packet->data[13]; - type = ntohs(*((uint16_t *)(&packet->data[12]))); switch (type) { case ETH_P_ARP: route_arp(source, packet); From 23e151aeed6b3ffe0fab10f51ffdb134deb7a852 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 13 Sep 2009 14:07:40 +0200 Subject: [PATCH 21/32] Remove superfluous call to avl_delete(). --- src/node.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/node.c b/src/node.c index 0c9033ca..4fbec08f 100644 --- a/src/node.c +++ b/src/node.c @@ -174,7 +174,6 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) if(sa) { n->address = *sa; n->hostname = sockaddr2hostname(&n->address); - avl_delete(node_udp_tree, n); avl_insert(node_udp_tree, n); ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); } else { From 75773efe2689d347a2f219c5f27e4a82eef1236b Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 13 Sep 2009 14:08:59 +0200 Subject: [PATCH 22/32] Apparently it's impolite to ask GCC to subtract two pointers. If two pointers do not belong to the same array, pointer subtraction gives nonsensical results, depending on the level of optimisation and the architecture one is compiling for. It is apparently not just subtracting the pointer values and dividing by the size of the object, but uses some kind of higher magic not intended for mere mortals. GCC will not warn about this at all. Casting to void * is also a no-no, because then GCC does warn that strict aliasing rules are being broken. The only safe way to query the ordering of two pointers is to use the (in)equality operators. The unsafe implementation of connection_compare() has probably caused the "old connection_t for ... still lingering" messages. Our implementation of AVL trees is augmented with a doubly linked list, which is normally what is traversed. Only when deleting an old connection the tree itself is traversed. --- src/connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/connection.c b/src/connection.c index 66eb0596..283ebd71 100644 --- a/src/connection.c +++ b/src/connection.c @@ -37,7 +37,7 @@ connection_t *broadcast; static int connection_compare(const connection_t *a, const connection_t *b) { - return a - b; + return a < b ? -1 : a == b ? 0 : 1; } void init_connections(void) From 35e87b903e08fc51975a8cc97f06251d5153a424 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 14 Sep 2009 23:06:00 +0200 Subject: [PATCH 23/32] Use only rand(), not random(). We used both rand() and random() in our code. Since it returns an int, we have to use %x in our format strings instead of %lx. This fixes a crash under Windows when cross-compiling tinc with a recent version of MinGW. --- src/net_packet.c | 2 +- src/protocol_edge.c | 4 ++-- src/protocol_key.c | 2 +- src/protocol_subnet.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/net_packet.c b/src/net_packet.c index 31c44771..2be599eb 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -87,7 +87,7 @@ void send_mtu_probe(node_t *n) return; } - len = n->minmtu + 1 + random() % (n->maxmtu - n->minmtu); + len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); if(len < 64) len = 64; diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 0db3e7b7..4066a30d 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -45,7 +45,7 @@ bool send_add_edge(connection_t *c, const edge_t *e) sockaddr2str(&e->address, &address, &port); - x = send_request(c, "%d %lx %s %s %s %s %lx %d", ADD_EDGE, random(), + x = send_request(c, "%d %x %s %s %s %s %lx %d", ADD_EDGE, rand(), e->from->name, e->to->name, address, port, e->options, e->weight); free(address); @@ -178,7 +178,7 @@ bool send_del_edge(connection_t *c, const edge_t *e) { cp(); - return send_request(c, "%d %lx %s %s", DEL_EDGE, random(), + return send_request(c, "%d %x %s %s", DEL_EDGE, rand(), e->from->name, e->to->name); } diff --git a/src/protocol_key.c b/src/protocol_key.c index 41479148..7ae98036 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -49,7 +49,7 @@ bool send_key_changed() if(!mykeyused) return true; - return send_request(broadcast, "%d %lx %s", KEY_CHANGED, random(), myself->name); + return send_request(broadcast, "%d %x %s", KEY_CHANGED, rand(), myself->name); } bool key_changed_h(connection_t *c) diff --git a/src/protocol_subnet.c b/src/protocol_subnet.c index d40b3a33..b50cf6a3 100644 --- a/src/protocol_subnet.c +++ b/src/protocol_subnet.c @@ -42,7 +42,7 @@ bool send_add_subnet(connection_t *c, const subnet_t *subnet) if(!net2str(netstr, sizeof netstr, subnet)) return false; - return send_request(c, "%d %lx %s %s", ADD_SUBNET, random(), subnet->owner->name, netstr); + return send_request(c, "%d %x %s %s", ADD_SUBNET, rand(), subnet->owner->name, netstr); } bool add_subnet_h(connection_t *c) @@ -161,7 +161,7 @@ bool send_del_subnet(connection_t *c, const subnet_t *s) if(!net2str(netstr, sizeof netstr, s)) return false; - return send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr); + return send_request(c, "%d %x %s %s", DEL_SUBNET, rand(), s->owner->name, netstr); } bool del_subnet_h(connection_t *c) From f80bf14f28925df6eaa56f3ed77adaf418ab9890 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 14 Sep 2009 23:28:28 +0200 Subject: [PATCH 24/32] Also do not use drand48(), it is not available on Windows. --- src/net.c | 1 - src/protocol_misc.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net.c b/src/net.c index 3cf1773d..c893f1e4 100644 --- a/src/net.c +++ b/src/net.c @@ -366,7 +366,6 @@ int main_loop(void) last_graph_dump = now; srand(now); - srand48(now); running = true; diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 8f56aee5..18ff13c8 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -158,7 +158,7 @@ bool send_tcppacket(connection_t *c, vpn_packet_t *packet) /* If there already is a lot of data in the outbuf buffer, discard this packet. We use a very simple Random Early Drop algorithm. */ - if(2.0 * c->outbuflen / (double)maxoutbufsize - 1 > drand48()) + if(2.0 * c->outbuflen / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX) return true; if(!send_request(c, "%d %hd", PACKET, packet->len)) From fa9bedd47cf8c143e801889c78f0a0979ac4d2fc Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 15 Sep 2009 00:24:31 +0200 Subject: [PATCH 25/32] Allow compiling for Windows XP and higher. This allows us to use getaddrinfo(), getnameinfo() and related functions, which allow tinc to make connections over existing IPv6 networks. These functions are not available on Windows 2000 however. By default, support is enabled, but when compiling for Windows 2000 the configure switch --with-windows2000 should be used. Since getaddrinfo() et al. are not functions but macros on Windows, we have to use AC_CHECK_DECLS() instead of AC_CHECK_FUNCS() in configure.in. --- configure.in | 7 ++++++- have.h | 16 +++++++++++----- lib/dropin.h | 5 ----- lib/fake-getaddrinfo.c | 6 +++--- lib/fake-getaddrinfo.h | 6 +++--- lib/fake-getnameinfo.c | 2 +- lib/fake-getnameinfo.h | 2 +- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/configure.in b/configure.in index eff93a08..1ff36b3f 100644 --- a/configure.in +++ b/configure.in @@ -82,6 +82,11 @@ AC_ARG_ENABLE(tunemu, ] ) +AC_ARG_WITH(windows2000, + AS_HELP_STRING([--with-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]), + [AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])] +) + AM_CONDITIONAL(TUNEMU, test "$tunemu" = true) AC_CACHE_SAVE @@ -143,7 +148,7 @@ AC_CHECK_FUNC(gethostbyname, [], [ AC_CHECK_LIB(nsl, gethostbyname) ]) -AC_CHECK_FUNCS([freeaddrinfo gai_strerror getaddrinfo getnameinfo inet_aton], +AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo], [], [], [#include "have.h"] ) diff --git a/have.h b/have.h index 8a58af33..7e2930dc 100644 --- a/have.h +++ b/have.h @@ -31,6 +31,17 @@ #include #include +#ifdef HAVE_MINGW +#ifdef WITH_WINDOWS2000 +#define WINVER Windows2000 +#else +#define WINVER WindowsXP +#endif +#include +#include +#include +#endif + #ifdef HAVE_STDBOOL_H #include #endif @@ -160,9 +171,4 @@ #include #endif -#ifdef HAVE_MINGW -#include -#include -#endif - #endif /* __TINC_SYSTEM_H__ */ diff --git a/lib/dropin.h b/lib/dropin.h index 72109c84..4db7d7e0 100644 --- a/lib/dropin.h +++ b/lib/dropin.h @@ -39,11 +39,6 @@ extern int asprintf(char **, const char *, ...); extern int vasprintf(char **, const char *, va_list ap); #endif -#ifndef HAVE_GETNAMEINFO -extern int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, - size_t hostlen, char *serv, size_t servlen, int flags); -#endif - #ifndef HAVE_GETTIMEOFDAY extern int gettimeofday(struct timeval *, void *); #endif diff --git a/lib/fake-getaddrinfo.c b/lib/fake-getaddrinfo.c index 14420b58..10672b7e 100644 --- a/lib/fake-getaddrinfo.c +++ b/lib/fake-getaddrinfo.c @@ -16,7 +16,7 @@ #include "fake-getaddrinfo.h" #include "xalloc.h" -#ifndef HAVE_GAI_STRERROR +#if !HAVE_DECL_GAI_STRERROR char *gai_strerror(int ecode) { switch (ecode) { @@ -32,7 +32,7 @@ char *gai_strerror(int ecode) } #endif /* !HAVE_GAI_STRERROR */ -#ifndef HAVE_FREEADDRINFO +#if !HAVE_DECL_FREEADDRINFO void freeaddrinfo(struct addrinfo *ai) { struct addrinfo *next; @@ -45,7 +45,7 @@ void freeaddrinfo(struct addrinfo *ai) } #endif /* !HAVE_FREEADDRINFO */ -#ifndef HAVE_GETADDRINFO +#if !HAVE_DECL_GETADDRINFO static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr) { struct addrinfo *ai; diff --git a/lib/fake-getaddrinfo.h b/lib/fake-getaddrinfo.h index d2b46f62..d31a89a1 100644 --- a/lib/fake-getaddrinfo.h +++ b/lib/fake-getaddrinfo.h @@ -33,16 +33,16 @@ struct addrinfo { }; #endif /* !HAVE_STRUCT_ADDRINFO */ -#ifndef HAVE_GETADDRINFO +#if !HAVE_DECL_GETADDRINFO int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res); #endif /* !HAVE_GETADDRINFO */ -#ifndef HAVE_GAI_STRERROR +#if !HAVE_DECL_GAI_STRERROR char *gai_strerror(int ecode); #endif /* !HAVE_GAI_STRERROR */ -#ifndef HAVE_FREEADDRINFO +#if !HAVE_DECL_FREEADDRINFO void freeaddrinfo(struct addrinfo *ai); #endif /* !HAVE_FREEADDRINFO */ diff --git a/lib/fake-getnameinfo.c b/lib/fake-getnameinfo.c index 796efdf8..80471730 100644 --- a/lib/fake-getnameinfo.c +++ b/lib/fake-getnameinfo.c @@ -14,7 +14,7 @@ #include "fake-getnameinfo.h" #include "fake-getaddrinfo.h" -#ifndef HAVE_GETNAMEINFO +#if !HAVE_DECL_GETNAMEINFO int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { diff --git a/lib/fake-getnameinfo.h b/lib/fake-getnameinfo.h index 0f0b4bcc..02ac77a1 100644 --- a/lib/fake-getnameinfo.h +++ b/lib/fake-getnameinfo.h @@ -3,7 +3,7 @@ #ifndef _FAKE_GETNAMEINFO_H #define _FAKE_GETNAMEINFO_H -#ifndef HAVE_GETNAMEINFO +#if !HAVE_DECL_GETNAMEINFO int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); #endif /* !HAVE_GETNAMEINFO */ From 6f1e0ece4e61f30612ed84ca4640635a02892cc8 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 15 Sep 2009 00:28:20 +0200 Subject: [PATCH 26/32] Remove dropin random() function, as it is not used anymore. --- lib/dropin.c | 12 ------------ lib/dropin.h | 4 ---- 2 files changed, 16 deletions(-) diff --git a/lib/dropin.c b/lib/dropin.c index 23d2b136..f6eda42a 100644 --- a/lib/dropin.c +++ b/lib/dropin.c @@ -168,15 +168,3 @@ int gettimeofday(struct timeval *tv, void *tz) { return 0; } #endif - -#ifndef HAVE_RANDOM -#include - -long int random(void) { - long int x; - - RAND_pseudo_bytes((unsigned char *)&x, sizeof(x)); - - return x; -} -#endif diff --git a/lib/dropin.h b/lib/dropin.h index 4db7d7e0..8c2e94a3 100644 --- a/lib/dropin.h +++ b/lib/dropin.h @@ -43,8 +43,4 @@ extern int vasprintf(char **, const char *, va_list ap); extern int gettimeofday(struct timeval *, void *); #endif -#ifndef HAVE_RANDOM -extern long int random(void); -#endif - #endif /* __DROPIN_H__ */ From 633c0cf1b067d118d5453bc8522fab65ffc82d2c Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 15 Sep 2009 00:36:07 +0200 Subject: [PATCH 27/32] Use access() instead of stat() for checking whether scripts exist. --- src/process.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/process.c b/src/process.c index f03f12a4..544c2242 100644 --- a/src/process.c +++ b/src/process.c @@ -364,7 +364,6 @@ bool execute_script(const char *name, char **envp) { #ifdef HAVE_SYSTEM int status, len; - struct stat s; char *scriptname, *p; int i; @@ -383,7 +382,7 @@ bool execute_script(const char *name, char **envp) #ifndef HAVE_TUNEMU /* First check if there is a script */ - if(stat(scriptname + 1, &s)) { + if(access(scriptname + 1, F_OK)) { free(scriptname); return true; } From 4bb3793e38b7c7f24dd308801e7f6dbb02cf02d2 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 15 Sep 2009 12:08:05 +0200 Subject: [PATCH 28/32] Raise default crypto algorithms to AES256 and SHA256. In light of the recent improvements of attacks on SHA1, the default hash algorithm in tinc is now SHA256. At the same time, the default symmetric encryption algorithm has been changed to AES256. --- src/net_setup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/net_setup.c b/src/net_setup.c index d45cb1bb..3c4bf48c 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -362,14 +362,14 @@ bool setup_myself(void) } } } else - myself->incipher = EVP_bf_cbc(); + myself->incipher = EVP_aes_256_cbc(); if(myself->incipher) myself->inkeylength = myself->incipher->key_len + myself->incipher->iv_len; else myself->inkeylength = 1; - myself->connection->outcipher = EVP_bf_ofb(); + myself->connection->outcipher = EVP_aes_256_ofb(); if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) keylifetime = 3600; @@ -390,9 +390,9 @@ bool setup_myself(void) } } } else - myself->indigest = EVP_sha1(); + myself->indigest = EVP_sha256(); - myself->connection->outdigest = EVP_sha1(); + myself->connection->outdigest = EVP_sha256(); if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->inmaclength)) { if(myself->indigest) { From 802a50ffcd5f39bfc6424ac841de4e41154092fc Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 15 Sep 2009 22:58:16 +0200 Subject: [PATCH 29/32] Remove extra {. --- lib/dropin.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/dropin.c b/lib/dropin.c index f6eda42a..1c2592df 100644 --- a/lib/dropin.c +++ b/lib/dropin.c @@ -135,7 +135,6 @@ int asprintf(char **buf, const char *fmt, ...) { } int vasprintf(char **buf, const char *fmt, va_list ap) { -{ int status; va_list aq; int len; From b47c17bcdeb70b63ad9346dc97ba575597cbd803 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 15 Sep 2009 22:59:01 +0200 Subject: [PATCH 30/32] Use a mutex to allow the TAP reader to process packets faster on Windows. The TAP-Win32 device is not a socket, and select() under Windows only works with sockets. Tinc used a separate thread to read from the TAP-Win32 device, and passed this via a local socket to the main thread which could then select() from it. We now use a global mutex, which is only unlocked when the main thread is waiting for select(), to allow the TAP reader thread to process packets directly. --- src/mingw/device.c | 126 ++++----------------------------------------- src/net.c | 11 +++- src/net.h | 2 + src/tincd.c | 3 ++ 4 files changed, 25 insertions(+), 117 deletions(-) diff --git a/src/mingw/device.c b/src/mingw/device.c index e025cf78..fa134332 100644 --- a/src/mingw/device.c +++ b/src/mingw/device.c @@ -34,7 +34,7 @@ #include "mingw/common.h" -int device_fd = 0; +int device_fd = -1; static HANDLE device_handle = INVALID_HANDLE_VALUE; char *device = NULL; char *iface = NULL; @@ -45,63 +45,24 @@ static int device_total_out = 0; extern char *myport; -static struct packetbuf { - uint8_t data[MTU]; - length_t len; -} *bufs; - -static int nbufs = 64; - static DWORD WINAPI tapreader(void *bla) { - int sock, err, status; - struct addrinfo *ai; - struct addrinfo hint = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - .ai_flags = 0, - }; - unsigned char bufno = 0; + int status; long len; OVERLAPPED overlapped; - - /* Open a socket to the parent process */ - - err = getaddrinfo(NULL, myport, &hint, &ai); - - if(err || !ai) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(errno)); - return -1; - } - - sock = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); - - if(sock < 0) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "socket", strerror(errno)); - freeaddrinfo(ai); - return -1; - } - - if(connect(sock, ai->ai_addr, ai->ai_addrlen)) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "connect", strerror(errno)); - freeaddrinfo(ai); - return -1; - } - - freeaddrinfo(ai); + vpn_packet_t packet; logger(LOG_DEBUG, _("Tap reader running")); /* Read from tap device and send to parent */ overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - + for(;;) { overlapped.Offset = 0; overlapped.OffsetHigh = 0; ResetEvent(overlapped.hEvent); - status = ReadFile(device_handle, bufs[bufno].data, MTU, &len, &overlapped); + status = ReadFile(device_handle, packet.data, MTU, &len, &overlapped); if(!status) { if(GetLastError() == ERROR_IO_PENDING) { @@ -115,11 +76,11 @@ static DWORD WINAPI tapreader(void *bla) { } } - bufs[bufno].len = len; - if(send(sock, &bufno, 1, 0) <= 0) - return -1; - if(++bufno >= nbufs) - bufno = 0; + EnterCriticalSection(&mutex); + packet.len = len; + packet.priority = 0; + route(myself, &packet); + LeaveCriticalSection(&mutex); } } @@ -240,44 +201,6 @@ bool setup_device(void) overwrite_mac = 1; } - /* Set up ringbuffer */ - - get_config_int(lookup_config(config_tree, "RingBufferSize"), &nbufs); - if(nbufs <= 1) - nbufs = 1; - else if(nbufs > 256) - nbufs = 256; - - bufs = xmalloc_and_zero(nbufs * sizeof *bufs); - - /* Create a listening socket */ - - err = getaddrinfo(NULL, myport, &hint, &ai); - - if(err || !ai) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(errno)); - return false; - } - - sock = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); - - if(sock < 0) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "socket", strerror(errno)); - return false; - } - - if(bind(sock, ai->ai_addr, ai->ai_addrlen)) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "bind", strerror(errno)); - return false; - } - - freeaddrinfo(ai); - - if(listen(sock, 1)) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno)); - return false; - } - /* Start the tap reader */ thread = CreateThread(NULL, 0, tapreader, NULL, 0, NULL); @@ -287,15 +210,6 @@ bool setup_device(void) return false; } - /* Wait for the tap reader to connect back to us */ - - if((device_fd = accept(sock, NULL, 0)) == -1) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "accept", strerror(errno)); - return false; - } - - closesocket(sock); - /* Set media status for newer TAP-Win32 devices */ status = true; @@ -320,25 +234,7 @@ void close_device(void) bool read_packet(vpn_packet_t *packet) { - unsigned char bufno; - - cp(); - - if((recv(device_fd, &bufno, 1, 0)) <= 0) { - logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, - device, strerror(errno)); - return false; - } - - packet->len = bufs[bufno].len; - memcpy(packet->data, bufs[bufno].data, bufs[bufno].len); - - device_total_in += packet->len; - - ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, - device_info); - - return true; + return false; } bool write_packet(vpn_packet_t *packet) diff --git a/src/net.c b/src/net.c index c893f1e4..82b0ede1 100644 --- a/src/net.c +++ b/src/net.c @@ -149,7 +149,8 @@ static int build_fdset(fd_set *readset, fd_set *writeset) max = listen_socket[i].udp; } - FD_SET(device_fd, readset); + if(device_fd >= 0) + FD_SET(device_fd, readset); if(device_fd > max) max = device_fd; @@ -294,7 +295,7 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) cp(); /* check input from kernel */ - if(FD_ISSET(device_fd, readset)) { + if(device_fd >= 0 && FD_ISSET(device_fd, readset)) { if(read_packet(&packet)) { packet.priority = 0; route(myself, &packet); @@ -378,7 +379,13 @@ int main_loop(void) maxfd = build_fdset(&readset, &writeset); +#ifdef HAVE_MINGW + LeaveCriticalSection(&mutex); +#endif r = select(maxfd + 1, &readset, &writeset, NULL, &tv); +#ifdef HAVE_MINGW + EnterCriticalSection(&mutex); +#endif if(r < 0) { if(errno != EINTR && errno != EAGAIN) { diff --git a/src/net.h b/src/net.h index 0f70a4b4..ff32b73c 100644 --- a/src/net.h +++ b/src/net.h @@ -143,6 +143,8 @@ extern void send_mtu_probe(struct node_t *); #ifndef HAVE_MINGW #define closesocket(s) close(s) +#else +extern CRITICAL_SECTION mutex; #endif #endif /* __TINC_NET_H__ */ diff --git a/src/tincd.c b/src/tincd.c index a13e2661..b2e055c6 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -115,6 +115,7 @@ static struct option const long_options[] = { #ifdef HAVE_MINGW static struct WSAData wsa_state; +CRITICAL_SECTION mutex; #endif static void usage(bool status) @@ -568,6 +569,8 @@ int main(int argc, char **argv) int main2(int argc, char **argv) { + InitializeCriticalSection(&mutex); + EnterCriticalSection(&mutex); #endif if(!detach()) From d273efb177738d429e3cef7d8db8ee5cc8dcada7 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 15 Sep 2009 23:04:52 +0200 Subject: [PATCH 31/32] Raise default RSA key length to 2048 bits. --- src/tincd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tincd.c b/src/tincd.c index b2e055c6..602f18b1 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -229,7 +229,7 @@ static bool parse_options(int argc, char **argv) generate_keys &= ~7; /* Round it to bytes */ } else - generate_keys = 1024; + generate_keys = 2048; break; case 'R': /* chroot to NETNAME dir */ From b5ccce296848aab72d574ca3de14af5fdf3efa4d Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 15 Sep 2009 23:22:13 +0200 Subject: [PATCH 32/32] Send large packets we cannot handle properly via TCP. During the path MTU discovery phase, we might not know the maximum MTU yet, but we do know a safe minimum. If we encounter a packet that is larger than that the minimum, we now send it via TCP instead to ensure it arrives. We also allow large packets that we cannot fragment or create ICMP replies for to be sent via TCP. --- src/net_packet.c | 4 ++-- src/route.c | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/net_packet.c b/src/net_packet.c index 2be599eb..aca84683 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -355,9 +355,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) return; } - if(n->options & OPTION_PMTU_DISCOVERY && !n->minmtu && (inpkt->data[12] | inpkt->data[13])) { + if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) { ifdebug(TRAFFIC) logger(LOG_INFO, - _("No minimum MTU established yet for %s (%s), forwarding via TCP"), + _("Packet for %s (%s) larger than minimum MTU, forwarding via TCP"), n->name, n->hostname); send_tcppacket(n->nexthop->connection, origpkt); diff --git a/src/route.c b/src/route.c index d748db16..9b689039 100644 --- a/src/route.c +++ b/src/route.c @@ -769,13 +769,12 @@ static void route_mac(node_t *source, vpn_packet_t *packet) } else { fragment_ipv4_packet(via, packet); } + return; } else if(type == ETH_P_IPV6) { packet->len = via->mtu; route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0); - } else - ifdebug(TRAFFIC) logger(LOG_INFO, _("Large packet of unhandled type %hx dropped"), type); - - return; + return; + } } send_packet(subnet->owner, packet);