AUTOMAKE_OPTIONS = gnu
-SUBDIRS = m4 src doc gui test
+SUBDIRS = m4 src doc test
ACLOCAL_AMFLAGS = -I m4
ChangeLog:
git log > ChangeLog
-
-deb:
- dpkg-buildpackage -rfakeroot
-
-rpm: dist
- cp $(distdir).tar.gz /usr/src/redhat/SOURCES/
- cp redhat/tinc.spec /usr/src/redhat/SOURCES/
- cd /usr/src/redhat/SOURCES/ && rpm -bb tinc.spec
-
-release:
- rm -f ChangeLog
- $(MAKE) ChangeLog
- echo "Please edit the NEWS file now..."
- /usr/bin/editor NEWS
- $(MAKE) dist
;;
esac
-AC_ARG_ENABLE(uml,
- AS_HELP_STRING([--enable-uml], [enable support for User Mode Linux]),
- [ AS_IF([test "x$enable_uml" = "xyes"],
- [ AC_DEFINE(ENABLE_UML, 1, [Support for UML])
- uml=true
- ],
- [uml=false])
- ],
- [uml=false]
-)
-
-AC_ARG_ENABLE(vde,
- AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]),
- [ AS_IF([test "x$enable_vde" = "xyes"],
- [ 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
- ],
- [vde=false])
- ],
- [vde=false]
-)
-
-AC_ARG_ENABLE(tunemu,
- AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]),
- [ AS_IF([test "x$enable_tunemu" = "xyes"],
- [ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu])
- tunemu=true
- ],
- [tunemu=false])
- ],
- [tunemu=false]
-)
-
AC_ARG_WITH(windows2000,
AS_HELP_STRING([--with-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]),
[ AS_IF([test "x$with_windows2000" = "xyes"],
dnl These are defined in files in m4/
-dnl AC_ARG_WITH(libgcrypt, AC_HELP_STRING([--with-libgcrypt], [enable use of libgcrypt instead of OpenSSL])], [])
-
-tinc_CURSES
-tinc_READLINE
tinc_ZLIB
tinc_LZO
-if test -n "$with_libgcrypt"; then
- gcrypt=true
- tinc_LIBGCRYPT
-else
- openssl=true
- tinc_OPENSSL
-fi
+tinc_OPENSSL
-AM_CONDITIONAL(OPENSSL, test -n "$openssl")
-AM_CONDITIONAL(GCRYPT, test -n "$gcrypt")
-
-dnl Check if support for jumbograms is requested
-AC_ARG_ENABLE(jumbograms,
- AS_HELP_STRING([--enable-jumbograms], [enable support for jumbograms (packets up to 9000 bytes)]),
- [ AS_IF([test "x$enable_jumbograms" = "xyes"],
- [ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ])
- ]
-)
-
-AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile m4/Makefile gui/Makefile test/Makefile])
+AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile m4/Makefile test/Makefile])
AC_OUTPUT
info_TEXINFOS = tinc.texi
-man_MANS = tincd.8 tinc.8 tinc.conf.5 tinc-gui.8
+man_MANS =
-EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.8.in tinc.conf.5.in tinc-gui.8.in sample-config.tar.gz
+EXTRA_DIST = tincinclude.texi.in
-CLEANFILES = *.html tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi
+CLEANFILES = *.html tincinclude.texi
# Use `ginstall' in the definition of man_MANS to avoid
# confusion with the `install' target. The install rule transforms `ginstall'
# For additional rules usually of interest only to the maintainer,
# see GNUmakefile and Makefile.maint.
-sample-config.tar.gz: sample-config
- GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz --exclude .svn sample-config
-
-tincd.8.html: tincd.8
- w3mman2html $? > $@
-
-tinc.8.html: tinc.8
- w3mman2html $? > $@
-
-tinc-gui.8.html: tinc-gui.8
- w3mman2html $? > $@
-
-tinc.conf.5.html: tinc.conf.5
- w3mman2html $? > $@
-
substitute = sed \
-e s,'@PACKAGE\@',"$(PACKAGE)",g \
-e s,'@VERSION\@',"$(VERSION)",g \
-e s,'@sysconfdir\@',"$(sysconfdir)",g \
-e s,'@localstatedir\@',"$(localstatedir)",g
-tincd.8: tincd.8.in
- $(substitute) $? > $@
-
-tinc.8: tinc.8.in
- $(substitute) $? > $@
-
-tinc-gui.8: tinc-gui.8.in
- $(substitute) $? > $@
-
-tinc.conf.5: tinc.conf.5.in
- $(substitute) $? > $@
-
tincinclude.texi: tincinclude.texi.in
$(substitute) $? > $@
+++ /dev/null
-.Dd 2011-06-26
-.Dt TINC-GUI 8
-.\" Manual page created by:
-.\" Guus Sliepen <guus@tinc-vpn.org>
-.Sh NAME
-.Nm tinc-gui
-.Nd tinc GUI
-.Sh SYNOPSIS
-.Nm
-.Op Fl n
-.Op Fl -net Ns = Ns Ar NETNAME
-.Op Fl -pidfile Ns = Ns Ar FILENAME
-.Op Fl -help
-.Sh DESCRIPTION
-This is a Python/wxWidgets based graphical user interface for tinc, a secure virtual private network (VPN) project.
-.Nm
-communicates with
-.Xr tincd 8
-to alter and inspect the running VPN's state.
-It can show the current settings, the list of connections, nodes, subnets, and edges.
-For now, the debug level can be changed from the GUI, and by right-clicking on a node in the list of connections,
-a pop-up menu will appear that allows one to disconnect that node.
-.Sh OPTIONS
-.Bl -tag -width indent
-.It Fl n, -net Ns = Ns Ar NETNAME
-Communicate with tincd(8) connected with
-.Ar NETNAME .
-.It Fl -pidfile Ns = Ns Ar FILENAME
-Use the cookie from
-.Ar FILENAME
-to authenticate with a running tinc daemon.
-If unspecified, the default is
-.Pa @localstatedir@/run/tinc. Ns Ar NETNAME Ns Pa .pid.
-.It Fl -help
-Display short list of options.
-.El
-.Sh BUGS
-The GUI is not finished yet, the final version will have much more functionality.
-If you find any bugs, report them to tinc@tinc-vpn.org.
-.Sh SEE ALSO
-.Xr tincd 8 ,
-.Pa http://www.tinc-vpn.org/ .
-.Pp
-The full documentation for tinc is maintained as a Texinfo manual.
-If the info and tinc programs are properly installed at your site,
-the command
-.Ic info tinc
-should give you access to the complete manual.
-.Pp
-tinc comes with ABSOLUTELY NO WARRANTY.
-This is free software, and you are welcome to redistribute it under certain conditions;
-see the file COPYING for details.
-.Sh AUTHORS
-.An "Ivo Timmermans"
-.An "Guus Sliepen" Aq guus@tinc-vpn.org
-.Pp
-And thanks to many others for their contributions to tinc!
+++ /dev/null
-.Dd 2014-01-16
-.Dt TINCCTL 8
-.\" Manual page created by:
-.\" Scott Lamb
-.Sh NAME
-.Nm tinc
-.Nd tinc VPN control
-.Sh SYNOPSIS
-.Nm
-.Op Fl cn
-.Op Fl -config Ns = Ns Ar DIR
-.Op Fl -net Ns = Ns Ar NETNAME
-.Op Fl -pidfile Ns = Ns Ar FILENAME
-.Op Fl -help
-.Op Fl -version
-.Op Ar COMMAND
-.Sh DESCRIPTION
-This is the control program of tinc, a secure virtual private network (VPN)
-project.
-.Nm
-can start and stop
-.Xr tincd 8 ,
-and can to alter and inspect the state of a running VPN.
-It can also be used to change the configuration,
-or to import or export host configuration files from other nodes.
-
-If
-.Nm
-is started with a
-.Ar COMMAND ,
-this command is immediately executed, after which
-.Nm
-exits.
-If no
-.Ar COMMAND
-is given,
-.Nm
-will act as a shell;
-it will display a prompt, and commands can be entered on the prompt.
-If
-.Nm
-is compiled with libreadline, history and command completion are available on the prompt.
-One can also pipe a script containing commands through
-.Nm .
-In that case, lines starting with a # symbol will be ignored.
-.Sh OPTIONS
-.Bl -tag -width indent
-.It Fl n, -net Ns = Ns Ar NETNAME
-Communicate with tincd(8) connected with
-.Ar NETNAME .
-.It Fl -pidfile Ns = Ns Ar FILENAME
-Use the cookie from
-.Ar FILENAME
-to authenticate with a running tinc daemon.
-If unspecified, the default is
-.Pa @localstatedir@/run/tinc. Ns Ar NETNAME Ns Pa .pid.
-.It Fl -help
-Display short list of options.
-.It Fl -version
-Output version information and exit.
-.El
-.Sh ENVIRONMENT VARIABLES
-.Bl -tag -width indent
-.It Ev NETNAME
-If no netname is specified on the command line with the
-.Fl n
-option, the value of this environment variable is used.
-.El
-.Sh COMMANDS
-.Bl -tag -width indent
-.It init Op Ar name
-Create initial configuration files and RSA and ECDSA keypairs with default length.
-If no
-.Ar name
-for this node is given, it will be asked for.
-.It get Ar variable
-Print the current value of configuration variable
-.Ar variable .
-If more than one variable with the same name exists,
-the value of each of them will be printed on a separate line.
-.It set Ar variable Ar value
-Set configuration variable
-.Ar variable
-to the given
-.Ar value .
-All previously existing configuration variables with the same name are removed.
-To set a variable for a specific host, use the notation
-.Ar host Ns Li . Ns Ar variable .
-.It add Ar variable Ar value
-As above, but without removing any previously existing configuration variables.
-.It del Ar variable Op Ar value
-Remove configuration variables with the same name and
-.Ar value .
-If no
-.Ar value
-is given, all configuration variables with the same name will be removed.
-.It edit Ar filename
-Start an editor for the given configuration file.
-You do not need to specify the full path to the file.
-.It export
-Export the host configuration file of the local node to standard output.
-.It export-all
-Export all host configuration files to standard output.
-.It import Op Fl -force
-Import host configuration data generated by the
-.Nm
-export command from standard input.
-Already existing host configuration files are not overwritten unless the option
-.Fl -force
-is used.
-.It exchange Op Fl -force
-The same as export followed by import.
-.It exchange-all Op Fl -force
-The same as export-all followed by import.
-.It invite Ar name
-Prepares an invitation for a new node with the given
-.Ar name ,
-and prints a short invitation URL that can be used with the join command.
-.It join Op Ar URL
-Join an existing VPN using an invitation URL created using the invite command.
-If no
-.Ar URL
-is given, it will be read from standard input.
-.It start Op tincd options
-Start
-.Xr tincd 8 ,
-optionally with the given extra options.
-.It stop
-Stop
-.Xr tincd 8 .
-.It restart Op tincd options
-Restart
-.Xr tincd 8 ,
-optionally with the given extra options.
-.It reload
-Partially rereads configuration files. Connections to hosts whose host
-config files are removed are closed. New outgoing connections specified
-in
-.Xr tinc.conf 5
-will be made.
-.It pid
-Shows the PID of the currently running
-.Xr tincd 8 .
-.It generate-keys Op bits
-Generate both RSA and ECDSA keypairs (see below) and exit.
-.It generate-ecdsa-keys
-Generate public/private ECDSA keypair and exit.
-.It generate-rsa-keys Op bits
-Generate public/private RSA keypair and exit.
-If
-.Ar bits
-is omitted, the default length will be 2048 bits.
-When saving keys to existing files, tinc will not delete the old keys;
-you have to remove them manually.
-.It dump [reachable] nodes
-Dump a list of all known nodes in the VPN.
-If the keyword reachable is used, only lists reachable nodes.
-.It dump edges
-Dump a list of all known connections in the VPN.
-.It dump subnets
-Dump a list of all known subnets in the VPN.
-.It dump connections
-Dump a list of all meta connections with ourself.
-.It dump graph | digraph
-Dump a graph of the VPN in
-.Xr dotty 1
-format.
-Nodes are colored according to their reachability:
-red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable.
-Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet.
-.It info Ar node | subnet | address
-Show information about a particular node, subnet or address.
-If an address is given, any matching subnet will be shown.
-.It purge
-Purges all information remembered about unreachable nodes.
-.It debug Ar N
-Sets debug level to
-.Ar N .
-.It log Op Ar N
-Capture log messages from a running tinc daemon.
-An optional debug level can be given that will be applied only for log messages sent to
-.Nm tinc .
-.It retry
-Forces
-.Xr tincd 8
-to try to connect to all uplinks immediately.
-Usually
-.Xr tincd 8
-attempts to do this itself,
-but increases the time it waits between the attempts each time it failed,
-and if
-.Xr tincd 8
-didn't succeed to connect to an uplink the first time after it started,
-it defaults to the maximum time of 15 minutes.
-.It disconnect Ar NODE
-Closes the meta connection with the given
-.Ar NODE .
-.It top
-If
-.Nm
-is compiled with libcurses support, this will display live traffic statistics
-for all the known nodes, similar to the UNIX
-.Xr top 1
-command.
-See below for more information.
-.It pcap
-Dump VPN traffic going through the local tinc node in
-.Xr pcap-savefile 5
-format to standard output,
-from where it can be redirected to a file or piped through a program that can parse it directly,
-such as
-.Xr tcpdump 8 .
-.It network Op Ar netname
-If
-.Ar netname
-is given, switch to that network.
-Otherwise, display a list of all networks for which configuration files exist.
-.El
-.Sh EXAMPLES
-Examples of some commands:
-.Bd -literal -offset indent
-tinc -n vpn dump graph | circo -Txlib
-tinc -n vpn pcap | tcpdump -r -
-tinc -n vpn top
-.Pp
-.Ed
-Examples of changing the configuration using
-.Nm :
-.Bd -literal -offset indent
-tinc -n vpn init foo
-tinc -n vpn add Subnet 192.168.1.0/24
-tinc -n vpn add bar.Address bar.example.com
-tinc -n vpn add ConnectTo bar
-tinc -n vpn export | gpg --clearsign | mail -s "My config" vpnmaster@example.com
-.Ed
-.Sh TOP
-The top command connects to a running tinc daemon and repeatedly queries its per-node traffic counters.
-It displays a list of all the known nodes in the left-most column,
-and the amount of bytes and packets read from and sent to each node in the other columns.
-By default, the information is updated every second.
-The behaviour of the top command can be changed using the following keys:
-.Bl -tag
-.It Ic s
-Change the interval between updates.
-After pressing the
-.Ic s
-key, enter the desired interval in seconds, followed by enter.
-Fractional seconds are honored.
-Intervals lower than 0.1 seconds are not allowed.
-.It Ic c
-Toggle between displaying current traffic rates (in packets and bytes per second)
-and cumulative traffic (total packets and bytes since the tinc daemon started).
-.It Ic n
-Sort the list of nodes by name.
-.It Ic i
-Sort the list of nodes by incoming amount of bytes.
-.It Ic I
-Sort the list of nodes by incoming amount of packets.
-.It Ic o
-Sort the list of nodes by outgoing amount of bytes.
-.It Ic O
-Sort the list of nodes by outgoing amount of packets.
-.It Ic t
-Sort the list of nodes by sum of incoming and outgoing amount of bytes.
-.It Ic T
-Sort the list of nodes by sum of incoming and outgoing amount of packets.
-.It Ic b
-Show amount of traffic in bytes.
-.It Ic k
-Show amount of traffic in kilobytes.
-.It Ic M
-Show amount of traffic in megabytes.
-.It Ic G
-Show amount of traffic in gigabytes.
-.It Ic q
-Quit.
-.El
-.Sh BUGS
-If you find any bugs, report them to tinc@tinc-vpn.org.
-.Sh SEE ALSO
-.Xr tincd 8 ,
-.Xr tinc.conf 5 ,
-.Xr dotty 1 ,
-.Xr pcap-savefile 5 ,
-.Xr tcpdump 8 ,
-.Xr top 1 ,
-.Pa http://www.tinc-vpn.org/ ,
-.Pa http://www.cabal.org/ .
-.Pp
-The full documentation for tinc is maintained as a Texinfo manual.
-If the info and tinc programs are properly installed at your site,
-the command
-.Ic info tinc
-should give you access to the complete manual.
-.Pp
-tinc comes with ABSOLUTELY NO WARRANTY.
-This is free software, and you are welcome to redistribute it under certain conditions;
-see the file COPYING for details.
-.Sh AUTHORS
-.An "Ivo Timmermans"
-.An "Guus Sliepen" Aq guus@tinc-vpn.org
-.Pp
-And thanks to many others for their contributions to tinc!
+++ /dev/null
-.Dd 2014-01-29
-.Dt TINC.CONF 5
-.\" Manual page created by:
-.\" Ivo Timmermans
-.\" Guus Sliepen <guus@tinc-vpn.org>
-.Sh NAME
-.Nm tinc.conf
-.Nd tinc daemon configuration
-.Sh DESCRIPTION
-The files in the
-.Pa @sysconfdir@/tinc/
-directory contain runtime and security information for the tinc daemon.
-.Sh NETWORKS
-To distinguish multiple instances of tinc running on one computer,
-you can use the
-.Fl n
-option to assign a network name to each tinc daemon.
-.Pp
-The effect of this option is that the daemon will set its configuration root to
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / ,
-where
-.Ar NETNAME
-is your argument to the
-.Fl n
-option.
-You'll notice that messages appear in syslog as coming from
-.Nm tincd. Ns Ar NETNAME ,
-and on Linux, unless specified otherwise, the name of the virtual network interface will be the same as the network name.
-.Pp
-It is recommended that you use network names even if you run only one instance of tinc.
-However, you can choose not to use the
-.Fl n
-option.
-In this case, the network name would just be empty, and
-.Nm tinc
-now looks for files in
-.Pa @sysconfdir@/tinc/ ,
-instead of
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / ;
-the configuration file should be
-.Pa @sysconfdir@/tinc/tinc.conf ,
-and the host configuration files are now expected to be in
-.Pa @sysconfdir@/tinc/hosts/ .
-.Sh NAMES
-Each tinc daemon should have a name that is unique in the network which it will be part of.
-The name will be used by other tinc daemons for identification.
-The name has to be declared in the
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
-file.
-.Pp
-To make things easy,
-choose something that will give unique and easy to remember names to your tinc daemon(s).
-You could try things like hostnames, owner surnames or location names.
-However, you are only allowed to use alphanumerical characters (a-z, A-Z, and 0-9) and underscores (_) in the name.
-.Sh INITIAL CONFIGURATION
-If you have not configured tinc yet, you can easily create a basic configuration using the following command:
-.Bd -literal -offset indent
-.Nm tinc Fl n Ar NETNAME Li init Ar NAME
-.Ed
-.Pp
-You can further change the configuration as needed either by manually editing the configuration files,
-or by using
-.Xr tinc 8 .
-.Sh PUBLIC/PRIVATE KEYS
-The
-.Nm tinc Li init
-command will have generated both RSA and ECDSA public/private keypairs.
-The private keys should be stored in files named
-.Pa rsa_key.priv
-and
-.Pa ecdsa_key.priv
-in the directory
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /
-The public keys should be stored in the host configuration file
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME .
-The RSA keys are used for backwards compatibility with tinc version 1.0.
-If you are upgrading from version 1.0 to 1.1, you can keep the old configuration files,
-but you will need to create ECDSA keys using the following command:
-.Bd -literal -offset indent
-.Nm tinc Fl n Ar NETNAME Li generate-ecdsa-keys
-.Ed
-.Sh SERVER CONFIGURATION
-The server configuration of the daemon is done in the file
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf .
-This file consists of comments (lines started with a
-.Li # )
-or assignments in the form of:
-.Pp
-.Va Variable Li = Ar Value .
-.Pp
-The variable names are case insensitive, and any spaces, tabs,
-newlines and carriage returns are ignored.
-Note: it is not required that you put in the
-.Li =
-sign, but doing so improves readability.
-If you leave it out, remember to replace it with at least one space character.
-.Pp
-The server configuration is complemented with host specific configuration (see the next section).
-Although all configuration options for the local host listed in this document can also be put in
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf ,
-it is recommended to put host specific configuration options in the host configuration file,
-as this makes it easy to exchange with other nodes.
-.Pp
-You can edit the config file manually, but it is recommended that you use
-.Xr tinc 8
-to change configuration variables for you.
-.Pp
-Here are all valid variables, listed in alphabetical order.
-The default value is given between parentheses.
-.Bl -tag -width indent
-.It Va AddressFamily Li = ipv4 | ipv6 | any Pq any
-This option affects the address family of listening and outgoing sockets.
-If
-.Qq any
-is selected, then depending on the operating system both IPv4 and IPv6 or just
-IPv6 listening sockets will be created.
-.It Va AutoConnect Li = Ar count Po 0 Pc Bq experimental
-If set to a non-zero value,
-.Nm
-will try to only have
-.Ar count
-meta connections to other nodes,
-by automatically making or breaking connections to known nodes.
-Higher values increase redundancy but also increase meta data overhead.
-When using this option, a good value is 3.
-.It Va BindToAddress Li = Ar address Op Ar port
-This is the same as
-.Va ListenAddress ,
-however the address given with the
-.Va BindToAddress
-option will also be used for outgoing connections. This is useful if your
-computer has more than one IPv4 or IPv6 address, and you want
-.Nm tinc
-to only use a specific one for outgoing packets.
-.It Va BindToInterface Li = Ar interface Bq experimental
-If your computer has more than one network interface,
-.Nm tinc
-will by default listen on all of them for incoming connections.
-It is possible to bind only to a single interface with this variable.
-.Pp
-This option may not work on all platforms.
-Also, on some platforms it will not actually bind to an interface,
-but rather to the address that the interface has at the moment a socket is created.
-.It Va Broadcast Li = no | mst | direct Po mst Pc Bq experimental
-This option selects the way broadcast packets are sent to other daemons.
-NOTE: all nodes in a VPN must use the same
-.Va Broadcast
-mode, otherwise routing loops can form.
-.Bl -tag -width indent
-.It no
-Broadcast packets are never sent to other nodes.
-.It mst
-Broadcast packets are sent and forwarded via the VPN's Minimum Spanning Tree.
-This ensures broadcast packets reach all nodes.
-.It direct
-Broadcast packets are sent directly to all nodes that can be reached directly.
-Broadcast packets received from other nodes are never forwarded.
-If the IndirectData option is also set, broadcast packets will only be sent to nodes which we have a meta connection to.
-.El
-.It Va ConnectTo Li = Ar name
-Specifies which other tinc daemon to connect to on startup.
-Multiple
-.Va ConnectTo
-variables may be specified,
-in which case outgoing connections to each specified tinc daemon are made.
-The names should be known to this tinc daemon
-(i.e., there should be a host configuration file for the name on the
-.Va ConnectTo
-line).
-.Pp
-If you don't specify a host with
-.Va ConnectTo ,
-.Nm tinc
-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 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.
-.Nm tinc
-will automatically detect what kind of device it is.
-Note that you can only use one device per daemon.
-Under Windows, use
-.Va Interface
-instead of
-.Va Device .
-The info pages of the tinc package contain more information
-about configuring the virtual network device.
-.It Va DeviceType Li = Ar type Pq platform dependent
-The type of the virtual network device.
-Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used.
-However, this option can be used to select one of the special interface types, if support for them is compiled in.
-.Bl -tag -width indent
-.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 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 ,
-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.
-Depending on the platform, this can either be with or without an address family header (see below).
-.It tunnohead Pq BSD
-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.
-On some platforms IPv6 packets cannot be read from or written to the device in this mode.
-.It tunifhead Pq BSD
-Set type to tun with an address family header.
-Tinc will expect packets read from the virtual network device
-to start with a four byte header containing the address family,
-followed by an IP header.
-This mode should support both IPv4 and IPv6 packets.
-.It tap Pq BSD and Linux
-Set type to tap.
-Tinc will expect packets read from the virtual network device
-to start with an Ethernet header.
-.El
-.It Va DirectOnly Li = yes | no Po no Pc Bq experimental
-When this option is enabled, packets that cannot be sent directly to the destination node,
-but which would have to be forwarded by an intermediate node, are dropped instead.
-When combined with the IndirectData option,
-packets for nodes for which we do not have a meta connection with are also dropped.
-.It Va ECDSAPrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /ecdsa_key.priv Pc
-The file in which the private ECDSA key of this tinc daemon resides.
-This is only used if
-.Va ExperimentalProtocol
-is enabled.
-.It Va ExperimentalProtocol Li = yes | no Pq yes
-When this option is enabled, the SPTPS protocol will be used when connecting to nodes that also support it.
-Ephemeral ECDH will be used for key exchanges,
-and ECDSA will be used instead of RSA for authentication.
-When enabled, an ECDSA key must have been generated before with
-.Nm tinc generate-ecdsa-keys .
-.It Va Forwarding Li = off | internal | kernel Po internal Pc Bq experimental
-This option selects the way indirect packets are forwarded.
-.Bl -tag -width indent
-.It off
-Incoming packets that are not meant for the local node,
-but which should be forwarded to another node, are dropped.
-.It internal
-Incoming packets that are meant for another node are forwarded by tinc internally.
-.Pp
-This is the default mode, and unless you really know you need another forwarding mode, don't change it.
-.It kernel
-Incoming packets are always sent to the TUN/TAP device, even if the packets are not for the local node.
-This is less efficient, but allows the kernel to apply its routing and firewall rules on them,
-and can also help debugging.
-.El
-.It Va Hostnames Li = yes | no Pq no
-This option selects whether IP addresses (both real and on the VPN) should
-be resolved. Since DNS lookups are blocking, it might affect tinc's
-efficiency, even stopping the daemon for a few seconds every time it does
-a lookup if your DNS server is not responding.
-.Pp
-This does not affect resolving hostnames to IP addresses from the
-host configuration files, but whether hostnames should be resolved while logging.
-.It Va IffOneQueue Li = yes | no Po no Pc Bq experimental
-(Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices.
-.It Va Interface Li = Ar interface
-Defines the name of the interface corresponding to the virtual network device.
-Depending on the operating system and the type of device this may or may not actually set the name of the interface.
-Under Windows, this variable is used to select which network interface will be used.
-If you specified a
-.Va Device ,
-this variable is almost always already correctly set.
-.It Va KeyExpire Li = Ar seconds Pq 3600
-This option controls the period the encryption keys used to encrypt the data are valid.
-It is common practice to change keys at regular intervals to make it even harder for crackers,
-even though it is thought to be nearly impossible to crack a single key.
-.It Va ListenAddress Li = Ar address Op Ar port
-If your computer has more than one IPv4 or IPv6 address,
-.Nm tinc
-will by default listen on all of them for incoming connections.
-This option can be used to restrict which addresses tinc listens on.
-Multiple
-.Va ListenAddress
-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 listen on the port specified by the
-.Va Port
-option, or to port 655 if neither is given.
-To only listen on a specific port but not on a specific address, use
-.Li *
-for the
-.Ar address .
-.It Va LocalDiscovery Li = yes | no Pq no
-When enabled,
-.Nm tinc
-will try to detect peers that are on the same local network.
-This will allow direct communication using LAN addresses, even if both peers are behind a NAT
-and they only ConnectTo a third node outside the NAT,
-which normally would prevent the peers from learning each other's LAN address.
-.Pp
-Currently, local discovery is implemented by sending broadcast packets to the LAN during path MTU discovery.
-This feature may not work in all possible situations.
-.It Va LocalDiscoveryAddress Li = Ar address
-If this variable is specified, local discovery packets are sent to the given
-.Ar address .
-.It Va MACExpire Li = Ar seconds Pq 600
-This option controls the amount of time MAC addresses are kept before they are removed.
-This only has effect when
-.Va Mode
-is set to
-.Qq switch .
-.It Va MaxConnectionBurst Li = Ar count Pq 100
-This option controls how many connections tinc accepts in quick succession.
-If there are more connections than the given number in a short time interval,
-tinc will reduce the number of accepted connections to only one per second,
-until the burst has passed.
-.It Va MaxTimeout Li = Ar seconds Pq 900
-This is the maximum delay before trying to reconnect to other tinc daemons.
-.It Va Mode Li = router | switch | hub Pq router
-This option selects the way packets are routed to other daemons.
-.Bl -tag -width indent
-.It router
-In this mode
-.Va Subnet
-variables in the host configuration files will be used to form a routing table.
-Only packets of routable protocols (IPv4 and IPv6) are supported in this mode.
-.Pp
-This is the default mode, and unless you really know you need another mode, don't change it.
-.It switch
-In this mode the MAC addresses of the packets on the VPN will be used to
-dynamically create a routing table just like an Ethernet switch does.
-Unicast, multicast and broadcast packets of every protocol that runs over Ethernet are supported in this mode
-at the cost of frequent broadcast ARP requests and routing table updates.
-.Pp
-This mode is primarily useful if you want to bridge Ethernet segments.
-.It hub
-This mode is almost the same as the switch mode, but instead
-every packet will be broadcast to the other daemons
-while no routing table is managed.
-.El
-.It Va Name Li = Ar name Bq required
-This is the name which identifies this tinc daemon.
-It must be unique for the virtual private network this daemon will connect to.
-The Name may only consist of alphanumeric and underscore characters (a-z, A-Z, 0-9 and _), and is case sensitive.
-If
-.Va Name
-starts with a
-.Li $ ,
-then the contents of the environment variable that follows will be used.
-In that case, invalid characters will be converted to underscores.
-If
-.Va Name
-is
-.Li $HOST ,
-but no such environment variable exist, the hostname will be read using the gethostname() system call.
-.It Va PingInterval Li = Ar seconds Pq 60
-The number of seconds of inactivity that
-.Nm tinc
-will wait before sending a probe to the other end.
-.It Va PingTimeout Li = Ar seconds Pq 5
-The number of seconds to wait for a response to pings or to allow meta
-connections to block. If the other end doesn't respond within this time,
-the connection is terminated,
-and the others will be notified of this.
-.It Va PriorityInheritance Li = yes | no Po no Pc Bq experimental
-When this option is enabled the value of the TOS field of tunneled IPv4 packets
-will be inherited by the UDP packets that are sent out.
-.It Va PrivateKey Li = Ar key Bq obsolete
-The private RSA key of this tinc daemon.
-It will allow this tinc daemon to authenticate itself to other daemons.
-.It Va PrivateKeyFile Li = Ar filename Po Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv Pc
-The file in which the private RSA key of this tinc daemon resides.
-.It Va ProcessPriority Li = low | normal | high
-When this option is used the priority of the
-.Nm tincd
-process will be adjusted.
-Increasing the priority may help to reduce latency and packet loss on the VPN.
-.It Va Proxy Li = socks4 | socks5 | http | exec Ar ... Bq experimental
-Use a proxy when making outgoing connections.
-The following proxy types are currently supported:
-.Bl -tag -width indent
-.It socks4 Ar address Ar port Op Ar username
-Connects to the proxy using the SOCKS version 4 protocol.
-Optionally, a
-.Ar username
-can be supplied which will be passed on to the proxy server.
-Only IPv4 connections can be proxied using SOCKS 4.
-.It socks5 Ar address Ar port Op Ar username Ar password
-Connect to the proxy using the SOCKS version 5 protocol.
-If a
-.Ar username
-and
-.Ar password
-are given, basic username/password authentication will be used,
-otherwise no authentication will be used.
-.It http Ar address Ar port
-Connects to the proxy and sends a HTTP CONNECT request.
-.It exec Ar command
-Executes the given
-.Ar command
-which should set up the outgoing connection.
-The environment variables
-.Ev NAME ,
-.Ev NODE ,
-.Ev REMOTEADDRES
-and
-.Ev REMOTEPORT
-are available.
-.El
-.It Va ReplayWindow Li = Ar bytes Pq 16
-This is the size of the replay tracking window for each remote node, in bytes.
-The window is a bitfield which tracks 1 packet per bit, so for example
-the default setting of 16 will track up to 128 packets in the window. In high
-bandwidth scenarios, setting this to a higher value can reduce packet loss from
-the interaction of replay tracking with underlying real packet loss and/or
-reordering. Setting this to zero will disable replay tracking completely and
-pass all traffic, but leaves tinc vulnerable to replay-based attacks on your
-traffic.
-.It Va StrictSubnets Li = yes | no Po no Pc Bq experimental
-When this option is enabled tinc will only use Subnet statements which are
-present in the host config files in the local
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
-directory. Subnets learned via connections to other nodes and which are not
-present in the local host config files are ignored.
-.It Va TunnelServer Li = yes | no Po no Pc Bq experimental
-When this option is enabled tinc will no longer forward information between other tinc daemons,
-and will only allow connections with nodes for which host config files are present in the local
-.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
-directory.
-Setting this options also implicitly sets StrictSubnets.
-.It Va UDPRcvBuf Li = Ar bytes Pq OS default
-Sets the socket receive buffer size for the UDP socket, in bytes.
-If unset, the default buffer size will be used by the operating system.
-.It Va UDPSndBuf Li = Ar bytes Pq OS default
-Sets the socket send buffer size for the UDP socket, in bytes.
-If unset, the default buffer size will be used by the operating system.
-.El
-.Sh HOST CONFIGURATION FILES
-The host configuration files contain all information needed
-to establish a connection to those hosts.
-A host configuration file is also required for the local tinc daemon,
-it will use it to read in it's listen port, public key and subnets.
-.Pp
-The idea is that these files are portable.
-You can safely mail your own host configuration file to someone else.
-That other person can then copy it to his own hosts directory,
-and now his tinc daemon will be able to connect to your tinc daemon.
-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 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.
-Multiple
-.Va Address
-variables can be specified, in which case each address will be tried until a working
-connection has been established.
-.It Va Cipher Li = Ar cipher Pq blowfish
-The symmetric cipher algorithm used to encrypt UDP packets.
-Any cipher supported by OpenSSL is recognised.
-Furthermore, specifying
-.Qq none
-will turn off packet encryption.
-It is best to use only those ciphers which support CBC mode.
-This option has no effect for connections between nodes using
-.Va ExperimentalProtocol .
-.It Va ClampMSS Li = yes | no Pq yes
-This option specifies whether tinc should clamp the maximum segment size (MSS)
-of TCP packets to the path MTU. This helps in situations where ICMP
-Fragmentation Needed or Packet too Big messages are dropped by firewalls.
-.It Va Compression Li = Ar level Pq 0
-This option sets the level of compression used for UDP packets.
-Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
-10 (fast lzo) and 11 (best lzo).
-.It Va Digest Li = Ar digest Pq sha1
-The digest algorithm used to authenticate UDP packets.
-Any digest supported by OpenSSL is recognised.
-Furthermore, specifying
-.Qq none
-will turn off packet authentication.
-This option has no effect for connections between nodes using
-.Va ExperimentalProtocol .
-.It Va IndirectData Li = yes | no Pq no
-When set to yes, other nodes which do not already have a meta connection to you
-will not try to establish direct communication with you.
-It is best to leave this option out or set it to no.
-.It Va MACLength Li = Ar length Pq 4
-The length of the message authentication code used to authenticate UDP packets.
-Can be anything from
-.Qq 0
-up to the length of the digest produced by the digest algorithm.
-This option has no effect for connections between nodes using
-.Va ExperimentalProtocol .
-.It Va PMTU Li = Ar mtu Po 1514 Pc
-This option controls the initial path MTU to this node.
-.It Va PMTUDiscovery Li = yes | no Po yes Pc
-When this option is enabled, tinc will try to discover the path MTU to this node.
-After the path MTU has been discovered, it will be enforced on the VPN.
-.It Va Port Li = Ar port Pq 655
-The port number on which this tinc daemon is listening for incoming connections,
-which is used if no port number is specified in an
-.Va Address
-statement.
-.It Va PublicKey Li = Ar key Bq obsolete
-The public RSA key of this tinc daemon.
-It will be used to cryptographically verify it's identity and to set up a secure connection.
-.It Va PublicKeyFile Li = Ar filename Bq obsolete
-The file in which the public RSA key of this tinc daemon resides.
-.Pp
-From version 1.0pre4 on
-.Nm tinc
-will store the public key directly into the host configuration file in PEM format,
-the above two options then are not necessary.
-Either the PEM format is used, or exactly one of the above two options must be specified
-in each host configuration file,
-if you want to be able to establish a connection with that host.
-.It Va Subnet Li = Ar address Ns Op Li / Ns Ar prefixlength Ns Op Li # Ns Ar weight
-The subnet which this tinc daemon will serve.
-.Nm tinc
-tries to look up which other daemon it should send a packet to by searching the appropriate subnet.
-If the packet matches a subnet,
-it will be sent to the daemon who has this subnet in his host configuration file.
-Multiple
-.Va Subnet
-variables can be specified.
-.Pp
-Subnets can either be single MAC, IPv4 or IPv6 addresses,
-in which case a subnet consisting of only that single address is assumed,
-or they can be a IPv4 or IPv6 network address with a prefixlength.
-For example, IPv4 subnets must be in a form like 192.168.1.0/24,
-where 192.168.1.0 is the network address and 24 is the number of bits set in the netmask.
-Note that subnets like 192.168.1.1/24 are invalid!
-Read a networking HOWTO/FAQ/guide if you don't understand this.
-IPv6 subnets are notated like fec0:0:0:1::/64.
-MAC addresses are notated like 0:1a:2b:3c:4d:5e.
-.Pp
-A Subnet can be given a weight to indicate its priority over identical Subnets
-owned by different nodes. The default weight is 10. Lower values indicate
-higher priority. Packets will be sent to the node with the highest priority,
-unless that node is not reachable, in which case the node with the next highest
-priority will be tried, and so on.
-.It Va TCPOnly Li = yes | no Pq no Bq obsolete
-If this variable is set to yes,
-then the packets are tunnelled over the TCP connection instead of a UDP connection.
-This is especially useful for those who want to run a tinc daemon
-from behind a masquerading firewall,
-or if UDP packet routing is disabled somehow.
-Setting this options also implicitly sets IndirectData.
-.Pp
-Since version 1.0.10, tinc will automatically detect whether communication via
-UDP is possible or not.
-.It Va Weight Li = Ar weight
-If this variable is set, it overrides the weight given to connections made with
-another host. A higher
-.Ar weight
-means a lower priority is given to this connection when broadcasting or
-forwarding packets.
-.El
-.Sh SCRIPTS
-Apart from reading the server and host configuration files,
-tinc can also run scripts at certain moments.
-Under Windows (not Cygwin), the scripts should have the extension
-.Pa .bat
-or
-.Pa cmd .
-.Bl -tag -width indent
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
-This is the most important script.
-If it is present it will be executed right after the tinc daemon has been started and has connected to the virtual network device.
-It should be used to set up the corresponding network interface,
-but can also be used to start other things.
-Under Windows you can use the Network Connections control panel instead of creating this script.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
-This script is started right before the tinc daemon quits.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -up
-This script is started when the tinc daemon with name
-.Ar HOST
-becomes reachable.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Ar HOST Ns Pa -down
-This script is started when the tinc daemon with name
-.Ar HOST
-becomes unreachable.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-up
-This script is started when any host becomes reachable.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /host-down
-This script is started when any host becomes unreachable.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-up
-This script is started when a Subnet becomes reachable.
-The Subnet and the node it belongs to are passed in environment variables.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /subnet-down
-This script is started when a Subnet becomes unreachable.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /invitation-created
-This script is started when a new invitation has been created.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /invitation-accepted
-This script is started when an invitation has been used.
-.El
-.Pp
-The scripts are started without command line arguments, but can make use of certain environment variables.
-Under UNIX like operating systems the names of environment variables must be preceded by a
-.Li $
-in scripts.
-Under Windows, in
-.Pa .bat
-or
-.Pa .cmd
-files, they have to be put between
-.Li %
-signs.
-.Bl -tag -width indent
-.It Ev NETNAME
-If a netname was specified, this environment variable contains it.
-.It Ev NAME
-Contains the name of this tinc daemon.
-.It Ev DEVICE
-Contains the name of the virtual network device that tinc uses.
-.It Ev INTERFACE
-Contains the name of the virtual network interface that tinc uses.
-This should be used for commands like
-.Pa ifconfig .
-.It Ev NODE
-When a host becomes (un)reachable, this is set to its name.
-If a subnet becomes (un)reachable, this is set to the owner of that subnet.
-.It Ev REMOTEADDRESS
-When a host becomes (un)reachable, this is set to its real address.
-.It Ev REMOTEPORT
-When a host becomes (un)reachable, this is set to the port number it uses for communication with other tinc daemons.
-.It Ev SUBNET
-When a subnet becomes (un)reachable, this is set to the subnet.
-.It Ev WEIGHT
-When a subnet becomes (un)reachable, this is set to the subnet weight.
-.It Ev INVITATION_FILE
-When the
-.Pa invitation-created
-script is called, this is set to the file where the invitation details will be stored.
-.It Ev INVITATION_URL
-When the
-.Pa invitation-created
-script is called, this is set to the invitation URL that has been created.
-.El
-.Pp
-Do not forget that under UNIX operating systems, you have to make the scripts executable, using the command
-.Nm chmod Li a+x Pa script .
-.Sh FILES
-The most important files are:
-.Bl -tag -width indent
-.It Pa @sysconfdir@/tinc/
-The top directory for configuration files.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf
-The default name of the server configuration file for net
-.Ar NETNAME .
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /conf.d/
-Optional directory from which any .conf file will be loaded
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/
-Host configuration files are kept in this directory.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up
-If an executable file with this name exists,
-it will be executed right after the tinc daemon has connected to the virtual network device.
-It can be used to set up the corresponding network interface.
-.It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-down
-If an executable file with this name exists,
-it will be executed right before the tinc daemon is going to close
-its connection to the virtual network device.
-.El
-.Sh SEE ALSO
-.Xr tincd 8 ,
-.Xr tinc 8 ,
-.Pa http://www.tinc-vpn.org/ ,
-.Pa http://www.tldp.org/LDP/nag2/ .
-.Pp
-The full documentation for
-.Nm tinc
-is maintained as a Texinfo manual.
-If the info and tinc programs are properly installed at your site, the command
-.Ic info tinc
-should give you access to the complete manual.
-.Pp
-.Nm tinc
-comes with ABSOLUTELY NO WARRANTY.
-This is free software, and you are welcome to redistribute it under certain conditions;
-see the file COPYING for details.
+++ /dev/null
-.Dd 2013-01-14
-.Dt TINCD 8
-.\" Manual page created by:
-.\" Ivo Timmermans
-.\" Guus Sliepen <guus@tinc-vpn.org>
-.Sh NAME
-.Nm tincd
-.Nd tinc VPN daemon
-.Sh SYNOPSIS
-.Nm
-.Op Fl cdDKnoLRU
-.Op Fl -config Ns = Ns Ar DIR
-.Op Fl -no-detach
-.Op Fl -debug Ns Op = Ns Ar LEVEL
-.Op Fl -net Ns = Ns Ar NETNAME
-.Op Fl -option Ns = Ns Ar [HOST.]KEY=VALUE
-.Op Fl -mlock
-.Op Fl -logfile Ns Op = Ns Ar FILE
-.Op Fl -bypass-security
-.Op Fl -chroot
-.Op Fl -user Ns = Ns Ar USER
-.Op Fl -help
-.Op Fl -version
-.Sh DESCRIPTION
-This is the daemon of tinc, a secure virtual private network (VPN) project.
-When started,
-.Nm
-will read it's configuration file to determine what virtual subnets it has to serve
-and to what other tinc daemons it should connect.
-It will connect to the ethertap or tun/tap device
-and set up a socket for incoming connections.
-Optionally a script will be executed to further configure the virtual device.
-If that succeeds,
-it will detach from the controlling terminal and continue in the background,
-accepting and setting up connections to other tinc daemons
-that are part of the virtual private network.
-Under Windows (not Cygwin) tinc will install itself as a service,
-which will be restarted automatically after reboots.
-.Sh OPTIONS
-.Bl -tag -width indent
-.It Fl c, -config Ns = Ns Ar DIR
-Read configuration files from
-.Ar DIR
-instead of
-.Pa @sysconfdir@/tinc/ .
-.It Fl D, -no-detach
-Don't fork and detach.
-This will also disable the automatic restart mechanism for fatal errors.
-If not mentioned otherwise, this will show log messages on the standard error output.
-.It Fl d, -debug Ns Op = Ns Ar LEVEL
-Increase debug level or set it to
-.Ar LEVEL
-(see below).
-.It Fl n, -net Ns = Ns Ar NETNAME
-Connect to net
-.Ar NETNAME .
-This will let tinc read all configuration files from
-.Pa @sysconfdir@/tinc/ Ar NETNAME .
-Specifying
-.Li .
-for
-.Ar NETNAME
-is the same as not specifying any
-.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
-Lock tinc into main memory.
-This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
-This option is not supported on all platforms.
-.It Fl -logfile Ns Op = Ns Ar FILE
-Write log entries to a file instead of to the system logging facility.
-If
-.Ar FILE
-is omitted, the default is
-.Pa @localstatedir@/log/tinc. Ns Ar NETNAME Ns Pa .log.
-.It Fl -pidfile Ns = Ns Ar FILENAME
-Store a cookie in
-.Ar FILENAME
-which allows
-.Xr tinc 8
-to authenticate.
-If
-.Ar FILE
-is omitted, the default is
-.Pa @localstatedir@/run/tinc. Ns Ar NETNAME Ns Pa .pid.
-.It Fl -bypass-security
-Disables encryption and authentication of the meta protocol.
-Only useful for debugging.
-.It Fl R, -chroot
-With this option tinc chroots into the directory where network
-config is located (@sysconfdir@/tinc/NETNAME if -n option is used,
-or to the directory specified with -c option) after initialization.
-This option is not supported on all platforms.
-.It Fl U, -user Ns = Ns Ar USER
-setuid to the specified
-.Ar USER
-after initialization.
-This option is not supported on all platforms.
-.It Fl -help
-Display short list of options.
-.It Fl -version
-Output version information and exit.
-.El
-.Sh SIGNALS
-.Bl -tag -width indent
-.It ALRM
-Forces
-.Nm
-to try to connect to all uplinks immediately.
-Usually
-.Nm
-attempts to do this itself,
-but increases the time it waits between the attempts each time it failed,
-and if
-.Nm
-didn't succeed to connect to an uplink the first time after it started,
-it defaults to the maximum time of 15 minutes.
-.It HUP
-Partially rereads configuration files.
-Connections to hosts whose host config file are removed are closed.
-New outgoing connections specified in
-.Pa tinc.conf
-will be made.
-If the
-.Fl -logfile
-option is used, this will also close and reopen the log file,
-useful when log rotation is used.
-.El
-.Sh DEBUG LEVELS
-The tinc daemon can send a lot of messages to the syslog.
-The higher the debug level,
-the more messages it will log.
-Each level inherits all messages of the previous level:
-.Bl -tag -width indent
-.It 0
-This will log a message indicating
-.Nm
-has started along with a version number.
-It will also log any serious error.
-.It 1
-This will log all connections that are made with other tinc daemons.
-.It 2
-This will log status and error messages from scripts and other tinc daemons.
-.It 3
-This will log all requests that are exchanged with other tinc daemons. These include
-authentication, key exchange and connection list updates.
-.It 4
-This will log a copy of everything received on the meta socket.
-.It 5
-This will log all network traffic over the virtual private network.
-.El
-.Sh FILES
-.Bl -tag -width indent
-.It Pa @sysconfdir@/tinc/
-Directory containing the configuration files tinc uses.
-For more information, see
-.Xr tinc.conf 5 .
-.It Pa @localstatedir@/run/tinc. Ns Ar NETNAME Ns Pa .pid
-The PID of the currently running
-.Nm
-is stored in this file.
-.El
-.Sh BUGS
-The
-.Va BindToInterface
-option may not work correctly.
-.Pp
-.Sy The cryptography in tinc is not well tested yet. Use it at your own risk!
-.Pp
-If you find any bugs, report them to tinc@tinc-vpn.org.
-.Sh TODO
-A lot, especially security auditing.
-.Sh SEE ALSO
-.Xr tinc 8 ,
-.Xr tinc.conf 5 ,
-.Pa http://www.tinc-vpn.org/ ,
-.Pa http://www.cabal.org/ .
-.Pp
-The full documentation for tinc is maintained as a Texinfo manual.
-If the info and tinc programs are properly installed at your site,
-the command
-.Ic info tinc
-should give you access to the complete manual.
-.Pp
-tinc comes with ABSOLUTELY NO WARRANTY.
-This is free software, and you are welcome to redistribute it under certain conditions;
-see the file COPYING for details.
-.Sh AUTHORS
-.An "Ivo Timmermans"
-.An "Guus Sliepen" Aq guus@tinc-vpn.org
-.Pp
-And thanks to many others for their contributions to tinc!
+++ /dev/null
-dist_bin_SCRIPTS = tinc-gui
-
-extra_DIST = README.gui
+++ /dev/null
-This experimental GUI is written in Python with wxPython widgets. You need to
-have both installed for it to work. After starting tinc with either tincd or
-tincctl, you can start the gui:
-
-tincd -n vpn
-tinc-gui -n vpn
-
-If the GUI cannot find the pid file (for example if it is not in
-/var/run), you can specify its location manually:
-
-tinc-gui --pidfile /usr/local/var/run/tinc.vpn.pid
-
-The following things sort of work:
-
-- Changing the debug level from the settings page
-- Viewing the list of connections, nodes, edges and subnets. These lists will
- be refreshed once per second.
-- Right-clicking on a connection brings up a popup menu, which allows you to
- close a connection.
-
-Python was chosen to enable rapid application development, wxWidgets for its
-cross-platform compatibility and platform-native widgets. Once the GUI is
-matured, it will probably rewritten in C++ to allow static linking and easy
-distribution, without needing to install both Python and wxWidgets.
+++ /dev/null
-#!/usr/bin/python
-
-# tinc-gui -- GUI for controlling a running tincd
-# Copyright (C) 2009-2014 Guus Sliepen <guus@tinc-vpn.org>
-# 2014 Dennis Joachimsthaler <dennis@efjot.de>
-#
-# 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.
-
-import string
-import socket
-import wx
-import sys
-import os
-import platform
-import time
-from wx.lib.mixins.listctrl import ColumnSorterMixin
-from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
-
-if platform.system() == 'Windows':
- import _winreg
-
-# Classes to interface with a running tinc daemon
-
-REQ_STOP = 0
-REQ_RELOAD = 1
-REQ_RESTART = 2
-REQ_DUMP_NODES = 3
-REQ_DUMP_EDGES = 4
-REQ_DUMP_SUBNETS = 5
-REQ_DUMP_CONNECTIONS = 6
-REQ_DUMP_GRAPH = 7
-REQ_PURGE = 8
-REQ_SET_DEBUG = 9
-REQ_RETRY = 10
-REQ_CONNECT = 11
-REQ_DISCONNECT = 12
-
-ID = 0
-ACK = 4
-CONTROL = 18
-
-class Node:
- def parse(self, args):
- self.name = args[0]
- self.address = args[1]
- self.port = args[3]
- self.cipher = int(args[4])
- self.digest = int(args[5])
- self.maclength = int(args[6])
- self.compression = int(args[7])
- self.options = int(args[8], 0x10)
- self.status = int(args[9], 0x10)
- self.nexthop = args[10]
- self.via = args[11]
- self.distance = int(args[12])
- self.pmtu = int(args[13])
- self.minmtu = int(args[14])
- self.maxmtu = int(args[15])
- self.last_state_change = float(args[16])
-
- self.subnets = {}
-
-class Edge:
- def parse(self, args):
- self.fr = args[0]
- self.to = args[1]
- self.address = args[2]
- self.port = args[4]
- self.options = int(args[5], 16)
- self.weight = int(args[6])
-
-class Subnet:
- def parse(self, args):
- if args[0].find('#') >= 0:
- (address, self.weight) = args[0].split('#', 1)
- else:
- self.weight = 10
- address = args[0]
-
- if address.find('/') >= 0:
- (self.address, self.prefixlen) = address.split('/', 1)
- else:
- self.address = address
- self.prefixlen = '48'
-
- self.owner = args[1]
-
-class Connection:
- def parse(self, args):
- self.name = args[0]
- self.address = args[1]
- self.port = args[3]
- self.options = int(args[4], 0x10)
- self.socket = int(args[5])
- self.status = int(args[6], 0x10)
- self.weight = 123
-
-class VPN:
- confdir = '/etc/tinc'
- piddir = '/var/run/'
-
- def connect(self):
- # read the pidfile
- f = open(self.pidfile)
- info = string.split(f.readline())
- f.close()
-
- # check if there is a UNIX socket as well
- if self.pidfile.endswith(".pid"):
- unixfile = self.pidfile.replace(".pid", ".socket");
- else:
- unixfile = self.pidfile + ".socket";
-
- if os.path.exists(unixfile):
- # use it if it exists
- print(unixfile + " exists!");
- s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- s.connect(unixfile)
- else:
- # otherwise connect via TCP
- print(unixfile + " does not exist.");
- if ':' in info[2]:
- af = socket.AF_INET6
- else:
- af = socket.AF_INET
- s = socket.socket(af, socket.SOCK_STREAM)
- s.connect((info[2], int(info[4])))
-
- self.sf = s.makefile()
- s.close()
- hello = string.split(self.sf.readline())
- self.name = hello[1]
- self.sf.write('0 ^' + info[1] + ' 17\r\n')
- self.sf.flush()
- resp = string.split(self.sf.readline())
- self.port = info[4]
- self.nodes = {}
- self.edges = {}
- self.subnets = {}
- self.connections = {}
- self.refresh()
-
- def refresh(self):
- self.sf.write('18 3\r\n18 4\r\n18 5\r\n18 6\r\n')
- self.sf.flush()
-
- for node in self.nodes.values():
- node.visited = False
- for edge in self.edges.values():
- edge.visited = False
- for subnet in self.subnets.values():
- subnet.visited = False
- for connections in self.connections.values():
- connections.visited = False
-
- while True:
- resp = string.split(self.sf.readline())
- if len(resp) < 2:
- break
- if resp[0] != '18':
- break
- if resp[1] == '3':
- if len(resp) < 19:
- continue
- node = self.nodes.get(resp[2]) or Node()
- node.parse(resp[2:])
- node.visited = True
- self.nodes[resp[2]] = node
- elif resp[1] == '4':
- if len(resp) < 9:
- continue
- edge = self.nodes.get((resp[2], resp[3])) or Edge()
- edge.parse(resp[2:])
- edge.visited = True
- self.edges[(resp[2], resp[3])] = edge
- elif resp[1] == '5':
- if len(resp) < 4:
- continue
- subnet = self.subnets.get((resp[2], resp[3])) or Subnet()
- subnet.parse(resp[2:])
- subnet.visited = True
- self.subnets[(resp[2], resp[3])] = subnet
- self.nodes[subnet.owner].subnets[resp[2]] = subnet
- elif resp[1] == '6':
- if len(resp) < 9:
- break
- connection = self.connections.get((resp[2], resp[3], resp[5])) or Connection()
- connection.parse(resp[2:])
- connection.visited = True
- self.connections[(resp[2], resp[3], resp[5])] = connection
- else:
- break
-
- for key, subnet in self.subnets.items():
- if not subnet.visited:
- del self.subnets[key]
-
- for key, edge in self.edges.items():
- if not edge.visited:
- del self.edges[key]
-
- for key, node in self.nodes.items():
- if not node.visited:
- del self.nodes[key]
- else:
- for key, subnet in node.subnets.items():
- if not subnet.visited:
- del node.subnets[key]
-
- for key, connection in self.connections.items():
- if not connection.visited:
- del self.connections[key]
-
- def close(self):
- self.sf.close()
-
- def disconnect(self, name):
- self.sf.write('18 12 ' + name + '\r\n')
- self.sf.flush()
- resp = string.split(self.sf.readline())
-
- def debug(self, level = -1):
- self.sf.write('18 9 ' + str(level) + '\r\n')
- self.sf.flush()
- resp = string.split(self.sf.readline())
- return int(resp[2])
-
- def __init__(self, netname = None, pidfile = None):
- if platform.system() == 'Windows':
- sam = _winreg.KEY_READ
- if platform.machine().endswith('64'):
- sam = sam | _winreg.KEY_WOW64_64KEY
- try:
- reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
- try:
- key = _winreg.OpenKey(reg, "SOFTWARE\\tinc", 0, sam)
- except WindowsError:
- key = _winreg.OpenKey(reg, "SOFTWARE\\Wow6432Node\\tinc", 0, sam)
- VPN.confdir = _winreg.QueryValue(key, None)
- except WindowsError:
- pass
-
- if netname:
- self.netname = netname
- self.confbase = os.path.join(VPN.confdir, netname)
- else:
- self.confbase = VPN.confdir
-
- self.tincconf = os.path.join(self.confbase, 'tinc.conf')
-
- if pidfile != None:
- self.pidfile = pidfile
- else:
- if platform.system() == 'Windows':
- self.pidfile = os.path.join(self.confbase, 'pid')
- else:
- if netname:
- self.pidfile = os.path.join(VPN.piddir, 'tinc.' + netname + '.pid')
- else:
- self.pidfile = os.path.join(VPN.piddir, 'tinc.pid')
-
-# GUI starts here
-
-argv0 = sys.argv[0]
-del sys.argv[0]
-netname = None
-pidfile = None
-
-def usage(exitcode = 0):
- print('Usage: ' + argv0 + ' [options]')
- print('\nValid options are:')
- print(' -n, --net=NETNAME Connect to net NETNAME.')
- print(' --pidfile=FILENAME Read control cookie from FILENAME.')
- print(' --help Display this help and exit.')
- print('\nReport bugs to tinc@tinc-vpn.org.')
- sys.exit(exitcode)
-
-while sys.argv:
- if sys.argv[0] in ('-n', '--net'):
- del sys.argv[0]
- netname = sys.argv[0]
- elif sys.argv[0] in ('--pidfile'):
- del sys.argv[0]
- pidfile = sys.argv[0]
- elif sys.argv[0] in ('--help'):
- usage(0)
- else:
- print(argv0 + ': unrecognized option \'' + sys.argv[0] + '\'')
- usage(1)
-
- del sys.argv[0]
-
-if netname == None:
- netname = os.getenv("NETNAME")
-
-if netname == ".":
- netname = None
-
-vpn = VPN(netname, pidfile)
-vpn.connect()
-
-class SuperListCtrl(wx.ListCtrl, ColumnSorterMixin, ListCtrlAutoWidthMixin):
- def __init__(self, parent, style):
- wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
- ListCtrlAutoWidthMixin.__init__(self)
- ColumnSorterMixin.__init__(self, 16)
-
- def GetListCtrl(self):
- return self
-
-
-class SettingsPage(wx.Panel):
- def OnDebugLevel(self, event):
- vpn.debug(self.debug.GetValue())
-
- def __init__(self, parent, id):
- wx.Panel.__init__(self, parent, id)
- grid = wx.FlexGridSizer(cols = 2)
- grid.AddGrowableCol(1, 1)
-
- namelabel = wx.StaticText(self, -1, 'Name:')
- self.name = wx.TextCtrl(self, -1, vpn.name)
- grid.Add(namelabel)
- grid.Add(self.name, 1, wx.EXPAND)
-
- portlabel = wx.StaticText(self, -1, 'Port:')
- self.port = wx.TextCtrl(self, -1, vpn.port)
- grid.Add(portlabel)
- grid.Add(self.port)
-
- debuglabel = wx.StaticText(self, -1, 'Debug level:')
- self.debug = wx.SpinCtrl(self, min = 0, max = 5, initial = vpn.debug())
- self.debug.Bind(wx.EVT_SPINCTRL, self.OnDebugLevel)
- grid.Add(debuglabel)
- grid.Add(self.debug)
-
- modelabel = wx.StaticText(self, -1, 'Mode:')
- self.mode = wx.ComboBox(self, -1, style = wx.CB_READONLY, value = 'Router', choices = ['Router', 'Switch', 'Hub'])
- grid.Add(modelabel)
- grid.Add(self.mode)
-
- self.SetSizer(grid)
-
-class ConnectionsPage(wx.Panel):
- def __init__(self, parent, id):
- wx.Panel.__init__(self, parent, id)
- self.list = SuperListCtrl(self, id)
- self.list.InsertColumn(0, 'Name')
- self.list.InsertColumn(1, 'Address')
- self.list.InsertColumn(2, 'Port')
- self.list.InsertColumn(3, 'Options')
- self.list.InsertColumn(4, 'Weight')
-
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- hbox.Add(self.list, 1, wx.EXPAND)
- self.SetSizer(hbox)
- self.refresh()
-
- class ContextMenu(wx.Menu):
- def __init__(self, item):
- wx.Menu.__init__(self)
-
- self.item = item
-
- disconnect = wx.MenuItem(self, -1, 'Disconnect')
- self.AppendItem(disconnect)
- self.Bind(wx.EVT_MENU, self.OnDisconnect, id=disconnect.GetId())
-
- def OnDisconnect(self, event):
- vpn.disconnect(self.item[0])
-
- def OnContext(self, event):
- i = event.GetIndex()
- self.PopupMenu(self.ContextMenu(self.list.itemDataMap[event.GetIndex()]), event.GetPosition())
-
- def refresh(self):
- sortstate = self.list.GetSortState()
- self.list.itemDataMap = {}
- i = 0
-
- for key, connection in vpn.connections.items():
- if self.list.GetItemCount() <= i:
- self.list.InsertStringItem(i, connection.name)
- else:
- self.list.SetStringItem(i, 0, connection.name)
- self.list.SetStringItem(i, 1, connection.address)
- self.list.SetStringItem(i, 2, connection.port)
- self.list.SetStringItem(i, 3, str(connection.options))
- self.list.SetStringItem(i, 4, str(connection.weight))
- self.list.itemDataMap[i] = (connection.name, connection.address, connection.port, connection.options, connection.weight)
- self.list.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnContext)
- self.list.SetItemData(i, i)
- i += 1
-
- while self.list.GetItemCount() > i:
- self.list.DeleteItem(self.list.GetItemCount() - 1)
-
- self.list.SortListItems(sortstate[0], sortstate[1])
-
-class NodesPage(wx.Panel):
- def __init__(self, parent, id):
- wx.Panel.__init__(self, parent, id)
- self.list = SuperListCtrl(self, id)
- self.list.InsertColumn( 0, 'Name')
- self.list.InsertColumn( 1, 'Address')
- self.list.InsertColumn( 2, 'Port')
- self.list.InsertColumn( 3, 'Cipher')
- self.list.InsertColumn( 4, 'Digest')
- self.list.InsertColumn( 5, 'MACLength')
- self.list.InsertColumn( 6, 'Compression')
- self.list.InsertColumn( 7, 'Options')
- self.list.InsertColumn( 8, 'Status')
- self.list.InsertColumn( 9, 'Nexthop')
- self.list.InsertColumn(10, 'Via')
- self.list.InsertColumn(11, 'Distance')
- self.list.InsertColumn(12, 'PMTU')
- self.list.InsertColumn(13, 'Min MTU')
- self.list.InsertColumn(14, 'Max MTU')
- self.list.InsertColumn(15, 'Since')
-
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- hbox.Add(self.list, 1, wx.EXPAND)
- self.SetSizer(hbox)
- self.refresh()
-
- def refresh(self):
- sortstate = self.list.GetSortState()
- self.list.itemDataMap = {}
- i = 0
-
- for key, node in vpn.nodes.items():
- if self.list.GetItemCount() <= i:
- self.list.InsertStringItem(i, node.name)
- else:
- self.list.SetStringItem(i, 0, node.name)
- self.list.SetStringItem(i, 1, node.address)
- self.list.SetStringItem(i, 2, node.port)
- self.list.SetStringItem(i, 3, str(node.cipher))
- self.list.SetStringItem(i, 4, str(node.digest))
- self.list.SetStringItem(i, 5, str(node.maclength))
- self.list.SetStringItem(i, 6, str(node.compression))
- self.list.SetStringItem(i, 7, format(node.options, "x"))
- self.list.SetStringItem(i, 8, format(node.status, "04x"))
- self.list.SetStringItem(i, 9, node.nexthop)
- self.list.SetStringItem(i, 10, node.via)
- self.list.SetStringItem(i, 11, str(node.distance))
- self.list.SetStringItem(i, 12, str(node.pmtu))
- self.list.SetStringItem(i, 13, str(node.minmtu))
- self.list.SetStringItem(i, 14, str(node.maxmtu))
- if node.last_state_change:
- since = time.strftime("%Y-%m-%d %H:%M", time.localtime(node.last_state_change))
- else:
- since = "never"
- self.list.SetStringItem(i, 15, since)
- self.list.itemDataMap[i] = (node.name, node.address, node.port, node.cipher, node.digest, node.maclength, node.compression, node.options, node.status, node.nexthop, node.via, node.distance, node.pmtu, node.minmtu, node.maxmtu, since)
- self.list.SetItemData(i, i)
- i += 1
-
- while self.list.GetItemCount() > i:
- self.list.DeleteItem(self.list.GetItemCount() - 1)
-
- self.list.SortListItems(sortstate[0], sortstate[1])
-
-class EdgesPage(wx.Panel):
- def __init__(self, parent, id):
- wx.Panel.__init__(self, parent, id)
- self.list = SuperListCtrl(self, id)
- self.list.InsertColumn(0, 'From')
- self.list.InsertColumn(1, 'To')
- self.list.InsertColumn(2, 'Address')
- self.list.InsertColumn(3, 'Port')
- self.list.InsertColumn(4, 'Options')
- self.list.InsertColumn(5, 'Weight')
-
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- hbox.Add(self.list, 1, wx.EXPAND)
- self.SetSizer(hbox)
- self.refresh()
-
- def refresh(self):
- sortstate = self.list.GetSortState()
- self.list.itemDataMap = {}
- i = 0
-
- for key, edge in vpn.edges.items():
- if self.list.GetItemCount() <= i:
- self.list.InsertStringItem(i, edge.fr)
- else:
- self.list.SetStringItem(i, 0, edge.fr)
- self.list.SetStringItem(i, 1, edge.to)
- self.list.SetStringItem(i, 2, edge.address)
- self.list.SetStringItem(i, 3, edge.port)
- self.list.SetStringItem(i, 4, format(edge.options, "x"))
- self.list.SetStringItem(i, 5, str(edge.weight))
- self.list.itemDataMap[i] = (edge.fr, edge.to, edge.address, edge.port, edge.options, edge.weight)
- self.list.SetItemData(i, i)
- i += 1
-
- while self.list.GetItemCount() > i:
- self.list.DeleteItem(self.list.GetItemCount() - 1)
-
- self.list.SortListItems(sortstate[0], sortstate[1])
-
-class SubnetsPage(wx.Panel):
- def __init__(self, parent, id):
- wx.Panel.__init__(self, parent, id)
- self.list = SuperListCtrl(self, id)
- self.list.InsertColumn(0, 'Subnet', wx.LIST_FORMAT_RIGHT)
- self.list.InsertColumn(1, 'Weight', wx.LIST_FORMAT_RIGHT)
- self.list.InsertColumn(2, 'Owner')
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- hbox.Add(self.list, 1, wx.EXPAND)
- self.SetSizer(hbox)
- self.refresh()
-
- def refresh(self):
- sortstate = self.list.GetSortState()
- self.list.itemDataMap = {}
- i = 0
-
- for key, subnet in vpn.subnets.items():
- if self.list.GetItemCount() <= i:
- self.list.InsertStringItem(i, subnet.address + '/' + subnet.prefixlen)
- else:
- self.list.SetStringItem(i, 0, subnet.address + '/' + subnet.prefixlen)
- self.list.SetStringItem(i, 1, subnet.weight)
- self.list.SetStringItem(i, 2, subnet.owner)
- self.list.itemDataMap[i] = (subnet.address + '/' + subnet.prefixlen, subnet.weight, subnet.owner)
- self.list.SetItemData(i, i)
- i += 1
-
- while self.list.GetItemCount() > i:
- self.list.DeleteItem(self.list.GetItemCount() - 1)
-
- self.list.SortListItems(sortstate[0], sortstate[1])
-
-class StatusPage(wx.Panel):
- def __init__(self, parent, id):
- wx.Panel.__init__(self, parent, id)
-
-class GraphPage(wx.Window):
- def __init__(self, parent, id):
- wx.Window.__init__(self, parent, id)
-
-class NetPage(wx.Notebook):
- def __init__(self, parent, id):
- wx.Notebook.__init__(self, parent)
- self.settings = SettingsPage(self, id)
- self.connections = ConnectionsPage(self, id)
- self.nodes = NodesPage(self, id)
- self.edges = EdgesPage(self, id)
- self.subnets = SubnetsPage(self, id)
- self.graph = GraphPage(self, id)
- self.status = StatusPage(self, id)
-
- self.AddPage(self.settings, 'Settings')
- #self.AddPage(self.status, 'Status')
- self.AddPage(self.connections, 'Connections')
- self.AddPage(self.nodes, 'Nodes')
- self.AddPage(self.edges, 'Edges')
- self.AddPage(self.subnets, 'Subnets')
- #self.AddPage(self.graph, 'Graph')
-
-
-class MainWindow(wx.Frame):
- def OnQuit(self, event):
- app.ExitMainLoop()
-
- def OnTimer(self, event):
- vpn.refresh()
- self.np.nodes.refresh()
- self.np.subnets.refresh()
- self.np.edges.refresh()
- self.np.connections.refresh()
-
- def __init__(self, parent, id, title):
- wx.Frame.__init__(self, parent, id, title)
-
- menubar = wx.MenuBar()
- file = wx.Menu()
- file.Append(1, '&Quit\tCtrl-X', 'Quit tinc GUI')
- menubar.Append(file, '&File')
-
- #nb = wx.Notebook(self, -1)
- #nb.SetPadding((0, 0))
- self.np = NetPage(self, -1)
- #nb.AddPage(np, 'VPN')
-
- self.timer = wx.Timer(self, -1)
- self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
- self.timer.Start(1000)
- self.Bind(wx.EVT_MENU, self.OnQuit, id=1)
- self.SetMenuBar(menubar)
- self.Show()
-
-app = wx.App()
-mw = MainWindow(None, -1, 'Tinc GUI')
-
-#def OnTaskBarIcon(event):
-# mw.Raise()
-#
-#icon = wx.Icon("tincgui.ico", wx.BITMAP_TYPE_PNG)
-#taskbaricon = wx.TaskBarIcon()
-#taskbaricon.SetIcon(icon, 'Tinc GUI')
-#wx.EVT_TASKBAR_RIGHT_UP(taskbaricon, OnTaskBarIcon)
-
-app.MainLoop()
-vpn.close()
+++ /dev/null
-dnl Check to find the curses headers/libraries
-
-AC_DEFUN([tinc_CURSES],
-[
- AC_ARG_ENABLE([curses],
- AS_HELP_STRING([--disable-curses], [disable curses support]))
- AS_IF([test "x$enable_curses" != "xno"], [
- AC_DEFINE(HAVE_CURSES, 1, [have curses support])
- curses=true
- AC_ARG_WITH(curses,
- AS_HELP_STRING([--with-curses=DIR], [curses base directory, or:]),
- [curses="$withval"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- LDFLAGS="$LDFLAGS -L$withval/lib"]
- )
-
- AC_ARG_WITH(curses-include,
- AS_HELP_STRING([--with-curses-include=DIR], [curses headers directory]),
- [curses_include="$withval"
- CPPFLAGS="$CPPFLAGS -I$withval"]
- )
-
- AC_ARG_WITH(curses-lib,
- AS_HELP_STRING([--with-curses-lib=DIR], [curses library directory]),
- [curses_lib="$withval"
- LDFLAGS="$LDFLAGS -L$withval"]
- )
-
- AC_CHECK_HEADERS(curses.h,
- [],
- [AC_MSG_ERROR("curses header files not found."); break]
- )
-
- AC_CHECK_LIB(ncurses, initscr,
- [CURSES_LIBS="-lncurses"],
- [AC_CHECK_LIB(curses, initscr,
- [CURSES_LIBS="-lcurses"],
- [AC_MSG_ERROR("curses libraries not found.")]
- )]
- )
- ])
-
- AC_SUBST(CURSES_LIBS)
-])
+++ /dev/null
-dnl Check to find the libgcrypt headers/libraries
-
-AC_DEFUN([tinc_LIBGCRYPT],
-[
- AC_ARG_WITH(libgcrypt,
- AS_HELP_STRING([--with-libgcrypt=DIR], [libgcrypt base directory, or:]),
- [libgcrypt="$withval"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- LDFLAGS="$LDFLAGS -L$withval/lib"]
- )
-
- AC_ARG_WITH(libgcrypt-include,
- AS_HELP_STRING([--with-libgcrypt-include=DIR], [libgcrypt headers directory (without trailing /libgcrypt)]),
- [libgcrypt_include="$withval"
- CPPFLAGS="$CPPFLAGS -I$withval"]
- )
-
- AC_ARG_WITH(libgcrypt-lib,
- AS_HELP_STRING([--with-libgcrypt-lib=DIR], [libgcrypt library directory]),
- [libgcrypt_lib="$withval"
- LDFLAGS="$LDFLAGS -L$withval"]
- )
-
- AC_CHECK_HEADERS([gcrypt.h],
- [],
- [AC_MSG_ERROR([libgcrypt header files not found.]); break]
- )
-
- AC_CHECK_LIB(gcrypt, gcry_cipher_encrypt,
- [LIBS="-lgcrypt $LIBS"],
- [AC_MSG_ERROR([libgcrypt libraries not found.])]
- )
-])
+++ /dev/null
-dnl Check to find the readline headers/libraries
-
-AC_DEFUN([tinc_READLINE],
-[
- AC_ARG_ENABLE([readline],
- AS_HELP_STRING([--disable-readline], [disable readline support]))
- AS_IF([test "x$enable_readline" != "xno"], [
- AC_DEFINE(HAVE_READLINE, 1, [have readline support])
- readline=true
- AC_ARG_WITH(readline,
- AS_HELP_STRING([--with-readline=DIR], [readline base directory, or:]),
- [readline="$withval"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- LDFLAGS="$LDFLAGS -L$withval/lib"]
- )
-
- AC_ARG_WITH(readline-include,
- AS_HELP_STRING([--with-readline-include=DIR], [readline headers directory]),
- [readline_include="$withval"
- CPPFLAGS="$CPPFLAGS -I$withval"]
- )
-
- AC_ARG_WITH(readline-lib,
- AS_HELP_STRING([--with-readline-lib=DIR], [readline library directory]),
- [readline_lib="$withval"
- LDFLAGS="$LDFLAGS -L$withval"]
- )
-
- AC_CHECK_HEADERS([readline/readline.h readline/history.h],
- [],
- [AC_MSG_ERROR("readline header files not found."); break]
- )
-
- AC_CHECK_LIB(readline, readline,
- [READLINE_LIBS="-lreadline"],
- [AC_MSG_ERROR("readline library not found.")],
- [$CURSES_LIBS]
- )
- ])
-
- AC_SUBST(READLINE_LIBS)
-])
## Produce this file with automake to get Makefile.in
-sbin_PROGRAMS = tincd tinc sptps_test
+sbin_PROGRAMS = sptps_test
if LINUX
sbin_PROGRAMS += sptps_speed
DEFAULT_INCLUDES =
-tincd_SOURCES = \
- buffer.c buffer.h \
- cipher.h \
- conf.c conf.h \
- connection.c connection.h \
- control.c control.h \
- control_common.h \
- crypto.h \
- device.h \
- digest.h \
- dropin.c dropin.h \
- dummy_device.c \
- ecdh.h \
- ecdsa.h \
- ecdsagen.h \
- edge.c edge.h \
- ethernet.h \
- event.c event.h \
- fake-gai-errnos.h \
- fake-getaddrinfo.c fake-getaddrinfo.h \
- fake-getnameinfo.c fake-getnameinfo.h \
- getopt.c getopt.h \
- getopt1.c \
- graph.c graph.h \
- hash.c hash.h \
- have.h \
- ipv4.h \
- ipv6.h \
- list.c list.h \
- logger.c logger.h \
- meta.c meta.h \
- multicast_device.c \
- names.c names.h \
- net.c net.h \
- net_packet.c \
- net_setup.c \
- net_socket.c \
- netutl.c netutl.h \
- node.c node.h \
- prf.h \
- process.c process.h \
- protocol.c protocol.h \
- protocol_auth.c \
- protocol_edge.c \
- protocol_key.c \
- protocol_misc.c \
- protocol_subnet.c \
- raw_socket_device.c \
- route.c route.h \
- rsa.h \
- rsagen.h \
- script.c script.h \
- splay_tree.c splay_tree.h \
- sptps.c sptps.h \
- subnet.c subnet.h \
- subnet_parse.c \
- system.h \
- tincd.c \
- utils.c utils.h \
- xalloc.h
-
-tincd_CFLAGS = -fPIC
-
-tinc_SOURCES = \
- dropin.c dropin.h \
- getopt.c getopt.h \
- getopt1.c \
- info.c info.h \
- invitation.c invitation.h \
- list.c list.h \
- names.c names.h \
- netutl.c netutl.h \
- script.c script.h \
- sptps.c sptps.h \
- subnet_parse.c subnet.h \
- tincctl.c tincctl.h \
- top.c top.h \
- utils.c utils.h
-
-tinc_CFLAGS = -fPIC
-
sptps_test_SOURCES = \
logger.c logger.h \
sptps.c sptps.h \
cipher.h \
conf.c conf.h \
connection.c connection.h \
- control.c control.h \
- control_common.h \
crypto.h \
- device.h \
digest.h \
dropin.c dropin.h \
- dummy_device.c \
ecdh.h \
ecdsa.h \
ecdsagen.h \
list.c list.h \
logger.c logger.h \
meta.c meta.h \
- multicast_device.c \
- names.c names.h \
net.c net.h \
net_packet.c \
net_setup.c \
netutl.c netutl.h \
node.c node.h \
prf.h \
- process.c process.h \
protocol.c protocol.h \
protocol_auth.c \
protocol_edge.c \
protocol_key.c \
protocol_misc.c \
- protocol_subnet.c \
- raw_socket_device.c \
route.c route.h \
rsa.h \
rsagen.h \
- script.c script.h \
splay_tree.c splay_tree.h \
sptps.c sptps.h \
- subnet.c subnet.h \
- subnet_parse.c \
system.h \
tincd.c \
utils.c utils.h \
libmeshlink_la_LIBADD = -lpthread
-## Conditionally compile device drivers
-
-if LINUX
-tincd_SOURCES += linux/device.c
-libmeshlink_la_SOURCES +=linux/device.c
-endif
-
-if BSD
-tincd_SOURCES += bsd/device.c
-if TUNEMU
-tincd_SOURCES += bsd/tunemu.c bsd/tunemu.h
-endif
-endif
-
-if SOLARIS
-tincd_SOURCES += solaris/device.c
-endif
-
-if MINGW
-tincd_SOURCES += mingw/device.c mingw/common.h
-endif
-
-if CYGWIN
-tincd_SOURCES += cygwin/device.c
-endif
-
-if UML
-tincd_SOURCES += uml_device.c
-endif
-
-if VDE
-tincd_SOURCES += vde_device.c
-endif
-
-if OPENSSL
-tincd_SOURCES += \
- openssl/cipher.c \
- openssl/crypto.c \
- openssl/digest.c openssl/digest.h \
- openssl/ecdh.c \
- openssl/ecdsa.c \
- openssl/prf.c \
- openssl/rsa.c
-tinc_SOURCES += \
- openssl/cipher.c \
- openssl/crypto.c \
- openssl/digest.c openssl/digest.h \
- openssl/ecdh.c \
- openssl/ecdsa.c \
- openssl/ecdsagen.c \
- openssl/prf.c \
- openssl/rsa.c \
- openssl/rsagen.c
libmeshlink_la_SOURCES += \
openssl/cipher.c \
openssl/crypto.c \
openssl/ecdsa.c \
openssl/ecdsagen.c \
openssl/prf.c
-endif
-if GCRYPT
-tincd_SOURCES += \
- gcrypt/cipher.c \
- gcrypt/crypto.c \
- gcrypt/digest.c gcrypt/digest.h \
- gcrypt/ecdh.c \
- gcrypt/ecdsa.c \
- gcrypt/prf.c \
- gcrypt/rsa.c
-tinc_SOURCES += \
- gcrypt/cipher.c \
- gcrypt/crypto.c \
- gcrypt/digest.c gcrypt/digest.h \
- gcrypt/ecdh.c \
- gcrypt/ecdsa.c \
- gcrypt/ecdsagen.c \
- gcrypt/prf.c \
- gcrypt/rsa.c \
- gcrypt/rsagen.c
-sptps_test_SOURCES += \
- gcrypt/cipher.c \
- gcrypt/crypto.c \
- gcrypt/digest.c gcrypt/digest.h \
- gcrypt/ecdh.c \
- gcrypt/ecdsa.c \
- gcrypt/prf.c
-endif
-
-tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
sptps_speed_LDADD = -lrt
LIBS = @LIBS@
-if TUNEMU
-LIBS += -lpcap
-endif
-
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
+++ /dev/null
-/*
- device.c -- Interaction BSD tun/tap device
- Copyright (C) 2001-2005 Ivo Timmermans,
- 2001-2013 Guus Sliepen <guus@tinc-vpn.org>
- 2009 Grzegorz Dymarek <gregd72002@googlemail.com>
-
- 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 "../logger.h"
-#include "../names.h"
-#include "../net.h"
-#include "../route.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-#ifdef ENABLE_TUNEMU
-#include "bsd/tunemu.h"
-#endif
-
-#define DEFAULT_TUN_DEVICE "/dev/tun0"
-#if defined(HAVE_FREEBSD) || defined(HAVE_NETBSD)
-#define DEFAULT_TAP_DEVICE "/dev/tap0"
-#else
-#define DEFAULT_TAP_DEVICE "/dev/tun0"
-#endif
-
-typedef enum device_type {
- DEVICE_TYPE_TUN,
- DEVICE_TYPE_TUNIFHEAD,
- DEVICE_TYPE_TAP,
-#ifdef ENABLE_TUNEMU
- DEVICE_TYPE_TUNEMU,
-#endif
-} device_type_t;
-
-int device_fd = -1;
-char *device = NULL;
-char *iface = NULL;
-static char *device_info = NULL;
-#if defined(ENABLE_TUNEMU)
-static device_type_t device_type = DEVICE_TYPE_TUNEMU;
-#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) || defined(HAVE_DRAGONFLY)
-static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
-#else
-static device_type_t device_type = DEVICE_TYPE_TUN;
-#endif
-
-static bool setup_device(void) {
- char *type;
-
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
- if(routing_mode == RMODE_ROUTER)
- device = xstrdup(DEFAULT_TUN_DEVICE);
- else
- device = xstrdup(DEFAULT_TAP_DEVICE);
- }
-
- if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
- iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device);
-
- if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
- if(!strcasecmp(type, "tun"))
- /* use default */;
-#ifdef ENABLE_TUNEMU
- else if(!strcasecmp(type, "tunemu"))
- device_type = DEVICE_TYPE_TUNEMU;
-#endif
- else if(!strcasecmp(type, "tunnohead"))
- device_type = DEVICE_TYPE_TUN;
- else if(!strcasecmp(type, "tunifhead"))
- device_type = DEVICE_TYPE_TUNIFHEAD;
- else if(!strcasecmp(type, "tap"))
- device_type = DEVICE_TYPE_TAP;
- else {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type);
- return false;
- }
- } else {
- if(strstr(device, "tap") || routing_mode != RMODE_ROUTER)
- device_type = DEVICE_TYPE_TAP;
- }
-
- switch(device_type) {
-#ifdef ENABLE_TUNEMU
- case DEVICE_TYPE_TUNEMU: {
- char dynamic_name[256] = "";
- device_fd = tunemu_open(dynamic_name);
- }
- break;
-#endif
- default:
- device_fd = open(device, O_RDWR | O_NONBLOCK);
- }
-
- if(device_fd < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device, strerror(errno));
- return false;
- }
-
-#ifdef FD_CLOEXEC
- fcntl(device_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- switch(device_type) {
- default:
- device_type = DEVICE_TYPE_TUN;
- case DEVICE_TYPE_TUN:
-#ifdef TUNSIFHEAD
- {
- const int zero = 0;
- if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof zero) == -1) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
- return false;
- }
- }
-#endif
-#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
- {
- const int mode = IFF_BROADCAST | IFF_MULTICAST;
- ioctl(device_fd, TUNSIFMODE, &mode, sizeof mode);
- }
-#endif
-
- device_info = "Generic BSD tun device";
- break;
- case DEVICE_TYPE_TUNIFHEAD:
-#ifdef TUNSIFHEAD
- {
- const int one = 1;
- if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof one) == -1) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "ioctl", strerror(errno));
- return false;
- }
- }
-#endif
-#if defined(TUNSIFMODE) && defined(IFF_BROADCAST) && defined(IFF_MULTICAST)
- {
- const int mode = IFF_BROADCAST | IFF_MULTICAST;
- ioctl(device_fd, TUNSIFMODE, &mode, sizeof mode);
- }
-#endif
-
- device_info = "Generic BSD tun device";
- break;
- case DEVICE_TYPE_TAP:
- if(routing_mode == RMODE_ROUTER)
- overwrite_mac = true;
- device_info = "Generic BSD tap device";
-#ifdef TAPGIFNAME
- {
- struct ifreq ifr;
- if(ioctl(device_fd, TAPGIFNAME, (void*)&ifr) == 0) {
- if(iface)
- free(iface);
- iface = xstrdup(ifr.ifr_name);
- }
- }
-
-#endif
- break;
-#ifdef ENABLE_TUNEMU
- case DEVICE_TYPE_TUNEMU:
- device_info = "BSD tunemu device";
- break;
-#endif
- }
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
-
- return true;
-}
-
-static void close_device(void) {
- switch(device_type) {
-#ifdef ENABLE_TUNEMU
- case DEVICE_TYPE_TUNEMU:
- tunemu_close(device_fd);
- break;
-#endif
- default:
- close(device_fd);
- }
-
- free(device);
- free(iface);
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- int inlen;
-
- switch(device_type) {
- case DEVICE_TYPE_TUN:
-#ifdef ENABLE_TUNEMU
- case DEVICE_TYPE_TUNEMU:
- if(device_type == DEVICE_TYPE_TUNEMU)
- inlen = tunemu_read(device_fd, packet->data + 14, MTU - 14);
- else
-#endif
- inlen = read(device_fd, packet->data + 14, MTU - 14);
-
- if(inlen <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
- return false;
- }
-
- switch(packet->data[14] >> 4) {
- case 4:
- packet->data[12] = 0x08;
- packet->data[13] = 0x00;
- break;
- case 6:
- packet->data[12] = 0x86;
- packet->data[13] = 0xDD;
- break;
- default:
- logger(DEBUG_TRAFFIC, LOG_ERR,
- "Unknown IP version %d while reading packet from %s %s",
- packet->data[14] >> 4, device_info, device);
- return false;
- }
-
- memset(packet->data, 0, 12);
- packet->len = inlen + 14;
- break;
-
- case DEVICE_TYPE_TUNIFHEAD: {
- u_int32_t type;
- struct iovec vector[2] = {{&type, sizeof type}, {packet->data + 14, MTU - 14}};
-
- if((inlen = readv(device_fd, vector, 2)) <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
- return false;
- }
-
- switch (ntohl(type)) {
- case AF_INET:
- packet->data[12] = 0x08;
- packet->data[13] = 0x00;
- break;
-
- case AF_INET6:
- packet->data[12] = 0x86;
- packet->data[13] = 0xDD;
- break;
-
- default:
- logger(DEBUG_TRAFFIC, LOG_ERR,
- "Unknown address family %x while reading packet from %s %s",
- ntohl(type), device_info, device);
- return false;
- }
-
- memset(packet->data, 0, 12);
- packet->len = inlen + 10;
- break;
- }
-
- case DEVICE_TYPE_TAP:
- if((inlen = read(device_fd, packet->data, MTU)) <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
- return false;
- }
-
- packet->len = inlen;
- break;
-
- default:
- return false;
- }
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s",
- packet->len, device_info);
-
- return true;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
- packet->len, device_info);
-
- switch(device_type) {
- case DEVICE_TYPE_TUN:
- if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
- device, strerror(errno));
- return false;
- }
- break;
-
- case DEVICE_TYPE_TUNIFHEAD: {
- u_int32_t type;
- struct iovec vector[2] = {{&type, sizeof type}, {packet->data + 14, packet->len - 14}};
- int af;
-
- af = (packet->data[12] << 8) + packet->data[13];
-
- switch (af) {
- case 0x0800:
- type = htonl(AF_INET);
- break;
- case 0x86DD:
- type = htonl(AF_INET6);
- break;
- default:
- logger(DEBUG_TRAFFIC, LOG_ERR,
- "Unknown address family %x while writing packet to %s %s",
- af, device_info, device);
- return false;
- }
-
- if(writev(device_fd, vector, 2) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
- strerror(errno));
- return false;
- }
- break;
- }
-
- case DEVICE_TYPE_TAP:
- if(write(device_fd, packet->data, packet->len) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
- device, strerror(errno));
- return false;
- }
- break;
-
-#ifdef ENABLE_TUNEMU
- case DEVICE_TYPE_TUNEMU:
- if(tunemu_write(device_fd, packet->data + 14, packet->len - 14) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info,
- device, strerror(errno));
- return false;
- }
- break;
-#endif
-
- default:
- return false;
- }
-
- return true;
-}
-
-const devops_t os_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
+++ /dev/null
-/*
- * tunemu - Tun device emulation for Darwin
- * Copyright (C) 2009 Friedrich Schöller <friedrich.schoeller@gmail.com>
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "tunemu.h"
-
-#include <sys/socket.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <util.h>
-#include <pcap.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdint.h>
-#include <ctype.h>
-#include <fcntl.h>
-
-#define PPPPROTO_CTL 1
-
-#define PPP_IP 0x21
-#define PPP_IPV6 0x57
-
-#define SC_LOOP_TRAFFIC 0x00000200
-
-#define PPPIOCNEWUNIT _IOWR('t', 62, int)
-#define PPPIOCSFLAGS _IOW('t', 89, int)
-#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl)
-#define PPPIOCATTCHAN _IOW('t', 56, int)
-#define PPPIOCGCHAN _IOR('t', 55, int)
-#define PPPIOCCONNECT _IOW('t', 58, int)
-#define PPPIOCGUNIT _IOR('t', 86, int)
-
-struct sockaddr_ppp
-{
- u_int8_t ppp_len;
- u_int8_t ppp_family;
- u_int16_t ppp_proto;
- u_int32_t ppp_cookie;
-};
-
-enum NPmode
-{
- NPMODE_PASS,
- NPMODE_DROP,
- NPMODE_ERROR,
- NPMODE_QUEUE
-};
-
-struct npioctl
-{
- int protocol;
- enum NPmode mode;
-};
-
-#define PPP_KEXT_PATH "/System/Library/Extensions/PPP.kext"
-
-#define ERROR_BUFFER_SIZE 1024
-
-char tunemu_error[ERROR_BUFFER_SIZE];
-
-static int pcap_use_count = 0;
-static pcap_t *pcap = NULL;
-
-static int data_buffer_length = 0;
-static char *data_buffer = NULL;
-
-static void tun_error(char *format, ...)
-{
- va_list vl;
- va_start(vl, format);
- vsnprintf(tunemu_error, ERROR_BUFFER_SIZE, format, vl);
- va_end(vl);
-}
-
-static void tun_noerror()
-{
- *tunemu_error = 0;
-}
-
-static void closeall()
-{
- int fd = getdtablesize();
- while (fd--)
- close(fd);
-
- open("/dev/null", O_RDWR, 0);
- dup(0);
- dup(0);
-}
-
-static int ppp_load_kext()
-{
- int pid = fork();
- if (pid < 0)
- {
- tun_error("fork for ppp kext: %s", strerror(errno));
- return -1;
- }
-
- if (pid == 0)
- {
- closeall();
- execle("/sbin/kextload", "kextload", PPP_KEXT_PATH, NULL, NULL);
- exit(1);
- }
-
- int status;
- while (waitpid(pid, &status, 0) < 0)
- {
- if (errno == EINTR)
- continue;
-
- tun_error("waitpid for ppp kext: %s", strerror(errno));
- return -1;
- }
-
- if (WEXITSTATUS(status) != 0)
- {
- tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH);
- return -1;
- }
-
- tun_noerror();
- return 0;
-}
-
-static int ppp_new_instance()
-{
- // create ppp socket
- int ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL);
- if (ppp_sockfd < 0)
- {
- if (ppp_load_kext() < 0)
- return -1;
-
- ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL);
- if (ppp_sockfd < 0)
- {
- tun_error("creating ppp socket: %s", strerror(errno));
- return -1;
- }
- }
-
- // connect to ppp procotol
- struct sockaddr_ppp pppaddr;
- pppaddr.ppp_len = sizeof(struct sockaddr_ppp);
- pppaddr.ppp_family = AF_PPP;
- pppaddr.ppp_proto = PPPPROTO_CTL;
- pppaddr.ppp_cookie = 0;
- if (connect(ppp_sockfd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0)
- {
- tun_error("connecting ppp socket: %s", strerror(errno));
- close(ppp_sockfd);
- return -1;
- }
-
- tun_noerror();
- return ppp_sockfd;
-}
-
-static int ppp_new_unit(int *unit_number)
-{
- int fd = ppp_new_instance();
- if (fd < 0)
- return -1;
-
- // create ppp unit
- if (ioctl(fd, PPPIOCNEWUNIT, unit_number) < 0)
- {
- tun_error("creating ppp unit: %s", strerror(errno));
- close(fd);
- return -1;
- }
-
- tun_noerror();
- return fd;
-}
-
-static int ppp_setup_unit(int unit_fd)
-{
- // send traffic to program
- int flags = SC_LOOP_TRAFFIC;
- if (ioctl(unit_fd, PPPIOCSFLAGS, &flags) < 0)
- {
- tun_error("setting ppp loopback mode: %s", strerror(errno));
- return -1;
- }
-
- // allow packets
- struct npioctl npi;
- npi.protocol = PPP_IP;
- npi.mode = NPMODE_PASS;
- if (ioctl(unit_fd, PPPIOCSNPMODE, &npi) < 0)
- {
- tun_error("starting ppp unit: %s", strerror(errno));
- return -1;
- }
-
- tun_noerror();
- return 0;
-}
-
-static int open_pcap()
-{
- if (pcap != NULL)
- {
- pcap_use_count++;
- return 0;
- }
-
- char errbuf[PCAP_ERRBUF_SIZE];
- pcap = pcap_open_live("lo0", BUFSIZ, 0, 1, errbuf);
- pcap_use_count = 1;
-
- if (pcap == NULL)
- {
- tun_error("opening pcap: %s", errbuf);
- return -1;
- }
-
- tun_noerror();
- return 0;
-}
-
-static void close_pcap()
-{
- if (pcap == NULL)
- return;
-
- pcap_use_count--;
- if (pcap_use_count == 0)
- {
- pcap_close(pcap);
- pcap = NULL;
- }
-}
-
-static void allocate_data_buffer(int size)
-{
- if (data_buffer_length < size)
- {
- free(data_buffer);
- data_buffer_length = size;
- data_buffer = malloc(data_buffer_length);
- }
-}
-
-static void make_device_name(tunemu_device device, int unit_number)
-{
- snprintf(device, sizeof(tunemu_device), "ppp%d", unit_number);
-}
-
-static int check_device_name(tunemu_device device)
-{
- if (strlen(device) < 4)
- return -1;
-
- int unit_number = atoi(device + 3);
- if (unit_number < 0 || unit_number > 999)
- return -1;
-
- tunemu_device compare;
- make_device_name(compare, unit_number);
-
- if (strcmp(device, compare) != 0)
- return -1;
-
- return 0;
-}
-
-int tunemu_open(tunemu_device device)
-{
- int ppp_unit_number = -1;
- if (device[0] != 0)
- {
- if (check_device_name(device) < 0)
- {
- tun_error("invalid device name \"%s\"", device);
- return -1;
- }
-
- ppp_unit_number = atoi(device + 3);
- }
-
- int ppp_unit_fd = ppp_new_unit(&ppp_unit_number);
- if (ppp_unit_fd < 0)
- return -1;
-
- if (ppp_setup_unit(ppp_unit_fd) < 0)
- {
- close(ppp_unit_fd);
- return -1;
- }
-
- if (open_pcap() < 0)
- {
- close(ppp_unit_fd);
- return -1;
- }
-
- make_device_name(device, ppp_unit_number);
-
- return ppp_unit_fd;
-}
-
-int tunemu_close(int ppp_sockfd)
-{
- int ret = close(ppp_sockfd);
-
- if (ret == 0)
- close_pcap();
-
- return ret;
-}
-
-int tunemu_read(int ppp_sockfd, char *buffer, int length)
-{
- allocate_data_buffer(length + 2);
-
- length = read(ppp_sockfd, data_buffer, length + 2);
- if (length < 0)
- {
- tun_error("reading packet: %s", strerror(errno));
- return length;
- }
- tun_noerror();
-
- length -= 2;
- if (length < 0)
- return 0;
-
- memcpy(buffer, data_buffer + 2, length);
-
- return length;
-}
-
-int tunemu_write(int ppp_sockfd, char *buffer, int length)
-{
- allocate_data_buffer(length + 4);
-
- data_buffer[0] = 0x02;
- data_buffer[1] = 0x00;
- data_buffer[2] = 0x00;
- data_buffer[3] = 0x00;
-
- memcpy(data_buffer + 4, buffer, length);
-
- if (pcap == NULL)
- {
- tun_error("pcap not open");
- return -1;
- }
-
- length = pcap_inject(pcap, data_buffer, length + 4);
- if (length < 0)
- {
- tun_error("injecting packet: %s", pcap_geterr(pcap));
- return length;
- }
- tun_noerror();
-
- length -= 4;
- if (length < 0)
- return 0;
-
- return length;
-}
+++ /dev/null
-/*
- * tunemu - Tun device emulation for Darwin
- * Copyright (C) 2009 Friedrich Schöller <friedrich.schoeller@gmail.com>
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef TUNEMU_H
-#define TUNEMU_H
-
-typedef char tunemu_device[7];
-
-extern char tunemu_error[];
-
-int tunemu_open(tunemu_device dev);
-int tunemu_close(int fd);
-int tunemu_read(int fd, char *buffer, int length);
-int tunemu_write(int fd, char *buffer, int length);
-
-#endif
#include "conf.h"
#include "list.h"
#include "logger.h"
-#include "names.h"
#include "netutl.h" /* for str2address */
#include "protocol.h"
#include "utils.h" /* for cp */
return false;
}
-bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
- subnet_t subnet = {NULL};
-
- if(!cfg)
- return false;
-
- if(!str2net(&subnet, cfg->value)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
- cfg->variable, cfg->file, cfg->line);
- return false;
- }
-
- /* Teach newbies what subnets are... */
-
- if(((subnet.type == SUBNET_IPV4)
- && !maskcheck(&subnet.net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof subnet.net.ipv4.address))
- || ((subnet.type == SUBNET_IPV6)
- && !maskcheck(&subnet.net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof subnet.net.ipv6.address))) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Network address and prefix length do not match for configuration variable %s in %s line %d",
- cfg->variable, cfg->file, cfg->line);
- return false;
- }
-
- *(*result = new_subnet()) = subnet;
-
- return true;
-}
-
/*
Read exactly one line and strip the trailing newline if any.
*/
int line;
} config_t;
-#include "subnet.h"
-
extern splay_tree_t *config_tree;
extern int pinginterval;
extern bool get_config_int(const config_t *, int *);
extern bool get_config_string(const config_t *, char **);
extern bool get_config_address(const config_t *, struct addrinfo **);
-extern bool get_config_subnet(const config_t *, struct subnet_t **);
extern config_t *parse_config_line(char *, const char *, int);
extern bool read_config_file(splay_tree_t *, const char *);
#include "list.h"
#include "cipher.h"
#include "conf.h"
-#include "control_common.h"
+#include "connection.h"
#include "list.h"
#include "logger.h"
#include "rsa.h"
-#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
void connection_del(connection_t *c) {
list_delete(connection_list, c);
}
-
-bool dump_connections(connection_t *cdump) {
- for list_each(connection_t, c, connection_list) {
- send_request(cdump, "%d %d %s %s %x %d %x",
- CONTROL, REQ_DUMP_CONNECTIONS,
- c->name, c->hostname, c->options, c->socket,
- bitfield_to_int(&c->status, sizeof c->status));
- }
-
- return send_request(cdump, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS);
-}
extern void free_connection(connection_t *);
extern void connection_add(connection_t *);
extern void connection_del(connection_t *);
-extern bool dump_connections(struct connection_t *);
#endif /* __TINC_CONNECTION_H__ */
+++ /dev/null
-/*
- control.c -- Control socket handling.
- Copyright (C) 2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "crypto.h"
-#include "conf.h"
-#include "control.h"
-#include "control_common.h"
-#include "graph.h"
-#include "logger.h"
-#include "meta.h"
-#include "names.h"
-#include "net.h"
-#include "netutl.h"
-#include "protocol.h"
-#include "route.h"
-#include "utils.h"
-#include "xalloc.h"
-
-char controlcookie[65];
-
-static bool control_return(connection_t *c, int type, int error) {
- return send_request(c, "%d %d %d", CONTROL, type, error);
-}
-
-static bool control_ok(connection_t *c, int type) {
- return control_return(c, type, 0);
-}
-
-bool control_h(connection_t *c, const char *request) {
- int type;
-
- if(!c->status.control || c->allow_request != CONTROL) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unauthorized control request from %s (%s)", c->name, c->hostname);
- return false;
- }
-
- if(sscanf(request, "%*d %d", &type) != 1) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CONTROL", c->name, c->hostname);
- return false;
- }
-
- switch (type) {
- case REQ_STOP:
- event_exit();
- return control_ok(c, REQ_STOP);
-
- case REQ_DUMP_NODES:
- return dump_nodes(c);
-
- case REQ_DUMP_EDGES:
- return dump_edges(c);
-
- case REQ_DUMP_SUBNETS:
- return dump_subnets(c);
-
- case REQ_DUMP_CONNECTIONS:
- return dump_connections(c);
-
- case REQ_PURGE:
- purge();
- return control_ok(c, REQ_PURGE);
-
- case REQ_SET_DEBUG: {
- int new_level;
- if(sscanf(request, "%*d %*d %d", &new_level) != 1)
- return false;
- send_request(c, "%d %d %d", CONTROL, REQ_SET_DEBUG, debug_level);
- if(new_level >= 0)
- debug_level = new_level;
- return true;
- }
-
- case REQ_RETRY:
- retry();
- return control_ok(c, REQ_RETRY);
-
- case REQ_RELOAD:
- logger(DEBUG_ALWAYS, LOG_NOTICE, "Got '%s' command", "reload");
- int result = reload_configuration();
- return control_return(c, REQ_RELOAD, result);
-
- case REQ_DISCONNECT: {
- char name[MAX_STRING_SIZE];
- bool found = false;
-
- if(sscanf(request, "%*d %*d " MAX_STRING, name) != 1)
- return control_return(c, REQ_DISCONNECT, -1);
-
- for list_each(connection_t, other, connection_list) {
- if(strcmp(other->name, name))
- continue;
- terminate_connection(other, other->status.active);
- found = true;
- }
-
- return control_return(c, REQ_DISCONNECT, found ? 0 : -2);
- }
-
- case REQ_DUMP_TRAFFIC:
- return dump_traffic(c);
-
- case REQ_PCAP:
- sscanf(request, "%*d %*d %d", &c->outmaclength);
- c->status.pcap = true;
- pcap = true;
- return true;
-
- case REQ_LOG:
- sscanf(request, "%*d %*d %d", &c->outcompression);
- c->status.log = true;
- logcontrol = true;
- return true;
-
- default:
- return send_request(c, "%d %d", CONTROL, REQ_INVALID);
- }
-}
-
-bool init_control(void) {
- randomize(controlcookie, sizeof controlcookie / 2);
- bin2hex(controlcookie, controlcookie, sizeof controlcookie / 2);
-
- mode_t mask = umask(0);
- umask(mask | 077);
- FILE *f = fopen(pidfilename, "w");
- umask(mask);
-
- if(!f) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Cannot write control socket cookie file %s: %s", pidfilename, strerror(errno));
- return false;
- }
-
- // Get the address and port of the first listening socket
-
- char *localhost = NULL;
- sockaddr_t sa;
- socklen_t len = sizeof sa;
-
- // Make sure we have a valid address, and map 0.0.0.0 and :: to 127.0.0.1 and ::1.
-
- if(getsockname(listen_socket[0].tcp.fd, (struct sockaddr *)&sa, &len)) {
- xasprintf(&localhost, "127.0.0.1 port %s", myport);
- } else {
- if(sa.sa.sa_family == AF_INET) {
- if(sa.in.sin_addr.s_addr == 0)
- sa.in.sin_addr.s_addr = htonl(0x7f000001);
- } else if(sa.sa.sa_family == AF_INET6) {
- static const uint8_t zero[16] = {0};
- if(!memcmp(sa.in6.sin6_addr.s6_addr, zero, sizeof zero))
- sa.in6.sin6_addr.s6_addr[15] = 1;
- }
-
- localhost = sockaddr2hostname(&sa);
- }
-
- fprintf(f, "%d %s %s\n", (int)getpid(), controlcookie, localhost);
-
- free(localhost);
- fclose(f);
-
-#ifndef HAVE_MINGW
- int unix_fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(unix_fd < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not create UNIX socket: %s", sockstrerror(errno));
- return false;
- }
-
- struct sockaddr_un sa_un;
- sa_un.sun_family = AF_UNIX;
- strncpy(sa_un.sun_path, unixsocketname, sizeof sa_un.sun_path);
-
- if(connect(unix_fd, (struct sockaddr *)&sa_un, sizeof sa_un) >= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname);
- return false;
- }
-
- unlink(unixsocketname);
-
- umask(mask | 077);
- int result = bind(unix_fd, (struct sockaddr *)&sa_un, sizeof sa_un);
- umask(mask);
-
- if(result < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind UNIX socket to %s: %s", unixsocketname, sockstrerror(errno));
- return false;
- }
-
- if(listen(unix_fd, 3) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not listen on UNIX socket %s: %s", unixsocketname, sockstrerror(errno));
- return false;
- }
-
- io_add(&unix_socket, handle_new_unix_connection, &unix_socket, unix_fd, IO_READ);
-#endif
-
- return true;
-}
-
-void exit_control(void) {
-#ifndef HAVE_MINGW
- unlink(unixsocketname);
- io_del(&unix_socket);
- close(unix_socket.fd);
-#endif
-
- unlink(pidfilename);
-}
+++ /dev/null
-/*
- control.h -- header for control.c.
- Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_CONTROL_H__
-#define __TINC_CONTROL_H__
-
-extern bool init_control();
-extern void exit_control();
-extern char controlcookie[];
-
-#endif
+++ /dev/null
-/*
- control_protocol.h -- control socket protocol.
- Copyright (C) 2007 Scott Lamb <slamb@slamb.org>
- 2009-2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_CONTROL_PROTOCOL_H__
-#define __TINC_CONTROL_PROTOCOL_H__
-
-#include "protocol.h"
-
-enum request_type {
- REQ_INVALID = -1,
- REQ_STOP = 0,
- REQ_RELOAD,
- REQ_RESTART,
- REQ_DUMP_NODES,
- REQ_DUMP_EDGES,
- REQ_DUMP_SUBNETS,
- REQ_DUMP_CONNECTIONS,
- REQ_DUMP_GRAPH,
- REQ_PURGE,
- REQ_SET_DEBUG,
- REQ_RETRY,
- REQ_CONNECT,
- REQ_DISCONNECT,
- REQ_DUMP_TRAFFIC,
- REQ_PCAP,
- REQ_LOG,
-};
-
-#define TINC_CTL_VERSION_CURRENT 0
-
-#endif
+++ /dev/null
-/*
- device.c -- Interaction with Windows tap driver in a Cygwin environment
- Copyright (C) 2002-2005 Ivo Timmermans,
- 2002-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <w32api/windows.h>
-#include <w32api/winioctl.h>
-
-#include "../conf.h"
-#include "../device.h"
-#include "../logger.h"
-#include "../names.h"
-#include "../net.h"
-#include "../route.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-#include "../mingw/common.h"
-
-int device_fd = -1;
-static HANDLE device_handle = INVALID_HANDLE_VALUE;
-char *device = NULL;
-char *iface = NULL;
-static char *device_info = NULL;
-
-static pid_t reader_pid;
-static int sp[2];
-
-static bool setup_device(void) {
- HKEY key, key2;
- int i, err;
-
- char regpath[1024];
- char adapterid[1024];
- char adaptername[1024];
- char tapname[1024];
- char gelukt = 0;
- long len;
-
- bool found = false;
-
- get_config_string(lookup_config(config_tree, "Device"), &device);
- get_config_string(lookup_config(config_tree, "Interface"), &iface);
-
- /* Open registry and look for network adapters */
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read registry: %s", winerror(GetLastError()));
- return false;
- }
-
- for (i = 0; ; i++) {
- len = sizeof adapterid;
- if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
- break;
-
- /* Find out more about this adapter */
-
- snprintf(regpath, sizeof regpath, "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
- continue;
-
- len = sizeof adaptername;
- err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len);
-
- RegCloseKey(key2);
-
- if(err)
- continue;
-
- if(device) {
- if(!strcmp(device, adapterid)) {
- found = true;
- break;
- } else
- continue;
- }
-
- if(iface) {
- if(!strcmp(iface, adaptername)) {
- found = true;
- break;
- } else
- continue;
- }
-
- snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
- device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
- if(device_handle != INVALID_HANDLE_VALUE) {
- CloseHandle(device_handle);
- found = true;
- break;
- }
- }
-
- RegCloseKey(key);
-
- if(!found) {
- logger(DEBUG_ALWAYS, LOG_ERR, "No Windows tap device found!");
- return false;
- }
-
- if(!device)
- device = xstrdup(adapterid);
-
- if(!iface)
- iface = xstrdup(adaptername);
-
- snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
-
- /* Now we are going to open this device twice: once for reading and once for writing.
- We do this because apparently it isn't possible to check for activity in the select() loop.
- Furthermore I don't really know how to do it the "Windows" way. */
-
- if(socketpair(AF_UNIX, SOCK_DGRAM, PF_UNIX, sp)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "System call `%s' failed: %s", "socketpair", strerror(errno));
- return false;
- }
-
- /* The parent opens the tap device for writing. */
-
- device_handle = CreateFile(tapname, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM , 0);
-
- if(device_handle == INVALID_HANDLE_VALUE) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open Windows tap device %s (%s) for writing: %s", device, iface, winerror(GetLastError()));
- return false;
- }
-
- device_fd = sp[0];
-
- /* Get MAC address from tap device */
-
- if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof mymac.x, mymac.x, sizeof mymac.x, &len, 0)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError()));
- return false;
- }
-
- if(routing_mode == RMODE_ROUTER) {
- overwrite_mac = 1;
- }
-
- /* Now we start the child */
-
- reader_pid = fork();
-
- if(reader_pid == -1) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "System call `%s' failed: %s", "fork", strerror(errno));
- return false;
- }
-
- if(!reader_pid) {
- /* The child opens the tap device for reading, blocking.
- It passes everything it reads to the socket. */
-
- char buf[MTU];
- long inlen;
-
- CloseHandle(device_handle);
-
- device_handle = CreateFile(tapname, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
-
- if(device_handle == INVALID_HANDLE_VALUE) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open Windows tap device %s (%s) for reading: %s", device, iface, winerror(GetLastError()));
- buf[0] = 0;
- write(sp[1], buf, 1);
- exit(1);
- }
-
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Tap reader forked and running.");
-
- /* Notify success */
-
- buf[0] = 1;
- write(sp[1], buf, 1);
-
- /* Pass packets */
-
- for(;;) {
- ReadFile(device_handle, buf, MTU, &inlen, NULL);
- write(sp[1], buf, inlen);
- }
- }
-
- read(device_fd, &gelukt, 1);
- if(gelukt != 1) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Tap reader failed!");
- return false;
- }
-
- device_info = "Windows tap device";
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
-
- return true;
-}
-
-static void close_device(void) {
- close(sp[0]);
- close(sp[1]);
- CloseHandle(device_handle);
-
- kill(reader_pid, SIGKILL);
-
- free(device);
- free(iface);
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- int inlen;
-
- if((inlen = read(sp[0], packet->data, MTU)) <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
- return false;
- }
-
- packet->len = inlen;
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
- device_info);
-
- return true;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- long outlen;
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
- packet->len, device_info);
-
- if(!WriteFile (device_handle, packet->data, packet->len, &outlen, NULL)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
- return false;
- }
-
- return true;
-}
-
-const devops_t os_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
+++ /dev/null
-/*
- device.h -- generic header for device.c
- Copyright (C) 2001-2005 Ivo Timmermans
- 2001-2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_DEVICE_H__
-#define __TINC_DEVICE_H__
-
-#include "net.h"
-
-extern int device_fd;
-extern char *device;
-extern char *iface;
-
-extern uint64_t device_in_packets;
-extern uint64_t device_in_bytes;
-extern uint64_t device_out_packets;
-extern uint64_t device_out_bytes;
-
-typedef struct devops_t {
- bool (*setup)(void);
- void (*close)(void);
- bool (*read)(struct vpn_packet_t *);
- bool (*write)(struct vpn_packet_t *);
-} 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;
-
-#endif /* __TINC_DEVICE_H__ */
+++ /dev/null
-/*
- device.c -- Dummy device
- Copyright (C) 2011-2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "device.h"
-#include "logger.h"
-#include "net.h"
-
-static char *device_info = "dummy device";
-
-static bool setup_device(void) {
- device = "dummy";
- iface = "dummy";
- logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
- return true;
-}
-
-static void close_device(void) {
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- return false;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- return true;
-}
-
-const devops_t dummy_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
#include "system.h"
#include "splay_tree.h"
-#include "control_common.h"
#include "edge.h"
#include "logger.h"
#include "netutl.h"
return splay_search(from->edge_tree, &v);
}
-
-bool dump_edges(connection_t *c) {
- for splay_each(node_t, n, node_tree) {
- for splay_each(edge_t, e, n->edge_tree) {
- char *address = sockaddr2hostname(&e->address);
- send_request(c, "%d %d %s %s %s %x %d",
- CONTROL, REQ_DUMP_EDGES,
- e->from->name, e->to->name, address,
- e->options, e->weight);
- free(address);
- }
- }
-
- return send_request(c, "%d %d", CONTROL, REQ_DUMP_EDGES);
-}
extern void edge_add(edge_t *);
extern void edge_del(edge_t *);
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
-extern bool dump_edges(struct connection_t *);
#endif /* __TINC_EDGE_H__ */
+++ /dev/null
-/*
- cipher.c -- Symmetric block cipher handling
- Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "cipher.h"
-#include "logger.h"
-#include "xalloc.h"
-
-static struct {
- const char *name;
- int algo;
- int mode;
- int nid;
-} ciphertable[] = {
- {"none", GCRY_CIPHER_NONE, GCRY_CIPHER_MODE_NONE, 0},
-
- {NULL, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_ECB, 92},
- {"blowfish", GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 91},
- {NULL, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CFB, 93},
- {NULL, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB, 94},
-
- {NULL, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 418},
- {"aes", GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 419},
- {NULL, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CFB, 421},
- {NULL, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OFB, 420},
-
- {NULL, GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_ECB, 422},
- {"aes192", GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC, 423},
- {NULL, GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CFB, 425},
- {NULL, GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_OFB, 424},
-
- {NULL, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_ECB, 426},
- {"aes256", GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 427},
- {NULL, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB, 429},
- {NULL, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB, 428},
-};
-
-static bool nametocipher(const char *name, int *algo, int *mode) {
- size_t i;
-
- for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
- if(ciphertable[i].name && !strcasecmp(name, ciphertable[i].name)) {
- *algo = ciphertable[i].algo;
- *mode = ciphertable[i].mode;
- return true;
- }
- }
-
- return false;
-}
-
-static bool nidtocipher(int nid, int *algo, int *mode) {
- size_t i;
-
- for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
- if(nid == ciphertable[i].nid) {
- *algo = ciphertable[i].algo;
- *mode = ciphertable[i].mode;
- return true;
- }
- }
-
- return false;
-}
-
-static bool ciphertonid(int algo, int mode, int *nid) {
- size_t i;
-
- for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
- if(algo == ciphertable[i].algo && mode == ciphertable[i].mode) {
- *nid = ciphertable[i].nid;
- return true;
- }
- }
-
- return false;
-}
-
-static bool cipher_open(cipher_t *cipher, int algo, int mode) {
- gcry_error_t err;
-
- if(!ciphertonid(algo, mode, &cipher->nid)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Cipher %d mode %d has no corresponding nid!", algo, mode);
- return false;
- }
-
- if((err = gcry_cipher_open(&cipher->handle, algo, mode, 0))) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Unable to intialise cipher %d mode %d: %s", algo, mode, gcry_strerror(err));
- return false;
- }
-
- cipher->keylen = gcry_cipher_get_algo_keylen(algo);
- cipher->blklen = gcry_cipher_get_algo_blklen(algo);
- cipher->key = xmalloc(cipher->keylen + cipher->blklen);
- cipher->padding = mode == GCRY_CIPHER_MODE_ECB || mode == GCRY_CIPHER_MODE_CBC;
-
- return true;
-}
-
-bool cipher_open_by_name(cipher_t *cipher, const char *name) {
- int algo, mode;
-
- if(!nametocipher(name, &algo, &mode)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown cipher name '%s'!", name);
- return false;
- }
-
- return cipher_open(cipher, algo, mode);
-}
-
-bool cipher_open_by_nid(cipher_t *cipher, int nid) {
- int algo, mode;
-
- if(!nidtocipher(nid, &algo, &mode)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown cipher ID %d!", nid);
- return false;
- }
-
- return cipher_open(cipher, algo, mode);
-}
-
-bool cipher_open_blowfish_ofb(cipher_t *cipher) {
- return cipher_open(cipher, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB);
-}
-
-void cipher_close(cipher_t *cipher) {
- if(cipher->handle) {
- gcry_cipher_close(cipher->handle);
- cipher->handle = NULL;
- }
-
- if(cipher->key) {
- free(cipher->key);
- cipher->key = NULL;
- }
-}
-
-size_t cipher_keylength(const cipher_t *cipher) {
- return cipher->keylen + cipher->blklen;
-}
-
-void cipher_get_key(const cipher_t *cipher, void *key) {
- memcpy(key, cipher->key, cipher->keylen + cipher->blklen);
-}
-
-bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) {
- memcpy(cipher->key, key, cipher->keylen + cipher->blklen);
-
- gcry_cipher_setkey(cipher->handle, cipher->key, cipher->keylen);
- gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
-
- return true;
-}
-
-bool cipher_set_key_from_rsa(cipher_t *cipher, void *key, size_t len, bool encrypt) {
- memcpy(cipher->key, key + len - cipher->keylen, cipher->keylen + cipher->blklen);
- memcpy(cipher->key + cipher->keylen, key + len - cipher->keylen - cipher->blklen, cipher->blklen);
-
- gcry_cipher_setkey(cipher->handle, cipher->key, cipher->keylen);
- gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
-
- return true;
-}
-
-bool cipher_regenerate_key(cipher_t *cipher, bool encrypt) {
- gcry_create_nonce(cipher->key, cipher->keylen + cipher->blklen);
-
- gcry_cipher_setkey(cipher->handle, cipher->key, cipher->keylen);
- gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
-
- return true;
-}
-
-bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
- gcry_error_t err;
- uint8_t pad[cipher->blklen];
-
- if(cipher->padding) {
- if(!oneshot)
- return false;
-
- size_t reqlen = ((inlen + cipher->blklen) / cipher->blklen) * cipher->blklen;
-
- if(*outlen < reqlen) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: not enough room for padding");
- return false;
- }
-
- uint8_t padbyte = reqlen - inlen;
- inlen = reqlen - cipher->blklen;
-
- for(int i = 0; i < cipher->blklen; i++)
- if(i < cipher->blklen - padbyte)
- pad[i] = ((uint8_t *)indata)[inlen + i];
- else
- pad[i] = padbyte;
- }
-
- if(oneshot)
- gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
-
- if((err = gcry_cipher_encrypt(cipher->handle, outdata, *outlen, indata, inlen))) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", gcry_strerror(err));
- return false;
- }
-
- if(cipher->padding) {
- if((err = gcry_cipher_encrypt(cipher->handle, outdata + inlen, cipher->blklen, pad, cipher->blklen))) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", gcry_strerror(err));
- return false;
- }
-
- inlen += cipher->blklen;
- }
-
- *outlen = inlen;
- return true;
-}
-
-bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
- gcry_error_t err;
-
- if(oneshot)
- gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
-
- if((err = gcry_cipher_decrypt(cipher->handle, outdata, *outlen, indata, inlen))) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", gcry_strerror(err));
- return false;
- }
-
- if(cipher->padding) {
- if(!oneshot)
- return false;
-
- uint8_t padbyte = ((uint8_t *)outdata)[inlen - 1];
-
- if(padbyte == 0 || padbyte > cipher->blklen || padbyte > inlen) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: invalid padding");
- return false;
- }
-
- size_t origlen = inlen - padbyte;
-
- for(int i = inlen - 1; i >= origlen; i--)
- if(((uint8_t *)outdata)[i] != padbyte) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: invalid padding");
- return false;
- }
-
- *outlen = origlen;
- } else
- *outlen = inlen;
-
- return true;
-}
-
-int cipher_get_nid(const cipher_t *cipher) {
- return cipher->nid;
-}
-
-bool cipher_active(const cipher_t *cipher) {
- return cipher->nid != 0;
-}
+++ /dev/null
-/*
- cipher.h -- header file cipher.c
- Copyright (C) 2007-2009 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_CIPHER_H__
-#define __TINC_CIPHER_H__
-
-#include <gcrypt.h>
-
-#define CIPHER_MAX_BLOCK_SIZE 32
-#define CIPHER_MAX_IV_SIZE 16
-#define CIPHER_MAX_KEY_SIZE 32
-
-typedef struct cipher {
- gcry_cipher_hd_t handle;
- char *key;
- int nid;
- uint16_t keylen;
- uint16_t blklen;
- bool padding;
-} cipher_t;
-
-extern bool cipher_open_by_name(struct cipher *, const char *);
-extern bool cipher_open_by_nid(struct cipher *, int);
-extern bool cipher_open_blowfish_ofb(struct cipher *);
-extern void cipher_close(struct cipher *);
-extern size_t cipher_keylength(const struct cipher *);
-extern void cipher_get_key(const struct cipher *, void *);
-extern bool cipher_set_key(struct cipher *, void *, bool);
-extern bool cipher_set_key_from_rsa(struct cipher *, void *, size_t, bool);
-extern bool cipher_regenerate_key(struct cipher *, bool);
-extern bool cipher_encrypt(struct cipher *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot);
-extern bool cipher_decrypt(struct cipher *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot);
-extern int cipher_get_nid(const struct cipher *);
-extern bool cipher_active(const struct cipher *);
-
-#endif
+++ /dev/null
-/*
- crypto.c -- Cryptographic miscellaneous functions and initialisation
- Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <gcrypt.h>
-
-#include "crypto.h"
-
-void crypto_init() {
-}
-
-void crypto_exit() {
-}
-
-void randomize(void *out, size_t outlen) {
- gcry_create_nonce(out, outlen);
-}
+++ /dev/null
-/*
- crypto.h -- header for crypto.c
- Copyright (C) 2007-2009 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_CRYPTO_H__
-#define __TINC_CRYPTO_H__
-
-extern void crypto_init();
-extern void crypto_exit();
-extern void randomize(void *, size_t);
-
-#endif
+++ /dev/null
-/*
- digest.c -- Digest handling
- Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "digest.h"
-#include "logger.h"
-
-static struct {
- const char *name;
- int algo;
- int nid;
-} digesttable[] = {
- {"none", GCRY_MD_NONE, 0},
- {"sha1", GCRY_MD_SHA1, 64},
- {"sha256", GCRY_MD_SHA256, 672},
- {"sha384", GCRY_MD_SHA384, 673},
- {"sha512", GCRY_MD_SHA512, 674},
-};
-
-static bool nametodigest(const char *name, int *algo) {
- int i;
-
- for(i = 0; i < sizeof digesttable / sizeof *digesttable; i++) {
- if(digesttable[i].name && !strcasecmp(name, digesttable[i].name)) {
- *algo = digesttable[i].algo;
- return true;
- }
- }
-
- return false;
-}
-
-static bool nidtodigest(int nid, int *algo) {
- int i;
-
- for(i = 0; i < sizeof digesttable / sizeof *digesttable; i++) {
- if(nid == digesttable[i].nid) {
- *algo = digesttable[i].algo;
- return true;
- }
- }
-
- return false;
-}
-
-static bool digesttonid(int algo, int *nid) {
- int i;
-
- for(i = 0; i < sizeof digesttable / sizeof *digesttable; i++) {
- if(algo == digesttable[i].algo) {
- *nid = digesttable[i].nid;
- return true;
- }
- }
-
- return false;
-}
-
-static bool digest_open(digest_t *digest, int algo, int maclength) {
- if(!digesttonid(algo, &digest->nid)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Digest %d has no corresponding nid!", algo);
- return false;
- }
-
- unsigned int len = gcry_md_get_algo_dlen(algo);
-
- if(maclength > len || maclength < 0)
- digest->maclength = len;
- else
- digest->maclength = maclength;
-
- digest->algo = algo;
- digest->hmac = NULL;
-
- return true;
-}
-
-bool digest_open_by_name(digest_t *digest, const char *name, int maclength) {
- int algo;
-
- if(!nametodigest(name, &algo)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest name '%s'!", name);
- return false;
- }
-
- return digest_open(digest, algo, maclength);
-}
-
-bool digest_open_by_nid(digest_t *digest, int nid, int maclength) {
- int algo;
-
- if(!nidtodigest(nid, &algo)) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest ID %d!", nid);
- return false;
- }
-
- return digest_open(digest, algo, maclength);
-}
-
-bool digest_open_sha1(digest_t *digest, int maclength) {
- return digest_open(digest, GCRY_MD_SHA1, maclength);
-}
-
-void digest_close(digest_t *digest) {
- if(digest->hmac)
- gcry_md_close(digest->hmac);
- digest->hmac = NULL;
-}
-
-bool digest_set_key(digest_t *digest, const void *key, size_t len) {
- if(!digest->hmac)
- gcry_md_open(&digest->hmac, digest->algo, GCRY_MD_FLAG_HMAC);
- if(!digest->hmac)
- return false;
-
- return !gcry_md_setkey(digest->hmac, key, len);
-}
-
-bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) {
- unsigned int len = gcry_md_get_algo_dlen(digest->algo);
-
- if(digest->hmac) {
- char *tmpdata;
- gcry_md_reset(digest->hmac);
- gcry_md_write(digest->hmac, indata, inlen);
- tmpdata = gcry_md_read(digest->hmac, digest->algo);
- if(!tmpdata)
- return false;
- memcpy(outdata, tmpdata, digest->maclength);
- } else {
- char tmpdata[len];
- gcry_md_hash_buffer(digest->algo, tmpdata, indata, inlen);
- memcpy(outdata, tmpdata, digest->maclength);
- }
-
- return true;
-}
-
-bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *cmpdata) {
- unsigned int len = digest->maclength;
- char outdata[len];
-
- return digest_create(digest, indata, inlen, outdata) && !memcmp(cmpdata, outdata, len);
-}
-
-int digest_get_nid(const digest_t *digest) {
- return digest->nid;
-}
-
-size_t digest_length(const digest_t *digest) {
- return digest->maclength;
-}
-
-bool digest_active(const digest_t *digest) {
- return digest->algo != GCRY_MD_NONE;
-}
+++ /dev/null
-/*
- digest.h -- header file digest.c
- Copyright (C) 2007-2009 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_DIGEST_H__
-#define __TINC_DIGEST_H__
-
-#include <gcrypt.h>
-
-#define DIGEST_MAX_SIZE 64
-
-typedef struct digest {
- int algo;
- int nid;
- int maclength;
- gcry_md_hd_t hmac;
-} digest_t;
-
-extern bool digest_open_by_name(struct digest *, const char *name, int maclength);
-extern bool digest_open_by_nid(struct digest *, int nid, int maclength);
-extern bool digest_open_sha1(struct digest *, int maclength);
-extern void digest_close(struct digest *);
-extern bool digest_create(struct digest *, const void *indata, size_t inlen, void *outdata);
-extern bool digest_verify(struct digest *, const void *indata, size_t inlen, const void *digestdata);
-extern bool digest_set_key(struct digest *, const void *key, size_t len);
-extern int digest_get_nid(const struct digest *);
-extern size_t digest_length(const struct digest *);
-extern bool digest_active(const struct digest *);
-
-#endif
+++ /dev/null
-/*
- ecdh.c -- Diffie-Hellman key exchange handling
- Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "../ecdh.h"
-#include "../logger.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-ecdh_t *ecdh_generate_public(void *pubkey) {
- logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
- return NULL;
-}
-
-bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
- return false
-}
-
-void ecdh_free(ecdh_t *ecdh) {
-}
+++ /dev/null
-/*
- ecdsa.c -- ECDSA key handling
- Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "../logger.h"
-#include "../ecdsa.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-// Get and set ECDSA keys
-//
-ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
- logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
- return NULL;
-}
-
-char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
- return NULL;
-}
-
-// Read PEM ECDSA keys
-
-ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
- logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
- return NULL;
-}
-
-ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
- logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
- return NULL;
-}
-
-size_t ecdsa_size(ecdsa_t *ecdsa) {
- return 0;
-}
-
-bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
- return false;
-}
-
-bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
- return false;
-}
-
-bool ecdsa_active(ecdsa_t *ecdsa) {
- return false;
-}
-
-void ecdsa_free(ecdsa_t *ecdsa) {
-}
+++ /dev/null
-/*
- ecdsagen.c -- ECDSA key generation and export
- Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "../ecdsagen.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-// Generate ECDSA key
-
-ecdsa_t *ecdsa_generate(void) {
- logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
- return NULL;
-}
-
-// Write PEM ECDSA keys
-
-bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
- return false;
-}
-
-bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
- return false;
-}
+++ /dev/null
-/*
- prf.c -- Pseudo-Random Function for key material generation
- Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "digest.h"
-#include "../digest.h"
-#include "../prf.h"
-
-bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) {
- logger(DEBUG_ALWAYS, LOG_ERR, "PRF support using libgcrypt not implemented");
- return false;
-}
+++ /dev/null
-/*
- rsa.c -- RSA key handling
- Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <gcrypt.h>
-
-#include "logger.h"
-#include "rsa.h"
-
-// Base64 decoding table
-
-static const uint8_t b64d[128] = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
- 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
- 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
- 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
- 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
- 0xff, 0xff
-};
-
-// PEM encoding/decoding functions
-
-static bool pem_decode(FILE *fp, const char *header, uint8_t *buf, size_t size, size_t *outsize) {
- bool decode = false;
- char line[1024];
- uint16_t word = 0;
- int shift = 10;
- size_t i, j = 0;
-
- while(!feof(fp)) {
- if(!fgets(line, sizeof line, fp))
- return false;
-
- if(!decode && !strncmp(line, "-----BEGIN ", 11)) {
- if(!strncmp(line + 11, header, strlen(header)))
- decode = true;
- continue;
- }
-
- if(decode && !strncmp(line, "-----END", 8)) {
- break;
- }
-
- if(!decode)
- continue;
-
- for(i = 0; line[i] >= ' '; i++) {
- if((signed char)line[i] < 0 || b64d[(int)line[i]] == 0xff)
- break;
- word |= b64d[(int)line[i]] << shift;
- shift -= 6;
- if(shift <= 2) {
- if(j > size) {
- errno = ENOMEM;
- return false;
- }
-
- buf[j++] = word >> 8;
- word <<= 8;
- shift += 8;
- }
- }
- }
-
- if(outsize)
- *outsize = j;
- return true;
-}
-
-
-// BER decoding functions
-
-static int ber_read_id(unsigned char **p, size_t *buflen) {
- if(*buflen <= 0)
- return -1;
-
- if((**p & 0x1f) == 0x1f) {
- int id = 0;
- bool more;
- while(*buflen > 0) {
- id <<= 7;
- id |= **p & 0x7f;
- more = *(*p)++ & 0x80;
- (*buflen)--;
- if(!more)
- break;
- }
- return id;
- } else {
- (*buflen)--;
- return *(*p)++ & 0x1f;
- }
-}
-
-static size_t ber_read_len(unsigned char **p, size_t *buflen) {
- if(*buflen <= 0)
- return -1;
-
- if(**p & 0x80) {
- size_t result = 0;
- int len = *(*p)++ & 0x7f;
- (*buflen)--;
- if(len > *buflen)
- return 0;
-
- while(len--) {
- result <<= 8;
- result |= *(*p)++;
- (*buflen)--;
- }
-
- return result;
- } else {
- (*buflen)--;
- return *(*p)++;
- }
-}
-
-
-static bool ber_read_sequence(unsigned char **p, size_t *buflen, size_t *result) {
- int tag = ber_read_id(p, buflen);
- size_t len = ber_read_len(p, buflen);
-
- if(tag == 0x10) {
- if(result)
- *result = len;
- return true;
- } else {
- return false;
- }
-}
-
-static bool ber_read_mpi(unsigned char **p, size_t *buflen, gcry_mpi_t *mpi) {
- int tag = ber_read_id(p, buflen);
- size_t len = ber_read_len(p, buflen);
- gcry_error_t err = 0;
-
- if(tag != 0x02 || len > *buflen)
- return false;
-
- if(mpi)
- err = gcry_mpi_scan(mpi, GCRYMPI_FMT_USG, *p, len, NULL);
-
- *p += len;
- *buflen -= len;
-
- return mpi ? !err : true;
-}
-
-bool rsa_set_hex_public_key(rsa_t *rsa, char *n, char *e) {
- gcry_error_t err = 0;
-
- err = gcry_mpi_scan(&rsa->n, GCRYMPI_FMT_HEX, n, 0, NULL)
- ?: gcry_mpi_scan(&rsa->e, GCRYMPI_FMT_HEX, e, 0, NULL);
-
- if(err) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading RSA public key: %s", gcry_strerror(errno));
- return false;
- }
-
- return true;
-}
-
-bool rsa_set_hex_private_key(rsa_t *rsa, char *n, char *e, char *d) {
- gcry_error_t err = 0;
-
- err = gcry_mpi_scan(&rsa->n, GCRYMPI_FMT_HEX, n, 0, NULL)
- ?: gcry_mpi_scan(&rsa->e, GCRYMPI_FMT_HEX, e, 0, NULL)
- ?: gcry_mpi_scan(&rsa->d, GCRYMPI_FMT_HEX, d, 0, NULL);
-
- if(err) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading RSA public key: %s", gcry_strerror(errno));
- return false;
- }
-
- return true;
-}
-
-// Read PEM RSA keys
-
-bool rsa_read_pem_public_key(rsa_t *rsa, FILE *fp) {
- uint8_t derbuf[8096], *derp = derbuf;
- size_t derlen;
-
- if(!pem_decode(fp, "RSA PUBLIC KEY", derbuf, sizeof derbuf, &derlen)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", strerror(errno));
- return NULL;
- }
-
- if(!ber_read_sequence(&derp, &derlen, NULL)
- || !ber_read_mpi(&derp, &derlen, &rsa->n)
- || !ber_read_mpi(&derp, &derlen, &rsa->e)
- || derlen) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decoding RSA public key");
- return NULL;
- }
-
- return true;
-}
-
-bool rsa_read_pem_private_key(rsa_t *rsa, FILE *fp) {
- uint8_t derbuf[8096], *derp = derbuf;
- size_t derlen;
-
- if(!pem_decode(fp, "RSA PRIVATE KEY", derbuf, sizeof derbuf, &derlen)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", strerror(errno));
- return NULL;
- }
-
- if(!ber_read_sequence(&derp, &derlen, NULL)
- || !ber_read_mpi(&derp, &derlen, NULL)
- || !ber_read_mpi(&derp, &derlen, &rsa->n)
- || !ber_read_mpi(&derp, &derlen, &rsa->e)
- || !ber_read_mpi(&derp, &derlen, &rsa->d)
- || !ber_read_mpi(&derp, &derlen, NULL) // p
- || !ber_read_mpi(&derp, &derlen, NULL) // q
- || !ber_read_mpi(&derp, &derlen, NULL)
- || !ber_read_mpi(&derp, &derlen, NULL)
- || !ber_read_mpi(&derp, &derlen, NULL) // u
- || derlen) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while decoding RSA private key");
- return NULL;
- }
-
- return true;
-}
-
-size_t rsa_size(rsa_t *rsa) {
- return (gcry_mpi_get_nbits(rsa->n) + 7) / 8;
-}
-
-/* Well, libgcrypt has functions to handle RSA keys, but they suck.
- * So we just use libgcrypt's mpi functions, and do the math ourselves.
- */
-
-// TODO: get rid of this macro, properly clean up gcry_ structures after use
-#define check(foo) { gcry_error_t err = (foo); if(err) {logger(DEBUG_ALWAYS, LOG_ERR, "gcrypt error %s/%s at %s:%d", gcry_strsource(err), gcry_strerror(err), __FILE__, __LINE__); return false; }}
-
-bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) {
- gcry_mpi_t inmpi;
- check(gcry_mpi_scan(&inmpi, GCRYMPI_FMT_USG, in, len, NULL));
-
- gcry_mpi_t outmpi = gcry_mpi_new(len * 8);
- gcry_mpi_powm(outmpi, inmpi, rsa->e, rsa->n);
-
- int pad = len - (gcry_mpi_get_nbits(outmpi) + 7) / 8;
- while(pad--)
- *(char *)out++ = 0;
-
- check(gcry_mpi_print(GCRYMPI_FMT_USG, out,len, NULL, outmpi));
-
- return true;
-}
-
-bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) {
- gcry_mpi_t inmpi;
- check(gcry_mpi_scan(&inmpi, GCRYMPI_FMT_USG, in, len, NULL));
-
- gcry_mpi_t outmpi = gcry_mpi_new(len * 8);
- gcry_mpi_powm(outmpi, inmpi, rsa->d, rsa->n);
-
- int pad = len - (gcry_mpi_get_nbits(outmpi) + 7) / 8;
- while(pad--)
- *(char *)out++ = 0;
-
- check(gcry_mpi_print(GCRYMPI_FMT_USG, out,len, NULL, outmpi));
-
- return true;
-}
+++ /dev/null
-/*
- rsa.h -- RSA key handling
- Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_RSA_H__
-#define __TINC_RSA_H__
-
-#include <gcrypt.h>
-
-typedef struct rsa {
- gcry_mpi_t n;
- gcry_mpi_t e;
- gcry_mpi_t d;
-} rsa_t;
-
-extern bool rsa_set_hex_public_key(rsa_t *rsa, char *n, char *e);
-extern bool rsa_set_hex_private_key(rsa_t *rsa, char *n, char *e, char *d);
-extern bool rsa_read_pem_public_key(rsa_t *rsa, FILE *fp);
-extern bool rsa_read_pem_private_key(rsa_t *rsa, FILE *fp);
-extern size_t rsa_size(rsa_t *rsa);
-extern bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out);
-extern bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out);
-
-#endif
+++ /dev/null
-/*
- rsagen.c -- RSA key generation and export
- Copyright (C) 2008-2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <gcrypt.h>
-
-#include "rsagen.h"
-
-#if 0
-// Base64 encoding table
-
-static const char b64e[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-// PEM encoding
-
-static bool pem_encode(FILE *fp, const char *header, uint8_t *buf, size_t size) {
- bool decode = false;
- char line[1024];
- uint32_t word = 0;
- int shift = 0;
- size_t i, j = 0;
-
- fprintf(fp, "-----BEGIN %s-----\n", header);
-
- for(i = 0; i < size; i += 3) {
- if(i <= size - 3) {
- word = buf[i] << 16 | buf[i + 1] << 8 | buf[i + 2];
- } else {
- word = buf[i] << 16;
- if(i == size - 2)
- word |= buf[i + 1] << 8;
- }
-
- line[j++] = b64e[(word >> 18) ];
- line[j++] = b64e[(word >> 12) & 0x3f];
- line[j++] = b64e[(word >> 6) & 0x3f];
- line[j++] = b64e[(word ) & 0x3f];
-
- if(j >= 64) {
- line[j++] = '\n';
- line[j] = 0;
- fputs(line, fp);
- j = 0;
- }
- }
-
- if(size % 3 > 0) {
- if(size % 3 > 1)
- line[j++] = '=';
- line[j++] = '=';
- }
-
- if(j) {
- line[j++] = '\n';
- line[j] = 0;
- fputs(line, fp);
- }
-
- fprintf(fp, "-----END %s-----\n", header);
-
- return true;
-}
-
-
-// BER encoding functions
-
-static bool ber_write_id(uint8_t **p, size_t *buflen, int id) {
- if(*buflen <= 0)
- return false;
-
- if(id >= 0x1f) {
- while(id) {
- if(*buflen <= 0)
- return false;
-
- (*buflen)--;
- **p = id & 0x7f;
- id >>= 7;
- if(id)
- **p |= 0x80;
- (*p)++;
- }
- } else {
- (*buflen)--;
- *(*p)++ = id;
- }
-
- return true;
-}
-
-static bool ber_write_len(uint8_t **p, size_t *buflen, size_t len) {
- do {
- if(*buflen <= 0)
- return false;
-
- (*buflen)--;
- **p = len & 0x7f;
- len >>= 7;
- if(len)
- **p |= 0x80;
- (*p)++;
- } while(len);
-
- return true;
-}
-
-static bool ber_write_sequence(uint8_t **p, size_t *buflen, uint8_t *seqbuf, size_t seqlen) {
- if(!ber_write_id(p, buflen, 0x10) || !ber_write_len(p, buflen, seqlen) || *buflen < seqlen)
- return false;
-
- memcpy(*p, seqbuf, seqlen);
- *p += seqlen;
- *buflen -= seqlen;
-
- return true;
-}
-
-static bool ber_write_mpi(uint8_t **p, size_t *buflen, gcry_mpi_t mpi) {
- uint8_t tmpbuf[1024];
- size_t tmplen = sizeof tmpbuf;
- gcry_error_t err;
-
- err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &tmpbuf, &tmplen, mpi);
- if(err)
- return false;
-
- if(!ber_write_id(p, buflen, 0x02) || !ber_write_len(p, buflen, tmplen) || *buflen < tmplen)
- return false;
-
- memcpy(*p, tmpbuf, tmplen);
- *p += tmplen;
- *buflen -= tmplen;
-
- return true;
-}
-
-// Write PEM RSA keys
-
-bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) {
- uint8_t derbuf1[8096];
- uint8_t derbuf2[8096];
- uint8_t *derp1 = derbuf1;
- uint8_t *derp2 = derbuf2;
- size_t derlen1 = sizeof derbuf1;
- size_t derlen2 = sizeof derbuf2;
-
- if(!ber_write_mpi(&derp1, &derlen1, &rsa->n)
- || !ber_write_mpi(&derp1, &derlen1, &rsa->e)
- || !ber_write_sequence(&derp2, &derlen2, derbuf1, derlen1)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encoding RSA public key");
- return false;
- }
-
- if(!pem_encode(fp, "RSA PUBLIC KEY", derbuf2, derlen2)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to write RSA public key: %s", strerror(errno));
- return false;
- }
-
- return true;
-}
-
-bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) {
- uint8_t derbuf1[8096];
- uint8_t derbuf2[8096];
- uint8_t *derp1 = derbuf1;
- uint8_t *derp2 = derbuf2;
- size_t derlen1 = sizeof derbuf1;
- size_t derlen2 = sizeof derbuf2;
-
- if(!ber_write_mpi(&derp1, &derlen1, &bits)
- || ber_write_mpi(&derp1, &derlen1, &rsa->n) // modulus
- || ber_write_mpi(&derp1, &derlen1, &rsa->e) // public exponent
- || ber_write_mpi(&derp1, &derlen1, &rsa->d) // private exponent
- || ber_write_mpi(&derp1, &derlen1, &p)
- || ber_write_mpi(&derp1, &derlen1, &q)
- || ber_write_mpi(&derp1, &derlen1, &exp1)
- || ber_write_mpi(&derp1, &derlen1, &exp2)
- || ber_write_mpi(&derp1, &derlen1, &coeff))
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while encoding RSA private key");
- return false;
- }
-
- if(!pem_encode(fp, "RSA PRIVATE KEY", derbuf2, derlen2)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to write RSA private key: %s", strerror(errno));
- return false;
- }
-
- return true;
-}
-#endif
-
-bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) {
- return false;
-}
-
-bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) {
- return false;
-}
-
-bool rsa_generate(rsa_t *rsa, size_t bits, unsigned long exponent) {
- fprintf(stderr, "Generating RSA keys with libgcrypt not implemented yet\n");
- return false;
-}
+++ /dev/null
-/*
- rsagen.h -- RSA key generation and export
- Copyright (C) 2008 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_RSAGEN_H__
-#define __TINC_RSAGEN_H__
-
-#include "rsa.h"
-
-extern bool rsa_generate(rsa_t *rsa, size_t bits, unsigned long exponent);
-extern bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp);
-extern bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp);
-
-#endif
#include "system.h"
#include "connection.h"
-#include "device.h"
#include "edge.h"
#include "graph.h"
#include "list.h"
#include "logger.h"
-#include "names.h"
#include "netutl.h"
#include "node.h"
#include "protocol.h"
-#include "script.h"
-#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
#include "graph.h"
timeout_del(&n->mtutimeout);
- char *name;
- char *address;
- char *port;
- char *envp[8] = {NULL};
-
- xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
- xasprintf(&envp[1], "DEVICE=%s", device ? : "");
- xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
- xasprintf(&envp[3], "NODE=%s", n->name);
- sockaddr2str(&n->address, &address, &port);
- xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
- xasprintf(&envp[5], "REMOTEPORT=%s", port);
- xasprintf(&envp[6], "NAME=%s", myself->name);
-
- execute_script(n->status.reachable ? "host-up" : "host-down", envp);
-
- xasprintf(&name, n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", n->name);
- execute_script(name, envp);
-
- free(name);
- free(address);
- free(port);
-
- for(int i = 0; i < 7; i++)
- free(envp[i]);
-
- subnet_update(n, NULL, n->status.reachable);
+ //TODO: callback to application to inform of this node going up/down
if(!n->status.reachable) {
update_node_udp(n, NULL);
}
void graph(void) {
- subnet_cache_flush();
sssp_bfs();
check_reachability();
mst_kruskal();
#define __TINC_GRAPH_H__
extern void graph(void);
-extern void dump_graph(void);
#endif /* __TINC_GRAPH_H__ */
+++ /dev/null
-/*
- info.c -- Show information about a node, subnet or address
- Copyright (C) 2012-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "control_common.h"
-#include "list.h"
-#include "subnet.h"
-#include "tincctl.h"
-#include "info.h"
-#include "xalloc.h"
-
-void logger(int level, int priority, const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- vfprintf(stderr, format, ap);
- va_end(ap);
- fputc('\n', stderr);
-}
-
-char *strip_weight(char *netstr) {
- int len = strlen(netstr);
- if(len >= 3 && !strcmp(netstr + len - 3, "#10"))
- netstr[len - 3] = 0;
- return netstr;
-}
-
-static int info_node(int fd, const char *item) {
- // Check the list of nodes
- sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_NODES, item);
-
- bool found = false;
- char line[4096];
-
- char node[4096];
- char from[4096];
- char to[4096];
- char subnet[4096];
- char host[4096];
- char port[4096];
- char via[4096];
- char nexthop[4096];
- int code, req, cipher, digest, maclength, compression, distance;
- short int pmtu, minmtu, maxmtu;
- unsigned int options;
- union {
- node_status_t bits;
- uint32_t raw;
- } status_union;
- node_status_t status;
- long int last_state_change;
-
- while(recvline(fd, line, sizeof line)) {
- int n = sscanf(line, "%d %d %s %s port %s %d %d %d %d %x %"PRIx32" %s %s %d %hd %hd %hd %ld", &code, &req, node, host, port, &cipher, &digest, &maclength, &compression, &options, &status_union.raw, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change);
-
- if(n == 2)
- break;
-
- if(n != 18) {
- fprintf(stderr, "Unable to parse node dump from tincd.\n");
- return 1;
- }
-
- if(!strcmp(node, item)) {
- found = true;
- break;
- }
- }
-
- if(!found) {
- fprintf(stderr, "Unknown node %s.\n", item);
- return 1;
- }
-
- while(recvline(fd, line, sizeof line)) {
- if(sscanf(line, "%d %d %s", &code, &req, node) == 2)
- break;
- }
-
- printf("Node: %s\n", item);
- printf("Address: %s port %s\n", host, port);
-
- char timestr[32] = "never";
- time_t lsc_time = last_state_change;
-
- if(last_state_change)
- strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&lsc_time));
-
- status = status_union.bits;
-
- if(status.reachable)
- printf("Online since: %s\n", timestr);
- else
- printf("Last seen: %s\n", timestr);
-
- printf("Status: ");
- if(status.validkey)
- printf(" validkey");
- if(status.visited)
- printf(" visited");
- if(status.reachable)
- printf(" reachable");
- if(status.indirect)
- printf(" indirect");
- if(status.sptps)
- printf(" sptps");
- if(status.udp_confirmed)
- printf(" udp_confirmed");
- printf("\n");
-
- printf("Options: ");
- if(options & OPTION_INDIRECT)
- printf(" indirect");
- if(options & OPTION_TCPONLY)
- printf(" tcponly");
- if(options & OPTION_PMTU_DISCOVERY)
- printf(" pmtu_discovery");
- if(options & OPTION_CLAMP_MSS)
- printf(" clamp_mss");
- printf("\n");
- printf("Protocol: %d.%d\n", PROT_MAJOR, OPTION_VERSION(options));
- printf("Reachability: ");
- if(!strcmp(host, "MYSELF"))
- printf("can reach itself\n");
- else if(!status.reachable)
- printf("unreachable\n");
- else if(strcmp(via, item))
- printf("indirectly via %s\n", via);
- else if(!status.validkey)
- printf("unknown\n");
- else if(minmtu > 0)
- printf("directly with UDP\nPMTU: %d\n", pmtu);
- else if(!strcmp(nexthop, item))
- printf("directly with TCP\n");
- else
- printf("none, forwarded via %s\n", nexthop);
-
- // List edges
- printf("Edges: ");
- sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_EDGES, item);
- while(recvline(fd, line, sizeof line)) {
- int n = sscanf(line, "%d %d %s %s", &code, &req, from, to);
- if(n == 2)
- break;
- if(n != 4) {
- fprintf(stderr, "Unable to parse edge dump from tincd.\n%s\n", line);
- return 1;
- }
- if(!strcmp(from, item))
- printf(" %s", to);
- }
- printf("\n");
-
- // List subnets
- printf("Subnets: ");
- sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_SUBNETS, item);
- while(recvline(fd, line, sizeof line)) {
- int n = sscanf(line, "%d %d %s %s", &code, &req, subnet, from);
- if(n == 2)
- break;
- if(n != 4) {
- fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
- return 1;
- }
- if(!strcmp(from, item))
- printf(" %s", strip_weight(subnet));
- }
- printf("\n");
-
- return 0;
-}
-
-static int info_subnet(int fd, const char *item) {
- subnet_t subnet, find;
-
- if(!str2net(&find, item)) {
- fprintf(stderr, "Could not parse subnet or address '%s'.\n", item);
- return 1;
- }
-
- bool address = !strchr(item, '/');
- bool weight = strchr(item, '#');
- bool found = false;
-
- char line[4096];
- char netstr[4096];
- char owner[4096];
-
- int code, req;
-
- sendline(fd, "%d %d %s", CONTROL, REQ_DUMP_SUBNETS, item);
- while(recvline(fd, line, sizeof line)) {
- int n = sscanf(line, "%d %d %s %s", &code, &req, netstr, owner);
- if(n == 2)
- break;
-
- if(n != 4 || !str2net(&subnet, netstr)) {
- fprintf(stderr, "Unable to parse subnet dump from tincd.\n");
- return 1;
- }
-
- if(find.type != subnet.type)
- continue;
-
- if(weight) {
- if(find.weight != subnet.weight)
- continue;
- }
-
- if(find.type == SUBNET_IPV4) {
- if(address) {
- if(maskcmp(&find.net.ipv4.address, &subnet.net.ipv4.address, subnet.net.ipv4.prefixlength))
- continue;
- } else {
- if(find.net.ipv4.prefixlength != subnet.net.ipv4.prefixlength)
- continue;
- if(memcmp(&find.net.ipv4.address, &subnet.net.ipv4.address, sizeof subnet.net.ipv4))
- continue;
- }
- } else if(find.type == SUBNET_IPV6) {
- if(address) {
- if(maskcmp(&find.net.ipv6.address, &subnet.net.ipv6.address, subnet.net.ipv6.prefixlength))
- continue;
- } else {
- if(find.net.ipv6.prefixlength != subnet.net.ipv6.prefixlength)
- continue;
- if(memcmp(&find.net.ipv6.address, &subnet.net.ipv6.address, sizeof subnet.net.ipv6))
- continue;
- }
- } if(find.type == SUBNET_MAC) {
- if(memcmp(&find.net.mac.address, &subnet.net.mac.address, sizeof subnet.net.mac))
- continue;
- }
-
- found = true;
- printf("Subnet: %s\n", strip_weight(netstr));
- printf("Owner: %s\n", owner);
- }
-
- if(!found) {
- if(address)
- fprintf(stderr, "Unknown address %s.\n", item);
- else
- fprintf(stderr, "Unknown subnet %s.\n", item);
- return 1;
- }
-
- return 0;
-}
-
-int info(int fd, const char *item) {
- if(check_id(item))
- return info_node(fd, item);
- if(strchr(item, '.') || strchr(item, ':'))
- return info_subnet(fd, item);
-
- fprintf(stderr, "Argument is not a node name, subnet or address.\n");
- return 1;
-}
+++ /dev/null
-/*
- info.h -- header for info.c.
- Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_INFO_H__
-#define __TINC_INFO_H__
-
-extern int info(int fd, const char *item);
-extern char *strip_weight(char *);
-
-#endif
-
#include "ecdsa.h"
#include "ecdsagen.h"
#include "invitation.h"
-#include "names.h"
#include "netutl.h"
#include "rsagen.h"
-#include "script.h"
#include "sptps.h"
#include "tincctl.h"
#include "utils.h"
char *url;
xasprintf(&url, "%s/%s%s", address, hash, cookie);
- // Call the inviation-created script
- char *envp[6] = {};
- xasprintf(&envp[0], "NAME=%s", myname);
- xasprintf(&envp[1], "NETNAME=%s", netname);
- xasprintf(&envp[2], "NODE=%s", argv[1]);
- xasprintf(&envp[3], "INVITATION_FILE=%s", filename);
- xasprintf(&envp[4], "INVITATION_URL=%s", url);
- execute_script("invitation-created", envp);
- for(int i = 0; i < 6 && envp[i]; i++)
- free(envp[i]);
-
- puts(url);
- free(url);
- free(filename);
- free(address);
-
return 0;
}
char temp_netname[32];
make_names:
- if(!confbasegiven) {
- free(confbase);
- confbase = NULL;
- }
-
- make_names();
-
free(tinc_conf);
free(hosts_dir);
free(newbase);
netname = line;
- make_names();
}
fprintf(stderr, "Configuration stored in: %s\n", confbase);
}
// Make sure confbase exists and is accessible.
- if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) {
- fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
- return 1;
- }
-
if(mkdir(confbase, 0777) && errno != EEXIST) {
fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
return 1;
*/
bool setup_meshlink_network(void) {
init_connections();
- init_subnets();
init_nodes();
init_edges();
init_requests();
if(!setup_myself())
return false;
- if(!init_control())
- return false;
-
- /* Run subnet-up scripts for our own subnets */
-
- subnet_update(myself, NULL, true);
-
return true;
}
}
//tinc_setup() should basically do what cmd_init() from src/tincctl.c does, except it doesn't have to generate a tinc-up script.
bool tinc_setup(const char* confbaseapi, const char* name) {
- confbase = confbaseapi;
- make_names();
+ confbase = xstrdup(confbaseapi);
xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
if(!access(tinc_conf, F_OK)) {
return false;
}
- if(!confbase_given && mkdir(confdir, 0755) && errno != EEXIST) {
- fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
- return false;
- }
-
if(mkdir(confbase, 0777) && errno != EEXIST) {
fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
return false;
}
bool tinc_main_thread(void * in) {
+ static bool status = false;
-static bool status = false;
-
-/* If nonzero, write log entries to a separate file. */
-bool use_logfile = false;
+ /* If nonzero, write log entries to a separate file. */
+ bool use_logfile = false;
-confbase = (char*) in;
+ confbase = (char*) in;
- openlogger("tinc", use_logfile?LOGMODE_FILE:LOGMODE_STDERR);
+ openlogger("tinc", LOGMODE_STDERR);
init_configuration(&config_tree);
exit_configuration(&config_tree);
free(cmdline_conf);
- free_names();
return status;
#include "system.h"
#include "node.h"
-#include "names.h"
//#include "tincctl.h"
#include "xalloc.h"
#include "logger.h"
+++ /dev/null
-/*
- device.c -- Interaction with Linux ethertap and tun/tap device
- Copyright (C) 2001-2005 Ivo Timmermans,
- 2001-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <linux/if_tun.h>
-#define DEFAULT_DEVICE "/dev/net/tun"
-
-#include "../conf.h"
-#include "../device.h"
-#include "../logger.h"
-#include "../names.h"
-#include "../net.h"
-#include "../route.h"
-#include "../utils.h"
-#include "../xalloc.h"
-#include "../device.h"
-
-typedef enum device_type_t {
- DEVICE_TYPE_TUN,
- DEVICE_TYPE_TAP,
-} device_type_t;
-
-int device_fd = -1;
-static device_type_t device_type;
-char *device = NULL;
-char *iface = NULL;
-static char *type = NULL;
-static char ifrname[IFNAMSIZ];
-static char *device_info;
-
-static bool setup_device(void) {
- if(!get_config_string(lookup_config(config_tree, "Device"), &device))
- device = xstrdup(DEFAULT_DEVICE);
-
- if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
- if(netname)
- iface = xstrdup(netname);
-
- device_fd = open(device, O_RDWR | O_NONBLOCK);
-
- if(device_fd < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device, strerror(errno));
- return false;
- }
-
-#ifdef FD_CLOEXEC
- fcntl(device_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- struct ifreq ifr = {{{0}}};
-
- get_config_string(lookup_config(config_tree, "DeviceType"), &type);
-
- if(type && strcasecmp(type, "tun") && strcasecmp(type, "tap")) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type);
- return false;
- }
-
- if((type && !strcasecmp(type, "tun")) || (!type && routing_mode == RMODE_ROUTER)) {
- ifr.ifr_flags = IFF_TUN;
- device_type = DEVICE_TYPE_TUN;
- device_info = "Linux tun/tap device (tun mode)";
- } else {
- if (routing_mode == RMODE_ROUTER)
- overwrite_mac = true;
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- device_type = DEVICE_TYPE_TAP;
- device_info = "Linux tun/tap device (tap mode)";
- }
-
-#ifdef IFF_ONE_QUEUE
- /* Set IFF_ONE_QUEUE flag... */
-
- bool t1q = false;
- if(get_config_bool(lookup_config(config_tree, "IffOneQueue"), &t1q) && t1q)
- ifr.ifr_flags |= IFF_ONE_QUEUE;
-#endif
-
- if(iface)
- strncpy(ifr.ifr_name, iface, IFNAMSIZ);
-
- if(!ioctl(device_fd, TUNSETIFF, &ifr)) {
- strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
- free(iface);
- iface = xstrdup(ifrname);
- }
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
-
- return true;
-}
-
-static void close_device(void) {
- close(device_fd);
-
- free(type);
- free(device);
- free(iface);
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- int inlen;
-
- switch(device_type) {
- case DEVICE_TYPE_TUN:
- inlen = read(device_fd, packet->data + 10, MTU - 10);
-
- if(inlen <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s",
- device_info, device, strerror(errno));
- return false;
- }
-
- memset(packet->data, 0, 12);
- packet->len = inlen + 10;
- break;
- case DEVICE_TYPE_TAP:
- inlen = read(device_fd, packet->data, MTU);
-
- if(inlen <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s",
- device_info, device, strerror(errno));
- return false;
- }
-
- packet->len = inlen;
- break;
- default:
- abort();
- }
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
- device_info);
-
- return true;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
- packet->len, device_info);
-
- switch(device_type) {
- case DEVICE_TYPE_TUN:
- packet->data[10] = packet->data[11] = 0;
- if(write(device_fd, packet->data + 10, packet->len - 10) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
- strerror(errno));
- return false;
- }
- break;
- case DEVICE_TYPE_TAP:
- if(write(device_fd, packet->data, packet->len) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
- strerror(errno));
- return false;
- }
- break;
- default:
- abort();
- }
-
- return true;
-}
-
-const devops_t os_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
#include "conf.h"
#include "meta.h"
-#include "names.h"
#include "logger.h"
#include "connection.h"
-#include "control_common.h"
#include "sptps.h"
debug_t debug_level = DEBUG_NOTHING;
static logmode_t logmode = LOGMODE_STDERR;
static pid_t logpid;
-static FILE *logfile = NULL;
#ifdef HAVE_MINGW
static HANDLE loghandle = NULL;
#endif
static const char *logident = NULL;
-bool logcontrol = false;
-
static void real_logger(int level, int priority, const char *message) {
char timestr[32] = "";
if(suppress)
return;
- if(!logcontrol && (level > debug_level || logmode == LOGMODE_NULL))
+ if(level > debug_level || logmode == LOGMODE_NULL)
return;
if(level <= debug_level) {
fprintf(stderr, "%s\n", message);
fflush(stderr);
break;
- case LOGMODE_FILE:
- if(!now.tv_sec)
- gettimeofday(&now, NULL);
- time_t now_sec = now.tv_sec;
- strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now_sec));
- fprintf(logfile, "%s %s[%ld]: %s\n", timestr, logident, (long)logpid, message);
- fflush(logfile);
- break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
{
break;
}
}
-
- if(logcontrol) {
- suppress = true;
- logcontrol = false;
- for list_each(connection_t, c, connection_list) {
- if(!c->status.log)
- continue;
- logcontrol = true;
- if(level > (c->outcompression >= 0 ? c->outcompression : debug_level))
- continue;
- int len = strlen(message);
- if(send_request(c, "%d %d %d", CONTROL, REQ_LOG, len))
- send_meta(c, message, len);
- }
- suppress = false;
- }
}
void logger(int level, int priority, const char *format, ...) {
case LOGMODE_STDERR:
logpid = getpid();
break;
- case LOGMODE_FILE:
- logpid = getpid();
- logfile = fopen(logfilename, "a");
- if(!logfile) {
- fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno));
- logmode = LOGMODE_NULL;
- }
- break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
loghandle = RegisterEventSource(NULL, logident);
sptps_log = sptps_log_quiet;
}
-void reopenlogger() {
- if(logmode != LOGMODE_FILE)
- return;
-
- fflush(logfile);
- FILE *newfile = fopen(logfilename, "a");
- if(!newfile) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reopen log file %s: %s", logfilename, strerror(errno));
- return;
- }
- fclose(logfile);
- logfile = newfile;
-}
-
-
void closelogger(void) {
switch(logmode) {
- case LOGMODE_FILE:
- fclose(logfile);
- break;
case LOGMODE_SYSLOG:
#ifdef HAVE_MINGW
DeregisterEventSource(loghandle);
typedef enum logmode_t {
LOGMODE_NULL,
LOGMODE_STDERR,
- LOGMODE_FILE,
LOGMODE_SYSLOG
} logmode_t;
extern debug_t debug_level;
extern bool logcontrol;
extern void openlogger(const char *, logmode_t);
-extern void reopenlogger(void);
extern void logger(int, int, const char *, ...) __attribute__ ((__format__(printf, 3, 4)));
extern void closelogger(void);
+++ /dev/null
-/*
- * TAP-Win32 -- A kernel driver to provide virtual tap device functionality
- * on Windows. Originally derived from the CIPE-Win32
- * project by Damion K. Wilson, with extensive modifications by
- * James Yonan.
- *
- * All source code which derives from the CIPE-Win32 project is
- * Copyright (C) Damion K. Wilson, 2003, and is released under the
- * GPL version 2 (see below).
- *
- * All other source code is Copyright (C) James Yonan, 2003-2004,
- * and is released under the GPL version 2 (see below).
- *
- * 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.
- */
-
-//===============================================
-// This file is included both by OpenVPN and
-// the TAP-Win32 driver and contains definitions
-// common to both.
-//===============================================
-
-//=============
-// TAP IOCTLs
-//=============
-
-#define TAP_CONTROL_CODE(request,method) \
- CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
-
-#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED)
-#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED)
-#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED)
-#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED)
-#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
-#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED)
-#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED)
-#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED)
-#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED)
-
-//=================
-// Registry keys
-//=================
-
-#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
-
-#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
-
-//======================
-// Filesystem prefixes
-//======================
-
-#define USERMODEDEVICEDIR "\\\\.\\Global\\"
-#define SYSDEVICEDIR "\\Device\\"
-#define USERDEVICEDIR "\\DosDevices\\Global\\"
-#define TAPSUFFIX ".tap"
-
-//=========================================================
-// TAP_COMPONENT_ID -- This string defines the TAP driver
-// type -- different component IDs can reside in the system
-// simultaneously.
-//=========================================================
-
-#define TAP_COMPONENT_ID "tap0801"
+++ /dev/null
-/*
- device.c -- Interaction with Windows tap driver in a MinGW environment
- Copyright (C) 2002-2005 Ivo Timmermans,
- 2002-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <windows.h>
-#include <winioctl.h>
-
-#include "../conf.h"
-#include "../device.h"
-#include "../logger.h"
-#include "../names.h"
-#include "../net.h"
-#include "../route.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-#include "common.h"
-
-int device_fd = -1;
-static HANDLE device_handle = INVALID_HANDLE_VALUE;
-char *device = NULL;
-char *iface = NULL;
-static char *device_info = NULL;
-
-static uint64_t device_total_in = 0;
-static uint64_t device_total_out = 0;
-
-extern char *myport;
-
-static DWORD WINAPI tapreader(void *bla) {
- int status;
- DWORD len;
- OVERLAPPED overlapped;
- vpn_packet_t packet;
-
- logger(DEBUG_ALWAYS, LOG_DEBUG, "Tap reader running");
-
- /* Read from tap device and send to parent */
-
- overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- for(;;) {
- overlapped.Offset = 0;
- overlapped.OffsetHigh = 0;
- ResetEvent(overlapped.hEvent);
-
- status = ReadFile(device_handle, (void *)packet.data, MTU, &len, &overlapped);
-
- if(!status) {
- if(GetLastError() == ERROR_IO_PENDING) {
- WaitForSingleObject(overlapped.hEvent, INFINITE);
- if(!GetOverlappedResult(device_handle, &overlapped, &len, FALSE))
- continue;
- } else {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
- return -1;
- }
- }
-
- EnterCriticalSection(&mutex);
- packet.len = len;
- packet.priority = 0;
- route(myself, &packet);
- event_flush_output();
- LeaveCriticalSection(&mutex);
- }
-}
-
-static bool setup_device(void) {
- HKEY key, key2;
- int i;
-
- char regpath[1024];
- char adapterid[1024];
- char adaptername[1024];
- char tapname[1024];
- DWORD len;
- unsigned long status;
-
- bool found = false;
-
- int err;
- HANDLE thread;
-
- get_config_string(lookup_config(config_tree, "Device"), &device);
- get_config_string(lookup_config(config_tree, "Interface"), &iface);
-
- /* Open registry and look for network adapters */
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read registry: %s", winerror(GetLastError()));
- return false;
- }
-
- for (i = 0; ; i++) {
- len = sizeof adapterid;
- if(RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL))
- break;
-
- /* Find out more about this adapter */
-
- snprintf(regpath, sizeof regpath, "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid);
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2))
- continue;
-
- len = sizeof adaptername;
- err = RegQueryValueEx(key2, "Name", 0, 0, (LPBYTE)adaptername, &len);
-
- RegCloseKey(key2);
-
- if(err)
- continue;
-
- if(device) {
- if(!strcmp(device, adapterid)) {
- found = true;
- break;
- } else
- continue;
- }
-
- if(iface) {
- if(!strcmp(iface, adaptername)) {
- found = true;
- break;
- } else
- continue;
- }
-
- snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
- device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
- if(device_handle != INVALID_HANDLE_VALUE) {
- found = true;
- break;
- }
- }
-
- RegCloseKey(key);
-
- if(!found) {
- logger(DEBUG_ALWAYS, LOG_ERR, "No Windows tap device found!");
- return false;
- }
-
- if(!device)
- device = xstrdup(adapterid);
-
- if(!iface)
- iface = xstrdup(adaptername);
-
- /* Try to open the corresponding tap device */
-
- if(device_handle == INVALID_HANDLE_VALUE) {
- snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, device);
- device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
- }
-
- if(device_handle == INVALID_HANDLE_VALUE) {
- logger(DEBUG_ALWAYS, LOG_ERR, "%s (%s) is not a usable Windows tap device: %s", device, iface, winerror(GetLastError()));
- return false;
- }
-
- /* Get MAC address from tap device */
-
- if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof mymac.x, mymac.x, sizeof mymac.x, &len, 0)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError()));
- return false;
- }
-
- if(routing_mode == RMODE_ROUTER) {
- overwrite_mac = 1;
- }
-
- /* Start the tap reader */
-
- thread = CreateThread(NULL, 0, tapreader, NULL, 0, NULL);
-
- if(!thread) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "CreateThread", winerror(GetLastError()));
- return false;
- }
-
- /* Set media status for newer TAP-Win32 devices */
-
- status = true;
- DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
-
- device_info = "Windows tap device";
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
-
- return true;
-}
-
-static void close_device(void) {
- CloseHandle(device_handle);
-
- free(device);
- free(iface);
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- return false;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- DWORD outlen;
- OVERLAPPED overlapped = {0};
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
- packet->len, device_info);
-
- if(!WriteFile(device_handle, packet->data, packet->len, &outlen, &overlapped)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError()));
- return false;
- }
-
- device_total_out += packet->len;
-
- return true;
-}
-
-const devops_t os_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
+++ /dev/null
-/*
- device.c -- multicast socket
- Copyright (C) 2002-2005 Ivo Timmermans,
- 2002-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 struct addrinfo *ai = NULL;
-static mac_t ignore_src = {{0}};
-
-static bool setup_device(void) {
- char *host = NULL;
- 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(DEBUG_ALWAYS, LOG_ERR, "Device variable required for %s", device_info);
- goto error;
- }
-
- host = xstrdup(device);
- space = strchr(host, ' ');
- if(!space) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Port number required for %s", device_info);
- goto error;
- }
-
- *space++ = 0;
- port = space;
- space = strchr(port, ' ');
-
- if(space) {
- *space++ = 0;
- ttl = atoi(space);
- }
-
- ai = str2addrinfo(host, port, SOCK_DGRAM);
- if(!ai)
- goto error;
-
- device_fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
- if(device_fd < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno));
- goto error;
- }
-
-#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)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to %s %s: %s", host, port, sockstrerror(sockerrno));
- goto error;
- }
-
- 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(DEBUG_ALWAYS, LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
- goto error;
- }
-#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(DEBUG_ALWAYS, LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno));
- goto error;
- }
-#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(DEBUG_ALWAYS, LOG_ERR, "Multicast for address family %hx unsupported", ai->ai_family);
- goto error;
- }
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
-
- return true;
-
-error:
- if(device_fd >= 0)
- closesocket(device_fd);
- if(ai)
- freeaddrinfo(ai);
- free(host);
-
- return false;
-}
-
-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, (void *)packet->data, MTU, 0)) <= 0) {
- logger(DEBUG_ALWAYS, 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)) {
- logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info);
- return false;
- }
-
- packet->len = lenin;
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
- device_info);
-
- return true;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
- packet->len, device_info);
-
- if(sendto(device_fd, (void *)packet->data, packet->len, 0, ai->ai_addr, ai->ai_addrlen) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
- strerror(errno));
- return false;
- }
-
- memcpy(&ignore_src, packet->data + 6, sizeof ignore_src);
-
- return true;
-}
-
-const devops_t multicast_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
+++ /dev/null
-/*
- names.c -- generate commonly used (file)names
- Copyright (C) 1998-2005 Ivo Timmermans
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "logger.h"
-#include "xalloc.h"
-
-char *netname = NULL;
-char *confdir = NULL; /* base configuration directory */
-char *confbase = NULL; /* base configuration directory for this instance of tinc */
-bool confbase_given;
-char *identname = NULL; /* program name for syslog */
-char *unixsocketname = NULL; /* UNIX socket location */
-char *logfilename = NULL; /* log file location */
-char *pidfilename = NULL;
-char *program_name = NULL;
-
-/*
- Set all files and paths according to netname
-*/
-void make_names(void) {
-#ifdef HAVE_MINGW
- HKEY key;
- char installdir[1024] = "";
- DWORD len = sizeof installdir;
-#endif
- confbase_given = confbase;
-
- if(netname && confbase)
- logger(DEBUG_ALWAYS, LOG_INFO, "Both netname and configuration directory given, using the latter...");
-
- if(netname)
- xasprintf(&identname, "tinc.%s", netname);
- else
- identname = xstrdup("tinc");
-
-#ifdef HAVE_MINGW
- if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) {
- if(!RegQueryValueEx(key, NULL, 0, 0, (LPBYTE)installdir, &len)) {
- confdir = xstrdup(installdir);
- if(!logfilename)
- xasprintf(&logfilename, "%s" SLASH "log" SLASH "%s.log", installdir, identname);
- if(!confbase) {
- if(netname)
- xasprintf(&confbase, "%s" SLASH "%s", installdir, netname);
- else
- xasprintf(&confbase, "%s", installdir);
- }
- if(!pidfilename)
- xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
- }
- RegCloseKey(key);
- }
-#endif
- if(!confdir)
- confdir = xstrdup(CONFDIR SLASH "tinc");
-
- if(!logfilename)
- xasprintf(&logfilename, LOCALSTATEDIR SLASH "log" SLASH "%s.log", identname);
-
- if(!pidfilename)
- xasprintf(&pidfilename, SLASH "tmp" SLASH "%s.pid", identname);
-
- if(!unixsocketname) {
- int len = strlen(pidfilename);
- unixsocketname = xmalloc(len + 8);
- strcpy(unixsocketname, pidfilename);
- if(len > 4 && !strcmp(pidfilename + len - 4, ".pid"))
- strcpy(unixsocketname + len - 4, ".socket");
- else
- strcpy(unixsocketname + len, ".socket");
- }
-
- if(!confbase) {
- if(netname)
- xasprintf(&confbase, CONFDIR SLASH "tinc" SLASH "%s", netname);
- else
- xasprintf(&confbase, CONFDIR SLASH "tinc");
- }
-}
-
-void free_names(void) {
- free(identname);
- free(netname);
- free(unixsocketname);
- free(pidfilename);
- free(logfilename);
- free(confbase);
- free(confdir);
-}
+++ /dev/null
-/*
- names.h -- header for names.c
- Copyright (C) 1998-2005 Ivo Timmermans
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_NAMES_H__
-#define __TINC_NAMES_H__
-
-extern char *confdir;
-extern char *confbase;
-extern bool confbase_given;
-extern char *netname;
-extern char *identname;
-extern char *unixsocketname;
-extern char *logfilename;
-extern char *pidfilename;
-extern char *program_name;
-
-extern void make_names(void);
-extern void free_names(void);
-
-#endif /* __TINC_NAMES_H__ */
#include "utils.h"
#include "conf.h"
#include "connection.h"
-#include "device.h"
#include "graph.h"
#include "logger.h"
#include "meta.h"
-#include "names.h"
#include "net.h"
#include "netutl.h"
#include "protocol.h"
-#include "subnet.h"
#include "xalloc.h"
int contradicting_add_edge = 0;
static timeout_t pingtimer;
static timeout_t periodictimer;
-/* Purge edges and subnets of unreachable nodes. Use carefully. */
+//TODO: move this to a better place
+char *confbase;
+/* Purge edges of unreachable nodes. Use carefully. */
+
+// TODO: remove
void purge(void) {
logger(DEBUG_PROTOCOL, LOG_DEBUG, "Purging unreachable nodes");
- /* Remove all edges and subnets owned by unreachable nodes. */
+ /* Remove all edges owned by unreachable nodes. */
for splay_each(node_t, n, node_tree) {
if(!n->status.reachable) {
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Purging node %s (%s)", n->name, n->hostname);
- for splay_each(subnet_t, s, n->subnet_tree) {
- send_del_subnet(everyone, s);
- if(!strictsubnets)
- subnet_del(n, s);
- }
-
for splay_each(edge_t, e, n->edge_tree) {
if(!tunnelserver)
send_del_edge(everyone, e);
for splay_each(edge_t, e, edge_weight_tree)
if(e->to == n)
return;
-
- if(!autoconnect && (!strictsubnets || !n->subnet_tree->head))
- /* in strictsubnets mode do not delete nodes with subnets */
- node_del(n);
}
}
}
*/
static void timeout_handler(void *data) {
for list_each(connection_t, c, connection_list) {
- if(c->status.control)
- continue;
-
if(c->last_ping_time + pingtimeout <= now.tv_sec) {
if(c->status.active) {
if(c->status.pinged) {
/* Count number of active connections */
int nc = 0;
for list_each(connection_t, c, connection_list) {
- if(c->status.active && !c->status.control)
+ if(c->status.active)
nc++;
}
int i = 0;
for list_each(connection_t, c, connection_list) {
- if(!c->status.active || c->status.control)
+ if(!c->status.active)
continue;
if(i++ != r)
}
}
-#ifndef HAVE_MINGW
-static void sigterm_handler(void *data) {
- logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
- event_exit();
-}
-
-static void sighup_handler(void *data) {
- logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
- reopenlogger();
- if(reload_configuration())
- exit(1);
-}
-
-static void sigalrm_handler(void *data) {
- logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s signal", strsignal(((signal_t *)data)->signum));
- retry();
-}
-#endif
-
int reload_configuration(void) {
char *fname = NULL;
setup_myself_reloadable();
- /* If StrictSubnet is set, expire deleted Subnets and read new ones in */
-
- if(strictsubnets) {
- for splay_each(subnet_t, subnet, subnet_tree)
- subnet->expires = 1;
-
- load_all_subnets();
-
- for splay_each(subnet_t, subnet, subnet_tree) {
- if(subnet->expires == 1) {
- send_del_subnet(everyone, subnet);
- if(subnet->owner->status.reachable)
- subnet_update(subnet->owner, subnet, false);
- subnet_del(subnet->owner, subnet);
- } else if(subnet->expires == -1) {
- subnet->expires = 0;
- } else {
- send_add_subnet(everyone, subnet);
- if(subnet->owner->status.reachable)
- subnet_update(subnet->owner, subnet, true);
- }
- }
- } else { /* Only read our own subnets back in */
- for splay_each(subnet_t, subnet, myself->subnet_tree)
- if(!subnet->expires)
- subnet->expires = 1;
-
- config_t *cfg = lookup_config(config_tree, "Subnet");
-
- while(cfg) {
- subnet_t *subnet, *s2;
-
- if(!get_config_subnet(cfg, &subnet))
- continue;
-
- if((s2 = lookup_subnet(myself, subnet))) {
- if(s2->expires == 1)
- s2->expires = 0;
-
- free_subnet(subnet);
- } else {
- subnet_add(myself, subnet);
- send_add_subnet(everyone, subnet);
- subnet_update(myself, subnet, true);
- }
-
- cfg = lookup_config_next(config_tree, cfg);
- }
-
- for splay_each(subnet_t, subnet, myself->subnet_tree) {
- if(subnet->expires == 1) {
- send_del_subnet(everyone, subnet);
- subnet_update(myself, subnet, false);
- subnet_del(myself, subnet);
- }
- }
- }
-
/* Try to make outgoing connections */
try_outgoing_connections();
/* Close connections to hosts that have a changed or deleted host config file */
for list_each(connection_t, c, connection_list) {
- if(c->status.control)
- continue;
-
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
struct stat s;
if(stat(fname, &s) || s.st_mtime > last_config_check) {
timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){pingtimeout, rand() % 100000});
-#ifndef HAVE_MINGW
- signal_t sighup = {0};
- signal_t sigterm = {0};
- signal_t sigquit = {0};
- signal_t sigint = {0};
- signal_t sigalrm = {0};
-
- signal_add(&sighup, sighup_handler, &sighup, SIGHUP);
- signal_add(&sigterm, sigterm_handler, &sigterm, SIGTERM);
- signal_add(&sigquit, sigterm_handler, &sigquit, SIGQUIT);
- signal_add(&sigint, sigterm_handler, &sigint, SIGINT);
- signal_add(&sigalrm, sigalrm_handler, &sigalrm, SIGALRM);
-#endif
-
if(!event_loop()) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno));
return 1;
}
-#ifndef HAVE_MINGW
- signal_del(&sighup);
- signal_del(&sigterm);
- signal_del(&sigquit);
- signal_del(&sigint);
- signal_del(&sigalrm);
-#endif
-
timeout_del(&periodictimer);
timeout_del(&pingtimer);
extern listen_socket_t listen_socket[MAXSOCKETS];
extern int listen_sockets;
-extern io_t unix_socket;
extern int keylifetime;
extern int udp_rcvbuf;
extern int udp_sndbuf;
extern void finish_connecting(struct connection_t *);
extern bool do_outgoing_connection(struct outgoing_t *);
extern void handle_new_meta_connection(void *, int);
-extern void handle_new_unix_connection(void *, int);
extern int setup_listen_socket(const sockaddr_t *);
extern int setup_vpn_in_socket(const sockaddr_t *);
extern bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len);
extern CRITICAL_SECTION mutex;
#endif
+//TODO: move this to a better place
+extern char *confbase;
+
#endif /* __TINC_NET_H__ */
#include "connection.h"
#include "crypto.h"
#include "digest.h"
-#include "device.h"
#include "ethernet.h"
#include "graph.h"
#include "logger.h"
memcpy(packet->data, mymac.x, ETH_ALEN);
n->out_packets++;
n->out_bytes += packet->len;
- devops.write(packet);
+ // TODO: send to application
return;
}
receive_udppacket(n, &pkt);
}
-
-//void handle_device_data(void *data, int flags) {
-// vpn_packet_t packet;
-//
-// packet.priority = 0;
-//
-// if(devops.read(&packet)) {
-// myself->in_packets++;
-// myself->in_bytes += packet.len;
-// route(myself, &packet);
-// }
-//}
#include "cipher.h"
#include "conf.h"
#include "connection.h"
-#include "control.h"
-#include "device.h"
#include "digest.h"
#include "ecdsa.h"
#include "graph.h"
#include "logger.h"
-#include "names.h"
#include "net.h"
#include "netutl.h"
-#include "process.h"
#include "protocol.h"
#include "route.h"
#include "rsa.h"
-#include "script.h"
-#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
char *myport;
-static io_t device_io;
-devops_t devops;
char *proxyhost;
char *proxyport;
int autoconnect;
bool disablebuggypeers;
-char *scriptinterpreter;
-char *scriptextension;
-
bool node_read_ecdsa_public_key(node_t *n) {
if(ecdsa_active(n->ecdsa))
return true;
if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error reading ECDSA private key file `%s': %s", fname, strerror(errno));
if(errno == ENOENT)
- logger(DEBUG_ALWAYS, LOG_INFO, "Create an ECDSA keypair with `tinc -n %s generate-ecdsa-keys'.", netname ?: ".");
+ logger(DEBUG_ALWAYS, LOG_INFO, "Create an ECDSA keypair with `tinc generate-ecdsa-keys'.");
free(fname);
return false;
}
send_key_changed();
}
-/*
- Read Subnets from all host config files
-*/
-void load_all_subnets(void) {
- DIR *dir;
- struct dirent *ent;
- char *dname;
-
- xasprintf(&dname, "%s" SLASH "hosts", confbase);
- dir = opendir(dname);
- if(!dir) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
- free(dname);
- return;
- }
-
- while((ent = readdir(dir))) {
- if(!check_id(ent->d_name))
- continue;
-
- node_t *n = lookup_node(ent->d_name);
- #ifdef _DIRENT_HAVE_D_TYPE
- //if(ent->d_type != DT_REG)
- // continue;
- #endif
-
- splay_tree_t *config_tree;
- init_configuration(&config_tree);
- read_config_options(config_tree, ent->d_name);
- read_host_config(config_tree, ent->d_name);
-
- if(!n) {
- n = new_node();
- n->name = xstrdup(ent->d_name);
- node_add(n);
- }
-
- for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
- subnet_t *s, *s2;
-
- if(!get_config_subnet(cfg, &s))
- continue;
-
- if((s2 = lookup_subnet(n, s))) {
- s2->expires = -1;
- } else {
- subnet_add(n, s);
- }
- }
-
- exit_configuration(&config_tree);
- }
-
- closedir(dir);
-}
-
void load_all_nodes(void) {
DIR *dir;
struct dirent *ent;
char *space;
bool choice;
- free(scriptinterpreter);
- scriptinterpreter = NULL;
- get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &scriptinterpreter);
-
-
- free(scriptextension);
- if(!get_config_string(lookup_config(config_tree, "ScriptsExtension"), &scriptextension))
- scriptextension = xstrdup("");
-
get_config_string(lookup_config(config_tree, "Proxy"), &proxy);
if(proxy) {
if((space = strchr(proxy, ' ')))
sockaddr2str(&sa, NULL, &myport);
}
- /* Read in all the subnets specified in the host configuration file */
-
- for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
- subnet_t *subnet;
-
- if(!get_config_subnet(cfg, &subnet))
- return false;
-
- subnet_add(myself, subnet);
- }
-
/* Check some options */
if(!setup_myself_reloadable())
return false;
- get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
- strictsubnets |= tunnelserver;
if(get_config_int(lookup_config(config_tree, "MaxConnectionBurst"), &max_connection_burst)) {
if(max_connection_burst <= 0) {
graph();
- if(strictsubnets)
- load_all_subnets();
- else if(autoconnect)
+ if(autoconnect)
load_all_nodes();
/* Open sockets */
- if(!do_detach && getenv("LISTEN_FDS")) {
- sockaddr_t sa;
- socklen_t salen;
+ listen_sockets = 0;
+ int cfgs = 0;
- listen_sockets = atoi(getenv("LISTEN_FDS"));
-#ifdef HAVE_UNSETENV
- unsetenv("LISTEN_FDS");
-#endif
-
- if(listen_sockets > MAXSOCKETS) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets");
+ for(config_t *cfg = lookup_config(config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ cfgs++;
+ get_config_string(cfg, &address);
+ if(!add_listen_address(address, true))
return false;
- }
-
- for(int i = 0; i < listen_sockets; i++) {
- salen = sizeof sa;
- if(getsockname(i + 3, &sa.sa, &salen) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno));
- return false;
- }
-
-#ifdef FD_CLOEXEC
- fcntl(i + 3, F_SETFD, FD_CLOEXEC);
-#endif
-
- int udp_fd = setup_vpn_in_socket(&sa);
- if(udp_fd < 0)
- return false;
-
- io_add(&listen_socket[i].tcp, (io_cb_t)handle_new_meta_connection, &listen_socket[i], i + 3, IO_READ);
- io_add(&listen_socket[i].udp, (io_cb_t)handle_incoming_vpn_data, &listen_socket[i], udp_fd, IO_READ);
-
- if(debug_level >= DEBUG_CONNECTIONS) {
- hostname = sockaddr2hostname(&sa);
- logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname);
- free(hostname);
- }
-
- memcpy(&listen_socket[i].sa, &sa, salen);
- }
- } else {
- listen_sockets = 0;
- int cfgs = 0;
-
- for(config_t *cfg = lookup_config(config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
- cfgs++;
- get_config_string(cfg, &address);
- if(!add_listen_address(address, true))
- return false;
- }
-
- for(config_t *cfg = lookup_config(config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
- cfgs++;
- get_config_string(cfg, &address);
- if(!add_listen_address(address, false))
- return false;
- }
+ }
- if(!cfgs)
- if(!add_listen_address(address, NULL))
- return false;
+ for(config_t *cfg = lookup_config(config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+ cfgs++;
+ get_config_string(cfg, &address);
+ if(!add_listen_address(address, false))
+ return false;
}
+ if(!cfgs)
+ if(!add_listen_address(address, NULL))
+ return false;
+
if(!listen_sockets) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to create any listening socket!");
return false;
*/
bool setup_network(void) {
init_connections();
- init_subnets();
init_nodes();
init_edges();
init_requests();
if(!setup_myself())
return false;
- if(!init_control())
- return false;
-
- /* Run tinc-up script to further initialize the tap interface */
-
- char *envp[5] = {NULL};
- xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
- xasprintf(&envp[1], "DEVICE=%s", device ? : "");
- xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
- xasprintf(&envp[3], "NAME=%s", myself->name);
-
- execute_script("tinc-up", envp);
-
- for(int i = 0; i < 4; i++)
- free(envp[i]);
-
- /* Run subnet-up scripts for our own subnets */
-
- subnet_update(myself, NULL, true);
-
return true;
}
for(list_node_t *node = connection_list->head, *next; node; node = next) {
next = node->next;
connection_t *c = node->data;
- /* Keep control connections open until the end, so they know when we really terminated */
- if(c->status.control)
- c->socket = -1;
c->outgoing = NULL;
terminate_connection(c, false);
}
list_delete_list(outgoing_list);
if(myself && myself->connection) {
- subnet_update(myself, NULL, false);
terminate_connection(myself->connection, false);
free_connection(myself->connection);
}
close(listen_socket[i].udp.fd);
}
- char *envp[5] = {NULL};
- xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
- xasprintf(&envp[1], "DEVICE=%s", device ? : "");
- xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
- xasprintf(&envp[3], "NAME=%s", myself->name);
-
exit_requests();
exit_edges();
- exit_subnets();
exit_nodes();
exit_connections();
- execute_script("tinc-down", envp);
-
if(myport) free(myport);
- for(int i = 0; i < 4; i++)
- free(envp[i]);
-
- devops.close();
-
- exit_control();
-
return;
}
#include "conf.h"
#include "connection.h"
-#include "control_common.h"
#include "list.h"
#include "logger.h"
#include "meta.h"
-#include "names.h"
#include "net.h"
#include "netutl.h"
#include "protocol.h"
listen_socket_t listen_socket[MAXSOCKETS];
int listen_sockets;
-#ifndef HAVE_MINGW
-io_t unix_socket;
-#endif
list_t *outgoing_list = NULL;
/* Setup sockets */
setenv("REMOTEPORT", port, true);
setenv("NODE", c->name, true);
setenv("NAME", myself->name, true);
- if(netname)
- setenv("NETNAME", netname, true);
int result = system(command);
if(result < 0)
send_id(c);
}
-#ifndef HAVE_MINGW
-/*
- accept a new UNIX socket connection
-*/
-void handle_new_unix_connection(void *data, int flags) {
- io_t *io = data;
- connection_t *c;
- sockaddr_t sa;
- int fd;
- socklen_t len = sizeof sa;
-
- fd = accept(io->fd, &sa.sa, &len);
-
- if(fd < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno));
- return;
- }
-
- sockaddrunmap(&sa);
-
- c = new_connection();
- c->name = xstrdup("<control>");
- c->address = sa;
- c->hostname = xstrdup("localhost port unix");
- c->socket = fd;
- c->last_ping_time = now.tv_sec;
-
- logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname);
-
- io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
-
- connection_add(c);
-
- c->allow_request = ID;
-
- send_id(c);
-}
-#endif
-
static void free_outgoing(outgoing_t *outgoing) {
timeout_del(&outgoing->ev);
#include "system.h"
-#include "control_common.h"
#include "hash.h"
#include "logger.h"
#include "net.h"
node_t *n = xzalloc(sizeof *n);
if(replaywin) n->late = xzalloc(replaywin);
- n->subnet_tree = new_subnet_tree();
n->edge_tree = new_edge_tree();
n->mtu = MTU;
n->maxmtu = MTU;
}
void free_node(node_t *n) {
- if(n->subnet_tree)
- free_subnet_tree(n->subnet_tree);
-
if(n->edge_tree)
free_edge_tree(n->edge_tree);
}
void node_del(node_t *n) {
- for splay_each(subnet_t, s, n->subnet_tree)
- subnet_del(n, s);
-
for splay_each(edge_t, e, n->edge_tree)
edge_del(e);
logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname);
}
}
-
-bool dump_nodes(connection_t *c) {
- for splay_each(node_t, n, node_tree)
- send_request(c, "%d %d %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES,
- n->name, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher),
- digest_get_nid(n->outdigest), (int)digest_length(n->outdigest), n->outcompression,
- n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-",
- n->via ? n->via->name ?: "-" : "-", n->distance, n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change);
-
- return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES);
-}
-
-bool dump_traffic(connection_t *c) {
- for splay_each(node_t, n, node_tree)
- send_request(c, "%d %d %s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, CONTROL, REQ_DUMP_TRAFFIC,
- n->name, n->in_packets, n->in_bytes, n->out_packets, n->out_bytes);
-
- return send_request(c, "%d %d", CONTROL, REQ_DUMP_TRAFFIC);
-}
#include "connection.h"
#include "digest.h"
#include "event.h"
-#include "subnet.h"
typedef struct node_status_t {
unsigned int unused_active:1; /* 1 if active (not used for nodes) */
struct edge_t *prevedge; /* nearest node from him to us */
struct node_t *via; /* next hop for UDP packets */
- splay_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */
-
splay_tree_t *edge_tree; /* Edges with this node as one of the endpoints */
struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */
extern void node_del(node_t *);
extern node_t *lookup_node(char *);
extern node_t *lookup_node_udp(const sockaddr_t *);
-extern bool dump_nodes(struct connection_t *);
-extern bool dump_traffic(struct connection_t *);
extern void update_node_udp(node_t *, const sockaddr_t *);
#endif /* __TINC_NODE_H__ */
+++ /dev/null
-/*
- process.c -- process management functions
- Copyright (C) 1999-2005 Ivo Timmermans,
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "connection.h"
-#include "control.h"
-#include "device.h"
-#include "edge.h"
-#include "event.h"
-#include "logger.h"
-#include "names.h"
-#include "net.h"
-#include "node.h"
-#include "process.h"
-#include "subnet.h"
-#include "utils.h"
-#include "xalloc.h"
-
-/* If zero, don't detach from the terminal. */
-bool do_detach = true;
-bool sigalrm = false;
-
-extern char **g_argv;
-extern bool use_logfile;
-
-/* Some functions the less gifted operating systems might lack... */
-
-#ifdef HAVE_MINGW
-static SC_HANDLE manager = NULL;
-static SC_HANDLE service = NULL;
-static SERVICE_STATUS status = {0};
-static SERVICE_STATUS_HANDLE statushandle = 0;
-
-static bool install_service(void) {
- char command[4096] = "\"";
- SERVICE_DESCRIPTION description = {"Virtual Private Network daemon"};
-
- manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if(!manager) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open service manager: %s", winerror(GetLastError()));
- return false;
- }
-
- if(!strchr(program_name, '\\')) {
- GetCurrentDirectory(sizeof command - 1, command + 1);
- strncat(command, "\\", sizeof command - strlen(command));
- }
-
- strncat(command, program_name, sizeof command - strlen(command));
-
- strncat(command, "\"", sizeof command - strlen(command));
-
- for(char **argp = g_argv + 1; *argp; argp++) {
- char *space = strchr(*argp, ' ');
- strncat(command, " ", sizeof command - strlen(command));
-
- if(space)
- strncat(command, "\"", sizeof command - strlen(command));
-
- strncat(command, *argp, sizeof command - strlen(command));
-
- if(space)
- strncat(command, "\"", sizeof command - strlen(command));
- }
-
- service = CreateService(manager, identname, identname,
- SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
- command, NULL, NULL, NULL, NULL, NULL);
-
- if(!service) {
- DWORD lasterror = GetLastError();
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not create %s service: %s", identname, winerror(lasterror));
- if(lasterror != ERROR_SERVICE_EXISTS)
- return false;
- }
-
- if(service) {
- ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description);
- logger(DEBUG_ALWAYS, LOG_INFO, "%s service installed", identname);
- } else {
- service = OpenService(manager, identname, SERVICE_ALL_ACCESS);
- }
-
- if(!StartService(service, 0, NULL))
- logger(DEBUG_ALWAYS, LOG_WARNING, "Could not start %s service: %s", identname, winerror(GetLastError()));
- else
- logger(DEBUG_ALWAYS, LOG_INFO, "%s service started", identname);
-
- return true;
-}
-
-DWORD WINAPI controlhandler(DWORD request, DWORD type, LPVOID boe, LPVOID bah) {
- switch(request) {
- case SERVICE_CONTROL_INTERROGATE:
- SetServiceStatus(statushandle, &status);
- return NO_ERROR;
- case SERVICE_CONTROL_STOP:
- logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_STOP");
- break;
- case SERVICE_CONTROL_SHUTDOWN:
- logger(DEBUG_ALWAYS, LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_SHUTDOWN");
- break;
- default:
- logger(DEBUG_ALWAYS, LOG_WARNING, "Got unexpected request %d", (int)request);
- return ERROR_CALL_NOT_IMPLEMENTED;
- }
-
- event_exit();
- status.dwWaitHint = 30000;
- status.dwCurrentState = SERVICE_STOP_PENDING;
- SetServiceStatus(statushandle, &status);
- return NO_ERROR;
-}
-
-VOID WINAPI run_service(DWORD argc, LPTSTR* argv) {
- extern int main2(int argc, char **argv);
-
- status.dwServiceType = SERVICE_WIN32;
- status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
- status.dwWin32ExitCode = 0;
- status.dwServiceSpecificExitCode = 0;
- status.dwCheckPoint = 0;
-
- statushandle = RegisterServiceCtrlHandlerEx(identname, controlhandler, NULL);
-
- if (!statushandle) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "RegisterServiceCtrlHandlerEx", winerror(GetLastError()));
- } else {
- status.dwWaitHint = 30000;
- status.dwCurrentState = SERVICE_START_PENDING;
- SetServiceStatus(statushandle, &status);
-
- status.dwWaitHint = 0;
- status.dwCurrentState = SERVICE_RUNNING;
- SetServiceStatus(statushandle, &status);
-
- main2(argc, argv);
-
- status.dwWaitHint = 0;
- status.dwCurrentState = SERVICE_STOPPED;
- SetServiceStatus(statushandle, &status);
- }
-
- return;
-}
-
-bool init_service(void) {
- SERVICE_TABLE_ENTRY services[] = {
- {identname, run_service},
- {NULL, NULL}
- };
-
- if(!StartServiceCtrlDispatcher(services)) {
- if(GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
- return false;
- }
- else
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "StartServiceCtrlDispatcher", winerror(GetLastError()));
- }
-
- return true;
-}
-#endif
-
-/*
- Detach from current terminal
-*/
-bool detach(void) {
-#ifndef HAVE_MINGW
- signal(SIGPIPE, SIG_IGN);
- signal(SIGUSR1, SIG_IGN);
- signal(SIGUSR2, SIG_IGN);
- signal(SIGWINCH, SIG_IGN);
-
- closelogger();
-#endif
-
- if(do_detach) {
-#ifndef HAVE_MINGW
- if(daemon(0, 0)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Couldn't detach from terminal: %s", strerror(errno));
- return false;
- }
-#else
- if(!statushandle)
- exit(!install_service());
-#endif
- }
-
- openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR));
-
- logger(DEBUG_ALWAYS, LOG_NOTICE, "tincd %s (%s %s) starting, debug level %d",
- VERSION, __DATE__, __TIME__, debug_level);
-
- return true;
-}
-
-
+++ /dev/null
-/*
- process.h -- header file for process.c
- Copyright (C) 1999-2005 Ivo Timmermans,
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_PROCESS_H__
-#define __TINC_PROCESS_H__
-
-extern bool do_detach;
-extern bool sigalrm;
-
-extern void setup_signals(void);
-extern bool detach(void);
-extern bool kill_other(int);
-
-#ifdef HAVE_MINGW
-extern bool init_service(void);
-#endif
-
-#endif /* __TINC_PROCESS_H__ */
#include "xalloc.h"
bool tunnelserver = false;
-bool strictsubnets = false;
bool experimental = true;
/* Jumptable for the request handlers */
id_h, metakey_h, challenge_h, chal_reply_h, ack_h,
status_h, error_h, termreq_h,
ping_h, pong_h,
- add_subnet_h, del_subnet_h,
+ NULL, NULL, //add_subnet_h, del_subnet_h,
add_edge_h, del_edge_h,
- key_changed_h, req_key_h, ans_key_h, tcppacket_h, control_h,
+ key_changed_h, req_key_h, ans_key_h, tcppacket_h, NULL, //control_h,
};
/* Request names */
} past_request_t;
extern bool tunnelserver;
-extern bool strictsubnets;
extern bool experimental;
extern ecdsa_t *invitation_key;
#include "edge.h"
#include "net.h"
#include "node.h"
-#include "subnet.h"
/* Basic functions */
extern bool send_termreq(struct connection_t *);
extern bool send_ping(struct connection_t *);
extern bool send_pong(struct connection_t *);
-extern bool send_add_subnet(struct connection_t *, const struct subnet_t *);
-extern bool send_del_subnet(struct connection_t *, const struct subnet_t *);
extern bool send_add_edge(struct connection_t *, const struct edge_t *);
extern bool send_del_edge(struct connection_t *, const struct edge_t *);
extern void send_key_changed(void);
extern bool termreq_h(struct connection_t *, const char *);
extern bool ping_h(struct connection_t *, const char *);
extern bool pong_h(struct connection_t *, const char *);
-extern bool add_subnet_h(struct connection_t *, const char *);
-extern bool del_subnet_h(struct connection_t *, const char *);
extern bool add_edge_h(struct connection_t *, const char *);
extern bool del_edge_h(struct connection_t *, const char *);
extern bool key_changed_h(struct connection_t *, const char *);
extern bool req_key_h(struct connection_t *, const char *);
extern bool ans_key_h(struct connection_t *, const char *);
extern bool tcppacket_h(struct connection_t *, const char *);
-extern bool control_h(struct connection_t *, const char *);
#endif /* __TINC_PROTOCOL_H__ */
#include "conf.h"
#include "connection.h"
-#include "control.h"
-#include "control_common.h"
#include "cipher.h"
#include "crypto.h"
-#include "device.h"
#include "digest.h"
#include "ecdsa.h"
#include "edge.h"
#include "graph.h"
#include "logger.h"
#include "meta.h"
-#include "names.h"
#include "net.h"
#include "netutl.h"
#include "node.h"
#include "prf.h"
#include "protocol.h"
#include "rsa.h"
-#include "script.h"
#include "sptps.h"
#include "utils.h"
#include "xalloc.h"
logger(DEBUG_CONNECTIONS, LOG_INFO, "Key succesfully received from %s (%s)", c->name, c->hostname);
- // Call invitation-accepted script
- char *envp[7] = {NULL};
- char *address, *port;
-
- xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
- xasprintf(&envp[1], "DEVICE=%s", device ? : "");
- xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
- xasprintf(&envp[3], "NODE=%s", c->name);
- sockaddr2str(&c->address, &address, &port);
- xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
- xasprintf(&envp[5], "NAME=%s", myself->name);
-
- execute_script("invitation-accepted", envp);
-
- for(int i = 0; envp[i] && i < 7; i++)
- free(envp[i]);
+ //TODO: callback to application to inform of an accepted invitation
sptps_send_record(&c->sptps, 2, data, 0);
return true;
return false;
}
- /* Check if this is a control connection */
-
- if(name[0] == '^' && !strcmp(name + 1, controlcookie)) {
- c->status.control = true;
- c->allow_request = CONTROL;
- c->last_ping_time = now.tv_sec + 3600;
-
- free(c->name);
- c->name = xstrdup("<control>");
-
- return send_request(c, "%d %d %d", ACK, TINC_CTL_VERSION_CURRENT, getpid());
- }
+ /* Check if this is an invitation */
if(name[0] == '?') {
if(!invitation_key) {
static void send_everything(connection_t *c) {
/* Send all known subnets and edges */
+ // TODO: remove this
if(disablebuggypeers) {
static struct {
vpn_packet_t pkt;
send_tcppacket(c, &zeropkt.pkt);
}
- if(tunnelserver) {
- for splay_each(subnet_t, s, myself->subnet_tree)
- send_add_subnet(c, s);
-
- return;
- }
-
for splay_each(node_t, n, node_tree) {
- for splay_each(subnet_t, s, n->subnet_tree)
- send_add_subnet(c, s);
-
for splay_each(edge_t, e, n->edge_tree)
send_add_edge(c, e);
}
}
terminate_connection(n->connection, false);
- /* Run graph algorithm to purge key and make sure up/down scripts are rerun with new IP addresses and stuff */
+ /* Run graph algorithm to keep things in sync */
graph();
}
}
+++ /dev/null
-/*
- protocol_subnet.c -- handle the meta-protocol, subnets
- Copyright (C) 1999-2005 Ivo Timmermans,
- 2000-2012 Guus Sliepen <guus@tinc-vpn.org>
- 2009 Michael Tokarev <mjt@tls.msk.ru>
-
- 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 "connection.h"
-#include "logger.h"
-#include "net.h"
-#include "netutl.h"
-#include "node.h"
-#include "protocol.h"
-#include "subnet.h"
-#include "utils.h"
-#include "xalloc.h"
-
-bool send_add_subnet(connection_t *c, const subnet_t *subnet) {
- char netstr[MAXNETSTR];
-
- if(!net2str(netstr, sizeof netstr, subnet))
- return false;
-
- return send_request(c, "%d %x %s %s", ADD_SUBNET, rand(), subnet->owner->name, netstr);
-}
-
-bool add_subnet_h(connection_t *c, const char *request) {
- char subnetstr[MAX_STRING_SIZE];
- char name[MAX_STRING_SIZE];
- node_t *owner;
- subnet_t s = {NULL}, *new, *old;
-
- if(sscanf(request, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ADD_SUBNET", c->name,
- c->hostname);
- return false;
- }
-
- /* Check if owner name is valid */
-
- if(!check_id(name)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_SUBNET", c->name,
- c->hostname, "invalid name");
- return false;
- }
-
- /* Check if subnet string is valid */
-
- if(!str2net(&s, subnetstr)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_SUBNET", c->name,
- c->hostname, "invalid subnet string");
- return false;
- }
-
- if(seen_request(request))
- return true;
-
- /* Check if the owner of the new subnet is in the connection list */
-
- owner = lookup_node(name);
-
- if(tunnelserver && owner != myself && owner != c->node) {
- /* in case of tunnelserver, ignore indirect subnet registrations */
- logger(DEBUG_PROTOCOL, LOG_WARNING, "Ignoring indirect %s from %s (%s) for %s",
- "ADD_SUBNET", c->name, c->hostname, subnetstr);
- return true;
- }
-
- if(!owner) {
- owner = new_node();
- owner->name = xstrdup(name);
- node_add(owner);
- }
-
- /* Check if we already know this subnet */
-
- if(lookup_subnet(owner, &s))
- return true;
-
- /* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */
-
- if(owner == myself) {
- logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself",
- "ADD_SUBNET", c->name, c->hostname);
- s.owner = myself;
- send_del_subnet(c, &s);
- return true;
- }
-
- /* In tunnel server mode, we should already know all allowed subnets */
-
- if(tunnelserver) {
- logger(DEBUG_ALWAYS, LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
- "ADD_SUBNET", c->name, c->hostname, subnetstr);
- return true;
- }
-
- /* Ignore if strictsubnets is true, but forward it to others */
-
- if(strictsubnets) {
- logger(DEBUG_ALWAYS, LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
- "ADD_SUBNET", c->name, c->hostname, subnetstr);
- forward_request(c, request);
- return true;
- }
-
- /* If everything is correct, add the subnet to the list of the owner */
-
- *(new = new_subnet()) = s;
- subnet_add(owner, new);
-
- if(owner->status.reachable)
- subnet_update(owner, new, true);
-
- /* Tell the rest */
-
- if(!tunnelserver)
- forward_request(c, request);
-
- /* Fast handoff of roaming MAC addresses */
-
- if(s.type == SUBNET_MAC && owner != myself && (old = lookup_subnet(myself, &s)) && old->expires)
- old->expires = 1;
-
- return true;
-}
-
-bool send_del_subnet(connection_t *c, const subnet_t *s) {
- char netstr[MAXNETSTR];
-
- if(!net2str(netstr, sizeof netstr, s))
- return false;
-
- return send_request(c, "%d %x %s %s", DEL_SUBNET, rand(), s->owner->name, netstr);
-}
-
-bool del_subnet_h(connection_t *c, const char *request) {
- char subnetstr[MAX_STRING_SIZE];
- char name[MAX_STRING_SIZE];
- node_t *owner;
- subnet_t s = {NULL}, *find;
-
- if(sscanf(request, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "DEL_SUBNET", c->name,
- c->hostname);
- return false;
- }
-
- /* Check if owner name is valid */
-
- if(!check_id(name)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_SUBNET", c->name,
- c->hostname, "invalid name");
- return false;
- }
-
- /* Check if subnet string is valid */
-
- if(!str2net(&s, subnetstr)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_SUBNET", c->name,
- c->hostname, "invalid subnet string");
- return false;
- }
-
- if(seen_request(request))
- return true;
-
- /* Check if the owner of the subnet being deleted is in the connection list */
-
- owner = lookup_node(name);
-
- if(tunnelserver && owner != myself && owner != c->node) {
- /* in case of tunnelserver, ignore indirect subnet deletion */
- logger(DEBUG_PROTOCOL, LOG_WARNING, "Ignoring indirect %s from %s (%s) for %s",
- "DEL_SUBNET", c->name, c->hostname, subnetstr);
- return true;
- }
-
- if(!owner) {
- logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for %s which is not in our node tree",
- "DEL_SUBNET", c->name, c->hostname, name);
- return true;
- }
-
- /* If everything is correct, delete the subnet from the list of the owner */
-
- s.owner = owner;
-
- find = lookup_subnet(owner, &s);
-
- if(!find) {
- logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for %s which does not appear in his subnet tree",
- "DEL_SUBNET", c->name, c->hostname, name);
- if(strictsubnets)
- forward_request(c, request);
- return true;
- }
-
- /* If we are the owner of this subnet, retaliate with an ADD_SUBNET */
-
- if(owner == myself) {
- logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself",
- "DEL_SUBNET", c->name, c->hostname);
- send_add_subnet(c, find);
- return true;
- }
-
- if(tunnelserver)
- return true;
-
- /* Tell the rest */
-
- if(!tunnelserver)
- forward_request(c, request);
- if(strictsubnets)
- return true;
-
- /* Finally, delete it. */
-
- if(owner->status.reachable)
- subnet_update(owner, find, false);
-
- subnet_del(owner, find);
-
- return true;
-}
+++ /dev/null
-/*
- device.c -- raw socket
- Copyright (C) 2002-2005 Ivo Timmermans,
- 2002-2012 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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"
-
-#ifdef HAVE_NETPACKET_PACKET_H
-#include <netpacket/packet.h>
-#endif
-
-#include "conf.h"
-#include "device.h"
-#include "net.h"
-#include "logger.h"
-#include "utils.h"
-#include "route.h"
-#include "xalloc.h"
-
-#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET) && defined(SIOCGIFINDEX)
-static char *device_info;
-
-static bool setup_device(void) {
- struct ifreq ifr;
- struct sockaddr_ll sa;
-
- if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
- iface = xstrdup("eth0");
-
- if(!get_config_string(lookup_config(config_tree, "Device"), &device))
- device = xstrdup(iface);
-
- device_info = "raw socket";
-
- if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device_info,
- strerror(errno));
- return false;
- }
-
- memset(&ifr, 0, sizeof ifr);
-
-#ifdef FD_CLOEXEC
- fcntl(device_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
- if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) {
- close(device_fd);
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't find interface %s: %s", iface,
- strerror(errno));
- return false;
- }
-
- memset(&sa, '0', sizeof sa);
- sa.sll_family = AF_PACKET;
- sa.sll_protocol = htons(ETH_P_ALL);
- sa.sll_ifindex = ifr.ifr_ifindex;
-
- if(bind(device_fd, (struct sockaddr *) &sa, (socklen_t) sizeof sa)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind %s to %s: %s", device, iface, strerror(errno));
- return false;
- }
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
-
- return true;
-}
-
-static void close_device(void) {
- close(device_fd);
-
- free(device);
- free(iface);
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- int inlen;
-
- if((inlen = read(device_fd, packet->data, MTU)) <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
- return false;
- }
-
- packet->len = inlen;
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
- device_info);
-
- return true;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
- packet->len, device_info);
-
- if(write(device_fd, packet->data, packet->len) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
- strerror(errno));
- return false;
- }
-
- return true;
-}
-
-const devops_t raw_socket_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
-
-#else
-
-static bool not_supported(void) {
- logger(DEBUG_ALWAYS, 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,
-};
-#endif
#include "system.h"
-#include "connection.h"
-#include "control_common.h"
-#include "ethernet.h"
-#include "ipv4.h"
-#include "ipv6.h"
#include "logger.h"
-#include "meta.h"
#include "net.h"
-#include "protocol.h"
#include "route.h"
-#include "subnet.h"
#include "utils.h"
rmode_t routing_mode = RMODE_ROUTER;
mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
bool pcap = false;
-/* Sizes of various headers */
-
-static const size_t ether_size = sizeof(struct ether_header);
-static const size_t arp_size = sizeof(struct ether_arp);
-static const size_t ip_size = sizeof(struct ip);
-static const size_t icmp_size = sizeof(struct icmp) - sizeof(struct ip);
-static const size_t ip6_size = sizeof(struct ip6_hdr);
-static const size_t icmp6_size = sizeof(struct icmp6_hdr);
-static const size_t ns_size = sizeof(struct nd_neighbor_solicit);
-static const size_t opt_size = sizeof(struct nd_opt_hdr);
-
-#ifndef MAX
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#endif
-
-static timeout_t age_subnets_timeout;
-
-/* RFC 1071 */
-
-static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) {
- uint16_t *p = data;
- uint32_t checksum = prevsum ^ 0xFFFF;
-
- while(len >= 2) {
- checksum += *p++;
- len -= 2;
- }
-
- if(len)
- checksum += *(uint8_t *)p;
-
- while(checksum >> 16)
- checksum = (checksum & 0xFFFF) + (checksum >> 16);
-
- return ~checksum;
-}
-
static bool ratelimit(int frequency) {
static time_t lasttime = 0;
static int count = 0;
return true;
}
-static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
- if(!source || !via || !(via->options & OPTION_CLAMP_MSS))
- return;
-
- uint16_t mtu = source->mtu;
- if(via != myself && via->mtu < mtu)
- mtu = via->mtu;
-
- /* Find TCP header */
- int start = ether_size;
- uint16_t type = packet->data[12] << 8 | packet->data[13];
-
- if(type == ETH_P_8021Q) {
- start += 4;
- type = packet->data[16] << 8 | packet->data[17];
- }
-
- if(type == ETH_P_IP && packet->data[start + 9] == 6)
- start += (packet->data[start] & 0xf) * 4;
- else if(type == ETH_P_IPV6 && packet->data[start + 6] == 6)
- start += 40;
- else
- return;
-
- if(packet->len <= start + 20)
- return;
-
- /* Use data offset field to calculate length of options field */
- int len = ((packet->data[start + 12] >> 4) - 5) * 4;
-
- if(packet->len < start + 20 + len)
- return;
-
- /* Search for MSS option header */
- for(int i = 0; i < len;) {
- if(packet->data[start + 20 + i] == 0)
- break;
-
- if(packet->data[start + 20 + i] == 1) {
- i++;
- continue;
- }
-
- if(i > len - 2 || i > len - packet->data[start + 21 + i])
- break;
-
- if(packet->data[start + 20 + i] != 2) {
- if(packet->data[start + 21 + i] < 2)
- break;
- i += packet->data[start + 21 + i];
- continue;
- }
-
- if(packet->data[start + 21] != 4)
- break;
-
- /* Found it */
- uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i];
- uint16_t newmss = mtu - start - 20;
- uint16_t csum = packet->data[start + 16] << 8 | packet->data[start + 17];
-
- if(oldmss <= newmss)
- break;
-
- logger(DEBUG_TRAFFIC, LOG_INFO, "Clamping MSS of packet from %s to %s to %d", source->name, via->name, newmss);
-
- /* Update the MSS value and the checksum */
- packet->data[start + 22 + i] = newmss >> 8;
- packet->data[start + 23 + i] = newmss & 0xff;
- csum ^= 0xffff;
- csum -= oldmss;
- csum += newmss;
- csum ^= 0xffff;
- packet->data[start + 16] = csum >> 8;
- packet->data[start + 17] = csum & 0xff;
- break;
- }
-}
-
-static void swap_mac_addresses(vpn_packet_t *packet) {
- mac_t tmp;
- memcpy(&tmp, &packet->data[0], sizeof tmp);
- memcpy(&packet->data[0], &packet->data[6], sizeof tmp);
- memcpy(&packet->data[6], &tmp, sizeof tmp);
-}
-
-static void age_subnets(void *data) {
- bool left = false;
-
- for splay_each(subnet_t, s, myself->subnet_tree) {
- if(s->expires && s->expires < now.tv_sec) {
- if(debug_level >= DEBUG_TRAFFIC) {
- char netstr[MAXNETSTR];
- if(net2str(netstr, sizeof netstr, s))
- logger(DEBUG_TRAFFIC, LOG_INFO, "Subnet %s expired", netstr);
- }
-
- for list_each(connection_t, c, connection_list)
- if(c->status.active)
- send_del_subnet(c, s);
-
- subnet_del(myself, s);
- } else {
- if(s->expires)
- left = true;
- }
- }
-
- if(left)
- timeout_set(&age_subnets_timeout, &(struct timeval){10, rand() % 100000});
-}
-
-static void learn_mac(mac_t *address) {
- subnet_t *subnet = lookup_subnet_mac(myself, address);
-
- /* If we don't know this MAC address yet, store it */
-
- if(!subnet) {
- logger(DEBUG_TRAFFIC, LOG_INFO, "Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx",
- address->x[0], address->x[1], address->x[2], address->x[3],
- address->x[4], address->x[5]);
-
- subnet = new_subnet();
- subnet->type = SUBNET_MAC;
- subnet->expires = now.tv_sec + macexpire;
- subnet->net.mac.address = *address;
- subnet->weight = 10;
- subnet_add(myself, subnet);
- subnet_update(myself, subnet, true);
-
- /* And tell all other tinc daemons it's our MAC */
-
- for list_each(connection_t, c, connection_list)
- if(c->status.active)
- send_add_subnet(c, subnet);
-
- timeout_add(&age_subnets_timeout, age_subnets, NULL, &(struct timeval){10, rand() % 100000});
- } else {
- if(subnet->expires)
- subnet->expires = now.tv_sec + macexpire;
- }
-}
-
-/* RFC 792 */
-
-static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
- struct ip ip = {0};
- struct icmp icmp = {0};
-
- struct in_addr ip_src;
- struct in_addr ip_dst;
- uint32_t oldlen;
-
- if(ratelimit(3))
- return;
-
- /* Swap Ethernet source and destination addresses */
-
- swap_mac_addresses(packet);
-
- /* Copy headers from packet into properly aligned structs on the stack */
-
- memcpy(&ip, packet->data + ether_size, ip_size);
-
- /* Remember original source and destination */
-
- ip_src = ip.ip_src;
- ip_dst = ip.ip_dst;
-
- oldlen = packet->len - ether_size;
-
- if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
- icmp.icmp_nextmtu = htons(packet->len - ether_size);
-
- if(oldlen >= IP_MSS - ip_size - icmp_size)
- oldlen = IP_MSS - ip_size - icmp_size;
-
- /* Copy first part of original contents to ICMP message */
-
- memmove(packet->data + ether_size + ip_size + icmp_size, packet->data + ether_size, oldlen);
-
- /* Fill in IPv4 header */
-
- ip.ip_v = 4;
- ip.ip_hl = ip_size / 4;
- ip.ip_tos = 0;
- ip.ip_len = htons(ip_size + icmp_size + oldlen);
- ip.ip_id = 0;
- ip.ip_off = 0;
- ip.ip_ttl = 255;
- ip.ip_p = IPPROTO_ICMP;
- ip.ip_sum = 0;
- ip.ip_src = ip_dst;
- ip.ip_dst = ip_src;
-
- ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
-
- /* Fill in ICMP header */
-
- icmp.icmp_type = type;
- icmp.icmp_code = code;
- icmp.icmp_cksum = 0;
-
- icmp.icmp_cksum = inet_checksum(&icmp, icmp_size, ~0);
- icmp.icmp_cksum = inet_checksum(packet->data + ether_size + ip_size + icmp_size, oldlen, icmp.icmp_cksum);
-
- /* Copy structs on stack back to packet */
-
- memcpy(packet->data + ether_size, &ip, ip_size);
- memcpy(packet->data + ether_size + ip_size, &icmp, icmp_size);
-
- packet->len = ether_size + ip_size + icmp_size + oldlen;
-
- send_packet(source, packet);
-}
-
-/* RFC 791 */
-
-static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t ether_size) {
- struct ip ip;
- vpn_packet_t fragment;
- int len, maxlen, todo;
- uint8_t *offset;
- uint16_t ip_off, origf;
-
- memcpy(&ip, packet->data + ether_size, ip_size);
- fragment.priority = packet->priority;
-
- if(ip.ip_hl != ip_size / 4)
- return;
-
- todo = ntohs(ip.ip_len) - ip_size;
-
- if(ether_size + ip_size + todo != packet->len) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Length of packet (%d) doesn't match length in IPv4 header (%d)", packet->len, (int)(ether_size + ip_size + todo));
- return;
- }
-
- logger(DEBUG_TRAFFIC, LOG_INFO, "Fragmenting packet of %d bytes to %s (%s)", packet->len, dest->name, dest->hostname);
-
- offset = packet->data + ether_size + ip_size;
- maxlen = (dest->mtu - ether_size - ip_size) & ~0x7;
- ip_off = ntohs(ip.ip_off);
- origf = ip_off & ~IP_OFFMASK;
- ip_off &= IP_OFFMASK;
-
- while(todo) {
- len = todo > maxlen ? maxlen : todo;
- memcpy(fragment.data + ether_size + ip_size, offset, len);
- todo -= len;
- offset += len;
-
- ip.ip_len = htons(ip_size + len);
- ip.ip_off = htons(ip_off | origf | (todo ? IP_MF : 0));
- ip.ip_sum = 0;
- ip.ip_sum = inet_checksum(&ip, ip_size, ~0);
- memcpy(fragment.data, packet->data, ether_size);
- memcpy(fragment.data + ether_size, &ip, ip_size);
- fragment.len = ether_size + ip_size + len;
-
- send_packet(dest, &fragment);
-
- ip_off += len / 8;
- }
-}
-
-static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
- subnet_t *subnet;
- node_t *via;
- ipv4_t dest;
-
- memcpy(&dest, &packet->data[30], sizeof dest);
- subnet = lookup_subnet_ipv4(&dest);
-
- if(!subnet) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet from %s (%s): unknown IPv4 destination address %d.%d.%d.%d",
- source->name, source->hostname,
- dest.x[0],
- dest.x[1],
- dest.x[2],
- dest.x[3]);
-
- route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNKNOWN);
- return;
- }
-
- if(subnet->owner == source) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname);
- return;
- }
-
- if(!subnet->owner->status.reachable)
- return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
-
- if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
- return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
-
- if(priorityinheritance)
- packet->priority = packet->data[15];
-
- via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
-
- if(via == source) {
- logger(DEBUG_TRAFFIC, LOG_ERR, "Routing loop for packet from %s (%s)!", source->name, source->hostname);
- return;
- }
-
- if(directonly && subnet->owner != via)
- return route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO);
-
- if(via && packet->len > MAX(via->mtu, 590) && via != myself) {
- logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
- if(packet->data[20] & 0x40) {
- packet->len = MAX(via->mtu, 590);
- route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
- } else {
- fragment_ipv4_packet(via, packet, ether_size);
- }
-
- return;
- }
-
- clamp_mss(source, via, packet);
-
- send_packet(subnet->owner, packet);
-}
-
-static void route_ipv4(node_t *source, vpn_packet_t *packet) {
- if(!checklength(source, packet, ether_size + ip_size))
- return;
-
- if(broadcast_mode && (((packet->data[30] & 0xf0) == 0xe0) || (
- packet->data[30] == 255 &&
- packet->data[31] == 255 &&
- packet->data[32] == 255 &&
- packet->data[33] == 255)))
- broadcast_packet(source, packet);
- else
- route_ipv4_unicast(source, packet);
-}
-
-/* RFC 2463 */
-
-static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, length_t ether_size, uint8_t type, uint8_t code) {
- struct ip6_hdr ip6;
- struct icmp6_hdr icmp6 = {0};
- uint16_t checksum;
-
- struct {
- struct in6_addr ip6_src; /* source address */
- struct in6_addr ip6_dst; /* destination address */
- uint32_t length;
- uint32_t next;
- } pseudo;
-
- if(ratelimit(3))
- return;
-
- /* Swap Ethernet source and destination addresses */
-
- swap_mac_addresses(packet);
-
- /* Copy headers from packet to structs on the stack */
-
- memcpy(&ip6, packet->data + ether_size, ip6_size);
-
- /* Remember original source and destination */
-
- pseudo.ip6_src = ip6.ip6_dst;
- pseudo.ip6_dst = ip6.ip6_src;
-
- pseudo.length = packet->len - ether_size;
-
- if(type == ICMP6_PACKET_TOO_BIG)
- icmp6.icmp6_mtu = htonl(pseudo.length);
-
- if(pseudo.length >= IP_MSS - ip6_size - icmp6_size)
- pseudo.length = IP_MSS - ip6_size - icmp6_size;
-
- /* Copy first part of original contents to ICMP message */
-
- memmove(packet->data + ether_size + ip6_size + icmp6_size, packet->data + ether_size, pseudo.length);
-
- /* Fill in IPv6 header */
-
- ip6.ip6_flow = htonl(0x60000000UL);
- ip6.ip6_plen = htons(icmp6_size + pseudo.length);
- ip6.ip6_nxt = IPPROTO_ICMPV6;
- ip6.ip6_hlim = 255;
- ip6.ip6_src = pseudo.ip6_src;
- ip6.ip6_dst = pseudo.ip6_dst;
-
- /* Fill in ICMP header */
-
- icmp6.icmp6_type = type;
- icmp6.icmp6_code = code;
- icmp6.icmp6_cksum = 0;
-
- /* Create pseudo header */
-
- pseudo.length = htonl(icmp6_size + pseudo.length);
- pseudo.next = htonl(IPPROTO_ICMPV6);
-
- /* Generate checksum */
-
- checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
- checksum = inet_checksum(&icmp6, icmp6_size, checksum);
- checksum = inet_checksum(packet->data + ether_size + ip6_size + icmp6_size, ntohl(pseudo.length) - icmp6_size, checksum);
-
- icmp6.icmp6_cksum = checksum;
-
- /* Copy structs on stack back to packet */
-
- memcpy(packet->data + ether_size, &ip6, ip6_size);
- memcpy(packet->data + ether_size + ip6_size, &icmp6, icmp6_size);
-
- packet->len = ether_size + ip6_size + ntohl(pseudo.length);
-
- send_packet(source, packet);
-}
-
-static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
- subnet_t *subnet;
- node_t *via;
- ipv6_t dest;
-
- memcpy(&dest, &packet->data[38], sizeof dest);
- subnet = lookup_subnet_ipv6(&dest);
-
- if(!subnet) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet from %s (%s): unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
- source->name, source->hostname,
- ntohs(dest.x[0]),
- ntohs(dest.x[1]),
- ntohs(dest.x[2]),
- ntohs(dest.x[3]),
- ntohs(dest.x[4]),
- ntohs(dest.x[5]),
- ntohs(dest.x[6]),
- ntohs(dest.x[7]));
-
- route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR);
- return;
- }
-
- if(subnet->owner == source) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname);
- return;
- }
-
- if(!subnet->owner->status.reachable)
- return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
-
- if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
- return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
-
- via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
-
- if(via == source) {
- logger(DEBUG_TRAFFIC, LOG_ERR, "Routing loop for packet from %s (%s)!", source->name, source->hostname);
- return;
- }
-
- if(directonly && subnet->owner != via)
- return route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
-
- if(via && packet->len > MAX(via->mtu, 1294) && via != myself) {
- logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
- packet->len = MAX(via->mtu, 1294);
- route_ipv6_unreachable(source, packet, ether_size, ICMP6_PACKET_TOO_BIG, 0);
- return;
- }
-
- clamp_mss(source, via, packet);
-
- send_packet(subnet->owner, packet);
-}
-
-/* RFC 2461 */
-
-static void route_neighborsol(node_t *source, vpn_packet_t *packet) {
- struct ip6_hdr ip6;
- struct nd_neighbor_solicit ns;
- struct nd_opt_hdr opt;
- subnet_t *subnet;
- uint16_t checksum;
- bool has_opt;
-
- struct {
- struct in6_addr ip6_src;
- struct in6_addr ip6_dst;
- uint32_t length;
- uint32_t next;
- } pseudo;
-
- if(!checklength(source, packet, ether_size + ip6_size + ns_size))
- return;
-
- has_opt = packet->len >= ether_size + ip6_size + ns_size + opt_size + ETH_ALEN;
-
- if(source != myself) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Got neighbor solicitation request from %s (%s) while in router mode!", source->name, source->hostname);
- return;
- }
-
- /* Copy headers from packet to structs on the stack */
-
- memcpy(&ip6, packet->data + ether_size, ip6_size);
- memcpy(&ns, packet->data + ether_size + ip6_size, ns_size);
- if(has_opt)
- memcpy(&opt, packet->data + ether_size + ip6_size + ns_size, opt_size);
-
- /* First, snatch the source address from the neighbor solicitation packet */
-
- if(overwrite_mac)
- memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN);
-
- /* Check if this is a valid neighbor solicitation request */
-
- if(ns.nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
- (has_opt && opt.nd_opt_type != ND_OPT_SOURCE_LINKADDR)) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet: received unknown type neighbor solicitation request");
- return;
- }
-
- /* Create pseudo header */
-
- pseudo.ip6_src = ip6.ip6_src;
- pseudo.ip6_dst = ip6.ip6_dst;
- if(has_opt)
- pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
- else
- pseudo.length = htonl(ns_size);
- pseudo.next = htonl(IPPROTO_ICMPV6);
-
- /* Generate checksum */
-
- checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
- checksum = inet_checksum(&ns, ns_size, checksum);
- if(has_opt) {
- checksum = inet_checksum(&opt, opt_size, checksum);
- checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
- }
-
- if(checksum) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet: checksum error for neighbor solicitation request");
- return;
- }
-
- /* Check if the IPv6 address exists on the VPN */
-
- subnet = lookup_subnet_ipv6((ipv6_t *) &ns.nd_ns_target);
-
- if(!subnet) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
- ntohs(((uint16_t *) &ns.nd_ns_target)[0]),
- ntohs(((uint16_t *) &ns.nd_ns_target)[1]),
- ntohs(((uint16_t *) &ns.nd_ns_target)[2]),
- ntohs(((uint16_t *) &ns.nd_ns_target)[3]),
- ntohs(((uint16_t *) &ns.nd_ns_target)[4]),
- ntohs(((uint16_t *) &ns.nd_ns_target)[5]),
- ntohs(((uint16_t *) &ns.nd_ns_target)[6]),
- ntohs(((uint16_t *) &ns.nd_ns_target)[7]));
-
- return;
- }
-
- /* Check if it is for our own subnet */
-
- if(subnet->owner == myself)
- return; /* silently ignore */
-
- /* Create neighbor advertation reply */
-
- memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */
- packet->data[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
-
- ip6.ip6_dst = ip6.ip6_src; /* swap destination and source protocoll address */
- ip6.ip6_src = ns.nd_ns_target;
-
- if(has_opt)
- memcpy(packet->data + ether_size + ip6_size + ns_size + opt_size, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
-
- ns.nd_ns_cksum = 0;
- ns.nd_ns_type = ND_NEIGHBOR_ADVERT;
- ns.nd_ns_reserved = htonl(0x40000000UL); /* Set solicited flag */
- opt.nd_opt_type = ND_OPT_TARGET_LINKADDR;
-
- /* Create pseudo header */
-
- pseudo.ip6_src = ip6.ip6_src;
- pseudo.ip6_dst = ip6.ip6_dst;
- if(has_opt)
- pseudo.length = htonl(ns_size + opt_size + ETH_ALEN);
- else
- pseudo.length = htonl(ns_size);
- pseudo.next = htonl(IPPROTO_ICMPV6);
-
- /* Generate checksum */
-
- checksum = inet_checksum(&pseudo, sizeof pseudo, ~0);
- checksum = inet_checksum(&ns, ns_size, checksum);
- if(has_opt) {
- checksum = inet_checksum(&opt, opt_size, checksum);
- checksum = inet_checksum(packet->data + ether_size + ip6_size + ns_size + opt_size, ETH_ALEN, checksum);
- }
-
- ns.nd_ns_hdr.icmp6_cksum = checksum;
-
- /* Copy structs on stack back to packet */
-
- memcpy(packet->data + ether_size, &ip6, ip6_size);
- memcpy(packet->data + ether_size + ip6_size, &ns, ns_size);
- if(has_opt)
- memcpy(packet->data + ether_size + ip6_size + ns_size, &opt, opt_size);
-
- send_packet(source, packet);
-}
-
-static void route_ipv6(node_t *source, vpn_packet_t *packet) {
- if(!checklength(source, packet, ether_size + ip6_size))
- return;
-
- if(packet->data[20] == IPPROTO_ICMPV6 && checklength(source, packet, ether_size + ip6_size + icmp6_size) && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
- route_neighborsol(source, packet);
- return;
- }
-
- if(broadcast_mode && packet->data[38] == 255)
- broadcast_packet(source, packet);
- else
- route_ipv6_unicast(source, packet);
-}
-
-/* RFC 826 */
-
-static void route_arp(node_t *source, vpn_packet_t *packet) {
- struct ether_arp arp;
- subnet_t *subnet;
- struct in_addr addr;
-
- if(!checklength(source, packet, ether_size + arp_size))
- return;
-
- if(source != myself) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Got ARP request from %s (%s) while in router mode!", source->name, source->hostname);
- return;
- }
-
- /* First, snatch the source address from the ARP packet */
-
- if(overwrite_mac)
- memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN);
-
- /* Copy headers from packet to structs on the stack */
-
- memcpy(&arp, packet->data + ether_size, arp_size);
-
- /* Check if this is a valid ARP request */
-
- if(ntohs(arp.arp_hrd) != ARPHRD_ETHER || ntohs(arp.arp_pro) != ETH_P_IP ||
- arp.arp_hln != ETH_ALEN || arp.arp_pln != sizeof addr || ntohs(arp.arp_op) != ARPOP_REQUEST) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet: received unknown type ARP request");
- return;
- }
-
- /* Check if the IPv4 address exists on the VPN */
-
- subnet = lookup_subnet_ipv4((ipv4_t *) &arp.arp_tpa);
-
- if(!subnet) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet: ARP request for unknown address %d.%d.%d.%d",
- arp.arp_tpa[0], arp.arp_tpa[1], arp.arp_tpa[2],
- arp.arp_tpa[3]);
- return;
- }
-
- /* Check if it is for our own subnet */
-
- if(subnet->owner == myself)
- return; /* silently ignore */
-
- memcpy(packet->data, packet->data + ETH_ALEN, ETH_ALEN); /* copy destination address */
- packet->data[ETH_ALEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
-
- memcpy(&addr, arp.arp_tpa, sizeof addr); /* save protocol addr */
- memcpy(arp.arp_tpa, arp.arp_spa, sizeof addr); /* swap destination and source protocol address */
- memcpy(arp.arp_spa, &addr, sizeof addr); /* ... */
-
- memcpy(arp.arp_tha, arp.arp_sha, ETH_ALEN); /* set target hard/proto addr */
- memcpy(arp.arp_sha, packet->data + ETH_ALEN, ETH_ALEN); /* add fake source hard addr */
- arp.arp_op = htons(ARPOP_REPLY);
-
- /* Copy structs on stack back to packet */
-
- memcpy(packet->data + ether_size, &arp, arp_size);
-
- send_packet(source, packet);
-}
-
-static void route_mac(node_t *source, vpn_packet_t *packet) {
- subnet_t *subnet;
- mac_t dest;
-
- /* Learn source address */
-
- if(source == myself) {
- mac_t src;
- memcpy(&src, &packet->data[6], sizeof src);
- learn_mac(&src);
- }
-
- /* Lookup destination address */
-
- memcpy(&dest, &packet->data[0], sizeof dest);
- subnet = lookup_subnet_mac(NULL, &dest);
-
- if(!subnet) {
- broadcast_packet(source, packet);
- return;
- }
-
- if(subnet->owner == source) {
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname);
- return;
- }
-
- if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
- return;
-
- uint16_t type = packet->data[12] << 8 | packet->data[13];
-
- if(priorityinheritance && type == ETH_P_IP && packet->len >= ether_size + ip_size)
- packet->priority = packet->data[15];
-
- // Handle packets larger than PMTU
-
- node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
-
- if(directonly && subnet->owner != via)
- return;
-
- if(via && packet->len > via->mtu && via != myself) {
- logger(DEBUG_TRAFFIC, LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
- length_t ethlen = 14;
-
- if(type == ETH_P_8021Q) {
- type = packet->data[16] << 8 | packet->data[17];
- ethlen += 4;
- }
-
- if(type == ETH_P_IP && packet->len > 576 + ethlen) {
- if(packet->data[6 + ethlen] & 0x40) {
- packet->len = via->mtu;
- route_ipv4_unreachable(source, packet, ethlen, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
- } else {
- fragment_ipv4_packet(via, packet, ethlen);
- }
- return;
- } else if(type == ETH_P_IPV6 && packet->len > 1280 + ethlen) {
- packet->len = via->mtu;
- route_ipv6_unreachable(source, packet, ethlen, ICMP6_PACKET_TOO_BIG, 0);
- return;
- }
- }
-
- clamp_mss(source, via, packet);
-
- send_packet(subnet->owner, packet);
-}
-
-static void send_pcap(vpn_packet_t *packet) {
- pcap = false;
-
- for list_each(connection_t, c, connection_list) {
- if(!c->status.pcap)
- continue;
-
- pcap = true;
- int len = packet->len;
- if(c->outmaclength && c->outmaclength < len)
- len = c->outmaclength;
-
- if(send_request(c, "%d %d %d", CONTROL, REQ_PCAP, len))
- send_meta(c, (char *)packet->data, len);
- }
-}
-
-static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
- uint16_t type = packet->data[12] << 8 | packet->data[13];
- length_t ethlen = ether_size;
-
- if(type == ETH_P_8021Q) {
- type = packet->data[16] << 8 | packet->data[17];
- ethlen += 4;
- }
-
- switch (type) {
- case ETH_P_IP:
- if(!checklength(source, packet, ethlen + ip_size))
- return false;
-
- if(packet->data[ethlen + 8] < 1) {
- if(packet->data[ethlen + 11] != IPPROTO_ICMP || packet->data[ethlen + 32] != ICMP_TIME_EXCEEDED)
- route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
- return false;
- }
-
- uint16_t old = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9];
- packet->data[ethlen + 8]--;
- uint16_t new = packet->data[ethlen + 8] << 8 | packet->data[ethlen + 9];
-
- uint32_t checksum = packet->data[ethlen + 10] << 8 | packet->data[ethlen + 11];
- checksum += old + (~new & 0xFFFF);
- while(checksum >> 16)
- checksum = (checksum & 0xFFFF) + (checksum >> 16);
- packet->data[ethlen + 10] = checksum >> 8;
- packet->data[ethlen + 11] = checksum & 0xff;
-
- return true;
-
- case ETH_P_IPV6:
- if(!checklength(source, packet, ethlen + ip6_size))
- return false;
-
- if(packet->data[ethlen + 7] < 1) {
- if(packet->data[ethlen + 6] != IPPROTO_ICMPV6 || packet->data[ethlen + 40] != ICMP6_TIME_EXCEEDED)
- route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
- return false;
- }
-
- packet->data[ethlen + 7]--;
-
- return true;
-
- default:
- return true;
- }
-}
-
void route(node_t *source, vpn_packet_t *packet) {
- if(pcap)
- send_pcap(packet);
-
- if(forwarding_mode == FMODE_KERNEL && source != myself) {
- send_packet(myself, packet);
- return;
- }
-
- if(!checklength(source, packet, ether_size))
- return;
-
- if(decrement_ttl && source != myself)
- if(!do_decrement_ttl(source, packet))
- return;
-
- uint16_t type = packet->data[12] << 8 | packet->data[13];
-
- switch (routing_mode) {
- case RMODE_ROUTER:
- switch (type) {
- case ETH_P_ARP:
- route_arp(source, packet);
- break;
-
- case ETH_P_IP:
- route_ipv4(source, packet);
- break;
-
- case ETH_P_IPV6:
- route_ipv6(source, packet);
- break;
-
- default:
- logger(DEBUG_TRAFFIC, LOG_WARNING, "Cannot route packet from %s (%s): unknown type %hx", source->name, source->hostname, type);
- break;
- }
- break;
-
- case RMODE_SWITCH:
- route_mac(source, packet);
- break;
-
- case RMODE_HUB:
- broadcast_packet(source, packet);
- break;
- }
+ // TODO: route on name or key
}
+++ /dev/null
-/*
- script.c -- call an external script
- Copyright (C) 1999-2005 Ivo Timmermans,
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 "logger.h"
-#include "names.h"
-#include "script.h"
-#include "xalloc.h"
-
-bool execute_script(const char *name, char **envp) {
-#ifdef HAVE_SYSTEM
- char *scriptname;
- char *command;
-
- xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
-
- /* First check if there is a script */
-
-#ifdef HAVE_MINGW
- if(!*scriptextension) {
- const char *pathext = getenv("PATHEXT") ?: ".COM;.EXE;.BAT;.CMD";
- char fullname[strlen(scriptname) + strlen(pathext)];
- char *ext = fullname + strlen(scriptname);
- strcpy(fullname, scriptname);
-
- const char *p = pathext;
- bool found = false;
- while(p && *p) {
- const char *q = strchr(p, ';');
- if(q) {
- memcpy(ext, p, q - p);
- ext[q - p] = 0;
- *q++;
- } else {
- strcpy(ext, p);
- }
- if((found = !access(fullname, F_OK)))
- break;
- p = q;
- }
- if(!found) {
- free(scriptname);
- return true;
- }
- } else
-#endif
-
- if(access(scriptname, F_OK)) {
- free(scriptname);
- return true;
- }
-
- logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
-
-#ifdef HAVE_PUTENV
- /* Set environment */
-
- for(int i = 0; envp[i]; i++)
- putenv(envp[i]);
-#endif
-
- if(scriptinterpreter)
- xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
- else
- xasprintf(&command, "\"%s\"", scriptname);
-
- int status = system(command);
-
- free(command);
- free(scriptname);
-
- /* Unset environment */
-
- for(int i = 0; envp[i]; i++) {
- char *e = strchr(envp[i], '=');
- if(e) {
- char p[e - envp[i] + 1];
- strncpy(p, envp[i], e - envp[i]);
- p[e - envp[i]] = '\0';
- putenv(p);
- }
- }
-
- if(status != -1) {
-#ifdef WEXITSTATUS
- if(WIFEXITED(status)) { /* Child exited by itself */
- if(WEXITSTATUS(status)) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Script %s exited with non-zero status %d",
- name, WEXITSTATUS(status));
- return false;
- }
- } else if(WIFSIGNALED(status)) { /* Child was killed by a signal */
- logger(DEBUG_ALWAYS, LOG_ERR, "Script %s was killed by signal %d (%s)",
- name, WTERMSIG(status), strsignal(WTERMSIG(status)));
- return false;
- } else { /* Something strange happened */
- logger(DEBUG_ALWAYS, LOG_ERR, "Script %s terminated abnormally", name);
- return false;
- }
-#endif
- } else {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno));
- return false;
- }
-#endif
- return true;
-}
+++ /dev/null
-/*
- script.h -- header file for script.c
- Copyright (C) 1999-2005 Ivo Timmermans,
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_SCRIPT_H__
-#define __TINC_SCRIPT_H__
-
-extern bool execute_script(const char *, char **);
-
-#endif /* __TINC_SCRIPT_H__ */
+++ /dev/null
-/*
- device.c -- Interaction with Solaris tun device
- Copyright (C) 2001-2005 Ivo Timmermans,
- 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
- 2001-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <sys/stropts.h>
-#include <sys/sockio.h>
-
-#include "../conf.h"
-#include "../device.h"
-#include "../logger.h"
-#include "../names.h"
-#include "../net.h"
-#include "../route.h"
-#include "../utils.h"
-#include "../xalloc.h"
-
-#ifndef TUNNEWPPA
-#warning Missing net/if_tun.h, using hardcoded value for TUNNEWPPA
-#define TUNNEWPPA (('T'<<16) | 0x0001)
-#endif
-
-#define DEFAULT_TUN_DEVICE "/dev/tun"
-#define DEFAULT_TAP_DEVICE "/dev/tap"
-
-static enum {
- DEVICE_TYPE_TUN,
- DEVICE_TYPE_TAP,
-} device_type = DEVICE_TYPE_TUN;
-
-int device_fd = -1;
-static int if_fd = -1;
-static int ip_fd = -1;
-char *device = NULL;
-char *iface = NULL;
-static char *device_info = NULL;
-
-static bool setup_device(void) {
- char *type;
-
- if(!get_config_string(lookup_config(config_tree, "Device"), &device)) {
- if(routing_mode == RMODE_ROUTER)
- device = xstrdup(DEFAULT_TUN_DEVICE);
- else
- device = xstrdup(DEFAULT_TAP_DEVICE);
- }
-
- if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
- if(!strcasecmp(type, "tun"))
- /* use default */;
- else if(!strcasecmp(type, "tap"))
- device_type = DEVICE_TYPE_TAP;
- else {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type);
- return false;
- }
- } else {
- if(strstr(device, "tap") || routing_mode != RMODE_ROUTER)
- device_type = DEVICE_TYPE_TAP;
- }
-
- if(device_type == DEVICE_TYPE_TUN)
- device_info = "Solaris tun device";
- else
- device_info = "Solaris tap device";
-
- /* The following is black magic copied from OpenVPN. */
-
- if((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s\n", "/dev/ip", strerror(errno));
- return false;
- }
-
- if((device_fd = open(device, O_RDWR, 0)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s\n", device, strerror(errno));
- return false;
- }
-
- /* Get unit number. */
-
- char *ptr = device;
- get_config_string(lookup_config(config_tree, "Interface"), &ptr);
-
- while(*ptr && !isdigit(*ptr))
- ptr++;
- int ppa = atoi(ptr);
-
- /* Assign a new PPA and get its unit number. */
-
- struct strioctl strioc_ppa = {
- .ic_cmd = TUNNEWPPA,
- .ic_len = sizeof ppa,
- .ic_dp = (char *)&ppa,
- };
-
- if(!*ptr) { /* no number given, try dynamic */
- bool found = false;
- while(!found && ppa < 64) {
- int new_ppa = ioctl(device_fd, I_STR, &strioc_ppa);
- if(new_ppa >= 0) {
- ppa = new_ppa;
- found = true;
- break;
- }
- ppa++;
- }
- if(!found) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not find free PPA for %s %s!", device_info, device);
- return false;
- }
- } else { /* try this particular one */
- if((ppa = ioctl(device_fd, I_STR, &strioc_ppa)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not assign PPA %d for %s %s!", ppa, device_info, device);
- return false;
- }
- }
-
- if((if_fd = open(device, O_RDWR, 0)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s\n", device, strerror(errno));
- return false;
- }
-
- if(ioctl(if_fd, I_PUSH, "ip") < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not push IP module onto %s %s!", device_info, device);
- return false;
- }
-
- xasprintf(&iface, "%s%d", device_type == DEVICE_TYPE_TUN ? "tun" : "tap", ppa);
-
- {
- /* Remove muxes just in case they are left over from a crashed tincd */
- struct lifreq ifr = {};
- strncpy(ifr.lifr_name, iface, sizeof ifr.lifr_name);
- if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) {
- int muxid = ifr.lifr_arp_muxid;
- ioctl(ip_fd, I_PUNLINK, muxid);
- muxid = ifr.lifr_ip_muxid;
- ioctl(ip_fd, I_PUNLINK, muxid);
- }
- }
-
- if(device_type == DEVICE_TYPE_TUN) {
- /* Assign ppa according to the unit number returned by tun device */
- if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device);
- return false;
- }
- }
-
- int arp_fd = -1;
-
- if(device_type == DEVICE_TYPE_TAP) {
- struct lifreq ifr = {};
-
- if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not set flags on %s %s!", device_info, device);
- return false;
- }
-
- strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name));
- ifr.lifr_ppa = ppa;
-
- /* Assign ppa according to the unit number returned by tun device */
- if(ioctl(if_fd, SIOCSLIFNAME, &ifr) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device);
- return false;
- }
- if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not set flags on %s %s!", device_info, device);
- return false;
- }
-
- /* Push arp module to if_fd */
- if(ioctl(if_fd, I_PUSH, "arp") < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not push ARP module onto %s %s!", device_info, device);
- return false;
- }
-
- /* Pop any modules on the stream */
- while(true) {
- if(ioctl(ip_fd, I_POP, NULL) < 0)
- break;
- }
-
- /* Push arp module to ip_fd */
- if(ioctl(ip_fd, I_PUSH, "arp") < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not push ARP module onto %s!", "/dev/ip");
- return false;
- }
-
- /* Open arp_fd */
- if((arp_fd = open(device, O_RDWR, 0)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s\n", device, strerror(errno));
- return false;
- }
-
- /* Push arp module to arp_fd */
- if(ioctl(arp_fd, I_PUSH, "arp") < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not push ARP module onto %s %s!", device_info, device);
- return false;
- }
-
- /* Set ifname to arp */
- struct strioctl strioc_if = {
- .ic_cmd = SIOCSLIFNAME,
- .ic_len = sizeof ifr,
- .ic_dp = (char *)&ifr,
- };
-
- if(ioctl(arp_fd, I_STR, &strioc_if) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not set ifname to %s %s", device_info, device);
- return false;
- }
- }
-
- int ip_muxid, arp_muxid;
-
- if((ip_muxid = ioctl(ip_fd, I_PLINK, if_fd)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not link %s %s to IP", device_info, device);
- return false;
- }
-
- if(device_type == DEVICE_TYPE_TAP) {
- if((arp_muxid = ioctl(ip_fd, I_PLINK, arp_fd)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not link %s %s to ARP", device_info, device);
- return false;
- }
- close(arp_fd);
- }
-
- struct lifreq ifr = {};
- strncpy(ifr.lifr_name, iface, sizeof(ifr.lifr_name));
- ifr.lifr_ip_muxid = ip_muxid;
- if(device_type == DEVICE_TYPE_TAP) {
- ifr.lifr_arp_muxid = arp_muxid;
- }
-
- if(ioctl(ip_fd, SIOCSLIFMUXID, &ifr) < 0) {
- if(device_type == DEVICE_TYPE_TAP) {
- ioctl(ip_fd, I_PUNLINK, arp_muxid);
- }
- ioctl(ip_fd, I_PUNLINK, ip_muxid);
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not set multiplexor id for %s %s", device_info, device);
- return false;
- }
-
- close(if_fd);
-
-#ifdef FD_CLOEXEC
- fcntl(device_fd, F_SETFD, FD_CLOEXEC);
- fcntl(ip_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
-
- return true;
-}
-
-static void close_device(void) {
- if(iface) {
- struct lifreq ifr = {};
- strncpy(ifr.lifr_name, iface, sizeof ifr.lifr_name);
- if(ioctl(ip_fd, SIOCGLIFMUXID, &ifr) >= 0) {
- int muxid = ifr.lifr_arp_muxid;
- ioctl(ip_fd, I_PUNLINK, muxid);
- muxid = ifr.lifr_ip_muxid;
- ioctl(ip_fd, I_PUNLINK, muxid);
- }
- }
-
- close(ip_fd);
- close(device_fd);
-
- free(device);
- free(iface);
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- int inlen;
-
- switch(device_type) {
- case DEVICE_TYPE_TUN:
- if((inlen = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
- return false;
- }
-
- switch(packet->data[14] >> 4) {
- case 4:
- packet->data[12] = 0x08;
- packet->data[13] = 0x00;
- break;
- case 6:
- packet->data[12] = 0x86;
- packet->data[13] = 0xDD;
- break;
- default:
- logger(DEBUG_TRAFFIC, LOG_ERR, "Unknown IP version %d while reading packet from %s %s", packet->data[14] >> 4, device_info, device);
- return false;
- }
-
- memset(packet->data, 0, 12);
- packet->len = inlen + 14;
- break;
-
- case DEVICE_TYPE_TAP:
- if((inlen = read(device_fd, packet->data, MTU)) <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
- return false;
- }
-
- packet->len = inlen + 14;
- break;
-
- default:
- abort();
- }
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, device_info);
-
- return true;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", packet->len, device_info);
-
- switch(device_type) {
- case DEVICE_TYPE_TUN:
- if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
- return false;
- }
- break;
-
- case DEVICE_TYPE_TAP:
- if(write(device_fd, packet->data, packet->len) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
- return false;
- }
- break;
-
- default:
- abort();
- }
-
- return true;
-}
-
-const devops_t os_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
+++ /dev/null
-/*
- subnet.c -- handle subnet lookups and lists
- Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
- 2000-2005 Ivo Timmermans
-
- 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 "splay_tree.h"
-#include "control_common.h"
-#include "device.h"
-#include "hash.h"
-#include "logger.h"
-#include "names.h"
-#include "net.h"
-#include "netutl.h"
-#include "node.h"
-#include "script.h"
-#include "subnet.h"
-#include "utils.h"
-#include "xalloc.h"
-
-/* lists type of subnet */
-
-splay_tree_t *subnet_tree;
-
-/* Subnet lookup cache */
-
-hash_t *ipv4_cache;
-hash_t *ipv6_cache;
-hash_t *mac_cache;
-
-void subnet_cache_flush(void) {
- hash_clear(ipv4_cache);
- hash_clear(ipv6_cache);
- hash_clear(mac_cache);
-}
-
-/* Initialising trees */
-
-void init_subnets(void) {
- subnet_tree = splay_alloc_tree((splay_compare_t) subnet_compare, (splay_action_t) free_subnet);
-
- ipv4_cache = hash_alloc(0x100, sizeof(ipv4_t));
- ipv6_cache = hash_alloc(0x100, sizeof(ipv6_t));
- mac_cache = hash_alloc(0x100, sizeof(mac_t));
-}
-
-void exit_subnets(void) {
- splay_delete_tree(subnet_tree);
-
- hash_free(ipv4_cache);
- hash_free(ipv6_cache);
- hash_free(mac_cache);
-}
-
-splay_tree_t *new_subnet_tree(void) {
- return splay_alloc_tree((splay_compare_t) subnet_compare, NULL);
-}
-
-void free_subnet_tree(splay_tree_t *subnet_tree) {
- splay_delete_tree(subnet_tree);
-}
-
-/* Allocating and freeing space for subnets */
-
-subnet_t *new_subnet(void) {
- return xzalloc(sizeof(subnet_t));
-}
-
-void free_subnet(subnet_t *subnet) {
- free(subnet);
-}
-
-/* Adding and removing subnets */
-
-void subnet_add(node_t *n, subnet_t *subnet) {
- subnet->owner = n;
-
- splay_insert(subnet_tree, subnet);
- splay_insert(n->subnet_tree, subnet);
-
- subnet_cache_flush();
-}
-
-void subnet_del(node_t *n, subnet_t *subnet) {
- splay_delete(n->subnet_tree, subnet);
- splay_delete(subnet_tree, subnet);
-
- subnet_cache_flush();
-}
-
-/* Subnet lookup routines */
-
-subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) {
- return splay_search(owner->subnet_tree, subnet);
-}
-
-subnet_t *lookup_subnet_mac(const node_t *owner, const mac_t *address) {
- subnet_t *r = NULL;
-
- // Check if this address is cached
-
- if((r = hash_search(mac_cache, address)))
- return r;
-
- // Search all subnets for a matching one
-
- for splay_each(subnet_t, p, owner ? owner->subnet_tree : subnet_tree) {
- if(!p || p->type != SUBNET_MAC)
- continue;
-
- if(!memcmp(address, &p->net.mac.address, sizeof *address)) {
- r = p;
- if(p->owner->status.reachable)
- break;
- }
- }
-
- // Cache the result
-
- if(r)
- hash_insert(mac_cache, address, r);
-
- return r;
-}
-
-subnet_t *lookup_subnet_ipv4(const ipv4_t *address) {
- subnet_t *r = NULL;
-
- // Check if this address is cached
-
- if((r = hash_search(ipv4_cache, address)))
- return r;
-
- // Search all subnets for a matching one
-
- for splay_each(subnet_t, p, subnet_tree) {
- if(!p || p->type != SUBNET_IPV4)
- continue;
-
- if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) {
- r = p;
- if(p->owner->status.reachable)
- break;
- }
- }
-
- // Cache the result
-
- if(r)
- hash_insert(ipv4_cache, address, r);
-
- return r;
-}
-
-subnet_t *lookup_subnet_ipv6(const ipv6_t *address) {
- subnet_t *r = NULL;
-
- // Check if this address is cached
-
- if((r = hash_search(ipv6_cache, address)))
- return r;
-
- // Search all subnets for a matching one
-
- for splay_each(subnet_t, p, subnet_tree) {
- if(!p || p->type != SUBNET_IPV6)
- continue;
-
- if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) {
- r = p;
- if(p->owner->status.reachable)
- break;
- }
- }
-
- // Cache the result
-
- if(r)
- hash_insert(ipv6_cache, address, r);
-
- return r;
-}
-
-void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
- char netstr[MAXNETSTR];
- char *name, *address, *port;
- char empty[] = "";
-
- // Prepare environment variables to be passed to the script
-
- char *envp[10] = {NULL};
- xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
- xasprintf(&envp[1], "DEVICE=%s", device ? : "");
- xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
- xasprintf(&envp[3], "NODE=%s", owner->name);
-
- if(owner != myself) {
- sockaddr2str(&owner->address, &address, &port);
- // 4 and 5 are reserved for SUBNET and WEIGHT
- xasprintf(&envp[6], "REMOTEADDRESS=%s", address);
- xasprintf(&envp[7], "REMOTEPORT=%s", port);
- free(port);
- free(address);
- }
-
- xasprintf(&envp[8], "NAME=%s", myself->name);
-
- name = up ? "subnet-up" : "subnet-down";
-
- if(!subnet) {
- for splay_each(subnet_t, subnet, owner->subnet_tree) {
- if(!net2str(netstr, sizeof netstr, subnet))
- continue;
-
- // Strip the weight from the subnet, and put it in its own environment variable
- char *weight = strchr(netstr, '#');
- if(weight)
- *weight++ = 0;
- else
- weight = empty;
-
- // Prepare the SUBNET and WEIGHT variables
- if(envp[4])
- free(envp[4]);
- if(envp[5])
- free(envp[5]);
- xasprintf(&envp[4], "SUBNET=%s", netstr);
- xasprintf(&envp[5], "WEIGHT=%s", weight);
-
- execute_script(name, envp);
- }
- } else {
- if(net2str(netstr, sizeof netstr, subnet)) {
- // Strip the weight from the subnet, and put it in its own environment variable
- char *weight = strchr(netstr, '#');
- if(weight)
- *weight++ = 0;
- else
- weight = empty;
-
- // Prepare the SUBNET and WEIGHT variables
- xasprintf(&envp[4], "SUBNET=%s", netstr);
- xasprintf(&envp[5], "WEIGHT=%s", weight);
-
- execute_script(name, envp);
- }
- }
-
- for(int i = 0; envp[i] && i < 9; i++)
- free(envp[i]);
-}
-
-bool dump_subnets(connection_t *c) {
- for splay_each(subnet_t, subnet, subnet_tree) {
- char netstr[MAXNETSTR];
-
- if(!net2str(netstr, sizeof netstr, subnet))
- continue;
-
- send_request(c, "%d %d %s %s",
- CONTROL, REQ_DUMP_SUBNETS,
- netstr, subnet->owner->name);
- }
-
- return send_request(c, "%d %d", CONTROL, REQ_DUMP_SUBNETS);
-}
+++ /dev/null
-/*
- subnet.h -- header for subnet.c
- Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
- 2000-2005 Ivo Timmermans
-
- 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.
-*/
-
-#ifndef __TINC_SUBNET_H__
-#define __TINC_SUBNET_H__
-
-#include "net.h"
-
-typedef enum subnet_type_t {
- SUBNET_MAC = 0,
- SUBNET_IPV4,
- SUBNET_IPV6,
- SUBNET_TYPES /* Guardian */
-} subnet_type_t;
-
-typedef struct subnet_mac_t {
- mac_t address;
-} subnet_mac_t;
-
-typedef struct subnet_ipv4_t {
- ipv4_t address;
- int prefixlength;
-} subnet_ipv4_t;
-
-typedef struct subnet_ipv6_t {
- ipv6_t address;
- int prefixlength;
-} subnet_ipv6_t;
-
-#include "node.h"
-
-typedef struct subnet_t {
- struct node_t *owner; /* the owner of this subnet */
-
- subnet_type_t type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */
- time_t expires; /* expiry time */
- int weight; /* weight (higher value is higher priority) */
-
- /* And now for the actual subnet: */
-
- union net {
- subnet_mac_t mac;
- subnet_ipv4_t ipv4;
- subnet_ipv6_t ipv6;
- } net;
-} subnet_t;
-
-#define MAXNETSTR 64
-
-extern splay_tree_t *subnet_tree;
-
-extern int subnet_compare(const struct subnet_t *, const struct subnet_t *);
-extern subnet_t *new_subnet(void) __attribute__ ((__malloc__));
-extern void free_subnet(subnet_t *);
-extern void init_subnets(void);
-extern void exit_subnets(void);
-extern splay_tree_t *new_subnet_tree(void) __attribute__ ((__malloc__));
-extern void free_subnet_tree(splay_tree_t *);
-extern void subnet_add(struct node_t *, subnet_t *);
-extern void subnet_del(struct node_t *, subnet_t *);
-extern void subnet_update(struct node_t *, subnet_t *, bool);
-extern int maskcmp(const void *, const void *, int);
-extern void maskcpy(void *, const void *, int, int);
-extern void mask(void *, int, int);
-extern bool maskcheck(const void *, int, int);
-extern bool net2str(char *, int, const subnet_t *);
-extern bool str2net(subnet_t *, const char *);
-extern subnet_t *lookup_subnet(const struct node_t *, const subnet_t *);
-extern subnet_t *lookup_subnet_mac(const struct node_t *, const mac_t *);
-extern subnet_t *lookup_subnet_ipv4(const ipv4_t *);
-extern subnet_t *lookup_subnet_ipv6(const ipv6_t *);
-extern bool dump_subnets(struct connection_t *);
-extern void subnet_cache_flush(void);
-
-#endif /* __TINC_SUBNET_H__ */
+++ /dev/null
-/*
- subnet_parse.c -- handle subnet parsing
- Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
- 2000-2005 Ivo Timmermans
-
- 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 "logger.h"
-#include "net.h"
-#include "netutl.h"
-#include "subnet.h"
-#include "utils.h"
-#include "xalloc.h"
-
-/* Subnet mask handling */
-
-int maskcmp(const void *va, const void *vb, int masklen) {
- int i, m, result;
- const char *a = va;
- const char *b = vb;
-
- for(m = masklen, i = 0; m >= 8; m -= 8, i++) {
- result = a[i] - b[i];
- if(result)
- return result;
- }
-
- if(m)
- return (a[i] & (0x100 - (1 << (8 - m)))) -
- (b[i] & (0x100 - (1 << (8 - m))));
-
- return 0;
-}
-
-void mask(void *va, int masklen, int len) {
- int i;
- char *a = va;
-
- i = masklen / 8;
- masklen %= 8;
-
- if(masklen)
- a[i++] &= (0x100 - (1 << (8 - masklen)));
-
- for(; i < len; i++)
- a[i] = 0;
-}
-
-void maskcpy(void *va, const void *vb, int masklen, int len) {
- int i, m;
- char *a = va;
- const char *b = vb;
-
- for(m = masklen, i = 0; m >= 8; m -= 8, i++)
- a[i] = b[i];
-
- if(m) {
- a[i] = b[i] & (0x100 - (1 << (8 - m)));
- i++;
- }
-
- for(; i < len; i++)
- a[i] = 0;
-}
-
-bool maskcheck(const void *va, int masklen, int len) {
- int i;
- const char *a = va;
-
- i = masklen / 8;
- masklen %= 8;
-
- if(masklen && a[i++] & (0xff >> masklen))
- return false;
-
- for(; i < len; i++)
- if(a[i] != 0)
- return false;
-
- return true;
-}
-
-/* Subnet comparison */
-
-static int subnet_compare_mac(const subnet_t *a, const subnet_t *b) {
- int result;
-
- result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof a->net.mac.address);
-
- if(result)
- return result;
-
- result = a->weight - b->weight;
-
- if(result || !a->owner || !b->owner)
- return result;
-
- return strcmp(a->owner->name, b->owner->name);
-}
-
-static int subnet_compare_ipv4(const subnet_t *a, const subnet_t *b) {
- int result;
-
- result = b->net.ipv4.prefixlength - a->net.ipv4.prefixlength;
-
- if(result)
- return result;
-
- result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
-
- if(result)
- return result;
-
- result = a->weight - b->weight;
-
- if(result || !a->owner || !b->owner)
- return result;
-
- return strcmp(a->owner->name, b->owner->name);
-}
-
-static int subnet_compare_ipv6(const subnet_t *a, const subnet_t *b) {
- int result;
-
- result = b->net.ipv6.prefixlength - a->net.ipv6.prefixlength;
-
- if(result)
- return result;
-
- result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
-
- if(result)
- return result;
-
- result = a->weight - b->weight;
-
- if(result || !a->owner || !b->owner)
- return result;
-
- return strcmp(a->owner->name, b->owner->name);
-}
-
-int subnet_compare(const subnet_t *a, const subnet_t *b) {
- int result;
-
- result = a->type - b->type;
-
- if(result)
- return result;
-
- switch (a->type) {
- case SUBNET_MAC:
- return subnet_compare_mac(a, b);
- case SUBNET_IPV4:
- return subnet_compare_ipv4(a, b);
- case SUBNET_IPV6:
- return subnet_compare_ipv6(a, b);
- default:
- logger(DEBUG_ALWAYS, LOG_ERR, "subnet_compare() was called with unknown subnet type %d, exitting!", a->type);
- exit(1);
- }
-
- return 0;
-}
-
-/* Ascii representation of subnets */
-
-bool str2net(subnet_t *subnet, const char *subnetstr) {
- int i, l;
- uint16_t x[8];
- int weight = 10;
-
- if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d#%d",
- &x[0], &x[1], &x[2], &x[3], &l, &weight) >= 5) {
- if(l < 0 || l > 32)
- return false;
-
- subnet->type = SUBNET_IPV4;
- subnet->net.ipv4.prefixlength = l;
- subnet->weight = weight;
-
- for(int i = 0; i < 4; i++) {
- if(x[i] > 255)
- return false;
- subnet->net.ipv4.address.x[i] = x[i];
- }
-
- return true;
- }
-
- if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d#%d",
- &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
- &l, &weight) >= 9) {
- if(l < 0 || l > 128)
- return false;
-
- subnet->type = SUBNET_IPV6;
- subnet->net.ipv6.prefixlength = l;
- subnet->weight = weight;
-
- for(i = 0; i < 8; i++)
- subnet->net.ipv6.address.x[i] = htons(x[i]);
-
- return true;
- }
-
- if(sscanf(subnetstr, "%hu.%hu.%hu.%hu#%d", &x[0], &x[1], &x[2], &x[3], &weight) >= 4) {
- subnet->type = SUBNET_IPV4;
- subnet->net.ipv4.prefixlength = 32;
- subnet->weight = weight;
-
- for(i = 0; i < 4; i++) {
- if(x[i] > 255)
- return false;
- subnet->net.ipv4.address.x[i] = x[i];
- }
-
- return true;
- }
-
- if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx#%d",
- &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], &weight) >= 8) {
- subnet->type = SUBNET_IPV6;
- subnet->net.ipv6.prefixlength = 128;
- subnet->weight = weight;
-
- for(i = 0; i < 8; i++)
- subnet->net.ipv6.address.x[i] = htons(x[i]);
-
- return true;
- }
-
- if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx#%d",
- &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &weight) >= 6) {
- subnet->type = SUBNET_MAC;
- subnet->weight = weight;
-
- for(i = 0; i < 6; i++)
- subnet->net.mac.address.x[i] = x[i];
-
- return true;
- }
-
- // IPv6 short form
- if(strstr(subnetstr, "::")) {
- const char *p;
- char *q;
- int colons = 0;
-
- // Count number of colons
- for(p = subnetstr; *p; p++)
- if(*p == ':')
- colons++;
-
- if(colons > 7)
- return false;
-
- // Scan numbers before the double colon
- p = subnetstr;
- for(i = 0; i < colons; i++) {
- if(*p == ':')
- break;
- x[i] = strtoul(p, &q, 0x10);
- if(!q || p == q || *q != ':')
- return false;
- p = ++q;
- }
-
- p++;
- colons -= i;
- if(!i) {
- p++;
- colons--;
- }
-
- if(!*p || *p == '/' || *p == '#')
- colons--;
-
- // Fill in the blanks
- for(; i < 8 - colons; i++)
- x[i] = 0;
-
- // Scan the remaining numbers
- for(; i < 8; i++) {
- x[i] = strtoul(p, &q, 0x10);
- if(!q || p == q)
- return false;
- if(i == 7) {
- p = q;
- break;
- }
- if(*q != ':')
- return false;
- p = ++q;
- }
-
- l = 128;
- if(*p == '/')
- sscanf(p, "/%d#%d", &l, &weight);
- else if(*p == '#')
- sscanf(p, "#%d", &weight);
-
- if(l < 0 || l > 128)
- return false;
-
- subnet->type = SUBNET_IPV6;
- subnet->net.ipv6.prefixlength = l;
- subnet->weight = weight;
-
- for(i = 0; i < 8; i++)
- subnet->net.ipv6.address.x[i] = htons(x[i]);
-
- return true;
- }
-
- return false;
-}
-
-bool net2str(char *netstr, int len, const subnet_t *subnet) {
- if(!netstr || !subnet) {
- logger(DEBUG_ALWAYS, LOG_ERR, "net2str() was called with netstr=%p, subnet=%p!", netstr, subnet);
- return false;
- }
-
- switch (subnet->type) {
- case SUBNET_MAC:
- snprintf(netstr, len, "%hx:%hx:%hx:%hx:%hx:%hx#%d",
- subnet->net.mac.address.x[0],
- subnet->net.mac.address.x[1],
- subnet->net.mac.address.x[2],
- subnet->net.mac.address.x[3],
- subnet->net.mac.address.x[4],
- subnet->net.mac.address.x[5],
- subnet->weight);
- break;
-
- case SUBNET_IPV4:
- snprintf(netstr, len, "%hu.%hu.%hu.%hu/%d#%d",
- subnet->net.ipv4.address.x[0],
- subnet->net.ipv4.address.x[1],
- subnet->net.ipv4.address.x[2],
- subnet->net.ipv4.address.x[3],
- subnet->net.ipv4.prefixlength,
- subnet->weight);
- break;
-
- case SUBNET_IPV6:
- snprintf(netstr, len, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d#%d",
- ntohs(subnet->net.ipv6.address.x[0]),
- ntohs(subnet->net.ipv6.address.x[1]),
- ntohs(subnet->net.ipv6.address.x[2]),
- ntohs(subnet->net.ipv6.address.x[3]),
- ntohs(subnet->net.ipv6.address.x[4]),
- ntohs(subnet->net.ipv6.address.x[5]),
- ntohs(subnet->net.ipv6.address.x[6]),
- ntohs(subnet->net.ipv6.address.x[7]),
- subnet->net.ipv6.prefixlength,
- subnet->weight);
- break;
-
- default:
- logger(DEBUG_ALWAYS, LOG_ERR, "net2str() was called with unknown subnet type %d, exiting!", subnet->type);
- exit(1);
- }
-
- return true;
-}
#include "ecdsagen.h"
#include "info.h"
#include "invitation.h"
-#include "names.h"
#include "rsagen.h"
#include "utils.h"
#include "tincctl.h"
free(netname);
netname = strcmp(name, ".") ? xstrdup(name) : NULL;
- make_names();
xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
xasprintf(&prompt, "%s> ", identname);
if(!parse_options(argc, argv))
return 1;
- make_names();
xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);
#include <getopt.h>
#include "conf.h"
-#include "control.h"
#include "crypto.h"
-#include "device.h"
#include "logger.h"
-#include "names.h"
#include "net.h"
#include "netutl.h"
-#include "process.h"
#include "protocol.h"
#include "utils.h"
#include "xalloc.h"
static const char *switchuser = NULL;
#endif
-/* If nonzero, write log entries to a separate file. */
-bool use_logfile = false;
-
char **g_argv; /* a copy of the cmdline arguments */
static int status = 1;
{"mlock", no_argument, NULL, 'L'},
{"chroot", no_argument, NULL, 'R'},
{"user", required_argument, NULL, 'U'},
- {"logfile", optional_argument, NULL, 4},
- {"pidfile", required_argument, NULL, 5},
{"option", required_argument, NULL, 'o'},
{NULL, 0, NULL, 0}
};
static void usage(bool status) {
if(status)
- fprintf(stderr, "Try `%s --help\' for more information.\n",
- program_name);
+ fprintf(stderr, "Try `tincd --help\' for more information.\n");
else {
- printf("Usage: %s [option]...\n\n", program_name);
+ printf("Usage: tincd [option]...\n\n");
printf( " -c, --config=DIR Read configuration options from DIR.\n"
" -D, --no-detach Don't fork and detach.\n"
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
#ifdef HAVE_MLOCKALL
" -L, --mlock Lock tinc into main memory.\n"
#endif
- " --logfile[=FILENAME] Write log entries to a logfile.\n"
- " --pidfile=FILENAME Write PID and control socket cookie to FILENAME.\n"
" --bypass-security Disables meta protocol security, for debugging.\n"
" -o, --option[HOST.]KEY=VALUE Set global/host configuration value.\n"
#ifndef HAVE_MINGW
confbase = xstrdup(optarg);
break;
- case 'D': /* no detach */
- do_detach = false;
- break;
-
case 'L': /* no detach */
#ifndef HAVE_MLOCKALL
logger(DEBUG_ALWAYS, LOG_ERR, "The %s option is not supported on this platform.", argv[optind - 1]);
debug_level++;
break;
- case 'n': /* net name given */
- netname = xstrdup(optarg);
- break;
-
case 'o': /* option */
cfg = parse_config_line(optarg, NULL, ++lineno);
if (!cfg)
bypass_security = true;
break;
- case 4: /* write log entries to a file */
- use_logfile = true;
- if(!optarg && optind < argc && *argv[optind] != '-')
- optarg = argv[optind++];
- if(optarg)
- logfilename = xstrdup(optarg);
- break;
-
- case 5: /* open control socket here */
- pidfilename = xstrdup(optarg);
- break;
-
case '?': /* wrong options */
usage(true);
return false;
return false;
}
- if(!netname && (netname = getenv("NETNAME")))
- netname = xstrdup(netname);
-
- /* netname "." is special: a "top-level name" */
-
- if(netname && (!*netname || !strcmp(netname, "."))) {
- free(netname);
- netname = NULL;
- }
-
- if(netname && (strpbrk(netname, "\\/") || *netname == '.')) {
- fprintf(stderr, "Invalid character in netname!\n");
- return false;
- }
-
return true;
}
#endif
int main(int argc, char **argv) {
- program_name = argv[0];
-
if(!parse_options(argc, argv))
return 1;
- make_names();
-
if(show_version) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
VERSION, __DATE__, __TIME__, PROT_MAJOR, PROT_MINOR);
}
#endif
- openlogger("tinc", use_logfile?LOGMODE_FILE:LOGMODE_STDERR);
+ openlogger("tinc", LOGMODE_STDERR);
g_argv = argv;
- if(getenv("LISTEN_PID") && atoi(getenv("LISTEN_PID")) == getpid())
- do_detach = false;
-#ifdef HAVE_UNSETENV
- unsetenv("LISTEN_PID");
-#endif
-
init_configuration(&config_tree);
/* Slllluuuuuuurrrrp! */
}
#endif
-#ifdef HAVE_MINGW
- if(!do_detach || !init_service())
- return main2(argc, argv);
- else
- return 1;
-}
-
-int main2(int argc, char **argv) {
- InitializeCriticalSection(&mutex);
- EnterCriticalSection(&mutex);
-#endif
char *priority = NULL;
- if(!detach())
- return 1;
-
#ifdef HAVE_MLOCKALL
/* Lock all pages into memory if requested.
* This has to be done after daemon()/fork() so it works for child.
}
#endif
- /* Setup sockets and open device. */
+ /* Setup sockets. */
if(!setup_network())
goto end;
exit_configuration(&config_tree);
free(cmdline_conf);
- free_names();
return status;
}
+++ /dev/null
-/*
- top.c -- Show real-time statistics from a running tincd
- Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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"
-
-#ifdef HAVE_CURSES
-
-#include <curses.h>
-
-#include "control_common.h"
-#include "list.h"
-#include "names.h"
-#include "tincctl.h"
-#include "top.h"
-#include "xalloc.h"
-
-typedef struct nodestats_t {
- char *name;
- int i;
- uint64_t in_packets;
- uint64_t in_bytes;
- uint64_t out_packets;
- uint64_t out_bytes;
- float in_packets_rate;
- float in_bytes_rate;
- float out_packets_rate;
- float out_bytes_rate;
- bool known;
-} nodestats_t;
-
-static const char *const sortname[] = {
- "name",
- "in pkts",
- "in bytes",
- "out pkts",
- "out bytes",
- "tot pkts",
- "tot bytes",
-};
-
-static int sortmode = 0;
-static bool cumulative = false;
-
-static list_t node_list;
-static struct timeval cur, prev, diff;
-static int delay = 1000;
-static bool changed = true;
-static const char *bunit = "bytes";
-static float bscale = 1;
-static const char *punit = "pkts";
-static float pscale = 1;
-
-static bool update(int fd) {
- if(!sendline(fd, "%d %d", CONTROL, REQ_DUMP_TRAFFIC))
- return false;
-
- gettimeofday(&cur, NULL);
-
- timersub(&cur, &prev, &diff);
- prev = cur;
- float interval = diff.tv_sec + diff.tv_usec * 1e-6;
-
- char line[4096];
- char name[4096];
- int code;
- int req;
- uint64_t in_packets;
- uint64_t in_bytes;
- uint64_t out_packets;
- uint64_t out_bytes;
-
- for list_each(nodestats_t, ns, &node_list)
- ns->known = false;
-
- while(recvline(fd, line, sizeof line)) {
- int n = sscanf(line, "%d %d %s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, &code, &req, name, &in_packets, &in_bytes, &out_packets, &out_bytes);
-
- if(n == 2)
- return true;
-
- if(n != 7)
- return false;
-
- nodestats_t *found = NULL;
-
- for list_each(nodestats_t, ns, &node_list) {
- int result = strcmp(name, ns->name);
- if(result > 0) {
- continue;
- } if(result == 0) {
- found = ns;
- break;
- } else {
- found = xzalloc(sizeof *found);
- found->name = xstrdup(name);
- list_insert_before(&node_list, node, found);
- changed = true;
- break;
- }
- }
-
- if(!found) {
- found = xzalloc(sizeof *found);
- found->name = xstrdup(name);
- list_insert_tail(&node_list, found);
- changed = true;
- }
-
- found->known = true;
- found->in_packets_rate = (in_packets - found->in_packets) / interval;
- found->in_bytes_rate = (in_bytes - found->in_bytes) / interval;
- found->out_packets_rate = (out_packets - found->out_packets) / interval;
- found->out_bytes_rate = (out_bytes - found->out_bytes) / interval;
- found->in_packets = in_packets;
- found->in_bytes = in_bytes;
- found->out_packets = out_packets;
- found->out_bytes = out_bytes;
- }
-
- return false;
-}
-
-static int cmpfloat(float a, float b) {
- if(a < b)
- return -1;
- else if(a > b)
- return 1;
- else
- return 0;
-}
-
-static int cmpu64(uint64_t a, uint64_t b) {
- if(a < b)
- return -1;
- else if(a > b)
- return 1;
- else
- return 0;
-}
-
-static int sortfunc(const void *a, const void *b) {
- const nodestats_t *na = *(const nodestats_t **)a;
- const nodestats_t *nb = *(const nodestats_t **)b;
- switch(sortmode) {
- case 1:
- if(cumulative)
- return -cmpu64(na->in_packets, nb->in_packets) ?: na->i - nb->i;
- else
- return -cmpfloat(na->in_packets_rate, nb->in_packets_rate) ?: na->i - nb->i;
- case 2:
- if(cumulative)
- return -cmpu64(na->in_bytes, nb->in_bytes) ?: na->i - nb->i;
- else
- return -cmpfloat(na->in_bytes_rate, nb->in_bytes_rate) ?: na->i - nb->i;
- case 3:
- if(cumulative)
- return -cmpu64(na->out_packets, nb->out_packets) ?: na->i - nb->i;
- else
- return -cmpfloat(na->out_packets_rate, nb->out_packets_rate) ?: na->i - nb->i;
- case 4:
- if(cumulative)
- return -cmpu64(na->out_bytes, nb->out_bytes) ?: na->i - nb->i;
- else
- return -cmpfloat(na->out_bytes_rate, nb->out_bytes_rate) ?: na->i - nb->i;
- case 5:
- if(cumulative)
- return -cmpu64(na->in_packets + na->out_packets, nb->in_packets + nb->out_packets) ?: na->i - nb->i;
- else
- return -cmpfloat(na->in_packets_rate + na->out_packets_rate, nb->in_packets_rate + nb->out_packets_rate) ?: na->i - nb->i;
- case 6:
- if(cumulative)
- return -cmpu64(na->in_bytes + na->out_bytes, nb->in_bytes + nb->out_bytes) ?: na->i - nb->i;
- else
- return -cmpfloat(na->in_bytes_rate + na->out_bytes_rate, nb->in_bytes_rate + nb->out_bytes_rate) ?: na->i - nb->i;
- default:
- return strcmp(na->name, nb->name) ?: na->i - nb->i;
- }
-}
-
-static void redraw(void) {
- erase();
-
- mvprintw(0, 0, "Tinc %-16s Nodes: %4d Sort: %-10s %s", netname ?: "", node_list.count, sortname[sortmode], cumulative ? "Cumulative" : "Current");
- attrset(A_REVERSE);
- mvprintw(2, 0, "Node IN %s IN %s OUT %s OUT %s", punit, bunit, punit, bunit);
- chgat(-1, A_REVERSE, 0, NULL);
-
- static nodestats_t **sorted = 0;
- static int n = 0;
- if(changed) {
- n = 0;
- sorted = xrealloc(sorted, node_list.count * sizeof *sorted);
- for list_each(nodestats_t, ns, &node_list)
- sorted[n++] = ns;
- changed = false;
- }
-
- for(int i = 0; i < n; i++)
- sorted[i]->i = i;
-
- if(sorted)
- qsort(sorted, n, sizeof *sorted, sortfunc);
-
- for(int i = 0, row = 3; i < n; i++, row++) {
- nodestats_t *node = sorted[i];
- if(node->known)
- if(node->in_packets_rate || node->out_packets_rate)
- attrset(A_BOLD);
- else
- attrset(A_NORMAL);
- else
- attrset(A_DIM);
-
- if(cumulative)
- mvprintw(row, 0, "%-16s %10.0f %10.0f %10.0f %10.0f",
- node->name, node->in_packets * pscale, node->in_bytes * bscale, node->out_packets * pscale, node->out_bytes * bscale);
- else
- mvprintw(row, 0, "%-16s %10.0f %10.0f %10.0f %10.0f",
- node->name, node->in_packets_rate * pscale, node->in_bytes_rate * bscale, node->out_packets_rate * pscale, node->out_bytes_rate * bscale);
- }
-
- attrset(A_NORMAL);
- move(1, 0);
-
- refresh();
-}
-
-void top(int fd) {
- initscr();
- timeout(delay);
- bool running = true;
-
- while(running) {
- if(!update(fd))
- break;
-
- redraw();
-
- switch(getch()) {
- case 's': {
- timeout(-1);
- float input = delay * 1e-3;
- mvprintw(1, 0, "Change delay from %.1fs to: ", input);
- scanw("%f", &input);
- if(input < 0.1)
- input = 0.1;
- delay = input * 1e3;
- timeout(delay);
- break;
- }
- case 'c':
- cumulative = !cumulative;
- break;
- case 'n':
- sortmode = 0;
- break;
- case 'i':
- sortmode = 2;
- break;
- case 'I':
- sortmode = 1;
- break;
- case 'o':
- sortmode = 4;
- break;
- case 'O':
- sortmode = 3;
- break;
- case 't':
- sortmode = 6;
- break;
- case 'T':
- sortmode = 5;
- break;
- case 'b':
- bunit = "bytes";
- bscale = 1;
- punit = "pkts";
- pscale = 1;
- break;
- case 'k':
- bunit = "kbyte";
- bscale = 1e-3;
- punit = "pkts";
- pscale = 1;
- break;
- case 'M':
- bunit = "Mbyte";
- bscale = 1e-6;
- punit = "kpkt";
- pscale = 1e-3;
- break;
- case 'G':
- bunit = "Gbyte";
- bscale = 1e-9;
- punit = "Mpkt";
- pscale = 1e-6;
- break;
- case 'q':
- case KEY_BREAK:
- running = false;
- break;
- default:
- break;
- }
- }
-
- endwin();
-}
-
-#endif
+++ /dev/null
-/*
- top.h -- header for top.c.
- Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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.
-*/
-
-#ifndef __TINC_TOP_H__
-#define __TINC_TOP_H__
-
-extern void top(int fd);
-
-#endif
-
+++ /dev/null
-/*
- device.c -- UML network socket
- Copyright (C) 2002-2005 Ivo Timmermans,
- 2002-2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <sys/un.h>
-
-#include "conf.h"
-#include "device.h"
-#include "names.h"
-#include "net.h"
-#include "logger.h"
-#include "utils.h"
-#include "route.h"
-#include "xalloc.h"
-
-static int listen_fd = -1;
-static int request_fd = -1;
-static int data_fd = -1;
-static int write_fd = -1;
-static int state = 0;
-static char *device_info;
-
-enum request_type { REQ_NEW_CONTROL };
-
-static struct request {
- uint32_t magic;
- uint32_t version;
- enum request_type type;
- struct sockaddr_un sock;
-} request;
-
-static struct sockaddr_un data_sun;
-
-static bool setup_device(void) {
- struct sockaddr_un listen_sun;
- static const int one = 1;
- struct {
- char zero;
- int pid;
- int usecs;
- } name;
- struct timeval tv;
-
- if(!get_config_string(lookup_config(config_tree, "Device"), &device))
- xasprintf(&device, LOCALSTATEDIR "/run/%s.umlsocket", identname);
-
- get_config_string(lookup_config(config_tree, "Interface"), &iface);
-
- device_info = "UML network socket";
-
- if((write_fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open write %s: %s", device_info, strerror(errno));
- event_exit();
- return false;
- }
-
-#ifdef FD_CLOEXEC
- fcntl(write_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- setsockopt(write_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
-
- if(fcntl(write_fd, F_SETFL, O_NONBLOCK) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno));
- event_exit();
- return false;
- }
-
- if((data_fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open data %s: %s", device_info, strerror(errno));
- event_exit();
- return false;
- }
-
-#ifdef FD_CLOEXEC
- fcntl(data_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- setsockopt(data_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
-
- if(fcntl(data_fd, F_SETFL, O_NONBLOCK) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno));
- event_exit();
- return false;
- }
-
- name.zero = 0;
- name.pid = getpid();
- gettimeofday(&tv, NULL);
- name.usecs = tv.tv_usec;
- data_sun.sun_family = AF_UNIX;
- memcpy(&data_sun.sun_path, &name, sizeof name);
-
- if(bind(data_fd, (struct sockaddr *)&data_sun, sizeof data_sun) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind data %s: %s", device_info, strerror(errno));
- event_exit();
- return false;
- }
-
- if((listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device_info,
- strerror(errno));
- return false;
- }
-
-#ifdef FD_CLOEXEC
- fcntl(device_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
-
- if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno));
- return false;
- }
-
- listen_sun.sun_family = AF_UNIX;
- strncpy(listen_sun.sun_path, device, sizeof listen_sun.sun_path);
- if(bind(listen_fd, (struct sockaddr *)&listen_sun, sizeof listen_sun) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind %s to %s: %s", device_info, device, strerror(errno));
- return false;
- }
-
- if(listen(listen_fd, 1) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not listen on %s %s: %s", device_info, device, strerror(errno));
- return false;
- }
-
- device_fd = listen_fd;
- state = 0;
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
-
- if(routing_mode == RMODE_ROUTER)
- overwrite_mac = true;
-
- return true;
-}
-
-void close_device(void) {
- if(listen_fd >= 0)
- close(listen_fd);
-
- if(request_fd >= 0)
- close(request_fd);
-
- if(data_fd >= 0)
- close(data_fd);
-
- if(write_fd >= 0)
- close(write_fd);
-
- unlink(device);
-
- free(device);
- if(iface) free(iface);
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- int inlen;
-
- switch(state) {
- case 0: {
- struct sockaddr sa;
- socklen_t salen = sizeof sa;
-
- request_fd = accept(listen_fd, &sa, &salen);
- if(request_fd < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not accept connection to %s %s: %s", device_info, device, strerror(errno));
- return false;
- }
-
-#ifdef FD_CLOEXEC
- fcntl(request_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno));
- event_exit();
- return false;
- }
-
- close(listen_fd);
- listen_fd = -1;
- device_fd = request_fd;
- state = 1;
-
- return false;
- }
-
- case 1: {
- if((inlen = read(request_fd, &request, sizeof request)) != sizeof request) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading request from %s %s: %s", device_info,
- device, strerror(errno));
- event_exit();
- return false;
- }
-
- if(request.magic != 0xfeedface || request.version != 3 || request.type != REQ_NEW_CONTROL) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unknown magic %x, version %d, request type %d from %s %s",
- request.magic, request.version, request.type, device_info, device);
- event_exit();
- return false;
- }
-
- if(connect(write_fd, &request.sock, sizeof request.sock) < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind write %s: %s", device_info, strerror(errno));
- event_exit();
- return false;
- }
-
- write(request_fd, &data_sun, sizeof data_sun);
- device_fd = data_fd;
-
- logger(DEBUG_ALWAYS, LOG_INFO, "Connection with UML established");
-
- state = 2;
- return false;
- }
-
- case 2: {
- if((inlen = read(data_fd, packet->data, MTU)) <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
- device, strerror(errno));
- event_exit();
- return false;
- }
-
- packet->len = inlen;
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len,
- device_info);
-
- return true;
- }
-
- default:
- logger(DEBUG_ALWAYS, LOG_ERR, "Invalid value for state variable in " __FILE__);
- abort();
- }
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- if(state != 2) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Dropping packet of %d bytes to %s: not connected to UML yet",
- packet->len, device_info);
- return false;
- }
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s",
- packet->len, device_info);
-
- if(write(write_fd, packet->data, packet->len) < 0) {
- if(errno != EINTR && errno != EAGAIN) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
- event_exit();
- }
-
- return false;
- }
-
- return true;
-}
-
-const devops_t uml_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};
+++ /dev/null
-/*
- device.c -- VDE plug
- Copyright (C) 2013 Guus Sliepen <guus@tinc-vpn.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- 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 <libvdeplug_dyn.h>
-
-#include "conf.h"
-#include "device.h"
-#include "names.h"
-#include "net.h"
-#include "logger.h"
-#include "utils.h"
-#include "route.h"
-#include "xalloc.h"
-
-static struct vdepluglib plug;
-static struct vdeconn *conn = NULL;
-static int port = 0;
-static char *group = NULL;
-static char *device_info;
-
-static bool setup_device(void) {
- libvdeplug_dynopen(plug);
-
- if(!plug.dl_handle) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open libvdeplug library!");
- return false;
- }
-
- if(!get_config_string(lookup_config(config_tree, "Device"), &device))
- xasprintf(&device, LOCALSTATEDIR "/run/vde.ctl");
-
- get_config_string(lookup_config(config_tree, "Interface"), &iface);
-
- get_config_int(lookup_config(config_tree, "VDEPort"), &port);
-
- get_config_string(lookup_config(config_tree, "VDEGroup"), &group);
-
- device_info = "VDE socket";
-
- struct vde_open_args args = {
- .port = port,
- .group = group,
- .mode = 0700,
- };
-
- conn = plug.vde_open(device, identname, &args);
- if(!conn) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Could not open VDE socket %s", device);
- return false;
- }
-
- device_fd = plug.vde_datafd(conn);
-
-#ifdef FD_CLOEXEC
- fcntl(device_fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);
-
- if(routing_mode == RMODE_ROUTER)
- overwrite_mac = true;
-
- return true;
-}
-
-static void close_device(void) {
- if(conn)
- plug.vde_close(conn);
-
- if(plug.dl_handle)
- libvdeplug_dynclose(plug);
-
- free(device);
-
- free(iface);
-}
-
-static bool read_packet(vpn_packet_t *packet) {
- int lenin = (ssize_t)plug.vde_recv(conn, packet->data, MTU, 0);
- if(lenin <= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
- event_exit();
- return false;
- }
-
- packet->len = lenin;
-
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, device_info);
-
- return true;
-}
-
-static bool write_packet(vpn_packet_t *packet) {
- if((ssize_t)plug.vde_send(conn, packet->data, packet->len, 0) < 0) {
- if(errno != EINTR && errno != EAGAIN) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
- event_exit();
- }
-
- return false;
- }
-
- return true;
-}
-
-const devops_t vde_devops = {
- .setup = setup_device,
- .close = close_device,
- .read = read_packet,
- .write = write_packet,
-};