From e5d35e092f5a86a4eb274cc66251cc813d2cf8e7 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 26 Aug 2019 13:44:42 +0200 Subject: [PATCH] Import Upstream version 1.0.18 --- ChangeLog | 104 +++++++++++++++++++ NEWS | 9 ++ README | 4 +- configure | 2 +- configure.in | 2 +- doc/tinc.conf.5.in | 29 +++++- doc/tinc.info | 167 ++++++++++++++++++------------ doc/tinc.texi | 35 ++++++- src/Makefile.am | 2 +- src/Makefile.in | 11 +- src/connection.c | 50 +++++---- src/connection.h | 1 + src/device.h | 3 +- src/multicast_device.c | 228 +++++++++++++++++++++++++++++++++++++++++ src/net.c | 24 ++--- src/net_setup.c | 17 ++- src/protocol_misc.c | 10 +- src/route.c | 2 +- src/vde_device.c | 4 +- 19 files changed, 581 insertions(+), 123 deletions(-) create mode 100644 src/multicast_device.c diff --git a/ChangeLog b/ChangeLog index 49524d0..6d5f5f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,107 @@ +commit 482c6119a7ae80f320e5b519ef2e785e04a77b8e +Author: Guus Sliepen +Date: Sun Mar 25 15:32:26 2012 +0100 + + Releasing 1.0.18. + +commit 64c657b32d1eb34eb669c6d5b0ec26c1a643b194 +Author: Guus Sliepen +Date: Sun Mar 25 15:30:58 2012 +0100 + + Mark DecrementTTL option experimental. + +commit f71ce341800739c7cdee01d7cf025e7492da22ac +Author: Guus Sliepen +Date: Sun Mar 25 15:17:50 2012 +0100 + + Fix return type of vde_recv() as well. + + In this case it is not really necessary as the conversion to int will already + take care of ensuring the return value is treated as signed. + +commit 6225b1884a25af4debc2d0821a4c377ddbaec696 +Author: Guus Sliepen +Date: Sun Mar 25 14:55:56 2012 +0100 + + Document OpenBSD "ifconfig link0" and Linux "ip tuntap" commands. + +commit 399835385380d485416d6d59a8f27ce71f1db644 +Author: Guus Sliepen +Date: Sun Mar 25 14:46:50 2012 +0100 + + Fix some more compiler warnings. + +commit cfe6558d4ba4f572311aeafd62737f6f2692ad86 +Author: Guus Sliepen +Date: Sun Mar 25 14:00:21 2012 +0100 + + Fix return value type of vde_send(). + + The libvdeplug_dyn.h header file incorrectly declares the return type of + vde_send() to size_t, while in reality it is ssize_t. + +commit 95968c67f9df9102ddbce5b7c8d34107989ad51a +Author: Guus Sliepen +Date: Sun Mar 25 13:58:14 2012 +0100 + + Fix compiler warnings. + +commit e2d1b0b899ef66cd7ff227549e58b96c292f784e +Author: Guus Sliepen +Date: Sun Mar 25 13:42:10 2012 +0100 + + Allow scoped addresses to be used for IPv6 multicast socket. + +commit 251204063255d95910f9a079015e2f9b428fd983 +Author: Guus Sliepen +Date: Sun Mar 25 13:40:55 2012 +0100 + + Add #ifdefs in case not all platforms support IPv4 and IPv6 multicast. + +commit b5e3bf1a85462f0c41638c11305d28f87af24395 +Author: Guus Sliepen +Date: Fri Mar 23 13:18:36 2012 +0100 + + Set default value of DecrementTTL to "no". + + Decrementing the TTL causes IPv6 to fail when Mode = switch, and there may be + other unforeseen side-effects. + +commit c373de2e9812700c0568640727ad917b6fc7d758 +Author: Guus Sliepen +Date: Wed Mar 21 17:00:53 2012 +0100 + + Add support for multicast communication with UML/QEMU/KVM. + + DeviceType = multicast allows one to specify a multicast address and port with + a Device statement. Tinc will then read/send packets to that multicast group + instead of to a tun/tap device. This allows interaction with UML, QEMU and KVM + instances that are listening on the same group. + +commit a7dbb50c23f447a23b543c92ec096ff178bc2de3 +Author: Guus Sliepen +Date: Wed Mar 21 13:20:15 2012 +0100 + + Allow a port to be specified in BindToAddress statements. + + This can be used to let tinc listen on multiple ports for incoming connections. + +commit 80e15d8b96e5313b33c91003b1f75d7f6db9924e +Author: Guus Sliepen +Date: Tue Mar 20 23:49:16 2012 +0100 + + Always try next Address when an outgoing connection fails to authenticate. + + When making outgoing connections, tinc goes through the list of Addresses and + tries all of them until one succeeds. However, before it would consider + establishing a TCP connection a success, even when the authentication failed. + This would be a problem if the first Address would point to a hostname and port + combination that belongs to the wrong tinc node, or perhaps even to a non-tinc + service, causing tinc to endlessly try this Address instead of moving to the + next one. + + Problem found by Delf Eldkraft. + commit 28a1501b9a8b4c730f7f965d6b2e8fc50feba261 Author: Guus Sliepen Date: Sat Mar 10 13:31:36 2012 +0100 diff --git a/NEWS b/NEWS index 6e9a100..e2215fc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +Version 1.0.18 March 25 2012 + + * Fixed IPv6 in switch mode by turning off DecrementTTL by default. + + * Allow a port number to be specified in BindToAddress, which also allows tinc + to listen on multiple ports. + + * Add support for multicast communication with UML/QEMU/KVM. + Version 1.0.17 March 10 2012 * The DeviceType option can now be used to select dummy, raw socket, UML and diff --git a/README b/README index 3c23b06..ed1d2b4 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is the README file for tinc version 1.0.17. Installation +This is the README file for tinc version 1.0.18. Installation instructions may be found in the INSTALL file. tinc is Copyright (C) 1998-2012 by: @@ -55,7 +55,7 @@ should be changed into "Device", and "Device" should be changed into Compatibility ------------- -Version 1.0.17 is compatible with 1.0pre8, 1.0 and later, but not with older +Version 1.0.18 is compatible with 1.0pre8, 1.0 and later, but not with older versions of tinc. diff --git a/configure b/configure index c91ddc3..c53c38e 100755 --- a/configure +++ b/configure @@ -2740,7 +2740,7 @@ fi # Define the identity of the package. PACKAGE=tinc - VERSION=1.0.17 + VERSION=1.0.18 cat >>confdefs.h <<_ACEOF diff --git a/configure.in b/configure.in index 5ff4a3e..2ea69f6 100644 --- a/configure.in +++ b/configure.in @@ -3,7 +3,7 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) AC_INIT AC_CONFIG_SRCDIR([src/tincd.c]) -AM_INIT_AUTOMAKE(tinc, 1.0.17) +AM_INIT_AUTOMAKE(tinc, 1.0.18) AC_CONFIG_HEADERS([config.h]) AM_MAINTAINER_MODE diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in index a6ae4f5..8034418 100644 --- a/doc/tinc.conf.5.in +++ b/doc/tinc.conf.5.in @@ -129,7 +129,7 @@ If is selected, then depending on the operating system both IPv4 and IPv6 or just IPv6 listening sockets will be created. -.It Va BindToAddress Li = Ar address Bq experimental +.It Va BindToAddress Li = Ar address Oo Ar port Oc Bq experimental If your computer has more than one IPv4 or IPv6 address, .Nm tinc will by default listen on all of them for incoming connections. @@ -137,7 +137,16 @@ Multiple .Va BindToAddress variables may be specified, in which case listening sockets for each specified address are made. - +.Pp +If no +.Ar port +is specified, the socket will be bound to the port specified by the +.Va Port +option, or to port 655 if neither is given. +To only bind to a specific port but not to a specific address, use +.Li * +for the +.Ar address . .Pp This option may not work on all platforms. @@ -171,13 +180,15 @@ If you don't specify a host with won't try to connect to other daemons at all, and will instead just listen for incoming connections. -.It Va DecrementTTL Li = yes | no Po yes Pc +.It Va DecrementTTL Li = yes | no Po no Pc Bq experimental 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. +.Pp +Do not use this option if you use switch mode and want to use IPv6. .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. @@ -210,6 +221,16 @@ 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 multicast +Open a multicast UDP socket and bind it to the address and port (separated by spaces) and optionally a TTL value specified using +.Va Device . +Packets are read from and written to this multicast socket. +This can be used to connect to UML, QEMU or KVM instances listening on the same multicast address. +Do NOT connect multiple +.Nm tinc +daemons to the same multicast address, this will very likely cause routing loops. +Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured. + .It uml Pq not compiled in by default Create a UNIX socket with the filename specified by .Va Device , @@ -452,7 +473,7 @@ Since host configuration files only contain public keys, no secrets are revealed by sending out this information. .Bl -tag -width indent -.It Va Address Li = Ar address Oo port Oc Bq recommended +.It Va Address Li = Ar address Oo Ar port Oc Bq recommended The IP address or hostname of this tinc daemon on the real network. This will only be used when trying to make an outgoing connection to this tinc daemon. Optionally, a port can be specified to use for this address. diff --git a/doc/tinc.info b/doc/tinc.info index 7039e00..f2d7567 100644 --- a/doc/tinc.info +++ b/doc/tinc.info @@ -684,12 +684,17 @@ AddressFamily = (any) system both IPv4 and IPv6 or just IPv6 listening sockets will be created. -BindToAddress =
[experimental] +BindToAddress =
[] [experimental] If your computer has more than one IPv4 or IPv6 address, tinc will by default listen on all of them for incoming connections. Multiple BindToAddress variables may be specified, in which case listening sockets for each specified address are made. + If no PORT is specified, the socket will be bound to the port + specified by the Port option, or to port 655 if neither is given. + To only bind to a specific port but not to a specific address, use + "*" for the ADDRESS. + This option may not work on all platforms. BindToInterface = [experimental] @@ -715,13 +720,15 @@ ConnectTo = connect to other daemons at all, and will instead just listen for incoming connections. -DecrementTTL = (yes) +DecrementTTL = (no) [experimental] 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. + Do not use this option if you use switch mode and want to use IPv6. + Device = (`/dev/tap0', `/dev/net/tun' or other depending on platform) The virtual network device to use. Tinc will automatically detect what kind of device it is. Note that you can only use one device @@ -748,6 +755,17 @@ DeviceType = (platform dependent) socket. However, at least on Linux, the operating system does not process IP packets destined for the local host. + multicast + Open a multicast UDP socket and bind it to the address and + port (separated by spaces) and optionally a TTL value + specified using DEVICE. Packets are read from and written to + this multicast socket. This can be used to connect to UML, + QEMU or KVM instances listening on the same multicast address. + Do NOT connect multiple tinc daemons to the same multicast + address, this will very likely cause routing loops. Also + note that this can cause decrypted VPN packets to be sent out + on a real network if misconfigured. + uml (not compiled in by default) Create a UNIX socket with the filename specified by DEVICE, or `/var/run/NETNAME.umlsocket' if not specified. Tinc will @@ -2246,6 +2264,19 @@ Solaris `ifconfig' INTERFACE `inet6 plumb up' Darwin (MacOS/X) `ifconfig' INTERFACE `inet6' ADDRESS `prefixlen' PREFIXLENGTH Windows `netsh interface ipv6 add address' INTERFACE `static' ADDRESS/PREFIXLENGTH + On some platforms, when running tinc in switch mode, the VPN +interface must be set to tap mode with an ifconfig command: + +OpenBSD `ifconfig' INTERFACE `link0' + + On Linux, it is possible to create a persistent tun/tap interface +which will continue to exist even if tinc quit, although this is +normally not required. It can be useful to set up a tun/tap interface +owned by a non-root user, so tinc can be started without needing any +root privileges at all. + +Linux `ip tuntap add dev' INTERFACE `mode' TUN|TAP `user' USERNAME +  File: tinc.info, Node: Routes, Prev: Interface configuration, Up: Platform specific information @@ -2346,9 +2377,9 @@ Concept Index * BindToAddress: Main configuration variables. (line 12) * BindToInterface: Main configuration variables. - (line 20) + (line 25) * Broadcast: Main configuration variables. - (line 28) + (line 33) * Cabal: Security. (line 6) * CHAL_REPLY: Authentication protocol. (line 10) @@ -2367,27 +2398,27 @@ Concept Index (line 24) * connection: The connection. (line 6) * ConnectTo: Main configuration variables. - (line 32) + (line 37) * daemon: Running tinc. (line 11) * data-protocol: The meta-connection. (line 18) * debug level: Runtime options. (line 17) * debug levels: Debug levels. (line 6) * DecrementTTL: Main configuration variables. - (line 43) + (line 48) * DEL_EDGE: The meta-protocol. (line 47) * DEL_SUBNET: The meta-protocol. (line 47) * DEVICE: Scripts. (line 55) * Device: Main configuration variables. - (line 50) + (line 57) * device files: Device files. (line 6) * DeviceType: Main configuration variables. - (line 57) + (line 64) * Digest: Host configuration variables. (line 29) * DirectOnly: Main configuration variables. - (line 111) + (line 129) * dummy: Main configuration variables. - (line 64) + (line 71) * encapsulating: The UDP tunnel. (line 30) * encryption: Encryption of network packets. (line 6) @@ -2395,44 +2426,46 @@ Concept Index * example: Example configuration. (line 6) * Forwarding: Main configuration variables. - (line 118) + (line 136) * frame type: The UDP tunnel. (line 6) * GraphDumpFile: Main configuration variables. - (line 138) + (line 156) * Hostnames: Main configuration variables. - (line 146) + (line 164) * hub: Main configuration variables. - (line 198) + (line 216) * ID: Authentication protocol. (line 10) * IndirectData: Host configuration variables. (line 34) * INTERFACE: Scripts. (line 58) * Interface: Main configuration variables. - (line 156) + (line 174) * IRC: Contact information. (line 9) * key generation: Generating keypairs. (line 6) * KEY_CHANGED: The meta-protocol. (line 64) * KeyExpire: Main configuration variables. - (line 203) + (line 221) * libraries: Libraries. (line 6) * license: OpenSSL. (line 36) * LocalDiscovery: Main configuration variables. - (line 164) + (line 182) * lzo: lzo. (line 6) * MACExpire: Main configuration variables. - (line 209) + (line 227) * MACLength: Host configuration variables. (line 42) * meta-protocol: The meta-connection. (line 18) * META_KEY: Authentication protocol. (line 10) * Mode: Main configuration variables. - (line 175) + (line 193) +* multicast: Main configuration variables. + (line 83) * multiple networks: Multiple networks. (line 6) * NAME: Scripts. (line 52) * Name: Main configuration variables. - (line 214) + (line 232) * netmask: Network interfaces. (line 34) * NETNAME: Scripts. (line 49) * netname: Multiple networks. (line 6) @@ -2445,9 +2478,9 @@ Concept Index (line 67) * PING: The meta-protocol. (line 89) * PingInterval: Main configuration variables. - (line 219) + (line 237) * PingTimeout: Main configuration variables. - (line 223) + (line 241) * platforms: Supported platforms. (line 6) * PMTU: Host configuration variables. (line 47) @@ -2458,30 +2491,30 @@ Concept Index (line 55) * port numbers: Other files. (line 17) * PriorityInheritance: Main configuration variables. - (line 229) + (line 247) * private: Virtual Private Networks. (line 10) * PrivateKey: Main configuration variables. - (line 234) + (line 252) * PrivateKeyFile: Main configuration variables. - (line 240) + (line 258) * ProcessPriority: Main configuration variables. - (line 248) + (line 266) * PublicKey: Host configuration variables. (line 59) * PublicKeyFile: Host configuration variables. (line 62) * raw_socket: Main configuration variables. - (line 69) + (line 76) * release: Supported platforms. (line 14) * REMOTEADDRESS: Scripts. (line 67) * REMOTEPORT: Scripts. (line 70) * ReplayWindow: Main configuration variables. - (line 253) + (line 271) * REQ_KEY: The meta-protocol. (line 64) * requirements: Libraries. (line 6) * router: Main configuration variables. - (line 178) + (line 196) * runtime options: Runtime options. (line 9) * scalability: tinc. (line 19) * scripts: Scripts. (line 6) @@ -2489,7 +2522,7 @@ Concept Index (line 18) * signals: Signals. (line 6) * StrictSubnets: Main configuration variables. - (line 264) + (line 282) * SUBNET: Scripts. (line 74) * Subnet: Host configuration variables. (line 74) @@ -2497,7 +2530,7 @@ Concept Index (line 97) * SVPN: Security. (line 11) * switch: Main configuration variables. - (line 187) + (line 205) * TCP: The meta-connection. (line 10) * TCPonly: Host configuration variables. (line 104) @@ -2509,24 +2542,24 @@ Concept Index * tincd: tinc. (line 14) * traditional VPNs: tinc. (line 19) * tunifhead: Main configuration variables. - (line 100) + (line 118) * TunnelServer: Main configuration variables. - (line 269) + (line 287) * tunnohead: Main configuration variables. - (line 94) + (line 112) * UDP <1>: Encryption of network packets. (line 12) * UDP: The UDP tunnel. (line 30) * UDPRcvBuf: Main configuration variables. - (line 276) + (line 294) * UDPSndBuf: Main configuration variables. - (line 281) + (line 299) * UML: Main configuration variables. - (line 76) + (line 94) * Universal tun/tap: Configuration of Linux kernels. (line 6) * VDE: Main configuration variables. - (line 81) + (line 99) * virtual: Virtual Private Networks. (line 18) * virtual network device: The UDP tunnel. (line 6) @@ -2572,34 +2605,34 @@ Node: Multiple networks21169 Node: How connections work22595 Node: Configuration files23817 Node: Main configuration variables25204 -Node: Host configuration variables38105 -Node: Scripts43516 -Node: How to configure46286 -Node: Generating keypairs47549 -Node: Network interfaces48048 -Node: Example configuration49896 -Node: Running tinc55219 -Node: Runtime options55809 -Node: Signals59109 -Node: Debug levels60301 -Node: Solving problems61237 -Node: Error messages62789 -Node: Sending bug reports66802 -Node: Technical information67754 -Node: The connection67985 -Node: The UDP tunnel68297 -Node: The meta-connection71358 -Node: The meta-protocol72827 -Node: Security77836 -Node: Authentication protocol78966 -Node: Encryption of network packets83970 -Node: Security issues85343 -Node: Platform specific information86960 -Node: Interface configuration87188 -Node: Routes89087 -Node: About us91003 -Node: Contact information91178 -Node: Authors91582 -Node: Concept Index91987 +Node: Host configuration variables39057 +Node: Scripts44468 +Node: How to configure47238 +Node: Generating keypairs48501 +Node: Network interfaces49000 +Node: Example configuration50848 +Node: Running tinc56171 +Node: Runtime options56761 +Node: Signals60061 +Node: Debug levels61253 +Node: Solving problems62189 +Node: Error messages63741 +Node: Sending bug reports67754 +Node: Technical information68706 +Node: The connection68937 +Node: The UDP tunnel69249 +Node: The meta-connection72310 +Node: The meta-protocol73779 +Node: Security78788 +Node: Authentication protocol79918 +Node: Encryption of network packets84922 +Node: Security issues86295 +Node: Platform specific information87912 +Node: Interface configuration88140 +Node: Routes90593 +Node: About us92509 +Node: Contact information92684 +Node: Authors93088 +Node: Concept Index93493  End Tag Table diff --git a/doc/tinc.texi b/doc/tinc.texi index aedde3f..c8eea1f 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -756,12 +756,16 @@ If any is selected, then depending on the operating system both IPv4 and IPv6 or just IPv6 listening sockets will be created. @cindex BindToAddress -@item BindToAddress = <@var{address}> [experimental] +@item BindToAddress = <@var{address}> [<@var{port}>] [experimental] If your computer has more than one IPv4 or IPv6 address, tinc will by default listen on all of them for incoming connections. Multiple BindToAddress variables may be specified, in which case listening sockets for each specified address are made. +If no @var{port} is specified, the socket will be bound to the port specified by the Port option, +or to port 655 if neither is given. +To only bind to a specific port but not to a specific address, use "*" for the @var{address}. + This option may not work on all platforms. @cindex BindToInterface @@ -790,12 +794,14 @@ tinc won't try to connect to other daemons at all, and will instead just listen for incoming connections. @cindex DecrementTTL -@item DecrementTTL = (yes) +@item DecrementTTL = (no) [experimental] 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. +Do not use this option if you use switch mode and want to use IPv6. + @cindex Device @item Device = <@var{device}> (@file{/dev/tap0}, @file{/dev/net/tun} or other depending on platform) The virtual network device to use. @@ -826,6 +832,14 @@ 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 multicast +@item multicast +Open a multicast UDP socket and bind it to the address and port (separated by spaces) and optionally a TTL value specified using @var{Device}. +Packets are read from and written to this multicast socket. +This can be used to connect to UML, QEMU or KVM instances listening on the same multicast address. +Do NOT connect multiple tinc daemons to the same multicast address, this will very likely cause routing loops. +Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured. + @cindex UML @item uml (not compiled in by default) Create a UNIX socket with the filename specified by @@ -2390,7 +2404,6 @@ For IPv4 addresses: @tab @code{netsh interface ip set address} @var{interface} @code{static} @var{address} @var{netmask} @end multitable - For IPv6 addresses: @multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} @@ -2412,6 +2425,22 @@ For IPv6 addresses: @tab @code{netsh interface ipv6 add address} @var{interface} @code{static} @var{address}/@var{prefixlength} @end multitable +On some platforms, when running tinc in switch mode, the VPN interface must be set to tap mode with an ifconfig command: + +@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@item OpenBSD +@tab @code{ifconfig} @var{interface} @code{link0} +@end multitable + +On Linux, it is possible to create a persistent tun/tap interface which will +continue to exist even if tinc quit, although this is normally not required. +It can be useful to set up a tun/tap interface owned by a non-root user, so +tinc can be started without needing any root privileges at all. + +@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@item Linux +@tab @code{ip tuntap add dev} @var{interface} @code{mode} @var{tun|tap} @code{user} @var{username} +@end multitable @c ================================================================== @node Routes diff --git a/src/Makefile.am b/src/Makefile.am index aca0e2d..cd44eb6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,7 @@ EXTRA_DIST = linux/device.c bsd/device.c solaris/device.c cygwin/device.c mingw/ tincd_SOURCES = conf.c connection.c edge.c event.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 \ protocol_key.c protocol_subnet.c route.c subnet.c tincd.c \ - dummy_device.c raw_socket_device.c + dummy_device.c raw_socket_device.c multicast_device.c if UML tincd_SOURCES += uml_device.c diff --git a/src/Makefile.in b/src/Makefile.in index d1d3989..da7f367 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -60,7 +60,8 @@ am__tincd_SOURCES_DIST = conf.c connection.c edge.c event.c graph.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 dummy_device.c \ - raw_socket_device.c uml_device.c vde_device.c bsd/tunemu.c + raw_socket_device.c multicast_device.c uml_device.c \ + vde_device.c bsd/tunemu.c @UML_TRUE@am__objects_1 = uml_device.$(OBJEXT) @VDE_TRUE@am__objects_2 = vde_device.$(OBJEXT) @TUNEMU_TRUE@am__objects_3 = tunemu.$(OBJEXT) @@ -73,8 +74,8 @@ am_tincd_OBJECTS = conf.$(OBJEXT) connection.$(OBJEXT) edge.$(OBJEXT) \ protocol_misc.$(OBJEXT) protocol_key.$(OBJEXT) \ protocol_subnet.$(OBJEXT) route.$(OBJEXT) subnet.$(OBJEXT) \ tincd.$(OBJEXT) dummy_device.$(OBJEXT) \ - raw_socket_device.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) + raw_socket_device.$(OBJEXT) multicast_device.$(OBJEXT) \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) nodist_tincd_OBJECTS = device.$(OBJEXT) tincd_OBJECTS = $(am_tincd_OBJECTS) $(nodist_tincd_OBJECTS) tincd_DEPENDENCIES = $(top_builddir)/lib/libvpn.a @@ -196,7 +197,8 @@ tincd_SOURCES = conf.c connection.c edge.c event.c graph.c logger.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 dummy_device.c raw_socket_device.c \ - $(am__append_1) $(am__append_2) $(am__append_3) + multicast_device.c $(am__append_1) $(am__append_2) \ + $(am__append_3) nodist_tincd_SOURCES = device.c DEFAULT_INCLUDES = noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h logger.h meta.h net.h netutl.h node.h process.h \ @@ -296,6 +298,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meta.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_device.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_packet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_setup.Po@am__quote@ diff --git a/src/connection.c b/src/connection.c index 612587d..9b752fa 100644 --- a/src/connection.c +++ b/src/connection.c @@ -60,44 +60,54 @@ connection_t *new_connection(void) { return c; } -void free_connection(connection_t *c) { - if(c->name) - free(c->name); +void free_connection_partially(connection_t *c) { + free(c->inkey); + free(c->outkey); + free(c->mychallenge); + free(c->hischallenge); + free(c->outbuf); - if(c->hostname) - free(c->hostname); + c->inkey = NULL; + c->outkey = NULL; + c->mychallenge = NULL; + c->hischallenge = NULL; + c->outbuf = NULL; - if(c->inkey) - free(c->inkey); - - if(c->outkey) - free(c->outkey); + c->buflen = 0; + c->reqlen = 0; + c->tcplen = 0; + c->allow_request = 0; + c->outbuflen = 0; + c->outbufsize = 0; + c->outbufstart = 0; if(c->inctx) { EVP_CIPHER_CTX_cleanup(c->inctx); free(c->inctx); + c->inctx = NULL; } if(c->outctx) { EVP_CIPHER_CTX_cleanup(c->outctx); free(c->outctx); + c->outctx = NULL; } - if(c->mychallenge) - free(c->mychallenge); + if(c->rsa_key) { + RSA_free(c->rsa_key); + c->rsa_key = NULL; + } +} - if(c->hischallenge) - free(c->hischallenge); +void free_connection(connection_t *c) { + free_connection_partially(c); + + free(c->name); + free(c->hostname); if(c->config_tree) exit_configuration(&c->config_tree); - if(c->outbuf) - free(c->outbuf); - - if(c->rsa_key) - RSA_free(c->rsa_key); - free(c); } diff --git a/src/connection.h b/src/connection.h index 544c2d0..fbe4e02 100644 --- a/src/connection.h +++ b/src/connection.h @@ -107,6 +107,7 @@ extern void init_connections(void); extern void exit_connections(void); extern connection_t *new_connection(void) __attribute__ ((__malloc__)); extern void free_connection(connection_t *); +extern void free_connection_partially(connection_t *); extern void connection_add(connection_t *); extern void connection_del(connection_t *); extern void dump_connections(void); diff --git a/src/device.h b/src/device.h index eaeca18..a3c2914 100644 --- a/src/device.h +++ b/src/device.h @@ -1,7 +1,7 @@ /* device.h -- generic header for device.c Copyright (C) 2001-2005 Ivo Timmermans - 2001-2011 Guus Sliepen + 2001-2012 Guus Sliepen 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 @@ -39,6 +39,7 @@ typedef struct 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 multicast_devops; extern const devops_t uml_devops; extern const devops_t vde_devops; extern devops_t devops; diff --git a/src/multicast_device.c b/src/multicast_device.c new file mode 100644 index 0000000..0b232db --- /dev/null +++ b/src/multicast_device.c @@ -0,0 +1,228 @@ +/* + device.c -- multicast socket + Copyright (C) 2002-2005 Ivo Timmermans, + 2002-2012 Guus Sliepen + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "conf.h" +#include "device.h" +#include "net.h" +#include "logger.h" +#include "netutl.h" +#include "utils.h" +#include "route.h" +#include "xalloc.h" + +static char *device_info; + +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; + +static struct addrinfo *ai = NULL; +static mac_t ignore_src = {{0}}; + +static bool setup_device(void) { + char *host; + char *port; + char *space; + int ttl = 1; + + device_info = "multicast socket"; + + get_config_string(lookup_config(config_tree, "Interface"), &iface); + + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + logger(LOG_ERR, "Device variable required for %s", device_info); + return false; + } + + host = xstrdup(device); + space = strchr(host, ' '); + if(!space) { + logger(LOG_ERR, "Port number required for %s", device_info); + return false; + } + + *space++ = 0; + port = space; + space = strchr(port, ' '); + + if(space) { + *space++ = 0; + ttl = atoi(space); + } + + ai = str2addrinfo(host, port, SOCK_DGRAM); + if(!ai) + return false; + + device_fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP); + if(device_fd < 0) { + logger(LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno)); + return false; + } + +#ifdef FD_CLOEXEC + fcntl(device_fd, F_SETFD, FD_CLOEXEC); +#endif + + static const int one = 1; + setsockopt(device_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof one); + + if(bind(device_fd, ai->ai_addr, ai->ai_addrlen)) { + closesocket(device_fd); + logger(LOG_ERR, "Can't bind to %s %s: %s", host, port, sockstrerror(sockerrno)); + return false; + } + + switch(ai->ai_family) { +#ifdef IP_ADD_MEMBERSHIP + case AF_INET: { + struct ip_mreq mreq; + struct sockaddr_in in; + memcpy(&in, ai->ai_addr, sizeof in); + mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof mreq)) { + logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno)); + closesocket(device_fd); + return false; + } +#ifdef IP_MULTICAST_LOOP + setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof one); +#endif +#ifdef IP_MULTICAST_TTL + setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof ttl); +#endif + } break; +#endif + +#ifdef IPV6_JOIN_GROUP + case AF_INET6: { + struct ipv6_mreq mreq; + struct sockaddr_in6 in6; + memcpy(&in6, ai->ai_addr, sizeof in6); + memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof mreq.ipv6mr_multiaddr); + mreq.ipv6mr_interface = in6.sin6_scope_id; + if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof mreq)) { + logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno)); + closesocket(device_fd); + return false; + } +#ifdef IPV6_MULTICAST_LOOP + setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof one); +#endif +#ifdef IPV6_MULTICAST_HOPS + setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof ttl); +#endif + } break; +#endif + + default: + logger(LOG_ERR, "Multicast for address family %hx unsupported", ai->ai_family); + closesocket(device_fd); + return false; + } + + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; +} + +static void close_device(void) { + close(device_fd); + + free(device); + free(iface); + + if(ai) + freeaddrinfo(ai); +} + +static bool read_packet(vpn_packet_t *packet) { + int lenin; + + if((lenin = recv(device_fd, packet->data, MTU, 0)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + if(!memcmp(&ignore_src, packet->data + 6, sizeof ignore_src)) { + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info); + packet->len = 0; + return true; + } + + packet->len = lenin; + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); + + return true; +} + +static bool write_packet(vpn_packet_t *packet) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", + packet->len, device_info); + + if(sendto(device_fd, packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + device_total_out += packet->len; + + memcpy(&ignore_src, packet->data + 6, sizeof ignore_src); + + return true; +} + +static void dump_device_stats(void) { + 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 out: %10"PRIu64, device_total_out); +} + +const devops_t multicast_devops = { + .setup = setup_device, + .close = close_device, + .read = read_packet, + .write = write_packet, + .dump_stats = dump_device_stats, +}; + +#if 0 + +static bool not_supported(void) { + logger(LOG_ERR, "Raw socket device not supported on this platform"); + return false; +} + +const devops_t multicast_devops = { + .setup = not_supported, + .close = NULL, + .read = NULL, + .write = NULL, + .dump_stats = NULL, +}; +#endif diff --git a/src/net.c b/src/net.c index 6979083..9799fea 100644 --- a/src/net.c +++ b/src/net.c @@ -204,18 +204,14 @@ void terminate_connection(connection_t *c, bool report) { } } + free_connection_partially(c); + /* Check if this was our outgoing connection */ if(c->outgoing) { - retry_outgoing(c->outgoing); - c->outgoing = NULL; + c->status.remove = false; + do_outgoing_connection(c); } - - free(c->outbuf); - c->outbuf = NULL; - c->outbuflen = 0; - c->outbufsize = 0; - c->outbufstart = 0; } /* @@ -238,7 +234,7 @@ static void check_dead_connections(void) { if(c->status.active) { if(c->status.pinged) { ifdebug(CONNECTIONS) logger(LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", - c->name, c->hostname, now - c->last_ping_time); + c->name, c->hostname, (long)now - c->last_ping_time); c->status.timeout = true; terminate_connection(c, true); } else if(c->last_ping_time + pinginterval <= now) { @@ -267,7 +263,7 @@ static void check_dead_connections(void) { if(c->status.active) { ifdebug(CONNECTIONS) logger(LOG_INFO, "%s (%s) could not flush for %ld seconds (%d bytes remaining)", - c->name, c->hostname, now - c->last_flushed_time, c->outbuflen); + c->name, c->hostname, (long)now - c->last_flushed_time, c->outbuflen); c->status.timeout = true; terminate_connection(c, true); } @@ -290,9 +286,11 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) { /* check input from kernel */ if(device_fd >= 0 && FD_ISSET(device_fd, readset)) { if(devops.read(&packet)) { - errors = 0; - packet.priority = 0; - route(myself, &packet); + if(packet.len) { + errors = 0; + packet.priority = 0; + route(myself, &packet); + } } else { usleep(errors * 50000); errors++; diff --git a/src/net_setup.c b/src/net_setup.c index 2684514..4b90737 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -548,6 +548,8 @@ static bool setup_myself(void) { devops = dummy_devops; else if(!strcasecmp(type, "raw_socket")) devops = raw_socket_devops; + else if(!strcasecmp(type, "multicast")) + devops = multicast_devops; #ifdef ENABLE_UML else if(!strcasecmp(type, "uml")) devops = uml_devops; @@ -587,12 +589,25 @@ static bool setup_myself(void) { if(cfg) cfg = lookup_config_next(config_tree, cfg); + char *port = myport; + + if(address) { + char *space = strchr(address, ' '); + if(space) { + *space++ = 0; + port = space; + } + + if(!strcmp(address, "*")) + *address = 0; + } + 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); + err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai); free(address); if(err || !ai) { diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 3d405bc..05afbce 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -1,7 +1,7 @@ /* protocol_misc.c -- handle the meta-protocol, miscellaneous functions Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2009 Guus Sliepen + 2000-2012 Guus Sliepen 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 @@ -111,8 +111,14 @@ bool pong_h(connection_t *c) { /* Succesful connection, reset timeout if this is an outgoing connection. */ - if(c->outgoing) + if(c->outgoing) { c->outgoing->timeout = 0; + c->outgoing->cfg = NULL; + if(c->outgoing->ai) + freeaddrinfo(c->outgoing->ai); + c->outgoing->ai = NULL; + c->outgoing->aip = NULL; + } return true; } diff --git a/src/route.c b/src/route.c index 051deff..6eadb88 100644 --- a/src/route.c +++ b/src/route.c @@ -34,7 +34,7 @@ rmode_t routing_mode = RMODE_ROUTER; fmode_t forwarding_mode = FMODE_INTERNAL; -bool decrement_ttl = true; +bool decrement_ttl = false; bool directonly = false; bool priorityinheritance = false; int macexpire = 600; diff --git a/src/vde_device.c b/src/vde_device.c index 258945e..e69ae80 100644 --- a/src/vde_device.c +++ b/src/vde_device.c @@ -99,7 +99,7 @@ static void close_device(void) { } static bool read_packet(vpn_packet_t *packet) { - int lenin = plug.vde_recv(conn, packet->data, MTU, 0); + int lenin = (ssize_t)plug.vde_recv(conn, packet->data, MTU, 0); if(lenin <= 0) { logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno)); running = false; @@ -114,7 +114,7 @@ static bool read_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((ssize_t)plug.vde_send(conn, packet->data, packet->len, 0) < 0) { if(errno != EINTR && errno != EAGAIN) { logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); running = false;