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:
commit
08aabbf931
34 changed files with 601 additions and 326 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
18
src/net.h
18
src/net.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
54
src/route.c
54
src/route.c
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
197
src/subnet.c
197
src/subnet.c
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
16
src/tincd.c
16
src/tincd.c
|
|
@ -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"));
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue