Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1
Conflicts: NEWS README configure.in doc/tincd.8.in src/Makefile.am src/bsd/device.c src/connection.c src/connection.h src/cygwin/device.c src/device.h src/dropin.h src/linux/device.c src/mingw/device.c src/net.c src/net_packet.c src/net_setup.c src/net_socket.c src/process.c src/protocol.c src/protocol_key.c src/raw_socket_device.c src/route.c src/solaris/device.c src/tincd.c src/uml_device.c
This commit is contained in:
commit
3fba80174d
33 changed files with 614 additions and 273 deletions
7
NEWS
7
NEWS
|
@ -28,6 +28,13 @@ Version 1.1pre1 June 25 2011
|
||||||
Thanks to Scott Lamb and Sven-Haegar Koch for their contributions to this
|
Thanks to Scott Lamb and Sven-Haegar Koch for their contributions to this
|
||||||
version of tinc.
|
version of tinc.
|
||||||
|
|
||||||
|
Version 1.0.16 July 23 2011
|
||||||
|
|
||||||
|
* Fixed a performance issue with TCP communication under Windows.
|
||||||
|
|
||||||
|
* Fixed code that, during network outages, would cause tinc to exit when it
|
||||||
|
thought two nodes with identical Names were on the VPN.
|
||||||
|
|
||||||
Version 1.0.15 June 24 2011
|
Version 1.0.15 June 24 2011
|
||||||
|
|
||||||
* Improved logging to file.
|
* Improved logging to file.
|
||||||
|
|
1
THANKS
1
THANKS
|
@ -32,6 +32,7 @@ We would like to thank the following people for their contributions to tinc:
|
||||||
* Menno Smits
|
* Menno Smits
|
||||||
* Michael Tokarev
|
* Michael Tokarev
|
||||||
* Miles Nordin
|
* Miles Nordin
|
||||||
|
* Nick Hibma
|
||||||
* Nick Patavalis
|
* Nick Patavalis
|
||||||
* Paul Littlefield
|
* Paul Littlefield
|
||||||
* Robert van der Meulen
|
* Robert van der Meulen
|
||||||
|
|
19
configure.in
19
configure.in
|
@ -73,6 +73,21 @@ case $host_os in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(uml,
|
||||||
|
AS_HELP_STRING([--enable-uml], [enable support for User Mode Linux]),
|
||||||
|
[ AC_DEFINE(ENABLE_UML, 1, [Support for UML])
|
||||||
|
uml=true
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(vde,
|
||||||
|
AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]),
|
||||||
|
[ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break])
|
||||||
|
AC_DEFINE(ENABLE_VDE, 1, [Support for VDE])
|
||||||
|
vde=true
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
AC_ARG_ENABLE(tunemu,
|
AC_ARG_ENABLE(tunemu,
|
||||||
AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]),
|
AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]),
|
||||||
[ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu])
|
[ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu])
|
||||||
|
@ -85,6 +100,8 @@ AC_ARG_WITH(windows2000,
|
||||||
[AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])]
|
[AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AM_CONDITIONAL(UML, test "$uml" = true)
|
||||||
|
AM_CONDITIONAL(VDE, test "$vde" = true)
|
||||||
AM_CONDITIONAL(TUNEMU, test "$tunemu" = true)
|
AM_CONDITIONAL(TUNEMU, test "$tunemu" = true)
|
||||||
|
|
||||||
AC_CACHE_SAVE
|
AC_CACHE_SAVE
|
||||||
|
@ -101,7 +118,7 @@ dnl We do this in multiple stages, because unlike Linux all the other operating
|
||||||
|
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h])
|
AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h])
|
||||||
AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h],
|
AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h netpacket/packet.h],
|
||||||
[], [], [#include "have.h"]
|
[], [], [#include "have.h"]
|
||||||
)
|
)
|
||||||
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h],
|
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h],
|
||||||
|
|
|
@ -133,7 +133,10 @@ IPv6 listening sockets will be created.
|
||||||
If your computer has more than one IPv4 or IPv6 address,
|
If your computer has more than one IPv4 or IPv6 address,
|
||||||
.Nm tinc
|
.Nm tinc
|
||||||
will by default listen on all of them for incoming connections.
|
will by default listen on all of them for incoming connections.
|
||||||
It is possible to bind only to a single address with this variable.
|
Multiple
|
||||||
|
.Va BindToAddress
|
||||||
|
variables may be specified,
|
||||||
|
in which case listening sockets for each specified address are made.
|
||||||
|
|
||||||
.Pp
|
.Pp
|
||||||
This option may not work on all platforms.
|
This option may not work on all platforms.
|
||||||
|
@ -147,6 +150,9 @@ It is possible to bind only to a single interface with this variable.
|
||||||
.Pp
|
.Pp
|
||||||
This option may not work on all platforms.
|
This option may not work on all platforms.
|
||||||
|
|
||||||
|
.It Va Broadcast Li = yes | no Po yes Pc Bq experimental
|
||||||
|
When disabled, tinc will drop all broadcast and multicast packets, in both router and switch mode.
|
||||||
|
|
||||||
.It Va ConnectTo Li = Ar name
|
.It Va ConnectTo Li = Ar name
|
||||||
Specifies which other tinc daemon to connect to on startup.
|
Specifies which other tinc daemon to connect to on startup.
|
||||||
Multiple
|
Multiple
|
||||||
|
@ -165,6 +171,14 @@ If you don't specify a host with
|
||||||
won't try to connect to other daemons at all,
|
won't try to connect to other daemons at all,
|
||||||
and will instead just listen for incoming connections.
|
and will instead just listen for incoming connections.
|
||||||
|
|
||||||
|
.It Va DecrementTTL Li = yes | no Po yes Pc
|
||||||
|
When enabled,
|
||||||
|
.Nm tinc
|
||||||
|
will decrement the Time To Live field in IPv4 packets, or the Hop Limit field in IPv6 packets,
|
||||||
|
before forwarding a received packet to the virtual network device or to another node,
|
||||||
|
and will drop packets that have a TTL value of zero,
|
||||||
|
in which case it will send an ICMP Time Exceeded packet back.
|
||||||
|
|
||||||
.It Va Device Li = Ar device Po Pa /dev/tap0 , Pa /dev/net/tun No or other depending on platform Pc
|
.It Va Device Li = Ar device Po Pa /dev/tap0 , Pa /dev/net/tun No or other depending on platform Pc
|
||||||
The virtual network device to use.
|
The virtual network device to use.
|
||||||
.Nm tinc
|
.Nm tinc
|
||||||
|
@ -177,30 +191,65 @@ instead of
|
||||||
The info pages of the tinc package contain more information
|
The info pages of the tinc package contain more information
|
||||||
about configuring the virtual network device.
|
about configuring the virtual network device.
|
||||||
|
|
||||||
.It Va DeviceType Li = tun | tunnohead | tunifhead | tap Po only supported on BSD platforms Pc
|
.It Va DeviceType Li = Ar type Pq platform dependent
|
||||||
The type of the virtual network device.
|
The type of the virtual network device.
|
||||||
Tinc will normally automatically select the right type, and this option should not be used.
|
Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used.
|
||||||
However, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
However, this option can be used to select one of the special interface types, if support for them is compiled in.
|
||||||
using this option might help.
|
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
|
|
||||||
.It tun
|
.It dummy
|
||||||
|
Use a dummy interface.
|
||||||
|
No packets are ever read or written to a virtual network device.
|
||||||
|
Useful for testing, or when setting up a node that only forwards packets for other nodes.
|
||||||
|
|
||||||
|
.It raw_socket
|
||||||
|
Open a raw socket, and bind it to a pre-existing
|
||||||
|
.Va Interface
|
||||||
|
(eth0 by default).
|
||||||
|
All packets are read from this interface.
|
||||||
|
Packets received for the local node are written to the raw socket.
|
||||||
|
However, at least on Linux, the operating system does not process IP packets destined for the local host.
|
||||||
|
|
||||||
|
.It uml Pq not compiled in by default
|
||||||
|
Create a UNIX socket with the filename specified by
|
||||||
|
.Va Device ,
|
||||||
|
or
|
||||||
|
.Pa @localstatedir@/run/ Ns Ar NETNAME Ns Pa .umlsocket
|
||||||
|
if not specified.
|
||||||
|
.Nm tinc
|
||||||
|
will wait for a User Mode Linux instance to connect to this socket.
|
||||||
|
|
||||||
|
.It vde Pq not compiled in by default
|
||||||
|
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
|
||||||
|
using the UNIX socket specified by
|
||||||
|
.Va Device ,
|
||||||
|
or
|
||||||
|
.Pa @localstatedir@/run/vde.ctl
|
||||||
|
if not specified.
|
||||||
|
.El
|
||||||
|
|
||||||
|
Also, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
||||||
|
it can be used to change the way packets are interpreted:
|
||||||
|
|
||||||
|
.Bl -tag -width indent
|
||||||
|
|
||||||
|
.It tun Pq BSD and Linux
|
||||||
Set type to tun.
|
Set type to tun.
|
||||||
Depending on the platform, this can either be with or without an address family header (see below).
|
Depending on the platform, this can either be with or without an address family header (see below).
|
||||||
|
|
||||||
.It tunnohead
|
.It tunnohead Pq BSD
|
||||||
Set type to tun without an address family header.
|
Set type to tun without an address family header.
|
||||||
Tinc will expect packets read from the virtual network device to start with an IP header.
|
Tinc will expect packets read from the virtual network device to start with an IP header.
|
||||||
On some platforms IPv6 packets cannot be read from or written to the device in this mode.
|
On some platforms IPv6 packets cannot be read from or written to the device in this mode.
|
||||||
|
|
||||||
.It tunifhead
|
.It tunifhead Pq BSD
|
||||||
Set type to tun with an address family header.
|
Set type to tun with an address family header.
|
||||||
Tinc will expect packets read from the virtual network device
|
Tinc will expect packets read from the virtual network device
|
||||||
to start with a four byte header containing the address family,
|
to start with a four byte header containing the address family,
|
||||||
followed by an IP header.
|
followed by an IP header.
|
||||||
This mode should support both IPv4 and IPv6 packets.
|
This mode should support both IPv4 and IPv6 packets.
|
||||||
|
|
||||||
.It tap
|
.It tap Pq BSD and Linux
|
||||||
Set type to tap.
|
Set type to tap.
|
||||||
Tinc will expect packets read from the virtual network device
|
Tinc will expect packets read from the virtual network device
|
||||||
to start with an Ethernet header.
|
to start with an Ethernet header.
|
||||||
|
|
|
@ -782,7 +782,8 @@ both IPv4 and IPv6 or just IPv6 listening sockets will be created.
|
||||||
@item BindToAddress = <@var{address}> [experimental]
|
@item BindToAddress = <@var{address}> [experimental]
|
||||||
If your computer has more than one IPv4 or IPv6 address, tinc
|
If your computer has more than one IPv4 or IPv6 address, tinc
|
||||||
will by default listen on all of them for incoming connections.
|
will by default listen on all of them for incoming connections.
|
||||||
It is possible to bind only to a single address with this variable.
|
Multiple BindToAddress variables may be specified,
|
||||||
|
in which case listening sockets for each specified address are made.
|
||||||
|
|
||||||
This option may not work on all platforms.
|
This option may not work on all platforms.
|
||||||
|
|
||||||
|
@ -795,6 +796,10 @@ variable.
|
||||||
|
|
||||||
This option may not work on all platforms.
|
This option may not work on all platforms.
|
||||||
|
|
||||||
|
@cindex Broadcast
|
||||||
|
@item Broadcast = <yes | no> (yes) [experimental]
|
||||||
|
When disabled, tinc will drop all broadcast and multicast packets, in both router and switch mode.
|
||||||
|
|
||||||
@cindex ConnectTo
|
@cindex ConnectTo
|
||||||
@item ConnectTo = <@var{name}>
|
@item ConnectTo = <@var{name}>
|
||||||
Specifies which other tinc daemon to connect to on startup.
|
Specifies which other tinc daemon to connect to on startup.
|
||||||
|
@ -807,6 +812,13 @@ If you don't specify a host with ConnectTo,
|
||||||
tinc won't try to connect to other daemons at all,
|
tinc won't try to connect to other daemons at all,
|
||||||
and will instead just listen for incoming connections.
|
and will instead just listen for incoming connections.
|
||||||
|
|
||||||
|
@cindex DecrementTTL
|
||||||
|
@item DecrementTTL = <yes | no> (yes)
|
||||||
|
When enabled, tinc will decrement the Time To Live field in IPv4 packets, or the Hop Limit field in IPv6 packets,
|
||||||
|
before forwarding a received packet to the virtual network device or to another node,
|
||||||
|
and will drop packets that have a TTL value of zero,
|
||||||
|
in which case it will send an ICMP Time Exceeded packet back.
|
||||||
|
|
||||||
@cindex Device
|
@cindex Device
|
||||||
@item Device = <@var{device}> (@file{/dev/tap0}, @file{/dev/net/tun} or other depending on platform)
|
@item Device = <@var{device}> (@file{/dev/tap0}, @file{/dev/net/tun} or other depending on platform)
|
||||||
The virtual network device to use.
|
The virtual network device to use.
|
||||||
|
@ -817,32 +829,64 @@ Note that you can only use one device per daemon.
|
||||||
See also @ref{Device files}.
|
See also @ref{Device files}.
|
||||||
|
|
||||||
@cindex DeviceType
|
@cindex DeviceType
|
||||||
@item DeviceType = <tun|tunnohead|tunifhead|tap> (only supported on BSD platforms)
|
@item DeviceType = <@var{type}> (platform dependent)
|
||||||
The type of the virtual network device.
|
The type of the virtual network device.
|
||||||
Tinc will normally automatically select the right type, and this option should not be used.
|
Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used.
|
||||||
However, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
However, this option can be used to select one of the special interface types, if support for them is compiled in.
|
||||||
using this option might help.
|
|
||||||
|
|
||||||
@table @asis
|
@table @asis
|
||||||
@item tun
|
@cindex dummy
|
||||||
|
@item dummy
|
||||||
|
Use a dummy interface.
|
||||||
|
No packets are ever read or written to a virtual network device.
|
||||||
|
Useful for testing, or when setting up a node that only forwards packets for other nodes.
|
||||||
|
|
||||||
|
@cindex raw_socket
|
||||||
|
@item raw_socket
|
||||||
|
Open a raw socket, and bind it to a pre-existing
|
||||||
|
@var{Interface} (eth0 by default).
|
||||||
|
All packets are read from this interface.
|
||||||
|
Packets received for the local node are written to the raw socket.
|
||||||
|
However, at least on Linux, the operating system does not process IP packets destined for the local host.
|
||||||
|
|
||||||
|
@cindex UML
|
||||||
|
@item uml (not compiled in by default)
|
||||||
|
Create a UNIX socket with the filename specified by
|
||||||
|
@var{Device}, or @file{@value{localstatedir}/run/@var{netname}.umlsocket}
|
||||||
|
if not specified.
|
||||||
|
Tinc will wait for a User Mode Linux instance to connect to this socket.
|
||||||
|
|
||||||
|
@cindex VDE
|
||||||
|
@item vde (not compiled in by default)
|
||||||
|
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
|
||||||
|
using the UNIX socket specified by
|
||||||
|
@var{Device}, or @file{@value{localstatedir}/run/vde.ctl}
|
||||||
|
if not specified.
|
||||||
|
@end table
|
||||||
|
|
||||||
|
Also, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
||||||
|
it can be used to change the way packets are interpreted:
|
||||||
|
|
||||||
|
@table @asis
|
||||||
|
@item tun (BSD and Linux)
|
||||||
Set type to tun.
|
Set type to tun.
|
||||||
Depending on the platform, this can either be with or without an address family header (see below).
|
Depending on the platform, this can either be with or without an address family header (see below).
|
||||||
|
|
||||||
@cindex tunnohead
|
@cindex tunnohead
|
||||||
@item tunnohead
|
@item tunnohead (BSD)
|
||||||
Set type to tun without an address family header.
|
Set type to tun without an address family header.
|
||||||
Tinc will expect packets read from the virtual network device to start with an IP header.
|
Tinc will expect packets read from the virtual network device to start with an IP header.
|
||||||
On some platforms IPv6 packets cannot be read from or written to the device in this mode.
|
On some platforms IPv6 packets cannot be read from or written to the device in this mode.
|
||||||
|
|
||||||
@cindex tunifhead
|
@cindex tunifhead
|
||||||
@item tunifhead
|
@item tunifhead (BSD)
|
||||||
Set type to tun with an address family header.
|
Set type to tun with an address family header.
|
||||||
Tinc will expect packets read from the virtual network device
|
Tinc will expect packets read from the virtual network device
|
||||||
to start with a four byte header containing the address family,
|
to start with a four byte header containing the address family,
|
||||||
followed by an IP header.
|
followed by an IP header.
|
||||||
This mode should support both IPv4 and IPv6 packets.
|
This mode should support both IPv4 and IPv6 packets.
|
||||||
|
|
||||||
@item tap
|
@item tap (BSD and Linux)
|
||||||
Set type to tap.
|
Set type to tap.
|
||||||
Tinc will expect packets read from the virtual network device
|
Tinc will expect packets read from the virtual network device
|
||||||
to start with an Ethernet header.
|
to start with an Ethernet header.
|
||||||
|
@ -1600,6 +1644,12 @@ Store a cookie in @var{filename} which allows tincctl to authenticate.
|
||||||
If unspecified, the default is
|
If unspecified, the default is
|
||||||
@file{@value{localstatedir}/run/tinc.@var{netname}.pid}.
|
@file{@value{localstatedir}/run/tinc.@var{netname}.pid}.
|
||||||
|
|
||||||
|
@item -o, --option=[@var{HOST}.]@var{KEY}=@var{VALUE}
|
||||||
|
Without specifying a @var{HOST}, this will set server configuration variable @var{KEY} to @var{VALUE}.
|
||||||
|
If specified as @var{HOST}.@var{KEY}=@var{VALUE},
|
||||||
|
this will set the host configuration variable @var{KEY} of the host named @var{HOST} to @var{VALUE}.
|
||||||
|
This option can be used more than once to specify multiple configuration variables.
|
||||||
|
|
||||||
@item -L, --mlock
|
@item -L, --mlock
|
||||||
Lock tinc into main memory.
|
Lock tinc into main memory.
|
||||||
This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
|
This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
|
||||||
|
|
|
@ -8,11 +8,12 @@
|
||||||
.Nd tinc VPN daemon
|
.Nd tinc VPN daemon
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl cdDKnLRU
|
.Op Fl cdDKnoLRU
|
||||||
.Op Fl -config Ns = Ns Ar DIR
|
.Op Fl -config Ns = Ns Ar DIR
|
||||||
.Op Fl -no-detach
|
.Op Fl -no-detach
|
||||||
.Op Fl -debug Ns Op = Ns Ar LEVEL
|
.Op Fl -debug Ns Op = Ns Ar LEVEL
|
||||||
.Op Fl -net Ns = Ns Ar NETNAME
|
.Op Fl -net Ns = Ns Ar NETNAME
|
||||||
|
.Op Fl -option Ns = Ns Ar [HOST.]KEY=VALUE
|
||||||
.Op Fl -mlock
|
.Op Fl -mlock
|
||||||
.Op Fl -logfile Ns Op = Ns Ar FILE
|
.Op Fl -logfile Ns Op = Ns Ar FILE
|
||||||
.Op Fl -bypass-security
|
.Op Fl -bypass-security
|
||||||
|
@ -61,6 +62,22 @@ for
|
||||||
.Ar NETNAME
|
.Ar NETNAME
|
||||||
is the same as not specifying any
|
is the same as not specifying any
|
||||||
.Ar NETNAME .
|
.Ar NETNAME .
|
||||||
|
.It Fl o, -option Ns = Ns Ar [HOST.]KEY=VALUE
|
||||||
|
Without specifying a
|
||||||
|
.Ar HOST ,
|
||||||
|
this will set server configuration variable
|
||||||
|
.Ar KEY
|
||||||
|
to
|
||||||
|
.Ar VALUE .
|
||||||
|
If specified as
|
||||||
|
.Ar HOST.KEY=VALUE ,
|
||||||
|
this will set the host configuration variable
|
||||||
|
.Ar KEY
|
||||||
|
of the host named
|
||||||
|
.Ar HOST
|
||||||
|
to
|
||||||
|
.Ar VALUE .
|
||||||
|
This option can be used more than once to specify multiple configuration variables.
|
||||||
.It Fl L, -mlock
|
.It Fl L, -mlock
|
||||||
Lock tinc into main memory.
|
Lock tinc into main memory.
|
||||||
This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
|
This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
|
||||||
|
|
|
@ -2,13 +2,22 @@
|
||||||
|
|
||||||
sbin_PROGRAMS = tincd tincctl sptps_test
|
sbin_PROGRAMS = tincd tincctl sptps_test
|
||||||
|
|
||||||
EXTRA_DIST = linux bsd solaris cygwin mingw raw_socket uml_socket openssl gcrypt
|
EXTRA_DIST = linux bsd solaris cygwin mingw openssl gcrypt
|
||||||
|
|
||||||
tincd_SOURCES = \
|
tincd_SOURCES = \
|
||||||
utils.c getopt.c getopt1.c list.c splay_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c \
|
utils.c getopt.c getopt1.c list.c splay_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c \
|
||||||
buffer.c conf.c connection.c control.c edge.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \
|
buffer.c conf.c connection.c control.c edge.c graph.c logger.c meta.c net.c net_packet.c net_setup.c \
|
||||||
net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
|
net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
|
||||||
protocol_key.c protocol_subnet.c route.c subnet.c tincd.c
|
protocol_key.c protocol_subnet.c route.c subnet.c tincd.c \
|
||||||
|
dummy_device.c raw_socket_device.c
|
||||||
|
|
||||||
|
if UML
|
||||||
|
tincd_SOURCES += uml_device.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if VDE
|
||||||
|
tincd_SOURCES += vde_device.c
|
||||||
|
endif
|
||||||
|
|
||||||
nodist_tincd_SOURCES = \
|
nodist_tincd_SOURCES = \
|
||||||
device.c cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c rsa.c
|
device.c cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c rsa.c
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
device.c -- Interaction BSD tun/tap device
|
device.c -- Interaction BSD tun/tap device
|
||||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||||
2001-2011 Guus Sliepen <guus@tinc-vpn.org>
|
2001-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
|
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -58,7 +58,7 @@ static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
|
||||||
static device_type_t device_type = DEVICE_TYPE_TUN;
|
static device_type_t device_type = DEVICE_TYPE_TUN;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
char *type;
|
char *type;
|
||||||
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
|
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
|
||||||
|
@ -106,6 +106,10 @@ bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
default:
|
default:
|
||||||
device_type = DEVICE_TYPE_TUN;
|
device_type = DEVICE_TYPE_TUN;
|
||||||
|
@ -175,7 +179,7 @@ bool setup_device(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_device(void) {
|
static void close_device(void) {
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
#ifdef HAVE_TUNEMU
|
#ifdef HAVE_TUNEMU
|
||||||
case DEVICE_TYPE_TUNEMU:
|
case DEVICE_TYPE_TUNEMU:
|
||||||
|
@ -190,7 +194,7 @@ void close_device(void) {
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int inlen;
|
int inlen;
|
||||||
|
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
|
@ -282,7 +286,7 @@ bool read_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||||
packet->len, device_info);
|
packet->len, device_info);
|
||||||
|
|
||||||
|
@ -351,8 +355,16 @@ bool write_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t os_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
splay_tree_t *connection_tree; /* Meta connections */
|
splay_tree_t *connection_tree; /* Meta connections */
|
||||||
connection_t *broadcast;
|
connection_t *everyone;
|
||||||
|
|
||||||
static int connection_compare(const connection_t *a, const connection_t *b) {
|
static int connection_compare(const connection_t *a, const connection_t *b) {
|
||||||
return a < b ? -1 : a == b ? 0 : 1;
|
return a < b ? -1 : a == b ? 0 : 1;
|
||||||
|
@ -40,14 +40,14 @@ static int connection_compare(const connection_t *a, const connection_t *b) {
|
||||||
|
|
||||||
void init_connections(void) {
|
void init_connections(void) {
|
||||||
connection_tree = splay_alloc_tree((splay_compare_t) connection_compare, (splay_action_t) free_connection);
|
connection_tree = splay_alloc_tree((splay_compare_t) connection_compare, (splay_action_t) free_connection);
|
||||||
broadcast = new_connection();
|
everyone = new_connection();
|
||||||
broadcast->name = xstrdup("everyone");
|
everyone->name = xstrdup("everyone");
|
||||||
broadcast->hostname = xstrdup("BROADCAST");
|
everyone->hostname = xstrdup("BROADCAST");
|
||||||
}
|
}
|
||||||
|
|
||||||
void exit_connections(void) {
|
void exit_connections(void) {
|
||||||
splay_delete_tree(connection_tree);
|
splay_delete_tree(connection_tree);
|
||||||
free_connection(broadcast);
|
free_connection(everyone);
|
||||||
}
|
}
|
||||||
|
|
||||||
connection_t *new_connection(void) {
|
connection_t *new_connection(void) {
|
||||||
|
|
|
@ -99,7 +99,7 @@ typedef struct connection_t {
|
||||||
} connection_t;
|
} connection_t;
|
||||||
|
|
||||||
extern splay_tree_t *connection_tree;
|
extern splay_tree_t *connection_tree;
|
||||||
extern connection_t *broadcast;
|
extern connection_t *everyone;
|
||||||
|
|
||||||
extern void init_connections(void);
|
extern void init_connections(void);
|
||||||
extern void exit_connections(void);
|
extern void exit_connections(void);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
device.c -- Interaction with Windows tap driver in a Cygwin environment
|
device.c -- Interaction with Windows tap driver in a Cygwin environment
|
||||||
Copyright (C) 2002-2005 Ivo Timmermans,
|
Copyright (C) 2002-2005 Ivo Timmermans,
|
||||||
2002-2009 Guus Sliepen <guus@tinc-vpn.org>
|
2002-2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -45,7 +45,7 @@ static uint64_t device_total_out = 0;
|
||||||
static pid_t reader_pid;
|
static pid_t reader_pid;
|
||||||
static int sp[2];
|
static int sp[2];
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
HKEY key, key2;
|
HKEY key, key2;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ bool setup_device(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_device(void) {
|
static void close_device(void) {
|
||||||
close(sp[0]);
|
close(sp[0]);
|
||||||
close(sp[1]);
|
close(sp[1]);
|
||||||
CloseHandle(device_handle);
|
CloseHandle(device_handle);
|
||||||
|
@ -225,7 +225,7 @@ void close_device(void) {
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int inlen;
|
int inlen;
|
||||||
|
|
||||||
if((inlen = read(sp[0], packet->data, MTU)) <= 0) {
|
if((inlen = read(sp[0], packet->data, MTU)) <= 0) {
|
||||||
|
@ -244,7 +244,7 @@ bool read_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
long outlen;
|
long outlen;
|
||||||
|
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||||
|
@ -260,8 +260,16 @@ bool write_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t os_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
||||||
|
|
23
src/device.h
23
src/device.h
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
net.h -- generic header for device.c
|
device.h -- generic header for device.c
|
||||||
Copyright (C) 2001-2005 Ivo Timmermans
|
Copyright (C) 2001-2005 Ivo Timmermans
|
||||||
2001-2006 Guus Sliepen <guus@tinc-vpn.org>
|
2001-2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,10 +32,19 @@ extern uint64_t device_in_bytes;
|
||||||
extern uint64_t device_out_packets;
|
extern uint64_t device_out_packets;
|
||||||
extern uint64_t device_out_bytes;
|
extern uint64_t device_out_bytes;
|
||||||
|
|
||||||
extern bool setup_device(void);
|
typedef struct devops_t {
|
||||||
extern void close_device(void);
|
bool (*setup)(void);
|
||||||
extern bool read_packet(struct vpn_packet_t *);
|
void (*close)(void);
|
||||||
extern bool write_packet(struct vpn_packet_t *);
|
bool (*read)(struct vpn_packet_t *);
|
||||||
extern void dump_device_stats(void);
|
bool (*write)(struct vpn_packet_t *);
|
||||||
|
void (*dump_stats)(void);
|
||||||
|
} devops_t;
|
||||||
|
|
||||||
|
extern const devops_t os_devops;
|
||||||
|
extern const devops_t dummy_devops;
|
||||||
|
extern const devops_t raw_socket_devops;
|
||||||
|
extern const devops_t uml_devops;
|
||||||
|
extern const devops_t vde_devops;
|
||||||
|
extern devops_t devops;
|
||||||
|
|
||||||
#endif /* __TINC_DEVICE_H__ */
|
#endif /* __TINC_DEVICE_H__ */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
device.c -- Dummy device
|
device.c -- Dummy device
|
||||||
Copyright (C) 2009 Guus Sliepen <guus@tinc-vpn.org>
|
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -23,33 +23,40 @@
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
int device_fd = -1;
|
|
||||||
char *device = "dummy";
|
|
||||||
char *iface = "dummy";
|
|
||||||
static char *device_info = "dummy device";
|
static char *device_info = "dummy device";
|
||||||
|
|
||||||
static uint64_t device_total_in = 0;
|
static uint64_t device_total_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
|
device = "dummy";
|
||||||
|
iface = "dummy";
|
||||||
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_device(void) {
|
static void close_device(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
device_total_out += packet->len;
|
device_total_out += packet->len;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t dummy_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
|
@ -41,6 +41,14 @@
|
||||||
#define ICMP_NET_UNKNOWN 6
|
#define ICMP_NET_UNKNOWN 6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ICMP_TIME_EXCEEDED
|
||||||
|
#define ICMP_TIME_EXCEEDED 11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ICMP_EXC_TTL
|
||||||
|
#define ICMP_EXC_TTL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef ICMP_NET_UNREACH
|
#ifndef ICMP_NET_UNREACH
|
||||||
#define ICMP_NET_UNREACH 0
|
#define ICMP_NET_UNREACH 0
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
device.c -- Interaction with Linux ethertap and tun/tap device
|
device.c -- Interaction with Linux ethertap and tun/tap device
|
||||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||||
2001-2009 Guus Sliepen <guus@tinc-vpn.org>
|
2001-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -41,6 +41,7 @@ int device_fd = -1;
|
||||||
static device_type_t device_type;
|
static device_type_t device_type;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *iface = NULL;
|
char *iface = NULL;
|
||||||
|
static char *type = NULL;
|
||||||
static char ifrname[IFNAMSIZ];
|
static char ifrname[IFNAMSIZ];
|
||||||
static char *device_info;
|
static char *device_info;
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ uint64_t device_in_bytes = 0;
|
||||||
uint64_t device_out_packets = 0;
|
uint64_t device_out_packets = 0;
|
||||||
uint64_t device_out_bytes = 0;
|
uint64_t device_out_bytes = 0;
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
|
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
|
||||||
device = xstrdup(DEFAULT_DEVICE);
|
device = xstrdup(DEFAULT_DEVICE);
|
||||||
|
|
||||||
|
@ -67,9 +68,20 @@ bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ifreq ifr = {{{0}}};
|
struct ifreq ifr = {{{0}}};
|
||||||
|
|
||||||
if(routing_mode == RMODE_ROUTER) {
|
get_config_string(lookup_config(config_tree, "DeviceType"), &type);
|
||||||
|
|
||||||
|
if(type && strcasecmp(type, "tun") && strcasecmp(type, "tap")) {
|
||||||
|
logger(LOG_ERR, "Unknown device type %s!", type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((type && !strcasecmp(type, "tun")) || (!type && routing_mode == RMODE_ROUTER)) {
|
||||||
ifr.ifr_flags = IFF_TUN;
|
ifr.ifr_flags = IFF_TUN;
|
||||||
device_type = DEVICE_TYPE_TUN;
|
device_type = DEVICE_TYPE_TUN;
|
||||||
device_info = "Linux tun/tap device (tun mode)";
|
device_info = "Linux tun/tap device (tun mode)";
|
||||||
|
@ -106,14 +118,15 @@ bool setup_device(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_device(void) {
|
static void close_device(void) {
|
||||||
close(device_fd);
|
close(device_fd);
|
||||||
|
|
||||||
|
free(type);
|
||||||
free(device);
|
free(device);
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int inlen;
|
int inlen;
|
||||||
|
|
||||||
switch(device_type) {
|
switch(device_type) {
|
||||||
|
@ -152,7 +165,7 @@ bool read_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||||
packet->len, device_info);
|
packet->len, device_info);
|
||||||
|
|
||||||
|
@ -182,8 +195,16 @@ bool write_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_in_bytes);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_in_bytes);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_out_bytes);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_out_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t os_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
||||||
|
|
|
@ -83,7 +83,7 @@ static DWORD WINAPI tapreader(void *bla) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
HKEY key, key2;
|
HKEY key, key2;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -210,18 +210,18 @@ bool setup_device(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_device(void) {
|
static void close_device(void) {
|
||||||
CloseHandle(device_handle);
|
CloseHandle(device_handle);
|
||||||
|
|
||||||
free(device);
|
free(device);
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
long outlen;
|
long outlen;
|
||||||
OVERLAPPED overlapped = {0};
|
OVERLAPPED overlapped = {0};
|
||||||
|
|
||||||
|
@ -238,8 +238,16 @@ bool write_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t os_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
||||||
|
|
12
src/net.c
12
src/net.c
|
@ -64,7 +64,7 @@ void purge(void) {
|
||||||
for(snode = n->subnet_tree->head; snode; snode = snext) {
|
for(snode = n->subnet_tree->head; snode; snode = snext) {
|
||||||
snext = snode->next;
|
snext = snode->next;
|
||||||
s = snode->data;
|
s = snode->data;
|
||||||
send_del_subnet(broadcast, s);
|
send_del_subnet(everyone, s);
|
||||||
if(!strictsubnets)
|
if(!strictsubnets)
|
||||||
subnet_del(n, s);
|
subnet_del(n, s);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ void purge(void) {
|
||||||
enext = enode->next;
|
enext = enode->next;
|
||||||
e = enode->data;
|
e = enode->data;
|
||||||
if(!tunnelserver)
|
if(!tunnelserver)
|
||||||
send_del_edge(broadcast, e);
|
send_del_edge(everyone, e);
|
||||||
edge_del(e);
|
edge_del(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ void terminate_connection(connection_t *c, bool report) {
|
||||||
|
|
||||||
if(c->edge) {
|
if(c->edge) {
|
||||||
if(report && !tunnelserver)
|
if(report && !tunnelserver)
|
||||||
send_del_edge(broadcast, c->edge);
|
send_del_edge(everyone, c->edge);
|
||||||
|
|
||||||
edge_del(c->edge);
|
edge_del(c->edge);
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ void terminate_connection(connection_t *c, bool report) {
|
||||||
e = lookup_edge(c->node, myself);
|
e = lookup_edge(c->node, myself);
|
||||||
if(e) {
|
if(e) {
|
||||||
if(!tunnelserver)
|
if(!tunnelserver)
|
||||||
send_del_edge(broadcast, e);
|
send_del_edge(everyone, e);
|
||||||
edge_del(e);
|
edge_del(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,14 +310,14 @@ int reload_configuration(void) {
|
||||||
next = node->next;
|
next = node->next;
|
||||||
subnet = node->data;
|
subnet = node->data;
|
||||||
if(subnet->expires == 1) {
|
if(subnet->expires == 1) {
|
||||||
send_del_subnet(broadcast, subnet);
|
send_del_subnet(everyone, subnet);
|
||||||
if(subnet->owner->status.reachable)
|
if(subnet->owner->status.reachable)
|
||||||
subnet_update(subnet->owner, subnet, false);
|
subnet_update(subnet->owner, subnet, false);
|
||||||
subnet_del(subnet->owner, subnet);
|
subnet_del(subnet->owner, subnet);
|
||||||
} else if(subnet->expires == -1) {
|
} else if(subnet->expires == -1) {
|
||||||
subnet->expires = 0;
|
subnet->expires = 0;
|
||||||
} else {
|
} else {
|
||||||
send_add_subnet(broadcast, subnet);
|
send_add_subnet(everyone, subnet);
|
||||||
if(subnet->owner->status.reachable)
|
if(subnet->owner->status.reachable)
|
||||||
subnet_update(subnet->owner, subnet, true);
|
subnet_update(subnet->owner, subnet, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,7 +381,6 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
||||||
static int priority = 0;
|
static int priority = 0;
|
||||||
int origpriority = origpkt->priority;
|
int origpriority = origpkt->priority;
|
||||||
#endif
|
#endif
|
||||||
int sock;
|
|
||||||
|
|
||||||
if(!n->status.reachable) {
|
if(!n->status.reachable) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname);
|
ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname);
|
||||||
|
@ -463,26 +462,28 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
||||||
|
|
||||||
/* Determine which socket we have to use */
|
/* Determine which socket we have to use */
|
||||||
|
|
||||||
for(sock = 0; sock < listen_sockets; sock++)
|
if(n->address.sa.sa_family != listen_socket[n->sock].sa.sa.sa_family) {
|
||||||
if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family)
|
for(int sock = 0; sock < listen_sockets; sock++) {
|
||||||
break;
|
if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) {
|
||||||
|
n->sock = sock;
|
||||||
if(sock >= listen_sockets)
|
break;
|
||||||
sock = 0; /* If none is available, just use the first and hope for the best. */
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Send the packet */
|
/* Send the packet */
|
||||||
|
|
||||||
#if defined(SOL_IP) && defined(IP_TOS)
|
#if defined(SOL_IP) && defined(IP_TOS)
|
||||||
if(priorityinheritance && origpriority != priority
|
if(priorityinheritance && origpriority != priority
|
||||||
&& listen_socket[sock].sa.sa.sa_family == AF_INET) {
|
&& listen_socket[n->sock].sa.sa.sa_family == AF_INET) {
|
||||||
priority = origpriority;
|
priority = origpriority;
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
|
||||||
if(setsockopt(listen_socket[sock].udp, SOL_IP, IP_TOS, &priority, sizeof priority)) /* SO_PRIORITY doesn't seem to work */
|
if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
|
||||||
logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
|
logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) {
|
if(sendto(listen_socket[n->sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) {
|
||||||
if(sockmsgsize(sockerrno)) {
|
if(sockmsgsize(sockerrno)) {
|
||||||
if(n->maxmtu >= origlen)
|
if(n->maxmtu >= origlen)
|
||||||
n->maxmtu = origlen - 1;
|
n->maxmtu = origlen - 1;
|
||||||
|
@ -507,7 +508,7 @@ void send_packet(node_t *n, vpn_packet_t *packet) {
|
||||||
memcpy(packet->data, mymac.x, ETH_ALEN);
|
memcpy(packet->data, mymac.x, ETH_ALEN);
|
||||||
n->out_packets++;
|
n->out_packets++;
|
||||||
n->out_bytes += packet->len;
|
n->out_bytes += packet->len;
|
||||||
write_packet(packet);
|
devops.write(packet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,6 +632,8 @@ void handle_incoming_vpn_data(int sock, short events, void *data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n->sock = (intptr_t)data;
|
||||||
|
|
||||||
receive_udppacket(n, &pkt);
|
receive_udppacket(n, &pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,7 +642,7 @@ void handle_device_data(int sock, short events, void *data) {
|
||||||
|
|
||||||
packet.priority = 0;
|
packet.priority = 0;
|
||||||
|
|
||||||
if(read_packet(&packet)) {
|
if(devops.read(&packet)) {
|
||||||
myself->in_packets++;
|
myself->in_packets++;
|
||||||
myself->in_bytes += packet.len;
|
myself->in_bytes += packet.len;
|
||||||
route(myself, &packet);
|
route(myself, &packet);
|
||||||
|
|
156
src/net_setup.c
156
src/net_setup.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
net_setup.c -- Setup.
|
net_setup.c -- Setup.
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||||
2000-2010 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
2006 Scott Lamb <slamb@slamb.org>
|
2006 Scott Lamb <slamb@slamb.org>
|
||||||
2010 Brandon Black <blblack@gmail.com>
|
2010 Brandon Black <blblack@gmail.com>
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
char *myport;
|
char *myport;
|
||||||
static struct event device_ev;
|
static struct event device_ev;
|
||||||
|
devops_t devops;
|
||||||
|
|
||||||
bool node_read_ecdsa_public_key(node_t *n) {
|
bool node_read_ecdsa_public_key(node_t *n) {
|
||||||
if(ecdsa_active(&n->ecdsa))
|
if(ecdsa_active(&n->ecdsa))
|
||||||
|
@ -151,8 +152,7 @@ bool read_rsa_public_key(connection_t *c) {
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
|
|
||||||
if(!fp) {
|
if(!fp) {
|
||||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s",
|
logger(LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno));
|
||||||
fname, strerror(errno));
|
|
||||||
free(fname);
|
free(fname);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -179,8 +179,7 @@ static bool read_ecdsa_private_key(void) {
|
||||||
fp = fopen(fname, "r");
|
fp = fopen(fname, "r");
|
||||||
|
|
||||||
if(!fp) {
|
if(!fp) {
|
||||||
logger(LOG_ERR, "Error reading ECDSA private key file `%s': %s",
|
logger(LOG_ERR, "Error reading ECDSA private key file `%s': %s", fname, strerror(errno));
|
||||||
fname, strerror(errno));
|
|
||||||
free(fname);
|
free(fname);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -349,7 +348,7 @@ void load_all_subnets(void) {
|
||||||
static bool setup_myself(void) {
|
static bool setup_myself(void) {
|
||||||
config_t *cfg;
|
config_t *cfg;
|
||||||
subnet_t *subnet;
|
subnet_t *subnet;
|
||||||
char *name, *hostname, *mode, *afname, *cipher, *digest;
|
char *name, *hostname, *mode, *afname, *cipher, *digest, *type;
|
||||||
char *fname = NULL;
|
char *fname = NULL;
|
||||||
char *address = NULL;
|
char *address = NULL;
|
||||||
char *envp[5];
|
char *envp[5];
|
||||||
|
@ -475,6 +474,8 @@ static bool setup_myself(void) {
|
||||||
myself->options |= OPTION_CLAMP_MSS;
|
myself->options |= OPTION_CLAMP_MSS;
|
||||||
|
|
||||||
get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
|
get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
|
||||||
|
get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
|
||||||
|
get_config_bool(lookup_config(config_tree, "Broadcast"), &broadcast);
|
||||||
|
|
||||||
#if !defined(SOL_IP) || !defined(IP_TOS)
|
#if !defined(SOL_IP) || !defined(IP_TOS)
|
||||||
if(priorityinheritance)
|
if(priorityinheritance)
|
||||||
|
@ -589,7 +590,24 @@ static bool setup_myself(void) {
|
||||||
|
|
||||||
/* Open device */
|
/* Open device */
|
||||||
|
|
||||||
if(!setup_device())
|
devops = os_devops;
|
||||||
|
|
||||||
|
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
||||||
|
if(!strcasecmp(type, "dummy"))
|
||||||
|
devops = dummy_devops;
|
||||||
|
else if(!strcasecmp(type, "raw_socket"))
|
||||||
|
devops = raw_socket_devops;
|
||||||
|
#ifdef ENABLE_UML
|
||||||
|
else if(!strcasecmp(type, "uml"))
|
||||||
|
devops = uml_devops;
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_VDE
|
||||||
|
else if(!strcasecmp(type, "vde"))
|
||||||
|
devops = vde_devops;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!devops.setup())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(device_fd >= 0) {
|
if(device_fd >= 0) {
|
||||||
|
@ -597,7 +615,7 @@ static bool setup_myself(void) {
|
||||||
|
|
||||||
if (event_add(&device_ev, NULL) < 0) {
|
if (event_add(&device_ev, NULL) < 0) {
|
||||||
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
||||||
close_device();
|
devops.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -620,72 +638,78 @@ static bool setup_myself(void) {
|
||||||
|
|
||||||
/* Open sockets */
|
/* Open sockets */
|
||||||
|
|
||||||
get_config_string(lookup_config(config_tree, "BindToAddress"), &address);
|
|
||||||
|
|
||||||
hint.ai_family = addressfamily;
|
|
||||||
hint.ai_socktype = SOCK_STREAM;
|
|
||||||
hint.ai_protocol = IPPROTO_TCP;
|
|
||||||
hint.ai_flags = AI_PASSIVE;
|
|
||||||
|
|
||||||
err = getaddrinfo(address, myport, &hint, &ai);
|
|
||||||
|
|
||||||
if(err || !ai) {
|
|
||||||
logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
|
|
||||||
gai_strerror(err));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
listen_sockets = 0;
|
listen_sockets = 0;
|
||||||
|
cfg = lookup_config(config_tree, "BindToAddress");
|
||||||
|
|
||||||
for(aip = ai; aip; aip = aip->ai_next) {
|
do {
|
||||||
listen_socket[listen_sockets].tcp =
|
get_config_string(cfg, &address);
|
||||||
setup_listen_socket((sockaddr_t *) aip->ai_addr);
|
if(cfg)
|
||||||
|
cfg = lookup_config_next(config_tree, cfg);
|
||||||
|
|
||||||
if(listen_socket[listen_sockets].tcp < 0)
|
hint.ai_family = addressfamily;
|
||||||
continue;
|
hint.ai_socktype = SOCK_STREAM;
|
||||||
|
hint.ai_protocol = IPPROTO_TCP;
|
||||||
|
hint.ai_flags = AI_PASSIVE;
|
||||||
|
|
||||||
listen_socket[listen_sockets].udp =
|
err = getaddrinfo(address, myport, &hint, &ai);
|
||||||
setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
|
free(address);
|
||||||
|
|
||||||
if(listen_socket[listen_sockets].udp < 0) {
|
if(err || !ai) {
|
||||||
close(listen_socket[listen_sockets].tcp);
|
logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
|
||||||
continue;
|
gai_strerror(err));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
event_set(&listen_socket[listen_sockets].ev_tcp,
|
for(aip = ai; aip; aip = aip->ai_next) {
|
||||||
listen_socket[listen_sockets].tcp,
|
if(listen_sockets >= MAXSOCKETS) {
|
||||||
EV_READ|EV_PERSIST,
|
logger(LOG_ERR, "Too many listening sockets");
|
||||||
handle_new_meta_connection, NULL);
|
return false;
|
||||||
if(event_add(&listen_socket[listen_sockets].ev_tcp, NULL) < 0) {
|
}
|
||||||
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
|
||||||
abort();
|
listen_socket[listen_sockets].tcp =
|
||||||
|
setup_listen_socket((sockaddr_t *) aip->ai_addr);
|
||||||
|
|
||||||
|
if(listen_socket[listen_sockets].tcp < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
listen_socket[listen_sockets].udp =
|
||||||
|
setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
|
||||||
|
|
||||||
|
if(listen_socket[listen_sockets].udp < 0) {
|
||||||
|
close(listen_socket[listen_sockets].tcp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_set(&listen_socket[listen_sockets].ev_tcp,
|
||||||
|
listen_socket[listen_sockets].tcp,
|
||||||
|
EV_READ|EV_PERSIST,
|
||||||
|
handle_new_meta_connection, NULL);
|
||||||
|
if(event_add(&listen_socket[listen_sockets].ev_tcp, NULL) < 0) {
|
||||||
|
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
event_set(&listen_socket[listen_sockets].ev_udp,
|
||||||
|
listen_socket[listen_sockets].udp,
|
||||||
|
EV_READ|EV_PERSIST,
|
||||||
|
handle_incoming_vpn_data, (void *)(intptr_t)listen_sockets);
|
||||||
|
if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) {
|
||||||
|
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ifdebug(CONNECTIONS) {
|
||||||
|
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
|
||||||
|
logger(LOG_NOTICE, "Listening on %s", hostname);
|
||||||
|
free(hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
|
||||||
|
listen_sockets++;
|
||||||
}
|
}
|
||||||
|
|
||||||
event_set(&listen_socket[listen_sockets].ev_udp,
|
freeaddrinfo(ai);
|
||||||
listen_socket[listen_sockets].udp,
|
} while(cfg);
|
||||||
EV_READ|EV_PERSIST,
|
|
||||||
handle_incoming_vpn_data, NULL);
|
|
||||||
if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) {
|
|
||||||
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
ifdebug(CONNECTIONS) {
|
|
||||||
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
|
|
||||||
logger(LOG_NOTICE, "Listening on %s", hostname);
|
|
||||||
free(hostname);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
|
|
||||||
listen_sockets++;
|
|
||||||
|
|
||||||
if(listen_sockets >= MAXSOCKETS) {
|
|
||||||
logger(LOG_WARNING, "Maximum of %d listening sockets reached", MAXSOCKETS);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
freeaddrinfo(ai);
|
|
||||||
|
|
||||||
if(listen_sockets)
|
if(listen_sockets)
|
||||||
logger(LOG_NOTICE, "Ready");
|
logger(LOG_NOTICE, "Ready");
|
||||||
|
@ -778,7 +802,7 @@ void close_network_connections(void) {
|
||||||
for(i = 0; i < 4; i++)
|
for(i = 0; i < 4; i++)
|
||||||
free(envp[i]);
|
free(envp[i]);
|
||||||
|
|
||||||
close_device();
|
devops.close();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
net_socket.c -- Handle various kinds of sockets.
|
net_socket.c -- Handle various kinds of sockets.
|
||||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||||
2000-2010 Guus Sliepen <guus@tinc-vpn.org>
|
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
2006 Scott Lamb <slamb@slamb.org>
|
2006 Scott Lamb <slamb@slamb.org>
|
||||||
2009 Florian Forster <octo@verplant.org>
|
2009 Florian Forster <octo@verplant.org>
|
||||||
|
|
||||||
|
@ -33,8 +33,6 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* Needed on Mac OS/X */
|
/* Needed on Mac OS/X */
|
||||||
#ifndef SOL_TCP
|
#ifndef SOL_TCP
|
||||||
#define SOL_TCP IPPROTO_TCP
|
#define SOL_TCP IPPROTO_TCP
|
||||||
|
@ -109,63 +107,6 @@ static bool bind_to_interface(int sd) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool bind_to_address(connection_t *c) {
|
|
||||||
char *node;
|
|
||||||
struct addrinfo *ai_list;
|
|
||||||
struct addrinfo *ai_ptr;
|
|
||||||
struct addrinfo ai_hints;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
assert(c != NULL);
|
|
||||||
assert(c->socket >= 0);
|
|
||||||
|
|
||||||
node = NULL;
|
|
||||||
if(!get_config_string(lookup_config(config_tree, "BindToAddress"),
|
|
||||||
&node))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
assert(node != NULL);
|
|
||||||
|
|
||||||
memset(&ai_hints, 0, sizeof(ai_hints));
|
|
||||||
ai_hints.ai_family = c->address.sa.sa_family;
|
|
||||||
/* We're called from `do_outgoing_connection' only. */
|
|
||||||
ai_hints.ai_socktype = SOCK_STREAM;
|
|
||||||
ai_hints.ai_protocol = IPPROTO_TCP;
|
|
||||||
|
|
||||||
ai_list = NULL;
|
|
||||||
|
|
||||||
status = getaddrinfo(node, /* service = */ NULL,
|
|
||||||
&ai_hints, &ai_list);
|
|
||||||
if(status) {
|
|
||||||
logger(LOG_WARNING, "Error looking up %s port %s: %s",
|
|
||||||
node, "any", gai_strerror(status));
|
|
||||||
free(node);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
assert(ai_list != NULL);
|
|
||||||
|
|
||||||
status = -1;
|
|
||||||
for(ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
|
|
||||||
status = bind(c->socket,
|
|
||||||
ai_list->ai_addr, ai_list->ai_addrlen);
|
|
||||||
if(!status)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(status) {
|
|
||||||
logger(LOG_ERR, "Can't bind to %s/tcp: %s", node, sockstrerror(sockerrno));
|
|
||||||
} else ifdebug(CONNECTIONS) {
|
|
||||||
logger(LOG_DEBUG, "Successfully bound outgoing "
|
|
||||||
"TCP socket to %s", node);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(node);
|
|
||||||
freeaddrinfo(ai_list);
|
|
||||||
|
|
||||||
return status ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int setup_listen_socket(const sockaddr_t *sa) {
|
int setup_listen_socket(const sockaddr_t *sa) {
|
||||||
int nfd;
|
int nfd;
|
||||||
char *addrstr;
|
char *addrstr;
|
||||||
|
@ -179,6 +120,10 @@ int setup_listen_socket(const sockaddr_t *sa) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(nfd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Optimize TCP settings */
|
/* Optimize TCP settings */
|
||||||
|
|
||||||
option = 1;
|
option = 1;
|
||||||
|
@ -237,6 +182,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(nfd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef O_NONBLOCK
|
#ifdef O_NONBLOCK
|
||||||
{
|
{
|
||||||
int flags = fcntl(nfd, F_GETFL);
|
int flags = fcntl(nfd, F_GETFL);
|
||||||
|
@ -409,6 +358,10 @@ begin:
|
||||||
|
|
||||||
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
|
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(c->socket, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(c->socket == -1) {
|
if(c->socket == -1) {
|
||||||
ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno));
|
ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno));
|
||||||
goto begin;
|
goto begin;
|
||||||
|
@ -421,7 +374,6 @@ begin:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bind_to_interface(c->socket);
|
bind_to_interface(c->socket);
|
||||||
bind_to_address(c);
|
|
||||||
|
|
||||||
/* Optimize TCP settings */
|
/* Optimize TCP settings */
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ typedef struct node_t {
|
||||||
char *name; /* name of this node */
|
char *name; /* name of this node */
|
||||||
uint32_t options; /* options turned on for this node */
|
uint32_t options; /* options turned on for this node */
|
||||||
|
|
||||||
|
int sock; /* Socket to use for outgoing UDP packets */
|
||||||
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
|
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
|
||||||
char *hostname; /* the hostname of its real ip */
|
char *hostname; /* the hostname of its real ip */
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
|
#include <openssl/obj_mac.h>
|
||||||
|
|
||||||
#include "digest.h"
|
#include "digest.h"
|
||||||
#include "prf.h"
|
#include "prf.h"
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ bool send_request(connection_t *c, const char *format, ...) {
|
||||||
|
|
||||||
request[len++] = '\n';
|
request[len++] = '\n';
|
||||||
|
|
||||||
if(c == broadcast) {
|
if(c == everyone) {
|
||||||
broadcast_meta(NULL, request, len);
|
broadcast_meta(NULL, request, len);
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -651,7 +651,7 @@ bool ack_h(connection_t *c, char *request) {
|
||||||
if(tunnelserver)
|
if(tunnelserver)
|
||||||
send_add_edge(c, c->edge);
|
send_add_edge(c, c->edge);
|
||||||
else
|
else
|
||||||
send_add_edge(broadcast, c->edge);
|
send_add_edge(everyone, c->edge);
|
||||||
|
|
||||||
/* Run MST and SSSP algorithms */
|
/* Run MST and SSSP algorithms */
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,7 @@ bool del_edge_h(connection_t *c, char *request) {
|
||||||
e = lookup_edge(to, myself);
|
e = lookup_edge(to, myself);
|
||||||
if(e) {
|
if(e) {
|
||||||
if(!tunnelserver)
|
if(!tunnelserver)
|
||||||
send_del_edge(broadcast, e);
|
send_del_edge(everyone, e);
|
||||||
edge_del(e);
|
edge_del(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ void send_key_changed(void) {
|
||||||
splay_node_t *node;
|
splay_node_t *node;
|
||||||
connection_t *c;
|
connection_t *c;
|
||||||
|
|
||||||
send_request(broadcast, "%d %x %s", KEY_CHANGED, rand(), myself->name);
|
send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name);
|
||||||
|
|
||||||
/* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
|
/* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
device.c -- raw socket
|
device.c -- raw socket
|
||||||
Copyright (C) 2002-2005 Ivo Timmermans,
|
Copyright (C) 2002-2005 Ivo Timmermans,
|
||||||
2002-2009 Guus Sliepen <guus@tinc-vpn.org>
|
2002-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_NETPACKET_PACKET_H
|
||||||
#include <netpacket/packet.h>
|
#include <netpacket/packet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
@ -30,16 +32,13 @@
|
||||||
#include "route.h"
|
#include "route.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
int device_fd = -1;
|
#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET)
|
||||||
char *device = NULL;
|
|
||||||
char *iface = NULL;
|
|
||||||
static char ifrname[IFNAMSIZ];
|
|
||||||
static char *device_info;
|
static char *device_info;
|
||||||
|
|
||||||
static uint64_t device_total_in = 0;
|
static uint64_t device_total_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct sockaddr_ll sa;
|
struct sockaddr_ll sa;
|
||||||
|
|
||||||
|
@ -58,6 +57,11 @@ bool setup_device(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ifr, 0, sizeof ifr);
|
memset(&ifr, 0, sizeof ifr);
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
|
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
|
||||||
if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) {
|
if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) {
|
||||||
close(device_fd);
|
close(device_fd);
|
||||||
|
@ -81,14 +85,14 @@ bool setup_device(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_device(void) {
|
static void close_device(void) {
|
||||||
close(device_fd);
|
close(device_fd);
|
||||||
|
|
||||||
free(device);
|
free(device);
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int inlen;
|
int inlen;
|
||||||
|
|
||||||
if((inlen = read(device_fd, packet->data, MTU)) <= 0) {
|
if((inlen = read(device_fd, packet->data, MTU)) <= 0) {
|
||||||
|
@ -107,7 +111,7 @@ bool read_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||||
packet->len, device_info);
|
packet->len, device_info);
|
||||||
|
|
||||||
|
@ -122,8 +126,32 @@ bool write_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t raw_socket_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static bool not_supported(void) {
|
||||||
|
logger(LOG_ERR, "Raw socket device not supported on this platform");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const devops_t raw_socket_devops = {
|
||||||
|
.setup = not_supported,
|
||||||
|
.close = NULL,
|
||||||
|
.read = NULL,
|
||||||
|
.write = NULL,
|
||||||
|
.dump_stats = NULL,
|
||||||
|
};
|
||||||
|
#endif
|
59
src/route.c
59
src/route.c
|
@ -36,10 +36,12 @@
|
||||||
|
|
||||||
rmode_t routing_mode = RMODE_ROUTER;
|
rmode_t routing_mode = RMODE_ROUTER;
|
||||||
fmode_t forwarding_mode = FMODE_INTERNAL;
|
fmode_t forwarding_mode = FMODE_INTERNAL;
|
||||||
|
bool decrement_ttl = true;
|
||||||
bool directonly = false;
|
bool directonly = false;
|
||||||
bool priorityinheritance = false;
|
bool priorityinheritance = false;
|
||||||
int macexpire = 600;
|
int macexpire = 600;
|
||||||
bool overwrite_mac = false;
|
bool overwrite_mac = false;
|
||||||
|
bool broadcast = true;
|
||||||
mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
|
mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
|
||||||
bool pcap = false;
|
bool pcap = false;
|
||||||
|
|
||||||
|
@ -439,11 +441,11 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
||||||
if(!checklength(source, packet, ether_size + ip_size))
|
if(!checklength(source, packet, ether_size + ip_size))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(((packet->data[30] & 0xf0) == 0xe0) || (
|
if(broadcast && (((packet->data[30] & 0xf0) == 0xe0) || (
|
||||||
packet->data[30] == 255 &&
|
packet->data[30] == 255 &&
|
||||||
packet->data[31] == 255 &&
|
packet->data[31] == 255 &&
|
||||||
packet->data[32] == 255 &&
|
packet->data[32] == 255 &&
|
||||||
packet->data[33] == 255))
|
packet->data[33] == 255)))
|
||||||
broadcast_packet(source, packet);
|
broadcast_packet(source, packet);
|
||||||
else
|
else
|
||||||
route_ipv4_unicast(source, packet);
|
route_ipv4_unicast(source, packet);
|
||||||
|
@ -731,7 +733,7 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(packet->data[38] == 255)
|
if(broadcast && packet->data[38] == 255)
|
||||||
broadcast_packet(source, packet);
|
broadcast_packet(source, packet);
|
||||||
else
|
else
|
||||||
route_ipv6_unicast(source, packet);
|
route_ipv6_unicast(source, packet);
|
||||||
|
@ -821,7 +823,8 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
||||||
subnet = lookup_subnet_mac(NULL, &dest);
|
subnet = lookup_subnet_mac(NULL, &dest);
|
||||||
|
|
||||||
if(!subnet) {
|
if(!subnet) {
|
||||||
broadcast_packet(source, packet);
|
if(broadcast)
|
||||||
|
broadcast_packet(source, packet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,6 +879,50 @@ static void send_pcap(vpn_packet_t *packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||||
|
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case ETH_P_IP:
|
||||||
|
if(!checklength(source, packet, 14 + 32))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(packet->data[22] < 1) {
|
||||||
|
route_ipv4_unreachable(source, packet, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t old = packet->data[22] << 8 | packet->data[23];
|
||||||
|
packet->data[22]--;
|
||||||
|
uint16_t new = packet->data[22] << 8 | packet->data[23];
|
||||||
|
|
||||||
|
uint32_t checksum = packet->data[24] << 8 | packet->data[25];
|
||||||
|
checksum += old + (~new & 0xFFFF);
|
||||||
|
while(checksum >> 16)
|
||||||
|
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||||
|
packet->data[24] = checksum >> 8;
|
||||||
|
packet->data[25] = checksum & 0xff;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ETH_P_IPV6:
|
||||||
|
if(!checklength(source, packet, 14 + 40))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(packet->data[21] < 1) {
|
||||||
|
route_ipv6_unreachable(source, packet, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet->data[21]--;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void route(node_t *source, vpn_packet_t *packet) {
|
void route(node_t *source, vpn_packet_t *packet) {
|
||||||
if(pcap)
|
if(pcap)
|
||||||
send_pcap(packet);
|
send_pcap(packet);
|
||||||
|
@ -888,6 +935,10 @@ void route(node_t *source, vpn_packet_t *packet) {
|
||||||
if(!checklength(source, packet, ether_size))
|
if(!checklength(source, packet, ether_size))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(decrement_ttl && source != myself)
|
||||||
|
if(!do_decrement_ttl(source, packet))
|
||||||
|
return;
|
||||||
|
|
||||||
switch (routing_mode) {
|
switch (routing_mode) {
|
||||||
case RMODE_ROUTER:
|
case RMODE_ROUTER:
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,8 +38,10 @@ typedef enum fmode_t {
|
||||||
|
|
||||||
extern rmode_t routing_mode;
|
extern rmode_t routing_mode;
|
||||||
extern fmode_t forwarding_mode;
|
extern fmode_t forwarding_mode;
|
||||||
|
extern bool decrement_ttl;
|
||||||
extern bool directonly;
|
extern bool directonly;
|
||||||
extern bool overwrite_mac;
|
extern bool overwrite_mac;
|
||||||
|
extern bool broadcast;
|
||||||
extern bool priorityinheritance;
|
extern bool priorityinheritance;
|
||||||
extern int macexpire;
|
extern int macexpire;
|
||||||
extern bool pcap;
|
extern bool pcap;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
device.c -- Interaction with Solaris tun device
|
device.c -- Interaction with Solaris tun device
|
||||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||||
2001-2011 Guus Sliepen <guus@tinc-vpn.org>
|
2001-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
#define DEFAULT_DEVICE "/dev/tun"
|
#define DEFAULT_DEVICE "/dev/tun"
|
||||||
|
|
||||||
int device_fd = -1;
|
int device_fd = -1;
|
||||||
int ip_fd = -1, if_fd = -1;
|
static int ip_fd = -1, if_fd = -1;
|
||||||
char *device = NULL;
|
char *device = NULL;
|
||||||
char *iface = NULL;
|
char *iface = NULL;
|
||||||
static char *device_info = NULL;
|
static char *device_info = NULL;
|
||||||
|
@ -43,7 +43,7 @@ static char *device_info = NULL;
|
||||||
static uint64_t device_total_in = 0;
|
static uint64_t device_total_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
int ppa;
|
int ppa;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
|
@ -55,6 +55,10 @@ bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
ppa = 0;
|
ppa = 0;
|
||||||
|
|
||||||
ptr = device;
|
ptr = device;
|
||||||
|
@ -67,6 +71,10 @@ bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(ip_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Assign a new PPA and get its unit number. */
|
/* Assign a new PPA and get its unit number. */
|
||||||
if((ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0) {
|
if((ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0) {
|
||||||
logger(LOG_ERR, "Can't assign new interface: %s", strerror(errno));
|
logger(LOG_ERR, "Can't assign new interface: %s", strerror(errno));
|
||||||
|
@ -79,6 +87,10 @@ bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(if_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(ioctl(if_fd, I_PUSH, "ip") < 0) {
|
if(ioctl(if_fd, I_PUSH, "ip") < 0) {
|
||||||
logger(LOG_ERR, "Can't push IP module: %s", strerror(errno));
|
logger(LOG_ERR, "Can't push IP module: %s", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
|
@ -105,7 +117,7 @@ bool setup_device(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_device(void) {
|
static void close_device(void) {
|
||||||
close(if_fd);
|
close(if_fd);
|
||||||
close(ip_fd);
|
close(ip_fd);
|
||||||
close(device_fd);
|
close(device_fd);
|
||||||
|
@ -114,7 +126,7 @@ void close_device(void) {
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int inlen;
|
int inlen;
|
||||||
|
|
||||||
if((inlen = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
|
if((inlen = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
|
||||||
|
@ -149,7 +161,7 @@ bool read_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||||
packet->len, device_info);
|
packet->len, device_info);
|
||||||
|
|
||||||
|
@ -164,8 +176,16 @@ bool write_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t os_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
||||||
|
|
30
src/tincd.c
30
src/tincd.c
|
@ -107,6 +107,7 @@ static struct option const long_options[] = {
|
||||||
{"user", required_argument, NULL, 'U'},
|
{"user", required_argument, NULL, 'U'},
|
||||||
{"logfile", optional_argument, NULL, 4},
|
{"logfile", optional_argument, NULL, 4},
|
||||||
{"pidfile", required_argument, NULL, 5},
|
{"pidfile", required_argument, NULL, 5},
|
||||||
|
{"option", required_argument, NULL, 'o'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,18 +123,18 @@ static void usage(bool status) {
|
||||||
program_name);
|
program_name);
|
||||||
else {
|
else {
|
||||||
printf("Usage: %s [option]...\n\n", program_name);
|
printf("Usage: %s [option]...\n\n", program_name);
|
||||||
printf( " -c, --config=DIR Read configuration options from DIR.\n"
|
printf( " -c, --config=DIR Read configuration options from DIR.\n"
|
||||||
" -D, --no-detach Don't fork and detach.\n"
|
" -D, --no-detach Don't fork and detach.\n"
|
||||||
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
|
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
|
||||||
" -n, --net=NETNAME Connect to net NETNAME.\n"
|
" -n, --net=NETNAME Connect to net NETNAME.\n"
|
||||||
" -L, --mlock Lock tinc into main memory.\n"
|
" -L, --mlock Lock tinc into main memory.\n"
|
||||||
" --logfile[=FILENAME] Write log entries to a logfile.\n"
|
" --logfile[=FILENAME] Write log entries to a logfile.\n"
|
||||||
" --pidfile=FILENAME Write PID and control socket cookie to FILENAME.\n"
|
" --pidfile=FILENAME Write PID and control socket cookie to FILENAME.\n"
|
||||||
" --bypass-security Disables meta protocol security, for debugging.\n"
|
" --bypass-security Disables meta protocol security, for debugging.\n"
|
||||||
" -o [HOST.]KEY=VALUE Set global/host configuration value.\n"
|
" -o, --option[HOST.]KEY=VALUE Set global/host configuration value.\n"
|
||||||
" -R, --chroot chroot to NET dir at startup.\n"
|
" -R, --chroot chroot to NET dir at startup.\n"
|
||||||
" -U, --user=USER setuid to given USER at startup.\n" " --help Display this help and exit.\n"
|
" -U, --user=USER setuid to given USER at startup.\n" " --help Display this help and exit.\n"
|
||||||
" --version Output version information and exit.\n\n");
|
" --version Output version information and exit.\n\n");
|
||||||
printf("Report bugs to tinc@tinc-vpn.org.\n");
|
printf("Report bugs to tinc@tinc-vpn.org.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,6 +417,7 @@ int main2(int argc, char **argv) {
|
||||||
InitializeCriticalSection(&mutex);
|
InitializeCriticalSection(&mutex);
|
||||||
EnterCriticalSection(&mutex);
|
EnterCriticalSection(&mutex);
|
||||||
#endif
|
#endif
|
||||||
|
char *priority = NULL;
|
||||||
|
|
||||||
if(!detach())
|
if(!detach())
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -445,8 +447,6 @@ int main2(int argc, char **argv) {
|
||||||
|
|
||||||
/* Change process priority */
|
/* Change process priority */
|
||||||
|
|
||||||
char *priority = NULL;
|
|
||||||
|
|
||||||
if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) {
|
if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) {
|
||||||
if(!strcasecmp(priority, "Normal")) {
|
if(!strcasecmp(priority, "Normal")) {
|
||||||
if (setpriority(NORMAL_PRIORITY_CLASS) != 0) {
|
if (setpriority(NORMAL_PRIORITY_CLASS) != 0) {
|
||||||
|
@ -483,7 +483,7 @@ int main2(int argc, char **argv) {
|
||||||
/* Shutdown properly. */
|
/* Shutdown properly. */
|
||||||
|
|
||||||
ifdebug(CONNECTIONS)
|
ifdebug(CONNECTIONS)
|
||||||
dump_device_stats();
|
devops.dump_stats();
|
||||||
|
|
||||||
close_network_connections();
|
close_network_connections();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
device.c -- UML network socket
|
device.c -- UML network socket
|
||||||
Copyright (C) 2002-2005 Ivo Timmermans,
|
Copyright (C) 2002-2005 Ivo Timmermans,
|
||||||
2002-2009 Guus Sliepen <guus@tinc-vpn.org>
|
2002-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -28,19 +28,17 @@
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "route.h"
|
#include "route.h"
|
||||||
|
#include "xalloc.h"
|
||||||
|
|
||||||
int device_fd = -1;
|
|
||||||
static int listen_fd = -1;
|
static int listen_fd = -1;
|
||||||
static int request_fd = -1;
|
static int request_fd = -1;
|
||||||
static int data_fd = -1;
|
static int data_fd = -1;
|
||||||
static int write_fd = -1;
|
static int write_fd = -1;
|
||||||
static int state = 0;
|
static int state = 0;
|
||||||
char *device = NULL;
|
|
||||||
char *iface = NULL;
|
|
||||||
static char *device_info;
|
static char *device_info;
|
||||||
|
|
||||||
extern char *identname;
|
extern char *identname;
|
||||||
extern bool running;
|
extern volatile bool running;
|
||||||
|
|
||||||
static uint64_t device_total_in = 0;
|
static uint64_t device_total_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
@ -56,7 +54,7 @@ static struct request {
|
||||||
|
|
||||||
static struct sockaddr_un data_sun;
|
static struct sockaddr_un data_sun;
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
struct sockaddr_un listen_sun;
|
struct sockaddr_un listen_sun;
|
||||||
static const int one = 1;
|
static const int one = 1;
|
||||||
struct {
|
struct {
|
||||||
|
@ -79,6 +77,10 @@ bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(write_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
setsockopt(write_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
setsockopt(write_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
||||||
|
|
||||||
if(fcntl(write_fd, F_SETFL, O_NONBLOCK) < 0) {
|
if(fcntl(write_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||||
|
@ -93,6 +95,10 @@ bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(data_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
setsockopt(data_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
setsockopt(data_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
||||||
|
|
||||||
if(fcntl(data_fd, F_SETFL, O_NONBLOCK) < 0) {
|
if(fcntl(data_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||||
|
@ -120,6 +126,10 @@ bool setup_device(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
||||||
|
|
||||||
if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
|
if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||||
|
@ -169,13 +179,13 @@ void close_device(void) {
|
||||||
if(iface) free(iface);
|
if(iface) free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int inlen;
|
int inlen;
|
||||||
|
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case 0: {
|
case 0: {
|
||||||
struct sockaddr sa;
|
struct sockaddr sa;
|
||||||
int salen = sizeof sa;
|
socklen_t salen = sizeof sa;
|
||||||
|
|
||||||
request_fd = accept(listen_fd, &sa, &salen);
|
request_fd = accept(listen_fd, &sa, &salen);
|
||||||
if(request_fd < 0) {
|
if(request_fd < 0) {
|
||||||
|
@ -183,6 +193,10 @@ bool read_packet(vpn_packet_t *packet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(request_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
|
if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||||
logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno));
|
logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno));
|
||||||
running = false;
|
running = false;
|
||||||
|
@ -244,10 +258,14 @@ bool read_packet(vpn_packet_t *packet) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
logger(LOG_ERR, "Invalid value for state variable in " __FILE__);
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
if(state != 2) {
|
if(state != 2) {
|
||||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Dropping packet of %d bytes to %s: not connected to UML yet",
|
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Dropping packet of %d bytes to %s: not connected to UML yet",
|
||||||
packet->len, device_info);
|
packet->len, device_info);
|
||||||
|
@ -271,8 +289,16 @@ bool write_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t uml_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
device.c -- VDE plug
|
device.c -- VDE plug
|
||||||
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
|
Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -29,22 +29,19 @@
|
||||||
#include "route.h"
|
#include "route.h"
|
||||||
#include "xalloc.h"
|
#include "xalloc.h"
|
||||||
|
|
||||||
int device_fd = -1;
|
|
||||||
static struct vdepluglib plug;
|
static struct vdepluglib plug;
|
||||||
static struct vdeconn *conn = NULL;
|
static struct vdeconn *conn = NULL;
|
||||||
static int port = 0;
|
static int port = 0;
|
||||||
static char *group = NULL;
|
static char *group = NULL;
|
||||||
char *device = NULL;
|
|
||||||
char *iface = NULL;
|
|
||||||
static char *device_info;
|
static char *device_info;
|
||||||
|
|
||||||
extern char *identname;
|
extern char *identname;
|
||||||
extern bool running;
|
extern volatile bool running;
|
||||||
|
|
||||||
static uint64_t device_total_in = 0;
|
static uint64_t device_total_in = 0;
|
||||||
static uint64_t device_total_out = 0;
|
static uint64_t device_total_out = 0;
|
||||||
|
|
||||||
bool setup_device(void) {
|
static bool setup_device(void) {
|
||||||
libvdeplug_dynopen(plug);
|
libvdeplug_dynopen(plug);
|
||||||
|
|
||||||
if(!plug.dl_handle) {
|
if(!plug.dl_handle) {
|
||||||
|
@ -77,6 +74,10 @@ bool setup_device(void) {
|
||||||
|
|
||||||
device_fd = plug.vde_datafd(conn);
|
device_fd = plug.vde_datafd(conn);
|
||||||
|
|
||||||
|
#ifdef FD_CLOEXEC
|
||||||
|
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
#endif
|
||||||
|
|
||||||
logger(LOG_INFO, "%s is a %s", device, device_info);
|
logger(LOG_INFO, "%s is a %s", device, device_info);
|
||||||
|
|
||||||
if(routing_mode == RMODE_ROUTER)
|
if(routing_mode == RMODE_ROUTER)
|
||||||
|
@ -85,7 +86,7 @@ bool setup_device(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_device(void) {
|
static void close_device(void) {
|
||||||
if(conn)
|
if(conn)
|
||||||
plug.vde_close(conn);
|
plug.vde_close(conn);
|
||||||
|
|
||||||
|
@ -97,7 +98,7 @@ void close_device(void) {
|
||||||
free(iface);
|
free(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool read_packet(vpn_packet_t *packet) {
|
static bool read_packet(vpn_packet_t *packet) {
|
||||||
int lenin = plug.vde_recv(conn, packet->data, MTU, 0);
|
int lenin = plug.vde_recv(conn, packet->data, MTU, 0);
|
||||||
if(lenin <= 0) {
|
if(lenin <= 0) {
|
||||||
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
|
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
|
||||||
|
@ -112,7 +113,7 @@ bool read_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool write_packet(vpn_packet_t *packet) {
|
static bool write_packet(vpn_packet_t *packet) {
|
||||||
if(plug.vde_send(conn, packet->data, packet->len, 0) < 0) {
|
if(plug.vde_send(conn, packet->data, packet->len, 0) < 0) {
|
||||||
if(errno != EINTR && errno != EAGAIN) {
|
if(errno != EINTR && errno != EAGAIN) {
|
||||||
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
||||||
|
@ -127,8 +128,16 @@ bool write_packet(vpn_packet_t *packet) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_device_stats(void) {
|
static void dump_device_stats(void) {
|
||||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const devops_t vde_devops = {
|
||||||
|
.setup = setup_device,
|
||||||
|
.close = close_device,
|
||||||
|
.read = read_packet,
|
||||||
|
.write = write_packet,
|
||||||
|
.dump_stats = dump_device_stats,
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue