Import Upstream version 1.0.21
This commit is contained in:
parent
d131e9a06f
commit
37abcfc1ea
38 changed files with 2387 additions and 11248 deletions
|
|
@ -1,4 +1,4 @@
|
|||
# Makefile.in generated by automake 1.11.5 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.11.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
|
|
|
|||
|
|
@ -29,17 +29,22 @@
|
|||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#ifdef HAVE_TUNEMU
|
||||
#ifdef ENABLE_TUNEMU
|
||||
#include "bsd/tunemu.h"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_DEVICE "/dev/tun0"
|
||||
#define DEFAULT_TUN_DEVICE "/dev/tun0"
|
||||
#if defined(HAVE_FREEBSD) || defined(HAVE_NETBSD)
|
||||
#define DEFAULT_TAP_DEVICE "/dev/tap0"
|
||||
#else
|
||||
#define DEFAULT_TAP_DEVICE "/dev/tun0"
|
||||
#endif
|
||||
|
||||
typedef enum device_type {
|
||||
DEVICE_TYPE_TUN,
|
||||
DEVICE_TYPE_TUNIFHEAD,
|
||||
DEVICE_TYPE_TAP,
|
||||
#ifdef HAVE_TUNEMU
|
||||
#ifdef ENABLE_TUNEMU
|
||||
DEVICE_TYPE_TUNEMU,
|
||||
#endif
|
||||
} device_type_t;
|
||||
|
|
@ -50,7 +55,7 @@ char *iface = NULL;
|
|||
static char *device_info = NULL;
|
||||
static uint64_t device_total_in = 0;
|
||||
static uint64_t device_total_out = 0;
|
||||
#if defined(TUNEMU)
|
||||
#if defined(ENABLE_TUNEMU)
|
||||
static device_type_t device_type = DEVICE_TYPE_TUNEMU;
|
||||
#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
|
||||
static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
|
||||
|
|
@ -61,8 +66,12 @@ static device_type_t device_type = DEVICE_TYPE_TUN;
|
|||
static bool setup_device(void) {
|
||||
char *type;
|
||||
|
||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
|
||||
device = xstrdup(DEFAULT_DEVICE);
|
||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
|
||||
if(routing_mode == RMODE_ROUTER)
|
||||
device = xstrdup(DEFAULT_TUN_DEVICE);
|
||||
else
|
||||
device = xstrdup(DEFAULT_TAP_DEVICE);
|
||||
}
|
||||
|
||||
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
|
||||
iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
|
||||
|
|
@ -70,7 +79,7 @@ static bool setup_device(void) {
|
|||
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
||||
if(!strcasecmp(type, "tun"))
|
||||
/* use default */;
|
||||
#ifdef HAVE_TUNEMU
|
||||
#ifdef ENABLE_TUNEMU
|
||||
else if(!strcasecmp(type, "tunemu"))
|
||||
device_type = DEVICE_TYPE_TUNEMU;
|
||||
#endif
|
||||
|
|
@ -90,7 +99,7 @@ static bool setup_device(void) {
|
|||
}
|
||||
|
||||
switch(device_type) {
|
||||
#ifdef HAVE_TUNEMU
|
||||
#ifdef ENABLE_TUNEMU
|
||||
case DEVICE_TYPE_TUNEMU: {
|
||||
char dynamic_name[256] = "";
|
||||
device_fd = tunemu_open(dynamic_name);
|
||||
|
|
@ -167,7 +176,7 @@ static bool setup_device(void) {
|
|||
|
||||
#endif
|
||||
break;
|
||||
#ifdef HAVE_TUNEMU
|
||||
#ifdef ENABLE_TUNEMU
|
||||
case DEVICE_TYPE_TUNEMU:
|
||||
device_info = "BSD tunemu device";
|
||||
break;
|
||||
|
|
@ -181,7 +190,7 @@ static bool setup_device(void) {
|
|||
|
||||
static void close_device(void) {
|
||||
switch(device_type) {
|
||||
#ifdef HAVE_TUNEMU
|
||||
#ifdef ENABLE_TUNEMU
|
||||
case DEVICE_TYPE_TUNEMU:
|
||||
tunemu_close(device_fd);
|
||||
break;
|
||||
|
|
@ -199,7 +208,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
|
||||
switch(device_type) {
|
||||
case DEVICE_TYPE_TUN:
|
||||
#ifdef HAVE_TUNEMU
|
||||
#ifdef ENABLE_TUNEMU
|
||||
case DEVICE_TYPE_TUNEMU:
|
||||
if(device_type == DEVICE_TYPE_TUNEMU)
|
||||
lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14);
|
||||
|
|
@ -229,6 +238,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
return false;
|
||||
}
|
||||
|
||||
memset(packet->data, 0, 12);
|
||||
packet->len = lenin + 14;
|
||||
break;
|
||||
|
||||
|
|
@ -260,6 +270,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
return false;
|
||||
}
|
||||
|
||||
memset(packet->data, 0, 12);
|
||||
packet->len = lenin + 10;
|
||||
break;
|
||||
}
|
||||
|
|
@ -336,7 +347,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
|||
}
|
||||
break;
|
||||
|
||||
#ifdef HAVE_TUNEMU
|
||||
#ifdef ENABLE_TUNEMU
|
||||
case DEVICE_TYPE_TUNEMU:
|
||||
if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) {
|
||||
logger(LOG_ERR, "Error while writing to %s %s: %s", device_info,
|
||||
|
|
|
|||
|
|
@ -73,6 +73,15 @@ void free_connection_partially(connection_t *c) {
|
|||
c->hischallenge = NULL;
|
||||
c->outbuf = NULL;
|
||||
|
||||
c->status.pinged = false;
|
||||
c->status.active = false;
|
||||
c->status.connecting = false;
|
||||
c->status.timeout = false;
|
||||
c->status.encryptout = false;
|
||||
c->status.decryptin = false;
|
||||
c->status.mst = false;
|
||||
|
||||
c->options = 0;
|
||||
c->buflen = 0;
|
||||
c->reqlen = 0;
|
||||
c->tcplen = 0;
|
||||
|
|
@ -80,6 +89,8 @@ void free_connection_partially(connection_t *c) {
|
|||
c->outbuflen = 0;
|
||||
c->outbufsize = 0;
|
||||
c->outbufstart = 0;
|
||||
c->last_ping_time = 0;
|
||||
c->last_flushed_time = 0;
|
||||
|
||||
if(c->inctx) {
|
||||
EVP_CIPHER_CTX_cleanup(c->inctx);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ typedef struct connection_status_t {
|
|||
unsigned int pinged:1; /* sent ping */
|
||||
unsigned int active:1; /* 1 if active.. */
|
||||
unsigned int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
|
||||
unsigned int termreq:1; /* the termination of this connection was requested */
|
||||
unsigned int unused_termreq:1; /* the termination of this connection was requested */
|
||||
unsigned int remove:1; /* Set to 1 if you want this connection removed */
|
||||
unsigned int timeout:1; /* 1 if gotten timeout */
|
||||
unsigned int encryptout:1; /* 1 if we can encrypt outgoing traffic */
|
||||
|
|
|
|||
17
src/graph.c
17
src/graph.c
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
graph.c -- graph algorithms
|
||||
Copyright (C) 2001-2012 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
2001-2005 Ivo Timmermans
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
|
@ -287,10 +287,13 @@ static void sssp_bfs(void) {
|
|||
|
||||
subnet_update(n, NULL, n->status.reachable);
|
||||
|
||||
if(!n->status.reachable)
|
||||
if(!n->status.reachable) {
|
||||
update_node_udp(n, NULL);
|
||||
else if(n->connection)
|
||||
memset(&n->status, 0, sizeof n->status);
|
||||
n->options = 0;
|
||||
} else if(n->connection) {
|
||||
send_ans_key(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -315,7 +318,7 @@ void dump_graph(void) {
|
|||
node_t *n;
|
||||
edge_t *e;
|
||||
char *filename = NULL, *tmpname = NULL;
|
||||
FILE *file;
|
||||
FILE *file, *pipe = NULL;
|
||||
|
||||
if(!graph_changed || !get_config_string(lookup_config(config_tree, "GraphDumpFile"), &filename))
|
||||
return;
|
||||
|
|
@ -325,7 +328,7 @@ void dump_graph(void) {
|
|||
ifdebug(PROTOCOL) logger(LOG_NOTICE, "Dumping graph");
|
||||
|
||||
if(filename[0] == '|') {
|
||||
file = popen(filename + 1, "w");
|
||||
file = pipe = popen(filename + 1, "w");
|
||||
} else {
|
||||
xasprintf(&tmpname, "%s.new", filename);
|
||||
file = fopen(tmpname, "w");
|
||||
|
|
@ -353,8 +356,8 @@ void dump_graph(void) {
|
|||
|
||||
fprintf(file, "}\n");
|
||||
|
||||
if(filename[0] == '|') {
|
||||
pclose(file);
|
||||
if(pipe) {
|
||||
pclose(pipe);
|
||||
} else {
|
||||
fclose(file);
|
||||
#ifdef HAVE_MINGW
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
return false;
|
||||
}
|
||||
|
||||
memset(packet->data, 0, 12);
|
||||
packet->len = lenin + 10;
|
||||
break;
|
||||
case DEVICE_TYPE_TAP:
|
||||
|
|
|
|||
44
src/meta.c
44
src/meta.c
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
meta.c -- handle the meta communication
|
||||
Copyright (C) 2000-2009 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
2000-2005 Ivo Timmermans
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
|
||||
|
|
@ -177,15 +177,45 @@ bool receive_meta(connection_t *c) {
|
|||
|
||||
if(c->tcplen) {
|
||||
if(c->tcplen <= c->buflen) {
|
||||
if(proxytype == PROXY_SOCKS4 && c->allow_request == ID) {
|
||||
if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) {
|
||||
logger(LOG_DEBUG, "Proxy request granted");
|
||||
if(!c->node) {
|
||||
if(c->outgoing && proxytype == PROXY_SOCKS4 && c->allow_request == ID) {
|
||||
if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) {
|
||||
logger(LOG_DEBUG, "Proxy request granted");
|
||||
} else {
|
||||
logger(LOG_ERR, "Proxy request rejected");
|
||||
return false;
|
||||
}
|
||||
} else if(c->outgoing && proxytype == PROXY_SOCKS5 && c->allow_request == ID) {
|
||||
if(c->buffer[0] != 5) {
|
||||
logger(LOG_ERR, "Invalid response from proxy server");
|
||||
return false;
|
||||
}
|
||||
if(c->buffer[1] == (char)0xff) {
|
||||
logger(LOG_ERR, "Proxy request rejected: unsuitable authentication method");
|
||||
return false;
|
||||
}
|
||||
if(c->buffer[2] != 5) {
|
||||
logger(LOG_ERR, "Invalid response from proxy server");
|
||||
return false;
|
||||
}
|
||||
if(c->buffer[3] == 0) {
|
||||
logger(LOG_DEBUG, "Proxy request granted");
|
||||
} else {
|
||||
logger(LOG_DEBUG, "Proxy request rejected");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
logger(LOG_ERR, "Proxy request rejected");
|
||||
logger(LOG_ERR, "c->tcplen set but c->node is NULL!");
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
if(c->allow_request == ALL) {
|
||||
receive_tcppacket(c, c->buffer, c->tcplen);
|
||||
} else {
|
||||
logger(LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname);
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
receive_tcppacket(c, c->buffer, c->tcplen);
|
||||
}
|
||||
|
||||
c->buflen -= c->tcplen;
|
||||
lenin -= c->tcplen - oldlen;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- Interaction with Windows tap driver in a MinGW environment
|
||||
Copyright (C) 2002-2005 Ivo Timmermans,
|
||||
2002-2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2002-2013 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
|
||||
|
|
@ -46,7 +46,7 @@ extern char *myport;
|
|||
|
||||
static DWORD WINAPI tapreader(void *bla) {
|
||||
int status;
|
||||
long len;
|
||||
DWORD len;
|
||||
OVERLAPPED overlapped;
|
||||
vpn_packet_t packet;
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ static bool setup_device(void) {
|
|||
char adapterid[1024];
|
||||
char adaptername[1024];
|
||||
char tapname[1024];
|
||||
long len;
|
||||
DWORD len;
|
||||
unsigned long status;
|
||||
|
||||
bool found = false;
|
||||
|
|
@ -122,7 +122,7 @@ static bool setup_device(void) {
|
|||
continue;
|
||||
|
||||
len = sizeof(adaptername);
|
||||
err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len);
|
||||
err = RegQueryValueEx(key2, "Name", 0, 0, (LPBYTE)adaptername, &len);
|
||||
|
||||
RegCloseKey(key2);
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
long lenout;
|
||||
DWORD lenout;
|
||||
OVERLAPPED overlapped = {0};
|
||||
|
||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- multicast socket
|
||||
Copyright (C) 2002-2005 Ivo Timmermans,
|
||||
2002-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2002-2013 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
|
||||
|
|
@ -158,7 +158,7 @@ static void close_device(void) {
|
|||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int lenin;
|
||||
|
||||
if((lenin = recv(device_fd, packet->data, MTU, 0)) <= 0) {
|
||||
if((lenin = recv(device_fd, (void *)packet->data, MTU, 0)) <= 0) {
|
||||
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info,
|
||||
device, strerror(errno));
|
||||
return false;
|
||||
|
|
@ -184,7 +184,7 @@ static bool write_packet(vpn_packet_t *packet) {
|
|||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
packet->len, device_info);
|
||||
|
||||
if(sendto(device_fd, packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
if(sendto(device_fd, (void *)packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device,
|
||||
strerror(errno));
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net_packet.c -- Handles in- and outgoing VPN packets
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2010 Timothy Redaelli <timothy@redaelli.eu>
|
||||
2010 Brandon Black <blblack@gmail.com>
|
||||
|
||||
|
|
@ -70,11 +70,15 @@ bool localdiscovery = false;
|
|||
mtuprobes == 32: send 1 burst, sleep pingtimeout second
|
||||
mtuprobes == 33: no response from other side, restart PMTU discovery process
|
||||
|
||||
Probes are sent in batches of three, with random sizes between the lower and
|
||||
upper boundaries for the MTU thus far discovered.
|
||||
Probes are sent in batches of at least three, with random sizes between the
|
||||
lower and upper boundaries for the MTU thus far discovered.
|
||||
|
||||
In case local discovery is enabled, a fourth packet is added to each batch,
|
||||
After the initial discovery, a fourth packet is added to each batch with a
|
||||
size larger than the currently known PMTU, to test if the PMTU has increased.
|
||||
|
||||
In case local discovery is enabled, another packet is added to each batch,
|
||||
which will be broadcast to the local network.
|
||||
|
||||
*/
|
||||
|
||||
void send_mtu_probe(node_t *n) {
|
||||
|
|
@ -126,11 +130,16 @@ void send_mtu_probe(node_t *n) {
|
|||
timeout = pingtimeout;
|
||||
}
|
||||
|
||||
for(i = 0; i < 3 + localdiscovery; i++) {
|
||||
if(n->maxmtu <= n->minmtu)
|
||||
for(i = 0; i < 4 + localdiscovery; i++) {
|
||||
if(i == 0) {
|
||||
if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU)
|
||||
continue;
|
||||
len = n->maxmtu + 8;
|
||||
} else if(n->maxmtu <= n->minmtu) {
|
||||
len = n->maxmtu;
|
||||
else
|
||||
} else {
|
||||
len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu);
|
||||
}
|
||||
|
||||
if(len < 64)
|
||||
len = 64;
|
||||
|
|
@ -138,7 +147,7 @@ void send_mtu_probe(node_t *n) {
|
|||
memset(packet.data, 0, 14);
|
||||
RAND_pseudo_bytes(packet.data + 14, len - 14);
|
||||
packet.len = len;
|
||||
if(i >= 3 && n->mtuprobes <= 10)
|
||||
if(i >= 4 && n->mtuprobes <= 10)
|
||||
packet.priority = -1;
|
||||
else
|
||||
packet.priority = 0;
|
||||
|
|
@ -164,6 +173,13 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
|
|||
send_udppacket(n, packet);
|
||||
} else {
|
||||
if(n->mtuprobes > 30) {
|
||||
if (len == n->maxmtu + 8) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname);
|
||||
n->maxmtu = MTU;
|
||||
n->mtuprobes = 10;
|
||||
return;
|
||||
}
|
||||
|
||||
if(n->minmtu)
|
||||
n->mtuprobes = 30;
|
||||
else
|
||||
|
|
@ -378,6 +394,9 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
|||
void receive_tcppacket(connection_t *c, const char *buffer, int len) {
|
||||
vpn_packet_t outpkt;
|
||||
|
||||
if(len > sizeof outpkt.data)
|
||||
return;
|
||||
|
||||
outpkt.len = len;
|
||||
if(c->options & OPTION_TCPONLY)
|
||||
outpkt.priority = 0;
|
||||
|
|
@ -500,17 +519,27 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
|||
struct sockaddr *sa;
|
||||
socklen_t sl;
|
||||
int sock;
|
||||
sockaddr_t broadcast;
|
||||
|
||||
/* Overloaded use of priority field: -1 means local broadcast */
|
||||
|
||||
if(origpriority == -1 && n->prevedge) {
|
||||
struct sockaddr_in in;
|
||||
in.sin_family = AF_INET;
|
||||
in.sin_addr.s_addr = -1;
|
||||
in.sin_port = n->prevedge->address.in.sin_port;
|
||||
sa = (struct sockaddr *)∈
|
||||
sl = sizeof in;
|
||||
sock = 0;
|
||||
sock = rand() % listen_sockets;
|
||||
memset(&broadcast, 0, sizeof broadcast);
|
||||
if(listen_socket[sock].sa.sa.sa_family == AF_INET6) {
|
||||
broadcast.in6.sin6_family = AF_INET6;
|
||||
broadcast.in6.sin6_addr.s6_addr[0x0] = 0xff;
|
||||
broadcast.in6.sin6_addr.s6_addr[0x1] = 0x02;
|
||||
broadcast.in6.sin6_addr.s6_addr[0xf] = 0x01;
|
||||
broadcast.in6.sin6_port = n->prevedge->address.in.sin_port;
|
||||
broadcast.in6.sin6_scope_id = listen_socket[sock].sa.in6.sin6_scope_id;
|
||||
} else {
|
||||
broadcast.in.sin_family = AF_INET;
|
||||
broadcast.in.sin_addr.s_addr = -1;
|
||||
broadcast.in.sin_port = n->prevedge->address.in.sin_port;
|
||||
}
|
||||
sa = &broadcast.sa;
|
||||
sl = SALEN(broadcast.sa);
|
||||
} else {
|
||||
if(origpriority == -1)
|
||||
origpriority = 0;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net_setup.c -- Setup.
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
2010 Brandon Black <blblack@gmail.com>
|
||||
|
||||
|
|
@ -55,7 +55,8 @@ proxytype_t proxytype;
|
|||
|
||||
bool read_rsa_public_key(connection_t *c) {
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
char *pubname;
|
||||
char *hcfname;
|
||||
char *key;
|
||||
|
||||
if(!c->rsa_key) {
|
||||
|
|
@ -66,7 +67,10 @@ bool read_rsa_public_key(connection_t *c) {
|
|||
/* First, check for simple PublicKey statement */
|
||||
|
||||
if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) {
|
||||
BN_hex2bn(&c->rsa_key->n, key);
|
||||
if(BN_hex2bn(&c->rsa_key->n, key) != strlen(key)) {
|
||||
logger(LOG_ERR, "Invalid PublicKey for %s!", c->name);
|
||||
return false;
|
||||
}
|
||||
BN_hex2bn(&c->rsa_key->e, "FFFF");
|
||||
free(key);
|
||||
return true;
|
||||
|
|
@ -74,80 +78,79 @@ bool read_rsa_public_key(connection_t *c) {
|
|||
|
||||
/* Else, check for PublicKeyFile statement and read it */
|
||||
|
||||
if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) {
|
||||
fp = fopen(fname, "r");
|
||||
if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &pubname)) {
|
||||
fp = fopen(pubname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s",
|
||||
fname, strerror(errno));
|
||||
free(fname);
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s", pubname, strerror(errno));
|
||||
free(pubname);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(fname);
|
||||
c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
|
||||
fclose(fp);
|
||||
|
||||
if(c->rsa_key)
|
||||
if(c->rsa_key) {
|
||||
free(pubname);
|
||||
return true; /* Woohoo. */
|
||||
}
|
||||
|
||||
/* If it fails, try PEM_read_RSA_PUBKEY. */
|
||||
fp = fopen(fname, "r");
|
||||
fp = fopen(pubname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s",
|
||||
fname, strerror(errno));
|
||||
free(fname);
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s", pubname, strerror(errno));
|
||||
free(pubname);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(fname);
|
||||
c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL);
|
||||
fclose(fp);
|
||||
|
||||
if(c->rsa_key) {
|
||||
// RSA_blinding_on(c->rsa_key, NULL);
|
||||
free(pubname);
|
||||
return true;
|
||||
}
|
||||
|
||||
logger(LOG_ERR, "Reading RSA public key file `%s' failed: %s",
|
||||
fname, strerror(errno));
|
||||
logger(LOG_ERR, "Reading RSA public key file `%s' failed: %s", pubname, strerror(errno));
|
||||
free(pubname);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Else, check if a harnessed public key is in the config file */
|
||||
|
||||
xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
|
||||
fp = fopen(fname, "r");
|
||||
xasprintf(&hcfname, "%s/hosts/%s", confbase, c->name);
|
||||
fp = fopen(hcfname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno));
|
||||
free(fname);
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s", hcfname, strerror(errno));
|
||||
free(hcfname);
|
||||
return false;
|
||||
}
|
||||
|
||||
c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
|
||||
fclose(fp);
|
||||
free(fname);
|
||||
|
||||
if(c->rsa_key)
|
||||
if(c->rsa_key) {
|
||||
free(hcfname);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Try again with PEM_read_RSA_PUBKEY. */
|
||||
|
||||
xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
|
||||
fp = fopen(fname, "r");
|
||||
fp = fopen(hcfname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno));
|
||||
free(fname);
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s", hcfname, strerror(errno));
|
||||
free(hcfname);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(hcfname);
|
||||
c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL);
|
||||
// RSA_blinding_on(c->rsa_key, NULL);
|
||||
fclose(fp);
|
||||
free(fname);
|
||||
|
||||
if(c->rsa_key)
|
||||
return true;
|
||||
|
|
@ -160,7 +163,6 @@ bool read_rsa_public_key(connection_t *c) {
|
|||
static bool read_rsa_private_key(void) {
|
||||
FILE *fp;
|
||||
char *fname, *key, *pubkey;
|
||||
struct stat s;
|
||||
|
||||
if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
|
||||
if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) {
|
||||
|
|
@ -169,8 +171,14 @@ static bool read_rsa_private_key(void) {
|
|||
}
|
||||
myself->connection->rsa_key = RSA_new();
|
||||
// RSA_blinding_on(myself->connection->rsa_key, NULL);
|
||||
BN_hex2bn(&myself->connection->rsa_key->d, key);
|
||||
BN_hex2bn(&myself->connection->rsa_key->n, pubkey);
|
||||
if(BN_hex2bn(&myself->connection->rsa_key->d, key) != strlen(key)) {
|
||||
logger(LOG_ERR, "Invalid PrivateKey for myself!");
|
||||
return false;
|
||||
}
|
||||
if(BN_hex2bn(&myself->connection->rsa_key->n, pubkey) != strlen(pubkey)) {
|
||||
logger(LOG_ERR, "Invalid PublicKey for myself!");
|
||||
return false;
|
||||
}
|
||||
BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
|
||||
free(key);
|
||||
free(pubkey);
|
||||
|
|
@ -190,6 +198,8 @@ static bool read_rsa_private_key(void) {
|
|||
}
|
||||
|
||||
#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN)
|
||||
struct stat s;
|
||||
|
||||
if(fstat(fileno(fp), &s)) {
|
||||
logger(LOG_ERR, "Could not stat RSA private key file `%s': %s'",
|
||||
fname, strerror(errno));
|
||||
|
|
@ -290,7 +300,7 @@ char *get_name(void) {
|
|||
fprintf(stderr, "Invalid Name: environment variable %s does not exist\n", name + 1);
|
||||
return false;
|
||||
}
|
||||
envname = alloca(32);
|
||||
char envname[32];
|
||||
if(gethostname(envname, 32)) {
|
||||
fprintf(stderr, "Could not get hostname: %s\n", strerror(errno));
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net_socket.c -- Handle various kinds of sockets.
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
2009 Florian Forster <octo@verplant.org>
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ static void configure_tcp(connection_t *c) {
|
|||
unsigned long arg = 1;
|
||||
|
||||
if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) {
|
||||
logger(LOG_ERR, "ioctlsocket for %s: %d", c->hostname, sockstrerror(sockerrno));
|
||||
logger(LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -294,9 +294,6 @@ void retry_outgoing(outgoing_t *outgoing) {
|
|||
void finish_connecting(connection_t *c) {
|
||||
ifdebug(CONNECTIONS) logger(LOG_INFO, "Connected to %s (%s)", c->name, c->hostname);
|
||||
|
||||
if(proxytype != PROXY_EXEC)
|
||||
configure_tcp(c);
|
||||
|
||||
c->last_ping_time = now;
|
||||
|
||||
send_id(c);
|
||||
|
|
@ -419,6 +416,7 @@ begin:
|
|||
goto begin;
|
||||
ifdebug(CONNECTIONS) logger(LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport);
|
||||
c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
configure_tcp(c);
|
||||
}
|
||||
|
||||
if(c->socket == -1) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
process.c -- process management functions
|
||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||
2000-2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2013 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
|
||||
|
|
@ -47,8 +47,6 @@ extern bool use_logfile;
|
|||
static sigset_t emptysigset;
|
||||
#endif
|
||||
|
||||
static int saved_debug_level = -1;
|
||||
|
||||
static void memory_full(int size) {
|
||||
logger(LOG_ERR, "Memory exhausted (couldn't allocate %d bytes), exitting.", size);
|
||||
exit(1);
|
||||
|
|
@ -167,7 +165,7 @@ DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
|
|||
logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_SHUTDOWN");
|
||||
break;
|
||||
default:
|
||||
logger(LOG_WARNING, "Got unexpected request %d", request);
|
||||
logger(LOG_WARNING, "Got unexpected request %d", (int)request);
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
|
@ -187,10 +185,8 @@ DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
|
|||
}
|
||||
|
||||
VOID WINAPI run_service(DWORD argc, LPTSTR* argv) {
|
||||
int err = 1;
|
||||
extern int main2(int argc, char **argv);
|
||||
|
||||
|
||||
status.dwServiceType = SERVICE_WIN32;
|
||||
status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
|
||||
status.dwWin32ExitCode = 0;
|
||||
|
|
@ -201,7 +197,6 @@ VOID WINAPI run_service(DWORD argc, LPTSTR* argv) {
|
|||
|
||||
if (!statushandle) {
|
||||
logger(LOG_ERR, "System call `%s' failed: %s", "RegisterServiceCtrlHandlerEx", winerror(GetLastError()));
|
||||
err = 1;
|
||||
} else {
|
||||
status.dwWaitHint = 30000;
|
||||
status.dwCurrentState = SERVICE_START_PENDING;
|
||||
|
|
@ -211,11 +206,10 @@ VOID WINAPI run_service(DWORD argc, LPTSTR* argv) {
|
|||
status.dwCurrentState = SERVICE_RUNNING;
|
||||
SetServiceStatus(statushandle, &status);
|
||||
|
||||
err = main2(argc, argv);
|
||||
main2(argc, argv);
|
||||
|
||||
status.dwWaitHint = 0;
|
||||
status.dwCurrentState = SERVICE_STOPPED;
|
||||
//status.dwWin32ExitCode = err;
|
||||
SetServiceStatus(statushandle, &status);
|
||||
}
|
||||
|
||||
|
|
@ -358,6 +352,7 @@ bool execute_script(const char *name, char **envp) {
|
|||
int status, len;
|
||||
char *scriptname;
|
||||
int i;
|
||||
char *interpreter = NULL;
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name);
|
||||
|
|
@ -369,14 +364,22 @@ bool execute_script(const char *name, char **envp) {
|
|||
|
||||
scriptname[len - 1] = '\0';
|
||||
|
||||
#ifndef HAVE_TUNEMU
|
||||
/* First check if there is a script */
|
||||
|
||||
if(access(scriptname + 1, F_OK)) {
|
||||
free(scriptname);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Custom scripts interpreter
|
||||
if(get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &interpreter)) {
|
||||
// Force custom scripts interpreter allowing execution of scripts on android without execution flag (such as on /sdcard)
|
||||
free(scriptname);
|
||||
len = xasprintf(&scriptname, "%s \"%s/%s\"", interpreter, confbase, name);
|
||||
free(interpreter);
|
||||
if(len < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
ifdebug(STATUS) logger(LOG_INFO, "Executing script %s", name);
|
||||
|
||||
|
|
@ -404,8 +407,8 @@ bool execute_script(const char *name, char **envp) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef WEXITSTATUS
|
||||
if(status != -1) {
|
||||
#ifdef WEXITSTATUS
|
||||
if(WIFEXITED(status)) { /* Child exited by itself */
|
||||
if(WEXITSTATUS(status)) {
|
||||
logger(LOG_ERR, "Script %s exited with non-zero status %d",
|
||||
|
|
@ -420,11 +423,11 @@ bool execute_script(const char *name, char **envp) {
|
|||
logger(LOG_ERR, "Script %s terminated abnormally", name);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
logger(LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
|
@ -485,6 +488,8 @@ static RETSIGTYPE sighup_handler(int a) {
|
|||
}
|
||||
|
||||
static RETSIGTYPE sigint_handler(int a) {
|
||||
static int saved_debug_level = -1;
|
||||
|
||||
logger(LOG_NOTICE, "Got %s signal", "INT");
|
||||
|
||||
if(saved_debug_level != -1) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
protocol.c -- handle the meta-protocol, basic functions
|
||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2013 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
|
||||
|
|
@ -125,7 +125,7 @@ void forward_request(connection_t *from) {
|
|||
bool receive_request(connection_t *c) {
|
||||
int request;
|
||||
|
||||
if(proxytype == PROXY_HTTP && c->allow_request == ID) {
|
||||
if(c->outgoing && proxytype == PROXY_HTTP && c->allow_request == ID) {
|
||||
if(!c->buffer[0] || c->buffer[0] == '\r')
|
||||
return true;
|
||||
if(!strncasecmp(c->buffer, "HTTP/1.1 ", 9)) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
protocol_auth.c -- handle the meta-protocol, authentication
|
||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2013 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
|
||||
|
|
@ -126,7 +126,7 @@ static bool send_proxyrequest(connection_t *c) {
|
|||
}
|
||||
|
||||
bool send_id(connection_t *c) {
|
||||
if(proxytype)
|
||||
if(proxytype && c->outgoing)
|
||||
if(!send_proxyrequest(c))
|
||||
return false;
|
||||
|
||||
|
|
@ -244,8 +244,8 @@ bool send_metakey(connection_t *c) {
|
|||
*/
|
||||
|
||||
if(RSA_public_encrypt(len, (unsigned char *)c->outkey, (unsigned char *)buffer, c->rsa_key, RSA_NO_PADDING) != len) {
|
||||
logger(LOG_ERR, "Error during encryption of meta key for %s (%s)",
|
||||
c->name, c->hostname);
|
||||
logger(LOG_ERR, "Error during encryption of meta key for %s (%s): %s",
|
||||
c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -308,13 +308,16 @@ bool metakey_h(connection_t *c) {
|
|||
|
||||
/* Convert the challenge from hexadecimal back to binary */
|
||||
|
||||
hex2bin(buffer, buffer, len);
|
||||
if(!hex2bin(buffer, buffer, len)) {
|
||||
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "METAKEY", c->name, c->hostname, "invalid key");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Decrypt the meta key */
|
||||
|
||||
if(RSA_private_decrypt(len, (unsigned char *)buffer, (unsigned char *)c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) { /* See challenge() */
|
||||
logger(LOG_ERR, "Error during decryption of meta key for %s (%s)",
|
||||
c->name, c->hostname);
|
||||
logger(LOG_ERR, "Error during decryption of meta key for %s (%s): %s",
|
||||
c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -426,7 +429,10 @@ bool challenge_h(connection_t *c) {
|
|||
|
||||
/* Convert the challenge from hexadecimal back to binary */
|
||||
|
||||
hex2bin(buffer, c->mychallenge, len);
|
||||
if(!hex2bin(buffer, c->mychallenge, len)) {
|
||||
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHALLENGE", c->name, c->hostname, "invalid challenge");
|
||||
return false;
|
||||
}
|
||||
|
||||
c->allow_request = CHAL_REPLY;
|
||||
|
||||
|
|
@ -480,7 +486,10 @@ bool chal_reply_h(connection_t *c) {
|
|||
|
||||
/* Convert the hash to binary format */
|
||||
|
||||
hex2bin(hishash, hishash, c->outdigest->md_size);
|
||||
if(!hex2bin(hishash, hishash, c->outdigest->md_size)) {
|
||||
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHAL_REPLY", c->name, c->hostname, "invalid hash");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Calculate the hash from the challenge we sent */
|
||||
|
||||
|
|
|
|||
|
|
@ -240,10 +240,16 @@ bool ans_key_h(connection_t *c) {
|
|||
return send_request(to->nexthop->connection, "%s", c->buffer);
|
||||
}
|
||||
|
||||
/* Don't use key material until every check has passed. */
|
||||
from->status.validkey = false;
|
||||
|
||||
/* Update our copy of the origin's packet key */
|
||||
from->outkey = xrealloc(from->outkey, strlen(key) / 2);
|
||||
from->outkeylength = strlen(key) / 2;
|
||||
hex2bin(key, from->outkey, from->outkeylength);
|
||||
if(!hex2bin(key, from->outkey, from->outkeylength)) {
|
||||
logger(LOG_ERR, "Got bad %s from %s(%s): %s", "ANS_KEY", from->name, from->hostname, "invalid key");
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check and lookup cipher and digest algorithms */
|
||||
|
||||
|
|
|
|||
112
src/route.c
112
src/route.c
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
route.c -- routing
|
||||
Copyright (C) 2000-2005 Ivo Timmermans,
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2013 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
|
||||
|
|
@ -110,15 +110,22 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
|
|||
mtu = via->mtu;
|
||||
|
||||
/* Find TCP header */
|
||||
int start = 0;
|
||||
int start = ether_size;
|
||||
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
||||
|
||||
if(type == ETH_P_IP && packet->data[23] == 6)
|
||||
start = 14 + (packet->data[14] & 0xf) * 4;
|
||||
else if(type == ETH_P_IPV6 && packet->data[20] == 6)
|
||||
start = 14 + 40;
|
||||
if(type == ETH_P_8021Q) {
|
||||
start += 4;
|
||||
type = packet->data[16] << 8 | packet->data[17];
|
||||
}
|
||||
|
||||
if(!start || packet->len <= start + 20)
|
||||
if(type == ETH_P_IP && packet->data[start + 9] == 6)
|
||||
start += (packet->data[start] & 0xf) * 4;
|
||||
else if(type == ETH_P_IPV6 && packet->data[start + 6] == 6)
|
||||
start += 40;
|
||||
else
|
||||
return;
|
||||
|
||||
if(packet->len <= start + 20)
|
||||
return;
|
||||
|
||||
/* Use data offset field to calculate length of options field */
|
||||
|
|
@ -244,7 +251,7 @@ void age_subnets(void) {
|
|||
|
||||
/* RFC 792 */
|
||||
|
||||
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) {
|
||||
static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
||||
struct ip ip = {0};
|
||||
struct icmp icmp = {0};
|
||||
|
||||
|
|
@ -317,7 +324,7 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t
|
|||
|
||||
/* RFC 791 */
|
||||
|
||||
static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet) {
|
||||
static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t ether_size) {
|
||||
struct ip ip;
|
||||
vpn_packet_t fragment;
|
||||
int len, maxlen, todo;
|
||||
|
|
@ -333,7 +340,7 @@ static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet) {
|
|||
todo = ntohs(ip.ip_len) - ip_size;
|
||||
|
||||
if(ether_size + ip_size + todo != packet->len) {
|
||||
ifdebug(TRAFFIC) logger(LOG_WARNING, "Length of packet (%d) doesn't match length in IPv4 header (%zd)", packet->len, ether_size + ip_size + todo);
|
||||
ifdebug(TRAFFIC) logger(LOG_WARNING, "Length of packet (%d) doesn't match length in IPv4 header (%d)", packet->len, (int)(ether_size + ip_size + todo));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -381,7 +388,7 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
dest.x[2],
|
||||
dest.x[3]);
|
||||
|
||||
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN);
|
||||
route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -391,10 +398,10 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
if(!subnet->owner->status.reachable)
|
||||
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
|
||||
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
|
||||
|
||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
||||
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
||||
|
||||
if(priorityinheritance)
|
||||
packet->priority = packet->data[15];
|
||||
|
|
@ -407,15 +414,15 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
if(directonly && subnet->owner != via)
|
||||
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
||||
return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
|
||||
|
||||
if(via && packet->len > MAX(via->mtu, 590) && via != myself) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
||||
if(packet->data[20] & 0x40) {
|
||||
packet->len = MAX(via->mtu, 590);
|
||||
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
|
||||
route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
|
||||
} else {
|
||||
fragment_ipv4_packet(via, packet);
|
||||
fragment_ipv4_packet(via, packet, ether_size);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -442,7 +449,7 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
|||
|
||||
/* RFC 2463 */
|
||||
|
||||
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) {
|
||||
static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
|
||||
struct ip6_hdr ip6;
|
||||
struct icmp6_hdr icmp6 = {0};
|
||||
uint16_t checksum;
|
||||
|
|
@ -540,7 +547,7 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
ntohs(dest.x[6]),
|
||||
ntohs(dest.x[7]));
|
||||
|
||||
route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR);
|
||||
route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -550,10 +557,10 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
if(!subnet->owner->status.reachable)
|
||||
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
|
||||
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
|
||||
|
||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
||||
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
||||
|
||||
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||
|
||||
|
|
@ -563,12 +570,12 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
if(directonly && subnet->owner != via)
|
||||
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
||||
return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
|
||||
|
||||
if(via && packet->len > MAX(via->mtu, 1294) && via != myself) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
||||
packet->len = MAX(via->mtu, 1294);
|
||||
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
|
||||
route_ipv6_unreachable(source, packet, ether_size, ICMP6_PACKET_TOO_BIG, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -829,6 +836,11 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
|||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||
return;
|
||||
|
||||
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
||||
|
||||
if(priorityinheritance && type == ETH_P_IP && packet->len >= ether_size + ip_size)
|
||||
packet->priority = packet->data[15];
|
||||
|
||||
// Handle packets larger than PMTU
|
||||
|
||||
node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||
|
|
@ -838,18 +850,24 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
|||
|
||||
if(via && packet->len > via->mtu && via != myself) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
|
||||
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
||||
if(type == ETH_P_IP && packet->len > 590) {
|
||||
if(packet->data[20] & 0x40) {
|
||||
length_t ethlen = 14;
|
||||
|
||||
if(type == ETH_P_8021Q) {
|
||||
type = packet->data[16] << 8 | packet->data[17];
|
||||
ethlen += 4;
|
||||
}
|
||||
|
||||
if(type == ETH_P_IP && packet->len > 576 + ethlen) {
|
||||
if(packet->data[6 + ethlen] & 0x40) {
|
||||
packet->len = via->mtu;
|
||||
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
|
||||
route_ipv4_unreachable(source, packet, ethlen, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
|
||||
} else {
|
||||
fragment_ipv4_packet(via, packet);
|
||||
fragment_ipv4_packet(via, packet, ethlen);
|
||||
}
|
||||
return;
|
||||
} else if(type == ETH_P_IPV6 && packet->len > 1294) {
|
||||
} else if(type == ETH_P_IPV6 && packet->len > 1280 + ethlen) {
|
||||
packet->len = via->mtu;
|
||||
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
|
||||
route_ipv6_unreachable(source, packet, ethlen, ICMP6_PACKET_TOO_BIG, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -861,42 +879,48 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
|||
|
||||
static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
||||
length_t ethlen = ether_size;
|
||||
|
||||
if(type == ETH_P_8021Q) {
|
||||
type = packet->data[16] << 8 | packet->data[17];
|
||||
ethlen += 4;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ETH_P_IP:
|
||||
if(!checklength(source, packet, 14 + 32))
|
||||
if(!checklength(source, packet, ethlen + ip_size))
|
||||
return false;
|
||||
|
||||
if(packet->data[22] < 1) {
|
||||
if(packet->data[25] != IPPROTO_ICMP || packet->data[46] != ICMP_TIME_EXCEEDED)
|
||||
route_ipv4_unreachable(source, packet, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
||||
if(packet->data[ethlen + 8] < 1) {
|
||||
if(packet->data[ethlen + 11] != IPPROTO_ICMP || packet->data[ethlen + 32] != ICMP_TIME_EXCEEDED)
|
||||
route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t old = packet->data[22] << 8 | packet->data[23];
|
||||
packet->data[22]--;
|
||||
uint16_t new = packet->data[22] << 8 | packet->data[23];
|
||||
uint16_t old = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9];
|
||||
packet->data[ethlen + 8]--;
|
||||
uint16_t new = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9];
|
||||
|
||||
uint32_t checksum = packet->data[24] << 8 | packet->data[25];
|
||||
uint32_t checksum = packet->data[ethlen + 10] << 8 | packet->data[ethlen + 11];
|
||||
checksum += old + (~new & 0xFFFF);
|
||||
while(checksum >> 16)
|
||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||
packet->data[24] = checksum >> 8;
|
||||
packet->data[25] = checksum & 0xff;
|
||||
packet->data[ethlen + 10] = checksum >> 8;
|
||||
packet->data[ethlen + 11] = checksum & 0xff;
|
||||
|
||||
return true;
|
||||
|
||||
case ETH_P_IPV6:
|
||||
if(!checklength(source, packet, 14 + 40))
|
||||
if(!checklength(source, packet, ethlen + ip6_size))
|
||||
return false;
|
||||
|
||||
if(packet->data[21] < 1) {
|
||||
if(packet->data[20] != IPPROTO_ICMPV6 || packet->data[54] != ICMP6_TIME_EXCEEDED)
|
||||
route_ipv6_unreachable(source, packet, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
||||
if(packet->data[ethlen + 7] < 1) {
|
||||
if(packet->data[ethlen + 6] != IPPROTO_ICMPV6 || packet->data[ethlen + 40] != ICMP6_TIME_EXCEEDED)
|
||||
route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
||||
return false;
|
||||
}
|
||||
|
||||
packet->data[21]--;
|
||||
packet->data[ethlen + 7]--;
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
return false;
|
||||
}
|
||||
|
||||
memset(packet->data, 0, 12);
|
||||
packet->len = lenin + 14;
|
||||
|
||||
device_total_in += packet->len;
|
||||
|
|
|
|||
27
src/tincd.c
27
src/tincd.c
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
tincd.c -- the main file for tincd
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2008 Max Rijevski <maksuf@gmail.com>
|
||||
2009 Michael Tokarev <mjt@tls.msk.ru>
|
||||
2010 Julien Muchembled <jm@jmuchemb.eu>
|
||||
|
|
@ -338,7 +338,7 @@ static bool keygen(int bits) {
|
|||
RSA *rsa_key;
|
||||
FILE *f;
|
||||
char *name = get_name();
|
||||
char *filename;
|
||||
char *pubname, *privname;
|
||||
|
||||
fprintf(stderr, "Generating %d bits keys:\n", bits);
|
||||
rsa_key = RSA_generate_key(bits, 0x10001, indicator, NULL);
|
||||
|
|
@ -349,8 +349,9 @@ static bool keygen(int bits) {
|
|||
} else
|
||||
fprintf(stderr, "Done.\n");
|
||||
|
||||
xasprintf(&filename, "%s/rsa_key.priv", confbase);
|
||||
f = ask_and_open(filename, "private RSA key");
|
||||
xasprintf(&privname, "%s/rsa_key.priv", confbase);
|
||||
f = ask_and_open(privname, "private RSA key");
|
||||
free(privname);
|
||||
|
||||
if(!f)
|
||||
return false;
|
||||
|
|
@ -363,14 +364,14 @@ static bool keygen(int bits) {
|
|||
fputc('\n', f);
|
||||
PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
|
||||
fclose(f);
|
||||
free(filename);
|
||||
|
||||
if(name)
|
||||
xasprintf(&filename, "%s/hosts/%s", confbase, name);
|
||||
xasprintf(&pubname, "%s/hosts/%s", confbase, name);
|
||||
else
|
||||
xasprintf(&filename, "%s/rsa_key.pub", confbase);
|
||||
xasprintf(&pubname, "%s/rsa_key.pub", confbase);
|
||||
|
||||
f = ask_and_open(filename, "public RSA key");
|
||||
f = ask_and_open(pubname, "public RSA key");
|
||||
free(pubname);
|
||||
|
||||
if(!f)
|
||||
return false;
|
||||
|
|
@ -378,7 +379,6 @@ static bool keygen(int bits) {
|
|||
fputc('\n', f);
|
||||
PEM_write_RSAPublicKey(f, rsa_key);
|
||||
fclose(f);
|
||||
free(filename);
|
||||
free(name);
|
||||
|
||||
return true;
|
||||
|
|
@ -391,7 +391,7 @@ static void make_names(void) {
|
|||
#ifdef HAVE_MINGW
|
||||
HKEY key;
|
||||
char installdir[1024] = "";
|
||||
long len = sizeof(installdir);
|
||||
DWORD len = sizeof(installdir);
|
||||
#endif
|
||||
|
||||
if(netname)
|
||||
|
|
@ -401,7 +401,7 @@ static void make_names(void) {
|
|||
|
||||
#ifdef HAVE_MINGW
|
||||
if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) {
|
||||
if(!RegQueryValueEx(key, NULL, 0, 0, installdir, &len)) {
|
||||
if(!RegQueryValueEx(key, NULL, 0, 0, (LPBYTE)installdir, &len)) {
|
||||
if(!logfilename)
|
||||
xasprintf(&logfilename, "%s/log/%s.log", identname);
|
||||
if(!confbase) {
|
||||
|
|
@ -467,8 +467,11 @@ static bool drop_privs() {
|
|||
"initgroups", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#ifndef __ANDROID__
|
||||
// Not supported in android NDK
|
||||
endgrent();
|
||||
endpwent();
|
||||
#endif
|
||||
}
|
||||
if (do_chroot) {
|
||||
tzset(); /* for proper timestamps in logs */
|
||||
|
|
@ -510,7 +513,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-2012 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||
printf("Copyright (C) 1998-2013 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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue