Merge branch 'master' into 1.1

Conflicts:
	NEWS
	README
	configure.in
	src/net.c
	src/net.h
This commit is contained in:
Guus Sliepen 2010-04-17 12:21:53 +02:00
commit 79e46d08a4
14 changed files with 96 additions and 25 deletions

16
NEWS
View file

@ -4,6 +4,22 @@ Version 1.1-cvs Work in progress
* Use splay trees instead of AVL trees. * Use splay trees instead of AVL trees.
Version 1.0.14 not released yet
* Fixed reading configuration files that do not end with a newline. Again.
Version 1.0.13 Apr 11 2010
* Allow building tinc without LZO and/or Zlib.
* Clamp MSS of TCP packets in both directions.
* Experimental StrictSubnets, Forwarding and DirectOnly options,
giving more control over information and packets received from/sent to other
nodes.
* Ensure tinc never sends symbolic names for ports over the wire.
Version 1.0.12 Feb 3 2010 Version 1.0.12 Feb 3 2010
* Really allow fast roaming of hosts to other nodes in a switched VPN. * Really allow fast roaming of hosts to other nodes in a switched VPN.

1
THANKS
View file

@ -34,6 +34,7 @@ We would like to thank the following people for their contributions to tinc:
* Scott Lamb * Scott Lamb
* Sven-Haegar Koch * Sven-Haegar Koch
* Teemu Kiviniemi * Teemu Kiviniemi
* Timothy Redaelli
* Tonnerre Lombard * Tonnerre Lombard
* Wessel Dankers * Wessel Dankers
* Wouter van Heyst * Wouter van Heyst

View file

@ -199,13 +199,13 @@ Tinc will expect packets read from the virtual network device
to start with an Ethernet header. to start with an Ethernet header.
.El .El
.It Va DirectOnly Li = yes | no Pq no .It Va DirectOnly Li = yes | no Po no Pc Bq experimental
When this option is enabled, packets that cannot be sent directly to the destination node, When this option is enabled, packets that cannot be sent directly to the destination node,
but which would have to be forwarded by an intermediate node, are dropped instead. but which would have to be forwarded by an intermediate node, are dropped instead.
When combined with the IndirectData option, When combined with the IndirectData option,
packets for nodes for which we do not have a meta connection with are also dropped. packets for nodes for which we do not have a meta connection with are also dropped.
.It Va Forwarding Li = off | internal | kernel Pq internal .It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
This option selects the way indirect packets are forwarded. This option selects the way indirect packets are forwarded.
.Bl -tag -width indent .Bl -tag -width indent

View file

@ -843,14 +843,14 @@ to start with an Ethernet header.
@end table @end table
@cindex DirectOnly @cindex DirectOnly
@item DirectOnly = <yes|no> (no) @item DirectOnly = <yes|no> (no) [experimental]
When this option is enabled, packets that cannot be sent directly to the destination node, When this option is enabled, packets that cannot be sent directly to the destination node,
but which would have to be forwarded by an intermediate node, are dropped instead. but which would have to be forwarded by an intermediate node, are dropped instead.
When combined with the IndirectData option, When combined with the IndirectData option,
packets for nodes for which we do not have a meta connection with are also dropped. packets for nodes for which we do not have a meta connection with are also dropped.
@cindex Forwarding @cindex Forwarding
@item Forwarding = <off|internal|kernel> (internal) @item Forwarding = <off|internal|kernel> (internal) [experimental]
This option selects the way indirect packets are forwarded. This option selects the way indirect packets are forwarded.
@table @asis @table @asis

View file

@ -224,7 +224,7 @@ static char *readline(FILE * fp, char *buf, size_t buflen) {
newline = strchr(p, '\n'); newline = strchr(p, '\n');
if(!newline) if(!newline)
return NULL; return buf;
*newline = '\0'; /* kill newline */ *newline = '\0'; /* kill newline */
if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */ if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */
@ -238,7 +238,6 @@ static char *readline(FILE * fp, char *buf, size_t buflen) {
starting at *base. starting at *base.
*/ */
int read_config_file(splay_tree_t *config_tree, const char *fname) { int read_config_file(splay_tree_t *config_tree, const char *fname) {
int err = -2; /* Parse error */
FILE *fp; FILE *fp;
char buffer[MAX_STRING_SIZE]; char buffer[MAX_STRING_SIZE];
char *line; char *line;

View file

@ -45,6 +45,10 @@
#define ICMP_NET_UNREACH 0 #define ICMP_NET_UNREACH 0
#endif #endif
#ifndef ICMP_NET_ANO
#define ICMP_NET_ANO 9
#endif
#ifndef IP_MSS #ifndef IP_MSS
#define IP_MSS 576 #define IP_MSS 576
#endif #endif

View file

@ -95,6 +95,7 @@ struct icmp6_hdr {
#define ICMP6_DST_UNREACH_NOROUTE 0 #define ICMP6_DST_UNREACH_NOROUTE 0
#define ICMP6_DST_UNREACH 1 #define ICMP6_DST_UNREACH 1
#define ICMP6_PACKET_TOO_BIG 2 #define ICMP6_PACKET_TOO_BIG 2
#define ICMP6_DST_UNREACH_ADMIN 1
#define ICMP6_DST_UNREACH_ADDR 3 #define ICMP6_DST_UNREACH_ADDR 3
#define ND_NEIGHBOR_SOLICIT 135 #define ND_NEIGHBOR_SOLICIT 135
#define ND_NEIGHBOR_ADVERT 136 #define ND_NEIGHBOR_ADVERT 136

View file

@ -270,6 +270,36 @@ int reload_configuration(void) {
last_config_check = time(NULL); last_config_check = time(NULL);
/* If StrictSubnet is set, expire deleted Subnets and read new ones in */
if(strictsubnets) {
subnet_t *subnet;
for(node = subnet_tree->head; node; node = node->next) {
subnet = node->data;
subnet->expires = 1;
}
load_all_subnets();
for(node = subnet_tree->head; node; node = next) {
next = node->next;
subnet = node->data;
if(subnet->expires == 1) {
send_del_subnet(broadcast, subnet);
if(subnet->owner->status.reachable)
subnet_update(subnet->owner, subnet, false);
subnet_del(subnet->owner, subnet);
} else if(subnet->expires == -1) {
subnet->expires = 0;
} else {
send_add_subnet(broadcast, subnet);
if(subnet->owner->status.reachable)
subnet_update(subnet->owner, subnet, true);
}
}
}
/* Try to make outgoing connections */ /* Try to make outgoing connections */
try_outgoing_connections(); try_outgoing_connections();

View file

@ -144,6 +144,7 @@ extern void regenerate_key();
extern void purge(void); extern void purge(void);
extern void retry(void); extern void retry(void);
extern int reload_configuration(void); extern int reload_configuration(void);
extern void load_all_subnets();
#ifndef HAVE_MINGW #ifndef HAVE_MINGW
#define closesocket(s) close(s) #define closesocket(s) close(s)

View file

@ -157,14 +157,14 @@ void regenerate_key() {
/* /*
Read Subnets from all host config files Read Subnets from all host config files
*/ */
static void load_all_subnets(void) { void load_all_subnets(void) {
DIR *dir; DIR *dir;
struct dirent *ent; struct dirent *ent;
char *dname; char *dname;
char *fname; char *fname;
splay_tree_t *config_tree; splay_tree_t *config_tree;
config_t *cfg; config_t *cfg;
subnet_t *s; subnet_t *s, *s2;
node_t *n; node_t *n;
bool result; bool result;
@ -181,9 +181,6 @@ static void load_all_subnets(void) {
continue; continue;
n = lookup_node(ent->d_name); n = lookup_node(ent->d_name);
if(n)
continue;
#ifdef _DIRENT_HAVE_D_TYPE #ifdef _DIRENT_HAVE_D_TYPE
//if(ent->d_type != DT_REG) //if(ent->d_type != DT_REG)
// continue; // continue;
@ -196,15 +193,21 @@ static void load_all_subnets(void) {
if(!result) if(!result)
continue; continue;
n = new_node(); if(!n) {
n->name = xstrdup(ent->d_name); n = new_node();
node_add(n); n->name = xstrdup(ent->d_name);
node_add(n);
}
for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) { for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
if(!get_config_subnet(cfg, &s)) if(!get_config_subnet(cfg, &s))
continue; continue;
subnet_add(n, s); if((s2 = lookup_subnet(n, s))) {
s2->expires = -1;
} else {
subnet_add(n, s);
}
} }
exit_configuration(&config_tree); exit_configuration(&config_tree);
@ -262,6 +265,16 @@ bool setup_myself(void) {
&& !get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport)) && !get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
myport = xstrdup("655"); myport = xstrdup("655");
if(!atoi(myport)) {
struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
sockaddr_t sa;
if(!ai || !ai->ai_addr)
return false;
free(myport);
memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
sockaddr2str(&sa, NULL, &myport);
}
/* Read in all the subnets specified in the host configuration file */ /* Read in all the subnets specified in the host configuration file */
cfg = lookup_config(myself->connection->config_tree, "Subnet"); cfg = lookup_config(myself->connection->config_tree, "Subnet");

View file

@ -102,8 +102,10 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
if(scopeid) if(scopeid)
*scopeid = '\0'; /* Descope. */ *scopeid = '\0'; /* Descope. */
*addrstr = xstrdup(address); if(addrstr)
*portstr = xstrdup(port); *addrstr = xstrdup(address);
if(portstr)
*portstr = xstrdup(port);
} }
char *sockaddr2hostname(const sockaddr_t *sa) { char *sockaddr2hostname(const sockaddr_t *sa) {

View file

@ -401,7 +401,7 @@ static void send_everything(connection_t *c) {
bool ack_h(connection_t *c, char *request) { bool ack_h(connection_t *c, char *request) {
char hisport[MAX_STRING_SIZE]; char hisport[MAX_STRING_SIZE];
char *hisaddress, *dummy; char *hisaddress;
int weight, mtu; int weight, mtu;
uint32_t options; uint32_t options;
node_t *n; node_t *n;
@ -479,10 +479,9 @@ bool ack_h(connection_t *c, char *request) {
c->edge = new_edge(); c->edge = new_edge();
c->edge->from = myself; c->edge->from = myself;
c->edge->to = n; c->edge->to = n;
sockaddr2str(&c->address, &hisaddress, &dummy); sockaddr2str(&c->address, &hisaddress, NULL);
c->edge->address = str2sockaddr(hisaddress, hisport); c->edge->address = str2sockaddr(hisaddress, hisport);
free(hisaddress); free(hisaddress);
free(dummy);
c->edge->weight = (weight + c->estimated_weight) / 2; c->edge->weight = (weight + c->estimated_weight) / 2;
c->edge->connection = c; c->edge->connection = c;
c->edge->options = c->options; c->edge->options = c->options;

View file

@ -50,7 +50,10 @@ static const size_t ip6_size = sizeof(struct ip6_hdr);
static const size_t icmp6_size = sizeof(struct icmp6_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 ns_size = sizeof(struct nd_neighbor_solicit);
static const size_t opt_size = sizeof(struct nd_opt_hdr); static const size_t opt_size = sizeof(struct nd_opt_hdr);
#define max(a, b) ((a) > (b) ? (a) : (b))
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
static struct event age_subnets_event; static struct event age_subnets_event;
@ -412,10 +415,10 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
if(directonly && subnet->owner != via) if(directonly && subnet->owner != via)
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO); return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO);
if(via && packet->len > max(via->mtu, 590) && 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); 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) { if(packet->data[20] & 0x40) {
packet->len = max(via->mtu, 590); packet->len = MAX(via->mtu, 590);
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
} else { } else {
fragment_ipv4_packet(via, packet); fragment_ipv4_packet(via, packet);
@ -563,9 +566,9 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
if(directonly && subnet->owner != via) if(directonly && subnet->owner != via)
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
if(via && packet->len > max(via->mtu, 1294) && 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); 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); packet->len = MAX(via->mtu, 1294);
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0); route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
return; return;
} }

View file

@ -64,6 +64,8 @@ typedef struct subnet_t {
#define MAXNETSTR 64 #define MAXNETSTR 64
extern splay_tree_t *subnet_tree;
extern int subnet_compare(const struct subnet_t *, const struct subnet_t *); extern int subnet_compare(const struct subnet_t *, const struct subnet_t *);
extern subnet_t *new_subnet(void) __attribute__ ((__malloc__)); extern subnet_t *new_subnet(void) __attribute__ ((__malloc__));
extern void free_subnet(subnet_t *); extern void free_subnet(subnet_t *);