Import Upstream version 1.0.12

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:39 +02:00
parent 23bd9e9d53
commit c54d214bf2
33 changed files with 751 additions and 271 deletions

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.11 from Makefile.am.
# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,

View file

@ -1,6 +1,6 @@
/*
connection.h -- header for connection.c
Copyright (C) 2000-2009 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2010 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -29,6 +29,7 @@
#define OPTION_INDIRECT 0x0001
#define OPTION_TCPONLY 0x0002
#define OPTION_PMTU_DISCOVERY 0x0004
#define OPTION_CLAMP_MSS 0x0008
typedef struct connection_status_t {
int pinged:1; /* sent ping */

View file

@ -1,6 +1,6 @@
/*
graph.c -- graph algorithms
Copyright (C) 2001-2009 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2001-2010 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -53,6 +53,7 @@
#include "netutl.h"
#include "node.h"
#include "process.h"
#include "protocol.h"
#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
@ -251,7 +252,7 @@ void sssp_bfs(void) {
/* TODO: only clear status.validkey if node is unreachable? */
n->status.validkey = false;
n->status.waitingforkey = false;
n->last_req_key = 0;
n->maxmtu = MTU;
n->minmtu = 0;
@ -286,6 +287,11 @@ void sssp_bfs(void) {
free(envp[i]);
subnet_update(n, NULL, n->status.reachable);
if(!n->status.reachable)
update_node_udp(n, NULL);
else if(n->connection)
send_ans_key(n);
}
}
}

View file

@ -1,7 +1,7 @@
/*
net.c -- most of the network code
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2010 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
This program is free software; you can redistribute it and/or modify
@ -374,11 +374,10 @@ int main_loop(void) {
dump_connections();
return 1;
}
continue;
}
check_network_activity(&readset, &writeset);
if(r > 0)
check_network_activity(&readset, &writeset);
if(do_purge) {
purge();
@ -418,8 +417,13 @@ int main_loop(void) {
}
if(sigalrm) {
avl_node_t *node;
logger(LOG_INFO, "Flushing event queue");
expire_events();
for(node = connection_tree->head; node; node = node->next) {
connection_t *c = node->data;
send_ping(c);
}
sigalrm = false;
}

View file

@ -1,7 +1,7 @@
/*
net_packet.c -- Handles in- and outgoing VPN packets
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2010 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
@ -353,10 +353,10 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
"No valid key known yet for %s (%s), forwarding via TCP",
n->name, n->hostname);
if(!n->status.waitingforkey)
if(n->last_req_key + 10 < now) {
send_req_key(n);
n->status.waitingforkey = true;
n->last_req_key = now;
}
send_tcppacket(n->nexthop->connection, origpkt);

View file

@ -1,7 +1,7 @@
/*
net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2010 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
This program is free software; you can redistribute it and/or modify
@ -218,8 +218,8 @@ bool setup_myself(void) {
myself->connection = new_connection();
init_configuration(&myself->connection->config_tree);
xasprintf(&myself->hostname, "MYSELF");
xasprintf(&myself->connection->hostname, "MYSELF");
myself->hostname = xstrdup("MYSELF");
myself->connection->hostname = xstrdup("MYSELF");
myself->connection->options = 0;
myself->connection->protocol_version = PROT_CURRENT;
@ -246,8 +246,9 @@ bool setup_myself(void) {
if(!read_rsa_private_key())
return false;
if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
xasprintf(&myport, "655");
if(!get_config_string(lookup_config(config_tree, "Port"), &myport)
&& !get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
myport = xstrdup("655");
/* Read in all the subnets specified in the host configuration file */
@ -296,13 +297,18 @@ bool setup_myself(void) {
} else
routing_mode = RMODE_ROUTER;
// Enable PMTUDiscovery by default if we are in router mode.
choice = routing_mode == RMODE_ROUTER;
choice = true;
get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice);
if(choice)
get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
if(choice)
myself->options |= OPTION_PMTU_DISCOVERY;
choice = true;
get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
get_config_bool(lookup_config(myself->connection->config_tree, "ClampMSS"), &choice);
if(choice)
myself->options |= OPTION_CLAMP_MSS;
get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
#if !defined(SOL_IP) || !defined(IP_TOS)

View file

@ -1,7 +1,7 @@
/*
net_socket.c -- Handle various kinds of sockets.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2010 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2009 Florian Forster <octo@verplant.org>
@ -261,9 +261,13 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = 1;
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
if(sa->sa.sa_family == AF_INET6)
setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, &option, sizeof option);
setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, &option, sizeof option);
#endif
#if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT)
#define IP_DONTFRAGMENT IP_DONTFRAG
#endif
#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
@ -276,6 +280,8 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = 1;
setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, &option, sizeof(option));
}
#else
#warning No way to disable IPv4 fragmentation
#endif
#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
@ -283,6 +289,13 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
option = IPV6_PMTUDISC_DO;
setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, &option, sizeof(option));
}
#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
if(myself->options & OPTION_PMTU_DISCOVERY) {
option = 1;
setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, &option, sizeof(option));
}
#else
#warning No way to disable IPv6 fragmentation
#endif
if (!bind_to_interface(nfd)) {
@ -331,7 +344,7 @@ void finish_connecting(connection_t *c) {
}
void do_outgoing_connection(connection_t *c) {
char *address, *port;
char *address, *port, *space;
int result;
if(!c->outgoing) {
@ -352,8 +365,14 @@ begin:
get_config_string(c->outgoing->cfg, &address);
if(!get_config_string(lookup_config(c->config_tree, "Port"), &port))
xasprintf(&port, "655");
space = strchr(address, ' ');
if(space) {
port = xstrdup(space + 1);
*space = 0;
} else {
if(!get_config_string(lookup_config(c->config_tree, "Port"), &port))
port = xstrdup("655");
}
c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
free(address);

View file

@ -1,6 +1,6 @@
/*
node.h -- header for node.c
Copyright (C) 2001-2009 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2001-2010 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -30,7 +30,7 @@
typedef struct node_status_t {
int unused_active:1; /* 1 if active (not used for nodes) */
int validkey:1; /* 1 if we currently have a valid key for him */
int waitingforkey:1; /* 1 if we already sent out a request */
int unused_waitingforkey:1; /* 1 if we already sent out a request */
int visited:1; /* 1 if this node has been visited by one of the graph algorithms */
int reachable:1; /* 1 if this node is reachable in the graph */
int indirect:1; /* 1 if this node is not directly reachable by us */
@ -45,6 +45,7 @@ typedef struct node_t {
char *hostname; /* the hostname of its real ip */
node_status_t status;
time_t last_req_key;
const EVP_CIPHER *incipher; /* Cipher type for UDP packets received from him */
char *inkey; /* Cipher key and iv */

View file

@ -95,7 +95,7 @@ extern bool send_add_subnet(struct connection_t *, const struct subnet_t *);
extern bool send_del_subnet(struct connection_t *, const struct subnet_t *);
extern bool send_add_edge(struct connection_t *, const struct edge_t *);
extern bool send_del_edge(struct connection_t *, const struct edge_t *);
extern bool send_key_changed();
extern void send_key_changed();
extern bool send_req_key(struct node_t *);
extern bool send_ans_key(struct node_t *);
extern bool send_tcppacket(struct connection_t *, struct vpn_packet_t *);

View file

@ -1,7 +1,7 @@
/*
protocol_auth.c -- handle the meta-protocol, authentication
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2010 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
@ -453,6 +453,11 @@ bool send_ack(connection_t *c) {
if(myself->options & OPTION_PMTU_DISCOVERY)
c->options |= OPTION_PMTU_DISCOVERY;
choice = myself->options & OPTION_CLAMP_MSS;
get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice);
if(choice)
c->options |= OPTION_CLAMP_MSS;
get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options);
@ -496,6 +501,7 @@ bool ack_h(connection_t *c) {
int weight, mtu;
uint32_t options;
node_t *n;
bool choice;
if(sscanf(c->buffer, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) {
logger(LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name,
@ -536,6 +542,13 @@ bool ack_h(connection_t *c) {
if(get_config_int(lookup_config(myself->connection->config_tree, "PMTU"), &mtu) && mtu < n->mtu)
n->mtu = mtu;
if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) {
if(choice)
c->options |= OPTION_CLAMP_MSS;
else
c->options &= ~OPTION_CLAMP_MSS;
}
/* Activate this connection */
c->allow_request = ALL;

View file

@ -1,7 +1,7 @@
/*
protocol_key.c -- handle the meta-protocol, key exchange
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2010 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,15 +36,19 @@
bool mykeyused = false;
bool send_key_changed() {
/* Only send this message if some other daemon requested our key previously.
This reduces unnecessary key_changed broadcasts.
*/
void send_key_changed() {
avl_node_t *node;
connection_t *c;
if(!mykeyused)
return true;
send_request(broadcast, "%d %x %s", KEY_CHANGED, rand(), myself->name);
return send_request(broadcast, "%d %x %s", KEY_CHANGED, rand(), myself->name);
/* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
if(c->status.active && c->node && c->node->status.reachable)
send_ans_key(c->node);
}
}
bool key_changed_h(connection_t *c) {
@ -57,6 +61,11 @@ bool key_changed_h(connection_t *c) {
return false;
}
if(!check_id(name)) {
logger(LOG_ERR, "Got bad %s from %s (%s): %s", "KEY_CHANGED", c->name, c->hostname, "invalid name");
return false;
}
if(seen_request(c->buffer))
return true;
@ -65,11 +74,11 @@ bool key_changed_h(connection_t *c) {
if(!n) {
logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
"KEY_CHANGED", c->name, c->hostname, name);
return false;
return true;
}
n->status.validkey = false;
n->status.waitingforkey = false;
n->last_req_key = 0;
/* Tell the others */
@ -94,12 +103,17 @@ bool req_key_h(connection_t *c) {
return false;
}
if(!check_id(from_name) || !check_id(to_name)) {
logger(LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
return false;
}
from = lookup_node(from_name);
if(!from) {
logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
"REQ_KEY", c->name, c->hostname, from_name);
return false;
return true;
}
to = lookup_node(to_name);
@ -107,7 +121,7 @@ bool req_key_h(connection_t *c) {
if(!to) {
logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
"REQ_KEY", c->name, c->hostname, to_name);
return false;
return true;
}
/* Check if this key request is for us */
@ -116,7 +130,7 @@ bool req_key_h(connection_t *c) {
send_ans_key(from);
} else {
if(tunnelserver)
return false;
return true;
if(!to->status.reachable) {
logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
@ -169,23 +183,30 @@ bool ans_key_h(connection_t *c) {
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
char key[MAX_STRING_SIZE];
char address[MAX_STRING_SIZE] = "";
char port[MAX_STRING_SIZE] = "";
int cipher, digest, maclength, compression;
node_t *from, *to;
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d",
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING,
from_name, to_name, key, &cipher, &digest, &maclength,
&compression) != 7) {
&compression, address, port) < 7) {
logger(LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
c->hostname);
return false;
}
if(!check_id(from_name) || !check_id(to_name)) {
logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
return false;
}
from = lookup_node(from_name);
if(!from) {
logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
"ANS_KEY", c->name, c->hostname, from_name);
return false;
return true;
}
to = lookup_node(to_name);
@ -193,14 +214,14 @@ bool ans_key_h(connection_t *c) {
if(!to) {
logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
"ANS_KEY", c->name, c->hostname, to_name);
return false;
return true;
}
/* Forward it if necessary */
if(to != myself) {
if(tunnelserver)
return false;
return true;
if(!to->status.reachable) {
logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
@ -208,6 +229,16 @@ bool ans_key_h(connection_t *c) {
return true;
}
if(!*address) {
char *address, *port;
ifdebug(PROTOCOL) logger(LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
sockaddr2str(&from->address, &address, &port);
send_request(to->nexthop->connection, "%s %s %s", c->buffer, address, port);
free(address);
free(port);
return true;
}
return send_request(to->nexthop->connection, "%s", c->buffer);
}
@ -218,7 +249,6 @@ bool ans_key_h(connection_t *c) {
from->outkeylength = strlen(key) / 2;
hex2bin(key, from->outkey, from->outkeylength);
from->status.waitingforkey = false;
/* Check and lookup cipher and digest algorithms */
if(cipher) {
@ -227,13 +257,13 @@ bool ans_key_h(connection_t *c) {
if(!from->outcipher) {
logger(LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name,
from->hostname);
return false;
return true;
}
if(from->outkeylength != from->outcipher->key_len + from->outcipher->iv_len) {
logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name,
from->hostname);
return false;
return true;
}
} else {
from->outcipher = NULL;
@ -247,13 +277,13 @@ bool ans_key_h(connection_t *c) {
if(!from->outdigest) {
logger(LOG_ERR, "Node %s (%s) uses unknown digest!", from->name,
from->hostname);
return false;
return true;
}
if(from->outmaclength > from->outdigest->md_size || from->outmaclength < 0) {
logger(LOG_ERR, "Node %s (%s) uses bogus MAC length!",
from->name, from->hostname);
return false;
return true;
}
} else {
from->outdigest = NULL;
@ -261,7 +291,7 @@ bool ans_key_h(connection_t *c) {
if(compression < 0 || compression > 11) {
logger(LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
return false;
return true;
}
from->outcompression = compression;
@ -270,12 +300,18 @@ bool ans_key_h(connection_t *c) {
if(!EVP_EncryptInit_ex(&from->outctx, from->outcipher, NULL, (unsigned char *)from->outkey, (unsigned char *)from->outkey + from->outcipher->key_len)) {
logger(LOG_ERR, "Error during initialisation of key from %s (%s): %s",
from->name, from->hostname, ERR_error_string(ERR_get_error(), NULL));
return false;
return true;
}
from->status.validkey = true;
from->sent_seqno = 0;
if(*address && *port) {
ifdebug(PROTOCOL) logger(LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
sockaddr_t sa = str2sockaddr(address, port);
update_node_udp(from, &sa);
}
if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuprobes)
send_mtu_probe(from);

View file

@ -1,7 +1,7 @@
/*
route.c -- routing
Copyright (C) 2000-2005 Ivo Timmermans,
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2010 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 @@ static const size_t ip6_size = sizeof(struct ip6_hdr);
static const size_t icmp6_size = sizeof(struct icmp6_hdr);
static const size_t ns_size = sizeof(struct nd_neighbor_solicit);
static const size_t opt_size = sizeof(struct nd_opt_hdr);
#define max(a, b) ((a) > (b) ? (a) : (b))
/* RFC 1071 */
@ -92,6 +93,74 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
return true;
}
static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
if(!via || via == myself || !(via->options & OPTION_CLAMP_MSS))
return;
/* Find TCP header */
int start = 0;
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(!start || packet->len <= start + 20)
return;
/* Use data offset field to calculate length of options field */
int len = ((packet->data[start + 12] >> 4) - 5) * 4;
if(packet->len < start + 20 + len)
return;
/* Search for MSS option header */
for(int i = 0; i < len;) {
if(packet->data[start + 20 + i] == 0)
break;
if(packet->data[start + 20 + i] == 1) {
i++;
continue;
}
if(i > len - 2 || i > len - packet->data[start + 21 + i])
break;
if(packet->data[start + 20 + i] != 2) {
if(packet->data[start + 21 + i] < 2)
break;
i += packet->data[start + 21 + i];
continue;
}
if(packet->data[start + 21] != 4)
break;
/* Found it */
uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i];
uint16_t newmss = via->mtu - start - 20;
uint16_t csum = packet->data[start + 16] << 8 | packet->data[start + 17];
if(oldmss <= newmss)
break;
ifdebug(TRAFFIC) logger(LOG_INFO, "Clamping MSS of packet from %s to %s to %d", source->name, via->name, newmss);
/* Update the MSS value and the checksum */
packet->data[start + 22 + i] = newmss >> 8;
packet->data[start + 23 + i] = newmss & 0xff;
csum ^= 0xffff;
csum -= oldmss;
csum += newmss;
csum ^= 0xffff;
packet->data[start + 16] = csum >> 8;
packet->data[start + 17] = csum & 0xff;
break;
}
}
static void swap_mac_addresses(vpn_packet_t *packet) {
mac_t tmp;
memcpy(&tmp, &packet->data[0], sizeof tmp);
@ -104,7 +173,7 @@ static void learn_mac(mac_t *address) {
avl_node_t *node;
connection_t *c;
subnet = lookup_subnet_mac(address);
subnet = lookup_subnet_mac(myself, address);
/* If we don't know this MAC address yet, store it */
@ -119,6 +188,7 @@ static void learn_mac(mac_t *address) {
subnet->net.mac.address = *address;
subnet->weight = 10;
subnet_add(myself, subnet);
subnet_update(myself, subnet, true);
/* And tell all other tinc daemons it's our MAC */
@ -154,6 +224,7 @@ void age_subnets(void) {
send_del_subnet(c, s);
}
subnet_update(myself, s, false);
subnet_del(myself, s);
}
}
@ -315,10 +386,10 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
if(via && packet->len > via->mtu && via != myself) {
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 = via->mtu;
packet->len = max(via->mtu, 590);
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
} else {
fragment_ipv4_packet(via, packet);
@ -327,6 +398,8 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
return;
}
clamp_mss(source, via, packet);
send_packet(subnet->owner, packet);
}
@ -458,13 +531,15 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
if(via && packet->len > via->mtu && via != myself) {
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 = via->mtu;
packet->len = max(via->mtu, 1294);
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
return;
}
clamp_mss(source, via, packet);
send_packet(subnet->owner, packet);
}
@ -705,7 +780,7 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
/* Lookup destination address */
memcpy(&dest, &packet->data[0], sizeof dest);
subnet = lookup_subnet_mac(&dest);
subnet = lookup_subnet_mac(NULL, &dest);
if(!subnet) {
broadcast_packet(source, packet);
@ -724,7 +799,7 @@ 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) {
if(type == ETH_P_IP && packet->len > 590) {
if(packet->data[20] & 0x40) {
packet->len = via->mtu;
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
@ -732,13 +807,15 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
fragment_ipv4_packet(via, packet);
}
return;
} else if(type == ETH_P_IPV6) {
} else if(type == ETH_P_IPV6 && packet->len > 1294) {
packet->len = via->mtu;
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
return;
}
}
clamp_mss(source, via, packet);
send_packet(subnet->owner, packet);
}

View file

@ -1,6 +1,6 @@
/*
subnet.c -- handle subnet lookups and lists
Copyright (C) 2000-2009 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2000-2010 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -329,8 +329,8 @@ subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) {
return avl_search(owner->subnet_tree, subnet);
}
subnet_t *lookup_subnet_mac(const mac_t *address) {
subnet_t *p, *r = NULL, subnet = {0};
subnet_t *lookup_subnet_mac(const node_t *owner, const mac_t *address) {
subnet_t *p, *r = NULL;
avl_node_t *n;
int i;
@ -339,20 +339,18 @@ subnet_t *lookup_subnet_mac(const mac_t *address) {
for(i = 0; i < 2; i++) {
if(!cache_mac_valid[i])
continue;
if(owner && cache_mac_subnet[i] && cache_mac_subnet[i]->owner != owner)
continue;
if(!memcmp(address, &cache_mac_address[i], sizeof *address))
return cache_mac_subnet[i];
}
// Search all subnets for a matching one
subnet.type = SUBNET_MAC;
subnet.net.mac.address = *address;
subnet.owner = NULL;
for(n = subnet_tree->head; n; n = n->next) {
for(n = owner ? owner->subnet_tree->head : subnet_tree->head; n; n = n->next) {
p = n->data;
if(!p || p->type != subnet.type)
if(!p || p->type != SUBNET_MAC)
continue;
if(!memcmp(address, &p->net.mac.address, sizeof *address)) {
@ -373,7 +371,7 @@ subnet_t *lookup_subnet_mac(const mac_t *address) {
}
subnet_t *lookup_subnet_ipv4(const ipv4_t *address) {
subnet_t *p, *r = NULL, subnet = {0};
subnet_t *p, *r = NULL;
avl_node_t *n;
int i;
@ -388,15 +386,10 @@ subnet_t *lookup_subnet_ipv4(const ipv4_t *address) {
// Search all subnets for a matching one
subnet.type = SUBNET_IPV4;
subnet.net.ipv4.address = *address;
subnet.net.ipv4.prefixlength = 32;
subnet.owner = NULL;
for(n = subnet_tree->head; n; n = n->next) {
p = n->data;
if(!p || p->type != subnet.type)
if(!p || p->type != SUBNET_IPV4)
continue;
if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) {
@ -417,7 +410,7 @@ subnet_t *lookup_subnet_ipv4(const ipv4_t *address) {
}
subnet_t *lookup_subnet_ipv6(const ipv6_t *address) {
subnet_t *p, *r = NULL, subnet = {0};
subnet_t *p, *r = NULL;
avl_node_t *n;
int i;
@ -432,15 +425,10 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) {
// Search all subnets for a matching one
subnet.type = SUBNET_IPV6;
subnet.net.ipv6.address = *address;
subnet.net.ipv6.prefixlength = 128;
subnet.owner = NULL;
for(n = subnet_tree->head; n; n = n->next) {
p = n->data;
if(!p || p->type != subnet.type)
if(!p || p->type != SUBNET_IPV6)
continue;
if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) {
@ -490,7 +478,7 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
if(!net2str(netstr, sizeof netstr, subnet))
continue;
// Strip the weight from the subnet, and put it in its own environment variable
char *weight = strchr(netstr + 7, '#');
char *weight = strchr(netstr, '#');
if(weight)
*weight++ = 0;
else
@ -507,9 +495,9 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
execute_script(name, envp);
}
} else {
if(net2str(netstr + 7, sizeof netstr - 7, subnet)) {
if(net2str(netstr, sizeof netstr, subnet)) {
// Strip the weight from the subnet, and put it in its own environment variable
char *weight = strchr(netstr + 7, '#');
char *weight = strchr(netstr, '#');
if(weight)
*weight++ = 0;
else

View file

@ -77,7 +77,7 @@ extern void subnet_update(struct node_t *, subnet_t *, bool);
extern bool net2str(char *, int, const subnet_t *);
extern bool str2net(subnet_t *, const char *);
extern subnet_t *lookup_subnet(const struct node_t *, const subnet_t *);
extern subnet_t *lookup_subnet_mac(const mac_t *);
extern subnet_t *lookup_subnet_mac(const struct node_t *, const mac_t *);
extern subnet_t *lookup_subnet_ipv4(const ipv4_t *);
extern subnet_t *lookup_subnet_ipv6(const ipv6_t *);
extern void dump_subnets(void);

View file

@ -1,7 +1,7 @@
/*
tincd.c -- the main file for tincd
Copyright (C) 1998-2005 Ivo Timmermans
2000-2009 Guus Sliepen <guus@tinc-vpn.org>
2000-2010 Guus Sliepen <guus@tinc-vpn.org>
2008 Max Rijevski <maksuf@gmail.com>
2009 Michael Tokarev <mjt@tls.msk.ru>
@ -500,7 +500,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-2009 Ivo Timmermans, Guus Sliepen and others.\n"
printf("Copyright (C) 1998-2010 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"