Merge branch 'master' into 1.1

Conflicts:
	NEWS
	README
	configure.in
	doc/tinc.texi
	doc/tincd.8.in
	src/Makefile.am
	src/connection.c
	src/edge.c
	src/meta.c
	src/net.c
	src/net.h
	src/net_packet.c
	src/net_setup.c
	src/net_socket.c
	src/node.c
	src/openssl/rsagen.h
	src/protocol_auth.c
	src/protocol_edge.c
	src/subnet.c
This commit is contained in:
Guus Sliepen 2009-11-02 14:24:27 +01:00
commit 108b238915
26 changed files with 288 additions and 124 deletions

View file

@ -35,9 +35,7 @@ tincd_LDADD = \
tincctl_LDADD = \
$(top_builddir)/lib/libvpn.a
localedir = $(datadir)/locale
AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
dist-hook:
rm -f `find . -type l`

View file

@ -150,6 +150,17 @@ bool setup_device(void) {
if(routing_mode == RMODE_ROUTER)
overwrite_mac = true;
device_info = "Generic BSD tap device";
#ifdef TAPGIFNAME
{
struct ifreq ifr;
if(ioctl(device_fd, TAPGIFNAME, (void*)&ifr) == 0) {
if(iface)
free(iface);
iface = xstrdup(ifr.ifr_name);
}
}
#endif
break;
#ifdef HAVE_TUNEMU
case DEVICE_TYPE_TUNEMU:
@ -209,7 +220,7 @@ bool read_packet(vpn_packet_t *packet) {
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
_ ("Unknown IP version %d while reading packet from %s %s"),
"Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device);
return false;
}
@ -240,7 +251,7 @@ bool read_packet(vpn_packet_t *packet) {
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
_ ("Unknown address family %x while reading packet from %s %s"),
"Unknown address family %x while reading packet from %s %s",
ntohl(type), device_info, device);
return false;
}
@ -268,7 +279,6 @@ bool read_packet(vpn_packet_t *packet) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s",
packet->len, device_info);
logger(LOG_INFO, "E:fd_read");
return true;
}

View file

@ -56,7 +56,7 @@ typedef struct connection_t {
int protocol_version; /* used protocol */
int socket; /* socket used for this connection */
long int options; /* options for this connection */
uint32_t options; /* options for this connection */
connection_status_t status; /* status info */
int estimated_weight; /* estimation for the weight of the edge for this connection */
struct timeval start; /* time this connection was started, used for above estimation */

54
src/dummy/device.c Normal file
View file

@ -0,0 +1,54 @@
/*
device.c -- Dummy device
Copyright (C) 2009 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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "system.h"
#include "logger.h"
#include "net.h"
int device_fd = -1;
char *device = "dummy";
char *iface = "dummy";
static char *device_info = "dummy device";
static int device_total_in = 0;
static int device_total_out = 0;
bool setup_device(void) {
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
return true;
}
void close_device(void) {
}
bool read_packet(vpn_packet_t *packet) {
return false;
}
bool write_packet(vpn_packet_t *packet) {
device_total_out += packet->len;
return true;
}
void dump_device_stats(void) {
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
logger(LOG_DEBUG, " total bytes in: %10d", device_total_in);
logger(LOG_DEBUG, " total bytes out: %10d", device_total_out);
}

View file

@ -31,7 +31,7 @@ typedef struct edge_t {
struct node_t *to;
sockaddr_t address;
long int options; /* options turned on for this edge */
uint32_t options; /* options turned on for this edge */
int weight; /* weight of this edge */
struct connection_t *connection; /* connection associated with this edge, if available */

View file

@ -92,7 +92,14 @@ bool receive_meta(connection_t *c) {
inlen = recv(c->socket, inbuf, sizeof inbuf, 0);
if(inlen <= 0) {
logger(LOG_ERR, "Receive callback called for %s (%s) but no data to receive: %s", c->name, c->hostname, strerror(errno));
if(!inlen || !errno) {
ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)",
c->name, c->hostname);
} else if(sockwouldblock(sockerrno))
return true;
else
logger(LOG_ERR, "Metadata socket read error for %s (%s): %s",
c->name, c->hostname, sockstrerror(sockerrno));
return false;
}
@ -152,7 +159,5 @@ bool receive_meta(connection_t *c) {
}
} while(inlen);
c->last_ping_time = time(NULL);
return true;
}

View file

@ -208,7 +208,7 @@ void handle_meta_connection_data(int fd, short events, void *data) {
else {
ifdebug(CONNECTIONS) logger(LOG_DEBUG,
"Error while connecting to %s (%s): %s",
c->name, c->hostname, strerror(result));
c->name, c->hostname, sockstrerror(result));
closesocket(c->socket);
do_outgoing_connection(c);
return;

View file

@ -42,10 +42,6 @@
#include "utils.h"
#include "xalloc.h"
#ifdef WSAEMSGSIZE
#define EMSGSIZE WSAEMSGSIZE
#endif
int keylifetime = 0;
int keyexpires = 0;
static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS];
@ -54,31 +50,61 @@ static void send_udppacket(node_t *, vpn_packet_t *);
#define MAX_SEQNO 1073741824
// mtuprobes == 1..30: initial discovery, send bursts with 1 second interval
// mtuprobes == 31: sleep pinginterval seconds
// mtuprobes == 32: send 1 burst, sleep pingtimeout second
// mtuprobes == 33: no response from other side, restart PMTU discovery process
static void send_mtu_probe_handler(int fd, short events, void *data) {
node_t *n = data;
vpn_packet_t packet;
int len, i;
int timeout = 1;
n->mtuprobes++;
if(!n->status.reachable) {
logger(LOG_DEBUG, "Trying to send MTU probe to unreachable node %s (%s)", n->name, n->hostname);
if(!n->status.reachable || !n->status.validkey) {
ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send MTU probe to unreachable or rekeying node %s (%s)", n->name, n->hostname);
n->mtuprobes = 0;
return;
}
if(n->mtuprobes > 32) {
ifdebug(TRAFFIC) logger(LOG_INFO, "%s (%s) did not respond to UDP ping, restarting PMTU discovery", n->name, n->hostname);
n->mtuprobes = 1;
n->minmtu = 0;
n->maxmtu = MTU;
}
if(n->mtuprobes >= 10 && !n->minmtu) {
ifdebug(TRAFFIC) logger(LOG_INFO, "No response to MTU probes from %s (%s)", n->name, n->hostname);
n->mtuprobes = 0;
return;
}
for(i = 0; i < 3; i++) {
if(n->mtuprobes >= 30 || n->minmtu >= n->maxmtu) {
n->mtu = n->minmtu;
ifdebug(TRAFFIC) logger(LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes);
return;
}
if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) {
if(n->minmtu > n->maxmtu)
n->minmtu = n->maxmtu;
else
n->maxmtu = n->minmtu;
n->mtu = n->minmtu;
ifdebug(TRAFFIC) logger(LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes);
n->mtuprobes = 31;
}
if(n->mtuprobes == 31) {
timeout = pinginterval;
goto end;
} else if(n->mtuprobes == 32) {
timeout = pingtimeout;
}
for(i = 0; i < 3; i++) {
if(n->maxmtu <= n->minmtu)
len = n->maxmtu;
else
len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu);
len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu);
if(len < 64)
len = 64;
@ -92,7 +118,8 @@ static void send_mtu_probe_handler(int fd, short events, void *data) {
send_udppacket(n, &packet);
}
event_add(&n->mtuevent, &(struct timeval){1, 0});
end:
event_add(&n->mtuevent, &(struct timeval){timeout, 0});
}
void send_mtu_probe(node_t *n) {
@ -106,10 +133,14 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
if(!packet->data[0]) {
packet->data[0] = 1;
send_packet(n, packet);
send_udppacket(n, packet);
} else {
if(len > n->maxmtu)
len = n->maxmtu;
if(n->minmtu < len)
n->minmtu = len;
if(n->mtuprobes > 30)
n->mtuprobes = 30;
}
}
@ -317,10 +348,13 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) {
ifdebug(TRAFFIC) logger(LOG_INFO,
"Packet for %s (%s) larger than minimum MTU, forwarding via TCP",
n->name, n->hostname);
"Packet for %s (%s) larger than minimum MTU, forwarding via %s",
n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP");
send_tcppacket(n->nexthop->connection, origpkt);
if(n != n->nexthop)
send_packet(n->nexthop, origpkt);
else
send_tcppacket(n->nexthop->connection, origpkt);
return;
}
@ -390,14 +424,14 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
}
#endif
if((sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0) {
if(errno == EMSGSIZE) {
if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) {
if(sockmsgsize(sockerrno)) {
if(n->maxmtu >= origlen)
n->maxmtu = origlen - 1;
if(n->mtu >= origlen)
n->mtu = origlen - 1;
} else
logger(LOG_ERR, "Error sending packet to %s (%s): %s", n->name, n->hostname, strerror(errno));
logger(LOG_ERR, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno));
}
end:
@ -469,12 +503,17 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
splay_node_t *node;
edge_t *e;
node_t *n = NULL;
static time_t last_hard_try = 0;
time_t now = time(NULL);
for(node = edge_weight_tree->head; node; node = node->next) {
e = node->data;
if(sockaddrcmp_noport(from, &e->address))
continue;
if(sockaddrcmp_noport(from, &e->address)) {
if(last_hard_try == now)
continue;
last_hard_try = now;
}
if(!n)
n = e->to;
@ -499,8 +538,8 @@ void handle_incoming_vpn_data(int sock, short events, void *data) {
pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
if(pkt.len < 0) {
if(errno != EAGAIN && errno != EINTR)
logger(LOG_ERR, "Receiving packet failed: %s", strerror(errno));
if(!sockwouldblock(sockerrno))
logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno));
return;
}

View file

@ -293,7 +293,7 @@ bool setup_myself(void) {
/* Generate packet encryption key */
if(!get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
cipher = xstrdup("aes256");
cipher = xstrdup("blowfish");
if(!cipher_open_by_name(&myself->incipher, cipher)) {
logger(LOG_ERR, "Unrecognized cipher type!");
@ -308,7 +308,7 @@ bool setup_myself(void) {
/* Check if we want to use message authentication codes... */
if(!get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
digest = xstrdup("sha256");
digest = xstrdup("sha1");
int maclength = 4;
get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &maclength);

View file

@ -35,10 +35,6 @@
#include <assert.h>
#ifdef WSAEINPROGRESS
#define EINPROGRESS WSAEINPROGRESS
#endif
/* Needed on Mac OS/X */
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
@ -67,7 +63,7 @@ static void configure_tcp(connection_t *c) {
unsigned long arg = 1;
if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) {
logger(LOG_ERR, "ioctlsocket for %s: WSA error %d", c->hostname, WSAGetLastError());
logger(LOG_ERR, "ioctlsocket for %s: %d", c->hostname, sockstrerror(sockerrno));
}
#endif
@ -156,8 +152,7 @@ static bool bind_to_address(connection_t *c) {
if(status) {
logger(LOG_ERR, "Can't bind to %s/tcp: %s", node,
strerror(errno));
logger(LOG_ERR, "Can't bind to %s/tcp: %s", node, sockstrerror(sockerrno));
} else ifdebug(CONNECTIONS) {
logger(LOG_DEBUG, "Successfully bound outgoing "
"TCP socket to %s", node);
@ -178,7 +173,7 @@ int setup_listen_socket(const sockaddr_t *sa) {
nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if(nfd < 0) {
ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", strerror(errno));
ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno));
return -1;
}
@ -203,7 +198,7 @@ int setup_listen_socket(const sockaddr_t *sa) {
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof ifr)) {
closesocket(nfd);
logger(LOG_ERR, "Can't bind to interface %s: %s", iface,
strerror(errno));
strerror(sockerrno));
return -1;
}
#else
@ -214,16 +209,14 @@ int setup_listen_socket(const sockaddr_t *sa) {
if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
closesocket(nfd);
addrstr = sockaddr2hostname(sa);
logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr,
strerror(errno));
logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno));
free(addrstr);
return -1;
}
if(listen(nfd, 3)) {
closesocket(nfd);
logger(LOG_ERR, "System call `%s' failed: %s", "listen",
strerror(errno));
logger(LOG_ERR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno));
return -1;
}
@ -238,7 +231,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
if(nfd < 0) {
logger(LOG_ERR, "Creating UDP socket failed: %s", strerror(errno));
logger(LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno));
return -1;
}
@ -258,8 +251,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
unsigned long arg = 1;
if(ioctlsocket(nfd, FIONBIO, &arg) != 0) {
closesocket(nfd);
logger(LOG_ERR, "Call to `%s' failed: WSA error %d", "ioctlsocket",
WSAGetLastError());
logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
return -1;
}
}
@ -278,6 +270,11 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = IP_PMTUDISC_DO;
setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, &option, sizeof(option));
}
#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
if(myself->options & OPTION_PMTU_DISCOVERY) {
option = 1;
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, &option, sizeof(option));
}
#endif
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
@ -295,8 +292,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
closesocket(nfd);
addrstr = sockaddr2hostname(sa);
logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr,
strerror(errno));
logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno));
free(addrstr);
return -1;
}
@ -337,6 +333,11 @@ void do_outgoing_connection(connection_t *c) {
char *address, *port;
int result;
if(!c->outgoing) {
logger(LOG_ERR, "do_outgoing_connection() for %s called without c->outgoing", c->name);
abort();
}
begin:
if(!c->outgoing->ai) {
if(!c->outgoing->cfg) {
@ -382,9 +383,7 @@ begin:
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if(c->socket == -1) {
ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname,
strerror(errno));
ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno));
goto begin;
}
@ -406,18 +405,14 @@ begin:
result = connect(c->socket, &c->address.sa, SALEN(c->address.sa));
if(result == -1) {
if(errno == EINPROGRESS
#if defined(WIN32) && !defined(O_NONBLOCK)
|| WSAGetLastError() == WSAEWOULDBLOCK
#endif
) {
if(sockinprogress(sockerrno)) {
c->status.connecting = true;
return;
}
closesocket(c->socket);
ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, strerror(errno));
ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, sockstrerror(sockerrno));
goto begin;
}
@ -446,6 +441,8 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
connection_t *c;
node_t *n;
event_del(&outgoing->ev);
n = lookup_node(outgoing->name);
if(n)
@ -504,7 +501,7 @@ void handle_new_meta_connection(int sock, short events, void *data) {
fd = accept(sock, &sa.sa, &len);
if(fd < 0) {
logger(LOG_ERR, "Accepting a new connection failed: %s", strerror(errno));
logger(LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno));
return;
}
@ -555,18 +552,7 @@ void try_outgoing_connections(void) {
static config_t *cfg = NULL;
char *name;
outgoing_t *outgoing;
connection_t *c;
splay_node_t *node;
if(outgoing_list) {
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
c->outgoing = NULL;
}
list_delete_list(outgoing_list);
}
outgoing_list = list_alloc((list_action_t)free_outgoing);
for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) {

View file

@ -42,7 +42,7 @@ typedef struct node_status_t {
typedef struct node_t {
char *name; /* name of this node */
long int options; /* options turned on for this node */
uint32_t options; /* options turned on for this node */
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
char *hostname; /* the hostname of its real ip */

View file

@ -98,13 +98,18 @@ bool install_service(void) {
command, NULL, NULL, NULL, NULL, NULL);
if(!service) {
logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(GetLastError()));
return false;
DWORD lasterror = GetLastError();
logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(lasterror));
if(lasterror != ERROR_SERVICE_EXISTS)
return false;
}
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
logger(LOG_INFO, "%s service installed", identname);
if(service) {
ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
logger(LOG_INFO, "%s service installed", identname);
} else {
service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
}
if(!StartService(service, 0, NULL))
logger(LOG_WARNING, "Could not start %s service: %s", identname, winerror(GetLastError()));

View file

@ -348,7 +348,7 @@ bool send_ack(connection_t *c) {
get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
return send_request(c, "%d %s %d %lx", ACK, myport, c->estimated_weight, c->options);
return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options);
}
static void send_everything(connection_t *c) {
@ -387,10 +387,10 @@ bool ack_h(connection_t *c, char *request) {
char hisport[MAX_STRING_SIZE];
char *hisaddress, *dummy;
int weight, mtu;
long int options;
uint32_t options;
node_t *n;
if(sscanf(request, "%*d " MAX_STRING " %d %lx", hisport, &weight, &options) != 3) {
if(sscanf(request, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) {
logger(LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name,
c->hostname);
return false;

View file

@ -41,7 +41,7 @@ bool send_add_edge(connection_t *c, const edge_t *e) {
sockaddr2str(&e->address, &address, &port);
x = send_request(c, "%d %x %s %s %s %s %lx %d", ADD_EDGE, rand(),
x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(),
e->from->name, e->to->name, address, port,
e->options, e->weight);
free(address);
@ -58,10 +58,10 @@ bool add_edge_h(connection_t *c, char *request) {
char to_address[MAX_STRING_SIZE];
char to_port[MAX_STRING_SIZE];
sockaddr_t address;
long int options;
uint32_t options;
int weight;
if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d",
from_name, to_name, to_address, to_port, &options, &weight) != 6) {
logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name,
c->hostname);
@ -70,13 +70,7 @@ bool add_edge_h(connection_t *c, char *request) {
/* Check if names are valid */
if(!check_id(from_name)) {
logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name,
c->hostname, "invalid name");
return false;
}
if(!check_id(to_name)) {
if(!check_id(from_name) || !check_id(to_name)) {
logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name,
c->hostname, "invalid name");
return false;
@ -186,13 +180,7 @@ bool del_edge_h(connection_t *c, char *request) {
/* Check if names are valid */
if(!check_id(from_name)) {
logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name,
c->hostname, "invalid name");
return false;
}
if(!check_id(to_name)) {
if(!check_id(from_name) || !check_id(to_name)) {
logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name,
c->hostname, "invalid name");
return false;

View file

@ -45,7 +45,7 @@ bool add_subnet_h(connection_t *c, char *request) {
char subnetstr[MAX_STRING_SIZE];
char name[MAX_STRING_SIZE];
node_t *owner;
subnet_t s = {0}, *new;
subnet_t s = {0}, *new, *old;
if(sscanf(request, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_SUBNET", c->name,
@ -112,7 +112,7 @@ bool add_subnet_h(connection_t *c, char *request) {
for(cfg = lookup_config(c->config_tree, "Subnet"); cfg; cfg = lookup_config_next(c->config_tree, cfg)) {
if(!get_config_subnet(cfg, &allowed))
return false;
continue;
if(!subnet_compare(&s, allowed))
break;
@ -121,9 +121,9 @@ bool add_subnet_h(connection_t *c, char *request) {
}
if(!cfg) {
logger(LOG_WARNING, "Unauthorized %s from %s (%s) for %s",
"ADD_SUBNET", c->name, c->hostname, subnetstr);
return false;
logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
"ADD_SUBNET", c->name, c->hostname, subnetstr);
return true;
}
free_subnet(allowed);
@ -142,6 +142,11 @@ bool add_subnet_h(connection_t *c, char *request) {
if(!tunnelserver)
forward_request(c, request);
/* Fast handoff of roaming MAC addresses */
if(s.type == SUBNET_MAC && owner != myself && (old = lookup_subnet(myself, &s)) && old->expires)
old->expires = 1;
return true;
}

View file

@ -154,6 +154,7 @@ static void learn_mac(mac_t *address) {
subnet->type = SUBNET_MAC;
subnet->expires = time(NULL) + macexpire;
subnet->net.mac.address = *address;
subnet->weight = 10;
subnet_add(myself, subnet);
/* And tell all other tinc daemons it's our MAC */

View file

@ -131,7 +131,7 @@ bool read_packet(vpn_packet_t *packet) {
break;
default:
ifdebug(TRAFFIC) logger(LOG_ERR,
_ ("Unknown IP version %d while reading packet from %s %s"),
"Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device);
return false;
}

View file

@ -47,9 +47,15 @@ static subnet_t *cache_ipv6_subnet[2];
static bool cache_ipv6_valid[2];
static int cache_ipv6_slot;
static mac_t cache_mac_address[2];
static subnet_t *cache_mac_subnet[2];
static bool cache_mac_valid[2];
static int cache_mac_slot;
void subnet_cache_flush() {
cache_ipv4_valid[0] = cache_ipv4_valid[1] = false;
cache_ipv6_valid[0] = cache_ipv6_valid[1] = false;
cache_mac_valid[0] = cache_mac_valid[1] = false;
}
/* Subnet comparison */
@ -324,15 +330,46 @@ subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) {
}
subnet_t *lookup_subnet_mac(const mac_t *address) {
subnet_t *p, subnet = {0};
subnet_t *p, *r = NULL, subnet = {0};
splay_node_t *n;
int i;
// Check if this address is cached
for(i = 0; i < 2; i++) {
if(!cache_mac_valid[i])
continue;
if(!memcmp(address, &cache_mac_address[i], sizeof *address))
return cache_mac_subnet[i];
}
// Search all subnets for a matching one
subnet.type = SUBNET_MAC;
subnet.net.mac.address = *address;
subnet.owner = NULL;
p = splay_search(subnet_tree, &subnet);
for(n = subnet_tree->head; n; n = n->next) {
p = n->data;
if(!p || p->type != subnet.type)
continue;
return p;
if(!memcmp(address, &p->net.mac.address, sizeof *address)) {
r = p;
if(p->owner->status.reachable)
break;
}
}
// Cache the result
cache_mac_slot = !cache_mac_slot;
memcpy(&cache_mac_address[cache_mac_slot], address, sizeof *address);
cache_mac_subnet[cache_mac_slot] = r;
cache_mac_valid[cache_mac_slot] = true;
return r;
}
subnet_t *lookup_subnet_ipv4(const ipv4_t *address) {