Merge branch 'master' into 1.1

Conflicts:
	NEWS
	README
	doc/tinc.conf.5.in
	doc/tinc.texi
	po/nl.po
	src/conf.c
	src/connection.c
	src/event.c
	src/graph.c
	src/net.c
	src/net_packet.c
	src/net_socket.c
	src/node.c
	src/node.h
	src/openssl/rsagen.h
	src/protocol_auth.c
	src/protocol_key.c
	src/protocol_misc.c
	src/subnet.c
	src/subnet.h
	src/tincd.c
This commit is contained in:
Guus Sliepen 2009-03-09 19:02:24 +01:00
commit 08aabbf931
34 changed files with 601 additions and 326 deletions

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction BSD tun/tap device
Copyright (C) 2001-2005 Ivo Timmermans,
2001-2007 Guus Sliepen <guus@tinc-vpn.org>
2001-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
@ -27,6 +27,7 @@
#include "net.h"
#include "route.h"
#include "utils.h"
#include "xalloc.h"
#define DEFAULT_DEVICE "/dev/tun0"
@ -37,12 +38,12 @@ typedef enum device_type {
} device_type_t;
int device_fd = -1;
char *device;
char *iface;
char *device_info;
char *device = NULL;
char *iface = NULL;
static char *device_info = NULL;
static int device_total_in = 0;
static int device_total_out = 0;
#ifdef HAVE_OPENBSD
#if defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD)
static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
#else
static device_type_t device_type = DEVICE_TYPE_TUN;
@ -54,10 +55,10 @@ bool setup_device(void) {
cp();
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
device = xstrdup(DEFAULT_DEVICE);
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
iface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
iface = xstrdup(rindex(device, '/') ? rindex(device, '/') + 1 : device);
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
logger(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
@ -78,7 +79,7 @@ bool setup_device(void) {
return false;
}
} else {
if(strstr(device, "tap"))
if(strstr(device, "tap") || routing_mode != RMODE_ROUTER)
device_type = DEVICE_TYPE_TAP;
}
@ -139,6 +140,9 @@ void close_device(void) {
cp();
close(device_fd);
free(device);
free(iface);
}
bool read_packet(vpn_packet_t *packet) {

View file

@ -2,7 +2,7 @@
conf.c -- configuration code
Copyright (C) 1998 Robert van der Meulen
1998-2005 Ivo Timmermans
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000 Cris van Pelt
This program is free software; you can redistribute it and/or modify
@ -287,6 +287,8 @@ static char *readline(FILE * fp, char **buf, size_t *buflen) {
size = newsize;
} else {
*newline = '\0'; /* kill newline */
if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */
newline[-1] = '\0';
break; /* yay */
}
}

View file

@ -1,7 +1,7 @@
/*
conf.h -- header for conf.c
Copyright (C) 1998-2005 Ivo Timmermans
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -60,5 +60,6 @@ extern int read_config_file(splay_tree_t *, const char *);
extern bool read_server_config(void);
extern FILE *ask_and_open(const char *, const char *, const char *);
extern bool is_safe_path(const char *);
extern bool disable_old_keys(FILE *);
#endif /* __TINC_CONF_H__ */

View file

@ -80,6 +80,9 @@ void free_connection(connection_t *c) {
if(c->hischallenge)
free(c->hischallenge);
if(c->config_tree)
exit_configuration(&c->config_tree);
if(c->buffer)
bufferevent_free(c->buffer);
@ -110,9 +113,9 @@ int dump_connections(struct evbuffer *out) {
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
if(evbuffer_add_printf(out,
_(" %s at %s options %lx socket %d status %04x\n"),
c->name, c->hostname, c->options, c->socket,
c->status.value) == -1)
_(" %s at %s options %lx socket %d status %04x\n"),
c->name, c->hostname, c->options, c->socket,
c->status.value) == -1)
return errno;
}

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Windows tap driver in a Cygwin environment
Copyright (C) 2002-2005 Ivo Timmermans,
2002-2006 Guus Sliepen <guus@tinc-vpn.org>
2002-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
@ -38,7 +38,7 @@ int device_fd = -1;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
char *device = NULL;
char *iface = NULL;
char *device_info = NULL;
static char *device_info = NULL;
static int device_total_in = 0;
static int device_total_out = 0;
@ -225,6 +225,9 @@ void close_device(void) {
CloseHandle(device_handle);
kill(reader_pid, SIGKILL);
free(device);
free(iface);
}
bool read_packet(vpn_packet_t *packet) {

View file

@ -1,6 +1,6 @@
/*
graph.c -- graph algorithms
Copyright (C) 2001-2006 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2001-2009 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -443,6 +443,7 @@ int dump_graph(struct evbuffer *out) {
}
void graph(void) {
subnet_cache_flush();
sssp_dijkstra();
check_reachability();
mst_kruskal();

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Linux ethertap and tun/tap device
Copyright (C) 2001-2005 Ivo Timmermans,
2001-2006 Guus Sliepen <guus@tinc-vpn.org>
2001-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
@ -34,6 +34,7 @@
#include "net.h"
#include "route.h"
#include "utils.h"
#include "xalloc.h"
typedef enum device_type_t {
DEVICE_TYPE_ETHERTAP,
@ -43,10 +44,10 @@ typedef enum device_type_t {
int device_fd = -1;
static device_type_t device_type;
char *device;
char *iface;
char ifrname[IFNAMSIZ];
char *device_info;
char *device = NULL;
char *iface = NULL;
static char ifrname[IFNAMSIZ];
static char *device_info;
static int device_total_in = 0;
static int device_total_out = 0;
@ -57,13 +58,13 @@ bool setup_device(void) {
cp();
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
device = xstrdup(DEFAULT_DEVICE);
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
#ifdef HAVE_LINUX_IF_TUN_H
iface = netname;
iface = xstrdup(netname);
#else
iface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
iface = xstrdup(rindex(device, '/') ? rindex(device, '/') + 1 : device);
#endif
device_fd = open(device, O_RDWR | O_NONBLOCK);
@ -91,11 +92,13 @@ bool setup_device(void) {
if(!ioctl(device_fd, TUNSETIFF, &ifr)) {
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
iface = ifrname;
if(iface) 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);
iface = ifrname;
if(iface) free(iface);
iface = xstrdup(ifrname);
} else
#endif
{
@ -103,7 +106,9 @@ bool setup_device(void) {
overwrite_mac = true;
device_info = _("Linux ethertap device");
device_type = DEVICE_TYPE_ETHERTAP;
iface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
if(iface)
free(iface);
iface = xstrdup(rindex(device, '/') ? rindex(device, '/') + 1 : device);
}
logger(LOG_INFO, _("%s is a %s"), device, device_info);
@ -115,6 +120,9 @@ void close_device(void) {
cp();
close(device_fd);
free(device);
free(iface);
}
bool read_packet(vpn_packet_t *packet) {

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Windows tap driver in a MinGW environment
Copyright (C) 2002-2005 Ivo Timmermans,
2002-2007 Guus Sliepen <guus@tinc-vpn.org>
2002-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
@ -38,7 +38,7 @@ int device_fd = 0;
static HANDLE device_handle = INVALID_HANDLE_VALUE;
char *device = NULL;
char *iface = NULL;
char *device_info = NULL;
static char *device_info = NULL;
static int device_total_in = 0;
static int device_total_out = 0;
@ -52,7 +52,7 @@ static struct packetbuf {
static int nbufs = 64;
DWORD WINAPI tapreader(void *bla) {
static DWORD WINAPI tapreader(void *bla) {
int sock, err, status;
struct addrinfo *ai;
struct addrinfo hint = {
@ -311,6 +311,9 @@ void close_device(void) {
cp();
CloseHandle(device_handle);
free(device);
free(iface);
}
bool read_packet(vpn_packet_t *packet) {

View file

@ -1,7 +1,7 @@
/*
net.c -- most of the network code
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-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

View file

@ -1,7 +1,7 @@
/*
net.h -- header for net.c
Copyright (C) 1998-2005 Ivo Timmermans <zarq@iname.com>
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -38,8 +38,6 @@
#define MAXSOCKETS 8 /* Probably overkill... */
#define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */
typedef struct mac_t {
uint8_t x[6];
} mac_t;
@ -87,17 +85,6 @@ typedef struct vpn_packet_t {
uint8_t data[MAXSIZE];
} vpn_packet_t;
typedef struct queue_element_t {
void *packet;
struct queue_element_t *prev;
struct queue_element_t *next;
} queue_element_t;
typedef struct packet_queue_t {
queue_element_t *head;
queue_element_t *tail;
} packet_queue_t;
typedef struct listen_socket_t {
struct event ev_tcp;
struct event ev_udp;
@ -107,6 +94,7 @@ typedef struct listen_socket_t {
} listen_socket_t;
#include "conf.h"
#include "list.h"
typedef struct outgoing_t {
char *name;
@ -117,6 +105,8 @@ typedef struct outgoing_t {
struct event ev;
} outgoing_t;
extern list_t *outgoing_list;
extern int maxoutbufsize;
extern int seconds_till_retry;
extern int addressfamily;

View file

@ -1,7 +1,7 @@
/*
net_packet.c -- Handles in- and outgoing VPN packets
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -83,6 +83,7 @@ static void send_mtu_probe_handler(int fd, short events, void *data) {
memset(packet.data, 0, 14);
randomize(packet.data + 14, len - 14);
packet.len = len;
packet.priority = 0;
ifdebug(TRAFFIC) logger(LOG_INFO, _("Sending MTU probe length %d to %s (%s)"), len, n->name, n->hostname);
@ -244,6 +245,8 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
inpkt = outpkt;
}
inpkt->priority = 0;
if(!inpkt->data[12] && !inpkt->data[13])
mtu_probe_h(n, inpkt);
else
@ -256,6 +259,10 @@ void receive_tcppacket(connection_t *c, char *buffer, int len) {
cp();
outpkt.len = len;
if(c->options & OPTION_TCPONLY)
outpkt.priority = 0;
else
outpkt.priority = -1;
memcpy(outpkt.data, buffer, len);
receive_packet(c->node, &outpkt);
@ -269,7 +276,6 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
vpn_packet_t *outpkt;
int origlen;
size_t outlen;
vpn_packet_t *copy;
static int priority = 0;
int origpriority;
int sock;
@ -280,26 +286,27 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(!n->status.validkey) {
ifdebug(TRAFFIC) logger(LOG_INFO,
_("No valid key known yet for %s (%s), queueing packet"),
_("No valid key known yet for %s (%s), forwarding via TCP"),
n->name, n->hostname);
/* Since packet is on the stack of handle_tap_input(), we have to make a copy of it first. */
*(copy = xmalloc(sizeof *copy)) = *inpkt;
list_insert_tail(n->queue, copy);
if(n->queue->count > MAXQUEUELENGTH)
list_delete_head(n->queue);
if(!n->status.waitingforkey)
send_req_key(n->nexthop->connection, myself, n);
n->status.waitingforkey = true;
send_tcppacket(n->nexthop->connection, origpkt);
return;
}
if(!n->minmtu && (inpkt->data[12] | inpkt->data[13])) {
ifdebug(TRAFFIC) logger(LOG_INFO,
_("No minimum MTU established yet for %s (%s), forwarding via TCP"),
n->name, n->hostname);
send_tcppacket(n->nexthop->connection, origpkt);
}
origlen = inpkt->len;
origpriority = inpkt->priority;
@ -403,13 +410,13 @@ void send_packet(const node_t *n, vpn_packet_t *packet) {
return;
}
via = (n->via == myself) ? n->nexthop : n->via;
via = (packet->priority == -1 || n->via == myself) ? n->nexthop : n->via;
if(via != n)
ifdebug(TRAFFIC) logger(LOG_ERR, _("Sending packet to %s via %s (%s)"),
ifdebug(TRAFFIC) logger(LOG_INFO, _("Sending packet to %s via %s (%s)"),
n->name, via->name, n->via->hostname);
if((myself->options | via->options) & OPTION_TCPONLY) {
if(packet->priority == -1 || ((myself->options | via->options) & OPTION_TCPONLY)) {
if(!send_tcppacket(via->connection, packet))
terminate_connection(via->connection, true);
} else
@ -438,21 +445,8 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) {
}
}
void flush_queue(node_t *n) {
list_node_t *node, *next;
cp();
ifdebug(TRAFFIC) logger(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname);
for(node = n->queue->head; node; node = next) {
next = node->next;
send_udppacket(n, node->data);
list_delete_node(n->queue, node);
}
}
void handle_incoming_vpn_data(int sock, short events, void *data) {
void handle_incoming_vpn_data(int sock, short events, void *data)
{
vpn_packet_t pkt;
char *hostname;
sockaddr_t from;

View file

@ -1,7 +1,7 @@
/*
net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -242,9 +242,6 @@ bool setup_myself(void) {
if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice) && choice)
myself->options |= OPTION_TCPONLY;
if(get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice) && choice)
myself->options |= OPTION_PMTU_DISCOVERY;
if(myself->options & OPTION_TCPONLY)
myself->options |= OPTION_INDIRECT;
@ -265,6 +262,10 @@ bool setup_myself(void) {
} else
routing_mode = RMODE_ROUTER;
if(routing_mode == RMODE_ROUTER)
if(!get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice) || choice)
myself->options |= OPTION_PMTU_DISCOVERY;
get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
#if !defined(SOL_IP) || !defined(IP_TOS)
@ -490,7 +491,7 @@ bool setup_network_connections(void) {
pingtimeout = pinginterval;
if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize))
maxoutbufsize = 4 * MTU;
maxoutbufsize = 10 * MTU;
if(!setup_myself())
return false;
@ -514,21 +515,16 @@ void close_network_connections(void) {
for(node = connection_tree->head; node; node = next) {
next = node->next;
c = node->data;
if(c->outgoing) {
if(c->outgoing->ai)
freeaddrinfo(c->outgoing->ai);
free(c->outgoing->name);
free(c->outgoing);
c->outgoing = NULL;
}
c->outgoing = false;
terminate_connection(c, false);
}
list_delete_list(outgoing_list);
if(myself && myself->connection) {
subnet_update(myself, NULL, false);
terminate_connection(myself->connection, false);
free_connection(myself->connection);
}
for(i = 0; i < listen_sockets; i++) {
@ -552,6 +548,8 @@ void close_network_connections(void) {
execute_script("tinc-down", envp);
if(myport) free(myport);
for(i = 0; i < 4; i++)
free(envp[i]);

View file

@ -1,7 +1,7 @@
/*
net_socket.c -- Handle various kinds of sockets.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2007 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -48,6 +48,7 @@ int seconds_till_retry = 5;
listen_socket_t listen_socket[MAXSOCKETS];
int listen_sockets;
list_t *outgoing_list = NULL;
/* Setup sockets */
@ -188,24 +189,16 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
#endif
#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
{
bool choice;
if(get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice) && choice) {
option = IP_PMTUDISC_DO;
setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, &option, sizeof option);
}
if(myself->options & OPTION_PMTU_DISCOVERY) {
option = IP_PMTUDISC_DO;
setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, &option, sizeof(option));
}
#endif
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
{
bool choice;
if(get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice) && choice) {
option = IPV6_PMTUDISC_DO;
setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, &option, sizeof option);
}
if(myself->options & OPTION_PMTU_DISCOVERY) {
option = IPV6_PMTUDISC_DO;
setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, &option, sizeof(option));
}
#endif
@ -412,8 +405,6 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
if(!outgoing->cfg) {
logger(LOG_ERR, _("No address specified for %s"), c->name);
free_connection(c);
free(outgoing->name);
free(outgoing);
return;
}
@ -486,13 +477,37 @@ void handle_new_meta_connection(int sock, short events, void *data) {
send_id(c);
}
void try_outgoing_connections(void) {
void free_outgoing(outgoing_t *outgoing) {
if(outgoing->ai)
freeaddrinfo(outgoing->ai);
if(outgoing->name)
free(outgoing->name);
free(outgoing);
}
void try_outgoing_connections(void)
{
static config_t *cfg = NULL;
char *name;
outgoing_t *outgoing;
connection_t *c;
splay_node_t *node;
cp();
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)) {
get_config_string(cfg, &name);
@ -506,6 +521,7 @@ void try_outgoing_connections(void) {
outgoing = xmalloc_and_zero(sizeof *outgoing);
outgoing->name = name;
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
}
}

View file

@ -1,6 +1,6 @@
/*
node.c -- node tree management
Copyright (C) 2001-2006 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2001-2009 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -73,7 +73,6 @@ node_t *new_node(void) {
n->subnet_tree = new_subnet_tree();
n->edge_tree = new_edge_tree();
n->queue = list_alloc((list_action_t) free);
n->mtu = MTU;
n->maxmtu = MTU;
@ -83,9 +82,6 @@ node_t *new_node(void) {
void free_node(node_t *n) {
cp();
if(n->queue)
list_delete_list(n->queue);
if(n->subnet_tree)
free_subnet_tree(n->subnet_tree);

View file

@ -1,6 +1,6 @@
/*
node.h -- header for node.c
Copyright (C) 2001-2006 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2001-2009 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -60,8 +60,6 @@ typedef struct node_t {
int compression; /* Compressionlevel, 0 = no compression */
list_t *queue; /* Queue for packets awaiting to be encrypted */
int distance;
struct node_t *nexthop; /* nearest node from us to him */
struct node_t *via; /* next hop for UDP packets */

View file

@ -1,7 +1,7 @@
/*
process.c -- process management functions
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-2007 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

View file

@ -1,7 +1,7 @@
/*
protocol_auth.c -- handle the meta-protocol, authentication
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2007 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -363,7 +363,7 @@ bool send_ack(connection_t *c) {
if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY)
c->options |= OPTION_TCPONLY | OPTION_INDIRECT;
if((get_config_bool(lookup_config(c->config_tree, "PMTUDiscovery"), &choice) && choice) || myself->options & OPTION_PMTU_DISCOVERY)
if(myself->options & OPTION_PMTU_DISCOVERY)
c->options |= OPTION_PMTU_DISCOVERY;
get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
@ -448,6 +448,10 @@ bool ack_h(connection_t *c, char *request) {
n->connection = c;
c->node = n;
if(!(c->options & options & OPTION_PMTU_DISCOVERY)) {
c->options &= ~OPTION_PMTU_DISCOVERY;
options &= ~OPTION_PMTU_DISCOVERY;
}
c->options |= options;
if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu)

View file

@ -1,7 +1,7 @@
/*
protocol_key.c -- handle the meta-protocol, key exchange
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -248,7 +248,5 @@ bool ans_key_h(connection_t *c, char *request) {
if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuprobes)
send_mtu_probe(from);
flush_queue(from);
return true;
}

View file

@ -151,9 +151,10 @@ bool send_tcppacket(connection_t *c, vpn_packet_t *packet)
{
cp();
/* If there already is a lot of data in the outbuf buffer, discard this packet. */
/* If there already is a lot of data in the outbuf buffer, discard this packet.
We use a very simple Random Early Drop algorithm. */
if(c->buffer->output->off > maxoutbufsize)
if(2.0 * c->buffer->output->off / (double)maxoutbufsize - 1 > drand48())
return true;
if(!send_request(c, "%d %hd", PACKET, packet->len))

View file

@ -1,7 +1,7 @@
/*
protocol_subnet.c -- handle the meta-protocol, subnets
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -83,15 +83,19 @@ bool add_subnet_h(connection_t *c, char *request)
owner = lookup_node(name);
if(tunnelserver && owner != myself && owner != c->node) {
/* in case of tunnelserver, ignore indirect subnet registrations */
ifdebug(PROTOCOL) logger(LOG_WARNING, _("Ignoring indirect %s from %s (%s) for %s"),
"ADD_SUBNET", c->name, c->hostname, subnetstr);
return true;
}
if(!owner) {
owner = new_node();
owner->name = xstrdup(name);
node_add(owner);
}
if(tunnelserver && owner != myself && owner != c->node)
return false;
/* Check if we already know this subnet */
if(lookup_subnet(owner, &s))

View file

@ -1,7 +1,7 @@
/*
device.c -- raw socket
Copyright (C) 2002-2005 Ivo Timmermans,
2002-2006 Guus Sliepen <guus@tinc-vpn.org>
2002-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
@ -29,12 +29,13 @@
#include "logger.h"
#include "utils.h"
#include "route.h"
#include "xalloc.h"
int device_fd = -1;
char *device;
char *iface;
char ifrname[IFNAMSIZ];
char *device_info;
char *device = NULL;
char *iface = NULL;
static char ifrname[IFNAMSIZ];
static char *device_info;
static int device_total_in = 0;
static int device_total_out = 0;
@ -45,12 +46,11 @@ bool setup_device(void) {
cp();
if(!get_config_string
(lookup_config(config_tree, "Interface"), &iface))
iface = "eth0";
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
iface = xstrdup("eth0");
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = iface;
device = xstrdup(iface);
device_info = _("raw socket");
@ -88,6 +88,9 @@ void close_device(void) {
cp();
close(device_fd);
free(device);
free(iface);
}
bool read_packet(vpn_packet_t *packet) {

View file

@ -1,7 +1,7 @@
/*
route.c -- routing
Copyright (C) 2000-2005 Ivo Timmermans,
2000-2006 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -391,7 +391,14 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet)
if(!checklength(source, packet, ether_size + ip_size))
return;
route_ipv4_unicast(source, packet);
if(((packet->data[30] & 0xf0) == 0xe0) || (
packet->data[30] == 255 &&
packet->data[31] == 255 &&
packet->data[32] == 255 &&
packet->data[33] == 255))
broadcast_packet(source, packet);
else
route_ipv4_unicast(source, packet);
}
/* RFC 2463 */
@ -529,6 +536,7 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet)
struct nd_opt_hdr opt;
subnet_t *subnet;
uint16_t checksum;
bool has_opt;
struct {
struct in6_addr ip6_src; /* source address */
@ -539,9 +547,11 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet)
cp();
if(!checklength(source, packet, ether_size + ip6_size + ns_size + opt_size + ETH_ALEN))
if(!checklength(source, packet, ether_size + ip6_size + ns_size))
return;
has_opt = packet->len >= ether_size + ip6_size + ns_size + opt_size + ETH_ALEN;
if(source != myself) {
ifdebug(TRAFFIC) logger(LOG_WARNING, _("Got neighbor solicitation request from %s (%s) while in router mode!"), source->name, source->hostname);
return;
@ -551,7 +561,8 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet)
memcpy(&ip6, packet->data + ether_size, ip6_size);
memcpy(&ns, packet->data + ether_size + ip6_size, ns_size);
memcpy(&opt, packet->data + ether_size + ip6_size + ns_size, opt_size);
if(has_opt)
memcpy(&opt, packet->data + ether_size + ip6_size + ns_size, opt_size);
/* First, snatch the source address from the neighbor solicitation packet */
@ -561,7 +572,7 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet)
/* Check if this is a valid neighbor solicitation request */
if(ns.nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
opt.nd_opt_type != ND_OPT_SOURCE_LINKADDR) {
(has_opt && opt.nd_opt_type != ND_OPT_SOURCE_LINKADDR)) {
ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request"));
return;
}
@ -570,15 +581,20 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet)
pseudo.ip6_src = ip6.ip6_src;
pseudo.ip6_dst = ip6.ip6_dst;
pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
if(has_opt)
pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
else
pseudo.length = htonl(ns_size);
pseudo.next = htonl(IPPROTO_ICMPV6);
/* Generate checksum */
checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
checksum = inet_checksum(&ns, ns_size, checksum);
checksum = inet_checksum(&opt, opt_size, checksum);
checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
if(has_opt) {
checksum = inet_checksum(&opt, opt_size, checksum);
checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
}
if(checksum) {
ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request"));
@ -616,7 +632,8 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet)
ip6.ip6_dst = ip6.ip6_src; /* swap destination and source protocoll address */
ip6.ip6_src = ns.nd_ns_target;
memcpy(packet->data + ether_size + ip6_size + ns_size + opt_size, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
if(has_opt)
memcpy(packet->data + ether_size + ip6_size + ns_size + opt_size, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
ns.nd_ns_cksum = 0;
ns.nd_ns_type = ND_NEIGHBOR_ADVERT;
@ -627,15 +644,20 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet)
pseudo.ip6_src = ip6.ip6_src;
pseudo.ip6_dst = ip6.ip6_dst;
pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
if(has_opt)
pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
else
pseudo.length = htonl(ns_size);
pseudo.next = htonl(IPPROTO_ICMPV6);
/* Generate checksum */
checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
checksum = inet_checksum(&ns, ns_size, checksum);
checksum = inet_checksum(&opt, opt_size, checksum);
checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
if(has_opt) {
checksum = inet_checksum(&opt, opt_size, checksum);
checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
}
ns.nd_ns_hdr.icmp6_cksum = checksum;
@ -643,7 +665,8 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet)
memcpy(packet->data + ether_size, &ip6, ip6_size);
memcpy(packet->data + ether_size + ip6_size, &ns, ns_size);
memcpy(packet->data + ether_size + ip6_size + ns_size, &opt, opt_size);
if(has_opt)
memcpy(packet->data + ether_size + ip6_size + ns_size, &opt, opt_size);
send_packet(source, packet);
}
@ -660,7 +683,10 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet)
return;
}
route_ipv6_unicast(source, packet);
if(packet->data[38] == 255)
broadcast_packet(source, packet);
else
route_ipv6_unicast(source, packet);
}
/* RFC 826 */

View file

@ -1,7 +1,7 @@
/*
device.c -- Interaction with Solaris tun device
Copyright (C) 2001-2005 Ivo Timmermans,
2001-2006 Guus Sliepen <guus@tinc-vpn.org>
2001-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
@ -31,13 +31,14 @@
#include "logger.h"
#include "net.h"
#include "utils.h"
#include "xalloc.h"
#define DEFAULT_DEVICE "/dev/tun"
int device_fd = -1;
char *device = NULL;
char *iface = NULL;
char *device_info = NULL;
static char *device_info = NULL;
static int device_total_in = 0;
static int device_total_out = 0;
@ -50,7 +51,7 @@ bool setup_device(void) {
cp();
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_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));
@ -111,6 +112,9 @@ void close_device(void) {
cp();
close(device_fd);
free(device);
free(iface);
}
bool read_packet(vpn_packet_t *packet) {

View file

@ -1,6 +1,6 @@
/*
subnet.c -- handle subnet lookups and lists
Copyright (C) 2000-2006 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2009 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -37,6 +37,23 @@
splay_tree_t *subnet_tree;
/* Subnet lookup cache */
static ipv4_t cache_ipv4_address[2];
static subnet_t *cache_ipv4_subnet[2];
static bool cache_ipv4_valid[2];
static int cache_ipv4_slot;
static ipv6_t cache_ipv6_address[2];
static subnet_t *cache_ipv6_subnet[2];
static bool cache_ipv6_valid[2];
static int cache_ipv6_slot;
void subnet_cache_flush() {
cache_ipv4_valid[0] = cache_ipv4_valid[1] = false;
cache_ipv6_valid[0] = cache_ipv6_valid[1] = false;
}
/* Subnet comparison */
static int subnet_compare_mac(const subnet_t *a, const subnet_t *b)
@ -45,6 +62,11 @@ static int subnet_compare_mac(const subnet_t *a, const subnet_t *b)
result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof a->net.mac.address);
if(result)
return result;
result = a->weight - b->weight;
if(result || !a->owner || !b->owner)
return result;
@ -55,12 +77,17 @@ static int subnet_compare_ipv4(const subnet_t *a, const subnet_t *b)
{
int result;
result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof a->net.ipv4.address);
result = b->net.ipv4.prefixlength - a->net.ipv4.prefixlength;
if(result)
return result;
result = a->net.ipv4.prefixlength - b->net.ipv4.prefixlength;
result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
if(result)
return result;
result = a->weight - b->weight;
if(result || !a->owner || !b->owner)
return result;
@ -72,12 +99,17 @@ static int subnet_compare_ipv6(const subnet_t *a, const subnet_t *b)
{
int result;
result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof a->net.ipv6.address);
result = b->net.ipv6.prefixlength - a->net.ipv6.prefixlength;
if(result)
return result;
result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
result = a->net.ipv6.prefixlength - b->net.ipv6.prefixlength;
if(result)
return result;
result = a->weight - b->weight;
if(result || !a->owner || !b->owner)
return result;
@ -118,6 +150,8 @@ void init_subnets(void)
cp();
subnet_tree = splay_alloc_tree((splay_compare_t) subnet_compare, (splay_action_t) free_subnet);
subnet_cache_flush();
}
void exit_subnets(void)
@ -167,6 +201,8 @@ void subnet_add(node_t *n, subnet_t *subnet)
splay_insert(subnet_tree, subnet);
splay_insert(n->subnet_tree, subnet);
subnet_cache_flush();
}
void subnet_del(node_t *n, subnet_t *subnet)
@ -175,6 +211,8 @@ void subnet_del(node_t *n, subnet_t *subnet)
splay_delete(n->subnet_tree, subnet);
splay_delete(subnet_tree, subnet);
subnet_cache_flush();
}
/* Ascii representation of subnets */
@ -183,16 +221,18 @@ bool str2net(subnet_t *subnet, const char *subnetstr)
{
int i, l;
uint16_t x[8];
int weight = 10;
cp();
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d",
&x[0], &x[1], &x[2], &x[3], &l) == 5) {
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d#%d",
&x[0], &x[1], &x[2], &x[3], &l, &weight) >= 5) {
if(l < 0 || l > 32)
return false;
subnet->type = SUBNET_IPV4;
subnet->net.ipv4.prefixlength = l;
subnet->weight = weight;
for(i = 0; i < 4; i++) {
if(x[i] > 255)
@ -203,14 +243,15 @@ bool str2net(subnet_t *subnet, const char *subnetstr)
return true;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d#%d",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
&l) == 9) {
&l, &weight) >= 9) {
if(l < 0 || l > 128)
return false;
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.prefixlength = l;
subnet->weight = weight;
for(i = 0; i < 8; i++)
subnet->net.ipv6.address.x[i] = htons(x[i]);
@ -218,9 +259,10 @@ bool str2net(subnet_t *subnet, const char *subnetstr)
return true;
}
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu", &x[0], &x[1], &x[2], &x[3]) == 4) {
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu#%d", &x[0], &x[1], &x[2], &x[3], &weight) >= 4) {
subnet->type = SUBNET_IPV4;
subnet->net.ipv4.prefixlength = 32;
subnet->weight = weight;
for(i = 0; i < 4; i++) {
if(x[i] > 255)
@ -231,10 +273,11 @@ bool str2net(subnet_t *subnet, const char *subnetstr)
return true;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8) {
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx#%d",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], &weight) >= 8) {
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.prefixlength = 128;
subnet->weight = weight;
for(i = 0; i < 8; i++)
subnet->net.ipv6.address.x[i] = htons(x[i]);
@ -242,9 +285,10 @@ bool str2net(subnet_t *subnet, const char *subnetstr)
return true;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6) {
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx#%d",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &weight) >= 6) {
subnet->type = SUBNET_MAC;
subnet->weight = weight;
for(i = 0; i < 6; i++)
subnet->net.mac.address.x[i] = x[i];
@ -266,24 +310,28 @@ 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",
snprintf(netstr, len, "%hx:%hx:%hx:%hx:%hx:%hx#%d",
subnet->net.mac.address.x[0],
subnet->net.mac.address.x[1],
subnet->net.mac.address.x[2],
subnet->net.mac.address.x[3],
subnet->net.mac.address.x[4], subnet->net.mac.address.x[5]);
subnet->net.mac.address.x[4],
subnet->net.mac.address.x[5],
subnet->weight);
break;
case SUBNET_IPV4:
snprintf(netstr, len, "%hu.%hu.%hu.%hu/%d",
snprintf(netstr, len, "%hu.%hu.%hu.%hu/%d#%d",
subnet->net.ipv4.address.x[0],
subnet->net.ipv4.address.x[1],
subnet->net.ipv4.address.x[2],
subnet->net.ipv4.address.x[3], subnet->net.ipv4.prefixlength);
subnet->net.ipv4.address.x[3],
subnet->net.ipv4.prefixlength,
subnet->weight);
break;
case SUBNET_IPV6:
snprintf(netstr, len, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
snprintf(netstr, len, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d#%d",
ntohs(subnet->net.ipv6.address.x[0]),
ntohs(subnet->net.ipv6.address.x[1]),
ntohs(subnet->net.ipv6.address.x[2]),
@ -292,7 +340,8 @@ bool net2str(char *netstr, int len, const subnet_t *subnet)
ntohs(subnet->net.ipv6.address.x[5]),
ntohs(subnet->net.ipv6.address.x[6]),
ntohs(subnet->net.ipv6.address.x[7]),
subnet->net.ipv6.prefixlength);
subnet->net.ipv6.prefixlength,
subnet->weight);
break;
default:
@ -332,80 +381,96 @@ subnet_t *lookup_subnet_mac(const mac_t *address)
subnet_t *lookup_subnet_ipv4(const ipv4_t *address)
{
subnet_t *p, subnet = {0};
subnet_t *p, *r = NULL, subnet = {0};
splay_node_t *n;
int i;
cp();
// Check if this address is cached
for(i = 0; i < 2; i++) {
if(!cache_ipv4_valid[i])
continue;
if(!memcmp(address, &cache_ipv4_address[i], sizeof *address))
return cache_ipv4_subnet[i];
}
// Search all subnets for a matching one
subnet.type = SUBNET_IPV4;
subnet.net.ipv4.address = *address;
subnet.net.ipv4.prefixlength = 32;
subnet.owner = NULL;
do {
/* Go find subnet */
for(n = subnet_tree->head; n; n = n->next) {
p = n->data;
if(!p || p->type != subnet.type)
continue;
p = splay_search_closest_smaller(subnet_tree, &subnet);
/* Check if the found subnet REALLY matches */
if(p) {
if(p->type != SUBNET_IPV4) {
p = NULL;
if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) {
r = p;
if(p->owner->status.reachable)
break;
}
if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength))
break;
else {
/* Otherwise, see if there is a bigger enclosing subnet */
subnet.net.ipv4.prefixlength = p->net.ipv4.prefixlength - 1;
if(subnet.net.ipv4.prefixlength < 0 || subnet.net.ipv4.prefixlength > 32)
return NULL;
maskcpy(&subnet.net.ipv4.address, &p->net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof subnet.net.ipv4.address);
}
}
} while(p);
}
return p;
// Cache the result
cache_ipv4_slot = !cache_ipv4_slot;
memcpy(&cache_ipv4_address[cache_ipv4_slot], address, sizeof *address);
cache_ipv4_subnet[cache_ipv4_slot] = r;
cache_ipv4_valid[cache_ipv4_slot] = true;
return r;
}
subnet_t *lookup_subnet_ipv6(const ipv6_t *address)
{
subnet_t *p, subnet = {0};
subnet_t *p, *r = NULL, subnet = {0};
splay_node_t *n;
int i;
cp();
// Check if this address is cached
for(i = 0; i < 2; i++) {
if(!cache_ipv6_valid[i])
continue;
if(!memcmp(address, &cache_ipv6_address[i], sizeof *address))
return cache_ipv6_subnet[i];
}
// Search all subnets for a matching one
subnet.type = SUBNET_IPV6;
subnet.net.ipv6.address = *address;
subnet.net.ipv6.prefixlength = 128;
subnet.owner = NULL;
do {
/* Go find subnet */
for(n = subnet_tree->head; n; n = n->next) {
p = n->data;
if(!p || p->type != subnet.type)
continue;
p = splay_search_closest_smaller(subnet_tree, &subnet);
/* Check if the found subnet REALLY matches */
if(p) {
if(p->type != SUBNET_IPV6)
return NULL;
if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength))
if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) {
r = p;
if(p->owner->status.reachable)
break;
else {
/* Otherwise, see if there is a bigger enclosing subnet */
subnet.net.ipv6.prefixlength = p->net.ipv6.prefixlength - 1;
if(subnet.net.ipv6.prefixlength < 0 || subnet.net.ipv6.prefixlength > 128)
return NULL;
maskcpy(&subnet.net.ipv6.address, &p->net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof subnet.net.ipv6.address);
}
}
} while(p);
}
return p;
// Cache the result
cache_ipv6_slot = !cache_ipv6_slot;
memcpy(&cache_ipv6_address[cache_ipv6_slot], address, sizeof *address);
cache_ipv6_subnet[cache_ipv6_slot] = r;
cache_ipv6_valid[cache_ipv6_slot] = true;
return r;
}
void subnet_update(node_t *owner, subnet_t *subnet, bool up) {

View file

@ -1,6 +1,6 @@
/*
subnet.h -- header for subnet.c
Copyright (C) 2000-2006 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2009 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -53,6 +53,7 @@ typedef struct subnet_t {
subnet_type_t type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */
time_t expires; /* expiry time */
int weight; /* weight (higher value is higher priority) */
/* And now for the actual subnet: */
@ -82,5 +83,6 @@ extern subnet_t *lookup_subnet_mac(const mac_t *);
extern subnet_t *lookup_subnet_ipv4(const ipv4_t *);
extern subnet_t *lookup_subnet_ipv6(const ipv6_t *);
extern int dump_subnets(struct evbuffer *);
extern void subnet_cache_flush(void);
#endif /* __TINC_SUBNET_H__ */

View file

@ -1,7 +1,7 @@
/*
tincd.c -- the main file for tincd
Copyright (C) 1998-2005 Ivo Timmermans
2000-2007 Guus Sliepen <guus@tinc-vpn.org>
2000-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
@ -229,6 +229,14 @@ static void make_names(void)
}
}
static void free_names() {
if (identname) free(identname);
if (netname) free(netname);
if (controlsocketname) free(controlsocketname);
if (logfilename) free(logfilename);
if (confbase) free(confbase);
}
int main(int argc, char **argv)
{
program_name = argv[0];
@ -245,7 +253,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-2007 Ivo Timmermans, Guus Sliepen and others.\n"
printf(_("Copyright (C) 1998-2009 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"
@ -331,11 +339,11 @@ int main2(int argc, char **argv)
/* Shutdown properly. */
close_network_connections();
ifdebug(CONNECTIONS)
dump_device_stats();
close_network_connections();
end:
logger(LOG_NOTICE, _("Terminating"));

View file

@ -1,7 +1,7 @@
/*
device.c -- UML network socket
Copyright (C) 2002-2005 Ivo Timmermans,
2002-2006 Guus Sliepen <guus@tinc-vpn.org>
2002-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
@ -36,9 +36,9 @@ static int request_fd = -1;
static int data_fd = -1;
static int write_fd = -1;
static int state = 0;
char *device;
char *device = NULL;
char *iface = NULL;
char *device_info;
static char *device_info;
extern char *identname;
extern bool running;
@ -169,6 +169,9 @@ void close_device(void) {
close(write_fd);
unlink(device);
free(device);
if(iface) free(iface);
}
bool read_packet(vpn_packet_t *packet) {