Merge branch 'master' into 1.1
Conflicts: NEWS README configure.in have.h src/conf.c src/conf.h src/net.c src/net_packet.c src/protocol_key.c src/protocol_subnet.c src/route.c src/tincd.c
This commit is contained in:
commit
103543aa2c
27 changed files with 694 additions and 237 deletions
2
COPYING
2
COPYING
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 1998-2009 Ivo Timmermans, Guus Sliepen and others.
|
||||
Copyright (C) 1998-2010 Ivo Timmermans, Guus Sliepen and others.
|
||||
See the AUTHORS file for a complete list.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
|
|
|
@ -15,3 +15,5 @@ The following applies to the LZO library:
|
|||
|
||||
When tinc is compiled with the --enable-tunemu option, the resulting binary
|
||||
falls under the GPL version 3 or later.
|
||||
|
||||
|
||||
|
|
15
NEWS
15
NEWS
|
@ -4,6 +4,21 @@ Version 1.1-cvs Work in progress
|
|||
|
||||
* Use splay trees instead of AVL trees.
|
||||
|
||||
Version 1.0.12 Feb 3 2010
|
||||
|
||||
* Really allow fast roaming of hosts to other nodes in a switched VPN.
|
||||
|
||||
* Fixes missing or incorrect environment variables when calling host-up/down
|
||||
and subnet-up/down scripts in some cases.
|
||||
|
||||
* Allow port to be specified in Address statements.
|
||||
|
||||
* Clamp MSS of TCP packets to the discovered path MTU.
|
||||
|
||||
* Let two nodes behind NAT learn each others current UDP address and port via
|
||||
a third node, potentially allowing direct communications in a similar way to
|
||||
STUN.
|
||||
|
||||
Version 1.0.11 Nov 1 2009
|
||||
|
||||
* Fixed potential crash when the HUP signal is sent.
|
||||
|
|
2
README
2
README
|
@ -1,7 +1,7 @@
|
|||
This is the README file for tinc version 1.1-cvs. Installation
|
||||
instructions may be found in the INSTALL file.
|
||||
|
||||
tinc is Copyright (C) 1998-2009 by:
|
||||
tinc is Copyright (C) 1998-2010 by:
|
||||
|
||||
Ivo Timmermans,
|
||||
Guus Sliepen <guus@tinc-vpn.org>,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.Dd 2009-03-05
|
||||
.Dd 2010-01-16
|
||||
.Dt TINC.CONF 5
|
||||
.\" Manual page created by:
|
||||
.\" Ivo Timmermans
|
||||
|
@ -199,6 +199,32 @@ 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
|
||||
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
|
||||
This option selects the way indirect packets are forwarded.
|
||||
.Bl -tag -width indent
|
||||
|
||||
.It off
|
||||
Incoming packets that are not meant for the local node,
|
||||
but which should be forwarded to another node, are dropped.
|
||||
|
||||
.It internal
|
||||
Incoming packets that are meant for another node are forwarded by tinc internally.
|
||||
|
||||
.Pp
|
||||
This is the default mode, and unless you really know you need another forwarding mode, don't change it.
|
||||
|
||||
.It kernel
|
||||
Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node.
|
||||
This is less efficient, but allows the kernel to apply its routing and firewall rules on them,
|
||||
and can also help debugging.
|
||||
.El
|
||||
|
||||
.It Va GraphDumpFile Li = Ar filename Bq experimental
|
||||
If this option is present,
|
||||
.Nm tinc
|
||||
|
@ -308,11 +334,18 @@ specified in the configuration file.
|
|||
When this option is used the priority of the tincd process will be adjusted.
|
||||
Increasing the priority may help to reduce latency and packet loss on the VPN.
|
||||
|
||||
.It Va TunnelServer Li = yes | no Po no Pc Bq experimental
|
||||
When this option is enabled tinc will no longer forward information between other tinc daemons,
|
||||
and will only allow nodes and subnets on the VPN which are present in the
|
||||
.It Va StrictSubnets Li = yes | no Po no Pc Bq experimental
|
||||
When this option is enabled tinc will only use Subnet statements which are
|
||||
present in the host config files in the local
|
||||
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
|
||||
directory.
|
||||
|
||||
.It Va TunnelServer Li = yes | no Po no Pc Bq experimental
|
||||
When this option is enabled tinc will no longer forward information between other tinc daemons,
|
||||
and will only allow connections with nodes for which host config files are present in the local
|
||||
.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
|
||||
directory.
|
||||
Setting this options also implicitly sets StrictSubnets.
|
||||
.El
|
||||
|
||||
.Sh HOST CONFIGURATION FILES
|
||||
|
@ -330,9 +363,10 @@ Since host configuration files only contain public keys,
|
|||
no secrets are revealed by sending out this information.
|
||||
.Bl -tag -width indent
|
||||
|
||||
.It Va Address Li = Ar address Bq recommended
|
||||
.It Va Address Li = Ar address Oo port Oc Bq recommended
|
||||
The IP address or hostname of this tinc daemon on the real network.
|
||||
This will only be used when trying to make an outgoing connection to this tinc daemon.
|
||||
Optionally, a port can be specified to use for this address.
|
||||
Multiple
|
||||
.Va Address
|
||||
variables can be specified, in which case each address will be tried until a working
|
||||
|
@ -346,6 +380,11 @@ Furthermore, specifying
|
|||
will turn off packet encryption.
|
||||
It is best to use only those ciphers which support CBC mode.
|
||||
|
||||
.It Va ClampMSS Li = yes | no Pq yes
|
||||
This option specifies whether tinc should clamp the maximum segment size (MSS)
|
||||
of TCP packets to the path MTU. This helps in situations where ICMP
|
||||
Fragmentation Needed or Packet too Big messages are dropped by firewalls.
|
||||
|
||||
.It Va Compression Li = Ar level Pq 0
|
||||
This option sets the level of compression used for UDP packets.
|
||||
Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
|
||||
|
@ -380,7 +419,10 @@ When this option is enabled, tinc will try to discover the path MTU to this node
|
|||
After the path MTU has been discovered, it will be enforced on the VPN.
|
||||
|
||||
.It Va Port Li = Ar port Pq 655
|
||||
The port number on which this tinc daemon is listening for incoming connections.
|
||||
The port number on which this tinc daemon is listening for incoming connections,
|
||||
which is used if no port number is specified in an
|
||||
.Va Address
|
||||
statement.
|
||||
|
||||
.It Va PublicKey Li = Ar key Bq obsolete
|
||||
The public RSA key of this tinc daemon.
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
|
||||
|
||||
Copyright @copyright{} 1998-2009 Ivo Timmermans,
|
||||
Copyright @copyright{} 1998-2010 Ivo Timmermans,
|
||||
Guus Sliepen <guus@@tinc-vpn.org> and
|
||||
Wessel Dankers <wsl@@tinc-vpn.org>.
|
||||
|
||||
|
@ -40,7 +40,7 @@ permission notice identical to this one.
|
|||
@cindex copyright
|
||||
This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon.
|
||||
|
||||
Copyright @copyright{} 1998-2009 Ivo Timmermans,
|
||||
Copyright @copyright{} 1998-2010 Ivo Timmermans,
|
||||
Guus Sliepen <guus@@tinc-vpn.org> and
|
||||
Wessel Dankers <wsl@@tinc-vpn.org>.
|
||||
|
||||
|
@ -842,6 +842,33 @@ Tinc will expect packets read from the virtual network device
|
|||
to start with an Ethernet header.
|
||||
@end table
|
||||
|
||||
@cindex DirectOnly
|
||||
@item DirectOnly = <yes|no> (no)
|
||||
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)
|
||||
This option selects the way indirect packets are forwarded.
|
||||
|
||||
@table @asis
|
||||
@item off
|
||||
Incoming packets that are not meant for the local node,
|
||||
but which should be forwarded to another node, are dropped.
|
||||
|
||||
@item internal
|
||||
Incoming packets that are meant for another node are forwarded by tinc internally.
|
||||
|
||||
This is the default mode, and unless you really know you need another forwarding mode, don't change it.
|
||||
|
||||
@item kernel
|
||||
Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node.
|
||||
This is less efficient, but allows the kernel to apply its routing and firewall rules on them,
|
||||
and can also help debugging.
|
||||
@end table
|
||||
|
||||
@cindex GraphDumpFile
|
||||
@item GraphDumpFile = <@var{filename}> [experimental]
|
||||
If this option is present,
|
||||
|
@ -952,11 +979,18 @@ specified in the configuration file.
|
|||
When this option is used the priority of the tincd process will be adjusted.
|
||||
Increasing the priority may help to reduce latency and packet loss on the VPN.
|
||||
|
||||
@cindex StrictSubnets
|
||||
@item StrictSubnets <yes|no> (no) [experimental]
|
||||
When this option is enabled tinc will only use Subnet statements which are
|
||||
present in the host config files in the local
|
||||
@file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory.
|
||||
|
||||
@cindex TunnelServer
|
||||
@item TunnelServer = <yes|no> (no) [experimental]
|
||||
When this option is enabled tinc will no longer forward information between other tinc daemons,
|
||||
and will only allow nodes and subnets on the VPN which are present in the
|
||||
and will only allow connections with nodes for which host config files are present in the local
|
||||
@file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory.
|
||||
Setting this options also implicitly sets StrictSubnets.
|
||||
|
||||
@end table
|
||||
|
||||
|
@ -967,10 +1001,11 @@ and will only allow nodes and subnets on the VPN which are present in the
|
|||
|
||||
@table @asis
|
||||
@cindex Address
|
||||
@item Address = <@var{IP address}|@var{hostname}> [recommended]
|
||||
@item Address = <@var{IP address}|@var{hostname}> [<port>] [recommended]
|
||||
This variable is only required if you want to connect to this host. It
|
||||
must resolve to the external IP address where the host can be reached,
|
||||
not the one that is internal to the VPN.
|
||||
If no port is specified, the default Port is used.
|
||||
|
||||
@cindex Cipher
|
||||
@item Cipher = <@var{cipher}> (blowfish)
|
||||
|
@ -979,6 +1014,12 @@ Any cipher supported by OpenSSL is recognized.
|
|||
Furthermore, specifying "none" will turn off packet encryption.
|
||||
It is best to use only those ciphers which support CBC mode.
|
||||
|
||||
@cindex ClampMSS
|
||||
@item ClampMSS = <yes|no> (yes)
|
||||
This option specifies whether tinc should clamp the maximum segment size (MSS)
|
||||
of TCP packets to the path MTU. This helps in situations where ICMP
|
||||
Fragmentation Needed or Packet too Big messages are dropped by firewalls.
|
||||
|
||||
@cindex Compression
|
||||
@item Compression = <@var{level}> (0)
|
||||
This option sets the level of compression used for UDP packets.
|
||||
|
@ -1323,7 +1364,7 @@ Address = 1.2.3.4
|
|||
|
||||
Note that the IP addresses of eth0 and tap0 are the same.
|
||||
This is quite possible, if you make sure that the netmasks of the interfaces are different.
|
||||
It is in fact recommended to give give both real internal network interfaces and tap interfaces the same IP address,
|
||||
It is in fact recommended to give both real internal network interfaces and tap interfaces the same IP address,
|
||||
since that will make things a lot easier to remember and set up.
|
||||
|
||||
|
||||
|
@ -1346,8 +1387,8 @@ ConnectTo = BranchA
|
|||
@end example
|
||||
|
||||
Note here that the internal address (on eth0) doesn't have to be the
|
||||
same as on the tap0 device. Also, ConnectTo is given so that no-one can
|
||||
connect to this node.
|
||||
same as on the tap0 device. Also, ConnectTo is given so that this node will
|
||||
always try to connect to BranchA.
|
||||
|
||||
On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchB}:
|
||||
|
||||
|
|
4
have.h
4
have.h
|
@ -105,6 +105,10 @@
|
|||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
/* SunOS really wants sys/socket.h BEFORE net/if.h,
|
||||
and FreeBSD wants these lines below the rest. */
|
||||
|
||||
|
|
71
m4/lzo.m4
71
m4/lzo.m4
|
@ -2,41 +2,46 @@ dnl Check to find the lzo headers/libraries
|
|||
|
||||
AC_DEFUN([tinc_LZO],
|
||||
[
|
||||
AC_ARG_WITH(lzo,
|
||||
AS_HELP_STRING([--with-lzo=DIR], [lzo base directory, or:]),
|
||||
[lzo="$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"]
|
||||
)
|
||||
AC_ARG_ENABLE([lzo],
|
||||
AS_HELP_STRING([--disable-lzo], [disable lzo compression support]))
|
||||
AS_IF([test "x$enable_lzo" != "xno"], [
|
||||
AC_DEFINE(HAVE_LZO, 1, [enable lzo compression support])
|
||||
AC_ARG_WITH(lzo,
|
||||
AS_HELP_STRING([--with-lzo=DIR], [lzo base directory, or:]),
|
||||
[lzo="$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(lzo-include,
|
||||
AS_HELP_STRING([--with-lzo-include=DIR], [lzo headers directory]),
|
||||
[lzo_include="$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval"]
|
||||
)
|
||||
AC_ARG_WITH(lzo-include,
|
||||
AS_HELP_STRING([--with-lzo-include=DIR], [lzo headers directory]),
|
||||
[lzo_include="$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(lzo-lib,
|
||||
AS_HELP_STRING([--with-lzo-lib=DIR], [lzo library directory]),
|
||||
[lzo_lib="$withval"
|
||||
LDFLAGS="$LDFLAGS -L$withval"]
|
||||
)
|
||||
AC_ARG_WITH(lzo-lib,
|
||||
AS_HELP_STRING([--with-lzo-lib=DIR], [lzo library directory]),
|
||||
[lzo_lib="$withval"
|
||||
LDFLAGS="$LDFLAGS -L$withval"]
|
||||
)
|
||||
|
||||
AC_CHECK_LIB(lzo2, lzo1x_1_compress,
|
||||
[LIBS="$LIBS -llzo2"],
|
||||
[AC_CHECK_LIB(lzo, lzo1x_1_compress,
|
||||
[LIBS="$LIBS -llzo"],
|
||||
[AC_MSG_ERROR("lzo libraries not found."); break]
|
||||
)]
|
||||
)
|
||||
|
||||
AC_CHECK_HEADERS(lzo/lzo1x.h,
|
||||
[AC_DEFINE(LZO1X_H, [<lzo/lzo1x.h>], [Location of lzo1x.h])],
|
||||
[AC_CHECK_HEADERS(lzo2/lzo1x.h,
|
||||
[AC_DEFINE(LZO1X_H, [<lzo2/lzo1x.h>], [Location of lzo1x.h])],
|
||||
[AC_CHECK_HEADERS(lzo1x.h,
|
||||
[AC_DEFINE(LZO1X_H, [<lzo1x.h>], [Location of lzo1x.h])],
|
||||
[AC_MSG_ERROR("lzo header files not found."); break]
|
||||
AC_CHECK_LIB(lzo2, lzo1x_1_compress,
|
||||
[LIBS="$LIBS -llzo2"],
|
||||
[AC_CHECK_LIB(lzo, lzo1x_1_compress,
|
||||
[LIBS="$LIBS -llzo"],
|
||||
[AC_MSG_ERROR("lzo libraries not found."); break]
|
||||
)]
|
||||
)]
|
||||
)
|
||||
)
|
||||
|
||||
AC_CHECK_HEADERS(lzo/lzo1x.h,
|
||||
[AC_DEFINE(LZO1X_H, [<lzo/lzo1x.h>], [Location of lzo1x.h])],
|
||||
[AC_CHECK_HEADERS(lzo2/lzo1x.h,
|
||||
[AC_DEFINE(LZO1X_H, [<lzo2/lzo1x.h>], [Location of lzo1x.h])],
|
||||
[AC_CHECK_HEADERS(lzo1x.h,
|
||||
[AC_DEFINE(LZO1X_H, [<lzo1x.h>], [Location of lzo1x.h])],
|
||||
[AC_MSG_ERROR("lzo header files not found."); break]
|
||||
)]
|
||||
)]
|
||||
)
|
||||
])
|
||||
])
|
||||
|
|
53
m4/zlib.m4
53
m4/zlib.m4
|
@ -2,32 +2,37 @@ dnl Check to find the zlib headers/libraries
|
|||
|
||||
AC_DEFUN([tinc_ZLIB],
|
||||
[
|
||||
AC_ARG_WITH(zlib,
|
||||
AS_HELP_STRING([--with-zlib=DIR], [zlib base directory, or:]),
|
||||
[zlib="$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"]
|
||||
)
|
||||
AC_ARG_ENABLE([zlib],
|
||||
AS_HELP_STRING([--disable-zlib], [disable zlib compression support]))
|
||||
AS_IF([test "x$enable_zlib" != "xno"], [
|
||||
AC_DEFINE(HAVE_ZLIB, 1, [have zlib compression support])
|
||||
AC_ARG_WITH(zlib,
|
||||
AS_HELP_STRING([--with-zlib=DIR], [zlib base directory, or:]),
|
||||
[zlib="$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(zlib-include,
|
||||
AS_HELP_STRING([--with-zlib-include=DIR], [zlib headers directory]),
|
||||
[zlib_include="$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval"]
|
||||
)
|
||||
AC_ARG_WITH(zlib-include,
|
||||
AS_HELP_STRING([--with-zlib-include=DIR], [zlib headers directory]),
|
||||
[zlib_include="$withval"
|
||||
CPPFLAGS="$CPPFLAGS -I$withval"]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(zlib-lib,
|
||||
AS_HELP_STRING([--with-zlib-lib=DIR], [zlib library directory]),
|
||||
[zlib_lib="$withval"
|
||||
LDFLAGS="$LDFLAGS -L$withval"]
|
||||
)
|
||||
AC_ARG_WITH(zlib-lib,
|
||||
AS_HELP_STRING([--with-zlib-lib=DIR], [zlib library directory]),
|
||||
[zlib_lib="$withval"
|
||||
LDFLAGS="$LDFLAGS -L$withval"]
|
||||
)
|
||||
|
||||
AC_CHECK_HEADERS(zlib.h,
|
||||
[],
|
||||
[AC_MSG_ERROR("zlib header files not found."); break]
|
||||
)
|
||||
AC_CHECK_HEADERS(zlib.h,
|
||||
[],
|
||||
[AC_MSG_ERROR("zlib header files not found."); break]
|
||||
)
|
||||
|
||||
AC_CHECK_LIB(z, compress2,
|
||||
[LIBS="$LIBS -lz"],
|
||||
[AC_MSG_ERROR("zlib libraries not found.")]
|
||||
)
|
||||
AC_CHECK_LIB(z, compress2,
|
||||
[LIBS="$LIBS -lz"],
|
||||
[AC_MSG_ERROR("zlib libraries not found.")]
|
||||
)
|
||||
])
|
||||
])
|
||||
|
|
191
src/conf.c
191
src/conf.c
|
@ -26,6 +26,7 @@
|
|||
#include "conf.h"
|
||||
#include "logger.h"
|
||||
#include "netutl.h" /* for str2address */
|
||||
#include "protocol.h"
|
||||
#include "utils.h" /* for cp */
|
||||
#include "xalloc.h"
|
||||
|
||||
|
@ -206,73 +207,30 @@ bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
|
|||
}
|
||||
|
||||
/*
|
||||
Read exactly one line and strip the trailing newline if any. If the
|
||||
file was on EOF, return NULL. Otherwise, return all the data in a
|
||||
dynamically allocated buffer.
|
||||
|
||||
If line is non-NULL, it will be used as an initial buffer, to avoid
|
||||
unnecessary mallocing each time this function is called. If buf is
|
||||
given, and buf needs to be expanded, the var pointed to by buflen
|
||||
will be increased.
|
||||
Read exactly one line and strip the trailing newline if any.
|
||||
*/
|
||||
static char *readline(FILE * fp, char **buf, size_t *buflen) {
|
||||
static char *readline(FILE * fp, char *buf, size_t buflen) {
|
||||
char *newline = NULL;
|
||||
char *p;
|
||||
char *line; /* The array that contains everything that has been read so far */
|
||||
char *idx; /* Read into this pointer, which points to an offset within line */
|
||||
size_t size, newsize; /* The size of the current array pointed to by line */
|
||||
size_t maxlen; /* Maximum number of characters that may be read with fgets. This is newsize - oldsize. */
|
||||
|
||||
if(feof(fp))
|
||||
return NULL;
|
||||
|
||||
if(buf && buflen) {
|
||||
size = *buflen;
|
||||
line = *buf;
|
||||
} else {
|
||||
size = 100;
|
||||
line = xmalloc(size);
|
||||
}
|
||||
p = fgets(buf, buflen, fp);
|
||||
|
||||
maxlen = size;
|
||||
idx = line;
|
||||
*idx = 0;
|
||||
if(!p)
|
||||
return NULL;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
p = fgets(idx, maxlen, fp);
|
||||
newline = strchr(p, '\n');
|
||||
|
||||
if(!p) { /* EOF or error */
|
||||
if(feof(fp))
|
||||
break;
|
||||
if(!newline)
|
||||
return NULL;
|
||||
|
||||
/* otherwise: error; let the calling function print an error message if applicable */
|
||||
free(line);
|
||||
return NULL;
|
||||
}
|
||||
*newline = '\0'; /* kill newline */
|
||||
if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */
|
||||
newline[-1] = '\0';
|
||||
|
||||
newline = strchr(p, '\n');
|
||||
|
||||
if(!newline) { /* We haven't yet read everything to the end of the line */
|
||||
newsize = size << 1;
|
||||
line = xrealloc(line, newsize);
|
||||
idx = &line[size - 1];
|
||||
maxlen = newsize - size + 1;
|
||||
size = newsize;
|
||||
} else {
|
||||
*newline = '\0'; /* kill newline */
|
||||
if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */
|
||||
newline[-1] = '\0';
|
||||
break; /* yay */
|
||||
}
|
||||
}
|
||||
|
||||
if(buf && buflen) {
|
||||
*buflen = size;
|
||||
*buf = line;
|
||||
}
|
||||
|
||||
return line;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -282,35 +240,28 @@ static char *readline(FILE * fp, char **buf, size_t *buflen) {
|
|||
int read_config_file(splay_tree_t *config_tree, const char *fname) {
|
||||
int err = -2; /* Parse error */
|
||||
FILE *fp;
|
||||
char *buffer, *line;
|
||||
char buffer[MAX_STRING_SIZE];
|
||||
char *line;
|
||||
char *variable, *value, *eol;
|
||||
int lineno = 0;
|
||||
int len;
|
||||
bool ignore = false;
|
||||
config_t *cfg;
|
||||
size_t bufsize;
|
||||
bool result = false;
|
||||
|
||||
fp = fopen(fname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, "Cannot open config file %s: %s", fname,
|
||||
strerror(errno));
|
||||
return -3;
|
||||
logger(LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
bufsize = 100;
|
||||
buffer = xmalloc(bufsize);
|
||||
|
||||
for(;;) {
|
||||
if(feof(fp)) {
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
line = readline(fp, &buffer, &bufsize);
|
||||
line = readline(fp, buffer, sizeof buffer);
|
||||
|
||||
if(!line) {
|
||||
err = -1;
|
||||
if(feof(fp))
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -361,24 +312,114 @@ int read_config_file(splay_tree_t *config_tree, const char *fname) {
|
|||
config_add(config_tree, cfg);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
fclose(fp);
|
||||
|
||||
return err;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool read_server_config() {
|
||||
char *fname;
|
||||
int x;
|
||||
bool x;
|
||||
|
||||
xasprintf(&fname, "%s/tinc.conf", confbase);
|
||||
x = read_config_file(config_tree, fname);
|
||||
|
||||
if(x == -1) { /* System error: complain */
|
||||
if(!x) { /* System error: complain */
|
||||
logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
|
||||
}
|
||||
|
||||
free(fname);
|
||||
|
||||
return x == 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
FILE *ask_and_open(const char *filename, const char *what) {
|
||||
FILE *r;
|
||||
char *directory;
|
||||
char line[PATH_MAX];
|
||||
const char *fn;
|
||||
|
||||
/* Check stdin and stdout */
|
||||
if(!isatty(0) || !isatty(1)) {
|
||||
/* Argh, they are running us from a script or something. Write
|
||||
the files to the current directory and let them burn in hell
|
||||
for ever. */
|
||||
fn = filename;
|
||||
} else {
|
||||
/* Ask for a file and/or directory name. */
|
||||
fprintf(stdout, "Please enter a file to save %s to [%s]: ",
|
||||
what, filename);
|
||||
fflush(stdout);
|
||||
|
||||
fn = readline(stdin, line, sizeof line);
|
||||
|
||||
if(!fn) {
|
||||
fprintf(stderr, "Error while reading stdin: %s\n",
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!strlen(fn))
|
||||
/* User just pressed enter. */
|
||||
fn = filename;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) {
|
||||
#else
|
||||
if(fn[0] != '/') {
|
||||
#endif
|
||||
/* The directory is a relative path or a filename. */
|
||||
char *p;
|
||||
|
||||
directory = get_current_dir_name();
|
||||
xasprintf(&p, "%s/%s", directory, fn);
|
||||
free(directory);
|
||||
fn = p;
|
||||
}
|
||||
|
||||
umask(0077); /* Disallow everything for group and other */
|
||||
|
||||
/* Open it first to keep the inode busy */
|
||||
|
||||
r = fopen(fn, "r+") ?: fopen(fn, "w+");
|
||||
|
||||
if(!r) {
|
||||
fprintf(stderr, "Error opening file `%s': %s\n",
|
||||
fn, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
bool disable_old_keys(FILE *f) {
|
||||
char buf[100];
|
||||
long pos;
|
||||
bool disabled = false;
|
||||
|
||||
rewind(f);
|
||||
pos = ftell(f);
|
||||
|
||||
while(fgets(buf, sizeof buf, f)) {
|
||||
if(!strncmp(buf, "-----BEGIN RSA", 14)) {
|
||||
buf[11] = 'O';
|
||||
buf[12] = 'L';
|
||||
buf[13] = 'D';
|
||||
fseek(f, pos, SEEK_SET);
|
||||
fputs(buf, f);
|
||||
disabled = true;
|
||||
}
|
||||
else if(!strncmp(buf, "-----END RSA", 12)) {
|
||||
buf[ 9] = 'O';
|
||||
buf[10] = 'L';
|
||||
buf[11] = 'D';
|
||||
fseek(f, pos, SEEK_SET);
|
||||
fputs(buf, f);
|
||||
disabled = true;
|
||||
}
|
||||
pos = ftell(f);
|
||||
}
|
||||
|
||||
return disabled;
|
||||
}
|
||||
|
|
|
@ -109,11 +109,11 @@ bool dump_connections(connection_t *cdump) {
|
|||
|
||||
bool read_connection_config(connection_t *c) {
|
||||
char *fname;
|
||||
int x;
|
||||
bool x;
|
||||
|
||||
xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
|
||||
x = read_config_file(c->config_tree, fname);
|
||||
free(fname);
|
||||
|
||||
return x == 0;
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
@ -346,7 +347,7 @@ void check_reachability() {
|
|||
/* 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;
|
||||
|
@ -381,6 +382,8 @@ void check_reachability() {
|
|||
|
||||
if(!n->status.reachable)
|
||||
update_node_udp(n, NULL);
|
||||
else if(n->connection)
|
||||
send_ans_key(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
src/net.c
11
src/net.c
|
@ -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
|
||||
|
@ -59,9 +59,9 @@ void purge(void) {
|
|||
for(snode = n->subnet_tree->head; snode; snode = snext) {
|
||||
snext = snode->next;
|
||||
s = snode->data;
|
||||
if(!tunnelserver)
|
||||
send_del_subnet(broadcast, s);
|
||||
subnet_del(n, s);
|
||||
send_del_subnet(broadcast, s);
|
||||
if(!strictsubnets)
|
||||
subnet_del(n, s);
|
||||
}
|
||||
|
||||
for(enode = n->edge_tree->head; enode; enode = enext) {
|
||||
|
@ -89,7 +89,8 @@ void purge(void) {
|
|||
break;
|
||||
}
|
||||
|
||||
if(!enode)
|
||||
if(!enode && (!strictsubnets || !n->subnet_tree->head))
|
||||
/* in strictsubnets mode do not delete nodes with subnets */
|
||||
node_del(n);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -20,8 +20,19 @@
|
|||
|
||||
#include "system.h"
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LZO
|
||||
#include LZO1X_H
|
||||
#endif
|
||||
|
||||
#include "splay_tree.h"
|
||||
#include "cipher.h"
|
||||
|
@ -44,7 +55,9 @@
|
|||
|
||||
int keylifetime = 0;
|
||||
int keyexpires = 0;
|
||||
#ifdef HAVE_LZO
|
||||
static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS];
|
||||
#endif
|
||||
|
||||
static void send_udppacket(node_t *, vpn_packet_t *);
|
||||
|
||||
|
@ -145,40 +158,61 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
|
|||
}
|
||||
|
||||
static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
|
||||
if(level == 10) {
|
||||
if(level == 0) {
|
||||
memcpy(dest, source, len);
|
||||
return len;
|
||||
} else if(level == 10) {
|
||||
#ifdef HAVE_LZO
|
||||
lzo_uint lzolen = MAXSIZE;
|
||||
lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem);
|
||||
return lzolen;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else if(level < 10) {
|
||||
#ifdef HAVE_ZLIB
|
||||
unsigned long destlen = MAXSIZE;
|
||||
if(compress2(dest, &destlen, source, len, level) == Z_OK)
|
||||
return destlen;
|
||||
else
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
#ifdef HAVE_LZO
|
||||
lzo_uint lzolen = MAXSIZE;
|
||||
lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem);
|
||||
return lzolen;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
|
||||
if(level > 9) {
|
||||
if(level == 0) {
|
||||
memcpy(dest, source, len);
|
||||
return len;
|
||||
} else if(level > 9) {
|
||||
#ifdef HAVE_LZO
|
||||
lzo_uint lzolen = MAXSIZE;
|
||||
if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK)
|
||||
return lzolen;
|
||||
else
|
||||
#endif
|
||||
return -1;
|
||||
} else {
|
||||
}
|
||||
#ifdef HAVE_ZLIB
|
||||
else {
|
||||
unsigned long destlen = MAXSIZE;
|
||||
if(uncompress(dest, &destlen, source, len) == Z_OK)
|
||||
return destlen;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -338,10 +372,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);
|
||||
|
||||
|
|
104
src/net_setup.c
104
src/net_setup.c
|
@ -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
|
||||
|
@ -154,6 +154,65 @@ void regenerate_key() {
|
|||
event_add(&keyexpire_event, &(struct timeval){keylifetime, 0});
|
||||
}
|
||||
|
||||
/*
|
||||
Read Subnets from all host config files
|
||||
*/
|
||||
static void load_all_subnets(void) {
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
char *dname;
|
||||
char *fname;
|
||||
avl_tree_t *config_tree;
|
||||
config_t *cfg;
|
||||
subnet_t *s;
|
||||
node_t *n;
|
||||
bool result;
|
||||
|
||||
xasprintf(&dname, "%s/hosts", confbase);
|
||||
dir = opendir(dname);
|
||||
if(!dir) {
|
||||
logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
|
||||
free(dname);
|
||||
return;
|
||||
}
|
||||
|
||||
while((ent = readdir(dir))) {
|
||||
if(!check_id(ent->d_name))
|
||||
continue;
|
||||
|
||||
n = lookup_node(ent->d_name);
|
||||
if(n)
|
||||
continue;
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
//if(ent->d_type != DT_REG)
|
||||
// continue;
|
||||
#endif
|
||||
|
||||
xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name);
|
||||
init_configuration(&config_tree);
|
||||
result = read_config_file(config_tree, fname);
|
||||
free(fname);
|
||||
if(!result)
|
||||
continue;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
exit_configuration(&config_tree);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
/*
|
||||
Configure node_t myself and set up the local sockets (listen only)
|
||||
*/
|
||||
|
@ -171,8 +230,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;
|
||||
|
@ -199,8 +258,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 */
|
||||
|
||||
|
@ -232,7 +292,10 @@ bool setup_myself(void) {
|
|||
if(myself->options & OPTION_TCPONLY)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
|
||||
get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
|
||||
get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
|
||||
get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
|
||||
strictsubnets |= tunnelserver;
|
||||
|
||||
if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
|
||||
if(!strcasecmp(mode, "router"))
|
||||
|
@ -246,16 +309,34 @@ bool setup_myself(void) {
|
|||
return false;
|
||||
}
|
||||
free(mode);
|
||||
} else
|
||||
routing_mode = RMODE_ROUTER;
|
||||
}
|
||||
|
||||
// Enable PMTUDiscovery by default if we are in router mode.
|
||||
if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
|
||||
if(!strcasecmp(mode, "off"))
|
||||
forwarding_mode = FMODE_OFF;
|
||||
else if(!strcasecmp(mode, "internal"))
|
||||
forwarding_mode = FMODE_INTERNAL;
|
||||
else if(!strcasecmp(mode, "kernel"))
|
||||
forwarding_mode = FMODE_KERNEL;
|
||||
else {
|
||||
logger(LOG_ERR, "Invalid forwarding mode!");
|
||||
return false;
|
||||
}
|
||||
free(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)
|
||||
|
@ -344,6 +425,9 @@ bool setup_myself(void) {
|
|||
|
||||
graph();
|
||||
|
||||
if(strictsubnets)
|
||||
load_all_subnets();
|
||||
|
||||
/* Open device */
|
||||
|
||||
if(!setup_device())
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
@ -260,9 +260,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)
|
||||
|
@ -275,6 +279,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)
|
||||
|
@ -282,6 +288,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)) {
|
||||
|
@ -330,7 +343,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) {
|
||||
|
@ -351,8 +364,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);
|
||||
|
|
|
@ -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
|
||||
|
@ -31,7 +31,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 */
|
||||
|
@ -46,6 +46,7 @@ typedef struct node_t {
|
|||
char *hostname; /* the hostname of its real ip */
|
||||
|
||||
node_status_t status;
|
||||
time_t last_req_key;
|
||||
|
||||
cipher_t incipher; /* Cipher for UDP packets */
|
||||
digest_t indigest; /* Digest for UDP packets */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "xalloc.h"
|
||||
|
||||
bool tunnelserver = false;
|
||||
bool strictsubnets = false;
|
||||
|
||||
/* Jumptable for the request handlers */
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ typedef struct past_request_t {
|
|||
} past_request_t;
|
||||
|
||||
extern bool tunnelserver;
|
||||
extern bool strictsubnets;
|
||||
|
||||
/* Maximum size of strings in a request.
|
||||
* scanf terminates %2048s with a NUL character,
|
||||
|
@ -95,7 +96,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 *);
|
||||
|
|
|
@ -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
|
||||
|
@ -357,6 +357,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);
|
||||
|
@ -400,6 +405,7 @@ bool ack_h(connection_t *c, char *request) {
|
|||
int weight, mtu;
|
||||
uint32_t options;
|
||||
node_t *n;
|
||||
bool choice;
|
||||
|
||||
if(sscanf(request, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) {
|
||||
logger(LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name,
|
||||
|
@ -449,6 +455,13 @@ bool ack_h(connection_t *c, char *request) {
|
|||
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;
|
||||
|
|
|
@ -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
|
||||
|
@ -34,15 +34,19 @@
|
|||
|
||||
static 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, char *request) {
|
||||
|
@ -63,11 +67,11 @@ bool key_changed_h(connection_t *c, char *request) {
|
|||
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 */
|
||||
|
||||
|
@ -92,12 +96,17 @@ bool req_key_h(connection_t *c, char *request) {
|
|||
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);
|
||||
|
@ -105,7 +114,7 @@ bool req_key_h(connection_t *c, char *request) {
|
|||
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 */
|
||||
|
@ -115,7 +124,7 @@ bool req_key_h(connection_t *c, char *request) {
|
|||
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",
|
||||
|
@ -161,23 +170,30 @@ bool ans_key_h(connection_t *c, char *request) {
|
|||
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, keylen;
|
||||
node_t *from, *to;
|
||||
|
||||
if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d",
|
||||
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);
|
||||
|
@ -185,14 +201,14 @@ bool ans_key_h(connection_t *c, char *request) {
|
|||
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",
|
||||
|
@ -229,7 +245,7 @@ bool ans_key_h(connection_t *c, char *request) {
|
|||
|
||||
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;
|
||||
|
@ -244,6 +260,12 @@ bool ans_key_h(connection_t *c, char *request) {
|
|||
from->status.waitingforkey = false;
|
||||
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);
|
||||
|
||||
|
|
|
@ -104,29 +104,21 @@ bool add_subnet_h(connection_t *c, char *request) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/* In tunnel server mode, check if the subnet matches one in the config file of this node */
|
||||
/* In tunnel server mode, we should already know all allowed subnets */
|
||||
|
||||
if(tunnelserver) {
|
||||
config_t *cfg;
|
||||
subnet_t *allowed;
|
||||
logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
|
||||
"ADD_SUBNET", c->name, c->hostname, subnetstr);
|
||||
return true;
|
||||
}
|
||||
|
||||
for(cfg = lookup_config(c->config_tree, "Subnet"); cfg; cfg = lookup_config_next(c->config_tree, cfg)) {
|
||||
if(!get_config_subnet(cfg, &allowed))
|
||||
continue;
|
||||
/* Ignore if strictsubnets is true, but forward it to others */
|
||||
|
||||
if(!subnet_compare(&s, allowed))
|
||||
break;
|
||||
|
||||
free_subnet(allowed);
|
||||
}
|
||||
|
||||
if(!cfg) {
|
||||
logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
|
||||
"ADD_SUBNET", c->name, c->hostname, subnetstr);
|
||||
return true;
|
||||
}
|
||||
|
||||
free_subnet(allowed);
|
||||
if(strictsubnets) {
|
||||
logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
|
||||
"ADD_SUBNET", c->name, c->hostname, subnetstr);
|
||||
forward_request(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If everything is correct, add the subnet to the list of the owner */
|
||||
|
@ -216,6 +208,8 @@ bool del_subnet_h(connection_t *c, char *request) {
|
|||
if(!find) {
|
||||
ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for %s which does not appear in his subnet tree",
|
||||
"DEL_SUBNET", c->name, c->hostname, name);
|
||||
if(strictsubnets)
|
||||
forward_request(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -228,10 +222,15 @@ bool del_subnet_h(connection_t *c, char *request) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if(tunnelserver)
|
||||
return true;
|
||||
|
||||
/* Tell the rest */
|
||||
|
||||
if(!tunnelserver)
|
||||
forward_request(c, request);
|
||||
if(strictsubnets)
|
||||
return true;
|
||||
|
||||
/* Finally, delete it. */
|
||||
|
||||
|
|
123
src/route.c
123
src/route.c
|
@ -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
|
||||
|
@ -33,6 +33,8 @@
|
|||
#include "utils.h"
|
||||
|
||||
rmode_t routing_mode = RMODE_ROUTER;
|
||||
fmode_t forwarding_mode = FMODE_INTERNAL;
|
||||
bool directonly = false;
|
||||
bool priorityinheritance = false;
|
||||
int macexpire = 600;
|
||||
bool overwrite_mac = false;
|
||||
|
@ -48,6 +50,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))
|
||||
|
||||
static struct event age_subnets_event;
|
||||
|
||||
|
@ -95,6 +98,78 @@ 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(!source || !via || !(via->options & OPTION_CLAMP_MSS))
|
||||
return;
|
||||
|
||||
uint16_t mtu = source->mtu;
|
||||
if(via != myself && via->mtu < mtu)
|
||||
mtu = via->mtu;
|
||||
|
||||
/* 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 = 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);
|
||||
|
@ -156,6 +231,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 */
|
||||
|
||||
|
@ -323,17 +399,23 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
if(!subnet->owner->status.reachable)
|
||||
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
|
||||
return route_ipv4_unreachable(source, packet, 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);
|
||||
|
||||
if(priorityinheritance)
|
||||
packet->priority = packet->data[15];
|
||||
|
||||
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||
|
||||
if(via && packet->len > via->mtu && via != myself) {
|
||||
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) {
|
||||
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);
|
||||
|
@ -342,6 +424,8 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
return;
|
||||
}
|
||||
|
||||
clamp_mss(source, via, packet);
|
||||
|
||||
send_packet(subnet->owner, packet);
|
||||
}
|
||||
|
||||
|
@ -469,17 +553,25 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
if(!subnet->owner->status.reachable)
|
||||
route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
|
||||
return route_ipv6_unreachable(source, packet, 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);
|
||||
|
||||
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||
|
||||
if(via && packet->len > via->mtu && via != myself) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -732,14 +824,20 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
|||
return;
|
||||
}
|
||||
|
||||
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
|
||||
return;
|
||||
|
||||
// Handle packets larger than PMTU
|
||||
|
||||
node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||
|
||||
if(directonly && subnet->owner != via)
|
||||
return;
|
||||
|
||||
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);
|
||||
|
@ -747,17 +845,24 @@ 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);
|
||||
}
|
||||
|
||||
void route(node_t *source, vpn_packet_t *packet) {
|
||||
if(forwarding_mode == FMODE_KERNEL && source != myself) {
|
||||
send_packet(myself, packet);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!checklength(source, packet, ether_size))
|
||||
return;
|
||||
|
||||
|
|
|
@ -30,7 +30,15 @@ typedef enum rmode_t {
|
|||
RMODE_ROUTER,
|
||||
} rmode_t;
|
||||
|
||||
typedef enum fmode_t {
|
||||
FMODE_OFF = 0,
|
||||
FMODE_INTERNAL,
|
||||
FMODE_KERNEL,
|
||||
} fmode_t;
|
||||
|
||||
extern rmode_t routing_mode;
|
||||
extern fmode_t forwarding_mode;
|
||||
extern bool directonly;
|
||||
extern bool overwrite_mac;
|
||||
extern bool priorityinheritance;
|
||||
extern int macexpire;
|
||||
|
|
|
@ -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
|
||||
|
@ -479,7 +479,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
|
||||
|
@ -496,9 +496,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
|
||||
|
|
14
src/tincd.c
14
src/tincd.c
|
@ -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>
|
||||
|
||||
|
@ -31,7 +31,15 @@
|
|||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
#ifdef HAVE_LZO
|
||||
#include LZO1X_H
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
#include <pwd.h>
|
||||
|
@ -333,7 +341,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"
|
||||
|
@ -373,10 +381,12 @@ int main(int argc, char **argv) {
|
|||
if(!read_server_config())
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_LZO
|
||||
if(lzo_init() != LZO_E_OK) {
|
||||
logger(LOG_ERR, "Error initializing LZO compressor!");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MINGW
|
||||
if(!do_detach || !init_service())
|
||||
|
|
Loading…
Reference in a new issue