Import Upstream version 1.0.24

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:45 +02:00
parent 413f90b815
commit 45b80e247e
45 changed files with 1342 additions and 341 deletions

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.14 from Makefile.am.
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@ -93,8 +93,10 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/openssl.m4 \
$(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 $(top_srcdir)/m4/lzo.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d

View file

@ -2,7 +2,7 @@
avl_tree.c -- avl_ tree and linked list convenience
Copyright (C) 1998 Michael H. Buselli
2000-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2000-2005 Wessel Dankers <wsl@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
@ -168,14 +168,12 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
child->right->parent = child;
gchild->right = node;
if(gchild->right)
gchild->right->parent = gchild;
gchild->right->parent = gchild;
gchild->left = child;
if(gchild->left)
gchild->left->parent = gchild;
*superparent = gchild;
gchild->left->parent = gchild;
*superparent = gchild;
gchild->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
@ -224,12 +222,10 @@ static void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
child->left->parent = child;
gchild->left = node;
if(gchild->left)
gchild->left->parent = gchild;
gchild->left->parent = gchild;
gchild->right = child;
if(gchild->right)
gchild->right->parent = gchild;
gchild->right->parent = gchild;
*superparent = gchild;
gchild->parent = parent;
@ -600,6 +596,8 @@ void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
balnode = parent;
} else {
subst = node->prev;
if(!subst) // This only happens if node is not actually in a tree at all.
abort();
if(subst == left) {
balnode = subst;

View file

@ -2,7 +2,7 @@
conf.c -- configuration code
Copyright (C) 1998 Robert van der Meulen
1998-2005 Ivo Timmermans
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2010-2011 Julien Muchembled <jm@jmuchemb.eu>
2000 Cris van Pelt
@ -378,6 +378,29 @@ bool read_server_config(void) {
xasprintf(&fname, "%s/tinc.conf", confbase);
x = read_config_file(config_tree, fname);
// We will try to read the conf files in the "conf.d" dir
if (x) {
char * dname;
xasprintf(&dname, "%s/conf.d", confbase);
DIR *dir = opendir (dname);
// If we can find this dir
if (dir) {
struct dirent *ep;
// We list all the files in it
while (x && (ep = readdir (dir))) {
size_t l = strlen(ep->d_name);
// And we try to read the ones that end with ".conf"
if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
free(fname);
xasprintf(&fname, "%s/%s", dname, ep->d_name);
x = read_config_file(config_tree, fname);
}
}
closedir (dir);
}
free(dname);
}
if(!x) { /* System error: complain */
logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
}

View file

@ -1,6 +1,6 @@
/*
graph.c -- graph algorithms
Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2001-2014 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -212,9 +212,13 @@ static void sssp_bfs(void) {
&& (!e->to->status.indirect || indirect))
continue;
// Only update nexthop the first time we visit this node.
if(!e->to->status.visited)
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
e->to->status.visited = true;
e->to->status.indirect = indirect;
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
e->to->prevedge = e;
e->to->via = indirect ? n->via : e->to;
e->to->options = e->options;
@ -336,6 +340,7 @@ void dump_graph(void) {
if(!file) {
logger(LOG_ERR, "Unable to open graph dump file %s: %s", filename, strerror(errno));
free(filename);
free(tmpname);
return;
}
@ -363,7 +368,10 @@ void dump_graph(void) {
#ifdef HAVE_MINGW
unlink(filename);
#endif
rename(tmpname, filename);
if(rename(tmpname, filename))
logger(LOG_ERR, "Could not rename %s to %s: %s\n", tmpname, filename, strerror(errno));
free(tmpname);
}
free(filename);
}

View file

@ -1,7 +1,7 @@
/*
have.h -- include headers which are known to exist
Copyright (C) 1998-2005 Ivo Timmermans
2003-2011 Guus Sliepen <guus@tinc-vpn.org>
2003-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -38,6 +38,7 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#ifdef HAVE_MINGW
#include <w32api.h>

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Linux ethertap and tun/tap device
Copyright (C) 2001-2005 Ivo Timmermans,
2001-2013 Guus Sliepen <guus@tinc-vpn.org>
2001-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -107,17 +107,21 @@ static bool setup_device(void) {
ifr.ifr_flags |= IFF_ONE_QUEUE;
#endif
if(iface)
if(iface) {
strncpy(ifr.ifr_name, iface, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = 0;
}
if(!ioctl(device_fd, TUNSETIFF, &ifr)) {
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
if(iface) free(iface);
ifrname[IFNAMSIZ - 1] = 0;
free(iface);
iface = xstrdup(ifrname);
} else if(!ioctl(device_fd, (('T' << 8) | 202), &ifr)) {
logger(LOG_WARNING, "Old ioctl() request was needed for %s", device);
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
if(iface) free(iface);
ifrname[IFNAMSIZ - 1] = 0;
free(iface);
iface = xstrdup(ifrname);
} else
#endif
@ -126,8 +130,7 @@ static bool setup_device(void) {
overwrite_mac = true;
device_info = "Linux ethertap device";
device_type = DEVICE_TYPE_ETHERTAP;
if(iface)
free(iface);
free(iface);
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
}

View file

@ -1,6 +1,6 @@
/*
meta.c -- handle the meta communication
Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2014 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
2006 Scott Lamb <slamb@slamb.org>
@ -180,7 +180,7 @@ bool receive_meta(connection_t *c) {
if(!c->node) {
if(c->outgoing && proxytype == PROXY_SOCKS4 && c->allow_request == ID) {
if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) {
logger(LOG_DEBUG, "Proxy request granted");
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted");
} else {
logger(LOG_ERR, "Proxy request rejected");
return false;
@ -199,9 +199,9 @@ bool receive_meta(connection_t *c) {
return false;
}
if(c->buffer[3] == 0) {
logger(LOG_DEBUG, "Proxy request granted");
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted");
} else {
logger(LOG_DEBUG, "Proxy request rejected");
logger(LOG_ERR, "Proxy request rejected");
return false;
}
} else {

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Windows tap driver in a MinGW environment
Copyright (C) 2002-2005 Ivo Timmermans,
2002-2013 Guus Sliepen <guus@tinc-vpn.org>
2002-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -49,6 +49,7 @@ static DWORD WINAPI tapreader(void *bla) {
DWORD len;
OVERLAPPED overlapped;
vpn_packet_t packet;
int errors = 0;
logger(LOG_DEBUG, "Tap reader running");
@ -71,16 +72,27 @@ static DWORD WINAPI tapreader(void *bla) {
} else {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return -1;
errors++;
if(errors >= 10) {
EnterCriticalSection(&mutex);
running = false;
LeaveCriticalSection(&mutex);
}
usleep(1000000);
continue;
}
}
EnterCriticalSection(&mutex);
errors = 0;
packet.len = len;
packet.priority = 0;
EnterCriticalSection(&mutex);
route(myself, &packet);
LeaveCriticalSection(&mutex);
}
return 0;
}
static bool setup_device(void) {

View file

@ -1,7 +1,7 @@
/*
device.c -- multicast socket
Copyright (C) 2002-2005 Ivo Timmermans,
2002-2013 Guus Sliepen <guus@tinc-vpn.org>
2002-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -56,6 +56,7 @@ static bool setup_device(void) {
space = strchr(host, ' ');
if(!space) {
logger(LOG_ERR, "Port number required for %s", device_info);
free(host);
return false;
}
@ -75,6 +76,7 @@ static bool setup_device(void) {
device_fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
if(device_fd < 0) {
logger(LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno));
free(host);
return false;
}
@ -88,6 +90,7 @@ static bool setup_device(void) {
if(bind(device_fd, ai->ai_addr, ai->ai_addrlen)) {
closesocket(device_fd);
logger(LOG_ERR, "Can't bind to %s %s: %s", host, port, sockstrerror(sockerrno));
free(host);
return false;
}
@ -102,6 +105,7 @@ static bool setup_device(void) {
if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof mreq)) {
logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
closesocket(device_fd);
free(host);
return false;
}
#ifdef IP_MULTICAST_LOOP
@ -123,6 +127,7 @@ static bool setup_device(void) {
if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof mreq)) {
logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
closesocket(device_fd);
free(host);
return false;
}
#ifdef IPV6_MULTICAST_LOOP
@ -135,11 +140,13 @@ static bool setup_device(void) {
#endif
default:
logger(LOG_ERR, "Multicast for address family %hx unsupported", ai->ai_family);
logger(LOG_ERR, "Multicast for address family %x unsupported", ai->ai_family);
closesocket(device_fd);
free(host);
return false;
}
free(host);
logger(LOG_INFO, "%s is a %s", device, device_info);
return true;

View file

@ -1,7 +1,7 @@
/*
net.c -- most of the network code
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2011 Loïc Grenié <loic.grenie@gmail.com>
@ -41,6 +41,14 @@
#include "subnet.h"
#include "xalloc.h"
#ifdef HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
#include <resolv.h>
#endif
bool do_purge = false;
volatile bool running = false;
#ifdef HAVE_PSELECT
@ -182,6 +190,12 @@ void terminate_connection(connection_t *c, bool report) {
closesocket(c->socket);
if(c->edge) {
if(!c->node) {
logger(LOG_ERR, "Connection to %s (%s) has an edge but node is NULL!", c->name, c->hostname);
// And that should never happen.
abort();
}
if(report && !tunnelserver)
send_del_edge(everyone, c->edge);
@ -494,6 +508,9 @@ int main_loop(void) {
avl_node_t *node;
logger(LOG_INFO, "Flushing event queue");
expire_events();
#if HAVE_DECL_RES_INIT
res_init();
#endif
for(node = connection_tree->head; node; node = node->next) {
connection_t *c = node->data;
if(c->status.active)

View file

@ -1,7 +1,7 @@
/*
net_packet.c -- Handles in- and outgoing VPN packets
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2010 Timothy Redaelli <timothy@redaelli.eu>
2010 Brandon Black <blblack@gmail.com>
@ -269,7 +269,7 @@ static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) {
HMAC(n->indigest, n->inkey, n->inkeylength, (unsigned char *) &inpkt->seqno, inpkt->len - n->inmaclength, (unsigned char *)hmac, NULL);
return !memcmp(hmac, (char *) &inpkt->seqno + inpkt->len - n->inmaclength, n->inmaclength);
return !memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len - n->inmaclength, n->inmaclength);
}
static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
@ -302,7 +302,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
HMAC(n->indigest, n->inkey, n->inkeylength,
(unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL);
if(memcmp(hmac, (char *) &inpkt->seqno + inpkt->len, n->inmaclength)) {
if(memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len, n->inmaclength)) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got unauthenticated packet from %s (%s)",
n->name, n->hostname);
return;
@ -664,7 +664,6 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
avl_node_t *node;
edge_t *e;
node_t *n = NULL;
bool hard = false;
static time_t last_hard_try = 0;
for(node = edge_weight_tree->head; node; node = node->next) {
@ -673,11 +672,8 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
if(e->to == myself)
continue;
if(sockaddrcmp_noport(from, &e->address)) {
if(last_hard_try == now)
continue;
hard = true;
}
if(last_hard_try == now && sockaddrcmp_noport(from, &e->address))
continue;
if(!try_mac(e->to, pkt))
continue;
@ -686,9 +682,6 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
break;
}
if(hard)
last_hard_try = now;
last_hard_try = now;
return n;
}

View file

@ -1,7 +1,7 @@
/*
net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2010 Brandon Black <blblack@gmail.com>
@ -165,23 +165,25 @@ static bool read_rsa_private_key(void) {
char *fname, *key, *pubkey;
if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) {
logger(LOG_ERR, "PrivateKey used but no PublicKey found!");
return false;
}
myself->connection->rsa_key = RSA_new();
// RSA_blinding_on(myself->connection->rsa_key, NULL);
if(BN_hex2bn(&myself->connection->rsa_key->d, key) != strlen(key)) {
logger(LOG_ERR, "Invalid PrivateKey for myself!");
free(key);
return false;
}
free(key);
if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) {
logger(LOG_ERR, "PrivateKey used but no PublicKey found!");
return false;
}
if(BN_hex2bn(&myself->connection->rsa_key->n, pubkey) != strlen(pubkey)) {
logger(LOG_ERR, "Invalid PublicKey for myself!");
free(pubkey);
return false;
}
BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
free(key);
free(pubkey);
BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
return true;
}
@ -200,15 +202,12 @@ static bool read_rsa_private_key(void) {
#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
struct stat s;
if(fstat(fileno(fp), &s)) {
logger(LOG_ERR, "Could not stat RSA private key file `%s': %s'",
fname, strerror(errno));
free(fname);
return false;
if(!fstat(fileno(fp), &s)) {
if(s.st_mode & ~0100700)
logger(LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
} else {
logger(LOG_WARNING, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno));
}
if(s.st_mode & ~0100700)
logger(LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
#endif
myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
@ -299,10 +298,12 @@ char *get_name(void) {
if(!envname) {
if(strcmp(name + 1, "HOST")) {
fprintf(stderr, "Invalid Name: environment variable %s does not exist\n", name + 1);
free(name);
return false;
}
if(gethostname(hostname, sizeof hostname) || !*hostname) {
fprintf(stderr, "Could not get hostname: %s\n", strerror(errno));
free(name);
return false;
}
hostname[31] = 0;
@ -340,6 +341,7 @@ static bool setup_myself(void) {
bool choice;
int i, err;
int replaywin_int;
bool port_specified = false;
myself = new_node();
myself->connection = new_connection();
@ -355,6 +357,8 @@ static bool setup_myself(void) {
return false;
}
/* Read tinc.conf and our own host config file */
myself->name = name;
myself->connection->name = xstrdup(name);
xasprintf(&fname, "%s/hosts/%s", confbase, name);
@ -367,6 +371,10 @@ static bool setup_myself(void) {
if(!get_config_string(lookup_config(config_tree, "Port"), &myport))
myport = xstrdup("655");
else
port_specified = true;
/* Ensure myport is numeric */
if(!atoi(myport)) {
struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
@ -378,8 +386,7 @@ static bool setup_myself(void) {
sockaddr2str(&sa, NULL, &myport);
}
get_config_string(lookup_config(config_tree, "Proxy"), &proxy);
if(proxy) {
if(get_config_string(lookup_config(config_tree, "Proxy"), &proxy)) {
if((space = strchr(proxy, ' ')))
*space++ = 0;
@ -397,6 +404,7 @@ static bool setup_myself(void) {
proxytype = PROXY_EXEC;
} else {
logger(LOG_ERR, "Unknown proxy type %s!", proxy);
free(proxy);
return false;
}
@ -408,6 +416,7 @@ static bool setup_myself(void) {
case PROXY_EXEC:
if(!space || !*space) {
logger(LOG_ERR, "Argument expected for proxy type exec!");
free(proxy);
return false;
}
proxyhost = xstrdup(space);
@ -426,6 +435,7 @@ static bool setup_myself(void) {
*space++ = 0, proxypass = space;
if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
logger(LOG_ERR, "Host and port argument expected for proxy!");
free(proxy);
return false;
}
proxyhost = xstrdup(proxyhost);
@ -479,6 +489,7 @@ static bool setup_myself(void) {
routing_mode = RMODE_HUB;
else {
logger(LOG_ERR, "Invalid routing mode!");
free(mode);
return false;
}
free(mode);
@ -493,6 +504,7 @@ static bool setup_myself(void) {
forwarding_mode = FMODE_KERNEL;
else {
logger(LOG_ERR, "Invalid forwarding mode!");
free(mode);
return false;
}
free(mode);
@ -519,6 +531,7 @@ static bool setup_myself(void) {
broadcast_mode = BMODE_DIRECT;
else {
logger(LOG_ERR, "Invalid broadcast mode!");
free(mode);
return false;
}
free(mode);
@ -571,6 +584,7 @@ static bool setup_myself(void) {
addressfamily = AF_UNSPEC;
else {
logger(LOG_ERR, "Invalid address family!");
free(afname);
return false;
}
free(afname);
@ -580,8 +594,7 @@ static bool setup_myself(void) {
/* Generate packet encryption key */
if(get_config_string
(lookup_config(config_tree, "Cipher"), &cipher)) {
if(get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) {
if(!strcasecmp(cipher, "none")) {
myself->incipher = NULL;
} else {
@ -589,9 +602,11 @@ static bool setup_myself(void) {
if(!myself->incipher) {
logger(LOG_ERR, "Unrecognized cipher type!");
free(cipher);
return false;
}
}
free(cipher);
} else
myself->incipher = EVP_bf_cbc();
@ -617,9 +632,12 @@ static bool setup_myself(void) {
if(!myself->indigest) {
logger(LOG_ERR, "Unrecognized digest type!");
free(digest);
return false;
}
}
free(digest);
} else
myself->indigest = EVP_sha1();
@ -683,6 +701,7 @@ static bool setup_myself(void) {
else if(!strcasecmp(type, "vde"))
devops = vde_devops;
#endif
free(type);
}
if(!devops.setup())
@ -812,13 +831,27 @@ static bool setup_myself(void) {
} while(cfg);
}
if(listen_sockets)
logger(LOG_NOTICE, "Ready");
else {
if(!listen_sockets) {
logger(LOG_ERR, "Unable to create any listening socket!");
return false;
}
/* If no Port option was specified, set myport to the port used by the first listening socket. */
if(!port_specified) {
sockaddr_t sa;
socklen_t salen = sizeof sa;
if(!getsockname(listen_socket[0].udp, &sa.sa, &salen)) {
free(myport);
sockaddr2str(&sa, NULL, &myport);
if(!myport)
myport = xstrdup("655");
}
}
/* Done. */
logger(LOG_NOTICE, "Ready");
return true;
}

View file

@ -1,7 +1,7 @@
/*
net_socket.c -- Handle various kinds of sockets.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2009 Florian Forster <octo@verplant.org>
@ -87,20 +87,21 @@ static bool bind_to_interface(int sd) {
int status;
#endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */
if(!get_config_string (lookup_config (config_tree, "BindToInterface"), &iface))
if(!get_config_string(lookup_config (config_tree, "BindToInterface"), &iface))
return true;
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
free(iface);
status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
if(status) {
logger(LOG_ERR, "Can't bind to interface %s: %s", iface,
strerror(errno));
logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno));
return false;
}
#else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface");
#endif
@ -135,20 +136,21 @@ int setup_listen_socket(const sockaddr_t *sa) {
setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
#endif
if(get_config_string
(lookup_config(config_tree, "BindToInterface"), &iface)) {
if(get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) {
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
free(iface);
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) {
closesocket(nfd);
logger(LOG_ERR, "Can't bind to interface %s: %s", iface,
strerror(sockerrno));
logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(sockerrno));
return -1;
}
#else
logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface");
#endif
@ -238,8 +240,6 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = 1;
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
}
#else
#warning No way to disable IPv4 fragmentation
#endif
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
@ -252,8 +252,6 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = 1;
setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
}
#else
#warning No way to disable IPv6 fragmentation
#endif
if (!bind_to_interface(nfd)) {
@ -311,7 +309,7 @@ static void do_outgoing_pipe(connection_t *c, char *command) {
if(fork()) {
c->socket = fd[0];
close(fd[1]);
logger(LOG_DEBUG, "Using proxy %s", command);
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Using proxy %s", command);
return;
}
@ -407,7 +405,6 @@ begin:
if(!proxytype) {
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
configure_tcp(c);
} else if(proxytype == PROXY_EXEC) {
do_outgoing_pipe(c, proxyhost);
} else {
@ -416,7 +413,6 @@ begin:
goto begin;
ifdebug(CONNECTIONS) logger(LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport);
c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP);
configure_tcp(c);
}
if(c->socket == -1) {
@ -424,6 +420,9 @@ begin:
goto begin;
}
if(proxytype != PROXY_EXEC)
configure_tcp(c);
#ifdef FD_CLOEXEC
fcntl(c->socket, F_SETFD, FD_CLOEXEC);
#endif

View file

@ -46,7 +46,7 @@ pid_t read_pid (const char *pidfile)
if(fscanf(f,"%20ld", &pid) != 1)
pid = 0;
fclose(f);
return pid;
return (pid_t)pid;
}
/* check_pid

View file

@ -1,7 +1,7 @@
/*
protocol_auth.c -- handle the meta-protocol, authentication
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -107,7 +107,7 @@ static bool send_proxyrequest(connection_t *c) {
i += 2;
c->tcplen += 22;
} else {
logger(LOG_ERR, "Address family %hx not supported for SOCKS 5 proxies!", c->address.sa.sa_family);
logger(LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family);
return false;
}
if(i > len)
@ -215,7 +215,12 @@ bool send_metakey(connection_t *c) {
/* Copy random data to the buffer */
RAND_pseudo_bytes((unsigned char *)c->outkey, len);
if (1 != RAND_bytes((unsigned char *)c->outkey, len)) {
int err = ERR_get_error();
logger(LOG_ERR, "Failed to generate meta key (%s)", ERR_error_string(err, NULL));
return false;
}
/* The message we send must be smaller than the modulus of the RSA key.
By definition, for a key of k bits, the following formula holds:
@ -391,7 +396,11 @@ bool send_challenge(connection_t *c) {
/* Copy random data to the buffer */
RAND_pseudo_bytes((unsigned char *)c->hischallenge, len);
if (1 != RAND_bytes((unsigned char *)c->hischallenge, len)) {
int err = ERR_get_error();
logger(LOG_ERR, "Failed to generate challenge (%s)", ERR_error_string(err, NULL));
return false; // Do not send predictable challenges, let connection attempt fail.
}
/* Convert to hex */

View file

@ -1,7 +1,7 @@
/*
protocol_key.c -- handle the meta-protocol, key exchange
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -127,7 +127,8 @@ bool req_key_h(connection_t *c) {
/* Check if this key request is for us */
if(to == myself) { /* Yes, send our own key back */
send_ans_key(from);
if (!send_ans_key(from))
return false;
} else {
if(tunnelserver)
return true;
@ -156,7 +157,12 @@ bool send_ans_key(node_t *to) {
to->inkey = xrealloc(to->inkey, to->inkeylength);
// Create a new key
RAND_pseudo_bytes((unsigned char *)to->inkey, to->inkeylength);
if (1 != RAND_bytes((unsigned char *)to->inkey, to->inkeylength)) {
int err = ERR_get_error();
logger(LOG_ERR, "Failed to generate random for key (%s)", ERR_error_string(err, NULL));
return false; // Do not send insecure keys, let connection attempt fail.
}
if(to->incipher)
EVP_DecryptInit_ex(&to->inctx, to->incipher, NULL, (unsigned char *)to->inkey, (unsigned char *)to->inkey + to->incipher->key_len);

View file

@ -1,7 +1,7 @@
/*
device.c -- raw socket
Copyright (C) 2002-2005 Ivo Timmermans,
2002-2012 Guus Sliepen <guus@tinc-vpn.org>
2002-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -32,7 +32,7 @@
#include "route.h"
#include "xalloc.h"
#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET)
#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET) && defined(SIOCGIFINDEX)
static char *device_info;
static uint64_t device_total_in = 0;
@ -62,20 +62,21 @@ static bool setup_device(void) {
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0;
if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) {
close(device_fd);
logger(LOG_ERR, "Can't find interface %s: %s", iface,
strerror(errno));
logger(LOG_ERR, "Can't find interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno));
return false;
}
memset(&sa, '0', sizeof(sa));
memset(&sa, 0, sizeof(sa));
sa.sll_family = AF_PACKET;
sa.sll_protocol = htons(ETH_P_ALL);
sa.sll_ifindex = ifr.ifr_ifindex;
if(bind(device_fd, (struct sockaddr *) &sa, (socklen_t) sizeof(sa))) {
logger(LOG_ERR, "Could not bind %s to %s: %s", device, iface, strerror(errno));
logger(LOG_ERR, "Could not bind %s to %s: %s", device, ifr.ifr_ifrn.ifrn_name, strerror(errno));
return false;
}

View file

@ -1,7 +1,7 @@
/*
route.c -- routing
Copyright (C) 2000-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -197,7 +197,7 @@ static void learn_mac(mac_t *address) {
/* If we don't know this MAC address yet, store it */
if(!subnet) {
ifdebug(TRAFFIC) logger(LOG_INFO, "Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx",
ifdebug(TRAFFIC) logger(LOG_INFO, "Learned new MAC address %x:%x:%x:%x:%x:%x",
address->x[0], address->x[1], address->x[2], address->x[3],
address->x[4], address->x[5]);

View file

@ -1,7 +1,8 @@
/*
device.c -- Interaction with Solaris tun device
Copyright (C) 2001-2005 Ivo Timmermans,
2001-2012 Guus Sliepen <guus@tinc-vpn.org>
2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
2001-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -18,98 +19,258 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "../system.h"
#include <sys/stropts.h>
#include <sys/sockio.h>
#include <net/if_tun.h>
#include "../conf.h"
#include "../device.h"
#include "../logger.h"
#include "../net.h"
#include "../route.h"
#include "../utils.h"
#include "../xalloc.h"
#define DEFAULT_DEVICE "/dev/tun"
#ifndef TUNNEWPPA
#warning Missing net/if_tun.h, using hardcoded value for TUNNEWPPA
#define TUNNEWPPA (('T'<<16) | 0x0001)
#endif
#define DEFAULT_TUN_DEVICE "/dev/tun"
#define DEFAULT_TAP_DEVICE "/dev/tap"
static enum {
DEVICE_TYPE_TUN,
DEVICE_TYPE_TAP,
} device_type = DEVICE_TYPE_TUN;
int device_fd = -1;
static int ip_fd = -1, if_fd = -1;
static int if_fd = -1;
static int ip_fd = -1;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
static uint64_t device_total_in = 0;
static uint64_t device_total_out = 0;
uint64_t device_total_in = 0;
uint64_t device_total_out = 0;
static bool setup_device(void) {
int ppa;
char *ptr;
char *type;
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = xstrdup(DEFAULT_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, "Device"), &device)) {
if(routing_mode == RMODE_ROUTER)
device = xstrdup(DEFAULT_TUN_DEVICE);
else
device = xstrdup(DEFAULT_TAP_DEVICE);
}
#ifdef FD_CLOEXEC
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
#endif
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
if(!strcasecmp(type, "tun"))
/* use default */;
else if(!strcasecmp(type, "tap"))
device_type = DEVICE_TYPE_TAP;
else {
logger(LOG_ERR, "Unknown device type %s!", type);
return false;
}
} else {
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER)
device_type = DEVICE_TYPE_TAP;
}
ppa = 0;
if(device_type == DEVICE_TYPE_TUN)
device_info = "Solaris tun device";
else
device_info = "Solaris tap device";
ptr = device;
while(*ptr && !isdigit((int) *ptr))
ptr++;
ppa = atoi(ptr);
/* The following is black magic copied from OpenVPN. */
if((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) {
logger(LOG_ERR, "Could not open /dev/ip: %s", strerror(errno));
logger(LOG_ERR, "Could not open %s: %s\n", "/dev/ip", strerror(errno));
return false;
}
#ifdef FD_CLOEXEC
fcntl(ip_fd, F_SETFD, FD_CLOEXEC);
#endif
if((device_fd = open(device, O_RDWR, 0)) < 0) {
logger(LOG_ERR, "Could not open %s: %s\n", device, strerror(errno));
return false;
}
/* Get unit number. */
char *ptr = device;
get_config_string(lookup_config(config_tree, "Interface"), &ptr);
while(*ptr && !isdigit(*ptr))
ptr++;
int ppa = atoi(ptr);
/* Assign a new PPA and get its unit number. */
if((ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0) {
logger(LOG_ERR, "Can't assign new interface: %s", strerror(errno));
return false;
struct strioctl strioc_ppa = {
.ic_cmd = TUNNEWPPA,
.ic_len = sizeof ppa,
.ic_dp = (char *)&ppa,
};
if(!*ptr) { /* no number given, try dynamic */
bool found = false;
while(!found && ppa < 64) {
int new_ppa = ioctl(device_fd, I_STR, &strioc_ppa);
if(new_ppa >= 0) {
ppa = new_ppa;
found = true;
break;
}
ppa++;
}
if(!found) {
logger(LOG_ERR, "Could not find free PPA for %s %s!", device_info, device);
return false;
}
} else { /* try this particular one */
if((ppa = ioctl(device_fd, I_STR, &strioc_ppa)) < 0) {
logger(LOG_ERR, "Could not assign PPA %d for %s %s!", ppa, device_info, device);
return false;
}
}
if((if_fd = open(device, O_RDWR, 0)) < 0) {
logger(LOG_ERR, "Could not open %s twice: %s", device,
strerror(errno));
logger(LOG_ERR, "Could not open %s: %s\n", device, strerror(errno));
return false;
}
#ifdef FD_CLOEXEC
fcntl(if_fd, F_SETFD, FD_CLOEXEC);
#endif
if(ioctl(if_fd, I_PUSH, "ip") < 0) {
logger(LOG_ERR, "Can't push IP module: %s", strerror(errno));
logger(LOG_ERR, "Could not push IP module onto %s %s!", device_info, device);
return false;
}
/* Assign ppa according to the unit number returned by tun device */
if(ioctl(if_fd, IF_UNITSEL, (char *) &ppa) < 0) {
logger(LOG_ERR, "Can't set PPA %d: %s", ppa, strerror(errno));
xasprintf(&iface, "%s%d", device_type == DEVICE_TYPE_TUN ? "tun" : "tap", ppa);
{
/* Remove muxes just in case they are left over from a crashed tincd */
struct lifreq ifr = {};
strncpy(ifr.lifr_name, iface, sizeof ifr.lifr_name);
if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) {
int muxid = ifr.lifr_arp_muxid;
ioctl(ip_fd, I_PUNLINK, muxid);
muxid = ifr.lifr_ip_muxid;
ioctl(ip_fd, I_PUNLINK, muxid);
}
}
if(device_type == DEVICE_TYPE_TUN) {
/* Assign ppa according to the unit number returned by tun device */
if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) {
logger(LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device);
return false;
}
}
int arp_fd = -1;
if(device_type == DEVICE_TYPE_TAP) {
struct lifreq ifr = {};
if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) {
logger(LOG_ERR, "Could not set flags on %s %s!", device_info, device);
return false;
}
strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name));
ifr.lifr_ppa = ppa;
/* Assign ppa according to the unit number returned by tun device */
if(ioctl(if_fd, SIOCSLIFNAME, &ifr) < 0) {
logger(LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device);
return false;
}
if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) {
logger(LOG_ERR, "Could not set flags on %s %s!", device_info, device);
return false;
}
/* Push arp module to if_fd */
if(ioctl(if_fd, I_PUSH, "arp") < 0) {
logger(LOG_ERR, "Could not push ARP module onto %s %s!", device_info, device);
return false;
}
/* Pop any modules on the stream */
while(true) {
if(ioctl(ip_fd, I_POP, NULL) < 0)
break;
}
/* Push arp module to ip_fd */
if(ioctl(ip_fd, I_PUSH, "arp") < 0) {
logger(LOG_ERR, "Could not push ARP module onto %s!", "/dev/ip");
return false;
}
/* Open arp_fd */
if((arp_fd = open(device, O_RDWR, 0)) < 0) {
logger(LOG_ERR, "Could not open %s: %s\n", device, strerror(errno));
return false;
}
/* Push arp module to arp_fd */
if(ioctl(arp_fd, I_PUSH, "arp") < 0) {
logger(LOG_ERR, "Could not push ARP module onto %s %s!", device_info, device);
return false;
}
/* Set ifname to arp */
struct strioctl strioc_if = {
.ic_cmd = SIOCSLIFNAME,
.ic_len = sizeof ifr,
.ic_dp = (char *)&ifr,
};
if(ioctl(arp_fd, I_STR, &strioc_if) < 0) {
logger(LOG_ERR, "Could not set ifname to %s %s", device_info, device);
return false;
}
}
int ip_muxid, arp_muxid;
if((ip_muxid = ioctl(ip_fd, I_PLINK, if_fd)) < 0) {
logger(LOG_ERR, "Could not link %s %s to IP", device_info, device);
return false;
}
if(ioctl(ip_fd, I_LINK, if_fd) < 0) {
logger(LOG_ERR, "Can't link TUN device to IP: %s", strerror(errno));
if(device_type == DEVICE_TYPE_TAP) {
if((arp_muxid = ioctl(ip_fd, I_PLINK, arp_fd)) < 0) {
logger(LOG_ERR, "Could not link %s %s to ARP", device_info, device);
return false;
}
close(arp_fd);
}
struct lifreq ifr = {};
strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name));
ifr.lifr_ip_muxid = ip_muxid;
if(device_type == DEVICE_TYPE_TAP) {
ifr.lifr_arp_muxid = arp_muxid;
}
if(ioctl(ip_fd, SIOCSLIFMUXID, &ifr) < 0) {
if(device_type == DEVICE_TYPE_TAP) {
ioctl(ip_fd, I_PUNLINK, arp_muxid);
}
ioctl(ip_fd, I_PUNLINK, ip_muxid);
logger(LOG_ERR, "Could not set multiplexor id for %s %s", device_info, device);
return false;
}
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
xasprintf(&iface, "tun%d", ppa);
close(if_fd);
device_info = "Solaris tun device";
#ifdef FD_CLOEXEC
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
fcntl(ip_fd, F_SETFD, FD_CLOEXEC);
#endif
logger(LOG_INFO, "%s is a %s", device, device_info);
@ -117,7 +278,17 @@ static bool setup_device(void) {
}
static void close_device(void) {
close(if_fd);
if(iface) {
struct lifreq ifr = {};
strncpy(ifr.lifr_name, iface, sizeof ifr.lifr_name);
if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) {
int muxid = ifr.lifr_arp_muxid;
ioctl(ip_fd, I_PUNLINK, muxid);
muxid = ifr.lifr_ip_muxid;
ioctl(ip_fd, I_PUNLINK, muxid);
}
}
close(ip_fd);
close(device_fd);
@ -126,49 +297,73 @@ static void close_device(void) {
}
static bool read_packet(vpn_packet_t *packet) {
int lenin;
int inlen;
if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch(device_type) {
case DEVICE_TYPE_TUN:
if((inlen = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
return false;
}
switch(packet->data[14] >> 4) {
case 4:
packet->data[12] = 0x08;
packet->data[13] = 0x00;
switch(packet->data[14] >> 4) {
case 4:
packet->data[12] = 0x08;
packet->data[13] = 0x00;
break;
case 6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR, "Unknown IP version %d while reading packet from %s %s", packet->data[14] >> 4, device_info, device);
return false;
}
memset(packet->data, 0, 12);
packet->len = inlen + 14;
break;
case 6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
case DEVICE_TYPE_TAP:
if((inlen = read(device_fd, packet->data, MTU)) <= 0) {
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
return false;
}
packet->len = inlen + 14;
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device);
return false;
abort();
}
memset(packet->data, 0, 12);
packet->len = lenin + 14;
device_total_in += packet->len;
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
device_info);
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, device_info);
return true;
}
static bool write_packet(vpn_packet_t *packet) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
packet->len, device_info);
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", packet->len, device_info);
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info,
device, strerror(errno));
return false;
switch(device_type) {
case DEVICE_TYPE_TUN:
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
return false;
}
break;
case DEVICE_TYPE_TAP:
if(write(device_fd, packet->data, packet->len) < 0) {
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
return false;
}
break;
default:
abort();
}
device_total_out += packet->len;

View file

@ -1,6 +1,6 @@
/*
subnet.c -- handle subnet lookups and lists
Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2014 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -351,7 +351,7 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) {
switch (subnet->type) {
case SUBNET_MAC:
snprintf(netstr, len, "%hx:%hx:%hx:%hx:%hx:%hx#%d",
snprintf(netstr, len, "%x:%x:%x:%x:%x:%x#%d",
subnet->net.mac.address.x[0],
subnet->net.mac.address.x[1],
subnet->net.mac.address.x[2],
@ -362,7 +362,7 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) {
break;
case SUBNET_IPV4:
snprintf(netstr, len, "%hu.%hu.%hu.%hu/%d#%d",
snprintf(netstr, len, "%u.%u.%u.%u/%d#%d",
subnet->net.ipv4.address.x[0],
subnet->net.ipv4.address.x[1],
subnet->net.ipv4.address.x[2],
@ -372,7 +372,7 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) {
break;
case SUBNET_IPV6:
snprintf(netstr, len, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d#%d",
snprintf(netstr, len, "%x:%x:%x:%x:%x:%x:%x:%x/%d#%d",
ntohs(subnet->net.ipv6.address.x[0]),
ntohs(subnet->net.ipv6.address.x[1]),
ntohs(subnet->net.ipv6.address.x[2]),

View file

@ -1,7 +1,7 @@
/*
tincd.c -- the main file for tincd
Copyright (C) 1998-2005 Ivo Timmermans
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2008 Max Rijevski <maksuf@gmail.com>
2009 Michael Tokarev <mjt@tls.msk.ru>
2010 Julien Muchembled <jm@jmuchemb.eu>
@ -162,6 +162,11 @@ static bool parse_options(int argc, char **argv) {
break;
case 'c': /* config file */
if(confbase) {
fprintf(stderr, "Only one configuration directory can be given.\n");
usage(true);
return false;
}
confbase = xstrdup(optarg);
break;
@ -229,6 +234,11 @@ static bool parse_options(int argc, char **argv) {
case 'n': /* net name given */
/* netname "." is special: a "top-level name" */
if(netname) {
fprintf(stderr, "Only one netname can be given.\n");
usage(true);
return false;
}
netname = strcmp(optarg, ".") != 0 ? xstrdup(optarg) : NULL;
break;
@ -281,11 +291,22 @@ static bool parse_options(int argc, char **argv) {
use_logfile = true;
if(!optarg && optind < argc && *argv[optind] != '-')
optarg = argv[optind++];
if(optarg)
if(optarg) {
if(logfilename) {
fprintf(stderr, "Only one logfile can be given.\n");
usage(true);
return false;
}
logfilename = xstrdup(optarg);
}
break;
case 5: /* write PID to a file */
if(pidfilename) {
fprintf(stderr, "Only one pidfile can be given.\n");
usage(true);
return false;
}
pidfilename = xstrdup(optarg);
break;
@ -350,7 +371,6 @@ static void indicator(int a, int b, void *p) {
static bool keygen(int bits) {
RSA *rsa_key;
FILE *f;
char *name = get_name();
char *pubname, *privname;
fprintf(stderr, "Generating %d bits keys:\n", bits);
@ -378,10 +398,14 @@ static bool keygen(int bits) {
PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
fclose(f);
if(name)
char *name = get_name();
if(name) {
xasprintf(&pubname, "%s/hosts/%s", confbase, name);
else
free(name);
} else {
xasprintf(&pubname, "%s/rsa_key.pub", confbase);
}
f = ask_and_open(pubname, "public RSA key");
free(pubname);
@ -392,7 +416,6 @@ static bool keygen(int bits) {
fputc('\n', f);
PEM_write_RSAPublicKey(f, rsa_key);
fclose(f);
free(name);
return true;
}
@ -526,7 +549,7 @@ int main(int argc, char **argv) {
if(show_version) {
printf("%s version %s (built %s %s, protocol %d)\n", PACKAGE,
VERSION, __DATE__, __TIME__, PROT_CURRENT);
printf("Copyright (C) 1998-2013 Ivo Timmermans, Guus Sliepen and others.\n"
printf("Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen and others.\n"
"See the AUTHORS file for a complete list.\n\n"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
"and you are welcome to redistribute it under certain conditions;\n"

View file

@ -1,7 +1,7 @@
/*
utils.c -- gathering of some stupid small functions
Copyright (C) 1999-2005 Ivo Timmermans
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -78,3 +78,18 @@ unsigned int bitfield_to_int(const void *bitfield, size_t size) {
memcpy(&value, bitfield, size);
return value;
}
/**
* As memcmp(), but constant-time.
* Returns 0 when data is equal, non-zero otherwise.
*/
int memcmp_constant_time (const void *a, const void *b, size_t size) {
const uint8_t *a1 = a, *b1 = b;
int ret = 0;
size_t i;
for (i = 0; i < size; i++)
ret |= *a1++ ^ *b1++;
return ret;
}

View file

@ -1,7 +1,7 @@
/*
utils.h -- header file for utils.c
Copyright (C) 1999-2005 Ivo Timmermans
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
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
@ -42,4 +42,6 @@ extern const char *winerror(int);
extern unsigned int bitfield_to_int(const void *bitfield, size_t size);
int memcmp_constant_time (const void *a, const void *b, size_t size);
#endif /* __TINC_UTILS_H__ */

View file

@ -113,6 +113,9 @@ char *xstrdup(const char *s)
{
char *p;
if(!s)
return NULL;
p = strdup(s);
if(!p)
xalloc_fail ((int)strlen(s));