Import Upstream version 1.0.24
This commit is contained in:
parent
413f90b815
commit
45b80e247e
45 changed files with 1342 additions and 341 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
25
src/conf.c
25
src/conf.c
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
14
src/graph.c
14
src/graph.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
19
src/net.c
19
src/net.c
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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]),
|
||||
|
|
|
|||
37
src/tincd.c
37
src/tincd.c
|
|
@ -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"
|
||||
|
|
|
|||
17
src/utils.c
17
src/utils.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue