Merge branch 'master' into 1.1
Conflicts: NEWS README configure.in src/net.c src/net.h
This commit is contained in:
commit
79e46d08a4
14 changed files with 96 additions and 25 deletions
16
NEWS
16
NEWS
|
@ -4,6 +4,22 @@ Version 1.1-cvs Work in progress
|
|||
|
||||
* 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
|
||||
|
||||
* Really allow fast roaming of hosts to other nodes in a switched VPN.
|
||||
|
|
1
THANKS
1
THANKS
|
@ -34,6 +34,7 @@ We would like to thank the following people for their contributions to tinc:
|
|||
* Scott Lamb
|
||||
* Sven-Haegar Koch
|
||||
* Teemu Kiviniemi
|
||||
* Timothy Redaelli
|
||||
* Tonnerre Lombard
|
||||
* Wessel Dankers
|
||||
* Wouter van Heyst
|
||||
|
|
|
@ -199,13 +199,13 @@ Tinc will expect packets read from the virtual network device
|
|||
to start with an Ethernet header.
|
||||
.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,
|
||||
but which would have to be forwarded by an intermediate node, are dropped instead.
|
||||
When combined with the IndirectData option,
|
||||
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.
|
||||
.Bl -tag -width indent
|
||||
|
||||
|
|
|
@ -843,14 +843,14 @@ to start with an Ethernet header.
|
|||
@end table
|
||||
|
||||
@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,
|
||||
but which would have to be forwarded by an intermediate node, are dropped instead.
|
||||
When combined with the IndirectData option,
|
||||
packets for nodes for which we do not have a meta connection with are also dropped.
|
||||
|
||||
@cindex Forwarding
|
||||
@item Forwarding = <off|internal|kernel> (internal)
|
||||
@item Forwarding = <off|internal|kernel> (internal) [experimental]
|
||||
This option selects the way indirect packets are forwarded.
|
||||
|
||||
@table @asis
|
||||
|
|
|
@ -224,7 +224,7 @@ static char *readline(FILE * fp, char *buf, size_t buflen) {
|
|||
newline = strchr(p, '\n');
|
||||
|
||||
if(!newline)
|
||||
return NULL;
|
||||
return buf;
|
||||
|
||||
*newline = '\0'; /* kill newline */
|
||||
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.
|
||||
*/
|
||||
int read_config_file(splay_tree_t *config_tree, const char *fname) {
|
||||
int err = -2; /* Parse error */
|
||||
FILE *fp;
|
||||
char buffer[MAX_STRING_SIZE];
|
||||
char *line;
|
||||
|
|
|
@ -45,6 +45,10 @@
|
|||
#define ICMP_NET_UNREACH 0
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_NET_ANO
|
||||
#define ICMP_NET_ANO 9
|
||||
#endif
|
||||
|
||||
#ifndef IP_MSS
|
||||
#define IP_MSS 576
|
||||
#endif
|
||||
|
|
|
@ -95,6 +95,7 @@ struct icmp6_hdr {
|
|||
#define ICMP6_DST_UNREACH_NOROUTE 0
|
||||
#define ICMP6_DST_UNREACH 1
|
||||
#define ICMP6_PACKET_TOO_BIG 2
|
||||
#define ICMP6_DST_UNREACH_ADMIN 1
|
||||
#define ICMP6_DST_UNREACH_ADDR 3
|
||||
#define ND_NEIGHBOR_SOLICIT 135
|
||||
#define ND_NEIGHBOR_ADVERT 136
|
||||
|
|
30
src/net.c
30
src/net.c
|
@ -270,6 +270,36 @@ int reload_configuration(void) {
|
|||
|
||||
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_outgoing_connections();
|
||||
|
|
|
@ -144,6 +144,7 @@ extern void regenerate_key();
|
|||
extern void purge(void);
|
||||
extern void retry(void);
|
||||
extern int reload_configuration(void);
|
||||
extern void load_all_subnets();
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
#define closesocket(s) close(s)
|
||||
|
|
|
@ -157,14 +157,14 @@ void regenerate_key() {
|
|||
/*
|
||||
Read Subnets from all host config files
|
||||
*/
|
||||
static void load_all_subnets(void) {
|
||||
void load_all_subnets(void) {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char *dname;
|
||||
char *fname;
|
||||
splay_tree_t *config_tree;
|
||||
config_t *cfg;
|
||||
subnet_t *s;
|
||||
subnet_t *s, *s2;
|
||||
node_t *n;
|
||||
bool result;
|
||||
|
||||
|
@ -181,9 +181,6 @@ static void load_all_subnets(void) {
|
|||
continue;
|
||||
|
||||
n = lookup_node(ent->d_name);
|
||||
if(n)
|
||||
continue;
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
//if(ent->d_type != DT_REG)
|
||||
// continue;
|
||||
|
@ -196,15 +193,21 @@ static void load_all_subnets(void) {
|
|||
if(!result)
|
||||
continue;
|
||||
|
||||
n = new_node();
|
||||
n->name = xstrdup(ent->d_name);
|
||||
node_add(n);
|
||||
if(!n) {
|
||||
n = new_node();
|
||||
n->name = xstrdup(ent->d_name);
|
||||
node_add(n);
|
||||
}
|
||||
|
||||
for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
|
||||
if(!get_config_subnet(cfg, &s))
|
||||
continue;
|
||||
|
||||
subnet_add(n, s);
|
||||
if((s2 = lookup_subnet(n, s))) {
|
||||
s2->expires = -1;
|
||||
} else {
|
||||
subnet_add(n, s);
|
||||
}
|
||||
}
|
||||
|
||||
exit_configuration(&config_tree);
|
||||
|
@ -262,6 +265,16 @@ bool setup_myself(void) {
|
|||
&& !get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
|
||||
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 */
|
||||
|
||||
cfg = lookup_config(myself->connection->config_tree, "Subnet");
|
||||
|
|
|
@ -102,8 +102,10 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
|
|||
if(scopeid)
|
||||
*scopeid = '\0'; /* Descope. */
|
||||
|
||||
*addrstr = xstrdup(address);
|
||||
*portstr = xstrdup(port);
|
||||
if(addrstr)
|
||||
*addrstr = xstrdup(address);
|
||||
if(portstr)
|
||||
*portstr = xstrdup(port);
|
||||
}
|
||||
|
||||
char *sockaddr2hostname(const sockaddr_t *sa) {
|
||||
|
|
|
@ -401,7 +401,7 @@ static void send_everything(connection_t *c) {
|
|||
|
||||
bool ack_h(connection_t *c, char *request) {
|
||||
char hisport[MAX_STRING_SIZE];
|
||||
char *hisaddress, *dummy;
|
||||
char *hisaddress;
|
||||
int weight, mtu;
|
||||
uint32_t options;
|
||||
node_t *n;
|
||||
|
@ -479,10 +479,9 @@ bool ack_h(connection_t *c, char *request) {
|
|||
c->edge = new_edge();
|
||||
c->edge->from = myself;
|
||||
c->edge->to = n;
|
||||
sockaddr2str(&c->address, &hisaddress, &dummy);
|
||||
sockaddr2str(&c->address, &hisaddress, NULL);
|
||||
c->edge->address = str2sockaddr(hisaddress, hisport);
|
||||
free(hisaddress);
|
||||
free(dummy);
|
||||
c->edge->weight = (weight + c->estimated_weight) / 2;
|
||||
c->edge->connection = c;
|
||||
c->edge->options = c->options;
|
||||
|
|
13
src/route.c
13
src/route.c
|
@ -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 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))
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
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)
|
||||
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);
|
||||
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);
|
||||
} else {
|
||||
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)
|
||||
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);
|
||||
packet->len = max(via->mtu, 1294);
|
||||
packet->len = MAX(via->mtu, 1294);
|
||||
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,8 @@ typedef struct subnet_t {
|
|||
|
||||
#define MAXNETSTR 64
|
||||
|
||||
extern splay_tree_t *subnet_tree;
|
||||
|
||||
extern int subnet_compare(const struct subnet_t *, const struct subnet_t *);
|
||||
extern subnet_t *new_subnet(void) __attribute__ ((__malloc__));
|
||||
extern void free_subnet(subnet_t *);
|
||||
|
|
Loading…
Reference in a new issue