diff --git a/COPYING b/COPYING index f4dd065..1384f46 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright (C) 1998-2013 Ivo Timmermans, Guus Sliepen and others. +Copyright (C) 1998-2019 Ivo Timmermans, Guus Sliepen and others. See the AUTHORS file for a complete list. This program is free software; you can redistribute it and/or modify it under diff --git a/ChangeLog b/ChangeLog index 0feb52e..041bf3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,621 +1,421 @@ -Version 1.1pre8 August 13 2013 +Version 1.0.36 August 26 2019 ------------------------------------------------------------------------ -Guus Sliepen (56): - Don't try to create tinc.conf when using set or add commands. - Modernize the configure script a bit. - Use conditional compilation for device.c. - Use conditional compilation for cryptographic functions. - Rename xmalloc_and_zero() to xzalloc(). - Add generic crypto headers. - Add more __attribute__((malloc)) where appropriate. - Add __attribute__((warn_unused_result)) to crypto functions. - Fix warnings for functions marked __attribute((warn_unused_result)). - Add a few more checks and warnings in the crypto functions. - Enable the SPTPS protocol by default. - Fix check for presence of ECDSA public key for outgoing connections. - Use read_host_config() where appropriate. - Don't free ephemeral ECDH keys twice. - Fix potential NULL pointer dereferences. - Don't try to handle incoming data if sptps_start() has not been called yet. - Enable and fix warnings from automake. - Send a new key when we receive packets from a node we don't have a valid key for. - Annotate the xalloc functions. - Improve base64 encoding/decoding, add URL-safe variant. - Add a newline when logging to stderr in the tinc binary. - Fix port number in pidfile. - Add an invitation protocol. - Better optional argument handling. - Allow the log output to be stopped with control-C in tinc's shell. - Use strerror() instead of gai_strerror() when err == EAI_SYSTEM. - Add the LocalDiscoveryAddress option. - Set $NAME when calling host-up/down and subnet-up/down scripts. - Add connection rate limiting. - Fix warning "Both netname and configuration directory given" on Windows. - Add missing definitions on Windows. - Don't search in local directories for include files. - Don't use vasprintf() anymore on Windows. - Attribution for Etienne Dechamps. - Forbid protocol version rollback. - Allow extra options to be passed to "tinc restart" again. - Honour umask, let temporary key files inherit original's permissions. - Fix compression when using the SPTPS protocol. - Warn when incorrect use of add or set causes variables to be removed. - Allow control-C to stop tincd without stopping the tinc shell. - Don't forget the Port variable when creating an invitation URL. - Choose a different Port when 655 isn't available when doing "tinc init". - Choose a different Port when 655 isn't available when doing "tinc join". - Make absolutely sure we can write config files before accepting an invitation. - Defer handling netname conflicts when accepting an invitation. - Use umask() to set file and UNIX socket permissions without race conditions. - Clean up the SIGINT handler. - Really retry outgoing connections immediately if requested. - Non-zero exit code when reloading config file fails after SIGHUP. - Fix a typo. - Don't echo broadcast packets back when Broadcast = direct. - Move .h files from noinst_HEADERS to tincd_SOURCES. - Build .tar.gz instead of .tar.xz. - Update copyright notices. - Don't typedef the same struct in two header files. - Releasing 1.1pre8. +Guus Sliepen (8): + Remove the call to RAND_load_file(). + Update THANKS. + Backport tinc 1.1's str2net() function. + Update THANKS. + Fix spelling errors found by codespell. + Reformat all code using astyle. + Add a missing check for a pathname being too long. + Releasing 1.0.36. -Etienne Dechamps (5): - Fix combination of Mode = router and DeviceType = tap on Linux. - Fix hash_function(). - Disable PMTU discovery when TCPOnly is set. - Introduce lightweight PMTU probe replies. - Further improve bandwidth estimation for type 2 MTU probe replies. +Rosen Penev (2): + Fix compilation when OpenSSL has no ENGINE support + Fix compilation without deprecated OpenSSL APIs -Sven-Haegar Koch (1): - Modified some error messages in src/sptps.c. +Quentin Rameau (1): + Double-quote nodes in graphviz network file -Version 1.1pre7 April 22 2013 +Werner Schreiber (1): + Fix segfault when dest->mtu is 0. + +Version 1.0.35 October 05 2018 ------------------------------------------------------------------------ Guus Sliepen (12): - Use UDP when using sptps_test in datagram mode. - Flush output buffers in the tap reader thread on Windows. - Better default output file for generated public keys. - Allow changing configuration with tincctl without the "config" keyword. - Avoid calling time(NULL). - Include README.android in the tarballs. - Rename tincctl to tinc. - Remove references to the config keyword. - Describe the SPTPS protocol in the manual. - Fix completion of add/del/get/set commands. - Drop packets forwarded via TCP if they are too big (CVE-2013-1428). - Releasing 1.1pre7. + Prevent oracle attacks (CVE-2018-16737, CVE-2018-16738) + Prevent a MITM from forcing a NULL cipher for UDP (CVE-2018-16758) + Check the return value from snprintf(). + Check the return values from BN_hex2bn() and RAND_load_file(). + Fix all warnings when compiling with -Wall -W -pedantic. + Fix two small memory leaks. + Don't check for NULL-pointers before calling free(). + Update THANKS. + Fix checks for Cygwin-related macros. + Fix spelling errors. + Update README and links to required libraries. + Releasing 1.0.35. -Version 1.1pre6 February 20 2013 +AMRI Amine (1): + Fixing typo + +Rafael Sadowski (1): + OpenBSD has a proper tap device. + +Version 1.0.34 June 12 2018 ------------------------------------------------------------------------ -Guus Sliepen (16): - Fix datagram SPTPS. - Fix a typo. - Get microsecond time resolution on Windows. - Detect increases in PMTU. - Remove direct inclusion of OpenSSL headers in net_packet.c and tincd.c. - Fix tincd terminating immediately on Windows. +Guus Sliepen (10): + Add missing thanks to the NEWS message. + Fix building documentation when using OpenBSD's make. + Fix #ifdefs that were broken due to commit d178b58. + Don't use SOL_IP and SOL_IPV6. + Make systemd service file handling identical to tinc 1.1. + Rename distro/ to systemd/. + Document how to enable tinc at boot time using systemd. + Fix all spelling errors found by codespell. + Properly implement tinc.texi's dependency on tincinclude.texi. + Releasing 1.0.34. + +Maximilian Stein (1): + Fix SEGFAULT when trying to connect to IPv6 peer in non-IPv6 environment + +wangliushuai (1): + Remove redundant 'break'. + +Version 1.0.33 November 04 2017 +------------------------------------------------------------------------ + +Guus Sliepen (31): + Udpate THANKS. + Fix a potential memory leak. + Use AC_CONFIG_MACRO_DIR(). + Give absolute path for #include to AC_CHECK_HEADERS(). + Prepare for automatic code formatting using Artistic Style. + Never remove items from cmdline_conf. + Use stack-allocated strings for temporary filenames. + Fix a few minor memory leaks. + Remove unused/obsolete checks from configure.ac. + Use getcwd() instead of get_current_dir_name(). + Remove xmalloc.c, backport xalloc.h from tinc 1.1. + Update all header guards. + Convert sizeof foo to sizeof(foo). + Reformat all code using astyle. + Don't call ERR_remove_state(). + Unconditionally include stdbool.h and inttypes.h. + Remove more obsolete autoconf checks. + Remove obsolete m4/README. + Fix some "make distcheck" errors. + Add some information about the requirements of a chroot environment. + Handle tun/tap device returning EPERM or EBUSY. + Disable PMTU discovery when TCPOnly is used. + Fix all -Wall -W compiler warnings. + Realign comments. + Remove unused functions. + Ensure all parameters have names in header files. + Support autoconf's --runstatedir option. + Const correctness. + Fix compilation errors when --enable-uml is used. + Update THANKS. + Releasing 1.0.33. + +Rafael Sadowski (1): + fix tinc.conf for OpenBSD + +nemunaire (1): + Allow compilation from a build directory + +Version 1.0.32 September 02 2017 +------------------------------------------------------------------------ + +Guus Sliepen (13): + Don't dereference myself->incipher if it's NULL. + Merge remote-tracking branch 'VittGam/master' + Use /dev/udp instead of /dev/ip on Solaris. + Use getmsg()/putmsg() instead of read()/write() on Solaris. + Fix Solaris DeviceType = tap in router Mode. + Bind outgoing TCP sockets. + Move logging of "would block" messages to debug level 4. + Set KillMode=mixed in the systemd service file. + Don't forget about outgoing connections on host file read errors. + Fix Proxy = exec. + Set status.proxy_passed early for Proxy = exec. + Don't try to bind Proxy = exec sockets to an address. + Releasing 1.0.32. + +Vittorio Gambaletta (VittGam) (1): + route: Support ToS/DiffServ priority inheritance when routing IPv6 packets. + +Version 1.0.31 January 15 2017 +------------------------------------------------------------------------ + +Guus Sliepen (1): + Releasing 1.0.31. + +Élie Bouttier (1): + Remove ExecStop in tinc@.service + +Version 1.0.30 October 30 2016 +------------------------------------------------------------------------ + +Guus Sliepen (11): + Allow non-empty lines after status code from a HTTP proxy. + Fix proxy reply parsing broken by the previous commit. + Log only the first line of a proxy request rejection message. + Delay sending the real ID request until after a proxy request is granted. + Use AES256 and SHA256 by default, also for the meta-connections. + Enforce maximum amount of bytes sent/received on meta-connections. + Fix bit shifting arithmetic so the code actually does what the last commit message says. + Really fix byte budget calculation. + Use AES in CTR mode instead of OFB mode for meta-connections. + Use CFB mode for meta-connections to improve security. + Releasing 1.0.30. + +Version 1.0.29 October 09 2016 +------------------------------------------------------------------------ + +Guus Sliepen (11): + Preserve IPv6 scope_id in edges. + Ensure compatibility with OpenSSL 1.1.0. + Add -Wall to CFLAGS. + Check return value of RSA_generate_key_ex(). + Force nul-termination of strings after vsnprintf(). + Log warnings about dropped packets only with debug level 5 or higher. + Add a copy of ax_append_flag.m4. + Add ax_require_defined.m4. + Fix possibly unitialized variable. + Fix compiler warnings about format string errors on BSD. + Releasing 1.0.29. + +Version 1.0.28 April 10 2016 +------------------------------------------------------------------------ + +Guus Sliepen (8): + Fix compiling bsd/device.c on systems without utun. + Really remove use of __DATE__ and __TIME__ to facilitate reproducible builds. + Add systemd service files. + Update .gitignore. + Ensure the service files are in the tarball. + Explicitly mention that LibreSSL can be used as well. + Update links in the documentation. + Releasing 1.0.28. + +Version 1.0.27 April 10 2016 +------------------------------------------------------------------------ + +Guus Sliepen (26): + Add missing AM_PROG_CC_C_O to configure.ac. + Attribution for various contributors. + Update "now" after connect() when making outgoing connections. + Add ability to use proxies to connect to hostnames when there is no nameserver. + Only add a reflexive address when we're sure it's working. + Fix compatibility with TAP-Win32 9.0.0.21 and later. + Fix warnings from the Clang Static Analyzer. + Improve performance of edge updates. + Clarify that scripts are called synchronously. + Small fixes for the documentation. + Add warnings for bad combinations of Device and Interface. + Fix forwarding of edge updates. + Don't compile getopt*.c if the system provides getopt_long(). + Update .gitignore. + Update THANKS. + Use iface instead of interface. + Update copyright notices. + Remove use of __DATE__ and __TIME__ to facilitate reproducible builds. + Cast 0xff to char before comparing it to another char. + Get rid of a warning when compiling tinc using MinGW. + Every BSD flavor has a tap device nowadays. + Use devname() if available to support devfs cloning on BSD. + Use SIOCGIFADDR on BSDs that support it. + Enable silent builds by default. + Add support for OS X utun interfaces. + Releasing 1.0.27. + +Vittorio Gambaletta (VittGam) (6): + Fix DecrementTTL option. + Fix source IP address for ICMP unreachable packets generated by tinc. + Try to reply with node address only when decrementing the TTL. + Fix DecrementTTL option for packets destined to the local node. + s/broadcast_packet_helper/route_broadcast/ + Remove forward declaration for do_decrement_ttl. + +LunarShaddow (3): + fix typo + re-arrange include sequence to avoid a mingw introduced bug. + Proofing README. + +Florian Weik (1): + Fix NAME variable in subnet-* scripts for local subnets. + +Nathan Stratton Treadway (1): + Fix invalid checksum generation. + +Version 1.0.26 July 05 2015 +------------------------------------------------------------------------ + +Guus Sliepen (14): + Use VittGam's real name. + Attribution for Saverio Proto. + Always call res_init() before getaddrinfo(). + Fix --logfile without a filename on Windows. + Never call putenv() with data on the stack. + Return non-zero exit code when encountering configuration errors during startup. + Fix autoconf check for function attributes. + Fix spelling of FORTIFY_SOURCE. + Update copyright notices. + Attribution for various contributors. + Only check for -fno-strict-overflow if -fwrapv does not work. + Fix unputenv() on Windows. + Don't try to call res_init() if ./configure told us it doesn't exist. + Releasing 1.0.26. + +Jo-Philipp Wich (1): + fix musl compatibility + +Version 1.0.25 December 22 2014 +------------------------------------------------------------------------ + +Guus Sliepen (7): + Fix date of last NEWS entry. + Remember ToS/Diffserv priority for each socket individually. + Attribution for various contributors. + Automatically choose a tap device on Mac OS X when using switch Mode. + Update documentation for Mac OS X. + Check whether res_init() really lives in libresolv. + Releasing 1.0.25. + +Borg (3): + Fixed scripts calling under Win32. + Get MAC of TAP device. + Fixed tinc-up script calling on Win32. + +Alexis Hildebrandt (1): + Add support to link against libresolv Mac OS X + +Baptiste Jonglez (1): + Use the description from the 1.1 man page for the IndirectData option + +David Pflug (1): + Update README.android + +Jochen Voss (1): + Fix some typos in the manual. + +Tomislav Čohar (1): + Configure minimum reconnect timeouts. + +VittGam (1): + Support ToS/DiffServ priority handling for IPv6 meta and UDP connections. + +Version 1.0.24 May 11 2014 +------------------------------------------------------------------------ + +Guus Sliepen (13): + Remove useless variable 'hard' from try_harder(). + Merge pull request #14 from luckyhacky/master + Add an autoconf check for res_init(). + Nexthop calculation should always use the shortest path. + Fix issues found by Coverity. + Fix warnings found by GCC 4.9. + Fix a few more issues found by Coverity. + Fix a few more issues found by Coverity. + Drop h and hh length modifiers from printf format strings. + Fix a bug that could prevent tinc from starting correctly on Windows. + FIx the autoconf checks for res_init(). + Remove the warnings when IP_DONTFRAGMENT/IPV6-DONTFRAG is not supported. + Releasing 1.0.24. + +Steffan Karger (3): + Use constant time memcmp() when comparing packet HMACs. + Use cryptographically strong random when generating keys. + Check RAND_bytes() return value, fail when getting random fails. + +Armin Fisslthaler (1): + reload /etc/resolv.conf in SIGALRM handler + +Loic Dachary (1): + fix documentation typo + +luckyhacky (1): + update to openssl version 1.0.1g due to lack of heartbleed bug in prior version of openssl + +refs/tags/1.0.23-android-1 March 11 2014 +------------------------------------------------------------------------ + +Guus Sliepen (13): + Mention in the manual that multiple Address staments are allowed. + If no Port is specified, set myport to actual port of first listening socket. + Enable compiler hardening flags by default. + Update support for Solaris. + Include for PATH_MAX. + Stricter check for raw socket support. + Use hardcoded value for TUNNEWPPA if net/if_tun.h is missing on Solaris. + Fix incorrectly merged bits from 80cd2ff73071941a5356555b85a00ee90dfd0e16. + Don't enable -fstack-protector-all. + Remove or lower the priority of some debug messages. + Clarify StrictSubnets. + Attribution for various contributors. + Handle errors from TAP-Win32/64 adapter in a better way. + +Florent Clairambault (2): + Adding "conf.d" configuration dir support. + Adding some documentation around the /etc/tinc/$NET/conf.d directory. + +Vilbrekin (1): + Update android build instructions. Disable PIE as this is not supported on some devices. + +Version 1.0.23 October 19 2013 +------------------------------------------------------------------------ + +Guus Sliepen (9): Check for writability when waiting for a socket to finish connecting. - Fix segmentation fault when trying to connect via a SOCKS5 proxy. - Don't send proxy requests for incoming connections. - Derive UNIX socket filename from PID filename. - Let the GUI use UNIX sockets if available. - Don't expect a response from tincd after sending REQ_STOP. - Fix a tiny memory leak. - Fix compiler warnings on Windows. - Fix compiler warnings on some BSD variants. - Releasing 1.1pre6. + Don't send PING requests on connections which are not active yet. + Fix segfault when Name = $HOST but $HOST is not set. + Fix typos in the documentation. + Modernize the build system. + Get rid of the splay tree implementation. + Add description of IffOneQueue and MaxTimeout to the info manual. + Clean up child processes from proxy type exec. + Releasing 1.0.23. -Version 1.1pre5 January 20 2013 +Version 1.0.22 August 13 2013 ------------------------------------------------------------------------ -Guus Sliepen (24): - Clarify the description of IndirectData and Mode = router. - Fix display of cumulative packet counters. - Fix infinite loop in timeout handling on Windows. - Fix support for tunemu on iOS devices. +Guus Sliepen (7): + Better optional argument handling. Fix a typo. - Note that node Names are case sensitive. - Note that tincctl import is only meant to work with data from tincctl export. - Mention that the -L, -R and -U options are not supported on all platforms. - Don't complain about garbage if we skipped importing a host file. - Better error messages when using -L, -R or -U on platforms that do not support it. - Always complain if too many arguments are given for tincctl commands. - Check HMAC before sequence number. - Add the tincctl exchange and exchange-all commands. - Count the number of correctly received UDP packets. - Estimate RTT, bandwidth and packet loss between nodes. - Fix the minimum spanning tree algorithm. - Handle SIGINT gracefully. - Move make_names() and related variables to its own source file. - Fix compilation of UML and VDE device support. - Allow connections via UNIX sockets. - Make sure PriorityInheritance also works in switch mode. - Remove possible definition of timersub(), which is also in dropin.h. - Fix tincctl init when /etc/tinc does not yet exist. - Releasing 1.1pre5. + Set $NAME when calling host-up/down and subnet-up/down scripts. + Don't use vasprintf() anymore on Windows. + Don't echo broadcast packets back when Broadcast = direct. + Update copyright notices. + Releasing 1.0.22. -Version 1.1pre4 December 05 2012 +Etienne Dechamps (1): + Fix combination of Mode = router and DeviceType = tap on Linux. + +Version 1.0.21 April 22 2013 ------------------------------------------------------------------------ -Guus Sliepen (35): +Guus Sliepen (2): + Drop packets forwarded via TCP if they are too big (CVE-2013-1428). + Releasing 1.0.21. + +Version 1.0.20 March 03 2013 +------------------------------------------------------------------------ + +Guus Sliepen (30): + Use /dev/tap0 by default on FreeBSD and NetBSD when using Mode = switch. + Document how to load the tap driver on FreeBSD. + Update THANKS file. + Also clarify hostnames=[yes|no] in tinc.conf(5). + Attribution for Vil Brekin and some code style cleanups. + Don't ignore Makefile.am. + Fix links in documenation. + Attribution for Martin Schürrer. + Add strict checks to hex to binary conversions. + Clear connection options and status fields in free_connection_partially(). + Fix warnings from cppcheck. + Clear Ethernet header when reading packets from a tun device. + Clear status and options fields of unreachable nodes. Fix warnings from groff. - Keep track of the number of nodes in a tree. - Add the AutoConnect option. - Slightly randomize all timeouts. - Fix potential buffer overflow reading the PID file. Using alloca() for a constant sized buffer is very silly. Make sure PMTU discovery works in switch mode with VLAN tags. - Mention libcurses and libreadline in the manual. Mention in the manual that support for LZO and zlib can be disabled. - Fix index entry for section about readline library. Fix configure script help text for --enable options. Don't take the address of a variable whose scope is about to disappear. Send broadcast packets using a random socket, and properly support IPv6. Remove text saying you must have one of PrivateKey or PrivateKeyFile in tinc.conf. - Disable support for kqueue on MacOS/X. - Also don't use poll() on MacOS/X. - Choose a suitable socket when updating a node's UDP address. - Try all known addresses of node during PMTU discovery, now also for SPTPS. - Improve UDP address selection. - Ensure MTU probe replies are sent back the same way they came in. - Drop libevent and use our own event handling again. - Allow multiple timeouts to expire at the exact same time. - Fix check for expired events. - Fix use of unitialised values in hash tables. - Set a node's pointers to zero before trying to insert it into a tree. - Fix crash in timeout handling. - Fix compiler error on Windows. - More fixes for Windows. - Add option to dump only a list of reachable nodes. - Remove GraphDumpFile from the manual and manpages. - Fix compiler warnings on OpenBSD. - Don't use nested functions. - Scale packet counters similar to byte counters. - Fix whitespace. - Releasing 1.1pre4. - -Version 1.1pre3 October 14 2012 ------------------------------------------------------------------------- - -Guus Sliepen (384): - Created the 1.1 branch where large code changes can take place, - Only free members of connection_t that have been allocated. - Port fixes from release 1.0.8. - Properly delete listener socket events on shutdown. - 128 listener sockets is way too much. - Use a separate event structure to handle meta data writes. - Use libevent to dump graphs when necessary. - Use libevent to handle HUP signal. - Configure events after obtaining a socket. - Use libevent to send MTU probes. - Use libevent for retrying outgoing connections. - Remove legacy event system. - Properly use the timeout_initialized() macro. - Use libevent to handle all non-fatal signals. - Redo SIGALRM handling. - Use libevent to age past requests. - Use libevent to age learned MAC addresses. - Use libevent to handle key expiration. - Move key regeneration handling to net_setup.c. - Remove global variable "now". - Remove the last bits of the legacy main_loop(). - Remove last references to the global variable "running". - K&R style braces - Use splay trees instead of AVL trees. - Detect duplicate outgoing connections. - More consistent variable naming. - Show branch version number. - Update documentation. - Start of control socket implementation. - We can safely delete a connection_t in terminate_connection() now. - Fix retrying outgoing connections. - Remove pidfile in favour of control socket. - Move key generation to tincctl. - Implement "stop" command, and allow tincctl to retrieve a running tincd's PID. - Use bufferevents to handle control socket buffering. - Use libevent for meta socket input/output buffering. - Parse PEM RSA keys ourself, and use libgcrypt to do RSA encryption and decryption. - Create wrappers for the cryptographic operations used in tinc. - Make sure the crypto wrapper functions can actually be compiled. - Some more crypto wrapper functions are needed. - Finish crypto wrapping. Also provide wrappers for OpenSSL. - Only check for libgcrypt if --with-gcrypt is used. - Fix formatting of --help output. - Small fixes to make gcrypt routines compile. - Apply patch from Scott Lamb: Update documentation to match tincctl changes - Fix connection weight estimation. - Use a dummy function as the read callback for connection bufferevents. Should not be triggered. - Fix meta data segfault when receiving a partial command. - Prevent double free() of a used challenge nonce. - Look in the configured sbin directory for the tincd binary. - Only show meta connection related debug messages when debug level >= 4 - Move AC_GNU_SOURCE up to make autoconf happy. - Use the crypto wrappers again instead of calling OpenSSL directly. - Backport fixes from trunk since revision 1555. - Fix compiler warnings. - Remove unnecessary parentheses from sizeof, apply sizeof to variables instead of types whereever possible. - Remove wrong checks. - Use Dijkstra's algorithm. Based on patches from Max Rijevskiy. - Make sure IPv6 sockets are IPv6 only. - Move RSA key generation into the wrappers. - Merge branch 'master' into 1.1 - Merge branch 'master' into 1.1 - Handle truncated message authentication codes. - Fix pointer arithmetic when creating and verifying message authentication codes. - Merge branch 'master' into 1.1 - Add missing #include. - Use correct format specifiers. - Replace asprintf()s not covered by the merge to xasprintf(). - Add a better autoconf check for libevent. - Merge branch 'master' into 1.1 - Drop localisation and checkpoint tracing in files not covered by the merge. - Update FSF address in files not covered by the merge. - Merge branch 'master' into 1.1 - Don't enable device events when there is no valid filedescriptor. - Use %x instead of %lx where appropriate. - Handle truncated message authentication codes with gcrypt. - Handle PKCS#5 padding in the gcrypt backend. - Make sure the 1.1 branch compiles in a MinGW environment. - Better integration of libevent in build system. - Small fixes to get really working control sockets on Windows. - Use the TCP socket infrastructure for control sockets. - Only call ioctlsocket() on Windows. - Merge branch 'master' into 1.1 - Fix compiler warnings. - Do not include OpenSSL headers directly. - Include missing header files and source directories. - Allow connections to be closed. - Start of a GUI for tinc. - Fix packet authentication. - Fix block cipher padding when using libgcrypt. - Reinitialise block cipher IV each time we encrypt a packet when using libgcrypt. - Fix reading raw RSA keys with libgcrypt. - recv() and recvfrom() return int, do not prematurely cast the return value. - Do not consider unreachable nodes when trying to determine packet origin. - Fix alignment of results of RSA operations when using libgcrypt. - Do not use hardcoded cipher block length when padding. - Remove unused AVL tree library. - Move source from lib/ to src/. - Fix experimental GUI when reading hexadecimal values. - Merge branch 'master' into 1.1 - Fix merge of commit 4a0b9981513059755b9fd15b38fc198f46a0d6f2. - Add missing return statement. - Use correct digest length when checking a received key. - Do not try to free NULL pointers. - Remove obsolete lib/ directory. - Merge branch 'master' into 1.1 - Link tincctl with dropin.o. - Merge branch 'master' into 1.1 - Do not try to dereference myself->connection->config_tree. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Fix check for event initialization due to the merge. - Add simple buffer management code. - Remove use of bufferevent and eventbuffers, use our own buffering instead. - Several fixes for the buffer code. - Add per-node traffic counters. - Dump traffic statistics over control sockets. - Add an autoconf check for the curses library. - Add a very primitive "top" command to tincctl. - Allow inserting items in the middle of a list. - Nicer top command. - Add tincctl.h. - Add top.h. - Use GetItemCount() on ListCtrls instead of directly accessing ItemCount. - Fix some compiler warnings. - Compact input buffer before trying to read instead of after. - Always compact the buffer if it has reached MAXBUFSIZE. - Check if an event is initialized before calling event_del(). - Reset tcplen after use. - Add the ability to dump all traffic going through route() over a control connection. - Allow tincctl to connect to something besides localhost. - Show hostname and port in error message when connecting to a running tincd. - Cosmetic fix when pressing 's' in tincctl top. - Initialise priority field to zero for packets read from the VPN interface. - Remove outgoing event in free_connection(). - Simplify signal handling. - Drop the GNU malloc.c, realloc.c, and xmalloc.c. - Drop the GNU memcmp.c implementation. - Don't #include anymore. - Remove unused functions and variables. - Remove support for the Ethertap device. - Fix some compiler and cppcheck warnings. - More stable sorting in tincctl top. - Make traffic statistics more readable with configurable scaling. - Fix nodes joining the VPN after tincctl top started. - Don't treat packets coming in via TCP as having zero length. - Remove debugging message that was accidentily left in. - Even simpler signal handling. - Small fixes for Windows. - Use send() when writing to sockets, and the return type is ssize_t. - Fix format strings for Windows. - Don't ignore SIGCHLD, system() needs it. - Clean up digests when freeing a connection_t. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Reopen log file after SIGHUP. - Only log UDP address changes at the appropriate debug levels. - No need to check for pselect() in tinc 1.1. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Delete mtuevent if it is not used. - Don't call event_del() from the mtuevent handler, always send_mtu_probe() in ans_key_h(). - Don't use AM_CONDITIONAL for CURSES. - Add Makefile.am in gui/. - Update manpages and info manual. - Ensure that the texinfo manual can be converted to HTML. - Releasing 1.1pre1. - Ensure the right files end up in the tarball after make dist. - Thank Scott Lamb, Sven-Haegar Koch and Loïc Grenié in the NEWS file. - Merge Tinc.py into tinc-gui to simplify make install. - Re-add support for SIGALRM. - Don't call exit_control() if we didn't do init_control(). - Rename controlcookie file to pidfile. - Make pid files backwards compatible and add address of listening socket. - Add +git to the version string. - Really stable sorting of tincctl top output. - Use pidfile in tinc-gui as well. - Don't react to escape character in tincctl top. - Update documentation to mention pidfiles instead of controlcookies. - Remove debug messages that were printed to stdout. - Add manpage for tinc-gui. - Preliminary implementation of Elliptic Curve Diffie-Hellman Ephemeral key exchange. - Support ECDH key exchange. - Add PRF to derive key material from the ECDH shared secret. - Use PRF. - Proper use of PRF. - No need to keep around pointers to EC_GROUP. - Cleanups in ECDH code. - Base64 encoding and decoding functions. - Add ECDSA key generation. - Have tincctl generate ECDSA keys. - Finish base64 decoding routine. - Add ECDSA key import. - Round up the size of the secret parts after splitting it in two. - Add a minor number to the protocol version. - Bump minor protocol to indicate ECDH capability for UDP session keys. - Implement ECDSA sign and verify operations. - Read ECDSA keys. - Very primitive ECDSA signed ECDH key exchange for the meta protocol. - Hash input before signing it with ECDSA. - Free ECDSA and RSA structures when freeing a connection_t. - Automatically exchange ECDSA keys and upgrade to new authentication protocol. - Close meta connection socket after cleaning up event structures. - Require ExperimentalProtocol = yes for new features, update documentation. - Don't use wildcards in filenames in configure.in. - Make hexadecimal and base64 routines behave the same. - Make use of the improved hex and base64 functions. - Remove unnecessary variables and functions. - Fix compiler warnings. - Use the correct direction flag when setting cipher keys. - Use the same logic as tinc 1.0.x for detecting two nodes with the same Name. - Use ECDSA to sign ECDH key exchange for UDP session keys. - Update info manual. - Use usleep() instead of sleep(), MinGW complained. - Use const pointer to source in base64 and hex routines. - Ensure symlinked files do not end up in the tarball. - Fix declaration of usleep(). - "tincctl stop" now removes the tinc service on Windows. - Write loopback address instead of "any" address in pidfile. - Add missing newline. - Releasing 1.1pre2. - Fix tinc 1.0.x daemons connecting when ExperimentalProtocol = yes. - Don't abort() on low-level crypto errors, just return false. - Start of "Simple Peer-To-Peer Security" protocol. - Handle UDP packets with unknown source addresses properly. - Fix compiler warning. - Update SPTPS protocol. - Test corner cases in the SPTPS protocol. - Add counter mode encryption. - Use counter mode encryption. - Exchange ACK records to indicate switch to new keys. - Fix compiler warnings. - Fix a few small memory leaks. - Use only one hash algorithm (SHA512) in the PRF. - Remove useless warning about signature length being shorter than expected. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Apply HMAC after encryption. - Use SPTPS when ExperimentalProtocol is enabled. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Go back to breadth first search for path finding. - Ensure all SPTPS functions are prefixed with sptps_. - Let tincctl use the NETNAME environment variable if no -n option is given. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Don't close control connections when handling a reload command. - Allow log messages to be captured by tincctl. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Allow CTR mode counter to be set to a specific value. - Add datagram mode to the SPTPS protocol. - Test SPTPS messages sent while key renegotation is in progress. - Don't send an ACK message after the first key exchange in the SPTPS protocol. - Start documenting the SPTPS protocol. - Make sure the signature also covers the session label. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Add autoconf checks for OpenSSL's elliptic curve functions. - Update README to reflect that only OpenSSL is currently supported. - Always pass request strings to other functions as const char *. - Don't forget to send a newline when forwarding requests. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Fix crash when handling the ALRM signal. - Use /dev/tap0 by default on FreeBSD and NetBSD when using Mode = switch. - Document how to load the tap driver on FreeBSD. - Update THANKS file. - Merge branch 'master' into 1.1 - "tincctl init" creates initial directory structure, tinc.conf and keypairs. - Put every command in its own function. - Allow configuration variables to be added/removed using tincctl. - Stricter checks for node names. - Add an easy way to edit a configuration file. - Have tincctl notify a running tincd of configuration file changes. - Fix tincctl start. - Let tincctl ignore tincd options, so they will be passed on. - Fix tincctl dump. - Move all functions related to subnet parsing to subnet_parse.c. - "tincctl info" gives more human readable information about nodes or subnets. - Give an error message when tincctl info cannot parse the given subnet or address. - Strip default subnet weight from output. - Add an easy way to export and import host configuration files. - When exporting configuration files, don't copy Name variables. - Put minor protocol version in connection options so other nodes can see it. - Use minor protocol version to determine whether to use ECDH key exchange between nodes. - Never remove items from cmdline_conf. - Split setup_myself() into two functions, one for reloading configuration. - Allow more configuration variables to be changed when reloading configuration. - Prefer routes with lower weight as long as they do not increase the number of hops. - Make sure tinc compiles on Windows. - Make sure sptps.h and info.h are in the tarball. - BSD make doesn't like $<. - Fix various compiler warnings. - Call event_init() after detaching. - Add some checks when changing configuration. - Add a newline to a configuration file if it is missing. - Have tincd and tincctl use the same method of determining netname. - Fix some compiler warnings. - Fix crash when no netname is specified. - Don't try to mkdir(CONFDIR) on Windows when there is a registry key for tinc. - Use backslashes on Windows. - Windows doesn't like quotes around "edit" when calling it through system(). - Fix exit code when installing tincd as a service on Windows. - tincctl init now also creates a template tinc-up script. - Have tinc-gui use same way of locating pidfile as tincd and tincctl. - Remove unused po/ directory. - Also clarify hostnames=[yes|no] in tinc.conf(5). - Merge branch 'master' into 1.1 - Use datagram SPTPS for packet exchange between nodes. - Remove unused #include. - Handle SPTPS datagrams in try_mac(). - Add Brandon Black's replay window code to SPTPS. - Use a status bit to track which nodes use SPTPS. - Try sending SIGTERM if we cannot connect to a tincd but we know its PID. - tincctl restart should work even if no tincd is running. - Add the ability to query configuration variables to tincctl. - Add missing configuration variables. - Stricter checks for netname and node names. - Update the documentation to encourage using "tincctl init" and "tincctl config". - Clear struct sptps before reusing it. - Have tincctl act as a shell when no command is given. - Optionally compress and/or strip Ethernet header from SPTPS packets. - Add readline completion for tincctl config and tincctl info. - Fork when using the "start" command in tincctl. - Make sure the top command can be used more than once in tincctl's shell. - Add bash completion script. - Fix segfault when using tincctl's shell without readline. - Quit when "exit" or "quit" commands are used in tincctl's shell. - Fix node name check for "connect" and "disconnect" commands. - Properly handle SPTPS packets with stripped Ethernet headers. - Remove some debug messages. - Remove newlines at end of log messages. - Add a simple hash table implementation. - Use hash tables to lookup owners of addresses. - Replace node_udp_tree with a hash table. - Ensure sptps_test compiles with -flto. - Attribution for Vil Brekin and some code style cleanups. - Don't ignore Makefile.am. - Fix typo in manpage. - Remove remnants of Ethertap and old TUNSETIFF ioctl(). - Keep last known address and time since reachability changed. - Let tincctl parse and format dumps. - Allow dumping either directed or undirected graphs. - Update documentation of the "dump graph" command. - Comment out old public/private keys when generating new ones. - Fix links in documentation. - Fix links in documenation. - Let the GUI handle the new dump format. - Fix column sorting, make all lists sortable. - Correctly add/remove outgoing connections when reloading configuration. - Make tincctl robust against dropped control connections. - Remove some debugging messages. - Attribution for Martin Schürrer. - Add strict checks to hex to binary conversions. - Merge branch 'master' into 1.1 - Fix not reading Port statement from host config file. - Remove unused function declaration. - Make sure sptps_test compiles without -flto. - Remove abort() call that accidentily sneaked into commit dd1b69e. - Libreadline might depend on libcurses. - Fix off-by-one error. - Improve starting/stopping tincd using tincctl. - Clear connection options and status fields in free_connection_partially(). - When terminating, keep control connections open until the end. - Useful error messages when writing to a meta connection fails. - Make datagram SPTPS key exchange more robust. - Handle packets encrypted via SPTPS that need to be forwarded via TCP. - Remove a debug message. - Fix warnings from cppcheck. - Refactor outgoing connection handling. - Replace the connection_tree with a connection_list. - C99 extravaganza. - Fix deleting connections from the connection list. - Remove unused variables, fix some #includes. - Clear Ethernet header when reading packets from a tun device. - Fix memory leaks found by valgrind. - Fix hash functions for keys whose size is not divisible by 4. - Try all known addresses of node during the PMTU discovery phase. - Fix whitespace. - Clear status and options fields of unreachable nodes. - Strip newline from incoming SPTPS requests. - Fix handling of initial datagram SPTPS packet. - Only log success of initial datagram SPTPS handshake. - Make sure the ReplayWindow option works for SPTPS as well. - Log more messages using logger(). - tincctl: add node colors and edge weight to graph dump. - Fix compile error on Windows. - Update copyright notices. - Fix a few compiler errors/warnings. - Releasing 1.1pre3. - -Sven-Haegar Koch (29): - Merge branch 'master' into 1.1 - Fixed 1.0 miss-merges - Add missing AC_CHECK_HEADERS([dirent.h]) to configure.in - Function flush_meta() does not exist anymore. - README.git: tinc 1.1 needs libevent - Demote all LOG_EMERG to LOG_ERR, spamming all xterms is bad. - Fixed metadata protokoll corruption on forwarded requests - Fixed error logging on "Input buffer full" condition. - Removed two newlines from the end of log messages which created empty lines. - Use same definition for xalloc_fail_func as is really used. - sparse fixup: error: dubious one-bit signed bitfield - sparse fixup: error: too many arguments for function send_key_changed - sparse fixup: warning: symbol '...' was not declared. Should it be static? - sparse fixup: warning: non-ANSI function declaration of function '...' - sparse fixup: warning: Using plain integer as NULL pointer - fgets() returns NULL on error, not < 0 - src/net_socket.c bind_to_address(): Use after free in error path. - do_outgoing_connection() may delete a failed connection, and the structure - sptps_stop(): clear pointers after free to avoid double free. - Remove confusing error message for failed reading in ECDSA keys. - ecdh & ecdsa: avoid some possible memory leaks in error conditions. - terminate_connection(): Avoid use-after-free and double-free for - terminate_connection(): only kill c->node->connection if it is pointing - free_connection_partially(): Avoid possible use-after-free for c->hischallenge - Label control connections for log output as "", not "". - terminate_connection(): delete non-outgoing (aka incoming) connections. - Silence SPTPS log messages, reduce them from DEBUG_ALWAYS to DEBUG_META. - free_connection_partially(): also reset remote protocol version infos - sptps.c: Add missing newline to log message. - -Scott Lamb (19): - Rename "event_t" to "tevent_t", along with associated functions. - A couple missed tevent things. - Convert to libevent. - Lots of svn:ignore entries - Revert to only requiring autoconf 2.59. - Refresh po/POTFILES.in. - Updated svn:ignores list for new symlinked sources and tincctl. - const correctness - Temporarily revert to old crypto code - Update documentation to match tincctl changes - Fix reload crash - Fancier protocol for control socket - Dump through control socket - Purge through the control socket - Alter debugging levels through control socket - Retry connections through control socket - Reload configuration through control socket - Coding style corrections - Use a control socket directory to restrict access + Fix support for tunemu on iOS devices. + Make sure PriorityInheritance also works in switch mode. + Detect increases in PMTU. + Fix a compiler warning. + Fix segmentation fault when trying to connect via a SOCKS5 proxy. + Don't send proxy requests for incoming connections. + Fix compiler warnings on Windows. + Fix detection of rejected SOCKS5 proxy requests. + Releasing 1.0.20. Vilbrekin (5): Basic patch for android cross-compilation. @@ -624,11 +424,6 @@ Vilbrekin (5): Use __ANDROID__ define rather than dirty hard-code to allow android NDK cross-compilation. Android cross-compilation instructions. -Michael Tokarev (3): - don't mention reload twice in tincctl help - run tincd from the same directory as tincctl and pass all options to it - use execvp() not execve() in tincctl start - Martin Schürrer (1): Output details of encryption errors @@ -727,275 +522,6 @@ Guus Sliepen (4): Use usleep() instead of sleep(), MinGW complained. Releasing 1.0.16. -Version 1.1pre2 July 17 2011 ------------------------------------------------------------------------- - -Guus Sliepen (54): - Ensure the right files end up in the tarball after make dist. - Thank Scott Lamb, Sven-Haegar Koch and Loïc Grenié in the NEWS file. - Merge Tinc.py into tinc-gui to simplify make install. - Re-add support for SIGALRM. - Don't call exit_control() if we didn't do init_control(). - Rename controlcookie file to pidfile. - Make pid files backwards compatible and add address of listening socket. - Add +git to the version string. - Really stable sorting of tincctl top output. - Use pidfile in tinc-gui as well. - Don't react to escape character in tincctl top. - Update documentation to mention pidfiles instead of controlcookies. - Remove debug messages that were printed to stdout. - Add manpage for tinc-gui. - Preliminary implementation of Elliptic Curve Diffie-Hellman Ephemeral key exchange. - Support ECDH key exchange. - Add PRF to derive key material from the ECDH shared secret. - Use PRF. - Proper use of PRF. - No need to keep around pointers to EC_GROUP. - Cleanups in ECDH code. - Base64 encoding and decoding functions. - Add ECDSA key generation. - Have tincctl generate ECDSA keys. - Finish base64 decoding routine. - Add ECDSA key import. - Round up the size of the secret parts after splitting it in two. - Add a minor number to the protocol version. - Bump minor protocol to indicate ECDH capability for UDP session keys. - Implement ECDSA sign and verify operations. - Read ECDSA keys. - Very primitive ECDSA signed ECDH key exchange for the meta protocol. - Hash input before signing it with ECDSA. - Free ECDSA and RSA structures when freeing a connection_t. - Automatically exchange ECDSA keys and upgrade to new authentication protocol. - Close meta connection socket after cleaning up event structures. - Require ExperimentalProtocol = yes for new features, update documentation. - Don't use wildcards in filenames in configure.in. - Make hexadecimal and base64 routines behave the same. - Make use of the improved hex and base64 functions. - Remove unnecessary variables and functions. - Fix compiler warnings. - Use the correct direction flag when setting cipher keys. - Use the same logic as tinc 1.0.x for detecting two nodes with the same Name. - Use ECDSA to sign ECDH key exchange for UDP session keys. - Update info manual. - Use usleep() instead of sleep(), MinGW complained. - Use const pointer to source in base64 and hex routines. - Ensure symlinked files do not end up in the tarball. - Fix declaration of usleep(). - "tincctl stop" now removes the tinc service on Windows. - Write loopback address instead of "any" address in pidfile. - Add missing newline. - Releasing 1.1pre2. - -Version 1.1pre1 June 25 2011 ------------------------------------------------------------------------- - -Guus Sliepen (164): - Created the 1.1 branch where large code changes can take place, - Only free members of connection_t that have been allocated. - Port fixes from release 1.0.8. - Properly delete listener socket events on shutdown. - 128 listener sockets is way too much. - Use a separate event structure to handle meta data writes. - Use libevent to dump graphs when necessary. - Use libevent to handle HUP signal. - Configure events after obtaining a socket. - Use libevent to send MTU probes. - Use libevent for retrying outgoing connections. - Remove legacy event system. - Properly use the timeout_initialized() macro. - Use libevent to handle all non-fatal signals. - Redo SIGALRM handling. - Use libevent to age past requests. - Use libevent to age learned MAC addresses. - Use libevent to handle key expiration. - Move key regeneration handling to net_setup.c. - Remove global variable "now". - Remove the last bits of the legacy main_loop(). - Remove last references to the global variable "running". - K&R style braces - Use splay trees instead of AVL trees. - Detect duplicate outgoing connections. - More consistent variable naming. - Show branch version number. - Update documentation. - Start of control socket implementation. - We can safely delete a connection_t in terminate_connection() now. - Fix retrying outgoing connections. - Remove pidfile in favour of control socket. - Move key generation to tincctl. - Implement "stop" command, and allow tincctl to retrieve a running tincd's PID. - Use bufferevents to handle control socket buffering. - Use libevent for meta socket input/output buffering. - Parse PEM RSA keys ourself, and use libgcrypt to do RSA encryption and decryption. - Create wrappers for the cryptographic operations used in tinc. - Make sure the crypto wrapper functions can actually be compiled. - Some more crypto wrapper functions are needed. - Finish crypto wrapping. Also provide wrappers for OpenSSL. - Only check for libgcrypt if --with-gcrypt is used. - Fix formatting of --help output. - Small fixes to make gcrypt routines compile. - Apply patch from Scott Lamb: Update documentation to match tincctl changes - Fix connection weight estimation. - Use a dummy function as the read callback for connection bufferevents. Should not be triggered. - Fix meta data segfault when receiving a partial command. - Prevent double free() of a used challenge nonce. - Look in the configured sbin directory for the tincd binary. - Only show meta connection related debug messages when debug level >= 4 - Move AC_GNU_SOURCE up to make autoconf happy. - Use the crypto wrappers again instead of calling OpenSSL directly. - Backport fixes from trunk since revision 1555. - Fix compiler warnings. - Remove unnecessary parentheses from sizeof, apply sizeof to variables instead of types whereever possible. - Remove wrong checks. - Use Dijkstra's algorithm. Based on patches from Max Rijevskiy. - Make sure IPv6 sockets are IPv6 only. - Move RSA key generation into the wrappers. - Merge branch 'master' into 1.1 - Merge branch 'master' into 1.1 - Handle truncated message authentication codes. - Fix pointer arithmetic when creating and verifying message authentication codes. - Merge branch 'master' into 1.1 - Add missing #include. - Use correct format specifiers. - Replace asprintf()s not covered by the merge to xasprintf(). - Add a better autoconf check for libevent. - Merge branch 'master' into 1.1 - Drop localisation and checkpoint tracing in files not covered by the merge. - Update FSF address in files not covered by the merge. - Merge branch 'master' into 1.1 - Don't enable device events when there is no valid filedescriptor. - Use %x instead of %lx where appropriate. - Handle truncated message authentication codes with gcrypt. - Handle PKCS#5 padding in the gcrypt backend. - Make sure the 1.1 branch compiles in a MinGW environment. - Better integration of libevent in build system. - Small fixes to get really working control sockets on Windows. - Use the TCP socket infrastructure for control sockets. - Only call ioctlsocket() on Windows. - Merge branch 'master' into 1.1 - Fix compiler warnings. - Do not include OpenSSL headers directly. - Include missing header files and source directories. - Allow connections to be closed. - Start of a GUI for tinc. - Fix packet authentication. - Fix block cipher padding when using libgcrypt. - Reinitialise block cipher IV each time we encrypt a packet when using libgcrypt. - Fix reading raw RSA keys with libgcrypt. - recv() and recvfrom() return int, do not prematurely cast the return value. - Do not consider unreachable nodes when trying to determine packet origin. - Fix alignment of results of RSA operations when using libgcrypt. - Do not use hardcoded cipher block length when padding. - Remove unused AVL tree library. - Move source from lib/ to src/. - Fix experimental GUI when reading hexadecimal values. - Merge branch 'master' into 1.1 - Fix merge of commit 4a0b9981513059755b9fd15b38fc198f46a0d6f2. - Add missing return statement. - Use correct digest length when checking a received key. - Do not try to free NULL pointers. - Remove obsolete lib/ directory. - Merge branch 'master' into 1.1 - Link tincctl with dropin.o. - Merge branch 'master' into 1.1 - Do not try to dereference myself->connection->config_tree. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Fix check for event initialization due to the merge. - Add simple buffer management code. - Remove use of bufferevent and eventbuffers, use our own buffering instead. - Several fixes for the buffer code. - Add per-node traffic counters. - Dump traffic statistics over control sockets. - Add an autoconf check for the curses library. - Add a very primitive "top" command to tincctl. - Allow inserting items in the middle of a list. - Nicer top command. - Add tincctl.h. - Add top.h. - Use GetItemCount() on ListCtrls instead of directly accessing ItemCount. - Fix some compiler warnings. - Compact input buffer before trying to read instead of after. - Always compact the buffer if it has reached MAXBUFSIZE. - Check if an event is initialized before calling event_del(). - Reset tcplen after use. - Add the ability to dump all traffic going through route() over a control connection. - Allow tincctl to connect to something besides localhost. - Show hostname and port in error message when connecting to a running tincd. - Cosmetic fix when pressing 's' in tincctl top. - Initialise priority field to zero for packets read from the VPN interface. - Remove outgoing event in free_connection(). - Simplify signal handling. - Drop the GNU malloc.c, realloc.c, and xmalloc.c. - Drop the GNU memcmp.c implementation. - Don't #include anymore. - Remove unused functions and variables. - Remove support for the Ethertap device. - Fix some compiler and cppcheck warnings. - More stable sorting in tincctl top. - Make traffic statistics more readable with configurable scaling. - Fix nodes joining the VPN after tincctl top started. - Don't treat packets coming in via TCP as having zero length. - Remove debugging message that was accidentily left in. - Even simpler signal handling. - Small fixes for Windows. - Use send() when writing to sockets, and the return type is ssize_t. - Fix format strings for Windows. - Don't ignore SIGCHLD, system() needs it. - Clean up digests when freeing a connection_t. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Reopen log file after SIGHUP. - Only log UDP address changes at the appropriate debug levels. - No need to check for pselect() in tinc 1.1. - Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1 - Delete mtuevent if it is not used. - Don't call event_del() from the mtuevent handler, always send_mtu_probe() in ans_key_h(). - Don't use AM_CONDITIONAL for CURSES. - Add Makefile.am in gui/. - Update manpages and info manual. - Ensure that the texinfo manual can be converted to HTML. - Releasing 1.1pre1. - -Scott Lamb (19): - Rename "event_t" to "tevent_t", along with associated functions. - A couple missed tevent things. - Convert to libevent. - Lots of svn:ignore entries - Revert to only requiring autoconf 2.59. - Refresh po/POTFILES.in. - Updated svn:ignores list for new symlinked sources and tincctl. - const correctness - Temporarily revert to old crypto code - Update documentation to match tincctl changes - Fix reload crash - Fancier protocol for control socket - Dump through control socket - Purge through the control socket - Alter debugging levels through control socket - Retry connections through control socket - Reload configuration through control socket - Coding style corrections - Use a control socket directory to restrict access - -Sven-Haegar Koch (18): - Merge branch 'master' into 1.1 - Fixed 1.0 miss-merges - Add missing AC_CHECK_HEADERS([dirent.h]) to configure.in - Function flush_meta() does not exist anymore. - README.git: tinc 1.1 needs libevent - Demote all LOG_EMERG to LOG_ERR, spamming all xterms is bad. - Fixed metadata protokoll corruption on forwarded requests - Fixed error logging on "Input buffer full" condition. - Removed two newlines from the end of log messages which created empty lines. - Use same definition for xalloc_fail_func as is really used. - sparse fixup: error: dubious one-bit signed bitfield - sparse fixup: error: too many arguments for function send_key_changed - sparse fixup: warning: symbol '...' was not declared. Should it be static? - sparse fixup: warning: non-ANSI function declaration of function '...' - sparse fixup: warning: Using plain integer as NULL pointer - fgets() returns NULL on error, not < 0 - src/net_socket.c bind_to_address(): Use after free in error path. - do_outgoing_connection() may delete a failed connection, and the structure - Version 1.0.15 June 24 2011 ------------------------------------------------------------------------ diff --git a/INSTALL b/INSTALL index 007e939..8865734 100644 --- a/INSTALL +++ b/INSTALL @@ -1,8 +1,8 @@ Installation Instructions ************************* -Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, -Inc. + Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software +Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright @@ -12,97 +12,96 @@ without warranty of any kind. Basic Installation ================== - Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for + Briefly, the shell command './configure && make && make install' +should configure, build, and install this package. The following +more-detailed instructions are generic; see the 'README' file for instructions specific to this package. Some packages provide this -`INSTALL' file but do not implement all of the features documented +'INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. - The `configure' shell script attempts to guess correct values for + The 'configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that +those values to create a 'Makefile' in each directory of the package. +It may also create one or more '.h' files containing system-dependent +definitions. Finally, it creates a shell script 'config.status' that you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). +file 'config.log' containing compiler output (useful mainly for +debugging 'configure'). - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. + It can also use an optional file (typically called 'config.cache' and +enabled with '--cache-file=config.cache' or simply '-C') that saves the +results of its tests to speed up reconfiguring. Caching is disabled by +default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can +to figure out how 'configure' could check whether to do them, and mail +diffs or instructions to the address given in the 'README' so they can be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you +some point 'config.cache' contains results you don't want to keep, you may remove or edit it. - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. + The file 'configure.ac' (or 'configure.in') is used to create +'configure' by a program called 'autoconf'. You need 'configure.ac' if +you want to change it or regenerate 'configure' using a newer version of +'autoconf'. The simplest way to compile this package is: - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. + 1. 'cd' to the directory containing the package's source code and type + './configure' to configure the package for your system. - Running `configure' might take a while. While running, it prints + Running 'configure' might take a while. While running, it prints some messages telling which features it is checking for. - 2. Type `make' to compile the package. + 2. Type 'make' to compile the package. - 3. Optionally, type `make check' to run any self-tests that come with + 3. Optionally, type 'make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. - 4. Type `make install' to install the programs and any data files and + 4. Type 'make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular - user, and only the `make install' phase executed with root + user, and only the 'make install' phase executed with root privileges. - 5. Optionally, type `make installcheck' to repeat any self-tests, but + 5. Optionally, type 'make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a - regular user, particularly if the prior `make install' required + regular user, particularly if the prior 'make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly + source code directory by typing 'make clean'. To also remove the + files that 'configure' created (so you can compile the package for + a different kind of computer), type 'make distclean'. There is + also a 'make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. - 7. Often, you can also type `make uninstall' to remove the installed + 7. Often, you can also type 'make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. - 8. Some packages, particularly those that use Automake, provide `make + 8. Some packages, particularly those that use Automake, provide 'make distcheck', which can by used by developers to test that all other - targets like `make install' and `make uninstall' work correctly. + targets like 'make install' and 'make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' +the 'configure' script does not know about. Run './configure --help' for details on some of the pertinent environment variables. - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: + You can give 'configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here is +an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix @@ -113,21 +112,21 @@ Compiling For Multiple Architectures You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the +own directory. To do this, you can use GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. This -is known as a "VPATH" build. +the 'configure' script. 'configure' automatically checks for the source +code in the directory that 'configure' is in and in '..'. This is known +as a "VPATH" build. - With a non-GNU `make', it is safer to compile the package for one + With a non-GNU 'make', it is safer to compile the package for one architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before +installed the package for one architecture, use 'make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like +"universal" binaries--by specifying multiple '-arch' options to the +compiler but only a single '-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ @@ -136,105 +135,104 @@ this: This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. +using the 'lipo' tool if you have problems. Installation Names ================== - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX', where PREFIX must be an + By default, 'make install' installs the package's commands under +'/usr/local/bin', include files under '/usr/local/include', etc. You +can specify an installation prefix other than '/usr/local' by giving +'configure' the option '--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses +pass the option '--exec-prefix=PREFIX' to 'configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. In general, the -default for these options is expressed in terms of `${prefix}', so that -specifying just `--prefix' will affect all of the other directory +options like '--bindir=DIR' to specify different values for particular +kinds of files. Run 'configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the default +for these options is expressed in terms of '${prefix}', so that +specifying just '--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the -correct locations to `configure'; however, many packages provide one or +correct locations to 'configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the -`make install' command line to change installation locations without +'make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each -affected directory. For example, `make install +affected directory. For example, 'make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of -`${prefix}'. Any directories that were specified during `configure', -but not in terms of `${prefix}', must each be overridden at install -time for the entire installation to be relocated. The approach of -makefile variable overrides for each directory variable is required by -the GNU Coding Standards, and ideally causes no recompilation. -However, some platforms have known limitations with the semantics of -shared libraries that end up requiring recompilation when using this -method, particularly noticeable in packages that use GNU Libtool. +'${prefix}'. Any directories that were specified during 'configure', +but not in terms of '${prefix}', must each be overridden at install time +for the entire installation to be relocated. The approach of makefile +variable overrides for each directory variable is required by the GNU +Coding Standards, and ideally causes no recompilation. However, some +platforms have known limitations with the semantics of shared libraries +that end up requiring recompilation when using this method, particularly +noticeable in packages that use GNU Libtool. - The second method involves providing the `DESTDIR' variable. For -example, `make install DESTDIR=/alternate/directory' will prepend -`/alternate/directory' before all installation names. The approach of -`DESTDIR' overrides is not required by the GNU Coding Standards, and + The second method involves providing the 'DESTDIR' variable. For +example, 'make install DESTDIR=/alternate/directory' will prepend +'/alternate/directory' before all installation names. The approach of +'DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even -when some directory options were not specified in terms of `${prefix}' -at `configure' time. +when some directory options were not specified in terms of '${prefix}' +at 'configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. +with an extra prefix or suffix on their names by giving 'configure' the +option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the + Some packages pay attention to '--enable-FEATURE' options to +'configure', where FEATURE indicates an optional part of the package. +They may also pay attention to '--with-PACKAGE' options, where PACKAGE +is something like 'gnu-as' or 'x' (for the X Window System). The +'README' should mention any '--enable-' and '--with-' options that the package recognizes. - For packages that use the X Window System, `configure' can usually + For packages that use the X Window System, 'configure' can usually find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. +you can use the 'configure' options '--x-includes=DIR' and +'--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the -execution of `make' will be. For these packages, running `./configure +execution of 'make' will be. For these packages, running './configure --enable-silent-rules' sets the default to minimal output, which can be -overridden with `make V=1'; while running `./configure +overridden with 'make V=1'; while running './configure --disable-silent-rules' sets the default to verbose, which can be -overridden with `make V=0'. +overridden with 'make V=0'. Particular systems ================== - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in + On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC +is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. - HP-UX `make' updates targets which have the same time stamps as -their prerequisites, which makes it generally unusable when shipped -generated files such as `configure' are involved. Use GNU `make' -instead. + HP-UX 'make' updates targets which have the same time stamps as their +prerequisites, which makes it generally unusable when shipped generated +files such as 'configure' are involved. Use GNU 'make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try +parse its '' header file. The option '-nodtk' can be used as a +workaround. If GNU CC is not installed, it is therefore recommended to +try ./configure CC="cc" @@ -242,26 +240,26 @@ and if that doesn't work, try ./configure CC="cc -nodtk" - On Solaris, don't put `/usr/ucb' early in your `PATH'. This + On Solaris, don't put '/usr/ucb' early in your 'PATH'. This directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. +these programs are available in '/usr/bin'. So, if you need '/usr/ucb' +in your 'PATH', put it _after_ '/usr/bin'. - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: + On Haiku, software installed for all users goes in '/boot/common', +not '/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== - There may be some features `configure' cannot figure out + There may be some features 'configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints +_same_ architectures, 'configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: +'--build=TYPE' option. TYPE can either be a short name for the system +type, such as 'sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM @@ -270,101 +268,101 @@ where SYSTEM can have one of these forms: OS KERNEL-OS - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't + See the file 'config.sub' for the possible values of each field. If +'config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will +use the option '--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. +eventually be run) with '--host=TYPE'. Sharing Defaults ================ - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. + If you want to set default values for 'configure' scripts to share, +you can create a site shell script called 'config.site' that gives +default values for variables like 'CC', 'cache_file', and 'prefix'. +'configure' looks for 'PREFIX/share/config.site' if it exists, then +'PREFIX/etc/config.site' if it exists. Or, you can set the +'CONFIG_SITE' environment variable to the location of the site script. +A warning: not all 'configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run +environment passed to 'configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: +them in the 'configure' command line, using 'VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc -causes the specified `gcc' to be used as the C compiler (unless it is +causes the specified 'gcc' to be used as the C compiler (unless it is overridden in the site shell script). -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf limitation. Until the limitation is lifted, you can use -this workaround: +Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an +Autoconf limitation. Until the limitation is lifted, you can use this +workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash -`configure' Invocation +'configure' Invocation ====================== - `configure' recognizes the following options to control how it + 'configure' recognizes the following options to control how it operates. -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. +'--help' +'-h' + Print a summary of all of the options to 'configure', and exit. -`--help=short' -`--help=recursive' +'--help=short' +'--help=recursive' Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. + 'configure', and exit. The 'short' variant lists options used only + in the top level, while the 'recursive' variant lists options also + present in any nested packages. -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' +'--version' +'-V' + Print the version of Autoconf used to generate the 'configure' script, and exit. -`--cache-file=FILE' +'--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to + traditionally 'config.cache'. FILE defaults to '/dev/null' to disable caching. -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. +'--config-cache' +'-C' + Alias for '--cache-file=config.cache'. -`--quiet' -`--silent' -`-q' +'--quiet' +'--silent' +'-q' Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error + suppress all normal output, redirect it to '/dev/null' (any error messages will still be shown). -`--srcdir=DIR' +'--srcdir=DIR' Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. + 'configure' can determine that directory automatically. -`--prefix=DIR' - Use DIR as the installation prefix. *note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. +'--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: for + more details, including other options available for fine-tuning the + installation locations. -`--no-create' -`-n' +'--no-create' +'-n' Run the configure checks, but stop before creating any output files. -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. +'configure' also accepts some other, not widely useful, options. Run +'configure --help' for more details. diff --git a/Makefile.am b/Makefile.am index d2e6f3f..8e43fe5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = gnu -SUBDIRS = m4 src doc gui +SUBDIRS = src doc systemd ACLOCAL_AMFLAGS = -I m4 @@ -11,17 +11,5 @@ EXTRA_DIST = COPYING.README README.android 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 +astyle: + astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch] diff --git a/Makefile.in b/Makefile.in index 3ca1385..2940df5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -78,18 +88,19 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . -DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ - $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/configure $(am__configure_deps) \ - $(srcdir)/config.h.in COPYING THANKS compile config.guess \ - config.sub depcomp install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ - $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ - $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ - $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ax_append_flag.m4 \ + $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ + $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d @@ -130,9 +141,9 @@ am__recursive_targets = \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ - cscope distdir dist dist-all distcheck -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ - $(LISP)config.h.in + cscope distdir distdir-am dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. @@ -153,6 +164,9 @@ ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ + COPYING ChangeLog INSTALL NEWS README THANKS compile \ + config.guess config.sub depcomp install-sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -207,7 +221,6 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CURSES_LIBS = @CURSES_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ @@ -223,12 +236,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ -LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ @@ -241,8 +250,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ @@ -289,16 +296,18 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +systemd_path = @systemd_path@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = gnu -SUBDIRS = m4 src doc gui +SUBDIRS = src doc systemd ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = COPYING.README README.android all: config.h @@ -320,15 +329,14 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -341,8 +349,8 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): config.h: stamp-h1 - @if test ! -f $@; then rm -f stamp-h1; else :; fi - @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 @@ -461,7 +469,10 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @case `sed 15q $(srcdir)/NEWS` in \ *"$(VERSION)"*) : ;; \ *) \ @@ -532,7 +543,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -547,12 +558,22 @@ dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -570,7 +591,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -580,22 +601,25 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_inst + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -758,7 +782,7 @@ uninstall-am: am--refresh check check-am clean clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ - distcheck distclean distclean-generic distclean-hdr \ + dist-zstd distcheck distclean distclean-generic distclean-hdr \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ @@ -770,24 +794,14 @@ uninstall-am: mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am +.PRECIOUS: Makefile + 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 +astyle: + astyle --options=.astylerc -nQ src/*.[ch] src/*/*.[ch] # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/NEWS b/NEWS index 66ed06f..c587e87 100644 --- a/NEWS +++ b/NEWS @@ -1,125 +1,163 @@ -Version 1.1pre8 August 13 2013 +Version 1.0.36 August 26 2019 - * ExperimentalProtocol is now enabled by default. + * Fix compiling tinc with certain versions of the OpenSSL library. + * Fix parsing some IPv6 addresses with :: in them. + * Fix GraphDumpFile output to handle node names starting with a digit. + * Fix a potential segmentation fault when fragmenting packets. - * Added an invitation protocol that makes it easy to invite new nodes. +Thanks to Rosen Penev, Quentin Rameau and Werner Schreiber for their +contributions to this version of tinc. - * Added the LocalDiscoveryAddress option to change the broadcast address used - to find local nodes. +Version 1.0.35 October 5 2018 - * Limit the rate of incoming meta-connections. + * Prevent oracle attacks (CVE-2018-16737, CVE-2018-16738). + * Prevent a MITM from forcing a NULL cipher for UDP (CVE-2018-16758). + * Minor fixes in the documentation. - * Many small bug fixes and code cleanups. - -Thanks to Etienne Dechamps and Sven-Haegar Koch for their contributions to this +Thanks to Amine Amri and Rafael Sadowski for their contributions to this version of tinc. -Version 1.1pre7 April 22 2013 +Version 1.0.34 June 12 2018 - * Fixed large latencies on Windows. + * Fix a potential segmentation fault when connecting to an IPv6 peer via a + proxy. + * Minor improvements to the build system. + * Make the systemd service file identical to the one from the 1.1 branch. + * Fix a potential problem causing IPv4 sockets to not work on macOS. - * Renamed the tincctl tool to tinc. +Thanks to Maximilian Stein and Wang Liu Shuai for their contributions to this +version of tinc. - * Simplified changing the configuration using the tinc tool. +Version 1.0.33 November 4 2017 - * Added a full description of the ExperimentalProtocol to the manual. + * Allow compilation from a build directory. + * Source code cleanups. + * Fix some options specified on the command line not surviving a HUP signal. + * Handle tun/tap device returning EPERM or EBUSY. + * Disable PMTUDiscovery when TCPOnly is used. + * Support the --runstatedir option of the autoconf 2.70. - * Drop packets forwarded via TCP if they are too big (CVE-2013-1428). +Thanks to Rafael Sadowski and Pierre-Olivier Mercier for their contributions to +this version of tinc. -Thanks to Martin Schobert for auditing tinc and reporting the vulnerability. +Version 1.0.32 September 2 2017 -Version 1.1pre6 February 20 2013 + * Fix segmentation fault when using Cipher = none. + * Fix Proxy = exec. + * Support PriorityInheritance for IPv6 packets. + * Fixes for Solaris tun/tap support. + * Bind outgoing TCP sockets when ListenAddress is used. - * Fixed tincd exitting immediately on Windows. +Thanks to Vittorio Gambaletta for his contribution to this version of tinc. - * Detect PMTU increases. +Version 1.0.31 January 15 2017 - * Fixed crashes when using a SOCKS5 proxy. + * Remove ExecStop in tinc@.service. - * Fixed control connection when using a proxy. +Thanks to Élie Bouttier for his contribution to this version of tinc. -Version 1.1pre5 January 20 2013 +Version 1.0.30 October 30 2016 - * Fixed long delays and possible hangs on Windows. + * Fix troubles connecting to some HTTP proxies. - * Fixed support for the tunemu device on iOS, the UML and VDE devices. + * Add mitigations for the Sweet32 attack when using a 64-bit block cipher. - * Small improvements to the documentation and error messages. + * Use AES256 and SHA256 as the default encryption and digest algorithms. - * Fixed broadcast packets not reaching the whole VPN. +Version 1.0.29 October 9 2016 - * Tincctl now connects via a UNIX socket to the tincd on platforms that - support this. + * Fix UDP communication with peers with link-local IPv6 addresses. - * The PriorityInheritance option now also works in switch mode. + * Ensure compatibility with OpenSSL 1.1.0. -Version 1.1pre4 December 5 2012 + * Ensure autoreconf can be run without requiring autoconf-archive. - * Added the "AutoConnect" option which will let tinc automatically select - which nodes to connect to. + * Log warnings about dropped packets only at debug level 5. - * Improved performance of VLAN-tagged IP traffic inside the VPN. +Version 1.0.28 April 10 2016 - * Ensured LocalDiscovery works with multiple BindToAddress statements and/or - IPv6-only LANs. + * Fix compilation on BSD platforms. - * Dropped dependency on libevent. + * Add systemd service files. - * Fixed Windows version not reading packets from the TAP adapter. +Version 1.0.27 April 10 2016 -Version 1.1pre3 October 14 2012 + * When using Proxy, let the proxy resolve hostnames if tinc can't. - * New experimental protocol: - * Uses 521 bit ECDSA keys for authentication. - * Uses AES-256-CTR and HMAC-SHA256. - * Always provides perfect forward secrecy. - * Used for both meta-connections and VPN packets. - * VPN packets are encrypted end-to-end. + * Fixes and improvements of the DecrementTTL option. - * Many improvements to tincctl: - * "config" command shows/adds/changes configuration variables. - * "export" and "import" commands help exchange configuration files. - * "init" command sets up initial configuration files. - * "info" command shows details about a node, subnet or address. - * "log" command shows live log messages. - * Without a command it acts as a shell, with history and TAB completion. - * Improved starting/stopping tincd. - * Improved graph output. + * Fixed the $NAME variable in subnet-up/down scripts for the local Subnets. - * When trying to directly send UDP packets to a node for which multiple - addresses are known, all of them are tried. + * Fixed potentially wrong checksum generation when clamping the MSS. - * Many small fixes, code cleanups and documentation updates. + * Properly choose between the system's or our own copy of getopt. -Version 1.1pre2 July 17 2011 + * Fixed compiling tinc for Cygwin with MinGW installed. - * .cookie files are renamed to .pid files, which are compatible with 1.0.x. + * Added support for OS X utun interfaces. - * Experimental protocol enhancements that can be enabled with the option - ExperimentalProtocol = yes: + * Documentation updates and minor fixes. - * Ephemeral ECDH key exchange will be used for both the meta protocol and - UDP session keys. - * Key exchanges are signed with ECDSA. - * ECDSA public keys are automatically exchanged after RSA authentication if - nodes do not know each other's ECDSA public key yet. +Thanks to Vittorio Gambaletta, LunarShaddow, Florian Weik and Nathan Stratton +Treadway for their contributions to this version of tinc. -Version 1.1pre1 June 25 2011 +Version 1.0.26 July 5 2015 - * Control interface allows control of a running tinc daemon. Used by: - * tincctl, a commandline utility - * tinc-gui, a preliminary GUI implemented in Python/wxWidgets + * Tinc now forces glibc to reload /etc/resolv.conf for every hostname lookup. - * Code cleanups and reorganization. + * Fixed --logfile without a filename on Windows. - * Repleacable cryptography backend, currently supports OpenSSL and libgcrypt. + * Ensure tinc can be compiled when using musl libc. - * Use libevent to handle I/O events and timeouts. +Thanks to Jo-Philipp Wich for his contribution to this version of tinc. - * Use splay trees instead of AVL trees to manage internal datastructures. +Version 1.0.25 December 22 2014 - Thanks to Scott Lamb and Sven-Haegar Koch for their contributions to this - version of tinc. + * Documentation updates. + + * Support linking against -lresolv on Mac OS X. + + * Fix scripts on Windows when using the ScriptsInterpreter option. + + * Allow a minimum reconnect timeout to be specified. + + * Support PriorityInheritance on IPv6 sockets. + +Thanks to David Pflug, Baptiste Jonglez, Alexis Hildebrandt, Borg, Jochen Voss, +Tomislav Čohar and VittGam for their contributions to this version of tinc. + +Version 1.0.24 May 11 2014 + + * Various compiler hardening flags are enabled by default. + + * Updated support for Solaris, allowing switch mode on Solaris 11. + + * Configuration will now also be read from a conf.d directory. + + * Various updates to the documentation. + + * Tinc now forces glibc to reload /etc/resolv.conf after it receives SIGALRM. + + * Fixed a potential routing loop when IndirectData or TCPOnly is used and + broadcast packets are being sent. + + * Improved security with constant time memcmp and stricter use of OpenSSL's + RNG functions. + + * Fixed all issues found by Coverity. + +Thanks to Florent Clairambault, Vilbrekin, luckyhacky, Armin Fisslthaler, Loïc +Dachary and Steffan Karger for their contributions to this version of tinc. + +Version 1.0.23 October 19 2013 + + * Start authentication immediately on outgoing connections (useful for sslh). + + * Fixed segfault when Name = $HOST but $HOST is not set. + + * Updated the build system and the documentation. + + * Clean up child processes left over from Proxy = exec. Version 1.0.22 August 13 2013 @@ -172,6 +210,9 @@ Version 1.0.19 June 25 2012 * Add basic support for SOCKS proxies, HTTP proxies, and proxying through an external command. +Thanks to Anthony G. Basile and Michael Tokarev for their contributions to +this version of tinc. + Version 1.0.18 March 25 2012 * Fixed IPv6 in switch mode by turning off DecrementTTL by default. @@ -198,6 +239,8 @@ Version 1.0.17 March 10 2012 * Disabling old RSA keys when generating new ones now also works properly on Windows. +Thanks to Nick Hibma for his contribution to this version of tinc. + Version 1.0.16 July 23 2011 * Fixed a performance issue with TCP communication under Windows. @@ -213,8 +256,6 @@ Version 1.0.15 June 24 2011 * Fixed ProcessPriority option under Windows. - Thanks to Loïc Grenié for his contribution to this version of tinc. - Version 1.0.14 May 8 2011 * Fixed reading configuration files that do not end with a newline. Again. @@ -330,7 +371,7 @@ Version 1.0.9 Dec 26 2008 * Enable path MTU discovery by default. - * Fixed a memory leak that occured when connections were closed. + * Fixed a memory leak that occurred when connections were closed. Thanks to Max Rijevski for his contributions to this version of tinc. @@ -356,13 +397,13 @@ Version 1.0.6 Dec 18 2006 * Fixed a bug where broadcasts in switch and hub modes sometimes would not work anymore when part of the VPN had become disconnected from the rest. -Version 1.0.5 Nov 14 2006 +version 1.0.5 Nov 14 2006 * Lots of small fixes. * Broadcast packets no longer grow in size with each hop. This should fix switch mode (again). - + * Generic host-up and host-down scripts. * Optionally dump graph in graphviz format to a file or a script. @@ -371,354 +412,347 @@ Version 1.0.5 Nov 14 2006 Thanks to Scott Lamb for his contributions to this version of tinc. -Version 1.0.4 May 4 2005 +version 1.0.4 May 4 2005 * Fix switch and hub modes. * Optionally start scripts when a Subnet becomes (un)reachable. -Version 1.0.3 Nov 11 2004 +version 1.0.3 Nov 11 2004 - * Show error message when failing to write a PID file. +* Show error message when failing to write a PID file. - * Ignore spaces at end of lines in config files. +* Ignore spaces at end of lines in config files. - * Fix handling of late packets. +* Fix handling of late packets. - * Unify BSD tun/tap device handling. This allows IPv6 on tun devices and - anything on tap devices as long as the underlying OS supports it. +* Unify BSD tun/tap device handling. This allows IPv6 on tun devices and + anything on tap devices as long as the underlying OS supports it. - * Handle IPv6 on Solaris tun devices. +* Handle IPv6 on Solaris tun devices. - * Allow tinc to work properly under Windows XP SP2. +* Allow tinc to work properly under Windows XP SP2. - * Allow VLAN tagged Ethernet frames in switch and hub mode. +* Allow VLAN tagged Ethernet frames in switch and hub mode. - * Experimental PMTUDiscovery, TunnelServer and BlockingTCP options. +* Experimental PMTUDiscovery, TunnelServer and BlockingTCP options. -Version 1.0.2 Nov 8 2003 +version 1.0.2 Nov 8 2003 - * Fix address and hostname resolving under Windows. +* Fix address and hostname resolving under Windows. - * Remove warnings about non-existing scripts and unsupported address families. +* Remove warnings about non-existing scripts and unsupported address families. - * Use the event logger under Windows. +* Use the event logger under Windows. - * Fix quoting of filenames and command line arguments under Windows. +* Fix quoting of filenames and command line arguments under Windows. - * Strict checks for length incoming network packets and return values of - cryptographic functions, +* Strict checks for length incoming network packets and return values of + cryptographic functions, - * Fix a bug in metadata handling that made the tinc daemon abort. +* Fix a bug in metadata handling that made the tinc daemon abort. -Version 1.0.1 Aug 14 2003 +version 1.0.1 Aug 14 2003 - * Allow empty lines in config files. +* Allow empty lines in config files. - * Fix handling of spaces and backslashes in filenames under native Windows. +* Fix handling of spaces and backslashes in filenames under native Windows. - * Allow scripts to be executed under native Windows. +* Allow scripts to be executed under native Windows. - * Update documentation, make it less Linux specific. +* Update documentation, make it less Linux specific. -Version 1.0 Aug 4 2003 +version 1.0 Aug 4 2003 - * Lots of small bugfixes and code cleanups. +* Lots of small bugfixes and code cleanups. - * Throughput doubled and latency reduced. +* Throughput doubled and latency reduced. - * Added support for LZO compression. +* Added support for LZO compression. - * No need to set MAC address or disable ARP anymore. +* No need to set MAC address or disable ARP anymore. - * Added support for Windows 2000 and XP, both natively and in a Cygwin - environment. +* Added support for Windows 2000 and XP, both natively and in a Cygwin + environment. -Version 1.0pre8 Sep 16 2002 +version 1.0pre8 Sep 16 2002 - * More fixes for subnets with prefixlength undivisible by 8. +* More fixes for subnets with prefixlength undivisible by 8. - * Added support for NetBSD and MacOS/X. +* Added support for NetBSD and MacOS/X. - * Switched from undirected graphs to directed graphs to avoid certain race - conditions and improve scalability. +* Switched from undirected graphs to directed graphs to avoid certain race + conditions and improve scalability. - * Generalized broadcasting and forwarding of protocol messages. +* Generalized broadcasting and forwarding of protocol messages. - * Cleanup of source code. +* Cleanup of source code. -Version 1.0pre7 Apr 7 2002 - * Don't do blocking read()s when getting a signal. +version 1.0pre7 Apr 7 2002 - * Remove RSA key checking code, since it sometimes thinks perfectly good RSA - keys are bad. +* Don't do blocking read()s when getting a signal. - * Fix handling of subnets when prefixlength isn't divisible by 8. +* Remove RSA key checking code, since it sometimes thinks perfectly good RSA + keys are bad. -Version 1.0pre6 Mar 27 2002 +* Fix handling of subnets when prefixlength isn't divisible by 8. - * Improvement of redundant links: - * Non-blocking connects. - * Protocol broadcast messages can no longer go into an infinite loop. - * Graph algorithm updated to look harder for direct connections. - * Good support for routing IPv6 packets over the VPN. Works on Linux, - FreeBSD, possibly OpenBSD but not on Solaris. +version 1.0pre6 Mar 27 2002 - * Support for tunnels over IPv6 networks. Works on all supported - operating systems. +* Improvement of redundant links: - * Optional compression of UDP connections using zlib. + * Non-blocking connects. + + * Protocol broadcast messages can no longer go into an infinite loop. + + * Graph algorithm updated to look harder for direct connections. - * Optionally let UDP connections inherit TOS field of tunneled packets. +* Good support for routing IPv6 packets over the VPN. Works on Linux, + FreeBSD, possibly OpenBSD but not on Solaris. - * Optionally start scripts when certain hosts become (un)reachable. +* Support for tunnels over IPv6 networks. Works on all supported + operating systems. -Version 1.0pre5 Feb 9 2002 +* Optional compression of UDP connections using zlib. - * Security enhancements: - * Added sequence number and optional message authentication code to - the packets. - * Configurable encryption cipher and digest algorithms. +* Optionally let UDP connections inherit TOS field of tunneled packets. - * More robust handling of dis- and reconnects. +* Optionally start scripts when certain hosts become (un)reachable. - * Added a "switch" and a "hub" mode to allow bridging setups. - * Preliminary support for routing of IPv6 packets. +version 1.0pre5 Feb 9 2002 - * Supports Linux, FreeBSD, OpenBSD and Solaris. +* Security enhancements: -Version 1.0pre4 Jan 17 2001 + * Added sequence number and optional message authentication code to + the packets. - * Updated documentation; the documentation now reflects the - configuration as it is. + * Configurable encryption cipher and digest algorithms. - * Some internal changes to make tinc scale better for large - networks, such as using AVL trees instead of linked lists for the - connection list. +* More robust handling of dis- and reconnects. - * RSA keys can be stored in separate files if needed. See the - documentation for more information. +* Added a "switch" and a "hub" mode to allow bridging setups. - * Tinc has now been reported to run on Linux PowerPC and FreeBSD x86. +* Preliminary support for routing of IPv6 packets. -Version 1.0pre3 Oct 31 2000 +* Supports Linux, FreeBSD, OpenBSD and Solaris. - * The protocol has been redesigned, and although some details are - still under discussion, this is secure. Care has been taken to - resist most, if not all, attacks. - * Unfortunately this protocol is not compatible with earlier versions, - nor are earlier versions compatible with this version. Because the - older protocol has huge security flaws, we feel that not - implementing backwards compatibility is justified. +It looks like this might be the last release before 1.0. - * Some data about the protocol: - * It uses public/private RSA keys for authentication (this is the - actual fix for the security hole). - * All cryptographic functions have been taken out of tinc, instead - it uses the OpenSSL library functions. - * Offers support for multiple subnets per tinc daemon. - * New is also the support for the universal tun/tap device. This - means better portability to FreeBSD and Solaris. +version 1.0pre4 Jan 17 2001 - * Tinc is tested to compile on Solaris, Linux x86, Linux alpha. +* Updated documentation; the documentation now reflects the + configuration as it is. - * Tinc now uses the OpenSSL library for cryptographic operations. - More information on getting and installing OpenSSL is in the manual. - This also means that the GMP library is no longer required. +* Some internal changes to make tinc scale better for large + networks, such as using AVL trees instead of linked lists for the + connection list. - * Further, thanks to Enrique Zanardi, we have Spanish messages; Matias - Carrasco provided us with a Spanish translation of the manual. +* RSA keys can be stored in separate files if needed. See the + documentation for more information. -Version 1.0pre2 May 31 2000 +* tinc has now been reported to run on Linux PowerPC and FreeBSD x86. - * This version has been internationalized; and a Dutch translation has - been included. - * Two configuration variables have been added: - * VpnMask - the IP network mask for the entire VPN, not just our - subnet (as given by MyVirtualIP). The Redhat and Debian packages - use this variable in their system startup scripts, but it is - ignored by tinc. - * Hostnames - if set to `yes', look up the names of IP addresses - trying to connect to us. Default set to `no', to prevent lockups - during lookups. - * The system startup scripts for Debian and Redhat use - /etc/tinc/nets.boot to find out which networks need to be started - during system boot. +version 1.0pre3 Oct 31 2000 - * Fixes to prevent denial of service attacks by sending random data - after connecting (and even when the connection has been established), - either random garbage or just nonsensical protocol fields. +* The protocol has been redesigned, and although some details are + still under discussion, this is secure. Care has been taken to + resist most, if not all, attacks. + +* Unfortunately this protocol is not compatible with earlier versions, + nor are earlier versions compatible with this version. Because the + older protocol has huge security flaws, we feel that not + implementing backwards compatibility is justified. - * Tinc will retry to connect upon startup, does not quit if it doesn't - work the first time. +* Some data about the protocol: - * Hosts that are disconnected implicitly if we lose a connection get - deleted from the internal list, to prevent hogging eachother with - add and delete requests when the connection is restored. + * It uses public/private RSA keys for authentication (this is the + actual fix for the security hole). -Version 1.0pre1 May 12 2000 + * All cryptographic functions have been taken out of tinc, instead + it uses the OpenSSL library functions. + * Offers support for multiple subnets per tinc daemon. + +* New is also the support for the universal tun/tap device. This + means better portability to FreeBSD and Solaris. + +* tinc is tested to compile on Solaris, Linux x86, Linux alpha. + +* tinc now uses the OpenSSL library for cryptographic operations. + More information on getting and installing OpenSSL is in the manual. + This also means that the GMP library is no longer required. + +* Further, thanks to Enrique Zanardi, we have Spanish messages; Matias + Carrasco provided us with a Spanish translation of the manual. + + +What still needs to be done before 1.0: + +* Documentation. Especially since the protocol has changed, and a lot + of configuration directives have been added. + + + + +version 1.0pre2 May 31 2000 + +* This version has been internationalized; and a Dutch translation has + been included. + +* Two configuration variables have been added: + * VpnMask - the IP network mask for the entire VPN, not just our + subnet (as given by MyVirtualIP). The Redhat and Debian packages + use this variable in their system startup scripts, but it is + ignored by tinc. + * Hostnames - if set to `yes', look up the names of IP addresses + trying to connect to us. Default set to `no', to prevent lockups + during lookups. + +* The system startup scripts for Debian and Redhat use + /etc/tinc/nets.boot to find out which networks need to be started + during system boot. + +* Fixes to prevent denial of service attacks by sending random data + after connecting (and even when the connection has been established), + either random garbage or just nonsensical protocol fields. + +* tinc will retry to connect upon startup, does not quit if it doesn't + work the first time. + +* Hosts that are disconnected implicitly if we lose a connection get + deleted from the internal list, to prevent hogging eachother with + add and delete requests when the connection is restored. + + +What still needs to be done before 1.0: + +* Documentation. +* Failover ConnectTo lines, try another one if the first doesn't work. + + + + +version 1.0pre1 May 12 2000 * New meta-protocol - * Various other bugfixes - * Documentation updates -Version 0.3.3 Feb 9 2000 - - * Fixed bug that made tinc stop working with latest kernels - +version 0.3.3 Feb 9 2000 + * Fixed bug that made tinc stop working with latest kernels (Guus + Sliepen) * Updated the manual -Version 0.3.2 Nov 12 1999 +version 0.3.2 Nov 12 1999 + * no more `Invalid filedescriptor' when working with multiple + connections + * forward unknown packets to uplink - * No more `Invalid filedescriptor' when working with multiple - connections. +version 0.3.1 Oct 20 1999 + * fixed a bug where tinc would exit without a trace - * Forward unknown packets to uplink. +version 0.3 Aug 20 1999 + * pings now work immediately + * all packet sizes get transmitted correctly -Version 0.3.1 Oct 20 1999 +version 0.2.26 Aug 15 1999 + * fixed some remaining bugs + * --sysconfdir works with configure + * last version before 0.3 - * Fixed a bug where tinc would exit without a trace. +version 0.2.25 Aug 8 1999 + * improved stability, going towards 0.3 now. -Version 0.3 Aug 20 1999 +version 0.2.24 Aug 7 1999 + * added key aging, there's a new config variable, KeyExpire. + * updated man and info pages - * Pings now work immediately. +version 0.2.23 Aug 5 1999 + * all known bugs fixed, this is a candidate for 0.3 - * All packet sizes get transmitted correctly. - -Version 0.2.26 Aug 15 1999 - - * Fixed some remaining bugs. - - * --sysconfdir works with configure. - - * Last version before 0.3. - -Version 0.2.25 Aug 8 1999 - - * Improved stability, going towards 0.3 now. - -Version 0.2.24 Aug 7 1999 - - * Added key aging, there's a new config variable, KeyExpire. - - * Updated man and info pages. - -Version 0.2.23 Aug 5 1999 - - * All known bugs fixed, this is a candidate for 0.3. - -Version 0.2.22 Apr 11 1999 - - * Multiconnection thing is now working nearly perfect :) - -Version 0.2.21 Apr 10 1999 +version 0.2.22 Apr 11 1999 + * multiconnection thing is now working nearly perfect :) +version 0.2.21 Apr 10 1999 * You shouldn't notice a thing, but a lot has changed wrt key management - except that it refuses to talk to versions < 0.2.20 -Version 0.2.19 Apr 3 1999 +version 0.2.20 - * Don't install a libcipher.so. +version 0.2.19 Apr 3 1999 + * don't install a libcipher.so -Version 0.2.18 Apr 3 1999 +version 0.2.18 Apr 3 1999 + * blowfish library dynamically loaded upon execution + * included Eric Young's IDEA library - * Blowfish library dynamically loaded upon execution. +version 0.2.17 Apr 1 1999 + * tincd now re-executes itself in case of a segmentation fault. - * Included Eric Young's IDEA library. +version 0.2.16 Apr 1 1999 + * wrote tincd.conf(5) man page, which still needs a lot of work. + * config file now accepts and tolerates spaces, and any integer base +for integer variables, and better error reporting. See +doc/tincd.conf.sample for an example. -Version 0.2.17 Apr 1 1999 +version 0.2.15 Mar 29 1999 + * fixed bugs - * Tincd now re-executes itself in case of a segmentation fault. +version 0.2.14 Feb 10 1999 + * added --timeout flag and PingTimeout configuration + * did some first syslog cleanup work -Version 0.2.16 Apr 1 1999 +version 0.2.13 Jan 23 1999 + * bugfixes - * Wrote tincd.conf(5) man page, which still needs a lot of work. +version 0.2.12 Jan 23 1999 + * fixed nauseating bug so that it would crash whenever a connection +got lost - * Config file now accepts and tolerates spaces, and any integer base - for integer variables, and better error reporting. See - doc/tincd.conf.sample for an example. +version 0.2.11 Jan 22 1999 + * framework for multiple connections has been done + * simple manpage for tincd -Version 0.2.15 Mar 29 1999 +version 0.2.10 Jan 18 1999 + * passphrase support added - * Fixed bugs. +version 0.2.9 Jan 13 1999 + * bugs fixed. -Version 0.2.14 Feb 10 1999 +version 0.2.8 Jan 11 1999 + * a reworked protocol version + * a ping/pong system + * more reliable networking code + * automatic reconnection + * still does not work with more than one connection :) + * strips MAC addresses before sending, so there's less overhead, and +less redundancy - * Added --timeout flag and PingTimeout configuration. - * Did some first syslog cleanup work. - -Version 0.2.13 Jan 23 1999 - - * Bugfixes. - -Version 0.2.12 Jan 23 1999 - - * Fixed nauseating bug so that it would crash whenever a connection - got lost. - -Version 0.2.11 Jan 22 1999 - - * Framework for multiple connections has been done. - - * Simple manpage for tincd. - -Version 0.2.10 Jan 18 1999 - - * Passphrase support added. - -Version 0.2.9 Jan 13 1999 - - * Bugs fixed. - -Version 0.2.8 Jan 11 1999 - - * A reworked protocol version. - - * A ping/pong system. - - * More reliable networking code. - - * Automatic reconnection. - - * Still does not work with more than one connection :) - - * Strips MAC addresses before sending, so there's less overhead, and - less redundancy. - -Version 0.2.7 Jan 3 1999 - - * Several updates to make extending more easy. - -Version 0.2.6 Dec 20 1998 +version 0.2.7 Jan 3 1999 + * several updates to make extending more easy. +version 0.2.6 Dec 20 1998 * Point-to-Point connections have been established, including - Blowfish encryption and a secret key-exchange. - -Version 0.2.5 Dec 16 1998 +blowfish encryption and a secret key-exchange. +version 0.2.5 Dec 16 1998 * Project renamed to tinc, in honour of TINC. -Version 0.2.4 Dec 16 1998 +version 0.2.4 Dec 16 1998 + * now it really does ;) - * Now it really does ;) +version 0.2.3 Nov 24 1998 + * it sort of works now -Version 0.2.3 Nov 24 1998 +version 0.2.2 Nov 20 1998 + * uses GNU gmp. - * It sort of works now. - -Version 0.2.2 Nov 20 1998 - - * Uses GNU gmp. - -Version 0.2.1 Nov 14 1998 +version 0.2.1 Nov 14 1998 * Bare version. diff --git a/README b/README index 73eb070..127cde2 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ -This is the README file for tinc version 1.1pre8. Installation +This is the README file for tinc version 1.0.36. Installation instructions may be found in the INSTALL file. -tinc is Copyright (C) 1998-2013 by: +tinc is Copyright (C) 1998-2019 by: Ivo Timmermans, Guus Sliepen , @@ -15,81 +15,119 @@ the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING for more details. -This is a pre-release ---------------------- - -Please note that this is NOT a stable release. Until version 1.1.0 is released, -please use one of the 1.0.x versions if you need a stable version of tinc. - -Although tinc 1.1 will be protocol compatible with tinc 1.0.x, the -functionality of the tinc program may still change, and the control socket -protocol is not fixed yet. - - Security statement ------------------ -This version uses an experimental and unfinished cryptographic protocol. Use it -at your own risk. +In August 2000, we discovered the existence of a security hole in all versions +of tinc up to and including 1.0pre2. This had to do with the way we exchanged +keys. Since then, we have been working on a new authentication scheme to make +tinc as secure as possible. The current version uses the OpenSSL library and +uses strong authentication with RSA keys. + +On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc +1.0pre4. Due to a lack of sequence numbers and a message authentication code +for each packet, an attacker could possibly disrupt certain network services or +launch a denial of service attack by replaying intercepted packets. The current +version adds sequence numbers and message authentication codes to prevent such +attacks. + +On September the 15th of 2003, Peter Gutmann contacted us and showed us a +writeup describing various security issues in several VPN daemons. He showed +that tinc lacks perfect forward security, the connection authentication could +be done more properly, that the sequence number we use as an IV is not the best +practice and that the default length of the HMAC for packets is too short in +his opinion. We do not know of a way to exploit these weaknesses, but these +issues are being addressed in the tinc 1.1 branch. + +The Sweet32 attack affects versions of tinc prior to 1.0.30. + +On September 6th, 2018, Michael Yonly contacted us and provided +proof-of-concept code that allowed a remote attacker to create an +authenticated, one-way connection with a node, and also that there was a +possibility for a man-in-the-middle to force UDP packets from a node to be sent +in plaintext. The first issue was trivial to exploit on tinc versions prior to +1.0.30, but the changes in 1.0.30 to mitigate the Sweet32 attack made this +weakness much harder to exploit. These issues have been fixed in tinc 1.0.35. +The new protocol in the tinc 1.1 branch is not susceptible to these issues. + +Cryptography is a hard thing to get right. We cannot make any +guarantees. Time, review and feedback are the only things that can +prove the security of any cryptographic product. If you wish to review +tinc or give us feedback, you are strongly encouraged to do so. Compatibility ------------- -Version 1.1pre8 is compatible with 1.0pre8, 1.0 and later, but not with older -versions of tinc. - -When the ExperimentalProtocol option is used, which is the default since -1.1pre8, tinc is still compatible with 1.0.X and 1.1pre8 itself, but not with -any other 1.1preX version. +Version 1.0.35 is compatible with 1.0pre8, 1.0 and later, but not with older +versions of tinc. Note that since version 1.0.30, tinc requires all nodes in +the VPN to be compiled with a version of LibreSSL or OpenSSL that supports the +AES256 and SHA256 algorithms. Requirements ------------ -In order to compile tinc, you will need a GNU C compiler environment. Please -ensure you have the latest stable versions of all the required libraries: +The OpenSSL library is used for all cryptographic functions. You can find it at +https://www.openssl.org/. You will need version 1.0.1 or later with support for +AES256 and SHA256 enabled. If this library is not installed on your system, the +configure script will fail. The manual in doc/tinc.texi contains more detailed +information on how to install this library. Alternatively, you may also use the +LibreSSL library. -- OpenSSL (http://www.openssl.org/) version 1.0.0 or later, with support for - elliptic curve cryptography (ECC) enabeld. +The zlib library is used for optional compression. You can +find it at https://zlib.net/. Because of a possible exploit in +earlier versions we recommend that you download version 1.1.4 or later. -The following libraries are used by default, but can be disabled if necessary: +The LZO library is also used for optional compression. You can +find it at https://www.oberhumer.com/opensource/lzo/. -- zlib (http://www.gzip.org/zlib/) -- lzo (http://www.oberhumer.com/opensource/lzo/) -- ncurses (http://invisible-island.net/ncurses/) -- readline (ftp://ftp.gnu.org/pub/gnu/readline/) +In order to compile tinc, you will need a C99 compliant compiler. Features -------- -Tinc is a peer-to-peer VPN daemon that supports VPNs with an arbitrary number -of nodes. Instead of configuring tunnels, you give tinc the location and -public key of a few nodes in the VPN. After making the initial connections to -those nodes, tinc will learn about all other nodes on the VPN, and will make -connections automatically. When direct connections are not possible, data will -be forwarded by intermediate nodes. +This version of tinc supports multiple virtual networks at once. To +use this feature, you may supply a netname via the -n or --net +options. The standard locations for the config files will then be +/etc/tinc//. -By default, nodes authenticate each other using 2048 bit RSA (or 521 bit -ECDSA*) keys. Traffic is encrypted using Blowfish in CBC mode (or AES-256 in -CTR mode*), authenticated using HMAC-SHA1 (or HMAC-SHA-256*), and is protected -against replay attacks. +tincd regenerates its encryption key pairs. It does this on the first +activity after the keys have expired. This period is adjustable in the +configuration file, and the default time is 3600 seconds (one hour). -*) When using the ExperimentalProtocol option. +This version supports multiple subnets at once. They are also sorted +on subnet mask size. This means that it is possible to have +overlapping subnets on the VPN, as long as their subnet mask sizes +differ. -Tinc fully supports IPv6. +Since pre5, tinc can operate in several routing modes. The default mode, +"router", works exactly like the older version, and uses Subnet lines to +determine the destination of packets. The other two modes, "switch" and "hub", +allow the tinc daemons to work together like a single network switch or hub. +This is useful for bridging networks. The latter modes only work properly on +Linux, FreeBSD and Windows. -Tinc can operate in several routing modes. In the default mode, "router", every -node is associated with one or more IPv4 and/or IPv6 Subnets. The other two -modes, "switch" and "hub", let the tinc daemons work together to form a virtual -Ethernet network switch or hub. +The algorithms used for encryption and generating message authentication codes +can now be changed in the configuration files. All cipher and digest algorithms +supported by OpenSSL can be used. Useful ciphers are "blowfish" (default), +"bf-ofb", "des", "des3", et cetera. Useful digests are "sha1" (default), "md5", +et cetera. + +Support for routing IPv6 packets has been added. Just add Subnet lines with +IPv6 addresses (without using :: abbreviations) and use ifconfig or ip (from +the iproute package) to give the virtual network interface corresponding IPv6 +addresses. tinc does not provide autoconfiguration for IPv6 hosts. Consider +using radvd or zebra if you need it. + +It is also possible to make tunnels to other tinc daemons over IPv6 networks, +if the operating system supports IPv6. tinc will automatically use both IPv6 +and IPv4 when available, but this can be changed by adding the option +"AddressFamily = ipv4" or "AddressFamily = ipv6" to the tinc.conf file. Normally, when started tinc will detach and run in the background. In a native -Windows environment this means tinc will intall itself as a service, which will +Windows environment this means tinc will install itself as a service, which will restart after reboots. To prevent tinc from detaching or running as a service, use the -D option. -The status of the VPN can be queried using the "tinc" command, which connects -to a running tinc daemon via a control connection. The same tool also makes it -easy to start and stop tinc, and to change its configuration. diff --git a/README.android b/README.android index 6fffe41..7925bdb 100644 --- a/README.android +++ b/README.android @@ -1,20 +1,25 @@ -Quick how-o cross compile tinc for android (done from $HOME/android/): +Quick how-to cross compile tinc for android (done from $HOME/android/): - Download android NDK and setup local ARM toolchain: -wget http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2 -tar xfj android-ndk-r8b-linux-x86.tar.bz2 -./android-ndk-r8b/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain +wget http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2 +tar xfj android-ndk-r9d-linux-x86.tar.bz2 +./android-ndk-r9d/build/tools/make-standalone-toolchain.sh --platform=android-5 --install-dir=/tmp/my-android-toolchain - Download and cross-compile openSSL for ARM: -wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz -tar xfz openssl-1.0.1c.tar.gz -cd openssl-1.0.1c +wget http://www.openssl.org/source/openssl-1.0.1h.tar.gz +tar xfz openssl-1.0.1h.tar.gz +cd openssl-1.0.1h ./Configure dist make CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc AR="/tmp/my-android-toolchain/bin/arm-linux-androideabi-ar r" RANLIB=/tmp/my-android-toolchain/bin/arm-linux-androideabi-ranlib +cd - - Clone and cross-compile tinc: git clone git://tinc-vpn.org/tinc cd tinc autoreconf -fsi -CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux --disable-lzo --with-openssl-lib=$HOME/android/openssl-1.0.1c --with-openssl-include=$HOME/android/openssl-1.0.1c/include/ +CC=/tmp/my-android-toolchain/bin/arm-linux-androideabi-gcc ./configure --host=arm-linux --disable-lzo --with-openssl-lib=$HOME/android/openssl-1.0.1g --with-openssl-include=$HOME/android/openssl-1.0.1g/include/ --disable-hardening make -j5 + +- Strip tincd binary to make it smaller +/tmp/my-android-toolchain/bin/arm-linux-androideabi-strip src/tincd + diff --git a/THANKS b/THANKS index 6753c2f..a0f7966 100644 --- a/THANKS +++ b/THANKS @@ -1,60 +1,126 @@ We would like to thank the following people for their contributions to tinc: * Alexander Reil and Gemeinde Berg +* Alexander Ried +* Alexis Hildebrandt * Allesandro Gatti * Andreas van Cranenburgh +* Andrew Hahn * Anthony G. Basile * Armijn Hemel +* Armin Fisslthaler +* Aron Cowan +* Ashish Bajaj +* Baptiste Jonglez +* Borg * Brandon Black * Cheng LI * Cris van Pelt * Darius Jahandarie +* Dato Simó +* David Pflug * Delf Eldkraft +* Dennis Joachimsthaler * dnk +* Егор Палкин +* Élie Bouttier * Enrique Zanardi * Erik Tews * Etienne Dechamps +* Florent Clairambault +* Florian Forster +* Florian Klink +* Florian Weik * Flynn Marquardt +* Franz Pletz +* Gary Kessler and Claudia Gonzalez * Grzegorz Dymarek +* Gusariev Oleksandr * Hans Bayle +* Harvest * Ivo van Dong +* Ivo Smits +* James Cook * James MacLean * Jamie Briggs +* Jan Štembera * Jason Harper +* Jason Livesay +* Jasper Krijgsman +* Jelle de Jong +* Jeroen Domburg * Jeroen Ubbink * Jerome Etienne +* Jo-Philipp Wich +* Jochen Voss * Julien Muchembled +* Lavrans Laading +* Loïc Dachary * Loïc Grenié * Lubomír Bulej +* luckyhacky +* LunarShaddow * Mads Kiilerich * Marc A. Lehmann * Mark Glines +* Mark Petryk * Markus Goetz * Martin Kihlgren * Martin Schobert * Martin Schürrer +* Martin Weinelt * Matias Carrasco * Max Rijevski * Menno Smits * Mesar Hameed +* Michael Taylor * Michael Tokarev +* Michael Yonli * Miles Nordin +* Nathan Stratton Treadway +* Murat Donmez * Nick Hibma * Nick Patavalis * Paul Littlefield * Philipp Babel +* Pierre Emeriaud +* Pierre-Olivier Mercier +* Rafael Wolf +* Rafael Sadowski +* Rafał Leśniak +* Rhosyn Celyn * Robert van der Meulen +* Robert Waniek * Rumko +* Ryan Miller +* Sam Bryan +* Samuel Thibault +* Saverio Proto * Scott Lamb +* Steffan Karger +* Stig Fagrell * Sven-Haegar Koch * Teemu Kiviniemi +* Thomas Tsiakalakis * Timothy Redaelli +* Tomasz Fortuna +* Tomislav Čohar +* Tommy Arnkværn * Tonnerre Lombard +* Ulrich Seifert * Vil Brekin +* Vincent Laurent +* Vittorio Gambaletta +* Wendy Willard * Wessel Dankers +* William A. Kennington III +* William McArthur * Wouter van Heyst +* xentec +* 戴 鸣 -And everyone we forgot. Thank you! +And everyone we forgot (if we did, please let us know). Thank you! -Ivo Timmermans -Guus Sliepen +--- +Ivo Timmermans, +Guus Sliepen. diff --git a/aclocal.m4 b/aclocal.m4 index b4047e3..a50e7c2 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.13.3 -*- Autoconf -*- +# generated automatically by aclocal 1.16.2 -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,131 +20,7 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -dnl Autoconf macros for libgcrypt -dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc. -dnl -dnl This file is free software; as a special exception the author gives -dnl unlimited permission to copy and/or distribute it, with or without -dnl modifications, as long as this notice is preserved. -dnl -dnl This file is distributed in the hope that it will be useful, but -dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - -dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, -dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) -dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. -dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed -dnl with the API version to also check the API compatibility. Example: -dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed -dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using -dnl this features allows to prevent build against newer versions of libgcrypt -dnl with a changed API. -dnl -AC_DEFUN([AM_PATH_LIBGCRYPT], -[ AC_ARG_WITH(libgcrypt-prefix, - AC_HELP_STRING([--with-libgcrypt-prefix=PFX], - [prefix where LIBGCRYPT is installed (optional)]), - libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") - if test x$libgcrypt_config_prefix != x ; then - if test x${LIBGCRYPT_CONFIG+set} != xset ; then - LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config - fi - fi - - AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no) - tmp=ifelse([$1], ,1:1.2.0,$1) - if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then - req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` - min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` - else - req_libgcrypt_api=0 - min_libgcrypt_version="$tmp" - fi - - AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) - ok=no - if test "$LIBGCRYPT_CONFIG" != "no" ; then - req_major=`echo $min_libgcrypt_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` - req_minor=`echo $min_libgcrypt_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` - req_micro=`echo $min_libgcrypt_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` - libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` - major=`echo $libgcrypt_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` - minor=`echo $libgcrypt_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` - micro=`echo $libgcrypt_config_version | \ - sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` - if test "$major" -gt "$req_major"; then - ok=yes - else - if test "$major" -eq "$req_major"; then - if test "$minor" -gt "$req_minor"; then - ok=yes - else - if test "$minor" -eq "$req_minor"; then - if test "$micro" -ge "$req_micro"; then - ok=yes - fi - fi - fi - fi - fi - fi - if test $ok = yes; then - AC_MSG_RESULT([yes ($libgcrypt_config_version)]) - else - AC_MSG_RESULT(no) - fi - if test $ok = yes; then - # If we have a recent libgcrypt, we should also check that the - # API is compatible - if test "$req_libgcrypt_api" -gt 0 ; then - tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` - if test "$tmp" -gt 0 ; then - AC_MSG_CHECKING([LIBGCRYPT API version]) - if test "$req_libgcrypt_api" -eq "$tmp" ; then - AC_MSG_RESULT([okay]) - else - ok=no - AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp]) - fi - fi - fi - fi - if test $ok = yes; then - LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` - LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` - ifelse([$2], , :, [$2]) - if test x"$host" != x ; then - libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` - if test x"$libgcrypt_config_host" != xnone ; then - if test x"$libgcrypt_config_host" != x"$host" ; then - AC_MSG_WARN([[ -*** -*** The config script $LIBGCRYPT_CONFIG was -*** built for $libgcrypt_config_host and thus may not match the -*** used host $host. -*** You may want to use the configure option --with-libgcrypt-prefix -*** to specify a matching config script. -***]]) - fi - fi - fi - else - LIBGCRYPT_CFLAGS="" - LIBGCRYPT_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(LIBGCRYPT_CFLAGS) - AC_SUBST(LIBGCRYPT_LIBS) -]) - -# Copyright (C) 2002-2013 Free Software Foundation, Inc. +# Copyright (C) 2002-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -156,10 +32,10 @@ AC_DEFUN([AM_PATH_LIBGCRYPT], # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.13' +[am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.13.3], [], +m4_if([$1], [1.16.2], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -175,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.13.3])dnl +[AM_AUTOMAKE_VERSION([1.16.2])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -227,15 +103,14 @@ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -266,7 +141,7 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -457,13 +332,12 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. - # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], @@ -471,49 +345,43 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS @@ -522,18 +390,17 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each '.P' file that we will -# need in order to bootstrap the dependency handling code. +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -542,6 +409,12 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- @@ -614,11 +487,11 @@ AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: -# -# +# +# AC_SUBST([mkdir_p], ['$(MKDIR_P)']) -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl @@ -650,6 +523,51 @@ dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not @@ -658,7 +576,6 @@ dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. @@ -680,7 +597,7 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -691,7 +608,7 @@ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_co # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -701,7 +618,7 @@ if test x"${install_sh}" != xset; then fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2013 Free Software Foundation, Inc. +# Copyright (C) 2003-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -722,7 +639,7 @@ AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -730,81 +647,42 @@ AC_SUBST([am__leading_dot])]) # AM_MAKE_INCLUDE() # ----------------- -# Check to see how make treats includes. +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# Copyright (C) 1999-2013 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_CC_C_O -# -------------- -# Like AC_PROG_CC_C_O, but changed for automake. -AC_DEFUN([AM_PROG_CC_C_O], -[AC_REQUIRE([AC_PROG_CC_C_O])dnl -AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -AC_REQUIRE_AUX_FILE([compile])dnl -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -dnl Make sure AC_PROG_CC is never called again, or it will override our -dnl setting of CC. -m4_define([AC_PROG_CC], - [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) -]) +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# Copyright (C) 1997-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -843,7 +721,7 @@ fi # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -872,9 +750,73 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -955,7 +897,7 @@ AC_CONFIG_COMMANDS_PRE( rm -f conftest.file ]) -# Copyright (C) 2009-2013 Free Software Foundation, Inc. +# Copyright (C) 2009-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1015,7 +957,7 @@ AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1043,7 +985,7 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2013 Free Software Foundation, Inc. +# Copyright (C) 2006-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1062,7 +1004,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2013 Free Software Foundation, Inc. +# Copyright (C) 2004-2020 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1194,8 +1136,11 @@ AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/attribute.m4]) -m4_include([m4/curses.m4]) +m4_include([m4/ax_append_flag.m4]) +m4_include([m4/ax_cflags_warn_all.m4]) +m4_include([m4/ax_check_compile_flag.m4]) +m4_include([m4/ax_check_link_flag.m4]) +m4_include([m4/ax_require_defined.m4]) m4_include([m4/lzo.m4]) m4_include([m4/openssl.m4]) -m4_include([m4/readline.m4]) m4_include([m4/zlib.m4]) diff --git a/compile b/compile index 531136b..23fcba0 100755 --- a/compile +++ b/compile @@ -1,9 +1,9 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-10-14.11; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ scriptversion=2012-10-14.11; # UTC # 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 . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -53,7 +53,7 @@ func_file_conv () MINGW*) file_conv=mingw ;; - CYGWIN*) + CYGWIN* | MSYS*) file_conv=cygwin ;; *) @@ -67,7 +67,7 @@ func_file_conv () mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; - cygwin/*) + cygwin/* | msys/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) @@ -255,7 +255,8 @@ EOF echo "compile $scriptversion" exit $? ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac @@ -339,9 +340,9 @@ exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/config.guess b/config.guess index b79252d..f50dcdb 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2013-06-10' +timestamp='2018-02-24' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2013-06-10' # 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 . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -24,12 +24,12 @@ timestamp='2013-06-10' # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # -# Originally written by Per Bothner. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` @@ -39,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -107,9 +107,9 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; + ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; @@ -132,14 +132,14 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "${UNAME_SYSTEM}" in +case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu - eval $set_cc_for_build - cat <<-EOF > $dummy.c + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc @@ -149,13 +149,20 @@ Linux|GNU|GNU/*) LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -168,21 +175,31 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -197,44 +214,67 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in os=netbsd ;; esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "$machine-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -251,63 +291,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -319,7 +350,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos @@ -346,38 +377,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" + eval "$set_cc_for_build" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -386,25 +417,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -415,44 +446,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} + echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} + echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} + echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -461,23 +492,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -503,17 +534,17 @@ EOF AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -530,7 +561,7 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -542,14 +573,14 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -560,7 +591,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -574,26 +605,27 @@ EOF exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -608,28 +640,28 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -662,13 +694,13 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + eval "$set_cc_for_build" # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -679,23 +711,23 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -720,11 +752,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -733,7 +765,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -741,9 +773,9 @@ EOF exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -768,127 +800,109 @@ EOF echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + echo "$UNAME_MACHINE"-pc-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -901,58 +915,64 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el @@ -966,64 +986,74 @@ EOF #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} + echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} + echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} + echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} + echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1037,34 +1067,34 @@ EOF # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) @@ -1074,12 +1104,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1089,9 +1119,9 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1099,7 +1129,7 @@ EOF # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; @@ -1111,9 +1141,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1133,9 +1163,9 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1144,28 +1174,28 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1176,7 +1206,7 @@ EOF *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1196,23 +1226,23 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1231,67 +1261,93 @@ EOF echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build + eval "$set_cc_for_build" if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1300,18 +1356,18 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1332,14 +1388,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1348,182 +1404,48 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs exit ;; esac -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif +echo "$0: unable to guess system type" >&2 -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 </dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi + ;; +esac cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1542,16 +1464,16 @@ hostinfo = `(hostinfo) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/config.h.in b/config.h.in index e78f182..cc68348 100644 --- a/config.h.in +++ b/config.h.in @@ -15,18 +15,18 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_NAMESER_H + /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF +/* Define to 1 if you have the `BN_GENCB_new' function. */ +#undef HAVE_BN_GENCB_NEW + /* Unknown BSD variant */ #undef HAVE_BSD -/* have curses support */ -#undef HAVE_CURSES - -/* Define to 1 if you have the header file. */ -#undef HAVE_CURSES_H - /* Cygwin */ #undef HAVE_CYGWIN @@ -36,6 +36,10 @@ /* Darwin (MacOS/X) */ #undef HAVE_DARWIN +/* Define to 1 if you have the declaration of `EVP_aes_256_cfb', and to 0 if + you don't. */ +#undef HAVE_DECL_EVP_AES_256_CFB + /* Define to 1 if you have the declaration of `freeaddrinfo', and to 0 if you don't. */ #undef HAVE_DECL_FREEADDRINFO @@ -52,17 +56,25 @@ don't. */ #undef HAVE_DECL_GETNAMEINFO +/* Define to 1 if you have the declaration of `OpenSSL_add_all_algorithms', + and to 0 if you don't. */ +#undef HAVE_DECL_OPENSSL_ADD_ALL_ALGORITHMS + +/* Define to 1 if you have the declaration of `res_init', and to 0 if you + don't. */ +#undef HAVE_DECL_RES_INIT + +/* Define to 1 if you have the `devname' function. */ +#undef HAVE_DEVNAME + /* Define to 1 if you have the header file. */ #undef HAVE_DIRENT_H /* DragonFly */ #undef HAVE_DRAGONFLY -/* Define to 1 if you have the `ECDH_compute_key' function. */ -#undef HAVE_ECDH_COMPUTE_KEY - -/* Define to 1 if you have the `ECDSA_verify' function. */ -#undef HAVE_ECDSA_VERIFY +/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */ +#undef HAVE_EVP_CIPHER_CTX_NEW /* Define to 1 if you have the `EVP_EncryptInit_ex' function. */ #undef HAVE_EVP_ENCRYPTINIT_EX @@ -70,6 +82,9 @@ /* Define to 1 if you have the `fchmod' function. */ #undef HAVE_FCHMOD +/* Define to 1 if you have the `fdevname' function. */ +#undef HAVE_FDEVNAME + /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK @@ -79,21 +94,24 @@ /* FreeBSD */ #undef HAVE_FREEBSD -/* Define to 1 if you have the `ftime' function. */ -#undef HAVE_FTIME +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* getopt_long() */ +#undef HAVE_GETOPT_LONG /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY -/* Define to 1 if you have the `get_current_dir_name' function. */ -#undef HAVE_GET_CURRENT_DIR_NAME - /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET @@ -181,6 +199,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_TYPES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_UTUN_H + /* Define to 1 if you have the header file. */ #undef HAVE_NET_TAP_IF_TAP_H @@ -190,12 +211,6 @@ /* OpenBSD */ #undef HAVE_OPENBSD -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_ECDH_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_OPENSSL_EC_H - /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_ENGINE_H @@ -217,26 +232,20 @@ /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_SHA_H +/* Define to 1 if you have the `pselect' function. */ +#undef HAVE_PSELECT + /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV -/* Define to 1 if you have the `random' function. */ -#undef HAVE_RANDOM +/* Define to 1 if you have the `RAND_bytes' function. */ +#undef HAVE_RAND_BYTES -/* Define to 1 if you have the `RAND_pseudo_bytes' function. */ -#undef HAVE_RAND_PSEUDO_BYTES +/* Define to 1 if you have the header file. */ +#undef HAVE_RESOLV_H -/* have readline support */ -#undef HAVE_READLINE - -/* Define to 1 if you have the header file. */ -#undef HAVE_READLINE_HISTORY_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_READLINE_READLINE_H - -/* Define to 1 if you have the `select' function. */ -#undef HAVE_SELECT +/* Define to 1 if you have the `RSA_set0_key' function. */ +#undef HAVE_RSA_SET0_KEY /* Define to 1 if the system has the type `socklen_t'. */ #undef HAVE_SOCKLEN_T @@ -244,21 +253,12 @@ /* Solaris/SunOS */ #undef HAVE_SOLARIS -/* Define to 1 if you have the header file. */ -#undef HAVE_STDBOOL_H - /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H -/* Define to 1 if you have the `strdup' function. */ -#undef HAVE_STRDUP - -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H @@ -268,9 +268,6 @@ /* Define to 1 if you have the `strsignal' function. */ #undef HAVE_STRSIGNAL -/* Define to 1 if you have the `strtol' function. */ -#undef HAVE_STRTOL - /* Define to 1 if the system has the type `struct addrinfo'. */ #undef HAVE_STRUCT_ADDRINFO @@ -346,18 +343,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UIO_H -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_UN_H - /* Define to 1 if you have the header file. */ #undef HAVE_SYS_WAIT_H -/* Define to 1 if you have the `time' function. */ -#undef HAVE_TIME - -/* Define to 1 if you have the header file. */ -#undef HAVE_TIME_H - /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H @@ -370,9 +358,6 @@ /* Define to 1 if you have the `vsyslog' function. */ #undef HAVE_VSYSLOG -/* Define to 1 if you have the `writev' function. */ -#undef HAVE_WRITEV - /* have zlib compression support */ #undef HAVE_ZLIB @@ -382,9 +367,6 @@ /* Location of lzo1x.h */ #undef LZO1X_H -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -#undef NO_MINUS_C_MINUS_O - /* Name of package */ #undef PACKAGE @@ -412,12 +394,6 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS -/* Define to 1 if you can safely include both and . */ -#undef TIME_WITH_SYS_TIME - -/* Define to 1 if your declares `struct tm'. */ -#undef TM_IN_SYS_TIME - /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE @@ -462,18 +438,5 @@ /* Defined if the __malloc__ attribute is not supported. */ #undef __malloc__ -/* Defined if the __warn_unused_result__ attribute is not supported. */ -#undef __warn_unused_result__ - -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - /* Define to `int' if does not define. */ #undef pid_t - -/* Define to `unsigned int' if does not define. */ -#undef size_t - -/* Define to empty if the keyword `volatile' does not work. Warning: valid - code using `volatile' can become incorrect without. Disable with care. */ -#undef volatile diff --git a/config.sub b/config.sub index 9633db7..1d8e98b 100755 --- a/config.sub +++ b/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2013-08-10' +timestamp='2018-02-22' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2013-08-10' # 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 . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -25,7 +25,7 @@ timestamp='2013-08-10' # of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -33,7 +33,7 @@ timestamp='2013-08-10' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -53,12 +53,11 @@ timestamp='2013-08-10' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -68,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -95,7 +94,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -113,24 +112,24 @@ esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -179,44 +178,44 @@ case $os in ;; -sco6) os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 @@ -228,10 +227,7 @@ case $os in os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -255,16 +251,18 @@ case $basic_machine in | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ + | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ + | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ @@ -282,8 +280,10 @@ case $basic_machine in | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ @@ -295,14 +295,15 @@ case $basic_machine in | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | open8 \ - | or1k | or32 \ - | pdp10 | pdp11 | pj | pjl \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ + | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -310,7 +311,8 @@ case $basic_machine in | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ + | visium \ + | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -324,11 +326,14 @@ case $basic_machine in c6x) basic_machine=tic6x-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown @@ -357,7 +362,7 @@ case $basic_machine in ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. @@ -369,18 +374,20 @@ case $basic_machine in | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ + | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ @@ -400,8 +407,10 @@ case $basic_machine in | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ @@ -413,16 +422,19 @@ case $basic_machine in | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ + | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ + | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -430,6 +442,8 @@ case $basic_machine in | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ + | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -443,7 +457,7 @@ case $basic_machine in # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -477,7 +491,7 @@ case $basic_machine in basic_machine=x86_64-pc ;; amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl @@ -506,6 +520,9 @@ case $basic_machine in basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -519,7 +536,7 @@ case $basic_machine in os=-linux ;; blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) @@ -527,13 +544,13 @@ case $basic_machine in os=-cnk ;; c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray @@ -622,10 +639,18 @@ case $basic_machine in basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -715,9 +740,6 @@ case $basic_machine in hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; - hppa-next) - os=-nextstep3 - ;; hppaosf) basic_machine=hppa1.1-hp os=-osf @@ -730,26 +752,26 @@ case $basic_machine in basic_machine=i370-ibm ;; i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -767,17 +789,17 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; - m88k-omron*) - basic_machine=m88k-omron - ;; magnum | m3230) basic_machine=mips-mips os=-sysv @@ -809,10 +831,10 @@ case $basic_machine in os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -822,12 +844,16 @@ case $basic_machine in basic_machine=powerpc-unknown os=-morphos ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc @@ -869,7 +895,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -914,6 +940,12 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -946,7 +978,7 @@ case $basic_machine in os=-linux ;; parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) @@ -962,7 +994,7 @@ case $basic_machine in basic_machine=i386-pc ;; pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc @@ -977,16 +1009,16 @@ case $basic_machine in basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould @@ -996,23 +1028,23 @@ case $basic_machine in ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -1066,17 +1098,10 @@ case $basic_machine in sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; sh5el) basic_machine=sh5le-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -1095,7 +1120,7 @@ case $basic_machine in os=-sysv4 ;; strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun @@ -1217,6 +1242,9 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1225,20 +1253,12 @@ case $basic_machine in basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -1267,10 +1287,6 @@ case $basic_machine in vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; @@ -1280,9 +1296,6 @@ case $basic_machine in sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; cydra) basic_machine=cydra-cydrome ;; @@ -1302,7 +1315,7 @@ case $basic_machine in # Make sure to match an already-canonicalized machine name. ;; *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1310,10 +1323,10 @@ esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1324,8 +1337,8 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1336,45 +1349,48 @@ case $os in -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1391,12 +1407,12 @@ case $os in -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc @@ -1405,10 +1421,10 @@ case $os in os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition @@ -1419,12 +1435,6 @@ case $os in -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1449,7 +1459,7 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1471,7 +1481,7 @@ case $os in -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1486,32 +1496,38 @@ case $os in -ose*) os=-ose ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; - -aros*) - os=-aros - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; + -ios) + ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1592,9 +1608,6 @@ case $basic_machine in mips*-*) os=-elf ;; - or1k-*) - os=-elf - ;; or32-*) os=-coff ;; @@ -1604,12 +1617,12 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; @@ -1649,7 +1662,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1664,9 +1677,6 @@ case $basic_machine in i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; *-gould) os=-sysv ;; @@ -1776,15 +1786,15 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$basic_machine$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/configure b/configure index ae5c23d..2f7cd24 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for tinc 1.1pre8. +# Generated by GNU Autoconf 2.69 for tinc 1.0.36. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='tinc' PACKAGE_TARNAME='tinc' -PACKAGE_VERSION='1.1pre8' -PACKAGE_STRING='tinc 1.1pre8' +PACKAGE_VERSION='1.0.36' +PACKAGE_STRING='tinc 1.0.36' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -623,15 +623,10 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS -GCRYPT_FALSE -GCRYPT_TRUE -OPENSSL_FALSE -OPENSSL_TRUE -LIBGCRYPT_LIBS -LIBGCRYPT_CFLAGS -LIBGCRYPT_CONFIG -READLINE_LIBS -CURSES_LIBS +GETOPT_FALSE +GETOPT_TRUE +WITH_SYSTEMD_FALSE +WITH_SYSTEMD_TRUE TUNEMU_FALSE TUNEMU_TRUE VDE_FALSE @@ -648,6 +643,7 @@ BSD_FALSE BSD_TRUE LINUX_FALSE LINUX_TRUE +systemd_path host_os host_vendor host_cpu @@ -656,12 +652,9 @@ build_os build_vendor build_cpu build -RANLIB -LN_S -AM_BACKSLASH -AM_DEFAULT_VERBOSITY -AM_DEFAULT_V -AM_V +EGREP +GREP +CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE @@ -669,9 +662,19 @@ am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE -am__quote am__include DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V am__untar am__tar AMTAR @@ -695,16 +698,6 @@ am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM -EGREP -GREP -CPP -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC target_alias host_alias build_alias @@ -724,6 +717,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -742,24 +736,19 @@ PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR -SHELL' +SHELL +am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking -enable_dependency_tracking enable_silent_rules +enable_dependency_tracking enable_uml enable_vde enable_tunemu with_windows2000 -enable_curses -with_curses -with_curses_include -with_curses_lib -enable_readline -with_readline -with_readline_include -with_readline_lib +with_systemd +enable_hardening enable_zlib with_zlib with_zlib_include @@ -768,7 +757,6 @@ enable_lzo with_lzo with_lzo_include with_lzo_lib -with_libgcrypt_prefix with_openssl with_openssl_include with_openssl_lib @@ -821,6 +809,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1073,6 +1062,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1210,7 +1208,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1323,7 +1321,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures tinc 1.1pre8 to adapt to many kinds of systems. +\`configure' configures tinc 1.0.36 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1363,6 +1361,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1393,7 +1392,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of tinc 1.1pre8:";; + short | recursive ) echo "Configuration of tinc 1.0.36:";; esac cat <<\_ACEOF @@ -1401,48 +1400,38 @@ Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build - --enable-silent-rules less verbose build output (undo: "make V=1") - --disable-silent-rules verbose build output (undo: "make V=0") --enable-uml enable support for User Mode Linux --enable-vde enable support for Virtual Distributed Ethernet --enable-tunemu enable support for the tunemu driver - --disable-curses disable curses support - --disable-readline disable readline support + --disable-hardening disable compiler and linker hardening flags --disable-zlib disable zlib compression support --disable-lzo disable lzo compression support - --disable-jumbograms enable support for jumbograms (packets up to 9000 + --enable-jumbograms enable support for jumbograms (packets up to 9000 bytes) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --without-windows2000 compile with support for Windows 2000. This disables + --with-windows2000 compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks. - --with-curses=DIR curses base directory, or: - --with-curses-include=DIR - curses headers directory - --with-curses-lib=DIR curses library directory - --with-readline=DIR readline base directory, or: - --with-readline-include=DIR - readline headers directory - --with-readline-lib=DIR readline library directory + --with-systemd[=DIR] install systemd service files [to DIR if specified] --with-zlib=DIR zlib base directory, or: --with-zlib-include=DIR zlib headers directory --with-zlib-lib=DIR zlib library directory --with-lzo=DIR lzo base directory, or: --with-lzo-include=DIR lzo headers directory --with-lzo-lib=DIR lzo library directory - --with-libgcrypt-prefix=PFX - prefix where LIBGCRYPT is installed (optional) - --with-openssl=DIR OpenSSL base directory, or: + --with-openssl=DIR LibreSSL/OpenSSL base directory, or: --with-openssl-include=DIR - OpenSSL headers directory (without trailing + LibreSSL/OpenSSL headers directory (without trailing /openssl) - --with-openssl-lib=DIR OpenSSL library directory + --with-openssl-lib=DIR LibreSSL/OpenSSL library directory Some influential environment variables: CC C compiler command @@ -1520,7 +1509,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -tinc configure 1.1pre8 +tinc configure 1.0.36 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1769,6 +1758,52 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_header_compile +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -1823,52 +1858,6 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_type -# ac_fn_c_try_link LINENO -# ----------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_link - # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly @@ -1985,7 +1974,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by tinc $as_me 1.1pre8, which was +It was created by tinc $as_me 1.0.36, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2334,6 +2323,723 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu +am__api_version='1.16' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='tinc' + VERSION='1.0.36' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +ac_config_headers="$ac_config_headers config.h" + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=0;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + + +# Enable GNU extensions. +# Define this here, not in acconfig's @TOP@ section, since definitions +# in the latter don't make it into the configure-time tests. +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : + ;; +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3123,6 +3829,193 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -3583,770 +4476,6 @@ $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } -am__api_version='1.13' - -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } -if test -z "$INSTALL"; then -if ${ac_cv_path_install+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - fi - done - done - ;; -esac - - done -IFS=$as_save_IFS - -rm -rf conftest.one conftest.two conftest.dir - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -$as_echo_n "checking whether build environment is sane... " >&6; } -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[\\\"\#\$\&\'\`$am_lf]*) - as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; -esac -case $srcdir in - *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; -esac - -# Do 'set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - am_has_slept=no - for am_try in 1 2; do - echo "timestamp, slept: $am_has_slept" > conftest.file - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - as_fn_error $? "ls -t appears to fail. Make sure there is not a broken - alias in your environment" "$LINENO" 5 - fi - if test "$2" = conftest.file || test $am_try -eq 2; then - break - fi - # Just in case. - sleep 1 - am_has_slept=yes - done - test "$2" = conftest.file - ) -then - # Ok. - : -else - as_fn_error $? "newly created file is older than distributed files! -Check your system clock" "$LINENO" 5 -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -# If we didn't sleep, we still need to ensure time stamps of config.status and -# generated files are strictly newer. -am_sleep_pid= -if grep 'slept: no' conftest.file >/dev/null 2>&1; then - ( sleep 1 ) & - am_sleep_pid=$! -fi - -rm -f conftest.file - -test "$program_prefix" != NONE && - program_transform_name="s&^&$program_prefix&;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s&\$&$program_suffix&;$program_transform_name" -# Double any \ or $. -# By default was `s,x,x', remove it if useless. -ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' -program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` - -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` - -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --is-lightweight"; then - am_missing_run="$MISSING " -else - am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} -fi - -if test x"${install_sh}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi - -# Installed binaries are usually stripped using 'strip' when the user -# run "make install-strip". However 'strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the 'STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 -$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } -if test -z "$MKDIR_P"; then - if ${ac_cv_path_mkdir+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext - break 3;; - esac - done - done - done -IFS=$as_save_IFS - -fi - - test -d ./--version && rmdir ./--version - if test "${ac_cv_path_mkdir+set}" = set; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - MKDIR_P="$ac_install_sh -d" - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -$as_echo "$MKDIR_P" >&6; } - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AWK" && break -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -DEPDIR="${am__leading_dot}deps" - -ac_config_commands="$ac_config_commands depfiles" - - -am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf - -# Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then : - enableval=$enable_dependency_tracking; -fi - -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' - am__nodep='_no' -fi - if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - - -# Check whether --enable-silent-rules was given. -if test "${enable_silent_rules+set}" = set; then : - enableval=$enable_silent_rules; -fi - -case $enable_silent_rules in # ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=1;; -esac -am_make=${MAKE-make} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 -$as_echo_n "checking whether $am_make supports nested variables... " >&6; } -if ${am_cv_make_support_nested_variables+:} false; then : - $as_echo_n "(cached) " >&6 -else - if $as_echo 'TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 -$as_echo "$am_cv_make_support_nested_variables" >&6; } -if test $am_cv_make_support_nested_variables = yes; then - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AM_BACKSLASH='\' - -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - am__isrc=' -I$(srcdir)' - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE='tinc' - VERSION='1.1pre8' - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - -# For better backward compatibility. To be removed once Automake 1.9.x -# dies out for good. For more background, see: -# -# -mkdir_p='$(MKDIR_P)' - -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -# Always define AMTAR for backward compatibility. Yes, it's still used -# in the wild :-( We should find a proper way to deprecate it ... -AMTAR='$${TAR-tar}' - - -# We'll loop over all known methods to create a tar archive until one works. -_am_tools='gnutar pax cpio none' - -am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' - - - - - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - - -ac_config_headers="$ac_config_headers config.h" - - -# Enable GNU extensions. -# Define this here, not in acconfig's @TOP@ section, since definitions -# in the latter don't make it into the configure-time tests. - $as_echo "#define __USE_BSD 1" >>confdefs.h @@ -4666,234 +4795,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 -$as_echo_n "checking whether ln -s works... " >&6; } -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 -$as_echo "no, using $LN_S" >&6; } -fi - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - RANLIB=$ac_ct_RANLIB - fi -else - RANLIB="$ac_cv_prog_RANLIB" -fi - - -if test "x$CC" != xcc; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 -$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 -$as_echo_n "checking whether cc understands -c and -o together... " >&6; } -fi -set dummy $CC; ac_cc=`$as_echo "$2" | - sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -# Make sure it works both with $CC and with simple cc. -# We do the test twice because some compilers refuse to overwrite an -# existing .o file with -o, though they will create one. -ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' -rm -f conftest2.* -if { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; -then - eval ac_cv_prog_cc_${ac_cc}_c_o=yes - if test "x$CC" != xcc; then - # Test first that cc exists at all. - if { ac_try='cc -c conftest.$ac_ext >&5' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' - rm -f conftest2.* - if { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && - test -f conftest2.$ac_objext && { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; - then - # cc works too. - : - else - # cc exists but doesn't like -o. - eval ac_cv_prog_cc_${ac_cc}_c_o=no - fi - fi - fi -else - eval ac_cv_prog_cc_${ac_cc}_c_o=no -fi -rm -f core conftest* - -fi -if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h - -fi - -# FIXME: we rely on the cache variable name because -# there is no other way. -set dummy $CC -am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` -eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o -if test "$am_t" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi @@ -5120,6 +5021,27 @@ fi fi + +# Check whether --with-systemd was given. +if test "${with_systemd+set}" = set; then : + withval=$with_systemd; systemd=true; systemd_path="$with_systemd" +else + systemd=false + +fi + + +if test "x$with_systemd" = "xyes"; then : + systemd_path="\${libdir}/systemd/system" +else + if test "x$with_systemd" = "xno"; then : + systemd=false +fi +fi + +systemd_path=$systemd_path + + if test "$linux" = true; then LINUX_TRUE= LINUX_FALSE='#' @@ -5184,6 +5106,14 @@ else TUNEMU_FALSE= fi + if test "$systemd" = true; then + WITH_SYSTEMD_TRUE= + WITH_SYSTEMD_FALSE='#' +else + WITH_SYSTEMD_TRUE='#' + WITH_SYSTEMD_FALSE= +fi + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -5279,17 +5209,23 @@ if test -d /sw/lib ; then fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking CFLAGS for maximum warnings" >&5 +$as_echo_n "checking CFLAGS for maximum warnings... " >&6; } +if ${ac_cv_cflags_warn_all+:} false; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + ac_cv_cflags_warn_all="no, unknown" +ac_save_CFLAGS="$CFLAGS" +for ac_arg in "-warn all % -warn all" "-pedantic % -Wall" "-xstrconst % -v" "-std1 % -verbose -w0 -warnprotos" "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" "-ansi -ansiE % -fullwarn" "+ESlit % +w1" "-Xc % -pvctl,fullmsg" "-h conform % -h msglevel 2" # +do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -#include -#include -#include int main () @@ -5300,98 +5236,390 @@ main () } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no + ac_cv_cflags_warn_all=`echo $ac_arg | sed -e 's,.*% *,,'` ; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +CFLAGS="$ac_save_CFLAGS" -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cflags_warn_all" >&5 +$as_echo "$ac_cv_cflags_warn_all" >&6; } + + +case ".$ac_cv_cflags_warn_all" in + .ok|.ok,*) ;; + .|.no|.no,*) ;; + *) if ${CFLAGS+:} false; then : + case " $CFLAGS " in + *" $ac_cv_cflags_warn_all "*) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS already contains \$ac_cv_cflags_warn_all"; } >&5 + (: CFLAGS already contains $ac_cv_cflags_warn_all) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + ;; + *) + { { $as_echo "$as_me:${as_lineno-$LINENO}: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_warn_all\""; } >&5 + (: CFLAGS="$CFLAGS $ac_cv_cflags_warn_all") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + CFLAGS="$CFLAGS $ac_cv_cflags_warn_all" + ;; + esac +else + CFLAGS="$ac_cv_cflags_warn_all" +fi + ;; +esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Check whether --enable-hardening was given. +if test "${enable_hardening+set}" = set; then : + enableval=$enable_hardening; +fi + +if test "x$enable_hardening" != "xno"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -DFORTIFY_SOURCE=2" >&5 +$as_echo_n "checking whether C compiler accepts -DFORTIFY_SOURCE=2... " >&6; } +if ${ax_cv_check_cflags___DFORTIFY_SOURCE_2+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -DFORTIFY_SOURCE=2" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; + + ; return 0; } _ACEOF -if ac_fn_c_try_run "$LINENO"; then : - +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___DFORTIFY_SOURCE_2=yes else - ac_cv_header_stdc=no + ax_cv_check_cflags___DFORTIFY_SOURCE_2=no fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___DFORTIFY_SOURCE_2" >&5 +$as_echo "$ax_cv_check_cflags___DFORTIFY_SOURCE_2" >&6; } +if test x"$ax_cv_check_cflags___DFORTIFY_SOURCE_2" = xyes; then : + CPPFLAGS="$CPPFLAGS -DFORTIFY_SOURCE=2" +else + : +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fwrapv" >&5 +$as_echo_n "checking whether C compiler accepts -fwrapv... " >&6; } +if ${ax_cv_check_cflags___fwrapv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fwrapv" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fwrapv=yes +else + ax_cv_check_cflags___fwrapv=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fwrapv" >&5 +$as_echo "$ax_cv_check_cflags___fwrapv" >&6; } +if test x"$ax_cv_check_cflags___fwrapv" = xyes; then : + CPPFLAGS="$CPPFLAGS -fwrapv" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fno-strict-overflow" >&5 +$as_echo_n "checking whether C compiler accepts -fno-strict-overflow... " >&6; } +if ${ax_cv_check_cflags___fno_strict_overflow+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fno-strict-overflow" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fno_strict_overflow=yes +else + ax_cv_check_cflags___fno_strict_overflow=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fno_strict_overflow" >&5 +$as_echo "$ax_cv_check_cflags___fno_strict_overflow" >&6; } +if test x"$ax_cv_check_cflags___fno_strict_overflow" = xyes; then : + CPPFLAGS="$CPPFLAGS -fno-strict-overflow" +else + : fi fi + + case $host_os in + *mingw*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--dynamicbase" >&5 +$as_echo_n "checking whether the linker accepts -Wl,--dynamicbase... " >&6; } +if ${ax_cv_check_ldflags___Wl___dynamicbase+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,--dynamicbase" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___Wl___dynamicbase=yes +else + ax_cv_check_ldflags___Wl___dynamicbase=no fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___dynamicbase" >&5 +$as_echo "$ax_cv_check_ldflags___Wl___dynamicbase" >&6; } +if test x"$ax_cv_check_ldflags___Wl___dynamicbase" = xyes; then : + LDFLAGS="$LDFLAGS -Wl,--dynamicbase" +else + : fi -for ac_header in stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,--nxcompat" >&5 +$as_echo_n "checking whether the linker accepts -Wl,--nxcompat... " >&6; } +if ${ax_cv_check_ldflags___Wl___nxcompat+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,--nxcompat" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___Wl___nxcompat=yes +else + ax_cv_check_ldflags___Wl___nxcompat=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl___nxcompat" >&5 +$as_echo "$ax_cv_check_ldflags___Wl___nxcompat" >&6; } +if test x"$ax_cv_check_ldflags___Wl___nxcompat" = xyes; then : + LDFLAGS="$LDFLAGS -Wl,--nxcompat" +else + : +fi + + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fPIE" >&5 +$as_echo_n "checking whether C compiler accepts -fPIE... " >&6; } +if ${ax_cv_check_cflags___fPIE+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -fPIE" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___fPIE=yes +else + ax_cv_check_cflags___fPIE=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___fPIE" >&5 +$as_echo "$ax_cv_check_cflags___fPIE" >&6; } +if test x"$ax_cv_check_cflags___fPIE" = xyes; then : + CPPFLAGS="$CPPFLAGS -fPIE" +else + : +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -pie" >&5 +$as_echo_n "checking whether the linker accepts -pie... " >&6; } +if ${ax_cv_check_ldflags___pie+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -pie" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___pie=yes +else + ax_cv_check_ldflags___pie=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___pie" >&5 +$as_echo "$ax_cv_check_ldflags___pie" >&6; } +if test x"$ax_cv_check_ldflags___pie" = xyes; then : + LDFLAGS="$LDFLAGS -pie" +else + : +fi + + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,relro" >&5 +$as_echo_n "checking whether the linker accepts -Wl,-z,relro... " >&6; } +if ${ax_cv_check_ldflags___Wl__z_relro+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-z,relro" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___Wl__z_relro=yes +else + ax_cv_check_ldflags___Wl__z_relro=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_relro" >&5 +$as_echo "$ax_cv_check_ldflags___Wl__z_relro" >&6; } +if test x"$ax_cv_check_ldflags___Wl__z_relro" = xyes; then : + LDFLAGS="$LDFLAGS -Wl,-z,relro" +else + : +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker accepts -Wl,-z,now" >&5 +$as_echo_n "checking whether the linker accepts -Wl,-z,now... " >&6; } +if ${ax_cv_check_ldflags___Wl__z_now+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-z,now" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_check_ldflags___Wl__z_now=yes +else + ax_cv_check_ldflags___Wl__z_now=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_ldflags___Wl__z_now" >&5 +$as_echo "$ax_cv_check_ldflags___Wl__z_now" >&6; } +if test x"$ax_cv_check_ldflags___Wl__z_now" = xyes; then : + LDFLAGS="$LDFLAGS -Wl,-z,now" +else + : +fi + + + +fi; + + + +for ac_header in syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h arpa/nameser.h dirent.h getopt.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -5404,10 +5632,10 @@ fi done -for ac_header in net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h netpacket/packet.h +for ac_header in net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/if_utun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"src/have.h\" +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\" " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : @@ -5419,10 +5647,10 @@ fi done -for ac_header in netinet/if_ether.h netinet/ip.h netinet/ip6.h +for ac_header in netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"src/have.h\" +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\" " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : @@ -5437,7 +5665,7 @@ done for ac_header in netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"src/have.h\" +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include \"$srcdir/src/have.h\" " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : @@ -5450,121 +5678,6 @@ fi done -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 -$as_echo_n "checking for an ANSI C-conforming const... " >&6; } -if ${ac_cv_c_const+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - -#ifndef __cplusplus - /* Ultrix mips cc rejects this sort of thing. */ - typedef int charset[2]; - const charset cs = { 0, 0 }; - /* SunOS 4.1.1 cc rejects this. */ - char const *const *pcpcc; - char **ppc; - /* NEC SVR4.0.2 mips cc rejects this. */ - struct point {int x, y;}; - static struct point const zero = {0,0}; - /* AIX XL C 1.02.0.0 rejects this. - It does not let you subtract one const X* pointer from another in - an arm of an if-expression whose if-part is not a constant - expression */ - const char *g = "string"; - pcpcc = &g + (g ? g-g : 0); - /* HPUX 7.0 cc rejects these. */ - ++pcpcc; - ppc = (char**) pcpcc; - pcpcc = (char const *const *) ppc; - { /* SCO 3.2v4 cc rejects this sort of thing. */ - char tx; - char *t = &tx; - char const *s = 0 ? (char *) 0 : (char const *) 0; - - *t++ = 0; - if (s) return 0; - } - { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ - int x[] = {25, 17}; - const int *foo = &x[0]; - ++foo; - } - { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ - typedef const int *iptr; - iptr p = 0; - ++p; - } - { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying - "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; } bx; - struct s *b = &bx; b->j = 5; - } - { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ - const int foo = 10; - if (!foo) return 0; - } - return !cs[0] && !zero.x; -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_const=yes -else - ac_cv_c_const=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 -$as_echo "$ac_cv_c_const" >&6; } -if test $ac_cv_c_const = no; then - -$as_echo "#define const /**/" >>confdefs.h - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working volatile" >&5 -$as_echo_n "checking for working volatile... " >&6; } -if ${ac_cv_c_volatile+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - -volatile int x; -int * volatile y = (int *) 0; -return !x && !y; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_volatile=yes -else - ac_cv_c_volatile=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_volatile" >&5 -$as_echo "$ac_cv_c_volatile" >&6; } -if test $ac_cv_c_volatile = no; then - -$as_echo "#define volatile /**/" >>confdefs.h - -fi - ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : @@ -5574,87 +5687,6 @@ cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF -fi - -ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" -if test "x$ac_cv_type_size_t" = xyes; then : - -else - -cat >>confdefs.h <<_ACEOF -#define size_t unsigned int -_ACEOF - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 -$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } -if ${ac_cv_header_time+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include - -int -main () -{ -if ((struct tm *) 0) -return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_time=yes -else - ac_cv_header_time=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 -$as_echo "$ac_cv_header_time" >&6; } -if test $ac_cv_header_time = yes; then - -$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 -$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } -if ${ac_cv_struct_tm+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include - -int -main () -{ -struct tm tm; - int *p = &tm.tm_sec; - return !p; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_struct_tm=time.h -else - ac_cv_struct_tm=sys/time.h -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 -$as_echo "$ac_cv_struct_tm" >&6; } -if test $ac_cv_struct_tm = sys/time.h; then - -$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h - fi @@ -5669,8 +5701,8 @@ else CFLAGS="$CFLAGS -Wall -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -void test(void) __attribute__ ((__malloc__)); - void test(void) { return; } +void *test(void) __attribute__ ((__malloc__)); + void *test(void) { return (void *)0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : @@ -5693,41 +5725,7 @@ $as_echo "#define __malloc__ /**/" >>confdefs.h fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working __warn_unused_result__ attribute" >&5 -$as_echo_n "checking for working __warn_unused_result__ attribute... " >&6; } -if ${tinc_cv_attribute___warn_unused_result__+:} false; then : - $as_echo_n "(cached) " >&6 -else - - tempcflags="$CFLAGS" - CFLAGS="$CFLAGS -Wall -Werror" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -void test(void) __attribute__ ((__warn_unused_result__)); - void test(void) { return; } - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - tinc_cv_attribute___warn_unused_result__=yes -else - tinc_cv_attribute___warn_unused_result__=no - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS="$tempcflags" - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tinc_cv_attribute___warn_unused_result__" >&5 -$as_echo "$tinc_cv_attribute___warn_unused_result__" >&6; } - - if test ${tinc_cv_attribute___warn_unused_result__} = no; then - -$as_echo "#define __warn_unused_result__ /**/" >>confdefs.h - - fi - - -ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_socklen_t" = xyes; then : @@ -5738,7 +5736,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct ether_header" "ac_cv_type_struct_ether_header" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct ether_header" "ac_cv_type_struct_ether_header" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_ether_header" = xyes; then : @@ -5749,7 +5747,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct arphdr" "ac_cv_type_struct_arphdr" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct arphdr" "ac_cv_type_struct_arphdr" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_arphdr" = xyes; then : @@ -5760,7 +5758,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct ether_arp" "ac_cv_type_struct_ether_arp" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct ether_arp" "ac_cv_type_struct_ether_arp" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_ether_arp" = xyes; then : @@ -5771,7 +5769,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct in_addr" "ac_cv_type_struct_in_addr" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct in_addr" "ac_cv_type_struct_in_addr" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_in_addr" = xyes; then : @@ -5782,7 +5780,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct addrinfo" "ac_cv_type_struct_addrinfo" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_addrinfo" = xyes; then : @@ -5793,7 +5791,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct ip" "ac_cv_type_struct_ip" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct ip" "ac_cv_type_struct_ip" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_ip" = xyes; then : @@ -5804,7 +5802,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct icmp" "ac_cv_type_struct_icmp" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct icmp" "ac_cv_type_struct_icmp" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_icmp" = xyes; then : @@ -5815,7 +5813,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct in6_addr" "ac_cv_type_struct_in6_addr" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_in6_addr" = xyes; then : @@ -5826,7 +5824,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then : @@ -5837,7 +5835,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct ip6_hdr" "ac_cv_type_struct_ip6_hdr" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct ip6_hdr" "ac_cv_type_struct_ip6_hdr" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_ip6_hdr" = xyes; then : @@ -5848,7 +5846,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct icmp6_hdr" "ac_cv_type_struct_icmp6_hdr" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct icmp6_hdr" "ac_cv_type_struct_icmp6_hdr" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_icmp6_hdr" = xyes; then : @@ -5859,7 +5857,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct nd_neighbor_solicit" "ac_cv_type_struct_nd_neighbor_solicit" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct nd_neighbor_solicit" "ac_cv_type_struct_nd_neighbor_solicit" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_nd_neighbor_solicit" = xyes; then : @@ -5870,7 +5868,7 @@ _ACEOF fi -ac_fn_c_check_type "$LINENO" "struct nd_opt_hdr" "ac_cv_type_struct_nd_opt_hdr" "#include \"src/have.h\" +ac_fn_c_check_type "$LINENO" "struct nd_opt_hdr" "ac_cv_type_struct_nd_opt_hdr" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_type_struct_nd_opt_hdr" = xyes; then : @@ -5916,7 +5914,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF -for ac_func in asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall putenv random select strdup strerror strsignal strtol system time usleep unsetenv vsyslog writev +for ac_func in asprintf daemon fchmod flock fork gettimeofday mlockall pselect putenv strsignal system unsetenv usleep vsyslog devname fdevname do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -5929,6 +5927,24 @@ fi done +ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long" +if test "x$ac_cv_func_getopt_long" = xyes; then : + getopt=true; +$as_echo "#define HAVE_GETOPT_LONG 1" >>confdefs.h + +else + getopt=false +fi + + if test "$getopt" = true; then + GETOPT_TRUE= + GETOPT_FALSE='#' +else + GETOPT_TRUE='#' + GETOPT_FALSE= +fi + + ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" if test "x$ac_cv_func_socket" = xyes; then : @@ -6037,7 +6053,7 @@ fi fi -ac_fn_c_check_decl "$LINENO" "freeaddrinfo" "ac_cv_have_decl_freeaddrinfo" "#include \"src/have.h\" +ac_fn_c_check_decl "$LINENO" "freeaddrinfo" "ac_cv_have_decl_freeaddrinfo" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_have_decl_freeaddrinfo" = xyes; then : @@ -6049,7 +6065,7 @@ fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_FREEADDRINFO $ac_have_decl _ACEOF -ac_fn_c_check_decl "$LINENO" "gai_strerror" "ac_cv_have_decl_gai_strerror" "#include \"src/have.h\" +ac_fn_c_check_decl "$LINENO" "gai_strerror" "ac_cv_have_decl_gai_strerror" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_have_decl_gai_strerror" = xyes; then : @@ -6061,7 +6077,7 @@ fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GAI_STRERROR $ac_have_decl _ACEOF -ac_fn_c_check_decl "$LINENO" "getaddrinfo" "ac_cv_have_decl_getaddrinfo" "#include \"src/have.h\" +ac_fn_c_check_decl "$LINENO" "getaddrinfo" "ac_cv_have_decl_getaddrinfo" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_have_decl_getaddrinfo" = xyes; then : @@ -6073,7 +6089,7 @@ fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GETADDRINFO $ac_have_decl _ACEOF -ac_fn_c_check_decl "$LINENO" "getnameinfo" "ac_cv_have_decl_getnameinfo" "#include \"src/have.h\" +ac_fn_c_check_decl "$LINENO" "getnameinfo" "ac_cv_have_decl_getnameinfo" "#include \"$srcdir/src/have.h\" " if test "x$ac_cv_have_decl_getnameinfo" = xyes; then : @@ -6087,6 +6103,69 @@ cat >>confdefs.h <<_ACEOF _ACEOF +ac_fn_c_check_decl "$LINENO" "res_init" "ac_cv_have_decl_res_init" " + #include + #include + +" +if test "x$ac_cv_have_decl_res_init" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_RES_INIT $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_init in -lresolv" >&5 +$as_echo_n "checking for res_init in -lresolv... " >&6; } +if ${ac_cv_lib_resolv_res_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lresolv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char res_init (); +int +main () +{ +return res_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_resolv_res_init=yes +else + ac_cv_lib_resolv_res_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_init" >&5 +$as_echo "$ac_cv_lib_resolv_res_init" >&6; } +if test "x$ac_cv_lib_resolv_res_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBRESOLV 1 +_ACEOF + + LIBS="-lresolv $LIBS" + +fi + +fi + + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -6175,216 +6254,6 @@ rm -f confcache - - # Check whether --enable-curses was given. -if test "${enable_curses+set}" = set; then : - enableval=$enable_curses; -fi - - if test "x$enable_curses" != "xno"; then : - - -$as_echo "#define HAVE_CURSES 1" >>confdefs.h - - curses=true - -# Check whether --with-curses was given. -if test "${with_curses+set}" = set; then : - withval=$with_curses; curses="$withval" - CPPFLAGS="$CPPFLAGS -I$withval/include" - LDFLAGS="$LDFLAGS -L$withval/lib" - -fi - - - -# Check whether --with-curses-include was given. -if test "${with_curses_include+set}" = set; then : - withval=$with_curses_include; curses_include="$withval" - CPPFLAGS="$CPPFLAGS -I$withval" - -fi - - - -# Check whether --with-curses-lib was given. -if test "${with_curses_lib+set}" = set; then : - withval=$with_curses_lib; curses_lib="$withval" - LDFLAGS="$LDFLAGS -L$withval" - -fi - - - for ac_header in curses.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "curses.h" "ac_cv_header_curses_h" "$ac_includes_default" -if test "x$ac_cv_header_curses_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_CURSES_H 1 -_ACEOF - -else - as_fn_error $? "\"curses header files not found.\"" "$LINENO" 5; break - -fi - -done - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for initscr in -lcurses" >&5 -$as_echo_n "checking for initscr in -lcurses... " >&6; } -if ${ac_cv_lib_curses_initscr+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcurses $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char initscr (); -int -main () -{ -return initscr (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_curses_initscr=yes -else - ac_cv_lib_curses_initscr=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_initscr" >&5 -$as_echo "$ac_cv_lib_curses_initscr" >&6; } -if test "x$ac_cv_lib_curses_initscr" = xyes; then : - CURSES_LIBS="-lcurses" -else - as_fn_error $? "\"curses libraries not found.\"" "$LINENO" 5 - -fi - - -fi - - - - - # Check whether --enable-readline was given. -if test "${enable_readline+set}" = set; then : - enableval=$enable_readline; -fi - - if test "x$enable_readline" != "xno"; then : - - -$as_echo "#define HAVE_READLINE 1" >>confdefs.h - - readline=true - -# Check whether --with-readline was given. -if test "${with_readline+set}" = set; then : - withval=$with_readline; readline="$withval" - CPPFLAGS="$CPPFLAGS -I$withval/include" - LDFLAGS="$LDFLAGS -L$withval/lib" - -fi - - - -# Check whether --with-readline-include was given. -if test "${with_readline_include+set}" = set; then : - withval=$with_readline_include; readline_include="$withval" - CPPFLAGS="$CPPFLAGS -I$withval" - -fi - - - -# Check whether --with-readline-lib was given. -if test "${with_readline_lib+set}" = set; then : - withval=$with_readline_lib; readline_lib="$withval" - LDFLAGS="$LDFLAGS -L$withval" - -fi - - - for ac_header in readline/readline.h readline/history.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -else - as_fn_error $? "\"readline header files not found.\"" "$LINENO" 5; break - -fi - -done - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 -$as_echo_n "checking for readline in -lreadline... " >&6; } -if ${ac_cv_lib_readline_readline+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lreadline $CURSES_LIBS - $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char readline (); -int -main () -{ -return readline (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_readline_readline=yes -else - ac_cv_lib_readline_readline=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 -$as_echo "$ac_cv_lib_readline_readline" >&6; } -if test "x$ac_cv_lib_readline_readline" = xyes; then : - READLINE_LIBS="-lreadline" -else - as_fn_error $? "\"readline library not found.\"" "$LINENO" 5 -fi - - -fi - - - - # Check whether --enable-zlib was given. if test "${enable_zlib+set}" = set; then : enableval=$enable_zlib; @@ -6663,226 +6532,6 @@ done fi -if test "$with_libgcrypt" = yes; then - gcrypt=true - -# Check whether --with-libgcrypt-prefix was given. -if test "${with_libgcrypt_prefix+set}" = set; then : - withval=$with_libgcrypt_prefix; libgcrypt_config_prefix="$withval" -else - libgcrypt_config_prefix="" -fi - - if test x$libgcrypt_config_prefix != x ; then - if test x${LIBGCRYPT_CONFIG+set} != xset ; then - LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config - fi - fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}libgcrypt-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}libgcrypt-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $LIBGCRYPT_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG -if test -n "$LIBGCRYPT_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5 -$as_echo "$LIBGCRYPT_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_LIBGCRYPT_CONFIG"; then - ac_pt_LIBGCRYPT_CONFIG=$LIBGCRYPT_CONFIG - # Extract the first word of "libgcrypt-config", so it can be a program name with args. -set dummy libgcrypt-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_LIBGCRYPT_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_LIBGCRYPT_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$ac_pt_LIBGCRYPT_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_LIBGCRYPT_CONFIG=$ac_cv_path_ac_pt_LIBGCRYPT_CONFIG -if test -n "$ac_pt_LIBGCRYPT_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LIBGCRYPT_CONFIG" >&5 -$as_echo "$ac_pt_LIBGCRYPT_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_LIBGCRYPT_CONFIG" = x; then - LIBGCRYPT_CONFIG="no" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - LIBGCRYPT_CONFIG=$ac_pt_LIBGCRYPT_CONFIG - fi -else - LIBGCRYPT_CONFIG="$ac_cv_path_LIBGCRYPT_CONFIG" -fi - - tmp=1.4.0 - if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then - req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` - min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` - else - req_libgcrypt_api=0 - min_libgcrypt_version="$tmp" - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5 -$as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; } - ok=no - if test "$LIBGCRYPT_CONFIG" != "no" ; then - req_major=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` - req_minor=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` - req_micro=`echo $min_libgcrypt_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` - libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` - major=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'` - minor=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'` - micro=`echo $libgcrypt_config_version | \ - sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'` - if test "$major" -gt "$req_major"; then - ok=yes - else - if test "$major" -eq "$req_major"; then - if test "$minor" -gt "$req_minor"; then - ok=yes - else - if test "$minor" -eq "$req_minor"; then - if test "$micro" -ge "$req_micro"; then - ok=yes - fi - fi - fi - fi - fi - fi - if test $ok = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libgcrypt_config_version)" >&5 -$as_echo "yes ($libgcrypt_config_version)" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - if test $ok = yes; then - # If we have a recent libgcrypt, we should also check that the - # API is compatible - if test "$req_libgcrypt_api" -gt 0 ; then - tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` - if test "$tmp" -gt 0 ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGCRYPT API version" >&5 -$as_echo_n "checking LIBGCRYPT API version... " >&6; } - if test "$req_libgcrypt_api" -eq "$tmp" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5 -$as_echo "okay" >&6; } - else - ok=no - { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match. want=$req_libgcrypt_api got=$tmp" >&5 -$as_echo "does not match. want=$req_libgcrypt_api got=$tmp" >&6; } - fi - fi - fi - fi - if test $ok = yes; then - LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` - LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` - : - if test x"$host" != x ; then - libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` - if test x"$libgcrypt_config_host" != xnone ; then - if test x"$libgcrypt_config_host" != x"$host" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: -*** -*** The config script $LIBGCRYPT_CONFIG was -*** built for $libgcrypt_config_host and thus may not match the -*** used host $host. -*** You may want to use the configure option --with-libgcrypt-prefix -*** to specify a matching config script. -***" >&5 -$as_echo "$as_me: WARNING: -*** -*** The config script $LIBGCRYPT_CONFIG was -*** built for $libgcrypt_config_host and thus may not match the -*** used host $host. -*** You may want to use the configure option --with-libgcrypt-prefix -*** to specify a matching config script. -***" >&2;} - fi - fi - fi - else - LIBGCRYPT_CFLAGS="" - LIBGCRYPT_LIBS="" - : - fi - - - -else - openssl=true - case $host_os in *mingw*) ;; @@ -6930,7 +6579,7 @@ $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : LIBS="$LIBS -ldl" else - as_fn_error $? "OpenSSL depends on libdl." "$LINENO" 5; break + as_fn_error $? "LibreSSL/OpenSSL depends on libdl." "$LINENO" 5; break fi @@ -6968,7 +6617,7 @@ if test "${with_openssl_lib+set}" = set; then : fi - for ac_header in openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h openssl/ecdh.h openssl/ec.h + for ac_header in openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -6978,7 +6627,7 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : _ACEOF else - as_fn_error $? "OpenSSL header files not found." "$LINENO" 5; break + as_fn_error $? "LibreSSL/OpenSSL header files not found." "$LINENO" 5; break fi @@ -7024,12 +6673,12 @@ $as_echo "$ac_cv_lib_crypto_EVP_EncryptInit_ex" >&6; } if test "x$ac_cv_lib_crypto_EVP_EncryptInit_ex" = xyes; then : LIBS="-lcrypto $LIBS" else - as_fn_error $? "OpenSSL libraries not found." "$LINENO" 5 + as_fn_error $? "LibreSSL/OpenSSL libraries not found." "$LINENO" 5 fi - for ac_func in RAND_pseudo_bytes EVP_EncryptInit_ex ECDH_compute_key ECDSA_verify + for ac_func in RAND_bytes EVP_EncryptInit_ex EVP_CIPHER_CTX_new do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -7039,7 +6688,7 @@ if eval test \"x\$"$as_ac_var"\" = x"yes"; then : _ACEOF else - as_fn_error $? "Missing OpenSSL functionality, make sure you have installed the latest version." "$LINENO" 5; break + as_fn_error $? "Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version." "$LINENO" 5; break fi done @@ -7048,31 +6697,52 @@ done " if test "x$ac_cv_have_decl_OpenSSL_add_all_algorithms" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_OPENSSL_ADD_ALL_ALGORITHMS $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : else - as_fn_error $? "Missing OpenSSL functionality, make sure you have installed the latest version." "$LINENO" 5; break + as_fn_error $? "Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version." "$LINENO" 5; break fi +ac_fn_c_check_decl "$LINENO" "EVP_aes_256_cfb" "ac_cv_have_decl_EVP_aes_256_cfb" "#include - -fi - - if test "$openssl" = true; then - OPENSSL_TRUE= - OPENSSL_FALSE='#' +" +if test "x$ac_cv_have_decl_EVP_aes_256_cfb" = xyes; then : + ac_have_decl=1 else - OPENSSL_TRUE='#' - OPENSSL_FALSE= + ac_have_decl=0 fi - if test "$grypt" = true; then - GCRYPT_TRUE= - GCRYPT_FALSE='#' +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_EVP_AES_256_CFB $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + else - GCRYPT_TRUE='#' - GCRYPT_FALSE= + as_fn_error $? "Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version." "$LINENO" 5; break fi + for ac_func in BN_GENCB_new RSA_set0_key +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + # Check whether --enable-jumbograms was given. if test "${enable_jumbograms+set}" = set; then : enableval=$enable_jumbograms; if test "x$enable_jumbograms" = "xyes"; then : @@ -7085,7 +6755,12 @@ fi fi -ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile m4/Makefile gui/Makefile" +if test "x$runstatedir" = "x"; then + runstatedir='${localstatedir}/run' + +fi + +ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile systemd/Makefile" cat >confcache <<\_ACEOF @@ -7205,14 +6880,6 @@ $as_echo_n "checking that generated files are newer than configure... " >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - as_fn_error $? "conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' @@ -7221,6 +6888,14 @@ else am__EXEEXT_FALSE= fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${LINUX_TRUE}" && test -z "${LINUX_FALSE}"; then as_fn_error $? "conditional \"LINUX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -7253,12 +6928,12 @@ if test -z "${TUNEMU_TRUE}" && test -z "${TUNEMU_FALSE}"; then as_fn_error $? "conditional \"TUNEMU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${OPENSSL_TRUE}" && test -z "${OPENSSL_FALSE}"; then - as_fn_error $? "conditional \"OPENSSL\" was never defined. +if test -z "${WITH_SYSTEMD_TRUE}" && test -z "${WITH_SYSTEMD_FALSE}"; then + as_fn_error $? "conditional \"WITH_SYSTEMD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${GCRYPT_TRUE}" && test -z "${GCRYPT_FALSE}"; then - as_fn_error $? "conditional \"GCRYPT\" was never defined. +if test -z "${GETOPT_TRUE}" && test -z "${GETOPT_FALSE}"; then + as_fn_error $? "conditional \"GETOPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi @@ -7658,7 +7333,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by tinc $as_me 1.1pre8, which was +This file was extended by tinc $as_me 1.0.36, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7724,7 +7399,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -tinc config.status 1.1pre8 +tinc config.status 1.0.36 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -7843,7 +7518,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" _ACEOF @@ -7853,13 +7528,12 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 for ac_config_target in $ac_config_targets do case $ac_config_target in - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; - "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;; - "gui/Makefile") CONFIG_FILES="$CONFIG_FILES gui/Makefile" ;; + "systemd/Makefile") CONFIG_FILES="$CONFIG_FILES systemd/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac @@ -8459,29 +8133,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -8499,53 +8179,50 @@ $as_echo X"$mf" | q } s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } - /^X\(\/\/\)[^/].*/{ + /^X\/\(\/\/\)$/{ s//\1/ q } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ + /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk } ;; diff --git a/configure.ac b/configure.ac index af12f12..ca2948a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,12 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([tinc], [1.1pre8]) +AC_INIT([tinc], [1.0.36]) AC_CONFIG_SRCDIR([src/tincd.c]) -AC_GNU_SOURCE -AM_INIT_AUTOMAKE([check-news std-options subdir-objects -Wall]) +AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall]) AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) +AM_SILENT_RULES([yes]) # Enable GNU extensions. # Define this here, not in acconfig's @TOP@ section, since definitions @@ -17,8 +18,6 @@ dnl Checks for programs. AC_PROG_CC_C99 AC_PROG_CPP AC_PROG_INSTALL -AC_PROG_LN_S -AC_PROG_RANLIB AM_PROG_CC_C_O @@ -109,12 +108,23 @@ AC_ARG_ENABLE(tunemu, ) AC_ARG_WITH(windows2000, - AS_HELP_STRING([--without-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]), + 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"], [AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])]) ] ) +AC_ARG_WITH(systemd, + AS_HELP_STRING([--with-systemd@<:@=DIR@:>@], [install systemd service files @<:@to DIR if specified@:>@]), + [ systemd=true; systemd_path="$with_systemd" ], + [ systemd=false ] +) + +AS_IF([test "x$with_systemd" = "xyes"], [systemd_path="\${libdir}/systemd/system"], + [AS_IF([test "x$with_systemd" = "xno"], [systemd=false])]) + +AC_SUBST(systemd_path, $systemd_path) + AM_CONDITIONAL(LINUX, test "$linux" = true) AM_CONDITIONAL(BSD, test "$bsd" = true) AM_CONDITIONAL(SOLARIS, test "$solaris" = true) @@ -123,6 +133,7 @@ AM_CONDITIONAL(CYGWIN, test "$cygwin" = true) AM_CONDITIONAL(UML, test "$uml" = true) AM_CONDITIONAL(VDE, test "$vde" = true) AM_CONDITIONAL(TUNEMU, test "$tunemu" = true) +AM_CONDITIONAL(WITH_SYSTEMD, test "$systemd" = true) AC_CACHE_SAVE @@ -133,42 +144,65 @@ if test -d /sw/lib ; then LIBS="$LIBS -L/sw/lib" fi +dnl Compiler hardening flags +dnl No -fstack-protector-all because it doesn't work on all platforms or architectures. + +AX_CFLAGS_WARN_ALL(CFLAGS) + +AC_ARG_ENABLE([hardening], AS_HELP_STRING([--disable-hardening], [disable compiler and linker hardening flags])) +AS_IF([test "x$enable_hardening" != "xno"], + [AX_CHECK_COMPILE_FLAG([-DFORTIFY_SOURCE=2], [CPPFLAGS="$CPPFLAGS -DFORTIFY_SOURCE=2"]) + AX_CHECK_COMPILE_FLAG([-fwrapv], [CPPFLAGS="$CPPFLAGS -fwrapv"], + AX_CHECK_COMPILE_FLAG([-fno-strict-overflow], [CPPFLAGS="$CPPFLAGS -fno-strict-overflow"])) + case $host_os in + *mingw*) + AX_CHECK_LINK_FLAG([-Wl,--dynamicbase], [LDFLAGS="$LDFLAGS -Wl,--dynamicbase"]) + AX_CHECK_LINK_FLAG([-Wl,--nxcompat], [LDFLAGS="$LDFLAGS -Wl,--nxcompat"]) + ;; + *) + AX_CHECK_COMPILE_FLAG([-fPIE], [CPPFLAGS="$CPPFLAGS -fPIE"]) + AX_CHECK_LINK_FLAG([-pie], [LDFLAGS="$LDFLAGS -pie"]) + ;; + esac + AX_CHECK_LINK_FLAG([-Wl,-z,relro], [LDFLAGS="$LDFLAGS -Wl,-z,relro"]) + AX_CHECK_LINK_FLAG([-Wl,-z,now], [LDFLAGS="$LDFLAGS -Wl,-z,now"]) + ] +); + +dnl Checks for libraries. + dnl Checks for header files. dnl We do this in multiple stages, because unlike Linux all the other operating systems really suck and don't include their own dependencies. -AC_HEADER_STDC -AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h]) -AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h netpacket/packet.h], - [], [], [#include "src/have.h"] +AC_CHECK_HEADERS([syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/wait.h netdb.h arpa/inet.h arpa/nameser.h dirent.h getopt.h]) +AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/if_utun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h netpacket/packet.h], + [], [], [#include "$srcdir/src/have.h"] ) -AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h], - [], [], [#include "src/have.h"] +AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h], + [], [], [#include "$srcdir/src/have.h"] ) AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h], - [], [], [#include "src/have.h"] + [], [], [#include "$srcdir/src/have.h"] ) dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_C_VOLATILE AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_HEADER_TIME -AC_STRUCT_TM tinc_ATTRIBUTE(__malloc__) -tinc_ATTRIBUTE(__warn_unused_result__) AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, struct in_addr, struct addrinfo, struct ip, struct icmp, struct in6_addr, struct sockaddr_in6, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , , - [#include "src/have.h"] + [#include "$srcdir/src/have.h"] ) dnl Checks for library functions. AC_TYPE_SIGNAL -AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall putenv random select strdup strerror strsignal strtol system time usleep unsetenv vsyslog writev], - [], [], [#include "src/have.h"] +AC_CHECK_FUNCS([asprintf daemon fchmod flock fork gettimeofday mlockall pselect putenv strsignal system unsetenv usleep vsyslog devname fdevname], + [], [], [#include "$srcdir/src/have.h"] ) +AC_CHECK_FUNC(getopt_long, [getopt=true; AC_DEFINE(HAVE_GETOPT_LONG, 1, [getopt_long()])], [getopt=false]) +AM_CONDITIONAL(GETOPT, test "$getopt" = true) + dnl Support for SunOS AC_CHECK_FUNC(socket, [], [ @@ -179,39 +213,35 @@ AC_CHECK_FUNC(gethostbyname, [], [ ]) AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo], - [], [], [#include "src/have.h"] + [], [], [#include "$srcdir/src/have.h"] ) +AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [ + #include + #include +]) + AC_CACHE_SAVE 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 +tinc_OPENSSL -if test "$with_libgcrypt" = yes; then - gcrypt=true - AM_PATH_LIBGCRYPT([1.4.0], [], []) -else - openssl=true - tinc_OPENSSL -fi - -AM_CONDITIONAL(OPENSSL, test "$openssl" = true) -AM_CONDITIONAL(GCRYPT, test "$grypt" = true) - -dnl Check if support for jumbograms is requested +dnl Check if support for jumbograms is requested AC_ARG_ENABLE(jumbograms, - AS_HELP_STRING([--disable-jumbograms], [enable support for jumbograms (packets up to 9000 bytes)]), + 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]) +dnl Ensure runstatedir is set if we are using a version of autoconf that does not support it +if test "x$runstatedir" = "x"; then + AC_SUBST([runstatedir], ['${localstatedir}/run']) +fi + +AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile systemd/Makefile]) AC_OUTPUT diff --git a/debian/NEWS b/debian/NEWS new file mode 100644 index 0000000..b3eb367 --- /dev/null +++ b/debian/NEWS @@ -0,0 +1,14 @@ +tinc (1.0.27-1) unstable; urgency=medium + + This package now provides native systemd service files, allowing multiple + instances of tinc to be managed. Existing networks listed in + /etc/tinc/nets.boot will be converted to service instances once during this + upgrade. Afterwards, you can enable and disable networks using: + + systemctl enable tinc@ + systemctl disable tinc@ + + If you do not have systemd installed, the SysV init script will continue to + work as usual. For more information, see README.Debian. + + -- Guus Sliepen Sun, 10 Apr 2016 01:33:55 +0200 diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..d911295 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,80 @@ +tinc for Debian +--------------- + +The manual for tinc is also available as info pages, type `info tinc' +to read it. + +There are several ways in which tinc may be automatically started at boot: + +Systemd +------- + +Since 1.0.27-1, the tinc package comes with native systemd service files. +To enable and start a net, call: + +systemctl enable tinc@ +systemctl start tinc@ + +This will cause a tincd to be started which uses the configuration from +/etc/tinc/, and also makes sure that it will be started next time your +system boots. + +Apart from controlling individual instances, you can also start/stop/reload all +enabled instances simultaneously by omitting @, for example: + +systemctl reload tinc + +Note that when you have systemd installed on your system, the file +/etc/tinc/nets.boot will not be used anymore to automatically start tinc +daemons. If the variable EXTRA is defined in /etc/default/tinc, it will be +passed on to tinc. The variable LIMITS is however not used. + +The service files that come with this package start tinc unconditionally. +However, tinc does support socket activation. If you wish to write a socket +unit for tinc, use the ListenStream option to specify on which port(s) and +address(es) tinc should listen. + +SysVinit +-------- + +The system startup script for tinc, /etc/init.d/tinc, uses the file +/etc/tinc/nets.boot to find out which networks have to be started. Use one +netname per line. Lines starting with a # are ignored. + +/etc/network/interfaces +----------------------- + +You can create a stanza in /etc/network/interfaces, and add a line with +"tinc-net ". This will cause a tincd to be started which uses the +configuration from /etc/tinc/. You can use an inet static (with +address and netmask options) or inet dhcp stanza, in which case the ifup will +configure the VPN interface and you do not need to have a tinc-up script. + +The following options are also recognized and map directly to the corresponding +command line options for tincd: + +tinc-config +tinc-debug +tinc-mlock yes +tinc-logfile +tinc-pidfile +tinc-chroot yes +tinc-user + +An example stanza: + +iface vpn inet static + address 192.168.2.42 + netmask 255.255.0.0 + tinc-net myvpn + tinc-debug 1 + tinc-mlock yes + tinc-user nobody + tinc-pidfile /tmp/tinc.pid + +This will start a tinc daemon that reads its configuration from +/etc/tinc/myvpn, logs at debug level 1, locks itself in RAM, runs as user +nobody, and creates a network interface called "vpn". Ifup then sets the +address and netmask on that interface. + + -- Guus Sliepen , Sun, 10 April 2016, 01:38:08 +0200 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..04508d0 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,685 @@ +tinc (1.0.36-2) unstable; urgency=medium + + * Disable support for libvdeplug. Closes: #973233 + + -- Guus Sliepen Sun, 22 Nov 2020 10:40:27 +0100 + +tinc (1.0.36-1) unstable; urgency=medium + + * New upstream version 1.0.36 + * Add Vcs tags to debian/control. + * Bump Standards-Version. + + -- Guus Sliepen Mon, 26 Aug 2019 14:17:21 +0200 + +tinc (1.0.35-2) unstable; urgency=medium + + * Bump Standards-Version and Build-Depend on debhelper-compat (= 12). + * Remove calls to dh_installinit and dh_systemd_start from debian/rules, + compat level 12 does the right thing by default. + * Ensure we clean up doc/tinc.info. + + -- Guus Sliepen Mon, 28 Jan 2019 21:54:45 +0100 + +tinc (1.0.35-1) unstable; urgency=medium + + * New upstream release. + - Includes fixes for CVE-2018-16737, CVE-2018-16738, CVE-2018-16758. + + -- Guus Sliepen Mon, 08 Oct 2018 16:09:06 +0200 + +tinc (1.0.34-1) unstable; urgency=medium + + [ Guus Sliepen ] + * New upstream release. + - Fixes a potential segmentation fault when connecting to an IPv6 + peer via a proxy. Closes: #887401 + * Add support for the $EXTRA variable in /etc/default/tinc when using + systemd. Closes: #887116 + + [ Benda Xu ] + * Prevent possible incorrect IPv6 checksums due to function inlining. + Closes: #891400 + + -- Guus Sliepen Tue, 12 Jun 2018 23:00:49 +0200 + +tinc (1.0.33-1) unstable; urgency=medium + + * New upstream release. + * Test for /etc/default/tinc before trying to source it. Closes: #777262 + * Use --runstatedir=/run. + + -- Guus Sliepen Sat, 04 Nov 2017 16:22:06 +0100 + +tinc (1.0.32-1) unstable; urgency=medium + + * New upstream release. + * Add a note to new nets.boot files that it is not used with systemd. + Closes: #841052 + * In the post-down script, read the pid file only once. Closes: #832784 + * Explicitly use /bin/sleep from coreutils. Closes: #772379 + * Bump Standards-Version. + + -- Guus Sliepen Tue, 05 Sep 2017 20:23:36 +0200 + +tinc (1.0.31-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version. + * Bump debian/compat. + * Add missing Depends: lsb-base. + + -- Guus Sliepen Sun, 15 Jan 2017 16:20:40 +0100 + +tinc (1.0.29-2) unstable; urgency=medium + + * Rebuild with libssl-dev from unstable. + + -- Guus Sliepen Thu, 27 Oct 2016 13:09:46 +0200 + +tinc (1.0.29-1) unstable; urgency=medium + + * New upstream release. + * Bump debian/compat. + + -- Guus Sliepen Mon, 10 Oct 2016 22:30:25 +0200 + +tinc (1.0.28-1) unstable; urgency=medium + + * New upstream release. + - Fixes FTBFS on kfreebsd. + * Systemd service files are now provided by upstream. + + -- Guus Sliepen Sun, 10 Apr 2016 15:44:28 +0200 + +tinc (1.0.27-2) unstable; urgency=medium + + * Fix tinc@.service. + + -- Guus Sliepen Sun, 10 Apr 2016 12:45:33 +0200 + +tinc (1.0.27-1) unstable; urgency=medium + + * New upstream release. + * Bump Standards-Version. + * Add native systemd unit files. + * Automatically convert networks listed in nets.boot to systemd service + instances on upgrade. + + -- Guus Sliepen Sun, 10 Apr 2016 01:39:16 +0200 + +tinc (1.0.26-1) unstable; urgency=medium + + * New upstream release. + * Use the contents, not the presence, of the pidfile to check that tincd is + shut down properly. Closes: #774682 + * Bump Standards-Version. + + -- Guus Sliepen Sun, 05 Jul 2015 17:23:08 +0200 + +tinc (1.0.24-2) unstable; urgency=medium + + * Improve the init script: stopping tinc now waits for the process to + terminate. If that doesn't happen in 5 seconds, it will send the TERM + signal again (which helps if tinc is waiting for a script to finish + executing). It now also detects whether the process mentioned in the PID + file is actually running, and if not it will exit early and without + warnings. Closes: #748107 + + -- Guus Sliepen Wed, 14 May 2014 21:44:16 +0200 + +tinc (1.0.24-1) unstable; urgency=medium + + [ Guus Sliepen ] + * New upstream release + * Add a debian/watch file. + * Bump Standards-Version. + + [ Gian Piero Carrubba ] + * Allow resource limits to be set in /etc/default/tinc. + Closes: #690685, #704702 + + -- Guus Sliepen Sun, 11 May 2014 21:17:13 +0200 + +tinc (1.0.23-2) unstable; urgency=low + + * Use if-statements instead of && in shell scripts. Closes: #731279 + The && operator does not clear the error status, and if the next statement + in a shell script does not change the error status it would cause the + script to prematurely exit. Thanks to Peter Reinholdtsen for spotting it. + * Use absolute path to tincd in the if-post-down script. + + -- Guus Sliepen Thu, 05 Dec 2013 09:41:13 +0000 + +tinc (1.0.23-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Sat, 19 Oct 2013 21:06:05 +0200 + +tinc (1.0.22-1) unstable; urgency=low + + * New upstream release. + - Handles whitespace between command line flags and optional arguments. + Closes: #710267 + * Bump Standards-Version. + * Source /lib/lsb/init-functions in the init.d script. + * Don't use texi2html anymore, use automake's install-html target which uses + makeinfo. + + -- Guus Sliepen Wed, 14 Aug 2013 15:34:29 +0200 + +tinc (1.0.21-1) unstable; urgency=low + + * New upstream release. + - Includes fix for CVE-2013-1428. + + -- Guus Sliepen Sun, 05 May 2013 10:42:33 +0200 + +tinc (1.0.19-3) unstable; urgency=high + + * Drop packets forwarded via TCP if they are too big (CVE-2013-1428). + + -- Guus Sliepen Fri, 12 Apr 2013 22:52:10 +0200 + +tinc (1.0.19-2) unstable; urgency=low + + * Fix behaviour of tinc-pidfile. Closes: #679130 + * Enable parallel building in debian/rules. + + -- Guus Sliepen Tue, 26 Jun 2012 18:28:34 +0200 + +tinc (1.0.19-1) unstable; urgency=low + + * New upstream release. + * Bump debian/compat so tinc gets built with hardening flags. + * Allow tinc-pidfile in /etc/network/interfaces. + + -- Guus Sliepen Mon, 25 Jun 2012 20:29:22 +0200 + +tinc (1.0.18-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Sun, 25 Mar 2012 18:52:15 +0200 + +tinc (1.0.17-1) unstable; urgency=low + + * New upstream release. + * Enable support for UML and VDE. + + -- Guus Sliepen Sat, 10 Mar 2012 14:50:00 +0100 + +tinc (1.0.16-1) unstable; urgency=low + + * New upstream release. + * Mention alarm option in /etc/init.d/tinc's usage information. + Closes: #631761 + + -- Guus Sliepen Sat, 23 Jul 2011 14:37:56 +0200 + +tinc (1.0.15-1) unstable; urgency=low + + * New upstream release. + * Send SIGALRM to running tinc daemons whenever an interface is brought up + with the ifupdown framework. Based on a patch from Joachim Breitner. + Closes: #629880 + * Allow tinc daemons to be started using ifupdown. + + -- Guus Sliepen Fri, 24 Jun 2011 18:21:51 +0200 + +tinc (1.0.14-1) unstable; urgency=low + + * New upstream release. + * Bump Standards-Version. + + -- Guus Sliepen Mon, 09 May 2011 00:25:37 +0200 + +tinc (1.0.13-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Tue, 13 Apr 2010 12:06:36 +0200 + +tinc (1.0.12-2) unstable; urgency=low + + * Remove debconf questions. Closes: #572116 + Apparently debconf may not be used to ask a question at install time and + use the answer at upgrade time. Instead of kludging around this + restriction, no questions are asked anymore, and tinc will now always be + restarted when upgrading. + * Wait up to 5 seconds for tinc daemon to stop before restarting it. + + -- Guus Sliepen Tue, 02 Mar 2010 14:01:36 +0100 + +tinc (1.0.12-1) unstable; urgency=low + + * New upstream release. + * Bump Standards-Version. + * Migrate from CDBS to debhelper. + * Convert source package to 3.0 (quilt) format. + * Remove useless tinc.modules. + * Use init.d script from Michael Tokarev, allowing per-network arguments to + tincd. + * Remove update-rc.d calls from postinst and postrm. + * Let the init.d script depend on $remote_fs. + + -- Guus Sliepen Thu, 04 Feb 2010 00:56:45 +0100 + +tinc (1.0.11-1) unstable; urgency=low + + * New upstream release. + * Cope with texi2html arbitrarily changing its output directory. + Closes: #552927 + * Do not stop tinc when configuring a new version, just restart after + the upgrade. + + -- Guus Sliepen Sun, 01 Nov 2009 20:37:16 +0100 + +tinc (1.0.10-1) unstable; urgency=low + + * New upstream release. + * Include Russian debconf translation. Closes: #548759 + + -- Guus Sliepen Sun, 18 Oct 2009 16:31:49 +0200 + +tinc (1.0.9-1) unstable; urgency=low + + * New upstream release. + - Binds IPv6 sockets only to IPv6. Closes: #440150 + * Update copyright file. Closes: #482566 + + -- Guus Sliepen Fri, 26 Dec 2008 13:25:05 +0100 + +tinc (1.0.8-2) unstable; urgency=low + + * Include Portugese debconf translation. Closes: #434191 + + -- Guus Sliepen Tue, 14 Aug 2007 13:50:27 +0200 + +tinc (1.0.8-1) unstable; urgency=low + + * New upstream release. Closes: #173987 + * Include german debconf translation. Closes: #412351 + * Build-Depend on texinfo. Closes: #424209 + + -- Guus Sliepen Wed, 16 May 2007 17:59:16 +0200 + +tinc (1.0.7-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Fri, 5 Jan 2007 15:55:42 +0100 + +tinc (1.0.6-1) unstable; urgency=low + + * New upstream release. + + -- Guus Sliepen Mon, 18 Dec 2006 15:41:03 +0100 + +tinc (1.0.5-1) unstable; urgency=low + + * New upstream release. Closes: #391610 + * Add an LSB section to the init script. + + -- Guus Sliepen Tue, 14 Nov 2006 16:32:20 +0100 + +tinc (1.0.4-4) unstable; urgency=low + + * Include swedish debconf translation. Closes: #332963 + * Remove nets.boot on purge. Closes: #333303 + + -- Guus Sliepen Mon, 17 Oct 2005 12:34:32 +0200 + +tinc (1.0.4-3) unstable; urgency=low + + * Depend on debconf | debconf-2.0. + * Include vietnamese debconf translation. Closes: #322305 + * Include japanese debconf translation. Closes: #319591 + + -- Guus Sliepen Thu, 29 Sep 2005 11:15:34 +0200 + +tinc (1.0.4-2) unstable; urgency=low + + * Compensate for change in texinfo's output directory. Closes: #318562 + * Include Czech translation of the debconf questions. Closes: #312982 + + -- Guus Sliepen Sat, 16 Jul 2005 11:42:04 +0200 + +tinc (1.0.4-1) unstable; urgency=low + + * New upstream release. Closes: #294819 + * Update french translation of debconf template. Closes: #293371, #296148 + * Allow dashes in nets.boot. Closes: #296281 + + -- Guus Sliepen Wed, 4 May 2005 21:56:22 +0200 + +tinc (1.0.3-4) unstable; urgency=low + + * Call debconf early in postinst so it won't get confused by output + from other commands in the postinst script. Closes: #292920 + * If MAKEDEV doesn't know about net/tun, fall back to tun. + + -- Guus Sliepen Mon, 31 Jan 2005 13:27:16 +0100 + +tinc (1.0.3-3) unstable; urgency=low + + * Fix clean rule in debian/rules. + + -- Guus Sliepen Thu, 27 Jan 2005 23:16:59 +0000 + +tinc (1.0.3-2) unstable; urgency=low + + * Don't check for /dev/tap* in postinst if we don't create them anyway. + * MAKEDEV expects net/tun instead of tun. + * Don't ask if /dev/net/tun should be created, just do it. + Closes: #259489, #292450 + * Move $EXTRA from init.d/tinc to /etc/default/tinc. Closes: #281366 + + -- Guus Sliepen Thu, 27 Jan 2005 14:10:02 +0100 + +tinc (1.0.3-1) unstable; urgency=low + + * New upstream release. + * Adopting the package from Ivo. + * Use invoke-rc.d, and tell user to do so as well. Closes: #223276 + * Let force-reload do the same thing as reload. Closes: #230180 + + -- Guus Sliepen Fri, 1 Oct 2004 21:04:14 +0200 + +tinc (1.0.2-2) unstable; urgency=low + + * debian/control: Oops, really make that automake1.7. + + -- Ivo Timmermans Sat, 8 Nov 2003 21:53:04 +0100 + +tinc (1.0.2-1) unstable; urgency=low + + * New upstream release: + * Fix broken replies to CHAL_RESP. (Closes: #217646) + * debian/control: Updated automake build dependency to automake1.7. + (Closes: #219360) + + -- Ivo Timmermans Sat, 8 Nov 2003 19:56:04 +0100 + +tinc (1.0.1-2) unstable; urgency=low + + * debian/dirs: Removed, moved contents to tinc.dirs. + (Closes: #208591) + * debian/docs: Renamed to tinc.docs. + * debian/rules: Install the contents of doc/sample-config.tar.gz in + /usr/share/doc/tinc/examples instead of /etc/tinc. + * debian/Makefile*: Removed. + + -- Ivo Timmermans Wed, 10 Sep 2003 12:19:32 +0200 + +tinc (1.0.1-1) unstable; urgency=low + + * New upstream release. + * debian/patches/001_openbsd_device.c.patch: Removed. + + -- Ivo Timmermans Thu, 14 Aug 2003 17:03:28 +0200 + +tinc (1.0release-1) unstable; urgency=low + + * New upstream version. (Closes: #204639) + * Fixes switching back to normal logging mode when killing with + SIGINT twice. (Closes: #175633) + * Uses one SSL context struct for each connection, speeding up + encrypting/decrypting data; don't throw away out of sequence + packets. (Closes: #188874) + * Fixes handling of broadcast messages. (Closes: #175632) + * debian/rules: Use cdbs. + * debian/control: Build-Depend on cdbs, liblzo-dev. + * debian/patches/001_openbsd_device.c.patch: Sync openbsd/device.c to + latest CVS version. + + -- Ivo Timmermans Sun, 10 Aug 2003 16:13:29 +0200 + +tinc (1.0pre8-6) unstable; urgency=low + + * debian/po/fr.po: Added French debconf translation. (Closes: #201803) + + -- Ivo Timmermans Fri, 18 Jul 2003 10:03:20 +0200 + +tinc (1.0pre8-5) unstable; urgency=low + + * debian/*: Change to po-debconf, thanks to From: Michel Grentzinger + for the patch: + - change debhelper dependency to 4.1.16 (according to man + po-debconf), + - manually add nl translation in old tinc.templates (master), + - run debconf-gettextize debian/tinc.templates, + - move old templates files (debian/tinc.templates.*), + - change construction "If you say no" to "If you refuse", + * debian/rules: Call po2debconf. + * debian/rules: Don't copy COPYING.README to the package. + * debian/control: Update Standards-Version. + * debian/conffiles: Removed. + * debian/postinst: No longer use mknod directly, use MAKEDEV. + + -- Ivo Timmermans Tue, 15 Jul 2003 20:13:47 +0200 + +tinc (1.0pre8-4) unstable; urgency=low + + * src/net.h, src/net_packet.c, src/net_setup.c: Apply fix from CVS + for OpenSSL-related memory leaks. (Closes: #189432) + + -- Ivo Timmermans Mon, 5 May 2003 15:00:29 +0200 + +tinc (1.0pre8-3) unstable; urgency=low + + * m4/openssl.m4: Updated to CVS version. (Closes: #184400) + + -- Ivo Timmermans Thu, 13 Mar 2003 17:24:42 +0100 + +tinc (1.0pre8-2) unstable; urgency=low + + * debian/postinst: Create /dev/net/tun if it doesn't exist. + * debian/tinc.modules: Add alias for /dev/net/tun. + * debian/rules: Install tinc.modules. + * These things together: (Closes: #151967, #153156) + + -- Ivo Timmermans Wed, 13 Nov 2002 22:45:38 +0100 + +tinc (1.0pre8-1) unstable; urgency=low + + * New upstream version. + * debian/rules: + - DEB_BUILD_OPTIONS support. + - Enable --enable-tracing by default. + + -- Ivo Timmermans Tue, 17 Sep 2002 13:50:44 +0200 + +tinc (1.0pre7-3) unstable; urgency=low + + * Properly install _all_ info pages. (Closes: #144718) + + -- Ivo Timmermans Wed, 29 May 2002 14:01:21 +0200 + +tinc (1.0pre7-2) unstable; urgency=low + + * Dutch translation wasn't being installed. + + -- Ivo Timmermans Thu, 11 Apr 2002 09:26:14 +0200 + +tinc (1.0pre7-1) unstable; urgency=medium + + * New upstream release. + + -- Ivo Timmermans Tue, 9 Apr 2002 16:04:46 +0200 + +tinc (1.0pre6-3) unstable; urgency=medium + + * Synched with upstream CVS. + * Added build dependency on zlib1g-dev. (Closes: #141705) + + -- Ivo Timmermans Mon, 8 Apr 2002 21:19:31 +0200 + +tinc (1.0pre6-2) unstable; urgency=low + + * The Section was non-US again, so changed it back to main/net. + + -- Ivo Timmermans Thu, 28 Mar 2002 07:26:10 +0100 + +tinc (1.0pre6-1) unstable; urgency=low + + * New upstream release. + * Fixed text in debian/copyright + + -- Ivo Timmermans Wed, 27 Mar 2002 23:10:07 +0100 + +tinc (1.0pre5-4) unstable; urgency=low + + * Added a debconf question for restarting on upgrade. + * Added reload option to init.d, start with EXTRA='-d' default. + * Moved from non-US to main. + * Install example configuration files. + * The HTML documentation wasn't installed; fixed. + + -- Ivo Timmermans Tue, 26 Mar 2002 20:14:19 +0100 + +tinc (1.0pre5-3) unstable; urgency=low + + * Config variables are now treated case sentitivly again. + * Added a forgotten xstrdup. + + -- Ivo Timmermans Fri, 15 Feb 2002 12:35:17 +0100 + +tinc (1.0pre5-2) unstable; urgency=low + + * MaxTimeout accidentally wasn't configurable. (Closes: #119653) + + -- Ivo Timmermans Wed, 13 Feb 2002 13:36:54 +0100 + +tinc (1.0pre5-1) unstable; urgency=low + + * New upstream version. (Closes: #119653) + * Init script redone in sh. + + -- Ivo Timmermans Sun, 10 Feb 2002 16:39:53 +0100 + +tinc (1.0pre4-1.cvs010621.6) unstable; urgency=low + + * Somehow po-Makefile.in.in.diff got lost, readded. (Closes: #119157) + + -- Ivo Timmermans Thu, 15 Nov 2001 17:00:03 +0100 + +tinc (1.0pre4-1.cvs010621.5) unstable; urgency=low + + * Fix a typo in postinst that let it MAKEDEV even on devfs. + (Closes: #116034) + + -- Ivo Timmermans Thu, 18 Oct 2001 09:35:16 +0200 + +tinc (1.0pre4-1.cvs010621.4) unstable; urgency=low + + * Ask before creating the device files. (Closes: #111099) + * Add a section to the info file. + + -- Ivo Timmermans Fri, 12 Oct 2001 20:47:09 +0200 + +tinc (1.0pre4-1.cvs010621.3) unstable; urgency=low + + * Build and install html documentation. (Closes: #106843) + * Remove build-time dependency on libc6-dev. + + -- Ivo Timmermans Mon, 30 Jul 2001 22:03:52 +0200 + +tinc (1.0pre4-1.cvs010621.2) unstable; urgency=low + + * Changed location of the pidfile. (Closes: #102798) + + -- Ivo Timmermans Sun, 1 Jul 2001 01:57:43 +0200 + +tinc (1.0pre4-1.cvs010621.1) unstable; urgency=low + + * New upstream version. (Closes: #98730) + * Rebuilding automatically inserted new config.{sub|guess}. + (Closes: #98165) + * Updated Standards-Version. + * Don't include a sample configuration file. + + -- Ivo Timmermans Thu, 21 Jun 2001 14:08:49 +0200 + +tinc (1.0pre3-5) unstable; urgency=low + + * Fixed an error in the init script that prevented tinc from + starting correctly. + + -- Ivo Timmermans Thu, 8 Feb 2001 02:45:09 +0100 + +tinc (1.0pre3-4) unstable; urgency=low + + * Change build-depends for OpenSSL to libssl096-dev + (Closes: #84197, #84873). + + -- Ivo Timmermans Sun, 4 Feb 2001 22:43:22 +0100 + +tinc (1.0pre3-3) unstable; urgency=low + + * Set architecture to any (really this time!) (Closes: #80451). + * Section set to non-US + + -- Ivo Timmermans Tue, 23 Jan 2001 22:52:53 +0100 + +tinc (1.0pre3-2) unstable; urgency=low + + * Set architecture to any (Closes: #80451). + * Added tinc.modules with some useful module aliases. + + -- Ivo Timmermans Sat, 13 Jan 2001 16:10:57 +0100 + +tinc (1.0pre3-1) unstable; urgency=low + + * New upstream version (1.0pre3) (Closes: #71274). + * Better Depends and Build-Depends lines. + * Dropped dependencies on libgmp, added libssl. + * doc-base.tinc: New file. + * Deleted the file shlibs, as there on longer is a libblowfish. + * Patch po/Makefile.in.in from po-Makefile.in.in.diff if necessary. + * Use dh_perl to get accurate perl dependencies. + + -- Ivo Timmermans Thu, 9 Nov 2000 21:58:40 +0100 + +tinc (1.0pre2-1.1) unstable; urgency=low + + * NMU at Ivo's request as his application is being processed, and his + sponsor is based in the US. + + -- J.H.M. Dassen (Ray) Wed, 28 Jun 2000 21:52:30 +0200 + +tinc (1.0pre2-1) unstable; urgency=low + + * postinst creates a file /etc/tinc/nets.boot, containing all networks + to be started upon system startup; + * init.d script starts all networks from that list. + * postinst script creates tap devices. + + -- Ivo Timmermans Tue, 16 May 2000 00:06:25 +0200 + +tinc (1.0pre1-0.4) unstable; urgency=low + + * postinst script. + + -- Ivo Timmermans Mon, 15 May 2000 19:22:05 +0200 + +tinc (1.0pre1-0.3) unstable; urgency=low + + * system startup script. + + -- Ivo Timmermans Sun, 14 May 2000 22:58:02 +0200 + +tinc (1.0pre1-0.2) unstable; urgency=low + + * Included the blowfish license. + + -- Ivo Timmermans Fri, 21 Apr 2000 17:07:50 +0200 + +tinc (1.0pre1-0.1) unstable; urgency=low + + * Initial Release. + + -- Ivo Timmermans Fri, 21 Apr 2000 17:07:50 +0200 + + diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..98c0678 --- /dev/null +++ b/debian/control @@ -0,0 +1,20 @@ +Source: tinc +Section: net +Priority: optional +Maintainer: Guus Sliepen +Standards-Version: 4.4.0 +Build-Depends: libssl-dev, debhelper-compat (= 12), gettext, texinfo, zlib1g-dev, liblzo2-dev +Homepage: http://www.tinc-vpn.org/ +Vcs-Browser: https://salsa.debian.org/guus/tinc +Vcs-Git: https://salsa.debian.org/guus/tinc.git +Rules-Requires-Root: no + +Package: tinc +Architecture: any +Pre-Depends: ${misc:Pre-Depends} +Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.0-6) +Description: Virtual Private Network daemon + tinc is a daemon with which you can create a virtual private network + (VPN). One daemon can handle multiple connections, so you can + create an entire (moderately sized) VPN with only one daemon per + participating computer. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..c8a6fb8 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,34 @@ +This package was debianized by Ivo Timmermans on +Fri, 21 Apr 2000 17:07:50 +0200. + +It was downloaded from http://www.tinc-vpn.org/ + +Upstream Authors: + Guus Sliepen + Ivo Timmermans + +Copyright (C) 1998-2005 Ivo Timmermans + 1998-2008 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + +On Debian GNU/Linux systems, the complete text of the GNU General Public +License version 2 can be found in /usr/share/common-licenses/GPL-2. + +The following applies to tinc: + +This program is released under the GPL with the additional exemption +that compiling, linking, and/or using OpenSSL is allowed. You may +provide binary packages linked to the OpenSSL libraries, provided that +all other requirements of the GPL are met. + +The following applies to the LZO library: + +Hereby I grant a special exception to the tinc VPN project +(http://tinc.nl.linux.org/) to link the LZO library with the OpenSSL library +(http://www.openssl.org). + +Markus F.X.J. Oberhumer diff --git a/debian/doc-base.tinc b/debian/doc-base.tinc new file mode 100644 index 0000000..a37f46a --- /dev/null +++ b/debian/doc-base.tinc @@ -0,0 +1,10 @@ +Document: tinc +Title: tinc Manual +Author: Ivo Timmermans, Guus Sliepen +Abstract: This manual describes how to set up a Virtual Private + Network with tinc. +Section: System/Security + +Format: HTML +Files: /usr/share/doc/tinc/tinc.html/* +Index: /usr/share/doc/tinc/tinc.html/index.html diff --git a/debian/info b/debian/info new file mode 100644 index 0000000..5468d6c --- /dev/null +++ b/debian/info @@ -0,0 +1 @@ +doc/tinc.info diff --git a/debian/patches/fix-incorrect-icmpv6-checksum b/debian/patches/fix-incorrect-icmpv6-checksum new file mode 100644 index 0000000..4448b88 --- /dev/null +++ b/debian/patches/fix-incorrect-icmpv6-checksum @@ -0,0 +1,65 @@ +Package: tinc +Version: 1.0.33-1 +Severity: important + +Dear Guus, + +I have been using tinc since 2009 and it is great! + +When PMTUDiscovery=yes and Mode=switch, and if ipv6 is used inside +tinc, the ICMPv6 "Packet Too Big" packets have incorrect checksums. +It can be reproduced by `ping6 -s 1800` and `tcpdump -i +`. Consequently, the host ignores the tinc-generated +ICMPv6 packets, PMTUDiscovery does not work and the connections freeze +when data flows are big. + +I find the bug is gone if the function "inet_checksum" in route.c is +not inlined, either by compiling tinc with "-O2 +-fno-inline-functions", or apply a patch such as, + +diff --git a/src/route.c b/src/route.c +index ff82c06e..cd55383a 100644 +--- a/src/route.c ++++ b/src/route.c +@@ -60,7 +60,7 @@ static const size_t opt_size = sizeof(struct nd_opt_hdr); + + /* RFC 1071 */ + +-static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { ++__attribute__ ((noinline)) static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { + uint16_t *p = data; + uint32_t checksum = prevsum ^ 0xFFFF; + + + +I have tested with gcc-7.3.0 and gcc-5.4.0. They behaved the same. I +am not good at assembly to find out what really happened, but it is +for sure that inet_checksum does not work as expected if compiled +inline. + +Thanks! + +Yours, +Benda + +-- System Information: +Debian Release: buster/sid + APT prefers unstable + APT policy: (500, 'unstable') +Architecture: amd64 (x86_64) + +Kernel: Linux 4.9.0-5-amd64 (SMP w/8 CPU cores) +Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8), LANGUAGE=en_US:en (charmap=UTF-8) (ignored: LC_ALL set to en_US.UTF-8) +Shell: /bin/sh linked to /bin/dash +Init: sysvinit (via /sbin/init) + +Versions of packages tinc depends on: +ii libc6 2.26-2 +ii liblzo2-2 2.08-1.2+b2 +ii libssl1.1 1.1.0g-2 +ii lsb-base 9.20170808 +ii zlib1g 1:1.2.8.dfsg-5 + +tinc recommends no packages. + +tinc suggests no packages. diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..a4c8974 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,2 @@ +fix-incorrect-icmpv6-checksum +support-etc-defaults-tinc diff --git a/debian/patches/support-etc-defaults-tinc b/debian/patches/support-etc-defaults-tinc new file mode 100644 index 0000000..80b3d86 --- /dev/null +++ b/debian/patches/support-etc-defaults-tinc @@ -0,0 +1,12 @@ +--- a/systemd/tinc@.service.in ++++ b/systemd/tinc@.service.in +@@ -9,7 +9,8 @@ + [Service] + Type=simple + WorkingDirectory=@sysconfdir@/tinc/%i +-ExecStart=@sbindir@/tincd -n %i -D ++EnvironmentFile=/etc/default/tinc ++ExecStart=@sbindir@/tincd -n %i -D $EXTRA + ExecReload=@sbindir@/tincd -n %i -kHUP + KillMode=mixed + Restart=on-failure diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000..c4f5d53 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,31 @@ +#! /bin/sh + +NETSFILE="/etc/tinc/nets.boot" + +set -e + +case "$1" in + configure) + if [ ! -e /dev/.devfsd ] ; then if [ ! -e /dev/.devfs ] ; then + if [ ! -e /dev/net/tun ] ; then if [ ! -e /dev/tun ] ; then if [ -e /dev/MAKEDEV ]; then + echo "Creating tun device..." + cd /dev && ./MAKEDEV net/tun 2>/dev/null || ./MAKEDEV tun 2>/dev/null || echo "Failed to create tun device." + fi; fi; fi + fi; fi + + if [ ! -e $NETSFILE ] ; then + echo "## This file contains all names of the networks to be started on system startup when using sysvinit." > $NETSFILE + echo "## If you are using systemd, use systemctl enable tinc@netname to enable individual networks." >> $NETSFILE + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 0 + ;; +esac + +#DEBHELPER# diff --git a/debian/postrm b/debian/postrm new file mode 100644 index 0000000..dc3247b --- /dev/null +++ b/debian/postrm @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +if [ "$1" = purge ]; then + rm -f /etc/tinc/nets.boot +fi + +#DEBHELPER# diff --git a/debian/preinst b/debian/preinst new file mode 100644 index 0000000..721a2bd --- /dev/null +++ b/debian/preinst @@ -0,0 +1,28 @@ +#!/bin/sh + +NETSFILE="/etc/tinc/nets.boot" +SYSTEM="/lib/systemd/system" +WANTS="/etc/systemd/system/multi-user.target.wants" + +set -e + +case "$1" in + upgrade) + if dpkg --compare-versions "$2" '<<' "1.0.27-1"; then + if [ -f "$NETSFILE" ]; then + echo -n "Creating systemd service instances from nets.boot:" + mkdir -p "$WANTS" + egrep '^[ ]*[a-zA-Z0-9_-]+' $NETSFILE | while read net args; do + echo -n " $net" + ln -s "$SYSTEM/tinc@.service" "$WANTS/tinc@$net.service" 2>/dev/null || true + done + echo "." + fi + fi + ;; + + *) + ;; +esac + +#DEBHELPER# diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..ee2949d --- /dev/null +++ b/debian/rules @@ -0,0 +1,16 @@ +#!/usr/bin/make -f + +%: + dh $@ + +override_dh_clean: + dh_clean + rm -f doc/tinc.info + +override_dh_auto_configure: + dh_auto_configure -- --enable-uml --with-systemd=/lib/systemd/system --runstatedir=/run + +override_dh_auto_install: + dh_auto_install -- install-html + # Remove info dir file + rm -f debian/tinc/usr/share/info/dir diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/tinc.default b/debian/tinc.default new file mode 100644 index 0000000..bca2432 --- /dev/null +++ b/debian/tinc.default @@ -0,0 +1,7 @@ +# Extra options to be passed to tincd. +# EXTRA="-d" + +# Limits to be configured for the tincd process. Please read your shell +# (pointed by /bin/sh) documentation for ulimit. You probably want to raise the +# max locked memory value if using both --mlock and --user flags. +# LIMITS="-l 1024" diff --git a/debian/tinc.dirs b/debian/tinc.dirs new file mode 100644 index 0000000..1eae2e2 --- /dev/null +++ b/debian/tinc.dirs @@ -0,0 +1,7 @@ +usr/sbin +usr/share +etc +etc/init.d +usr/share/locale +usr/share/doc/tinc +etc/tinc diff --git a/debian/tinc.docs b/debian/tinc.docs new file mode 100644 index 0000000..eb9b151 --- /dev/null +++ b/debian/tinc.docs @@ -0,0 +1,3 @@ +NEWS +README +AUTHORS diff --git a/debian/tinc.files b/debian/tinc.files new file mode 100644 index 0000000..3d376cc --- /dev/null +++ b/debian/tinc.files @@ -0,0 +1,6 @@ +usr/sbin/tincd +usr/share/man +etc +usr/share/doc/tinc +usr/share/locale +usr/share/info diff --git a/debian/tinc.if-post-down b/debian/tinc.if-post-down new file mode 100755 index 0000000..e173476 --- /dev/null +++ b/debian/tinc.if-post-down @@ -0,0 +1,41 @@ +#!/bin/sh + +set -e + +if [ "$METHOD" = loopback -o -z "$IF_TINC_NET" ]; then + exit 0 +fi + +# Determine location of the PID file + +EXTRA="" +if [ -n "$IF_TINC_PIDFILE" ]; then + EXTRA="--pidfile=$IF_TINC_PIDFILE" +else + IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid +fi + +# Stop the tinc daemon + +read pid rest < $IF_TINC_PIDFILE 2>/dev/null + +/usr/sbin/tincd -n "$IF_TINC_NET" -k $EXTRA + +# Wait for it to shut down properly + +/bin/sleep 0.1 +i=0; +while [ -f $IF_TINC_PIDFILE ] ; do + if [ ! -e "/proc/$pid" ] ; then + exit 0 + fi + + if [ $i = '30' ] ; then + echo 'Failed to stop tinc daemon!' + exit 1 + fi + /bin/sleep 0.1 + i=$(($i+1)) +done + +exit 0 diff --git a/debian/tinc.if-pre-up b/debian/tinc.if-pre-up new file mode 100755 index 0000000..68a3b53 --- /dev/null +++ b/debian/tinc.if-pre-up @@ -0,0 +1,70 @@ +#!/bin/sh + +set -e + +if [ "$METHOD" = loopback -o -z "$IF_TINC_NET" ]; then + exit 0 +fi + +# Read options from /etc/default + +[ -r /etc/default/tinc ] && . /etc/default/tinc + +# Set process limits + +setlimits() { + while [ $# -gt 0 ]; do + parm=$1 ; shift + if [ -n "$1" -a "${1#-}" = "$1" ]; then + value=$1 ; shift + ulimit $parm $value + else + ulimit $parm + fi + done +} + +test -n "$LIMITS" && setlimits $LIMITS + +# Read options from /etc/network/interfaces + +[ -n "$IF_TINC_CONFIG" ] && EXTRA="$EXTRA -c $IF_TINC_CONFIG" +[ -n "$IF_TINC_DEBUG" ] && EXTRA="$EXTRA -d$IF_TINC_DEBUG" +[ -n "$IF_TINC_MLOCK" ] && EXTRA="$EXTRA --mlock" +[ -n "$IF_TINC_LOGFILE" ] && EXTRA="$EXTRA --logfile=$IF_TINC_LOGFILE" +[ -n "$IF_TINC_PIDFILE" ] && EXTRA="$EXTRA --pidfile=$IF_TINC_PIDFILE" || IF_TINC_PIDFILE=/var/run/tinc.$IF_TINC_NET.pid +[ -n "$IF_TINC_CHROOT" ] && EXTRA="$EXTRA --chroot" +[ -n "$IF_TINC_USER" ] && EXTRA="$EXTRA --user=$IF_TINC_USER" + + +# Start tinc daemon + +/usr/sbin/tincd -n "$IF_TINC_NET" -o "Interface=$IFACE" $EXTRA + +# Wait for it to come up properly + +/bin/sleep 0.1 +i=0; +while [ ! -f $IF_TINC_PIDFILE ] ; do + if [ $i = '30' ] ; then + echo 'Failed to start tinc daemon!' + exit 1 + fi + /bin/sleep 0.1 + i=$(($i+1)) +done + +while read pid rest < $IF_TINC_PIDFILE ; do + if [ -e "/proc/$pid" ] ; then + exit 0 + fi + + if [ $i = '30' ] ; then + echo 'Failed to start tinc daemon!' + exit 1 + fi + /bin/sleep 0.1 + i=$(($i+1)) +done + +exit 0 diff --git a/debian/tinc.if-up b/debian/tinc.if-up new file mode 100755 index 0000000..364f88f --- /dev/null +++ b/debian/tinc.if-up @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +if [ "$METHOD" = loopback -o -n "$IF_TINC_NET" ]; then + exit 0 +fi + +invoke-rc.d tinc alarm || exit 0 diff --git a/debian/tinc.init b/debian/tinc.init new file mode 100644 index 0000000..44ff4cf --- /dev/null +++ b/debian/tinc.init @@ -0,0 +1,140 @@ +#! /bin/sh +# +### BEGIN INIT INFO +# Provides: tinc +# Required-Start: $remote_fs $network +# Required-Stop: $remote_fs $network +# Should-Start: $syslog $named +# Should-Stop: $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start tinc daemons +# Description: Create a file $NETSFILE (/etc/tinc/nets.boot), +# and put all the names of the networks in there. +# These names must be valid directory names under +# $TCONF (/etc/tinc). Lines starting with a # will be +# ignored in this file. +### END INIT INFO +# +# Based on Lubomir Bulej's Redhat init script. + +. /lib/lsb/init-functions + +DAEMON="/usr/sbin/tincd" +NAME="tinc" +DESC="tinc daemons" +TCONF="/etc/tinc" +NETSFILE="$TCONF/nets.boot" +NETS="" + +test -f $DAEMON || exit 0 + +[ -r /etc/default/tinc ] && . /etc/default/tinc + +# foreach_net "what-to-say" action [arguments...] +foreach_net() { + if [ ! -f $NETSFILE ] ; then + echo "Please create $NETSFILE." + exit 0 + fi + echo -n "$1" + shift + egrep '^[ ]*[a-zA-Z0-9_-]+' $NETSFILE | while read net args; do + echo -n " $net" + "$@" $net $args + done + echo "." +} + +signal_running() { + for i in /var/run/tinc.*pid; do + if [ -f "$i" ]; then + head -1 $i | while read pid; do + kill -$1 $pid + done + fi + done +} + +setlimits() { + while [ $# -gt 0 ]; do + parm=$1 ; shift + if [ -n "$1" -a "${1#-}" = "$1" ]; then + value=$1 ; shift + ulimit $parm $value + else + ulimit $parm + fi + done +} + +test -n "$LIMITS" && setlimits $LIMITS + +start() { + $DAEMON $EXTRA -n "$@" +} + +stop() { + [ -f /var/run/tinc.$1.pid ] || return + read pid rest /dev/null || return + + $DAEMON -n $1 -k || return + + i=0; + /bin/sleep 0.5 + + # Wait for the pidfile to disappear + while [ -f /var/run/tinc.$1.pid ]; do + # And check that there is an actual process running + kill -0 "$pid" 2>/dev/null || return + + if [ $i = '10' ] ; then + # It's still alive, kill it again and give up + $DAEMON -n $1 -k && /bin/sleep 0.5 + break + else + echo -n "." + i=$(($i+1)) + fi + + /bin/sleep 0.5 + done +} + +reload() { + $DAEMON -n $1 -kHUP +} + +alarm() { + $DAEMON -n $1 -kALRM +} + +restart() { + stop "$@" + start "$@" +} + +case "$1" in + start) + foreach_net "Starting $DESC:" start + ;; + stop) + foreach_net "Stopping $DESC:" stop + ;; + reload|force-reload) + foreach_net "Reloading $DESC configuration:" reload + ;; + restart) + foreach_net "Restarting $DESC:" restart + ;; + alarm) + signal_running ALRM + ;; + *) + echo "Usage: /etc/init.d/$NAME {start|stop|reload|restart|force-reload|alarm}" + exit 1 + ;; +esac + +exit 0 diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc new file mode 100644 index 0000000..a79b551 --- /dev/null +++ b/debian/upstream/signing-key.asc @@ -0,0 +1,70 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQINBEVZzTABEADawFv/ibQ48uA1eRhL07vdM36Pcq2HDyuyNA+vYEalNH4jLmha +nGPvDALWwX0DXIWDAG8zeTj8s8zliLIjuPS4WRI2YdKIvWeG9fEvpKSXVWa42ica +dpzn/H2aBd4Ax6rQaiTXKOvxANAp2Veb+73ssPV5AL00uGTpzhh98xQzfFQCZ9ZL +YSVPqbMed5oCt/4jM9FBO2CuBtkfiO0dVVYtW7FAVjcIlE2NaZol/KGvz7wsS+yA +dE42W0l5MdQueLmTF4AIUSSTyPFGMQoyqh+MPif73Y589IGcW6GdfKYWnVDo6Trh +HOhcEky+uTYKb6NL0vrJgUiYVMzAOXFDdJni1eQGO6EfZRNYtTga3alWq/jVelK7 +BID5JyNbkrTAqdPnhJGivVyk8gGX3+Hng8rkXTfWhp6yAYau1QfBm0F2tIQmpL1C ++7DoLvFErboQf685jXJBjzyvsJxB2ZLH1OOw6mNL0hy2LFkIyGza/bktY2em4apo +KWV5AM5LpyW6THH1oDS7706xFNkf4IFhKE0hKPzBiRnMDjRtMI131lkc5+P8Lqf5 +jLTCFUgbEhU6Dz2YjhHAumVm0NWJETUpFDtVvMrqk+mp5xldUOWRNlYQC5aQOyda +eHOlNzB/BFbPhKMWI/zWlEH6f0t6WjHb4iwpWO47511aVNHF59aPzbAHxwARAQAB +tC9UaW5jIERldmVsb3BtZW50IFRlYW0gPHRpbmMtZGV2ZWxAdGluYy12cG4ub3Jn +PokCNgQTAQIAIAUCRVnNMAIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEEpg +hLnA1x9KxOAQAMPhO2WTXv9AaGQBQhyyoGseKoSfcRjtI9YEfE0OInQQ2E+SPYF/ +dkfeLGAUqa4foTYQlMqfw70vBhTdVCb7HLTGn6/ICFUtDwakUQCgUQGlUVQiondA +8W6jj+QWrh5BQhHuXy2nCVaKnksu0/xQPsJotghxuYqaot3iJ4qVw9iT/Yeo9irH +Ffftqu0OVCdQ5zQuFNI9YCv/C83L59ecH7bOzYz2efTyobvxrhmgQtgOQwCWOE09 +Kr3veM9KLG33YoXlqv8QN/3CwtsJvSwfhj+R2JowZC7RqHe/yznRzmRMsgbrolxi +uiJLonGxcNNkD7WhXi7/zL4A/JaC27XrFf1MPLv8aiTwnOIfrXd5jawpauUOZOXK +UjIZHlIqviB0r5s7A+AFeHW38Tp9VzNuQ7aEl5bHbSXV+s7DTAwGb279z0AVaJ3h +5hWFxupw7UoGdzROwCBYzeX3sioAL6QvkXua8X6zOH45VEiSwrRX3Hlx/MLo7Z4g +PWgFLf6WviHQXCG834To1XIwUk9RgNsL7OzGjtaCuRymADImKMNwierq2zTfoRFQ +v9onIadIMF1fsc70hiBG9yAi36MEuk4VxG8Jc3PQQfSFm4RWazv1k3E0AAIob2Ek +DLVjvLO62Navo/OQ6D7yyiX0qes5S7/k3F1h8+87eRn3yxZE2kbxPg8KuQENBEVZ +zYYBCACoYgExmMKEtABL3pir/IXI4exR/45hkP6txFIrkVQb8DGJ9H39kiDr4gtj +F+pvcgMpec35S3m4fJ7WhDNvbDB4ZvONc1NMKs9cqDXfB+TLWPm4W+SkcKUrs+nK +i8l7ieggTALJcvRoLTX2EFmUFrD6y870W3rK2SfC/0VJX8Ou5cPbwCeueExjo5x0 +3gNfu0jWUS0cyA9y+1rVVekrLuJY/+SI4jv3gdzrYbxD0f6dpbpC37QHoJdd0KGF +acPtT2azjY+HxW10EA3Aw9oZWFXnb1nFg2RbDpkaGLmLbaXweltLyw154UmCXxym +PXPqi9bSfEkj0GiYrapk4mW114u9ABEBAAGJA0QEGAECAA8FAkVZzYcCGwIFCQHh +M4ABKQkQSmCEucDXH0rAXSAEGQECAAYFAkVZzYcACgkQ017duBDeLmmu3wf/TFZM +tLKxiyQPtGSTE3eULPdWCEMDZXdSPTY0QHM7Zvh+qn1ei+iFpD0549MYnBEAwDIV +4o62Nrcg8IPu0CEkZIAn2JiFFGYvMGk91awZGV1GS3umd7Dt349E1oKDPZVzRn+j +QIKarXxxabRmx2s/dZZgSs/eguWTboBFmvls9tVfe8x/xPvcHFmqHVUoGKEJy6Tm +no+s4yNjpc5wAaRml+GYf1tK9WMFuZn79qKxkYv4WI96dXR0FL59YbFRkkaI+1/b +G31MvWTqVjY1nJGslByFPUUB8Ca1djtp1gx6NXnOYr3V5MEDfdbjjPu79No+/y6M +tIua5yNtSRlk2nKhIqo3D/sGQ/uHijiMRAtoLhiyqYMc9W9vx/KOoCUHoMJqE39a +Eputvgwwo0rwgSmNfB1dzneFojBdJ47WBSHC8NKtkpJj6mzvvlaI9jmEpK54x3nl +OmBj3X/xaepoRGAtrmgTBP4A9hSjrTMGu/tUQjlX+Xcr6n3g7GSVe5FpUyIMPXEU ++JZDTiEUyn1OdzfNGmnWP+KJX5pQVq4czf5XK6otLZJELDVw/Hbjnjmdz5WOKgEH +jSof3WPeMBgPAcd/cMAZeiGtWM1UpJBHqEXTkthmrpmtRftJKDbooNM9d5OwKiT+ +I3vNBv/plMSr8NDjhTWC+ihrN6RBj1vaqpDgGpucPhoO2hwNqWuI4q5WUKtCyw6J +An7ErNaH4c0nVaZq6kJ8Vxdt+LpKYmOsJ8y9xtl6StcrkKNn+6ZfCfee7DEo2bvb +scfpqJqqOqb5KOagTpYs8mo6yQ3leRvFtoeBOQHVQzct23EwOMxbDyeunT50a1eH +MZTEWuIiuCUudM81QXU46oIcaAtj8tpG0Tmnku9g27EjwxUt+8kVmhlPHMb2TdoF +k5d0ce+JuxIG5+i+t8sUCorMc8zfp4g1bxZeMOcPnfyO3bSW11EVcN7ZxHlFC+XE +YOByP50CM3P8lItPlQ+WpY9kYWjiwu9kVPaGQ16G47nspngJInU5dhka3KJGtIZe +q7kBDQRFWc3GAQgAz/JUs24niKsd0ZtOjUWd4R4y0gjS0kC/vvLL2gbXYkA9tcjG +5iEvVWJY34QsudX0v1ULsVnJ89X/gsk8hAhAia1TQm+0Qq+MSxEaQkMSaOO8N70U +XzgH1dielvpea20WO4MyWQuRIJ0K2nsGmEPnt6ZP7fK8HVHFNggP/mQ6LMu1reAF +gvb8cEtjb9B5QaCUEoLjsbsuo+vLW7AWy4GfIRNESHw2Qt08AUaGrihpu6zi7N2b +QkHHJtqa63GzYJ+kYzAVvrFJXdwL/TRXLBzv+6yyvYSIHi8uB6/o6CZN6hpjfpME +ph+oYPqXeNOyMd1E9Kg8ymcPrNyQKfE3WnCRXQARAQABiQIlBBgBAgAPBQJFWc3H +AhsMBQkB4TOAAAoJEEpghLnA1x9KXYMP/3D9JYti6C8DWuX2hWv+2SUbLcMa5u1e +ETewIo5S3mqGWSaxX4YLPVRkZ1lOLmFysOLimf0thYm7IsatLcWmBdYUpK92ilvr +Sk2sKlhrOoBXEX/79Kz+Aj5PjeyiQxgQ7Ba/afwhU6aTqs2Dp1T0YNu2eBvV+1QH +lZnW2Wh96zzwc0dJUuY9eBk5Fgpu08Wce7o6jxFPtVyAaQa0zcNAmw2TSY7wbunJ +WTl9OgATAyqVCuhWW7AnPcSqkH8lQigSc00wfqJKOD2Us0FqN6UKDCZTyQkdP6hx +G+3aUkkvGSOxy7u9bVWmrikuJMoiIY/CH/m+GcJJATVibI7t5MhhtBGySKc3PAwc +58sVe9AnbDvs84efrNP59j2KG2KKqcqjTGAmKyJnG3N50xJGakDIsqfneIRNWpEE +pOOPaOqR4qnPAS9OSt9A3hqBpWPjQcScd6AuO+J2PE5y23pTnb9PtLBQb5e4VFiv +N54u8j4bU2CO0SC2isZ3CR68dPHthWsxt4XbjhgktjbpQRQ8L2EDBQ8oE13GOrOw +P8x4Q0eC5uzkXNyRqzKOsxlZEuc+75aDDd3M2GDw08FG7GI1p/L+NgenwT+9TmFX +2hOKVrjgyx+fPut1t5DJJubDWXGOK33qvrL7HTCEv1zz7LNbbPwwNHK4lfMAWuJW +D9wc3Y9Se/P/ +=5MAs +-----END PGP PUBLIC KEY BLOCK----- diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..f29609e --- /dev/null +++ b/debian/watch @@ -0,0 +1,2 @@ +version=3 +opts=pgpsigurlmangle=s/$/.sig/ http://www.tinc-vpn.org/packages/tinc-(1\.0\.\d+)\.tar\.gz diff --git a/depcomp b/depcomp index 4ebd5b3..6b39162 100755 --- a/depcomp +++ b/depcomp @@ -1,9 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2013-05-30.07; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2020 Free Software Foundation, Inc. # 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 @@ -16,7 +16,7 @@ scriptversion=2013-05-30.07; # UTC # 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 . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -783,9 +783,9 @@ exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/doc/Makefile.am b/doc/Makefile.am index 9540b49..29d6ffd 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,58 +1,35 @@ ## Process this file with automake to get Makefile.in info_TEXINFOS = tinc.texi +tinc_TEXINFOS = tincinclude.texi -man_MANS = tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 +man_MANS = tincd.8 tinc.conf.5 -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 tincd.8.in tinc.conf.5.in sample-config -CLEANFILES = *.html tinc.info tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi - -# Use `ginstall' in the definition of man_MANS to avoid -# confusion with the `install' target. The install rule transforms `ginstall' -# to install before applying any user-specified name transformations. -transform = s/ginstall/install/; @program_transform_name@ - -# 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 +CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi texi2html: tinc.texi - texi2html -split=chapter tinc.texi + $(AM_V_GEN)texi2html -split=chapter $< tincd.8.html: tincd.8 - w3mman2html $? > $@ - -tinc.8.html: tinc.8 - w3mman2html $? > $@ - -tinc-gui.8.html: tinc-gui.8 - w3mman2html $? > $@ + $(AM_V_GEN)w3mman2html $< > $@ tinc.conf.5.html: tinc.conf.5 - w3mman2html $? > $@ + $(AM_V_GEN)w3mman2html $< > $@ substitute = sed \ -e s,'@PACKAGE\@',"$(PACKAGE)",g \ -e s,'@VERSION\@',"$(VERSION)",g \ -e s,'@sysconfdir\@',"$(sysconfdir)",g \ + -e s,'@runstatedir\@',"$(runstatedir)",g \ -e s,'@localstatedir\@',"$(localstatedir)",g -tincd.8: tincd.8.in - $(substitute) $? > $@ +tincd.8: $(srcdir)/tincd.8.in + $(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@ -tinc.8: tinc.8.in - $(substitute) $? > $@ +tinc.conf.5: $(srcdir)/tinc.conf.5.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@ -tinc-gui.8: tinc-gui.8.in - $(substitute) $? > $@ - -tinc.conf.5: tinc.conf.5.in - $(substitute) $? > $@ - -tincinclude.texi: tincinclude.texi.in - $(substitute) $? > $@ - -tinc.texi: tincinclude.texi +tincinclude.texi: $(srcdir)/tincinclude.texi.in + $(AM_V_GEN)$(substitute) $(srcdir)/tincinclude.texi.in > $@ diff --git a/doc/Makefile.in b/doc/Makefile.in index 823c951..81e9c93 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -68,6 +78,7 @@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : @@ -77,14 +88,18 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = doc -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am texinfo.tex ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ - $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ - $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ - $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ax_append_flag.m4 \ + $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ + $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -131,7 +146,7 @@ AM_V_texidevnull = $(am__v_texidevnull_@AM_V@) am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@) am__v_texidevnull_0 = > /dev/null am__v_texidevnull_1 = -INFO_DEPS = tinc.info +INFO_DEPS = $(srcdir)/tinc.info am__TEXINFO_TEX_DIR = $(srcdir) DVIS = tinc.dvi PDFS = tinc.pdf @@ -182,12 +197,8 @@ man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in $(tinc_TEXINFOS) texinfo.tex DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) - -# Use `ginstall' in the definition of man_MANS to avoid -# confusion with the `install' target. The install rule transforms `ginstall' -# to install before applying any user-specified name transformations. -transform = s/ginstall/install/; @program_transform_name@ ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ @@ -200,7 +211,6 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CURSES_LIBS = @CURSES_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ @@ -216,12 +226,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ -LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ @@ -234,8 +240,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ @@ -282,28 +286,32 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +systemd_path = @systemd_path@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ info_TEXINFOS = tinc.texi -man_MANS = tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 -EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.8.in tinc.conf.5.in tinc-gui.8.in sample-config.tar.gz -CLEANFILES = *.html tinc.info tincd.8 tinc.8 tinc.conf.5 tinc-gui.8 tincinclude.texi +tinc_TEXINFOS = tincinclude.texi +man_MANS = tincd.8 tinc.conf.5 +EXTRA_DIST = tincinclude.texi.in tincd.8.in tinc.conf.5.in sample-config +CLEANFILES = *.html tincd.8 tinc.conf.5 tincinclude.texi substitute = sed \ -e s,'@PACKAGE\@',"$(PACKAGE)",g \ -e s,'@VERSION\@',"$(VERSION)",g \ -e s,'@sysconfdir\@',"$(sysconfdir)",g \ + -e s,'@runstatedir\@',"$(runstatedir)",g \ -e s,'@localstatedir\@',"$(localstatedir)",g all: all-am .SUFFIXES: -.SUFFIXES: .dvi .ps +.SUFFIXES: .dvi .html .info .pdf .ps .texi $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -316,14 +324,13 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -335,49 +342,53 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): -tinc.info: tinc.texi +.texi.info: $(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \ + am__cwd=`pwd` && $(am__cd) $(srcdir) && \ rm -rf $$backupdir && mkdir $$backupdir && \ if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ done; \ else :; fi && \ + cd "$$am__cwd"; \ if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ - -o $@ `test -f 'tinc.texi' || echo '$(srcdir)/'`tinc.texi; \ + -o $@ $<; \ then \ rc=0; \ + $(am__cd) $(srcdir); \ else \ rc=$$?; \ + $(am__cd) $(srcdir) && \ $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ fi; \ rm -rf $$backupdir; exit $$rc -tinc.dvi: tinc.texi +.texi.dvi: $(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \ - `test -f 'tinc.texi' || echo '$(srcdir)/'`tinc.texi + $< -tinc.pdf: tinc.texi +.texi.pdf: $(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \ - `test -f 'tinc.texi' || echo '$(srcdir)/'`tinc.texi + $< -tinc.html: tinc.texi +.texi.html: $(AM_V_MAKEINFO)rm -rf $(@:.html=.htp) $(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ - -o $(@:.html=.htp) `test -f 'tinc.texi' || echo '$(srcdir)/'`tinc.texi; \ + -o $(@:.html=.htp) $<; \ then \ - rm -rf $@; \ - if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ - mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ + rm -rf $@ && mv $(@:.html=.htp) $@; \ else \ - if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ - rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ - exit 1; \ + rm -rf $(@:.html=.htp); exit 1; \ fi +$(srcdir)/tinc.info: tinc.texi $(tinc_TEXINFOS) +tinc.dvi: tinc.texi $(tinc_TEXINFOS) +tinc.pdf: tinc.texi $(tinc_TEXINFOS) +tinc.html: tinc.texi $(tinc_TEXINFOS) .dvi.ps: $(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ $(DVIPS) $(AM_V_texinfo) -o $@ $< @@ -564,7 +575,10 @@ ctags CTAGS: cscope cscopelist: -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -813,44 +827,26 @@ uninstall-man: uninstall-man5 uninstall-man8 uninstall-html-am uninstall-info-am uninstall-man \ uninstall-man5 uninstall-man8 uninstall-pdf-am uninstall-ps-am +.PRECIOUS: Makefile -# 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 texi2html: tinc.texi - texi2html -split=chapter tinc.texi + $(AM_V_GEN)texi2html -split=chapter $< tincd.8.html: tincd.8 - w3mman2html $? > $@ - -tinc.8.html: tinc.8 - w3mman2html $? > $@ - -tinc-gui.8.html: tinc-gui.8 - w3mman2html $? > $@ + $(AM_V_GEN)w3mman2html $< > $@ tinc.conf.5.html: tinc.conf.5 - w3mman2html $? > $@ + $(AM_V_GEN)w3mman2html $< > $@ -tincd.8: tincd.8.in - $(substitute) $? > $@ +tincd.8: $(srcdir)/tincd.8.in + $(AM_V_GEN)$(substitute) $(srcdir)/tincd.8.in > $@ -tinc.8: tinc.8.in - $(substitute) $? > $@ +tinc.conf.5: $(srcdir)/tinc.conf.5.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc.conf.5.in > $@ -tinc-gui.8: tinc-gui.8.in - $(substitute) $? > $@ - -tinc.conf.5: tinc.conf.5.in - $(substitute) $? > $@ - -tincinclude.texi: tincinclude.texi.in - $(substitute) $? > $@ - -tinc.texi: tincinclude.texi +tincinclude.texi: $(srcdir)/tincinclude.texi.in + $(AM_V_GEN)$(substitute) $(srcdir)/tincinclude.texi.in > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/doc/sample-config.tar.gz b/doc/sample-config.tar.gz deleted file mode 100644 index 1a766a6..0000000 Binary files a/doc/sample-config.tar.gz and /dev/null differ diff --git a/doc/sample-config/hosts/alpha b/doc/sample-config/hosts/alpha new file mode 100644 index 0000000..0f5e56a --- /dev/null +++ b/doc/sample-config/hosts/alpha @@ -0,0 +1,15 @@ +# Sample host configuration file + +# The real IP address of this tinc host. Can be used by other tinc hosts. +Address = 123.234.35.67 + +# Portnumber for incoming connections. Default is 655. +Port = 655 + +# Subnet on the virtual private network that is local for this host. +Subnet = 192.168.1.0/24 + +# The public key generated by `tincd -n example -K' is stored here +-----BEGIN RSA PUBLIC KEY----- +... +-----END RSA PUBLIC KEY----- diff --git a/doc/sample-config/hosts/beta b/doc/sample-config/hosts/beta new file mode 100644 index 0000000..6f70d4f --- /dev/null +++ b/doc/sample-config/hosts/beta @@ -0,0 +1,16 @@ +# Sample host configuration file +# This file was generated by host beta. + +# The real IP address of this tinc host. Can be used by other tinc hosts. +Address = 123.45.67.189 + +# Portnumber for incoming connections. Default is 655. +Port = 6500 + +# Subnet on the virtual private network that is local for this host. +Subnet = 192.168.2.0/24 + +# The public key generated by `tincd -n example -K' is stored here +-----BEGIN RSA PUBLIC KEY----- +... +-----END RSA PUBLIC KEY----- diff --git a/doc/sample-config/rsa_key.priv b/doc/sample-config/rsa_key.priv new file mode 100644 index 0000000..ac13536 --- /dev/null +++ b/doc/sample-config/rsa_key.priv @@ -0,0 +1 @@ +# Generate this file with `tincd -n example -K` diff --git a/doc/sample-config/tinc-down b/doc/sample-config/tinc-down new file mode 100644 index 0000000..65b049e --- /dev/null +++ b/doc/sample-config/tinc-down @@ -0,0 +1,4 @@ +#!/bin/sh +# This file closes down the tap device. + +ifconfig $INTERFACE down diff --git a/doc/sample-config/tinc-up b/doc/sample-config/tinc-up new file mode 100644 index 0000000..2d8b4d6 --- /dev/null +++ b/doc/sample-config/tinc-up @@ -0,0 +1,11 @@ +#!/bin/sh +# This file sets up the tap device. +# It gives you the freedom to do anything you want with it. +# Use the correct name for the tap device: +# The environment variable $INTERFACE is set to the right name +# on most platforms, but if it doesn't work try to set it manually. + +# Give it the right ip and netmask. Remember, the subnet of the +# tap device must be larger than that of the individual Subnets +# as defined in the host configuration file! +ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 diff --git a/doc/sample-config/tinc.conf b/doc/sample-config/tinc.conf new file mode 100644 index 0000000..7081764 --- /dev/null +++ b/doc/sample-config/tinc.conf @@ -0,0 +1,22 @@ +# Sample tinc configuration file + +# This is a comment. +# Spaces and tabs are eliminated. +# The = sign isn't strictly necessary any longer, though you may want +# to leave it in as it improves readability :) +# Variable names are treated case insensitive. + +# The name of this tinc host. Required. +Name = alpha + +# The internet host to connect with. +# Comment these out to make yourself a listen-only connection +# You must use the name of another tinc host. +# May be used multiple times for redundance. +ConnectTo = beta + +# The tap device tinc will use. +# /dev/tap0 for ethertap, FreeBSD or OpenBSD +# /dev/tun0 for Solaris +# /dev/net/tun for Linux tun/tap +Device = /dev/net/tun diff --git a/doc/texinfo.tex b/doc/texinfo.tex index 85f184c..deca599 100644 --- a/doc/texinfo.tex +++ b/doc/texinfo.tex @@ -1,13 +1,11 @@ % texinfo.tex -- TeX macros to handle Texinfo files. -% +% % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2013-02-01.11} +\def\texinfoversion{2020-02-11.09} % -% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, -% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -% 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. +% Copyright 1985, 1986, 1988, 1990-2019 Free Software Foundation, Inc. % % This texinfo.tex file is free software: you can redistribute it and/or % modify it under the terms of the GNU General Public License as @@ -20,7 +18,7 @@ % 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 . +% along with this program. If not, see . % % As a special exception, when this file is read by TeX when processing % a Texinfo source document, you may use the result without @@ -29,9 +27,9 @@ % % Please try the latest version of texinfo.tex before submitting bug % reports; you can get the latest version from: -% http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or -% http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or -% http://www.gnu.org/software/texinfo/ (the Texinfo home page) +% https://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or +% https://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or +% https://www.gnu.org/software/texinfo/ (the Texinfo home page) % The texinfo.tex in any given distribution could well be out % of date, so if that's what you're using, please check. % @@ -55,7 +53,7 @@ % extent. You can get the existing language-specific files from the % full Texinfo distribution. % -% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. +% The GNU Texinfo home page is https://www.gnu.org/software/texinfo. \message{Loading texinfo [version \texinfoversion]:} @@ -66,6 +64,10 @@ \everyjob{\message{[Texinfo version \texinfoversion]}% \catcode`+=\active \catcode`\_=\active} +% LaTeX's \typeout. This ensures that the messages it is used for +% are identical in format to the corresponding ones from latex/pdflatex. +\def\typeout{\immediate\write17}% + \chardef\other=12 % We never want plain's \outer definition of \+ in Texinfo. @@ -96,7 +98,9 @@ \let\ptexraggedright=\raggedright \let\ptexrbrace=\} \let\ptexslash=\/ +\let\ptexsp=\sp \let\ptexstar=\* +\let\ptexsup=\sup \let\ptext=\t \let\ptextop=\top {\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode @@ -155,22 +159,13 @@ \ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi \ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi -% Since the category of space is not known, we have to be careful. -\chardef\spacecat = 10 -\def\spaceisspace{\catcode`\ =\spacecat} +% Give the space character the catcode for a space. +\def\spaceisspace{\catcode`\ =10\relax} + +% Likewise for ^^M, the end of line character. +\def\endlineisspace{\catcode13=10\relax} -% sometimes characters are active, so we need control sequences. -\chardef\ampChar = `\& -\chardef\colonChar = `\: -\chardef\commaChar = `\, \chardef\dashChar = `\- -\chardef\dotChar = `\. -\chardef\exclamChar= `\! -\chardef\hashChar = `\# -\chardef\lquoteChar= `\` -\chardef\questChar = `\? -\chardef\rquoteChar= `\' -\chardef\semiChar = `\; \chardef\slashChar = `\/ \chardef\underChar = `\_ @@ -193,17 +188,6 @@ wide-spread wrap-around } -% Margin to add to right of even pages, to left of odd pages. -\newdimen\bindingoffset -\newdimen\normaloffset -\newdimen\pagewidth \newdimen\pageheight - -% For a final copy, take out the rectangles -% that mark overfull boxes (in case you have decided -% that the text looks ok even though it passes the margin). -% -\def\finalout{\overfullrule=0pt } - % Sometimes it is convenient to have everything in the transcript file % and nothing on the terminal. We don't just call \tracingall here, % since that produces some useless output on the terminal. We also make @@ -234,7 +218,7 @@ % @errormsg{MSG}. Do the index-like expansions on MSG, but if things % aren't perfect, it's not the end of the world, being an error message, % after all. -% +% \def\errormsg{\begingroup \indexnofonts \doerrormsg} \def\doerrormsg#1{\errmessage{#1}} @@ -248,17 +232,16 @@ \def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount \removelastskip\penalty-200\bigskip\fi\fi} -% Do @cropmarks to get crop marks. +% Output routine % -\newif\ifcropmarks -\let\cropmarks = \cropmarkstrue -% -% Dimensions to add cropmarks at corners. -% Added by P. A. MacKay, 12 Nov. 1986 + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). % +\def\finalout{\overfullrule=0pt } + \newdimen\outerhsize \newdimen\outervsize % set by the paper size routines -\newdimen\cornerlong \cornerlong=1pc -\newdimen\cornerthick \cornerthick=.3pt \newdimen\topandbottommargin \topandbottommargin=.75in % Output a mark which sets \thischapter, \thissection and \thiscolor. @@ -270,99 +253,145 @@ % % Another complication is to let the user choose whether \thischapter % (\thissection) refers to the chapter (section) in effect at the top -% of a page, or that at the bottom of a page. The solution is -% described on page 260 of The TeXbook. It involves outputting two -% marks for the sectioning macros, one before the section break, and -% one after. I won't pretend I can describe this better than DEK... +% of a page, or that at the bottom of a page. + +% \domark is called twice inside \chapmacro, to add one +% mark before the section break, and one after. +% In the second call \prevchapterdefs is the same as \currentchapterdefs, +% and \prevsectiondefs is the same as \currentsectiondefs. +% Then if the page is not broken at the mark, some of the previous +% section appears on the page, and we can get the name of this section +% from \firstmark for @everyheadingmarks top. +% @everyheadingmarks bottom uses \botmark. +% +% See page 260 of The TeXbook. \def\domark{% - \toks0=\expandafter{\lastchapterdefs}% - \toks2=\expandafter{\lastsectiondefs}% + \toks0=\expandafter{\currentchapterdefs}% + \toks2=\expandafter{\currentsectiondefs}% \toks4=\expandafter{\prevchapterdefs}% \toks6=\expandafter{\prevsectiondefs}% - \toks8=\expandafter{\lastcolordefs}% + \toks8=\expandafter{\currentcolordefs}% \mark{% - \the\toks0 \the\toks2 - \noexpand\or \the\toks4 \the\toks6 - \noexpand\else \the\toks8 + \the\toks0 \the\toks2 % 0: marks for @everyheadingmarks top + \noexpand\or \the\toks4 \the\toks6 % 1: for @everyheadingmarks bottom + \noexpand\else \the\toks8 % 2: color marks }% } + +% \gettopheadingmarks, \getbottomheadingmarks, +% \getcolormarks - extract needed part of mark. +% % \topmark doesn't work for the very first chapter (after the title % page or the contents), so we use \firstmark there -- this gets us % the mark with the chapter defs, unless the user sneaks in, e.g., % @setcolor (or @url, or @link, etc.) between @contents and the very % first @chapter. \def\gettopheadingmarks{% - \ifcase0\topmark\fi + \ifcase0\the\savedtopmark\fi \ifx\thischapter\empty \ifcase0\firstmark\fi \fi } \def\getbottomheadingmarks{\ifcase1\botmark\fi} -\def\getcolormarks{\ifcase2\topmark\fi} +\def\getcolormarks{\ifcase2\the\savedtopmark\fi} % Avoid "undefined control sequence" errors. -\def\lastchapterdefs{} -\def\lastsectiondefs{} +\def\currentchapterdefs{} +\def\currentsectiondefs{} +\def\currentsection{} \def\prevchapterdefs{} \def\prevsectiondefs{} -\def\lastcolordefs{} +\def\currentcolordefs{} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\txipagewidth \newdimen\txipageheight % Main output routine. +% \chardef\PAGE = 255 -\output = {\onepageout{\pagecontents\PAGE}} +\newtoks\defaultoutput +\defaultoutput = {\savetopmark\onepageout{\pagecontents\PAGE}} +\output=\expandafter{\the\defaultoutput} \newbox\headlinebox \newbox\footlinebox -% \onepageout takes a vbox as an argument. Note that \pagecontents -% does insertions, but you have to call it yourself. +% When outputting the double column layout for indices, an output routine +% is run several times, which hides the original value of \topmark. This +% can lead to a page heading being output and duplicating the chapter heading +% of the index. Hence, save the contents of \topmark at the beginning of +% the output routine. The saved contents are valid until we actually +% \shipout a page. +% +% (We used to run a short output routine to actually set \topmark and +% \firstmark to the right values, but if this was called with an empty page +% containing whatsits for writing index entries, the whatsits would be thrown +% away and the index auxiliary file would remain empty.) +% +\newtoks\savedtopmark +\newif\iftopmarksaved +\topmarksavedtrue +\def\savetopmark{% + \iftopmarksaved\else + \global\savedtopmark=\expandafter{\topmark}% + \global\topmarksavedtrue + \fi +} + +% \onepageout takes a vbox as an argument. +% \shipout a vbox for a single page, adding an optional header, footer +% and footnote. This also causes index entries for this page to be written +% to the auxiliary files. +% \def\onepageout#1{% - \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + \hoffset=\normaloffset % \ifodd\pageno \advance\hoffset by \bindingoffset \else \advance\hoffset by -\bindingoffset\fi % + % Retrieve the information for the headings from the marks in the page, + % and call Plain TeX's \makeheadline and \makefootline, which use the + % values in \headline and \footline. + % + % This is used to check if we are on the first page of a chapter. + \ifcase1\the\savedtopmark\fi + \let\prevchaptername\thischaptername + \ifcase0\firstmark\fi + \let\curchaptername\thischaptername + % + \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi + % + \ifx\curchaptername\prevchaptername + \let\thischapterheading\thischapter + \else + % \thischapterheading is the same as \thischapter except it is blank + % for the first page of a chapter. This is to prevent the chapter name + % being shown twice. + \def\thischapterheading{}% + \fi + % + % Common context changes for both heading and footing. % Do this outside of the \shipout so @code etc. will be expanded in % the headline as they should be, not taken literally (outputting ''code). - \ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi - \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \def\commonheadfootline{\let\hsize=\txipagewidth \texinfochars} + % + \global\setbox\headlinebox = \vbox{\commonheadfootline \makeheadline}% + % \ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi - \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + \global\setbox\footlinebox = \vbox{\commonheadfootline \makefootline}% % {% + % Set context for writing to auxiliary files like index files. % Have to do this stuff outside the \shipout because we want it to % take effect in \write's, yet the group defined by the \vbox ends % before the \shipout runs. % - \indexdummies % don't expand commands in the output. - \normalturnoffactive % \ in index entries must not stay \, e.g., if - % the page break happens to be in the middle of an example. - % We don't want .vr (or whatever) entries like this: - % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} - % "\acronym" won't work when it's read back in; - % it needs to be - % {\code {{\tt \backslashcurfont }acronym} + \atdummies % don't expand commands in the output. + \turnoffactive \shipout\vbox{% % Do this early so pdf references go to the beginning of the page. \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi % - \ifcropmarks \vbox to \outervsize\bgroup - \hsize = \outerhsize - \vskip-\topandbottommargin - \vtop to0pt{% - \line{\ewtop\hfil\ewtop}% - \nointerlineskip - \line{% - \vbox{\moveleft\cornerthick\nstop}% - \hfill - \vbox{\moveright\cornerthick\nstop}% - }% - \vss}% - \vskip\topandbottommargin - \line\bgroup - \hfil % center the page within the outer (page) hsize. - \ifodd\pageno\hskip\bindingoffset\fi - \vbox\bgroup - \fi - % \unvbox\headlinebox \pagebody{#1}% \ifdim\ht\footlinebox > 0pt @@ -373,31 +402,17 @@ \unvbox\footlinebox \fi % - \ifcropmarks - \egroup % end of \vbox\bgroup - \hfil\egroup % end of (centering) \line\bgroup - \vskip\topandbottommargin plus1fill minus1fill - \boxmaxdepth = \cornerthick - \vbox to0pt{\vss - \line{% - \vbox{\moveleft\cornerthick\nsbot}% - \hfill - \vbox{\moveright\cornerthick\nsbot}% - }% - \nointerlineskip - \line{\ewbot\hfil\ewbot}% - }% - \egroup % \vbox from first cropmarks clause - \fi - }% end of \shipout\vbox - }% end of group with \indexdummies + }% + }% + \global\topmarksavedfalse \advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi } \newinsert\margin \dimen\margin=\maxdimen -\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +% Main part of page, including any footnotes +\def\pagebody#1{\vbox to\txipageheight{\boxmaxdepth=\maxdepth #1}} {\catcode`\@ =11 \gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi % marginal hacks, juha@viisa.uucp (Juha Takala) @@ -408,20 +423,13 @@ \ifr@ggedbottom \kern-\dimen@ \vfil \fi} } -% Here are the rules for the cropmarks. Note that they are -% offset so that the space between them is truly \outerhsize or \outervsize -% (P. A. MacKay, 12 November, 1986) -% -\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} -\def\nstop{\vbox - {\hrule height\cornerthick depth\cornerlong width\cornerthick}} -\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} -\def\nsbot{\vbox - {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Argument parsing % Parse an argument, then pass it to #1. The argument is the rest of % the input line (except we remove a trailing comment). #1 should be a % macro which expects an ordinary undelimited TeX argument. +% For example, \def\foo{\parsearg\fooxxx}. % \def\parsearg{\parseargusing{}} \def\parseargusing#1#2{% @@ -440,7 +448,8 @@ }% } -% First remove any @comment, then any @c comment. +% First remove any @comment, then any @c comment. Pass the result on to +% \argcheckspaces. \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} @@ -477,14 +486,13 @@ % \def\finishparsearg#1 \ArgTerm{\expandafter\argtorun\expandafter{#1}} + +% \parseargdef - define a command taking an argument on the line +% % \parseargdef\foo{...} % is roughly equivalent to % \def\foo{\parsearg\Xfoo} % \def\Xfoo#1{...} -% -% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my -% favourite TeX trick. --kasal, 16nov03 - \def\parseargdef#1{% \expandafter \doparseargdef \csname\string#1\endcsname #1% } @@ -674,21 +682,26 @@ \endgraf % Not \par, as it may have been set to \lisppar. \global\dimen1 = \prevdepth \egroup % End the \vtop. + \addgroupbox + \prevdepth = \dimen1 + \checkinserts +} + +\def\addgroupbox{ % \dimen0 is the vertical size of the group's box. \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox % \dimen2 is how much space is left on the page (more or less). - \dimen2 = \pageheight \advance\dimen2 by -\pagetotal + \dimen2 = \txipageheight \advance\dimen2 by -\pagetotal % if the group doesn't fit on the current page, and it's a big big % group, force a page break. \ifdim \dimen0 > \dimen2 - \ifdim \pagetotal < \vfilllimit\pageheight + \ifdim \pagetotal < \vfilllimit\txipageheight \page \fi \fi \box\groupbox - \prevdepth = \dimen1 - \checkinserts } + % % TeX puts in an \escapechar (i.e., `@') at the beginning of the help % message, so this ends up printing `@group can only ...'. @@ -812,36 +825,6 @@ where each line of input produces a line of output.} \temp } -% @| inserts a changebar to the left of the current line. It should -% surround any changed text. This approach does *not* work if the -% change spans more than two lines of output. To handle that, we would -% have adopt a much more difficult approach (putting marks into the main -% vertical list for the beginning and end of each change). This command -% is not documented, not supported, and doesn't work. -% -\def\|{% - % \vadjust can only be used in horizontal mode. - \leavevmode - % - % Append this vertical mode material after the current line in the output. - \vadjust{% - % We want to insert a rule with the height and depth of the current - % leading; that is exactly what \strutbox is supposed to record. - \vskip-\baselineskip - % - % \vadjust-items are inserted at the left edge of the type. So - % the \llap here moves out into the left-hand margin. - \llap{% - % - % For a thicker or thinner bar, change the `1pt'. - \vrule height\baselineskip width1pt - % - % This is the space between the bar and the text. - \hskip 12pt - }% - }% -} - % @include FILE -- \input text of FILE. % \def\include{\parseargusing\filenamecatcodes\includezzz} @@ -930,13 +913,14 @@ where each line of input produces a line of output.} % @comment ...line which is ignored... % @c is the same as @comment % @ignore ... @end ignore is another way to write a comment -% -\def\comment{\begingroup \catcode`\^^M=\other% + + +\def\c{\begingroup \catcode`\^^M=\active% \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% -\commentxxx} -{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} +\cxxx} +{\catcode`\^^M=\active \gdef\cxxx#1^^M{\endgroup}} % -\let\c=\comment +\let\comment\c % @paragraphindent NCHARS % We'll use ems for NCHARS, close enough. @@ -1007,69 +991,23 @@ where each line of input produces a line of output.} % paragraph. % \gdef\dosuppressfirstparagraphindent{% - \gdef\indent{% - \restorefirstparagraphindent - \indent - }% - \gdef\noindent{% - \restorefirstparagraphindent - \noindent - }% - \global\everypar = {% - \kern -\parindent - \restorefirstparagraphindent - }% + \gdef\indent {\restorefirstparagraphindent \indent}% + \gdef\noindent{\restorefirstparagraphindent \noindent}% + \global\everypar = {\kern -\parindent \restorefirstparagraphindent}% } - +% \gdef\restorefirstparagraphindent{% - \global \let \indent = \ptexindent - \global \let \noindent = \ptexnoindent - \global \everypar = {}% + \global\let\indent = \ptexindent + \global\let\noindent = \ptexnoindent + \global\everypar = {}% } % @refill is a no-op. \let\refill=\relax -% If working on a large document in chapters, it is convenient to -% be able to disable indexing, cross-referencing, and contents, for test runs. -% This is done with @novalidate (before @setfilename). -% -\newif\iflinks \linkstrue % by default we want the aux files. -\let\novalidate = \linksfalse - -% @setfilename is done at the beginning of every texinfo file. -% So open here the files we need to have open while reading the input. -% This makes it possible to make a .fmt file for texinfo. -\def\setfilename{% - \fixbackslash % Turn off hack to swallow `\input texinfo'. - \iflinks - \tryauxfile - % Open the new aux file. TeX will close it automatically at exit. - \immediate\openout\auxfile=\jobname.aux - \fi % \openindices needs to do some work in any case. - \openindices - \let\setfilename=\comment % Ignore extra @setfilename cmds. - % - % If texinfo.cnf is present on the system, read it. - % Useful for site-wide @afourpaper, etc. - \openin 1 texinfo.cnf - \ifeof 1 \else \input texinfo.cnf \fi - \closein 1 - % - \comment % Ignore the actual filename. -} - -% Called from \setfilename. -% -\def\openindices{% - \newindex{cp}% - \newcodeindex{fn}% - \newcodeindex{vr}% - \newcodeindex{tp}% - \newcodeindex{ky}% - \newcodeindex{pg}% -} +% @setfilename INFO-FILENAME - ignored +\let\setfilename=\comment % @bye. \outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} @@ -1087,10 +1025,95 @@ where each line of input produces a line of output.} \newtoks\toksC \newtoks\toksD \newbox\boxA +\newbox\boxB \newcount\countA \newif\ifpdf \newif\ifpdfmakepagedest +% +% For LuaTeX +% + +\newif\iftxiuseunicodedestname +\txiuseunicodedestnamefalse % For pdfTeX etc. + +\ifx\luatexversion\thisisundefined +\else + % Use Unicode destination names + \txiuseunicodedestnametrue + % Escape PDF strings with converting UTF-16 from UTF-8 + \begingroup + \catcode`\%=12 + \directlua{ + function UTF16oct(str) + tex.sprint(string.char(0x5c) .. '376' .. string.char(0x5c) .. '377') + for c in string.utfvalues(str) do + if c < 0x10000 then + tex.sprint( + string.format(string.char(0x5c) .. string.char(0x25) .. '03o' .. + string.char(0x5c) .. string.char(0x25) .. '03o', + math.floor(c / 256), math.floor(c % 256))) + else + c = c - 0x10000 + local c_hi = c / 1024 + 0xd800 + local c_lo = c % 1024 + 0xdc00 + tex.sprint( + string.format(string.char(0x5c) .. string.char(0x25) .. '03o' .. + string.char(0x5c) .. string.char(0x25) .. '03o' .. + string.char(0x5c) .. string.char(0x25) .. '03o' .. + string.char(0x5c) .. string.char(0x25) .. '03o', + math.floor(c_hi / 256), math.floor(c_hi % 256), + math.floor(c_lo / 256), math.floor(c_lo % 256))) + end + end + end + } + \endgroup + \def\pdfescapestrutfsixteen#1{\directlua{UTF16oct('\luaescapestring{#1}')}} + % Escape PDF strings without converting + \begingroup + \directlua{ + function PDFescstr(str) + for c in string.bytes(str) do + if c <= 0x20 or c >= 0x80 or c == 0x28 or c == 0x29 or c == 0x5c then + tex.sprint(-2, + string.format(string.char(0x5c) .. string.char(0x25) .. '03o', + c)) + else + tex.sprint(-2, string.char(c)) + end + end + end + } + % The -2 in the arguments here gives all the input to TeX catcode 12 + % (other) or 10 (space), preventing undefined control sequence errors. See + % https://lists.gnu.org/archive/html/bug-texinfo/2019-08/msg00031.html + % + \endgroup + \def\pdfescapestring#1{\directlua{PDFescstr('\luaescapestring{#1}')}} + \ifnum\luatexversion>84 + % For LuaTeX >= 0.85 + \def\pdfdest{\pdfextension dest} + \let\pdfoutput\outputmode + \def\pdfliteral{\pdfextension literal} + \def\pdfcatalog{\pdfextension catalog} + \def\pdftexversion{\numexpr\pdffeedback version\relax} + \let\pdfximage\saveimageresource + \let\pdfrefximage\useimageresource + \let\pdflastximage\lastsavedimageresourceindex + \def\pdfendlink{\pdfextension endlink\relax} + \def\pdfoutline{\pdfextension outline} + \def\pdfstartlink{\pdfextension startlink} + \def\pdffontattr{\pdfextension fontattr} + \def\pdfobj{\pdfextension obj} + \def\pdflastobj{\numexpr\pdffeedback lastobj\relax} + \let\pdfpagewidth\pagewidth + \let\pdfpageheight\pageheight + \edef\pdfhorigin{\pdfvariable horigin} + \edef\pdfvorigin{\pdfvariable vorigin} + \fi +\fi + % when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 % can be set). So we test for \relax and 0 as well as being undefined. \ifx\pdfoutput\thisisundefined @@ -1104,11 +1127,21 @@ where each line of input produces a line of output.} \fi \fi +\newif\ifpdforxetex +\pdforxetexfalse +\ifpdf + \pdforxetextrue +\fi +\ifx\XeTeXrevision\thisisundefined\else + \pdforxetextrue +\fi + + % PDF uses PostScript string constants for the names of xref targets, % for display in the outlines, and in other places. Thus, we have to % double any backslashes. Otherwise, a name like "\node" will be % interpreted as a newline (\n), followed by o, d, e. Not good. -% +% % See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and % related messages. The final outcome is that it is up to the TeX user % to double the backslashes and otherwise make the string valid, so @@ -1121,12 +1154,21 @@ where each line of input produces a line of output.} \ifx\pdfescapestring\thisisundefined % No primitive available; should we give a warning or log? % Many times it won't matter. + \xdef#1{#1}% \else % The expandable \pdfescapestring primitive escapes parentheses, % backslashes, and other special chars. \xdef#1{\pdfescapestring{#1}}% \fi } +\def\txiescapepdfutfsixteen#1{% + \ifx\pdfescapestrutfsixteen\thisisundefined + % No UTF-16 converting macro available. + \txiescapepdf{#1}% + \else + \xdef#1{\pdfescapestrutfsixteen{#1}}% + \fi +} \newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images with PDF output, and none of those formats could be found. (.eps cannot @@ -1135,21 +1177,23 @@ output) for that.)} \ifpdf % - % Color manipulation macros based on pdfcolor.tex, + % Color manipulation macros using ideas from pdfcolor.tex, % except using rgb instead of cmyk; the latter is said to render as a % very dark gray on-screen and a very dark halftone in print, instead - % of actual black. + % of actual black. The dark red here is dark enough to print on paper as + % nearly black, but still distinguishable for online viewing. We use + % black by default, though. \def\rgbDarkRed{0.50 0.09 0.12} \def\rgbBlack{0 0 0} % - % k sets the color for filling (usual text, etc.); - % K sets the color for stroking (thin rules, e.g., normal _'s). + % rg sets the color for filling (usual text, etc.); + % RG sets the color for stroking (thin rules, e.g., normal _'s). \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} % % Set color, and create a mark which defines \thiscolor accordingly, % so that \makeheadline knows which color to restore. \def\setcolor#1{% - \xdef\lastcolordefs{\gdef\noexpand\thiscolor{#1}}% + \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% \domark \pdfsetcolor{#1}% } @@ -1157,7 +1201,7 @@ output) for that.)} \def\maincolor{\rgbBlack} \pdfsetcolor{\maincolor} \edef\thiscolor{\maincolor} - \def\lastcolordefs{} + \def\currentcolordefs{} % \def\makefootline{% \baselineskip24pt @@ -1234,24 +1278,83 @@ output) for that.)} \pdfrefximage \pdflastximage \fi} % - \def\pdfmkdest#1{{% + \def\setpdfdestname#1{{% % We have to set dummies so commands such as @code, and characters % such as \, aren't expanded when present in a section title. \indexnofonts - \turnoffactive \makevalueexpandable + \turnoffactive + \iftxiuseunicodedestname + \ifx \declaredencoding \latone + % Pass through Latin-1 characters. + % LuaTeX with byte wise I/O converts Latin-1 characters to Unicode. + \else + \ifx \declaredencoding \utfeight + % Pass through Unicode characters. + \else + % Use ASCII approximations in destination names. + \passthroughcharsfalse + \fi + \fi + \else + % Use ASCII approximations in destination names. + \passthroughcharsfalse + \fi \def\pdfdestname{#1}% \txiescapepdf\pdfdestname - \safewhatsit{\pdfdest name{\pdfdestname} xyz}% }} % + \def\setpdfoutlinetext#1{{% + \indexnofonts + \makevalueexpandable + \turnoffactive + \ifx \declaredencoding \latone + % The PDF format can use an extended form of Latin-1 in bookmark + % strings. See Appendix D of the PDF Reference, Sixth Edition, for + % the "PDFDocEncoding". + \passthroughcharstrue + % Pass through Latin-1 characters. + % LuaTeX: Convert to Unicode + % pdfTeX: Use Latin-1 as PDFDocEncoding + \def\pdfoutlinetext{#1}% + \else + \ifx \declaredencoding \utfeight + \ifx\luatexversion\thisisundefined + % For pdfTeX with UTF-8. + % TODO: the PDF format can use UTF-16 in bookmark strings, + % but the code for this isn't done yet. + % Use ASCII approximations. + \passthroughcharsfalse + \def\pdfoutlinetext{#1}% + \else + % For LuaTeX with UTF-8. + % Pass through Unicode characters for title texts. + \passthroughcharstrue + \def\pdfoutlinetext{#1}% + \fi + \else + % For non-Latin-1 or non-UTF-8 encodings. + % Use ASCII approximations. + \passthroughcharsfalse + \def\pdfoutlinetext{#1}% + \fi + \fi + % LuaTeX: Convert to UTF-16 + % pdfTeX: Use Latin-1 as PDFDocEncoding + \txiescapepdfutfsixteen\pdfoutlinetext + }} + % + \def\pdfmkdest#1{% + \setpdfdestname{#1}% + \safewhatsit{\pdfdest name{\pdfdestname} xyz}% + } + % % used to mark target names; must be expandable. \def\pdfmkpgn#1{#1} % - % by default, use a color that is dark enough to print on paper as - % nearly black, but still distinguishable for online viewing. - \def\urlcolor{\rgbDarkRed} - \def\linkcolor{\rgbDarkRed} + % by default, use black for everything. + \def\urlcolor{\rgbBlack} + \def\linkcolor{\rgbBlack} \def\endlink{\setcolor{\maincolor}\pdfendlink} % % Adding outlines to PDF; macros for calculating structure of outlines @@ -1273,18 +1376,13 @@ output) for that.)} % page number. We could generate a destination for the section % text in the case where a section has no node, but it doesn't % seem worth the trouble, since most documents are normally structured. - \edef\pdfoutlinedest{#3}% - \ifx\pdfoutlinedest\empty - \def\pdfoutlinedest{#4}% - \else - \txiescapepdf\pdfoutlinedest + \setpdfoutlinetext{#1} + \setpdfdestname{#3} + \ifx\pdfdestname\empty + \def\pdfdestname{#4}% \fi % - % Also escape PDF chars in the display string. - \edef\pdfoutlinetext{#1}% - \txiescapepdf\pdfoutlinetext - % - \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% + \pdfoutline goto name{\pdfmkpgn{\pdfdestname}}#2{\pdfoutlinetext}% } % \def\pdfmakeoutlines{% @@ -1348,7 +1446,7 @@ output) for that.)} % their "best" equivalent, based on the @documentencoding. Too % much work for too little return. Just use the ASCII equivalents % we use for the index sort strings. - % + % \indexnofonts \setupdatafile % We can have normal brace characters in the PDF outlines, unlike @@ -1404,6 +1502,9 @@ output) for that.)} \startlink attr{/Border [0 0 0]}% user{/Subtype /Link /A << /S /URI /URI (#1) >>}% \endgroup} + % \pdfgettoks - Surround page numbers in #1 with @pdflink. #1 may + % be a simple number, or a list of numbers in the case of an index + % entry. \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} @@ -1439,42 +1540,298 @@ output) for that.)} \let\pdfmakeoutlines = \relax \fi % \ifx\pdfoutput +% +% For XeTeX +% +\ifx\XeTeXrevision\thisisundefined +\else + % + % XeTeX version check + % + \ifnum\strcmp{\the\XeTeXversion\XeTeXrevision}{0.99996}>-1 + % TeX Live 2016 contains XeTeX 0.99996 and xdvipdfmx 20160307. + % It can use the `dvipdfmx:config' special (from TeX Live SVN r40941). + % For avoiding PDF destination name replacement, we use this special + % instead of xdvipdfmx's command line option `-C 0x0010'. + \special{dvipdfmx:config C 0x0010} + % XeTeX 0.99995+ comes with xdvipdfmx 20160307+. + % It can handle Unicode destination names for PDF. + \txiuseunicodedestnametrue + \else + % XeTeX < 0.99996 (TeX Live < 2016) cannot use the + % `dvipdfmx:config' special. + % So for avoiding PDF destination name replacement, + % xdvipdfmx's command line option `-C 0x0010' is necessary. + % + % XeTeX < 0.99995 can not handle Unicode destination names for PDF + % because xdvipdfmx 20150315 has a UTF-16 conversion issue. + % It is fixed by xdvipdfmx 20160106 (TeX Live SVN r39753). + \txiuseunicodedestnamefalse + \fi + % + % Color support + % + \def\rgbDarkRed{0.50 0.09 0.12} + \def\rgbBlack{0 0 0} + % + \def\pdfsetcolor#1{\special{pdf:scolor [#1]}} + % + % Set color, and create a mark which defines \thiscolor accordingly, + % so that \makeheadline knows which color to restore. + \def\setcolor#1{% + \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% + \domark + \pdfsetcolor{#1}% + } + % + \def\maincolor{\rgbBlack} + \pdfsetcolor{\maincolor} + \edef\thiscolor{\maincolor} + \def\currentcolordefs{} + % + \def\makefootline{% + \baselineskip24pt + \line{\pdfsetcolor{\maincolor}\the\footline}% + } + % + \def\makeheadline{% + \vbox to 0pt{% + \vskip-22.5pt + \line{% + \vbox to8.5pt{}% + % Extract \thiscolor definition from the marks. + \getcolormarks + % Typeset the headline with \maincolor, then restore the color. + \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% + }% + \vss + }% + \nointerlineskip + } + % + % PDF outline support + % + % Emulate pdfTeX primitive + \def\pdfdest name#1 xyz{% + \special{pdf:dest (#1) [@thispage /XYZ @xpos @ypos null]}% + } + % + \def\setpdfdestname#1{{% + % We have to set dummies so commands such as @code, and characters + % such as \, aren't expanded when present in a section title. + \indexnofonts + \makevalueexpandable + \turnoffactive + \iftxiuseunicodedestname + % Pass through Unicode characters. + \else + % Use ASCII approximations in destination names. + \passthroughcharsfalse + \fi + \def\pdfdestname{#1}% + \txiescapepdf\pdfdestname + }} + % + \def\setpdfoutlinetext#1{{% + \turnoffactive + % Always use Unicode characters in title texts. + \def\pdfoutlinetext{#1}% + % For XeTeX, xdvipdfmx converts to UTF-16. + % So we do not convert. + \txiescapepdf\pdfoutlinetext + }} + % + \def\pdfmkdest#1{% + \setpdfdestname{#1}% + \safewhatsit{\pdfdest name{\pdfdestname} xyz}% + } + % + % by default, use black for everything. + \def\urlcolor{\rgbBlack} + \def\linkcolor{\rgbBlack} + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % + \def\dopdfoutline#1#2#3#4{% + \setpdfoutlinetext{#1} + \setpdfdestname{#3} + \ifx\pdfdestname\empty + \def\pdfdestname{#4}% + \fi + % + \special{pdf:out [-] #2 << /Title (\pdfoutlinetext) /A + << /S /GoTo /D (\pdfdestname) >> >> }% + } + % + \def\pdfmakeoutlines{% + \begingroup + % + % For XeTeX, counts of subentries are not necessary. + % Therefore, we read toc only once. + % + % We use node names as destinations. + \def\partentry##1##2##3##4{}% ignore parts in the outlines + \def\numchapentry##1##2##3##4{% + \dopdfoutline{##1}{1}{##3}{##4}}% + \def\numsecentry##1##2##3##4{% + \dopdfoutline{##1}{2}{##3}{##4}}% + \def\numsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{3}{##3}{##4}}% + \def\numsubsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{4}{##3}{##4}}% + % + \let\appentry\numchapentry% + \let\appsecentry\numsecentry% + \let\appsubsecentry\numsubsecentry% + \let\appsubsubsecentry\numsubsubsecentry% + \let\unnchapentry\numchapentry% + \let\unnsecentry\numsecentry% + \let\unnsubsecentry\numsubsecentry% + \let\unnsubsubsecentry\numsubsubsecentry% + % + % For XeTeX, xdvipdfmx converts strings to UTF-16. + % Therefore, the encoding and the language may not be considered. + % + \indexnofonts + \setupdatafile + % We can have normal brace characters in the PDF outlines, unlike + % Texinfo index files. So set that up. + \def\{{\lbracecharliteral}% + \def\}{\rbracecharliteral}% + \catcode`\\=\active \otherbackslash + \input \tocreadfilename + \endgroup + } + {\catcode`[=1 \catcode`]=2 + \catcode`{=\other \catcode`}=\other + \gdef\lbracecharliteral[{]% + \gdef\rbracecharliteral[}]% + ] + \special{pdf:docview << /PageMode /UseOutlines >> } + % ``\special{pdf:tounicode ...}'' is not necessary + % because xdvipdfmx converts strings from UTF-8 to UTF-16 without it. + % However, due to a UTF-16 conversion issue of xdvipdfmx 20150315, + % ``\special{pdf:dest ...}'' cannot handle non-ASCII strings. + % It is fixed by xdvipdfmx 20160106 (TeX Live SVN r39753). +% + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \nextsp} + \def\getfilename#1{% + \filenamelength=0 + % If we don't expand the argument now, \skipspaces will get + % snagged on things like "@value{foo}". + \edef\temp{#1}% + \expandafter\skipspaces\temp|\relax + } + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + % do we want to go so far as to use \indexnofonts instead of just + % special-casing \var here? + \def\var##1{##1}% + % + \leavevmode\setcolor{\urlcolor}% + \special{pdf:bann << /Border [0 0 0] + /Subtype /Link /A << /S /URI /URI (#1) >> >>}% + \endgroup} + \def\endlink{\setcolor{\maincolor}\special{pdf:eann}} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \special{pdf:bann << /Border [0 0 0] + /Type /Annot /Subtype /Link /A << /S /GoTo /D (#1) >> >>}% + \setcolor{\linkcolor}#1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +% + % + % @image support + % + % #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto). + \def\doxeteximage#1#2#3{% + \def\xeteximagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}% + \def\xeteximageheight{#3}\setbox2 = \hbox{\ignorespaces #3}% + % + % XeTeX (and the PDF format) supports .pdf, .png, .jpg (among + % others). Let's try in that order, PDF first since if + % someone has a scalable image, presumably better to use that than a + % bitmap. + \let\xeteximgext=\empty + \begingroup + \openin 1 #1.pdf \ifeof 1 + \openin 1 #1.PDF \ifeof 1 + \openin 1 #1.png \ifeof 1 + \openin 1 #1.jpg \ifeof 1 + \openin 1 #1.jpeg \ifeof 1 + \openin 1 #1.JPG \ifeof 1 + \errmessage{Could not find image file #1 for XeTeX}% + \else \gdef\xeteximgext{JPG}% + \fi + \else \gdef\xeteximgext{jpeg}% + \fi + \else \gdef\xeteximgext{jpg}% + \fi + \else \gdef\xeteximgext{png}% + \fi + \else \gdef\xeteximgext{PDF}% + \fi + \else \gdef\xeteximgext{pdf}% + \fi + \closein 1 + \endgroup + % + \def\xetexpdfext{pdf}% + \ifx\xeteximgext\xetexpdfext + \XeTeXpdffile "#1".\xeteximgext "" + \else + \def\xetexpdfext{PDF}% + \ifx\xeteximgext\xetexpdfext + \XeTeXpdffile "#1".\xeteximgext "" + \else + \XeTeXpicfile "#1".\xeteximgext "" + \fi + \fi + \ifdim \wd0 >0pt width \xeteximagewidth \fi + \ifdim \wd2 >0pt height \xeteximageheight \fi \relax + } +\fi + + +% \message{fonts,} -% Change the current font style to #1, remembering it in \curfontstyle. -% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in -% italics, not bold italics. -% -\def\setfontstyle#1{% - \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. - \csname ten#1\endcsname % change the current font -} - -% Select #1 fonts with the current style. -% -\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} - -\def\rm{\fam=0 \setfontstyle{rm}} -\def\it{\fam=\itfam \setfontstyle{it}} -\def\sl{\fam=\slfam \setfontstyle{sl}} -\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} -\def\tt{\fam=\ttfam \setfontstyle{tt}} - -% Unfortunately, we have to override this for titles and the like, since -% in those cases "rm" is bold. Sigh. -\def\rmisbold{\rm\def\curfontstyle{bf}} - -% Texinfo sort of supports the sans serif font style, which plain TeX does not. -% So we set up a \sf. -\newfam\sffam -\def\sf{\fam=\sffam \setfontstyle{sf}} -\let\li = \sf % Sometimes we call it \li, not \sf. - -% We don't need math for this font style. -\def\ttsl{\setfontstyle{ttsl}} - - % Set the baselineskip to #1, and the lineskip and strut size % correspondingly. There is no deep meaning behind these magic numbers % used as factors; they just match (closely enough) what Knuth defined. @@ -1822,8 +2179,10 @@ end % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstep1}{OT1} \setfont\deftt\ttshape{10}{\magstep1}{OT1TT} +\setfont\defsl\slshape{10}{\magstep1}{OT1} \setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} +\def\df{\let\ttfont=\deftt \let\bffont = \defbf +\let\ttslfont=\defttsl \let\slfont=\defsl \bf} % Fonts for indices, footnotes, small examples (9pt). \def\smallnominalsize{9pt} @@ -1853,6 +2212,20 @@ end \font\smallersy=cmsy8 \def\smallerecsize{0800} +% Fonts for math mode superscripts (7pt). +\def\sevennominalsize{7pt} +\setfont\sevenrm\rmshape{7}{1000}{OT1} +\setfont\seventt\ttshape{10}{700}{OT1TT} +\setfont\sevenbf\bfshape{10}{700}{OT1} +\setfont\sevenit\itshape{7}{1000}{OT1IT} +\setfont\sevensl\slshape{10}{700}{OT1} +\setfont\sevensf\sfshape{10}{700}{OT1} +\setfont\sevensc\scshape{10}{700}{OT1} +\setfont\seventtsl\ttslshape{10}{700}{OT1TT} +\font\seveni=cmmi7 +\font\sevensy=cmsy7 +\def\sevenecsize{0700} + % Fonts for title page (20.4pt): \def\titlenominalsize{20pt} \setfont\titlerm\rmbshape{12}{\magstep3}{OT1} @@ -1884,6 +2257,7 @@ end % Section fonts (14.4pt). \def\secnominalsize{14pt} \setfont\secrm\rmbshape{12}{\magstep1}{OT1} +\setfont\secrmnotbold\rmshape{12}{\magstep1}{OT1} \setfont\secit\itbshape{10}{\magstep2}{OT1IT} \setfont\secsl\slbshape{10}{\magstep2}{OT1} \setfont\sectt\ttbshape{12}{\magstep1}{OT1TT} @@ -1909,7 +2283,7 @@ end \font\ssecsy=cmsy10 scaled 1315 \def\ssececsize{1200} -% Reduced fonts for @acro in text (10pt). +% Reduced fonts for @acronym in text (10pt). \def\reducednominalsize{10pt} \setfont\reducedrm\rmshape{10}{1000}{OT1} \setfont\reducedtt\ttshape{10}{1000}{OT1TT} @@ -1953,8 +2327,10 @@ end % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstephalf}{OT1} \setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} +\setfont\defsl\slshape{10}{\magstephalf}{OT1} \setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} -\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} +\def\df{\let\ttfont=\deftt \let\bffont = \defbf +\let\slfont=\defsl \let\ttslfont=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \def\smallnominalsize{9pt} @@ -1984,6 +2360,20 @@ end \font\smallersy=cmsy8 \def\smallerecsize{0800} +% Fonts for math mode superscripts (7pt). +\def\sevennominalsize{7pt} +\setfont\sevenrm\rmshape{7}{1000}{OT1} +\setfont\seventt\ttshape{10}{700}{OT1TT} +\setfont\sevenbf\bfshape{10}{700}{OT1} +\setfont\sevenit\itshape{7}{1000}{OT1IT} +\setfont\sevensl\slshape{10}{700}{OT1} +\setfont\sevensf\sfshape{10}{700}{OT1} +\setfont\sevensc\scshape{10}{700}{OT1} +\setfont\seventtsl\ttslshape{10}{700}{OT1TT} +\font\seveni=cmmi7 +\font\sevensy=cmsy7 +\def\sevenecsize{0700} + % Fonts for title page (20.4pt): \def\titlenominalsize{20pt} \setfont\titlerm\rmbshape{12}{\magstep3}{OT1} @@ -2040,7 +2430,7 @@ end \font\ssecsy=cmsy10 \def\ssececsize{1000} -% Reduced fonts for @acro in text (9pt). +% Reduced fonts for @acronym in text (9pt). \def\reducednominalsize{9pt} \setfont\reducedrm\rmshape{9}{1000}{OT1} \setfont\reducedtt\ttshape{9}{1000}{OT1TT} @@ -2060,6 +2450,12 @@ end \rm } % end of 10pt text font size definitions, \definetextfontsizex +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000}{OT1} +\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 +\setfont\shortcontsl\slshape{12}{1000}{OT1} +\setfont\shortconttt\ttshape{12}{1000}{OT1TT} + % We provide the user-level command % @fonttextsize 10 @@ -2086,102 +2482,121 @@ end \endgroup } - -% In order for the font changes to affect most math symbols and letters, -% we have to define the \textfont of the standard families. Since -% texinfo doesn't allow for producing subscripts and superscripts except -% in the main text, we don't bother to reset \scriptfont and -% \scriptscriptfont (which would also require loading a lot more fonts). % -\def\resetmathfonts{% - \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy - \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf - \textfont\ttfam=\tentt \textfont\sffam=\tensf +% Change the current font style to #1, remembering it in \curfontstyle. +% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in +% italics, not bold italics. +% +\def\setfontstyle#1{% + \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. + \csname #1font\endcsname % change the current font } -% The font-changing commands redefine the meanings of \tenSTYLE, instead -% of just \STYLE. We do this because \STYLE needs to also set the -% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire -% \tenSTYLE to set the current font. +\def\rm{\fam=0 \setfontstyle{rm}} +\def\it{\fam=\itfam \setfontstyle{it}} +\def\sl{\fam=\slfam \setfontstyle{sl}} +\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} +\def\tt{\fam=\ttfam \setfontstyle{tt}} + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf. +\newfam\sffam +\def\sf{\fam=\sffam \setfontstyle{sf}} + +% We don't need math for this font style. +\def\ttsl{\setfontstyle{ttsl}} + + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. +% We don't bother to reset \scriptscriptfont; awaiting user need. +% +\def\resetmathfonts{% + \textfont0=\rmfont \textfont1=\ifont \textfont2=\syfont + \textfont\itfam=\itfont \textfont\slfam=\slfont \textfont\bffam=\bffont + \textfont\ttfam=\ttfont \textfont\sffam=\sffont + % + % Fonts for superscript. Note that the 7pt fonts are used regardless + % of the current font size. + \scriptfont0=\sevenrm \scriptfont1=\seveni \scriptfont2=\sevensy + \scriptfont\itfam=\sevenit \scriptfont\slfam=\sevensl + \scriptfont\bffam=\sevenbf \scriptfont\ttfam=\seventt + \scriptfont\sffam=\sevensf +} + +% + +% The font-changing commands (all called \...fonts) redefine the meanings +% of \STYLEfont, instead of just \STYLE. We do this because \STYLE needs +% to also set the current \fam for math mode. Our \STYLE (e.g., \rm) +% commands hardwire \STYLEfont to set the current font. +% +% The fonts used for \ifont are for "math italics" (\itfont is for italics +% in regular text). \syfont is also used in math mode only. % % Each font-changing command also sets the names \lsize (one size lower) -% and \lllsize (three sizes lower). These relative commands are used in -% the LaTeX logo and acronyms. +% and \lllsize (three sizes lower). These relative commands are used +% in, e.g., the LaTeX logo and acronyms. % % This all needs generalizing, badly. % -\def\textfonts{% - \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl - \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc - \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy - \let\tenttsl=\textttsl - \def\curfontsize{text}% - \def\lsize{reduced}\def\lllsize{smaller}% - \resetmathfonts \setleading{\textleading}} -\def\titlefonts{% - \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl - \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc - \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy - \let\tenttsl=\titlettsl - \def\curfontsize{title}% - \def\lsize{chap}\def\lllsize{subsec}% - \resetmathfonts \setleading{27pt}} -\def\titlefont#1{{\titlefonts\rmisbold #1}} -\def\chapfonts{% - \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl - \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc - \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy - \let\tenttsl=\chapttsl - \def\curfontsize{chap}% - \def\lsize{sec}\def\lllsize{text}% - \resetmathfonts \setleading{19pt}} -\def\secfonts{% - \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl - \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc - \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy - \let\tenttsl=\secttsl - \def\curfontsize{sec}% - \def\lsize{subsec}\def\lllsize{reduced}% - \resetmathfonts \setleading{16pt}} -\def\subsecfonts{% - \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl - \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc - \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy - \let\tenttsl=\ssecttsl - \def\curfontsize{ssec}% - \def\lsize{text}\def\lllsize{small}% - \resetmathfonts \setleading{15pt}} -\let\subsubsecfonts = \subsecfonts -\def\reducedfonts{% - \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl - \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc - \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy - \let\tenttsl=\reducedttsl - \def\curfontsize{reduced}% - \def\lsize{small}\def\lllsize{smaller}% - \resetmathfonts \setleading{10.5pt}} -\def\smallfonts{% - \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl - \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc - \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy - \let\tenttsl=\smallttsl - \def\curfontsize{small}% - \def\lsize{smaller}\def\lllsize{smaller}% - \resetmathfonts \setleading{10.5pt}} -\def\smallerfonts{% - \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl - \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc - \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy - \let\tenttsl=\smallerttsl - \def\curfontsize{smaller}% - \def\lsize{smaller}\def\lllsize{smaller}% - \resetmathfonts \setleading{9.5pt}} -% Fonts for short table of contents. -\setfont\shortcontrm\rmshape{12}{1000}{OT1} -\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12 -\setfont\shortcontsl\slshape{12}{1000}{OT1} -\setfont\shortconttt\ttshape{12}{1000}{OT1TT} +\def\assignfonts#1{% + \expandafter\let\expandafter\rmfont\csname #1rm\endcsname + \expandafter\let\expandafter\itfont\csname #1it\endcsname + \expandafter\let\expandafter\slfont\csname #1sl\endcsname + \expandafter\let\expandafter\bffont\csname #1bf\endcsname + \expandafter\let\expandafter\ttfont\csname #1tt\endcsname + \expandafter\let\expandafter\smallcaps\csname #1sc\endcsname + \expandafter\let\expandafter\sffont \csname #1sf\endcsname + \expandafter\let\expandafter\ifont \csname #1i\endcsname + \expandafter\let\expandafter\syfont \csname #1sy\endcsname + \expandafter\let\expandafter\ttslfont\csname #1ttsl\endcsname +} + +\newif\ifrmisbold + +% Select smaller font size with the current style. Used to change font size +% in, e.g., the LaTeX logo and acronyms. If we are using bold fonts for +% normal roman text, also use bold fonts for roman text in the smaller size. +\def\switchtolllsize{% + \expandafter\assignfonts\expandafter{\lllsize}% + \ifrmisbold + \let\rmfont\bffont + \fi + \csname\curfontstyle\endcsname +}% + +\def\switchtolsize{% + \expandafter\assignfonts\expandafter{\lsize}% + \ifrmisbold + \let\rmfont\bffont + \fi + \csname\curfontstyle\endcsname +}% + +\def\definefontsetatsize#1#2#3#4#5{% +\expandafter\def\csname #1fonts\endcsname{% + \def\curfontsize{#1}% + \def\lsize{#2}\def\lllsize{#3}% + \csname rmisbold#5\endcsname + \assignfonts{#1}% + \resetmathfonts + \setleading{#4}% +}} + +\definefontsetatsize{text} {reduced}{smaller}{\textleading}{false} +\definefontsetatsize{title} {chap} {subsec} {27pt} {true} +\definefontsetatsize{chap} {sec} {text} {19pt} {true} +\definefontsetatsize{sec} {subsec} {reduced}{17pt} {true} +\definefontsetatsize{ssec} {text} {small} {15pt} {true} +\definefontsetatsize{reduced}{small} {smaller}{10.5pt}{false} +\definefontsetatsize{small} {smaller}{smaller}{10.5pt}{false} +\definefontsetatsize{smaller}{smaller}{smaller}{9.5pt} {false} + +\def\titlefont#1{{\titlefonts\rm #1}} +\let\subsecfonts = \ssecfonts +\let\subsubsecfonts = \ssecfonts % Define these just so they can be easily changed for other fonts. \def\angleleft{$\langle$} @@ -2219,26 +2634,11 @@ end % Markup style infrastructure. \defmarkupstylesetup\INITMACRO will % define and register \INITMACRO to be called on markup style changes. % \INITMACRO can check \currentmarkupstyle for the innermost -% style and the set of \ifmarkupSTYLE switches for all styles -% currently in effect. -\newif\ifmarkupvar -\newif\ifmarkupsamp -\newif\ifmarkupkey -%\newif\ifmarkupfile % @file == @samp. -%\newif\ifmarkupoption % @option == @samp. -\newif\ifmarkupcode -\newif\ifmarkupkbd -%\newif\ifmarkupenv % @env == @code. -%\newif\ifmarkupcommand % @command == @code. -\newif\ifmarkuptex % @tex (and part of @math, for now). -\newif\ifmarkupexample -\newif\ifmarkupverb -\newif\ifmarkupverbatim +% style. \let\currentmarkupstyle\empty \def\setupmarkupstyle#1{% - \csname markup#1true\endcsname \def\currentmarkupstyle{#1}% \markupstylesetup } @@ -2300,11 +2700,15 @@ end % lilypond developers report. xpdf does work with the regular 0x27. % \def\codequoteright{% - \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax - \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax - '% + \ifmonospace + \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax + \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax + '% + \else \char'15 \fi \else \char'15 \fi - \else \char'15 \fi + \else + '% + \fi } % % and a similar option for the left quote char vs. a grave accent. @@ -2312,17 +2716,21 @@ end % the code environments to do likewise. % \def\codequoteleft{% - \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax - \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax - % [Knuth] pp. 380,381,391 - % \relax disables Spanish ligatures ?` and !` of \tt font. - \relax`% + \ifmonospace + \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax + \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax + % [Knuth] pp. 380,381,391 + % \relax disables Spanish ligatures ?` and !` of \tt font. + \relax`% + \else \char'22 \fi \else \char'22 \fi - \else \char'22 \fi + \else + \relax`% + \fi } % Commands to set the quote options. -% +% \parseargdef\codequoteundirected{% \def\temp{#1}% \ifx\temp\onword @@ -2363,7 +2771,7 @@ end % If we are in a monospaced environment, however, 1) always use \ttsl, % and 2) do not add an italic correction. \def\dosmartslant#1#2{% - \ifusingtt + \ifusingtt {{\ttsl #2}\let\next=\relax}% {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}% \next @@ -2377,8 +2785,10 @@ end \ifx\next,% \else\ifx\next-% \else\ifx\next.% + \else\ifx\next\.% + \else\ifx\next\comma% \else\ptexslash - \fi\fi\fi + \fi\fi\fi\fi\fi \aftersmartic } @@ -2426,8 +2836,8 @@ end % \catcode`@=11 \def\plainfrenchspacing{% - \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m - \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + \sfcode`\.=\@m \sfcode`\?=\@m \sfcode`\!=\@m + \sfcode`\:=\@m \sfcode`\;=\@m \sfcode`\,=\@m \def\endofsentencespacefactor{1000}% for @. and friends } \def\plainnonfrenchspacing{% @@ -2440,7 +2850,7 @@ end % @t, explicit typewriter. \def\t#1{% - {\tt \rawbackslash \plainfrenchspacing #1}% + {\tt \plainfrenchspacing #1}% \null } @@ -2467,7 +2877,6 @@ end % Turn off hyphenation. \nohyphenation % - \rawbackslash \plainfrenchspacing #1% }% @@ -2475,14 +2884,14 @@ end } % We *must* turn on hyphenation at `-' and `_' in @code. +% (But see \codedashfinish below.) % Otherwise, it is too hard to avoid overfull hboxes % in the Emacs manual, the Library manual, etc. % % Unfortunately, TeX uses one parameter (\hyphenchar) to control % both hyphenation at - and hyphenation within words. % We must therefore turn them both off (\tclose does that) -% and arrange explicitly to hyphenate at a dash. -% -- rms. +% and arrange explicitly to hyphenate at a dash. -- rms. { \catcode`\-=\active \catcode`\_=\active \catcode`\'=\active \catcode`\`=\active @@ -2499,14 +2908,35 @@ end \let-\normaldash \let_\realunder \fi + % Given -foo (with a single dash), we do not want to allow a break + % after the hyphen. + \global\let\codedashprev=\codedash + % \codex } + % + \gdef\codedash{\futurelet\next\codedashfinish} + \gdef\codedashfinish{% + \normaldash % always output the dash character itself. + % + % Now, output a discretionary to allow a line break, unless + % (a) the next character is a -, or + % (b) the preceding character is a -. + % E.g., given --posix, we do not want to allow a break after either -. + % Given --foo-bar, we do want to allow a break between the - and the b. + \ifx\next\codedash \else + \ifx\codedashprev\codedash + \else \discretionary{}{}{}\fi + \fi + % we need the space after the = for the case when \next itself is a + % space token; it would get swallowed otherwise. As in @code{- a}. + \global\let\codedashprev= \next + } } - +\def\normaldash{-} +% \def\codex #1{\tclose{#1}\endgroup} -\def\normaldash{-} -\def\codedash{-\discretionary{}{}{}} \def\codeunder{% % this is all so @math{@code{var_name}+1} can work. In math mode, _ % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) @@ -2548,37 +2978,21 @@ end \let\file=\code \let\option=\code -% @uref (abbreviation for `urlref') takes an optional (comma-separated) -% second argument specifying the text to display and an optional third -% arg as text to display instead of (rather than in addition to) the url -% itself. First (mandatory) arg is the url. -% (This \urefnobreak definition isn't used now, leaving it for a while -% for comparison.) -\def\urefnobreak#1{\dourefnobreak #1,,,\finish} -\def\dourefnobreak#1,#2,#3,#4\finish{\begingroup - \unsepspaces - \pdfurl{#1}% - \setbox0 = \hbox{\ignorespaces #3}% - \ifdim\wd0 > 0pt - \unhbox0 % third arg given, show only that - \else - \setbox0 = \hbox{\ignorespaces #2}% - \ifdim\wd0 > 0pt - \ifpdf - \unhbox0 % PDF: 2nd arg given, show only it - \else - \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url - \fi - \else - \code{#1}% only url given, so show it - \fi - \fi - \endlink -\endgroup} +% @uref (abbreviation for `urlref') aka @url takes an optional +% (comma-separated) second argument specifying the text to display and +% an optional third arg as text to display instead of (rather than in +% addition to) the url itself. First (mandatory) arg is the url. -% This \urefbreak definition is the active one. +% TeX-only option to allow changing PDF output to show only the second +% arg (if given), and not the url (which is then just the link target). +\newif\ifurefurlonlylink + +% The main macro is \urefbreak, which allows breaking at expected +% places within the url. (There used to be another version, which +% didn't support automatic breaking.) \def\urefbreak{\begingroup \urefcatcodes \dourefbreak} \let\uref=\urefbreak +% \def\dourefbreak#1{\urefbreakfinish #1,,,\finish} \def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example \unsepspaces @@ -2587,12 +3001,32 @@ end \ifdim\wd0 > 0pt \unhbox0 % third arg given, show only that \else - \setbox0 = \hbox{\ignorespaces #2}% + \setbox0 = \hbox{\ignorespaces #2}% look for second arg \ifdim\wd0 > 0pt \ifpdf - \unhbox0 % PDF: 2nd arg given, show only it + % For pdfTeX and LuaTeX + \ifurefurlonlylink + % PDF plus option to not display url, show just arg + \unhbox0 + \else + % PDF, normally display both arg and url for consistency, + % visibility, if the pdf is eventually used to print, etc. + \unhbox0\ (\urefcode{#1})% + \fi \else - \unhbox0\ (\urefcode{#1})% DVI: 2nd arg given, show both it and url + \ifx\XeTeXrevision\thisisundefined + \unhbox0\ (\urefcode{#1})% DVI, always show arg and url + \else + % For XeTeX + \ifurefurlonlylink + % PDF plus option to not display url, show just arg + \unhbox0 + \else + % PDF, normally display both arg and url for consistency, + % visibility, if the pdf is eventually used to print, etc. + \unhbox0\ (\urefcode{#1})% + \fi + \fi \fi \else \urefcode{#1}% only url given, so show it @@ -2603,9 +3037,9 @@ end % Allow line breaks around only a few characters (only). \def\urefcatcodes{% - \catcode\ampChar=\active \catcode\dotChar=\active - \catcode\hashChar=\active \catcode\questChar=\active - \catcode\slashChar=\active + \catcode`\&=\active \catcode`\.=\active + \catcode`\#=\active \catcode`\?=\active + \catcode`\/=\active } { \urefcatcodes @@ -2629,39 +3063,33 @@ end \global\def/{\normalslash} } -% we put a little stretch before and after the breakable chars, to help -% line breaking of long url's. The unequal skips make look better in -% cmtt at least, especially for dots. -\def\urefprestretch{\urefprebreak \hskip0pt plus.13em } -\def\urefpoststretch{\urefpostbreak \hskip0pt plus.1em } -% -\def\urefcodeamp{\urefprestretch \&\urefpoststretch} -\def\urefcodedot{\urefprestretch .\urefpoststretch} -\def\urefcodehash{\urefprestretch \#\urefpoststretch} -\def\urefcodequest{\urefprestretch ?\urefpoststretch} +\def\urefcodeamp{\urefprebreak \&\urefpostbreak} +\def\urefcodedot{\urefprebreak .\urefpostbreak} +\def\urefcodehash{\urefprebreak \#\urefpostbreak} +\def\urefcodequest{\urefprebreak ?\urefpostbreak} \def\urefcodeslash{\futurelet\next\urefcodeslashfinish} { \catcode`\/=\active \global\def\urefcodeslashfinish{% - \urefprestretch \slashChar + \urefprebreak \slashChar % Allow line break only after the final / in a sequence of % slashes, to avoid line break between the slashes in http://. - \ifx\next/\else \urefpoststretch \fi + \ifx\next/\else \urefpostbreak \fi } } -% One more complication: by default we'll break after the special -% characters, but some people like to break before the special chars, so -% allow that. Also allow no breaking at all, for manual control. -% +% By default we'll break after the special characters, but some people like to +% break before the special chars, so allow that. Also allow no breaking at +% all, for manual control. +% \parseargdef\urefbreakstyle{% \def\txiarg{#1}% \ifx\txiarg\wordnone \def\urefprebreak{\nobreak}\def\urefpostbreak{\nobreak} \else\ifx\txiarg\wordbefore - \def\urefprebreak{\allowbreak}\def\urefpostbreak{\nobreak} + \def\urefprebreak{\urefallowbreak}\def\urefpostbreak{\nobreak} \else\ifx\txiarg\wordafter - \def\urefprebreak{\nobreak}\def\urefpostbreak{\allowbreak} + \def\urefprebreak{\nobreak}\def\urefpostbreak{\urefallowbreak} \else \errhelp = \EMsimple \errmessage{Unknown @urefbreakstyle setting `\txiarg'}% @@ -2671,6 +3099,19 @@ end \def\wordbefore{before} \def\wordnone{none} +% Allow a ragged right output to aid breaking long URL's. There can +% be a break at the \allowbreak with no extra glue (if the existing stretch in +% the line is sufficent), a break at the \penalty100 with extra glue added +% at the end of the line, or no break at all here. +% Changing the value of the penalty and/or the amount of stretch affects how +% preferrable one choice is over the other. +\def\urefallowbreak{% + \allowbreak + \hskip 0pt plus 2 em\relax + \penalty300 + \hskip 0pt plus -2 em\relax +} + \urefbreakstyle after % @url synonym for @uref, since that's how everyone uses it. @@ -2681,7 +3122,7 @@ end % So now @email is just like @uref, unless we are pdf. % %\def\email#1{\angleleft{\tt #1}\angleright} -\ifpdf +\ifpdforxetex \def\email#1{\doemail#1,,\finish} \def\doemail#1,#2,#3\finish{\begingroup \unsepspaces @@ -2760,18 +3201,13 @@ end % \def\dmn#1{\thinspace #1} -% @l was never documented to mean ``switch to the Lisp font'', -% and it is not used as such in any manual I can find. We need it for -% Polish suppressed-l. --karl, 22sep96. -%\def\l#1{{\li #1}\null} - % @acronym for "FBI", "NATO", and the like. % We print this one point size smaller, since it's intended for % all-uppercase. % \def\acronym#1{\doacronym #1,,\finish} \def\doacronym#1,#2,#3\finish{% - {\selectfonts\lsize #1}% + {\switchtolsize #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% @@ -2817,21 +3253,24 @@ end \def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} % \def\math{% - \tex - \mathunderscore - \let\\ = \mathbackslash - \mathactive - % make the texinfo accent commands work in math mode - \let\"=\ddot - \let\'=\acute - \let\==\bar - \let\^=\hat - \let\`=\grave - \let\u=\breve - \let\v=\check - \let\~=\tilde - \let\dotaccent=\dot - $\finishmath + \ifmmode\else % only go into math if not in math mode already + \tex + \mathunderscore + \let\\ = \mathbackslash + \mathactive + % make the texinfo accent commands work in math mode + \let\"=\ddot + \let\'=\acute + \let\==\bar + \let\^=\hat + \let\`=\grave + \let\u=\breve + \let\v=\check + \let\~=\tilde + \let\dotaccent=\dot + % have to provide another name for sup operator + \let\mathopsup=\sup + $\expandafter\finishmath\fi } \def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. @@ -2854,13 +3293,22 @@ end } } -% ctrl is no longer a Texinfo command, but leave this definition for fun. -\def\ctrl #1{{\tt \rawbackslash \hat}#1} +% for @sub and @sup, if in math mode, just do a normal sub/superscript. +% If in text, use math to place as sub/superscript, but switch +% into text mode, with smaller fonts. This is a different font than the +% one used for real math sub/superscripts (8pt vs. 7pt), but let's not +% fix it (significant additions to font machinery) until someone notices. +% +\def\sub{\ifmmode \expandafter\sb \else \expandafter\finishsub\fi} +\def\finishsub#1{$\sb{\hbox{\switchtolllsize #1}}$}% +% +\def\sup{\ifmmode \expandafter\ptexsp \else \expandafter\finishsup\fi} +\def\finishsup#1{$\ptexsp{\hbox{\switchtolllsize #1}}$}% % @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}. % Ignore unless FMTNAME == tex; then it is like @iftex and @tex, % except specified as a normal braced arg, so no newlines to worry about. -% +% \def\outfmtnametex{tex} % \long\def\inlinefmt#1{\doinlinefmt #1,\finish} @@ -2868,6 +3316,15 @@ end \def\inlinefmtname{#1}% \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi } +% +% @inlinefmtifelse{FMTNAME,THEN-TEXT,ELSE-TEXT} expands THEN-TEXT if +% FMTNAME is tex, else ELSE-TEXT. +\long\def\inlinefmtifelse#1{\doinlinefmtifelse #1,,,\finish} +\long\def\doinlinefmtifelse#1,#2,#3,#4,\finish{% + \def\inlinefmtname{#1}% + \ifx\inlinefmtname\outfmtnametex \ignorespaces #2\else \ignorespaces #3\fi +} +% % For raw, must switch into @tex before parsing the argument, to avoid % setting catcodes prematurely. Doing it this way means that, for % example, @inlineraw{html, foo{bar} gets a parse error instead of being @@ -2875,7 +3332,7 @@ end % *right* brace they would have to use a command anyway, so they may as % well use a command to get a left brace too. We could re-use the % delimiter character idea from \verb, but it seems like overkill. -% +% \long\def\inlineraw{\tex \doinlineraw} \long\def\doinlineraw#1{\doinlinerawtwo #1,\finish} \def\doinlinerawtwo#1,#2,\finish{% @@ -2884,6 +3341,23 @@ end \endgroup % close group opened by \tex. } +% @inlineifset{VAR, TEXT} expands TEXT if VAR is @set. +% +\long\def\inlineifset#1{\doinlineifset #1,\finish} +\long\def\doinlineifset#1,#2,\finish{% + \def\inlinevarname{#1}% + \expandafter\ifx\csname SET\inlinevarname\endcsname\relax + \else\ignorespaces#2\fi +} + +% @inlineifclear{VAR, TEXT} expands TEXT if VAR is not @set. +% +\long\def\inlineifclear#1{\doinlineifclear #1,\finish} +\long\def\doinlineifclear#1,#2,\finish{% + \def\inlinevarname{#1}% + \expandafter\ifx\csname SET\inlinevarname\endcsname\relax \ignorespaces#2\fi +} + \message{glyphs,} % and logos. @@ -2893,23 +3367,10 @@ end \let\atchar=\@ % @{ @} @lbracechar{} @rbracechar{} all generate brace characters. -% Unless we're in typewriter, use \ecfont because the CM text fonts do -% not have braces, and we don't want to switch into math. -\def\mylbrace{{\ifmonospace\else\ecfont\fi \char123}} -\def\myrbrace{{\ifmonospace\else\ecfont\fi \char125}} -\let\{=\mylbrace \let\lbracechar=\{ -\let\}=\myrbrace \let\rbracechar=\} -\begingroup - % Definitions to produce \{ and \} commands for indices, - % and @{ and @} for the aux/toc files. - \catcode`\{ = \other \catcode`\} = \other - \catcode`\[ = 1 \catcode`\] = 2 - \catcode`\! = 0 \catcode`\\ = \other - !gdef!lbracecmd[\{]% - !gdef!rbracecmd[\}]% - !gdef!lbraceatcmd[@{]% - !gdef!rbraceatcmd[@}]% -!endgroup +\def\lbracechar{{\ifmonospace\char123\else\ensuremath\lbrace\fi}} +\def\rbracechar{{\ifmonospace\char125\else\ensuremath\rbrace\fi}} +\let\{=\lbracechar +\let\}=\rbracechar % @comma{} to avoid , parsing problems. \let\comma = , @@ -2927,8 +3388,8 @@ end % Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. \def\questiondown{?`} \def\exclamdown{!`} -\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} -\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} +\def\ordf{\leavevmode\raise1ex\hbox{\switchtolllsize \underbar{a}}} +\def\ordm{\leavevmode\raise1ex\hbox{\switchtolllsize \underbar{o}}} % Dotless i and dotless j, used for accents. \def\imacro{i} @@ -2957,12 +3418,12 @@ end {\setbox0=\hbox{T}% \vbox to \ht0{\hbox{% \ifx\textnominalsize\xwordpt - % for 10pt running text, \lllsize (8pt) is too small for the A in LaTeX. + % for 10pt running text, lllsize (8pt) is too small for the A in LaTeX. % Revert to plain's \scriptsize, which is 7pt. \count255=\the\fam $\fam\count255 \scriptstyle A$% \else % For 11pt, we can use our lllsize. - \selectfonts\lllsize A% + \switchtolllsize A% \fi }% \vss @@ -2971,11 +3432,16 @@ end \TeX } -% Some math mode symbols. -\def\bullet{$\ptexbullet$} -\def\geq{\ifmmode \ge\else $\ge$\fi} -\def\leq{\ifmmode \le\else $\le$\fi} -\def\minus{\ifmmode -\else $-$\fi} +% Some math mode symbols. Define \ensuremath to switch into math mode +% unless we are already there. Expansion tricks may not be needed here, +% but safer, and can't hurt. +\def\ensuremath{\ifmmode \expandafter\asis \else\expandafter\ensuredmath \fi} +\def\ensuredmath#1{$\relax#1$} +% +\def\bullet{\ensuremath\ptexbullet} +\def\geq{\ensuremath\ge} +\def\leq{\ensuremath\le} +\def\minus{\ensuremath-} % @dots{} outputs an ellipsis using the current font. % We do .5em per period so that it has the same spacing in the cm @@ -3023,7 +3489,7 @@ end % \newbox\errorbox % -{\tentt \global\dimen0 = 3em}% Width of the box. +{\ttfont \global\dimen0 = 3em}% Width of the box. \dimen2 = .55pt % Thickness of rules % The text. (`r' is open on the right, `e' somewhat less so on the left.) \setbox0 = \hbox{\kern-.75pt \reducedsf \putworderror\kern-1.5pt} @@ -3139,8 +3605,15 @@ end \def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E} \def\eogonek{{\ecfont \char"A6}}\def\macrochare{e} % -% Use the ec* fonts (cm-super in outline format) for non-CM glyphs. -\def\ecfont{% +% Use the European Computer Modern fonts (cm-super in outline format) +% for non-CM glyphs. That is ec* for regular text and tc* for the text +% companion symbols (LaTeX TS1 encoding). Both are part of the ec +% package and follow the same conventions. +% +\def\ecfont{\etcfont{e}} +\def\tcfont{\etcfont{t}} +% +\def\etcfont#1{% % We can't distinguish serif/sans and italic/slanted, but this % is used for crude hacks anyway (like adding French and German % quotes to documents typeset with CM, where we lose kerning), so @@ -3149,14 +3622,14 @@ end \edef\nominalsize{\csname\curfontsize nominalsize\endcsname}% \ifmonospace % typewriter: - \font\thisecfont = ectt\ecsize \space at \nominalsize + \font\thisecfont = #1ctt\ecsize \space at \nominalsize \else \ifx\curfontstyle\bfstylename % bold: - \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize + \font\thisecfont = #1cb\ifusingit{i}{x}\ecsize \space at \nominalsize \else % regular: - \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize + \font\thisecfont = #1c\ifusingit{ti}{rm}\ecsize \space at \nominalsize \fi \fi \thisecfont @@ -3167,7 +3640,7 @@ end % Adapted from the plain.tex definition of \copyright. % \def\registeredsymbol{% - $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% + $^{{\ooalign{\hfil\raise.07ex\hbox{\switchtolllsize R}% \hfil\crcr\Orb}}% }$% } @@ -3200,13 +3673,16 @@ end \newif\ifseenauthor \newif\iffinishedtitlepage -% Do an implicit @contents or @shortcontents after @end titlepage if the -% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. -% -\newif\ifsetcontentsaftertitlepage - \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue -\newif\ifsetshortcontentsaftertitlepage - \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue +% @setcontentsaftertitlepage used to do an implicit @contents or +% @shortcontents after @end titlepage, but it is now obsolete. +\def\setcontentsaftertitlepage{% + \errmessage{@setcontentsaftertitlepage has been removed as a Texinfo + command; move your @contents command if you want the contents + after the title page.}}% +\def\setshortcontentsaftertitlepage{% + \errmessage{@setshortcontentsaftertitlepage has been removed as a Texinfo + command; move your @shortcontents and @contents commands if you + want the contents after the title page.}}% \parseargdef\shorttitlepage{% \begingroup \hbox{}\vskip 1.5in \chaprm \centerline{#1}% @@ -3248,20 +3724,6 @@ end % Need this before the \...aftertitlepage checks so that if they are % in effect the toc pages will come out with page numbers. \HEADINGSon - % - % If they want short, they certainly want long too. - \ifsetshortcontentsaftertitlepage - \shortcontents - \contents - \global\let\shortcontents = \relax - \global\let\contents = \relax - \fi - % - \ifsetcontentsaftertitlepage - \contents - \global\let\contents = \relax - \global\let\shortcontents = \relax - \fi } \def\finishtitlepage{% @@ -3272,12 +3734,11 @@ end % Settings used for typesetting titles: no hyphenation, no indentation, % don't worry much about spacing, ragged right. This should be used -% inside a \vbox, and fonts need to be set appropriately first. Because -% it is always used for titles, nothing else, we call \rmisbold. \par -% should be specified before the end of the \vbox, since a vbox is a group. -% +% inside a \vbox, and fonts need to be set appropriately first. \par should +% be specified before the end of the \vbox, since a vbox is a group. +% \def\raggedtitlesettings{% - \rmisbold + \rm \hyphenpenalty=10000 \parindent=0pt \tolerance=5000 @@ -3286,7 +3747,7 @@ end % Macros to be used within @titlepage: -\let\subtitlerm=\tenrm +\let\subtitlerm=\rmfont \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} \parseargdef\title{% @@ -3312,7 +3773,7 @@ end \else \checkenv\titlepage \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi - {\secfonts\rmisbold \leftline{#1}}% + {\secfonts\rm \leftline{#1}}% \fi } @@ -3326,7 +3787,7 @@ end \newtoks\evenfootline % footline on even pages \newtoks\oddfootline % footline on odd pages -% Now make TeX use those variables +% Now make \makeheadline and \makefootline in Plain TeX use those variables \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}} \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline @@ -3365,7 +3826,7 @@ end % % Leave some space for the footline. Hopefully ok to assume % @evenfooting will not be used by itself. - \global\advance\pageheight by -12pt + \global\advance\txipageheight by -12pt \global\advance\vsize by -12pt } @@ -3382,13 +3843,17 @@ end % @everyheadingmarks % @everyfootingmarks +% These define \getoddheadingmarks, \getevenheadingmarks, +% \getoddfootingmarks, and \getevenfootingmarks, each to one of +% \gettopheadingmarks, \getbottomheadingmarks. +% \def\evenheadingmarks{\headingmarks{even}{heading}} \def\oddheadingmarks{\headingmarks{odd}{heading}} \def\evenfootingmarks{\headingmarks{even}{footing}} \def\oddfootingmarks{\headingmarks{odd}{footing}} -\def\everyheadingmarks#1 {\headingmarks{even}{heading}{#1} +\parseargdef\everyheadingmarks{\headingmarks{even}{heading}{#1} \headingmarks{odd}{heading}{#1} } -\def\everyfootingmarks#1 {\headingmarks{even}{footing}{#1} +\parseargdef\everyfootingmarks{\headingmarks{even}{footing}{#1} \headingmarks{odd}{footing}{#1} } % #1 = even/odd, #2 = heading/footing, #3 = top/bottom. \def\headingmarks#1#2#3 {% @@ -3409,7 +3874,7 @@ end % By default, they are off at the start of a document, % and turned `on' after @end titlepage. -\def\headings #1 {\csname HEADINGS#1\endcsname} +\parseargdef\headings{\csname HEADINGS#1\endcsname} \def\headingsoff{% non-global headings elimination \evenheadline={\hfil}\evenfootline={\hfil}% @@ -3429,7 +3894,7 @@ end \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \let\contentsalignmacro = \chappager @@ -3440,8 +3905,8 @@ end \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\evenheadline={\line{\thischapterheading\hfil\folio}} +\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\let\contentsalignmacro = \chappager } \def\HEADINGSon{\HEADINGSdouble} @@ -3452,7 +3917,7 @@ end \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} -\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } @@ -3460,8 +3925,8 @@ end \def\HEADINGSsinglex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} -\global\evenheadline={\line{\thischapter\hfil\folio}} -\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\evenheadline={\line{\thischapterheading\hfil\folio}} +\global\oddheadline={\line{\thischapterheading\hfil\folio}} \global\let\contentsalignmacro = \chappager } @@ -3639,7 +4104,7 @@ end \parskip=\smallskipamount \ifdim\parskip=0pt \parskip=2pt \fi % - % Try typesetting the item mark that if the document erroneously says + % Try typesetting the item mark so that if the document erroneously says % something like @itemize @samp (intending @table), there's an error % right away at the @itemize. It's not the best error message in the % world, but it's better than leaving it to the @item. This means if @@ -3671,7 +4136,12 @@ end \noindent \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% % - \vadjust{\penalty 1200}}% not good to break after first line of item. + \ifinner\else + \vadjust{\penalty 1200}% not good to break after first line of item. + \fi + % We can be in inner vertical mode in a footnote, although an + % @itemize looks awful there. + }% \flushcr } @@ -3890,18 +4360,22 @@ end % multitable-only commands. % -% @headitem starts a heading row, which we typeset in bold. -% Assignments have to be global since we are inside the implicit group -% of an alignment entry. \everycr resets \everytab so we don't have to +% @headitem starts a heading row, which we typeset in bold. Assignments +% have to be global since we are inside the implicit group of an +% alignment entry. \everycr below resets \everytab so we don't have to % undo it ourselves. \def\headitemfont{\b}% for people to use in the template row; not changeable \def\headitem{% \checkenv\multitable \crcr + \gdef\headitemcrhook{\nobreak}% attempt to avoid page break after headings \global\everytab={\bf}% can't use \headitemfont since the parsing differs \the\everytab % for the first item }% % +% default for tables with no headings. +\let\headitemcrhook=\relax +% % A \tab used to include \hskip1sp. But then the space in a template % line is not enough. That is bad. So let's go back to just `&' until % we again encounter the problem the 1sp was intended to solve. @@ -3932,15 +4406,15 @@ end % \everycr = {% \noalign{% - \global\everytab={}% + \global\everytab={}% Reset from possible headitem. \global\colcount=0 % Reset the column counter. - % Check for saved footnotes, etc. + % + % Check for saved footnotes, etc.: \checkinserts - % Keeps underfull box messages off when table breaks over pages. - %\filbreak - % Maybe so, but it also creates really weird page breaks when the - % table breaks over pages. Wouldn't \vfil be better? Wait until the - % problem manifests itself, so it can be fixed for real --karl. + % + % Perhaps a \nobreak, then reset: + \headitemcrhook + \global\let\headitemcrhook=\relax }% }% % @@ -4179,7 +4653,7 @@ end \def\value{\begingroup\makevalueexpandable\valuexxx} \def\valuexxx#1{\expandablevalue{#1}\endgroup} { - \catcode`\- = \active \catcode`\_ = \active + \catcode`\-=\active \catcode`\_=\active % \gdef\makevalueexpandable{% \let\value = \expandablevalue @@ -4192,14 +4666,6 @@ end } } -% We have this subroutine so that we can handle at least some @value's -% properly in indexes (we call \makevalueexpandable in \indexdummies). -% The command has to be fully expandable (if the variable is set), since -% the result winds up in the index file. This means that if the -% variable's value contains other Texinfo commands, it's almost certain -% it will fail (although perhaps we could fix that with sufficient work -% to do a one-level expansion on the result, instead of complete). -% \def\expandablevalue#1{% \expandafter\ifx\csname SET#1\endcsname\relax {[No value for ``#1'']}% @@ -4209,10 +4675,36 @@ end \fi } +% Like \expandablevalue, but completely expandable (the \message in the +% definition above operates at the execution level of TeX). Used when +% writing to auxiliary files, due to the expansion that \write does. +% If flag is undefined, pass through an unexpanded @value command: maybe it +% will be set by the time it is read back in. +% +% NB flag names containing - or _ may not work here. +\def\dummyvalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + \string\value{#1}% + \else + \csname SET#1\endcsname + \fi +} + +% Used for @value's in index entries to form the sort key: expand the @value +% if possible, otherwise sort late. +\def\indexnofontsvalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + ZZZZZZZ% + \else + \csname SET#1\endcsname + \fi +} + % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined % with @set. % -% To get special treatment of `@end ifset,' call \makeond and the redefine. +% To get the special treatment we need for `@end ifset,' we call +% \makecond and then redefine. % \makecond{ifset} \def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} @@ -4243,7 +4735,7 @@ end % without the @) is in fact defined. We can only feasibly check at the % TeX level, so something like `mathcode' is going to considered % defined even though it is not a Texinfo command. -% +% \makecond{ifcommanddefined} \def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}} % @@ -4283,19 +4775,16 @@ end % except not \outer, so it can be used within macros and \if's. \edef\newwrite{\makecsname{ptexnewwrite}} -% \newindex {foo} defines an index named foo. -% It automatically defines \fooindex such that -% \fooindex ...rest of line... puts an entry in the index foo. -% It also defines \fooindfile to be the number of the output channel for -% the file that accumulates this index. The file's extension is foo. +% \newindex {foo} defines an index named IX. +% It automatically defines \IXindex such that +% \IXindex ...rest of line... puts an entry in the index IX. +% It also defines \IXindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is IX. % The name of an index should be no more than 2 characters long % for the sake of vms. % \def\newindex#1{% - \iflinks - \expandafter\newwrite \csname#1indfile\endcsname - \openout \csname#1indfile\endcsname \jobname.#1 % Open the file - \fi + \expandafter\chardef\csname#1indfile\endcsname=0 \expandafter\xdef\csname#1index\endcsname{% % Define @#1index \noexpand\doindex{#1}} } @@ -4309,14 +4798,19 @@ end \def\defcodeindex{\parsearg\newcodeindex} % \def\newcodeindex#1{% - \iflinks - \expandafter\newwrite \csname#1indfile\endcsname - \openout \csname#1indfile\endcsname \jobname.#1 - \fi + \expandafter\chardef\csname#1indfile\endcsname=0 \expandafter\xdef\csname#1index\endcsname{% \noexpand\docodeindex{#1}}% } +% The default indices: +\newindex{cp}% concepts, +\newcodeindex{fn}% functions, +\newcodeindex{vr}% variables, +\newcodeindex{tp}% types, +\newcodeindex{ky}% keys +\newcodeindex{pg}% and programs. + % @synindex foo bar makes index foo feed into index bar. % Do this instead of @defindex foo if you don't want it as a separate index. @@ -4330,14 +4824,7 @@ end % #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), % #3 the target index (bar). \def\dosynindex#1#2#3{% - % Only do \closeout if we haven't already done it, else we'll end up - % closing the target index. - \expandafter \ifx\csname donesynindex#2\endcsname \relax - % The \closeout helps reduce unnecessary open files; the limit on the - % Acorn RISC OS is a mere 16 files. - \expandafter\closeout\csname#2indfile\endcsname - \expandafter\let\csname donesynindex#2\endcsname = 1 - \fi + \requireopenindexfile{#3}% % redefine \fooindfile: \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname \expandafter\let\csname#2indfile\endcsname=\temp @@ -4345,108 +4832,57 @@ end \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% } -% Define \doindex, the driver for all \fooindex macros. +% Define \doindex, the driver for all index macros. % Argument #1 is generated by the calling \fooindex macro, -% and it is "foo", the name of the index. +% and it is the two-letter name of the index. -% \doindex just uses \parsearg; it calls \doind for the actual work. -% This is because \doind is more useful to call from other macros. - -% There is also \dosubind {index}{topic}{subtopic} -% which makes an entry in a two-level index such as the operation index. - -\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} -\def\singleindexer #1{\doind{\indexname}{#1}} +\def\doindex#1{\edef\indexname{#1}\parsearg\doindexxxx} +\def\doindexxxx #1{\doind{\indexname}{#1}} % like the previous two, but they put @code around the argument. -\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} -\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} +\def\docodeindex#1{\edef\indexname{#1}\parsearg\docodeindexxxx} +\def\docodeindexxxx #1{\doind{\indexname}{\code{#1}}} -% Take care of Texinfo commands that can appear in an index entry. -% Since there are some commands we want to expand, and others we don't, -% we have to laboriously prevent expansion for those that we don't. -% -\def\indexdummies{% - \escapechar = `\\ % use backslash in output files. - \def\@{@}% change to @@ when we switch to @ as escape char in index files. - \def\ {\realbackslash\space }% - % - % Need these unexpandable (because we define \tt as a dummy) - % definitions when @{ or @} appear in index entry text. Also, more - % complicated, when \tex is in effect and \{ is a \delimiter again. - % We can't use \lbracecmd and \rbracecmd because texindex assumes - % braces and backslashes are used only as delimiters. Perhaps we - % should define @lbrace and @rbrace commands a la @comma. - \def\{{{\tt\char123}}% - \def\}{{\tt\char125}}% - % - % I don't entirely understand this, but when an index entry is - % generated from a macro call, the \endinput which \scanmacro inserts - % causes processing to be prematurely terminated. This is, - % apparently, because \indexsorttmp is fully expanded, and \endinput - % is an expandable command. The redefinition below makes \endinput - % disappear altogether for that purpose -- although logging shows that - % processing continues to some further point. On the other hand, it - % seems \endinput does not hurt in the printed index arg, since that - % is still getting written without apparent harm. - % - % Sample source (mac-idx3.tex, reported by Graham Percival to - % help-texinfo, 22may06): - % @macro funindex {WORD} - % @findex xyz - % @end macro - % ... - % @funindex commtest - % - % The above is not enough to reproduce the bug, but it gives the flavor. - % - % Sample whatsit resulting: - % .@write3{\entry{xyz}{@folio }{@code {xyz@endinput }}} - % - % So: - \let\endinput = \empty - % - % Do the redefinitions. - \commondummies -} -% For the aux and toc files, @ is the escape character. So we want to -% redefine everything using @ as the escape character (instead of -% \realbackslash, still used for index files). When everything uses @, -% this will be simpler. +% Used for the aux, toc and index files to prevent expansion of Texinfo +% commands. % \def\atdummies{% - \def\@{@@}% - \def\ {@ }% - \let\{ = \lbraceatcmd - \let\} = \rbraceatcmd + \definedummyletter\@% + \definedummyletter\ % + \definedummyletter\{% + \definedummyletter\}% + \definedummyletter\&% % % Do the redefinitions. - \commondummies + \definedummies \otherbackslash } -% Called from \indexdummies and \atdummies. +% \definedummyword defines \#1 as \string\#1\space, thus effectively +% preventing its expansion. This is used only for control words, +% not control letters, because the \space would be incorrect for +% control characters, but is needed to separate the control word +% from whatever follows. % -\def\commondummies{% - % - % \definedummyword defines \#1 as \string\#1\space, thus effectively - % preventing its expansion. This is used only for control words, - % not control letters, because the \space would be incorrect for - % control characters, but is needed to separate the control word - % from whatever follows. - % - % For control letters, we have \definedummyletter, which omits the - % space. - % - % These can be used both for control words that take an argument and - % those that do not. If it is followed by {arg} in the input, then - % that will dutifully get written to the index (or wherever). - % - \def\definedummyword ##1{\def##1{\string##1\space}}% - \def\definedummyletter##1{\def##1{\string##1}}% - \let\definedummyaccent\definedummyletter +% These can be used both for control words that take an argument and +% those that do not. If it is followed by {arg} in the input, then +% that will dutifully get written to the index (or wherever). +% +% For control letters, we have \definedummyletter, which omits the +% space. +% +\def\definedummyword #1{\def#1{\string#1\space}}% +\def\definedummyletter#1{\def#1{\string#1}}% +\let\definedummyaccent\definedummyletter + +% Called from \atdummies to prevent the expansion of commands. +% +\def\definedummies{% % + \let\commondummyword\definedummyword + \let\commondummyletter\definedummyletter + \let\commondummyaccent\definedummyaccent \commondummiesnofonts % \definedummyletter\_% @@ -4487,7 +4923,10 @@ end \definedummyword\TeX % % Assorted special characters. + \definedummyword\ampchar + \definedummyword\atchar \definedummyword\arrow + \definedummyword\backslashchar \definedummyword\bullet \definedummyword\comma \definedummyword\copyright @@ -4506,6 +4945,7 @@ end \definedummyword\guilsinglright \definedummyword\lbracechar \definedummyword\leq + \definedummyword\mathopsup \definedummyword\minus \definedummyword\ogonek \definedummyword\pounds @@ -4519,88 +4959,135 @@ end \definedummyword\quotesinglbase \definedummyword\rbracechar \definedummyword\result + \definedummyword\sub + \definedummyword\sup \definedummyword\textdegree % + \definedummyword\subentry + % % We want to disable all macros so that they are not expanded by \write. \macrolist + \let\value\dummyvalue % \normalturnoffactive - % - % Handle some cases of @value -- where it does not contain any - % (non-fully-expandable) commands. - \makevalueexpandable } -% \commondummiesnofonts: common to \commondummies and \indexnofonts. +% \commondummiesnofonts: common to \definedummies and \indexnofonts. +% Define \commondummyletter, \commondummyaccent and \commondummyword before +% using. Used for accents, font commands, and various control letters. % \def\commondummiesnofonts{% % Control letters and accents. - \definedummyletter\!% - \definedummyaccent\"% - \definedummyaccent\'% - \definedummyletter\*% - \definedummyaccent\,% - \definedummyletter\.% - \definedummyletter\/% - \definedummyletter\:% - \definedummyaccent\=% - \definedummyletter\?% - \definedummyaccent\^% - \definedummyaccent\`% - \definedummyaccent\~% - \definedummyword\u - \definedummyword\v - \definedummyword\H - \definedummyword\dotaccent - \definedummyword\ogonek - \definedummyword\ringaccent - \definedummyword\tieaccent - \definedummyword\ubaraccent - \definedummyword\udotaccent - \definedummyword\dotless + \commondummyletter\!% + \commondummyaccent\"% + \commondummyaccent\'% + \commondummyletter\*% + \commondummyaccent\,% + \commondummyletter\.% + \commondummyletter\/% + \commondummyletter\:% + \commondummyaccent\=% + \commondummyletter\?% + \commondummyaccent\^% + \commondummyaccent\`% + \commondummyaccent\~% + \commondummyword\u + \commondummyword\v + \commondummyword\H + \commondummyword\dotaccent + \commondummyword\ogonek + \commondummyword\ringaccent + \commondummyword\tieaccent + \commondummyword\ubaraccent + \commondummyword\udotaccent + \commondummyword\dotless % % Texinfo font commands. - \definedummyword\b - \definedummyword\i - \definedummyword\r - \definedummyword\sansserif - \definedummyword\sc - \definedummyword\slanted - \definedummyword\t + \commondummyword\b + \commondummyword\i + \commondummyword\r + \commondummyword\sansserif + \commondummyword\sc + \commondummyword\slanted + \commondummyword\t % % Commands that take arguments. - \definedummyword\abbr - \definedummyword\acronym - \definedummyword\anchor - \definedummyword\cite - \definedummyword\code - \definedummyword\command - \definedummyword\dfn - \definedummyword\dmn - \definedummyword\email - \definedummyword\emph - \definedummyword\env - \definedummyword\file - \definedummyword\image - \definedummyword\indicateurl - \definedummyword\inforef - \definedummyword\kbd - \definedummyword\key - \definedummyword\math - \definedummyword\option - \definedummyword\pxref - \definedummyword\ref - \definedummyword\samp - \definedummyword\strong - \definedummyword\tie - \definedummyword\uref - \definedummyword\url - \definedummyword\var - \definedummyword\verb - \definedummyword\w - \definedummyword\xref + \commondummyword\abbr + \commondummyword\acronym + \commondummyword\anchor + \commondummyword\cite + \commondummyword\code + \commondummyword\command + \commondummyword\dfn + \commondummyword\dmn + \commondummyword\email + \commondummyword\emph + \commondummyword\env + \commondummyword\file + \commondummyword\image + \commondummyword\indicateurl + \commondummyword\inforef + \commondummyword\kbd + \commondummyword\key + \commondummyword\math + \commondummyword\option + \commondummyword\pxref + \commondummyword\ref + \commondummyword\samp + \commondummyword\strong + \commondummyword\tie + \commondummyword\U + \commondummyword\uref + \commondummyword\url + \commondummyword\var + \commondummyword\verb + \commondummyword\w + \commondummyword\xref } +\let\indexlbrace\relax +\let\indexrbrace\relax +\let\indexatchar\relax +\let\indexbackslash\relax + +{\catcode`\@=0 +\catcode`\\=13 + @gdef@backslashdisappear{@def\{}} +} + +{ +\catcode`\<=13 +\catcode`\-=13 +\catcode`\`=13 + \gdef\indexnonalnumdisappear{% + \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax\else + % @set txiindexlquoteignore makes us ignore left quotes in the sort term. + % (Introduced for FSFS 2nd ed.) + \let`=\empty + \fi + % + \expandafter\ifx\csname SETtxiindexbackslashignore\endcsname\relax\else + \backslashdisappear + \fi + % + \expandafter\ifx\csname SETtxiindexhyphenignore\endcsname\relax\else + \def-{}% + \fi + \expandafter\ifx\csname SETtxiindexlessthanignore\endcsname\relax\else + \def<{}% + \fi + \expandafter\ifx\csname SETtxiindexatsignignore\endcsname\relax\else + \def\@{}% + \fi + } + + \gdef\indexnonalnumreappear{% + \let-\normaldash + \let<\normalless + } +} + + % \indexnofonts is used when outputting the strings to sort the index % by, and when constructing control sequence names. It eliminates all % control sequences and just writes whatever the best ASCII sort string @@ -4608,12 +5095,11 @@ end % \def\indexnofonts{% % Accent commands should become @asis. - \def\definedummyaccent##1{\let##1\asis}% + \def\commondummyaccent##1{\let##1\asis}% % We can just ignore other control letters. - \def\definedummyletter##1{\let##1\empty}% + \def\commondummyletter##1{\let##1\empty}% % All control words become @asis by default; overrides below. - \let\definedummyword\definedummyaccent - % + \let\commondummyword\commondummyaccent \commondummiesnofonts % % Don't no-op \tt, since it isn't a user-level command @@ -4626,14 +5112,10 @@ end \def\_{\normalunderscore}% \def\-{}% @- shouldn't affect sorting % - % Unfortunately, texindex is not prepared to handle braces in the - % content at all. So for index sorting, we map @{ and @} to strings - % starting with |, since that ASCII character is between ASCII { and }. - \def\{{|a}% - \def\lbracechar{|a}% - % - \def\}{|b}% - \def\rbracechar{|b}% + \uccode`\1=`\{ \uppercase{\def\{{1}}% + \uccode`\1=`\} \uppercase{\def\}{1}}% + \let\lbracechar\{% + \let\rbracechar\}% % % Non-English letters. \def\AA{AA}% @@ -4642,7 +5124,7 @@ end \def\L{L}% \def\OE{OE}% \def\O{O}% - \def\TH{ZZZ}% + \def\TH{TH}% \def\aa{aa}% \def\ae{ae}% \def\dh{dzz}% @@ -4654,45 +5136,45 @@ end \def\o{o}% \def\questiondown{?}% \def\ss{ss}% - \def\th{zzz}% + \def\th{th}% % \def\LaTeX{LaTeX}% \def\TeX{TeX}% % - % Assorted special characters. - % (The following {} will end up in the sort string, but that's ok.) - \def\arrow{->}% - \def\bullet{bullet}% - \def\comma{,}% - \def\copyright{copyright}% - \def\dots{...}% - \def\enddots{...}% - \def\equiv{==}% - \def\error{error}% - \def\euro{euro}% - \def\expansion{==>}% - \def\geq{>=}% - \def\guillemetleft{<<}% - \def\guillemetright{>>}% - \def\guilsinglleft{<}% - \def\guilsinglright{>}% - \def\leq{<=}% - \def\minus{-}% - \def\point{.}% - \def\pounds{pounds}% - \def\print{-|}% - \def\quotedblbase{"}% - \def\quotedblleft{"}% - \def\quotedblright{"}% - \def\quoteleft{`}% - \def\quoteright{'}% - \def\quotesinglbase{,}% - \def\registeredsymbol{R}% - \def\result{=>}% - \def\textdegree{o}% - % - \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax - \else \indexlquoteignore \fi + % Assorted special characters. \defglyph gives the control sequence a + % definition that removes the {} that follows its use. + \defglyph\atchar{@}% + \defglyph\arrow{->}% + \defglyph\bullet{bullet}% + \defglyph\comma{,}% + \defglyph\copyright{copyright}% + \defglyph\dots{...}% + \defglyph\enddots{...}% + \defglyph\equiv{==}% + \defglyph\error{error}% + \defglyph\euro{euro}% + \defglyph\expansion{==>}% + \defglyph\geq{>=}% + \defglyph\guillemetleft{<<}% + \defglyph\guillemetright{>>}% + \defglyph\guilsinglleft{<}% + \defglyph\guilsinglright{>}% + \defglyph\leq{<=}% + \defglyph\lbracechar{\{}% + \defglyph\minus{-}% + \defglyph\point{.}% + \defglyph\pounds{pounds}% + \defglyph\print{-|}% + \defglyph\quotedblbase{"}% + \defglyph\quotedblleft{"}% + \defglyph\quotedblright{"}% + \defglyph\quoteleft{`}% + \defglyph\quoteright{'}% + \defglyph\quotesinglbase{,}% + \defglyph\rbracechar{\}}% + \defglyph\registeredsymbol{R}% + \defglyph\result{=>}% + \defglyph\textdegree{o}% % % We need to get rid of all macros, leaving only the arguments (if present). % Of course this is not nearly correct, but it is the best we can do for now. @@ -4705,75 +5187,200 @@ end % goes to end-of-line is not handled. % \macrolist + \let\value\indexnofontsvalue } +\def\defglyph#1#2{\def#1##1{#2}} % see above + -% Undocumented (for FSFS 2nd ed.): @set txiindexlquoteignore makes us -% ignore left quotes in the sort term. -{\catcode`\`=\active - \gdef\indexlquoteignore{\let`=\empty}} -\let\indexbackslash=0 %overridden during \printindex. -\let\SETmarginindex=\relax % put index entries in margin (undocumented)? -% Most index entries go through here, but \dosubind is the general case. % #1 is the index name, #2 is the entry text. -\def\doind#1#2{\dosubind{#1}{#2}{}} - -% Workhorse for all \fooindexes. -% #1 is name of index, #2 is stuff to put there, #3 is subentry -- -% empty if called from \doind, as we usually are (the main exception -% is with most defuns, which call us directly). -% -\def\dosubind#1#2#3{% +\def\doind#1#2{% \iflinks {% - % Store the main index entry text (including the third arg). - \toks0 = {#2}% - % If third arg is present, precede it with a space. - \def\thirdarg{#3}% - \ifx\thirdarg\empty \else - \toks0 = \expandafter{\the\toks0 \space #3}% - \fi % + \requireopenindexfile{#1}% \edef\writeto{\csname#1indfile\endcsname}% % - \safewhatsit\dosubindwrite + \def\indextext{#2}% + \safewhatsit\doindwrite }% \fi } -% Write the entry in \toks0 to the index file: +% Check if an index file has been opened, and if not, open it. +\def\requireopenindexfile#1{% +\ifnum\csname #1indfile\endcsname=0 + \expandafter\newwrite \csname#1indfile\endcsname + \edef\suffix{#1}% + % A .fls suffix would conflict with the file extension for the output + % of -recorder, so use .f1s instead. + \ifx\suffix\indexisfl\def\suffix{f1}\fi + % Open the file + \immediate\openout\csname#1indfile\endcsname \jobname.\suffix + % Using \immediate above here prevents an object entering into the current + % box, which could confound checks such as those in \safewhatsit for + % preceding skips. + \typeout{Writing index file \jobname.\suffix}% +\fi} +\def\indexisfl{fl} + +% Definition for writing index entry sort key. +{ +\catcode`\-=13 +\gdef\indexwritesortas{% + \begingroup + \indexnonalnumreappear + \indexwritesortasxxx} +\gdef\indexwritesortasxxx#1{% + \xdef\indexsortkey{#1}\endgroup} +} + +\def\indexwriteseealso#1{ + \gdef\pagenumbertext{\string\seealso{#1}}% +} +\def\indexwriteseeentry#1{ + \gdef\pagenumbertext{\string\seeentry{#1}}% +} + +% The default definitions +\def\sortas#1{}% +\def\seealso#1{\i{\putwordSeeAlso}\ #1}% for sorted index file only +\def\putwordSeeAlso{See also} +\def\seeentry#1{\i{\putwordSee}\ #1}% for sorted index file only + + +% Given index entry text like "aaa @subentry bbb @sortas{ZZZ}": +% * Set \bracedtext to "{aaa}{bbb}" +% * Set \fullindexsortkey to "aaa @subentry ZZZ" +% * If @seealso occurs, set \pagenumbertext % -\def\dosubindwrite{% - % Put the index entry in the margin if desired. - \ifx\SETmarginindex\relax\else - \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% +\def\splitindexentry#1{% + \gdef\fullindexsortkey{}% + \xdef\bracedtext{}% + \def\sep{}% + \def\seealso##1{}% + \def\seeentry##1{}% + \expandafter\doindexsegment#1\subentry\finish\subentry +} + +% append the results from the next segment +\def\doindexsegment#1\subentry{% + \def\segment{#1}% + \ifx\segment\isfinish + \else + % + % Fully expand the segment, throwing away any @sortas directives, and + % trim spaces. + \edef\trimmed{\segment}% + \edef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}% + % + \xdef\bracedtext{\bracedtext{\trimmed}}% + % + % Get the string to sort by. Process the segment with all + % font commands turned off. + \bgroup + \let\sortas\indexwritesortas + \let\seealso\indexwriteseealso + \let\seeentry\indexwriteseeentry + \indexnofonts + % The braces around the commands are recognized by texindex. + \def\lbracechar{{\string\indexlbrace}}% + \def\rbracechar{{\string\indexrbrace}}% + \let\{=\lbracechar + \let\}=\rbracechar + \def\@{{\string\indexatchar}}% + \def\atchar##1{\@}% + \def\backslashchar{{\string\indexbackslash}}% + \uccode`\~=`\\ \uppercase{\let~\backslashchar}% + % + \let\indexsortkey\empty + \global\let\pagenumbertext\empty + % Execute the segment and throw away the typeset output. This executes + % any @sortas or @seealso commands in this segment. + \setbox\dummybox = \hbox{\segment}% + \ifx\indexsortkey\empty{% + \indexnonalnumdisappear + \xdef\trimmed{\segment}% + \xdef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}% + \xdef\indexsortkey{\trimmed}% + \ifx\indexsortkey\empty\xdef\indexsortkey{ }\fi + }\fi + % + % Append to \fullindexsortkey. + \edef\tmp{\gdef\noexpand\fullindexsortkey{% + \fullindexsortkey\sep\indexsortkey}}% + \tmp + \egroup + \def\sep{\subentry}% + % + \expandafter\doindexsegment + \fi +} +\def\isfinish{\finish}% +\newbox\dummybox % used above + +\let\subentry\relax + +% Use \ instead of @ in index files. To support old texi2dvi and texindex. +% This works without changing the escape character used in the toc or aux +% files because the index entries are fully expanded here, and \string uses +% the current value of \escapechar. +\def\escapeisbackslash{\escapechar=`\\} + +% Use \ in index files by default. texi2dvi didn't support @ as the escape +% character (as it checked for "\entry" in the files, and not "@entry"). When +% the new version of texi2dvi has had a chance to become more prevalent, then +% the escape character can change back to @ again. This should be an easy +% change to make now because both @ and \ are only used as escape characters in +% index files, never standing for themselves. +% +\set txiindexescapeisbackslash + +% Write the entry in \indextext to the index file. +% +\def\doindwrite{% + \maybemarginindex + % + \atdummies + % + \expandafter\ifx\csname SETtxiindexescapeisbackslash\endcsname\relax\else + \escapeisbackslash \fi % - % Remember, we are within a group. - \indexdummies % Must do this here, since \bf, etc expand at this stage - \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now - % so it will be output as is; and it will print as backslash. + % For texindex which always views { and } as separators. + \def\{{\lbracechar{}}% + \def\}{\rbracechar{}}% + \uccode`\~=`\\ \uppercase{\def~{\backslashchar{}}}% % - % Process the index entry with all font commands turned off, to - % get the string to sort by. - {\indexnofonts - \edef\temp{\the\toks0}% need full expansion - \xdef\indexsorttmp{\temp}% - }% + % Split the entry into primary entry and any subentries, and get the index + % sort key. + \splitindexentry\indextext % % Set up the complete index entry, with both the sort key and % the original text, including any font commands. We write % three arguments to \entry to the .?? file (four in the % subentry case), texindex reduces to two when writing the .??s % sorted result. + % \edef\temp{% \write\writeto{% - \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% + \string\entry{\fullindexsortkey}% + {\ifx\pagenumbertext\empty\noexpand\folio\else\pagenumbertext\fi}% + \bracedtext}% }% \temp } +% Put the index entry in the margin if desired (undocumented). +\def\maybemarginindex{% + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \relax\indextext}}% + \fi +} +\let\SETmarginindex=\relax + + % Take care of unwanted page breaks/skips around a whatsit: % % If a skip is the last thing on the list now, preserve it @@ -4860,9 +5467,14 @@ end % \entry {topic}{pagelist} % for a topic that is used without subtopics % \primary {topic} +% \entry {topic}{} % for the beginning of a topic that is used with subtopics % \secondary {subtopic}{pagelist} % for each subtopic. +% \secondary {subtopic}{} +% for a subtopic with sub-subtopics +% \tertiary {subtopic}{subsubtopic}{pagelist} +% for each sub-subtopic. % Define the user-accessible indexing commands % @findex, @vindex, @kindex, @cindex. @@ -4874,11 +5486,6 @@ end \def\tindex {\tpindex} \def\pindex {\pgindex} -\def\cindexsub {\begingroup\obeylines\cindexsub} -{\obeylines % -\gdef\cindexsub "#1" #2^^M{\endgroup % -\dosubind{cp}{#2}{#1}}} - % Define the macros used in formatting output of the sorted index material. % @printindex causes a particular index (the ??s file) to get printed. @@ -4892,57 +5499,123 @@ end \plainfrenchspacing \everypar = {}% don't want the \kern\-parindent from indentation suppression. % + % See comment in \requireopenindexfile. + \def\indexname{#1}\ifx\indexname\indexisfl\def\indexname{f1}\fi + % % See if the index file exists and is nonempty. - % Change catcode of @ here so that if the index file contains - % \initial {@} - % as its first line, TeX doesn't complain about mismatched braces - % (because it thinks @} is a control sequence). - \catcode`\@ = 11 - \openin 1 \jobname.#1s + \openin 1 \jobname.\indexname s \ifeof 1 % \enddoublecolumns gets confused if there is no text in the index, % and it loses the chapter title and the aux file entries for the % index. The easiest way to prevent this problem is to make sure % there is some text. \putwordIndexNonexistent + \typeout{No file \jobname.\indexname s.}% \else - % % If the index file exists but is empty, then \openin leaves \ifeof % false. We have to make TeX try to read something from the file, so % it can discover if there is anything in it. - \read 1 to \temp + \read 1 to \thisline \ifeof 1 \putwordIndexIsEmpty \else - % Index files are almost Texinfo source, but we use \ as the escape - % character. It would be better to use @, but that's too big a change - % to make right now. - \def\indexbackslash{\backslashcurfont}% - \catcode`\\ = 0 - \escapechar = `\\ - \begindoublecolumns - \input \jobname.#1s - \enddoublecolumns + \expandafter\printindexzz\thisline\relax\relax\finish% \fi \fi \closein 1 \endgroup} +% If the index file starts with a backslash, forgo reading the index +% file altogether. If somebody upgrades texinfo.tex they may still have +% old index files using \ as the escape character. Reading this would +% at best lead to typesetting garbage, at worst a TeX syntax error. +\def\printindexzz#1#2\finish{% + \expandafter\ifx\csname SETtxiindexescapeisbackslash\endcsname\relax + \uccode`\~=`\\ \uppercase{\if\noexpand~}\noexpand#1 + \expandafter\ifx\csname SETtxiskipindexfileswithbackslash\endcsname\relax +\errmessage{% +ERROR: A sorted index file in an obsolete format was skipped. +To fix this problem, please upgrade your version of 'texi2dvi' +or 'texi2pdf' to that at . +If you are using an old version of 'texindex' (part of the Texinfo +distribution), you may also need to upgrade to a newer version (at least 6.0). +You may be able to typeset the index if you run +'texindex \jobname.\indexname' yourself. +You could also try setting the 'txiindexescapeisbackslash' flag by +running a command like +'texi2dvi -t "@set txiindexescapeisbackslash" \jobname.texi'. If you do +this, Texinfo will try to use index files in the old format. +If you continue to have problems, deleting the index files and starting again +might help (with 'rm \jobname.?? \jobname.??s')% +}% + \else + (Skipped sorted index file in obsolete format) + \fi + \else + \begindoublecolumns + \input \jobname.\indexname s + \enddoublecolumns + \fi + \else + \begindoublecolumns + \catcode`\\=0\relax + \catcode`\@=12\relax + \input \jobname.\indexname s + \enddoublecolumns + \fi +} + % These macros are used by the sorted index file itself. % Change them to control the appearance of the index. -\def\initial#1{{% - % Some minor font changes for the special characters. - \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt +{\catcode`\/=13 \catcode`\-=13 \catcode`\^=13 \catcode`\~=13 \catcode`\_=13 +\catcode`\|=13 \catcode`\<=13 \catcode`\>=13 \catcode`\+=13 \catcode`\"=13 +\catcode`\$=3 +\gdef\initialglyphs{% + % special control sequences used in the index sort key + \let\indexlbrace\{% + \let\indexrbrace\}% + \let\indexatchar\@% + \def\indexbackslash{\math{\backslash}}% % + % Some changes for non-alphabetic characters. Using the glyphs from the + % math fonts looks more consistent than the typewriter font used elsewhere + % for these characters. + \uccode`\~=`\\ \uppercase{\def~{\math{\backslash}}} + % + % In case @\ is used for backslash + \uppercase{\let\\=~} + % Can't get bold backslash so don't use bold forward slash + \catcode`\/=13 + \def/{{\secrmnotbold \normalslash}}% + \def-{{\normaldash\normaldash}}% en dash `--' + \def^{{\chapbf \normalcaret}}% + \def~{{\chapbf \normaltilde}}% + \def\_{% + \leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }% + \def|{$\vert$}% + \def<{$\less$}% + \def>{$\gtr$}% + \def+{$\normalplus$}% +}} + +\def\initial{% + \bgroup + \initialglyphs + \initialx +} + +\def\initialx#1{% % Remove any glue we may have, we'll be inserting our own. \removelastskip % % We like breaks before the index initials, so insert a bonus. + % The glue before the bonus allows a little bit of space at the + % bottom of a column to reduce an increase in inter-line spacing. \nobreak - \vskip 0pt plus 3\baselineskip - \penalty 0 - \vskip 0pt plus -3\baselineskip + \vskip 0pt plus 5\baselineskip + \penalty -300 + \vskip 0pt plus -5\baselineskip % % Typeset the initial. Making this add up to a whole number of % baselineskips increases the chance of the dots lining up from column @@ -4950,24 +5623,24 @@ end % we need before each entry, but it's better. % % No shrink because it confuses \balancecolumns. - \vskip 1.67\baselineskip plus .5\baselineskip - \leftline{\secbf #1}% + \vskip 1.67\baselineskip plus 1\baselineskip + \leftline{\secfonts \kern-0.05em \secbf #1}% + % \secfonts is inside the argument of \leftline so that the change of + % \baselineskip will not affect any glue inserted before the vbox that + % \leftline creates. % Do our best not to break after the initial. \nobreak \vskip .33\baselineskip plus .1\baselineskip -}} + \egroup % \initialglyphs +} + +\newdimen\entryrightmargin +\entryrightmargin=0pt % \entry typesets a paragraph consisting of the text (#1), dot leaders, and % then page number (#2) flushed to the right margin. It is used for index % and table of contents entries. The paragraph is indented by \leftskip. % -% A straightforward implementation would start like this: -% \def\entry#1#2{... -% But this freezes the catcodes in the argument, and can cause problems to -% @code, which sets - active. This problem was fixed by a kludge--- -% ``-'' was active throughout whole index, but this isn't really right. -% The right solution is to prevent \entry from swallowing the whole text. -% --kasal, 21nov03 \def\entry{% \begingroup % @@ -4975,38 +5648,14 @@ end % affect previous text. \par % - % Do not fill out the last line with white space. - \parfillskip = 0in - % % No extra space above this paragraph. \parskip = 0in % - % Do not prefer a separate line ending with a hyphen to fewer lines. - \finalhyphendemerits = 0 - % - % \hangindent is only relevant when the entry text and page number - % don't both fit on one line. In that case, bob suggests starting the - % dots pretty far over on the line. Unfortunately, a large - % indentation looks wrong when the entry text itself is broken across - % lines. So we use a small indentation and put up with long leaders. - % - % \hangafter is reset to 1 (which is the value we want) at the start - % of each paragraph, so we need not do anything with that. - \hangindent = 2em - % - % When the entry text needs to be broken, just fill out the first line - % with blank space. - \rightskip = 0pt plus1fil - % - % A bit of stretch before each entry for the benefit of balancing - % columns. - \vskip 0pt plus1pt - % % When reading the text of entry, convert explicit line breaks % from @* into spaces. The user might give these in long section % titles, for instance. \def\*{\unskip\space\ignorespaces}% - \def\entrybreak{\hfil\break}% + \def\entrybreak{\hfil\break}% An undocumented command % % Swallow the left brace of the text (first parameter): \afterassignment\doentry @@ -5014,85 +5663,148 @@ end } \def\entrybreak{\unskip\space\ignorespaces}% \def\doentry{% + % Save the text of the entry + \global\setbox\boxA=\hbox\bgroup \bgroup % Instead of the swallowed brace. \noindent \aftergroup\finishentry % And now comes the text of the entry. + % Not absorbing as a macro argument reduces the chance of problems + % with catcodes occurring. } -\def\finishentry#1{% - % #1 is the page number. - % - % The following is kludged to not output a line of dots in the index if - % there are no page numbers. The next person who breaks this will be - % cursed by a Unix daemon. - \setbox\boxA = \hbox{#1}% - \ifdim\wd\boxA = 0pt - \ % - \else +{\catcode`\@=11 +\gdef\finishentry#1{% + \egroup % end box A + \dimen@ = \wd\boxA % Length of text of entry + \global\setbox\boxA=\hbox\bgroup + \unhbox\boxA + % #1 is the page number. % - % If we must, put the page number on a line of its own, and fill out - % this line with blank space. (The \hfil is overwhelmed with the - % fill leaders glue in \indexdotfill if the page number does fit.) - \hfil\penalty50 - \null\nobreak\indexdotfill % Have leaders before the page number. - % - % The `\ ' here is removed by the implicit \unskip that TeX does as - % part of (the primitive) \par. Without it, a spurious underfull - % \hbox ensues. - \ifpdf - \pdfgettoks#1.% - \ \the\toksA + % Get the width of the page numbers, and only use + % leaders if they are present. + \global\setbox\boxB = \hbox{#1}% + \ifdim\wd\boxB = 0pt + \null\nobreak\hfill\ % \else - \ #1% + % + \null\nobreak\indexdotfill % Have leaders before the page number. + % + \ifpdforxetex + \pdfgettoks#1.% + \hskip\skip\thinshrinkable\the\toksA + \else + \hskip\skip\thinshrinkable #1% + \fi \fi + \egroup % end \boxA + \ifdim\wd\boxB = 0pt + \noindent\unhbox\boxA\par + \nobreak + \else\bgroup + % We want the text of the entries to be aligned to the left, and the + % page numbers to be aligned to the right. + % + \parindent = 0pt + \advance\leftskip by 0pt plus 1fil + \advance\leftskip by 0pt plus -1fill + \rightskip = 0pt plus -1fil + \advance\rightskip by 0pt plus 1fill + % Cause last line, which could consist of page numbers on their own + % if the list of page numbers is long, to be aligned to the right. + \parfillskip=0pt plus -1fill + % + \advance\rightskip by \entryrightmargin + % Determine how far we can stretch into the margin. + % This allows, e.g., "Appendix H GNU Free Documentation License" to + % fit on one line in @letterpaper format. + \ifdim\entryrightmargin>2.1em + \dimen@i=2.1em + \else + \dimen@i=0em + \fi + \advance \parfillskip by 0pt minus 1\dimen@i + % + \dimen@ii = \hsize + \advance\dimen@ii by -1\leftskip + \advance\dimen@ii by -1\entryrightmargin + \advance\dimen@ii by 1\dimen@i + \ifdim\wd\boxA > \dimen@ii % If the entry doesn't fit in one line + \ifdim\dimen@ > 0.8\dimen@ii % due to long index text + % Try to split the text roughly evenly. \dimen@ will be the length of + % the first line. + \dimen@ = 0.7\dimen@ + \dimen@ii = \hsize + \ifnum\dimen@>\dimen@ii + % If the entry is too long (for example, if it needs more than + % two lines), use all the space in the first line. + \dimen@ = \dimen@ii + \fi + \advance\leftskip by 0pt plus 1fill % ragged right + \advance \dimen@ by 1\rightskip + \parshape = 2 0pt \dimen@ 0em \dimen@ii + % Ideally we'd add a finite glue at the end of the first line only, + % instead of using \parshape with explicit line lengths, but TeX + % doesn't seem to provide a way to do such a thing. + % + % Indent all lines but the first one. + \advance\leftskip by 1em + \advance\parindent by -1em + \fi\fi + \indent % start paragraph + \unhbox\boxA + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % Word spacing - no stretch + \spaceskip=\fontdimen2\font minus \fontdimen4\font + % + \linepenalty=1000 % Discourage line breaks. + \hyphenpenalty=5000 % Discourage hyphenation. + % + \par % format the paragraph + \egroup % The \vbox \fi - \par \endgroup -} +}} + +\newskip\thinshrinkable +\skip\thinshrinkable=.15em minus .15em % Like plain.tex's \dotfill, except uses up at least 1 em. +% The filll stretch here overpowers both the fil and fill stretch to push +% the page number to the right. \def\indexdotfill{\cleaders - \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1fill} + \hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 1em plus 1filll} + \def\primary #1{\line{#1\hfil}} -\newskip\secondaryindent \secondaryindent=0.5cm -\def\secondary#1#2{{% - \parfillskip=0in - \parskip=0in - \hangindent=1in - \hangafter=1 - \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill - \ifpdf - \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. - \else - #2 - \fi - \par -}} +\def\secondary{\indententry{0.5cm}} +\def\tertiary{\indententry{1cm}} + +\def\indententry#1#2#3{% + \bgroup + \leftskip=#1 + \entry{#2}{#3}% + \egroup +} % Define two-column mode, which we use to typeset indexes. % Adapted from the TeXbook, page 416, which is to say, % the manmac.tex format used to print the TeXbook itself. -\catcode`\@=11 +\catcode`\@=11 % private names \newbox\partialpage \newdimen\doublecolumnhsize \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % If not much space left on page, start a new page. + \ifdim\pagetotal>0.8\vsize\vfill\eject\fi + % % Grab any single-column material above us. \output = {% - % - % Here is a possibility not foreseen in manmac: if we accumulate a - % whole lot of material, we might end up calling this \output - % routine twice in a row (see the doublecol-lose test, which is - % essentially a couple of indexes with @setchapternewpage off). In - % that case we just ship out what is in \partialpage with the normal - % output routine. Generally, \partialpage will be empty when this - % runs and this will be a no-op. See the indexspread.tex test case. - \ifvoid\partialpage \else - \onepageout{\pagecontents\partialpage}% - \fi + \savetopmark % \global\setbox\partialpage = \vbox{% % Unvbox the main output page. @@ -5126,27 +5838,31 @@ end \divide\doublecolumnhsize by 2 \hsize = \doublecolumnhsize % - % Double the \vsize as well. (We don't need a separate register here, - % since nobody clobbers \vsize.) - \vsize = 2\vsize -} - -% The double-column output routine for all double-column pages except -% the last. -% -\def\doublecolumnout{% - \splittopskip=\topskip \splitmaxdepth=\maxdepth % Get the available space for the double columns -- the normal % (undoubled) page height minus any material left over from the % previous page. + \advance\vsize by -\ht\partialpage + \vsize = 2\vsize + % + % For the benefit of balancing columns + \advance\baselineskip by 0pt plus 0.5pt +} + +% The double-column output routine for all double-column pages except +% the last, which is done by \balancecolumns. +% +\def\doublecolumnout{% + % + \savetopmark + \splittopskip=\topskip \splitmaxdepth=\maxdepth \dimen@ = \vsize \divide\dimen@ by 2 - \advance\dimen@ by -\ht\partialpage % % box0 will be the left-hand column, box2 the right. - \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ - \onepageout\pagesofar - \unvbox255 + \setbox0=\vsplit\PAGE to\dimen@ \setbox2=\vsplit\PAGE to\dimen@ + \global\advance\vsize by 2\ht\partialpage + \onepageout\pagesofar % empty except for the first time we are called + \unvbox\PAGE \penalty\outputpenalty } % @@ -5157,10 +5873,11 @@ end % \hsize = \doublecolumnhsize \wd0=\hsize \wd2=\hsize - \hbox to\pagewidth{\box0\hfil\box2}% + \hbox to\txipagewidth{\box0\hfil\box2}% } -% -% All done with double columns. + + +% Finished with double columns. \def\enddoublecolumns{% % The following penalty ensures that the page builder is exercised % _before_ we change the output routine. This is necessary in the @@ -5183,7 +5900,7 @@ end % goal. When TeX sees \eject from below which follows the final % section, it invokes the new output routine that we've set after % \balancecolumns below; \onepageout will try to fit the two columns - % and the final section into the vbox of \pageheight (see + % and the final section into the vbox of \txipageheight (see % \pagebody), causing an overfull box. % % Note that glue won't work here, because glue does not exercise the @@ -5191,53 +5908,88 @@ end \penalty0 % \output = {% - % Split the last of the double-column material. Leave it on the - % current page, no automatic page break. + % Split the last of the double-column material. + \savetopmark \balancecolumns - % - % If we end up splitting too much material for the current page, - % though, there will be another page break right after this \output - % invocation ends. Having called \balancecolumns once, we do not + }% + \eject % call the \output just set + \ifdim\pagetotal=0pt + % Having called \balancecolumns once, we do not % want to call it again. Therefore, reset \output to its normal - % definition right away. (We hope \balancecolumns will never be - % called on to balance too much material, but if it is, this makes - % the output somewhat more palatable.) - \global\output = {\onepageout{\pagecontents\PAGE}}% - }% - \eject - \endgroup % started in \begindoublecolumns - % - % \pagegoal was set to the doubled \vsize above, since we restarted - % the current page. We're now back to normal single-column - % typesetting, so reset \pagegoal to the normal \vsize (after the - % \endgroup where \vsize got restored). - \pagegoal = \vsize + % definition right away. + \global\output=\expandafter{\the\defaultoutput} + % + \endgroup % started in \begindoublecolumns + % Leave the double-column material on the current page, no automatic + % page break. + \box\balancedcolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize. + \global\vsize = \txipageheight % + \pagegoal = \txipageheight % + \else + % We had some left-over material. This might happen when \doublecolumnout + % is called in \balancecolumns. Try again. + \expandafter\enddoublecolumns + \fi } +\newbox\balancedcolumns +\setbox\balancedcolumns=\vbox{shouldnt see this}% % -% Called at the end of the double column material. +% Only called for the last of the double column material. \doublecolumnout +% does the others. \def\balancecolumns{% - \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \setbox0 = \vbox{\unvbox\PAGE}% like \box255 but more efficient, see p.120. \dimen@ = \ht0 - \advance\dimen@ by \topskip - \advance\dimen@ by-\baselineskip - \divide\dimen@ by 2 % target to split to - %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% - \splittopskip = \topskip - % Loop until we get a decent breakpoint. - {% - \vbadness = 10000 - \loop - \global\setbox3 = \copy0 - \global\setbox1 = \vsplit3 to \dimen@ - \ifdim\ht3>\dimen@ - \global\advance\dimen@ by 1pt - \repeat - }% - %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% - \setbox0=\vbox to\dimen@{\unvbox1}% - \setbox2=\vbox to\dimen@{\unvbox3}% + \ifdim\dimen@<7\baselineskip + % Don't split a short final column in two. + \setbox2=\vbox{}% + \global\setbox\balancedcolumns=\vbox{\pagesofar}% + \else + % double the leading vertical space + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + \dimen@ii = \dimen@ + \splittopskip = \topskip + % Loop until left column is at least as high as the right column. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht1<\ht3 + \global\advance\dimen@ by 1pt + \repeat + }% + % Now the left column is in box 1, and the right column in box 3. + % + % Check whether the left column has come out higher than the page itself. + % (Note that we have doubled \vsize for the double columns, so + % the actual height of the page is 0.5\vsize). + \ifdim2\ht1>\vsize + % It appears that we have been called upon to balance too much material. + % Output some of it with \doublecolumnout, leaving the rest on the page. + \setbox\PAGE=\box0 + \doublecolumnout + \else + % Compare the heights of the two columns. + \ifdim4\ht1>5\ht3 + % Column heights are too different, so don't make their bottoms + % flush with each other. + \setbox2=\vbox to \ht1 {\unvbox3\vfill}% + \setbox0=\vbox to \ht1 {\unvbox1\vfill}% + \else + % Make column bottoms flush with each other. + \setbox2=\vbox to\ht1{\unvbox3\unskip}% + \setbox0=\vbox to\ht1{\unvbox1\unskip}% + \fi + \global\setbox\balancedcolumns=\vbox{\pagesofar}% + \fi + \fi % - \pagesofar } \catcode`\@ = \other @@ -5252,10 +6004,14 @@ end \null \vskip.3\vsize % move it down on the page a bit \begingroup - \noindent \titlefonts\rmisbold #1\par % the text + \noindent \titlefonts\rm #1\par % the text \let\lastnode=\empty % no node to associate with \writetocentry{part}{#1}{}% but put it in the toc \headingsoff % no headline or footline on the part page + % This outputs a mark at the end of the page that clears \thischapter + % and \thissection, as is done in \startcontents. + \let\pchapsepmacro\relax + \chapmacro{}{Yomitfromtoc}{}% \chapoddpage \endgroup } @@ -5329,11 +6085,9 @@ end % @raisesections: treat @section as chapter, @subsection as section, etc. \def\raisesections{\global\advance\secbase by -1} -\let\up=\raisesections % original BFox name % @lowersections: treat @chapter as section, @section as subsection, etc. \def\lowersections{\global\advance\secbase by 1} -\let\down=\lowersections % original BFox name % we only have subsub. \chardef\maxseclevel = 3 @@ -5500,9 +6254,6 @@ end % @centerchap is like @unnumbered, but the heading is centered. \outer\parseargdef\centerchap{% - % Well, we could do the following in a group, but that would break - % an assumption that \chapmacro is called at the outermost level. - % Thus we are safer this way: --kasal, 24feb04 \let\centerparametersmaybe = \centerparameters \unnmhead0{#1}% \let\centerparametersmaybe = \relax @@ -5512,7 +6263,7 @@ end \let\top\unnumbered % Sections. -% +% \outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz \def\seczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 @@ -5535,7 +6286,7 @@ end } % Subsections. -% +% % normally calls numberedsubseczzz: \outer\parseargdef\numberedsubsec{\numhead2{#1}} \def\numberedsubseczzz#1{% @@ -5560,7 +6311,7 @@ end } % Subsubsections. -% +% % normally numberedsubsubseczzz: \outer\parseargdef\numberedsubsubsec{\numhead3{#1}} \def\numberedsubsubseczzz#1{% @@ -5626,7 +6377,11 @@ end % Define plain chapter starts, and page on/off switching for it. \def\chapbreak{\dobreak \chapheadingskip {-4000}} + +% Start a new page \def\chappager{\par\vfill\supereject} + +% \chapoddpage - start on an odd page for a new chapter % Because \domark is called before \chapoddpage, the filler page will % get the headings for the next chapter, which is wrong. But we don't % care -- we just disable all headings on the filler page. @@ -5641,7 +6396,7 @@ end \fi } -\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} +\parseargdef\setchapternewpage{\csname CHAPPAG#1\endcsname} \def\CHAPPAGoff{% \global\let\contentsalignmacro = \chappager @@ -5662,33 +6417,37 @@ end \CHAPPAGon -% Chapter opening. +% \chapmacro - Chapter opening. % % #1 is the text, #2 is the section type (Ynumbered, Ynothing, % Yappendix, Yomitfromtoc), #3 the chapter number. +% Not used for @heading series. % % To test against our argument. \def\Ynothingkeyword{Ynothing} -\def\Yomitfromtockeyword{Yomitfromtoc} \def\Yappendixkeyword{Yappendix} +\def\Yomitfromtockeyword{Yomitfromtoc} % \def\chapmacro#1#2#3{% + \expandafter\ifx\thisenv\titlepage\else + \checkenv{}% chapters, etc., should not start inside an environment. + \fi % Insert the first mark before the heading break (see notes for \domark). - \let\prevchapterdefs=\lastchapterdefs - \let\prevsectiondefs=\lastsectiondefs - \gdef\lastsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% + \let\prevchapterdefs=\currentchapterdefs + \let\prevsectiondefs=\currentsectiondefs + \gdef\currentsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}% \gdef\thissection{}}% % \def\temptype{#2}% \ifx\temptype\Ynothingkeyword - \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\currentchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% \gdef\thischapter{\thischaptername}}% \else\ifx\temptype\Yomitfromtockeyword - \gdef\lastchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% + \gdef\currentchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}% \gdef\thischapter{}}% \else\ifx\temptype\Yappendixkeyword \toks0={#1}% - \xdef\lastchapterdefs{% + \xdef\currentchapterdefs{% \gdef\noexpand\thischaptername{\the\toks0}% \gdef\noexpand\thischapternum{\appendixletter}% % \noexpand\putwordAppendix avoids expanding indigestible @@ -5699,7 +6458,7 @@ end }% \else \toks0={#1}% - \xdef\lastchapterdefs{% + \xdef\currentchapterdefs{% \gdef\noexpand\thischaptername{\the\toks0}% \gdef\noexpand\thischapternum{\the\chapno}% % \noexpand\putwordChapter avoids expanding indigestible @@ -5719,17 +6478,18 @@ end % % Now the second mark, after the heading break. No break points % between here and the heading. - \let\prevchapterdefs=\lastchapterdefs - \let\prevsectiondefs=\lastsectiondefs + \let\prevchapterdefs=\currentchapterdefs + \let\prevsectiondefs=\currentsectiondefs \domark % {% - \chapfonts \rmisbold + \chapfonts \rm + \let\footnote=\errfootnoteheading % give better error message % - % Have to define \lastsection before calling \donoderef, because the + % Have to define \currentsection before calling \donoderef, because the % xref code eventually uses it. On the other hand, it has to be called % after \pchapsepmacro, or the headline will change too soon. - \gdef\lastsection{#1}% + \gdef\currentsection{#1}% % % Only insert the separating space if we have a chapter/appendix % number, and don't print the unnumbered ``number''. @@ -5777,30 +6537,6 @@ end } -% I don't think this chapter style is supported any more, so I'm not -% updating it with the new noderef stuff. We'll see. --karl, 11aug03. -% -\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} -% -\def\unnchfopen #1{% - \chapoddpage - \vbox{\chapfonts \raggedtitlesettings #1\par}% - \nobreak\bigskip\nobreak -} -\def\chfopen #1#2{\chapoddpage {\chapfonts -\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% -\par\penalty 5000 % -} -\def\centerchfopen #1{% - \chapoddpage - \vbox{\chapfonts \raggedtitlesettings \hfill #1\hfill}% - \nobreak\bigskip \nobreak -} -\def\CHAPFopen{% - \global\let\chapmacro=\chfopen - \global\let\centerchapmacro=\centerchfopen} - - % Section titles. These macros combine the section number parts and % call the generic \sectionheading to do the printing. % @@ -5818,27 +6554,34 @@ end % Print any size, any type, section title. % -% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is -% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the -% section number. +% #1 is the text of the title, +% #2 is the section level (sec/subsec/subsubsec), +% #3 is the section type (Ynumbered, Ynothing, Yappendix, Yomitfromtoc), +% #4 is the section number. % \def\seckeyword{sec} % \def\sectionheading#1#2#3#4{% {% - \checkenv{}% should not be in an environment. - % - % Switch to the right set of fonts. - \csname #2fonts\endcsname \rmisbold - % \def\sectionlevel{#2}% \def\temptype{#3}% % + % It is ok for the @heading series commands to appear inside an + % environment (it's been historically allowed, though the logic is + % dubious), but not the others. + \ifx\temptype\Yomitfromtockeyword\else + \checkenv{}% non-@*heading should not be in an environment. + \fi + \let\footnote=\errfootnoteheading + % + % Switch to the right set of fonts. + \csname #2fonts\endcsname \rm + % % Insert first mark before the heading break (see notes for \domark). - \let\prevsectiondefs=\lastsectiondefs + \let\prevsectiondefs=\currentsectiondefs \ifx\temptype\Ynothingkeyword \ifx\sectionlevel\seckeyword - \gdef\lastsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% + \gdef\currentsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}% \gdef\thissection{\thissectionname}}% \fi \else\ifx\temptype\Yomitfromtockeyword @@ -5846,7 +6589,7 @@ end \else\ifx\temptype\Yappendixkeyword \ifx\sectionlevel\seckeyword \toks0={#1}% - \xdef\lastsectiondefs{% + \xdef\currentsectiondefs{% \gdef\noexpand\thissectionname{\the\toks0}% \gdef\noexpand\thissectionnum{#4}% % \noexpand\putwordSection avoids expanding indigestible @@ -5859,7 +6602,7 @@ end \else \ifx\sectionlevel\seckeyword \toks0={#1}% - \xdef\lastsectiondefs{% + \xdef\currentsectiondefs{% \gdef\noexpand\thissectionname{\the\toks0}% \gdef\noexpand\thissectionnum{#4}% % \noexpand\putwordSection avoids expanding indigestible @@ -5885,28 +6628,28 @@ end % % Now the second mark, after the heading break. No break points % between here and the heading. - \let\prevsectiondefs=\lastsectiondefs + \global\let\prevsectiondefs=\currentsectiondefs \domark % % Only insert the space after the number if we have a section number. \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unn}% - \gdef\lastsection{#1}% + \gdef\currentsection{#1}% \else\ifx\temptype\Yomitfromtockeyword % for @headings -- no section number, don't include in toc, - % and don't redefine \lastsection. + % and don't redefine \currentsection. \setbox0 = \hbox{}% \def\toctype{omit}% \let\sectionlevel=\empty \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{#4\enspace}% \def\toctype{app}% - \gdef\lastsection{#1}% + \gdef\currentsection{#1}% \else \setbox0 = \hbox{#4\enspace}% \def\toctype{num}% - \gdef\lastsection{#1}% + \gdef\currentsection{#1}% \fi\fi\fi % % Write the toc entry (before \donoderef). See comments in \chapmacro. @@ -5996,7 +6739,9 @@ end % 1 and 2 (the page numbers aren't printed), and so are the first % two pages of the document. Thus, we'd have two destinations named % `1', and two named `2'. - \ifpdf \global\pdfmakepagedesttrue \fi + \ifpdforxetex + \global\pdfmakepagedesttrue + \fi } @@ -6045,7 +6790,7 @@ end \savepageno = \pageno \begingroup % Set up to handle contents files properly. \raggedbottom % Worry more about breakpoints than the bottom. - \advance\hsize by -\contentsrightmargin % Don't use the full line length. + \entryrightmargin=\contentsrightmargin % Don't use the full line length. % % Roman numerals for page numbers. \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi @@ -6139,7 +6884,15 @@ end % exist, with an empty box. Let's hope all the numbers have the same width. % Also ignore the page number, which is conventionally not printed. \def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}} -\def\partentry#1#2#3#4{\dochapentry{\numeralbox\labelspace#1}{}} +\def\partentry#1#2#3#4{% + % Add stretch and a bonus for breaking the page before the part heading. + % This reduces the chance of the page being broken immediately after the + % part heading, before a following chapter heading. + \vskip 0pt plus 5\baselineskip + \penalty-300 + \vskip 0pt plus -5\baselineskip + \dochapentry{\numeralbox\labelspace#1}{}% +} % % Parts, in the short toc. \def\shortpartentry#1#2#3#4{% @@ -6150,7 +6903,7 @@ end % Chapters, in the main contents. \def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} -% + % Chapters, in the short toc. % See comments in \dochapentry re vbox and related settings. \def\shortchapentry#1#2#3#4{% @@ -6165,7 +6918,7 @@ end \setbox0 = \hbox{\putwordAppendix{} M}% \hbox to \wd0{\putwordAppendix{} #1\hss}} % -\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} +\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\hskip.7em#1}{#4}} % Unnumbered chapters. \def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} @@ -6198,6 +6951,8 @@ end \def\dochapentry#1#2{% \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip \begingroup + % Move the page numbers slightly to the right + \advance\entryrightmargin by -0.05em \chapentryfonts \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup @@ -6252,14 +7007,14 @@ end \catcode `\|=\other \catcode `\<=\other \catcode `\>=\other - \catcode`\`=\other - \catcode`\'=\other - \escapechar=`\\ + \catcode `\`=\other + \catcode `\'=\other % % ' is active in math mode (mathcode"8000). So reset it, and all our % other math active characters (just in case), to plain's definitions. \mathactive % + % Inverse of the list at the beginning of the file. \let\b=\ptexb \let\bullet=\ptexbullet \let\c=\ptexc @@ -6275,9 +7030,11 @@ end \let\+=\tabalign \let\}=\ptexrbrace \let\/=\ptexslash + \let\sp=\ptexsp \let\*=\ptexstar + %\let\sup=\ptexsup % do not redefine, we want @sup to work in math mode \let\t=\ptext - \expandafter \let\csname top\endcsname=\ptextop % outer + \expandafter \let\csname top\endcsname=\ptextop % we've made it outer \let\frenchspacing=\plainfrenchspacing % \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% @@ -6307,6 +7064,24 @@ end % start of the next paragraph will insert \parskip. % \def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz and + % \sectionheading, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + \ifnum\lastpenalty<10000 + % Penalize breaking before the environment, because preceding text + % often leads into it. + \penalty100 + \fi + \vskip\envskipamount + \fi + \fi +}} + +\def\afterenvbreak{{% % =10000 instead of <10000 because of a special case in \itemzzz and % \sectionheading, q.v. \ifnum \lastpenalty=10000 \else @@ -6322,19 +7097,13 @@ end \fi }} -\let\afterenvbreak = \aboveenvbreak - % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will % also clear it, so that its embedded environments do the narrowing again. \let\nonarrowing=\relax % @cartouche ... @end cartouche: draw rectangle w/rounded corners around % environment contents. -\font\circle=lcircle10 -\newdimen\circthick -\newdimen\cartouter\newdimen\cartinner -\newskip\normbskip\newskip\normpskip\newskip\normlskip -\circthick=\fontdimen8\circle + % \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth \def\ctr{{\hskip 6pt\circle\char'010}} @@ -6349,7 +7118,18 @@ end % \newskip\lskip\newskip\rskip +% only require the font if @cartouche is actually used +\def\cartouchefontdefs{% + \font\circle=lcircle10\relax + \circthick=\fontdimen8\circle +} +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip + + \envdef\cartouche{% + \cartouchefontdefs \ifhmode\par\fi % can't be in the midst of a paragraph. \startsavinginserts \lskip=\leftskip \rskip=\rightskip @@ -6361,15 +7141,13 @@ end % side, and for 6pt waste from % each corner char, and rule thickness \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip - % Flag to tell @lisp, etc., not to narrow margin. - \let\nonarrowing = t% % % If this cartouche directly follows a sectioning command, we need the % \parskip glue (backspaced over by default) or the cartouche can % collide with the section heading. \ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi % - \vbox\bgroup + \setbox\groupbox=\vbox\bgroup \baselineskip=0pt\parskip=0pt\lineskip=0pt \carttop \hbox\bgroup @@ -6393,6 +7171,7 @@ end \egroup \cartbot \egroup + \addgroupbox \checkinserts } @@ -6402,7 +7181,7 @@ end \newdimen\nonfillparindent \def\nonfillstart{% \aboveenvbreak - \hfuzz = 12pt % Don't be fussy + \ifdim\hfuzz < 12pt \hfuzz = 12pt \fi % Don't be fussy \sepspaces % Make spaces be word-separators rather than space tokens. \let\par = \lisppar % don't ignore blank lines \obeylines % each line of input is a line of output @@ -6531,7 +7310,7 @@ end % @raggedright does more-or-less normal line breaking but no right % justification. From plain.tex. \envdef\raggedright{% - \rightskip0pt plus2em \spaceskip.3333em \xspaceskip.5em\relax + \rightskip0pt plus2.4em \spaceskip.3333em \xspaceskip.5em\relax } \let\Eraggedright\par @@ -6590,7 +7369,7 @@ end % @indentedblock is like @quotation, but indents only on the left and % has no optional argument. -% +% \makedispenvdef{indentedblock}{\indentedblockstart} % \def\indentedblockstart{% @@ -6693,7 +7472,7 @@ end \nonfillstart \tt % easiest (and conventionally used) font for verbatim % The \leavevmode here is for blank lines. Otherwise, we would - % never \starttabox and the \egroup would end verbatim mode. + % never \starttabbox and the \egroup would end verbatim mode. \def\par{\leavevmode\egroup\box\verbbox\endgraf}% \tabexpand \setupmarkupstyle{verbatim}% @@ -6756,9 +7535,12 @@ end {% \makevalueexpandable \setupverbatim - \indexnofonts % Allow `@@' and other weird things in file names. - \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}% - \input #1 + {% + \indexnofonts % Allow `@@' and other weird things in file names. + \wlog{texinfo.tex: doing @verbatiminclude of #1^^J}% + \edef\tmp{\noexpand\input #1 } + \expandafter + }\tmp \afterenvbreak }% } @@ -6771,7 +7553,7 @@ end % typesetting commands (@smallbook, font changes, etc.) have to be done % beforehand -- and a) we want @copying to be done first in the source % file; b) letting users define the frontmatter in as flexible order as -% possible is very desirable. +% possible is desirable. % \def\copying{\checkenv{}\begingroup\scanargctxt\docopying} \def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} @@ -6866,7 +7648,7 @@ end \temp } -% \domakedefun \deffn \deffnx \deffnheader +% \domakedefun \deffn \deffnx \deffnheader { (defn. of \deffnheader) } % % Define \deffn and \deffnx, without parameters. % \deffnheader has to be defined explicitly. @@ -6887,7 +7669,7 @@ end % @deftypefnnewline on|off says whether the return type of typed functions % are printed on their own line. This affects @deftypefn, @deftypefun, % @deftypeop, and @deftypemethod. -% +% \parseargdef\deftypefnnewline{% \def\temp{#1}% \ifx\temp\onword @@ -6903,6 +7685,21 @@ end \fi\fi } +% \dosubind {index}{topic}{subtopic} +% +% If SUBTOPIC is present, precede it with a space, and call \doind. +% (At some time during the 20th century, this made a two-level entry in an +% index such as the operation index. Nobody seemed to notice the change in +% behaviour though.) +\def\dosubind#1#2#3{% + \def\thirdarg{#3}% + \ifx\thirdarg\empty + \doind{#1}{#2}% + \else + \doind{#1}{#2\space#3}% + \fi +} + % Untyped functions: % @deffn category name args @@ -6917,7 +7714,6 @@ end % \deffngeneral {subind}category name args % \def\deffngeneral#1#2 #3 #4\endheader{% - % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. \dosubind{fn}{\code{#3}}{#1}% \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% } @@ -7068,14 +7864,14 @@ end \tclose{\temp}% typeset the return type \ifrettypeownline % put return type on its own line; prohibit line break following: - \hfil\vadjust{\nobreak}\break + \hfil\vadjust{\nobreak}\break \else \space % type on same line, so just followed by a space \fi \fi % no return type #3% output function name }% - {\rm\enskip}% hskip 0.5 em of \tenrm + {\rm\enskip}% hskip 0.5 em of \rmfont % \boldbrax % arguments will be output next, if any. @@ -7124,6 +7920,7 @@ end \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} } +\let\ampchar\& \newcount\parencount @@ -7204,34 +8001,23 @@ end } \fi -\def\scanmacro#1{\begingroup +% Used at the time of macro expansion. +% Argument is macro body with arguments substituted +\def\scanmacro#1{% \newlinechar`\^^M - \let\xeatspaces\eatspaces + \def\xeatspaces{\eatspaces}% % - % Undo catcode changes of \startcontents and \doprintindex - % When called from @insertcopying or (short)caption, we need active - % backslash to get it printed correctly. Previously, we had - % \catcode`\\=\other instead. We'll see whether a problem appears - % with macro expansion. --kasal, 19aug04 - \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ + % Process the macro body under the current catcode regime. + \scantokens{#1@comment}% % - % ... and for \example: - \spaceisspace - % - % The \empty here causes a following catcode 5 newline to be eaten as - % part of reading whitespace after a control sequence. It does not - % eat a catcode 13 newline. There's no good way to handle the two - % cases (untried: maybe e-TeX's \everyeof could help, though plain TeX - % would then have different behavior). See the Macro Details node in - % the manual for the workaround we recommend for macros and - % line-oriented commands. - % - \scantokens{#1\empty}% -\endgroup} + % The \comment is to remove the \newlinechar added by \scantokens, and + % can be noticed by \parsearg. Note \c isn't used because this means cedilla + % in math mode. +} +% Used for copying and captions \def\scanexp#1{% - \edef\temp{\noexpand\scanmacro{#1}}% - \temp + \expandafter\scanmacro\expandafter{#1}% } \newcount\paramno % Count of parameters @@ -7239,7 +8025,7 @@ end \newif\ifrecursive % Is it recursive? % List of all defined macros in the form -% \definedummyword\macro1\definedummyword\macro2... +% \commondummyword\macro1\commondummyword\macro2... % Currently is also contains all @aliases; the list can be split % if there is a need. \def\macrolist{} @@ -7247,7 +8033,7 @@ end % Add the macro to \macrolist \def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} \def\addtomacrolistxxx#1{% - \toks0 = \expandafter{\macrolist\definedummyword#1}% + \toks0 = \expandafter{\macrolist\commondummyword#1}% \xdef\macrolist{\the\toks0}% } @@ -7297,48 +8083,47 @@ end \catcode`\+=\other \catcode`\<=\other \catcode`\>=\other - \catcode`\@=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\~=\other - \ifx\declaredencoding\ascii \else \setnonasciicharscatcodenonglobal\other \fi + \passthroughcharstrue } \def\scanargctxt{% used for copying and captions, not macros. \scanctxt + \catcode`\@=\other \catcode`\\=\other \catcode`\^^M=\other } \def\macrobodyctxt{% used for @macro definitions \scanctxt + \catcode`\ =\other + \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other \catcode`\^^M=\other \usembodybackslash } -\def\macroargctxt{% used when scanning invocations +% Used when scanning braced macro arguments. Note, however, that catcode +% changes here are ineffectual if the macro invocation was nested inside +% an argument to another Texinfo command. +\def\macroargctxt{% \scanctxt - \catcode`\\=0 + \catcode`\ =\active + \catcode`\@=\other + \catcode`\^^M=\other + \catcode`\\=\active } -% why catcode 0 for \ in the above? To recognize \\ \{ \} as "escapes" -% for the single characters \ { }. Thus, we end up with the "commands" -% that would be written @\ @{ @} in a Texinfo document. -% -% We already have @{ and @}. For @\, we define it here, and only for -% this purpose, to produce a typewriter backslash (so, the @\ that we -% define for @math can't be used with @macro calls): -% -\def\\{\normalbackslash}% -% -% We would like to do this for \, too, since that is what makeinfo does. -% But it is not possible, because Texinfo already has a command @, for a -% cedilla accent. Documents must use @comma{} instead. -% -% \anythingelse will almost certainly be an error of some kind. +\def\macrolineargctxt{% used for whole-line arguments without braces + \scanctxt + \catcode`\@=\other + \catcode`\{=\other + \catcode`\}=\other +} % \mbodybackslash is the definition of \ in @macro bodies. % It maps \foo\ => \csname macarg.foo\endcsname => #N @@ -7391,7 +8176,7 @@ end % Remove the macro name from \macrolist: \begingroup \expandafter\let\csname#1\endcsname \relax - \let\definedummyword\unmacrodo + \let\commondummyword\unmacrodo \xdef\macrolist{\macrolist}% \endgroup \else @@ -7406,61 +8191,40 @@ end \ifx #1\relax % remove this \else - \noexpand\definedummyword \noexpand#1% + \noexpand\commondummyword \noexpand#1% \fi } -% This makes use of the obscure feature that if the last token of a -% is #, then the preceding argument is delimited by -% an opening brace, and that opening brace is not consumed. +% \getargs -- Parse the arguments to a @macro line. Set \macname to +% the name of the macro, and \argl to the braced argument list. \def\getargs#1{\getargsxxx#1{}} \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} \def\getmacname#1 #2\relax{\macname={#1}} \def\getmacargs#1{\def\argl{#1}} +% This made use of the feature that if the last token of a +% is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. -% For macro processing make @ a letter so that we can make Texinfo private macro names. -\edef\texiatcatcode{\the\catcode`\@} -\catcode `@=11\relax - -% Parse the optional {params} list. Set up \paramno and \paramlist -% so \defmacro knows what to do. Define \macarg.BLAH for each BLAH -% in the params list to some hook where the argument si to be expanded. If -% there are less than 10 arguments that hook is to be replaced by ##N where N +% Parse the optional {params} list to @macro or @rmacro. +% Set \paramno to the number of arguments, +% and \paramlist to a parameter text for the macro (e.g. #1,#2,#3 for a +% three-param macro.) Define \macarg.BLAH for each BLAH in the params +% list to some hook where the argument is to be expanded. If there are +% less than 10 arguments that hook is to be replaced by ##N where N % is the position in that list, that is to say the macro arguments are to be -% defined `a la TeX in the macro body. +% defined `a la TeX in the macro body. % % That gets used by \mbodybackslash (above). % -% We need to get `macro parameter char #' into several definitions. -% The technique used is stolen from LaTeX: let \hash be something -% unexpandable, insert that wherever you need a #, and then redefine -% it to # just before using the token list produced. +% If there are 10 or more arguments, a different technique is used: see +% \parsemmanyargdef. % -% The same technique is used to protect \eatspaces till just before -% the macro is used. -% -% If there are 10 or more arguments, a different technique is used, where the -% hook remains in the body, and when macro is to be expanded the body is -% processed again to replace the arguments. -% -% In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the -% argument N value and then \edef the body (nothing else will expand because of -% the catcode regime underwhich the body was input). -% -% If you compile with TeX (not eTeX), and you have macros with 10 or more -% arguments, you need that no macro has more than 256 arguments, otherwise an -% error is produced. \def\parsemargdef#1;{% \paramno=0\def\paramlist{}% \let\hash\relax + % \hash is redefined to `#' later to get it into definitions \let\xeatspaces\relax \parsemargdefxxx#1,;,% - % In case that there are 10 or more arguments we parse again the arguments - % list to set new definitions for the \macarg.BLAH macros corresponding to - % each BLAH argument. It was anyhow needed to parse already once this list - % in order to count the arguments, and as macros with at most 9 arguments - % are by far more frequent than macro with 10 or more arguments, defining - % twice the \macarg.BLAH macros does not cost too much processing power. \ifnum\paramno<10\relax\else \paramno0\relax \parsemmanyargdef@@#1,;,% 10 or more arguments @@ -7475,9 +8239,46 @@ end \edef\paramlist{\paramlist\hash\the\paramno,}% \fi\next} +% \parsemacbody, \parsermacbody +% +% Read recursive and nonrecursive macro bodies. (They're different since +% rec and nonrec macros end differently.) +% +% We are in \macrobodyctxt, and the \xdef causes backslashshes in the macro +% body to be transformed. +% Set \macrobody to the body of the macro, and call \defmacro. +% +{\catcode`\ =\other\long\gdef\parsemacbody#1@end macro{% +\xdef\macrobody{\eatcr{#1}}\endgroup\defmacro}}% +{\catcode`\ =\other\long\gdef\parsermacbody#1@end rmacro{% +\xdef\macrobody{\eatcr{#1}}\endgroup\defmacro}}% + +% Make @ a letter, so that we can make private-to-Texinfo macro names. +\edef\texiatcatcode{\the\catcode`\@} +\catcode `@=11\relax + +%%%%%%%%%%%%%% Code for > 10 arguments only %%%%%%%%%%%%%%%%%% + +% If there are 10 or more arguments, a different technique is used, where the +% hook remains in the body, and when macro is to be expanded the body is +% processed again to replace the arguments. +% +% In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the +% argument N value and then \edef the body (nothing else will expand because of +% the catcode regime under which the body was input). +% +% If you compile with TeX (not eTeX), and you have macros with 10 or more +% arguments, no macro can have more than 256 arguments (else error). +% +% In case that there are 10 or more arguments we parse again the arguments +% list to set new definitions for the \macarg.BLAH macros corresponding to +% each BLAH argument. It was anyhow needed to parse already once this list +% in order to count the arguments, and as macros with at most 9 arguments +% are by far more frequent than macro with 10 or more arguments, defining +% twice the \macarg.BLAH macros does not cost too much processing power. \def\parsemmanyargdef@@#1,{% \if#1;\let\next=\relax - \else + \else \let\next=\parsemmanyargdef@@ \edef\tempb{\eatspaces{#1}}% \expandafter\def\expandafter\tempa @@ -7490,16 +8291,6 @@ end \advance\paramno by 1\relax \fi\next} -% These two commands read recursive and nonrecursive macro bodies. -% (They're different since rec and nonrec macros end differently.) -% - -\catcode `\@\texiatcatcode -\long\def\parsemacbody#1@end macro% -{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% -\long\def\parsermacbody#1@end rmacro% -{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% -\catcode `\@=11\relax \let\endargs@\relax \let\nil@\relax @@ -7507,7 +8298,7 @@ end \long\def\nillm@{\nil@}% % This macro is expanded during the Texinfo macro expansion, not during its -% definition. It gets all the arguments values and assigns them to macros +% definition. It gets all the arguments' values and assigns them to macros % macarg.ARGNAME % % #1 is the macro name @@ -7528,8 +8319,6 @@ end \getargvals@@ \fi } - -% \def\getargvals@@{% \ifx\paramlist\nilm@ % Some sanity check needed here that \argvaluelist is also empty. @@ -7573,7 +8362,8 @@ end } % Replace arguments by their values in the macro body, and place the result -% in macro \@tempa +% in macro \@tempa. +% \def\macvalstoargs@{% % To do this we use the property that token registers that are \the'ed % within an \edef expand only once. So we are going to place all argument @@ -7597,8 +8387,9 @@ end \expandafter\def\expandafter\@tempa\expandafter{\@tempc}% } -\def\macargexpandinbody@{% - %% Define the named-macro outside of this group and then close this group. +% Define the named-macro outside of this group and then close this group. +% +\def\macargexpandinbody@{% \expandafter \endgroup \macargdeflist@ @@ -7635,14 +8426,8 @@ end \next } -% Save the token stack pointer into macro #1 -\def\texisavetoksstackpoint#1{\edef#1{\the\@cclvi}} -% Restore the token stack pointer from number in macro #1 -\def\texirestoretoksstackpoint#1{\expandafter\mathchardef\expandafter\@cclvi#1\relax} -% newtoks that can be used non \outer . -\def\texinonouternewtoks{\alloc@ 5\toks \toksdef \@cclvi} - -% Tailing missing arguments are set to empty +% Trailing missing arguments are set to empty. +% \def\setemptyargvalues@{% \ifx\paramlist\nilm@ \let\next\macargexpandinbody@ @@ -7672,99 +8457,191 @@ end \long\def#2{#4}% } -% This defines a Texinfo @macro. There are eight cases: recursive and -% nonrecursive macros of zero, one, up to nine, and many arguments. -% Much magic with \expandafter here. + +%%%%%%%%%%%%%% End of code for > 10 arguments %%%%%%%%%%%%%%%%%% + + +% This defines a Texinfo @macro or @rmacro, called by \parsemacbody. +% \macrobody has the body of the macro in it, with placeholders for +% its parameters, looking like "\xeatspaces{\hash 1}". +% \paramno is the number of parameters +% \paramlist is a TeX parameter text, e.g. "#1,#2,#3," +% There are four cases: macros of zero, one, up to nine, and many arguments. % \xdef is used so that macro definitions will survive the file -% they're defined in; @include reads the file inside a group. +% they're defined in: @include reads the file inside a group. % \def\defmacro{% \let\hash=##% convert placeholders to macro parameter chars - \ifrecursive - \ifcase\paramno - % 0 - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\scanmacro{\temp}}% - \or % 1 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\braceorline - \expandafter\noexpand\csname\the\macname xxx\endcsname}% - \expandafter\xdef\csname\the\macname xxx\endcsname##1{% - \egroup\noexpand\scanmacro{\temp}}% - \else - \ifnum\paramno<10\relax % at most 9 - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\csname\the\macname xx\endcsname}% - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{\egroup\noexpand\scanmacro{\temp}}% - \else % 10 or more - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\getargvals@{\the\macname}{\argl}% - }% - \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp - \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble - \fi - \fi + \ifnum\paramno=1 + \def\xeatspaces##1{##1}% + % This removes the pair of braces around the argument. We don't + % use \eatspaces, because this can cause ends of lines to be lost + % when the argument to \eatspaces is read, leading to line-based + % commands like "@itemize" not being read correctly. \else - \ifcase\paramno - % 0 + \let\xeatspaces\relax % suppress expansion + \fi + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup + \noexpand\spaceisspace + \noexpand\endlineisspace + \noexpand\expandafter % skip any whitespace after the macro name. + \expandafter\noexpand\csname\the\macname @@@\endcsname}% + \expandafter\xdef\csname\the\macname @@@\endcsname{% + \egroup + \noexpand\scanmacro{\macrobody}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname @@@\endcsname}% + \expandafter\xdef\csname\the\macname @@@\endcsname##1{% + \egroup + \noexpand\scanmacro{\macrobody}% + }% + \else % at most 9 + \ifnum\paramno<10\relax + % @MACNAME sets the context for reading the macro argument + % @MACNAME@@ gets the argument, processes backslashes and appends a + % comma. + % @MACNAME@@@ removes braces surrounding the argument list. + % @MACNAME@@@@ scans the macro body with arguments substituted. \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \or % 1 + \bgroup + \noexpand\expandafter % This \expandafter skip any spaces after the + \noexpand\macroargctxt % macro before we change the catcode of space. + \noexpand\expandafter + \expandafter\noexpand\csname\the\macname @@\endcsname}% + \expandafter\xdef\csname\the\macname @@\endcsname##1{% + \noexpand\passargtomacro + \expandafter\noexpand\csname\the\macname @@@\endcsname{##1,}}% + \expandafter\xdef\csname\the\macname @@@\endcsname##1{% + \expandafter\noexpand\csname\the\macname @@@@\endcsname ##1}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname @@@@\endcsname\paramlist{% + \egroup\noexpand\scanmacro{\macrobody}}% + \else % 10 or more: \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \noexpand\braceorline - \expandafter\noexpand\csname\the\macname xxx\endcsname}% - \expandafter\xdef\csname\the\macname xxx\endcsname##1{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \else % at most 9 - \ifnum\paramno<10\relax - \expandafter\xdef\csname\the\macname\endcsname{% - \bgroup\noexpand\macroargctxt - \expandafter\noexpand\csname\the\macname xx\endcsname}% - \expandafter\xdef\csname\the\macname xx\endcsname##1{% - \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% - \expandafter\expandafter - \expandafter\xdef - \expandafter\expandafter - \csname\the\macname xxx\endcsname - \paramlist{% - \egroup - \noexpand\norecurse{\the\macname}% - \noexpand\scanmacro{\temp}\egroup}% - \else % 10 or more: - \expandafter\xdef\csname\the\macname\endcsname{% - \noexpand\getargvals@{\the\macname}{\argl}% - }% - \global\expandafter\let\csname mac.\the\macname .body\endcsname\temp - \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\norecurse - \fi + \noexpand\getargvals@{\the\macname}{\argl}% + }% + \global\expandafter\let\csname mac.\the\macname .body\endcsname\macrobody + \global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble \fi \fi} -\catcode `\@\texiatcatcode\relax +\catcode `\@\texiatcatcode\relax % end private-to-Texinfo catcodes \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} -% \braceorline decides whether the next nonwhitespace character is a -% {. If so it reads up to the closing }, if not, it reads the whole -% line. Whatever was read is then fed to the next control sequence -% as an argument (by \parsebrace or \parsearg). -% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +{\catcode`\@=0 \catcode`\\=13 % We need to manipulate \ so use @ as escape +@catcode`@_=11 % private names +@catcode`@!=11 % used as argument separator + +% \passargtomacro#1#2 - +% Call #1 with a list of tokens #2, with any doubled backslashes in #2 +% compressed to one. +% +% This implementation works by expansion, and not execution (so we cannot use +% \def or similar). This reduces the risk of this failing in contexts where +% complete expansion is done with no execution (for example, in writing out to +% an auxiliary file for an index entry). +% +% State is kept in the input stream: the argument passed to +% @look_ahead, @gobble_and_check_finish and @add_segment is +% +% THE_MACRO ARG_RESULT ! {PENDING_BS} NEXT_TOKEN (... rest of input) +% +% where: +% THE_MACRO - name of the macro we want to call +% ARG_RESULT - argument list we build to pass to that macro +% PENDING_BS - either a backslash or nothing +% NEXT_TOKEN - used to look ahead in the input stream to see what's coming next + +@gdef@passargtomacro#1#2{% + @add_segment #1!{}@relax#2\@_finish\% +} +@gdef@_finish{@_finishx} @global@let@_finishx@relax + +% #1 - THE_MACRO ARG_RESULT +% #2 - PENDING_BS +% #3 - NEXT_TOKEN +% #4 used to look ahead +% +% If the next token is not a backslash, process the rest of the argument; +% otherwise, remove the next token. +@gdef@look_ahead#1!#2#3#4{% + @ifx#4\% + @expandafter@gobble_and_check_finish + @else + @expandafter@add_segment + @fi#1!{#2}#4#4% +} + +% #1 - THE_MACRO ARG_RESULT +% #2 - PENDING_BS +% #3 - NEXT_TOKEN +% #4 should be a backslash, which is gobbled. +% #5 looks ahead +% +% Double backslash found. Add a single backslash, and look ahead. +@gdef@gobble_and_check_finish#1!#2#3#4#5{% + @add_segment#1\!{}#5#5% +} + +@gdef@is_fi{@fi} + +% #1 - THE_MACRO ARG_RESULT +% #2 - PENDING_BS +% #3 - NEXT_TOKEN +% #4 is input stream until next backslash +% +% Input stream is either at the start of the argument, or just after a +% backslash sequence, either a lone backslash, or a doubled backslash. +% NEXT_TOKEN contains the first token in the input stream: if it is \finish, +% finish; otherwise, append to ARG_RESULT the segment of the argument up until +% the next backslash. PENDING_BACKSLASH contains a backslash to represent +% a backslash just before the start of the input stream that has not been +% added to ARG_RESULT. +@gdef@add_segment#1!#2#3#4\{% +@ifx#3@_finish + @call_the_macro#1!% +@else + % append the pending backslash to the result, followed by the next segment + @expandafter@is_fi@look_ahead#1#2#4!{\}@fi + % this @fi is discarded by @look_ahead. + % we can't get rid of it with \expandafter because we don't know how + % long #4 is. +} + +% #1 - THE_MACRO +% #2 - ARG_RESULT +% #3 discards the res of the conditional in @add_segment, and @is_fi ends the +% conditional. +@gdef@call_the_macro#1#2!#3@fi{@is_fi #1{#2}} + +} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% \braceorline MAC is used for a one-argument macro MAC. It checks +% whether the next non-whitespace character is a {. It sets the context +% for reading the argument (slightly different in the two cases). Then, +% to read the argument, in the whole-line case, it then calls the regular +% \parsearg MAC; in the lbrace case, it calls \passargtomacro MAC. +% \def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx} \def\braceorlinexxx{% - \ifx\nchar\bgroup\else - \expandafter\parsearg + \ifx\nchar\bgroup + \macroargctxt + \expandafter\passargtomacro + \else + \macrolineargctxt\expandafter\parsearg \fi \macnamexxx} @@ -7807,9 +8684,29 @@ end % also remove a trailing comma, in case of something like this: % @node Help-Cross, , , Cross-refs \def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} -\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} +\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}\omittopnode} + +% Used so that the @top node doesn't have to be wrapped in an @ifnottex +% conditional. +% \doignore goes to more effort to skip nested conditionals but we don't need +% that here. +\def\omittopnode{% + \ifx\lastnode\wordTop + \expandafter\ignorenode\fi +} +\def\wordTop{Top} + +% Until the next @node or @bye command, divert output to a box that is not +% output. +\def\ignorenode{\setbox\dummybox\vbox\bgroup\def\node{\egroup\node}% +\ignorenodebye +} + +{\let\bye\relax +\gdef\ignorenodebye{\let\bye\ignorenodebyedef} +\gdef\ignorenodebyedef{\egroup(`Top' node ignored)\bye}} +% The redefinition of \bye here is because it is declared \outer -\let\nwnode=\node \let\lastnode=\empty % Write a cross-reference definition for the current node. #1 is the @@ -7832,7 +8729,7 @@ end % \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an % anchor), which consists of three parts: -% 1) NAME-title - the current sectioning name taken from \lastsection, +% 1) NAME-title - the current sectioning name taken from \currentsection, % or the anchor name. % 2) NAME-snt - section number and type, passed as the SNT arg, or % empty for anchors. @@ -7846,12 +8743,15 @@ end \pdfmkdest{#1}% \iflinks {% + \requireauxfile \atdummies % preserve commands, but don't expand them + % match definition in \xrdef, \refx, \xrefX. + \def\value##1{##1}% \edef\writexrdef##1##2{% \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef ##1}{##2}}% these are parameters of \writexrdef }% - \toks0 = \expandafter{\lastsection}% + \toks0 = \expandafter{\currentsection}% \immediate \writexrdef{title}{\the\toks0 }% \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. \safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout @@ -7863,7 +8763,7 @@ end % automatically in xrefs, if the third arg is not explicitly specified. % This was provided as a "secret" @set xref-automatic-section-title % variable, now it's official. -% +% \parseargdef\xrefautomaticsectiontitle{% \def\temp{#1}% \ifx\temp\onword @@ -7879,15 +8779,18 @@ end \fi\fi } -% +% % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is % the node name, #2 the name of the Info cross-reference, #3 the printed % node name, #4 the name of the Info file, #5 the name of the printed % manual. All but the node name can be omitted. % -\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} -\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} -\def\ref#1{\xrefX[#1,,,,,,,]} +\def\pxref{\putwordsee{} \xrefXX} +\def\xref{\putwordSee{} \xrefXX} +\def\ref{\xrefXX} + +\def\xrefXX#1{\def\xrefXXarg{#1}\futurelet\tokenafterxref\xrefXXX} +\def\xrefXXX{\expandafter\xrefX\expandafter[\xrefXXarg,,,,,,,]} % \newbox\toprefbox \newbox\printedrefnamebox @@ -7934,9 +8837,10 @@ end % % Make link in pdf output. \ifpdf + % For pdfTeX and LuaTeX {\indexnofonts - \turnoffactive \makevalueexpandable + \turnoffactive % This expands tokens, so do it after making catcode changes, so _ % etc. don't get their TeX definitions. This ignores all spaces in % #4, including (wrongly) those in the middle of the filename. @@ -7944,35 +8848,74 @@ end % % This (wrongly) does not take account of leading or trailing % spaces in #1, which should be ignored. - \edef\pdfxrefdest{#1}% - \ifx\pdfxrefdest\empty - \def\pdfxrefdest{Top}% no empty targets - \else - \txiescapepdf\pdfxrefdest % escape PDF special chars + \setpdfdestname{#1}% + % + \ifx\pdfdestname\empty + \def\pdfdestname{Top}% no empty targets \fi % \leavevmode \startlink attr{/Border [0 0 0]}% \ifnum\filenamelength>0 - goto file{\the\filename.pdf} name{\pdfxrefdest}% + goto file{\the\filename.pdf} name{\pdfdestname}% \else - goto name{\pdfmkpgn{\pdfxrefdest}}% + goto name{\pdfmkpgn{\pdfdestname}}% \fi }% \setcolor{\linkcolor}% + \else + \ifx\XeTeXrevision\thisisundefined + \else + % For XeTeX + {\indexnofonts + \makevalueexpandable + \turnoffactive + % This expands tokens, so do it after making catcode changes, so _ + % etc. don't get their TeX definitions. This ignores all spaces in + % #4, including (wrongly) those in the middle of the filename. + \getfilename{#4}% + % + % This (wrongly) does not take account of leading or trailing + % spaces in #1, which should be ignored. + \setpdfdestname{#1}% + % + \ifx\pdfdestname\empty + \def\pdfdestname{Top}% no empty targets + \fi + % + \leavevmode + \ifnum\filenamelength>0 + % With default settings, + % XeTeX (xdvipdfmx) replaces link destination names with integers. + % In this case, the replaced destination names of + % remote PDFs are no longer known. In order to avoid a replacement, + % you can use xdvipdfmx's command line option `-C 0x0010'. + % If you use XeTeX 0.99996+ (TeX Live 2016+), + % this command line option is no longer necessary + % because we can use the `dvipdfmx:config' special. + \special{pdf:bann << /Border [0 0 0] /Type /Annot /Subtype /Link /A + << /S /GoToR /F (\the\filename.pdf) /D (\pdfdestname) >> >>}% + \else + \special{pdf:bann << /Border [0 0 0] /Type /Annot /Subtype /Link /A + << /S /GoTo /D (\pdfdestname) >> >>}% + \fi + }% + \setcolor{\linkcolor}% + \fi \fi - % - % Float references are printed completely differently: "Figure 1.2" - % instead of "[somenode], p.3". We distinguish them by the - % LABEL-title being set to a magic string. {% % Have to otherify everything special to allow the \csname to % include an _ in the xref name, etc. \indexnofonts \turnoffactive + \def\value##1{##1}% \expandafter\global\expandafter\let\expandafter\Xthisreftitle \csname XR#1-title\endcsname }% + % + % Float references are printed completely differently: "Figure 1.2" + % instead of "[somenode], p.3". \iffloat distinguishes them by + % \Xthisreftitle being set to a magic string. \iffloat\Xthisreftitle % If the user specified the print name (third arg) to the ref, % print it instead of our usual "Figure 1.2". @@ -7989,40 +8932,34 @@ end \fi \else % node/anchor (non-float) references. - % + % % If we use \unhbox to print the node names, TeX does not insert % empty discretionaries after hyphens, which means that it will not % find a line break at a hyphen in a node names. Since some manuals % are best written with fairly long node names, containing hyphens, % this is a loss. Therefore, we give the text of the node name % again, so it is as if TeX is seeing it for the first time. - % + % \ifdim \wd\printedmanualbox > 0pt % Cross-manual reference with a printed manual name. - % + % \crossmanualxref{\cite{\printedmanual\unskip}}% % \else\ifdim \wd\infofilenamebox > 0pt % Cross-manual reference with only an info filename (arg 4), no % printed manual name (arg 5). This is essentially the same as % the case above; we output the filename, since we have nothing else. - % + % \crossmanualxref{\code{\infofilename\unskip}}% % \else % Reference within this manual. % - % _ (for example) has to be the character _ for the purposes of the - % control sequence corresponding to the node, but it has to expand - % into the usual \leavevmode...\vrule stuff for purposes of - % printing. So we \turnoffactive for the \refx-snt, back on for the - % printing, back off for the \refx-pg. - {\turnoffactive - % Only output a following space if the -snt ref is nonempty; for - % @unnumbered and @anchor, it won't be. - \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% - \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi - }% + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + % % output the `[mynode]' via the macro below so it can be overridden. \xrefprintnodename\printedrefname % @@ -8031,26 +8968,35 @@ end % % output the `page 3'. \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + % Add a , if xref followed by a space + \if\space\noexpand\tokenafterxref ,% + \else\ifx\ \tokenafterxref ,% @TAB + \else\ifx\*\tokenafterxref ,% @* + \else\ifx\ \tokenafterxref ,% @SPACE + \else\ifx\ + \tokenafterxref ,% @NL + \else\ifx\tie\tokenafterxref ,% @tie + \fi\fi\fi\fi\fi\fi \fi\fi \fi \endlink \endgroup} % Output a cross-manual xref to #1. Used just above (twice). -% +% % Only include the text "Section ``foo'' in" if the foo is neither % missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply % "see The Foo Manual", the idea being to refer to the whole manual. -% +% % But, this being TeX, we can't easily compare our node name against the % string "Top" while ignoring the possible spaces before and after in % the input. By adding the arbitrary 7sp below, we make it much less % likely that a real node name would have the same width as "Top" (e.g., % in a monospaced font). Hopefully it will never happen in practice. -% +% % For the same basic reason, we retypeset the "Top" at every % reference, since the current font is indeterminate. -% +% \def\crossmanualxref#1{% \setbox\toprefbox = \hbox{Top\kern7sp}% \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}% @@ -8097,13 +9043,14 @@ end \fi\fi\fi } -% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. -% If its value is nonempty, SUFFIX is output afterward. -% +% \refx{NAME}{SUFFIX} - reference a cross-reference string named NAME. SUFFIX +% is output afterwards if non-empty. \def\refx#1#2{% + \requireauxfile {% \indexnofonts - \otherbackslash + \turnoffactive + \def\value##1{##1}% \expandafter\global\expandafter\let\expandafter\thisrefX \csname XR#1\endcsname }% @@ -8128,20 +9075,28 @@ end #2% Output the suffix in any case. } -% This is the macro invoked by entries in the aux file. Usually it's -% just a \def (we prepend XR to the control sequence name to avoid -% collisions). But if this is a float type, we have more work to do. +% This is the macro invoked by entries in the aux file. Define a control +% sequence for a cross-reference target (we prepend XR to the control sequence +% name to avoid collisions). The value is the page number. If this is a float +% type, we have more work to do. % \def\xrdef#1#2{% - {% The node name might contain 8-bit characters, which in our current - % implementation are changed to commands like @'e. Don't let these - % mess up the control sequence name. + {% Expand the node or anchor name to remove control sequences. + % \turnoffactive stops 8-bit characters being changed to commands + % like @'e. \refx does the same to retrieve the value in the definition. \indexnofonts \turnoffactive + \def\value##1{##1}% \xdef\safexrefname{#1}% }% % - \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% remember this xref + \bgroup + \expandafter\gdef\csname XR\safexrefname\endcsname{#2}% + \egroup + % We put the \gdef inside a group to avoid the definitions building up on + % TeX's save stack, which can cause it to run out of space for aux files with + % thousands of lines. \gdef doesn't use the save stack, but \csname does + % when it defines an unknown control sequence as \relax. % % Was that xref control sequence that we just defined for a float? \expandafter\iffloat\csname XR\safexrefname\endcsname @@ -8164,6 +9119,23 @@ end \fi } +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate at the beginning of the file. +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% Used when writing to the aux file, or when using data from it. +\def\requireauxfile{% + \iflinks + \tryauxfile + % Open the new aux file. TeX will close it automatically at exit. + \immediate\openout\auxfile=\jobname.aux + \fi + \global\let\requireauxfile=\relax % Only do this once. +} + % Read the last existing aux file, if any. No error if none exists. % \def\tryauxfile{% @@ -8203,19 +9175,6 @@ end \catcode`\^^]=\other \catcode`\^^^=\other \catcode`\^^_=\other - % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. - % in xref tags, i.e., node names. But since ^^e4 notation isn't - % supported in the main text, it doesn't seem desirable. Furthermore, - % that is not enough: for node names that actually contain a ^ - % character, we would end up writing a line like this: 'xrdef {'hat - % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first - % argument, and \hat is not an expandable control sequence. It could - % all be worked out, but why? Either we support ^^ or we don't. - % - % The other change necessary for this was to define \auxhat: - % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter - % and then to call \auxhat in \setq. - % \catcode`\^=\other % % Special characters. Should be turned off anyway, but... @@ -8233,24 +9192,7 @@ end \catcode`\%=\other \catcode`+=\other % avoid \+ for paranoia even though we've turned it off % - % This is to support \ in node names and titles, since the \ - % characters end up in a \csname. It's easier than - % leaving it active and making its active definition an actual \ - % character. What I don't understand is why it works in the *value* - % of the xrdef. Seems like it should be a catcode12 \, and that - % should not typeset properly. But it works, so I'm moving on for - % now. --karl, 15jan04. - \catcode`\\=\other - % - % Make the characters 128-255 be printing characters. - {% - \count1=128 - \def\loop{% - \catcode\count1=\other - \advance\count1 by 1 - \ifnum \count1<256 \loop \fi - }% - }% + \catcode`\\=\active % % @ is our escape character in .aux files, and we need braces. \catcode`\{=1 @@ -8284,8 +9226,6 @@ end % % Auto-number footnotes. Otherwise like plain. \gdef\footnote{% - \let\indent=\ptexindent - \let\noindent=\ptexnoindent \global\advance\footnoteno by \@ne \edef\thisfootno{$^{\the\footnoteno}$}% % @@ -8309,10 +9249,15 @@ end % \gdef\dofootnote{% \insert\footins\bgroup + % + % Nested footnotes are not supported in TeX, that would take a lot + % more work. (\startsavinginserts does not suffice.) + \let\footnote=\errfootnotenest + % % We want to typeset this text as a normal paragraph, even if the % footnote reference occurs in (for example) a display environment. % So reset some parameters. - \hsize=\pagewidth + \hsize=\txipagewidth \interlinepenalty\interfootnotelinepenalty \splittopskip\ht\strutbox % top baseline for broken footnotes \splitmaxdepth\dp\strutbox @@ -8346,13 +9291,24 @@ end } }%end \catcode `\@=11 +\def\errfootnotenest{% + \errhelp=\EMsimple + \errmessage{Nested footnotes not supported in texinfo.tex, + even though they work in makeinfo; sorry} +} + +\def\errfootnoteheading{% + \errhelp=\EMsimple + \errmessage{Footnotes in chapters, sections, etc., are not supported} +} + % In case a @footnote appears in a vbox, save the footnote text and create % the real \insert just after the vbox finished. Otherwise, the insertion % would be lost. % Similarly, if a @footnote appears inside an alignment, save the footnote % text to a box and make the \insert when a row of the table is finished. % And the same can be done for other insert classes. --kasal, 16nov03. - +% % Replace the \insert primitive by a cheating macro. % Deeper inside, just make sure that the saved insertions are not spilled % out prematurely. @@ -8426,7 +9382,7 @@ end \newif\ifwarnednoepsf \newhelp\noepsfhelp{epsf.tex must be installed for images to work. It is also included in the Texinfo distribution, or you can get - it from ftp://tug.org/tex/epsf.tex.} + it from https://ctan.org/texarchive/macros/texinfo/texinfo/doc/epsf.tex.} % \def\image#1{% \ifx\epsfbox\thisisundefined @@ -8450,6 +9406,7 @@ end \def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup \catcode`\^^M = 5 % in case we're inside an example \normalturnoffactive % allow _ et al. in names + \def\xprocessmacroarg{\eatspaces}% in case we are being used via a macro % If the image is by itself, center it. \ifvmode \imagevmodetrue @@ -8479,17 +9436,26 @@ end % % Output the image. \ifpdf + % For pdfTeX and LuaTeX <= 0.80 \dopdfimage{#1}{#2}{#3}% \else - % \epsfbox itself resets \epsf?size at each figure. - \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi - \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi - \epsfbox{#1.eps}% + \ifx\XeTeXrevision\thisisundefined + % For epsf.tex + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \else + % For XeTeX + \doxeteximage{#1}{#2}{#3}% + \fi \fi % \ifimagevmode \medskip % space after a standalone image - \fi + \fi \ifx\centersub\centerV \egroup \fi \endgroup} @@ -8557,13 +9523,13 @@ end \global\advance\floatno by 1 % {% - % This magic value for \lastsection is output by \setref as the + % This magic value for \currentsection is output by \setref as the % XREFLABEL-title value. \xrefX uses it to distinguish float % labels (which have a completely different output format) from % node and anchor labels. And \xrdef uses it to construct the % lists of floats. % - \edef\lastsection{\floatmagic=\safefloattype}% + \edef\currentsection{\floatmagic=\safefloattype}% \setref{\floatlabel}{Yfloat}% }% \fi @@ -8606,7 +9572,7 @@ end % \ifx\thiscaption\empty \else \ifx\floatident\empty \else - \appendtomacro\captionline{: }% had ident, so need a colon between + \appendtomacro\captionline{: }% had ident, so need a colon between \fi % % caption text. @@ -8630,32 +9596,20 @@ end % \floatlabel-lof. Besides \floatident, we include the short % caption if specified, else the full caption if specified, else nothing. {% + \requireauxfile \atdummies % - % since we read the caption text in the macro world, where ^^M - % is turned into a normal character, we have to scan it back, so - % we don't write the literal three characters "^^M" into the aux file. - \scanexp{% - \xdef\noexpand\gtemp{% - \ifx\thisshortcaption\empty - \thiscaption - \else - \thisshortcaption - \fi - }% - }% + \ifx\thisshortcaption\empty + \def\gtemp{\thiscaption}% + \else + \def\gtemp{\thisshortcaption}% + \fi \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident - \ifx\gtemp\empty \else : \gtemp \fi}}% + \ifx\gtemp\empty \else : \gtemp \fi}}% }% \fi \egroup % end of \vtop % - % place the captured inserts - % - % BEWARE: when the floats start floating, we have to issue warning - % whenever an insert appears inside a float which could possibly - % float. --kasal, 26may04 - % \checkinserts } @@ -8698,7 +9652,7 @@ end % #1 is the control sequence we are passed; we expand into a conditional % which is true if #1 represents a float ref. That is, the magic -% \lastsection value which we \setref above. +% \currentsection value which we \setref above. % \def\iffloat#1{\expandafter\doiffloat#1==\finish} % @@ -8769,20 +9723,20 @@ end { \catcode`\_ = \active \globaldefs=1 -\parseargdef\documentlanguage{\begingroup - \let_=\normalunderscore % normal _ character for filenames +\parseargdef\documentlanguage{% \tex % read txi-??.tex file in plain TeX. % Read the file by the name they passed if it exists. + \let_ = \normalunderscore % normal _ character for filename test \openin 1 txi-#1.tex \ifeof 1 - \documentlanguagetrywithoutunderscore{#1_\finish}% + \documentlanguagetrywithoutunderscore #1_\finish \else \globaldefs = 1 % everything in the txi-LL files needs to persist \input txi-#1.tex \fi \closein 1 \endgroup % end raw TeX -\endgroup} +} % % If they passed de_DE, and txi-de_DE.tex doesn't exist, % try txi-de.tex. @@ -8830,6 +9784,70 @@ directory should work if nowhere else does.} \global\righthyphenmin = #3\relax } +% XeTeX and LuaTeX can handle Unicode natively. +% Their default I/O uses UTF-8 sequences instead of a byte-wise operation. +% Other TeX engines' I/O (pdfTeX, etc.) is byte-wise. +% +\newif\iftxinativeunicodecapable +\newif\iftxiusebytewiseio + +\ifx\XeTeXrevision\thisisundefined + \ifx\luatexversion\thisisundefined + \txinativeunicodecapablefalse + \txiusebytewiseiotrue + \else + \txinativeunicodecapabletrue + \txiusebytewiseiofalse + \fi +\else + \txinativeunicodecapabletrue + \txiusebytewiseiofalse +\fi + +% Set I/O by bytes instead of UTF-8 sequence for XeTeX and LuaTex +% for non-UTF-8 (byte-wise) encodings. +% +\def\setbytewiseio{% + \ifx\XeTeXrevision\thisisundefined + \else + \XeTeXdefaultencoding "bytes" % For subsequent files to be read + \XeTeXinputencoding "bytes" % For document root file + % Unfortunately, there seems to be no corresponding XeTeX command for + % output encoding. This is a problem for auxiliary index and TOC files. + % The only solution would be perhaps to write out @U{...} sequences in + % place of non-ASCII characters. + \fi + + \ifx\luatexversion\thisisundefined + \else + \directlua{ + local utf8_char, byte, gsub = unicode.utf8.char, string.byte, string.gsub + local function convert_char (char) + return utf8_char(byte(char)) + end + + local function convert_line (line) + return gsub(line, ".", convert_char) + end + + callback.register("process_input_buffer", convert_line) + + local function convert_line_out (line) + local line_out = "" + for c in string.utfvalues(line) do + line_out = line_out .. string.char(c) + end + return line_out + end + + callback.register("process_output_buffer", convert_line_out) + } + \fi + + \txiusebytewiseiotrue +} + + % Helpers for encodings. % Set the catcode of characters 128 through 255 to the specified number. % @@ -8852,7 +9870,9 @@ directory should work if nowhere else does.} % @documentencoding sets the definition of non-ASCII characters % according to the specified encoding. % -\parseargdef\documentencoding{% +\def\documentencoding{\parseargusing\filenamecatcodes\documentencodingzzz} +\def\documentencodingzzz#1{% + % % Encoding being declared for the document. \def\declaredencoding{\csname #1.enc\endcsname}% % @@ -8868,35 +9888,66 @@ directory should work if nowhere else does.} \asciichardefs % \else \ifx \declaredencoding \lattwo + \iftxinativeunicodecapable + \setbytewiseio + \fi \setnonasciicharscatcode\active \lattwochardefs % \else \ifx \declaredencoding \latone + \iftxinativeunicodecapable + \setbytewiseio + \fi \setnonasciicharscatcode\active \latonechardefs % \else \ifx \declaredencoding \latnine + \iftxinativeunicodecapable + \setbytewiseio + \fi \setnonasciicharscatcode\active \latninechardefs % \else \ifx \declaredencoding \utfeight - \setnonasciicharscatcode\active - \utfeightchardefs + \iftxinativeunicodecapable + % For native Unicode handling (XeTeX and LuaTeX) + \nativeunicodechardefs + \else + % For treating UTF-8 as byte sequences (TeX, eTeX and pdfTeX) + \setnonasciicharscatcode\active + % since we already invoked \utfeightchardefs at the top level + % (below), do not re-invoke it, otherwise our check for duplicated + % definitions gets triggered. Making non-ascii chars active is + % sufficient. + \fi % \else - \message{Unknown document encoding #1, ignoring.}% + \message{Ignoring unknown document encoding: #1.}% % \fi % utfeight \fi % latnine \fi % latone \fi % lattwo \fi % ascii + % + \ifx\XeTeXrevision\thisisundefined + \else + \ifx \declaredencoding \utfeight + \else + \ifx \declaredencoding \ascii + \else + \message{Warning: XeTeX with non-UTF-8 encodings cannot handle % + non-ASCII characters in auxiliary files.}% + \fi + \fi + \fi } +% emacs-page % A message to be logged when using a character that isn't available % the default font encoding (OT1). % -\def\missingcharmsg#1{\message{Character missing in OT1 encoding: #1.}} +\def\missingcharmsg#1{\message{Character missing, sorry: #1.}} % Take account of \c (plain) vs. \, (Texinfo) difference. \def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi} @@ -8906,111 +9957,119 @@ directory should work if nowhere else does.} % macros containing the character definitions. \setnonasciicharscatcode\active % + +\def\gdefchar#1#2{% +\gdef#1{% + \ifpassthroughchars + \string#1% + \else + #2% + \fi +}} + % Latin1 (ISO-8859-1) character definitions. \def\latonechardefs{% - \gdef^^a0{\tie} - \gdef^^a1{\exclamdown} - \gdef^^a2{\missingcharmsg{CENT SIGN}} - \gdef^^a3{{\pounds}} - \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} - \gdef^^a5{\missingcharmsg{YEN SIGN}} - \gdef^^a6{\missingcharmsg{BROKEN BAR}} - \gdef^^a7{\S} - \gdef^^a8{\"{}} - \gdef^^a9{\copyright} - \gdef^^aa{\ordf} - \gdef^^ab{\guillemetleft} - \gdef^^ac{$\lnot$} - \gdef^^ad{\-} - \gdef^^ae{\registeredsymbol} - \gdef^^af{\={}} + \gdefchar^^a0{\tie} + \gdefchar^^a1{\exclamdown} + \gdefchar^^a2{{\tcfont \char162}} % cent + \gdefchar^^a3{\pounds{}} + \gdefchar^^a4{{\tcfont \char164}} % currency + \gdefchar^^a5{{\tcfont \char165}} % yen + \gdefchar^^a6{{\tcfont \char166}} % broken bar + \gdefchar^^a7{\S} + \gdefchar^^a8{\"{}} + \gdefchar^^a9{\copyright{}} + \gdefchar^^aa{\ordf} + \gdefchar^^ab{\guillemetleft{}} + \gdefchar^^ac{\ensuremath\lnot} + \gdefchar^^ad{\-} + \gdefchar^^ae{\registeredsymbol{}} + \gdefchar^^af{\={}} % - \gdef^^b0{\textdegree} - \gdef^^b1{$\pm$} - \gdef^^b2{$^2$} - \gdef^^b3{$^3$} - \gdef^^b4{\'{}} - \gdef^^b5{$\mu$} - \gdef^^b6{\P} + \gdefchar^^b0{\textdegree} + \gdefchar^^b1{$\pm$} + \gdefchar^^b2{$^2$} + \gdefchar^^b3{$^3$} + \gdefchar^^b4{\'{}} + \gdefchar^^b5{$\mu$} + \gdefchar^^b6{\P} + \gdefchar^^b7{\ensuremath\cdot} + \gdefchar^^b8{\cedilla\ } + \gdefchar^^b9{$^1$} + \gdefchar^^ba{\ordm} + \gdefchar^^bb{\guillemetright{}} + \gdefchar^^bc{$1\over4$} + \gdefchar^^bd{$1\over2$} + \gdefchar^^be{$3\over4$} + \gdefchar^^bf{\questiondown} % - \gdef^^b7{$^.$} - \gdef^^b8{\cedilla\ } - \gdef^^b9{$^1$} - \gdef^^ba{\ordm} + \gdefchar^^c0{\`A} + \gdefchar^^c1{\'A} + \gdefchar^^c2{\^A} + \gdefchar^^c3{\~A} + \gdefchar^^c4{\"A} + \gdefchar^^c5{\ringaccent A} + \gdefchar^^c6{\AE} + \gdefchar^^c7{\cedilla C} + \gdefchar^^c8{\`E} + \gdefchar^^c9{\'E} + \gdefchar^^ca{\^E} + \gdefchar^^cb{\"E} + \gdefchar^^cc{\`I} + \gdefchar^^cd{\'I} + \gdefchar^^ce{\^I} + \gdefchar^^cf{\"I} % - \gdef^^bb{\guillemetright} - \gdef^^bc{$1\over4$} - \gdef^^bd{$1\over2$} - \gdef^^be{$3\over4$} - \gdef^^bf{\questiondown} + \gdefchar^^d0{\DH} + \gdefchar^^d1{\~N} + \gdefchar^^d2{\`O} + \gdefchar^^d3{\'O} + \gdefchar^^d4{\^O} + \gdefchar^^d5{\~O} + \gdefchar^^d6{\"O} + \gdefchar^^d7{$\times$} + \gdefchar^^d8{\O} + \gdefchar^^d9{\`U} + \gdefchar^^da{\'U} + \gdefchar^^db{\^U} + \gdefchar^^dc{\"U} + \gdefchar^^dd{\'Y} + \gdefchar^^de{\TH} + \gdefchar^^df{\ss} % - \gdef^^c0{\`A} - \gdef^^c1{\'A} - \gdef^^c2{\^A} - \gdef^^c3{\~A} - \gdef^^c4{\"A} - \gdef^^c5{\ringaccent A} - \gdef^^c6{\AE} - \gdef^^c7{\cedilla C} - \gdef^^c8{\`E} - \gdef^^c9{\'E} - \gdef^^ca{\^E} - \gdef^^cb{\"E} - \gdef^^cc{\`I} - \gdef^^cd{\'I} - \gdef^^ce{\^I} - \gdef^^cf{\"I} + \gdefchar^^e0{\`a} + \gdefchar^^e1{\'a} + \gdefchar^^e2{\^a} + \gdefchar^^e3{\~a} + \gdefchar^^e4{\"a} + \gdefchar^^e5{\ringaccent a} + \gdefchar^^e6{\ae} + \gdefchar^^e7{\cedilla c} + \gdefchar^^e8{\`e} + \gdefchar^^e9{\'e} + \gdefchar^^ea{\^e} + \gdefchar^^eb{\"e} + \gdefchar^^ec{\`{\dotless i}} + \gdefchar^^ed{\'{\dotless i}} + \gdefchar^^ee{\^{\dotless i}} + \gdefchar^^ef{\"{\dotless i}} % - \gdef^^d0{\DH} - \gdef^^d1{\~N} - \gdef^^d2{\`O} - \gdef^^d3{\'O} - \gdef^^d4{\^O} - \gdef^^d5{\~O} - \gdef^^d6{\"O} - \gdef^^d7{$\times$} - \gdef^^d8{\O} - \gdef^^d9{\`U} - \gdef^^da{\'U} - \gdef^^db{\^U} - \gdef^^dc{\"U} - \gdef^^dd{\'Y} - \gdef^^de{\TH} - \gdef^^df{\ss} - % - \gdef^^e0{\`a} - \gdef^^e1{\'a} - \gdef^^e2{\^a} - \gdef^^e3{\~a} - \gdef^^e4{\"a} - \gdef^^e5{\ringaccent a} - \gdef^^e6{\ae} - \gdef^^e7{\cedilla c} - \gdef^^e8{\`e} - \gdef^^e9{\'e} - \gdef^^ea{\^e} - \gdef^^eb{\"e} - \gdef^^ec{\`{\dotless i}} - \gdef^^ed{\'{\dotless i}} - \gdef^^ee{\^{\dotless i}} - \gdef^^ef{\"{\dotless i}} - % - \gdef^^f0{\dh} - \gdef^^f1{\~n} - \gdef^^f2{\`o} - \gdef^^f3{\'o} - \gdef^^f4{\^o} - \gdef^^f5{\~o} - \gdef^^f6{\"o} - \gdef^^f7{$\div$} - \gdef^^f8{\o} - \gdef^^f9{\`u} - \gdef^^fa{\'u} - \gdef^^fb{\^u} - \gdef^^fc{\"u} - \gdef^^fd{\'y} - \gdef^^fe{\th} - \gdef^^ff{\"y} + \gdefchar^^f0{\dh} + \gdefchar^^f1{\~n} + \gdefchar^^f2{\`o} + \gdefchar^^f3{\'o} + \gdefchar^^f4{\^o} + \gdefchar^^f5{\~o} + \gdefchar^^f6{\"o} + \gdefchar^^f7{$\div$} + \gdefchar^^f8{\o} + \gdefchar^^f9{\`u} + \gdefchar^^fa{\'u} + \gdefchar^^fb{\^u} + \gdefchar^^fc{\"u} + \gdefchar^^fd{\'y} + \gdefchar^^fe{\th} + \gdefchar^^ff{\"y} } % Latin9 (ISO-8859-15) encoding character definitions. @@ -9018,119 +10077,119 @@ directory should work if nowhere else does.} % Encoding is almost identical to Latin1. \latonechardefs % - \gdef^^a4{\euro} - \gdef^^a6{\v S} - \gdef^^a8{\v s} - \gdef^^b4{\v Z} - \gdef^^b8{\v z} - \gdef^^bc{\OE} - \gdef^^bd{\oe} - \gdef^^be{\"Y} + \gdefchar^^a4{\euro{}} + \gdefchar^^a6{\v S} + \gdefchar^^a8{\v s} + \gdefchar^^b4{\v Z} + \gdefchar^^b8{\v z} + \gdefchar^^bc{\OE} + \gdefchar^^bd{\oe} + \gdefchar^^be{\"Y} } % Latin2 (ISO-8859-2) character definitions. \def\lattwochardefs{% - \gdef^^a0{\tie} - \gdef^^a1{\ogonek{A}} - \gdef^^a2{\u{}} - \gdef^^a3{\L} - \gdef^^a4{\missingcharmsg{CURRENCY SIGN}} - \gdef^^a5{\v L} - \gdef^^a6{\'S} - \gdef^^a7{\S} - \gdef^^a8{\"{}} - \gdef^^a9{\v S} - \gdef^^aa{\cedilla S} - \gdef^^ab{\v T} - \gdef^^ac{\'Z} - \gdef^^ad{\-} - \gdef^^ae{\v Z} - \gdef^^af{\dotaccent Z} + \gdefchar^^a0{\tie} + \gdefchar^^a1{\ogonek{A}} + \gdefchar^^a2{\u{}} + \gdefchar^^a3{\L} + \gdefchar^^a4{\missingcharmsg{CURRENCY SIGN}} + \gdefchar^^a5{\v L} + \gdefchar^^a6{\'S} + \gdefchar^^a7{\S} + \gdefchar^^a8{\"{}} + \gdefchar^^a9{\v S} + \gdefchar^^aa{\cedilla S} + \gdefchar^^ab{\v T} + \gdefchar^^ac{\'Z} + \gdefchar^^ad{\-} + \gdefchar^^ae{\v Z} + \gdefchar^^af{\dotaccent Z} % - \gdef^^b0{\textdegree} - \gdef^^b1{\ogonek{a}} - \gdef^^b2{\ogonek{ }} - \gdef^^b3{\l} - \gdef^^b4{\'{}} - \gdef^^b5{\v l} - \gdef^^b6{\'s} - \gdef^^b7{\v{}} - \gdef^^b8{\cedilla\ } - \gdef^^b9{\v s} - \gdef^^ba{\cedilla s} - \gdef^^bb{\v t} - \gdef^^bc{\'z} - \gdef^^bd{\H{}} - \gdef^^be{\v z} - \gdef^^bf{\dotaccent z} + \gdefchar^^b0{\textdegree{}} + \gdefchar^^b1{\ogonek{a}} + \gdefchar^^b2{\ogonek{ }} + \gdefchar^^b3{\l} + \gdefchar^^b4{\'{}} + \gdefchar^^b5{\v l} + \gdefchar^^b6{\'s} + \gdefchar^^b7{\v{}} + \gdefchar^^b8{\cedilla\ } + \gdefchar^^b9{\v s} + \gdefchar^^ba{\cedilla s} + \gdefchar^^bb{\v t} + \gdefchar^^bc{\'z} + \gdefchar^^bd{\H{}} + \gdefchar^^be{\v z} + \gdefchar^^bf{\dotaccent z} % - \gdef^^c0{\'R} - \gdef^^c1{\'A} - \gdef^^c2{\^A} - \gdef^^c3{\u A} - \gdef^^c4{\"A} - \gdef^^c5{\'L} - \gdef^^c6{\'C} - \gdef^^c7{\cedilla C} - \gdef^^c8{\v C} - \gdef^^c9{\'E} - \gdef^^ca{\ogonek{E}} - \gdef^^cb{\"E} - \gdef^^cc{\v E} - \gdef^^cd{\'I} - \gdef^^ce{\^I} - \gdef^^cf{\v D} + \gdefchar^^c0{\'R} + \gdefchar^^c1{\'A} + \gdefchar^^c2{\^A} + \gdefchar^^c3{\u A} + \gdefchar^^c4{\"A} + \gdefchar^^c5{\'L} + \gdefchar^^c6{\'C} + \gdefchar^^c7{\cedilla C} + \gdefchar^^c8{\v C} + \gdefchar^^c9{\'E} + \gdefchar^^ca{\ogonek{E}} + \gdefchar^^cb{\"E} + \gdefchar^^cc{\v E} + \gdefchar^^cd{\'I} + \gdefchar^^ce{\^I} + \gdefchar^^cf{\v D} % - \gdef^^d0{\DH} - \gdef^^d1{\'N} - \gdef^^d2{\v N} - \gdef^^d3{\'O} - \gdef^^d4{\^O} - \gdef^^d5{\H O} - \gdef^^d6{\"O} - \gdef^^d7{$\times$} - \gdef^^d8{\v R} - \gdef^^d9{\ringaccent U} - \gdef^^da{\'U} - \gdef^^db{\H U} - \gdef^^dc{\"U} - \gdef^^dd{\'Y} - \gdef^^de{\cedilla T} - \gdef^^df{\ss} + \gdefchar^^d0{\DH} + \gdefchar^^d1{\'N} + \gdefchar^^d2{\v N} + \gdefchar^^d3{\'O} + \gdefchar^^d4{\^O} + \gdefchar^^d5{\H O} + \gdefchar^^d6{\"O} + \gdefchar^^d7{$\times$} + \gdefchar^^d8{\v R} + \gdefchar^^d9{\ringaccent U} + \gdefchar^^da{\'U} + \gdefchar^^db{\H U} + \gdefchar^^dc{\"U} + \gdefchar^^dd{\'Y} + \gdefchar^^de{\cedilla T} + \gdefchar^^df{\ss} % - \gdef^^e0{\'r} - \gdef^^e1{\'a} - \gdef^^e2{\^a} - \gdef^^e3{\u a} - \gdef^^e4{\"a} - \gdef^^e5{\'l} - \gdef^^e6{\'c} - \gdef^^e7{\cedilla c} - \gdef^^e8{\v c} - \gdef^^e9{\'e} - \gdef^^ea{\ogonek{e}} - \gdef^^eb{\"e} - \gdef^^ec{\v e} - \gdef^^ed{\'{\dotless{i}}} - \gdef^^ee{\^{\dotless{i}}} - \gdef^^ef{\v d} + \gdefchar^^e0{\'r} + \gdefchar^^e1{\'a} + \gdefchar^^e2{\^a} + \gdefchar^^e3{\u a} + \gdefchar^^e4{\"a} + \gdefchar^^e5{\'l} + \gdefchar^^e6{\'c} + \gdefchar^^e7{\cedilla c} + \gdefchar^^e8{\v c} + \gdefchar^^e9{\'e} + \gdefchar^^ea{\ogonek{e}} + \gdefchar^^eb{\"e} + \gdefchar^^ec{\v e} + \gdefchar^^ed{\'{\dotless{i}}} + \gdefchar^^ee{\^{\dotless{i}}} + \gdefchar^^ef{\v d} % - \gdef^^f0{\dh} - \gdef^^f1{\'n} - \gdef^^f2{\v n} - \gdef^^f3{\'o} - \gdef^^f4{\^o} - \gdef^^f5{\H o} - \gdef^^f6{\"o} - \gdef^^f7{$\div$} - \gdef^^f8{\v r} - \gdef^^f9{\ringaccent u} - \gdef^^fa{\'u} - \gdef^^fb{\H u} - \gdef^^fc{\"u} - \gdef^^fd{\'y} - \gdef^^fe{\cedilla t} - \gdef^^ff{\dotaccent{}} + \gdefchar^^f0{\dh} + \gdefchar^^f1{\'n} + \gdefchar^^f2{\v n} + \gdefchar^^f3{\'o} + \gdefchar^^f4{\^o} + \gdefchar^^f5{\H o} + \gdefchar^^f6{\"o} + \gdefchar^^f7{$\div$} + \gdefchar^^f8{\v r} + \gdefchar^^f9{\ringaccent u} + \gdefchar^^fa{\'u} + \gdefchar^^fb{\H u} + \gdefchar^^fc{\"u} + \gdefchar^^fd{\'y} + \gdefchar^^fe{\cedilla t} + \gdefchar^^ff{\dotaccent{}} } % UTF-8 character definitions. @@ -9160,38 +10219,94 @@ directory should work if nowhere else does.} \fi } +% Give non-ASCII bytes the active definitions for processing UTF-8 sequences \begingroup \catcode`\~13 + \catcode`\$12 \catcode`\"12 + % Loop from \countUTFx to \countUTFy, performing \UTFviiiTmp + % substituting ~ and $ with a character token of that value. \def\UTFviiiLoop{% \global\catcode\countUTFx\active \uccode`\~\countUTFx + \uccode`\$\countUTFx \uppercase\expandafter{\UTFviiiTmp}% \advance\countUTFx by 1 \ifnum\countUTFx < \countUTFy \expandafter\UTFviiiLoop \fi} + % For bytes other than the first in a UTF-8 sequence. Not expected to + % be expanded except when writing to auxiliary files. + \countUTFx = "80 + \countUTFy = "C2 + \def\UTFviiiTmp{% + \gdef~{% + \ifpassthroughchars $\fi}}% + \UTFviiiLoop + \countUTFx = "C2 \countUTFy = "E0 \def\UTFviiiTmp{% - \xdef~{\noexpand\UTFviiiTwoOctets\string~}} + \gdef~{% + \ifpassthroughchars $% + \else\expandafter\UTFviiiTwoOctets\expandafter$\fi}}% \UTFviiiLoop \countUTFx = "E0 \countUTFy = "F0 \def\UTFviiiTmp{% - \xdef~{\noexpand\UTFviiiThreeOctets\string~}} + \gdef~{% + \ifpassthroughchars $% + \else\expandafter\UTFviiiThreeOctets\expandafter$\fi}}% \UTFviiiLoop \countUTFx = "F0 \countUTFy = "F4 \def\UTFviiiTmp{% - \xdef~{\noexpand\UTFviiiFourOctets\string~}} + \gdef~{% + \ifpassthroughchars $% + \else\expandafter\UTFviiiFourOctets\expandafter$\fi + }}% \UTFviiiLoop \endgroup +\def\globallet{\global\let} % save some \expandafter's below + +% @U{xxxx} to produce U+xxxx, if we support it. +\def\U#1{% + \expandafter\ifx\csname uni:#1\endcsname \relax + \iftxinativeunicodecapable + % All Unicode characters can be used if native Unicode handling is + % active. However, if the font does not have the glyph, + % letters are missing. + \begingroup + \uccode`\.="#1\relax + \uppercase{.} + \endgroup + \else + \errhelp = \EMsimple + \errmessage{Unicode character U+#1 not supported, sorry}% + \fi + \else + \csname uni:#1\endcsname + \fi +} + +% These macros are used here to construct the name of a control +% sequence to be defined. +\def\UTFviiiTwoOctetsName#1#2{% + \csname u8:#1\string #2\endcsname}% +\def\UTFviiiThreeOctetsName#1#2#3{% + \csname u8:#1\string #2\string #3\endcsname}% +\def\UTFviiiFourOctetsName#1#2#3#4{% + \csname u8:#1\string #2\string #3\string #4\endcsname}% + +% For UTF-8 byte sequences (TeX, e-TeX and pdfTeX), +% provide a definition macro to replace a Unicode character; +% this gets used by the @U command +% \begingroup \catcode`\"=12 \catcode`\<=12 @@ -9200,465 +10315,838 @@ directory should work if nowhere else does.} \catcode`\;=12 \catcode`\!=12 \catcode`\~=13 - - \gdef\DeclareUnicodeCharacter#1#2{% + \gdef\DeclareUnicodeCharacterUTFviii#1#2{% \countUTFz = "#1\relax - %\wlog{\space\space defining Unicode char U+#1 (decimal \the\countUTFz)}% \begingroup \parseXMLCharref - \def\UTFviiiTwoOctets##1##2{% - \csname u8:##1\string ##2\endcsname}% - \def\UTFviiiThreeOctets##1##2##3{% - \csname u8:##1\string ##2\string ##3\endcsname}% - \def\UTFviiiFourOctets##1##2##3##4{% - \csname u8:##1\string ##2\string ##3\string ##4\endcsname}% - \expandafter\expandafter\expandafter\expandafter - \expandafter\expandafter\expandafter - \gdef\UTFviiiTmp{#2}% - \endgroup} + % Give \u8:... its definition. The sequence of seven \expandafter's + % expands after the \gdef three times, e.g. + % + % 1. \UTFviiTwoOctetsName B1 B2 + % 2. \csname u8:B1 \string B2 \endcsname + % 3. \u8: B1 B2 (a single control sequence token) + % + \expandafter\expandafter + \expandafter\expandafter + \expandafter\expandafter + \expandafter\gdef \UTFviiiTmp{#2}% + % + \expandafter\ifx\csname uni:#1\endcsname \relax \else + \message{Internal error, already defined: #1}% + \fi + % + % define an additional control sequence for this code point. + \expandafter\globallet\csname uni:#1\endcsname \UTFviiiTmp + \endgroup} + % + % Given the value in \countUTFz as a Unicode code point, set \UTFviiiTmp + % to the corresponding UTF-8 sequence. \gdef\parseXMLCharref{% \ifnum\countUTFz < "A0\relax \errhelp = \EMsimple \errmessage{Cannot define Unicode char value < 00A0}% \else\ifnum\countUTFz < "800\relax \parseUTFviiiA,% - \parseUTFviiiB C\UTFviiiTwoOctets.,% + \parseUTFviiiB C\UTFviiiTwoOctetsName.,% \else\ifnum\countUTFz < "10000\relax \parseUTFviiiA;% \parseUTFviiiA,% - \parseUTFviiiB E\UTFviiiThreeOctets.{,;}% + \parseUTFviiiB E\UTFviiiThreeOctetsName.{,;}% \else \parseUTFviiiA;% \parseUTFviiiA,% \parseUTFviiiA!% - \parseUTFviiiB F\UTFviiiFourOctets.{!,;}% + \parseUTFviiiB F\UTFviiiFourOctetsName.{!,;}% \fi\fi\fi } + % Extract a byte from the end of the UTF-8 representation of \countUTFx. + % It must be a non-initial byte in the sequence. + % Change \uccode of #1 for it to be used in \parseUTFviiiB as one + % of the bytes. \gdef\parseUTFviiiA#1{% \countUTFx = \countUTFz \divide\countUTFz by 64 - \countUTFy = \countUTFz + \countUTFy = \countUTFz % Save to be the future value of \countUTFz. \multiply\countUTFz by 64 + + % \countUTFz is now \countUTFx with the last 5 bits cleared. Subtract + % in order to get the last five bits. \advance\countUTFx by -\countUTFz + + % Convert this to the byte in the UTF-8 sequence. \advance\countUTFx by 128 \uccode `#1\countUTFx \countUTFz = \countUTFy} + % Used to put a UTF-8 byte sequence into \UTFviiiTmp + % #1 is the increment for \countUTFz to yield a the first byte of the UTF-8 + % sequence. + % #2 is one of the \UTFviii*OctetsName macros. + % #3 is always a full stop (.) + % #4 is a template for the other bytes in the sequence. The values for these + % bytes is substituted in here with \uppercase using the \uccode's. \gdef\parseUTFviiiB#1#2#3#4{% \advance\countUTFz by "#10\relax \uccode `#3\countUTFz \uppercase{\gdef\UTFviiiTmp{#2#3#4}}} \endgroup +% For native Unicode handling (XeTeX and LuaTeX), +% provide a definition macro that sets a catcode to `other' non-globally +% +\def\DeclareUnicodeCharacterNativeOther#1#2{% + \catcode"#1=\other +} + +% https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_M +% U+0000..U+007F = https://en.wikipedia.org/wiki/Basic_Latin_(Unicode_block) +% U+0080..U+00FF = https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block) +% U+0100..U+017F = https://en.wikipedia.org/wiki/Latin_Extended-A +% U+0180..U+024F = https://en.wikipedia.org/wiki/Latin_Extended-B +% +% Many of our renditions are less than wonderful, and all the missing +% characters are available somewhere. Loading the necessary fonts +% awaits user request. We can't truly support Unicode without +% reimplementing everything that's been done in LaTeX for many years, +% plus probably using luatex or xetex, and who knows what else. +% We won't be doing that here in this simple file. But we can try to at +% least make most of the characters not bomb out. +% +\def\unicodechardefs{% + \DeclareUnicodeCharacter{00A0}{\tie}% + \DeclareUnicodeCharacter{00A1}{\exclamdown}% + \DeclareUnicodeCharacter{00A2}{{\tcfont \char162}}% 0242=cent + \DeclareUnicodeCharacter{00A3}{\pounds{}}% + \DeclareUnicodeCharacter{00A4}{{\tcfont \char164}}% 0244=currency + \DeclareUnicodeCharacter{00A5}{{\tcfont \char165}}% 0245=yen + \DeclareUnicodeCharacter{00A6}{{\tcfont \char166}}% 0246=brokenbar + \DeclareUnicodeCharacter{00A7}{\S}% + \DeclareUnicodeCharacter{00A8}{\"{ }}% + \DeclareUnicodeCharacter{00A9}{\copyright{}}% + \DeclareUnicodeCharacter{00AA}{\ordf}% + \DeclareUnicodeCharacter{00AB}{\guillemetleft{}}% + \DeclareUnicodeCharacter{00AC}{\ensuremath\lnot}% + \DeclareUnicodeCharacter{00AD}{\-}% + \DeclareUnicodeCharacter{00AE}{\registeredsymbol{}}% + \DeclareUnicodeCharacter{00AF}{\={ }}% + % + \DeclareUnicodeCharacter{00B0}{\ringaccent{ }}% + \DeclareUnicodeCharacter{00B1}{\ensuremath\pm}% + \DeclareUnicodeCharacter{00B2}{$^2$}% + \DeclareUnicodeCharacter{00B3}{$^3$}% + \DeclareUnicodeCharacter{00B4}{\'{ }}% + \DeclareUnicodeCharacter{00B5}{$\mu$}% + \DeclareUnicodeCharacter{00B6}{\P}% + \DeclareUnicodeCharacter{00B7}{\ensuremath\cdot}% + \DeclareUnicodeCharacter{00B8}{\cedilla{ }}% + \DeclareUnicodeCharacter{00B9}{$^1$}% + \DeclareUnicodeCharacter{00BA}{\ordm}% + \DeclareUnicodeCharacter{00BB}{\guillemetright{}}% + \DeclareUnicodeCharacter{00BC}{$1\over4$}% + \DeclareUnicodeCharacter{00BD}{$1\over2$}% + \DeclareUnicodeCharacter{00BE}{$3\over4$}% + \DeclareUnicodeCharacter{00BF}{\questiondown}% + % + \DeclareUnicodeCharacter{00C0}{\`A}% + \DeclareUnicodeCharacter{00C1}{\'A}% + \DeclareUnicodeCharacter{00C2}{\^A}% + \DeclareUnicodeCharacter{00C3}{\~A}% + \DeclareUnicodeCharacter{00C4}{\"A}% + \DeclareUnicodeCharacter{00C5}{\AA}% + \DeclareUnicodeCharacter{00C6}{\AE}% + \DeclareUnicodeCharacter{00C7}{\cedilla{C}}% + \DeclareUnicodeCharacter{00C8}{\`E}% + \DeclareUnicodeCharacter{00C9}{\'E}% + \DeclareUnicodeCharacter{00CA}{\^E}% + \DeclareUnicodeCharacter{00CB}{\"E}% + \DeclareUnicodeCharacter{00CC}{\`I}% + \DeclareUnicodeCharacter{00CD}{\'I}% + \DeclareUnicodeCharacter{00CE}{\^I}% + \DeclareUnicodeCharacter{00CF}{\"I}% + % + \DeclareUnicodeCharacter{00D0}{\DH}% + \DeclareUnicodeCharacter{00D1}{\~N}% + \DeclareUnicodeCharacter{00D2}{\`O}% + \DeclareUnicodeCharacter{00D3}{\'O}% + \DeclareUnicodeCharacter{00D4}{\^O}% + \DeclareUnicodeCharacter{00D5}{\~O}% + \DeclareUnicodeCharacter{00D6}{\"O}% + \DeclareUnicodeCharacter{00D7}{\ensuremath\times}% + \DeclareUnicodeCharacter{00D8}{\O}% + \DeclareUnicodeCharacter{00D9}{\`U}% + \DeclareUnicodeCharacter{00DA}{\'U}% + \DeclareUnicodeCharacter{00DB}{\^U}% + \DeclareUnicodeCharacter{00DC}{\"U}% + \DeclareUnicodeCharacter{00DD}{\'Y}% + \DeclareUnicodeCharacter{00DE}{\TH}% + \DeclareUnicodeCharacter{00DF}{\ss}% + % + \DeclareUnicodeCharacter{00E0}{\`a}% + \DeclareUnicodeCharacter{00E1}{\'a}% + \DeclareUnicodeCharacter{00E2}{\^a}% + \DeclareUnicodeCharacter{00E3}{\~a}% + \DeclareUnicodeCharacter{00E4}{\"a}% + \DeclareUnicodeCharacter{00E5}{\aa}% + \DeclareUnicodeCharacter{00E6}{\ae}% + \DeclareUnicodeCharacter{00E7}{\cedilla{c}}% + \DeclareUnicodeCharacter{00E8}{\`e}% + \DeclareUnicodeCharacter{00E9}{\'e}% + \DeclareUnicodeCharacter{00EA}{\^e}% + \DeclareUnicodeCharacter{00EB}{\"e}% + \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}}% + \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}}% + \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}}% + \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}}% + % + \DeclareUnicodeCharacter{00F0}{\dh}% + \DeclareUnicodeCharacter{00F1}{\~n}% + \DeclareUnicodeCharacter{00F2}{\`o}% + \DeclareUnicodeCharacter{00F3}{\'o}% + \DeclareUnicodeCharacter{00F4}{\^o}% + \DeclareUnicodeCharacter{00F5}{\~o}% + \DeclareUnicodeCharacter{00F6}{\"o}% + \DeclareUnicodeCharacter{00F7}{\ensuremath\div}% + \DeclareUnicodeCharacter{00F8}{\o}% + \DeclareUnicodeCharacter{00F9}{\`u}% + \DeclareUnicodeCharacter{00FA}{\'u}% + \DeclareUnicodeCharacter{00FB}{\^u}% + \DeclareUnicodeCharacter{00FC}{\"u}% + \DeclareUnicodeCharacter{00FD}{\'y}% + \DeclareUnicodeCharacter{00FE}{\th}% + \DeclareUnicodeCharacter{00FF}{\"y}% + % + \DeclareUnicodeCharacter{0100}{\=A}% + \DeclareUnicodeCharacter{0101}{\=a}% + \DeclareUnicodeCharacter{0102}{\u{A}}% + \DeclareUnicodeCharacter{0103}{\u{a}}% + \DeclareUnicodeCharacter{0104}{\ogonek{A}}% + \DeclareUnicodeCharacter{0105}{\ogonek{a}}% + \DeclareUnicodeCharacter{0106}{\'C}% + \DeclareUnicodeCharacter{0107}{\'c}% + \DeclareUnicodeCharacter{0108}{\^C}% + \DeclareUnicodeCharacter{0109}{\^c}% + \DeclareUnicodeCharacter{010A}{\dotaccent{C}}% + \DeclareUnicodeCharacter{010B}{\dotaccent{c}}% + \DeclareUnicodeCharacter{010C}{\v{C}}% + \DeclareUnicodeCharacter{010D}{\v{c}}% + \DeclareUnicodeCharacter{010E}{\v{D}}% + \DeclareUnicodeCharacter{010F}{d'}% + % + \DeclareUnicodeCharacter{0110}{\DH}% + \DeclareUnicodeCharacter{0111}{\dh}% + \DeclareUnicodeCharacter{0112}{\=E}% + \DeclareUnicodeCharacter{0113}{\=e}% + \DeclareUnicodeCharacter{0114}{\u{E}}% + \DeclareUnicodeCharacter{0115}{\u{e}}% + \DeclareUnicodeCharacter{0116}{\dotaccent{E}}% + \DeclareUnicodeCharacter{0117}{\dotaccent{e}}% + \DeclareUnicodeCharacter{0118}{\ogonek{E}}% + \DeclareUnicodeCharacter{0119}{\ogonek{e}}% + \DeclareUnicodeCharacter{011A}{\v{E}}% + \DeclareUnicodeCharacter{011B}{\v{e}}% + \DeclareUnicodeCharacter{011C}{\^G}% + \DeclareUnicodeCharacter{011D}{\^g}% + \DeclareUnicodeCharacter{011E}{\u{G}}% + \DeclareUnicodeCharacter{011F}{\u{g}}% + % + \DeclareUnicodeCharacter{0120}{\dotaccent{G}}% + \DeclareUnicodeCharacter{0121}{\dotaccent{g}}% + \DeclareUnicodeCharacter{0122}{\cedilla{G}}% + \DeclareUnicodeCharacter{0123}{\cedilla{g}}% + \DeclareUnicodeCharacter{0124}{\^H}% + \DeclareUnicodeCharacter{0125}{\^h}% + \DeclareUnicodeCharacter{0126}{\missingcharmsg{H WITH STROKE}}% + \DeclareUnicodeCharacter{0127}{\missingcharmsg{h WITH STROKE}}% + \DeclareUnicodeCharacter{0128}{\~I}% + \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}}% + \DeclareUnicodeCharacter{012A}{\=I}% + \DeclareUnicodeCharacter{012B}{\={\dotless{i}}}% + \DeclareUnicodeCharacter{012C}{\u{I}}% + \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}}% + \DeclareUnicodeCharacter{012E}{\ogonek{I}}% + \DeclareUnicodeCharacter{012F}{\ogonek{i}}% + % + \DeclareUnicodeCharacter{0130}{\dotaccent{I}}% + \DeclareUnicodeCharacter{0131}{\dotless{i}}% + \DeclareUnicodeCharacter{0132}{IJ}% + \DeclareUnicodeCharacter{0133}{ij}% + \DeclareUnicodeCharacter{0134}{\^J}% + \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}}% + \DeclareUnicodeCharacter{0136}{\cedilla{K}}% + \DeclareUnicodeCharacter{0137}{\cedilla{k}}% + \DeclareUnicodeCharacter{0138}{\ensuremath\kappa}% + \DeclareUnicodeCharacter{0139}{\'L}% + \DeclareUnicodeCharacter{013A}{\'l}% + \DeclareUnicodeCharacter{013B}{\cedilla{L}}% + \DeclareUnicodeCharacter{013C}{\cedilla{l}}% + \DeclareUnicodeCharacter{013D}{L'}% should kern + \DeclareUnicodeCharacter{013E}{l'}% should kern + \DeclareUnicodeCharacter{013F}{L\U{00B7}}% + % + \DeclareUnicodeCharacter{0140}{l\U{00B7}}% + \DeclareUnicodeCharacter{0141}{\L}% + \DeclareUnicodeCharacter{0142}{\l}% + \DeclareUnicodeCharacter{0143}{\'N}% + \DeclareUnicodeCharacter{0144}{\'n}% + \DeclareUnicodeCharacter{0145}{\cedilla{N}}% + \DeclareUnicodeCharacter{0146}{\cedilla{n}}% + \DeclareUnicodeCharacter{0147}{\v{N}}% + \DeclareUnicodeCharacter{0148}{\v{n}}% + \DeclareUnicodeCharacter{0149}{'n}% + \DeclareUnicodeCharacter{014A}{\missingcharmsg{ENG}}% + \DeclareUnicodeCharacter{014B}{\missingcharmsg{eng}}% + \DeclareUnicodeCharacter{014C}{\=O}% + \DeclareUnicodeCharacter{014D}{\=o}% + \DeclareUnicodeCharacter{014E}{\u{O}}% + \DeclareUnicodeCharacter{014F}{\u{o}}% + % + \DeclareUnicodeCharacter{0150}{\H{O}}% + \DeclareUnicodeCharacter{0151}{\H{o}}% + \DeclareUnicodeCharacter{0152}{\OE}% + \DeclareUnicodeCharacter{0153}{\oe}% + \DeclareUnicodeCharacter{0154}{\'R}% + \DeclareUnicodeCharacter{0155}{\'r}% + \DeclareUnicodeCharacter{0156}{\cedilla{R}}% + \DeclareUnicodeCharacter{0157}{\cedilla{r}}% + \DeclareUnicodeCharacter{0158}{\v{R}}% + \DeclareUnicodeCharacter{0159}{\v{r}}% + \DeclareUnicodeCharacter{015A}{\'S}% + \DeclareUnicodeCharacter{015B}{\'s}% + \DeclareUnicodeCharacter{015C}{\^S}% + \DeclareUnicodeCharacter{015D}{\^s}% + \DeclareUnicodeCharacter{015E}{\cedilla{S}}% + \DeclareUnicodeCharacter{015F}{\cedilla{s}}% + % + \DeclareUnicodeCharacter{0160}{\v{S}}% + \DeclareUnicodeCharacter{0161}{\v{s}}% + \DeclareUnicodeCharacter{0162}{\cedilla{T}}% + \DeclareUnicodeCharacter{0163}{\cedilla{t}}% + \DeclareUnicodeCharacter{0164}{\v{T}}% + \DeclareUnicodeCharacter{0165}{\v{t}}% + \DeclareUnicodeCharacter{0166}{\missingcharmsg{H WITH STROKE}}% + \DeclareUnicodeCharacter{0167}{\missingcharmsg{h WITH STROKE}}% + \DeclareUnicodeCharacter{0168}{\~U}% + \DeclareUnicodeCharacter{0169}{\~u}% + \DeclareUnicodeCharacter{016A}{\=U}% + \DeclareUnicodeCharacter{016B}{\=u}% + \DeclareUnicodeCharacter{016C}{\u{U}}% + \DeclareUnicodeCharacter{016D}{\u{u}}% + \DeclareUnicodeCharacter{016E}{\ringaccent{U}}% + \DeclareUnicodeCharacter{016F}{\ringaccent{u}}% + % + \DeclareUnicodeCharacter{0170}{\H{U}}% + \DeclareUnicodeCharacter{0171}{\H{u}}% + \DeclareUnicodeCharacter{0172}{\ogonek{U}}% + \DeclareUnicodeCharacter{0173}{\ogonek{u}}% + \DeclareUnicodeCharacter{0174}{\^W}% + \DeclareUnicodeCharacter{0175}{\^w}% + \DeclareUnicodeCharacter{0176}{\^Y}% + \DeclareUnicodeCharacter{0177}{\^y}% + \DeclareUnicodeCharacter{0178}{\"Y}% + \DeclareUnicodeCharacter{0179}{\'Z}% + \DeclareUnicodeCharacter{017A}{\'z}% + \DeclareUnicodeCharacter{017B}{\dotaccent{Z}}% + \DeclareUnicodeCharacter{017C}{\dotaccent{z}}% + \DeclareUnicodeCharacter{017D}{\v{Z}}% + \DeclareUnicodeCharacter{017E}{\v{z}}% + \DeclareUnicodeCharacter{017F}{\missingcharmsg{LONG S}}% + % + \DeclareUnicodeCharacter{01C4}{D\v{Z}}% + \DeclareUnicodeCharacter{01C5}{D\v{z}}% + \DeclareUnicodeCharacter{01C6}{d\v{z}}% + \DeclareUnicodeCharacter{01C7}{LJ}% + \DeclareUnicodeCharacter{01C8}{Lj}% + \DeclareUnicodeCharacter{01C9}{lj}% + \DeclareUnicodeCharacter{01CA}{NJ}% + \DeclareUnicodeCharacter{01CB}{Nj}% + \DeclareUnicodeCharacter{01CC}{nj}% + \DeclareUnicodeCharacter{01CD}{\v{A}}% + \DeclareUnicodeCharacter{01CE}{\v{a}}% + \DeclareUnicodeCharacter{01CF}{\v{I}}% + % + \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}}% + \DeclareUnicodeCharacter{01D1}{\v{O}}% + \DeclareUnicodeCharacter{01D2}{\v{o}}% + \DeclareUnicodeCharacter{01D3}{\v{U}}% + \DeclareUnicodeCharacter{01D4}{\v{u}}% + % + \DeclareUnicodeCharacter{01E2}{\={\AE}}% + \DeclareUnicodeCharacter{01E3}{\={\ae}}% + \DeclareUnicodeCharacter{01E6}{\v{G}}% + \DeclareUnicodeCharacter{01E7}{\v{g}}% + \DeclareUnicodeCharacter{01E8}{\v{K}}% + \DeclareUnicodeCharacter{01E9}{\v{k}}% + % + \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}}% + \DeclareUnicodeCharacter{01F1}{DZ}% + \DeclareUnicodeCharacter{01F2}{Dz}% + \DeclareUnicodeCharacter{01F3}{dz}% + \DeclareUnicodeCharacter{01F4}{\'G}% + \DeclareUnicodeCharacter{01F5}{\'g}% + \DeclareUnicodeCharacter{01F8}{\`N}% + \DeclareUnicodeCharacter{01F9}{\`n}% + \DeclareUnicodeCharacter{01FC}{\'{\AE}}% + \DeclareUnicodeCharacter{01FD}{\'{\ae}}% + \DeclareUnicodeCharacter{01FE}{\'{\O}}% + \DeclareUnicodeCharacter{01FF}{\'{\o}}% + % + \DeclareUnicodeCharacter{021E}{\v{H}}% + \DeclareUnicodeCharacter{021F}{\v{h}}% + % + \DeclareUnicodeCharacter{0226}{\dotaccent{A}}% + \DeclareUnicodeCharacter{0227}{\dotaccent{a}}% + \DeclareUnicodeCharacter{0228}{\cedilla{E}}% + \DeclareUnicodeCharacter{0229}{\cedilla{e}}% + \DeclareUnicodeCharacter{022E}{\dotaccent{O}}% + \DeclareUnicodeCharacter{022F}{\dotaccent{o}}% + % + \DeclareUnicodeCharacter{0232}{\=Y}% + \DeclareUnicodeCharacter{0233}{\=y}% + \DeclareUnicodeCharacter{0237}{\dotless{j}}% + % + \DeclareUnicodeCharacter{02DB}{\ogonek{ }}% + % + % Greek letters upper case + \DeclareUnicodeCharacter{0391}{{\it A}}% + \DeclareUnicodeCharacter{0392}{{\it B}}% + \DeclareUnicodeCharacter{0393}{\ensuremath{\mit\Gamma}}% + \DeclareUnicodeCharacter{0394}{\ensuremath{\mit\Delta}}% + \DeclareUnicodeCharacter{0395}{{\it E}}% + \DeclareUnicodeCharacter{0396}{{\it Z}}% + \DeclareUnicodeCharacter{0397}{{\it H}}% + \DeclareUnicodeCharacter{0398}{\ensuremath{\mit\Theta}}% + \DeclareUnicodeCharacter{0399}{{\it I}}% + \DeclareUnicodeCharacter{039A}{{\it K}}% + \DeclareUnicodeCharacter{039B}{\ensuremath{\mit\Lambda}}% + \DeclareUnicodeCharacter{039C}{{\it M}}% + \DeclareUnicodeCharacter{039D}{{\it N}}% + \DeclareUnicodeCharacter{039E}{\ensuremath{\mit\Xi}}% + \DeclareUnicodeCharacter{039F}{{\it O}}% + \DeclareUnicodeCharacter{03A0}{\ensuremath{\mit\Pi}}% + \DeclareUnicodeCharacter{03A1}{{\it P}}% + %\DeclareUnicodeCharacter{03A2}{} % none - corresponds to final sigma + \DeclareUnicodeCharacter{03A3}{\ensuremath{\mit\Sigma}}% + \DeclareUnicodeCharacter{03A4}{{\it T}}% + \DeclareUnicodeCharacter{03A5}{\ensuremath{\mit\Upsilon}}% + \DeclareUnicodeCharacter{03A6}{\ensuremath{\mit\Phi}}% + \DeclareUnicodeCharacter{03A7}{{\it X}}% + \DeclareUnicodeCharacter{03A8}{\ensuremath{\mit\Psi}}% + \DeclareUnicodeCharacter{03A9}{\ensuremath{\mit\Omega}}% + % + % Vowels with accents + \DeclareUnicodeCharacter{0390}{\ensuremath{\ddot{\acute\iota}}}% + \DeclareUnicodeCharacter{03AC}{\ensuremath{\acute\alpha}}% + \DeclareUnicodeCharacter{03AD}{\ensuremath{\acute\epsilon}}% + \DeclareUnicodeCharacter{03AE}{\ensuremath{\acute\eta}}% + \DeclareUnicodeCharacter{03AF}{\ensuremath{\acute\iota}}% + \DeclareUnicodeCharacter{03B0}{\ensuremath{\acute{\ddot\upsilon}}}% + % + % Standalone accent + \DeclareUnicodeCharacter{0384}{\ensuremath{\acute{\ }}}% + % + % Greek letters lower case + \DeclareUnicodeCharacter{03B1}{\ensuremath\alpha}% + \DeclareUnicodeCharacter{03B2}{\ensuremath\beta}% + \DeclareUnicodeCharacter{03B3}{\ensuremath\gamma}% + \DeclareUnicodeCharacter{03B4}{\ensuremath\delta}% + \DeclareUnicodeCharacter{03B5}{\ensuremath\epsilon}% + \DeclareUnicodeCharacter{03B6}{\ensuremath\zeta}% + \DeclareUnicodeCharacter{03B7}{\ensuremath\eta}% + \DeclareUnicodeCharacter{03B8}{\ensuremath\theta}% + \DeclareUnicodeCharacter{03B9}{\ensuremath\iota}% + \DeclareUnicodeCharacter{03BA}{\ensuremath\kappa}% + \DeclareUnicodeCharacter{03BB}{\ensuremath\lambda}% + \DeclareUnicodeCharacter{03BC}{\ensuremath\mu}% + \DeclareUnicodeCharacter{03BD}{\ensuremath\nu}% + \DeclareUnicodeCharacter{03BE}{\ensuremath\xi}% + \DeclareUnicodeCharacter{03BF}{{\it o}}% omicron + \DeclareUnicodeCharacter{03C0}{\ensuremath\pi}% + \DeclareUnicodeCharacter{03C1}{\ensuremath\rho}% + \DeclareUnicodeCharacter{03C2}{\ensuremath\varsigma}% + \DeclareUnicodeCharacter{03C3}{\ensuremath\sigma}% + \DeclareUnicodeCharacter{03C4}{\ensuremath\tau}% + \DeclareUnicodeCharacter{03C5}{\ensuremath\upsilon}% + \DeclareUnicodeCharacter{03C6}{\ensuremath\phi}% + \DeclareUnicodeCharacter{03C7}{\ensuremath\chi}% + \DeclareUnicodeCharacter{03C8}{\ensuremath\psi}% + \DeclareUnicodeCharacter{03C9}{\ensuremath\omega}% + % + % More Greek vowels with accents + \DeclareUnicodeCharacter{03CA}{\ensuremath{\ddot\iota}}% + \DeclareUnicodeCharacter{03CB}{\ensuremath{\ddot\upsilon}}% + \DeclareUnicodeCharacter{03CC}{\ensuremath{\acute o}}% + \DeclareUnicodeCharacter{03CD}{\ensuremath{\acute\upsilon}}% + \DeclareUnicodeCharacter{03CE}{\ensuremath{\acute\omega}}% + % + % Variant Greek letters + \DeclareUnicodeCharacter{03D1}{\ensuremath\vartheta}% + \DeclareUnicodeCharacter{03D6}{\ensuremath\varpi}% + \DeclareUnicodeCharacter{03F1}{\ensuremath\varrho}% + % + \DeclareUnicodeCharacter{1E02}{\dotaccent{B}}% + \DeclareUnicodeCharacter{1E03}{\dotaccent{b}}% + \DeclareUnicodeCharacter{1E04}{\udotaccent{B}}% + \DeclareUnicodeCharacter{1E05}{\udotaccent{b}}% + \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}}% + \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}}% + \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}}% + \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}}% + \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}}% + \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}}% + \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}}% + \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}}% + % + \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}}% + \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}}% + % + \DeclareUnicodeCharacter{1E20}{\=G}% + \DeclareUnicodeCharacter{1E21}{\=g}% + \DeclareUnicodeCharacter{1E22}{\dotaccent{H}}% + \DeclareUnicodeCharacter{1E23}{\dotaccent{h}}% + \DeclareUnicodeCharacter{1E24}{\udotaccent{H}}% + \DeclareUnicodeCharacter{1E25}{\udotaccent{h}}% + \DeclareUnicodeCharacter{1E26}{\"H}% + \DeclareUnicodeCharacter{1E27}{\"h}% + % + \DeclareUnicodeCharacter{1E30}{\'K}% + \DeclareUnicodeCharacter{1E31}{\'k}% + \DeclareUnicodeCharacter{1E32}{\udotaccent{K}}% + \DeclareUnicodeCharacter{1E33}{\udotaccent{k}}% + \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}}% + \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}}% + \DeclareUnicodeCharacter{1E36}{\udotaccent{L}}% + \DeclareUnicodeCharacter{1E37}{\udotaccent{l}}% + \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}}% + \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}}% + \DeclareUnicodeCharacter{1E3E}{\'M}% + \DeclareUnicodeCharacter{1E3F}{\'m}% + % + \DeclareUnicodeCharacter{1E40}{\dotaccent{M}}% + \DeclareUnicodeCharacter{1E41}{\dotaccent{m}}% + \DeclareUnicodeCharacter{1E42}{\udotaccent{M}}% + \DeclareUnicodeCharacter{1E43}{\udotaccent{m}}% + \DeclareUnicodeCharacter{1E44}{\dotaccent{N}}% + \DeclareUnicodeCharacter{1E45}{\dotaccent{n}}% + \DeclareUnicodeCharacter{1E46}{\udotaccent{N}}% + \DeclareUnicodeCharacter{1E47}{\udotaccent{n}}% + \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}}% + \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}}% + % + \DeclareUnicodeCharacter{1E54}{\'P}% + \DeclareUnicodeCharacter{1E55}{\'p}% + \DeclareUnicodeCharacter{1E56}{\dotaccent{P}}% + \DeclareUnicodeCharacter{1E57}{\dotaccent{p}}% + \DeclareUnicodeCharacter{1E58}{\dotaccent{R}}% + \DeclareUnicodeCharacter{1E59}{\dotaccent{r}}% + \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}}% + \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}}% + \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}}% + \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}}% + % + \DeclareUnicodeCharacter{1E60}{\dotaccent{S}}% + \DeclareUnicodeCharacter{1E61}{\dotaccent{s}}% + \DeclareUnicodeCharacter{1E62}{\udotaccent{S}}% + \DeclareUnicodeCharacter{1E63}{\udotaccent{s}}% + \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}}% + \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}}% + \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}}% + \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}}% + \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}}% + \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}}% + % + \DeclareUnicodeCharacter{1E7C}{\~V}% + \DeclareUnicodeCharacter{1E7D}{\~v}% + \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}}% + \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}}% + % + \DeclareUnicodeCharacter{1E80}{\`W}% + \DeclareUnicodeCharacter{1E81}{\`w}% + \DeclareUnicodeCharacter{1E82}{\'W}% + \DeclareUnicodeCharacter{1E83}{\'w}% + \DeclareUnicodeCharacter{1E84}{\"W}% + \DeclareUnicodeCharacter{1E85}{\"w}% + \DeclareUnicodeCharacter{1E86}{\dotaccent{W}}% + \DeclareUnicodeCharacter{1E87}{\dotaccent{w}}% + \DeclareUnicodeCharacter{1E88}{\udotaccent{W}}% + \DeclareUnicodeCharacter{1E89}{\udotaccent{w}}% + \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}}% + \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}}% + \DeclareUnicodeCharacter{1E8C}{\"X}% + \DeclareUnicodeCharacter{1E8D}{\"x}% + \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}}% + \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}}% + % + \DeclareUnicodeCharacter{1E90}{\^Z}% + \DeclareUnicodeCharacter{1E91}{\^z}% + \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}}% + \DeclareUnicodeCharacter{1E93}{\udotaccent{z}}% + \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}}% + \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}}% + \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}}% + \DeclareUnicodeCharacter{1E97}{\"t}% + \DeclareUnicodeCharacter{1E98}{\ringaccent{w}}% + \DeclareUnicodeCharacter{1E99}{\ringaccent{y}}% + % + \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}}% + \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}}% + % + \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}}% + \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}}% + \DeclareUnicodeCharacter{1EBC}{\~E}% + \DeclareUnicodeCharacter{1EBD}{\~e}% + % + \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}}% + \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}}% + \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}}% + \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}}% + % + \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}}% + \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}}% + % + \DeclareUnicodeCharacter{1EF2}{\`Y}% + \DeclareUnicodeCharacter{1EF3}{\`y}% + \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}}% + % + \DeclareUnicodeCharacter{1EF8}{\~Y}% + \DeclareUnicodeCharacter{1EF9}{\~y}% + % + % Punctuation + \DeclareUnicodeCharacter{2013}{--}% + \DeclareUnicodeCharacter{2014}{---}% + \DeclareUnicodeCharacter{2018}{\quoteleft{}}% + \DeclareUnicodeCharacter{2019}{\quoteright{}}% + \DeclareUnicodeCharacter{201A}{\quotesinglbase{}}% + \DeclareUnicodeCharacter{201C}{\quotedblleft{}}% + \DeclareUnicodeCharacter{201D}{\quotedblright{}}% + \DeclareUnicodeCharacter{201E}{\quotedblbase{}}% + \DeclareUnicodeCharacter{2020}{\ensuremath\dagger}% + \DeclareUnicodeCharacter{2021}{\ensuremath\ddagger}% + \DeclareUnicodeCharacter{2022}{\bullet{}}% + \DeclareUnicodeCharacter{202F}{\thinspace}% + \DeclareUnicodeCharacter{2026}{\dots{}}% + \DeclareUnicodeCharacter{2039}{\guilsinglleft{}}% + \DeclareUnicodeCharacter{203A}{\guilsinglright{}}% + % + \DeclareUnicodeCharacter{20AC}{\euro{}}% + % + \DeclareUnicodeCharacter{2192}{\expansion{}}% + \DeclareUnicodeCharacter{21D2}{\result{}}% + % + % Mathematical symbols + \DeclareUnicodeCharacter{2200}{\ensuremath\forall}% + \DeclareUnicodeCharacter{2203}{\ensuremath\exists}% + \DeclareUnicodeCharacter{2208}{\ensuremath\in}% + \DeclareUnicodeCharacter{2212}{\minus{}}% + \DeclareUnicodeCharacter{2217}{\ast}% + \DeclareUnicodeCharacter{221E}{\ensuremath\infty}% + \DeclareUnicodeCharacter{2225}{\ensuremath\parallel}% + \DeclareUnicodeCharacter{2227}{\ensuremath\wedge}% + \DeclareUnicodeCharacter{2229}{\ensuremath\cap}% + \DeclareUnicodeCharacter{2261}{\equiv{}}% + \DeclareUnicodeCharacter{2264}{\ensuremath\leq}% + \DeclareUnicodeCharacter{2265}{\ensuremath\geq}% + \DeclareUnicodeCharacter{2282}{\ensuremath\subset}% + \DeclareUnicodeCharacter{2287}{\ensuremath\supseteq}% + % + \DeclareUnicodeCharacter{2016}{\ensuremath\Vert}% + \DeclareUnicodeCharacter{2032}{\ensuremath\prime}% + \DeclareUnicodeCharacter{210F}{\ensuremath\hbar}% + \DeclareUnicodeCharacter{2111}{\ensuremath\Im}% + \DeclareUnicodeCharacter{2113}{\ensuremath\ell}% + \DeclareUnicodeCharacter{2118}{\ensuremath\wp}% + \DeclareUnicodeCharacter{211C}{\ensuremath\Re}% + \DeclareUnicodeCharacter{2135}{\ensuremath\aleph}% + \DeclareUnicodeCharacter{2190}{\ensuremath\leftarrow}% + \DeclareUnicodeCharacter{2191}{\ensuremath\uparrow}% + \DeclareUnicodeCharacter{2193}{\ensuremath\downarrow}% + \DeclareUnicodeCharacter{2194}{\ensuremath\leftrightarrow}% + \DeclareUnicodeCharacter{2195}{\ensuremath\updownarrow}% + \DeclareUnicodeCharacter{2196}{\ensuremath\nwarrow}% + \DeclareUnicodeCharacter{2197}{\ensuremath\nearrow}% + \DeclareUnicodeCharacter{2198}{\ensuremath\searrow}% + \DeclareUnicodeCharacter{2199}{\ensuremath\swarrow}% + \DeclareUnicodeCharacter{21A6}{\ensuremath\mapsto}% + \DeclareUnicodeCharacter{21A9}{\ensuremath\hookleftarrow}% + \DeclareUnicodeCharacter{21AA}{\ensuremath\hookrightarrow}% + \DeclareUnicodeCharacter{21BC}{\ensuremath\leftharpoonup}% + \DeclareUnicodeCharacter{21BD}{\ensuremath\leftharpoondown}% + \DeclareUnicodeCharacter{21C0}{\ensuremath\rightharpoonup}% + \DeclareUnicodeCharacter{21C1}{\ensuremath\rightharpoondown}% + \DeclareUnicodeCharacter{21CC}{\ensuremath\rightleftharpoons}% + \DeclareUnicodeCharacter{21D0}{\ensuremath\Leftarrow}% + \DeclareUnicodeCharacter{21D1}{\ensuremath\Uparrow}% + \DeclareUnicodeCharacter{21D3}{\ensuremath\Downarrow}% + \DeclareUnicodeCharacter{21D4}{\ensuremath\Leftrightarrow}% + \DeclareUnicodeCharacter{21D5}{\ensuremath\Updownarrow}% + \DeclareUnicodeCharacter{2202}{\ensuremath\partial}% + \DeclareUnicodeCharacter{2205}{\ensuremath\emptyset}% + \DeclareUnicodeCharacter{2207}{\ensuremath\nabla}% + \DeclareUnicodeCharacter{2209}{\ensuremath\notin}% + \DeclareUnicodeCharacter{220B}{\ensuremath\owns}% + \DeclareUnicodeCharacter{220F}{\ensuremath\prod}% + \DeclareUnicodeCharacter{2210}{\ensuremath\coprod}% + \DeclareUnicodeCharacter{2211}{\ensuremath\sum}% + \DeclareUnicodeCharacter{2213}{\ensuremath\mp}% + \DeclareUnicodeCharacter{2218}{\ensuremath\circ}% + \DeclareUnicodeCharacter{221A}{\ensuremath\surd}% + \DeclareUnicodeCharacter{221D}{\ensuremath\propto}% + \DeclareUnicodeCharacter{2220}{\ensuremath\angle}% + \DeclareUnicodeCharacter{2223}{\ensuremath\mid}% + \DeclareUnicodeCharacter{2228}{\ensuremath\vee}% + \DeclareUnicodeCharacter{222A}{\ensuremath\cup}% + \DeclareUnicodeCharacter{222B}{\ensuremath\smallint}% + \DeclareUnicodeCharacter{222E}{\ensuremath\oint}% + \DeclareUnicodeCharacter{223C}{\ensuremath\sim}% + \DeclareUnicodeCharacter{2240}{\ensuremath\wr}% + \DeclareUnicodeCharacter{2243}{\ensuremath\simeq}% + \DeclareUnicodeCharacter{2245}{\ensuremath\cong}% + \DeclareUnicodeCharacter{2248}{\ensuremath\approx}% + \DeclareUnicodeCharacter{224D}{\ensuremath\asymp}% + \DeclareUnicodeCharacter{2250}{\ensuremath\doteq}% + \DeclareUnicodeCharacter{2260}{\ensuremath\neq}% + \DeclareUnicodeCharacter{226A}{\ensuremath\ll}% + \DeclareUnicodeCharacter{226B}{\ensuremath\gg}% + \DeclareUnicodeCharacter{227A}{\ensuremath\prec}% + \DeclareUnicodeCharacter{227B}{\ensuremath\succ}% + \DeclareUnicodeCharacter{2283}{\ensuremath\supset}% + \DeclareUnicodeCharacter{2286}{\ensuremath\subseteq}% + \DeclareUnicodeCharacter{228E}{\ensuremath\uplus}% + \DeclareUnicodeCharacter{2291}{\ensuremath\sqsubseteq}% + \DeclareUnicodeCharacter{2292}{\ensuremath\sqsupseteq}% + \DeclareUnicodeCharacter{2293}{\ensuremath\sqcap}% + \DeclareUnicodeCharacter{2294}{\ensuremath\sqcup}% + \DeclareUnicodeCharacter{2295}{\ensuremath\oplus}% + \DeclareUnicodeCharacter{2296}{\ensuremath\ominus}% + \DeclareUnicodeCharacter{2297}{\ensuremath\otimes}% + \DeclareUnicodeCharacter{2298}{\ensuremath\oslash}% + \DeclareUnicodeCharacter{2299}{\ensuremath\odot}% + \DeclareUnicodeCharacter{22A2}{\ensuremath\vdash}% + \DeclareUnicodeCharacter{22A3}{\ensuremath\dashv}% + \DeclareUnicodeCharacter{22A4}{\ensuremath\ptextop}% + \DeclareUnicodeCharacter{22A5}{\ensuremath\bot}% + \DeclareUnicodeCharacter{22A8}{\ensuremath\models}% + \DeclareUnicodeCharacter{22C0}{\ensuremath\bigwedge}% + \DeclareUnicodeCharacter{22C1}{\ensuremath\bigvee}% + \DeclareUnicodeCharacter{22C2}{\ensuremath\bigcap}% + \DeclareUnicodeCharacter{22C3}{\ensuremath\bigcup}% + \DeclareUnicodeCharacter{22C4}{\ensuremath\diamond}% + \DeclareUnicodeCharacter{22C5}{\ensuremath\cdot}% + \DeclareUnicodeCharacter{22C6}{\ensuremath\star}% + \DeclareUnicodeCharacter{22C8}{\ensuremath\bowtie}% + \DeclareUnicodeCharacter{2308}{\ensuremath\lceil}% + \DeclareUnicodeCharacter{2309}{\ensuremath\rceil}% + \DeclareUnicodeCharacter{230A}{\ensuremath\lfloor}% + \DeclareUnicodeCharacter{230B}{\ensuremath\rfloor}% + \DeclareUnicodeCharacter{2322}{\ensuremath\frown}% + \DeclareUnicodeCharacter{2323}{\ensuremath\smile}% + % + \DeclareUnicodeCharacter{25B3}{\ensuremath\triangle}% + \DeclareUnicodeCharacter{25B7}{\ensuremath\triangleright}% + \DeclareUnicodeCharacter{25BD}{\ensuremath\bigtriangledown}% + \DeclareUnicodeCharacter{25C1}{\ensuremath\triangleleft}% + \DeclareUnicodeCharacter{25C7}{\ensuremath\diamond}% + \DeclareUnicodeCharacter{2660}{\ensuremath\spadesuit}% + \DeclareUnicodeCharacter{2661}{\ensuremath\heartsuit}% + \DeclareUnicodeCharacter{2662}{\ensuremath\diamondsuit}% + \DeclareUnicodeCharacter{2663}{\ensuremath\clubsuit}% + \DeclareUnicodeCharacter{266D}{\ensuremath\flat}% + \DeclareUnicodeCharacter{266E}{\ensuremath\natural}% + \DeclareUnicodeCharacter{266F}{\ensuremath\sharp}% + \DeclareUnicodeCharacter{26AA}{\ensuremath\bigcirc}% + \DeclareUnicodeCharacter{27B9}{\ensuremath\rangle}% + \DeclareUnicodeCharacter{27C2}{\ensuremath\perp}% + \DeclareUnicodeCharacter{27E8}{\ensuremath\langle}% + \DeclareUnicodeCharacter{27F5}{\ensuremath\longleftarrow}% + \DeclareUnicodeCharacter{27F6}{\ensuremath\longrightarrow}% + \DeclareUnicodeCharacter{27F7}{\ensuremath\longleftrightarrow}% + \DeclareUnicodeCharacter{27FC}{\ensuremath\longmapsto}% + \DeclareUnicodeCharacter{29F5}{\ensuremath\setminus}% + \DeclareUnicodeCharacter{2A00}{\ensuremath\bigodot}% + \DeclareUnicodeCharacter{2A01}{\ensuremath\bigoplus}% + \DeclareUnicodeCharacter{2A02}{\ensuremath\bigotimes}% + \DeclareUnicodeCharacter{2A04}{\ensuremath\biguplus}% + \DeclareUnicodeCharacter{2A06}{\ensuremath\bigsqcup}% + \DeclareUnicodeCharacter{2A3F}{\ensuremath\amalg}% + \DeclareUnicodeCharacter{2AAF}{\ensuremath\preceq}% + \DeclareUnicodeCharacter{2AB0}{\ensuremath\succeq}% + % + \global\mathchardef\checkmark="1370% actually the square root sign + \DeclareUnicodeCharacter{2713}{\ensuremath\checkmark}% +}% end of \unicodechardefs + +% UTF-8 byte sequence (pdfTeX) definitions (replacing and @U command) +% It makes the setting that replace UTF-8 byte sequence. \def\utfeightchardefs{% - \DeclareUnicodeCharacter{00A0}{\tie} - \DeclareUnicodeCharacter{00A1}{\exclamdown} - \DeclareUnicodeCharacter{00A3}{\pounds} - \DeclareUnicodeCharacter{00A8}{\"{ }} - \DeclareUnicodeCharacter{00A9}{\copyright} - \DeclareUnicodeCharacter{00AA}{\ordf} - \DeclareUnicodeCharacter{00AB}{\guillemetleft} - \DeclareUnicodeCharacter{00AD}{\-} - \DeclareUnicodeCharacter{00AE}{\registeredsymbol} - \DeclareUnicodeCharacter{00AF}{\={ }} + \let\DeclareUnicodeCharacter\DeclareUnicodeCharacterUTFviii + \unicodechardefs +} - \DeclareUnicodeCharacter{00B0}{\ringaccent{ }} - \DeclareUnicodeCharacter{00B4}{\'{ }} - \DeclareUnicodeCharacter{00B8}{\cedilla{ }} - \DeclareUnicodeCharacter{00BA}{\ordm} - \DeclareUnicodeCharacter{00BB}{\guillemetright} - \DeclareUnicodeCharacter{00BF}{\questiondown} +% Whether the active definitions of non-ASCII characters expand to +% non-active tokens with the same character code. This is used to +% write characters literally, instead of using active definitions for +% printing the correct glyphs. +\newif\ifpassthroughchars +\passthroughcharsfalse - \DeclareUnicodeCharacter{00C0}{\`A} - \DeclareUnicodeCharacter{00C1}{\'A} - \DeclareUnicodeCharacter{00C2}{\^A} - \DeclareUnicodeCharacter{00C3}{\~A} - \DeclareUnicodeCharacter{00C4}{\"A} - \DeclareUnicodeCharacter{00C5}{\AA} - \DeclareUnicodeCharacter{00C6}{\AE} - \DeclareUnicodeCharacter{00C7}{\cedilla{C}} - \DeclareUnicodeCharacter{00C8}{\`E} - \DeclareUnicodeCharacter{00C9}{\'E} - \DeclareUnicodeCharacter{00CA}{\^E} - \DeclareUnicodeCharacter{00CB}{\"E} - \DeclareUnicodeCharacter{00CC}{\`I} - \DeclareUnicodeCharacter{00CD}{\'I} - \DeclareUnicodeCharacter{00CE}{\^I} - \DeclareUnicodeCharacter{00CF}{\"I} +% For native Unicode handling (XeTeX and LuaTeX), +% provide a definition macro to replace/pass-through a Unicode character +% +\def\DeclareUnicodeCharacterNative#1#2{% + \catcode"#1=\active + \def\dodeclareunicodecharacternative##1##2##3{% + \begingroup + \uccode`\~="##2\relax + \uppercase{\gdef~}{% + \ifpassthroughchars + ##1% + \else + ##3% + \fi + } + \endgroup + } + \begingroup + \uccode`\.="#1\relax + \uppercase{\def\UTFNativeTmp{.}}% + \expandafter\dodeclareunicodecharacternative\UTFNativeTmp{#1}{#2}% + \endgroup +} - \DeclareUnicodeCharacter{00D0}{\DH} - \DeclareUnicodeCharacter{00D1}{\~N} - \DeclareUnicodeCharacter{00D2}{\`O} - \DeclareUnicodeCharacter{00D3}{\'O} - \DeclareUnicodeCharacter{00D4}{\^O} - \DeclareUnicodeCharacter{00D5}{\~O} - \DeclareUnicodeCharacter{00D6}{\"O} - \DeclareUnicodeCharacter{00D8}{\O} - \DeclareUnicodeCharacter{00D9}{\`U} - \DeclareUnicodeCharacter{00DA}{\'U} - \DeclareUnicodeCharacter{00DB}{\^U} - \DeclareUnicodeCharacter{00DC}{\"U} - \DeclareUnicodeCharacter{00DD}{\'Y} - \DeclareUnicodeCharacter{00DE}{\TH} - \DeclareUnicodeCharacter{00DF}{\ss} +% Native Unicode handling (XeTeX and LuaTeX) character replacing definition. +% It activates the setting that replaces Unicode characters. +\def\nativeunicodechardefs{% + \let\DeclareUnicodeCharacter\DeclareUnicodeCharacterNative + \unicodechardefs +} - \DeclareUnicodeCharacter{00E0}{\`a} - \DeclareUnicodeCharacter{00E1}{\'a} - \DeclareUnicodeCharacter{00E2}{\^a} - \DeclareUnicodeCharacter{00E3}{\~a} - \DeclareUnicodeCharacter{00E4}{\"a} - \DeclareUnicodeCharacter{00E5}{\aa} - \DeclareUnicodeCharacter{00E6}{\ae} - \DeclareUnicodeCharacter{00E7}{\cedilla{c}} - \DeclareUnicodeCharacter{00E8}{\`e} - \DeclareUnicodeCharacter{00E9}{\'e} - \DeclareUnicodeCharacter{00EA}{\^e} - \DeclareUnicodeCharacter{00EB}{\"e} - \DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}} - \DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}} - \DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}} - \DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}} - - \DeclareUnicodeCharacter{00F0}{\dh} - \DeclareUnicodeCharacter{00F1}{\~n} - \DeclareUnicodeCharacter{00F2}{\`o} - \DeclareUnicodeCharacter{00F3}{\'o} - \DeclareUnicodeCharacter{00F4}{\^o} - \DeclareUnicodeCharacter{00F5}{\~o} - \DeclareUnicodeCharacter{00F6}{\"o} - \DeclareUnicodeCharacter{00F8}{\o} - \DeclareUnicodeCharacter{00F9}{\`u} - \DeclareUnicodeCharacter{00FA}{\'u} - \DeclareUnicodeCharacter{00FB}{\^u} - \DeclareUnicodeCharacter{00FC}{\"u} - \DeclareUnicodeCharacter{00FD}{\'y} - \DeclareUnicodeCharacter{00FE}{\th} - \DeclareUnicodeCharacter{00FF}{\"y} - - \DeclareUnicodeCharacter{0100}{\=A} - \DeclareUnicodeCharacter{0101}{\=a} - \DeclareUnicodeCharacter{0102}{\u{A}} - \DeclareUnicodeCharacter{0103}{\u{a}} - \DeclareUnicodeCharacter{0104}{\ogonek{A}} - \DeclareUnicodeCharacter{0105}{\ogonek{a}} - \DeclareUnicodeCharacter{0106}{\'C} - \DeclareUnicodeCharacter{0107}{\'c} - \DeclareUnicodeCharacter{0108}{\^C} - \DeclareUnicodeCharacter{0109}{\^c} - \DeclareUnicodeCharacter{0118}{\ogonek{E}} - \DeclareUnicodeCharacter{0119}{\ogonek{e}} - \DeclareUnicodeCharacter{010A}{\dotaccent{C}} - \DeclareUnicodeCharacter{010B}{\dotaccent{c}} - \DeclareUnicodeCharacter{010C}{\v{C}} - \DeclareUnicodeCharacter{010D}{\v{c}} - \DeclareUnicodeCharacter{010E}{\v{D}} - - \DeclareUnicodeCharacter{0112}{\=E} - \DeclareUnicodeCharacter{0113}{\=e} - \DeclareUnicodeCharacter{0114}{\u{E}} - \DeclareUnicodeCharacter{0115}{\u{e}} - \DeclareUnicodeCharacter{0116}{\dotaccent{E}} - \DeclareUnicodeCharacter{0117}{\dotaccent{e}} - \DeclareUnicodeCharacter{011A}{\v{E}} - \DeclareUnicodeCharacter{011B}{\v{e}} - \DeclareUnicodeCharacter{011C}{\^G} - \DeclareUnicodeCharacter{011D}{\^g} - \DeclareUnicodeCharacter{011E}{\u{G}} - \DeclareUnicodeCharacter{011F}{\u{g}} - - \DeclareUnicodeCharacter{0120}{\dotaccent{G}} - \DeclareUnicodeCharacter{0121}{\dotaccent{g}} - \DeclareUnicodeCharacter{0124}{\^H} - \DeclareUnicodeCharacter{0125}{\^h} - \DeclareUnicodeCharacter{0128}{\~I} - \DeclareUnicodeCharacter{0129}{\~{\dotless{i}}} - \DeclareUnicodeCharacter{012A}{\=I} - \DeclareUnicodeCharacter{012B}{\={\dotless{i}}} - \DeclareUnicodeCharacter{012C}{\u{I}} - \DeclareUnicodeCharacter{012D}{\u{\dotless{i}}} - - \DeclareUnicodeCharacter{0130}{\dotaccent{I}} - \DeclareUnicodeCharacter{0131}{\dotless{i}} - \DeclareUnicodeCharacter{0132}{IJ} - \DeclareUnicodeCharacter{0133}{ij} - \DeclareUnicodeCharacter{0134}{\^J} - \DeclareUnicodeCharacter{0135}{\^{\dotless{j}}} - \DeclareUnicodeCharacter{0139}{\'L} - \DeclareUnicodeCharacter{013A}{\'l} - - \DeclareUnicodeCharacter{0141}{\L} - \DeclareUnicodeCharacter{0142}{\l} - \DeclareUnicodeCharacter{0143}{\'N} - \DeclareUnicodeCharacter{0144}{\'n} - \DeclareUnicodeCharacter{0147}{\v{N}} - \DeclareUnicodeCharacter{0148}{\v{n}} - \DeclareUnicodeCharacter{014C}{\=O} - \DeclareUnicodeCharacter{014D}{\=o} - \DeclareUnicodeCharacter{014E}{\u{O}} - \DeclareUnicodeCharacter{014F}{\u{o}} - - \DeclareUnicodeCharacter{0150}{\H{O}} - \DeclareUnicodeCharacter{0151}{\H{o}} - \DeclareUnicodeCharacter{0152}{\OE} - \DeclareUnicodeCharacter{0153}{\oe} - \DeclareUnicodeCharacter{0154}{\'R} - \DeclareUnicodeCharacter{0155}{\'r} - \DeclareUnicodeCharacter{0158}{\v{R}} - \DeclareUnicodeCharacter{0159}{\v{r}} - \DeclareUnicodeCharacter{015A}{\'S} - \DeclareUnicodeCharacter{015B}{\'s} - \DeclareUnicodeCharacter{015C}{\^S} - \DeclareUnicodeCharacter{015D}{\^s} - \DeclareUnicodeCharacter{015E}{\cedilla{S}} - \DeclareUnicodeCharacter{015F}{\cedilla{s}} - - \DeclareUnicodeCharacter{0160}{\v{S}} - \DeclareUnicodeCharacter{0161}{\v{s}} - \DeclareUnicodeCharacter{0162}{\cedilla{t}} - \DeclareUnicodeCharacter{0163}{\cedilla{T}} - \DeclareUnicodeCharacter{0164}{\v{T}} - - \DeclareUnicodeCharacter{0168}{\~U} - \DeclareUnicodeCharacter{0169}{\~u} - \DeclareUnicodeCharacter{016A}{\=U} - \DeclareUnicodeCharacter{016B}{\=u} - \DeclareUnicodeCharacter{016C}{\u{U}} - \DeclareUnicodeCharacter{016D}{\u{u}} - \DeclareUnicodeCharacter{016E}{\ringaccent{U}} - \DeclareUnicodeCharacter{016F}{\ringaccent{u}} - - \DeclareUnicodeCharacter{0170}{\H{U}} - \DeclareUnicodeCharacter{0171}{\H{u}} - \DeclareUnicodeCharacter{0174}{\^W} - \DeclareUnicodeCharacter{0175}{\^w} - \DeclareUnicodeCharacter{0176}{\^Y} - \DeclareUnicodeCharacter{0177}{\^y} - \DeclareUnicodeCharacter{0178}{\"Y} - \DeclareUnicodeCharacter{0179}{\'Z} - \DeclareUnicodeCharacter{017A}{\'z} - \DeclareUnicodeCharacter{017B}{\dotaccent{Z}} - \DeclareUnicodeCharacter{017C}{\dotaccent{z}} - \DeclareUnicodeCharacter{017D}{\v{Z}} - \DeclareUnicodeCharacter{017E}{\v{z}} - - \DeclareUnicodeCharacter{01C4}{D\v{Z}} - \DeclareUnicodeCharacter{01C5}{D\v{z}} - \DeclareUnicodeCharacter{01C6}{d\v{z}} - \DeclareUnicodeCharacter{01C7}{LJ} - \DeclareUnicodeCharacter{01C8}{Lj} - \DeclareUnicodeCharacter{01C9}{lj} - \DeclareUnicodeCharacter{01CA}{NJ} - \DeclareUnicodeCharacter{01CB}{Nj} - \DeclareUnicodeCharacter{01CC}{nj} - \DeclareUnicodeCharacter{01CD}{\v{A}} - \DeclareUnicodeCharacter{01CE}{\v{a}} - \DeclareUnicodeCharacter{01CF}{\v{I}} - - \DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}} - \DeclareUnicodeCharacter{01D1}{\v{O}} - \DeclareUnicodeCharacter{01D2}{\v{o}} - \DeclareUnicodeCharacter{01D3}{\v{U}} - \DeclareUnicodeCharacter{01D4}{\v{u}} - - \DeclareUnicodeCharacter{01E2}{\={\AE}} - \DeclareUnicodeCharacter{01E3}{\={\ae}} - \DeclareUnicodeCharacter{01E6}{\v{G}} - \DeclareUnicodeCharacter{01E7}{\v{g}} - \DeclareUnicodeCharacter{01E8}{\v{K}} - \DeclareUnicodeCharacter{01E9}{\v{k}} - - \DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}} - \DeclareUnicodeCharacter{01F1}{DZ} - \DeclareUnicodeCharacter{01F2}{Dz} - \DeclareUnicodeCharacter{01F3}{dz} - \DeclareUnicodeCharacter{01F4}{\'G} - \DeclareUnicodeCharacter{01F5}{\'g} - \DeclareUnicodeCharacter{01F8}{\`N} - \DeclareUnicodeCharacter{01F9}{\`n} - \DeclareUnicodeCharacter{01FC}{\'{\AE}} - \DeclareUnicodeCharacter{01FD}{\'{\ae}} - \DeclareUnicodeCharacter{01FE}{\'{\O}} - \DeclareUnicodeCharacter{01FF}{\'{\o}} - - \DeclareUnicodeCharacter{021E}{\v{H}} - \DeclareUnicodeCharacter{021F}{\v{h}} - - \DeclareUnicodeCharacter{0226}{\dotaccent{A}} - \DeclareUnicodeCharacter{0227}{\dotaccent{a}} - \DeclareUnicodeCharacter{0228}{\cedilla{E}} - \DeclareUnicodeCharacter{0229}{\cedilla{e}} - \DeclareUnicodeCharacter{022E}{\dotaccent{O}} - \DeclareUnicodeCharacter{022F}{\dotaccent{o}} - - \DeclareUnicodeCharacter{0232}{\=Y} - \DeclareUnicodeCharacter{0233}{\=y} - \DeclareUnicodeCharacter{0237}{\dotless{j}} - - \DeclareUnicodeCharacter{02DB}{\ogonek{ }} - - \DeclareUnicodeCharacter{1E02}{\dotaccent{B}} - \DeclareUnicodeCharacter{1E03}{\dotaccent{b}} - \DeclareUnicodeCharacter{1E04}{\udotaccent{B}} - \DeclareUnicodeCharacter{1E05}{\udotaccent{b}} - \DeclareUnicodeCharacter{1E06}{\ubaraccent{B}} - \DeclareUnicodeCharacter{1E07}{\ubaraccent{b}} - \DeclareUnicodeCharacter{1E0A}{\dotaccent{D}} - \DeclareUnicodeCharacter{1E0B}{\dotaccent{d}} - \DeclareUnicodeCharacter{1E0C}{\udotaccent{D}} - \DeclareUnicodeCharacter{1E0D}{\udotaccent{d}} - \DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}} - \DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}} - - \DeclareUnicodeCharacter{1E1E}{\dotaccent{F}} - \DeclareUnicodeCharacter{1E1F}{\dotaccent{f}} - - \DeclareUnicodeCharacter{1E20}{\=G} - \DeclareUnicodeCharacter{1E21}{\=g} - \DeclareUnicodeCharacter{1E22}{\dotaccent{H}} - \DeclareUnicodeCharacter{1E23}{\dotaccent{h}} - \DeclareUnicodeCharacter{1E24}{\udotaccent{H}} - \DeclareUnicodeCharacter{1E25}{\udotaccent{h}} - \DeclareUnicodeCharacter{1E26}{\"H} - \DeclareUnicodeCharacter{1E27}{\"h} - - \DeclareUnicodeCharacter{1E30}{\'K} - \DeclareUnicodeCharacter{1E31}{\'k} - \DeclareUnicodeCharacter{1E32}{\udotaccent{K}} - \DeclareUnicodeCharacter{1E33}{\udotaccent{k}} - \DeclareUnicodeCharacter{1E34}{\ubaraccent{K}} - \DeclareUnicodeCharacter{1E35}{\ubaraccent{k}} - \DeclareUnicodeCharacter{1E36}{\udotaccent{L}} - \DeclareUnicodeCharacter{1E37}{\udotaccent{l}} - \DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}} - \DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}} - \DeclareUnicodeCharacter{1E3E}{\'M} - \DeclareUnicodeCharacter{1E3F}{\'m} - - \DeclareUnicodeCharacter{1E40}{\dotaccent{M}} - \DeclareUnicodeCharacter{1E41}{\dotaccent{m}} - \DeclareUnicodeCharacter{1E42}{\udotaccent{M}} - \DeclareUnicodeCharacter{1E43}{\udotaccent{m}} - \DeclareUnicodeCharacter{1E44}{\dotaccent{N}} - \DeclareUnicodeCharacter{1E45}{\dotaccent{n}} - \DeclareUnicodeCharacter{1E46}{\udotaccent{N}} - \DeclareUnicodeCharacter{1E47}{\udotaccent{n}} - \DeclareUnicodeCharacter{1E48}{\ubaraccent{N}} - \DeclareUnicodeCharacter{1E49}{\ubaraccent{n}} - - \DeclareUnicodeCharacter{1E54}{\'P} - \DeclareUnicodeCharacter{1E55}{\'p} - \DeclareUnicodeCharacter{1E56}{\dotaccent{P}} - \DeclareUnicodeCharacter{1E57}{\dotaccent{p}} - \DeclareUnicodeCharacter{1E58}{\dotaccent{R}} - \DeclareUnicodeCharacter{1E59}{\dotaccent{r}} - \DeclareUnicodeCharacter{1E5A}{\udotaccent{R}} - \DeclareUnicodeCharacter{1E5B}{\udotaccent{r}} - \DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}} - \DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}} - - \DeclareUnicodeCharacter{1E60}{\dotaccent{S}} - \DeclareUnicodeCharacter{1E61}{\dotaccent{s}} - \DeclareUnicodeCharacter{1E62}{\udotaccent{S}} - \DeclareUnicodeCharacter{1E63}{\udotaccent{s}} - \DeclareUnicodeCharacter{1E6A}{\dotaccent{T}} - \DeclareUnicodeCharacter{1E6B}{\dotaccent{t}} - \DeclareUnicodeCharacter{1E6C}{\udotaccent{T}} - \DeclareUnicodeCharacter{1E6D}{\udotaccent{t}} - \DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}} - \DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}} - - \DeclareUnicodeCharacter{1E7C}{\~V} - \DeclareUnicodeCharacter{1E7D}{\~v} - \DeclareUnicodeCharacter{1E7E}{\udotaccent{V}} - \DeclareUnicodeCharacter{1E7F}{\udotaccent{v}} - - \DeclareUnicodeCharacter{1E80}{\`W} - \DeclareUnicodeCharacter{1E81}{\`w} - \DeclareUnicodeCharacter{1E82}{\'W} - \DeclareUnicodeCharacter{1E83}{\'w} - \DeclareUnicodeCharacter{1E84}{\"W} - \DeclareUnicodeCharacter{1E85}{\"w} - \DeclareUnicodeCharacter{1E86}{\dotaccent{W}} - \DeclareUnicodeCharacter{1E87}{\dotaccent{w}} - \DeclareUnicodeCharacter{1E88}{\udotaccent{W}} - \DeclareUnicodeCharacter{1E89}{\udotaccent{w}} - \DeclareUnicodeCharacter{1E8A}{\dotaccent{X}} - \DeclareUnicodeCharacter{1E8B}{\dotaccent{x}} - \DeclareUnicodeCharacter{1E8C}{\"X} - \DeclareUnicodeCharacter{1E8D}{\"x} - \DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}} - \DeclareUnicodeCharacter{1E8F}{\dotaccent{y}} - - \DeclareUnicodeCharacter{1E90}{\^Z} - \DeclareUnicodeCharacter{1E91}{\^z} - \DeclareUnicodeCharacter{1E92}{\udotaccent{Z}} - \DeclareUnicodeCharacter{1E93}{\udotaccent{z}} - \DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}} - \DeclareUnicodeCharacter{1E95}{\ubaraccent{z}} - \DeclareUnicodeCharacter{1E96}{\ubaraccent{h}} - \DeclareUnicodeCharacter{1E97}{\"t} - \DeclareUnicodeCharacter{1E98}{\ringaccent{w}} - \DeclareUnicodeCharacter{1E99}{\ringaccent{y}} - - \DeclareUnicodeCharacter{1EA0}{\udotaccent{A}} - \DeclareUnicodeCharacter{1EA1}{\udotaccent{a}} - - \DeclareUnicodeCharacter{1EB8}{\udotaccent{E}} - \DeclareUnicodeCharacter{1EB9}{\udotaccent{e}} - \DeclareUnicodeCharacter{1EBC}{\~E} - \DeclareUnicodeCharacter{1EBD}{\~e} - - \DeclareUnicodeCharacter{1ECA}{\udotaccent{I}} - \DeclareUnicodeCharacter{1ECB}{\udotaccent{i}} - \DeclareUnicodeCharacter{1ECC}{\udotaccent{O}} - \DeclareUnicodeCharacter{1ECD}{\udotaccent{o}} - - \DeclareUnicodeCharacter{1EE4}{\udotaccent{U}} - \DeclareUnicodeCharacter{1EE5}{\udotaccent{u}} - - \DeclareUnicodeCharacter{1EF2}{\`Y} - \DeclareUnicodeCharacter{1EF3}{\`y} - \DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}} - - \DeclareUnicodeCharacter{1EF8}{\~Y} - \DeclareUnicodeCharacter{1EF9}{\~y} - - \DeclareUnicodeCharacter{2013}{--} - \DeclareUnicodeCharacter{2014}{---} - \DeclareUnicodeCharacter{2018}{\quoteleft} - \DeclareUnicodeCharacter{2019}{\quoteright} - \DeclareUnicodeCharacter{201A}{\quotesinglbase} - \DeclareUnicodeCharacter{201C}{\quotedblleft} - \DeclareUnicodeCharacter{201D}{\quotedblright} - \DeclareUnicodeCharacter{201E}{\quotedblbase} - \DeclareUnicodeCharacter{2022}{\bullet} - \DeclareUnicodeCharacter{2026}{\dots} - \DeclareUnicodeCharacter{2039}{\guilsinglleft} - \DeclareUnicodeCharacter{203A}{\guilsinglright} - \DeclareUnicodeCharacter{20AC}{\euro} - - \DeclareUnicodeCharacter{2192}{\expansion} - \DeclareUnicodeCharacter{21D2}{\result} - - \DeclareUnicodeCharacter{2212}{\minus} - \DeclareUnicodeCharacter{2217}{\point} - \DeclareUnicodeCharacter{2261}{\equiv} -}% end of \utfeightchardefs +% For native Unicode handling (XeTeX and LuaTeX), +% make the character token expand +% to the sequences given in \unicodechardefs for printing. +\def\DeclareUnicodeCharacterNativeAtU#1#2{% + \def\UTFAtUTmp{#2} + \expandafter\globallet\csname uni:#1\endcsname \UTFAtUTmp +} +% @U command definitions for native Unicode handling (XeTeX and LuaTeX). +\def\nativeunicodechardefsatu{% + \let\DeclareUnicodeCharacter\DeclareUnicodeCharacterNativeAtU + \unicodechardefs +} % US-ASCII character definitions. \def\asciichardefs{% nothing need be done \relax } -% Make non-ASCII characters printable again for compatibility with -% existing Texinfo documents that may use them, even without declaring a -% document encoding. -% -\setnonasciicharscatcode \other - +% Define all Unicode characters we know about. This makes UTF-8 the default +% input encoding and allows @U to work. +\iftxinativeunicodecapable + \nativeunicodechardefsatu +\else + \utfeightchardefs +\fi \message{formatting,} @@ -9708,12 +11196,12 @@ directory should work if nowhere else does.} \advance\vsize by \topskip \outervsize = \vsize \advance\outervsize by 2\topandbottommargin - \pageheight = \vsize + \txipageheight = \vsize % \hsize = #2\relax \outerhsize = \hsize \advance\outerhsize by 0.5in - \pagewidth = \hsize + \txipagewidth = \hsize % \normaloffset = #4\relax \bindingoffset = #5\relax @@ -9725,6 +11213,14 @@ directory should work if nowhere else does.} % whatever layout pdftex was dumped with. \pdfhorigin = 1 true in \pdfvorigin = 1 true in + \else + \ifx\XeTeXrevision\thisisundefined + \special{papersize=#8,#7}% + \else + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + % XeTeX does not have \pdfhorigin and \pdfvorigin. + \fi \fi % \setleading{\textleading} @@ -9757,7 +11253,6 @@ directory should work if nowhere else does.} % \lispnarrowing = 0.3in \tolerance = 700 - \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .5cm }} @@ -9775,7 +11270,6 @@ directory should work if nowhere else does.} % \lispnarrowing = 0.25in \tolerance = 700 - \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .4cm }} @@ -9801,7 +11295,6 @@ directory should work if nowhere else does.} {297mm}{210mm}% % \tolerance = 700 - \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = 5mm }} @@ -9820,7 +11313,6 @@ directory should work if nowhere else does.} % \lispnarrowing = 0.2in \tolerance = 800 - \hfuzz = 1.2pt \contentsrightmargin = 0pt \defbodyindent = 2mm \tableindent = 12mm @@ -9862,9 +11354,11 @@ directory should work if nowhere else does.} % \dimen0 = #1\relax \advance\dimen0 by \voffset + \advance\dimen0 by 1in % reference point for DVI is 1 inch from top of page % \dimen2 = \hsize \advance\dimen2 by \normaloffset + \advance\dimen2 by 1in % reference point is 1 inch from left edge of page % \internalpagesizes{#1}{\hsize}% {\voffset}{\normaloffset}% @@ -9876,6 +11370,9 @@ directory should work if nowhere else does.} % \letterpaper +% Default value of \hfuzz, for suppressing warnings about overfull hboxes. +\hfuzz = 1pt + \message{and turning on texinfo input format.} @@ -9912,44 +11409,47 @@ directory should work if nowhere else does.} % this is not a problem. \def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} -% Turn off all special characters except @ -% (and those which the user can use as if they were ordinary). +% Set catcodes for Texinfo file + +% Active characters for printing the wanted glyph. % Most of these we simply print from the \tt font, but for some, we can % use math or other variants that look better in normal text. - +% \catcode`\"=\active \def\activedoublequote{{\tt\char34}} \let"=\activedoublequote -\catcode`\~=\active -\def~{{\tt\char126}} -\chardef\hat=`\^ -\catcode`\^=\active -\def^{{\tt \hat}} +\catcode`\~=\active \def\activetilde{{\tt\char126}} \let~ = \activetilde +\chardef\hatchar=`\^ +\catcode`\^=\active \def\activehat{{\tt \hatchar}} \let^ = \activehat \catcode`\_=\active \def_{\ifusingtt\normalunderscore\_} -\let\realunder=_ -% Subroutine for the previous macro. \def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } +\let\realunder=_ + +\catcode`\|=\active \def|{{\tt\char124}} -\catcode`\|=\active -\def|{{\tt\char124}} \chardef \less=`\< -\catcode`\<=\active -\def<{{\tt \less}} +\catcode`\<=\active \def\activeless{{\tt \less}}\let< = \activeless \chardef \gtr=`\> -\catcode`\>=\active -\def>{{\tt \gtr}} -\catcode`\+=\active -\def+{{\tt \char 43}} -\catcode`\$=\active -\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix +\catcode`\>=\active \def\activegtr{{\tt \gtr}}\let> = \activegtr +\catcode`\+=\active \def+{{\tt \char 43}} +\catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix +\catcode`\-=\active \let-=\normaldash -% If a .fmt file is being used, characters that might appear in a file -% name cannot be active until we have parsed the command line. -% So turn them off again, and have \everyjob (or @setfilename) turn them on. -% \otherifyactive is called near the end of this file. -\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +% used for headline/footline in the output routine, in case the page +% breaks in the middle of an @tex block. +\def\texinfochars{% + \let< = \activeless + \let> = \activegtr + \let~ = \activetilde + \let^ = \activehat + \markupsetuplqdefault \markupsetuprqdefault + \let\b = \strong + \let\i = \smartitalic + % in principle, all other definitions in \tex have to be undone too. +} % Used sometimes to turn off (effectively) the active characters even after % parsing them. @@ -9963,81 +11463,118 @@ directory should work if nowhere else does.} % \backslashcurfont outputs one backslash character in current font, % as in \char`\\. \global\chardef\backslashcurfont=`\\ -\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work -% \realbackslash is an actual character `\' with catcode other, and -% \doublebackslash is two of them (for the pdf outlines). -{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} +% \realbackslash is an actual character `\' with catcode other. +{\catcode`\\=\other @gdef@realbackslash{\}} -% In texinfo, backslash is an active character; it prints the backslash +% In Texinfo, backslash is an active character; it prints the backslash % in fixed width font. \catcode`\\=\active % @ for escape char from now on. -% The story here is that in math mode, the \char of \backslashcurfont -% ends up printing the roman \ from the math symbol font (because \char -% in math mode uses the \mathcode, and plain.tex sets -% \mathcode`\\="026E). It seems better for @backslashchar{} to always -% print a typewriter backslash, hence we use an explicit \mathchar, +% Print a typewriter backslash. For math mode, we can't simply use +% \backslashcurfont: the story here is that in math mode, the \char +% of \backslashcurfont ends up printing the roman \ from the math symbol +% font (because \char in math mode uses the \mathcode, and plain.tex +% sets \mathcode`\\="026E). Hence we use an explicit \mathchar, % which is the decimal equivalent of "715c (class 7, e.g., use \fam; % ignored family value; char position "5C). We can't use " for the % usual hex value because it has already been made active. -@def@normalbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}} -@let@backslashchar = @normalbackslash % @backslashchar{} is for user documents. -% On startup, @fixbackslash assigns: -% @let \ = @normalbackslash -% \rawbackslash defines an active \ to do \backslashcurfont. +@def@ttbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}} +@let@backslashchar = @ttbackslash % @backslashchar{} is for user documents. + % \otherbackslash defines an active \ to be a literal `\' character with -% catcode other. We switch back and forth between these. -@gdef@rawbackslash{@let\=@backslashcurfont} +% catcode other. @gdef@otherbackslash{@let\=@realbackslash} % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of -% the literal character `\'. Also revert - to its normal character, in -% case the active - from code has slipped in. +% the literal character `\'. % {@catcode`- = @active @gdef@normalturnoffactive{% + @passthroughcharstrue @let-=@normaldash @let"=@normaldoublequote @let$=@normaldollar %$ font-lock fix @let+=@normalplus @let<=@normalless @let>=@normalgreater - @let\=@normalbackslash @let^=@normalcaret @let_=@normalunderscore @let|=@normalverticalbar @let~=@normaltilde + @let\=@ttbackslash @markupsetuplqdefault @markupsetuprqdefault @unsepspaces } } -% Make _ and + \other characters, temporarily. -% This is canceled by @fixbackslash. -@otherifyactive +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have @fixbackslash turn them back on. +@catcode`+=@other @catcode`@_=@other +% \enablebackslashhack - allow file to begin `\input texinfo' +% % If a .fmt file is being used, we don't want the `\input texinfo' to show up. % That is what \eatinput is for; after that, the `\' should revert to printing % a backslash. -% -@gdef@eatinput input texinfo{@fixbackslash} -@global@let\ = @eatinput +% If the file did not have a `\input texinfo', then it is turned off after +% the first line; otherwise the first `\' in the file would cause an error. +% This is used on the very last line of this file, texinfo.tex. +% We also use @c to call @fixbackslash, in case ends of lines are hidden. +{ +@catcode`@^=7 +@catcode`@^^M=13@gdef@enablebackslashhack{% + @global@let\ = @eatinput% + @catcode`@^^M=13% + @def@c{@fixbackslash@c}% + % Definition for the newline at the end of this file. + @def ^^M{@let^^M@secondlinenl}% + % Definition for a newline in the main Texinfo file. + @gdef @secondlinenl{@fixbackslash}% + % In case the first line has a whole-line command on it + @let@originalparsearg@parsearg + @def@parsearg{@fixbackslash@originalparsearg} +}} + +{@catcode`@^=7 @catcode`@^^M=13% +@gdef@eatinput input texinfo#1^^M{@fixbackslash}} + +% Emergency active definition of newline, in case an active newline token +% appears by mistake. +{@catcode`@^=7 @catcode13=13% +@gdef@enableemergencynewline{% + @gdef^^M{% + @par% + %@par% +}}} + -% On the other hand, perhaps the file did not have a `\input texinfo'. Then -% the first `\' in the file would cause an error. This macro tries to fix -% that, assuming it is called before the first `\' could plausibly occur. -% Also turn back on active characters that might appear in the input -% file name, in case not using a pre-dumped format. -% @gdef@fixbackslash{% - @ifx\@eatinput @let\ = @normalbackslash @fi + @ifx\@eatinput @let\ = @ttbackslash @fi + @catcode13=5 % regular end of line + @enableemergencynewline + @let@c=@comment + @let@parsearg@originalparsearg + % Also turn back on active characters that might appear in the input + % file name, in case not using a pre-dumped format. @catcode`+=@active @catcode`@_=@active + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. This macro, @fixbackslash, gets + % called at the beginning of every Texinfo file. Not opening texinfo.cnf + % directly in this file, texinfo.tex, makes it possible to make a format + % file for Texinfo. + % + @openin 1 texinfo.cnf + @ifeof 1 @else @input texinfo.cnf @fi + @closein 1 } + % Say @foo, not \foo, in error messages. @escapechar = `@@ @@ -10065,8 +11602,8 @@ directory should work if nowhere else does.} @markupsetuprqdefault @c Local variables: -@c eval: (add-hook 'write-file-hooks 'time-stamp) -@c page-delimiter: "^\\\\message" +@c eval: (add-hook 'before-save-hook 'time-stamp) +@c page-delimiter: "^\\\\message\\|emacs-page" @c time-stamp-start: "def\\\\texinfoversion{" @c time-stamp-format: "%:y-%02m-%02d.%02H" @c time-stamp-end: "}" @@ -10074,6 +11611,4 @@ directory should work if nowhere else does.} @c vim:sw=2: -@ignore - arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 -@end ignore +@enablebackslashhack diff --git a/doc/tinc-gui.8.in b/doc/tinc-gui.8.in deleted file mode 100644 index f5ebadb..0000000 --- a/doc/tinc-gui.8.in +++ /dev/null @@ -1,57 +0,0 @@ -.Dd 2011-06-26 -.Dt TINC-GUI 8 -.\" Manual page created by: -.\" Guus Sliepen -.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! diff --git a/doc/tinc.8.in b/doc/tinc.8.in deleted file mode 100644 index ebf9df1..0000000 --- a/doc/tinc.8.in +++ /dev/null @@ -1,276 +0,0 @@ -.Dd 2013-01-15 -.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 -.Ar COMMAND -.Sh DESCRIPTION -This is the control program of tinc, a secure virtual private network (VPN) -project. -.Nm -communicates with -.Xr tincd 8 -to alter and inspect the running VPN's state. -.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 . -.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 -Example of configuring tinc 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! diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in index 69deace..cd7d1a0 100644 --- a/doc/tinc.conf.5.in +++ b/doc/tinc.conf.5.in @@ -1,4 +1,4 @@ -.Dd 2013-01-14 +.Dd 2016-10-29 .Dt TINC.CONF 5 .\" Manual page created by: .\" Ivo Timmermans @@ -11,12 +11,20 @@ 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. +It is perfectly ok for you to run more than one tinc daemon. +However, in its default form, +you will soon notice that you can't use two different configuration files without the +.Fl c +option. .Pp -The effect of this option is that the daemon will set its configuration root to +We have thought of another way of dealing with this: network names. +This means that you call +.Nm +with the +.Fl n +option, which will assign a name to this daemon. +.Pp +The effect of this is that the daemon will set its configuration root to .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa / , where .Ar NETNAME @@ -24,14 +32,13 @@ 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. +.Nm tincd. Ns Ar NETNAME . .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 +However, it is not strictly necessary that you call tinc with the .Fl n option. -In this case, the network name would just be empty, and +In this case, the network name would just be empty, +and it will be used as such. .Nm tinc now looks for files in .Pa @sysconfdir@/tinc/ , @@ -41,8 +48,13 @@ 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/ . +.Pp +But it is highly recommended that you use this feature of +.Nm tinc , +because it will be so much clearer whom your daemon talks to. +Hence, we will assume that you use it. .Sh NAMES -Each tinc daemon should have a name that is unique in the network which it will be part of. +Each tinc daemon must 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 @@ -51,34 +63,24 @@ file. 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 +You should use +.Ic tincd -K +to generate public/private keypairs. +It will generate two keys. +The private key should be stored in a separate file +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /rsa_key.priv +\-\- where +.Ar NETNAME +stands for the network (see +.Sx NETWORKS ) +above. +The public key should be stored in the host configuration file +.Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /hosts/ Ns Va NAME +\-\- where +.Va NAME +stands for the name of the local tinc daemon (see +.Sx NAMES ) . .Sh SERVER CONFIGURATION The server configuration of the daemon is done in the file .Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc.conf . @@ -101,10 +103,6 @@ Although all configuration options for the local host listed in this document ca 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 @@ -114,16 +112,7 @@ 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 +.It Va BindToAddress Li = Ar address Oo Ar port Oc Bq experimental If your computer has more than one IPv4 or IPv6 address, .Nm tinc will by default listen on all of them for incoming connections. @@ -141,6 +130,8 @@ To only bind to a specific port but not to a specific address, use .Li * for the .Ar address . +.Pp +This option may not work on all platforms. .It Va BindToInterface Li = Ar interface Bq experimental If your computer has more than one network interface, .Nm tinc @@ -231,7 +222,7 @@ Also note that this can cause decrypted VPN packets to be sent out on a real net Create a UNIX socket with the filename specified by .Va Device , or -.Pa @localstatedir@/run/ Ns Ar NETNAME Ns Pa .umlsocket +.Pa @runstatedir@/ Ns Ar NETNAME Ns Pa .umlsocket if not specified. .Nm tinc will wait for a User Mode Linux instance to connect to this socket. @@ -240,7 +231,7 @@ 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 +.Pa @runstatedir@/vde.ctl if not specified. .El Also, in case tinc does not seem to correctly interpret packets received from the virtual network device, @@ -259,6 +250,10 @@ 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 utun Pq OS X +Set type to utun. +This is only supported on OS X version 10.6.8 and higher, but doesn't require the tuntaposx module. +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 @@ -269,17 +264,6 @@ When this option is enabled, packets that cannot be sent directly to the destina 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 @@ -295,6 +279,18 @@ Incoming packets are always sent to the TUN/TAP device, even if the packets are This is less efficient, but allows the kernel to apply its routing and firewall rules on them, and can also help debugging. .El +.It Va GraphDumpFile Li = Ar filename Bq experimental +If this option is present, +.Nm tinc +will dump the current network graph to the file +.Ar filename +every minute, unless there were no changes to the graph. +The file is in a format that can be read by graphviz tools. +If +.Ar filename +starts with a pipe symbol |, +then the rest of the filename is interpreted as a shell command +that is executed, the graph is then sent to stdin. .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 @@ -316,7 +312,7 @@ this variable is almost always already correctly set. 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 LocalDiscovery Li = yes | no Pq no +.It Va LocalDiscovery Li = yes | no Po no Pc Bq experimental When enabled, .Nm tinc will try to detect peers that are on the same local network. @@ -326,20 +322,12 @@ 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 @@ -349,7 +337,7 @@ This option selects the way packets are routed to other daemons. 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. +Only unicast 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 @@ -367,7 +355,7 @@ while no routing table is managed. .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. +The Name may only consist of alphanumeric and underscore characters. If .Va Name starts with a @@ -397,9 +385,7 @@ 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. +When this option is used the priority of the tincd process will be adjusted. Increasing the priority may help to reduce latency and packet loss on the VPN. .It Va Proxy Li = socks4 | socks5 | http | exec Ar ... Bq experimental Use a proxy when making outgoing connections. @@ -446,7 +432,8 @@ traffic. 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. +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 @@ -481,15 +468,13 @@ 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 +.It Va Cipher Li = Ar cipher Pq aes-256-cbc The symmetric cipher algorithm used to encrypt UDP packets. -Any cipher supported by OpenSSL is recognised. +Any cipher supported by LibreSSL or 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 @@ -498,25 +483,21 @@ Fragmentation Needed or Packet too Big messages are dropped by firewalls. 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 +.It Va Digest Li = Ar digest Pq sha256 The digest algorithm used to authenticate UDP packets. -Any digest supported by OpenSSL is recognised. +Any digest supported by LibreSSL or 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. +When set to yes, only nodes which already have a meta connection to you +will 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 @@ -579,7 +560,15 @@ UDP is possible or not. .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 +Below is a list of filenames of scripts and a description of when they are run. +A script is only run if it exists and if it is executable. +.Pp +Scripts are run synchronously; +this means that tinc will temporarily stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the events that trigger them. +If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background. +.Pp +Under Windows (not Cygwin), the scripts must have the extension .Pa .bat . .Bl -tag -width indent .It Pa @sysconfdir@/tinc/ Ns Ar NETNAME Ns Pa /tinc-up @@ -587,6 +576,7 @@ 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. +.Pp 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. @@ -652,6 +642,8 @@ 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 @@ -665,8 +657,7 @@ its connection to the virtual network device. .El .Sh SEE ALSO .Xr tincd 8 , -.Xr tinc 8 , -.Pa http://www.tinc-vpn.org/ , +.Pa https://www.tinc-vpn.org/ , .Pa http://www.tldp.org/LDP/nag2/ . .Pp The full documentation for diff --git a/doc/tinc.info b/doc/tinc.info index 0e4c5ec..7ee4d91 100644 --- a/doc/tinc.info +++ b/doc/tinc.info @@ -1,14 +1,14 @@ -This is tinc.info, produced by makeinfo version 5.1 from tinc.texi. +This is tinc.info, produced by makeinfo version 6.7 from tinc.texi. INFO-DIR-SECTION Networking tools START-INFO-DIR-ENTRY * tinc: (tinc). The tinc Manual. END-INFO-DIR-ENTRY -This is the info manual for tinc version 1.1pre7, a Virtual Private +This is the info manual for tinc version 1.0.36, a Virtual Private Network daemon. - Copyright (C) 1998-2013 Ivo Timmermans, Guus Sliepen + Copyright (C) 1998-2019 Ivo Timmermans, Guus Sliepen and Wessel Dankers . Permission is granted to make and distribute verbatim copies of this @@ -33,7 +33,6 @@ Top * Installation:: * Configuration:: * Running tinc:: -* Controlling tinc:: * Technical information:: * Platform specific information:: * About us:: @@ -49,13 +48,13 @@ Tinc is a Virtual Private Network (VPN) daemon that uses tunneling and encryption to create a secure private network between hosts on the Internet. -Because the tunnel appears to the IP level network code as a normal + Because the tunnel appears to the IP level network code as a normal network device, there is no need to adapt any existing software. The encrypted tunnels allows VPN sites to share information with each other over the Internet without exposing any information to others. -This document is the manual for tinc. Included are chapters on how to -configure your computer to use tinc, as well as the configuration + This document is the manual for tinc. Included are chapters on how +to configure your computer to use tinc, as well as the configuration process of tinc itself. * Menu: @@ -74,7 +73,7 @@ A Virtual Private Network or VPN is a network that can only be accessed by a few elected computers that participate. This goal is achievable in more than just one way. -Private networks can consist of a single stand-alone Ethernet LAN. Or + Private networks can consist of a single stand-alone Ethernet LAN. Or even two computers hooked up using a null-modem cable. In these cases, it is obvious that the network is _private_, no one can access it from the outside. But if your computers are linked to the Internet, the @@ -82,7 +81,7 @@ network is not private anymore, unless one uses firewalls to block all private traffic. But then, there is no way to send private data to trusted computers on the other end of the Internet. -This problem can be solved by using _virtual_ networks. Virtual + This problem can be solved by using _virtual_ networks. Virtual networks can live on top of other networks, but they use encapsulation to keep using their private address space so they do not interfere with the Internet. Mostly, virtual networks appear like a single LAN, even @@ -90,14 +89,14 @@ though they can span the entire world. But virtual networks can't be secured by using firewalls, because the traffic that flows through it has to go through the Internet, where other people can look at it. -As is the case with either type of VPN, anybody could eavesdrop. Or + As is the case with either type of VPN, anybody could eavesdrop. Or worse, alter data. Hence it's probably advisable to encrypt the data that flows over the network. -When one introduces encryption, we can form a true VPN. Other people may -see encrypted traffic, but if they don't know how to decipher it (they -need to know the key for that), they cannot read the information that -flows through the VPN. This is what tinc was made for. + When one introduces encryption, we can form a true VPN. Other people +may see encrypted traffic, but if they don't know how to decipher it +(they need to know the key for that), they cannot read the information +that flows through the VPN. This is what tinc was made for.  File: tinc.info, Node: tinc, Next: Supported platforms, Prev: Virtual Private Networks, Up: Introduction @@ -111,26 +110,26 @@ used the ethertap device that Linux knows of since somewhere about kernel 2.1.60. It didn't work immediately and he improved it a bit. At this stage, the project was still simply called "vpnd". -Since then, a lot has changed--to say the least. + Since then, a lot has changed--to say the least. -Tinc now supports encryption, it consists of a single daemon (tincd) for -both the receiving and sending end, it has become largely + Tinc now supports encryption, it consists of a single daemon (tincd) +for both the receiving and sending end, it has become largely runtime-configurable--in short, it has become a full-fledged professional package. -Tinc also allows more than two sites to connect to eachother and form a -single VPN. Traditionally VPNs are created by making tunnels, which only -have two endpoints. Larger VPNs with more sites are created by adding -more tunnels. Tinc takes another approach: only endpoints are + Tinc also allows more than two sites to connect to each other and +form a single VPN. Traditionally VPNs are created by making tunnels, +which only have two endpoints. Larger VPNs with more sites are created +by adding more tunnels. Tinc takes another approach: only endpoints are specified, the software itself will take care of creating the tunnels. This allows for easier configuration and improved scalability. -A lot can--and will be--changed. We have a number of things that we + A lot can--and will be--changed. We have a number of things that we would like to see in the future releases of tinc. Not everything will be available in the near future. Our first objective is to make tinc work perfectly as it stands, and then add more advanced features. -Meanwhile, we're always open-minded towards new ideas. And we're + Meanwhile, we're always open-minded towards new ideas. And we're available too.  @@ -140,15 +139,15 @@ File: tinc.info, Node: Supported platforms, Prev: tinc, Up: Introduction ======================= Tinc has been verified to work under Linux, FreeBSD, OpenBSD, NetBSD, -MacOS/X (Darwin), Solaris, and Windows (both natively and in a Cygwin +Mac OS X (Darwin), Solaris, and Windows (both natively and in a Cygwin environment), with various hardware architectures. These are some of the platforms that are supported by the universal tun/tap device driver or other virtual network device drivers. Without such a driver, tinc will most likely compile and run, but it will not be able to send or receive data packets. -For an up to date list of supported platforms, please check the list on -our website: . + For an up to date list of supported platforms, please check the list +on our website: .  File: tinc.info, Node: Preparations, Next: Installation, Prev: Introduction, Up: Top @@ -177,7 +176,7 @@ File: tinc.info, Node: Configuring the kernel, Next: Libraries, Up: Preparati * Configuration of OpenBSD kernels:: * Configuration of NetBSD kernels:: * Configuration of Solaris kernels:: -* Configuration of Darwin (MacOS/X) kernels:: +* Configuration of Darwin (Mac OS X) kernels:: * Configuration of Windows::  @@ -195,11 +194,11 @@ Here are the options you have to turn on when configuring a new kernel: Network device support Universal tun/tap device driver support -It's not necessary to compile this driver as a module, even if you are -going to run more than one instance of tinc. + It's not necessary to compile this driver as a module, even if you +are going to run more than one instance of tinc. -If you decide to build the tun/tap driver as a kernel module, add these -lines to '/etc/modules.conf': + If you decide to build the tun/tap driver as a kernel module, add +these lines to '/etc/modules.conf': alias char-major-10-200 tun @@ -220,12 +219,8 @@ File: tinc.info, Node: Configuration of OpenBSD kernels, Next: Configuration o 2.1.3 Configuration of OpenBSD kernels -------------------------------------- -For OpenBSD version 2.9 and higher, the tun driver is included in the -default kernel configuration. There is also a kernel patch from - which adds a tap device to -OpenBSD which should work with tinc, but with recent versions of -OpenBSD, a tun device can act as a tap device by setting the link0 -option with ifconfig. +Recent versions of OpenBSD come with both tun and tap devices enabled in +the default kernel configuration.  File: tinc.info, Node: Configuration of NetBSD kernels, Next: Configuration of Solaris kernels, Prev: Configuration of OpenBSD kernels, Up: Configuring the kernel @@ -236,10 +231,10 @@ File: tinc.info, Node: Configuration of NetBSD kernels, Next: Configuration of For NetBSD version 1.5.2 and higher, the tun driver is included in the default kernel configuration. -Tunneling IPv6 may not work on NetBSD's tun device. + Tunneling IPv6 may not work on NetBSD's tun device.  -File: tinc.info, Node: Configuration of Solaris kernels, Next: Configuration of Darwin (MacOS/X) kernels, Prev: Configuration of NetBSD kernels, Up: Configuring the kernel +File: tinc.info, Node: Configuration of Solaris kernels, Next: Configuration of Darwin (Mac OS X) kernels, Prev: Configuration of NetBSD kernels, Up: Configuring the kernel 2.1.5 Configuration of Solaris kernels -------------------------------------- @@ -248,33 +243,35 @@ For Solaris 8 (SunOS 5.8) and higher, the tun driver may or may not be included in the default kernel configuration. If it isn't, the source can be downloaded from . For x86 and sparc64 architectures, precompiled versions can be found at -. If the 'net/if_tun.h' +. If the 'net/if_tun.h' header file is missing, install it from the source package.  -File: tinc.info, Node: Configuration of Darwin (MacOS/X) kernels, Next: Configuration of Windows, Prev: Configuration of Solaris kernels, Up: Configuring the kernel +File: tinc.info, Node: Configuration of Darwin (Mac OS X) kernels, Next: Configuration of Windows, Prev: Configuration of Solaris kernels, Up: Configuring the kernel -2.1.6 Configuration of Darwin (MacOS/X) kernels ------------------------------------------------ +2.1.6 Configuration of Darwin (Mac OS X) kernels +------------------------------------------------ Tinc on Darwin relies on a tunnel driver for its data acquisition from -the kernel. Tinc supports either the driver from +the kernel. OS X version 10.6.8 and later have a built-in tun driver +called "utun". Tinc also supports the driver from , which supports both tun and tap -style devices, and also the driver from from -. The former driver is -recommended. The tunnel driver must be loaded before starting tinc with -the following command: +style devices. - kmodload tunnel + By default, tinc expects the tuntaposx driver to be installed. To +use the utun driver, set add 'Device = utunX' to 'tinc.conf', where X is +the desired number for the utun interface. You can also omit the +number, in which case the first free number will be chosen.  -File: tinc.info, Node: Configuration of Windows, Prev: Configuration of Darwin (MacOS/X) kernels, Up: Configuring the kernel +File: tinc.info, Node: Configuration of Windows, Prev: Configuration of Darwin (Mac OS X) kernels, Up: Configuring the kernel 2.1.7 Configuration of Windows ------------------------------ You will need to install the latest TAP-Win32 driver from OpenVPN. You -can download it from . Using the +can download it from +. Using the Network Connections control panel, configure the TAP-Win32 network interface in the same way as you would do from the tinc-up script, as explained in the rest of the documentation. @@ -285,49 +282,50 @@ File: tinc.info, Node: Libraries, Prev: Configuring the kernel, Up: Preparati 2.2 Libraries ============= -Before you can configure or build tinc, you need to have the OpenSSL, -zlib and lzo libraries installed on your system. If you try to +Before you can configure or build tinc, you need to have the LibreSSL or +OpenSSL, zlib and lzo libraries installed on your system. If you try to configure tinc without having them installed, configure will give you an error message, and stop. * Menu: -* OpenSSL:: +* LibreSSL/OpenSSL:: * zlib:: * lzo:: -* libcurses:: -* libreadline::  -File: tinc.info, Node: OpenSSL, Next: zlib, Up: Libraries +File: tinc.info, Node: LibreSSL/OpenSSL, Next: zlib, Up: Libraries -2.2.1 OpenSSL -------------- +2.2.1 LibreSSL/OpenSSL +---------------------- For all cryptography-related functions, tinc uses the functions provided -by the OpenSSL library. +by the LibreSSL or the OpenSSL library. -If this library is not installed, you wil get an error when configuring -tinc for build. Support for running tinc with other cryptographic -libraries installed _may_ be added in the future. + If this library is not installed, you will get an error when +configuring tinc for build. Support for running tinc with other +cryptographic libraries installed _may_ be added in the future. -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. + You can use your operating system's package manager to install this +if available. Make sure you install the development AND runtime +versions of this package. -If you have to install OpenSSL manually, you can get the source code -from . Instructions on how to configure, build -and install this package are included within the package. Please make -sure you build development and runtime libraries (which is the default). + If your operating system comes neither with LibreSSL or OpenSSL, you +have to install one manually. It is recommended that you get the latest +version of LibreSSL from . Instructions on +how to configure, build and install this package are included within the +package. Please make sure you build development and runtime libraries +(which is the default). -If you installed the OpenSSL libraries from source, it may be necessary -to let configure know where they are, by passing configure one of the --with-openssl-* parameters. + If you installed the LibreSSL or OpenSSL libraries from source, it +may be necessary to let configure know where they are, by passing +configure one of the -with-openssl-* parameters. Note that you even +have to use -with-openssl-* if you are using LibreSSL. - --with-openssl=DIR OpenSSL library and headers prefix - --with-openssl-include=DIR OpenSSL headers directory + --with-openssl=DIR LibreSSL/OpenSSL library and headers prefix + --with-openssl-include=DIR LibreSSL/OpenSSL headers directory (Default is OPENSSL_DIR/include) - --with-openssl-lib=DIR OpenSSL library directory + --with-openssl-lib=DIR LibreSSL/OpenSSL library directory (Default is OPENSSL_DIR/lib) License @@ -336,7 +334,7 @@ License The complete source code of tinc is covered by the GNU GPL version 2. Since the license under which OpenSSL is distributed is not directly compatible with the terms of the GNU GPL -, we include an +, we include an exemption to the GPL (see also the file COPYING.README) to allow everyone to create a statically or dynamically linked executable: @@ -345,17 +343,17 @@ everyone to create a statically or dynamically linked executable: You may provide binary packages linked to the OpenSSL libraries, provided that all other requirements of the GPL are met. -Since the LZO library used by tinc is also covered by the GPL, we also -present the following exemption: + Since the LZO library used by tinc is also covered by the GPL, we +also present the following exemption: Hereby I grant a special exception to the tinc VPN project - (http://www.tinc-vpn.org/) to link the LZO library with the OpenSSL - library (http://www.openssl.org). + (https://www.tinc-vpn.org/) to link the LZO library with the + OpenSSL library (https://www.openssl.org). Markus F.X.J. Oberhumer  -File: tinc.info, Node: zlib, Next: lzo, Prev: OpenSSL, Up: Libraries +File: tinc.info, Node: zlib, Next: lzo, Prev: LibreSSL/OpenSSL, Up: Libraries 2.2.2 zlib ---------- @@ -363,90 +361,43 @@ File: tinc.info, Node: zlib, Next: lzo, Prev: OpenSSL, Up: Libraries For the optional compression of UDP packets, tinc uses the functions provided by the zlib library. -If this library is not installed, you wil get an error when running the -configure script. You can either install the zlib library, or disable -support for zlib compression by using the "-disable-zlib" option when -running the configure script. Note that if you disable support for + If this library is not installed, you will get an error when running +the configure script. You can either install the zlib library, or +disable support for zlib compression by using the "-disable-zlib" option +when running the configure script. Note that if you disable support for zlib, the resulting binary will not work correctly on VPNs where zlib compression is used. -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. + You can use your operating system's package manager to install this +if available. Make sure you install the development AND runtime +versions of this package. -If you have to install zlib manually, you can get the source code from -. Instructions on how to configure, build -and install this package are included within the package. Please make -sure you build development and runtime libraries (which is the default). + If you have to install zlib manually, you can get the source code +from . Instructions on how to configure, build and +install this package are included within the package. Please make sure +you build development and runtime libraries (which is the default).  -File: tinc.info, Node: lzo, Next: libcurses, Prev: zlib, Up: Libraries +File: tinc.info, Node: lzo, Prev: zlib, Up: Libraries 2.2.3 lzo --------- Another form of compression is offered using the LZO library. -If this library is not installed, you wil get an error when running the -configure script. You can either install the LZO library, or disable -support for LZO compression by using the "-disable-lzo" option when -running the configure script. Note that if you disable support for LZO, -the resulting binary will not work correctly on VPNs where LZO + If this library is not installed, you will get an error when running +the configure script. You can either install the LZO library, or +disable support for LZO compression by using the "-disable-lzo" option +when running the configure script. Note that if you disable support for +LZO, the resulting binary will not work correctly on VPNs where LZO compression is used. -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. + You can use your operating system's package manager to install this +if available. Make sure you install the development AND runtime +versions of this package. -If you have to install lzo manually, you can get the source code from -. Instructions on how to -configure, build and install this package are included within the -package. Please make sure you build development and runtime libraries -(which is the default). - - -File: tinc.info, Node: libcurses, Next: libreadline, Prev: lzo, Up: Libraries - -2.2.4 libcurses ---------------- - -For the "tinc top" command, tinc requires a curses library. - -If this library is not installed, you wil get an error when running the -configure script. You can either install a suitable curses library, or -disable all functionality that depends on a curses library by using the -"-disable-curses" option when running the configure script. - -There are several curses libraries. It is recommended that you install -"ncurses" (), however other curses -libraries should also work. In particular, "PDCurses" -() is recommended if you want to -compile tinc for Windows. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - - -File: tinc.info, Node: libreadline, Prev: libcurses, Up: Libraries - -2.2.5 libreadline ------------------ - -For the "tinc" command's shell functionality, tinc uses the readline -library. - -If this library is not installed, you wil get an error when running the -configure script. You can either install a suitable readline library, -or disable all functionality that depends on a readline library by using -the "-disable-readline" option when running the configure script. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - -If you have to install libreadline manually, you can get the source code -from . Instructions on how to + If you have to install lzo manually, you can get the source code from +. Instructions on how to configure, build and install this package are included within the package. Please make sure you build development and runtime libraries (which is the default). @@ -461,15 +412,13 @@ If you use Debian, you may want to install one of the precompiled packages for your system. These packages are equipped with system startup scripts and sample configurations. -If you cannot use one of the precompiled packages, or you want to + If you cannot use one of the precompiled packages, or you want to compile tinc for yourself, you can use the source. The source is distributed under the GNU General Public License (GPL). Download the -source from the download page (http://www.tinc-vpn.org/download/), which -has the checksums of these files listed; you may wish to check these -with md5sum before continuing. +source from the download page (https://www.tinc-vpn.org/download/). -Tinc comes in a convenient autoconf/automake package, which you can just -treat the same as any other package. Which is just untar it, type + Tinc comes in a convenient autoconf/automake package, which you can +just treat the same as any other package. Which is just untar it, type './configure' and then 'make'. More detailed instructions are in the file 'INSTALL', which is included in the source distribution. @@ -487,40 +436,41 @@ File: tinc.info, Node: Building and installing tinc, Next: System files, Up: Detailed instructions on configuring the source, building tinc and installing tinc can be found in the file called 'INSTALL'. -If you happen to have a binary package for tinc for your distribution, -you can use the package management tools of that distribution to install -tinc. The documentation that comes along with your distribution will -tell you how to do that. + If you happen to have a binary package for tinc for your +distribution, you can use the package management tools of that +distribution to install tinc. The documentation that comes along with +your distribution will tell you how to do that. * Menu: -* Darwin (MacOS/X) build environment:: +* Darwin (Mac OS X) build environment:: * Cygwin (Windows) build environment:: * MinGW (Windows) build environment::  -File: tinc.info, Node: Darwin (MacOS/X) build environment, Next: Cygwin (Windows) build environment, Up: Building and installing tinc +File: tinc.info, Node: Darwin (Mac OS X) build environment, Next: Cygwin (Windows) build environment, Up: Building and installing tinc -3.1.1 Darwin (MacOS/X) build environment ----------------------------------------- +3.1.1 Darwin (Mac OS X) build environment +----------------------------------------- -In order to build tinc on Darwin, you need to install the MacOS/X -Developer Tools from -and a recent version of Fink from . +In order to build tinc on Darwin, you need to install Xcode from +. It might also help to install a +recent version of Fink from . -After installation use fink to download and install the following -packages: autoconf25, automake, dlcompat, m4, openssl, zlib and lzo. + You need to download and install LibreSSL (or OpenSSL) and LZO, +either directly from their websites (see *note Libraries::) or using +Fink.  -File: tinc.info, Node: Cygwin (Windows) build environment, Next: MinGW (Windows) build environment, Prev: Darwin (MacOS/X) build environment, Up: Building and installing tinc +File: tinc.info, Node: Cygwin (Windows) build environment, Next: MinGW (Windows) build environment, Prev: Darwin (Mac OS X) build environment, Up: Building and installing tinc 3.1.2 Cygwin (Windows) build environment ---------------------------------------- If Cygwin hasn't already been installed, install it directly from -. +. -When tinc is compiled in a Cygwin environment, it can only be run in + When tinc is compiled in a Cygwin environment, it can only be run in this environment, but all programs, including those started outside the Cygwin environment, will be able to use the VPN. It will also support all features. @@ -532,12 +482,13 @@ File: tinc.info, Node: MinGW (Windows) build environment, Prev: Cygwin (Window --------------------------------------- You will need to install the MinGW environment from -. +. You also need to download and install LibreSSL +(or OpenSSL) and LZO. -When tinc is compiled using MinGW it runs natively under Windows, it is -not necessary to keep MinGW installed. + When tinc is compiled using MinGW it runs natively under Windows, it +is not necessary to keep MinGW installed. -When detaching, tinc will install itself as a service, which will be + When detaching, tinc will install itself as a service, which will be restarted automatically after reboots.  @@ -563,8 +514,8 @@ File: tinc.info, Node: Device files, Next: Other files, Up: System files Most operating systems nowadays come with the necessary device files by default, or they have a mechanism to create them on demand. -If you use Linux and do not have udev installed, you may need to create -the following device file if it does not exist: + If you use Linux and do not have udev installed, you may need to +create the following device file if it does not exist: mknod -m 600 /dev/net/tun c 10 200 @@ -605,6 +556,7 @@ File: tinc.info, Node: Configuration, Next: Running tinc, Prev: Installation, * Multiple networks:: * How connections work:: * Configuration files:: +* Generating keypairs:: * Network interfaces:: * Example configuration:: @@ -626,17 +578,11 @@ documentation. Make sure you have an adequate understanding of networks in general. A good resource on networking is the Linux Network Administrators Guide (http://www.tldp.org/LDP/nag2/). -If you have everything clearly pictured in your mind, proceed in the -following order: First, create the initial configuration files and -public/private keypairs using the following command: - tinc -n NETNAME init NAME -Second, use 'tinc -n NETNAME add ...' to further configure tinc. -Finally, export your host configuration file using 'tinc -n NETNAME -export' and send it to those people or computers you want tinc to -connect to. They should send you their host configuration file back, -which you can import using 'tinc -n NETNAME import'. - -These steps are described in the subsections below. + If you have everything clearly pictured in your mind, proceed in the +following order: First, generate the configuration files ('tinc.conf', +your host configuration file, 'tinc-up' and perhaps 'tinc-down'). Then +generate the keypairs. Finally, distribute the host configuration +files. These steps are described in the subsections below.  File: tinc.info, Node: Multiple networks, Next: How connections work, Prev: Configuration introduction, Up: Configuration @@ -647,25 +593,27 @@ File: tinc.info, Node: Multiple networks, Next: How connections work, Prev: C In order to allow you to run more than one tinc daemon on one computer, for instance if your computer is part of more than one VPN, you can assign a NETNAME to your VPN. It is not required if you only run one -tinc daemon, it doesn't even have to be the same on all the nodes of +tinc daemon, it doesn't even have to be the same on all the sites of your VPN, but it is recommended that you choose one anyway. -We will asume you use a netname throughout this document. This means -that you call tinc with the -n argument, which will specify the netname. + We will assume you use a netname throughout this document. This +means that you call tincd with the -n argument, which will assign a +netname to this daemon. -The effect of this option is that tinc will set its configuration root + The effect of this is that the daemon will set its configuration root to '/etc/tinc/NETNAME/', where NETNAME is your argument to the -n -option. You will also notice that log messages it appears in syslog as -coming from 'tinc.NETNAME', and on Linux, unless specified otherwise, -the name of the virtual network interface will be the same as the -network name. +option. You'll notice that it appears in syslog as 'tinc.NETNAME'. -However, it is not strictly necessary that you call tinc with the -n -option. If you don not use it, the network name will just be empty, and -tinc will look for files in '/etc/tinc/' instead of -'/etc/tinc/NETNAME/'; the configuration file will then be -'/etc/tinc/tinc.conf', and the host configuration files are expected to -be in '/etc/tinc/hosts/'. + However, it is not strictly necessary that you call tinc with the -n +option. In this case, the network name would just be empty, and it will +be used as such. tinc now looks for files in '/etc/tinc/', instead of +'/etc/tinc/NETNAME/'; the configuration file should be +'/etc/tinc/tinc.conf', and the host configuration files are now expected +to be in '/etc/tinc/hosts/'. + + But it is highly recommended that you use this feature of tinc, +because it will be so much clearer whom your daemon talks to. Hence, we +will assume that you use it.  File: tinc.info, Node: How connections work, Next: Configuration files, Prev: Multiple networks, Up: Configuration @@ -678,44 +626,21 @@ in the configuration file tinc.conf. If it sees one or more 'ConnectTo' values pointing to other tinc daemons in that file, it will try to connect to those other daemons. Whether this succeeds or not and whether 'ConnectTo' is specified or not, tinc will listen for incoming -connection from other deamons. If you did specify a 'ConnectTo' value +connection from other daemons. If you did specify a 'ConnectTo' value and the other side is not responding, tinc will keep retrying. This means that once started, tinc will stay running until you tell it to stop, and failures to connect to other tinc daemons will not stop your tinc daemon for trying again later. This means you don't have to intervene if there are temporary network problems. -There is no real distinction between a server and a client in tinc. If -you wish, you can view a tinc daemon without a 'ConnectTo' value as a + There is no real distinction between a server and a client in tinc. +If you wish, you can view a tinc daemon without a 'ConnectTo' value as a server, and one which does specify such a value as a client. It does not matter if two tinc daemons have a 'ConnectTo' value pointing to each other however. -Connections specified using 'ConnectTo' are so-called meta-connections. -Tinc daemons exchange information about all other daemon they know about -via these meta-connections. After learning about all the daemons in the -VPN, tinc will create other connections as necessary in order to -communicate with them. For example, if there are three daemons named A, -B and C, and A has 'ConnectTo = B' in its tinc.conf file, and C has -'ConnectTo = B' in its tinc.conf file, then A will learn about C from B, -and will be able to exchange VPN packets with C without the need to have -'ConnectTo = C' in its tinc.conf file. - -It could be that some daemons are located behind a Network Address -Translation (NAT) device, or behind a firewall. In the above scenario -with three daemons, if A and C are behind a NAT, B will automatically -help A and C punch holes through their NAT, in a way similar to the STUN -protocol, so that A and C can still communicate with each other -directly. It is not always possible to do this however, and firewalls -might also prevent direct communication. In that case, VPN packets -between A and C will be forwarded by B. - -In effect, all nodes in the VPN will be able to talk to each other, as -long as their is a path of meta-connections between them, and whenever -possible, two nodes will communicate with each other directly. -  -File: tinc.info, Node: Configuration files, Next: Network interfaces, Prev: How connections work, Up: Configuration +File: tinc.info, Node: Configuration files, Next: Generating keypairs, Prev: How connections work, Up: Configuration 4.4 Configuration files ======================= @@ -724,29 +649,29 @@ The actual configuration of the daemon is done in the file '/etc/tinc/NETNAME/tinc.conf' and at least one other file in the directory '/etc/tinc/NETNAME/hosts/'. -These file consists of comments (lines started with a #) or assignments -in the form of + An optional directory '/etc/tinc/NETNAME/conf.d' can be added from +which any .conf file will be read. + + These file consists of comments (lines started with a #) or +assignments in the form of Variable = Value. -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 '=' sign, but doing so improves readability. If you leave it -out, remember to replace it with at least one space character. + 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 '=' sign, but doing so improves readability. If you +leave it out, remember to replace it with at least one space character. -The server configuration is complemented with host specific + The server configuration is complemented with host specific configuration (see the next section). Although all host configuration options for the local node listed in this document can also be put in '/etc/tinc/NETNAME/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. -You can edit the config file manually, but it is recommended that you -use the tinc command to change configuration variables for you. - -In the following two subsections all valid variables are listed in -alphabetical order. The default value is given between parentheses, -other comments are between square brackets. + In this section all valid variables are listed in alphabetical order. +The default value is given between parentheses, other comments are +between square brackets. * Menu: @@ -767,14 +692,7 @@ AddressFamily = (any) system both IPv4 and IPv6 or just IPv6 listening sockets will be created. -AutoConnect = (0) [experimental] - If set to a non-zero value, tinc will try to only have 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. - -BindToAddress =
[] +BindToAddress =
[] [experimental] If your computer has more than one IPv4 or IPv6 address, tinc will by default listen on all of them for incoming connections. Multiple BindToAddress variables may be specified, in which case @@ -785,15 +703,15 @@ BindToAddress =
[] To only bind to a specific port but not to a specific address, use "*" for the ADDRESS. + This option may not work on all platforms. + BindToInterface = [experimental] If you have more than one network interface in your computer, tinc will by default listen on all of them for incoming connections. It is possible to bind tinc to a single interface like eth0 or ppp0 with this variable. - 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. + This option may not work on all platforms. Broadcast = (mst) [experimental] This option selects the way broadcast packets are sent to other @@ -837,10 +755,9 @@ DecrementTTL = (no) [experimental] Device = ('/dev/tap0', '/dev/net/tun' or other depending on platform) The virtual network device to use. Tinc will automatically detect - what kind of device it is. Note that you can only use one device - per daemon. Under Windows, use INTERFACE instead of DEVICE. Note - that you can only use one device per daemon. See also *note Device - files::. + what kind of device it is. Under Windows, use INTERFACE instead of + DEVICE. Note that you can only use one device per daemon. See + also *note Device files::. DeviceType = (platform dependent) The type of the virtual network device. Tinc will normally @@ -874,13 +791,13 @@ DeviceType = (platform dependent) uml (not compiled in by default) Create a UNIX socket with the filename specified by DEVICE, or - '/var/run/NETNAME.umlsocket' if not specified. Tinc will wait - for a User Mode Linux instance to connect to this socket. + '/run/NETNAME.umlsocket' if not specified. Tinc will wait for + a User Mode Linux instance to connect to this socket. vde (not compiled in by default) Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch, using the UNIX socket specified - by DEVICE, or '/var/run/vde.ctl' if not specified. + by DEVICE, or '/run/vde.ctl' if not specified. Also, in case tinc does not seem to correctly interpret packets received from the virtual network device, it can be used to change @@ -903,6 +820,11 @@ DeviceType = (platform dependent) followed by an IP header. This mode should support both IPv4 and IPv6 packets. + utun (OS X) + Set type to utun. This is only supported on OS X version + 10.6.8 and higher, but doesn't require the tuntaposx module. + This mode should support both IPv4 and IPv6 packets. + tap (BSD and Linux) Set type to tap. Tinc will expect packets read from the virtual network device to start with an Ethernet header. @@ -914,17 +836,6 @@ DirectOnly = (no) [experimental] IndirectData option, packets for nodes for which we do not have a meta connection with are also dropped. -ECDSAPrivateKeyFile = ('/etc/tinc/NETNAME/ecdsa_key.priv') - The file in which the private ECDSA key of this tinc daemon - resides. This is only used if ExperimentalProtocol is enabled. - -ExperimentalProtocol = (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 'tinc generate-ecdsa-keys'. - Forwarding = (internal) [experimental] This option selects the way indirect packets are forwarded. @@ -945,17 +856,28 @@ Forwarding = (internal) [experimental] efficient, but allows the kernel to apply its routing and firewall rules on them, and can also help debugging. +GraphDumpFile = [experimental] + If this option is present, tinc will dump the current network graph + to the file FILENAME every minute, unless there were no changes to + the graph. The file is in a format that can be read by graphviz + tools. If FILENAME starts with a pipe symbol |, then the rest of + the filename is interpreted as a shell command that is executed, + the graph is then sent to stdin. + Hostnames = (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 everytime it does a lookup if your DNS server is not + seconds every time it does a lookup if your DNS server is not responding. This does not affect resolving hostnames to IP addresses from the configuration file, but whether hostnames should be resolved while logging. +IffOneQueue = (no) [experimental] + (Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices. + Interface = Defines the name of the interface corresponding to the virtual network device. Depending on the operating system and the type of @@ -964,7 +886,13 @@ Interface = interface will be used. If you specified a Device, this variable is almost always already correctly set. -LocalDiscovery = (no) +KeyExpire = (3600) + This option controls the time 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. + +LocalDiscovery = (no) [experimental] When enabled, 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 @@ -975,16 +903,21 @@ LocalDiscovery = (no) packets to the LAN during path MTU discovery. This feature may not work in all possible situations. -LocalDiscoveryAddress
- If this variable is specified, local discovery packets are sent to - the given ADDRESS. +MACExpire = (600) + This option controls the amount of time MAC addresses are kept + before they are removed. This only has effect when Mode is set to + "switch". + +MaxTimeout = (900) + This is the maximum delay before trying to reconnect to other tinc + daemons. Mode = (router) This option selects the way packets are routed to other daemons. router In this mode Subnet variables in the host configuration files - will be used to form a routing table. Only packets of + will be used to form a routing table. Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode. This is the default mode, and unless you really know you need @@ -1006,27 +939,10 @@ Mode = (router) every packet will be broadcast to the other daemons while no routing table is managed. -KeyExpire = (3600) - This option controls the time 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. - -MACExpire = (600) - This option controls the amount of time MAC addresses are kept - before they are removed. This only has effect when Mode is set to - "switch". - -MaxConnectionBurst = (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. - Name = [required] - This is a symbolic name for this connection. The name should - consist only of alfanumeric and underscore characters (a-z, A-Z, - 0-9 and _), and is case sensitive. + This is a symbolic name for this connection. The name must consist + only of alphanumeric and underscore characters (a-z, A-Z, 0-9 and + _). If Name starts with a $, then the contents of the environment variable that follows will be used. In that case, invalid @@ -1052,20 +968,20 @@ PriorityInheritance = (no) [experimental] PrivateKey = [obsolete] This is the RSA private key for tinc. However, for safety reasons it is advised to store private keys of any kind in separate files. - This prevents accidental eavesdropping if you are editting the + This prevents accidental eavesdropping if you are editing the configuration file. PrivateKeyFile = ('/etc/tinc/NETNAME/rsa_key.priv') This is the full path name of the RSA private key file that was - generated by 'tinc generate-keys'. It must be a full path, not a - relative directory. + generated by 'tincd --generate-keys'. It must be a full path, not + a relative directory. ProcessPriority = When this option is used the priority of the tincd process will be adjusted. Increasing the priority may help to reduce latency and packet loss on the VPN. -Proxy = socks4 | socks4 | http | exec ... [experimental] +Proxy = socks4 | socks5 | http | exec ... [experimental] Use a proxy when making outgoing connections. The following proxy types are currently supported: @@ -1074,7 +990,7 @@ Proxy = socks4 | socks4 | http | exec ... [experimental] Optionally, a USERNAME can be supplied which will be passed on to the proxy server. - socks4
[ ] + socks5
[ ] Connect to the proxy using the SOCKS version 5 protocol. If a USERNAME and PASSWORD are given, basic username/password authentication will be used, otherwise no authentication will @@ -1099,10 +1015,12 @@ ReplayWindow = (16) pass all traffic, but leaves tinc vulnerable to replay-based attacks on your traffic. -StrictSubnets (no) [experimental] +StrictSubnets = (no) [experimental] When this option is enabled tinc will only use Subnet statements which are present in the host config files in the local - '/etc/tinc/NETNAME/hosts/' directory. + '/etc/tinc/NETNAME/hosts/' directory. Subnets learned via + connections to other nodes and which are not present in the local + host config files are ignored. TunnelServer = (no) [experimental] When this option is enabled tinc will no longer forward information @@ -1131,15 +1049,15 @@ Address = [] [recommended] This variable is only required if you want to connect to this host. It must resolve to the external IP address where the host can be reached, not the one that is internal to the VPN. If no port is - specified, the default Port is used. + specified, the default Port is used. Multiple Address variables + can be specified, in which case each address will be tried until a + working connection has been established. -Cipher = (blowfish) - The symmetric cipher algorithm used to encrypt UDP packets using - the legacy protocol. Any cipher supported by OpenSSL is - recognized. Furthermore, specifying "none" will turn off packet - encryption. It is best to use only those ciphers which support CBC - mode. This option has no effect for connections using the SPTPS - protocol, which always use AES-256-CTR. +Cipher = (aes-256-cbc) + The symmetric cipher algorithm used to encrypt UDP packets. Any + cipher supported by LibreSSL or OpenSSL is recognized. + Furthermore, specifying "none" will turn off packet encryption. It + is best to use only those ciphers which support CBC mode. ClampMSS = (yes) This option specifies whether tinc should clamp the maximum segment @@ -1152,24 +1070,23 @@ Compression = (0) Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib), 10 (fast lzo) and 11 (best lzo). -Digest = (sha1) - The digest algorithm used to authenticate UDP packets using the - legacy protocol. Any digest supported by OpenSSL is recognized. - Furthermore, specifying "none" will turn off packet authentication. - This option has no effect for connections using the SPTPS protocol, - which always use HMAC-SHA-256. +Digest = (sha256) + The digest algorithm used to authenticate UDP packets. Any digest + supported by LibreSSL or OpenSSL is recognized. Furthermore, + specifying "none" will turn off packet authentication. IndirectData = (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. + This option specifies whether other tinc daemons besides the one + you specified with ConnectTo can make a direct connection to you. + This is especially useful if you are behind a firewall and it is + impossible to make a connection from the outside to your tinc + daemon. Otherwise, it is best to leave this option out or set it + to no. MACLength = (4) The length of the message authentication code used to authenticate - UDP packets using the legacy protocol. Can be anything from 0 up - to the length of the digest produced by the digest algorithm. This - option has no effect for connections using the SPTPS protocol, - which never truncate MACs. + UDP packets. Can be anything from 0 up to the length of the digest + produced by the digest algorithm. PMTU = (1514) This option controls the initial path MTU to this node. @@ -1188,8 +1105,8 @@ PublicKey = [obsolete] PublicKeyFile = [obsolete] This is the full path name of the RSA public key file that was - generated by 'tinc generate-keys'. It must be a full path, not a - relative directory. + generated by 'tincd --generate-keys'. It must be a full path, not + a relative directory. From version 1.0pre4 on tinc will store the public key directly into the host configuration file in PEM format, the above two @@ -1201,9 +1118,9 @@ PublicKeyFile = [obsolete] Subnet = The subnet which this tinc daemon will serve. Tinc tries to look up which other daemon it should send a packet to by searching the - appropiate subnet. If the packet matches a subnet, it will be sent - to the daemon who has this subnet in his host configuration file. - Multiple subnet lines can be specified for each daemon. + 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 subnet lines can be specified for each daemon. Subnets can either be single MAC, IPv4 or IPv6 addresses, in which case a subnet consisting of only that single address is assumed, or @@ -1218,7 +1135,7 @@ Subnet = Prefixlength is the number of bits set to 1 in the netmask part; for example: netmask 255.255.255.0 would become /24, 255.255.252.0 becomes /22. This conforms to standard CIDR notation as described - in RFC1519 (http://www.ietf.org/rfc/rfc1519.txt) + in RFC1519 (https://www.ietf.org/rfc/rfc1519.txt) A Subnet can be given a weight to indicate its priority over identical Subnets owned by different nodes. The default weight is @@ -1227,13 +1144,16 @@ Subnet = reachable, in which case the node with the next highest priority will be tried, and so on. -TCPonly = (no) +TCPonly = (no) [deprecated] If this variable is set to yes, then the packets are tunnelled over a 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. + Since version 1.0.10, tinc will automatically detect whether + communication via UDP is possible or not. +  File: tinc.info, Node: Scripts, Next: How to configure, Prev: Host configuration variables, Up: Configuration files @@ -1241,16 +1161,27 @@ File: tinc.info, Node: Scripts, Next: How to configure, Prev: Host configurat ------------- 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 .bat. +also run scripts at certain moments. Below is a list of filenames of +scripts and a description of when they are run. A script is only run if +it exists and if it is executable. + + Scripts are run synchronously; this means that tinc will temporarily +stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the +events that trigger them. If you need to run commands asynchronously, +you have to ensure yourself that they are being run in the background. + + Under Windows (not Cygwin), the scripts must have the extension .bat. '/etc/tinc/NETNAME/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. + start other things. + + Under Windows you can use the Network Connections control panel + instead of creating this script. '/etc/tinc/NETNAME/tinc-down' This script is started right before the tinc daemon quits. @@ -1270,15 +1201,15 @@ scripts should have the extension .bat. This script is started when any host becomes unreachable. '/etc/tinc/NETNAME/subnet-up' - This script is started when a Subnet becomes reachable. The Subnet + This script is started when a subnet becomes reachable. The Subnet and the node it belongs to are passed in environment variables. '/etc/tinc/NETNAME/subnet-down' - This script is started when a Subnet becomes unreachable. + This script is started when a subnet becomes unreachable. -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 $ in scripts. + 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 $ in scripts. Under Windows, in '.bat' files, they have to be put between % signs. 'NETNAME' @@ -1309,164 +1240,99 @@ Under Windows, in '.bat' files, they have to be put between % signs. 'SUBNET' When a subnet becomes (un)reachable, this is set to the subnet. +'WEIGHT' + When a subnet becomes (un)reachable, this is set to the subnet + weight. +  File: tinc.info, Node: How to configure, Prev: Scripts, Up: Configuration files 4.4.4 How to configure ---------------------- -Step 1. Creating initial configuration files. -............................................. - -The initial directory structure, configuration files and public/private -keypairs are created using the following command: - - tinc -n NETNAME init NAME - -(You will need to run this as root, or use "sudo".) This will create -the configuration directory '/etc/tinc/NETNAME.', and inside it will -create another directory named 'hosts/'. In the configuration -directory, it will create the file 'tinc.conf' with the following -contents: - - Name = NAME - -It will also create private RSA and ECDSA keys, which will be stored in -the files 'rsa_key.priv' and 'ecdsa_key.priv'. It will also create a -host configuration file 'hosts/NAME', which will contain the -corresponding public RSA and ECDSA keys. - -Finally, on UNIX operating systems, it will create an executable script -'tinc-up', which will initially not do anything except warning that you -should edit it. - -Step 2. Modifying the initial configuration. +Step 1. Creating the main configuration file ............................................ -Unless you want to use tinc in switch mode, you should now configure -which range of addresses you will use on the VPN. Let's assume you will -be part of a VPN which uses the address range 192.168.0.0/16, and you -yourself have a smaller portion of that range: 192.168.2.0/24. Then you -should run the following command: +The main configuration file will be called +'/etc/tinc/NETNAME/tinc.conf'. Adapt the following example to create a +basic configuration file: - tinc -n NETNAME add subnet 192.168.2.0/24 + Name = YOURNAME + Device = /dev/tap0 -This will add a Subnet statement to your host configuration file. Try -opening the file '/etc/tinc/NETNAME/hosts/NAME' in an editor. You -should now see a file containing the public RSA and ECDSA keys (which -looks like a bunch of random characters), and the following line at the -bottom: + Then, if you know to which other tinc daemon(s) yours is going to +connect, add 'ConnectTo' values. - Subnet = 192.168.2.0/24 +Step 2. Creating your host configuration file +............................................. -If you will use more than one address range, you can add more Subnets. -For example, if you also use the IPv6 subnet fec0:0:0:2::/64, you can -add it as well: +If you added a line containing 'Name = yourname' in the main +configuration file, you will need to create a host configuration file +'/etc/tinc/NETNAME/hosts/yourname'. Adapt the following example to +create a host configuration file: - tinc -n NETNAME add subnet fec0:0:0:2::/24 + Address = your.real.hostname.org + Subnet = 192.168.1.0/24 -This will add another line to the file 'hosts/NAME'. If you make a -mistake, you can undo it by simply using 'del' instead of 'add'. - -If you want other tinc daemons to create meta-connections to your -daemon, you should add your public IP address or hostname to your host -configuration file. For example, if your hostname is foo.example.org, -run: - - tinc -n NETNAME add address foo.example.org - -If you already know to which daemons your daemon should make -meta-connections, you should configure that now as well. Suppose you -want to connect to a daemon named "bar", run: - - tinc -n NETNAME add connectto bar - -Note that you specify the Name of the other daemon here, not an IP -address or hostname! When you start tinc, and it tries to make a -connection to "bar", it will look for a host configuration file named -'hosts/bar', and will read Address statements and public keys from that -file. - -Step 2. Exchanging configuration files. -....................................... - -If your daemon has a ConnectTo = bar statement in its 'tinc.conf' file, -or if bar has a ConnectTo your daemon, then you both need each other's -host configuration files. You should send 'hosts/NAME' to bar, and bar -should send you his file which you should move to 'hosts/bar'. If you -are on a UNIX platform, you can easily send an email containing the -necessary information using the following command (assuming the owner of -bar has the email address bar@example.org): - - tinc -n NETNAME export | mail -s "My config file" bar@example.org - -If the owner of bar does the same to send his host configuration file to -you, you can probably pipe his email through the following command, or -you can just start this command in a terminal and copy&paste the email: - - tinc -n NETNAME import - -If you are the owner of bar yourself, and you have SSH access to that -computer, you can also swap the host configuration files using the -following command: - - tinc -n NETNAME export \ - | ssh bar.example.org tinc -n NETNAME exchange \ - | tinc -n NETNAME import - -You should repeat this for all nodes you ConnectTo, or which ConnectTo -you. However, remember that you do not need to ConnectTo all nodes in -the VPN; it is only necessary to create one or a few meta-connections, -after the connections are made tinc will learn about all the other nodes -in the VPN, and will automatically make other connections as necessary. + You can also use an IP address instead of a hostname. The 'Subnet' +specifies the address range that is local for _your part of the VPN +only_. If you have multiple address ranges you can specify more than +one 'Subnet'. You might also need to add a 'Port' if you want your tinc +daemon to run on a different port number than the default (655).  -File: tinc.info, Node: Network interfaces, Next: Example configuration, Prev: Configuration files, Up: Configuration +File: tinc.info, Node: Generating keypairs, Next: Network interfaces, Prev: Configuration files, Up: Configuration -4.5 Network interfaces +4.5 Generating keypairs +======================= + +Now that you have already created the main configuration file and your +host configuration file, you can easily create a public/private keypair +by entering the following command: + + tincd -n NETNAME -K + + Tinc will generate a public and a private key and ask you where to +put them. Just press enter to accept the defaults. + + +File: tinc.info, Node: Network interfaces, Next: Example configuration, Prev: Generating keypairs, Up: Configuration + +4.6 Network interfaces ====================== Before tinc can start transmitting data over the tunnel, it must set up the virtual network interface. -First, decide which IP addresses you want to have associated with these -devices, and what network mask they must have. + First, decide which IP addresses you want to have associated with +these devices, and what network mask they must have. -Tinc will open a virtual network device ('/dev/tun', '/dev/tap0' or + Tinc will open a virtual network device ('/dev/tun', '/dev/tap0' or similar), which will also create a network interface called something like 'tun0', 'tap0'. If you are using the Linux tun/tap driver, the network interface will by default have the same name as the NETNAME. Under Windows you can change the name of the network interface from the Network Connections control panel. -You can configure the network interface by putting ordinary ifconfig, + You can configure the network interface by putting ordinary ifconfig, route, and other commands to a script named '/etc/tinc/NETNAME/tinc-up'. When tinc starts, this script will be executed. When tinc exits, it will execute the script named '/etc/tinc/NETNAME/tinc-down', but -normally you don't need to create that script. You can manually open -the script in an editor, or use the following command: +normally you don't need to create that script. - tinc -n NETNAME edit tinc-up - -An example 'tinc-up' script, that would be appropriate for the scenario -in the previous section, is: + An example 'tinc-up' script: #!/bin/sh - ifconfig $INTERFACE 192.168.2.1 netmask 255.255.0.0 - ip addr add fec0:0:0:2::/48 dev $INTERFACE + ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 -The first command gives the interface an IPv4 address and a netmask. -The kernel will also automatically add an IPv4 route to this interface, -so normally you don't need to add route commands to the 'tinc-up' -script. The kernel will also bring the interface up after this command. -The netmask is the mask of the _entire_ VPN network, not just your own -subnet. The second command gives the interface an IPv6 address and -netmask, which will also automatically add an IPv6 route. If you only -want to use "ip addr" commands on Linux, don't forget that it doesn't -bring the interface up, unlike ifconfig, so you need to add 'ip link set -$INTERFACE up' in that case. + This script gives the interface an IP address and a netmask. The +kernel will also automatically add a route to this interface, so +normally you don't need to add route commands to the 'tinc-up' script. +The kernel will also bring the interface up after this command. The +netmask is the mask of the _entire_ VPN network, not just your own +subnet. -The exact syntax of the ifconfig and route commands differs from + The exact syntax of the ifconfig and route commands differs from platform to platform. You can look up the commands for setting addresses and adding routes in *note Platform specific information::, but it is best to consult the manpages of those utilities on your @@ -1475,56 +1341,52 @@ platform.  File: tinc.info, Node: Example configuration, Prev: Network interfaces, Up: Configuration -4.6 Example configuration +4.7 Example configuration ========================= Imagine the following situation. Branch A of our example 'company' wants to connect three branch offices in B, C and D using the Internet. All four offices have a 24/7 connection to the Internet. -A is going to serve as the center of the network. B and C will connect -to A, and D will connect to C. Each office will be assigned their own IP -network, 10.x.0.0. + A is going to serve as the center of the network. B and C will +connect to A, and D will connect to C. Each office will be assigned +their own IP network, 10.x.0.0. A: net 10.1.0.0 mask 255.255.0.0 gateway 10.1.54.1 internet IP 1.2.3.4 B: net 10.2.0.0 mask 255.255.0.0 gateway 10.2.1.12 internet IP 2.3.4.5 C: net 10.3.0.0 mask 255.255.0.0 gateway 10.3.69.254 internet IP 3.4.5.6 D: net 10.4.0.0 mask 255.255.0.0 gateway 10.4.3.32 internet IP 4.5.6.7 -Here, "gateway" is the VPN IP address of the machine that is running the -tincd, and "internet IP" is the IP address of the firewall, which does -not need to run tincd, but it must do a port forwarding of TCP and UDP -on port 655 (unless otherwise configured). + Here, "gateway" is the VPN IP address of the machine that is running +the tincd, and "internet IP" is the IP address of the firewall, which +does not need to run tincd, but it must do a port forwarding of TCP and +UDP on port 655 (unless otherwise configured). -In this example, it is assumed that eth0 is the interface that points to -the inner (physical) LAN of the office, although this could also be the -same as the interface that leads to the Internet. The configuration of -the real interface is also shown as a comment, to give you an idea of + In this example, it is assumed that eth0 is the interface that points +to the inner (physical) LAN of the office, although this could also be +the same as the interface that leads to the Internet. The configuration +of the real interface is also shown as a comment, to give you an idea of how these example host is set up. All branches use the netname 'company' for this particular VPN. -Each branch is set up using the 'tinc init' and 'tinc config' commands, -here we just show the end results: - For Branch A ............ _BranchA_ would be configured like this: -In '/etc/tinc/company/tinc-up': - - #!/bin/sh + In '/etc/tinc/company/tinc-up': # Real interface of internal network: # ifconfig eth0 10.1.54.1 netmask 255.255.0.0 ifconfig $INTERFACE 10.1.54.1 netmask 255.0.0.0 -and in '/etc/tinc/company/tinc.conf': + and in '/etc/tinc/company/tinc.conf': Name = BranchA + Device = /dev/tap0 -On all hosts, '/etc/tinc/company/hosts/BranchA' contains: + On all hosts, '/etc/tinc/company/hosts/BranchA' contains: Subnet = 10.1.0.0/16 Address = 1.2.3.4 @@ -1533,34 +1395,32 @@ On all hosts, '/etc/tinc/company/hosts/BranchA' contains: ... -----END RSA PUBLIC KEY----- -Note that the IP addresses of eth0 and the VPN interface are the same. -This is quite possible, if you make sure that the netmasks of the -interfaces are different. It is in fact recommended to give both real -internal network interfaces and VPN interfaces the same IP address, -since that will make things a lot easier to remember and set up. + Note that the IP addresses of eth0 and tap0 are the same. This is +quite possible, if you make sure that the netmasks of the interfaces are +different. It is in fact recommended to give both real internal network +interfaces and tap interfaces the same IP address, since that will make +things a lot easier to remember and set up. For Branch B ............ In '/etc/tinc/company/tinc-up': - #!/bin/sh - # Real interface of internal network: # ifconfig eth0 10.2.43.8 netmask 255.255.0.0 ifconfig $INTERFACE 10.2.1.12 netmask 255.0.0.0 -and in '/etc/tinc/company/tinc.conf': + and in '/etc/tinc/company/tinc.conf': Name = BranchB ConnectTo = BranchA -Note here that the internal address (on eth0) doesn't have to be the -same as on the VPN interface. Also, ConnectTo is given so that this -node will always try to connect to BranchA. + Note here that the internal address (on eth0) doesn't have to be the +same as on the tap0 device. Also, ConnectTo is given so that this node +will always try to connect to BranchA. -On all hosts, in '/etc/tinc/company/hosts/BranchB': + On all hosts, in '/etc/tinc/company/hosts/BranchB': Subnet = 10.2.0.0/16 Address = 2.3.4.5 @@ -1574,23 +1434,22 @@ For Branch C In '/etc/tinc/company/tinc-up': - #!/bin/sh - # Real interface of internal network: # ifconfig eth0 10.3.69.254 netmask 255.255.0.0 ifconfig $INTERFACE 10.3.69.254 netmask 255.0.0.0 -and in '/etc/tinc/company/tinc.conf': + and in '/etc/tinc/company/tinc.conf': Name = BranchC ConnectTo = BranchA + Device = /dev/tap1 -C already has another daemon that runs on port 655, so they have to + C already has another daemon that runs on port 655, so they have to reserve another port for tinc. It knows the portnumber it has to listen on from it's own host configuration file. -On all hosts, in '/etc/tinc/company/hosts/BranchC': + On all hosts, in '/etc/tinc/company/hosts/BranchC': Address = 3.4.5.6 Subnet = 10.3.0.0/16 @@ -1605,22 +1464,24 @@ For Branch D In '/etc/tinc/company/tinc-up': - #!/bin/sh - # Real interface of internal network: # ifconfig eth0 10.4.3.32 netmask 255.255.0.0 ifconfig $INTERFACE 10.4.3.32 netmask 255.0.0.0 -and in '/etc/tinc/company/tinc.conf': + and in '/etc/tinc/company/tinc.conf': Name = BranchD ConnectTo = BranchC + Device = /dev/net/tun -D will be connecting to C, which has a tincd running for this network on -port 2000. It knows the port number from the host configuration file. + D will be connecting to C, which has a tincd running for this network +on port 2000. It knows the port number from the host configuration +file. Also note that since D uses the tun/tap driver, the network +interface will not be called 'tun' or 'tap0' or something like that, but +will have the same name as netname. -On all hosts, in '/etc/tinc/company/hosts/BranchD': + On all hosts, in '/etc/tinc/company/hosts/BranchD': Subnet = 10.4.0.0/16 Address = 4.5.6.7 @@ -1632,12 +1493,16 @@ On all hosts, in '/etc/tinc/company/hosts/BranchD': Key files ......... -A, B, C and D all have their own public/private keypairs: +A, B, C and D all have generated a public/private keypair with the +following command: -The private RSA key is stored in '/etc/tinc/company/rsa_key.priv', the -private ECDSA key is stored in '/etc/tinc/company/ecdsa_key.priv', and -the public RSA and ECDSA keys are put into the host configuration file -in the '/etc/tinc/company/hosts/' directory. + tincd -n company -K + + The private key is stored in '/etc/tinc/company/rsa_key.priv', the +public key is put into the host configuration file in the +'/etc/tinc/company/hosts/' directory. During key generation, tinc +automatically guesses the right filenames based on the -n option and the +Name directive in the 'tinc.conf' file (if it is available). Starting ........ @@ -1649,7 +1514,7 @@ have started their daemons, tinc will try connecting until they are available.  -File: tinc.info, Node: Running tinc, Next: Controlling tinc, Prev: Configuration, Up: Top +File: tinc.info, Node: Running tinc, Next: Technical information, Prev: Configuration, Up: Top 5 Running tinc ************** @@ -1657,12 +1522,12 @@ File: tinc.info, Node: Running tinc, Next: Controlling tinc, Prev: Configurat If everything else is done, you can start tinc by typing the following command: - tinc -n NETNAME start + tincd -n NETNAME -Tinc will detach from the terminal and continue to run in the background -like a good daemon. If there are any problems however you can try to -increase the debug level and look in the syslog to find out what the -problems are. + Tinc will detach from the terminal and continue to run in the +background like a good daemon. If there are any problems however you +can try to increase the debug level and look in the syslog to find out +what the problems are. * Menu: @@ -1694,15 +1559,25 @@ command line options. Set debug level to LEVEL. The higher the debug level, the more gets logged. Everything goes via syslog. +'-k, --kill[=SIGNAL]' + Attempt to kill a running tincd (optionally with the specified + SIGNAL instead of SIGTERM) and exit. Use it in conjunction with + the -n option to make sure you kill the right tinc daemon. Under + native Windows the optional argument is ignored, the service will + always be stopped and removed. + '-n, --net=NETNAME' Use configuration for net NETNAME. This will let tinc read all configuration files from '/etc/tinc/NETNAME/'. Specifying . for NETNAME is the same as not specifying any NETNAME. *Note Multiple networks::. -'--pidfile=FILENAME' - Store a cookie in FILENAME which allows tinc to authenticate. If - unspecified, the default is '/var/run/tinc.NETNAME.pid'. +'-K, --generate-keys[=BITS]' + Generate public/private keypair of BITS length. If BITS is not + specified, 2048 is the default. tinc will ask where you want to + store the files, but will default to the configuration directory + (you can use the -c or -n option in combination with -K). After + that, tinc will quit. '-o, --option=[HOST.]KEY=VALUE' Without specifying a HOST, this will set server configuration @@ -1716,13 +1591,14 @@ command line options. shared private keys to be written to the system swap files/partitions. - This option is not supported on all platforms. - '--logfile[=FILE]' Write log entries to a file instead of to the system logging facility. If FILE is omitted, the default is '/var/log/tinc.NETNAME.log'. +'--pidfile=FILE' + Write PID to FILE instead of '/run/tinc.NETNAME.pid'. + '--bypass-security' Disables encryption and authentication. Only useful for debugging. @@ -1733,21 +1609,22 @@ command line options. chroot is performed after all the initialization is done, after writing pid files and opening network sockets. - Note that this option alone does not do any good without -U/-user, - below. + This option is best used in combination with the -U/-user option + described below. - Note also that tinc can't run scripts anymore (such as tinc-down or - host-up), unless it's setup to be runnable inside chroot - environment. + You will need to ensure the chroot environment contains all the + files necessary for tinc to run correctly. Most importantly, for + tinc to be able to resolve hostnames inside the chroot environment, + you must copy '/etc/resolv.conf' into the chroot directory. If you + want to be able to run scripts other than 'tinc-up' in the chroot, + you must ensure the appropriate shell is also installed in the + chroot, along with all its dependencies. - This option is not supported on all platforms. '-U, --user=USER' Switch to the given USER after initialization, at the same time as chroot is performed (see -chroot above). With this option tinc drops privileges, for added security. - This option is not supported on all platforms. - '--help' Display a short reminder of these runtime options and terminate. @@ -1776,6 +1653,20 @@ You can also send the following signals to a running tincd process: used, this will also close and reopen the log file, useful when log rotation is used. +'INT' + Temporarily increases debug level to 5. Send this signal again to + revert to the original level. + +'USR1' + Dumps the connection list to syslog. + +'USR2' + Dumps virtual network device statistics, all known nodes, edges and + subnets to syslog. + +'WINCH' + Purges all information remembered about unreachable nodes. +  File: tinc.info, Node: Debug levels, Next: Solving problems, Prev: Signals, Up: Running tinc @@ -1822,7 +1713,7 @@ directly see everything tinc logs: tincd -n NETNAME -d5 -D -If tinc does not log any error messages, then you might want to check + If tinc does not log any error messages, then you might want to check the following things: * 'tinc-up' script Does this script contain the right commands? @@ -1841,7 +1732,9 @@ the following things: it, make sure that it forwards TCP and UDP traffic to port 655 to the host running tinc. You can add 'TCPOnly = yes' to your host config file to force tinc to only use a single TCP connection, this - works through most firewalls and NATs. + works through most firewalls and NATs. Since version 1.0.10, tinc + will automatically fall back to TCP if direct communication via UDP + is not possible.  File: tinc.info, Node: Error messages, Next: Sending bug reports, Prev: Solving problems, Up: Running tinc @@ -1932,11 +1825,6 @@ high enough. * If you see this only sporadically, it is harmless and caused by a node sending packets using an old key. - * If you see this often and another node is not reachable - anymore, then a NAT (masquerading firewall) is changing the - source address of UDP packets. You can add 'TCPOnly = yes' to - host configuration files to force all VPN traffic to go over a - TCP connection. 'Got bad/bogus/unauthorized REQUEST from foo (1.2.3.4 port 12345)' @@ -1970,295 +1858,9 @@ bugreport: ping or traceroute).  -File: tinc.info, Node: Controlling tinc, Next: Technical information, Prev: Running tinc, Up: Top +File: tinc.info, Node: Technical information, Next: Platform specific information, Prev: Running tinc, Up: Top -6 Controlling tinc -****************** - -You can control and inspect a running tincd through the tinc command. A -quick example: - - tinc -n NETNAME reload - -* Menu: - -* tinc runtime options:: -* tinc environment variables:: -* tinc commands:: -* tinc examples:: -* tinc top:: - - -File: tinc.info, Node: tinc runtime options, Next: tinc environment variables, Up: Controlling tinc - -6.1 tinc runtime options -======================== - -'-c, --config=PATH' - Read configuration options from the directory PATH. The default is - '/etc/tinc/NETNAME/'. - -'-n, --net=NETNAME' - Use configuration for net NETNAME. *Note Multiple networks::. - -'--pidfile=FILENAME' - Use the cookie from FILENAME to authenticate with a running tinc - daemon. If unspecified, the default is - '/var/run/tinc.NETNAME.pid'. - -'--help' - Display a short reminder of runtime options and commands, then - terminate. - -'--version' - Output version information and exit. - - -File: tinc.info, Node: tinc environment variables, Next: tinc commands, Prev: tinc runtime options, Up: Controlling tinc - -6.2 tinc environment variables -============================== - -'NETNAME' - If no netname is specified on the command line with the '-n' - option, the value of this environment variable is used. - - -File: tinc.info, Node: tinc commands, Next: tinc examples, Prev: tinc environment variables, Up: Controlling tinc - -6.3 tinc commands -================= - -'init [NAME]' - Create initial configuration files and RSA and ECDSA keypairs with - default length. If no NAME for this node is given, it will be - asked for. - -'get VARIABLE' - Print the current value of configuration variable VARIABLE. If - more than one variable with the same name exists, the value of each - of them will be printed on a separate line. - -'set VARIABLE VALUE' - Set configuration variable VARIABLE to the given VALUE. All - previously existing configuration variables with the same name are - removed. To set a variable for a specific host, use the notation - HOST.VARIABLE. - -'add VARIABLE VALUE' - As above, but without removing any previously existing - configuration variables. - -'del VARIABLE [VALUE]' - Remove configuration variables with the same name and VALUE. If no - VALUE is given, all configuration variables with the same name will - be removed. - -'edit FILENAME' - Start an editor for the given configuration file. You do not need - to specify the full path to the file. - -'export' - Export the host configuration file of the local node to standard - output. - -'export-all' - Export all host configuration files to standard output. - -'import [--force]' - Import host configuration file(s) generated by the tinc export - command from standard input. Already existing host configuration - files are not overwritten unless the option -force is used. - -'exchange [--force]' - The same as export followed by import. - -'exchange-all [--force]' - The same as export-all followed by import. - -'invite NAME' - Prepares an invitation for a new node with the given NAME, and - prints a short invitation URL that can be used with the join - command. - -'join [URL]' - Join an existing VPN using an invitation URL created using the - invite command. If no URL is given, it will be read from standard - input. - -'start [tincd options]' - Start 'tincd', optionally with the given extra options. - -'stop' - Stop 'tincd'. - -'restart [tincd options]' - Restart 'tincd', optionally with the given extra options. - -'reload' - Partially rereads configuration files. Connections to hosts whose - host config files are removed are closed. New outgoing connections - specified in 'tinc.conf' will be made. - -'pid' - Shows the PID of the currently running 'tincd'. - -'generate-keys [BITS]' - Generate both RSA and ECDSA keypairs (see below) and exit. tinc - will ask where you want to store the files, but will default to the - configuration directory (you can use the -c or -n option). - -'generate-ecdsa-keys' - Generate public/private ECDSA keypair and exit. - -'generate-rsa-keys [BITS]' - Generate public/private RSA keypair and exit. If 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. - -'dump [reachable] nodes' - Dump a list of all known nodes in the VPN. If the reachable keyword - is used, only lists reachable nodes. - -'dump edges' - Dump a list of all known connections in the VPN. - -'dump subnets' - Dump a list of all known subnets in the VPN. - -'dump connections' - Dump a list of all meta connections with ourself. - -'dump graph | digraph' - Dump a graph of the VPN in dotty 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. - -'info NODE | SUBNET | ADDRESS' - Show information about a particular NODE, SUBNET or ADDRESS. If an - ADDRESS is given, any matching subnet will be shown. - -'purge' - Purges all information remembered about unreachable nodes. - -'debug LEVEL' - Sets debug level to LEVEL. - -'log [LEVEL]' - 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 tinc. - -'retry' - Forces tinc to try to connect to all uplinks immediately. Usually - tinc attempts to do this itself, but increases the time it waits - between the attempts each time it failed, and if tinc didn't - succeed to connect to an uplink the first time after it started, it - defaults to the maximum time of 15 minutes. - -'disconnect NODE' - Closes the meta connection with the given NODE. - -'top' - If tinc is compiled with libcurses support, this will display live - traffic statistics for all the known nodes, similar to the UNIX top - command. See below for more information. - -'pcap' - Dump VPN traffic going through the local tinc node in pcap-savefile - 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 - tcpdump. - - -File: tinc.info, Node: tinc examples, Next: tinc top, Prev: tinc commands, Up: Controlling tinc - -6.4 tinc examples -================= - -Examples of some commands: - - tinc -n vpn dump graph | circo -Txlib - tinc -n vpn pcap | tcpdump -r - - tinc -n vpn top - -Example of configuring tinc using the tinc command: - - 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 - - -File: tinc.info, Node: tinc top, Prev: tinc examples, Up: Controlling tinc - -6.5 tinc 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: - - - Change the interval between updates. After pressing the key, - enter the desired interval in seconds, followed by enter. - Fractional seconds are honored. Intervals lower than 0.1 seconds - are not allowed. - - - Toggle between displaying current traffic rates (in packets and - bytes per second) and cummulative traffic (total packets and bytes - since the tinc daemon started). - - - Sort the list of nodes by name. - - - Sort the list of nodes by incoming amount of bytes. - - - Sort the list of nodes by incoming amount of packets. - - - Sort the list of nodes by outgoing amount of bytes. - - - Sort the list of nodes by outgoing amount of packets. - - - Sort the list of nodes by sum of incoming and outgoing amount of - bytes. - - - Sort the list of nodes by sum of incoming and outgoing amount of - packets. - - - Show amount of traffic in bytes. - - - Show amount of traffic in kilobytes. - - - Show amount of traffic in megabytes. - - - Show amount of traffic in gigabytes. - - - Quit. - - -File: tinc.info, Node: Technical information, Next: Platform specific information, Prev: Controlling tinc, Up: Top - -7 Technical information +6 Technical information *********************** * Menu: @@ -2270,7 +1872,7 @@ File: tinc.info, Node: Technical information, Next: Platform specific informat  File: tinc.info, Node: The connection, Next: The meta-protocol, Up: Technical information -7.1 The connection +6.1 The connection ================== Tinc is a daemon that takes VPN data and transmit that to another host @@ -2284,7 +1886,7 @@ computer over the existing Internet infrastructure.  File: tinc.info, Node: The UDP tunnel, Next: The meta-connection, Up: The connection -7.1.1 The UDP tunnel +6.1.1 The UDP tunnel -------------------- The data itself is read from a character device file, the so-called @@ -2296,75 +1898,74 @@ are point-to-point devices which can only handle IPv4 and/or IPv6 packets, and 'tap' style, which are Ethernet devices and handle complete Ethernet frames. -So when tinc reads an Ethernet frame from the device, it determines its -type. When tinc is in it's default routing mode, it can handle IPv4 and -IPv6 packets. Depending on the Subnet lines, it will send the packets -off to their destination IP address. In the 'switch' and 'hub' mode, -tinc will use broadcasts and MAC address discovery to deduce the + So when tinc reads an Ethernet frame from the device, it determines +its type. When tinc is in its default routing mode, it can handle IPv4 +and IPv6 packets. Depending on the Subnet lines, it will send the +packets off to their destination IP address. In the 'switch' and 'hub' +mode, tinc will use broadcasts and MAC address discovery to deduce the destination of the packets. Since the latter modes only depend on the link layer information, any protocol that runs over Ethernet is supported (for instance IPX and Appletalk). However, only 'tap' style devices provide this information. -After the destination has been determined, the packet will be compressed -(optionally), a sequence number will be added to the packet, the packet -will then be encrypted and a message authentication code will be -appended. + After the destination has been determined, the packet will be +compressed (optionally), a sequence number will be added to the packet, +the packet will then be encrypted and a message authentication code will +be appended. -When that is done, time has come to actually transport the packet to the -destination computer. We do this by sending the packet over an UDP + When that is done, time has come to actually transport the packet to +the destination computer. We do this by sending the packet over an UDP connection to the destination host. This is called _encapsulating_, the VPN packet (though now encrypted) is encapsulated in another IP datagram. -When the destination receives this packet, the same thing happens, only -in reverse. So it checks the message authentication code, decrypts the -contents of the UDP datagram, checks the sequence number and writes the -decrypted information to its own virtual network device. + When the destination receives this packet, the same thing happens, +only in reverse. So it checks the message authentication code, decrypts +the contents of the UDP datagram, checks the sequence number and writes +the decrypted information to its own virtual network device. -If the virtual network device is a 'tun' device (a point-to-point + If the virtual network device is a 'tun' device (a point-to-point tunnel), there is no problem for the kernel to accept a packet. However, if it is a 'tap' device (this is the only available type on FreeBSD), the destination MAC address must match that of the virtual -network interface. If tinc is in it's default routing mode, ARP does -not work, so the correct destination MAC can not be known by the sending +network interface. If tinc is in its default routing mode, ARP does not +work, so the correct destination MAC can not be known by the sending host. Tinc solves this by letting the receiving end detect the MAC address of its own virtual network interface and overwriting the destination MAC address of the received packet. -In switch or hub modes ARP does work so the sender already knows the + In switch or hub modes ARP does work so the sender already knows the correct destination MAC address. In those modes every interface should have a unique MAC address, so make sure they are not the same. Because switch and hub modes rely on MAC addresses to function correctly, these modes cannot be used on the following operating systems which don't have -a 'tap' style virtual network device: OpenBSD, NetBSD, Darwin and -Solaris. +a 'tap' style virtual network device: NetBSD, Darwin and Solaris.  File: tinc.info, Node: The meta-connection, Prev: The UDP tunnel, Up: The connection -7.1.2 The meta-connection +6.1.2 The meta-connection ------------------------- Having only a UDP connection available is not enough. Though suitable for transmitting data, we want to be able to reliably send other information, such as routing and session key information to somebody. -TCP is a better alternative, because it already contains protection + TCP is a better alternative, because it already contains protection against information being lost, unlike UDP. -So we establish two connections. One for the encrypted VPN data, and + So we establish two connections. One for the encrypted VPN data, and one for other information, the meta-data. Hence, we call the second connection the meta-connection. We can now be sure that the meta-information doesn't get lost on the way to another computer. -Like with any communication, we must have a protocol, so that everybody -knows what everything stands for, and how she should react. Because we -have two connections, we also have two protocols. The protocol used for -the UDP data is the "data-protocol," the other one is the -"meta-protocol." + Like with any communication, we must have a protocol, so that +everybody knows what everything stands for, and how she should react. +Because we have two connections, we also have two protocols. The +protocol used for the UDP data is the "data-protocol," the other one is +the "meta-protocol." -The reason we don't use TCP for both protocols is that UDP is much + The reason we don't use TCP for both protocols is that UDP is much better for encapsulation, even while it is less reliable. The real problem is that when TCP would be used to encapsulate a TCP stream that's on the private network, for every packet sent there would be @@ -2375,24 +1976,24 @@ re-sending packets.  File: tinc.info, Node: The meta-protocol, Next: Security, Prev: The connection, Up: Technical information -7.2 The meta-protocol +6.2 The meta-protocol ===================== The meta protocol is used to tie all tinc daemons together, and exchange information about which tinc daemon serves which virtual subnet. -The meta protocol consists of requests that can be sent to the other + The meta protocol consists of requests that can be sent to the other side. Each request has a unique number and several parameters. All requests are represented in the standard ASCII character set. It is possible to use tools such as telnet or netcat to connect to a tinc daemon started with the -bypass-security option and to read and write requests by hand, provided that one understands the numeric codes sent. -The authentication scheme is described in *note Security::. After a -successful authentication, the server and the client will exchange all -the information about other tinc daemons and subnets they know of, so -that both sides (and all the other tinc daemons behind them) have their -information synchronised. + The authentication scheme is described in *note Authentication +protocol::. After a successful authentication, the server and the +client will exchange all the information about other tinc daemons and +subnets they know of, so that both sides (and all the other tinc daemons +behind them) have their information synchronised. message ------------------------------------------------------------------ @@ -2410,13 +2011,13 @@ information synchronised. +------------------> owner of this subnet ------------------------------------------------------------------ -The ADD_EDGE messages are to inform other tinc daemons that a connection -between two nodes exist. The address of the destination node is -available so that VPN packets can be sent directly to that node. + The ADD_EDGE messages are to inform other tinc daemons that a +connection between two nodes exist. The address of the destination node +is available so that VPN packets can be sent directly to that node. -The ADD_SUBNET messages inform other tinc daemons that certain subnets -belong to certain nodes. tinc will use it to determine to which node a -VPN packet has to be sent. + The ADD_SUBNET messages inform other tinc daemons that certain +subnets belong to certain nodes. tinc will use it to determine to which +node a VPN packet has to be sent. message ------------------------------------------------------------------ @@ -2430,10 +2031,10 @@ VPN packet has to be sent. +------------------> owner of this subnet ------------------------------------------------------------------ -In case a connection between two daemons is closed or broken, DEL_EDGE -messages are sent to inform the other daemons of that fact. Each daemon -will calculate a new route to the the daemons, or mark them unreachable -if there isn't any. + In case a connection between two daemons is closed or broken, +DEL_EDGE messages are sent to inform the other daemons of that fact. +Each daemon will calculate a new route to the the daemons, or mark them +unreachable if there isn't any. message ------------------------------------------------------------------ @@ -2453,20 +2054,20 @@ if there isn't any. +--> daemon that has changed it's packet key ------------------------------------------------------------------ -The keys used to encrypt VPN packets are not sent out directly. This is -because it would generate a lot of traffic on VPNs with many daemons, + The keys used to encrypt VPN packets are not sent out directly. This +is because it would generate a lot of traffic on VPNs with many daemons, and chances are that not every tinc daemon will ever send a packet to every other daemon. Instead, if a daemon needs a key it sends a request for it via the meta connection of the nearest hop in the direction of the destination. - daemon message + daemon message ------------------------------------------------------------------ - origin PING - dest. PONG + origin PING + dest. PONG ------------------------------------------------------------------ -There is also a mechanism to check if hosts are still alive. Since + There is also a mechanism to check if hosts are still alive. Since network failures or a crash can cause a daemon to be killed without properly shutting down the TCP connection, this is necessary to keep an up to date connection list. PINGs are sent at regular intervals, except @@ -2475,12 +2076,12 @@ data) is added with each PING and PONG message, to make sure that long sequences of PING/PONG messages without any other traffic won't result in known plaintext. -This basically covers what is sent over the meta connection by tinc. + This basically covers what is sent over the meta connection by tinc.  File: tinc.info, Node: Security, Prev: The meta-protocol, Up: Technical information -7.3 Security +6.3 Security ============ Tinc got its name from "TINC," short for _There Is No Cabal_; the @@ -2488,33 +2089,33 @@ alleged Cabal was/is an organisation that was said to keep an eye on the entire Internet. As this is exactly what you _don't_ want, we named the tinc project after TINC. -But in order to be "immune" to eavesdropping, you'll have to encrypt + But in order to be "immune" to eavesdropping, you'll have to encrypt your data. Because tinc is a _Secure_ VPN (SVPN) daemon, it does -exactly that: encrypt. However, encryption in itself does not prevent -an attacker from modifying the encrypted data. Therefore, tinc also -authenticates the data. Finally, tinc uses sequence numbers (which -themselves are also authenticated) to prevent an attacker from replaying -valid packets. - -Since version 1.1pre3, tinc has two protocols used to protect your data; -the legacy protocol, and the new Simple Peer-to-Peer Security (SPTPS) -protocol. The SPTPS protocol is designed to address some weaknesses in -the legacy protocol. The new authentication protocol is used when two -nodes connect to each other that both have the ExperimentalProtocol -option set to yes, otherwise the legacy protocol will be used. +exactly that: encrypt. Tinc by default uses blowfish encryption with +128 bit keys in CBC mode, 32 bit sequence numbers and 4 byte long +message authentication codes to make sure eavesdroppers cannot get and +cannot change any information at all from the packets they can +intercept. The encryption algorithm and message authentication +algorithm can be changed in the configuration. The length of the +message authentication codes is also adjustable. The length of the key +for the encryption algorithm is always the default length used by +LibreSSL/OpenSSL. * Menu: -* Legacy authentication protocol:: -* Simple Peer-to-Peer Security:: +* Authentication protocol:: * Encryption of network packets:: * Security issues::  -File: tinc.info, Node: Legacy authentication protocol, Next: Simple Peer-to-Peer Security, Up: Security +File: tinc.info, Node: Authentication protocol, Next: Encryption of network packets, Up: Security -7.3.1 Legacy authentication protocol ------------------------------------- +6.3.1 Authentication protocol +----------------------------- + +A new scheme for authentication in tinc has been devised, which offers +some improvements over the protocol used in 1.0pre2 and 1.0pre3. +Explanation is below. daemon message -------------------------------------------------------------------------- @@ -2522,46 +2123,28 @@ File: tinc.info, Node: Legacy authentication protocol, Next: Simple Peer-to-Pe server - client ID client 17.2 - | | +-> minor protocol version - | +----> major protocol version - +--------> name of tinc daemon + client ID client 12 + | +---> version + +-------> name of tinc daemon - server ID server 17.2 - | | +-> minor protocol version - | +----> major protocol version - +--------> name of tinc daemon + server ID server 12 + | +---> version + +-------> name of tinc daemon - client META_KEY 94 64 0 0 5f0823a93e35b69e...7086ec7866ce582b - | | | | \_________________________________/ - | | | | +-> RSAKEYLEN bits totally random string S1, - | | | | encrypted with server's public RSA key - | | | +-> compression level - | | +---> MAC length - | +------> digest algorithm NID - +---------> cipher algorithm NID + client META_KEY 5f0823a93e35b69e...7086ec7866ce582b + \_________________________________/ + +-> RSAKEYLEN bits totally random string S1, + encrypted with server's public RSA key - server META_KEY 94 64 0 0 6ab9c1640388f8f0...45d1a07f8a672630 - | | | | \_________________________________/ - | | | | +-> RSAKEYLEN bits totally random string S2, - | | | | encrypted with client's public RSA key - | | | +-> compression level - | | +---> MAC length - | +------> digest algorithm NID - +---------> cipher algorithm NID - -------------------------------------------------------------------------- + server META_KEY 6ab9c1640388f8f0...45d1a07f8a672630 + \_________________________________/ + +-> RSAKEYLEN bits totally random string S2, + encrypted with client's public RSA key -The protocol allows each side to specify encryption algorithms and -parameters, but in practice they are always fixed, since older versions -of tinc did not allow them to be different from the default values. The -cipher is always Blowfish in OFB mode, the digest is SHA1, but the MAC -length is zero and no compression is used. + From now on: + - the client will symmetrically encrypt outgoing traffic using S1 + - the server will symmetrically encrypt outgoing traffic using S2 -From now on: - * the client will symmetrically encrypt outgoing traffic using S1 - * the server will symmetrically encrypt outgoing traffic using S2 - - -------------------------------------------------------------------------- client CHALLENGE da02add1817c1920989ba6ae2a49cecbda0 \_________________________________/ +-> CHALLEN bits totally random string H1 @@ -2581,204 +2164,74 @@ From now on: client ACK 655 123 0 | | +-> options - | +----> estimated weight - +--------> listening port of client + | +----> estimated weight + +--------> listening port of client server ACK 655 321 0 | | +-> options - | +----> estimated weight - +--------> listening port of server + | +----> estimated weight + +--------> listening port of server -------------------------------------------------------------------------- -This legacy authentication protocol has several weaknesses, pointed out -by security export Peter Gutmann. First, data is encrypted with RSA -without padding. Padding schemes are designed to prevent attacks when -the size of the plaintext is not equal to the size of the RSA key. Tinc -always encrypts random nonces that have the same size as the RSA key, so -we do not believe this leads to a break of the security. There might be -timing or other side-channel attacks against RSA encryption and -decryption, tinc does not employ any protection against those. -Furthermore, both sides send identical messages to each other, there is -no distinction between server and client, which could make a MITM attack -easier. However, no exploit is known in which a third party who is not -already trusted by other nodes in the VPN could gain access. Finally, -the RSA keys are used to directly encrypt the session keys, which means -that if the RSA keys are compromised, it is possible to decrypt all -previous VPN traffic. In other words, the legacy protocol does not -provide perfect forward secrecy. + This new scheme has several improvements, both in efficiency and +security. + + First of all, the server sends exactly the same kind of messages over +the wire as the client. The previous versions of tinc first +authenticated the client, and then the server. This scheme even allows +both sides to send their messages simultaneously, there is no need to +wait for the other to send something first. This means that any +calculations that need to be done upon sending or receiving a message +can also be done in parallel. This is especially important when doing +RSA encryption/decryption. Given that these calculations are the main +part of the CPU time spent for the authentication, speed is improved by +a factor 2. + + Second, only one RSA encrypted message is sent instead of two. This +reduces the amount of information attackers can see (and thus use for a +cryptographic attack). It also improves speed by a factor two, making +the total speedup a factor 4. + + Third, and most important: The symmetric cipher keys are exchanged +first, the challenge is done afterwards. In the previous authentication +scheme, because a man-in-the-middle could pass the challenge/chal_reply +phase (by just copying the messages between the two real tinc daemons), +but no information was exchanged that was really needed to read the rest +of the messages, the challenge/chal_reply phase was of no real use. The +man-in-the-middle was only stopped by the fact that only after the ACK +messages were encrypted with the symmetric cipher. Potentially, it +could even send it's own symmetric key to the server (if it knew the +server's public key) and read some of the metadata the server would send +it (it was impossible for the mitm to read actual network packets +though). The new scheme however prevents this. + + This new scheme makes sure that first of all, symmetric keys are +exchanged. The rest of the messages are then encrypted with the +symmetric cipher. Then, each side can only read received messages if +they have their private key. The challenge is there to let the other +side know that the private key is really known, because a challenge +reply can only be sent back if the challenge is decrypted correctly, and +that can only be done with knowledge of the private key. + + Fourth: the first thing that is sent via the symmetric cipher +encrypted connection is a totally random string, so that there is no +known plaintext (for an attacker) in the beginning of the encrypted +stream.  -File: tinc.info, Node: Simple Peer-to-Peer Security, Next: Encryption of network packets, Prev: Legacy authentication protocol, Up: Security +File: tinc.info, Node: Encryption of network packets, Next: Security issues, Prev: Authentication protocol, Up: Security -7.3.2 Simple Peer-to-Peer Security ----------------------------------- - -The SPTPS protocol is designed to address the weaknesses in the legacy -protocol. SPTPS is based on TLS 1.2, but has been simplified: there is -no support for exchanging public keys, and there is no cipher suite -negotiation. Instead, SPTPS always uses a very strong cipher suite: -peers authenticate each other using 521 bits ECC keys, Diffie-Hellman -using ephemeral 521 bits ECC keys is used to provide perfect forward -secrecy (PFS), AES-256-CTR is used for encryption, and HMAC-SHA-256 for -message authentication. - -Similar to TLS, messages are split up in records. A complete logical -record contains the following information: - - * uint32_t seqno (network byte order) - * uint16_t length (network byte order) - * uint8_t type - * opaque data[length] - * opaque hmac[HMAC_SIZE] (HMAC over all preceding fields) - -Depending on whether SPTPS records are sent via TCP or UDP, either the -seqno or the length field is omitted on the wire (but they are still -included in the calculation of the HMAC); for TCP packets are guaranteed -to arrive in-order so we can infer the seqno, but packets can be split -or merged, so we still need the length field to determine the boundaries -between records; for UDP packets we know that there is exactly one -record per packet, and we know the length of a packet, but packets can -be dropped, duplicated and/or reordered, so we need to include the -seqno. - -The type field is used to distinguish between application records or -handshake records. Types 0 to 127 are application records, type 128 is -a handshake record, and types 129 to 255 are reserved. - -Before the initial handshake, no fields are encrypted, and the HMAC -field is not present. After the authentication handshake, the length -(if present), type and data fields are encrypted, and the HMAC field is -present. For UDP packets, the seqno field is not encrypted, as it is -used to determine the value of the counter used for encryption. - -The authentication consists of an exchange of Key EXchange, SIGnature -and ACKnowledge messages, transmitted using type 128 records. - -Overview: - - Initiator Responder - --------------------- - KEX -> - <- KEX - SIG -> - <- SIG - - ...encrypt and HMAC using session keys from now on... - - App -> - <- App - ... - ... - - ...key renegotiation starts here... - - KEX -> - <- KEX - SIG -> - <- SIG - ACK -> - <- ACK - - ...encrypt and HMAC using new session keys from now on... - - App -> - <- App - ... - ... - --------------------- - -Note that the responder does not need to wait before it receives the -first KEX message, it can immediately send its own once it has accepted -an incoming connection. - -Key EXchange message: - - * uint8_t kex_version (always 0 in this version of SPTPS) - * opaque nonce[32] (random number) - * opaque ecdh_key[ECDH_SIZE] - -SIGnature message: - - * opaque ecdsa_signature[ECDSA_SIZE] - -ACKnowledge message: - - * empty (only sent after key renegotiation) - -Remarks: - - * At the start, both peers generate a random nonce and an Elliptic - Curve public key and send it to the other in the KEX message. - * After receiving the other's KEX message, both KEX messages are - concatenated (see below), and the result is signed using ECDSA. The - result is sent to the other. - * After receiving the other's SIG message, the signature is verified. - If it is correct, the shared secret is calculated from the public - keys exchanged in the KEX message using the Elliptic Curve - Diffie-Helman algorithm. - * The shared secret key is expanded using a PRF. Both nonces and the - application specific label are also used as input for the PRF. - * An ACK message is sent only when doing key renegotiation, and is - sent using the old encryption keys. - * The expanded key is used to key the encryption and HMAC algorithms. - -The signature is calculated over this string: - - * uint8_t initiator (0 = local peer, 1 = remote peer is initiator) - * opaque remote_kex_message[1 + 32 + ECDH_SIZE] - * opaque local_kex_message[1 + 32 + ECDH_SIZE] - * opaque label[label_length] - -The PRF is calculated as follows: - - * A HMAC using SHA512 is used, the shared secret is used as the key. - * For each block of 64 bytes, a HMAC is calculated. For block n: - hmac[n] = HMAC_SHA512(hmac[n - 1] + seed) - * For the first block (n = 1), hmac[0] is given by HMAC_SHA512(zeroes - + seed), where zeroes is a block of 64 zero bytes. - -The seed is as follows: - - * const char[13] "key expansion" - * opaque responder_nonce[32] - * opaque initiator_nonce[32] - * opaque label[label_length] - -The expanded key is used as follows: - - * opaque responder_cipher_key[CIPHER_KEYSIZE] - * opaque responder_digest_key[DIGEST_KEYSIZE] - * opaque initiator_cipher_key[CIPHER_KEYSIZE] - * opaque initiator_digest_key[DIGEST_KEYSIZE] - -Where initiator_cipher_key is the key used by session initiator to -encrypt messages sent to the responder. - -When using 521 bits EC keys, the AES-256-CTR cipher and HMAC-SHA-256 -digest algorithm, the sizes are as follows: - - ECDH_SIZE: 67 (= ceil(521/8) + 1) - ECDSA_SIZE: 141 (= 2 * ceil(521/8) + 9) - CIPHER_KEYSIZE: 48 (= 256/8 + 128/8) - DIGEST_KEYSIZE: 32 (= 256/8) - -Note that the cipher key also includes the initial value for the -counter. - - -File: tinc.info, Node: Encryption of network packets, Next: Security issues, Prev: Simple Peer-to-Peer Security, Up: Security - -7.3.3 Encryption of network packets +6.3.2 Encryption of network packets ----------------------------------- A data packet can only be sent if the encryption key is known to both parties, and the connection is activated. If the encryption key is not known, a request is sent to the destination using the meta connection to -retrieve it. +retrieve it. The packet is stored in a queue while waiting for the key +to arrive. -The UDP packets can be either encrypted with the legacy protocol or with -SPTPS. In case of the legacy protocol, the UDP packet containing the -network packet from the VPN has the following layout: + The UDP packet containing the network packet from the VPN has the +following layout: ... | IP header | UDP header | seqno | VPN packet | MAC | UDP trailer \___________________/\_____/ @@ -2786,86 +2239,63 @@ network packet from the VPN has the following layout: V +---> digest algorithm Encrypted with symmetric cipher -So, the entire VPN packet is encrypted using a symmetric cipher, + So, the entire VPN packet is encrypted using a symmetric cipher, including a 32 bits sequence number that is added in front of the actual VPN packet, to act as a unique IV for each packet and to prevent replay attacks. A message authentication code is added to the UDP packet to -prevent alteration of packets. Tinc by default encrypts network packets -using Blowfish with 128 bit keys in CBC mode and uses 4 byte long -message authentication codes to make sure eavesdroppers cannot get and -cannot change any information at all from the packets they can -intercept. The encryption algorithm and message authentication -algorithm can be changed in the configuration. The length of the -message authentication codes is also adjustable. The length of the key -for the encryption algorithm is always the default length used by -OpenSSL. - -The SPTPS protocol is described in *note Simple Peer-to-Peer Security::. -For comparison, this is how SPTPS UDP packets look: - - ... | IP header | UDP header | seqno | type | VPN packet | MAC | UDP trailer - \__________________/\_____/ - | | - V +---> digest algorithm - Encrypted with symmetric cipher - -The difference is that the seqno is not encrypted, since the encryption -cipher is used in CTR mode, and therefore the seqno must be known before -the packet can be decrypted. Furthermore, the MAC is never truncated. -The SPTPS protocol always uses the AES-256-CTR cipher and HMAC-SHA-256 -digest, this cannot be changed. +prevent alteration of packets. By default the first 4 bytes of the +digest are used for this, but this can be changed using the MACLength +configuration variable.  File: tinc.info, Node: Security issues, Prev: Encryption of network packets, Up: Security -7.3.4 Security issues +6.3.3 Security issues --------------------- In August 2000, we discovered the existence of a security hole in all versions of tinc up to and including 1.0pre2. This had to do with the way we exchanged keys. Since then, we have been working on a new authentication scheme to make tinc as secure as possible. The current -version uses the OpenSSL library and uses strong authentication with RSA -keys. +version uses the LibreSSL or OpenSSL library and uses strong +authentication with RSA keys. -On the 29th of December 2001, Jerome Etienne posted a security analysis -of tinc 1.0pre4. Due to a lack of sequence numbers and a message -authentication code for each packet, an attacker could possibly disrupt -certain network services or launch a denial of service attack by + On the 29th of December 2001, Jerome Etienne posted a security +analysis of tinc 1.0pre4. Due to a lack of sequence numbers and a +message authentication code for each packet, an attacker could possibly +disrupt certain network services or launch a denial of service attack by replaying intercepted packets. The current version adds sequence numbers and message authentication codes to prevent such attacks. -On the 15th of September 2003, Peter Gutmann posted a security analysis -of tinc 1.0.1. He argues that the 32 bit sequence number used by tinc -is not a good IV, that tinc's default length of 4 bytes for the MAC is -too short, and he doesn't like tinc's use of RSA during authentication. -We do not know of a security hole in the legacy protocol of tinc, but it -is not as strong as TLS or IPsec. + On the 15th of September 2003, Peter Gutmann posted a security +analysis of tinc 1.0.1. He argues that the 32 bit sequence number used +by tinc is not a good IV, that tinc's default length of 4 bytes for the +MAC is too short, and he doesn't like tinc's use of RSA during +authentication. We do not know of a security hole in this version of +tinc, but tinc's security is not as strong as TLS or IPsec. We will +address these issues in tinc 2.0. -This version of tinc comes with an improved protocol, called Simple -Peer-to-Peer Security, which aims to be as strong as TLS with one of the -strongest cipher suites. - -Cryptography is a hard thing to get right. We cannot make any + Cryptography is a hard thing to get right. We cannot make any guarantees. Time, review and feedback are the only things that can prove the security of any cryptographic product. If you wish to review -tinc or give us feedback, you are stronly encouraged to do so. +tinc or give us feedback, you are strongly encouraged to do so.  File: tinc.info, Node: Platform specific information, Next: About us, Prev: Technical information, Up: Top -8 Platform specific information +7 Platform specific information ******************************* * Menu: * Interface configuration:: * Routes:: +* Automatically starting tinc::  File: tinc.info, Node: Interface configuration, Next: Routes, Up: Platform specific information -8.1 Interface configuration +7.1 Interface configuration =========================== When configuring an interface, one normally assigns it an address and a @@ -2877,45 +2307,40 @@ to that interface. Because all packets for the entire VPN should go to the virtual network interface used by tinc, the netmask should be such that it encompasses the entire VPN. -For IPv4 addresses: + For IPv4 addresses: -Linux 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK -Linux iproute2 'ip addr add' ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE -FreeBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK -OpenBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK -NetBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK -Solaris 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK -Darwin (MacOS/X) 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK -Windows 'netsh interface ip set address' INTERFACE 'static' ADDRESS NETMASK +Linux 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +Linux iproute2 'ip addr add' ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE +FreeBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +OpenBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +NetBSD 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +Solaris 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +Darwin (Mac OS X) 'ifconfig' INTERFACE ADDRESS 'netmask' NETMASK +Windows 'netsh interface ip set address' INTERFACE 'static' ADDRESS NETMASK -For IPv6 addresses: + For IPv6 addresses: -Linux 'ifconfig' INTERFACE 'add' ADDRESS'/'PREFIXLENGTH -FreeBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH -OpenBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH -NetBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH -Solaris 'ifconfig' INTERFACE 'inet6 plumb up' - 'ifconfig' INTERFACE 'inet6 addif' ADDRESS ADDRESS -Darwin (MacOS/X) 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH -Windows 'netsh interface ipv6 add address' INTERFACE 'static' ADDRESS/PREFIXLENGTH +Linux 'ifconfig' INTERFACE 'add' ADDRESS'/'PREFIXLENGTH +FreeBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH +OpenBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH +NetBSD 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH +Solaris 'ifconfig' INTERFACE 'inet6 plumb up' + 'ifconfig' INTERFACE 'inet6 addif' ADDRESS ADDRESS +Darwin (Mac OS X) 'ifconfig' INTERFACE 'inet6' ADDRESS 'prefixlen' PREFIXLENGTH +Windows 'netsh interface ipv6 add address' INTERFACE 'static' ADDRESS/PREFIXLENGTH -On some platforms, when running tinc in switch mode, the VPN interface -must be set to tap mode with an ifconfig command: + On Linux, it is possible to create a persistent tun/tap interface +which will continue to exist even if tinc quit, although this is +normally not required. It can be useful to set up a tun/tap interface +owned by a non-root user, so tinc can be started without needing any +root privileges at all. -OpenBSD 'ifconfig' INTERFACE 'link0' - -On Linux, it is possible to create a persistent tun/tap interface which -will continue to exist even if tinc quit, although this is normally not -required. It can be useful to set up a tun/tap interface owned by a -non-root user, so tinc can be started without needing any root -privileges at all. - -Linux 'ip tuntap add dev' INTERFACE 'mode' TUN|TAP 'user' USERNAME +Linux 'ip tuntap add dev' INTERFACE 'mode' TUN|TAP 'user' USERNAME  -File: tinc.info, Node: Routes, Prev: Interface configuration, Up: Platform specific information +File: tinc.info, Node: Routes, Next: Automatically starting tinc, Prev: Interface configuration, Up: Platform specific information -8.2 Routes +7.2 Routes ========== In some cases it might be necessary to add more routes to the virtual @@ -2925,33 +2350,99 @@ another way is to specify the (local) address that is assigned to that interface (LOCAL_ADDRESS). The former way is unambiguous and therefore preferable, but not all platforms support this. -Adding routes to IPv4 subnets: + Adding routes to IPv4 subnets: -Linux 'route add -net' NETWORK_ADDRESS 'netmask' NETMASK INTERFACE -Linux iproute2 'ip route add' NETWORK_ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE -FreeBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS -OpenBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS -NetBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS -Solaris 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS '-interface' -Darwin (MacOS/X) 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS -Windows 'netsh routing ip add persistentroute' NETWORK_ADDRESS NETMASK INTERFACE - LOCAL_ADDRESS +Linux 'route add -net' NETWORK_ADDRESS 'netmask' NETMASK INTERFACE +Linux iproute2 'ip route add' NETWORK_ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE +FreeBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS +OpenBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS +NetBSD 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS +Solaris 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS '-interface' +Darwin (Mac OS X) 'route add' NETWORK_ADDRESS'/'PREFIXLENGTH '-interface' INTERFACE +Windows 'netsh routing ip add persistentroute' NETWORK_ADDRESS NETMASK INTERFACE + LOCAL_ADDRESS -Adding routes to IPv6 subnets: + Adding routes to IPv6 subnets: -Linux 'route add -A inet6' NETWORK_ADDRESS'/'PREFIXLENGTH INTERFACE -Linux iproute2 'ip route add' NETWORK_ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE -FreeBSD 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS -OpenBSD 'route add -inet6' NETWORK_ADDRESS LOCAL_ADDRESS '-prefixlen' PREFIXLENGTH -NetBSD 'route add -inet6' NETWORK_ADDRESS LOCAL_ADDRESS '-prefixlen' PREFIXLENGTH -Solaris 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS '-interface' -Darwin (MacOS/X) ? -Windows 'netsh interface ipv6 add route' NETWORK ADDRESS/PREFIXLENGTH INTERFACE +Linux 'route add -A inet6' NETWORK_ADDRESS'/'PREFIXLENGTH INTERFACE +Linux iproute2 'ip route add' NETWORK_ADDRESS'/'PREFIXLENGTH 'dev' INTERFACE +FreeBSD 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS +OpenBSD 'route add -inet6' NETWORK_ADDRESS LOCAL_ADDRESS '-prefixlen' PREFIXLENGTH +NetBSD 'route add -inet6' NETWORK_ADDRESS LOCAL_ADDRESS '-prefixlen' PREFIXLENGTH +Solaris 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH LOCAL_ADDRESS '-interface' +Darwin (Mac OS X) 'route add -inet6' NETWORK_ADDRESS'/'PREFIXLENGTH '-interface' INTERFACE +Windows 'netsh interface ipv6 add route' NETWORK ADDRESS/PREFIXLENGTH INTERFACE + + +File: tinc.info, Node: Automatically starting tinc, Prev: Routes, Up: Platform specific information + +7.3 Automatically starting tinc +=============================== + +* Menu: + +* Linux:: +* Windows:: +* Other platforms:: + + +File: tinc.info, Node: Linux, Next: Windows, Up: Automatically starting tinc + +7.3.1 Linux +----------- + +There are many Linux distributions, and historically, many of them had +their own way of starting programs at boot time. Today, a number of +major Linux distributions have chosen to use systemd as their init +system. Tinc ships with systemd service files that allow you to start +and stop tinc using systemd. There are two service files: +'tinc.service' is used to globally enable or disable all tinc daemons +managed by systemd, and 'tinc@NETNAME.service' is used to enable or +disable specific tinc daemons. So if one has created a tinc network +with netname 'foo', then you have to run the following two commands to +ensure it is started at boot time: + + systemctl enable tinc + systemctl enable tinc@foo + + To start the tinc daemon immediately if it wasn't already running, +use the following command: + + systemctl start tinc@foo + + You can also use 'systemctl start tinc', this will start all tinc +daemons that are enabled. You can stop and disable tinc networks in the +same way. + + If your system is not using systemd, then you have to look up your +distribution's way of starting tinc at boot time. + + +File: tinc.info, Node: Windows, Next: Other platforms, Prev: Linux, Up: Automatically starting tinc + +7.3.2 Windows +------------- + +On Windows, if tinc is started without the '-D' or '--no-detach' option, +it will automatically register itself as a service that is started at +boot time. When tinc is stopped using the '-k' or '--kill', it will +also automatically unregister itself. Once tinc is registered as a +service, it is also possible to stop and start tinc using the Windows +Services Manager. + + +File: tinc.info, Node: Other platforms, Prev: Windows, Up: Automatically starting tinc + +7.3.3 Other platforms +--------------------- + +On platforms other than the ones mentioned in the earlier sections, you +have to look up your platform's way of starting programs at boot time.  File: tinc.info, Node: About us, Next: Concept Index, Prev: Platform specific information, Up: Top -9 About us +8 About us ********** * Menu: @@ -2962,29 +2453,29 @@ File: tinc.info, Node: About us, Next: Concept Index, Prev: Platform specific  File: tinc.info, Node: Contact information, Next: Authors, Up: About us -9.1 Contact information +8.1 Contact information ======================= -Tinc's website is at , this server is located +Tinc's website is at , this server is located in the Netherlands. -We have an IRC channel on the FreeNode and OFTC IRC networks. Connect -to irc.freenode.net (http://www.freenode.net/) or irc.oftc.net -(http://www.oftc.net/) and join channel #tinc. + We have an IRC channel on the FreeNode and OFTC IRC networks. +Connect to irc.freenode.net (https://freenode.net/) or irc.oftc.net +(https://www.oftc.net/) and join channel #tinc.  File: tinc.info, Node: Authors, Prev: Contact information, Up: About us -9.2 Authors +8.2 Authors =========== Ivo Timmermans (zarq) Guus Sliepen (guus) () -We have received a lot of valuable input from users. With their help, -tinc has become the flexible and robust tool that it is today. We have -composed a list of contributions, in the file called 'THANKS' in the -source distribution. + We have received a lot of valuable input from users. With their +help, tinc has become the flexible and robust tool that it is today. We +have composed a list of contributions, in the file called 'THANKS' in +the source distribution.  File: tinc.info, Node: Concept Index, Prev: About us, Up: Top @@ -2995,8 +2486,8 @@ Concept Index [index] * Menu: -* ACK: Legacy authentication protocol. - (line 6) +* ACK: Authentication protocol. + (line 10) * Address: Host configuration variables. (line 6) * AddressFamily: Main configuration variables. @@ -3004,25 +2495,25 @@ Concept Index * ADD_EDGE: The meta-protocol. (line 22) * ADD_SUBNET: The meta-protocol. (line 22) * ANS_KEY: The meta-protocol. (line 63) -* AutoConnect: Main configuration variables. - (line 12) +* authentication: Authentication protocol. + (line 6) * binary package: Building and installing tinc. (line 9) * BindToAddress: Main configuration variables. - (line 19) -* BindToInterface: Main configuration variables. - (line 30) -* Broadcast: Main configuration variables. - (line 40) -* Cabal: Security. (line 6) -* CHALLENGE: Legacy authentication protocol. - (line 6) -* CHAL_REPLY: Legacy authentication protocol. - (line 6) -* CIDR notation: Host configuration variables. - (line 94) -* Cipher: Host configuration variables. (line 12) +* BindToInterface: Main configuration variables. + (line 25) +* Broadcast: Main configuration variables. + (line 33) +* Cabal: Security. (line 6) +* CHALLENGE: Authentication protocol. + (line 10) +* CHAL_REPLY: Authentication protocol. + (line 10) +* CIDR notation: Host configuration variables. + (line 93) +* Cipher: Host configuration variables. + (line 14) * ClampMSS: Host configuration variables. (line 20) * client: How connections work. @@ -3032,140 +2523,134 @@ Concept Index (line 26) * connection: The connection. (line 6) * ConnectTo: Main configuration variables. - (line 60) + (line 53) * daemon: Running tinc. (line 11) * data-protocol: The meta-connection. (line 18) * debug level: Runtime options. (line 17) * debug levels: Debug levels. (line 6) * DecrementTTL: Main configuration variables. - (line 71) + (line 64) * DEL_EDGE: The meta-protocol. (line 46) * DEL_SUBNET: The meta-protocol. (line 46) * Device: Main configuration variables. - (line 80) -* DEVICE: Scripts. (line 53) + (line 73) +* DEVICE: Scripts. (line 64) * device files: Device files. (line 6) * DeviceType: Main configuration variables. - (line 87) + (line 79) * Digest: Host configuration variables. (line 31) * DirectOnly: Main configuration variables. - (line 152) + (line 149) * dummy: Main configuration variables. - (line 94) -* ECDSAPrivateKeyFile: Main configuration variables. - (line 159) + (line 86) * encapsulating: The UDP tunnel. (line 30) * encryption: Encryption of network packets. (line 6) -* environment variables: Scripts. (line 42) +* environment variables: Scripts. (line 53) * example: Example configuration. (line 6) * exec: Main configuration variables. - (line 328) -* ExperimentalProtocol: Main configuration variables. - (line 163) + (line 319) * Forwarding: Main configuration variables. - (line 170) + (line 156) * frame type: The UDP tunnel. (line 6) +* GraphDumpFile: Main configuration variables. + (line 176) * Hostnames: Main configuration variables. - (line 190) + (line 184) * http: Main configuration variables. - (line 325) + (line 316) * hub: Main configuration variables. - (line 246) -* ID: Legacy authentication protocol. - (line 6) + (line 254) +* ID: Authentication protocol. + (line 10) +* IffOneQueue: Main configuration variables. + (line 195) * IndirectData: Host configuration variables. - (line 38) + (line 36) * Interface: Main configuration variables. - (line 201) -* INTERFACE: Scripts. (line 56) + (line 198) +* INTERFACE: Scripts. (line 67) * IRC: Contact information. (line 9) +* key generation: Generating keypairs. (line 6) * KeyExpire: Main configuration variables. - (line 251) + (line 206) * KEY_CHANGED: The meta-protocol. (line 63) -* legacy authentication protocol: Legacy authentication protocol. - (line 6) -* libcurses: libcurses. (line 6) * libraries: Libraries. (line 6) -* libreadline: libreadline. (line 6) -* license: OpenSSL. (line 35) +* LibreSSL: LibreSSL/OpenSSL. (line 6) +* license: LibreSSL/OpenSSL. (line 38) * LocalDiscovery: Main configuration variables. - (line 209) -* LocalDiscoveryAddress: Main configuration variables. - (line 220) + (line 212) * lzo: lzo. (line 6) * MACExpire: Main configuration variables. - (line 257) + (line 223) * MACLength: Host configuration variables. - (line 43) -* MaxConnectionBurst: Main configuration variables. - (line 262) + (line 44) +* MaxTimeout: Main configuration variables. + (line 228) * meta-protocol: The meta-connection. (line 18) -* META_KEY: Legacy authentication protocol. - (line 6) +* META_KEY: Authentication protocol. + (line 10) * Mode: Main configuration variables. - (line 224) + (line 232) * multicast: Main configuration variables. - (line 106) + (line 98) * multiple networks: Multiple networks. (line 6) * Name: Main configuration variables. - (line 268) -* NAME: Scripts. (line 50) -* netmask: Network interfaces. (line 39) + (line 259) +* NAME: Scripts. (line 61) +* netmask: Network interfaces. (line 33) * netname: Multiple networks. (line 6) -* NETNAME: Scripts. (line 47) -* NETNAME <1>: tinc environment variables. - (line 6) +* NETNAME: Scripts. (line 58) * Network Administrators Guide: Configuration introduction. (line 15) -* NODE: Scripts. (line 60) -* OpenSSL: OpenSSL. (line 6) +* NODE: Scripts. (line 71) +* OpenSSL: LibreSSL/OpenSSL. (line 6) * options: Runtime options. (line 9) * PEM format: Host configuration variables. - (line 70) + (line 69) * PING: The meta-protocol. (line 88) * PingInterval: Main configuration variables. - (line 279) + (line 270) * PingTimeout: Main configuration variables. - (line 283) + (line 274) * platforms: Supported platforms. (line 6) * PMTU: Host configuration variables. - (line 50) + (line 49) * PMTUDiscovery: Host configuration variables. - (line 53) + (line 52) * PONG: The meta-protocol. (line 88) * Port: Host configuration variables. - (line 58) + (line 57) * port numbers: Other files. (line 17) * PriorityInheritance: Main configuration variables. - (line 289) + (line 280) * private: Virtual Private Networks. (line 10) * PrivateKey: Main configuration variables. - (line 294) + (line 285) * PrivateKeyFile: Main configuration variables. - (line 300) + (line 291) * ProcessPriority: Main configuration variables. - (line 305) + (line 296) * Proxy: Main configuration variables. - (line 310) + (line 301) * PublicKey: Host configuration variables. - (line 62) + (line 61) * PublicKeyFile: Host configuration variables. - (line 65) + (line 64) * raw_socket: Main configuration variables. - (line 99) + (line 91) * release: Supported platforms. (line 14) -* REMOTEADDRESS: Scripts. (line 65) -* REMOTEPORT: Scripts. (line 68) +* REMOTEADDRESS: Scripts. (line 76) +* REMOTEPORT: Scripts. (line 79) * ReplayWindow: Main configuration variables. - (line 333) + (line 324) * requirements: Libraries. (line 6) * REQ_KEY: The meta-protocol. (line 63) * router: Main configuration variables. - (line 227) + (line 235) * runtime options: Runtime options. (line 9) * scalability: tinc. (line 19) * scripts: Scripts. (line 6) @@ -3173,48 +2658,51 @@ Concept Index (line 18) * signals: Signals. (line 6) * socks4: Main configuration variables. - (line 314) + (line 305) * socks5: Main configuration variables. - (line 319) -* SPTPS: Simple Peer-to-Peer Security. - (line 6) + (line 310) * StrictSubnets: Main configuration variables. - (line 344) + (line 335) * Subnet: Host configuration variables. - (line 77) -* SUBNET: Scripts. (line 72) + (line 76) +* SUBNET: Scripts. (line 83) +* Subnet weight: Host configuration variables. + (line 98) * SVPN: Security. (line 11) * switch: Main configuration variables. - (line 235) + (line 243) +* systemd: Linux. (line 6) * TCP: The meta-connection. (line 10) * TCPonly: Host configuration variables. - (line 106) + (line 105) * tinc: Introduction. (line 6) * TINC: Security. (line 6) -* tinc-down: Scripts. (line 18) -* tinc-up: Scripts. (line 10) +* tinc-down: Scripts. (line 29) +* tinc-up: Scripts. (line 19) * tinc-up <1>: Network interfaces. (line 19) * tincd: tinc. (line 14) * traditional VPNs: tinc. (line 19) * tunifhead: Main configuration variables. - (line 141) + (line 133) * TunnelServer: Main configuration variables. - (line 349) + (line 342) * tunnohead: Main configuration variables. - (line 135) + (line 127) * UDP: The UDP tunnel. (line 30) * UDP <1>: Encryption of network packets. - (line 11) + (line 12) * UDPRcvBuf: Main configuration variables. - (line 356) + (line 349) * UDPSndBuf: Main configuration variables. - (line 361) + (line 354) * UML: Main configuration variables. - (line 117) + (line 109) * Universal tun/tap: Configuration of Linux kernels. (line 6) +* utun: Main configuration variables. + (line 140) * VDE: Main configuration variables. - (line 122) + (line 114) * virtual: Virtual Private Networks. (line 18) * virtual network device: The UDP tunnel. (line 6) @@ -3222,79 +2710,81 @@ Concept Index (line 6) * vpnd: tinc. (line 6) * website: Contact information. (line 6) +* WEIGHT: Scripts. (line 86) * zlib: zlib. (line 6)  Tag Table: -Node: Top807 -Node: Introduction1127 -Node: Virtual Private Networks1931 -Node: tinc3643 -Node: Supported platforms5155 -Node: Preparations5851 -Node: Configuring the kernel6107 -Node: Configuration of Linux kernels6516 -Node: Configuration of FreeBSD kernels7365 -Node: Configuration of OpenBSD kernels7830 -Node: Configuration of NetBSD kernels8438 -Node: Configuration of Solaris kernels8840 -Node: Configuration of Darwin (MacOS/X) kernels9501 -Node: Configuration of Windows10190 -Node: Libraries10703 -Node: OpenSSL11121 -Node: zlib13393 -Node: lzo14411 -Node: libcurses15401 -Node: libreadline16311 -Node: Installation17248 -Node: Building and installing tinc18257 -Node: Darwin (MacOS/X) build environment18913 -Node: Cygwin (Windows) build environment19477 -Node: MinGW (Windows) build environment20061 -Node: System files20579 -Node: Device files20844 -Node: Other files21257 -Node: Configuration21870 -Node: Configuration introduction22157 -Node: Multiple networks23678 -Node: How connections work25046 -Node: Configuration files27607 -Node: Main configuration variables29135 -Node: Host configuration variables45893 -Node: Scripts51364 -Node: How to configure54033 -Node: Network interfaces58509 -Node: Example configuration60888 -Node: Running tinc65981 -Node: Runtime options66568 -Node: Signals69428 -Node: Debug levels70277 -Node: Solving problems71213 -Node: Error messages72639 -Node: Sending bug reports76956 -Node: Controlling tinc77903 -Node: tinc runtime options78280 -Node: tinc environment variables78967 -Node: tinc commands79296 -Node: tinc examples84406 -Node: tinc top84969 -Node: Technical information86554 -Node: The connection86789 -Node: The UDP tunnel87101 -Node: The meta-connection90146 -Node: The meta-protocol91604 -Node: Security96587 -Node: Legacy authentication protocol97924 -Node: Simple Peer-to-Peer Security102541 -Node: Encryption of network packets108201 -Node: Security issues110830 -Node: Platform specific information112565 -Node: Interface configuration112793 -Node: Routes115234 -Node: About us117145 -Node: Contact information117320 -Node: Authors117722 -Node: Concept Index118124 +Node: Top806 +Node: Introduction1105 +Node: Virtual Private Networks1915 +Node: tinc3639 +Node: Supported platforms5167 +Node: Preparations5868 +Node: Configuring the kernel6124 +Node: Configuration of Linux kernels6534 +Node: Configuration of FreeBSD kernels7389 +Node: Configuration of OpenBSD kernels7854 +Node: Configuration of NetBSD kernels8211 +Node: Configuration of Solaris kernels8616 +Node: Configuration of Darwin (Mac OS X) kernels9279 +Node: Configuration of Windows10098 +Node: Libraries10638 +Node: LibreSSL/OpenSSL11047 +Node: zlib13589 +Node: lzo14618 +Node: Installation15601 +Node: Building and installing tinc16511 +Node: Darwin (Mac OS X) build environment17171 +Node: Cygwin (Windows) build environment17736 +Node: MinGW (Windows) build environment18325 +Node: System files18919 +Node: Device files19184 +Node: Other files19600 +Node: Configuration20213 +Node: Configuration introduction20524 +Node: Multiple networks21792 +Node: How connections work23218 +Node: Configuration files24440 +Node: Main configuration variables25934 +Node: Host configuration variables42182 +Node: Scripts47714 +Node: How to configure50980 +Node: Generating keypairs52238 +Node: Network interfaces52737 +Node: Example configuration54585 +Node: Running tinc59910 +Node: Runtime options60500 +Node: Signals64125 +Node: Debug levels65316 +Node: Solving problems66252 +Node: Error messages67804 +Node: Sending bug reports71813 +Node: Technical information72760 +Node: The connection72991 +Node: The UDP tunnel73303 +Node: The meta-connection76355 +Node: The meta-protocol77824 +Node: Security82841 +Node: Authentication protocol83983 +Node: Encryption of network packets89028 +Node: Security issues90404 +Node: Platform specific information92044 +Node: Interface configuration92304 +Node: Routes94600 +Node: Automatically starting tinc96650 +Node: Linux96873 +Node: Windows98094 +Node: Other platforms98599 +Node: About us98881 +Node: Contact information99056 +Node: Authors99459 +Node: Concept Index99864  End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/doc/tinc.texi b/doc/tinc.texi index a295293..0420e6f 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -15,7 +15,7 @@ This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon. -Copyright @copyright{} 1998-2013 Ivo Timmermans, +Copyright @copyright{} 1998-2019 Ivo Timmermans, Guus Sliepen and Wessel Dankers . @@ -30,10 +30,6 @@ permission notice identical to this one. @end ifinfo -@afourpaper -@paragraphindent none -@finalout - @titlepage @title tinc Manual @subtitle Setting up a Virtual Private Network with tinc @@ -43,7 +39,7 @@ permission notice identical to this one. @vskip 0pt plus 1filll This is the info manual for @value{PACKAGE} version @value{VERSION}, a Virtual Private Network daemon. -Copyright @copyright{} 1998-2013 Ivo Timmermans, +Copyright @copyright{} 1998-2019 Ivo Timmermans, Guus Sliepen and Wessel Dankers . @@ -69,7 +65,6 @@ permission notice identical to this one. * Installation:: * Configuration:: * Running tinc:: -* Controlling tinc:: * Technical information:: * Platform specific information:: * About us:: @@ -160,7 +155,7 @@ professional package. @cindex traditional VPNs @cindex scalability -Tinc also allows more than two sites to connect to eachother and form a single VPN. +Tinc also allows more than two sites to connect to each other and form a single VPN. Traditionally VPNs are created by making tunnels, which only have two endpoints. Larger VPNs with more sites are created by adding more tunnels. Tinc takes another approach: only endpoints are specified, @@ -181,7 +176,7 @@ available too. @section Supported platforms @cindex platforms -Tinc has been verified to work under Linux, FreeBSD, OpenBSD, NetBSD, MacOS/X (Darwin), Solaris, and Windows (both natively and in a Cygwin environment), +Tinc has been verified to work under Linux, FreeBSD, OpenBSD, NetBSD, Mac OS X (Darwin), Solaris, and Windows (both natively and in a Cygwin environment), with various hardware architectures. These are some of the platforms that are supported by the universal tun/tap device driver or other virtual network device drivers. Without such a driver, tinc will most @@ -191,7 +186,7 @@ packets. @cindex release For an up to date list of supported platforms, please check the list on our website: -@uref{http://www.tinc-vpn.org/platforms/}. +@uref{https://www.tinc-vpn.org/platforms/}. @c @c @@ -229,7 +224,7 @@ support tinc. * Configuration of OpenBSD kernels:: * Configuration of NetBSD kernels:: * Configuration of Solaris kernels:: -* Configuration of Darwin (MacOS/X) kernels:: +* Configuration of Darwin (Mac OS X) kernels:: * Configuration of Windows:: @end menu @@ -273,12 +268,7 @@ The tap driver can be loaded with @code{kldload if_tap}, or by adding @code{if_t @node Configuration of OpenBSD kernels @subsection Configuration of OpenBSD kernels -For OpenBSD version 2.9 and higher, -the tun driver is included in the default kernel configuration. -There is also a kernel patch from @uref{http://diehard.n-r-g.com/stuff/openbsd/} -which adds a tap device to OpenBSD which should work with tinc, -but with recent versions of OpenBSD, -a tun device can act as a tap device by setting the link0 option with ifconfig. +Recent versions of OpenBSD come with both tun and tap devices enabled in the default kernel configuration. @c ================================================================== @@ -298,24 +288,23 @@ Tunneling IPv6 may not work on NetBSD's tun device. For Solaris 8 (SunOS 5.8) and higher, the tun driver may or may not be included in the default kernel configuration. If it isn't, the source can be downloaded from @uref{http://vtun.sourceforge.net/tun/}. -For x86 and sparc64 architectures, precompiled versions can be found at @uref{http://www.monkey.org/~dugsong/fragroute/}. +For x86 and sparc64 architectures, precompiled versions can be found at @uref{https://www.monkey.org/~dugsong/fragroute/}. If the @file{net/if_tun.h} header file is missing, install it from the source package. @c ================================================================== -@node Configuration of Darwin (MacOS/X) kernels -@subsection Configuration of Darwin (MacOS/X) kernels +@node Configuration of Darwin (Mac OS X) kernels +@subsection Configuration of Darwin (Mac OS X) kernels Tinc on Darwin relies on a tunnel driver for its data acquisition from the kernel. -Tinc supports either the driver from @uref{http://tuntaposx.sourceforge.net/}, -which supports both tun and tap style devices, -and also the driver from from @uref{http://chrisp.de/en/projects/tunnel.html}. -The former driver is recommended. -The tunnel driver must be loaded before starting tinc with the following command: +OS X version 10.6.8 and later have a built-in tun driver called "utun". +Tinc also supports the driver from @uref{http://tuntaposx.sourceforge.net/}, +which supports both tun and tap style devices. -@example -kmodload tunnel -@end example +By default, tinc expects the tuntaposx driver to be installed. +To use the utun driver, set add @code{Device = utunX} to @file{tinc.conf}, +where X is the desired number for the utun interface. +You can also omit the number, in which case the first free number will be chosen. @c ================================================================== @@ -323,7 +312,7 @@ kmodload tunnel @subsection Configuration of Windows You will need to install the latest TAP-Win32 driver from OpenVPN. -You can download it from @uref{http://openvpn.sourceforge.net}. +You can download it from @uref{https://openvpn.net/index.php/open-source/downloads.html}. Using the Network Connections control panel, configure the TAP-Win32 network interface in the same way as you would do from the tinc-up script, as explained in the rest of the documentation. @@ -335,28 +324,27 @@ as explained in the rest of the documentation. @cindex requirements @cindex libraries -Before you can configure or build tinc, you need to have the OpenSSL, +Before you can configure or build tinc, you need to have the LibreSSL or OpenSSL, zlib and lzo libraries installed on your system. If you try to configure tinc without having them installed, configure will give you an error message, and stop. @menu -* OpenSSL:: +* LibreSSL/OpenSSL:: * zlib:: * lzo:: -* libcurses:: -* libreadline:: @end menu @c ================================================================== -@node OpenSSL -@subsection OpenSSL +@node LibreSSL/OpenSSL +@subsection LibreSSL/OpenSSL +@cindex LibreSSL @cindex OpenSSL For all cryptography-related functions, tinc uses the functions provided -by the OpenSSL library. +by the LibreSSL or the OpenSSL library. -If this library is not installed, you wil get an error when configuring +If this library is not installed, you will get an error when configuring tinc for build. Support for running tinc with other cryptographic libraries installed @emph{may} be added in the future. @@ -364,21 +352,23 @@ You can use your operating system's package manager to install this if available. Make sure you install the development AND runtime versions of this package. -If you have to install OpenSSL manually, you can get the source code -from @url{http://www.openssl.org/}. Instructions on how to configure, -build and install this package are included within the package. Please -make sure you build development and runtime libraries (which is the +If your operating system comes neither with LibreSSL or OpenSSL, you have to +install one manually. It is recommended that you get the latest version of +LibreSSL from @url{http://www.libressl.org/}. Instructions on how to +configure, build and install this package are included within the package. +Please make sure you build development and runtime libraries (which is the default). -If you installed the OpenSSL libraries from source, it may be necessary +If you installed the LibreSSL or OpenSSL libraries from source, it may be necessary to let configure know where they are, by passing configure one of the ---with-openssl-* parameters. +--with-openssl-* parameters. Note that you even have to use --with-openssl-* if you +are using LibreSSL. @example ---with-openssl=DIR OpenSSL library and headers prefix ---with-openssl-include=DIR OpenSSL headers directory +--with-openssl=DIR LibreSSL/OpenSSL library and headers prefix +--with-openssl-include=DIR LibreSSL/OpenSSL headers directory (Default is OPENSSL_DIR/include) ---with-openssl-lib=DIR OpenSSL library directory +--with-openssl-lib=DIR LibreSSL/OpenSSL library directory (Default is OPENSSL_DIR/lib) @end example @@ -389,7 +379,7 @@ to let configure know where they are, by passing configure one of the The complete source code of tinc is covered by the GNU GPL version 2. Since the license under which OpenSSL is distributed is not directly compatible with the terms of the GNU GPL -@uref{http://www.openssl.org/support/faq.html#LEGAL2}, we +@uref{https://www.openssl.org/support/faq.html#LEGAL2}, we include an exemption to the GPL (see also the file COPYING.README) to allow everyone to create a statically or dynamically linked executable: @@ -405,8 +395,8 @@ we also present the following exemption: @quotation Hereby I grant a special exception to the tinc VPN project -(http://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library -(http://www.openssl.org). +(https://www.tinc-vpn.org/) to link the LZO library with the OpenSSL library +(https://www.openssl.org). Markus F.X.J. Oberhumer @end quotation @@ -420,7 +410,7 @@ Markus F.X.J. Oberhumer For the optional compression of UDP packets, tinc uses the functions provided by the zlib library. -If this library is not installed, you wil get an error when running the +If this library is not installed, you will get an error when running the configure script. You can either install the zlib library, or disable support for zlib compression by using the "--disable-zlib" option when running the configure script. Note that if you disable support for zlib, the resulting @@ -431,7 +421,7 @@ available. Make sure you install the development AND runtime versions of this package. If you have to install zlib manually, you can get the source code -from @url{http://www.gzip.org/zlib/}. Instructions on how to configure, +from @url{https://zlib.net/}. Instructions on how to configure, build and install this package are included within the package. Please make sure you build development and runtime libraries (which is the default). @@ -444,7 +434,7 @@ default). @cindex lzo Another form of compression is offered using the LZO library. -If this library is not installed, you wil get an error when running the +If this library is not installed, you will get an error when running the configure script. You can either install the LZO library, or disable support for LZO compression by using the "--disable-lzo" option when running the configure script. Note that if you disable support for LZO, the resulting @@ -455,57 +445,12 @@ available. Make sure you install the development AND runtime versions of this package. If you have to install lzo manually, you can get the source code -from @url{http://www.oberhumer.com/opensource/lzo/}. Instructions on how to configure, +from @url{https://www.oberhumer.com/opensource/lzo/}. Instructions on how to configure, build and install this package are included within the package. Please make sure you build development and runtime libraries (which is the default). -@c ================================================================== -@node libcurses -@subsection libcurses - -@cindex libcurses -For the "tinc top" command, tinc requires a curses library. - -If this library is not installed, you wil get an error when running the -configure script. You can either install a suitable curses library, or disable -all functionality that depends on a curses library by using the -"--disable-curses" option when running the configure script. - -There are several curses libraries. It is recommended that you install -"ncurses" (@url{http://invisible-island.net/ncurses/}), -however other curses libraries should also work. -In particular, "PDCurses" (@url{http://pdcurses.sourceforge.net/}) -is recommended if you want to compile tinc for Windows. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - - -@c ================================================================== -@node libreadline -@subsection libreadline - -@cindex libreadline -For the "tinc" command's shell functionality, tinc uses the readline library. - -If this library is not installed, you wil get an error when running the -configure script. You can either install a suitable readline library, or -disable all functionality that depends on a readline library by using the -"--disable-readline" option when running the configure script. - -You can use your operating system's package manager to install this if -available. Make sure you install the development AND runtime versions -of this package. - -If you have to install libreadline manually, you can get the source code from -@url{http://www.gnu.org/software/readline/}. Instructions on how to configure, -build and install this package are included within the package. Please make -sure you build development and runtime libraries (which is the default). - - @c @c @c @@ -526,9 +471,7 @@ system startup scripts and sample configurations. If you cannot use one of the precompiled packages, or you want to compile tinc for yourself, you can use the source. The source is distributed under the GNU General Public License (GPL). Download the source from the -@uref{http://www.tinc-vpn.org/download/, download page}, which has -the checksums of these files listed; you may wish to check these with -md5sum before continuing. +@uref{https://www.tinc-vpn.org/download/, download page}. Tinc comes in a convenient autoconf/automake package, which you can just treat the same as any other package. Which is just untar it, type @@ -555,29 +498,28 @@ you can use the package management tools of that distribution to install tinc. The documentation that comes along with your distribution will tell you how to do that. @menu -* Darwin (MacOS/X) build environment:: +* Darwin (Mac OS X) build environment:: * Cygwin (Windows) build environment:: * MinGW (Windows) build environment:: @end menu @c ================================================================== -@node Darwin (MacOS/X) build environment -@subsection Darwin (MacOS/X) build environment +@node Darwin (Mac OS X) build environment +@subsection Darwin (Mac OS X) build environment -In order to build tinc on Darwin, you need to install the MacOS/X Developer Tools -from @uref{http://developer.apple.com/tools/macosxtools.html} and -a recent version of Fink from @uref{http://www.finkproject.org/}. +In order to build tinc on Darwin, you need to install Xcode from @uref{https://developer.apple.com/xcode/}. +It might also help to install a recent version of Fink from @uref{http://www.finkproject.org/}. -After installation use fink to download and install the following packages: -autoconf25, automake, dlcompat, m4, openssl, zlib and lzo. +You need to download and install LibreSSL (or OpenSSL) and LZO, +either directly from their websites (see @ref{Libraries}) or using Fink. @c ================================================================== @node Cygwin (Windows) build environment @subsection Cygwin (Windows) build environment If Cygwin hasn't already been installed, install it directly from -@uref{http://www.cygwin.com/}. +@uref{https://www.cygwin.com/}. When tinc is compiled in a Cygwin environment, it can only be run in this environment, but all programs, including those started outside the Cygwin environment, will be able to use the VPN. @@ -588,6 +530,7 @@ It will also support all features. @subsection MinGW (Windows) build environment You will need to install the MinGW environment from @uref{http://www.mingw.org}. +You also need to download and install LibreSSL (or OpenSSL) and LZO. When tinc is compiled using MinGW it runs natively under Windows, it is not necessary to keep MinGW installed. @@ -672,6 +615,7 @@ tinc 655/udp TINC * Multiple networks:: * How connections work:: * Configuration files:: +* Generating keypairs:: * Network interfaces:: * Example configuration:: @end menu @@ -698,15 +642,9 @@ A good resource on networking is the If you have everything clearly pictured in your mind, proceed in the following order: -First, create the initial configuration files and public/private keypairs using the following command: -@example -tinc -n @var{NETNAME} init @var{NAME} -@end example -Second, use @samp{tinc -n @var{NETNAME} add ...} to further configure tinc. -Finally, export your host configuration file using @samp{tinc -n @var{NETNAME} export} and send it to those -people or computers you want tinc to connect to. -They should send you their host configuration file back, which you can import using @samp{tinc -n @var{NETNAME} import}. - +First, generate the configuration files (@file{tinc.conf}, your host configuration file, @file{tinc-up} and perhaps @file{tinc-down}). +Then generate the keypairs. +Finally, distribute the host configuration files. These steps are described in the subsections below. @@ -716,29 +654,30 @@ These steps are described in the subsections below. @cindex multiple networks @cindex netname - In order to allow you to run more than one tinc daemon on one computer, for instance if your computer is part of more than one VPN, you can assign a @var{netname} to your VPN. It is not required if you only run one tinc daemon, -it doesn't even have to be the same on all the nodes of your VPN, +it doesn't even have to be the same on all the sites of your VPN, but it is recommended that you choose one anyway. -We will asume you use a netname throughout this document. -This means that you call tinc with the -n argument, -which will specify the netname. +We will assume you use a netname throughout this document. +This means that you call tincd with the -n argument, +which will assign a netname to this daemon. -The effect of this option is that tinc will set its configuration -root to @file{@value{sysconfdir}/tinc/@var{netname}/}, where @var{netname} is your argument to the -n option. -You will also notice that log messages it appears in syslog as coming from @file{tinc.@var{netname}}, -and on Linux, unless specified otherwise, the name of the virtual network interface will be the same as the network name. +The effect of this is that the daemon will set its configuration +root to @file{@value{sysconfdir}/tinc/@var{netname}/}, where @var{netname} is your argument to the -n +option. You'll notice that it appears in syslog as @file{tinc.@var{netname}}. However, it is not strictly necessary that you call tinc with the -n -option. If you don not use it, the network name will just be empty, and -tinc will look for files in @file{@value{sysconfdir}/tinc/} instead of -@file{@value{sysconfdir}/tinc/@var{netname}/}; -the configuration file will then be @file{@value{sysconfdir}/tinc/tinc.conf}, -and the host configuration files are expected to be in @file{@value{sysconfdir}/tinc/hosts/}. +option. In this case, the network name would just be empty, and it will +be used as such. tinc now looks for files in @file{@value{sysconfdir}/tinc/}, instead of +@file{@value{sysconfdir}/tinc/@var{netname}/}; the configuration file should be @file{@value{sysconfdir}/tinc/tinc.conf}, +and the host configuration files are now expected to be in @file{@value{sysconfdir}/tinc/hosts/}. + +But it is highly recommended that you use this feature of tinc, because +it will be so much clearer whom your daemon talks to. Hence, we will +assume that you use it. @c ================================================================== @@ -750,7 +689,7 @@ reads in the configuration file tinc.conf. If it sees one or more `ConnectTo' values pointing to other tinc daemons in that file, it will try to connect to those other daemons. Whether this succeeds or not and whether `ConnectTo' is specified or not, -tinc will listen for incoming connection from other deamons. +tinc will listen for incoming connection from other daemons. If you did specify a `ConnectTo' value and the other side is not responding, tinc will keep retrying. This means that once started, tinc will stay running until you tell it to stop, @@ -765,25 +704,6 @@ If you wish, you can view a tinc daemon without a `ConnectTo' value as a server, and one which does specify such a value as a client. It does not matter if two tinc daemons have a `ConnectTo' value pointing to each other however. -Connections specified using `ConnectTo' are so-called meta-connections. -Tinc daemons exchange information about all other daemon they know about via these meta-connections. -After learning about all the daemons in the VPN, -tinc will create other connections as necessary in order to communicate with them. -For example, if there are three daemons named A, B and C, and A has @samp{ConnectTo = B} in its tinc.conf file, -and C has @samp{ConnectTo = B} in its tinc.conf file, then A will learn about C from B, -and will be able to exchange VPN packets with C without the need to have @samp{ConnectTo = C} in its tinc.conf file. - -It could be that some daemons are located behind a Network Address Translation (NAT) device, or behind a firewall. -In the above scenario with three daemons, if A and C are behind a NAT, -B will automatically help A and C punch holes through their NAT, -in a way similar to the STUN protocol, so that A and C can still communicate with each other directly. -It is not always possible to do this however, and firewalls might also prevent direct communication. -In that case, VPN packets between A and C will be forwarded by B. - -In effect, all nodes in the VPN will be able to talk to each other, as long as -their is a path of meta-connections between them, and whenever possible, two -nodes will communicate with each other directly. - @c ================================================================== @node Configuration files @@ -793,6 +713,9 @@ The actual configuration of the daemon is done in the file @file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf} and at least one other file in the directory @file{@value{sysconfdir}/tinc/@var{netname}/hosts/}. +An optional directory @file{@value{sysconfdir}/tinc/@var{netname}/conf.d} can be added from which +any .conf file will be read. + These file consists of comments (lines started with a #) or assignments in the form of @@ -812,10 +735,7 @@ listed in this document can also be put in put host specific configuration options in the host configuration file, as this makes it easy to exchange with other nodes. -You can edit the config file manually, but it is recommended that you use -the tinc command to change configuration variables for you. - -In the following two subsections all valid variables are listed in alphabetical order. +In this section all valid variables are listed in alphabetical order. The default value is given between parentheses, other comments are between square brackets. @@ -838,16 +758,8 @@ This option affects the address family of listening and outgoing sockets. If any is selected, then depending on the operating system both IPv4 and IPv6 or just IPv6 listening sockets will be created. -@cindex AutoConnect -@item AutoConnect = (0) [experimental] -If set to a non-zero value, -tinc will try to only have 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. - @cindex BindToAddress -@item BindToAddress = <@var{address}> [<@var{port}>] +@item BindToAddress = <@var{address}> [<@var{port}>] [experimental] If your computer has more than one IPv4 or IPv6 address, tinc will by default listen on all of them for incoming connections. Multiple BindToAddress variables may be specified, @@ -857,6 +769,8 @@ If no @var{port} is specified, the socket will be bound to the port specified by or to port 655 if neither is given. To only bind to a specific port but not to a specific address, use "*" for the @var{address}. +This option may not work on all platforms. + @cindex BindToInterface @item BindToInterface = <@var{interface}> [experimental] If you have more than one network interface in your computer, tinc will @@ -865,8 +779,6 @@ possible to bind tinc to a single interface like eth0 or ppp0 with this variable. 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. @cindex Broadcast @item Broadcast = (mst) [experimental] @@ -912,7 +824,6 @@ Do not use this option if you use switch mode and want to use IPv6. @item Device = <@var{device}> (@file{/dev/tap0}, @file{/dev/net/tun} or other depending on platform) The virtual network device to use. Tinc will automatically detect what kind of device it is. -Note that you can only use one device per daemon. Under Windows, use @var{Interface} instead of @var{Device}. Note that you can only use one device per daemon. See also @ref{Device files}. @@ -949,7 +860,7 @@ Also note that this can cause decrypted VPN packets to be sent out on a real net @cindex UML @item uml (not compiled in by default) Create a UNIX socket with the filename specified by -@var{Device}, or @file{@value{localstatedir}/run/@var{netname}.umlsocket} +@var{Device}, or @file{@value{runstatedir}/@var{netname}.umlsocket} if not specified. Tinc will wait for a User Mode Linux instance to connect to this socket. @@ -957,7 +868,7 @@ Tinc will wait for a User Mode Linux instance to connect to this socket. @item vde (not compiled in by default) Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch, using the UNIX socket specified by -@var{Device}, or @file{@value{localstatedir}/run/vde.ctl} +@var{Device}, or @file{@value{runstatedir}/vde.ctl} if not specified. @end table @@ -983,6 +894,12 @@ 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. +@cindex utun +@item utun (OS X) +Set type to utun. +This is only supported on OS X version 10.6.8 and higher, but doesn't require the tuntaposx module. +This mode should support both IPv4 and IPv6 packets. + @item tap (BSD and Linux) Set type to tap. Tinc will expect packets read from the virtual network device @@ -996,19 +913,6 @@ but which would have to be forwarded by an intermediate node, are dropped instea When combined with the IndirectData option, packets for nodes for which we do not have a meta connection with are also dropped. -@cindex ECDSAPrivateKeyFile -@item ECDSAPrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/ecdsa_key.priv}) -The file in which the private ECDSA key of this tinc daemon resides. -This is only used if ExperimentalProtocol is enabled. - -@cindex ExperimentalProtocol -@item ExperimentalProtocol = (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 -@samp{tinc generate-ecdsa-keys}. - @cindex Forwarding @item Forwarding = (internal) [experimental] This option selects the way indirect packets are forwarded. @@ -1029,16 +933,30 @@ This is less efficient, but allows the kernel to apply its routing and firewall and can also help debugging. @end table +@cindex GraphDumpFile +@item GraphDumpFile = <@var{filename}> [experimental] +If this option is present, +tinc will dump the current network graph to the file @var{filename} +every minute, unless there were no changes to the graph. +The file is in a format that can be read by graphviz tools. +If @var{filename} starts with a pipe symbol |, +then the rest of the filename is interpreted as a shell command +that is executed, the graph is then sent to stdin. + @cindex Hostnames @item Hostnames = (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 everytime +tinc's efficiency, even stopping the daemon for a few seconds every time it does a lookup if your DNS server is not responding. This does not affect resolving hostnames to IP addresses from the configuration file, but whether hostnames should be resolved while logging. +@cindex IffOneQueue +@item IffOneQueue = (no) [experimental] +(Linux only) Set IFF_ONE_QUEUE flag on TUN/TAP devices. + @cindex Interface @item Interface = <@var{interface}> Defines the name of the interface corresponding to the virtual network device. @@ -1046,8 +964,15 @@ Depending on the operating system and the type of device this may or may not act Under Windows, this variable is used to select which network interface will be used. If you specified a Device, this variable is almost always already correctly set. +@cindex KeyExpire +@item KeyExpire = <@var{seconds}> (3600) +This option controls the time 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. + @cindex LocalDiscovery -@item LocalDiscovery = (no) +@item LocalDiscovery = (no) [experimental] When enabled, 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, @@ -1056,9 +981,14 @@ which normally would prevent the peers from learning each other's LAN address. 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. -@cindex LocalDiscoveryAddress -@item LocalDiscoveryAddress <@var{address}> -If this variable is specified, local discovery packets are sent to the given @var{address}. +@cindex MACExpire +@item MACExpire = <@var{seconds}> (600) +This option controls the amount of time MAC addresses are kept before they are removed. +This only has effect when Mode is set to "switch". + +@cindex MaxTimeout +@item MaxTimeout = <@var{seconds}> (900) +This is the maximum delay before trying to reconnect to other tinc daemons. @cindex Mode @item Mode = (router) @@ -1069,7 +999,7 @@ This option selects the way packets are routed to other daemons. @item router In this mode 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. +Only unicast packets of routable protocols (IPv4 and IPv6) are supported in this mode. This is the default mode, and unless you really know you need another mode, don't change it. @@ -1089,29 +1019,10 @@ every packet will be broadcast to the other daemons while no routing table is managed. @end table -@cindex KeyExpire -@item KeyExpire = <@var{seconds}> (3600) -This option controls the time 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. - -@cindex MACExpire -@item MACExpire = <@var{seconds}> (600) -This option controls the amount of time MAC addresses are kept before they are removed. -This only has effect when Mode is set to "switch". - -@cindex MaxConnectionBurst -@item MaxConnectionBurst = <@var{count}> (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. - @cindex Name @item Name = <@var{name}> [required] This is a symbolic name for this connection. -The name should consist only of alfanumeric and underscore characters (a-z, A-Z, 0-9 and _), and is case sensitive. +The name must consist only of alphanumeric and underscore characters (a-z, A-Z, 0-9 and _). If Name starts with a $, then the contents of the environment variable that follows will be used. In that case, invalid characters will be converted to underscores. @@ -1138,12 +1049,12 @@ will be inherited by the UDP packets that are sent out. @item PrivateKey = <@var{key}> [obsolete] This is the RSA private key for tinc. However, for safety reasons it is advised to store private keys of any kind in separate files. This prevents -accidental eavesdropping if you are editting the configuration file. +accidental eavesdropping if you are editing the configuration file. @cindex PrivateKeyFile @item PrivateKeyFile = <@var{path}> (@file{@value{sysconfdir}/tinc/@var{netname}/rsa_key.priv}) This is the full path name of the RSA private key file that was -generated by @samp{tinc generate-keys}. It must be a full path, not a +generated by @samp{tincd --generate-keys}. It must be a full path, not a relative directory. @cindex ProcessPriority @@ -1152,7 +1063,7 @@ When this option is used the priority of the tincd process will be adjusted. Increasing the priority may help to reduce latency and packet loss on the VPN. @cindex Proxy -@item Proxy = socks4 | socks4 | http | exec @var{...} [experimental] +@item Proxy = socks4 | socks5 | http | exec @var{...} [experimental] Use a proxy when making outgoing connections. The following proxy types are currently supported: @@ -1163,7 +1074,7 @@ Connects to the proxy using the SOCKS version 4 protocol. Optionally, a @var{username} can be supplied which will be passed on to the proxy server. @cindex socks5 -@item socks4 <@var{address}> <@var{port}> [<@var{username}> <@var{password}>] +@item socks5 <@var{address}> <@var{port}> [<@var{username}> <@var{password}>] Connect to the proxy using the SOCKS version 5 protocol. If a @var{username} and @var{password} are given, basic username/password authentication will be used, otherwise no authentication will be used. @@ -1190,10 +1101,12 @@ pass all traffic, but leaves tinc vulnerable to replay-based attacks on your traffic. @cindex StrictSubnets -@item StrictSubnets (no) [experimental] +@item StrictSubnets = (no) [experimental] When this option is enabled tinc will only use Subnet statements which are present in the host config files in the local @file{@value{sysconfdir}/tinc/@var{netname}/hosts/} directory. +Subnets learned via connections to other nodes and which are not +present in the local host config files are ignored. @cindex TunnelServer @item TunnelServer = (no) [experimental] @@ -1226,14 +1139,15 @@ This variable is only required if you want to connect to this host. It must resolve to the external IP address where the host can be reached, not the one that is internal to the VPN. If no port is specified, the default Port is used. +Multiple Address variables can be specified, in which case each address will be +tried until a working connection has been established. @cindex Cipher -@item Cipher = <@var{cipher}> (blowfish) -The symmetric cipher algorithm used to encrypt UDP packets using the legacy protocol. -Any cipher supported by OpenSSL is recognized. +@item Cipher = <@var{cipher}> (aes-256-cbc) +The symmetric cipher algorithm used to encrypt UDP packets. +Any cipher supported by LibreSSL or OpenSSL is recognized. Furthermore, specifying "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 using the SPTPS protocol, which always use AES-256-CTR. @cindex ClampMSS @item ClampMSS = (yes) @@ -1248,24 +1162,24 @@ Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib), 10 (fast lzo) and 11 (best lzo). @cindex Digest -@item Digest = <@var{digest}> (sha1) -The digest algorithm used to authenticate UDP packets using the legacy protocol. -Any digest supported by OpenSSL is recognized. +@item Digest = <@var{digest}> (sha256) +The digest algorithm used to authenticate UDP packets. +Any digest supported by LibreSSL or OpenSSL is recognized. Furthermore, specifying "none" will turn off packet authentication. -This option has no effect for connections using the SPTPS protocol, which always use HMAC-SHA-256. @cindex IndirectData @item IndirectData = (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. +This option specifies whether other tinc daemons besides the one you +specified with ConnectTo can make a direct connection to you. This is +especially useful if you are behind a firewall and it is impossible to +make a connection from the outside to your tinc daemon. Otherwise, it +is best to leave this option out or set it to no. @cindex MACLength @item MACLength = <@var{bytes}> (4) -The length of the message authentication code used to authenticate UDP packets using the legacy protocol. +The length of the message authentication code used to authenticate UDP packets. Can be anything from 0 up to the length of the digest produced by the digest algorithm. -This option has no effect for connections using the SPTPS protocol, which never truncate MACs. @cindex PMTU @item PMTU = <@var{mtu}> (1514) @@ -1288,7 +1202,7 @@ This is the RSA public key for this host. @cindex PublicKeyFile @item PublicKeyFile = <@var{path}> [obsolete] This is the full path name of the RSA public key file that was generated -by @samp{tinc generate-keys}. It must be a full path, not a relative +by @samp{tincd --generate-keys}. It must be a full path, not a relative directory. @cindex PEM format @@ -1302,7 +1216,7 @@ connection with that host. @cindex Subnet @item Subnet = <@var{address}[/@var{prefixlength}[#@var{weight}]]> The subnet which this tinc daemon will serve. -Tinc tries to look up which other daemon it should send a packet to by searching the appropiate subnet. +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 subnet lines can be specified for each daemon. @@ -1321,8 +1235,9 @@ MAC addresses are notated like 0:1a:2b:3c:4d:5e. Prefixlength is the number of bits set to 1 in the netmask part; for example: netmask 255.255.255.0 would become /24, 255.255.252.0 becomes /22. This conforms to standard CIDR notation as described in -@uref{http://www.ietf.org/rfc/rfc1519.txt, RFC1519} +@uref{https://www.ietf.org/rfc/rfc1519.txt, RFC1519} +@cindex Subnet weight 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, @@ -1330,12 +1245,15 @@ unless that node is not reachable, in which case the node with the next highest priority will be tried, and so on. @cindex TCPonly -@item TCPonly = (no) +@item TCPonly = (no) [deprecated] If this variable is set to yes, then the packets are tunnelled over a 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. + +Since version 1.0.10, tinc will automatically detect whether communication via +UDP is possible or not. @end table @@ -1346,7 +1264,15 @@ Setting this options also implicitly sets IndirectData. @cindex 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 .bat. +Below is a list of filenames of scripts and a description of when they are run. +A script is only run if it exists and if it is executable. + +Scripts are run synchronously; +this means that tinc will temporarily stop processing packets until the called script finishes executing. +This guarantees that scripts will execute in the exact same order as the events that trigger them. +If you need to run commands asynchronously, you have to ensure yourself that they are being run in the background. + +Under Windows (not Cygwin), the scripts must have the extension .bat. @table @file @cindex tinc-up @@ -1356,6 +1282,7 @@ 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. @cindex tinc-down @@ -1375,11 +1302,11 @@ This script is started when any host becomes reachable. This script is started when any host becomes unreachable. @item @value{sysconfdir}/tinc/@var{netname}/subnet-up -This script is started when a Subnet becomes reachable. +This script is started when a subnet becomes reachable. The Subnet and the node it belongs to are passed in environment variables. @item @value{sysconfdir}/tinc/@var{netname}/subnet-down -This script is started when a Subnet becomes unreachable. +This script is started when a subnet becomes unreachable. @end table @cindex environment variables @@ -1424,6 +1351,10 @@ this is set to the port number it uses for communication with other tinc daemons @item SUBNET When a subnet becomes (un)reachable, this is set to the subnet. +@cindex WEIGHT +@item WEIGHT +When a subnet becomes (un)reachable, this is set to the subnet weight. + @end table @@ -1431,116 +1362,50 @@ When a subnet becomes (un)reachable, this is set to the subnet. @node How to configure @subsection How to configure -@subsubheading Step 1. Creating initial configuration files. +@subsubheading Step 1. Creating the main configuration file -The initial directory structure, configuration files and public/private keypairs are created using the following command: +The main configuration file will be called @file{@value{sysconfdir}/tinc/@var{netname}/tinc.conf}. +Adapt the following example to create a basic configuration file: @example -tinc -n @var{netname} init @var{name} +Name = @var{yourname} +Device = @file{/dev/tap0} @end example -(You will need to run this as root, or use "sudo".) -This will create the configuration directory @file{@value{sysconfdir}/tinc/@var{netname}.}, -and inside it will create another directory named @file{hosts/}. -In the configuration directory, it will create the file @file{tinc.conf} with the following contents: +Then, if you know to which other tinc daemon(s) yours is going to connect, +add `ConnectTo' values. + +@subsubheading Step 2. Creating your host configuration file + +If you added a line containing `Name = yourname' in the main configuration file, +you will need to create a host configuration file @file{@value{sysconfdir}/tinc/@var{netname}/hosts/yourname}. +Adapt the following example to create a host configuration file: @example -Name = @var{name} +Address = your.real.hostname.org +Subnet = 192.168.1.0/24 @end example -It will also create private RSA and ECDSA keys, which will be stored in the files @file{rsa_key.priv} and @file{ecdsa_key.priv}. -It will also create a host configuration file @file{hosts/@var{name}}, -which will contain the corresponding public RSA and ECDSA keys. +You can also use an IP address instead of a hostname. +The `Subnet' specifies the address range that is local for @emph{your part of the VPN only}. +If you have multiple address ranges you can specify more than one `Subnet'. +You might also need to add a `Port' if you want your tinc daemon to run on a different port number than the default (655). -Finally, on UNIX operating systems, it will create an executable script @file{tinc-up}, -which will initially not do anything except warning that you should edit it. -@subsubheading Step 2. Modifying the initial configuration. +@c ================================================================== +@node Generating keypairs +@section Generating keypairs -Unless you want to use tinc in switch mode, -you should now configure which range of addresses you will use on the VPN. -Let's assume you will be part of a VPN which uses the address range 192.168.0.0/16, -and you yourself have a smaller portion of that range: 192.168.2.0/24. -Then you should run the following command: +@cindex key generation +Now that you have already created the main configuration file and your host configuration file, +you can easily create a public/private keypair by entering the following command: @example -tinc -n @var{netname} add subnet 192.168.2.0/24 +tincd -n @var{netname} -K @end example -This will add a Subnet statement to your host configuration file. -Try opening the file @file{@value{sysconfdir}/tinc/@var{netname}/hosts/@var{name}} in an editor. -You should now see a file containing the public RSA and ECDSA keys (which looks like a bunch of random characters), -and the following line at the bottom: - -@example -Subnet = 192.168.2.0/24 -@end example - -If you will use more than one address range, you can add more Subnets. -For example, if you also use the IPv6 subnet fec0:0:0:2::/64, you can add it as well: - -@example -tinc -n @var{netname} add subnet fec0:0:0:2::/24 -@end example - -This will add another line to the file @file{hosts/@var{name}}. -If you make a mistake, you can undo it by simply using @samp{del} instead of @samp{add}. - -If you want other tinc daemons to create meta-connections to your daemon, -you should add your public IP address or hostname to your host configuration file. -For example, if your hostname is foo.example.org, run: - -@example -tinc -n @var{netname} add address foo.example.org -@end example - -If you already know to which daemons your daemon should make meta-connections, -you should configure that now as well. -Suppose you want to connect to a daemon named "bar", run: - -@example -tinc -n @var{netname} add connectto bar -@end example - -Note that you specify the Name of the other daemon here, not an IP address or hostname! -When you start tinc, and it tries to make a connection to "bar", -it will look for a host configuration file named @file{hosts/bar}, -and will read Address statements and public keys from that file. - -@subsubheading Step 2. Exchanging configuration files. - -If your daemon has a ConnectTo = bar statement in its @file{tinc.conf} file, -or if bar has a ConnectTo your daemon, then you both need each other's host configuration files. -You should send @file{hosts/@var{name}} to bar, and bar should send you his file which you should move to @file{hosts/bar}. -If you are on a UNIX platform, you can easily send an email containing the necessary information using the following command -(assuming the owner of bar has the email address bar@@example.org): - -@example -tinc -n @var{netname} export | mail -s "My config file" bar@@example.org -@end example - -If the owner of bar does the same to send his host configuration file to you, -you can probably pipe his email through the following command, -or you can just start this command in a terminal and copy&paste the email: - -@example -tinc -n @var{netname} import -@end example - -If you are the owner of bar yourself, and you have SSH access to that computer, -you can also swap the host configuration files using the following command: - -@example -tinc -n @var{netname} export \ - | ssh bar.example.org tinc -n @var{netname} exchange \ - | tinc -n @var{netname} import -@end example - -You should repeat this for all nodes you ConnectTo, or which ConnectTo you. -However, remember that you do not need to ConnectTo all nodes in the VPN; -it is only necessary to create one or a few meta-connections, -after the connections are made tinc will learn about all the other nodes in the VPN, -and will automatically make other connections as necessary. +Tinc will generate a public and a private key and ask you where to put them. +Just press enter to accept the defaults. @c ================================================================== @@ -1563,31 +1428,21 @@ You can configure the network interface by putting ordinary ifconfig, route, and to a script named @file{@value{sysconfdir}/tinc/@var{netname}/tinc-up}. When tinc starts, this script will be executed. When tinc exits, it will execute the script named @file{@value{sysconfdir}/tinc/@var{netname}/tinc-down}, but normally you don't need to create that script. -You can manually open the script in an editor, or use the following command: -@example -tinc -n @var{netname} edit tinc-up -@end example - -An example @file{tinc-up} script, that would be appropriate for the scenario in the previous section, is: +An example @file{tinc-up} script: @example #!/bin/sh -ifconfig $INTERFACE 192.168.2.1 netmask 255.255.0.0 -ip addr add fec0:0:0:2::/48 dev $INTERFACE +ifconfig $INTERFACE 192.168.1.1 netmask 255.255.0.0 @end example -The first command gives the interface an IPv4 address and a netmask. -The kernel will also automatically add an IPv4 route to this interface, so normally you don't need +This script gives the interface an IP address and a netmask. +The kernel will also automatically add a route to this interface, so normally you don't need to add route commands to the @file{tinc-up} script. The kernel will also bring the interface up after this command. @cindex netmask The netmask is the mask of the @emph{entire} VPN network, not just your own subnet. -The second command gives the interface an IPv6 address and netmask, -which will also automatically add an IPv6 route. -If you only want to use "ip addr" commands on Linux, don't forget that it doesn't bring the interface up, unlike ifconfig, -so you need to add @samp{ip link set $INTERFACE up} in that case. The exact syntax of the ifconfig and route commands differs from platform to platform. You can look up the commands for setting addresses and adding routes in @ref{Platform specific information}, @@ -1627,9 +1482,6 @@ the real interface is also shown as a comment, to give you an idea of how these example host is set up. All branches use the netname `company' for this particular VPN. -Each branch is set up using the @samp{tinc init} and @samp{tinc config} commands, -here we just show the end results: - @subsubheading For Branch A @emph{BranchA} would be configured like this: @@ -1637,8 +1489,6 @@ here we just show the end results: In @file{@value{sysconfdir}/tinc/company/tinc-up}: @example -#!/bin/sh - # Real interface of internal network: # ifconfig eth0 10.1.54.1 netmask 255.255.0.0 @@ -1649,6 +1499,7 @@ and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: @example Name = BranchA +Device = /dev/tap0 @end example On all hosts, @file{@value{sysconfdir}/tinc/company/hosts/BranchA} contains: @@ -1662,9 +1513,9 @@ Address = 1.2.3.4 -----END RSA PUBLIC KEY----- @end example -Note that the IP addresses of eth0 and the VPN interface are the same. +Note that the IP addresses of eth0 and tap0 are the same. This is quite possible, if you make sure that the netmasks of the interfaces are different. -It is in fact recommended to give both real internal network interfaces and VPN interfaces the same IP address, +It is in fact recommended to give both real internal network interfaces and tap interfaces the same IP address, since that will make things a lot easier to remember and set up. @@ -1673,8 +1524,6 @@ since that will make things a lot easier to remember and set up. In @file{@value{sysconfdir}/tinc/company/tinc-up}: @example -#!/bin/sh - # Real interface of internal network: # ifconfig eth0 10.2.43.8 netmask 255.255.0.0 @@ -1689,7 +1538,7 @@ ConnectTo = BranchA @end example Note here that the internal address (on eth0) doesn't have to be the -same as on the VPN interface. Also, ConnectTo is given so that this node will +same as on the tap0 device. Also, ConnectTo is given so that this node will always try to connect to BranchA. On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchB}: @@ -1709,8 +1558,6 @@ Address = 2.3.4.5 In @file{@value{sysconfdir}/tinc/company/tinc-up}: @example -#!/bin/sh - # Real interface of internal network: # ifconfig eth0 10.3.69.254 netmask 255.255.0.0 @@ -1722,6 +1569,7 @@ and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: @example Name = BranchC ConnectTo = BranchA +Device = /dev/tap1 @end example C already has another daemon that runs on port 655, so they have to @@ -1746,8 +1594,6 @@ Port = 2000 In @file{@value{sysconfdir}/tinc/company/tinc-up}: @example -#!/bin/sh - # Real interface of internal network: # ifconfig eth0 10.4.3.32 netmask 255.255.0.0 @@ -1759,10 +1605,14 @@ and in @file{@value{sysconfdir}/tinc/company/tinc.conf}: @example Name = BranchD ConnectTo = BranchC +Device = /dev/net/tun @end example D will be connecting to C, which has a tincd running for this network on port 2000. It knows the port number from the host configuration file. +Also note that since D uses the tun/tap driver, the network interface +will not be called `tun' or `tap0' or something like that, but will +have the same name as netname. On all hosts, in @file{@value{sysconfdir}/tinc/company/hosts/BranchD}: @@ -1777,11 +1627,16 @@ Address = 4.5.6.7 @subsubheading Key files -A, B, C and D all have their own public/private keypairs: +A, B, C and D all have generated a public/private keypair with the following command: -The private RSA key is stored in @file{@value{sysconfdir}/tinc/company/rsa_key.priv}, -the private ECDSA key is stored in @file{@value{sysconfdir}/tinc/company/ecdsa_key.priv}, -and the public RSA and ECDSA keys are put into the host configuration file in the @file{@value{sysconfdir}/tinc/company/hosts/} directory. +@example +tincd -n company -K +@end example + +The private key is stored in @file{@value{sysconfdir}/tinc/company/rsa_key.priv}, +the public key is put into the host configuration file in the @file{@value{sysconfdir}/tinc/company/hosts/} directory. +During key generation, tinc automatically guesses the right filenames based on the -n option and +the Name directive in the @file{tinc.conf} file (if it is available). @subsubheading Starting @@ -1798,7 +1653,7 @@ their daemons, tinc will try connecting until they are available. If everything else is done, you can start tinc by typing the following command: @example -tinc -n @var{netname} start +tincd -n @var{netname} @end example @cindex daemon @@ -1841,6 +1696,12 @@ This will also disable the automatic restart mechanism for fatal errors. Set debug level to @var{level}. The higher the debug level, the more gets logged. Everything goes via syslog. +@item -k, --kill[=@var{signal}] +Attempt to kill a running tincd (optionally with the specified @var{signal} instead of SIGTERM) and exit. +Use it in conjunction with the -n option to make sure you kill the right tinc daemon. +Under native Windows the optional argument is ignored, +the service will always be stopped and removed. + @item -n, --net=@var{netname} Use configuration for net @var{netname}. This will let tinc read all configuration files from @@ -1848,10 +1709,11 @@ This will let tinc read all configuration files from Specifying . for @var{netname} is the same as not specifying any @var{netname}. @xref{Multiple networks}. -@item --pidfile=@var{filename} -Store a cookie in @var{filename} which allows tinc to authenticate. -If unspecified, the default is -@file{@value{localstatedir}/run/tinc.@var{netname}.pid}. +@item -K, --generate-keys[=@var{bits}] +Generate public/private keypair of @var{bits} length. If @var{bits} is not specified, +2048 is the default. tinc will ask where you want to store the files, +but will default to the configuration directory (you can use the -c or -n option +in combination with -K). After that, tinc will quit. @item -o, --option=[@var{HOST}.]@var{KEY}=@var{VALUE} Without specifying a @var{HOST}, this will set server configuration variable @var{KEY} to @var{VALUE}. @@ -1863,12 +1725,13 @@ This option can be used more than once to specify multiple configuration variabl 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. - @item --logfile[=@var{file}] Write log entries to a file instead of to the system logging facility. If @var{file} is omitted, the default is @file{@value{localstatedir}/log/tinc.@var{netname}.log}. +@item --pidfile=@var{file} +Write PID to @var{file} instead of @file{@value{runstatedir}/tinc.@var{netname}.pid}. + @item --bypass-security Disables encryption and authentication. Only useful for debugging. @@ -1880,19 +1743,20 @@ located (@file{@value{sysconfdir}/tinc/@var{netname}/} as determined by The chroot is performed after all the initialization is done, after writing pid files and opening network sockets. -Note that this option alone does not do any good without -U/--user, below. +This option is best used in combination with the -U/--user option described below. -Note also that tinc can't run scripts anymore (such as tinc-down or host-up), -unless it's setup to be runnable inside chroot environment. +You will need to ensure the chroot environment contains all the files necessary +for tinc to run correctly. +Most importantly, for tinc to be able to resolve hostnames inside the chroot environment, +you must copy @file{/etc/resolv.conf} into the chroot directory. +If you want to be able to run scripts other than @file{tinc-up} in the chroot, +you must ensure the appropriate shell is also installed in the chroot, along with all its dependencies. -This option is not supported on all platforms. @item -U, --user=@var{user} Switch to the given @var{user} after initialization, at the same time as chroot is performed (see --chroot above). With this option tinc drops privileges, for added security. -This option is not supported on all platforms. - @item --help Display a short reminder of these runtime options and terminate. @@ -1925,6 +1789,19 @@ New outgoing connections specified in @file{tinc.conf} will be made. If the --logfile option is used, this will also close and reopen the log file, useful when log rotation is used. +@item INT +Temporarily increases debug level to 5. +Send this signal again to revert to the original level. + +@item USR1 +Dumps the connection list to syslog. + +@item USR2 +Dumps virtual network device statistics, all known nodes, edges and subnets to syslog. + +@item WINCH +Purges all information remembered about unreachable nodes. + @end table @c ================================================================== @@ -1988,7 +1865,7 @@ Do you have a firewall or a NAT device (a masquerading firewall or perhaps an AD If so, check that it allows TCP and UDP traffic on port 655. If it masquerades and the host running tinc is behind it, make sure that it forwards TCP and UDP traffic to port 655 to the host running tinc. You can add @samp{TCPOnly = yes} to your host config file to force tinc to only use a single TCP connection, -this works through most firewalls and NATs. +this works through most firewalls and NATs. Since version 1.0.10, tinc will automatically fall back to TCP if direct communication via UDP is not possible. @end itemize @@ -2087,8 +1964,6 @@ or if that is not the case, try changing the prefix length into /32. @itemize @item If you see this only sporadically, it is harmless and caused by a node sending packets using an old key. -@item If you see this often and another node is not reachable anymore, then a NAT (masquerading firewall) is changing the source address of UDP packets. -You can add @samp{TCPOnly = yes} to host configuration files to force all VPN traffic to go over a TCP connection. @end itemize @item Got bad/bogus/unauthorized REQUEST from foo (1.2.3.4 port 12345) @@ -2119,287 +1994,6 @@ Be sure to include the following information in your bugreport: @item The output of any command that fails to work as it should (like ping or traceroute). @end itemize -@c ================================================================== -@node Controlling tinc -@chapter Controlling tinc - -You can control and inspect a running tincd through the tinc -command. A quick example: - -@example -tinc -n @var{netname} reload -@end example - -@menu -* tinc runtime options:: -* tinc environment variables:: -* tinc commands:: -* tinc examples:: -* tinc top:: -@end menu - - -@c ================================================================== -@node tinc runtime options -@section tinc runtime options - -@c from the manpage -@table @option -@item -c, --config=@var{path} -Read configuration options from the directory @var{path}. The default is -@file{@value{sysconfdir}/tinc/@var{netname}/}. - -@item -n, --net=@var{netname} -Use configuration for net @var{netname}. @xref{Multiple networks}. - -@item --pidfile=@var{filename} -Use the cookie from @var{filename} to authenticate with a running tinc daemon. -If unspecified, the default is -@file{@value{localstatedir}/run/tinc.@var{netname}.pid}. - -@item --help -Display a short reminder of runtime options and commands, then terminate. - -@item --version -Output version information and exit. - -@end table - -@c ================================================================== -@node tinc environment variables -@section tinc environment variables - -@table @env -@cindex NETNAME -@item NETNAME -If no netname is specified on the command line with the @option{-n} option, -the value of this environment variable is used. -@end table - -@c ================================================================== -@node tinc commands -@section tinc commands - -@c from the manpage -@table @code - -@item init [@var{name}] -Create initial configuration files and RSA and ECDSA keypairs with default length. -If no @var{name} for this node is given, it will be asked for. - -@item get @var{variable} -Print the current value of configuration variable @var{variable}. -If more than one variable with the same name exists, -the value of each of them will be printed on a separate line. - -@item set @var{variable} @var{value} -Set configuration variable @var{variable} to the given @var{value}. -All previously existing configuration variables with the same name are removed. -To set a variable for a specific host, use the notation @var{host}.@var{variable}. - -@item add @var{variable} @var{value} -As above, but without removing any previously existing configuration variables. - -@item del @var{variable} [@var{value}] -Remove configuration variables with the same name and @var{value}. -If no @var{value} is given, all configuration variables with the same name will be removed. - -@item edit @var{filename} -Start an editor for the given configuration file. -You do not need to specify the full path to the file. - -@item export -Export the host configuration file of the local node to standard output. - -@item export-all -Export all host configuration files to standard output. - -@item import [--force] -Import host configuration file(s) generated by the tinc export command from standard input. -Already existing host configuration files are not overwritten unless the option --force is used. - -@item exchange [--force] -The same as export followed by import. - -@item exchange-all [--force] -The same as export-all followed by import. - -@item invite @var{name} -Prepares an invitation for a new node with the given @var{name}, -and prints a short invitation URL that can be used with the join command. - -@item join [@var{URL}] -Join an existing VPN using an invitation URL created using the invite command. -If no @var{URL} is given, it will be read from standard input. - -@item start [tincd options] -Start @samp{tincd}, optionally with the given extra options. - -@item stop -Stop @samp{tincd}. - -@item restart [tincd options] -Restart @samp{tincd}, optionally with the given extra options. - -@item reload -Partially rereads configuration files. Connections to hosts whose host -config files are removed are closed. New outgoing connections specified -in @file{tinc.conf} will be made. - -@item pid -Shows the PID of the currently running @samp{tincd}. - -@item generate-keys [@var{bits}] -Generate both RSA and ECDSA keypairs (see below) and exit. -tinc will ask where you want to store the files, but will default to the -configuration directory (you can use the -c or -n option). - -@item generate-ecdsa-keys -Generate public/private ECDSA keypair and exit. - -@item generate-rsa-keys [@var{bits}] -Generate public/private RSA keypair and exit. If @var{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. - -@item dump [reachable] nodes -Dump a list of all known nodes in the VPN. -If the reachable keyword is used, only lists reachable nodes. - -@item dump edges -Dump a list of all known connections in the VPN. - -@item dump subnets -Dump a list of all known subnets in the VPN. - -@item dump connections -Dump a list of all meta connections with ourself. - -@item dump graph | digraph -Dump a graph of the VPN in dotty 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. - -@item info @var{node} | @var{subnet} | @var{address} -Show information about a particular @var{node}, @var{subnet} or @var{address}. -If an @var{address} is given, any matching subnet will be shown. - -@item purge -Purges all information remembered about unreachable nodes. - -@item debug @var{level} -Sets debug level to @var{level}. - -@item log [@var{level}] -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 tinc. - -@item retry -Forces tinc to try to connect to all uplinks immediately. -Usually tinc attempts to do this itself, -but increases the time it waits between the attempts each time it failed, -and if tinc didn't succeed to connect to an uplink the first time after it started, -it defaults to the maximum time of 15 minutes. - -@item disconnect @var{node} -Closes the meta connection with the given @var{node}. - -@item top -If tinc is compiled with libcurses support, this will display live traffic statistics for all the known nodes, -similar to the UNIX top command. -See below for more information. - -@item pcap -Dump VPN traffic going through the local tinc node in pcap-savefile 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 tcpdump. - -@end table - -@c ================================================================== -@node tinc examples -@section tinc examples - -Examples of some commands: - -@example -tinc -n vpn dump graph | circo -Txlib -tinc -n vpn pcap | tcpdump -r - -tinc -n vpn top -@end example - -Example of configuring tinc using the tinc command: - -@example -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 -@end example - -@c ================================================================== -@node tinc top -@section tinc 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: - -@table @key - -@item s -Change the interval between updates. -After pressing the @key{s} key, enter the desired interval in seconds, followed by enter. -Fractional seconds are honored. -Intervals lower than 0.1 seconds are not allowed. - -@item c -Toggle between displaying current traffic rates (in packets and bytes per second) -and cummulative traffic (total packets and bytes since the tinc daemon started). - -@item n -Sort the list of nodes by name. - -@item i -Sort the list of nodes by incoming amount of bytes. - -@item I -Sort the list of nodes by incoming amount of packets. - -@item o -Sort the list of nodes by outgoing amount of bytes. - -@item O -Sort the list of nodes by outgoing amount of packets. - -@item t -Sort the list of nodes by sum of incoming and outgoing amount of bytes. - -@item T -Sort the list of nodes by sum of incoming and outgoing amount of packets. - -@item b -Show amount of traffic in bytes. - -@item k -Show amount of traffic in kilobytes. - -@item M -Show amount of traffic in megabytes. - -@item G -Show amount of traffic in gigabytes. - -@item q -Quit. - -@end table - - @c ================================================================== @node Technical information @chapter Technical information @@ -2441,7 +2035,7 @@ There are two possible types of virtual network devices: and `tap' style, which are Ethernet devices and handle complete Ethernet frames. So when tinc reads an Ethernet frame from the device, it determines its -type. When tinc is in it's default routing mode, it can handle IPv4 and IPv6 +type. When tinc is in its default routing mode, it can handle IPv4 and IPv6 packets. Depending on the Subnet lines, it will send the packets off to their destination IP address. In the `switch' and `hub' mode, tinc will use broadcasts and MAC address discovery to deduce the destination of the packets. @@ -2472,7 +2066,7 @@ If the virtual network device is a `tun' device (a point-to-point tunnel), there is no problem for the kernel to accept a packet. However, if it is a `tap' device (this is the only available type on FreeBSD), the destination MAC address must match that of the virtual network interface. -If tinc is in it's default routing mode, ARP does not work, so the correct destination MAC +If tinc is in its default routing mode, ARP does not work, so the correct destination MAC can not be known by the sending host. Tinc solves this by letting the receiving end detect the MAC address of its own virtual network interface and overwriting the destination MAC address of the received packet. @@ -2481,7 +2075,7 @@ In switch or hub modes ARP does work so the sender already knows the correct des In those modes every interface should have a unique MAC address, so make sure they are not the same. Because switch and hub modes rely on MAC addresses to function correctly, these modes cannot be used on the following operating systems which don't have a `tap' style virtual network device: -OpenBSD, NetBSD, Darwin and Solaris. +NetBSD, Darwin and Solaris. @c ================================================================== @@ -2534,7 +2128,7 @@ daemon started with the --bypass-security option and to read and write requests by hand, provided that one understands the numeric codes sent. -The authentication scheme is described in @ref{Security}. After a +The authentication scheme is described in @ref{Authentication protocol}. After a successful authentication, the server and the client will exchange all the information about other tinc daemons and subnets they know of, so that both sides (and all the other tinc daemons behind them) have their information @@ -2621,10 +2215,10 @@ destination. @cindex PING @cindex PONG @example -daemon message +daemon message ------------------------------------------------------------------ -origin PING -dest. PONG +origin PING +dest. PONG ------------------------------------------------------------------ @end example @@ -2652,30 +2246,31 @@ the tinc project after TINC. @cindex SVPN But in order to be ``immune'' to eavesdropping, you'll have to encrypt -your data. Because tinc is a @emph{Secure} VPN (SVPN) daemon, it does +your data. Because tinc is a @emph{Secure} VPN (SVPN) daemon, it does exactly that: encrypt. -However, encryption in itself does not prevent an attacker from modifying the encrypted data. -Therefore, tinc also authenticates the data. -Finally, tinc uses sequence numbers (which themselves are also authenticated) to prevent an attacker from replaying valid packets. - -Since version 1.1pre3, tinc has two protocols used to protect your data; the legacy protocol, and the new Simple Peer-to-Peer Security (SPTPS) protocol. -The SPTPS protocol is designed to address some weaknesses in the legacy protocol. -The new authentication protocol is used when two nodes connect to each other that both have the ExperimentalProtocol option set to yes, -otherwise the legacy protocol will be used. +Tinc by default uses blowfish encryption with 128 bit keys in CBC mode, 32 bit +sequence numbers and 4 byte long message authentication codes to make sure +eavesdroppers cannot get and cannot change any information at all from the +packets they can intercept. The encryption algorithm and message authentication +algorithm can be changed in the configuration. The length of the message +authentication codes is also adjustable. The length of the key for the +encryption algorithm is always the default length used by LibreSSL/OpenSSL. @menu -* Legacy authentication protocol:: -* Simple Peer-to-Peer Security:: +* Authentication protocol:: * Encryption of network packets:: * Security issues:: @end menu @c ================================================================== -@node Legacy authentication protocol -@subsection Legacy authentication protocol +@node Authentication protocol +@subsection Authentication protocol -@cindex legacy authentication protocol +@cindex authentication +A new scheme for authentication in tinc has been devised, which offers some +improvements over the protocol used in 1.0pre2 and 1.0pre3. Explanation is +below. @cindex ID @cindex META_KEY @@ -2689,50 +2284,28 @@ client server -client ID client 17.2 - | | +-> minor protocol version - | +----> major protocol version - +--------> name of tinc daemon +client ID client 12 + | +---> version + +-------> name of tinc daemon -server ID server 17.2 - | | +-> minor protocol version - | +----> major protocol version - +--------> name of tinc daemon +server ID server 12 + | +---> version + +-------> name of tinc daemon -client META_KEY 94 64 0 0 5f0823a93e35b69e...7086ec7866ce582b - | | | | \_________________________________/ - | | | | +-> RSAKEYLEN bits totally random string S1, - | | | | encrypted with server's public RSA key - | | | +-> compression level - | | +---> MAC length - | +------> digest algorithm NID - +---------> cipher algorithm NID +client META_KEY 5f0823a93e35b69e...7086ec7866ce582b + \_________________________________/ + +-> RSAKEYLEN bits totally random string S1, + encrypted with server's public RSA key -server META_KEY 94 64 0 0 6ab9c1640388f8f0...45d1a07f8a672630 - | | | | \_________________________________/ - | | | | +-> RSAKEYLEN bits totally random string S2, - | | | | encrypted with client's public RSA key - | | | +-> compression level - | | +---> MAC length - | +------> digest algorithm NID - +---------> cipher algorithm NID --------------------------------------------------------------------------- -@end example - -The protocol allows each side to specify encryption algorithms and parameters, -but in practice they are always fixed, since older versions of tinc did not -allow them to be different from the default values. The cipher is always -Blowfish in OFB mode, the digest is SHA1, but the MAC length is zero and no -compression is used. +server META_KEY 6ab9c1640388f8f0...45d1a07f8a672630 + \_________________________________/ + +-> RSAKEYLEN bits totally random string S2, + encrypted with client's public RSA key From now on: -@itemize -@item the client will symmetrically encrypt outgoing traffic using S1 -@item the server will symmetrically encrypt outgoing traffic using S2 -@end itemize + - the client will symmetrically encrypt outgoing traffic using S1 + - the server will symmetrically encrypt outgoing traffic using S2 -@example --------------------------------------------------------------------------- client CHALLENGE da02add1817c1920989ba6ae2a49cecbda0 \_________________________________/ +-> CHALLEN bits totally random string H1 @@ -2752,188 +2325,57 @@ their identity. Further information is exchanged. client ACK 655 123 0 | | +-> options - | +----> estimated weight - +--------> listening port of client + | +----> estimated weight + +--------> listening port of client server ACK 655 321 0 | | +-> options - | +----> estimated weight - +--------> listening port of server + | +----> estimated weight + +--------> listening port of server -------------------------------------------------------------------------- @end example -This legacy authentication protocol has several weaknesses, pointed out by security export Peter Gutmann. -First, data is encrypted with RSA without padding. -Padding schemes are designed to prevent attacks when the size of the plaintext is not equal to the size of the RSA key. -Tinc always encrypts random nonces that have the same size as the RSA key, so we do not believe this leads to a break of the security. -There might be timing or other side-channel attacks against RSA encryption and decryption, tinc does not employ any protection against those. -Furthermore, both sides send identical messages to each other, there is no distinction between server and client, -which could make a MITM attack easier. -However, no exploit is known in which a third party who is not already trusted by other nodes in the VPN could gain access. -Finally, the RSA keys are used to directly encrypt the session keys, which means that if the RSA keys are compromised, it is possible to decrypt all previous VPN traffic. -In other words, the legacy protocol does not provide perfect forward secrecy. +This new scheme has several improvements, both in efficiency and security. -@c ================================================================== -@node Simple Peer-to-Peer Security -@subsection Simple Peer-to-Peer Security -@cindex SPTPS +First of all, the server sends exactly the same kind of messages over the wire +as the client. The previous versions of tinc first authenticated the client, +and then the server. This scheme even allows both sides to send their messages +simultaneously, there is no need to wait for the other to send something first. +This means that any calculations that need to be done upon sending or receiving +a message can also be done in parallel. This is especially important when doing +RSA encryption/decryption. Given that these calculations are the main part of +the CPU time spent for the authentication, speed is improved by a factor 2. -The SPTPS protocol is designed to address the weaknesses in the legacy protocol. -SPTPS is based on TLS 1.2, but has been simplified: there is no support for exchanging public keys, and there is no cipher suite negotiation. -Instead, SPTPS always uses a very strong cipher suite: -peers authenticate each other using 521 bits ECC keys, -Diffie-Hellman using ephemeral 521 bits ECC keys is used to provide perfect forward secrecy (PFS), -AES-256-CTR is used for encryption, and HMAC-SHA-256 for message authentication. +Second, only one RSA encrypted message is sent instead of two. This reduces the +amount of information attackers can see (and thus use for a cryptographic +attack). It also improves speed by a factor two, making the total speedup a +factor 4. -Similar to TLS, messages are split up in records. -A complete logical record contains the following information: +Third, and most important: +The symmetric cipher keys are exchanged first, the challenge is done +afterwards. In the previous authentication scheme, because a man-in-the-middle +could pass the challenge/chal_reply phase (by just copying the messages between +the two real tinc daemons), but no information was exchanged that was really +needed to read the rest of the messages, the challenge/chal_reply phase was of +no real use. The man-in-the-middle was only stopped by the fact that only after +the ACK messages were encrypted with the symmetric cipher. Potentially, it +could even send it's own symmetric key to the server (if it knew the server's +public key) and read some of the metadata the server would send it (it was +impossible for the mitm to read actual network packets though). The new scheme +however prevents this. -@itemize -@item uint32_t seqno (network byte order) -@item uint16_t length (network byte order) -@item uint8_t type -@item opaque data[length] -@item opaque hmac[HMAC_SIZE] (HMAC over all preceding fields) -@end itemize +This new scheme makes sure that first of all, symmetric keys are exchanged. The +rest of the messages are then encrypted with the symmetric cipher. Then, each +side can only read received messages if they have their private key. The +challenge is there to let the other side know that the private key is really +known, because a challenge reply can only be sent back if the challenge is +decrypted correctly, and that can only be done with knowledge of the private +key. -Depending on whether SPTPS records are sent via TCP or UDP, either the seqno or the length field is omitted on the wire -(but they are still included in the calculation of the HMAC); -for TCP packets are guaranteed to arrive in-order so we can infer the seqno, but packets can be split or merged, so we still need the length field to determine the boundaries between records; -for UDP packets we know that there is exactly one record per packet, and we know the length of a packet, but packets can be dropped, duplicated and/or reordered, so we need to include the seqno. +Fourth: the first thing that is sent via the symmetric cipher encrypted +connection is a totally random string, so that there is no known plaintext (for +an attacker) in the beginning of the encrypted stream. -The type field is used to distinguish between application records or handshake records. -Types 0 to 127 are application records, type 128 is a handshake record, and types 129 to 255 are reserved. - -Before the initial handshake, no fields are encrypted, and the HMAC field is not present. -After the authentication handshake, the length (if present), type and data fields are encrypted, and the HMAC field is present. -For UDP packets, the seqno field is not encrypted, as it is used to determine the value of the counter used for encryption. - -The authentication consists of an exchange of Key EXchange, SIGnature and ACKnowledge messages, transmitted using type 128 records. - -Overview: - -@example -Initiator Responder ---------------------- -KEX -> - <- KEX -SIG -> - <- SIG - -...encrypt and HMAC using session keys from now on... - -App -> - <- App -... - ... - -...key renegotiation starts here... - -KEX -> - <- KEX -SIG -> - <- SIG -ACK -> - <- ACK - -...encrypt and HMAC using new session keys from now on... - -App -> - <- App -... - ... ---------------------- -@end example - -Note that the responder does not need to wait before it receives the first KEX message, -it can immediately send its own once it has accepted an incoming connection. - -Key EXchange message: - -@itemize -@item uint8_t kex_version (always 0 in this version of SPTPS) -@item opaque nonce[32] (random number) -@item opaque ecdh_key[ECDH_SIZE] -@end itemize - -SIGnature message: - -@itemize -@item opaque ecdsa_signature[ECDSA_SIZE] -@end itemize - -ACKnowledge message: - -@itemize -@item empty (only sent after key renegotiation) -@end itemize - -Remarks: - -@itemize -@item At the start, both peers generate a random nonce and an Elliptic Curve public key and send it to the other in the KEX message. -@item After receiving the other's KEX message, both KEX messages are concatenated (see below), - and the result is signed using ECDSA. - The result is sent to the other. -@item After receiving the other's SIG message, the signature is verified. - If it is correct, the shared secret is calculated from the public keys exchanged in the KEX message using the Elliptic Curve Diffie-Helman algorithm. -@item The shared secret key is expanded using a PRF. - Both nonces and the application specific label are also used as input for the PRF. -@item An ACK message is sent only when doing key renegotiation, and is sent using the old encryption keys. -@item The expanded key is used to key the encryption and HMAC algorithms. -@end itemize - -The signature is calculated over this string: - -@itemize -@item uint8_t initiator (0 = local peer, 1 = remote peer is initiator) -@item opaque remote_kex_message[1 + 32 + ECDH_SIZE] -@item opaque local_kex_message[1 + 32 + ECDH_SIZE] -@item opaque label[label_length] -@end itemize - -The PRF is calculated as follows: - -@itemize -@item A HMAC using SHA512 is used, the shared secret is used as the key. -@item For each block of 64 bytes, a HMAC is calculated. For block n: hmac[n] = - HMAC_SHA512(hmac[n - 1] + seed) -@item For the first block (n = 1), hmac[0] is given by HMAC_SHA512(zeroes + seed), - where zeroes is a block of 64 zero bytes. -@end itemize - -The seed is as follows: - -@itemize -@item const char[13] "key expansion" -@item opaque responder_nonce[32] -@item opaque initiator_nonce[32] -@item opaque label[label_length] -@end itemize - -The expanded key is used as follows: - -@itemize -@item opaque responder_cipher_key[CIPHER_KEYSIZE] -@item opaque responder_digest_key[DIGEST_KEYSIZE] -@item opaque initiator_cipher_key[CIPHER_KEYSIZE] -@item opaque initiator_digest_key[DIGEST_KEYSIZE] -@end itemize - -Where initiator_cipher_key is the key used by session initiator to encrypt -messages sent to the responder. - -When using 521 bits EC keys, the AES-256-CTR cipher and HMAC-SHA-256 digest algorithm, -the sizes are as follows: - -@example -ECDH_SIZE: 67 (= ceil(521/8) + 1) -ECDSA_SIZE: 141 (= 2 * ceil(521/8) + 9) -CIPHER_KEYSIZE: 48 (= 256/8 + 128/8) -DIGEST_KEYSIZE: 32 (= 256/8) -@end example - -Note that the cipher key also includes the initial value for the counter. @c ================================================================== @node Encryption of network packets @@ -2943,11 +2385,11 @@ Note that the cipher key also includes the initial value for the counter. A data packet can only be sent if the encryption key is known to both parties, and the connection is activated. If the encryption key is not known, a request is sent to the destination using the meta connection -to retrieve it. +to retrieve it. The packet is stored in a queue while waiting for the +key to arrive. @cindex UDP -The UDP packets can be either encrypted with the legacy protocol or with SPTPS. -In case of the legacy protocol, the UDP packet containing the network packet from the VPN has the following layout: +The UDP packet containing the network packet from the VPN has the following layout: @example ... | IP header | UDP header | seqno | VPN packet | MAC | UDP trailer @@ -2957,38 +2399,12 @@ In case of the legacy protocol, the UDP packet containing the network packet fro Encrypted with symmetric cipher @end example - - - So, the entire VPN packet is encrypted using a symmetric cipher, including a 32 bits sequence number that is added in front of the actual VPN packet, to act as a unique IV for each packet and to prevent replay attacks. A message authentication code -is added to the UDP packet to prevent alteration of packets. -Tinc by default encrypts network packets using Blowfish with 128 bit keys in CBC mode -and uses 4 byte long message authentication codes to make sure -eavesdroppers cannot get and cannot change any information at all from the -packets they can intercept. The encryption algorithm and message authentication -algorithm can be changed in the configuration. The length of the message -authentication codes is also adjustable. The length of the key for the -encryption algorithm is always the default length used by OpenSSL. - -The SPTPS protocol is described in @ref{Simple Peer-to-Peer Security}. -For comparison, this is how SPTPS UDP packets look: - -@example -... | IP header | UDP header | seqno | type | VPN packet | MAC | UDP trailer - \__________________/\_____/ - | | - V +---> digest algorithm - Encrypted with symmetric cipher -@end example - -The difference is that the seqno is not encrypted, since the encryption cipher is used in CTR mode, -and therefore the seqno must be known before the packet can be decrypted. -Furthermore, the MAC is never truncated. -The SPTPS protocol always uses the AES-256-CTR cipher and HMAC-SHA-256 digest, -this cannot be changed. - +is added to the UDP packet to prevent alteration of packets. By default the +first 4 bytes of the digest are used for this, but this can be changed using +the MACLength configuration variable. @c ================================================================== @node Security issues @@ -2997,7 +2413,7 @@ this cannot be changed. In August 2000, we discovered the existence of a security hole in all versions of tinc up to and including 1.0pre2. This had to do with the way we exchanged keys. Since then, we have been working on a new authentication scheme to make -tinc as secure as possible. The current version uses the OpenSSL library and +tinc as secure as possible. The current version uses the LibreSSL or OpenSSL library and uses strong authentication with RSA keys. On the 29th of December 2001, Jerome Etienne posted a security analysis of tinc @@ -3011,15 +2427,13 @@ On the 15th of September 2003, Peter Gutmann posted a security analysis of tinc 1.0.1. He argues that the 32 bit sequence number used by tinc is not a good IV, that tinc's default length of 4 bytes for the MAC is too short, and he doesn't like tinc's use of RSA during authentication. We do not know of a security hole -in the legacy protocol of tinc, but it is not as strong as TLS or IPsec. - -This version of tinc comes with an improved protocol, called Simple Peer-to-Peer Security, -which aims to be as strong as TLS with one of the strongest cipher suites. +in this version of tinc, but tinc's security is not as strong as TLS or IPsec. +We will address these issues in tinc 2.0. Cryptography is a hard thing to get right. We cannot make any guarantees. Time, review and feedback are the only things that can prove the security of any cryptographic product. If you wish to review -tinc or give us feedback, you are stronly encouraged to do so. +tinc or give us feedback, you are strongly encouraged to do so. @c ================================================================== @@ -3029,6 +2443,7 @@ tinc or give us feedback, you are stronly encouraged to do so. @menu * Interface configuration:: * Routes:: +* Automatically starting tinc:: @end menu @c ================================================================== @@ -3045,7 +2460,7 @@ netmask should be such that it encompasses the entire VPN. For IPv4 addresses: -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} @item Linux @tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} @item Linux iproute2 @@ -3058,7 +2473,7 @@ For IPv4 addresses: @tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} @item Solaris @tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} -@item Darwin (MacOS/X) +@item Darwin (Mac OS X) @tab @code{ifconfig} @var{interface} @var{address} @code{netmask} @var{netmask} @item Windows @tab @code{netsh interface ip set address} @var{interface} @code{static} @var{address} @var{netmask} @@ -3066,7 +2481,7 @@ For IPv4 addresses: For IPv6 addresses: -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} @item Linux @tab @code{ifconfig} @var{interface} @code{add} @var{address}@code{/}@var{prefixlength} @item FreeBSD @@ -3079,25 +2494,18 @@ For IPv6 addresses: @tab @code{ifconfig} @var{interface} @code{inet6 plumb up} @item @tab @code{ifconfig} @var{interface} @code{inet6 addif} @var{address} @var{address} -@item Darwin (MacOS/X) +@item Darwin (Mac OS X) @tab @code{ifconfig} @var{interface} @code{inet6} @var{address} @code{prefixlen} @var{prefixlength} @item Windows @tab @code{netsh interface ipv6 add address} @var{interface} @code{static} @var{address}/@var{prefixlength} @end multitable -On some platforms, when running tinc in switch mode, the VPN interface must be set to tap mode with an ifconfig command: - -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} -@item OpenBSD -@tab @code{ifconfig} @var{interface} @code{link0} -@end multitable - On Linux, it is possible to create a persistent tun/tap interface which will continue to exist even if tinc quit, although this is normally not required. It can be useful to set up a tun/tap interface owned by a non-root user, so tinc can be started without needing any root privileges at all. -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} @item Linux @tab @code{ip tuntap add dev} @var{interface} @code{mode} @var{tun|tap} @code{user} @var{username} @end multitable @@ -3115,7 +2523,7 @@ support this. Adding routes to IPv4 subnets: -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} @item Linux @tab @code{route add -net} @var{network_address} @code{netmask} @var{netmask} @var{interface} @item Linux iproute2 @@ -3128,15 +2536,15 @@ Adding routes to IPv4 subnets: @tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} @item Solaris @tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} @code{-interface} -@item Darwin (MacOS/X) -@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @var{local_address} +@item Darwin (Mac OS X) +@tab @code{route add} @var{network_address}@code{/}@var{prefixlength} @code{-interface} @var{interface} @item Windows @tab @code{netsh routing ip add persistentroute} @var{network_address} @var{netmask} @var{interface} @var{local_address} @end multitable Adding routes to IPv6 subnets: -@multitable {Darwin (MacOS/X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} +@multitable {Darwin (Mac OS X)} {ifconfig route add -bla network address netmask netmask prefixlength interface} @item Linux @tab @code{route add -A inet6} @var{network_address}@code{/}@var{prefixlength} @var{interface} @item Linux iproute2 @@ -3149,12 +2557,72 @@ Adding routes to IPv6 subnets: @tab @code{route add -inet6} @var{network_address} @var{local_address} @code{-prefixlen} @var{prefixlength} @item Solaris @tab @code{route add -inet6} @var{network_address}@code{/}@var{prefixlength} @var{local_address} @code{-interface} -@item Darwin (MacOS/X) -@tab ? +@item Darwin (Mac OS X) +@tab @code{route add -inet6} @var{network_address}@code{/}@var{prefixlength} @code{-interface} @var{interface} @item Windows @tab @code{netsh interface ipv6 add route} @var{network address}/@var{prefixlength} @var{interface} @end multitable +@c ================================================================== +@node Automatically starting tinc +@section Automatically starting tinc + +@menu +* Linux:: +* Windows:: +* Other platforms:: +@end menu + +@c ================================================================== +@node Linux +@subsection Linux + +@cindex systemd +There are many Linux distributions, and historically, many of them had their +own way of starting programs at boot time. Today, a number of major Linux +distributions have chosen to use systemd as their init system. Tinc ships with +systemd service files that allow you to start and stop tinc using systemd. +There are two service files: @code{tinc.service} is used to globally enable or +disable all tinc daemons managed by systemd, and +@code{tinc@@@var{netname}.service} is used to enable or disable specific tinc +daemons. So if one has created a tinc network with netname @code{foo}, then +you have to run the following two commands to ensure it is started at boot +time: + +@example +systemctl enable tinc +systemctl enable tinc@@foo +@end example + +To start the tinc daemon immediately if it wasn't already running, use the +following command: + +@example +systemctl start tinc@@foo +@end example + +You can also use @samp{systemctl start tinc}, this will start all tinc daemons +that are enabled. You can stop and disable tinc networks in the same way. + +If your system is not using systemd, then you have to look up your +distribution's way of starting tinc at boot time. + +@c ================================================================== +@node Windows +@subsection Windows + +On Windows, if tinc is started without the @code{-D} or @code{--no-detach} +option, it will automatically register itself as a service that is started at +boot time. When tinc is stopped using the @code{-k} or @code{--kill}, it will +also automatically unregister itself. Once tinc is registered as a service, it +is also possible to stop and start tinc using the Windows Services Manager. + +@c ================================================================== +@node Other platforms +@subsection Other platforms + +On platforms other than the ones mentioned in the earlier sections, you have to +look up your platform's way of starting programs at boot time. @c ================================================================== @node About us @@ -3172,14 +2640,14 @@ Adding routes to IPv6 subnets: @section Contact information @cindex website -Tinc's website is at @url{http://www.tinc-vpn.org/}, +Tinc's website is at @url{https://www.tinc-vpn.org/}, this server is located in the Netherlands. @cindex IRC We have an IRC channel on the FreeNode and OFTC IRC networks. Connect to -@uref{http://www.freenode.net/, irc.freenode.net} +@uref{https://freenode.net/, irc.freenode.net} or -@uref{http://www.oftc.net/, irc.oftc.net} +@uref{https://www.oftc.net/, irc.oftc.net} and join channel #tinc. diff --git a/doc/tincd.8.in b/doc/tincd.8.in index 3c5886b..bdccf9d 100644 --- a/doc/tincd.8.in +++ b/doc/tincd.8.in @@ -1,4 +1,4 @@ -.Dd 2013-01-14 +.Dd 2014-05-11 .Dt TINCD 8 .\" Manual page created by: .\" Ivo Timmermans @@ -8,14 +8,17 @@ .Nd tinc VPN daemon .Sh SYNOPSIS .Nm -.Op Fl cdDKnoLRU +.Op Fl cdDkKnoLRU .Op Fl -config Ns = Ns Ar DIR .Op Fl -no-detach .Op Fl -debug Ns Op = Ns Ar LEVEL +.Op Fl -kill Ns Op = Ns Ar SIGNAL .Op Fl -net Ns = Ns Ar NETNAME +.Op Fl -generate-keys Ns Op = Ns Ar BITS .Op Fl -option Ns = Ns Ar [HOST.]KEY=VALUE .Op Fl -mlock .Op Fl -logfile Ns Op = Ns Ar FILE +.Op Fl -pidfile Ns = Ns Ar FILE .Op Fl -bypass-security .Op Fl -chroot .Op Fl -user Ns = Ns Ar USER @@ -51,6 +54,14 @@ If not mentioned otherwise, this will show log messages on the standard error ou Increase debug level or set it to .Ar LEVEL (see below). +.It Fl k, -kill Ns Op = Ns Ar SIGNAL +Attempt to kill a running +.Nm +(optionally with the specified +.Ar SIGNAL +instead of SIGTERM) and exit. +Under Windows (not Cygwin) the optional argument is ignored, +the service will always be stopped and removed. .It Fl n, -net Ns = Ns Ar NETNAME Connect to net .Ar NETNAME . @@ -62,6 +73,13 @@ for .Ar NETNAME is the same as not specifying any .Ar NETNAME . +.It Fl K, -generate-keys Ns Op = Ns Ar 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 Fl o, -option Ns = Ns Ar [HOST.]KEY=VALUE Without specifying a .Ar HOST , @@ -81,23 +99,18 @@ This option can be used more than once to specify multiple configuration variabl .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 +.It Fl -pidfile Ns = Ns Ar FILE +Write PID to .Ar FILE -is omitted, the default is -.Pa @localstatedir@/run/tinc. Ns Ar NETNAME Ns Pa .pid. +instead of +.Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid. +Under Windows this option will be ignored. .It Fl -bypass-security Disables encryption and authentication of the meta protocol. Only useful for debugging. @@ -105,12 +118,10 @@ Only useful for debugging. 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 @@ -140,6 +151,15 @@ If the .Fl -logfile option is used, this will also close and reopen the log file, useful when log rotation is used. +.It INT +Temporarily increases debug level to 5. +Send this signal again to revert to the original level. +.It USR1 +Dumps the connection list to syslog. +.It USR2 +Dumps virtual network device statistics, all known nodes, edges and subnets to syslog. +.It WINCH +Purges all information remembered about unreachable nodes. .El .Sh DEBUG LEVELS The tinc daemon can send a lot of messages to the syslog. @@ -170,7 +190,7 @@ This will log all network traffic over the virtual private network. 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 +.It Pa @runstatedir@/tinc. Ns Ar NETNAME Ns Pa .pid The PID of the currently running .Nm is stored in this file. @@ -186,9 +206,8 @@ 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 https://www.tinc-vpn.org/ , .Pa http://www.cabal.org/ . .Pp The full documentation for tinc is maintained as a Texinfo manual. diff --git a/doc/tincinclude.texi b/doc/tincinclude.texi new file mode 100644 index 0000000..ab2a41a --- /dev/null +++ b/doc/tincinclude.texi @@ -0,0 +1,5 @@ +@set VERSION 1.0.36 +@set PACKAGE tinc +@set sysconfdir /etc +@set localstatedir /var +@set runstatedir /run diff --git a/doc/tincinclude.texi.in b/doc/tincinclude.texi.in index da4adc5..01fee35 100644 --- a/doc/tincinclude.texi.in +++ b/doc/tincinclude.texi.in @@ -2,3 +2,4 @@ @set PACKAGE @PACKAGE@ @set sysconfdir @sysconfdir@ @set localstatedir @localstatedir@ +@set runstatedir @runstatedir@ diff --git a/gui/Makefile.am b/gui/Makefile.am deleted file mode 100644 index 4f2c7fe..0000000 --- a/gui/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -dist_bin_SCRIPTS = tinc-gui - -extra_DIST = README.gui diff --git a/gui/tinc-gui b/gui/tinc-gui deleted file mode 100755 index 2b4f903..0000000 --- a/gui/tinc-gui +++ /dev/null @@ -1,609 +0,0 @@ -#!/usr/bin/python - -# tinc-gui -- GUI for controlling a running tincd -# Copyright (C) 2009-2012 Guus Sliepen -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -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."); - s = socket.socket(socket.AF_INET, 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': - try: - reg = _winreg.ConnectRegistry(None, HKEY_LOCAL_MACHINE) - key = _winreg.OpenKey(reg, "SOFTWARE\\tinc") - 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() diff --git a/install-sh b/install-sh index 377bb86..20d8b2e 100755 --- a/install-sh +++ b/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2011-11-20.07; # UTC +scriptversion=2018-03-11.20; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -41,19 +41,15 @@ scriptversion=2011-11-20.07; # UTC # This script is compatible with the BSD install script, but was written # from scratch. +tab=' ' nl=' ' -IFS=" "" $nl" +IFS=" $tab$nl" -# set DOITPROG to echo to test this script +# Set DOITPROG to "echo" to test this script. -# Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi +doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. @@ -68,17 +64,6 @@ mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - posix_mkdir= # Desired mode of installed file. @@ -97,7 +82,7 @@ dir_arg= dst_arg= copy_on_change=false -no_target_directory= +is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE @@ -137,46 +122,57 @@ while test $# -ne 0; do -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift;; + shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift;; + shift;; -s) stripcmd=$stripprog;; - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; - -T) no_target_directory=true;; + -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; - --) shift - break;; + --) shift + break;; - -*) echo "$0: invalid option: $1" >&2 - exit 1;; + -*) echo "$0: invalid option: $1" >&2 + exit 1;; *) break;; esac shift done +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. @@ -207,6 +203,15 @@ if test $# -eq 0; then exit 0 fi +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 @@ -223,16 +228,16 @@ if test -z "$dir_arg"; then *[0-7]) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw='% 200' + u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw=,u+rw + u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac @@ -266,122 +271,113 @@ do fi dst=$dst_arg - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. + # If destination is a directory, append the input filename. if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi dstdir=$dst - dst=$dstdir/`basename "$src"` + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac dstdir_status=0 else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - + dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # Note that $RANDOM variable is not portable (e.g. dash); Use it + # here however when possible just to lower collision chance. + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # Because "mkdir -p" follows existing symlinks and we likely work + # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directory is successfully created first before we actually test + # 'mkdir -p' feature. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; esac if $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else @@ -391,53 +387,51 @@ do # directory the slow way, step by step, checking for races as we go. case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; esac - eval "$initialize_posix_glob" - oIFS=$IFS IFS=/ - $posix_glob set -f + set -f set fnord $dstdir shift - $posix_glob set +f + set +f IFS=$oIFS prefixes= for d do - test X"$d" = X && continue + test X"$d" = X && continue - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ done if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi fi fi @@ -450,14 +444,25 @@ do else # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + (umask $cp_umask && + { test -z "$stripcmd" || { + # Create $dsttmp read-write so that cp doesn't create it read-only, + # which would cause strip to fail. + if test -z "$doit"; then + : >"$dsttmp" # No need to fork-exec 'touch'. + else + $doit touch "$dsttmp" + fi + } + } && + $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # @@ -472,15 +477,12 @@ do # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - + set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then @@ -493,24 +495,24 @@ do # to itself, or perhaps because mv is so ancient that it does not # support -f. { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 @@ -519,9 +521,9 @@ do done # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/m4/Makefile.am b/m4/Makefile.am deleted file mode 100644 index 0f58aef..0000000 --- a/m4/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -## Process this file with automake to produce Makefile.in -*-Makefile-*- - -EXTRA_DIST = README *.m4 - diff --git a/m4/Makefile.in b/m4/Makefile.in deleted file mode 100644 index fc5af2d..0000000 --- a/m4/Makefile.in +++ /dev/null @@ -1,403 +0,0 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = m4 -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ - $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ - $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ - $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CURSES_LIBS = @CURSES_LIBS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -VERSION = @VERSION@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -EXTRA_DIST = README *.m4 -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu m4/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -tags TAGS: - -ctags CTAGS: - -cscope cscopelist: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ - ctags-am distclean distclean-generic distdir dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-pdf install-pdf-am \ - install-ps install-ps-am install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ - pdf-am ps ps-am tags-am uninstall uninstall-am - - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/m4/README b/m4/README deleted file mode 100644 index df032df..0000000 --- a/m4/README +++ /dev/null @@ -1,8 +0,0 @@ -These files are used by a program called aclocal (part of the GNU automake -package). aclocal uses these files to create aclocal.m4 which is in turn -used by autoconf to create the configure script at the the top level in -this distribution. - -The Makefile.am file in this directory is automatically generated -from the template file, Makefile.am.in. The generation will fail -if you don't have all the right tools. diff --git a/m4/attribute.m4 b/m4/attribute.m4 index 6a8f555..9d673e9 100644 --- a/m4/attribute.m4 +++ b/m4/attribute.m4 @@ -9,8 +9,8 @@ AC_DEFUN([tinc_ATTRIBUTE], CFLAGS="$CFLAGS -Wall -Werror" AC_COMPILE_IFELSE( [AC_LANG_SOURCE( - [void test(void) __attribute__ (($1)); - void test(void) { return; } + [void *test(void) __attribute__ (($1)); + void *test(void) { return (void *)0; } ], )], [tinc_cv_attribute_$1=yes], diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4 new file mode 100644 index 0000000..1d38b76 --- /dev/null +++ b/m4/ax_append_flag.m4 @@ -0,0 +1,69 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) +# +# DESCRIPTION +# +# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space +# added in between. +# +# If FLAGS-VARIABLE is not specified, the current language's flags (e.g. +# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains +# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly +# FLAG. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_APPEND_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl +AS_VAR_SET_IF(FLAGS, + [case " AS_VAR_GET(FLAGS) " in + *" $1 "*) + AC_RUN_LOG([: FLAGS already contains $1]) + ;; + *) + AC_RUN_LOG([: FLAGS="$FLAGS $1"]) + AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) + ;; + esac], + [AS_VAR_SET(FLAGS,["$1"])]) +AS_VAR_POPDEF([FLAGS])dnl +])dnl AX_APPEND_FLAG diff --git a/m4/ax_cflags_warn_all.m4 b/m4/ax_cflags_warn_all.m4 new file mode 100644 index 0000000..1f07799 --- /dev/null +++ b/m4/ax_cflags_warn_all.m4 @@ -0,0 +1,122 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] +# AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] +# AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])] +# +# DESCRIPTION +# +# Try to find a compiler option that enables most reasonable warnings. +# +# For the GNU compiler it will be -Wall (and -ansi -pedantic) The result +# is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default. +# +# Currently this macro knows about the GCC, Solaris, Digital Unix, AIX, +# HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and +# Intel compilers. For a given compiler, the Fortran flags are much more +# experimental than their C equivalents. +# +# - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS +# - $2 add-value-if-not-found : nothing +# - $3 action-if-found : add value to shellvariable +# - $4 action-if-not-found : nothing +# +# NOTE: These macros depend on AX_APPEND_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2010 Rhys Ulerich +# +# 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 15 + +AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl +AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl +AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl +AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings], +VAR,[VAR="no, unknown" +ac_save_[]FLAGS="$[]FLAGS" +for ac_arg dnl +in "-warn all % -warn all" dnl Intel + "-pedantic % -Wall" dnl GCC + "-xstrconst % -v" dnl Solaris C + "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix + "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX + "-ansi -ansiE % -fullwarn" dnl IRIX + "+ESlit % +w1" dnl HP-UX C + "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10) + "-h conform % -h msglevel 2" dnl Cray C (Unicos) + # +do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) +done +FLAGS="$ac_save_[]FLAGS" +]) +AS_VAR_POPDEF([FLAGS])dnl +AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) +case ".$VAR" in + .ok|.ok,*) m4_ifvaln($3,$3) ;; + .|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;; + *) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;; +esac +AS_VAR_POPDEF([VAR])dnl +])dnl AX_FLAGS_WARN_ALL +dnl implementation tactics: +dnl the for-argument contains a list of options. The first part of +dnl these does only exist to detect the compiler - usually it is +dnl a global option to enable -ansi or -extrawarnings. All other +dnl compilers will fail about it. That was needed since a lot of +dnl compilers will give false positives for some option-syntax +dnl like -Woption or -Xoption as they think of it is a pass-through +dnl to later compile stages or something. The "%" is used as a +dnl delimiter. A non-option comment can be given after "%%" marks +dnl which will be shown but not added to the respective C/CXXFLAGS. + +AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl +AC_LANG_PUSH([C]) +AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) +AC_LANG_POP([C]) +]) + +AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl +AC_LANG_PUSH([C++]) +AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) +AC_LANG_POP([C++]) +]) + +AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl +AC_LANG_PUSH([Fortran]) +AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4]) +AC_LANG_POP([Fortran]) +]) diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 0000000..c3a8d69 --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,72 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4 new file mode 100644 index 0000000..e2d0d36 --- /dev/null +++ b/m4/ax_check_link_flag.m4 @@ -0,0 +1,71 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the linker or gives an error. +# (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the linker's default flags +# when the check is done. The check is thus made with the flags: "LDFLAGS +# EXTRA-FLAGS FLAG". This can for example be used to force the linker to +# issue an error when a bad flag is given. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 2 + +AC_DEFUN([AX_CHECK_LINK_FLAG], +[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ + ax_check_save_flags=$LDFLAGS + LDFLAGS="$LDFLAGS $4 $1" + AC_LINK_IFELSE([AC_LANG_PROGRAM()], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + LDFLAGS=$ax_check_save_flags]) +AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_LINK_FLAGS diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4 new file mode 100644 index 0000000..cae1111 --- /dev/null +++ b/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/m4/curses.m4 b/m4/curses.m4 deleted file mode 100644 index 50a90a5..0000000 --- a/m4/curses.m4 +++ /dev/null @@ -1,41 +0,0 @@ -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(curses, initscr, - [CURSES_LIBS="-lcurses"], - [AC_MSG_ERROR("curses libraries not found.")] - ) - ]) - - AC_SUBST(CURSES_LIBS) -]) diff --git a/m4/openssl.m4 b/m4/openssl.m4 index 922e468..895c31a 100644 --- a/m4/openssl.m4 +++ b/m4/openssl.m4 @@ -1,4 +1,4 @@ -dnl Check to find the OpenSSL headers/libraries +dnl Check to find the LibreSSL/OpenSSL headers/libraries AC_DEFUN([tinc_OPENSSL], [ @@ -10,47 +10,49 @@ AC_DEFUN([tinc_OPENSSL], [], [AC_CHECK_LIB(dl, dlopen, [LIBS="$LIBS -ldl"], - [AC_MSG_ERROR([OpenSSL depends on libdl.]); break] + [AC_MSG_ERROR([LibreSSL/OpenSSL depends on libdl.]); break] )] ) ;; esac AC_ARG_WITH(openssl, - AS_HELP_STRING([--with-openssl=DIR], [OpenSSL base directory, or:]), + AS_HELP_STRING([--with-openssl=DIR], [LibreSSL/OpenSSL base directory, or:]), [openssl="$withval" CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib"] ) AC_ARG_WITH(openssl-include, - AS_HELP_STRING([--with-openssl-include=DIR], [OpenSSL headers directory (without trailing /openssl)]), + AS_HELP_STRING([--with-openssl-include=DIR], [LibreSSL/OpenSSL headers directory (without trailing /openssl)]), [openssl_include="$withval" CPPFLAGS="$CPPFLAGS -I$withval"] ) AC_ARG_WITH(openssl-lib, - AS_HELP_STRING([--with-openssl-lib=DIR], [OpenSSL library directory]), + AS_HELP_STRING([--with-openssl-lib=DIR], [LibreSSL/OpenSSL library directory]), [openssl_lib="$withval" LDFLAGS="$LDFLAGS -L$withval"] ) - AC_CHECK_HEADERS([openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h openssl/ecdh.h openssl/ec.h], + AC_CHECK_HEADERS(openssl/evp.h openssl/rsa.h openssl/rand.h openssl/err.h openssl/sha.h openssl/pem.h openssl/engine.h, [], - [AC_MSG_ERROR([OpenSSL header files not found.]); break] + [AC_MSG_ERROR([LibreSSL/OpenSSL header files not found.]); break] ) AC_CHECK_LIB(crypto, EVP_EncryptInit_ex, [LIBS="-lcrypto $LIBS"], - [AC_MSG_ERROR([OpenSSL libraries not found.])] + [AC_MSG_ERROR([LibreSSL/OpenSSL libraries not found.])] ) - AC_CHECK_FUNCS([RAND_pseudo_bytes EVP_EncryptInit_ex ECDH_compute_key ECDSA_verify], , - [AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break], + AC_CHECK_FUNCS([RAND_bytes EVP_EncryptInit_ex EVP_CIPHER_CTX_new], , + [AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break], ) - AC_CHECK_DECL([OpenSSL_add_all_algorithms], , - [AC_MSG_ERROR([Missing OpenSSL functionality, make sure you have installed the latest version.]); break], + AC_CHECK_DECLS([OpenSSL_add_all_algorithms, EVP_aes_256_cfb], , + [AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break], [#include ] ) + + AC_CHECK_FUNCS([BN_GENCB_new RSA_set0_key], , , [#include ]) ]) diff --git a/m4/readline.m4 b/m4/readline.m4 deleted file mode 100644 index f29e692..0000000 --- a/m4/readline.m4 +++ /dev/null @@ -1,42 +0,0 @@ -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) -]) diff --git a/missing b/missing index cdea514..8d0eaad 100755 --- a/missing +++ b/missing @@ -1,9 +1,9 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2012-06-26.16; # UTC +scriptversion=2018-03-07.03; # UTC -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ scriptversion=2012-06-26.16; # UTC # 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 . +# along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -101,9 +101,9 @@ else exit $st fi -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software +perl_URL=https://www.perl.org/ +flex_URL=https://github.com/westes/flex +gnu_software_URL=https://www.gnu.org/software program_details () { @@ -160,7 +160,7 @@ give_advice () ;; autom4te*) echo "You might have modified some maintainer files that require" - echo "the 'automa4te' program to be rebuilt." + echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) @@ -207,9 +207,9 @@ give_advice "$1" | sed -e '1s/^/WARNING: /' \ exit $st # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/src/Makefile.am b/src/Makefile.am index 27d2330..7b3dd97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,94 +1,56 @@ ## Produce this file with automake to get Makefile.in -sbin_PROGRAMS = tincd tinc sptps_test - -EXTRA_DIST = linux bsd solaris cygwin mingw openssl gcrypt - -DEFAULT_INCLUDES = +sbin_PROGRAMS = tincd tincd_SOURCES = \ - buffer.c buffer.h \ - cipher.h \ + have.h \ + system.h \ + avl_tree.c avl_tree.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 \ + pidfile.c pidfile.h \ process.c process.h \ protocol.c protocol.h \ protocol_auth.c \ protocol_edge.c \ - protocol_key.c \ protocol_misc.c \ + protocol_key.c \ protocol_subnet.c \ + proxy.c proxy.h \ raw_socket_device.c \ route.c route.h \ - rsa.h \ - rsagen.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 -tinc_SOURCES = \ - dropin.c dropin.h \ +if !GETOPT +tincd_SOURCES += \ 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 \ - sptps.c sptps.h \ - subnet_parse.c subnet.h \ - tincctl.c tincctl.h \ - top.c top.h \ - utils.c utils.h + getopt1.c +endif -sptps_test_SOURCES = \ - logger.c logger.h \ - sptps.c sptps.h \ - sptps_test.c \ - utils.c utils.h - -## Conditionally compile device drivers - if LINUX tincd_SOURCES += linux/device.c endif @@ -96,7 +58,7 @@ endif if BSD tincd_SOURCES += bsd/device.c if TUNEMU -tincd_SOURCES += bsd/tunemu.c +tincd_SOURCES += bsd/tunemu.c bsd/tunemu.h endif endif @@ -105,7 +67,7 @@ tincd_SOURCES += solaris/device.c endif if MINGW -tincd_SOURCES += mingw/device.c +tincd_SOURCES += mingw/device.c mingw/common.h endif if CYGWIN @@ -120,71 +82,8 @@ if VDE tincd_SOURCES += vde_device.c endif -if OPENSSL -tincd_SOURCES += \ - openssl/cipher.c \ - openssl/crypto.c \ - openssl/digest.c \ - openssl/ecdh.c \ - openssl/ecdsa.c \ - openssl/prf.c \ - openssl/rsa.c -tinc_SOURCES += \ - openssl/cipher.c \ - openssl/crypto.c \ - openssl/digest.c \ - openssl/ecdh.c \ - openssl/ecdsa.c \ - openssl/ecdsagen.c \ - openssl/prf.c \ - openssl/rsa.c \ - openssl/rsagen.c -sptps_test_SOURCES += \ - openssl/cipher.c \ - openssl/crypto.c \ - openssl/digest.c \ - openssl/ecdh.c \ - openssl/ecdsa.c \ - openssl/prf.c -endif - -if GCRYPT -tincd_SOURCES += \ - gcrypt/cipher.c \ - gcrypt/crypto.c \ - gcrypt/digest.c \ - gcrypt/ecdh.c \ - gcrypt/ecdsa.c \ - gcrypt/prf.c \ - gcrypt/rsa.c -tinc_SOURCES += \ - gcrypt/cipher.c \ - gcrypt/crypto.c \ - gcrypt/digest.c \ - 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/ecdh.c \ - gcrypt/ecdsa.c \ - gcrypt/prf.c -endif - -tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS) - -LIBS = @LIBS@ @LIBGCRYPT_LIBS@ - if TUNEMU LIBS += -lpcap endif -AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" - -dist-hook: - rm -f `find . -type l` +AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/ diff --git a/src/Makefile.in b/src/Makefile.in index ab5daa4..5d52921 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -78,192 +88,80 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT) -@LINUX_TRUE@am__append_1 = linux/device.c -@BSD_TRUE@am__append_2 = bsd/device.c -@BSD_TRUE@@TUNEMU_TRUE@am__append_3 = bsd/tunemu.c -@SOLARIS_TRUE@am__append_4 = solaris/device.c -@MINGW_TRUE@am__append_5 = mingw/device.c -@CYGWIN_TRUE@am__append_6 = cygwin/device.c -@UML_TRUE@am__append_7 = uml_device.c -@VDE_TRUE@am__append_8 = vde_device.c -@OPENSSL_TRUE@am__append_9 = \ -@OPENSSL_TRUE@ openssl/cipher.c \ -@OPENSSL_TRUE@ openssl/crypto.c \ -@OPENSSL_TRUE@ openssl/digest.c \ -@OPENSSL_TRUE@ openssl/ecdh.c \ -@OPENSSL_TRUE@ openssl/ecdsa.c \ -@OPENSSL_TRUE@ openssl/prf.c \ -@OPENSSL_TRUE@ openssl/rsa.c +sbin_PROGRAMS = tincd$(EXEEXT) +@GETOPT_FALSE@am__append_1 = \ +@GETOPT_FALSE@ getopt.c getopt.h \ +@GETOPT_FALSE@ getopt1.c -@OPENSSL_TRUE@am__append_10 = \ -@OPENSSL_TRUE@ openssl/cipher.c \ -@OPENSSL_TRUE@ openssl/crypto.c \ -@OPENSSL_TRUE@ openssl/digest.c \ -@OPENSSL_TRUE@ openssl/ecdh.c \ -@OPENSSL_TRUE@ openssl/ecdsa.c \ -@OPENSSL_TRUE@ openssl/ecdsagen.c \ -@OPENSSL_TRUE@ openssl/prf.c \ -@OPENSSL_TRUE@ openssl/rsa.c \ -@OPENSSL_TRUE@ openssl/rsagen.c - -@OPENSSL_TRUE@am__append_11 = \ -@OPENSSL_TRUE@ openssl/cipher.c \ -@OPENSSL_TRUE@ openssl/crypto.c \ -@OPENSSL_TRUE@ openssl/digest.c \ -@OPENSSL_TRUE@ openssl/ecdh.c \ -@OPENSSL_TRUE@ openssl/ecdsa.c \ -@OPENSSL_TRUE@ openssl/prf.c - -@GCRYPT_TRUE@am__append_12 = \ -@GCRYPT_TRUE@ gcrypt/cipher.c \ -@GCRYPT_TRUE@ gcrypt/crypto.c \ -@GCRYPT_TRUE@ gcrypt/digest.c \ -@GCRYPT_TRUE@ gcrypt/ecdh.c \ -@GCRYPT_TRUE@ gcrypt/ecdsa.c \ -@GCRYPT_TRUE@ gcrypt/prf.c \ -@GCRYPT_TRUE@ gcrypt/rsa.c - -@GCRYPT_TRUE@am__append_13 = \ -@GCRYPT_TRUE@ gcrypt/cipher.c \ -@GCRYPT_TRUE@ gcrypt/crypto.c \ -@GCRYPT_TRUE@ gcrypt/digest.c \ -@GCRYPT_TRUE@ gcrypt/ecdh.c \ -@GCRYPT_TRUE@ gcrypt/ecdsa.c \ -@GCRYPT_TRUE@ gcrypt/ecdsagen.c \ -@GCRYPT_TRUE@ gcrypt/prf.c \ -@GCRYPT_TRUE@ gcrypt/rsa.c \ -@GCRYPT_TRUE@ gcrypt/rsagen.c - -@GCRYPT_TRUE@am__append_14 = \ -@GCRYPT_TRUE@ gcrypt/cipher.c \ -@GCRYPT_TRUE@ gcrypt/crypto.c \ -@GCRYPT_TRUE@ gcrypt/digest.c \ -@GCRYPT_TRUE@ gcrypt/ecdh.c \ -@GCRYPT_TRUE@ gcrypt/ecdsa.c \ -@GCRYPT_TRUE@ gcrypt/prf.c - -@TUNEMU_TRUE@am__append_15 = -lpcap +@LINUX_TRUE@am__append_2 = linux/device.c +@BSD_TRUE@am__append_3 = bsd/device.c +@BSD_TRUE@@TUNEMU_TRUE@am__append_4 = bsd/tunemu.c bsd/tunemu.h +@SOLARIS_TRUE@am__append_5 = solaris/device.c +@MINGW_TRUE@am__append_6 = mingw/device.c mingw/common.h +@CYGWIN_TRUE@am__append_7 = cygwin/device.c +@UML_TRUE@am__append_8 = uml_device.c +@VDE_TRUE@am__append_9 = vde_device.c +@TUNEMU_TRUE@am__append_10 = -lpcap subdir = src -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ - $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ - $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ - $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ax_append_flag.m4 \ + $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ + $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) -am__sptps_test_SOURCES_DIST = logger.c logger.h sptps.c sptps.h \ - sptps_test.c utils.c utils.h openssl/cipher.c openssl/crypto.c \ - openssl/digest.c openssl/ecdh.c openssl/ecdsa.c openssl/prf.c \ - gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c gcrypt/ecdh.c \ - gcrypt/ecdsa.c gcrypt/prf.c -am__dirstamp = $(am__leading_dot)dirstamp -@OPENSSL_TRUE@am__objects_1 = openssl/cipher.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT) -@GCRYPT_TRUE@am__objects_2 = gcrypt/cipher.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT) -am_sptps_test_OBJECTS = logger.$(OBJEXT) sptps.$(OBJEXT) \ - sptps_test.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \ - $(am__objects_2) -sptps_test_OBJECTS = $(am_sptps_test_OBJECTS) -sptps_test_LDADD = $(LDADD) -am__tinc_SOURCES_DIST = 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 sptps.c sptps.h subnet_parse.c \ - subnet.h tincctl.c tincctl.h top.c top.h utils.c utils.h \ - openssl/cipher.c openssl/crypto.c openssl/digest.c \ - openssl/ecdh.c openssl/ecdsa.c openssl/ecdsagen.c \ - openssl/prf.c openssl/rsa.c openssl/rsagen.c gcrypt/cipher.c \ - gcrypt/crypto.c gcrypt/digest.c gcrypt/ecdh.c gcrypt/ecdsa.c \ - gcrypt/ecdsagen.c gcrypt/prf.c gcrypt/rsa.c gcrypt/rsagen.c -@OPENSSL_TRUE@am__objects_3 = openssl/cipher.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/ecdsagen.$(OBJEXT) openssl/prf.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/rsa.$(OBJEXT) openssl/rsagen.$(OBJEXT) -@GCRYPT_TRUE@am__objects_4 = gcrypt/cipher.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/ecdsagen.$(OBJEXT) gcrypt/prf.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/rsa.$(OBJEXT) gcrypt/rsagen.$(OBJEXT) -am_tinc_OBJECTS = dropin.$(OBJEXT) getopt.$(OBJEXT) getopt1.$(OBJEXT) \ - info.$(OBJEXT) invitation.$(OBJEXT) list.$(OBJEXT) \ - names.$(OBJEXT) netutl.$(OBJEXT) sptps.$(OBJEXT) \ - subnet_parse.$(OBJEXT) tincctl.$(OBJEXT) top.$(OBJEXT) \ - utils.$(OBJEXT) $(am__objects_3) $(am__objects_4) -tinc_OBJECTS = $(am_tinc_OBJECTS) -am__DEPENDENCIES_1 = -tinc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am__tincd_SOURCES_DIST = 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 \ +am__tincd_SOURCES_DIST = have.h system.h avl_tree.c avl_tree.h conf.c \ + conf.h connection.c connection.h device.h dropin.c dropin.h \ + dummy_device.c edge.c edge.h ethernet.h event.c event.h \ + fake-getaddrinfo.c fake-getaddrinfo.h fake-getnameinfo.c \ + fake-getnameinfo.h graph.c graph.h ipv4.h ipv6.h list.c list.h \ + logger.c logger.h meta.c meta.h multicast_device.c 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 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 linux/device.c bsd/device.c bsd/tunemu.c \ - solaris/device.c mingw/device.c cygwin/device.c uml_device.c \ - vde_device.c openssl/cipher.c openssl/crypto.c \ - openssl/digest.c openssl/ecdh.c openssl/ecdsa.c openssl/prf.c \ - openssl/rsa.c gcrypt/cipher.c gcrypt/crypto.c gcrypt/digest.c \ - gcrypt/ecdh.c gcrypt/ecdsa.c gcrypt/prf.c gcrypt/rsa.c -@LINUX_TRUE@am__objects_5 = linux/device.$(OBJEXT) -@BSD_TRUE@am__objects_6 = bsd/device.$(OBJEXT) -@BSD_TRUE@@TUNEMU_TRUE@am__objects_7 = bsd/tunemu.$(OBJEXT) -@SOLARIS_TRUE@am__objects_8 = solaris/device.$(OBJEXT) -@MINGW_TRUE@am__objects_9 = mingw/device.$(OBJEXT) -@CYGWIN_TRUE@am__objects_10 = cygwin/device.$(OBJEXT) -@UML_TRUE@am__objects_11 = uml_device.$(OBJEXT) -@VDE_TRUE@am__objects_12 = vde_device.$(OBJEXT) -@OPENSSL_TRUE@am__objects_13 = openssl/cipher.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/crypto.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/digest.$(OBJEXT) openssl/ecdh.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/ecdsa.$(OBJEXT) openssl/prf.$(OBJEXT) \ -@OPENSSL_TRUE@ openssl/rsa.$(OBJEXT) -@GCRYPT_TRUE@am__objects_14 = gcrypt/cipher.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/crypto.$(OBJEXT) gcrypt/digest.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/ecdh.$(OBJEXT) gcrypt/ecdsa.$(OBJEXT) \ -@GCRYPT_TRUE@ gcrypt/prf.$(OBJEXT) gcrypt/rsa.$(OBJEXT) -am_tincd_OBJECTS = buffer.$(OBJEXT) conf.$(OBJEXT) \ - connection.$(OBJEXT) control.$(OBJEXT) dropin.$(OBJEXT) \ - dummy_device.$(OBJEXT) edge.$(OBJEXT) event.$(OBJEXT) \ - fake-getaddrinfo.$(OBJEXT) fake-getnameinfo.$(OBJEXT) \ - getopt.$(OBJEXT) getopt1.$(OBJEXT) graph.$(OBJEXT) \ - hash.$(OBJEXT) list.$(OBJEXT) logger.$(OBJEXT) meta.$(OBJEXT) \ - multicast_device.$(OBJEXT) names.$(OBJEXT) net.$(OBJEXT) \ - net_packet.$(OBJEXT) net_setup.$(OBJEXT) net_socket.$(OBJEXT) \ - netutl.$(OBJEXT) node.$(OBJEXT) process.$(OBJEXT) \ - protocol.$(OBJEXT) protocol_auth.$(OBJEXT) \ - protocol_edge.$(OBJEXT) protocol_key.$(OBJEXT) \ - protocol_misc.$(OBJEXT) protocol_subnet.$(OBJEXT) \ - raw_socket_device.$(OBJEXT) route.$(OBJEXT) \ - splay_tree.$(OBJEXT) sptps.$(OBJEXT) subnet.$(OBJEXT) \ - subnet_parse.$(OBJEXT) tincd.$(OBJEXT) utils.$(OBJEXT) \ + node.h pidfile.c pidfile.h process.c process.h protocol.c \ + protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \ + protocol_key.c protocol_subnet.c proxy.c proxy.h \ + raw_socket_device.c route.c route.h subnet.c subnet.h tincd.c \ + utils.c utils.h xalloc.h getopt.c getopt.h getopt1.c \ + linux/device.c bsd/device.c bsd/tunemu.c bsd/tunemu.h \ + solaris/device.c mingw/device.c mingw/common.h cygwin/device.c \ + uml_device.c vde_device.c +@GETOPT_FALSE@am__objects_1 = getopt.$(OBJEXT) getopt1.$(OBJEXT) +am__dirstamp = $(am__leading_dot)dirstamp +@LINUX_TRUE@am__objects_2 = linux/device.$(OBJEXT) +@BSD_TRUE@am__objects_3 = bsd/device.$(OBJEXT) +@BSD_TRUE@@TUNEMU_TRUE@am__objects_4 = bsd/tunemu.$(OBJEXT) +@SOLARIS_TRUE@am__objects_5 = solaris/device.$(OBJEXT) +@MINGW_TRUE@am__objects_6 = mingw/device.$(OBJEXT) +@CYGWIN_TRUE@am__objects_7 = cygwin/device.$(OBJEXT) +@UML_TRUE@am__objects_8 = uml_device.$(OBJEXT) +@VDE_TRUE@am__objects_9 = vde_device.$(OBJEXT) +am_tincd_OBJECTS = avl_tree.$(OBJEXT) conf.$(OBJEXT) \ + connection.$(OBJEXT) dropin.$(OBJEXT) dummy_device.$(OBJEXT) \ + edge.$(OBJEXT) event.$(OBJEXT) fake-getaddrinfo.$(OBJEXT) \ + fake-getnameinfo.$(OBJEXT) graph.$(OBJEXT) list.$(OBJEXT) \ + logger.$(OBJEXT) meta.$(OBJEXT) multicast_device.$(OBJEXT) \ + net.$(OBJEXT) net_packet.$(OBJEXT) net_setup.$(OBJEXT) \ + net_socket.$(OBJEXT) netutl.$(OBJEXT) node.$(OBJEXT) \ + pidfile.$(OBJEXT) process.$(OBJEXT) protocol.$(OBJEXT) \ + protocol_auth.$(OBJEXT) protocol_edge.$(OBJEXT) \ + protocol_misc.$(OBJEXT) protocol_key.$(OBJEXT) \ + protocol_subnet.$(OBJEXT) proxy.$(OBJEXT) \ + raw_socket_device.$(OBJEXT) route.$(OBJEXT) subnet.$(OBJEXT) \ + tincd.$(OBJEXT) utils.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ - $(am__objects_8) $(am__objects_9) $(am__objects_10) \ - $(am__objects_11) $(am__objects_12) $(am__objects_13) \ - $(am__objects_14) + $(am__objects_8) $(am__objects_9) tincd_OBJECTS = $(am_tincd_OBJECTS) tincd_LDADD = $(LDADD) AM_V_P = $(am__v_P_@AM_V@) @@ -278,8 +176,31 @@ AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = +DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/avl_tree.Po ./$(DEPDIR)/conf.Po \ + ./$(DEPDIR)/connection.Po ./$(DEPDIR)/dropin.Po \ + ./$(DEPDIR)/dummy_device.Po ./$(DEPDIR)/edge.Po \ + ./$(DEPDIR)/event.Po ./$(DEPDIR)/fake-getaddrinfo.Po \ + ./$(DEPDIR)/fake-getnameinfo.Po ./$(DEPDIR)/getopt.Po \ + ./$(DEPDIR)/getopt1.Po ./$(DEPDIR)/graph.Po \ + ./$(DEPDIR)/list.Po ./$(DEPDIR)/logger.Po ./$(DEPDIR)/meta.Po \ + ./$(DEPDIR)/multicast_device.Po ./$(DEPDIR)/net.Po \ + ./$(DEPDIR)/net_packet.Po ./$(DEPDIR)/net_setup.Po \ + ./$(DEPDIR)/net_socket.Po ./$(DEPDIR)/netutl.Po \ + ./$(DEPDIR)/node.Po ./$(DEPDIR)/pidfile.Po \ + ./$(DEPDIR)/process.Po ./$(DEPDIR)/protocol.Po \ + ./$(DEPDIR)/protocol_auth.Po ./$(DEPDIR)/protocol_edge.Po \ + ./$(DEPDIR)/protocol_key.Po ./$(DEPDIR)/protocol_misc.Po \ + ./$(DEPDIR)/protocol_subnet.Po ./$(DEPDIR)/proxy.Po \ + ./$(DEPDIR)/raw_socket_device.Po ./$(DEPDIR)/route.Po \ + ./$(DEPDIR)/subnet.Po ./$(DEPDIR)/tincd.Po \ + ./$(DEPDIR)/uml_device.Po ./$(DEPDIR)/utils.Po \ + ./$(DEPDIR)/vde_device.Po bsd/$(DEPDIR)/device.Po \ + bsd/$(DEPDIR)/tunemu.Po cygwin/$(DEPDIR)/device.Po \ + linux/$(DEPDIR)/device.Po mingw/$(DEPDIR)/device.Po \ + solaris/$(DEPDIR)/device.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -293,9 +214,8 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(sptps_test_SOURCES) $(tinc_SOURCES) $(tincd_SOURCES) -DIST_SOURCES = $(am__sptps_test_SOURCES_DIST) $(am__tinc_SOURCES_DIST) \ - $(am__tincd_SOURCES_DIST) +SOURCES = $(tincd_SOURCES) +DIST_SOURCES = $(am__tincd_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -320,6 +240,7 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -333,7 +254,6 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CURSES_LIBS = @CURSES_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ @@ -349,12 +269,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ @LIBGCRYPT_LIBS@ $(am__append_15) -LN_S = @LN_S@ +LIBS = @LIBS@ $(am__append_10) LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ @@ -367,8 +283,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ @@ -415,44 +329,32 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +systemd_path = @systemd_path@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = linux bsd solaris cygwin mingw openssl gcrypt -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 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 $(am__append_1) $(am__append_2) $(am__append_3) \ - $(am__append_4) $(am__append_5) $(am__append_6) \ - $(am__append_7) $(am__append_8) $(am__append_9) \ - $(am__append_12) -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 sptps.c sptps.h subnet_parse.c subnet.h \ - tincctl.c tincctl.h top.c top.h utils.c utils.h \ - $(am__append_10) $(am__append_13) -sptps_test_SOURCES = logger.c logger.h sptps.c sptps.h sptps_test.c \ - utils.c utils.h $(am__append_11) $(am__append_14) -tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS) -AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" +tincd_SOURCES = have.h system.h avl_tree.c avl_tree.h conf.c conf.h \ + connection.c connection.h device.h dropin.c dropin.h \ + dummy_device.c edge.c edge.h ethernet.h event.c event.h \ + fake-getaddrinfo.c fake-getaddrinfo.h fake-getnameinfo.c \ + fake-getnameinfo.h graph.c graph.h ipv4.h ipv6.h list.c list.h \ + logger.c logger.h meta.c meta.h multicast_device.c net.c net.h \ + net_packet.c net_setup.c net_socket.c netutl.c netutl.h node.c \ + node.h pidfile.c pidfile.h process.c process.h protocol.c \ + protocol.h protocol_auth.c protocol_edge.c protocol_misc.c \ + protocol_key.c protocol_subnet.c proxy.c proxy.h \ + raw_socket_device.c route.c route.h subnet.c subnet.h tincd.c \ + utils.c utils.h xalloc.h $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) \ + $(am__append_6) $(am__append_7) $(am__append_8) \ + $(am__append_9) +AM_CPPFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DRUNSTATEDIR=\"$(runstatedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -I $(abs_top_builddir)/ all: all-am .SUFFIXES: @@ -469,14 +371,13 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -545,62 +446,6 @@ installcheck-sbinPROGRAMS: $(sbin_PROGRAMS) else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \ done; \ done; rm -f c$${pid}_.???; exit $$bad -openssl/$(am__dirstamp): - @$(MKDIR_P) openssl - @: > openssl/$(am__dirstamp) -openssl/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) openssl/$(DEPDIR) - @: > openssl/$(DEPDIR)/$(am__dirstamp) -openssl/cipher.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -openssl/crypto.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -openssl/digest.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -openssl/ecdh.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -openssl/ecdsa.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -openssl/prf.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -gcrypt/$(am__dirstamp): - @$(MKDIR_P) gcrypt - @: > gcrypt/$(am__dirstamp) -gcrypt/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) gcrypt/$(DEPDIR) - @: > gcrypt/$(DEPDIR)/$(am__dirstamp) -gcrypt/cipher.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) -gcrypt/crypto.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) -gcrypt/digest.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) -gcrypt/ecdh.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) -gcrypt/ecdsa.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) -gcrypt/prf.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) - -sptps_test$(EXEEXT): $(sptps_test_OBJECTS) $(sptps_test_DEPENDENCIES) $(EXTRA_sptps_test_DEPENDENCIES) - @rm -f sptps_test$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(sptps_test_OBJECTS) $(sptps_test_LDADD) $(LIBS) -openssl/ecdsagen.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -openssl/rsa.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -openssl/rsagen.$(OBJEXT): openssl/$(am__dirstamp) \ - openssl/$(DEPDIR)/$(am__dirstamp) -gcrypt/ecdsagen.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) -gcrypt/rsa.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) -gcrypt/rsagen.$(OBJEXT): gcrypt/$(am__dirstamp) \ - gcrypt/$(DEPDIR)/$(am__dirstamp) - -tinc$(EXEEXT): $(tinc_OBJECTS) $(tinc_DEPENDENCIES) $(EXTRA_tinc_DEPENDENCIES) - @rm -f tinc$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(tinc_OBJECTS) $(tinc_LDADD) $(LIBS) linux/$(am__dirstamp): @$(MKDIR_P) linux @: > linux/$(am__dirstamp) @@ -652,86 +497,63 @@ mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f bsd/*.$(OBJEXT) -rm -f cygwin/*.$(OBJEXT) - -rm -f gcrypt/*.$(OBJEXT) -rm -f linux/*.$(OBJEXT) -rm -f mingw/*.$(OBJEXT) - -rm -f openssl/*.$(OBJEXT) -rm -f solaris/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/control.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dropin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy_device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getaddrinfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getnameinfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/info.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/invitation.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meta.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_packet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_setup.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_socket.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netutl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_auth.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_edge.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_key.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_misc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_subnet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_socket_device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/splay_tree.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sptps_test.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet_parse.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincctl.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/top.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/cipher.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/crypto.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/digest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/ecdh.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/ecdsa.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/ecdsagen.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/prf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/rsa.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@gcrypt/$(DEPDIR)/rsagen.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@linux/$(DEPDIR)/device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@mingw/$(DEPDIR)/device.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/cipher.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/crypto.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/digest.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/ecdh.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/ecdsa.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/ecdsagen.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/prf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsa.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@openssl/$(DEPDIR)/rsagen.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@solaris/$(DEPDIR)/device.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avl_tree.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dropin.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edge.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getaddrinfo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fake-getnameinfo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/meta.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_packet.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_setup.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net_socket.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netutl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pidfile.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_auth.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_edge.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_key.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_misc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_subnet.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proxy.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_socket_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/route.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subnet.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tincd.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uml_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vde_device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@bsd/$(DEPDIR)/tunemu.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@cygwin/$(DEPDIR)/device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@linux/$(DEPDIR)/device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@mingw/$(DEPDIR)/device.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@solaris/$(DEPDIR)/device.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -801,7 +623,10 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -831,9 +656,6 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done - $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$(top_distdir)" distdir="$(distdir)" \ - dist-hook check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) @@ -871,14 +693,10 @@ distclean-generic: -rm -f bsd/$(am__dirstamp) -rm -f cygwin/$(DEPDIR)/$(am__dirstamp) -rm -f cygwin/$(am__dirstamp) - -rm -f gcrypt/$(DEPDIR)/$(am__dirstamp) - -rm -f gcrypt/$(am__dirstamp) -rm -f linux/$(DEPDIR)/$(am__dirstamp) -rm -f linux/$(am__dirstamp) -rm -f mingw/$(DEPDIR)/$(am__dirstamp) -rm -f mingw/$(am__dirstamp) - -rm -f openssl/$(DEPDIR)/$(am__dirstamp) - -rm -f openssl/$(am__dirstamp) -rm -f solaris/$(DEPDIR)/$(am__dirstamp) -rm -f solaris/$(am__dirstamp) @@ -890,7 +708,50 @@ clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) bsd/$(DEPDIR) cygwin/$(DEPDIR) gcrypt/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) openssl/$(DEPDIR) solaris/$(DEPDIR) + -rm -f ./$(DEPDIR)/avl_tree.Po + -rm -f ./$(DEPDIR)/conf.Po + -rm -f ./$(DEPDIR)/connection.Po + -rm -f ./$(DEPDIR)/dropin.Po + -rm -f ./$(DEPDIR)/dummy_device.Po + -rm -f ./$(DEPDIR)/edge.Po + -rm -f ./$(DEPDIR)/event.Po + -rm -f ./$(DEPDIR)/fake-getaddrinfo.Po + -rm -f ./$(DEPDIR)/fake-getnameinfo.Po + -rm -f ./$(DEPDIR)/getopt.Po + -rm -f ./$(DEPDIR)/getopt1.Po + -rm -f ./$(DEPDIR)/graph.Po + -rm -f ./$(DEPDIR)/list.Po + -rm -f ./$(DEPDIR)/logger.Po + -rm -f ./$(DEPDIR)/meta.Po + -rm -f ./$(DEPDIR)/multicast_device.Po + -rm -f ./$(DEPDIR)/net.Po + -rm -f ./$(DEPDIR)/net_packet.Po + -rm -f ./$(DEPDIR)/net_setup.Po + -rm -f ./$(DEPDIR)/net_socket.Po + -rm -f ./$(DEPDIR)/netutl.Po + -rm -f ./$(DEPDIR)/node.Po + -rm -f ./$(DEPDIR)/pidfile.Po + -rm -f ./$(DEPDIR)/process.Po + -rm -f ./$(DEPDIR)/protocol.Po + -rm -f ./$(DEPDIR)/protocol_auth.Po + -rm -f ./$(DEPDIR)/protocol_edge.Po + -rm -f ./$(DEPDIR)/protocol_key.Po + -rm -f ./$(DEPDIR)/protocol_misc.Po + -rm -f ./$(DEPDIR)/protocol_subnet.Po + -rm -f ./$(DEPDIR)/proxy.Po + -rm -f ./$(DEPDIR)/raw_socket_device.Po + -rm -f ./$(DEPDIR)/route.Po + -rm -f ./$(DEPDIR)/subnet.Po + -rm -f ./$(DEPDIR)/tincd.Po + -rm -f ./$(DEPDIR)/uml_device.Po + -rm -f ./$(DEPDIR)/utils.Po + -rm -f ./$(DEPDIR)/vde_device.Po + -rm -f bsd/$(DEPDIR)/device.Po + -rm -f bsd/$(DEPDIR)/tunemu.Po + -rm -f cygwin/$(DEPDIR)/device.Po + -rm -f linux/$(DEPDIR)/device.Po + -rm -f mingw/$(DEPDIR)/device.Po + -rm -f solaris/$(DEPDIR)/device.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -936,7 +797,50 @@ install-ps-am: installcheck-am: installcheck-sbinPROGRAMS maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) bsd/$(DEPDIR) cygwin/$(DEPDIR) gcrypt/$(DEPDIR) linux/$(DEPDIR) mingw/$(DEPDIR) openssl/$(DEPDIR) solaris/$(DEPDIR) + -rm -f ./$(DEPDIR)/avl_tree.Po + -rm -f ./$(DEPDIR)/conf.Po + -rm -f ./$(DEPDIR)/connection.Po + -rm -f ./$(DEPDIR)/dropin.Po + -rm -f ./$(DEPDIR)/dummy_device.Po + -rm -f ./$(DEPDIR)/edge.Po + -rm -f ./$(DEPDIR)/event.Po + -rm -f ./$(DEPDIR)/fake-getaddrinfo.Po + -rm -f ./$(DEPDIR)/fake-getnameinfo.Po + -rm -f ./$(DEPDIR)/getopt.Po + -rm -f ./$(DEPDIR)/getopt1.Po + -rm -f ./$(DEPDIR)/graph.Po + -rm -f ./$(DEPDIR)/list.Po + -rm -f ./$(DEPDIR)/logger.Po + -rm -f ./$(DEPDIR)/meta.Po + -rm -f ./$(DEPDIR)/multicast_device.Po + -rm -f ./$(DEPDIR)/net.Po + -rm -f ./$(DEPDIR)/net_packet.Po + -rm -f ./$(DEPDIR)/net_setup.Po + -rm -f ./$(DEPDIR)/net_socket.Po + -rm -f ./$(DEPDIR)/netutl.Po + -rm -f ./$(DEPDIR)/node.Po + -rm -f ./$(DEPDIR)/pidfile.Po + -rm -f ./$(DEPDIR)/process.Po + -rm -f ./$(DEPDIR)/protocol.Po + -rm -f ./$(DEPDIR)/protocol_auth.Po + -rm -f ./$(DEPDIR)/protocol_edge.Po + -rm -f ./$(DEPDIR)/protocol_key.Po + -rm -f ./$(DEPDIR)/protocol_misc.Po + -rm -f ./$(DEPDIR)/protocol_subnet.Po + -rm -f ./$(DEPDIR)/proxy.Po + -rm -f ./$(DEPDIR)/raw_socket_device.Po + -rm -f ./$(DEPDIR)/route.Po + -rm -f ./$(DEPDIR)/subnet.Po + -rm -f ./$(DEPDIR)/tincd.Po + -rm -f ./$(DEPDIR)/uml_device.Po + -rm -f ./$(DEPDIR)/utils.Po + -rm -f ./$(DEPDIR)/vde_device.Po + -rm -f bsd/$(DEPDIR)/device.Po + -rm -f bsd/$(DEPDIR)/tunemu.Po + -rm -f cygwin/$(DEPDIR)/device.Po + -rm -f linux/$(DEPDIR)/device.Po + -rm -f mingw/$(DEPDIR)/device.Po + -rm -f solaris/$(DEPDIR)/device.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -956,8 +860,8 @@ uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-sbinPROGRAMS cscopelist-am ctags ctags-am dist-hook \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-dvi \ @@ -970,9 +874,8 @@ uninstall-am: uninstall-sbinPROGRAMS mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS +.PRECIOUS: Makefile -dist-hook: - rm -f `find . -type l` # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/avl_tree.c b/src/avl_tree.c new file mode 100644 index 0000000..96d3d43 --- /dev/null +++ b/src/avl_tree.c @@ -0,0 +1,757 @@ +/* + avl_tree.c -- avl_ tree and linked list convenience + Copyright (C) 1998 Michael H. Buselli + 2000-2005 Ivo Timmermans, + 2000-2015 Guus Sliepen + 2000-2005 Wessel Dankers + + 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. + + Original AVL tree library by Michael H. Buselli . + + Modified 2000-11-28 by Wessel Dankers to use counts + instead of depths, to add the ->next and ->prev and to generally obfuscate + the code. Mail me if you found a bug. + + Cleaned up and incorporated some of the ideas from the red-black tree + library for inclusion into tinc (https://www.tinc-vpn.org/) by + Guus Sliepen . +*/ + +#include "system.h" + +#include "avl_tree.h" +#include "xalloc.h" + +#ifdef AVL_COUNT +#define AVL_NODE_COUNT(n) ((n) ? (n)->count : 0) +#define AVL_L_COUNT(n) (AVL_NODE_COUNT((n)->left)) +#define AVL_R_COUNT(n) (AVL_NODE_COUNT((n)->right)) +#define AVL_CALC_COUNT(n) (AVL_L_COUNT(n) + AVL_R_COUNT(n) + 1) +#endif + +#ifdef AVL_DEPTH +#define AVL_NODE_DEPTH(n) ((n) ? (n)->depth : 0) +#define L_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->left)) +#define R_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->right)) +#define AVL_CALC_DEPTH(n) ((L_AVL_DEPTH(n)>R_AVL_DEPTH(n)?L_AVL_DEPTH(n):R_AVL_DEPTH(n)) + 1) +#endif + +#ifndef AVL_DEPTH +static int lg(unsigned int u) __attribute__((__const__)); + +static int lg(unsigned int u) { + int r = 1; + + if(!u) { + return 0; + } + + if(u & 0xffff0000) { + u >>= 16; + r += 16; + } + + if(u & 0x0000ff00) { + u >>= 8; + r += 8; + } + + if(u & 0x000000f0) { + u >>= 4; + r += 4; + } + + if(u & 0x0000000c) { + u >>= 2; + r += 2; + } + + if(u & 0x00000002) { + r++; + } + + return r; +} +#endif + +/* Internal helper functions */ + +static int avl_check_balance(const avl_node_t *node) { +#ifdef AVL_DEPTH + int d; + + d = R_AVL_DEPTH(node) - L_AVL_DEPTH(node); + + return d < -1 ? -1 : d > 1 ? 1 : 0; +#else + /* int d; + * d = lg(AVL_R_COUNT(node)) - lg(AVL_L_COUNT(node)); + * d = d<-1?-1:d>1?1:0; + */ + int pl, r; + + pl = lg(AVL_L_COUNT(node)); + r = AVL_R_COUNT(node); + + if(r >> pl + 1) { + return 1; + } + + if(pl < 2 || r >> pl - 2) { + return 0; + } + + return -1; +#endif +} + +static void avl_rebalance(avl_tree_t *tree, avl_node_t *node) { + avl_node_t *child; + avl_node_t *gchild; + avl_node_t *parent; + avl_node_t **superparent; + + while(node) { + parent = node->parent; + + superparent = + parent ? node == + parent->left ? &parent->left : &parent->right : &tree->root; + + switch(avl_check_balance(node)) { + case -1: + child = node->left; +#ifdef AVL_DEPTH + + if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) { +#else + + if(AVL_L_COUNT(child) >= AVL_R_COUNT(child)) { +#endif + node->left = child->right; + + if(node->left) { + node->left->parent = node; + } + + child->right = node; + node->parent = child; + *superparent = child; + child->parent = parent; +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); + child->count = AVL_CALC_COUNT(child); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); + child->depth = AVL_CALC_DEPTH(child); +#endif + } else { + gchild = child->right; + node->left = gchild->right; + + if(node->left) { + node->left->parent = node; + } + + child->right = gchild->left; + + if(child->right) { + child->right->parent = child; + } + + gchild->right = node; + + gchild->right->parent = gchild; + gchild->left = child; + + gchild->left->parent = gchild; + + *superparent = gchild; + gchild->parent = parent; +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); + child->count = AVL_CALC_COUNT(child); + gchild->count = AVL_CALC_COUNT(gchild); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); + child->depth = AVL_CALC_DEPTH(child); + gchild->depth = AVL_CALC_DEPTH(gchild); +#endif + } + + break; + + case 1: + child = node->right; +#ifdef AVL_DEPTH + + if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) { +#else + + if(AVL_R_COUNT(child) >= AVL_L_COUNT(child)) { +#endif + node->right = child->left; + + if(node->right) { + node->right->parent = node; + } + + child->left = node; + node->parent = child; + *superparent = child; + child->parent = parent; +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); + child->count = AVL_CALC_COUNT(child); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); + child->depth = AVL_CALC_DEPTH(child); +#endif + } else { + gchild = child->left; + node->right = gchild->left; + + if(node->right) { + node->right->parent = node; + } + + child->left = gchild->right; + + if(child->left) { + child->left->parent = child; + } + + gchild->left = node; + + gchild->left->parent = gchild; + gchild->right = child; + + gchild->right->parent = gchild; + + *superparent = gchild; + gchild->parent = parent; +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); + child->count = AVL_CALC_COUNT(child); + gchild->count = AVL_CALC_COUNT(gchild); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); + child->depth = AVL_CALC_DEPTH(child); + gchild->depth = AVL_CALC_DEPTH(gchild); +#endif + } + + break; + + default: +#ifdef AVL_COUNT + node->count = AVL_CALC_COUNT(node); +#endif +#ifdef AVL_DEPTH + node->depth = AVL_CALC_DEPTH(node); +#endif + } + + node = parent; + } +} + +/* (De)constructors */ + +avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete) { + avl_tree_t *tree; + + tree = xmalloc_and_zero(sizeof(avl_tree_t)); + tree->compare = compare; + tree->delete = delete; + + return tree; +} + +void avl_free_tree(avl_tree_t *tree) { + free(tree); +} + +avl_node_t *avl_alloc_node(void) { + return xmalloc_and_zero(sizeof(avl_node_t)); +} + +void avl_free_node(avl_tree_t *tree, avl_node_t *node) { + if(node->data && tree->delete) { + tree->delete(node->data); + } + + free(node); +} + +/* Searching */ + +void *avl_search(const avl_tree_t *tree, const void *data) { + avl_node_t *node; + + node = avl_search_node(tree, data); + + return node ? node->data : NULL; +} + +void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result) { + avl_node_t *node; + + node = avl_search_closest_node(tree, data, result); + + return node ? node->data : NULL; +} + +void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data) { + avl_node_t *node; + + node = avl_search_closest_smaller_node(tree, data); + + return node ? node->data : NULL; +} + +void *avl_search_closest_greater(const avl_tree_t *tree, const void *data) { + avl_node_t *node; + + node = avl_search_closest_greater_node(tree, data); + + return node ? node->data : NULL; +} + +avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data) { + avl_node_t *node; + int result; + + node = avl_search_closest_node(tree, data, &result); + + return result ? NULL : node; +} + +avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data, + int *result) { + avl_node_t *node; + int c; + + node = tree->root; + + if(!node) { + if(result) { + *result = 0; + } + + return NULL; + } + + for(;;) { + c = tree->compare(data, node->data); + + if(c < 0) { + if(node->left) { + node = node->left; + } else { + if(result) { + *result = -1; + } + + break; + } + } else if(c > 0) { + if(node->right) { + node = node->right; + } else { + if(result) { + *result = 1; + } + + break; + } + } else { + if(result) { + *result = 0; + } + + break; + } + } + + return node; +} + +avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree, + const void *data) { + avl_node_t *node; + int result; + + node = avl_search_closest_node(tree, data, &result); + + if(result < 0) { + node = node->prev; + } + + return node; +} + +avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree, + const void *data) { + avl_node_t *node; + int result; + + node = avl_search_closest_node(tree, data, &result); + + if(result > 0) { + node = node->next; + } + + return node; +} + +/* Insertion and deletion */ + +avl_node_t *avl_insert(avl_tree_t *tree, void *data) { + avl_node_t *closest, *new; + int result; + + if(!tree->root) { + new = avl_alloc_node(); + new->data = data; + avl_insert_top(tree, new); + } else { + closest = avl_search_closest_node(tree, data, &result); + + switch(result) { + case -1: + new = avl_alloc_node(); + new->data = data; + avl_insert_before(tree, closest, new); + break; + + case 1: + new = avl_alloc_node(); + new->data = data; + avl_insert_after(tree, closest, new); + break; + + default: + return NULL; + } + } + +#ifdef AVL_COUNT + new->count = 1; +#endif +#ifdef AVL_DEPTH + new->depth = 1; +#endif + + return new; +} + +avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node) { + avl_node_t *closest; + int result; + + if(!tree->root) { + avl_insert_top(tree, node); + } else { + closest = avl_search_closest_node(tree, node->data, &result); + + switch(result) { + case -1: + avl_insert_before(tree, closest, node); + break; + + case 1: + avl_insert_after(tree, closest, node); + break; + + case 0: + return NULL; + } + } + +#ifdef AVL_COUNT + node->count = 1; +#endif +#ifdef AVL_DEPTH + node->depth = 1; +#endif + + return node; +} + +void avl_insert_top(avl_tree_t *tree, avl_node_t *node) { + node->prev = node->next = node->parent = NULL; + tree->head = tree->tail = tree->root = node; +} + +void avl_insert_before(avl_tree_t *tree, avl_node_t *before, + avl_node_t *node) { + if(!before) { + if(tree->tail) { + avl_insert_after(tree, tree->tail, node); + } else { + avl_insert_top(tree, node); + } + + return; + } + + node->next = before; + node->parent = before; + node->prev = before->prev; + + if(before->left) { + avl_insert_after(tree, before->prev, node); + return; + } + + if(before->prev) { + before->prev->next = node; + } else { + tree->head = node; + } + + before->prev = node; + before->left = node; + + avl_rebalance(tree, before); +} + +void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node) { + if(!after) { + if(tree->head) { + avl_insert_before(tree, tree->head, node); + } else { + avl_insert_top(tree, node); + } + + return; + } + + if(after->right) { + avl_insert_before(tree, after->next, node); + return; + } + + node->prev = after; + node->parent = after; + node->next = after->next; + + if(after->next) { + after->next->prev = node; + } else { + tree->tail = node; + } + + after->next = node; + after->right = node; + + avl_rebalance(tree, after); +} + +avl_node_t *avl_unlink(avl_tree_t *tree, void *data) { + avl_node_t *node; + + node = avl_search_node(tree, data); + + if(node) { + avl_unlink_node(tree, node); + } + + return node; +} + +void avl_unlink_node(avl_tree_t *tree, avl_node_t *node) { + avl_node_t *parent; + avl_node_t **superparent; + avl_node_t *subst, *left, *right; + avl_node_t *balnode; + + if(node->prev) { + node->prev->next = node->next; + } else { + tree->head = node->next; + } + + if(node->next) { + node->next->prev = node->prev; + } else { + tree->tail = node->prev; + } + + parent = node->parent; + + superparent = + parent ? node == + parent->left ? &parent->left : &parent->right : &tree->root; + + left = node->left; + right = node->right; + + if(!left) { + *superparent = right; + + if(right) { + right->parent = parent; + } + + balnode = parent; + } else if(!right) { + *superparent = left; + left->parent = parent; + balnode = parent; + } else { + subst = node->prev; + + if(!subst) { // This only happens if node is not actually in a tree at all. + abort(); + } + + if(subst == left) { + balnode = subst; + } else { + balnode = subst->parent; + balnode->right = subst->left; + + if(balnode->right) { + balnode->right->parent = balnode; + } + + subst->left = left; + left->parent = subst; + } + + subst->right = right; + subst->parent = parent; + right->parent = subst; + *superparent = subst; + } + + avl_rebalance(tree, balnode); + + node->next = node->prev = node->parent = node->left = node->right = NULL; + +#ifdef AVL_COUNT + node->count = 0; +#endif +#ifdef AVL_DEPTH + node->depth = 0; +#endif +} + +void avl_delete_node(avl_tree_t *tree, avl_node_t *node) { + avl_unlink_node(tree, node); + avl_free_node(tree, node); +} + +void avl_delete(avl_tree_t *tree, void *data) { + avl_node_t *node; + + node = avl_search_node(tree, data); + + if(node) { + avl_delete_node(tree, node); + } +} + +/* Fast tree cleanup */ + +void avl_delete_tree(avl_tree_t *tree) { + avl_node_t *node, *next; + + for(node = tree->head; node; node = next) { + next = node->next; + avl_free_node(tree, node); + } + + avl_free_tree(tree); +} + +/* Tree walking */ + +void avl_foreach(const avl_tree_t *tree, avl_action_t action) { + avl_node_t *node, *next; + + for(node = tree->head; node; node = next) { + next = node->next; + action(node->data); + } +} + +void avl_foreach_node(const avl_tree_t *tree, avl_action_t action) { + avl_node_t *node, *next; + + for(node = tree->head; node; node = next) { + next = node->next; + action(node); + } +} + +/* Indexing */ + +#ifdef AVL_COUNT +unsigned int avl_count(const avl_tree_t *tree) { + return AVL_NODE_COUNT(tree->root); +} + +avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index) { + avl_node_t *node; + unsigned int c; + + node = tree->root; + + while(node) { + c = AVL_L_COUNT(node); + + if(index < c) { + node = node->left; + } else if(index > c) { + node = node->right; + index -= c + 1; + } else { + return node; + } + } + + return NULL; +} + +unsigned int avl_index(const avl_node_t *node) { + avl_node_t *next; + unsigned int index; + + index = AVL_L_COUNT(node); + + while((next = node->parent)) { + if(node == next->right) { + index += AVL_L_COUNT(next) + 1; + } + + node = next; + } + + return index; +} +#endif +#ifdef AVL_DEPTH +unsigned int avl_depth(const avl_tree_t *tree) { + return AVL_NODE_DEPTH(tree->root); +} +#endif diff --git a/src/avl_tree.h b/src/avl_tree.h new file mode 100644 index 0000000..e8cefcf --- /dev/null +++ b/src/avl_tree.h @@ -0,0 +1,142 @@ +#ifndef TINC_AVL_TREE_H +#define TINC_AVL_TREE_H + +/* + avl_tree.h -- header file for avl_tree.c + Copyright (C) 1998 Michael H. Buselli + 2000-2005 Ivo Timmermans, + 2000-2006 Guus Sliepen + 2000-2005 Wessel Dankers + + 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. + + Original AVL tree library by Michael H. Buselli . + + Modified 2000-11-28 by Wessel Dankers to use counts + instead of depths, to add the ->next and ->prev and to generally obfuscate + the code. Mail me if you found a bug. + + Cleaned up and incorporated some of the ideas from the red-black tree + library for inclusion into tinc (https://www.tinc-vpn.org/) by + Guus Sliepen . +*/ + +#ifndef AVL_DEPTH +#ifndef AVL_COUNT +#define AVL_DEPTH +#endif +#endif + +typedef struct avl_node_t { + + /* Linked list part */ + + struct avl_node_t *next; + struct avl_node_t *prev; + + /* Tree part */ + + struct avl_node_t *parent; + struct avl_node_t *left; + struct avl_node_t *right; + +#ifdef AVL_COUNT + unsigned int count; +#endif +#ifdef AVL_DEPTH + unsigned char depth; +#endif + + /* Payload */ + + void *data; + +} avl_node_t; + +typedef int (*avl_compare_t)(const void *data1, const void *data2); +typedef void (*avl_action_t)(const void *data); +typedef void (*avl_action_node_t)(const avl_node_t *node); + +typedef struct avl_tree_t { + + /* Linked list part */ + + avl_node_t *head; + avl_node_t *tail; + + /* Tree part */ + + avl_node_t *root; + + avl_compare_t compare; + avl_action_t delete; + +} avl_tree_t; + +/* (De)constructors */ + +extern avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete); +extern void avl_free_tree(avl_tree_t *tree); + +extern avl_node_t *avl_alloc_node(void); +extern void avl_free_node(avl_tree_t *tree, avl_node_t *node); + +/* Insertion and deletion */ + +extern avl_node_t *avl_insert(avl_tree_t *tree, void *data); +extern avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node); + +extern void avl_insert_top(avl_tree_t *tree, avl_node_t *node); +extern void avl_insert_before(avl_tree_t *tree, avl_node_t *before, avl_node_t *node); +extern void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node); + +extern avl_node_t *avl_unlink(avl_tree_t *tree, void *data); +extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *node); +extern void avl_delete(avl_tree_t *tree, void *data); +extern void avl_delete_node(avl_tree_t *tree, avl_node_t *node); + +/* Fast tree cleanup */ + +extern void avl_delete_tree(avl_tree_t *tree); + +/* Searching */ + +extern void *avl_search(const avl_tree_t *tree, const void *data); +extern void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result); +extern void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data); +extern void *avl_search_closest_greater(const avl_tree_t *tree, const void *data); + +extern avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data); +extern avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data, int *result); +extern avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree, const void *data); +extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree, const void *data); + +/* Tree walking */ + +extern void avl_foreach(const avl_tree_t *tree, avl_action_t action); +extern void avl_foreach_node(const avl_tree_t *tree, avl_action_t action); + +/* Indexing */ + +#ifdef AVL_COUNT +extern unsigned int avl_count(const avl_tree_t *tree); +extern avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index); +extern unsigned int avl_index(const avl_node_t *node); +#endif +#ifdef AVL_DEPTH +extern unsigned int avl_depth(const avl_tree_t *tree); +#endif + +#endif diff --git a/src/bsd/.deps/device.Po b/src/bsd/.deps/device.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/bsd/.deps/device.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/bsd/.deps/tunemu.Po b/src/bsd/.deps/tunemu.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/bsd/.deps/tunemu.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/bsd/device.c b/src/bsd/device.c index e083519..23d6d69 100644 --- a/src/bsd/device.c +++ b/src/bsd/device.c @@ -1,7 +1,7 @@ /* device.c -- Interaction BSD tun/tap device Copyright (C) 2001-2005 Ivo Timmermans, - 2001-2013 Guus Sliepen + 2001-2016 Guus Sliepen 2009 Grzegorz Dymarek This program is free software; you can redistribute it and/or modify @@ -24,22 +24,23 @@ #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" +#include "tunemu.h" +#endif + +#ifdef HAVE_NET_IF_UTUN_H +#include +#include +#include #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, @@ -48,12 +49,13 @@ typedef enum device_type { #ifdef ENABLE_TUNEMU DEVICE_TYPE_TUNEMU, #endif + DEVICE_TYPE_UTUN, } device_type_t; int device_fd = -1; char *device = NULL; char *iface = NULL; -static char *device_info = NULL; +static const char *device_info = "OS X utun device"; static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; #if defined(ENABLE_TUNEMU) @@ -64,55 +66,144 @@ static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD; static device_type_t device_type = DEVICE_TYPE_TUN; #endif -static bool setup_device(void) { - char *type; +#ifdef HAVE_NET_IF_UTUN_H +static bool setup_utun(void) { + device_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); - 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(device_fd == -1) { + logger(LOG_ERR, "Could not open PF_SYSTEM socket: %s\n", strerror(errno)); + return false; } - if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) - iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); + struct ctl_info info = {}; + + strlcpy(info.ctl_name, UTUN_CONTROL_NAME, sizeof(info.ctl_name)); + + if(ioctl(device_fd, CTLIOCGINFO, &info) == -1) { + logger(LOG_ERR, "ioctl(CTLIOCGINFO) failed: %s", strerror(errno)); + return false; + } + + int unit = -1; + char *p = strstr(device, "utun"), *e = NULL; + + if(p) { + unit = strtol(p + 4, &e, 10); + + if(!e) { + unit = -1; + } + } + + struct sockaddr_ctl sc = { + .sc_id = info.ctl_id, + .sc_len = sizeof(sc), + .sc_family = AF_SYSTEM, + .ss_sysaddr = AF_SYS_CONTROL, + .sc_unit = unit + 1, + }; + + if(connect(device_fd, (struct sockaddr *)&sc, sizeof(sc)) == -1) { + logger(LOG_ERR, "Could not connect utun socket: %s\n", strerror(errno)); + return false; + } + + char name[64] = ""; + socklen_t len = sizeof(name); + + if(getsockopt(device_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) { + iface = xstrdup(device); + } else { + iface = xstrdup(name); + } + + logger(LOG_INFO, "%s is a %s", device, device_info); + + return true; +} +#endif + +static bool setup_device(void) { + // Find out which device file to open + + 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); + } + } + + // Find out if it's supposed to be a tun or a tap device + + char *type; if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { if(!strcasecmp(type, "tun")) /* use default */; + #ifdef ENABLE_TUNEMU - else if(!strcasecmp(type, "tunemu")) + else if(!strcasecmp(type, "tunemu")) { device_type = DEVICE_TYPE_TUNEMU; + } + #endif - else if(!strcasecmp(type, "tunnohead")) +#ifdef HAVE_NET_IF_UTUN_H + else if(!strcasecmp(type, "utun")) { + device_type = DEVICE_TYPE_UTUN; + } + +#endif + else if(!strcasecmp(type, "tunnohead")) { device_type = DEVICE_TYPE_TUN; - else if(!strcasecmp(type, "tunifhead")) + } else if(!strcasecmp(type, "tunifhead")) { device_type = DEVICE_TYPE_TUNIFHEAD; - else if(!strcasecmp(type, "tap")) + } else if(!strcasecmp(type, "tap")) { device_type = DEVICE_TYPE_TAP; - else { - logger(DEBUG_ALWAYS, LOG_ERR, "Unknown device type %s!", type); + } else { + logger(LOG_ERR, "Unknown device type %s!", type); return false; } } else { - if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) - device_type = DEVICE_TYPE_TAP; +#ifdef HAVE_NET_IF_UTUN_H + + if(strncmp(device, "utun", 4) == 0 || strncmp(device, "/dev/utun", 9) == 0) { + device_type = DEVICE_TYPE_UTUN; + } else +#endif + if(strstr(device, "tap") || routing_mode != RMODE_ROUTER) { + device_type = DEVICE_TYPE_TAP; + } } + if(routing_mode == RMODE_SWITCH && device_type != DEVICE_TYPE_TAP) { + logger(LOG_ERR, "Only tap devices support switch mode!"); + return false; + } + + // Open the device + switch(device_type) { #ifdef ENABLE_TUNEMU - case DEVICE_TYPE_TUNEMU: { - char dynamic_name[256] = ""; - device_fd = tunemu_open(dynamic_name); - } - break; + + 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); +#ifdef HAVE_NET_IF_UTUN_H + + case DEVICE_TYPE_UTUN: + return setup_utun(); +#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)); + logger(LOG_ERR, "Could not open %s: %s", device, strerror(errno)); return false; } @@ -120,71 +211,119 @@ static bool setup_device(void) { fcntl(device_fd, F_SETFD, FD_CLOEXEC); #endif + // Guess what the corresponding interface is called + + char *realname = NULL; + +#if defined(HAVE_FDEVNAME) + realname = fdevname(device_fd); +#elif defined(HAVE_DEVNAME) + struct stat buf; + + if(!fstat(device_fd, &buf)) { + realname = devname(buf.st_rdev, S_IFCHR); + } + +#endif + + if(!realname) { + realname = device; + } + + if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) { + iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname); + } else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) { + logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly."); + } + + // Configure the device as best as we can + switch(device_type) { - default: - device_type = DEVICE_TYPE_TUN; - case DEVICE_TYPE_TUN: + 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)); + + if(ioctl(device_fd, TUNSIFHEAD, &zero, sizeof(zero)) == -1) { + logger(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); + ioctl(device_fd, TUNSIFMODE, &mode, sizeof(mode)); } #endif - device_info = "Generic BSD tun device"; - break; - case DEVICE_TYPE_TUNIFHEAD: + 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)); + + if(ioctl(device_fd, TUNSIFHEAD, &one, sizeof(one)) == -1) { + logger(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); + 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"; + 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); + { + struct ifreq ifr; + + if(ioctl(device_fd, TAPGIFNAME, (void *)&ifr) == 0) { + if(iface) { + free(iface); } + + iface = xstrdup(ifr.ifr_name); } + } #endif - break; + break; #ifdef ENABLE_TUNEMU - case DEVICE_TYPE_TUNEMU: - device_info = "BSD tunemu device"; - break; + + case DEVICE_TYPE_TUNEMU: + device_info = "BSD tunemu device"; + break; #endif } - logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info); +#ifdef SIOCGIFADDR + + if(overwrite_mac) { + ioctl(device_fd, SIOCGIFADDR, mymac.x); + } + +#endif + + logger(LOG_INFO, "%s is a %s", device, device_info); return true; } @@ -192,12 +331,14 @@ static bool setup_device(void) { static void close_device(void) { switch(device_type) { #ifdef ENABLE_TUNEMU - case DEVICE_TYPE_TUNEMU: - tunemu_close(device_fd); - break; + + case DEVICE_TYPE_TUNEMU: + tunemu_close(device_fd); + break; #endif - default: - close(device_fd); + + default: + close(device_fd); } free(device); @@ -205,161 +346,168 @@ static void close_device(void) { } static bool read_packet(vpn_packet_t *packet) { - int inlen; + int lenin; switch(device_type) { - case DEVICE_TYPE_TUN: + 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 + case DEVICE_TYPE_TUNEMU: + if(device_type == DEVICE_TYPE_TUNEMU) { + lenin = tunemu_read(device_fd, packet->data + 14, MTU - 14); + } else #endif - inlen = read(device_fd, packet->data + 14, MTU - 14); + lenin = 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; + if(lenin <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; } - 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; - } + switch(packet->data[14] >> 4) { + case 4: + packet->data[12] = 0x08; + packet->data[13] = 0x00; + break; - packet->len = inlen; + case 6: + packet->data[12] = 0x86; + packet->data[13] = 0xDD; break; default: + ifdebug(TRAFFIC) logger(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 = lenin + 14; + break; + + case DEVICE_TYPE_UTUN: + case DEVICE_TYPE_TUNIFHEAD: { + if((lenin = read(device_fd, packet->data + 10, MTU - 10)) <= 0) { + logger(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: + ifdebug(TRAFFIC) logger(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 = lenin + 10; + break; + } + + case DEVICE_TYPE_TAP: + if((lenin = read(device_fd, packet->data, MTU)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + packet->len = lenin; + break; + + default: + return false; } device_total_in += packet->len; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", - packet->len, device_info); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", + packet->len, device_info); return true; } static bool write_packet(vpn_packet_t *packet) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", - packet->len, device_info); + ifdebug(TRAFFIC) logger(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_TUN: + if(write(device_fd, packet->data + 14, packet->len - 14) < 0) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, + device, strerror(errno)); + return false; } - 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; + + case DEVICE_TYPE_UTUN: + case DEVICE_TYPE_TUNIFHEAD: { + int af = (packet->data[12] << 8) + packet->data[13]; + uint32_t type; + + switch(af) { + case 0x0800: + type = htonl(AF_INET); 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; - } + case 0x86DD: + type = htonl(AF_INET6); break; -#endif default: + ifdebug(TRAFFIC) logger(LOG_ERR, + "Unknown address family %x while writing packet to %s %s", + af, device_info, device); return false; + } + + memcpy(packet->data + 10, &type, sizeof(type)); + + if(write(device_fd, packet->data + 10, packet->len - 10) < 0) { + logger(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(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(LOG_ERR, "Error while writing to %s %s: %s", device_info, + device, strerror(errno)); + return false; + } + + break; +#endif + + default: + return false; } device_total_out += packet->len; @@ -368,9 +516,9 @@ static bool write_packet(vpn_packet_t *packet) { } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t os_devops = { diff --git a/src/bsd/tunemu.c b/src/bsd/tunemu.c index 1ce9007..7ff6f72 100644 --- a/src/bsd/tunemu.c +++ b/src/bsd/tunemu.c @@ -45,28 +45,25 @@ #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 PPPIOCGCHAN _IOR('t', 55, int) #define PPPIOCCONNECT _IOW('t', 58, int) -#define PPPIOCGUNIT _IOR('t', 86, int) +#define PPPIOCGUNIT _IOR('t', 86, int) -struct sockaddr_ppp -{ +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 -{ +enum NPmode { NPMODE_PASS, - NPMODE_DROP, - NPMODE_ERROR, - NPMODE_QUEUE + NPMODE_DROP, + NPMODE_ERROR, + NPMODE_QUEUE }; -struct npioctl -{ +struct npioctl { int protocol; enum NPmode mode; }; @@ -83,58 +80,55 @@ static pcap_t *pcap = NULL; static int data_buffer_length = 0; static char *data_buffer = NULL; -static void tun_error(char *format, ...) -{ +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() -{ +static void tun_noerror() { *tunemu_error = 0; } -static void closeall() -{ - int fd = getdtablesize(); - while (fd--) - close(fd); +static void closeall() { + int fd = getdtablesize(); - open("/dev/null", O_RDWR, 0); - dup(0); - dup(0); + while(fd--) { + close(fd); + } + + open("/dev/null", O_RDWR, 0); + dup(0); + dup(0); } -static int ppp_load_kext() -{ +static int ppp_load_kext() { int pid = fork(); - if (pid < 0) - { + + if(pid < 0) { tun_error("fork for ppp kext: %s", strerror(errno)); return -1; } - if (pid == 0) - { + 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) + + 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) - { + if(WEXITSTATUS(status) != 0) { tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH); return -1; } @@ -143,74 +137,73 @@ static int ppp_load_kext() return 0; } -static int ppp_new_instance() -{ +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) + 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) - { + + 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) - { + 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) -{ +static int ppp_new_unit(int *unit_number) { int fd = ppp_new_instance(); - if (fd < 0) + + if(fd < 0) { return -1; + } // create ppp unit - if (ioctl(fd, PPPIOCNEWUNIT, unit_number) < 0) - { + 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) -{ +static int ppp_setup_unit(int unit_fd) { // send traffic to program int flags = SC_LOOP_TRAFFIC; - if (ioctl(unit_fd, PPPIOCSFLAGS, &flags) < 0) - { + + 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) - { + + if(ioctl(unit_fd, PPPIOCSNPMODE, &npi) < 0) { tun_error("starting ppp unit: %s", strerror(errno)); return -1; } @@ -219,10 +212,8 @@ static int ppp_setup_unit(int unit_fd) return 0; } -static int open_pcap() -{ - if (pcap != NULL) - { +static int open_pcap() { + if(pcap != NULL) { pcap_use_count++; return 0; } @@ -231,8 +222,7 @@ static int open_pcap() pcap = pcap_open_live("lo0", BUFSIZ, 0, 1, errbuf); pcap_use_count = 1; - if (pcap == NULL) - { + if(pcap == NULL) { tun_error("opening pcap: %s", errbuf); return -1; } @@ -241,59 +231,57 @@ static int open_pcap() return 0; } -static void close_pcap() -{ - if (pcap == NULL) +static void close_pcap() { + if(pcap == NULL) { return; + } pcap_use_count--; - if (pcap_use_count == 0) - { + + if(pcap_use_count == 0) { pcap_close(pcap); pcap = NULL; } } -static void allocate_data_buffer(int size) -{ - if (data_buffer_length < size) - { +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) -{ +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) +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) + + if(unit_number < 0 || unit_number > 999) { return -1; + } tunemu_device compare; make_device_name(compare, unit_number); - if (strcmp(device, compare) != 0) + if(strcmp(device, compare) != 0) { return -1; + } return 0; } -int tunemu_open(tunemu_device device) -{ +int tunemu_open(tunemu_device device) { int ppp_unit_number = -1; - if (device[0] != 0) - { - if (check_device_name(device) < 0) - { + + if(device[0] != 0) { + if(check_device_name(device) < 0) { tun_error("invalid device name \"%s\"", device); return -1; } @@ -302,17 +290,17 @@ int tunemu_open(tunemu_device device) } 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) - { + 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) - { + if(open_pcap() < 0) { close(ppp_unit_fd); return -1; } @@ -322,39 +310,40 @@ int tunemu_open(tunemu_device device) return ppp_unit_fd; } -int tunemu_close(int ppp_sockfd) -{ +int tunemu_close(int ppp_sockfd) { int ret = close(ppp_sockfd); - if (ret == 0) + if(ret == 0) { close_pcap(); + } return ret; } -int tunemu_read(int ppp_sockfd, char *buffer, int length) -{ +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) - { + + if(length < 0) { tun_error("reading packet: %s", strerror(errno)); return length; } + tun_noerror(); length -= 2; - if (length < 0) + + if(length < 0) { return 0; + } memcpy(buffer, data_buffer + 2, length); return length; } -int tunemu_write(int ppp_sockfd, char *buffer, int length) -{ +int tunemu_write(int ppp_sockfd, char *buffer, int length) { allocate_data_buffer(length + 4); data_buffer[0] = 0x02; @@ -364,23 +353,25 @@ int tunemu_write(int ppp_sockfd, char *buffer, int length) memcpy(data_buffer + 4, buffer, length); - if (pcap == NULL) - { + if(pcap == NULL) { tun_error("pcap not open"); return -1; } length = pcap_inject(pcap, data_buffer, length + 4); - if (length < 0) - { + + if(length < 0) { tun_error("injecting packet: %s", pcap_geterr(pcap)); return length; } + tun_noerror(); length -= 4; - if (length < 0) + + if(length < 0) { return 0; + } return length; } diff --git a/src/buffer.c b/src/buffer.c deleted file mode 100644 index ac57d1c..0000000 --- a/src/buffer.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - buffer.c -- buffer management - Copyright (C) 2011 Guus Sliepen , - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "buffer.h" -#include "xalloc.h" - -void buffer_compact(buffer_t *buffer, int maxsize) { - if(buffer->len >= maxsize || buffer->offset / 7 > buffer->len / 8) { - memmove(buffer->data, buffer->data + buffer->offset, buffer->len - buffer->offset); - buffer->len -= buffer->offset; - buffer->offset = 0; - } -} - -// Make sure we can add size bytes to the buffer, and return a pointer to the start of those bytes. - -char *buffer_prepare(buffer_t *buffer, int size) { - if(!buffer->data) { - buffer->maxlen = size; - buffer->data = xmalloc(size); - } else { - if(buffer->offset && buffer->len + size > buffer->maxlen) { - memmove(buffer->data, buffer->data + buffer->offset, buffer->len - buffer->offset); - buffer->len -= buffer->offset; - buffer->offset = 0; - } - - if(buffer->len + size > buffer->maxlen) { - buffer->maxlen = buffer->len + size; - buffer->data = xrealloc(buffer->data, buffer->maxlen); - } - } - - char *start = buffer->data + buffer->len; - - buffer->len += size; - - return start; -} - -// Copy data into the buffer. - -void buffer_add(buffer_t *buffer, const char *data, int size) { - memcpy(buffer_prepare(buffer, size), data, size); -} - -// Remove given number of bytes from the buffer, return a pointer to the start of them. - -static char *buffer_consume(buffer_t *buffer, int size) { - char *start = buffer->data + buffer->offset; - - buffer->offset += size; - - if(buffer->offset >= buffer->len) { - buffer->offset = 0; - buffer->len = 0; - } - - return start; -} - -// Check if there is a complete line in the buffer, and if so, return it NULL-terminated. - -char *buffer_readline(buffer_t *buffer) { - char *newline = memchr(buffer->data + buffer->offset, '\n', buffer->len - buffer->offset); - - if(!newline) - return NULL; - - int len = newline + 1 - (buffer->data + buffer->offset); - *newline = 0; - return buffer_consume(buffer, len); -} - -// Check if we have enough bytes in the buffer, and if so, return a pointer to the start of them. - -char *buffer_read(buffer_t *buffer, int size) { - if(buffer->len - buffer->offset < size) - return NULL; - - return buffer_consume(buffer, size); -} - -void buffer_clear(buffer_t *buffer) { - free(buffer->data); - buffer->data = NULL; - buffer->maxlen = 0; - buffer->len = 0; - buffer->offset = 0; -} diff --git a/src/buffer.h b/src/buffer.h deleted file mode 100644 index a96c15a..0000000 --- a/src/buffer.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __TINC_BUFFER_H__ -#define __TINC_BUFFER_H__ - -typedef struct buffer_t { - char *data; - int maxlen; - int len; - int offset; -} buffer_t; - -extern void buffer_compact(buffer_t *buffer, int maxsize); -extern char *buffer_prepare(buffer_t *buffer, int size); -extern void buffer_add(buffer_t *buffer, const char *data, int size); -extern char *buffer_readline(buffer_t *buffer); -extern char *buffer_read(buffer_t *buffer, int size); -extern void buffer_clear(buffer_t *buffer); - -#endif diff --git a/src/cipher.h b/src/cipher.h deleted file mode 100644 index 17ca614..0000000 --- a/src/cipher.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - cipher.h -- header file cipher.c - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_CIPHER_H__ -#define __TINC_CIPHER_H__ - -#define CIPHER_MAX_BLOCK_SIZE 32 -#define CIPHER_MAX_IV_SIZE 16 -#define CIPHER_MAX_KEY_SIZE 32 - -typedef struct cipher cipher_t; - -extern cipher_t *cipher_open_by_name(const char *) __attribute__ ((__malloc__)); -extern cipher_t *cipher_open_by_nid(int) __attribute__ ((__malloc__)); -extern cipher_t *cipher_open_blowfish_ofb(void) __attribute__ ((__malloc__)); -extern void cipher_close(cipher_t *); -extern size_t cipher_keylength(const cipher_t *); -extern void cipher_get_key(const cipher_t *, void *); -extern bool cipher_set_key(cipher_t *, void *, bool) __attribute__ ((__warn_unused_result__)); -extern bool cipher_set_key_from_rsa(cipher_t *, void *, size_t, bool) __attribute__ ((__warn_unused_result__)); -extern bool cipher_set_counter(cipher_t *, const void *, size_t) __attribute__ ((__warn_unused_result__)); -extern bool cipher_set_counter_key(cipher_t *, void *) __attribute__ ((__warn_unused_result__)); -extern bool cipher_encrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__)); -extern bool cipher_decrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__)); -extern bool cipher_counter_xor(cipher_t *, const void *indata, size_t inlen, void *outdata) __attribute__ ((__warn_unused_result__)); -extern int cipher_get_nid(const cipher_t *); -extern bool cipher_active(const cipher_t *); - -#endif diff --git a/src/conf.c b/src/conf.c index 3c64519..3f81877 100644 --- a/src/conf.c +++ b/src/conf.c @@ -2,7 +2,7 @@ conf.c -- configuration code Copyright (C) 1998 Robert van der Meulen 1998-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2014 Guus Sliepen 2010-2011 Julien Muchembled 2000 Cris van Pelt @@ -23,104 +23,107 @@ #include "system.h" -#include "splay_tree.h" +#include "avl_tree.h" #include "connection.h" #include "conf.h" #include "list.h" #include "logger.h" -#include "names.h" -#include "netutl.h" /* for str2address */ +#include "netutl.h" /* for str2address */ #include "protocol.h" -#include "utils.h" /* for cp */ +#include "utils.h" /* for cp */ #include "xalloc.h" -splay_tree_t *config_tree; +avl_tree_t *config_tree; -int pinginterval = 0; /* seconds between pings */ -int pingtimeout = 0; /* seconds to wait for response */ +int pinginterval = 0; /* seconds between pings */ +int pingtimeout = 0; /* seconds to wait for response */ +char *confbase = NULL; /* directory in which all config files are */ +char *netname = NULL; /* name of the vpn network */ list_t *cmdline_conf = NULL; /* global/host configuration values given at the command line */ + static int config_compare(const config_t *a, const config_t *b) { int result; result = strcasecmp(a->variable, b->variable); - if(result) + if(result) { return result; + } /* give priority to command line options */ result = !b->file - !a->file; - if (result) + + if(result) { return result; + } result = a->line - b->line; - if(result) + if(result) { return result; - else + } else { return a->file ? strcmp(a->file, b->file) : 0; + } } -void init_configuration(splay_tree_t ** config_tree) { - *config_tree = splay_alloc_tree((splay_compare_t) config_compare, (splay_action_t) free_config); +void init_configuration(avl_tree_t **config_tree) { + *config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config); } -void exit_configuration(splay_tree_t ** config_tree) { - splay_delete_tree(*config_tree); +void exit_configuration(avl_tree_t **config_tree) { + avl_delete_tree(*config_tree); *config_tree = NULL; } config_t *new_config(void) { - return xzalloc(sizeof(config_t)); + return xmalloc_and_zero(sizeof(config_t)); } void free_config(config_t *cfg) { - if(cfg->variable) - free(cfg->variable); - - if(cfg->value) - free(cfg->value); - - if(cfg->file) - free(cfg->file); - + free(cfg->variable); + free(cfg->value); + free(cfg->file); free(cfg); } -void config_add(splay_tree_t *config_tree, config_t *cfg) { - splay_insert(config_tree, cfg); +void config_add(avl_tree_t *config_tree, config_t *cfg) { + avl_insert(config_tree, cfg); } -config_t *lookup_config(splay_tree_t *config_tree, char *variable) { +config_t *lookup_config(const avl_tree_t *config_tree, char *variable) { config_t cfg, *found; cfg.variable = variable; cfg.file = NULL; cfg.line = 0; - found = splay_search_closest_greater(config_tree, &cfg); + found = avl_search_closest_greater(config_tree, &cfg); - if(!found) + if(!found) { return NULL; + } - if(strcasecmp(found->variable, variable)) + if(strcasecmp(found->variable, variable)) { return NULL; + } return found; } -config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *cfg) { - splay_node_t *node; +config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg) { + avl_node_t *node; config_t *found; - node = splay_search_node(config_tree, cfg); + node = avl_search_node(config_tree, cfg); if(node) { if(node->next) { found = node->next->data; - if(!strcasecmp(found->variable, cfg->variable)) + if(!strcasecmp(found->variable, cfg->variable)) { return found; + } } } @@ -128,8 +131,9 @@ config_t *lookup_config_next(splay_tree_t *config_tree, const config_t *cfg) { } bool get_config_bool(const config_t *cfg, bool *result) { - if(!cfg) + if(!cfg) { return false; + } if(!strcasecmp(cfg->value, "yes")) { *result = true; @@ -139,28 +143,31 @@ bool get_config_bool(const config_t *cfg, bool *result) { return true; } - logger(DEBUG_ALWAYS, LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d", - cfg->variable, cfg->file, cfg->line); + logger(LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d", + cfg->variable, cfg->file, cfg->line); return false; } bool get_config_int(const config_t *cfg, int *result) { - if(!cfg) + if(!cfg) { return false; + } - if(sscanf(cfg->value, "%d", result) == 1) + if(sscanf(cfg->value, "%d", result) == 1) { return true; + } - logger(DEBUG_ALWAYS, LOG_ERR, "Integer expected for configuration variable %s in %s line %d", - cfg->variable, cfg->file, cfg->line); + logger(LOG_ERR, "Integer expected for configuration variable %s in %s line %d", + cfg->variable, cfg->file, cfg->line); return false; } bool get_config_string(const config_t *cfg, char **result) { - if(!cfg) + if(!cfg) { return false; + } *result = xstrdup(cfg->value); @@ -170,8 +177,9 @@ bool get_config_string(const config_t *cfg, char **result) { bool get_config_address(const config_t *cfg, struct addrinfo **result) { struct addrinfo *ai; - if(!cfg) + if(!cfg) { return false; + } ai = str2addrinfo(cfg->value, NULL, 0); @@ -180,32 +188,33 @@ bool get_config_address(const config_t *cfg, struct addrinfo **result) { return true; } - logger(DEBUG_ALWAYS, LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d", - cfg->variable, cfg->file, cfg->line); + logger(LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d", + cfg->variable, cfg->file, cfg->line); return false; } -bool get_config_subnet(const config_t *cfg, subnet_t ** result) { - subnet_t subnet = {NULL}; +bool get_config_subnet(const config_t *cfg, subnet_t **result) { + subnet_t subnet = {0}; - if(!cfg) + 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); + logger(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); + && !maskcheck(&subnet.net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t))) + || ((subnet.type == SUBNET_IPV6) + && !maskcheck(&subnet.net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t)))) { + logger(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; } @@ -217,27 +226,31 @@ bool get_config_subnet(const config_t *cfg, subnet_t ** result) { /* Read exactly one line and strip the trailing newline if any. */ -static char *readline(FILE * fp, char *buf, size_t buflen) { +static char *readline(FILE *fp, char *buf, size_t buflen) { char *newline = NULL; char *p; - if(feof(fp)) + if(feof(fp)) { return NULL; + } p = fgets(buf, buflen, fp); - if(!p) + if(!p) { return NULL; + } newline = strchr(p, '\n'); - if(!newline) + if(!newline) { return buf; + } - /* kill newline and carriage return if necessary */ - *newline = '\0'; - if(newline > p && newline[-1] == '\r') + *newline = '\0'; /* kill newline */ + + if(newline > p && newline[-1] == '\r') { /* and carriage return if necessary */ newline[-1] = '\0'; + } return buf; } @@ -249,26 +262,32 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) { variable = value = line; eol = line + strlen(line); - while(strchr("\t ", *--eol)) + + while(strchr("\t ", *--eol)) { *eol = '\0'; + } len = strcspn(value, "\t ="); value += len; value += strspn(value, "\t "); + if(*value == '=') { value++; value += strspn(value, "\t "); } + variable[len] = '\0'; if(!*value) { const char err[] = "No value for variable"; - if (fname) - logger(DEBUG_ALWAYS, LOG_ERR, "%s `%s' on line %d while reading config file %s", - err, variable, lineno, fname); + + if(fname) + logger(LOG_ERR, "%s `%s' on line %d while reading config file %s", + err, variable, lineno, fname); else - logger(DEBUG_ALWAYS, LOG_ERR, "%s `%s' in command line option %d", - err, variable, lineno); + logger(LOG_ERR, "%s `%s' in command line option %d", + err, variable, lineno); + return NULL; } @@ -285,7 +304,7 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) { Parse a configuration file and put the results in the configuration tree starting at *base. */ -bool read_config_file(splay_tree_t *config_tree, const char *fname) { +bool read_config_file(avl_tree_t *config_tree, const char *fname) { FILE *fp; char buffer[MAX_STRING_SIZE]; char *line; @@ -297,27 +316,32 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) { fp = fopen(fname, "r"); if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno)); + logger(LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno)); return false; } for(;;) { - line = readline(fp, buffer, sizeof buffer); + line = readline(fp, buffer, sizeof(buffer)); if(!line) { - if(feof(fp)) + if(feof(fp)) { result = true; + } + break; } lineno++; - if(!*line || *line == '#') + if(!*line || *line == '#') { continue; + } if(ignore) { - if(!strncmp(line, "-----END", 8)) + if(!strncmp(line, "-----END", 8)) { ignore = false; + } + continue; } @@ -327,8 +351,11 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) { } cfg = parse_config_line(line, fname, lineno); - if (!cfg) + + if(!cfg) { break; + } + config_add(config_tree, cfg); } @@ -337,27 +364,31 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) { return result; } -void read_config_options(splay_tree_t *config_tree, const char *prefix) { +void read_config_options(avl_tree_t *config_tree, const char *prefix) { size_t prefix_len = prefix ? strlen(prefix) : 0; for(const list_node_t *node = cmdline_conf->tail; node; node = node->prev) { const config_t *cfg = node->data; - config_t *new; if(!prefix) { - if(strchr(cfg->variable, '.')) + if(strchr(cfg->variable, '.')) { continue; + } } else { if(strncmp(prefix, cfg->variable, prefix_len) || - cfg->variable[prefix_len] != '.') + cfg->variable[prefix_len] != '.') { continue; + } } - new = new_config(); - if(prefix) + config_t *new = new_config(); + + if(prefix) { new->variable = xstrdup(cfg->variable + prefix_len + 1); - else + } else { new->variable = xstrdup(cfg->variable); + } + new->value = xstrdup(cfg->value); new->file = NULL; new->line = cfg->line; @@ -367,50 +398,205 @@ void read_config_options(splay_tree_t *config_tree, const char *prefix) { } bool read_server_config(void) { - char *fname; + char fname[PATH_MAX]; bool x; read_config_options(config_tree, NULL); - xasprintf(&fname, "%s" SLASH "tinc.conf", confbase); + snprintf(fname, sizeof(fname), "%s/tinc.conf", confbase); errno = 0; x = read_config_file(config_tree, fname); - if(!x && errno) - logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno)); + // We will try to read the conf files in the "conf.d" dir + if(x) { + char dname[PATH_MAX]; + snprintf(dname, sizeof(dname), "%s/conf.d", confbase); + DIR *dir = opendir(dname); - free(fname); + // If we can find this dir + if(dir) { + struct dirent *ep; - return x; -} + // We list all the files in it + while(x && (ep = readdir(dir))) { + size_t l = strlen(ep->d_name); -bool read_host_config(splay_tree_t *config_tree, const char *name) { - char *fname; - bool x; + // And we try to read the ones that end with ".conf" + if(l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) { + if((size_t)snprintf(fname, sizeof(fname), "%s/%s", dname, ep->d_name) >= sizeof(fname)) { + logger(LOG_ERR, "Pathname too long: %s/%s", dname, ep->d_name); + return false; + } - read_config_options(config_tree, name); + x = read_config_file(config_tree, fname); + } + } - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name); - x = read_config_file(config_tree, fname); - free(fname); - - return x; -} - -bool append_config_file(const char *name, const char *key, const char *value) { - char *fname; - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name); - - FILE *fp = fopen(fname, "a"); - - if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno)); - } else { - fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value); - fclose(fp); + closedir(dir); + } } - free(fname); + if(!x && errno) { + logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno)); + } - return fp != NULL; + return x; } + +bool read_connection_config(connection_t *c) { + char fname[PATH_MAX]; + bool x; + + read_config_options(c->config_tree, c->name); + + snprintf(fname, sizeof(fname), "%s/hosts/%s", confbase, c->name); + x = read_config_file(c->config_tree, fname); + + return x; +} + +static void disable_old_keys(const char *filename) { + char tmpfile[PATH_MAX] = ""; + char buf[1024]; + bool disabled = false; + FILE *r, *w; + + r = fopen(filename, "r"); + + if(!r) { + return; + } + + int len = snprintf(tmpfile, sizeof(tmpfile), "%s.tmp", filename); + + if(len < 0 || len >= PATH_MAX) { + fprintf(stderr, "Pathname too long: %s.tmp\n", filename); + w = NULL; + } else { + w = fopen(tmpfile, "w"); + } + + while(fgets(buf, sizeof(buf), r)) { + if(!strncmp(buf, "-----BEGIN RSA", 14)) { + buf[11] = 'O'; + buf[12] = 'L'; + buf[13] = 'D'; + disabled = true; + } else if(!strncmp(buf, "-----END RSA", 12)) { + buf[ 9] = 'O'; + buf[10] = 'L'; + buf[11] = 'D'; + disabled = true; + } + + if(w && fputs(buf, w) < 0) { + disabled = false; + break; + } + } + + if(w) { + fclose(w); + } + + fclose(r); + + if(!w && disabled) { + fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); + return; + } + + if(disabled) { +#ifdef HAVE_MINGW + // We cannot atomically replace files on Windows. + char bakfile[PATH_MAX] = ""; + snprintf(bakfile, sizeof(bakfile), "%s.bak", filename); + + if(rename(filename, bakfile) || rename(tmpfile, filename)) { + rename(bakfile, filename); +#else + + if(rename(tmpfile, filename)) { +#endif + fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); + } else { +#ifdef HAVE_MINGW + unlink(bakfile); +#endif + fprintf(stderr, "Warning: old key(s) found and disabled.\n"); + } + } + + unlink(tmpfile); +} + +FILE *ask_and_open(const char *filename, const char *what) { + FILE *r; + char directory[PATH_MAX]; + char line[PATH_MAX]; + char abspath[PATH_MAX]; + const char *fn; + + /* Check stdin and stdout */ + if(!isatty(0) || !isatty(1)) { + /* Argh, they are running us from a script or something. Write + the files to the current directory and let them burn in hell + for ever. */ + fn = filename; + } else { + /* Ask for a file and/or directory name. */ + fprintf(stdout, "Please enter a file to save %s to [%s]: ", + what, filename); + fflush(stdout); + + fn = readline(stdin, line, sizeof(line)); + + if(!fn) { + fprintf(stderr, "Error while reading stdin: %s\n", + strerror(errno)); + return NULL; + } + + if(!strlen(fn)) + /* User just pressed enter. */ + { + fn = filename; + } + } + +#ifdef HAVE_MINGW + + if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) { +#else + + if(fn[0] != '/') { +#endif + /* The directory is a relative path or a filename. */ + getcwd(directory, sizeof(directory)); + + if((size_t)snprintf(abspath, sizeof(abspath), "%s/%s", directory, fn) >= sizeof(abspath)) { + fprintf(stderr, "Pathname too long: %s/%s\n", directory, fn); + return NULL; + } + + fn = abspath; + } + + umask(0077); /* Disallow everything for group and other */ + + disable_old_keys(fn); + + /* Open it first to keep the inode busy */ + + r = fopen(fn, "a"); + + if(!r) { + fprintf(stderr, "Error opening file `%s': %s\n", + fn, strerror(errno)); + return NULL; + } + + return r; +} + + diff --git a/src/conf.h b/src/conf.h index 4f39b20..770ada7 100644 --- a/src/conf.h +++ b/src/conf.h @@ -1,7 +1,10 @@ +#ifndef TINC_CONF_H +#define TINC_CONF_H + /* conf.h -- header for conf.c Copyright (C) 1998-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2012 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,10 +21,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_CONF_H__ -#define __TINC_CONF_H__ - -#include "splay_tree.h" +#include "avl_tree.h" #include "list.h" typedef struct config_t { @@ -33,32 +33,35 @@ typedef struct config_t { #include "subnet.h" -extern splay_tree_t *config_tree; +extern avl_tree_t *config_tree; extern int pinginterval; extern int pingtimeout; extern int maxtimeout; +extern int mintimeout; extern bool bypass_security; +extern char *confbase; +extern char *netname; extern list_t *cmdline_conf; -extern void init_configuration(splay_tree_t **); -extern void exit_configuration(splay_tree_t **); -extern config_t *new_config(void) __attribute__ ((__malloc__)); -extern void free_config(config_t *); -extern void config_add(splay_tree_t *, config_t *); -extern config_t *lookup_config(splay_tree_t *, char *); -extern config_t *lookup_config_next(splay_tree_t *, const config_t *); -extern bool get_config_bool(const config_t *, bool *); -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 void init_configuration(avl_tree_t **config_tree); +extern void exit_configuration(avl_tree_t **config_tree); +extern config_t *new_config(void) __attribute__((__malloc__)); +extern void free_config(config_t *cfg); +extern void config_add(avl_tree_t *config_tree, config_t *cfg); +extern config_t *lookup_config(const avl_tree_t *config_tree, char *variable); +extern config_t *lookup_config_next(const avl_tree_t *config_tree, const config_t *cfg); +extern bool get_config_bool(const config_t *cfg, bool *result); +extern bool get_config_int(const config_t *cfg, int *result); +extern bool get_config_string(const config_t *cfg, char **result); +extern bool get_config_address(const config_t *cfg, struct addrinfo **result); +extern bool get_config_subnet(const config_t *cfg, struct subnet_t **result); -extern config_t *parse_config_line(char *, const char *, int); -extern bool read_config_file(splay_tree_t *, const char *); -extern void read_config_options(splay_tree_t *, const char *); +extern config_t *parse_config_line(char *line, const char *fname, int lineno); +extern bool read_config_file(avl_tree_t *config_tree, const char *fname); +extern void read_config_options(avl_tree_t *config_tree, const char *prefix); extern bool read_server_config(void); -extern bool read_host_config(splay_tree_t *, const char *); -extern bool append_config_file(const char *, const char *, const char *); +extern bool read_connection_config(struct connection_t *c); +extern FILE *ask_and_open(const char *fname, const char *what); -#endif /* __TINC_CONF_H__ */ +#endif diff --git a/src/connection.c b/src/connection.c index 496f674..d137af1 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1,6 +1,6 @@ /* connection.c -- connection list management - Copyright (C) 2000-2013 Guus Sliepen , + Copyright (C) 2000-2016 Guus Sliepen , 2000-2005 Ivo Timmermans 2008 Max Rijevski @@ -21,83 +21,131 @@ #include "system.h" -#include "list.h" -#include "cipher.h" +#include "avl_tree.h" #include "conf.h" -#include "control_common.h" -#include "list.h" #include "logger.h" -#include "rsa.h" #include "subnet.h" #include "utils.h" #include "xalloc.h" -list_t *connection_list; +avl_tree_t *connection_tree; /* Meta connections */ connection_t *everyone; +static int connection_compare(const connection_t *a, const connection_t *b) { + return a < b ? -1 : a == b ? 0 : 1; +} + void init_connections(void) { - connection_list = list_alloc((list_action_t) free_connection); + connection_tree = avl_alloc_tree((avl_compare_t) connection_compare, (avl_action_t) free_connection); everyone = new_connection(); everyone->name = xstrdup("everyone"); everyone->hostname = xstrdup("BROADCAST"); } void exit_connections(void) { - list_delete_list(connection_list); + avl_delete_tree(connection_tree); free_connection(everyone); } connection_t *new_connection(void) { - return xzalloc(sizeof(connection_t)); + connection_t *c; + + c = xmalloc_and_zero(sizeof(connection_t)); + + if(!c) { + return NULL; + } + + gettimeofday(&c->start, NULL); + + return c; +} + +void free_connection_partially(connection_t *c) { + free(c->inkey); + free(c->outkey); + free(c->mychallenge); + free(c->hischallenge); + free(c->outbuf); + + c->inkey = NULL; + c->outkey = NULL; + c->mychallenge = NULL; + c->hischallenge = NULL; + c->outbuf = NULL; + + c->status.pinged = false; + c->status.active = false; + c->status.connecting = false; + c->status.timeout = false; + c->status.encryptout = false; + c->status.decryptin = false; + c->status.mst = false; + + c->options = 0; + c->buflen = 0; + c->reqlen = 0; + c->tcplen = 0; + c->allow_request = 0; + c->outbuflen = 0; + c->outbufsize = 0; + c->outbufstart = 0; + c->last_ping_time = 0; + c->last_flushed_time = 0; + c->inbudget = 0; + c->outbudget = 0; + + if(c->inctx) { + EVP_CIPHER_CTX_reset(c->inctx); + free(c->inctx); + c->inctx = NULL; + } + + if(c->outctx) { + EVP_CIPHER_CTX_reset(c->outctx); + free(c->outctx); + c->outctx = NULL; + } + + if(c->rsa_key) { + RSA_free(c->rsa_key); + c->rsa_key = NULL; + } } void free_connection(connection_t *c) { - if(!c) - return; - - cipher_close(c->incipher); - digest_close(c->indigest); - cipher_close(c->outcipher); - digest_close(c->outdigest); - - sptps_stop(&c->sptps); - ecdsa_free(c->ecdsa); - rsa_free(c->rsa); - - free(c->hischallenge); - - buffer_clear(&c->inbuf); - buffer_clear(&c->outbuf); - - io_del(&c->io); - - if(c->socket > 0) - closesocket(c->socket); + free_connection_partially(c); free(c->name); free(c->hostname); - if(c->config_tree) + if(c->config_tree) { exit_configuration(&c->config_tree); + } free(c); } void connection_add(connection_t *c) { - list_insert_tail(connection_list, c); + avl_insert(connection_tree, c); } void connection_del(connection_t *c) { - list_delete(connection_list, c); + avl_delete(connection_tree, 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)); +void dump_connections(void) { + avl_node_t *node; + connection_t *c; + + logger(LOG_DEBUG, "Connections:"); + + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + logger(LOG_DEBUG, " %s at %s options %x socket %d status %04x outbuf %d/%d/%d", + c->name, c->hostname, c->options, c->socket, bitfield_to_int(&c->status, sizeof(c->status)), + c->outbufsize, c->outbufstart, c->outbuflen); } - return send_request(cdump, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS); + logger(LOG_DEBUG, "End of connections."); } diff --git a/src/connection.h b/src/connection.h index b5d3d18..d619e85 100644 --- a/src/connection.h +++ b/src/connection.h @@ -1,6 +1,9 @@ +#ifndef TINC_CONNECTION_H +#define TINC_CONNECTION_H + /* connection.h -- header for connection.c - Copyright (C) 2000-2013 Guus Sliepen , + Copyright (C) 2000-2016 Guus Sliepen , 2000-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -18,41 +21,35 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_CONNECTION_H__ -#define __TINC_CONNECTION_H__ +#include +#include -#include "buffer.h" -#include "cipher.h" -#include "digest.h" -#include "rsa.h" -#include "list.h" -#include "sptps.h" +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_CIPHER_CTX_reset(c) EVP_CIPHER_CTX_cleanup(c) +#endif + +#include "avl_tree.h" #define OPTION_INDIRECT 0x0001 #define OPTION_TCPONLY 0x0002 #define OPTION_PMTU_DISCOVERY 0x0004 #define OPTION_CLAMP_MSS 0x0008 -#define OPTION_VERSION(x) ((x) >> 24) /* Top 8 bits are for protocol minor version */ typedef struct connection_status_t { - unsigned int pinged:1; /* sent ping */ - unsigned int active:1; /* 1 if active.. */ - unsigned int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ - unsigned int unused_termreq:1; /* the termination of this connection was requested */ - unsigned int remove_unused:1; /* Set to 1 if you want this connection removed */ - unsigned int timeout_unused:1; /* 1 if gotten timeout */ - unsigned int encryptout:1; /* 1 if we can encrypt outgoing traffic */ - unsigned int decryptin:1; /* 1 if we have to decrypt incoming traffic */ - unsigned int mst:1; /* 1 if this connection is part of a minimum spanning tree */ - unsigned int control:1; /* 1 if this is a control connection */ - unsigned int pcap:1; /* 1 if this is a control connection requesting packet capture */ - unsigned int log:1; /* 1 if this is a control connection requesting log dump */ - unsigned int invitation:1; /* 1 if this is an invitation */ - unsigned int invitation_used:1; /* 1 if the invitation has been consumed */ - unsigned int unused:19; + unsigned int pinged: 1; /* sent ping */ + unsigned int active: 1; /* 1 if active.. */ + unsigned int connecting: 1; /* 1 if we are waiting for a non-blocking connect() to finish */ + unsigned int unused_termreq: 1; /* the termination of this connection was requested */ + unsigned int remove: 1; /* Set to 1 if you want this connection removed */ + unsigned int timeout: 1; /* 1 if gotten timeout */ + unsigned int encryptout: 1; /* 1 if we can encrypt outgoing traffic */ + unsigned int decryptin: 1; /* 1 if we have to decrypt incoming traffic */ + unsigned int mst: 1; /* 1 if this connection is part of a minimum spanning tree */ + unsigned int proxy_passed: 1; /* 1 if we are connecting via a proxy and we have finished talking with it */ + unsigned int tarpit: 1; /* 1 if the connection should be added to the tarpit */ + unsigned int unused: 21; } connection_status_t; -#include "ecdsa.h" #include "edge.h" #include "net.h" #include "node.h" @@ -62,8 +59,7 @@ typedef struct connection_t { union sockaddr_t address; /* his real (internet) ip */ char *hostname; /* the hostname of its real ip */ - int protocol_major; /* used protocol */ - int protocol_minor; /* used protocol */ + int protocol_version; /* used protocol */ int socket; /* socket used for this connection */ uint32_t options; /* options for this connection */ @@ -75,41 +71,53 @@ typedef struct connection_t { struct node_t *node; /* node associated with the other end */ struct edge_t *edge; /* edge associated with this connection */ - rsa_t *rsa; /* his public RSA key */ - ecdsa_t *ecdsa; /* his public ECDSA key */ - cipher_t *incipher; /* Cipher he will use to send data to us */ - cipher_t *outcipher; /* Cipher we will use to send data to him */ - digest_t *indigest; - digest_t *outdigest; - sptps_t sptps; - + RSA *rsa_key; /* his public/private key */ + const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */ + const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */ + EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */ + EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */ + uint64_t inbudget; /* Encrypted bytes send budget */ + uint64_t outbudget; /* Encrypted bytes receive budget */ + char *inkey; /* His symmetric meta key + iv */ + char *outkey; /* Our symmetric meta key + iv */ + int inkeylength; /* Length of his key + iv */ + int outkeylength; /* Length of our key + iv */ + const EVP_MD *indigest; + const EVP_MD *outdigest; int inmaclength; int outmaclength; int incompression; int outcompression; + char *mychallenge; /* challenge we received from him */ + char *hischallenge; /* challenge we sent to him */ - char *hischallenge; /* The challenge we sent to him */ - - struct buffer_t inbuf; - struct buffer_t outbuf; - io_t io; /* input/output event on this metadata connection */ - int tcplen; /* length of incoming TCPpacket */ + char buffer[MAXBUFSIZE]; /* metadata input buffer */ + int buflen; /* bytes read into buffer */ + int reqlen; /* length of incoming request */ + length_t tcplen; /* length of incoming TCPpacket */ int allow_request; /* defined if there's only one request possible */ - time_t last_ping_time; /* last time we saw some activity from the other end or pinged them */ + char *outbuf; /* metadata output buffer */ + int outbufstart; /* index of first meaningful byte in output buffer */ + int outbuflen; /* number of meaningful bytes in output buffer */ + int outbufsize; /* number of bytes allocated to output buffer */ - splay_tree_t *config_tree; /* Pointer to configuration tree belonging to him */ + time_t last_ping_time; /* last time we saw some activity from the other end or pinged them */ + time_t last_flushed_time; /* last time buffer was empty. Only meaningful if outbuflen > 0 */ + + avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */ } connection_t; -extern list_t *connection_list; +extern avl_tree_t *connection_tree; extern connection_t *everyone; extern void init_connections(void); extern void exit_connections(void); -extern connection_t *new_connection(void) __attribute__ ((__malloc__)); -extern void free_connection(connection_t *); -extern void connection_add(connection_t *); -extern void connection_del(connection_t *); -extern bool dump_connections(struct connection_t *); +extern connection_t *new_connection(void) __attribute__((__malloc__)); +extern void free_connection(connection_t *c); +extern void free_connection_partially(connection_t *c); +extern void connection_add(connection_t *c); +extern void connection_del(connection_t *c); +extern void dump_connections(void); -#endif /* __TINC_CONNECTION_H__ */ +#endif diff --git a/src/control.c b/src/control.c deleted file mode 100644 index 84098be..0000000 --- a/src/control.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - control.c -- Control socket handling. - Copyright (C) 2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" -#include "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); - - return true; -} - -void exit_control(void) { - unlink(pidfilename); -} diff --git a/src/control.h b/src/control.h deleted file mode 100644 index ce8145a..0000000 --- a/src/control.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - control.h -- header for control.c. - Copyright (C) 2007 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_CONTROL_H__ -#define __TINC_CONTROL_H__ - -extern bool init_control(); -extern void exit_control(); -extern char controlcookie[]; - -#endif diff --git a/src/control_common.h b/src/control_common.h deleted file mode 100644 index cd54889..0000000 --- a/src/control_common.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - control_protocol.h -- control socket protocol. - Copyright (C) 2007 Scott Lamb - 2009-2012 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#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 diff --git a/src/crypto.h b/src/crypto.h deleted file mode 100644 index cd3654f..0000000 --- a/src/crypto.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - crypto.h -- header for crypto.c - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_CRYPTO_H__ -#define __TINC_CRYPTO_H__ - -extern void crypto_init(); -extern void crypto_exit(); -extern void randomize(void *, size_t); - -#endif diff --git a/src/cygwin/.deps/device.Po b/src/cygwin/.deps/device.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/cygwin/.deps/device.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/cygwin/device.c b/src/cygwin/device.c index f4dcae4..1165d67 100644 --- a/src/cygwin/device.c +++ b/src/cygwin/device.c @@ -1,7 +1,7 @@ /* device.c -- Interaction with Windows tap driver in a Cygwin environment Copyright (C) 2002-2005 Ivo Timmermans, - 2002-2013 Guus Sliepen + 2002-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ */ #include "../system.h" +#include "../net.h" #include #include @@ -26,8 +27,6 @@ #include "../conf.h" #include "../device.h" #include "../logger.h" -#include "../names.h" -#include "../net.h" #include "../route.h" #include "../utils.h" #include "../xalloc.h" @@ -38,7 +37,7 @@ int device_fd = -1; static HANDLE device_handle = INVALID_HANDLE_VALUE; char *device = NULL; char *iface = NULL; -static char *device_info = NULL; +static const char *device_info = "Windows tap device"; static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; @@ -62,51 +61,62 @@ static bool setup_device(void) { get_config_string(lookup_config(config_tree, "Device"), &device); get_config_string(lookup_config(config_tree, "Interface"), &iface); + if(device && iface) { + logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected"); + } + /* 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())); + logger(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)) + 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); + snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid); - if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) { continue; + } - len = sizeof adaptername; + len = sizeof(adaptername); err = RegQueryValueEx(key2, "Name", 0, 0, adaptername, &len); RegCloseKey(key2); - if(err) + if(err) { continue; + } if(device) { if(!strcmp(device, adapterid)) { found = true; break; - } else + } else { continue; + } } if(iface) { if(!strcmp(iface, adaptername)) { found = true; break; - } else + } else { continue; + } } - snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); + 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; @@ -117,33 +127,35 @@ static bool setup_device(void) { RegCloseKey(key); if(!found) { - logger(DEBUG_ALWAYS, LOG_ERR, "No Windows tap device found!"); + logger(LOG_ERR, "No Windows tap device found!"); return false; } - if(!device) + if(!device) { device = xstrdup(adapterid); + } - if(!iface) + if(!iface) { iface = xstrdup(adaptername); + } - snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, device); + 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)); + logger(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); + 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())); + logger(LOG_ERR, "Could not open Windows tap device %s (%s) for writing: %s", device, iface, winerror(GetLastError())); return false; } @@ -151,8 +163,8 @@ static bool setup_device(void) { /* 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())); + if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) { + logger(LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError())); return false; } @@ -165,7 +177,7 @@ static bool setup_device(void) { reader_pid = fork(); if(reader_pid == -1) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "System call `%s' failed: %s", "fork", strerror(errno)); + logger(LOG_DEBUG, "System call `%s' failed: %s", "fork", strerror(errno)); return false; } @@ -174,20 +186,20 @@ static bool setup_device(void) { It passes everything it reads to the socket. */ char buf[MTU]; - long inlen; + long lenin; 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())); + logger(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."); + logger(LOG_DEBUG, "Tap reader forked and running."); /* Notify success */ @@ -197,20 +209,19 @@ static bool setup_device(void) { /* Pass packets */ for(;;) { - ReadFile(device_handle, buf, MTU, &inlen, NULL); - write(sp[1], buf, inlen); + ReadFile(device_handle, buf, MTU, &lenin, NULL); + write(sp[1], buf, lenin); } } read(device_fd, &gelukt, 1); + if(gelukt != 1) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Tap reader failed!"); + logger(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); + logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info); return true; } @@ -227,32 +238,32 @@ static void close_device(void) { } static bool read_packet(vpn_packet_t *packet) { - int inlen; + int lenin; - 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)); + if((lenin = read(sp[0], packet->data, MTU)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); return false; } - packet->len = inlen; + packet->len = lenin; device_total_in += packet->len; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, - device_info); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); return true; } static bool write_packet(vpn_packet_t *packet) { - long outlen; + long lenout; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", - packet->len, device_info); + ifdebug(TRAFFIC) logger(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())); + if(!WriteFile(device_handle, packet->data, packet->len, &lenout, NULL)) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(GetLastError())); return false; } @@ -262,9 +273,9 @@ static bool write_packet(vpn_packet_t *packet) { } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t os_devops = { diff --git a/src/device.h b/src/device.h index c91f035..6bfc44d 100644 --- a/src/device.h +++ b/src/device.h @@ -1,3 +1,6 @@ +#ifndef TINC_DEVICE_H +#define TINC_DEVICE_H + /* device.h -- generic header for device.c Copyright (C) 2001-2005 Ivo Timmermans @@ -18,25 +21,18 @@ 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; +extern char *iface; typedef struct devops_t { bool (*setup)(void); void (*close)(void); - bool (*read)(struct vpn_packet_t *); - bool (*write)(struct vpn_packet_t *); + bool (*read)(struct vpn_packet_t *packet); + bool (*write)(struct vpn_packet_t *packet); void (*dump_stats)(void); } devops_t; @@ -48,4 +44,4 @@ extern const devops_t uml_devops; extern const devops_t vde_devops; extern devops_t devops; -#endif /* __TINC_DEVICE_H__ */ +#endif diff --git a/src/digest.h b/src/digest.h deleted file mode 100644 index 1e14945..0000000 --- a/src/digest.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - digest.h -- header file digest.c - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_DIGEST_H__ -#define __TINC_DIGEST_H__ - -#define DIGEST_MAX_SIZE 64 - -typedef struct digest digest_t; - -extern digest_t *digest_open_by_name(const char *name, int maclength) __attribute__ ((__malloc__)); -extern digest_t *digest_open_by_nid(int nid, int maclength) __attribute__ ((__malloc__)); -extern digest_t *digest_open_sha1(int maclength) __attribute__ ((__malloc__)); -extern void digest_close(digest_t *); -extern bool digest_create(digest_t *, const void *indata, size_t inlen, void *outdata) __attribute__ ((__warn_unused_result__)); -extern bool digest_verify(digest_t *, const void *indata, size_t inlen, const void *digestdata) __attribute__ ((__warn_unused_result__)); -extern bool digest_set_key(digest_t *, const void *key, size_t len) __attribute__ ((__warn_unused_result__)); -extern int digest_get_nid(const digest_t *); -extern size_t digest_keylength(const digest_t *); -extern size_t digest_length(const digest_t *); -extern bool digest_active(const digest_t *); - -#endif diff --git a/src/dropin.c b/src/dropin.c index 6d40850..93511f1 100644 --- a/src/dropin.c +++ b/src/dropin.c @@ -1,7 +1,7 @@ /* dropin.c -- a set of drop-in replacements for libc functions Copyright (C) 2000-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,8 +50,9 @@ int daemon(int nochdir, int noclose) { } /* If we are the parent, terminate */ - if(pid) + if(pid) { exit(0); + } /* Detach by becoming the new process group leader */ if(setsid() < 0) { @@ -86,40 +87,6 @@ int daemon(int nochdir, int noclose) { } #endif -#ifndef HAVE_GET_CURRENT_DIR_NAME -/* - Replacement for the GNU get_current_dir_name function: - - get_current_dir_name will malloc(3) an array big enough to hold the - current directory name. If the environment variable PWD is set, and - its value is correct, then that value will be returned. -*/ -char *get_current_dir_name(void) { - size_t size; - char *buf; - char *r; - - /* Start with 100 bytes. If this turns out to be insufficient to - contain the working directory, double the size. */ - size = 100; - buf = xmalloc(size); - - errno = 0; /* Success */ - r = getcwd(buf, size); - - /* getcwd returns NULL and sets errno to ERANGE if the bufferspace - is insufficient to contain the entire working directory. */ - while(r == NULL && errno == ERANGE) { - free(buf); - size <<= 1; /* double the size */ - buf = xmalloc(size); - r = getcwd(buf, size); - } - - return buf; -} -#endif - #ifndef HAVE_ASPRINTF int asprintf(char **buf, const char *fmt, ...) { int result; @@ -140,10 +107,12 @@ int vasprintf(char **buf, const char *fmt, va_list ap) { va_copy(aq, ap); status = vsnprintf(*buf, len, fmt, aq); + buf[len - 1] = 0; va_end(aq); - if(status >= 0) + if(status >= 0) { *buf = xrealloc(*buf, status + 1); + } if(status > len - 1) { len = status; @@ -158,18 +127,8 @@ int vasprintf(char **buf, const char *fmt, va_list ap) { #ifndef HAVE_GETTIMEOFDAY int gettimeofday(struct timeval *tv, void *tz) { -#ifdef HAVE_MINGW - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - uint64_t lt = (uint64_t)ft.dwLowDateTime | ((uint64_t)ft.dwHighDateTime << 32); - lt -= 116444736000000000ULL; - tv->tv_sec = lt / 10000000; - tv->tv_usec = (lt / 10) % 1000000; -#else -#warning No high resolution time source! tv->tv_sec = time(NULL); tv->tv_usec = 0; -#endif return 0; } #endif diff --git a/src/dropin.h b/src/dropin.h index 5601a31..012099b 100644 --- a/src/dropin.h +++ b/src/dropin.h @@ -1,7 +1,10 @@ +#ifndef TINC_DROPIN_H +#define TINC_DROPIN_H + /* dropin.h -- header file for dropin.c Copyright (C) 2000-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2011 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,14 +21,11 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __DROPIN_H__ -#define __DROPIN_H__ - #include "fake-getaddrinfo.h" #include "fake-getnameinfo.h" #ifndef HAVE_DAEMON -extern int daemon(int, int); +extern int daemon(int nochdir, int noclose); #endif #ifndef HAVE_GET_CURRENT_DIR_NAME @@ -33,41 +33,16 @@ extern char *get_current_dir_name(void); #endif #ifndef HAVE_ASPRINTF -extern int asprintf(char **, const char *, ...); -extern int vasprintf(char **, const char *, va_list ap); +extern int asprintf(char **buf, const char *fmt, ...); +extern int vasprintf(char **buf, const char *fmt, va_list ap); #endif #ifndef HAVE_GETTIMEOFDAY -extern int gettimeofday(struct timeval *, void *); +extern int gettimeofday(struct timeval *tv, void *tz); #endif #ifndef HAVE_USLEEP extern int usleep(long long usec); #endif -#ifndef timeradd -#define timeradd(a, b, r) do {\ - (r)->tv_sec = (a)->tv_sec + (b)->tv_sec;\ - (r)->tv_usec = (a)->tv_usec + (b)->tv_usec;\ - if((r)->tv_usec >= 1000000)\ - (r)->tv_sec++, (r)->tv_usec -= 1000000;\ -} while (0) #endif - -#ifndef timersub -#define timersub(a, b, r) do {\ - (r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\ - (r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\ - if((r)->tv_usec < 0)\ - (r)->tv_sec--, (r)->tv_usec += 1000000;\ -} while (0) -#endif - -#ifdef HAVE_MINGW -#define mkdir(a, b) mkdir(a) -#ifndef SHUT_RDWR -#define SHUT_RDWR SD_BOTH -#endif -#endif - -#endif /* __DROPIN_H__ */ diff --git a/src/dummy_device.c b/src/dummy_device.c index d508180..d1d751b 100644 --- a/src/dummy_device.c +++ b/src/dummy_device.c @@ -1,6 +1,6 @@ /* device.c -- Dummy device - Copyright (C) 2011-2012 Guus Sliepen + Copyright (C) 2011 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,23 +22,27 @@ #include "device.h" #include "logger.h" #include "net.h" +#include "xalloc.h" -static char *device_info = "dummy device"; +static const char *device_info = "dummy device"; static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; static bool setup_device(void) { - device = "dummy"; - iface = "dummy"; - logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info); + device = xstrdup("dummy"); + iface = xstrdup("dummy"); + logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info); return true; } static void close_device(void) { + free(device); + free(iface); } static bool read_packet(vpn_packet_t *packet) { + (void)packet; return false; } @@ -48,9 +52,9 @@ static bool write_packet(vpn_packet_t *packet) { } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t dummy_devops = { diff --git a/src/ecdsa.h b/src/ecdsa.h deleted file mode 100644 index d03a58e..0000000 --- a/src/ecdsa.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - ecdsa.h -- ECDSA key handling - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_ECDSA_H__ -#define __TINC_ECDSA_H__ - -#ifndef __TINC_ECDSA_INTERNAL__ -typedef struct ecdsa ecdsa_t; -#endif - -extern ecdsa_t *ecdsa_set_base64_public_key(const char *p) __attribute__ ((__malloc__)); -extern char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa); -extern ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) __attribute__ ((__malloc__)); -extern ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) __attribute__ ((__malloc__)); -extern size_t ecdsa_size(ecdsa_t *ecdsa); -extern bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t inlen, void *out) __attribute__ ((__warn_unused_result__)); -extern bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t inlen, const void *out) __attribute__ ((__warn_unused_result__)); -extern bool ecdsa_active(ecdsa_t *ecdsa); -extern void ecdsa_free(ecdsa_t *ecdsa); - -#endif diff --git a/src/ecdsagen.h b/src/ecdsagen.h deleted file mode 100644 index 12e5c00..0000000 --- a/src/ecdsagen.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - ecdsagen.h -- ECDSA key generation and export - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_ECDSAGEN_H__ -#define __TINC_ECDSAGEN_H__ - -#include "ecdsa.h" - -extern ecdsa_t *ecdsa_generate(void) __attribute__ ((__malloc__)); -extern bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) __attribute__ ((__warn_unused_result__)); -extern bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) __attribute__ ((__warn_unused_result__)); - -#endif diff --git a/src/edge.c b/src/edge.c index f185b4f..c30d6cc 100644 --- a/src/edge.c +++ b/src/edge.c @@ -1,6 +1,6 @@ /* edge.c -- edge tree management - Copyright (C) 2000-2013 Guus Sliepen , + Copyright (C) 2000-2006 Guus Sliepen , 2000-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -20,8 +20,7 @@ #include "system.h" -#include "splay_tree.h" -#include "control_common.h" +#include "avl_tree.h" #include "edge.h" #include "logger.h" #include "netutl.h" @@ -29,7 +28,7 @@ #include "utils.h" #include "xalloc.h" -splay_tree_t *edge_weight_tree; +avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */ static int edge_compare(const edge_t *a, const edge_t *b) { return strcmp(a->to->name, b->to->name); @@ -40,37 +39,39 @@ static int edge_weight_compare(const edge_t *a, const edge_t *b) { result = a->weight - b->weight; - if(result) + if(result) { return result; + } result = strcmp(a->from->name, b->from->name); - if(result) + if(result) { return result; + } return strcmp(a->to->name, b->to->name); } void init_edges(void) { - edge_weight_tree = splay_alloc_tree((splay_compare_t) edge_weight_compare, NULL); + edge_weight_tree = avl_alloc_tree((avl_compare_t) edge_weight_compare, NULL); } -splay_tree_t *new_edge_tree(void) { - return splay_alloc_tree((splay_compare_t) edge_compare, (splay_action_t) free_edge); +avl_tree_t *new_edge_tree(void) { + return avl_alloc_tree((avl_compare_t) edge_compare, (avl_action_t) free_edge); } -void free_edge_tree(splay_tree_t *edge_tree) { - splay_delete_tree(edge_tree); +void free_edge_tree(avl_tree_t *edge_tree) { + avl_delete_tree(edge_tree); } void exit_edges(void) { - splay_delete_tree(edge_weight_tree); + avl_delete_tree(edge_weight_tree); } /* Creation and deletion of connection elements */ edge_t *new_edge(void) { - return xzalloc(sizeof(edge_t)); + return xmalloc_and_zero(sizeof(edge_t)); } void free_edge(edge_t *e) { @@ -80,21 +81,23 @@ void free_edge(edge_t *e) { } void edge_add(edge_t *e) { - splay_insert(edge_weight_tree, e); - splay_insert(e->from->edge_tree, e); + avl_insert(edge_weight_tree, e); + avl_insert(e->from->edge_tree, e); e->reverse = lookup_edge(e->to, e->from); - if(e->reverse) + if(e->reverse) { e->reverse->reverse = e; + } } void edge_del(edge_t *e) { - if(e->reverse) + if(e->reverse) { e->reverse->reverse = NULL; + } - splay_delete(edge_weight_tree, e); - splay_delete(e->from->edge_tree, e); + avl_delete(edge_weight_tree, e); + avl_delete(e->from->edge_tree, e); } edge_t *lookup_edge(node_t *from, node_t *to) { @@ -103,20 +106,28 @@ edge_t *lookup_edge(node_t *from, node_t *to) { v.from = from; v.to = to; - return splay_search(from->edge_tree, &v); + return avl_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); +void dump_edges(void) { + avl_node_t *node, *node2; + node_t *n; + edge_t *e; + char *address; + + logger(LOG_DEBUG, "Edges:"); + + for(node = node_tree->head; node; node = node->next) { + n = node->data; + + for(node2 = n->edge_tree->head; node2; node2 = node2->next) { + e = node2->data; + address = sockaddr2hostname(&e->address); + logger(LOG_DEBUG, " %s to %s at %s options %x weight %d", + e->from->name, e->to->name, address, e->options, e->weight); free(address); } } - return send_request(c, "%d %d", CONTROL, REQ_DUMP_EDGES); + logger(LOG_DEBUG, "End of edges."); } diff --git a/src/edge.h b/src/edge.h index cbd9e5a..a7a6302 100644 --- a/src/edge.h +++ b/src/edge.h @@ -1,6 +1,9 @@ +#ifndef TINC_EDGE_H +#define TINC_EDGE_H + /* edge.h -- header for edge.c - Copyright (C) 2001-2012 Guus Sliepen , + Copyright (C) 2001-2006 Guus Sliepen , 2001-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -18,10 +21,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_EDGE_H__ -#define __TINC_EDGE_H__ - -#include "splay_tree.h" +#include "avl_tree.h" #include "connection.h" #include "net.h" #include "node.h" @@ -31,24 +31,24 @@ typedef struct edge_t { struct node_t *to; sockaddr_t address; - uint32_t options; /* options turned on for this edge */ - int weight; /* weight of this edge */ + uint32_t options; /* options turned on for this edge */ + int weight; /* weight of this edge */ - struct connection_t *connection; /* connection associated with this edge, if available */ - struct edge_t *reverse; /* edge in the opposite direction, if available */ + struct connection_t *connection; /* connection associated with this edge, if available */ + struct edge_t *reverse; /* edge in the opposite direction, if available */ } edge_t; -extern splay_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */ +extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */ extern void init_edges(void); extern void exit_edges(void); -extern edge_t *new_edge(void) __attribute__ ((__malloc__)); -extern void free_edge(edge_t *); -extern splay_tree_t *new_edge_tree(void) __attribute__ ((__malloc__)); -extern void free_edge_tree(splay_tree_t *); -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 *); +extern edge_t *new_edge(void) __attribute__((__malloc__)); +extern void free_edge(edge_t *e); +extern avl_tree_t *new_edge_tree(void) __attribute__((__malloc__)); +extern void free_edge_tree(avl_tree_t *edge_tree); +extern void edge_add(edge_t *e); +extern void edge_del(edge_t *e); +extern edge_t *lookup_edge(struct node_t *from, struct node_t *to); +extern void dump_edges(void); -#endif /* __TINC_EDGE_H__ */ +#endif diff --git a/src/ethernet.h b/src/ethernet.h index a8b6420..32f5553 100644 --- a/src/ethernet.h +++ b/src/ethernet.h @@ -1,3 +1,6 @@ +#ifndef TINC_ETHERNET_H +#define TINC_ETHERNET_H + /* ethernet.h -- missing Ethernet related definitions Copyright (C) 2005 Ivo Timmermans @@ -18,9 +21,6 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_ETHERNET_H__ -#define __TINC_ETHERNET_H__ - #ifndef ETH_ALEN #define ETH_ALEN 6 #endif @@ -50,7 +50,7 @@ struct ether_header { uint8_t ether_dhost[ETH_ALEN]; uint8_t ether_shost[ETH_ALEN]; uint16_t ether_type; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #endif #ifndef HAVE_STRUCT_ARPHDR @@ -60,7 +60,7 @@ struct arphdr { uint8_t ar_hln; uint8_t ar_pln; uint16_t ar_op; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #define ARPOP_REQUEST 1 #define ARPOP_REPLY 2 @@ -78,7 +78,7 @@ struct ether_arp { uint8_t arp_spa[4]; uint8_t arp_tha[ETH_ALEN]; uint8_t arp_tpa[4]; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #define arp_hrd ea_hdr.ar_hrd #define arp_pro ea_hdr.ar_pro #define arp_hln ea_hdr.ar_hln @@ -86,4 +86,4 @@ struct ether_arp { #define arp_op ea_hdr.ar_op #endif -#endif /* __TINC_ETHERNET_H__ */ +#endif diff --git a/src/event.c b/src/event.c index 5a1e4f5..1223222 100644 --- a/src/event.c +++ b/src/event.c @@ -1,6 +1,7 @@ /* - event.c -- I/O, timeout and signal event handling - Copyright (C) 2012-2013 Guus Sliepen + event.c -- event queue + Copyright (C) 2002-2009 Guus Sliepen , + 2002-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 @@ -19,238 +20,102 @@ #include "system.h" -#include "dropin.h" +#include "avl_tree.h" #include "event.h" -#include "net.h" #include "utils.h" +#include "xalloc.h" -struct timeval now; +avl_tree_t *event_tree; +extern time_t now; -static fd_set readfds; -static fd_set writefds; -static volatile bool running; +static int id; -static int io_compare(const io_t *a, const io_t *b) { - return a->fd - b->fd; -} - -static int timeout_compare(const timeout_t *a, const timeout_t *b) { - struct timeval diff; - timersub(&a->tv, &b->tv, &diff); - if(diff.tv_sec < 0) - return -1; - if(diff.tv_sec > 0) +static int event_compare(const event_t *a, const event_t *b) { + if(a->time > b->time) { return 1; - if(diff.tv_usec < 0) + } + + if(a->time < b->time) { return -1; - if(diff.tv_usec > 0) - return 1; - if(a < b) - return -1; - if(a > b) - return 1; - return 0; + } + + return a->id - b->id; } -static splay_tree_t io_tree = {.compare = (splay_compare_t)io_compare}; -static splay_tree_t timeout_tree = {.compare = (splay_compare_t)timeout_compare}; +void init_events(void) { + event_tree = avl_alloc_tree((avl_compare_t) event_compare, (avl_action_t) free_event); +} -void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) { - if(io->cb) +void exit_events(void) { + avl_delete_tree(event_tree); +} + +void expire_events(void) { + avl_node_t *node; + event_t *event; + time_t diff; + + /* + * Make all events appear expired by subtracting the difference between + * the expiration time of the last event and the current time. + */ + + if(!event_tree->tail) { return; + } - io->fd = fd; - io->cb = cb; - io->data = data; - io->node.data = io; + event = event_tree->tail->data; - io_set(io, flags); - - if(!splay_insert_node(&io_tree, &io->node)) - abort(); -} - -void io_set(io_t *io, int flags) { - io->flags = flags; - - if(flags & IO_READ) - FD_SET(io->fd, &readfds); - else - FD_CLR(io->fd, &readfds); - - if(flags & IO_WRITE) - FD_SET(io->fd, &writefds); - else - FD_CLR(io->fd, &writefds); -} - -void io_del(io_t *io) { - if(!io->cb) + if(event->time <= now) { return; + } - io_set(io, 0); + diff = event->time - now; - splay_unlink_node(&io_tree, &io->node); - io->cb = NULL; + for(node = event_tree->head; node; node = node->next) { + event = node->data; + event->time -= diff; + } } -void timeout_add(timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv) { - timeout->cb = cb; - timeout->data = data; - timeout->node.data = timeout; - - timeout_set(timeout, tv); +event_t *new_event(void) { + return xmalloc_and_zero(sizeof(event_t)); } -void timeout_set(timeout_t *timeout, struct timeval *tv) { - if(timerisset(&timeout->tv)) - splay_unlink_node(&timeout_tree, &timeout->node); - - if(!now.tv_sec) - gettimeofday(&now, NULL); - - timeradd(&now, tv, &timeout->tv); - - if(!splay_insert_node(&timeout_tree, &timeout->node)) - abort(); +void free_event(event_t *event) { + free(event); } -void timeout_del(timeout_t *timeout) { - if(!timeout->cb) - return; - - splay_unlink_node(&timeout_tree, &timeout->node); - timeout->cb = 0; - timeout->tv = (struct timeval){0, 0}; +void event_add(event_t *event) { + event->id = ++id; + avl_insert(event_tree, event); } -#ifndef HAVE_MINGW -static int signal_compare(const signal_t *a, const signal_t *b) { - return a->signum - b->signum; +void event_del(event_t *event) { + avl_delete(event_tree, event); } -static io_t signalio; -static int pipefd[2] = {-1, -1}; -static splay_tree_t signal_tree = {.compare = (splay_compare_t)signal_compare}; +event_t *get_expired_event(void) { + event_t *event; -static void signal_handler(int signum) { - unsigned char num = signum; - write(pipefd[1], &num, 1); -} + if(event_tree->head) { + event = event_tree->head->data; -static void signalio_handler(void *data, int flags) { - unsigned char signum; - if(read(pipefd[0], &signum, 1) != 1) - return; - - signal_t *sig = splay_search(&signal_tree, &((signal_t){.signum = signum})); - if(sig) - sig->cb(sig->data); -} - -static void pipe_init(void) { - if(!pipe(pipefd)) - io_add(&signalio, signalio_handler, NULL, pipefd[0], IO_READ); -} - -void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum) { - if(sig->cb) - return; - - sig->cb = cb; - sig->data = data; - sig->signum = signum; - sig->node.data = sig; - - if(pipefd[0] == -1) - pipe_init(); - - signal(sig->signum, signal_handler); - - if(!splay_insert_node(&signal_tree, &sig->node)) - abort(); -} - -void signal_del(signal_t *sig) { - if(!sig->cb) - return; - - signal(sig->signum, SIG_DFL); - - splay_unlink_node(&signal_tree, &sig->node); - sig->cb = NULL; -} -#endif - -bool event_loop(void) { - running = true; - - fd_set readable; - fd_set writable; - - while(running) { - gettimeofday(&now, NULL); - struct timeval diff, *tv = NULL; - - while(timeout_tree.head) { - timeout_t *timeout = timeout_tree.head->data; - timersub(&timeout->tv, &now, &diff); - - if(diff.tv_sec < 0) { - timeout->cb(timeout->data); - if(timercmp(&timeout->tv, &now, <)) - timeout_del(timeout); - } else { - tv = &diff; - break; - } - } - - memcpy(&readable, &readfds, sizeof readable); - memcpy(&writable, &writefds, sizeof writable); - - int fds = 0; - - if(io_tree.tail) { - io_t *last = io_tree.tail->data; - fds = last->fd + 1; - } - -#ifdef HAVE_MINGW - LeaveCriticalSection(&mutex); -#endif - int n = select(fds, &readable, &writable, NULL, tv); -#ifdef HAVE_MINGW - EnterCriticalSection(&mutex); -#endif - - if(n < 0) { - if(sockwouldblock(errno)) - continue; - else - return false; - } - - if(!n) - continue; - - for splay_each(io_t, io, &io_tree) { - if(FD_ISSET(io->fd, &writable)) - io->cb(io->data, IO_WRITE); - else if(FD_ISSET(io->fd, &readable)) - io->cb(io->data, IO_READ); + if(event->time <= now) { + avl_node_t *node = event_tree->head; + avl_unlink_node(event_tree, node); + free(node); + return event; } } - return true; + return NULL; } -void event_flush_output(void) { - for splay_each(io_t, io, &io_tree) - if(FD_ISSET(io->fd, &writefds)) - io->cb(io->data, IO_WRITE); -} +event_t *peek_next_event(void) { + if(event_tree->head) { + return event_tree->head->data; + } -void event_exit(void) { - running = false; + return NULL; } diff --git a/src/event.h b/src/event.h index c6522c0..6d521bb 100644 --- a/src/event.h +++ b/src/event.h @@ -1,6 +1,10 @@ +#ifndef TINC_EVENT_H +#define TINC_EVENT_H + /* - event.h -- I/O, timeout and signal event handling - Copyright (C) 2012-2013 Guus Sliepen + event.h -- header for event.c + Copyright (C) 2002-2009 Guus Sliepen , + 2002-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 @@ -17,55 +21,27 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_EVENT_H__ -#define __TINC_EVENT_H__ +#include "avl_tree.h" -#include "splay_tree.h" +extern avl_tree_t *event_tree; -#define IO_READ 1 -#define IO_WRITE 2 +typedef void (*event_handler_t)(void *); -typedef void (*io_cb_t)(void *data, int flags); -typedef void (*timeout_cb_t)(void *data); -typedef void (*signal_cb_t)(void *data); - -typedef struct io_t { - int fd; - int flags; - io_cb_t cb; +typedef struct event { + time_t time; + int id; + event_handler_t handler; void *data; - splay_node_t node; -} io_t; +} event_t; -typedef struct timeout_t { - struct timeval tv; - timeout_cb_t cb; - void *data; - splay_node_t node; -} timeout_t; - -typedef struct signal_t { - int signum; - signal_cb_t cb; - void *data; - splay_node_t node; -} signal_t; - -extern struct timeval now; - -extern void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags); -extern void io_del(io_t *io); -extern void io_set(io_t *io, int flags); - -extern void timeout_add(timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv); -extern void timeout_del(timeout_t *timeout); -extern void timeout_set(timeout_t *timeout, struct timeval *tv); - -extern void signal_add(signal_t *sig, signal_cb_t cb, void *data, int signum); -extern void signal_del(signal_t *sig); - -extern bool event_loop(void); -extern void event_flush_output(void); -extern void event_exit(void); +extern void init_events(void); +extern void exit_events(void); +extern void expire_events(void); +extern event_t *new_event(void) __attribute__((__malloc__)); +extern void free_event(event_t *event); +extern void event_add(event_t *event); +extern void event_del(event_t *event); +extern event_t *get_expired_event(void); +extern event_t *peek_next_event(void); #endif diff --git a/src/fake-gai-errnos.h b/src/fake-gai-errnos.h deleted file mode 100644 index 2f41d8f..0000000 --- a/src/fake-gai-errnos.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * fake library for ssh - * - * This file is included in getaddrinfo.c and getnameinfo.c. - * See getaddrinfo.c and getnameinfo.c. - */ - -/* for old netdb.h */ -#ifndef EAI_NODATA -#define EAI_NODATA 1 -#endif - -#ifndef EAI_MEMORY -#define EAI_MEMORY 2 -#endif - -#ifndef EAI_FAMILY -#define EAI_FAMILY 3 -#endif - -#ifndef EAI_SYSTEM -#define EAI_SYSTEM 4 -#endif diff --git a/src/fake-getaddrinfo.c b/src/fake-getaddrinfo.c index cb821b5..1ee11c5 100644 --- a/src/fake-getaddrinfo.c +++ b/src/fake-getaddrinfo.c @@ -2,10 +2,10 @@ * fake library for ssh * * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror(). - * These funtions are defined in rfc2133. + * These functions are defined in rfc2133. * * But these functions are not implemented correctly. The minimum subset - * is implemented for ssh use only. For exapmle, this routine assumes + * is implemented for ssh use only. For example, this routine assumes * that ai_family is AF_INET. Don't use it for another purpose. */ @@ -16,18 +16,20 @@ #include "fake-getaddrinfo.h" #include "xalloc.h" - #if !HAVE_DECL_GAI_STRERROR char *gai_strerror(int ecode) { - switch (ecode) { - case EAI_NODATA: - return "No address associated with hostname"; - case EAI_MEMORY: - return "Memory allocation failure"; - case EAI_FAMILY: - return "Address family not supported"; - default: - return "Unknown error"; + switch(ecode) { + case EAI_NODATA: + return "No address associated with hostname"; + + case EAI_MEMORY: + return "Memory allocation failure"; + + case EAI_FAMILY: + return "Address family not supported"; + + default: + return "Unknown error"; } } #endif /* !HAVE_GAI_STRERROR */ @@ -48,7 +50,7 @@ void freeaddrinfo(struct addrinfo *ai) { static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr) { struct addrinfo *ai; - ai = xzalloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + ai = xmalloc_and_zero(sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); ai->ai_addr = (struct sockaddr *)(ai + 1); ai->ai_addrlen = sizeof(struct sockaddr_in); @@ -67,32 +69,36 @@ int getaddrinfo(const char *hostname, const char *servname, const struct addrinf int i; uint16_t port = 0; - if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) + if(hints && hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) { return EAI_FAMILY; + } - if (servname) + if(servname) { port = htons(atoi(servname)); + } - if (hints && hints->ai_flags & AI_PASSIVE) { + if(hints && hints->ai_flags & AI_PASSIVE) { *res = malloc_ai(port, htonl(0x00000000)); return 0; } - if (!hostname) { + if(!hostname) { *res = malloc_ai(port, htonl(0x7f000001)); return 0; } hp = gethostbyname(hostname); - if(!hp || !hp->h_addr_list || !hp->h_addr_list[0]) + if(!hp || !hp->h_addr_list || !hp->h_addr_list[0]) { return EAI_NODATA; + } - for (i = 0; hp->h_addr_list[i]; i++) { + for(i = 0; hp->h_addr_list[i]; i++) { *res = malloc_ai(port, ((struct in_addr *)hp->h_addr_list[i])->s_addr); - if(prev) + if(prev) { prev->ai_next = *res; + } prev = *res; } diff --git a/src/fake-getaddrinfo.h b/src/fake-getaddrinfo.h index 5809985..f10cb83 100644 --- a/src/fake-getaddrinfo.h +++ b/src/fake-getaddrinfo.h @@ -1,7 +1,17 @@ -#ifndef _FAKE_GETADDRINFO_H -#define _FAKE_GETADDRINFO_H +#ifndef TINC_FAKE_GETADDRINFO_H +#define TINC_FAKE_GETADDRINFO_H -#include "fake-gai-errnos.h" +#ifndef EAI_NODATA +#define EAI_NODATA 1 +#endif + +#ifndef EAI_MEMORY +#define EAI_MEMORY 2 +#endif + +#ifndef EAI_FAMILY +#define EAI_FAMILY 3 +#endif #ifndef AI_PASSIVE # define AI_PASSIVE 1 @@ -15,24 +25,25 @@ #endif #ifndef AI_NUMERICHOST -#define AI_NUMERICHOST 4 +#define AI_NUMERICHOST 4 #endif #ifndef HAVE_STRUCT_ADDRINFO struct addrinfo { - int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ - int ai_family; /* PF_xxx */ - int ai_socktype; /* SOCK_xxx */ - int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ - char *ai_canonname; /* canonical name for hostname */ - struct sockaddr *ai_addr; /* binary address */ - struct addrinfo *ai_next; /* next structure in linked list */ + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ }; #endif /* !HAVE_STRUCT_ADDRINFO */ #if !HAVE_DECL_GETADDRINFO -int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res); +int getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res); #endif /* !HAVE_GETADDRINFO */ #if !HAVE_DECL_GAI_STRERROR @@ -43,4 +54,4 @@ char *gai_strerror(int ecode); void freeaddrinfo(struct addrinfo *ai); #endif /* !HAVE_FREEADDRINFO */ -#endif /* _FAKE_GETADDRINFO_H */ +#endif diff --git a/src/fake-getnameinfo.c b/src/fake-getnameinfo.c index 4a4d132..e51bce2 100644 --- a/src/fake-getnameinfo.c +++ b/src/fake-getnameinfo.c @@ -2,10 +2,10 @@ * fake library for ssh * * This file includes getnameinfo(). - * These funtions are defined in rfc2133. + * These functions are defined in rfc2133. * * But these functions are not implemented correctly. The minimum subset - * is implemented for ssh use only. For exapmle, this routine assumes + * is implemented for ssh use only. For example, this routine assumes * that ai_family is AF_INET. Don't use it for another purpose. */ @@ -21,33 +21,43 @@ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t host struct hostent *hp; int len; - if(sa->sa_family != AF_INET) + if(sa->sa_family != AF_INET) { return EAI_FAMILY; + } if(serv && servlen) { len = snprintf(serv, servlen, "%d", ntohs(sin->sin_port)); - if(len < 0 || len >= servlen) + + if(len < 0 || len >= servlen) { return EAI_MEMORY; + } } - if(!host || !hostlen) + if(!host || !hostlen) { return 0; + } if(flags & NI_NUMERICHOST) { len = snprintf(host, hostlen, "%s", inet_ntoa(sin->sin_addr)); - if(len < 0 || len >= hostlen) + + if(len < 0 || len >= hostlen) { return EAI_MEMORY; + } + return 0; } hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET); - if(!hp || !hp->h_name || !hp->h_name[0]) + if(!hp || !hp->h_name || !hp->h_name[0]) { return EAI_NODATA; + } len = snprintf(host, hostlen, "%s", hp->h_name); - if(len < 0 || len >= hostlen) + + if(len < 0 || len >= hostlen) { return EAI_MEMORY; + } return 0; } diff --git a/src/fake-getnameinfo.h b/src/fake-getnameinfo.h index 043ed97..4f24ad1 100644 --- a/src/fake-getnameinfo.h +++ b/src/fake-getnameinfo.h @@ -1,8 +1,9 @@ -#ifndef _FAKE_GETNAMEINFO_H -#define _FAKE_GETNAMEINFO_H +#ifndef TINC_FAKE_GETNAMEINFO_H +#define TINC_FAKE_GETNAMEINFO_H #if !HAVE_DECL_GETNAMEINFO -int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); +int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags); #endif /* !HAVE_GETNAMEINFO */ #ifndef NI_MAXSERV @@ -12,4 +13,4 @@ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t host # define NI_MAXHOST 1025 #endif /* !NI_MAXHOST */ -#endif /* _FAKE_GETNAMEINFO_H */ +#endif diff --git a/src/gcrypt/.deps/cipher.Po b/src/gcrypt/.deps/cipher.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/cipher.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/.deps/crypto.Po b/src/gcrypt/.deps/crypto.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/crypto.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/.deps/digest.Po b/src/gcrypt/.deps/digest.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/digest.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/.deps/ecdh.Po b/src/gcrypt/.deps/ecdh.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/ecdh.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/.deps/ecdsa.Po b/src/gcrypt/.deps/ecdsa.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/ecdsa.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/.deps/ecdsagen.Po b/src/gcrypt/.deps/ecdsagen.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/ecdsagen.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/.deps/prf.Po b/src/gcrypt/.deps/prf.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/prf.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/.deps/rsa.Po b/src/gcrypt/.deps/rsa.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/rsa.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/.deps/rsagen.Po b/src/gcrypt/.deps/rsagen.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/gcrypt/.deps/rsagen.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/gcrypt/cipher.c b/src/gcrypt/cipher.c deleted file mode 100644 index e9b32cf..0000000 --- a/src/gcrypt/cipher.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - cipher.c -- Symmetric block cipher handling - Copyright (C) 2007-2012 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "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; -} diff --git a/src/gcrypt/cipher.h b/src/gcrypt/cipher.h deleted file mode 100644 index 389bb11..0000000 --- a/src/gcrypt/cipher.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - cipher.h -- header file cipher.c - Copyright (C) 2007-2009 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_CIPHER_H__ -#define __TINC_CIPHER_H__ - -#include - -#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 diff --git a/src/gcrypt/crypto.c b/src/gcrypt/crypto.c deleted file mode 100644 index dc92b3e..0000000 --- a/src/gcrypt/crypto.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - crypto.c -- Cryptographic miscellaneous functions and initialisation - Copyright (C) 2007 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include - -#include "crypto.h" - -void crypto_init() { -} - -void crypto_exit() { -} - -void randomize(void *out, size_t outlen) { - gcry_create_nonce(out, outlen); -} diff --git a/src/gcrypt/crypto.h b/src/gcrypt/crypto.h deleted file mode 100644 index 71df50c..0000000 --- a/src/gcrypt/crypto.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - crypto.h -- header for crypto.c - Copyright (C) 2007-2009 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_CRYPTO_H__ -#define __TINC_CRYPTO_H__ - -extern void crypto_init(); -extern void crypto_exit(); -extern void randomize(void *, size_t); - -#endif diff --git a/src/gcrypt/digest.c b/src/gcrypt/digest.c deleted file mode 100644 index 4229b0c..0000000 --- a/src/gcrypt/digest.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - digest.c -- Digest handling - Copyright (C) 2007-2012 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "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; -} diff --git a/src/gcrypt/digest.h b/src/gcrypt/digest.h deleted file mode 100644 index 9f0d7d8..0000000 --- a/src/gcrypt/digest.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - digest.h -- header file digest.c - Copyright (C) 2007-2009 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_DIGEST_H__ -#define __TINC_DIGEST_H__ - -#include - -#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 diff --git a/src/gcrypt/ecdh.c b/src/gcrypt/ecdh.c deleted file mode 100644 index 4e30733..0000000 --- a/src/gcrypt/ecdh.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - ecdh.c -- Diffie-Hellman key exchange handling - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include "../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) { -} diff --git a/src/gcrypt/ecdsa.c b/src/gcrypt/ecdsa.c deleted file mode 100644 index ee19aec..0000000 --- a/src/gcrypt/ecdsa.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - ecdsa.c -- ECDSA key handling - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include "../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) { -} diff --git a/src/gcrypt/ecdsagen.c b/src/gcrypt/ecdsagen.c deleted file mode 100644 index 2d4912d..0000000 --- a/src/gcrypt/ecdsagen.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - ecdsagen.c -- ECDSA key generation and export - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include "../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; -} diff --git a/src/gcrypt/prf.c b/src/gcrypt/prf.c deleted file mode 100644 index f9a2112..0000000 --- a/src/gcrypt/prf.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - prf.c -- Pseudo-Random Function for key material generation - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include "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; -} diff --git a/src/gcrypt/rsa.c b/src/gcrypt/rsa.c deleted file mode 100644 index 751f7b6..0000000 --- a/src/gcrypt/rsa.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - rsa.c -- RSA key handling - Copyright (C) 2007-2012 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include - -#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; -} diff --git a/src/gcrypt/rsa.h b/src/gcrypt/rsa.h deleted file mode 100644 index 143f015..0000000 --- a/src/gcrypt/rsa.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - rsa.h -- RSA key handling - Copyright (C) 2007 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_RSA_H__ -#define __TINC_RSA_H__ - -#include - -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 diff --git a/src/gcrypt/rsagen.c b/src/gcrypt/rsagen.c deleted file mode 100644 index 36fb104..0000000 --- a/src/gcrypt/rsagen.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - rsagen.c -- RSA key generation and export - Copyright (C) 2008-2012 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include - -#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; -} diff --git a/src/gcrypt/rsagen.h b/src/gcrypt/rsagen.h deleted file mode 100644 index 422d156..0000000 --- a/src/gcrypt/rsagen.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - rsagen.h -- RSA key generation and export - Copyright (C) 2008 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#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 diff --git a/src/getopt.c b/src/getopt.c index d63887e..741c7f2 100644 --- a/src/getopt.c +++ b/src/getopt.c @@ -4,7 +4,7 @@ before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 - Free Software Foundation, Inc. + Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. @@ -69,12 +69,12 @@ with this program; if not, write to the Free Software Foundation, Inc., /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ +#ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #include -#endif /* GNU C library. */ +#endif /* GNU C library. */ #ifdef VMS #include @@ -132,7 +132,7 @@ int optind = 1; causes problems with re-calling getopt as programs generally don't know that. */ -int __getopt_initialized = 0; +int getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. @@ -183,40 +183,41 @@ int optopt = '?'; of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +static enum { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; -#ifdef __GNU_LIBRARY__ +#ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include -#define my_index strchr +#define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ -char *getenv (); +char *getenv(); static char * -my_index (str, chr) - const char *str; - int chr; +my_index(str, chr) +const char *str; +int chr; { - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; + while(*str) { + if(*str == chr) { + return (char *) str; + } + + str++; + } + + return 0; } /* If using GCC, we can safely declare strlen this way. @@ -227,7 +228,7 @@ my_index (str, chr) #if !defined (__STDC__) || !__STDC__ /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); +extern int strlen(const char *); #endif /* not __STDC__ */ #endif /* __GNUC__ */ @@ -247,7 +248,7 @@ static int last_nonopt; indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; +extern char *getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; @@ -255,32 +256,31 @@ static int nonoption_flags_len; static int original_argc; static char *const *original_argv; -extern pid_t __libc_pid; +extern pid_t libc_pid; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void -__attribute__ ((__unused__)) -store_args_and_env (int argc, char *const *argv) -{ - /* XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; +__attribute__((__unused__)) +store_args_and_env(int argc, char *const *argv) { + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; } -text_set_element (__libc_subinit, store_args_and_env); +text_set_element(libc_subinit, store_args_and_env); # define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -#else /* !_LIBC */ + if (nonoption_flags_len > 0) \ + { \ + char tmp = getopt_nonoption_flags[ch1]; \ + getopt_nonoption_flags[ch1] = getopt_nonoption_flags[ch2]; \ + getopt_nonoption_flags[ch2] = tmp; \ + } +#else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ +#endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) @@ -292,161 +292,158 @@ text_set_element (__libc_subinit, store_args_and_env); the new indices of the non-options in ARGV after they are moved. */ #if defined (__STDC__) && __STDC__ -static void exchange (char **); +static void exchange(char **); #endif static void -exchange (argv) - char **argv; +exchange(argv) +char **argv; { - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ #ifdef _LIBC - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len); - memset (&new_str[nonoption_flags_max_len], '\0', - top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; + + /* First make sure the handling of the `getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if(nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc(top + 1); + + if(new_str == NULL) { + nonoption_flags_len = nonoption_flags_max_len = 0; + } else { + memcpy(new_str, getopt_nonoption_flags, nonoption_flags_max_len); + memset(&new_str[nonoption_flags_max_len], '\0', + top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + getopt_nonoption_flags = new_str; + } } - } + #endif - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; + while(top > middle && middle > bottom) { + if(top - middle > middle - bottom) { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; + /* Swap it with the top part of the top segment. */ + for(i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS(bottom + i, top - (middle - bottom) + i); + } + + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } else { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for(i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS(bottom + i, middle + i); + } + + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } + /* Update records for the slots the non-options now occupy. */ - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined (__STDC__) && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); +static const char *_getopt_initialize(int, char *const *, const char *); #endif static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; +_getopt_initialize(argc, argv, optstring) +int argc; +char *const *argv; +const char *optstring; { - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ - first_nonopt = last_nonopt = optind; + first_nonopt = last_nonopt = optind; - nextchar = NULL; + nextchar = NULL; - posixly_correct = getenv ("POSIXLY_CORRECT"); + posixly_correct = getenv("POSIXLY_CORRECT"); - /* Determine how to handle the ordering of options and nonoptions. */ + /* Determine how to handle the ordering of options and nonoptions. */ - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; + if(optstring[0] == '-') { + ordering = RETURN_IN_ORDER; + ++optstring; + } else if(optstring[0] == '+') { + ordering = REQUIRE_ORDER; + ++optstring; + } else if(posixly_correct != NULL) { + ordering = REQUIRE_ORDER; + } else { + ordering = PERMUTE; + } #ifdef _LIBC - if (posixly_correct == NULL - && argc == original_argc && argv == original_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - { - memcpy (__getopt_nonoption_flags, orig_str, len); - memset (&__getopt_nonoption_flags[len], '\0', - nonoption_flags_max_len - len); + + if(posixly_correct == NULL + && argc == original_argc && argv == original_argv) { + if(nonoption_flags_max_len == 0) { + if(getopt_nonoption_flags == NULL + || getopt_nonoption_flags[0] == '\0') { + nonoption_flags_max_len = -1; + } else { + const char *orig_str = getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen(orig_str); + + if(nonoption_flags_max_len < argc) { + nonoption_flags_max_len = argc; + } + + getopt_nonoption_flags = + (char *) malloc(nonoption_flags_max_len); + + if(getopt_nonoption_flags == NULL) { + nonoption_flags_max_len = -1; + } else { + memcpy(getopt_nonoption_flags, orig_str, len); + memset(&getopt_nonoption_flags[len], '\0', + nonoption_flags_max_len - len); + } + } } - } + + nonoption_flags_len = nonoption_flags_max_len; + } else { + nonoption_flags_len = 0; } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; + #endif - return optstring; + return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters @@ -506,474 +503,476 @@ _getopt_initialize (argc, argv, optstring) long-named options. */ int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; +_getopt_internal(argc, argv, optstring, longopts, longind, long_only) +int argc; +char *const *argv; +const char *optstring; +const struct option *longopts; +int *longind; +int long_only; { - optarg = NULL; + optarg = NULL; - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; - } + if(optind == 0 || !getopt_initialized) { + if(optind == 0) { + optind = 1; /* Don't scan ARGV[0], the program name. */ + } - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ + optstring = _getopt_initialize(argc, argv, optstring); + getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ #ifdef _LIBC -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && getopt_nonoption_flags[optind] == '1')) #else #define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ + if(nextchar == NULL || *nextchar == '\0') { + /* Advance to the next ARGV-element. */ - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, "%s: option `%s' is ambiguous\n", - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - "%s: option `--%s' doesn't allow an argument\n", - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - "%s: option `%c%s' doesn't allow an argument\n", - argv[0], argv[optind - 1][0], pfound->name); - } - - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if(last_nonopt > optind) { + last_nonopt = optind; } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - "%s: option `%s' requires an argument\n", - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; + + if(first_nonopt > optind) { + first_nonopt = optind; } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; + + if(ordering == PERMUTE) { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if(first_nonopt != last_nonopt && last_nonopt != optind) { + exchange((char **) argv); + } else if(last_nonopt != optind) { + first_nonopt = optind; + } + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while(optind < argc && NONOPTION_P) { + optind++; + } + + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if(optind != argc && !strcmp(argv[optind], "--")) { + optind++; + + if(first_nonopt != last_nonopt && last_nonopt != optind) { + exchange((char **) argv); + } else if(first_nonopt == last_nonopt) { + first_nonopt = optind; + } + + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if(optind == argc) { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if(first_nonopt != last_nonopt) { + optind = first_nonopt; + } + + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if(NONOPTION_P) { + if(ordering == REQUIRE_ORDER) { + return -1; + } + + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); } - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if(longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index(optstring, argv[optind][1]))))) { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for(nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for(p = longopts, option_index = 0; p->name; p++, option_index++) + if(!strncmp(p->name, nextchar, nameend - nextchar)) { + if((unsigned int)(nameend - nextchar) + == (unsigned int) strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if(pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact match found. */ + { + ambig = 1; + } + } + + if(ambig && !exact) { + if(opterr) + fprintf(stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + + nextchar += strlen(nextchar); + optind++; + optopt = 0; + return '?'; + } + + if(pfound != NULL) { + option_index = indfound; + optind++; + + if(*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if(pfound->has_arg) { + optarg = nameend + 1; + } else { + if(opterr) { + if(argv[optind - 1][1] == '-') + /* --option */ + fprintf(stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf(stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + + nextchar += strlen(nextchar); + + optopt = pfound->val; + return '?'; + } + } else if(pfound->has_arg == 1) { + if(optind < argc) { + optarg = argv[optind++]; + } else { + if(opterr) + fprintf(stderr, + "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + + nextchar += strlen(nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + + nextchar += strlen(nextchar); + + if(longind != NULL) { + *longind = option_index; + } + + if(pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if(!long_only || argv[optind][1] == '-' + || my_index(optstring, *nextchar) == NULL) { + if(opterr) { + if(argv[optind][1] == '-') + /* --option */ + fprintf(stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf(stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, "%s: unrecognized option `--%s'\n", - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, "%s: unrecognized option `%c%s'\n", - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; + char c = *nextchar++; + char *temp = my_index(optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if(*nextchar == '\0') { + ++optind; + } + + if(temp == NULL || c == ':') { + if(opterr) { + if(posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, "%s: illegal option -- %c\n", + argv[0], c); + else + fprintf(stderr, "%s: invalid option -- %c\n", + argv[0], c); + } + + optopt = c; + return '?'; + } + + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if(temp[0] == 'W' && temp[1] == ';') { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if(*nextchar != '\0') { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } else if(optind == argc) { + if(opterr) { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, "%s: option requires an argument -- %c\n", + argv[0], c); + } + + optopt = c; + + if(optstring[0] == ':') { + c = ':'; + } else { + c = '?'; + } + + return c; + } else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + { + optarg = argv[optind++]; + } + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for(nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for(p = longopts, option_index = 0; p->name; p++, option_index++) + if(!strncmp(p->name, nextchar, nameend - nextchar)) { + if((unsigned int)(nameend - nextchar) == strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if(pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact match found. */ + { + ambig = 1; + } + } + + if(ambig && !exact) { + if(opterr) + fprintf(stderr, "%s: option `-W %s' is ambiguous\n", + argv[0], argv[optind]); + + nextchar += strlen(nextchar); + optind++; + return '?'; + } + + if(pfound != NULL) { + option_index = indfound; + + if(*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if(pfound->has_arg) { + optarg = nameend + 1; + } else { + if(opterr) + fprintf(stderr, + "%s: option `-W %s' doesn't allow an argument\n", + argv[0], pfound->name); + + nextchar += strlen(nextchar); + return '?'; + } + } else if(pfound->has_arg == 1) { + if(optind < argc) { + optarg = argv[optind++]; + } else { + if(opterr) + fprintf(stderr, + "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + + nextchar += strlen(nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + + nextchar += strlen(nextchar); + + if(longind != NULL) { + *longind = option_index; + } + + if(pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + + return pfound->val; + } + + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + + if(temp[1] == ':') { + if(temp[2] == ':') { + /* This is an option that accepts an argument optionally. */ + if(*nextchar != '\0') { + optarg = nextchar; + optind++; + } else { + optarg = NULL; + } + + nextchar = NULL; + } else { + /* This is an option that requires an argument. */ + if(*nextchar != '\0') { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } else if(optind == argc) { + if(opterr) { + /* 1003.2 specifies the format of this message. */ + fprintf(stderr, + "%s: option requires an argument -- %c\n", + argv[0], c); + } + + optopt = c; + + if(optstring[0] == ':') { + c = ':'; + } else { + c = '?'; + } + } else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + { + optarg = argv[optind++]; + } + + nextchar = NULL; + } + } + + return c; } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, "%s: illegal option -- %c\n", - argv[0], c); - else - fprintf (stderr, "%s: invalid option -- %c\n", - argv[0], c); - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, "%s: option requires an argument -- %c\n", - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, "%s: option `-W %s' is ambiguous\n", - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - fprintf (stderr, - "%s: option `-W %s' doesn't allow an argument\n", - argv[0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - "%s: option `%s' requires an argument\n", - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, - "%s: option requires an argument -- %c\n", - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } } int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; +getopt(argc, argv, optstring) +int argc; +char *const *argv; +const char *optstring; { - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); + return _getopt_internal(argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); } -#endif /* Not ELIDE_CODE. */ +#endif /* Not ELIDE_CODE. */ #ifdef TEST @@ -981,68 +980,72 @@ getopt (argc, argv, optstring) the above definition of `getopt'. */ int -main (argc, argv) - int argc; - char **argv; +main(argc, argv) +int argc; +char **argv; { - int c; - int digit_optind = 0; + int c; + int digit_optind = 0; - while (1) - { - int this_option_optind = optind ? optind : 1; + while(1) { + int this_option_optind = optind ? optind : 1; - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; + c = getopt(argc, argv, "abc:d:0123456789"); - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; + if(c == -1) { + break; + } - case 'a': - printf ("option a\n"); - break; + switch(c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if(digit_optind != 0 && digit_optind != this_option_optind) { + printf("digits occur in two different argv-elements.\n"); + } - case 'b': - printf ("option b\n"); - break; + digit_optind = this_option_optind; + printf("option %c\n", c); + break; - case 'c': - printf ("option c with value `%s'\n", optarg); - break; + case 'a': + printf("option a\n"); + break; - case '?': - break; + case 'b': + printf("option b\n"); + break; - default: - printf ("?? getopt returned character code 0%o ??\n", c); + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } } - } - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } + if(optind < argc) { + printf("non-option ARGV-elements: "); - exit (0); + while(optind < argc) { + printf("%s ", argv[optind++]); + } + + printf("\n"); + } + + exit(0); } #endif /* TEST */ diff --git a/src/getopt.h b/src/getopt.h index ddf6fdd..ab1d40b 100644 --- a/src/getopt.h +++ b/src/getopt.h @@ -1,3 +1,6 @@ +#ifndef TINC_GETOPT_H +#define TINC_GETOPT_H + /* Declarations for getopt. Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. @@ -19,115 +22,111 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef _GETOPT_H -#define _GETOPT_H 1 - -#ifdef __cplusplus +#ifdef cplusplus extern "C" { #endif -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ + /* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ -extern char *optarg; + extern char *optarg; -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. + /* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. - On entry to `getopt', zero means this is the first call; initialize. + On entry to `getopt', zero means this is the first call; initialize. - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ -extern int optind; + extern int optind; -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ + /* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ -extern int opterr; + extern int opterr; -/* Set to an option character which was unrecognized. */ + /* Set to an option character which was unrecognized. */ -extern int optopt; + extern int optopt; -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. + /* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ -struct option -{ + struct option { #if defined (__STDC__) && __STDC__ - const char *name; + const char *name; #else - char *name; + char *name; #endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; + }; -/* Names for the values of the `has_arg' field of `struct option'. */ + /* Names for the values of the `has_arg' field of `struct option'. */ -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ -extern int getopt (int argc, char *const *argv, const char *shortopts); + /* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ + extern int getopt(int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ -extern int getopt (); + extern int getopt(); #endif /* __GNU_LIBRARY__ */ -extern int getopt_long (int argc, char *const *argv, const char *shortopts, - const struct option *longopts, int *longind); -extern int getopt_long_only (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind); + extern int getopt_long(int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); + extern int getopt_long_only(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind, - int long_only); + /* Internal only. Users should not call this directly. */ + extern int _getopt_internal(int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); #else /* not __STDC__ */ -extern int getopt (); -extern int getopt_long (); -extern int getopt_long_only (); + extern int getopt(); + extern int getopt_long(); + extern int getopt_long_only(); -extern int _getopt_internal (); + extern int _getopt_internal(); #endif /* __STDC__ */ -#ifdef __cplusplus +#ifdef cplusplus } #endif -#endif /* _GETOPT_H */ +#endif diff --git a/src/getopt1.c b/src/getopt1.c index 19605a5..3ccb150 100644 --- a/src/getopt1.c +++ b/src/getopt1.c @@ -60,19 +60,19 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #endif -#ifndef NULL +#ifndef NULL #define NULL 0 #endif int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; +getopt_long(argc, argv, options, long_options, opt_index) +int argc; +char *const *argv; +const char *options; +const struct option *long_options; +int *opt_index; { - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); + return _getopt_internal(argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. @@ -81,109 +81,115 @@ getopt_long (argc, argv, options, long_options, opt_index) instead. */ int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; +getopt_long_only(argc, argv, options, long_options, opt_index) +int argc; +char *const *argv; +const char *options; +const struct option *long_options; +int *opt_index; { - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); + return _getopt_internal(argc, argv, options, long_options, opt_index, 1); } -#endif /* Not ELIDE_CODE. */ +#endif /* Not ELIDE_CODE. */ #ifdef TEST #include int -main (argc, argv) - int argc; - char **argv; +main(argc, argv) +int argc; +char **argv; { - int c; - int digit_optind = 0; + int c; + int digit_optind = 0; - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; + while(1) { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; + c = getopt_long(argc, argv, "abc:d:0123456789", + long_options, &option_index); - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; + if(c == -1) { + break; + } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; + switch(c) { + case 0: + printf("option %s", long_options[option_index].name); - case 'a': - printf ("option a\n"); - break; + if(optarg) { + printf(" with arg %s", optarg); + } - case 'b': - printf ("option b\n"); - break; + printf("\n"); + break; - case 'c': - printf ("option c with value `%s'\n", optarg); - break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if(digit_optind != 0 && digit_optind != this_option_optind) { + printf("digits occur in two different argv-elements.\n"); + } - case 'd': - printf ("option d with value `%s'\n", optarg); - break; + digit_optind = this_option_optind; + printf("option %c\n", c); + break; - case '?': - break; + case 'a': + printf("option a\n"); + break; - default: - printf ("?? getopt returned character code 0%o ??\n", c); + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case 'd': + printf("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } } - } - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } + if(optind < argc) { + printf("non-option ARGV-elements: "); - exit (0); + while(optind < argc) { + printf("%s ", argv[optind++]); + } + + printf("\n"); + } + + exit(0); } #endif /* TEST */ diff --git a/src/graph.c b/src/graph.c index b4c01bb..c63fdf9 100644 --- a/src/graph.c +++ b/src/graph.c @@ -1,6 +1,6 @@ /* graph.c -- graph algorithms - Copyright (C) 2001-2013 Guus Sliepen , + Copyright (C) 2001-2014 Guus Sliepen , 2001-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -44,13 +44,13 @@ #include "system.h" +#include "avl_tree.h" +#include "conf.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 "process.h" @@ -58,7 +58,8 @@ #include "subnet.h" #include "utils.h" #include "xalloc.h" -#include "graph.h" + +static bool graph_changed = true; /* Implementation of Kruskal's algorithm. Running time: O(EN) @@ -66,21 +67,42 @@ */ static void mst_kruskal(void) { + avl_node_t *node, *next; + edge_t *e; + node_t *n; + connection_t *c; + int nodes = 0; + int safe_edges = 0; + bool skipped; + /* Clear MST status on connections */ - for list_each(connection_t, c, connection_list) + for(node = connection_tree->head; node; node = node->next) { + c = node->data; c->status.mst = false; + } - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Running Kruskal's algorithm:"); + /* Do we have something to do at all? */ + + if(!edge_weight_tree->head) { + return; + } + + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Running Kruskal's algorithm:"); /* Clear visited status on nodes */ - for splay_each(node_t, n, node_tree) + for(node = node_tree->head; node; node = node->next) { + n = node->data; n->status.visited = false; + nodes++; + } /* Starting point */ - for splay_each(edge_t, e, edge_weight_tree) { + for(node = edge_weight_tree->head; node; node = node->next) { + e = node->data; + if(e->from->status.reachable) { e->from->status.visited = true; break; @@ -89,10 +111,11 @@ static void mst_kruskal(void) { /* Add safe edges */ - bool skipped = false; + for(skipped = false, node = edge_weight_tree->head; node; node = next) { + next = node->next; + e = node->data; - for splay_each(edge_t, e, edge_weight_tree) { - if(!e->reverse || (e->from->status.visited == e->to->status.visited)) { + if(!e->reverse || e->from->status.visited == e->to->status.visited) { skipped = true; continue; } @@ -100,19 +123,28 @@ static void mst_kruskal(void) { e->from->status.visited = true; e->to->status.visited = true; - if(e->connection) + if(e->connection) { e->connection->status.mst = true; + } - if(e->reverse->connection) + if(e->reverse->connection) { e->reverse->connection->status.mst = true; + } - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, e->to->name, e->weight); + safe_edges++; + + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, + e->to->name, e->weight); if(skipped) { skipped = false; next = edge_weight_tree->head; + continue; } } + + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes, + safe_edges); } /* Implementation of a simple breadth-first search algorithm. @@ -120,14 +152,25 @@ static void mst_kruskal(void) { */ static void sssp_bfs(void) { - list_t *todo_list = list_alloc(NULL); + avl_node_t *node, *next, *to; + edge_t *e; + node_t *n; + list_t *todo_list; + list_node_t *from, *todonext; + bool indirect; + char *name; + char *address, *port; + char *envp[8] = {NULL}; + int i; + + todo_list = list_alloc(NULL); /* Clear visited status on nodes */ - for splay_each(node_t, n, node_tree) { + for(node = node_tree->head; node; node = node->next) { + n = node->data; n->status.visited = false; n->status.indirect = true; - n->distance = -1; } /* Begin with myself */ @@ -137,28 +180,27 @@ static void sssp_bfs(void) { myself->nexthop = myself; myself->prevedge = NULL; myself->via = myself; - myself->distance = 0; list_insert_head(todo_list, myself); /* Loop while todo_list is filled */ - for list_each(node_t, n, todo_list) { /* "n" is the node from which we start */ - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Examining edges from %s", n->name); + for(from = todo_list->head; from; from = todonext) { /* "from" is the node from which we start */ + n = from->data; - if(n->distance < 0) - abort(); + for(to = n->edge_tree->head; to; to = to->next) { /* "to" is the edge connected to "from" */ + e = to->data; - for splay_each(edge_t, e, n->edge_tree) { /* "e" is the edge connected to "from" */ - if(!e->reverse) + if(!e->reverse) { continue; + } /* Situation: - / - / + / + / ----->(n)---e-->(e->to) - \ - \ + \ + \ Where e is an edge, (n) and (e->to) are nodes. n->address is set to the e->address of the edge left of n to n. @@ -169,77 +211,72 @@ static void sssp_bfs(void) { of nodes behind it. */ - bool indirect = n->status.indirect || e->options & OPTION_INDIRECT; + indirect = n->status.indirect || e->options & OPTION_INDIRECT; if(e->to->status.visited - && (!e->to->status.indirect || indirect) - && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) + && (!e->to->status.indirect || indirect)) { continue; + } + + // Only update nexthop the first time we visit this node. + + if(!e->to->status.visited) { + e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop; + } e->to->status.visited = true; e->to->status.indirect = indirect; - e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop; e->to->prevedge = e; e->to->via = indirect ? n->via : e->to; e->to->options = e->options; - e->to->distance = n->distance + 1; - if(!e->to->status.reachable || (e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN)) + if(e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN) { update_node_udp(e->to, &e->address); + } list_insert_tail(todo_list, e->to); } - next = node->next; /* Because the list_insert_tail() above could have added something extra for us! */ - list_delete_node(todo_list, node); + todonext = from->next; + list_delete_node(todo_list, from); } list_free(todo_list); -} -static void check_reachability(void) { /* Check reachability status. */ - for splay_each(node_t, n, node_tree) { + for(node = node_tree->head; node; node = next) { + next = node->next; + n = node->data; + if(n->status.visited != n->status.reachable) { n->status.reachable = !n->status.reachable; - n->last_state_change = now.tv_sec; if(n->status.reachable) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became reachable", - n->name, n->hostname); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Node %s (%s) became reachable", + n->name, n->hostname); } else { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became unreachable", - n->name, n->hostname); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Node %s (%s) became unreachable", + n->name, n->hostname); } - if(experimental && OPTION_VERSION(n->options) >= 2) - n->status.sptps = true; - /* TODO: only clear status.validkey if node is unreachable? */ n->status.validkey = false; - if(n->status.sptps) { - sptps_stop(&n->sptps); - n->status.waitingforkey = false; - } n->last_req_key = 0; - n->status.udp_confirmed = false; n->maxmtu = MTU; n->minmtu = 0; n->mtuprobes = 0; - timeout_del(&n->mtutimeout); + if(n->mtuevent) { + event_del(n->mtuevent); + n->mtuevent = NULL; + } - 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[0], "NETNAME=%s", netname ? netname : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? device : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : ""); xasprintf(&envp[3], "NODE=%s", n->name); sockaddr2str(&n->address, &address, &port); xasprintf(&envp[4], "REMOTEADDRESS=%s", address); @@ -248,29 +285,27 @@ static void check_reachability(void) { execute_script(n->status.reachable ? "host-up" : "host-down", envp); - xasprintf(&name, n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", n->name); + 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++) + for(i = 0; i < 7; i++) { free(envp[i]); + } subnet_update(n, NULL, n->status.reachable); if(!n->status.reachable) { update_node_udp(n, NULL); - memset(&n->status, 0, sizeof n->status); + memset(&n->status, 0, sizeof(n->status)); n->options = 0; } else if(n->connection) { - if(n->status.sptps) { - if(n->connection->outgoing) - send_req_key(n); - } else { - send_ans_key(n); - } + send_ans_key(n); } } } @@ -279,6 +314,77 @@ static void check_reachability(void) { void graph(void) { subnet_cache_flush(); sssp_bfs(); - check_reachability(); mst_kruskal(); + graph_changed = true; +} + + + +/* Dump nodes and edges to a graphviz file. + + The file can be converted to an image with + dot -Tpng graph_filename -o image_filename.png -Gconcentrate=true +*/ + +void dump_graph(void) { + avl_node_t *node; + node_t *n; + edge_t *e; + char *filename = NULL, *tmpname = NULL; + FILE *file, *pipe = NULL; + + if(!graph_changed || !get_config_string(lookup_config(config_tree, "GraphDumpFile"), &filename)) { + return; + } + + graph_changed = false; + + ifdebug(PROTOCOL) logger(LOG_NOTICE, "Dumping graph"); + + if(filename[0] == '|') { + file = pipe = popen(filename + 1, "w"); + } else { + xasprintf(&tmpname, "%s.new", filename); + file = fopen(tmpname, "w"); + } + + if(!file) { + logger(LOG_ERR, "Unable to open graph dump file %s: %s", filename, strerror(errno)); + free(filename); + free(tmpname); + return; + } + + fprintf(file, "digraph {\n"); + + /* dump all nodes first */ + for(node = node_tree->head; node; node = node->next) { + n = node->data; + fprintf(file, " \"%s\" [label = \"%s\"];\n", n->name, n->name); + } + + /* now dump all edges */ + for(node = edge_weight_tree->head; node; node = node->next) { + e = node->data; + fprintf(file, " \"%s\" -> \"%s\";\n", e->from->name, e->to->name); + } + + fprintf(file, "}\n"); + + if(pipe) { + pclose(pipe); + } else { + fclose(file); +#ifdef HAVE_MINGW + unlink(filename); +#endif + + if(rename(tmpname, filename)) { + logger(LOG_ERR, "Could not rename %s to %s: %s\n", tmpname, filename, strerror(errno)); + } + + free(tmpname); + } + + free(filename); } diff --git a/src/graph.h b/src/graph.h index fa521f5..fafffcb 100644 --- a/src/graph.h +++ b/src/graph.h @@ -1,3 +1,6 @@ +#ifndef TINC_GRAPH_H +#define TINC_GRAPH_H + /* graph.h -- header for graph.c Copyright (C) 2001-2012 Guus Sliepen , @@ -18,10 +21,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_GRAPH_H__ -#define __TINC_GRAPH_H__ - extern void graph(void); extern void dump_graph(void); -#endif /* __TINC_GRAPH_H__ */ +#endif diff --git a/src/hash.c b/src/hash.c deleted file mode 100644 index 8fb9ca6..0000000 --- a/src/hash.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - hash.c -- hash table management - Copyright (C) 2012-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "hash.h" -#include "xalloc.h" - -/* Generic hash function */ - -static uint32_t hash_function(const void *p, size_t len) { - const uint8_t *q = p; - uint32_t hash = 0; - while(true) { - for(int i = len > 4 ? 4 : len; --i;) - hash += q[len - i] << (8 * i); - hash *= 0x9e370001UL; // Golden ratio prime. - if(len <= 4) - break; - len -= 4; - } - return hash; -} - -/* Map 32 bits int onto 0..n-1, without throwing away too many bits if n is 2^8 or 2^16 */ - -static uint32_t modulo(uint32_t hash, size_t n) { - if(n == 0x100) - return (hash >> 24) ^ ((hash >> 16) & 0xff) ^ ((hash >> 8) & 0xff) ^ (hash & 0xff); - else if(n == 0x10000) - return (hash >> 16) ^ (hash & 0xffff); - else - return hash % n; -} - -/* (De)allocation */ - -hash_t *hash_alloc(size_t n, size_t size) { - hash_t *hash = xzalloc(sizeof *hash); - hash->n = n; - hash->size = size; - hash->keys = xzalloc(hash->n * hash->size); - hash->values = xzalloc(hash->n * sizeof *hash->values); - return hash; -} - -void hash_free(hash_t *hash) { - free(hash->keys); - free(hash->values); - free(hash); -} - -/* Searching and inserting */ - -void hash_insert(hash_t *hash, const void *key, const void *value) { - uint32_t i = modulo(hash_function(key, hash->size), hash->n); - memcpy(hash->keys + i * hash->size, key, hash->size); - hash->values[i] = value; -} - -void *hash_search(const hash_t *hash, const void *key) { - uint32_t i = modulo(hash_function(key, hash->size), hash->n); - if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) { - return (void *)hash->values[i]; - } - return NULL; -} - -void *hash_search_or_insert(hash_t *hash, const void *key, const void *value) { - uint32_t i = modulo(hash_function(key, hash->size), hash->n); - if(hash->values[i] && !memcmp(key, hash->keys + i * hash->size, hash->size)) - return (void *)hash->values[i]; - memcpy(hash->keys + i * hash->size, key, hash->size); - hash->values[i] = value; - return NULL; -} - -/* Utility functions */ - -void hash_clear(hash_t *hash) { - memset(hash->values, 0, hash->n * sizeof *hash->values); -} - -void hash_resize(hash_t *hash, size_t n) { - hash->keys = xrealloc(hash->keys, n * hash->size); - hash->values = xrealloc(hash->values, n * sizeof *hash->values); - if(n > hash->n) { - memset(hash->keys + hash->n * hash->size, 0, (n - hash->n) * hash->size); - memset(hash->values + hash->n, 0, (n - hash->n) * sizeof *hash->values); - } -} diff --git a/src/hash.h b/src/hash.h deleted file mode 100644 index 83ed6af..0000000 --- a/src/hash.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - hash.h -- header file for hash.c - Copyright (C) 2012 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_HASH_H__ -#define __TINC_HASH_H__ - -typedef struct hash_t { - size_t n; - size_t size; - char *keys; - const void **values; -} hash_t; - -extern hash_t *hash_alloc(size_t n, size_t size) __attribute__ ((__malloc__)); -extern void hash_free(hash_t *); - -extern void hash_insert(hash_t *, const void *key, const void *value); - -extern void *hash_search(const hash_t *, const void *key); -extern void *hash_search_or_insert(hash_t *, const void *key, const void *value); - -extern void hash_clear(hash_t *); -extern void hash_resize(hash_t *, size_t n); - -#endif /* __TINC_HASH_H__ */ diff --git a/src/have.h b/src/have.h index 3ada63a..11fa56a 100644 --- a/src/have.h +++ b/src/have.h @@ -1,7 +1,10 @@ +#ifndef TINC_HAVE_H +#define TINC_HAVE_H + /* have.h -- include headers which are known to exist Copyright (C) 1998-2005 Ivo Timmermans - 2003-2013 Guus Sliepen + 2003-2015 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,27 +21,28 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_HAVE_H__ -#define __TINC_HAVE_H__ - #ifdef HAVE_MINGW #ifdef WITH_WINDOWS2000 #define WINVER Windows2000 #else #define WINVER WindowsXP #endif -#define WIN32_LEAN_AND_MEAN #endif #include +#include +#include +#include #include #include #include #include -#include #include +#include + #include #include +#include #ifdef HAVE_MINGW #include @@ -55,8 +59,8 @@ #include #endif -#ifdef HAVE_INTTYPES_H -#include +#ifdef HAVE_ALLOCA_H +#include #endif /* Include system specific headers */ @@ -105,10 +109,6 @@ #include #endif -#ifdef HAVE_SYS_UN_H -#include -#endif - #ifdef HAVE_DIRENT_H #include #endif @@ -196,10 +196,19 @@ #include #endif -#ifdef HAVE_MINGW -#define SLASH "\\" -#else -#define SLASH "/" +#ifdef HAVE_ARPA_NAMESER_H +#include +#ifdef STATUS +#undef STATUS +#endif #endif -#endif /* __TINC_SYSTEM_H__ */ +#ifdef HAVE_RESOLV_H +#include +#endif + +#ifdef HAVE_LINUX_IF_TUN_H +#include +#endif + +#endif diff --git a/src/info.c b/src/info.c deleted file mode 100644 index af085bc..0000000 --- a/src/info.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - info.c -- Show information about a node, subnet or address - Copyright (C) 2012-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "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; -} diff --git a/src/info.h b/src/info.h deleted file mode 100644 index a3f387f..0000000 --- a/src/info.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - info.h -- header for info.c. - Copyright (C) 2012 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_INFO_H__ -#define __TINC_INFO_H__ - -extern int info(int fd, const char *item); -extern char *strip_weight(char *); - -#endif - diff --git a/src/invitation.c b/src/invitation.c deleted file mode 100644 index f1cde58..0000000 --- a/src/invitation.c +++ /dev/null @@ -1,939 +0,0 @@ -/* - invitation.c -- Create and accept invitations - Copyright (C) 2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "control_common.h" -#include "crypto.h" -#include "ecdsa.h" -#include "ecdsagen.h" -#include "invitation.h" -#include "names.h" -#include "netutl.h" -#include "rsagen.h" -#include "sptps.h" -#include "tincctl.h" -#include "utils.h" -#include "xalloc.h" - -#ifdef HAVE_MINGW -#define SCRIPTEXTENSION ".bat" -#else -#define SCRIPTEXTENSION "" -#endif - -int addressfamily = AF_UNSPEC; - -char *get_my_hostname() { - char *hostname = NULL; - char *port = NULL; - char *hostport = NULL; - char *name = get_my_name(false); - char *filename = NULL; - - // Use first Address statement in own host config file - if(check_id(name)) { - xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name); - FILE *f = fopen(filename, "r"); - if(f) { - while(fgets(line, sizeof line, f)) { - if(!rstrip(line)) - continue; - char *p = line, *q; - p += strcspn(p, "\t ="); - if(!*p) - continue; - q = p + strspn(p, "\t "); - if(*q == '=') - q += 1 + strspn(q + 1, "\t "); - *p = 0; - p = q + strcspn(q, "\t "); - if(*p) - *p++ = 0; - p += strspn(p, "\t "); - p[strcspn(p, "\t ")] = 0; - if(!port && !strcasecmp(line, "Port")) { - port = xstrdup(q); - continue; - } - if(strcasecmp(line, "Address")) - continue; - hostname = xstrdup(q); - if(*p) { - free(port); - port = xstrdup(p); - } - break; - } - fclose(f); - } - } - - if(hostname) - goto done; - - // If that doesn't work, guess externally visible hostname - fprintf(stderr, "Trying to discover externally visible hostname...\n"); - struct addrinfo *ai = str2addrinfo("ifconfig.me", "80", SOCK_STREAM); - static const char request[] = "GET /host HTTP/1.0\r\n\r\n"; - if(ai) { - int s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if(s >= 0) { - if(connect(s, ai->ai_addr, ai->ai_addrlen)) { - closesocket(s); - s = -1; - } - } - if(s >= 0) { - send(s, request, sizeof request - 1, 0); - int len = recv(s, line, sizeof line - 1, MSG_WAITALL); - if(len > 0) { - line[len] = 0; - if(line[len - 1] == '\n') - line[--len] = 0; - char *p = strrchr(line, '\n'); - if(p && p[1]) - hostname = xstrdup(p + 1); - } - closesocket(s); - } - freeaddrinfo(ai); - } - - // Check that the hostname is reasonable - if(hostname) { - for(char *p = hostname; *p; p++) { - if(isalnum(*p) || *p == '-' || *p == '.') - continue; - // If not, forget it. - free(hostname); - hostname = NULL; - break; - } - } - -again: - printf("Please enter your host's external address or hostname"); - if(hostname) - printf(" [%s]", hostname); - printf(": "); - fflush(stdout); - - if(!fgets(line, sizeof line, stdin)) { - fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno)); - free(hostname); - return NULL; - } - - if(!rstrip(line)) { - if(hostname) - goto save; - else - goto again; - } - - for(char *p = line; *p; p++) { - if(isalnum(*p) || *p == '-' || *p == '.') - continue; - fprintf(stderr, "Invalid address or hostname.\n"); - goto again; - } - - free(hostname); - hostname = xstrdup(line); - -save: - if(filename) { - FILE *f = fopen(filename, "a"); - if(f) { - fprintf(f, "\nAddress = %s\n", hostname); - fclose(f); - } else { - fprintf(stderr, "Could not append Address to %s: %s\n", filename, strerror(errno)); - } - } - -done: - if(port) { - if(strchr(hostname, ':')) - xasprintf(&hostport, "[%s]:%s", hostname, port); - else - xasprintf(&hostport, "%s:%s", hostname, port); - } else { - hostport = hostname; - hostname = NULL; - } - - free(hostname); - free(port); - free(filename); - return hostport; -} - -static bool fcopy(FILE *out, const char *filename) { - FILE *in = fopen(filename, "r"); - if(!in) { - fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno)); - return false; - } - - char buf[1024]; - size_t len; - while((len = fread(buf, 1, sizeof buf, in))) - fwrite(buf, len, 1, out); - fclose(in); - return true; -} - -int cmd_invite(int argc, char *argv[]) { - if(argc < 2) { - fprintf(stderr, "Not enough arguments!\n"); - return 1; - } - - // Check validity of the new node's name - if(!check_id(argv[1])) { - fprintf(stderr, "Invalid name for node.\n"); - return 1; - } - - char *myname = get_my_name(true); - if(!myname) - return 1; - - // Ensure no host configuration file with that name exists - char *filename = NULL; - xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]); - if(!access(filename, F_OK)) { - free(filename); - fprintf(stderr, "A host config file for %s already exists!\n", argv[1]); - return 1; - } - free(filename); - - // If a daemon is running, ensure no other nodes now about this name - bool found = false; - if(connect_tincd(false)) { - sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES); - - while(recvline(fd, line, sizeof line)) { - char node[4096]; - int code, req; - if(sscanf(line, "%d %d %s", &code, &req, node) != 3) - break; - if(!strcmp(node, argv[1])) - found = true; - } - - if(found) { - fprintf(stderr, "A node with name %s is already known!\n", argv[1]); - return 1; - } - } - - char hash[25]; - - xasprintf(&filename, "%s" SLASH "invitations", confbase); - if(mkdir(filename, 0700) && errno != EEXIST) { - fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno)); - free(filename); - return 1; - } - - // Count the number of valid invitations, clean up old ones - DIR *dir = opendir(filename); - if(!dir) { - fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno)); - free(filename); - return 1; - } - - errno = 0; - int count = 0; - struct dirent *ent; - time_t deadline = time(NULL) - 604800; // 1 week in the past - - while((ent = readdir(dir))) { - if(strlen(ent->d_name) != 24) - continue; - char *invname; - struct stat st; - xasprintf(&invname, "%s" SLASH "%s", filename, ent->d_name); - if(!stat(invname, &st)) { - if(deadline < st.st_mtime) - count++; - else - unlink(invname); - } else { - fprintf(stderr, "Could not stat %s: %s\n", invname, strerror(errno)); - errno = 0; - } - free(invname); - } - - if(errno) { - fprintf(stderr, "Error while reading directory %s: %s\n", filename, strerror(errno)); - closedir(dir); - free(filename); - return 1; - } - - closedir(dir); - free(filename); - - ecdsa_t *key; - xasprintf(&filename, "%s" SLASH "invitations" SLASH "ecdsa_key.priv", confbase); - - // Remove the key if there are no outstanding invitations. - if(!count) - unlink(filename); - - // Create a new key if necessary. - FILE *f = fopen(filename, "r"); - if(!f) { - if(errno != ENOENT) { - fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno)); - free(filename); - return 1; - } - - key = ecdsa_generate(); - if(!key) { - free(filename); - return 1; - } - f = fopen(filename, "w"); - if(!f) { - fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno)); - free(filename); - return 1; - } - chmod(filename, 0600); - ecdsa_write_pem_private_key(key, f); - } else { - key = ecdsa_read_pem_private_key(f); - if(!key) - fprintf(stderr, "Could not read private key from %s\n", filename); - } - fclose(f); - free(filename); - if(!key) - return 1; - - // Create a hash of the key. - char *fingerprint = ecdsa_get_base64_public_key(key); - digest_t *digest = digest_open_by_name("sha256", 18); - if(!digest) - abort(); - digest_create(digest, fingerprint, strlen(fingerprint), hash); - b64encode_urlsafe(hash, hash, 18); - - // Create a random cookie for this invitation. - char cookie[25]; - randomize(cookie, 18); - b64encode_urlsafe(cookie, cookie, 18); - - // Create a file containing the details of the invitation. - xasprintf(&filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookie); - int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); - if(!ifd) { - fprintf(stderr, "Could not create invitation file %s: %s\n", filename, strerror(errno)); - free(filename); - return 1; - } - free(filename); - f = fdopen(ifd, "w"); - if(!f) - abort(); - - // Fill in the details. - fprintf(f, "Name = %s\n", argv[1]); - if(netname) - fprintf(f, "NetName = %s\n", netname); - fprintf(f, "ConnectTo = %s\n", myname); - // TODO: copy Broadcast and Mode - fprintf(f, "#---------------------------------------------------------------#\n"); - fprintf(f, "Name = %s\n", myname); - - xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, myname); - fcopy(f, filename); - fclose(f); - - // Create an URL from the local address, key hash and cookie - char *address = get_my_hostname(); - printf("%s/%s%s\n", address, hash, cookie); - free(filename); - free(address); - - return 0; -} - -static int sock; -static char cookie[18]; -static sptps_t sptps; -static char *data; -static size_t datalen; -static bool success = false; - -static char cookie[18], hash[18]; - -static char *get_line(const char **data) { - if(!data || !*data) - return NULL; - - if(!**data) { - *data = NULL; - return NULL; - } - - static char line[1024]; - const char *end = strchr(*data, '\n'); - size_t len = end ? end - *data : strlen(*data); - if(len >= sizeof line) { - fprintf(stderr, "Maximum line length exceeded!\n"); - return NULL; - } - if(len && !isprint(**data)) - abort(); - - memcpy(line, *data, len); - line[len] = 0; - - if(end) - *data = end + 1; - else - *data = NULL; - - return line; -} - -static char *get_value(const char *data, const char *var) { - char *line = get_line(&data); - if(!line) - return NULL; - - char *sep = line + strcspn(line, " \t="); - char *val = sep + strspn(sep, " \t"); - if(*val == '=') - val += 1 + strspn(val + 1, " \t"); - *sep = 0; - if(strcasecmp(line, var)) - return NULL; - return val; -} - -static char *grep(const char *data, const char *var) { - static char value[1024]; - - const char *p = data; - int varlen = strlen(var); - - // Skip all lines not starting with var - while(strncasecmp(p, var, varlen) || !strchr(" \t=", p[varlen])) { - p = strchr(p, '\n'); - if(!p) - break; - else - p++; - } - - if(!p) - return NULL; - - p += varlen; - p += strspn(p, " \t"); - if(*p == '=') - p += 1 + strspn(p + 1, " \t"); - - const char *e = strchr(p, '\n'); - if(!e) - return xstrdup(p); - - if(e - p >= sizeof value) { - fprintf(stderr, "Maximum line length exceeded!\n"); - return NULL; - } - - memcpy(value, p, e - p); - value[e - p] = 0; - return value; -} - -static bool finalize_join(void) { - char *name = xstrdup(get_value(data, "Name")); - if(!name) { - fprintf(stderr, "No Name found in invitation!\n"); - return false; - } - - if(!check_id(name)) { - fprintf(stderr, "Invalid Name found in invitation: %s!\n", name); - return false; - } - - if(!netname) - netname = grep(data, "NetName"); - - bool ask_netname = false; - char temp_netname[32]; - -make_names: - if(!confbasegiven) { - free(confbase); - confbase = NULL; - } - - make_names(); - - free(tinc_conf); - free(hosts_dir); - - xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase); - xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase); - - if(!access(tinc_conf, F_OK)) { - fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf); - if(!tty || confbasegiven) - return false; - - // Generate a random netname, ask for a better one later. - ask_netname = true; - snprintf(temp_netname, sizeof temp_netname, "join_%x", rand()); - netname = temp_netname; - goto make_names; - } - - if(mkdir(confbase, 0777) && errno != EEXIST) { - fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno)); - return false; - } - - if(mkdir(hosts_dir, 0777) && errno != EEXIST) { - fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno)); - return false; - } - - FILE *f = fopen(tinc_conf, "w"); - if(!f) { - fprintf(stderr, "Could not create file %s: %s\n", tinc_conf, strerror(errno)); - return false; - } - - fprintf(f, "Name = %s\n", name); - - char *filename; - xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name); - FILE *fh = fopen(filename, "w"); - if(!fh) { - fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno)); - return false; - } - - // Filter first chunk on approved keywords, split between tinc.conf and hosts/Name - // Other chunks go unfiltered to their respective host config files - const char *p = data; - char *l, *value; - - while((l = get_line(&p))) { - // Ignore comments - if(*l == '#') - continue; - - // Split line into variable and value - int len = strcspn(l, "\t ="); - value = l + len; - value += strspn(value, "\t "); - if(*value == '=') { - value++; - value += strspn(value, "\t "); - } - l[len] = 0; - - // Is it a Name? - if(!strcasecmp(l, "Name")) - if(strcmp(value, name)) - break; - else - continue; - else if(!strcasecmp(l, "NetName")) - continue; - - // Check the list of known variables - bool found = false; - int i; - for(i = 0; variables[i].name; i++) { - if(strcasecmp(l, variables[i].name)) - continue; - found = true; - break; - } - - // Ignore unknown and unsafe variables - if(!found) { - fprintf(stderr, "Ignoring unknown variable '%s' in invitation.\n", l); - continue; - } else if(!(variables[i].type & VAR_SAFE)) { - fprintf(stderr, "Ignoring unsafe variable '%s' in invitation.\n", l); - continue; - } - - // Copy the safe variable to the right config file - fprintf(variables[i].type & VAR_HOST ? fh : f, "%s = %s\n", l, value); - } - - fclose(f); - free(filename); - - while(l && !strcasecmp(l, "Name")) { - if(!check_id(value)) { - fprintf(stderr, "Invalid Name found in invitation.\n"); - return false; - } - - if(!strcmp(value, name)) { - fprintf(stderr, "Secondary chunk would overwrite our own host config file.\n"); - return false; - } - - xasprintf(&filename, "%s" SLASH "%s", hosts_dir, value); - f = fopen(filename, "w"); - - if(!f) { - fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno)); - return false; - } - - while((l = get_line(&p))) { - if(!strcmp(l, "#---------------------------------------------------------------#")) - continue; - int len = strcspn(l, "\t ="); - if(len == 4 && !strncasecmp(l, "Name", 4)) { - value = l + len; - value += strspn(value, "\t "); - if(*value == '=') { - value++; - value += strspn(value, "\t "); - } - l[len] = 0; - break; - } - - fputs(l, f); - fputc('\n', f); - } - - fclose(f); - free(filename); - } - - // Generate our key and send a copy to the server - ecdsa_t *key = ecdsa_generate(); - if(!key) - return false; - - char *b64key = ecdsa_get_base64_public_key(key); - if(!b64key) - return false; - - xasprintf(&filename, "%s" SLASH "ecdsa_key.priv", confbase); - f = fopenmask(filename, "w", 0600); - - if(!ecdsa_write_pem_private_key(key, f)) { - fprintf(stderr, "Error writing private key!\n"); - ecdsa_free(key); - fclose(f); - return false; - } - - fclose(f); - - fprintf(fh, "ECDSAPublicKey = %s\n", b64key); - - sptps_send_record(&sptps, 1, b64key, strlen(b64key)); - free(b64key); - - - rsa_t *rsa = rsa_generate(2048, 0x1001); - xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase); - f = fopenmask(filename, "w", 0600); - - rsa_write_pem_private_key(rsa, f); - fclose(f); - - rsa_write_pem_public_key(rsa, fh); - fclose(fh); - - ecdsa_free(key); - rsa_free(rsa); - - check_port(name); - - fprintf(stderr, "Invitation succesfully accepted.\n"); - shutdown(sock, SHUT_RDWR); - success = true; - -ask_netname: - if(ask_netname) { - fprintf(stderr, "Enter a new netname: "); - if(!fgets(line, sizeof line, stdin)) { - fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno)); - return false; - } - if(!*line || *line == '\n') - goto ask_netname; - - line[strlen(line) - 1] = 0; - - char *newbase; - xasprintf(&newbase, CONFDIR SLASH "tinc" SLASH "%s", line); - if(rename(confbase, newbase)) { - fprintf(stderr, "Error trying to rename %s to %s: %s\n", confbase, newbase, strerror(errno)); - free(newbase); - goto ask_netname; - } - - free(newbase); - netname = line; - make_names(); - } - - return true; -} - -static bool invitation_send(void *handle, uint8_t type, const char *data, size_t len) { - while(len) { - int result = send(sock, data, len, 0); - if(result == -1 && errno == EINTR) - continue; - else if(result <= 0) - return false; - data += result; - len -= result; - } - return true; -} - -static bool invitation_receive(void *handle, uint8_t type, const char *msg, uint16_t len) { - switch(type) { - case SPTPS_HANDSHAKE: - return sptps_send_record(&sptps, 0, cookie, sizeof cookie); - - case 0: - data = xrealloc(data, datalen + len + 1); - memcpy(data + datalen, msg, len); - datalen += len; - data[datalen] = 0; - break; - - case 1: - return finalize_join(); - - default: - return false; - } - - return true; -} - -int cmd_join(int argc, char *argv[]) { - free(data); - data = NULL; - datalen = 0; - - if(argc > 2) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - // Make sure confbase exists and is accessible. - if(strcmp(confdir, confbase) && 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; - } - - if(access(confbase, R_OK | W_OK | X_OK)) { - fprintf(stderr, "No permission to write in directory %s: %s\n", confbase, strerror(errno)); - return 1; - } - - // If a netname or explicit configuration directory is specified, check for an existing tinc.conf. - if((netname || confbasegiven) && !access(tinc_conf, F_OK)) { - fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf); - return 1; - } - - // Either read the invitation from the command line or from stdin. - char *invitation; - - if(argc > 1) { - invitation = argv[1]; - } else { - if(tty) { - printf("Enter invitation URL: "); - fflush(stdout); - } - errno = EPIPE; - if(!fgets(line, sizeof line, stdin)) { - fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno)); - return false; - } - invitation = line; - } - - // Parse the invitation URL. - rstrip(line); - - char *slash = strchr(invitation, '/'); - if(!slash) - goto invalid; - - *slash++ = 0; - - if(strlen(slash) != 48) - goto invalid; - - char *address = invitation; - char *port = NULL; - if(*address == '[') { - address++; - char *bracket = strchr(address, ']'); - if(!bracket) - goto invalid; - *bracket = 0; - if(bracket[1] == ':') - port = bracket + 2; - } else { - port = strchr(address, ':'); - if(port) - *port++ = 0; - } - - if(!port || !*port) - port = "655"; - - if(!b64decode(slash, hash, 18) || !b64decode(slash + 24, cookie, 18)) - goto invalid; - - // Generate a throw-away key for the invitation. - ecdsa_t *key = ecdsa_generate(); - if(!key) - return 1; - - char *b64key = ecdsa_get_base64_public_key(key); - - // Connect to the tinc daemon mentioned in the URL. - struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM); - if(!ai) - return 1; - - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if(sock <= 0) { - fprintf(stderr, "Could not open socket: %s\n", strerror(errno)); - return 1; - } - - if(connect(sock, ai->ai_addr, ai->ai_addrlen)) { - fprintf(stderr, "Could not connect to %s port %s: %s\n", address, port, strerror(errno)); - closesocket(sock); - return 1; - } - - fprintf(stderr, "Connected to %s port %s...\n", address, port); - - // Tell him we have an invitation, and give him our throw-away key. - int len = snprintf(line, sizeof line, "0 ?%s %d.%d\n", b64key, PROT_MAJOR, PROT_MINOR); - if(len <= 0 || len >= sizeof line) - abort(); - - if(!sendline(sock, "0 ?%s %d.%d", b64key, PROT_MAJOR, 1)) { - fprintf(stderr, "Error sending request to %s port %s: %s\n", address, port, strerror(errno)); - closesocket(sock); - return 1; - } - - char hisname[4096] = ""; - int code, hismajor, hisminor = 0; - - if(!recvline(sock, line, sizeof line) || sscanf(line, "%d %s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(sock, line, sizeof line) || !rstrip(line) || sscanf(line, "%d ", &code) != 1 || code != ACK || strlen(line) < 3) { - fprintf(stderr, "Cannot read greeting from peer\n"); - closesocket(sock); - return 1; - } - - // Check if the hash of the key he gave us matches the hash in the URL. - char *fingerprint = line + 2; - digest_t *digest = digest_open_by_name("sha256", 18); - if(!digest) - abort(); - char hishash[18]; - if(!digest_create(digest, fingerprint, strlen(fingerprint), hishash)) { - fprintf(stderr, "Could not create digest\n%s\n", line + 2); - return 1; - } - if(memcmp(hishash, hash, 18)) { - fprintf(stderr, "Peer has an invalid key!\n%s\n", line + 2); - return 1; - - } - - ecdsa_t *hiskey = ecdsa_set_base64_public_key(fingerprint); - if(!hiskey) - return 1; - - // Start an SPTPS session - if(!sptps_start(&sptps, NULL, true, false, key, hiskey, "tinc invitation", 15, invitation_send, invitation_receive)) - return 1; - - // Feed rest of input buffer to SPTPS - if(!sptps_receive_data(&sptps, buffer, blen)) - return 1; - - while((len = recv(sock, line, sizeof line, 0))) { - if(len < 0) { - if(errno == EINTR) - continue; - fprintf(stderr, "Error reading data from %s port %s: %s\n", address, port, strerror(errno)); - return 1; - } - - if(!sptps_receive_data(&sptps, line, len)) - return 1; - } - - sptps_stop(&sptps); - ecdsa_free(hiskey); - ecdsa_free(key); - closesocket(sock); - - if(!success) { - fprintf(stderr, "Connection closed by peer, invitation cancelled.\n"); - return 1; - } - - return 0; - -invalid: - fprintf(stderr, "Invalid invitation URL.\n"); - return 1; -} diff --git a/src/invitation.h b/src/invitation.h deleted file mode 100644 index 3d017e9..0000000 --- a/src/invitation.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - invitation.h -- header for invitation.c. - Copyright (C) 2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_INVITATION_H__ -#define __TINC_INVITATION_H__ - -bool recvdata(int fd, char *data, size_t len); -int cmd_invite(int argc, char *argv[]); -int cmd_join(int argc, char *argv[]); - -#endif diff --git a/src/ipv4.h b/src/ipv4.h index 6cb969b..7979f7d 100644 --- a/src/ipv4.h +++ b/src/ipv4.h @@ -1,3 +1,6 @@ +#ifndef TINC_IPV4_H +#define TINC_IPV4_H + /* ipv4.h -- missing IPv4 related definitions Copyright (C) 2005 Ivo Timmermans @@ -18,9 +21,6 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_IPV4_H__ -#define __TINC_IPV4_H__ - #ifndef AF_INET #define AF_INET 2 #endif @@ -64,11 +64,11 @@ #ifndef HAVE_STRUCT_IP struct ip { #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int ip_hl:4; - unsigned int ip_v:4; + unsigned int ip_hl: 4; + unsigned int ip_v: 4; #else - unsigned int ip_v:4; - unsigned int ip_hl:4; + unsigned int ip_v: 4; + unsigned int ip_hl: 4; #endif uint8_t ip_tos; uint16_t ip_len; @@ -81,7 +81,7 @@ struct ip { uint8_t ip_p; uint16_t ip_sum; struct in_addr ip_src, ip_dst; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #endif #ifndef IP_OFFMASK @@ -143,7 +143,7 @@ struct icmp { #define icmp_radv icmp_dun.id_radv #define icmp_mask icmp_dun.id_mask #define icmp_data icmp_dun.id_data -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #endif -#endif /* __TINC_IPV4_H__ */ +#endif diff --git a/src/ipv6.h b/src/ipv6.h index 37d999a..1642278 100644 --- a/src/ipv6.h +++ b/src/ipv6.h @@ -1,3 +1,6 @@ +#ifndef TINC_IPV6_H +#define TINC_IPV6_H + /* ipv6.h -- missing IPv6 related definitions Copyright (C) 2005 Ivo Timmermans @@ -18,9 +21,6 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_IPV6_H__ -#define __TINC_IPV6_H__ - #ifndef AF_INET6 #define AF_INET6 10 #endif @@ -36,7 +36,7 @@ struct in6_addr { uint16_t u6_addr16[8]; uint32_t u6_addr32[4]; } in6_u; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #define s6_addr in6_u.u6_addr8 #define s6_addr16 in6_u.u6_addr16 #define s6_addr32 in6_u.u6_addr32 @@ -49,14 +49,14 @@ struct sockaddr_in6 { uint32_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #endif #ifndef IN6_IS_ADDR_V4MAPPED #define IN6_IS_ADDR_V4MAPPED(a) \ - ((((__const uint32_t *) (a))[0] == 0) \ - && (((__const uint32_t *) (a))[1] == 0) \ - && (((__const uint32_t *) (a))[2] == htonl (0xffff))) + ((((const uint32_t *) (a))[0] == 0) \ + && (((const uint32_t *) (a))[1] == 0) \ + && (((const uint32_t *) (a))[2] == htonl (0xffff))) #endif #ifndef HAVE_STRUCT_IP6_HDR @@ -72,7 +72,7 @@ struct ip6_hdr { } ip6_ctlun; struct in6_addr ip6_src; struct in6_addr ip6_dst; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #define ip6_vfc ip6_ctlun.ip6_un2_vfc #define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow #define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen @@ -91,7 +91,7 @@ struct icmp6_hdr { uint16_t icmp6_un_data16[2]; uint8_t icmp6_un_data8[4]; } icmp6_dataun; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #define ICMP6_DST_UNREACH_NOROUTE 0 #define ICMP6_DST_UNREACH 1 #define ICMP6_PACKET_TOO_BIG 2 @@ -111,7 +111,7 @@ struct icmp6_hdr { struct nd_neighbor_solicit { struct icmp6_hdr nd_ns_hdr; struct in6_addr nd_ns_target; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #define ND_OPT_SOURCE_LINKADDR 1 #define ND_OPT_TARGET_LINKADDR 2 #define nd_ns_type nd_ns_hdr.icmp6_type @@ -124,7 +124,7 @@ struct nd_neighbor_solicit { struct nd_opt_hdr { uint8_t nd_opt_type; uint8_t nd_opt_len; -} __attribute__ ((__packed__)); +} __attribute__((__packed__)); #endif -#endif /* __TINC_IPV6_H__ */ +#endif diff --git a/src/linux/.deps/.dirstamp b/src/linux/.deps/.dirstamp deleted file mode 100644 index e69de29..0000000 diff --git a/src/linux/.deps/device.Po b/src/linux/.deps/device.Po deleted file mode 100644 index 8541068..0000000 --- a/src/linux/.deps/device.Po +++ /dev/null @@ -1,467 +0,0 @@ -linux/device.o: linux/device.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h linux/../system.h \ - linux/../../config.h linux/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h linux/../dropin.h \ - linux/../fake-getaddrinfo.h linux/../fake-gai-errnos.h \ - linux/../fake-getnameinfo.h /usr/include/linux/if_tun.h \ - /usr/include/linux/filter.h linux/../conf.h linux/../splay_tree.h \ - linux/../list.h linux/../subnet.h linux/../net.h linux/../ipv6.h \ - linux/../cipher.h linux/../digest.h linux/../event.h linux/../conf.h \ - linux/../connection.h linux/../buffer.h linux/../rsa.h linux/../sptps.h \ - linux/../system.h linux/../ecdh.h linux/../ecdsa.h linux/../edge.h \ - linux/../node.h linux/../device.h linux/../logger.h linux/../names.h \ - linux/../net.h linux/../route.h linux/../utils.h linux/../xalloc.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -linux/../system.h: - -linux/../../config.h: - -linux/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -linux/../dropin.h: - -linux/../fake-getaddrinfo.h: - -linux/../fake-gai-errnos.h: - -linux/../fake-getnameinfo.h: - -/usr/include/linux/if_tun.h: - -/usr/include/linux/filter.h: - -linux/../conf.h: - -linux/../splay_tree.h: - -linux/../list.h: - -linux/../subnet.h: - -linux/../net.h: - -linux/../ipv6.h: - -linux/../cipher.h: - -linux/../digest.h: - -linux/../event.h: - -linux/../conf.h: - -linux/../connection.h: - -linux/../buffer.h: - -linux/../rsa.h: - -linux/../sptps.h: - -linux/../system.h: - -linux/../ecdh.h: - -linux/../ecdsa.h: - -linux/../edge.h: - -linux/../node.h: - -linux/../device.h: - -linux/../logger.h: - -linux/../names.h: - -linux/../net.h: - -linux/../route.h: - -linux/../utils.h: - -linux/../xalloc.h: diff --git a/src/linux/.dirstamp b/src/linux/.dirstamp deleted file mode 100644 index e69de29..0000000 diff --git a/src/linux/device.c b/src/linux/device.c index 127e3e8..38debe8 100644 --- a/src/linux/device.c +++ b/src/linux/device.c @@ -1,7 +1,7 @@ /* device.c -- Interaction with Linux ethertap and tun/tap device Copyright (C) 2001-2005 Ivo Timmermans, - 2001-2013 Guus Sliepen + 2001-2014 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,20 +20,23 @@ #include "../system.h" +#ifdef HAVE_LINUX_IF_TUN_H #include #define DEFAULT_DEVICE "/dev/net/tun" +#else +#define DEFAULT_DEVICE "/dev/tap0" +#endif #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_ETHERTAP, DEVICE_TYPE_TUN, DEVICE_TYPE_TAP, } device_type_t; @@ -44,25 +47,32 @@ char *device = NULL; char *iface = NULL; static char *type = NULL; static char ifrname[IFNAMSIZ]; -static char *device_info; +static const char *device_info; -uint64_t device_in_packets = 0; -uint64_t device_in_bytes = 0; -uint64_t device_out_packets = 0; -uint64_t device_out_bytes = 0; +static uint64_t device_total_in = 0; +static uint64_t device_total_out = 0; static bool setup_device(void) { - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + struct ifreq ifr; + bool t1q = false; + + 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) +#ifdef HAVE_LINUX_IF_TUN_H + if(netname != NULL) { iface = xstrdup(netname); + } +#else + iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); +#endif 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)); + logger(LOG_ERR, "Could not open %s: %s", device, strerror(errno)); return false; } @@ -70,12 +80,15 @@ static bool setup_device(void) { fcntl(device_fd, F_SETFD, FD_CLOEXEC); #endif - struct ifreq ifr = {{{0}}}; +#ifdef HAVE_LINUX_IF_TUN_H + /* Ok now check if this is an old ethertap or a new tun/tap thingie */ + + memset(&ifr, 0, sizeof(ifr)); 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); + logger(LOG_ERR, "Unknown device type %s!", type); return false; } @@ -84,31 +97,61 @@ static bool setup_device(void) { device_type = DEVICE_TYPE_TUN; device_info = "Linux tun/tap device (tun mode)"; } else { - if (routing_mode == RMODE_ROUTER) + 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) + /* Set IFF_ONE_QUEUE flag... */ + if(get_config_bool(lookup_config(config_tree, "IffOneQueue"), &t1q) && t1q) { ifr.ifr_flags |= IFF_ONE_QUEUE; + } + #endif - if(iface) + if(iface) { strncpy(ifr.ifr_name, iface, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = 0; + } if(!ioctl(device_fd, TUNSETIFF, &ifr)) { strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); + ifrname[IFNAMSIZ - 1] = 0; free(iface); iface = xstrdup(ifrname); + } else if(errno == EPERM || errno == EBUSY) { + logger(LOG_ERR, "Error while trying to configure %s: %s", device, strerror(errno)); + return false; + } else if(!ioctl(device_fd, (('T' << 8) | 202), &ifr)) { + logger(LOG_WARNING, "Old ioctl() request was needed for %s", device); + strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); + ifrname[IFNAMSIZ - 1] = 0; + free(iface); + iface = xstrdup(ifrname); + } else +#endif + { + if(routing_mode == RMODE_ROUTER) { + overwrite_mac = true; + } + + device_info = "Linux ethertap device"; + device_type = DEVICE_TYPE_ETHERTAP; + free(iface); + iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); } - logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info); + if(overwrite_mac && !ioctl(device_fd, SIOCGIFHWADDR, &ifr)) { + memcpy(mymac.x, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + } + + logger(LOG_INFO, "%s is a %s", device, device_info); return true; } @@ -122,79 +165,101 @@ static void close_device(void) { } static bool read_packet(vpn_packet_t *packet) { - int inlen; + int lenin; switch(device_type) { - case DEVICE_TYPE_TUN: - inlen = read(device_fd, packet->data + 10, MTU - 10); + case DEVICE_TYPE_TUN: + lenin = 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; - } + if(lenin <= 0) { + logger(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); + memset(packet->data, 0, 12); + packet->len = lenin + 10; + break; - if(inlen <= 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", - device_info, device, strerror(errno)); - return false; - } + case DEVICE_TYPE_TAP: + lenin = read(device_fd, packet->data, MTU); - packet->len = inlen; - break; - default: - abort(); + if(lenin <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", + device_info, device, strerror(errno)); + return false; + } + + packet->len = lenin; + break; + + case DEVICE_TYPE_ETHERTAP: + lenin = read(device_fd, packet->data - 2, MTU + 2); + + if(lenin <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", + device_info, device, strerror(errno)); + return false; + } + + packet->len = lenin - 2; + break; } - device_in_packets++; - device_in_bytes += packet->len; + device_total_in += packet->len; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, - device_info); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); return true; } static bool write_packet(vpn_packet_t *packet) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", - packet->len, device_info); + ifdebug(TRAFFIC) logger(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(); + case DEVICE_TYPE_TUN: + packet->data[10] = packet->data[11] = 0; + + if(write(device_fd, packet->data + 10, packet->len - 10) < 0) { + logger(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(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + break; + + case DEVICE_TYPE_ETHERTAP: + memcpy(packet->data - 2, &packet->len, 2); + + if(write(device_fd, packet->data - 2, packet->len + 2) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); + return false; + } + + break; } - device_out_packets++; - device_out_bytes += packet->len; + device_total_out += packet->len; return true; } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_in_bytes); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_out_bytes); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t os_devops = { diff --git a/src/linux/device.o b/src/linux/device.o deleted file mode 100644 index 6502843..0000000 Binary files a/src/linux/device.o and /dev/null differ diff --git a/src/list.c b/src/list.c index 0bbc5d4..a807c6d 100644 --- a/src/list.c +++ b/src/list.c @@ -1,7 +1,7 @@ /* list.c -- functions to deal with double linked lists Copyright (C) 2000-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2006 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,7 +26,9 @@ /* (De)constructors */ list_t *list_alloc(list_action_t delete) { - list_t *list = xzalloc(sizeof(list_t)); + list_t *list; + + list = xmalloc_and_zero(sizeof(list_t)); list->delete = delete; return list; @@ -37,12 +39,13 @@ void list_free(list_t *list) { } list_node_t *list_alloc_node(void) { - return xzalloc(sizeof(list_node_t)); + return xmalloc_and_zero(sizeof(list_node_t)); } void list_free_node(list_t *list, list_node_t *node) { - if(node->data && list->delete) + if(node->data && list->delete) { list->delete(node->data); + } free(node); } @@ -50,17 +53,20 @@ void list_free_node(list_t *list, list_node_t *node) { /* Insertion and deletion */ list_node_t *list_insert_head(list_t *list, void *data) { - list_node_t *node = list_alloc_node(); + list_node_t *node; + + node = list_alloc_node(); node->data = data; node->prev = NULL; node->next = list->head; list->head = node; - if(node->next) + if(node->next) { node->next->prev = node; - else + } else { list->tail = node; + } list->count++; @@ -68,55 +74,20 @@ list_node_t *list_insert_head(list_t *list, void *data) { } list_node_t *list_insert_tail(list_t *list, void *data) { - list_node_t *node = list_alloc_node(); + list_node_t *node; + + node = list_alloc_node(); node->data = data; node->next = NULL; node->prev = list->tail; list->tail = node; - if(node->prev) + if(node->prev) { node->prev->next = node; - else - list->head = node; - - list->count++; - - return node; -} - -list_node_t *list_insert_after(list_t *list, list_node_t *after, void *data) { - list_node_t *node = list_alloc_node(); - - node->data = data; - node->next = after->next; - node->prev = after; - after->next = node; - - if(node->next) - node->next->prev = node; - else - list->tail = node; - - list->count++; - - return node; -} - -list_node_t *list_insert_before(list_t *list, list_node_t *before, void *data) { - list_node_t *node; - - node = list_alloc_node(); - - node->data = data; - node->next = before; - node->prev = before->prev; - before->prev = node; - - if(node->prev) - node->prev->next = node; - else + } else { list->head = node; + } list->count++; @@ -124,15 +95,17 @@ list_node_t *list_insert_before(list_t *list, list_node_t *before, void *data) { } void list_unlink_node(list_t *list, list_node_t *node) { - if(node->prev) + if(node->prev) { node->prev->next = node->next; - else + } else { list->head = node->next; + } - if(node->next) + if(node->next) { node->next->prev = node->prev; - else + } else { list->tail = node->prev; + } list->count--; } @@ -150,33 +123,33 @@ void list_delete_tail(list_t *list) { list_delete_node(list, list->tail); } -void list_delete(list_t *list, const void *data) { - for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) - if(node->data == data) - list_delete_node(list, node); -} - /* Head/tail lookup */ void *list_get_head(list_t *list) { - if(list->head) + if(list->head) { return list->head->data; - else + } else { return NULL; + } } void *list_get_tail(list_t *list) { - if(list->tail) + if(list->tail) { return list->tail->data; - else + } else { return NULL; + } } /* Fast list deletion */ void list_delete_list(list_t *list) { - for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) + list_node_t *node, *next; + + for(node = list->head; node; node = next) { + next = node->next; list_free_node(list, node); + } list_free(list); } @@ -184,12 +157,22 @@ void list_delete_list(list_t *list) { /* Traversing */ void list_foreach_node(list_t *list, list_action_node_t action) { - for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) + list_node_t *node, *next; + + for(node = list->head; node; node = next) { + next = node->next; action(node); + } } void list_foreach(list_t *list, list_action_t action) { - for(list_node_t *node = list->head, *next; next = node ? node->next : NULL, node; node = next) - if(node->data) + list_node_t *node, *next; + + for(node = list->head; node; node = next) { + next = node->next; + + if(node->data) { action(node->data); + } + } } diff --git a/src/list.h b/src/list.h index 0437bd9..b2a9b3d 100644 --- a/src/list.h +++ b/src/list.h @@ -1,7 +1,10 @@ +#ifndef TINC_LIST_H +#define TINC_LIST_H + /* list.h -- header file for list.c Copyright (C) 2000-2005 Ivo Timmermans - 2000-2012 Guus Sliepen + 2000-2006 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,9 +21,6 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_LIST_H__ -#define __TINC_LIST_H__ - typedef struct list_node_t { struct list_node_t *prev; struct list_node_t *next; @@ -45,40 +45,34 @@ typedef struct list_t { /* (De)constructors */ -extern list_t *list_alloc(list_action_t) __attribute__ ((__malloc__)); -extern void list_free(list_t *); +extern list_t *list_alloc(list_action_t) __attribute__((__malloc__)); +extern void list_free(list_t *list); extern list_node_t *list_alloc_node(void); -extern void list_free_node(list_t *, list_node_t *); +extern void list_free_node(list_t *list, list_node_t *node); /* Insertion and deletion */ -extern list_node_t *list_insert_head(list_t *, void *); -extern list_node_t *list_insert_tail(list_t *, void *); -extern list_node_t *list_insert_after(list_t *, list_node_t *, void *); -extern list_node_t *list_insert_before(list_t *, list_node_t *, void *); +extern list_node_t *list_insert_head(list_t *list, void *data); +extern list_node_t *list_insert_tail(list_t *list, void *data); -extern void list_delete(list_t *, const void *); +extern void list_unlink_node(list_t *list, list_node_t *node); +extern void list_delete_node(list_t *list, list_node_t *node); -extern void list_unlink_node(list_t *, list_node_t *); -extern void list_delete_node(list_t *, list_node_t *); - -extern void list_delete_head(list_t *); -extern void list_delete_tail(list_t *); +extern void list_delete_head(list_t *list); +extern void list_delete_tail(list_t *list); /* Head/tail lookup */ -extern void *list_get_head(list_t *); -extern void *list_get_tail(list_t *); +extern void *list_get_head(list_t *list); +extern void *list_get_tail(list_t *list); /* Fast list deletion */ -extern void list_delete_list(list_t *); +extern void list_delete_list(list_t *list); /* Traversing */ -extern void list_foreach(list_t *, list_action_t); -extern void list_foreach_node(list_t *, list_action_node_t); +extern void list_foreach(list_t *list, list_action_t action); +extern void list_foreach_node(list_t *list, list_action_node_t action); -#define list_each(type, item, list) (type *item = (type *)1; item; item = NULL) for(list_node_t *node = (list)->head, *next; item = node ? node->data : NULL, next = node ? node->next : NULL, node; node = next) - -#endif /* __TINC_LIST_H__ */ +#endif diff --git a/src/logger.c b/src/logger.c index 2b4c7e3..8d4aea1 100644 --- a/src/logger.c +++ b/src/logger.c @@ -1,6 +1,6 @@ /* logger.c -- logging code - Copyright (C) 2004-2013 Guus Sliepen + Copyright (C) 2004-2016 Guus Sliepen 2004-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -21,179 +21,151 @@ #include "system.h" #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; +extern char *logfilename; 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] = ""; - static bool suppress = false; - - // Bail out early if there is nothing to do. - if(suppress) - return; - - if(!logcontrol && (level > debug_level || logmode == LOGMODE_NULL)) - return; - - if(level <= debug_level) { - switch(logmode) { - case LOGMODE_STDERR: - 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 - { - const char *messages[] = {message}; - ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL); - } -#else -#ifdef HAVE_SYSLOG_H - syslog(priority, "%s", message); -#endif -#endif - break; - case LOGMODE_NULL: - 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, ...) { - va_list ap; - char message[1024] = ""; - - va_start(ap, format); - int len = vsnprintf(message, sizeof message, format, ap); - va_end(ap); - - if(len > 0 && len < sizeof message && message[len - 1] == '\n') - message[len - 1] = 0; - - real_logger(level, priority, message); -} - -static void sptps_logger(sptps_t *s, int s_errno, const char *format, va_list ap) { - char message[1024] = ""; - int len = vsnprintf(message, sizeof message, format, ap); - if(len > 0 && len < sizeof message && message[len - 1] == '\n') - message[len - 1] = 0; - - real_logger(DEBUG_ALWAYS, LOG_ERR, message); -} void openlogger(const char *ident, logmode_t mode) { logident = ident; logmode = mode; switch(mode) { - 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: + 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); - if(!loghandle) { - fprintf(stderr, "Could not open log handle!"); - logmode = LOGMODE_NULL; - } - break; + loghandle = RegisterEventSource(NULL, logident); + + if(!loghandle) { + fprintf(stderr, "Could not open log handle!"); + logmode = LOGMODE_NULL; + } + + break; #else #ifdef HAVE_SYSLOG_H - openlog(logident, LOG_CONS | LOG_PID, LOG_DAEMON); - break; + openlog(logident, LOG_CONS | LOG_PID, LOG_DAEMON); + break; #endif #endif - case LOGMODE_NULL: - break; - } - if(logmode != LOGMODE_NULL) - sptps_log = sptps_logger; - else - sptps_log = sptps_log_quiet; + case LOGMODE_NULL: + break; + } } void reopenlogger() { - if(logmode != LOGMODE_FILE) + 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)); + logger(LOG_ERR, "Unable to reopen log file %s: %s", logfilename, strerror(errno)); return; } + fclose(logfile); logfile = newfile; } +void logger(int priority, const char *format, ...) { + va_list ap; + char timestr[32] = ""; + time_t now; + + va_start(ap, format); + + switch(logmode) { + case LOGMODE_STDERR: + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + fflush(stderr); + break; + + case LOGMODE_FILE: + now = time(NULL); + strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now)); + fprintf(logfile, "%s %s[%ld]: ", timestr, logident, (long)logpid); + vfprintf(logfile, format, ap); + fprintf(logfile, "\n"); + fflush(logfile); + break; + + case LOGMODE_SYSLOG: +#ifdef HAVE_MINGW + { + char message[4096]; + const char *messages[] = {message}; + vsnprintf(message, sizeof(message), format, ap); + message[sizeof(message) - 1] = 0; + ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL); + } + +#else +#ifdef HAVE_SYSLOG_H +#ifdef HAVE_VSYSLOG + vsyslog(priority, format, ap); +#else + { + char message[4096]; + vsnprintf(message, sizeof(message), format, ap); + syslog(priority, "%s", message); + } +#endif + break; +#endif +#endif + + case LOGMODE_NULL: + break; + } + + va_end(ap); +} void closelogger(void) { switch(logmode) { - case LOGMODE_FILE: - fclose(logfile); - break; - case LOGMODE_SYSLOG: + case LOGMODE_FILE: + fclose(logfile); + break; + + case LOGMODE_SYSLOG: #ifdef HAVE_MINGW - DeregisterEventSource(loghandle); - break; + DeregisterEventSource(loghandle); + break; #else #ifdef HAVE_SYSLOG_H - closelog(); - break; + closelog(); + break; #endif #endif - case LOGMODE_NULL: - case LOGMODE_STDERR: - break; - break; + + case LOGMODE_NULL: + case LOGMODE_STDERR: + break; } } diff --git a/src/logger.h b/src/logger.h index 637eef8..5a17ffb 100644 --- a/src/logger.h +++ b/src/logger.h @@ -1,7 +1,9 @@ +#ifndef TINC_LOGGER_H +#define TINC_LOGGER_H + /* logger.h -- header file for logger.c - Copyright (C) 1998-2005 Ivo Timmermans - 2000-2012 Guus Sliepen + Copyright (C) 2003-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,20 +20,17 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_LOGGER_H__ -#define __TINC_LOGGER_H__ - typedef enum debug_t { - DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */ + DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */ DEBUG_ALWAYS = 0, - DEBUG_CONNECTIONS = 1, /* Show (dis)connects of other tinc daemons via TCP */ - DEBUG_ERROR = 2, /* Show error messages received from other hosts */ - DEBUG_STATUS = 2, /* Show status messages received from other hosts */ - DEBUG_PROTOCOL = 3, /* Show the requests that are sent/received */ - DEBUG_META = 4, /* Show contents of every request that is sent/received */ - DEBUG_TRAFFIC = 5, /* Show network traffic information */ - DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */ - DEBUG_SCARY_THINGS = 10 /* You have been warned */ + DEBUG_CONNECTIONS = 1, /* Show (dis)connects of other tinc daemons via TCP */ + DEBUG_ERROR = 2, /* Show error messages received from other hosts */ + DEBUG_STATUS = 2, /* Show status messages received from other hosts */ + DEBUG_PROTOCOL = 3, /* Show the requests that are sent/received */ + DEBUG_META = 4, /* Show contents of every request that is sent/received */ + DEBUG_TRAFFIC = 5, /* Show network traffic information */ + DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */ + DEBUG_SCARY_THINGS = 10, /* You have been warned */ } debug_t; typedef enum logmode_t { @@ -66,10 +65,11 @@ enum { #endif extern debug_t debug_level; -extern bool logcontrol; -extern void openlogger(const char *, logmode_t); +extern void openlogger(const char *ident, logmode_t mode); extern void reopenlogger(void); -extern void logger(int, int, const char *, ...) __attribute__ ((__format__(printf, 3, 4))); +extern void logger(int priority, const char *format, ...) __attribute__((__format__(printf, 2, 3))); extern void closelogger(void); -#endif /* __TINC_LOGGER_H__ */ +#define ifdebug(l) if(debug_level >= DEBUG_##l) + +#endif diff --git a/src/meta.c b/src/meta.c index 887da4a..ee55ecd 100644 --- a/src/meta.c +++ b/src/meta.c @@ -1,6 +1,6 @@ /* meta.c -- handle the meta communication - Copyright (C) 2000-2013 Guus Sliepen , + Copyright (C) 2000-2017 Guus Sliepen , 2000-2005 Ivo Timmermans 2006 Scott Lamb @@ -21,107 +21,125 @@ #include "system.h" -#include "cipher.h" +#include +#include + +#include "avl_tree.h" #include "connection.h" #include "logger.h" #include "meta.h" #include "net.h" #include "protocol.h" +#include "proxy.h" #include "utils.h" #include "xalloc.h" -bool send_meta_sptps(void *handle, uint8_t type, const char *buffer, size_t length) { - connection_t *c = handle; +bool send_meta(connection_t *c, const char *buffer, int length) { + int outlen; + int result; - if(!c) { - logger(DEBUG_ALWAYS, LOG_ERR, "send_meta_sptps() called with NULL pointer!"); - abort(); + ifdebug(META) logger(LOG_DEBUG, "Sending %d bytes of metadata to %s (%s)", length, + c->name, c->hostname); + + if(!c->outbuflen) { + c->last_flushed_time = now; } - buffer_add(&c->outbuf, buffer, length); - io_set(&c->io, IO_READ | IO_WRITE); + /* Find room in connection's buffer */ + if(length + c->outbuflen > c->outbufsize) { + c->outbufsize = length + c->outbuflen; + c->outbuf = xrealloc(c->outbuf, c->outbufsize); + } + + if(length + c->outbuflen + c->outbufstart > c->outbufsize) { + memmove(c->outbuf, c->outbuf + c->outbufstart, c->outbuflen); + c->outbufstart = 0; + } + + /* Add our data to buffer */ + if(c->status.encryptout) { + /* Check encryption limits */ + if((uint64_t)length > c->outbudget) { + ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname); + return false; + } else { + c->outbudget -= length; + } + + result = EVP_EncryptUpdate(c->outctx, (unsigned char *)c->outbuf + c->outbufstart + c->outbuflen, + &outlen, (unsigned char *)buffer, length); + + if(!result || outlen < length) { + logger(LOG_ERR, "Error while encrypting metadata to %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } else if(outlen > length) { + logger(LOG_EMERG, "Encrypted data too long! Heap corrupted!"); + abort(); + } + + c->outbuflen += outlen; + } else { + memcpy(c->outbuf + c->outbufstart + c->outbuflen, buffer, length); + c->outbuflen += length; + } return true; } -bool send_meta(connection_t *c, const char *buffer, int length) { - if(!c) { - logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!"); - abort(); - } +bool flush_meta(connection_t *c) { + int result; - logger(DEBUG_META, LOG_DEBUG, "Sending %d bytes of metadata to %s (%s)", length, - c->name, c->hostname); + ifdebug(META) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s)", + c->outbuflen, c->name, c->hostname); - if(c->protocol_minor >= 2) - return sptps_send_record(&c->sptps, 0, buffer, length); + while(c->outbuflen) { + result = send(c->socket, c->outbuf + c->outbufstart, c->outbuflen, 0); - /* Add our data to buffer */ - if(c->status.encryptout) { - size_t outlen = length; + if(result <= 0) { + if(!errno || errno == EPIPE) { + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)", + c->name, c->hostname); + } else if(errno == EINTR) { + continue; + } else if(sockwouldblock(sockerrno)) { + ifdebug(META) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s) would block", + c->outbuflen, c->name, c->hostname); + return true; + } else { + logger(LOG_ERR, "Flushing meta data to %s (%s) failed: %s", c->name, + c->hostname, sockstrerror(sockerrno)); + } - if(!cipher_encrypt(c->outcipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting metadata to %s (%s)", - c->name, c->hostname); return false; } - } else { - buffer_add(&c->outbuf, buffer, length); + + c->outbufstart += result; + c->outbuflen -= result; } - io_set(&c->io, IO_READ | IO_WRITE); - + c->outbufstart = 0; /* avoid unnecessary memmoves */ return true; } void broadcast_meta(connection_t *from, const char *buffer, int length) { - for list_each(connection_t, c, connection_list) - if(c != from && c->status.active) + avl_node_t *node; + connection_t *c; + + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + + if(c != from && c->status.active) { send_meta(c, buffer, length); -} - -bool receive_meta_sptps(void *handle, uint8_t type, const char *data, uint16_t length) { - connection_t *c = handle; - - if(!c) { - logger(DEBUG_ALWAYS, LOG_ERR, "receive_meta_sptps() called with NULL pointer!"); - abort(); + } } - - if(type == SPTPS_HANDSHAKE) { - if(c->allow_request == ACK) - return send_ack(c); - else - return true; - } - - if(!data) - return true; - - /* Are we receiving a TCPpacket? */ - - if(c->tcplen) { - if(length != c->tcplen) - return false; - receive_tcppacket(c, data, length); - c->tcplen = 0; - return true; - } - - /* Change newline to null byte, just like non-SPTPS requests */ - - if(data[length - 1] == '\n') - ((char *)data)[length - 1] = 0; - - /* Otherwise we are waiting for a request */ - - return receive_request(c, data); } bool receive_meta(connection_t *c) { - int inlen; + int oldlen, i, result; + int lenin, lenout, reqlen; + bool decrypted = false; char inbuf[MAXBUFSIZE]; - char *bufp = inbuf, *endp; /* Strategy: - Read as much as possible from the TCP socket in one go. @@ -132,118 +150,109 @@ bool receive_meta(connection_t *c) { - If not, keep stuff in buffer and exit. */ - buffer_compact(&c->inbuf, MAXBUFSIZE); + lenin = recv(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen, 0); - if(sizeof inbuf <= c->inbuf.len) { - logger(DEBUG_ALWAYS, LOG_ERR, "Input buffer full for %s (%s)", c->name, c->hostname); - return false; - } - - inlen = recv(c->socket, inbuf, sizeof inbuf - c->inbuf.len, 0); - - if(inlen <= 0) { - if(!inlen || !errno) { - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", - c->name, c->hostname); - } else if(sockwouldblock(sockerrno)) + if(lenin <= 0) { + if(!lenin || !errno) { + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)", + c->name, c->hostname); + } else if(sockwouldblock(sockerrno)) { return true; - else - logger(DEBUG_ALWAYS, LOG_ERR, "Metadata socket read error for %s (%s): %s", - c->name, c->hostname, sockstrerror(sockerrno)); + } else + logger(LOG_ERR, "Metadata socket read error for %s (%s): %s", + c->name, c->hostname, sockstrerror(sockerrno)); + return false; } - do { - if(c->protocol_minor >= 2) - return sptps_receive_data(&c->sptps, bufp, inlen); + oldlen = c->buflen; + c->buflen += lenin; - if(!c->status.decryptin) { - endp = memchr(bufp, '\n', inlen); - if(endp) - endp++; - else - endp = bufp + inlen; + while(lenin > 0) { + reqlen = 0; - buffer_add(&c->inbuf, bufp, endp - bufp); + /* Is it proxy metadata? */ - inlen -= endp - bufp; - bufp = endp; - } else { - size_t outlen = inlen; + if(c->allow_request == PROXY) { + reqlen = receive_proxy_meta(c); - if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || inlen != outlen) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting metadata from %s (%s)", - c->name, c->hostname); + if(reqlen < 0) { return false; } - inlen = 0; + goto consume; } - while(c->inbuf.len) { - /* Are we receiving a TCPpacket? */ + /* Decrypt */ - if(c->tcplen) { - char *tcpbuffer = buffer_read(&c->inbuf, c->tcplen); - if(!tcpbuffer) - break; + if(c->status.decryptin && !decrypted) { + /* Check decryption limits */ + if((uint64_t)lenin > c->inbudget) { + ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname); + return false; + } else { + c->inbudget -= lenin; + } - if(!c->node) { - if(c->outgoing && proxytype == PROXY_SOCKS4 && c->allow_request == ID) { - if(tcpbuffer[0] == 0 && tcpbuffer[1] == 0x5a) { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted"); - } else { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected"); - return false; - } - } else if(c->outgoing && proxytype == PROXY_SOCKS5 && c->allow_request == ID) { - if(tcpbuffer[0] != 5) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server"); - return false; - } - if(tcpbuffer[1] == (char)0xff) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected: unsuitable authentication method"); - return false; - } - if(tcpbuffer[2] != 5) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server"); - return false; - } - if(tcpbuffer[3] == 0) { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted"); - } else { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request rejected"); - return false; - } - } else { - logger(DEBUG_CONNECTIONS, LOG_ERR, "c->tcplen set but c->node is NULL!"); - abort(); - } - } else { - if(c->allow_request == ALL) { - receive_tcppacket(c, tcpbuffer, c->tcplen); - } else { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname); - return false; - } + result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin); + + if(!result || lenout != lenin) { + logger(LOG_ERR, "Error while decrypting metadata from %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + memcpy(c->buffer + oldlen, inbuf, lenin); + decrypted = true; + } + + /* Are we receiving a TCPpacket? */ + + if(c->tcplen) { + if(c->tcplen <= c->buflen) { + if(c->allow_request != ALL) { + logger(LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname); + return false; } + receive_tcppacket(c, c->buffer, c->tcplen); + reqlen = c->tcplen; c->tcplen = 0; } - + } else { /* Otherwise we are waiting for a request */ - char *request = buffer_readline(&c->inbuf); - if(request) { - bool result = receive_request(c, request); - if(!result) - return false; - continue; - } else { - break; + for(i = oldlen; i < c->buflen; i++) { + if(c->buffer[i] == '\n') { + c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */ + c->reqlen = reqlen = i + 1; + break; + } + } + + if(reqlen && !receive_request(c)) { + return false; } } - } while(inlen); + +consume: + + if(reqlen) { + c->buflen -= reqlen; + lenin -= reqlen - oldlen; + memmove(c->buffer, c->buffer + reqlen, c->buflen); + oldlen = 0; + continue; + } else { + break; + } + } + + if(c->buflen >= MAXBUFSIZE) { + logger(LOG_ERR, "Metadata read buffer overflow for %s (%s)", + c->name, c->hostname); + return false; + } return true; } diff --git a/src/meta.h b/src/meta.h index 2a71228..36914f1 100644 --- a/src/meta.h +++ b/src/meta.h @@ -1,6 +1,9 @@ +#ifndef TINC_META_H +#define TINC_META_H + /* meta.h -- header for meta.c - Copyright (C) 2000-2012 Guus Sliepen , + Copyright (C) 2000-2006 Guus Sliepen , 2000-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -18,15 +21,11 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_META_H__ -#define __TINC_META_H__ - #include "connection.h" -extern bool send_meta(struct connection_t *, const char *, int); -extern bool send_meta_sptps(void *, uint8_t, const char *, size_t); -extern bool receive_meta_sptps(void *, uint8_t, const char *, uint16_t); -extern void broadcast_meta(struct connection_t *, const char *, int); -extern bool receive_meta(struct connection_t *); +extern bool send_meta(struct connection_t *c, const char *buffer, int length); +extern void broadcast_meta(struct connection_t *c, const char *buffer, int length); +extern bool flush_meta(struct connection_t *c); +extern bool receive_meta(struct connection_t *c); -#endif /* __TINC_META_H__ */ +#endif diff --git a/src/mingw/.deps/device.Po b/src/mingw/.deps/device.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/mingw/.deps/device.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/mingw/common.h b/src/mingw/common.h index 6e5e75c..41b9dc5 100644 --- a/src/mingw/common.h +++ b/src/mingw/common.h @@ -37,7 +37,7 @@ //============= #define TAP_CONTROL_CODE(request,method) \ - CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) + 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) diff --git a/src/mingw/device.c b/src/mingw/device.c index abe544e..321c515 100644 --- a/src/mingw/device.c +++ b/src/mingw/device.c @@ -1,7 +1,7 @@ /* device.c -- Interaction with Windows tap driver in a MinGW environment Copyright (C) 2002-2005 Ivo Timmermans, - 2002-2013 Guus Sliepen + 2002-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,7 +26,6 @@ #include "../conf.h" #include "../device.h" #include "../logger.h" -#include "../names.h" #include "../net.h" #include "../route.h" #include "../utils.h" @@ -38,51 +37,65 @@ int device_fd = -1; static HANDLE device_handle = INVALID_HANDLE_VALUE; char *device = NULL; char *iface = NULL; -static char *device_info = NULL; +static const char *device_info = "Windows tap device"; static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; extern char *myport; +OVERLAPPED r_overlapped; +OVERLAPPED w_overlapped; static DWORD WINAPI tapreader(void *bla) { int status; DWORD len; - OVERLAPPED overlapped; vpn_packet_t packet; + int errors = 0; - logger(DEBUG_ALWAYS, LOG_DEBUG, "Tap reader running"); + logger(LOG_DEBUG, "Tap reader running"); /* Read from tap device and send to parent */ - overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + r_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); for(;;) { - overlapped.Offset = 0; - overlapped.OffsetHigh = 0; - ResetEvent(overlapped.hEvent); + ResetEvent(r_overlapped.hEvent); - status = ReadFile(device_handle, (void *)packet.data, MTU, &len, &overlapped); + status = ReadFile(device_handle, packet.data, MTU, &len, &r_overlapped); if(!status) { if(GetLastError() == ERROR_IO_PENDING) { - WaitForSingleObject(overlapped.hEvent, INFINITE); - if(!GetOverlappedResult(device_handle, &overlapped, &len, FALSE)) + WaitForSingleObject(r_overlapped.hEvent, INFINITE); + + if(!GetOverlappedResult(device_handle, &r_overlapped, &len, FALSE)) { continue; + } } else { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info, - device, strerror(errno)); - return -1; + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + errors++; + + if(errors >= 10) { + EnterCriticalSection(&mutex); + running = false; + LeaveCriticalSection(&mutex); + } + + usleep(1000000); + continue; } } - EnterCriticalSection(&mutex); + errors = 0; packet.len = len; packet.priority = 0; + + EnterCriticalSection(&mutex); route(myself, &packet); - event_flush_output(); LeaveCriticalSection(&mutex); } + + return 0; } static bool setup_device(void) { @@ -104,51 +117,62 @@ static bool setup_device(void) { get_config_string(lookup_config(config_tree, "Device"), &device); get_config_string(lookup_config(config_tree, "Interface"), &iface); + if(device && iface) { + logger(LOG_WARNING, "Warning: both Device and Interface specified, results may not be as expected"); + } + /* 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())); + logger(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)) + 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); + snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapterid); - if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &key2)) { continue; + } - len = sizeof adaptername; + len = sizeof(adaptername); err = RegQueryValueEx(key2, "Name", 0, 0, (LPBYTE)adaptername, &len); RegCloseKey(key2); - if(err) + if(err) { continue; + } if(device) { if(!strcmp(device, adapterid)) { found = true; break; - } else + } else { continue; + } } if(iface) { if(!strcmp(iface, adaptername)) { found = true; break; - } else + } else { continue; + } } - snprintf(tapname, sizeof tapname, USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid); + 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; @@ -158,32 +182,34 @@ static bool setup_device(void) { RegCloseKey(key); if(!found) { - logger(DEBUG_ALWAYS, LOG_ERR, "No Windows tap device found!"); + logger(LOG_ERR, "No Windows tap device found!"); return false; } - if(!device) + if(!device) { device = xstrdup(adapterid); + } - if(!iface) + 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); + 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())); + logger(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())); + if(!DeviceIoControl(device_handle, TAP_IOCTL_GET_MAC, mymac.x, sizeof(mymac.x), mymac.x, sizeof(mymac.x), &len, 0)) { + logger(LOG_ERR, "Could not get MAC address from Windows tap device %s (%s): %s", device, iface, winerror(GetLastError())); return false; } @@ -191,23 +217,26 @@ static bool setup_device(void) { overwrite_mac = 1; } + /* Create overlapped events for tap I/O */ + + r_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + w_overlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + /* 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())); + logger(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); + 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); + logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info); return true; } @@ -224,15 +253,53 @@ static bool read_packet(vpn_packet_t *packet) { } static bool write_packet(vpn_packet_t *packet) { - DWORD outlen; - OVERLAPPED overlapped = {0}; + DWORD lenout; + static vpn_packet_t queue; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", - packet->len, device_info); + ifdebug(TRAFFIC) logger(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; + /* Check if there is something in progress */ + + if(queue.len) { + DWORD size; + BOOL success = GetOverlappedResult(device_handle, &w_overlapped, &size, FALSE); + + if(success) { + ResetEvent(&w_overlapped); + queue.len = 0; + } else { + int err = GetLastError(); + + if(err != ERROR_IO_INCOMPLETE) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error completing previously queued write: %s", winerror(err)); + ResetEvent(&w_overlapped); + queue.len = 0; + } else { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Previous overlapped write still in progress"); + // drop this packet + return true; + } + } + } + + /* Otherwise, try to write. */ + + memcpy(queue.data, packet->data, packet->len); + + if(!WriteFile(device_handle, queue.data, packet->len, &lenout, &w_overlapped)) { + int err = GetLastError(); + + if(err != ERROR_IO_PENDING) { + logger(LOG_ERR, "Error while writing to %s %s: %s", device_info, device, winerror(err)); + return false; + } + + // Write is being done asynchronously. + queue.len = packet->len; + } else { + // Write was completed immediately. + ResetEvent(&w_overlapped); } device_total_out += packet->len; @@ -241,9 +308,9 @@ static bool write_packet(vpn_packet_t *packet) { } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t os_devops = { diff --git a/src/multicast_device.c b/src/multicast_device.c index 5eaf103..93a40c4 100644 --- a/src/multicast_device.c +++ b/src/multicast_device.c @@ -1,7 +1,7 @@ /* device.c -- multicast socket Copyright (C) 2002-2005 Ivo Timmermans, - 2002-2013 Guus Sliepen + 2002-2014 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ #include "route.h" #include "xalloc.h" -static char *device_info; +static const char *device_info = "multicast socket"; static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; @@ -38,25 +38,25 @@ static struct addrinfo *ai = NULL; static mac_t ignore_src = {{0}}; static bool setup_device(void) { - char *host = NULL; + char *host; char *port; char *space; int ttl = 1; - device_info = "multicast socket"; - get_config_string(lookup_config(config_tree, "Interface"), &iface); if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Device variable required for %s", device_info); - goto error; + logger(LOG_ERR, "Device variable required for %s", device_info); + return false; } host = xstrdup(device); space = strchr(host, ' '); + if(!space) { - logger(DEBUG_ALWAYS, LOG_ERR, "Port number required for %s", device_info); - goto error; + logger(LOG_ERR, "Port number required for %s", device_info); + free(host); + return false; } *space++ = 0; @@ -69,13 +69,18 @@ static bool setup_device(void) { } ai = str2addrinfo(host, port, SOCK_DGRAM); - if(!ai) - goto error; + + if(!ai) { + free(host); + return false; + } 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; + logger(LOG_ERR, "Creating socket failed: %s", sockstrerror(sockerrno)); + free(host); + return false; } #ifdef FD_CLOEXEC @@ -83,73 +88,79 @@ static bool setup_device(void) { #endif static const int one = 1; - setsockopt(device_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof one); + 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; + closesocket(device_fd); + logger(LOG_ERR, "Can't bind to %s %s: %s", host, port, sockstrerror(sockerrno)); + free(host); + return false; } switch(ai->ai_family) { #ifdef IP_ADD_MEMBERSHIP - case AF_INET: { - struct ip_mreq mreq; - struct sockaddr_in in; - memcpy(&in, ai->ai_addr, sizeof in); - mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr; - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof mreq)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno)); - goto error; - } + + case AF_INET: { + struct ip_mreq mreq; + struct sockaddr_in in; + memcpy(&in, ai->ai_addr, sizeof(in)); + mreq.imr_multiaddr.s_addr = in.sin_addr.s_addr; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + + if(setsockopt(device_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq))) { + logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno)); + closesocket(device_fd); + free(host); + return false; + } + #ifdef IP_MULTICAST_LOOP - setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&one, sizeof one); + 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); + setsockopt(device_fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl, sizeof(ttl)); #endif - } break; + } + 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; - } + + case AF_INET6: { + struct ipv6_mreq mreq; + struct sockaddr_in6 in6; + memcpy(&in6, ai->ai_addr, sizeof(in6)); + memcpy(&mreq.ipv6mr_multiaddr, &in6.sin6_addr, sizeof(mreq.ipv6mr_multiaddr)); + mreq.ipv6mr_interface = in6.sin6_scope_id; + + if(setsockopt(device_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (void *)&mreq, sizeof(mreq))) { + logger(LOG_ERR, "Cannot join multicast group %s %s: %s", host, port, sockstrerror(sockerrno)); + closesocket(device_fd); + free(host); + return false; + } + #ifdef IPV6_MULTICAST_LOOP - setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&one, sizeof one); + 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); + setsockopt(device_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (void *)&ttl, sizeof(ttl)); #endif - } break; + } + break; #endif - default: - logger(DEBUG_ALWAYS, LOG_ERR, "Multicast for address family %hx unsupported", ai->ai_family); - goto error; + default: + logger(LOG_ERR, "Multicast for address family %x unsupported", ai->ai_family); + closesocket(device_fd); + free(host); + return false; } - freeaddrinfo(ai); - - logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info); + free(host); + logger(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) { @@ -158,21 +169,22 @@ static void close_device(void) { free(device); free(iface); - if(ai) + 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)); + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); return false; } - if(!memcmp(&ignore_src, packet->data + 6, sizeof ignore_src)) { - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info); + if(!memcmp(&ignore_src, packet->data + 6, sizeof(ignore_src))) { + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignoring loopback packet of %d bytes from %s", lenin, device_info); packet->len = 0; return true; } @@ -181,33 +193,33 @@ static bool read_packet(vpn_packet_t *packet) { device_total_in += packet->len; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, - device_info); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); return true; } static bool write_packet(vpn_packet_t *packet) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", - packet->len, device_info); + ifdebug(TRAFFIC) logger(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)); + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); return false; } device_total_out += packet->len; - memcpy(&ignore_src, packet->data + 6, sizeof ignore_src); + memcpy(&ignore_src, packet->data + 6, sizeof(ignore_src)); return true; } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t multicast_devops = { @@ -221,7 +233,7 @@ const devops_t multicast_devops = { #if 0 static bool not_supported(void) { - logger(DEBUG_ALWAYS, LOG_ERR, "Raw socket device not supported on this platform"); + logger(LOG_ERR, "Raw socket device not supported on this platform"); return false; } diff --git a/src/names.c b/src/names.c deleted file mode 100644 index a631ad9..0000000 --- a/src/names.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - names.c -- generate commonly used (file)names - Copyright (C) 1998-2005 Ivo Timmermans - 2000-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "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 */ -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 - - 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, LOCALSTATEDIR SLASH "run" 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); -} diff --git a/src/names.h b/src/names.h deleted file mode 100644 index 6f43a2c..0000000 --- a/src/names.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - names.h -- header for names.c - Copyright (C) 1998-2005 Ivo Timmermans - 2000-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_NAMES_H__ -#define __TINC_NAMES_H__ - -extern char *confdir; -extern char *confbase; -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__ */ diff --git a/src/net.c b/src/net.c index bf6cfcf..37ae116 100644 --- a/src/net.c +++ b/src/net.c @@ -1,7 +1,7 @@ /* net.c -- most of the network code Copyright (C) 1998-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2015 Guus Sliepen 2006 Scott Lamb 2011 Loïc Grenié @@ -22,48 +22,74 @@ #include "system.h" +#include + #include "utils.h" +#include "avl_tree.h" #include "conf.h" #include "connection.h" #include "device.h" +#include "event.h" #include "graph.h" #include "logger.h" #include "meta.h" -#include "names.h" #include "net.h" #include "netutl.h" #include "process.h" #include "protocol.h" +#include "route.h" #include "subnet.h" #include "xalloc.h" +bool do_purge = false; +volatile bool running = false; +#ifdef HAVE_PSELECT +bool graph_dump = false; +#endif + +time_t now = 0; int contradicting_add_edge = 0; int contradicting_del_edge = 0; static int sleeptime = 10; -time_t last_config_check = 0; -static timeout_t pingtimer; -static timeout_t periodictimer; /* Purge edges and subnets of unreachable nodes. Use carefully. */ -void purge(void) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "Purging unreachable nodes"); +static void purge(void) { + avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext; + node_t *n; + edge_t *e; + subnet_t *s; + + ifdebug(PROTOCOL) logger(LOG_DEBUG, "Purging unreachable nodes"); /* Remove all edges and subnets 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(nnode = node_tree->head; nnode; nnode = nnext) { + nnext = nnode->next; + n = nnode->data; - for splay_each(subnet_t, s, n->subnet_tree) { + if(!n->status.reachable) { + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Purging node %s (%s)", n->name, + n->hostname); + + for(snode = n->subnet_tree->head; snode; snode = snext) { + snext = snode->next; + s = snode->data; send_del_subnet(everyone, s); - if(!strictsubnets) + + if(!strictsubnets) { subnet_del(n, s); + } } - for splay_each(edge_t, e, n->edge_tree) { - if(!tunnelserver) + for(enode = n->edge_tree->head; enode; enode = enext) { + enext = enode->next; + e = enode->data; + + if(!tunnelserver) { send_del_edge(everyone, e); + } + edge_del(e); } } @@ -71,37 +97,145 @@ void purge(void) { /* Check if anyone else claims to have an edge to an unreachable node. If not, delete node. */ - for splay_each(node_t, n, node_tree) { - if(!n->status.reachable) { - for splay_each(edge_t, e, edge_weight_tree) - if(e->to == n) - return; + for(nnode = node_tree->head; nnode; nnode = nnext) { + nnext = nnode->next; + n = nnode->data; - if(!autoconnect && (!strictsubnets || !n->subnet_tree->head)) + if(!n->status.reachable) { + for(enode = edge_weight_tree->head; enode; enode = enext) { + enext = enode->next; + e = enode->data; + + if(e->to == n) { + break; + } + } + + if(!enode && (!strictsubnets || !n->subnet_tree->head)) /* in strictsubnets mode do not delete nodes with subnets */ + { node_del(n); + } } } } +/* + put all file descriptors in an fd_set array + While we're at it, purge stuff that needs to be removed. +*/ +static int build_fdset(fd_set *readset, fd_set *writeset) { + avl_node_t *node, *next; + connection_t *c; + int i, max = 0; + + FD_ZERO(readset); + FD_ZERO(writeset); + + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = node->data; + + if(c->status.remove) { + connection_del(c); + + if(!connection_tree->head) { + purge(); + } + } else { + FD_SET(c->socket, readset); + + if(c->outbuflen > 0 || c->status.connecting) { + FD_SET(c->socket, writeset); + } + + if(c->socket > max) { + max = c->socket; + } + } + } + + for(i = 0; i < listen_sockets; i++) { + FD_SET(listen_socket[i].tcp, readset); + + if(listen_socket[i].tcp > max) { + max = listen_socket[i].tcp; + } + + FD_SET(listen_socket[i].udp, readset); + + if(listen_socket[i].udp > max) { + max = listen_socket[i].udp; + } + } + + if(device_fd >= 0) { + FD_SET(device_fd, readset); + } + + if(device_fd > max) { + max = device_fd; + } + + return max; +} + +/* Put a misbehaving connection in the tarpit */ +void tarpit(int fd) { + static int pits[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + static int next_pit = 0; + + if(pits[next_pit] != -1) { + closesocket(pits[next_pit]); + } + + pits[next_pit++] = fd; + + if(next_pit >= (int)(sizeof pits / sizeof pits[0])) { + next_pit = 0; + } +} + /* Terminate a connection: - - Mark it as inactive - - Remove the edge representing this connection - - Kill it with fire + - Close the socket + - Remove associated edge and tell other connections about it if report = true - Check if we need to retry making an outgoing connection + - Deactivate the host */ void terminate_connection(connection_t *c, bool report) { - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname); + if(c->status.remove) { + return; + } + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Closing connection with %s (%s)", + c->name, c->hostname); + + c->status.remove = true; c->status.active = false; - if(c->node && c->node->connection == c) + if(c->node) { c->node->connection = NULL; + } + + if(c->socket) { + if(c->status.tarpit) { + tarpit(c->socket); + } else { + closesocket(c->socket); + } + } if(c->edge) { - if(report && !tunnelserver) + if(!c->node) { + logger(LOG_ERR, "Connection to %s (%s) has an edge but node is NULL!", c->name, c->hostname); + // And that should never happen. + abort(); + } + + if(report && !tunnelserver) { send_del_edge(everyone, c->edge); + } edge_del(c->edge); c->edge = NULL; @@ -115,21 +249,32 @@ void terminate_connection(connection_t *c, bool report) { if(report && !c->node->status.reachable) { edge_t *e; e = lookup_edge(c->node, myself); + if(e) { - if(!tunnelserver) + if(!tunnelserver) { send_del_edge(everyone, e); + } + edge_del(e); } } } - outgoing_t *outgoing = c->outgoing; - connection_del(c); + free_connection_partially(c); /* Check if this was our outgoing connection */ - if(outgoing) - do_outgoing_connection(outgoing); + if(c->outgoing) { + c->status.remove = false; + do_outgoing_connection(c); + } + +#ifndef HAVE_MINGW + /* Clean up dead proxy processes */ + + while(waitpid(-1, NULL, WNOHANG) > 0); + +#endif } /* @@ -140,333 +285,427 @@ void terminate_connection(connection_t *c, bool report) { end does not reply in time, we consider them dead and close the connection. */ -static void timeout_handler(void *data) { - for list_each(connection_t, c, connection_list) { - if(c->status.control) - continue; +static void check_dead_connections(void) { + avl_node_t *node, *next; + connection_t *c; - if(c->last_ping_time + pingtimeout <= now.tv_sec) { + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = node->data; + + if(c->last_ping_time + pingtimeout <= now) { if(c->status.active) { if(c->status.pinged) { - logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now.tv_sec - c->last_ping_time); - } else if(c->last_ping_time + pinginterval <= now.tv_sec) { + ifdebug(CONNECTIONS) logger(LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", + c->name, c->hostname, (long)(now - c->last_ping_time)); + c->status.timeout = true; + terminate_connection(c, true); + } else if(c->last_ping_time + pinginterval <= now) { send_ping(c); + } + } else { + if(c->status.remove) { + logger(LOG_WARNING, "Old connection_t for %s (%s) status %04x still lingering, deleting...", + c->name, c->hostname, bitfield_to_int(&c->status, sizeof(c->status))); + connection_del(c); continue; + } + + ifdebug(CONNECTIONS) logger(LOG_WARNING, "Timeout from %s (%s) during authentication", + c->name, c->hostname); + + if(c->status.connecting) { + c->status.connecting = false; + closesocket(c->socket); + do_outgoing_connection(c); } else { - continue; - } - } else { - if(c->status.connecting) - logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname); - else - logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname); - } - terminate_connection(c, c->status.active); - } - } - - timeout_set(data, &(struct timeval){pingtimeout, rand() % 100000}); -} - -static void periodic_handler(void *data) { - /* Check if there are too many contradicting ADD_EDGE and DEL_EDGE messages. - This usually only happens when another node has the same Name as this node. - If so, sleep for a short while to prevent a storm of contradicting messages. - */ - - if(contradicting_del_edge > 100 && contradicting_add_edge > 100) { - logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime); - usleep(sleeptime * 1000000LL); - sleeptime *= 2; - if(sleeptime < 0) - sleeptime = 3600; - } else { - sleeptime /= 2; - if(sleeptime < 10) - sleeptime = 10; - } - - contradicting_add_edge = 0; - contradicting_del_edge = 0; - - /* If AutoConnect is set, check if we need to make or break connections. */ - - if(autoconnect && node_tree->count > 1) { - /* Count number of active connections */ - int nc = 0; - for list_each(connection_t, c, connection_list) { - if(c->status.active && !c->status.control) - nc++; - } - - if(nc < autoconnect) { - /* Not enough active connections, try to add one. - Choose a random node, if we don't have a connection to it, - and we are not already trying to make one, create an - outgoing connection to this node. - */ - int r = rand() % node_tree->count; - int i = 0; - - for splay_each(node_t, n, node_tree) { - if(i++ != r) - continue; - - if(n->connection) - break; - - bool found = false; - - for list_each(outgoing_t, outgoing, outgoing_list) { - if(!strcmp(outgoing->name, n->name)) { - found = true; - break; - } - } - - if(!found) { - logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name); - outgoing_t *outgoing = xzalloc(sizeof *outgoing); - outgoing->name = xstrdup(n->name); - list_insert_tail(outgoing_list, outgoing); - setup_outgoing_connection(outgoing); - } - break; - } - } else if(nc > autoconnect) { - /* Too many active connections, try to remove one. - Choose a random outgoing connection to a node - that has at least one other connection. - */ - int r = rand() % nc; - int i = 0; - - for list_each(connection_t, c, connection_list) { - if(!c->status.active || c->status.control) - continue; - - if(i++ != r) - continue; - - if(!c->outgoing || !c->node || c->node->edge_tree->count < 2) - break; - - logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name); - list_delete(outgoing_list, c->outgoing); - c->outgoing = NULL; - terminate_connection(c, c->status.active); - break; - } - } - - if(nc >= autoconnect) { - /* If we have enough active connections, - remove any pending outgoing connections. - */ - for list_each(outgoing_t, o, outgoing_list) { - bool found = false; - for list_each(connection_t, c, connection_list) { - if(c->outgoing == o) { - found = true; - break; - } - } - if(!found) { - logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name); - list_delete_node(outgoing_list, node); + c->status.tarpit = true; + terminate_connection(c, false); } } } - } - timeout_set(data, &(struct timeval){5, rand() % 100000}); -} - -void handle_meta_connection_data(connection_t *c) { - if (!receive_meta(c)) { - terminate_connection(c, c->status.active); - return; - } -} - -#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; - - /* Reread our own configuration file */ - - exit_configuration(&config_tree); - init_configuration(&config_tree); - - if(!read_server_config()) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file."); - return EINVAL; - } - - read_config_options(config_tree, NULL); - - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name); - read_config_file(config_tree, fname); - free(fname); - - /* Parse some options that are allowed to be changed while tinc is running */ - - 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); + if(c->outbuflen > 0 && c->last_flushed_time + pingtimeout <= now) { + if(c->status.active) { + ifdebug(CONNECTIONS) logger(LOG_INFO, + "%s (%s) could not flush for %ld seconds (%d bytes remaining)", + c->name, c->hostname, (long)(now - c->last_flushed_time), c->outbuflen); + c->status.timeout = true; + terminate_connection(c, 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"); +/* + check all connections to see if anything + happened on their sockets +*/ +static void check_network_activity(fd_set *readset, fd_set *writeset) { + connection_t *c; + avl_node_t *node; + int result, i; + socklen_t len = sizeof(result); + vpn_packet_t packet; + static int errors = 0; - 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); + /* check input from kernel */ + if(device_fd >= 0 && FD_ISSET(device_fd, readset)) { + if(devops.read(&packet)) { + if(packet.len) { + errors = 0; + packet.priority = 0; + route(myself, &packet); } + } else { + usleep(errors * 50000); + errors++; - 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); + if(errors > 10) { + logger(LOG_ERR, "Too many errors from %s, exiting!", device); + running = false; } } } - /* Try to make outgoing connections */ + /* check meta connections */ + for(node = connection_tree->head; node; node = node->next) { + c = node->data; - 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) + if(c->status.remove) { continue; - - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name); - struct stat s; - if(stat(fname, &s) || s.st_mtime > last_config_check) { - logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name); - terminate_connection(c, c->status.active); } - free(fname); + + if(FD_ISSET(c->socket, writeset)) { + if(c->status.connecting) { + c->status.connecting = false; + getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len); + + if(!result) { + finish_connecting(c); + } else { + ifdebug(CONNECTIONS) logger(LOG_DEBUG, + "Error while connecting to %s (%s): %s", + c->name, c->hostname, sockstrerror(result)); + closesocket(c->socket); + do_outgoing_connection(c); + continue; + } + } + + if(!flush_meta(c)) { + terminate_connection(c, c->status.active); + continue; + } + } + + if(FD_ISSET(c->socket, readset)) { + if(!receive_meta(c)) { + c->status.tarpit = true; + terminate_connection(c, c->status.active); + continue; + } + } } - last_config_check = now.tv_sec; + for(i = 0; i < listen_sockets; i++) { + if(FD_ISSET(listen_socket[i].udp, readset)) { + handle_incoming_vpn_data(i); + } - return 0; -} - -void retry(void) { - /* Reset the reconnection timers for all outgoing connections */ - for list_each(outgoing_t, outgoing, outgoing_list) { - outgoing->timeout = 0; - if(outgoing->ev.cb) - timeout_set(&outgoing->ev, &(struct timeval){0, 0}); + if(FD_ISSET(listen_socket[i].tcp, readset)) { + handle_new_meta_connection(listen_socket[i].tcp); + } } - - /* Check for outgoing connections that are in progress, and reset their ping timers */ - for list_each(connection_t, c, connection_list) { - if(c->outgoing && !c->node) - c->last_ping_time = 0; - } - - /* Kick the ping timeout handler */ - timeout_set(&pingtimer, &(struct timeval){0, 0}); } /* this is where it all happens... */ int main_loop(void) { - 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); + fd_set readset, writeset; +#ifdef HAVE_PSELECT + struct timespec tv; + sigset_t omask, block_mask; + time_t next_event; +#else + struct timeval tv; #endif + int r, maxfd; + time_t last_ping_check, last_config_check, last_graph_dump; + event_t *event; - if(!event_loop()) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno)); - return 1; + last_ping_check = now; + last_config_check = now; + last_graph_dump = now; + + srand(now); + +#ifdef HAVE_PSELECT + + if(lookup_config(config_tree, "GraphDumpFile")) { + graph_dump = true; } -#ifndef HAVE_MINGW - signal_del(&sighup); - signal_del(&sigterm); - signal_del(&sigquit); - signal_del(&sigint); - signal_del(&sigalrm); + /* Block SIGHUP & SIGALRM */ + sigemptyset(&block_mask); + sigaddset(&block_mask, SIGHUP); + sigaddset(&block_mask, SIGALRM); + sigprocmask(SIG_BLOCK, &block_mask, &omask); #endif - timeout_del(&periodictimer); - timeout_del(&pingtimer); + running = true; + + while(running) { +#ifdef HAVE_PSELECT + next_event = last_ping_check + pingtimeout; + + if(graph_dump && next_event > last_graph_dump + 60) { + next_event = last_graph_dump + 60; + } + + if((event = peek_next_event()) && next_event > event->time) { + next_event = event->time; + } + + if(next_event <= now) { + tv.tv_sec = 0; + } else { + tv.tv_sec = next_event - now; + } + + tv.tv_nsec = 0; +#else + tv.tv_sec = 1; + tv.tv_usec = 0; +#endif + + maxfd = build_fdset(&readset, &writeset); + +#ifdef HAVE_MINGW + LeaveCriticalSection(&mutex); +#endif +#ifdef HAVE_PSELECT + r = pselect(maxfd + 1, &readset, &writeset, NULL, &tv, &omask); +#else + r = select(maxfd + 1, &readset, &writeset, NULL, &tv); +#endif + now = time(NULL); +#ifdef HAVE_MINGW + EnterCriticalSection(&mutex); +#endif + + if(r < 0) { + if(!sockwouldblock(sockerrno)) { + logger(LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno)); + dump_connections(); + return 1; + } + } + + if(r > 0) { + check_network_activity(&readset, &writeset); + } + + if(do_purge) { + purge(); + do_purge = false; + } + + /* Let's check if everybody is still alive */ + + if(last_ping_check + pingtimeout <= now) { + check_dead_connections(); + last_ping_check = now; + + if(routing_mode == RMODE_SWITCH) { + age_subnets(); + } + + age_past_requests(); + + /* Should we regenerate our key? */ + + if(keyexpires <= now) { + avl_node_t *node; + node_t *n; + + ifdebug(STATUS) logger(LOG_INFO, "Expiring symmetric keys"); + + for(node = node_tree->head; node; node = node->next) { + n = node->data; + + if(n->inkey) { + free(n->inkey); + n->inkey = NULL; + } + } + + send_key_changed(); + keyexpires = now + keylifetime; + } + + /* Detect ADD_EDGE/DEL_EDGE storms that are caused when + * two tinc daemons with the same name are on the VPN. + * If so, sleep a while. If this happens multiple times + * in a row, sleep longer. */ + + if(contradicting_del_edge > 100 && contradicting_add_edge > 100) { + logger(LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime); + usleep(sleeptime * 1000000LL); + sleeptime *= 2; + + if(sleeptime < 0) { + sleeptime = 3600; + } + } else { + sleeptime /= 2; + + if(sleeptime < 10) { + sleeptime = 10; + } + } + + contradicting_add_edge = 0; + contradicting_del_edge = 0; + } + + if(sigalrm) { + avl_node_t *node; + logger(LOG_INFO, "Flushing event queue"); + expire_events(); + + for(node = connection_tree->head; node; node = node->next) { + connection_t *c = node->data; + + if(c->status.active) { + send_ping(c); + } + } + + sigalrm = false; + } + + while((event = get_expired_event())) { + event->handler(event->data); + free_event(event); + } + + if(sighup) { + connection_t *c; + avl_node_t *node, *next; + char *fname; + struct stat s; + + sighup = false; + + reopenlogger(); + + /* Reread our own configuration file */ + + exit_configuration(&config_tree); + init_configuration(&config_tree); + + if(!read_server_config()) { + logger(LOG_ERR, "Unable to reread configuration file, exitting."); + return 1; + } + + /* Cancel non-active outgoing connections */ + + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = node->data; + + c->outgoing = NULL; + + if(c->status.connecting) { + terminate_connection(c, false); + connection_del(c); + } + } + + /* Wipe list of outgoing connections */ + + for(list_node_t *node = outgoing_list->head; node; node = node->next) { + outgoing_t *outgoing = node->data; + + if(outgoing->event) { + event_del(outgoing->event); + } + } + + list_delete_list(outgoing_list); + + /* Close connections to hosts that have a changed or deleted host config file */ + + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); + + if(stat(fname, &s) || s.st_mtime > last_config_check) { + terminate_connection(c, c->status.active); + } + + free(fname); + } + + last_config_check = now; + + /* If StrictSubnet is set, expire deleted Subnets and read new ones in */ + + if(strictsubnets) { + subnet_t *subnet; + + for(node = subnet_tree->head; node; node = node->next) { + subnet = node->data; + subnet->expires = 1; + } + + load_all_subnets(); + + for(node = subnet_tree->head; node; node = next) { + next = node->next; + subnet = node->data; + + if(subnet->expires == 1) { + send_del_subnet(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); + } + } + } + } + + /* Try to make outgoing connections */ + + try_outgoing_connections(); + } + + /* Dump graph if wanted every 60 seconds*/ + + if(last_graph_dump + 60 <= now) { + dump_graph(); + last_graph_dump = now; + } + } + +#ifdef HAVE_PSELECT + /* Restore SIGHUP & SIGALARM mask */ + sigprocmask(SIG_SETMASK, &omask, NULL); +#endif return 0; } diff --git a/src/net.h b/src/net.h index 9a97276..a9becb6 100644 --- a/src/net.h +++ b/src/net.h @@ -1,7 +1,10 @@ +#ifndef TINC_NET_H +#define TINC_NET_H + /* net.h -- header for net.c Copyright (C) 1998-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2015 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,13 +21,9 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_NET_H__ -#define __TINC_NET_H__ +#include #include "ipv6.h" -#include "cipher.h" -#include "digest.h" -#include "event.h" #ifdef ENABLE_JUMBOGRAMS #define MTU 9018 /* 9000 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ @@ -32,13 +31,10 @@ #define MTU 1518 /* 1500 bytes payload + 14 bytes ethernet header + 4 bytes VLAN tag */ #endif -/* MAXSIZE is the maximum size of an encapsulated packet: MTU + seqno + padding + HMAC + compressor overhead */ -#define MAXSIZE (MTU + 4 + CIPHER_MAX_BLOCK_SIZE + DIGEST_MAX_SIZE + MTU/64 + 20) +#define MAXSIZE (MTU + 4 + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + MTU/64 + 20) /* MTU + seqno + padding + HMAC + compressor overhead */ +#define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128) /* Enough room for a request with a MAXSIZEd packet or a 8192 bits RSA key */ -/* MAXBUFSIZE is the maximum size of a request: enough for a MAXSIZEd packet or a 8192 bits RSA key */ -#define MAXBUFSIZE ((MAXSIZE > 2048 ? MAXSIZE : 2048) + 128) - -#define MAXSOCKETS 8 /* Probably overkill... */ +#define MAXSOCKETS 128 /* Overkill... */ typedef struct mac_t { uint8_t x[6]; @@ -52,7 +48,7 @@ typedef struct ipv6_t { uint16_t x[8]; } ipv6_t; -typedef short length_t; +typedef uint16_t length_t; #define AF_UNKNOWN 255 @@ -87,22 +83,11 @@ typedef struct vpn_packet_t { uint8_t data[MAXSIZE]; } vpn_packet_t; -/* Packet types when using SPTPS */ - -#define PKT_COMPRESSED 1 -#define PKT_MAC 2 -#define PKT_PROBE 4 - -typedef enum packet_type_t { - PACKET_NORMAL, - PACKET_COMPRESSED, - PACKET_PROBE -} packet_type_t; - typedef struct listen_socket_t { - io_t tcp; - io_t udp; + int tcp; + int udp; sockaddr_t sa; + int priority; } listen_socket_t; #include "conf.h" @@ -111,11 +96,10 @@ typedef struct listen_socket_t { typedef struct outgoing_t { char *name; int timeout; - splay_tree_t *config_tree; struct config_t *cfg; struct addrinfo *ai; struct addrinfo *aip; - timeout_t ev; + struct event *event; } outgoing_t; extern list_t *outgoing_list; @@ -125,77 +109,48 @@ extern int seconds_till_retry; extern int addressfamily; extern unsigned replaywin; extern bool localdiscovery; -extern sockaddr_t localdiscovery_address; extern listen_socket_t listen_socket[MAXSOCKETS]; extern int listen_sockets; -extern io_t unix_socket; +extern int keyexpires; extern int keylifetime; extern int udp_rcvbuf; extern int udp_sndbuf; -extern int max_connection_burst; extern bool do_prune; +extern bool do_purge; extern char *myport; -extern int autoconnect; -extern bool disablebuggypeers; +extern time_t now; extern int contradicting_add_edge; extern int contradicting_del_edge; -extern time_t last_config_check; -extern char *proxyhost; -extern char *proxyport; -extern char *proxyuser; -extern char *proxypass; -typedef enum proxytype_t { - PROXY_NONE = 0, - PROXY_SOCKS4, - PROXY_SOCKS4A, - PROXY_SOCKS5, - PROXY_HTTP, - PROXY_EXEC, -} proxytype_t; -extern proxytype_t proxytype; - -extern char *scriptinterpreter; -extern char *scriptextension; +extern volatile bool running; /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */ #include "connection.h" #include "node.h" -extern void retry_outgoing(outgoing_t *); -extern void handle_incoming_vpn_data(void *, int); -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 bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t len); -extern void send_packet(struct node_t *, vpn_packet_t *); -extern void receive_tcppacket(struct connection_t *, const char *, int); -extern void broadcast_packet(const struct node_t *, vpn_packet_t *); +extern void retry_outgoing(outgoing_t *outgoing); +extern void handle_incoming_vpn_data(int sock); +extern void finish_connecting(struct connection_t *c); +extern void do_outgoing_connection(struct connection_t *c); +extern bool handle_new_meta_connection(int sock); +extern int setup_listen_socket(const sockaddr_t *sa); +extern int setup_vpn_in_socket(const sockaddr_t *sa); +extern void send_packet(const struct node_t *n, vpn_packet_t *packet); +extern void receive_tcppacket(struct connection_t *c, const char *buffer, length_t len); +extern void broadcast_packet(const struct node_t *, vpn_packet_t *packet); extern char *get_name(void); -extern bool setup_myself_reloadable(void); extern bool setup_network(void); -extern void setup_outgoing_connection(struct outgoing_t *); +extern void setup_outgoing_connection(struct outgoing_t *outgoing); extern void try_outgoing_connections(void); extern void close_network_connections(void); extern int main_loop(void); -extern void terminate_connection(struct connection_t *, bool); -extern bool node_read_ecdsa_public_key(struct node_t *); -extern bool read_ecdsa_public_key(struct connection_t *); -extern bool read_rsa_public_key(struct connection_t *); -extern void send_mtu_probe(struct node_t *); -extern void handle_device_data(void *, int); -extern void handle_meta_connection_data(struct connection_t *); -extern void regenerate_key(void); -extern void purge(void); -extern void retry(void); -extern int reload_configuration(void); +extern void terminate_connection(struct connection_t *c, bool report); +extern void flush_queue(struct node_t *n); +extern bool read_rsa_public_key(struct connection_t *c); +extern void send_mtu_probe(struct node_t *n); extern void load_all_subnets(void); -extern void load_all_nodes(void); +extern void tarpit(int fd); #ifndef HAVE_MINGW #define closesocket(s) close(s) @@ -203,4 +158,4 @@ extern void load_all_nodes(void); extern CRITICAL_SECTION mutex; #endif -#endif /* __TINC_NET_H__ */ +#endif diff --git a/src/net_packet.c b/src/net_packet.c index f79c9a7..938b3b6 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -1,7 +1,7 @@ /* net_packet.c -- Handles in- and outgoing VPN packets Copyright (C) 1998-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2016 Guus Sliepen 2010 Timothy Redaelli 2010 Brandon Black @@ -22,6 +22,12 @@ #include "system.h" +#include +#include +#include +#include +#include + #ifdef HAVE_ZLIB #include #endif @@ -30,13 +36,12 @@ #include LZO1X_H #endif -#include "cipher.h" +#include "avl_tree.h" #include "conf.h" #include "connection.h" -#include "crypto.h" -#include "digest.h" #include "device.h" #include "ethernet.h" +#include "event.h" #include "graph.h" #include "logger.h" #include "net.h" @@ -48,6 +53,7 @@ #include "xalloc.h" int keylifetime = 0; +int keyexpires = 0; #ifdef HAVE_LZO static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS]; #endif @@ -56,7 +62,6 @@ static void send_udppacket(node_t *, vpn_packet_t *); unsigned replaywin = 16; bool localdiscovery = false; -sockaddr_t localdiscovery_address; #define MAX_SEQNO 1073741824 @@ -76,14 +81,16 @@ sockaddr_t localdiscovery_address; */ -static void send_mtu_probe_handler(void *data) { - node_t *n = data; +void send_mtu_probe(node_t *n) { + vpn_packet_t packet; + int len, i; int timeout = 1; n->mtuprobes++; + n->mtuevent = NULL; if(!n->status.reachable || !n->status.validkey) { - logger(DEBUG_TRAFFIC, LOG_INFO, "Trying to send MTU probe to unreachable or rekeying node %s (%s)", n->name, n->hostname); + ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send MTU probe to unreachable or rekeying node %s (%s)", n->name, n->hostname); n->mtuprobes = 0; return; } @@ -95,25 +102,26 @@ static void send_mtu_probe_handler(void *data) { goto end; } - logger(DEBUG_TRAFFIC, LOG_INFO, "%s (%s) did not respond to UDP ping, restarting PMTU discovery", n->name, n->hostname); - n->status.udp_confirmed = false; + ifdebug(TRAFFIC) logger(LOG_INFO, "%s (%s) did not respond to UDP ping, restarting PMTU discovery", n->name, n->hostname); n->mtuprobes = 1; n->minmtu = 0; n->maxmtu = MTU; } if(n->mtuprobes >= 10 && n->mtuprobes < 32 && !n->minmtu) { - logger(DEBUG_TRAFFIC, LOG_INFO, "No response to MTU probes from %s (%s)", n->name, n->hostname); + ifdebug(TRAFFIC) logger(LOG_INFO, "No response to MTU probes from %s (%s)", n->name, n->hostname); n->mtuprobes = 31; } if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) { - if(n->minmtu > n->maxmtu) + if(n->minmtu > n->maxmtu) { n->minmtu = n->maxmtu; - else + } else { n->maxmtu = n->minmtu; + } + n->mtu = n->minmtu; - logger(DEBUG_TRAFFIC, LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes); + ifdebug(TRAFFIC) logger(LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes); n->mtuprobes = 31; } @@ -124,12 +132,12 @@ static void send_mtu_probe_handler(void *data) { timeout = pingtimeout; } - for(int i = 0; i < 4 + localdiscovery; i++) { - int len; - + for(i = 0; i < 4 + localdiscovery; i++) { if(i == 0) { - if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) + if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU) { continue; + } + len = n->maxmtu + 8; } else if(n->maxmtu <= n->minmtu) { len = n->maxmtu; @@ -137,143 +145,61 @@ static void send_mtu_probe_handler(void *data) { len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); } - if(len < 64) + if(len < 64) { len = 64; + } - vpn_packet_t packet; memset(packet.data, 0, 14); - randomize(packet.data + 14, len - 14); + RAND_bytes(packet.data + 14, len - 14); packet.len = len; - if(i >= 4 && n->mtuprobes <= 10) - packet.priority = -1; - else - packet.priority = 0; - logger(DEBUG_TRAFFIC, LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); + if(i >= 4 && n->mtuprobes <= 10) { + packet.priority = -1; + } else { + packet.priority = 0; + } + + ifdebug(TRAFFIC) logger(LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname); send_udppacket(n, &packet); } - n->probe_counter = 0; - gettimeofday(&n->probe_time, NULL); - - /* Calculate the packet loss of incoming traffic by comparing the rate of - packets received to the rate with which the sequence number has increased. - */ - - if(n->received > n->prev_received) - n->packetloss = 1.0 - (n->received - n->prev_received) / (float)(n->received_seqno - n->prev_received_seqno); - else - n->packetloss = n->received_seqno <= n->prev_received_seqno; - - n->prev_received_seqno = n->received_seqno; - n->prev_received = n->received; - end: - timeout_set(&n->mtutimeout, &(struct timeval){timeout, rand() % 100000}); + n->mtuevent = new_event(); + n->mtuevent->handler = (event_handler_t)send_mtu_probe; + n->mtuevent->data = n; + n->mtuevent->time = now + timeout; + event_add(n->mtuevent); } -void send_mtu_probe(node_t *n) { - timeout_add(&n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval){1, 0}); - send_mtu_probe_handler(n); -} +void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname); -static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { if(!packet->data[0]) { - logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe request %d from %s (%s)", packet->len, n->name, n->hostname); - - /* It's a probe request, send back a reply */ - - /* Type 2 probe replies were introduced in protocol 17.3 */ - if ((n->options >> 24) == 3) { - uint8_t* data = packet->data; - *data++ = 2; - uint16_t len16 = htons(len); memcpy(data, &len16, 2); data += 2; - struct timeval now; - gettimeofday(&now, NULL); - uint32_t sec = htonl(now.tv_sec); memcpy(data, &sec, 4); data += 4; - uint32_t usec = htonl(now.tv_usec); memcpy(data, &usec, 4); data += 4; - packet->len = data - packet->data; - } else { - /* Legacy protocol: n won't understand type 2 probe replies. */ - packet->data[0] = 1; - } - - /* Temporarily set udp_confirmed, so that the reply is sent - back exactly the way it came in. */ - - bool udp_confirmed = n->status.udp_confirmed; - n->status.udp_confirmed = true; + packet->data[0] = 1; send_udppacket(n, packet); - n->status.udp_confirmed = udp_confirmed; } else { - length_t probelen = len; - if (packet->data[0] == 2) { - if (len < 3) - logger(DEBUG_TRAFFIC, LOG_WARNING, "Received invalid (too short) MTU probe reply from %s (%s)", n->name, n->hostname); - else { - uint16_t probelen16; memcpy(&probelen16, packet->data + 1, 2); probelen = ntohs(probelen16); - } - } - logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d MTU probe reply %d from %s (%s)", packet->data[0], probelen, n->name, n->hostname); - - /* It's a valid reply: now we know bidirectional communication - is possible using the address and socket that the reply - packet used. */ - - n->status.udp_confirmed = true; - - /* If we haven't established the PMTU yet, restart the discovery process. */ - if(n->mtuprobes > 30) { - if (probelen == n->maxmtu + 8) { - logger(DEBUG_TRAFFIC, LOG_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname); + if(len == n->maxmtu + 8) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname); n->maxmtu = MTU; n->mtuprobes = 10; return; } - if(n->minmtu) + if(n->minmtu) { n->mtuprobes = 30; - else + } else { n->mtuprobes = 1; + } } - /* If applicable, raise the minimum supported MTU */ - - if(probelen > n->maxmtu) - probelen = n->maxmtu; - if(n->minmtu < probelen) - n->minmtu = probelen; - - /* Calculate RTT and bandwidth. - The RTT is the time between the MTU probe burst was sent and the first - reply is received. The bandwidth is measured using the time between the - arrival of the first and third probe reply (or type 2 probe requests). - */ - - struct timeval now, diff; - gettimeofday(&now, NULL); - timersub(&now, &n->probe_time, &diff); - - struct timeval probe_timestamp = now; - if (packet->data[0] == 2 && packet->len >= 11) { - uint32_t sec; memcpy(&sec, packet->data + 3, 4); - uint32_t usec; memcpy(&usec, packet->data + 7, 4); - probe_timestamp.tv_sec = ntohl(sec); - probe_timestamp.tv_usec = ntohl(usec); + if(len > n->maxmtu) { + len = n->maxmtu; } - - n->probe_counter++; - if(n->probe_counter == 1) { - n->rtt = diff.tv_sec + diff.tv_usec * 1e-6; - n->probe_time = probe_timestamp; - } else if(n->probe_counter == 3) { - struct timeval probe_timestamp_diff; - timersub(&probe_timestamp, &n->probe_time, &probe_timestamp_diff); - n->bandwidth = 2.0 * probelen / (probe_timestamp_diff.tv_sec + probe_timestamp_diff.tv_usec * 1e-6); - logger(DEBUG_TRAFFIC, LOG_DEBUG, "%s (%s) RTT %.2f ms, burst bandwidth %.3f Mbit/s, rx packet loss %.2f %%", n->name, n->hostname, n->rtt * 1e3, n->bandwidth * 8e-6, n->packetloss * 1e2); + if(n->minmtu < len) { + n->minmtu = len; } } } @@ -288,27 +214,28 @@ static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t l lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem); return lzolen; #else - return -1; + return 0; #endif } else if(level < 10) { #ifdef HAVE_ZLIB unsigned long destlen = MAXSIZE; - if(compress2(dest, &destlen, source, len, level) == Z_OK) + + if(compress2(dest, &destlen, source, len, level) == Z_OK) { return destlen; - else + } else #endif - return -1; + return 0; } else { #ifdef HAVE_LZO lzo_uint lzolen = MAXSIZE; lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem); return lzolen; #else - return -1; + return 0; #endif } - return -1; + return 0; } static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { @@ -318,20 +245,25 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t } else if(level > 9) { #ifdef HAVE_LZO lzo_uint lzolen = MAXSIZE; - if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK) + + if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK) { return lzolen; - else + } else #endif - return -1; + return 0; } + #ifdef HAVE_ZLIB else { unsigned long destlen = MAXSIZE; - if(uncompress(dest, &destlen, source, len) == Z_OK) + + if(uncompress(dest, &destlen, source, len) == Z_OK) { return destlen; - else - return -1; + } else { + return 0; + } } + #endif return -1; @@ -340,108 +272,105 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t /* VPN packet I/O */ static void receive_packet(node_t *n, vpn_packet_t *packet) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Received packet of %d bytes from %s (%s)", - packet->len, n->name, n->hostname); - - n->in_packets++; - n->in_bytes += packet->len; + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Received packet of %d bytes from %s (%s)", + packet->len, n->name, n->hostname); route(n, packet); } -static bool try_mac(node_t *n, const vpn_packet_t *inpkt) { - if(n->status.sptps) - return sptps_verify_datagram(&n->sptps, (char *)&inpkt->seqno, inpkt->len); +static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) { + unsigned char hmac[EVP_MAX_MD_SIZE]; - if(!digest_active(n->indigest) || inpkt->len < sizeof inpkt->seqno + digest_length(n->indigest)) + if(!n->indigest || !n->inmaclength || !n->inkey || inpkt->len < sizeof(inpkt->seqno) + n->inmaclength) { return false; + } - return digest_verify(n->indigest, &inpkt->seqno, inpkt->len - digest_length(n->indigest), (const char *)&inpkt->seqno + inpkt->len - digest_length(n->indigest)); + HMAC(n->indigest, n->inkey, n->inkeylength, (unsigned char *) &inpkt->seqno, inpkt->len - n->inmaclength, (unsigned char *)hmac, NULL); + + return !memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len - n->inmaclength, n->inmaclength); } static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { vpn_packet_t pkt1, pkt2; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; int nextpkt = 0; - vpn_packet_t *outpkt = pkt[0]; - size_t outlen; + vpn_packet_t *outpkt; + int outlen, outpad; + unsigned char hmac[EVP_MAX_MD_SIZE]; - if(n->status.sptps) { - if(!n->sptps.state) { - if(!n->status.waitingforkey) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but we haven't exchanged keys yet", n->name, n->hostname); - send_req_key(n); - } else { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); - } - return; - } - sptps_receive_data(&n->sptps, (char *)&inpkt->seqno, inpkt->len); - return; - } - - if(!cipher_active(n->incipher)) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); + if(!n->inkey) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", + n->name, n->hostname); return; } /* Check packet length */ - if(inpkt->len < sizeof inpkt->seqno + digest_length(n->indigest)) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got too short packet from %s (%s)", - n->name, n->hostname); + if(inpkt->len < sizeof(inpkt->seqno) + n->inmaclength) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got too short packet from %s (%s)", + n->name, n->hostname); return; } /* Check the message authentication code */ - if(digest_active(n->indigest)) { - inpkt->len -= digest_length(n->indigest); - if(!digest_verify(n->indigest, &inpkt->seqno, inpkt->len, (const char *)&inpkt->seqno + inpkt->len)) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got unauthenticated packet from %s (%s)", n->name, n->hostname); + if(n->indigest && n->inmaclength) { + inpkt->len -= n->inmaclength; + HMAC(n->indigest, n->inkey, n->inkeylength, + (unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL); + + if(memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len, n->inmaclength)) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got unauthenticated packet from %s (%s)", + n->name, n->hostname); return; } } + /* Decrypt the packet */ - if(cipher_active(n->incipher)) { + if(n->incipher) { outpkt = pkt[nextpkt++]; - outlen = MAXSIZE; - if(!cipher_decrypt(n->incipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Error decrypting packet from %s (%s)", n->name, n->hostname); + if(!EVP_DecryptInit_ex(n->inctx, NULL, NULL, NULL, NULL) + || !EVP_DecryptUpdate(n->inctx, (unsigned char *) &outpkt->seqno, &outlen, + (unsigned char *) &inpkt->seqno, inpkt->len) + || !EVP_DecryptFinal_ex(n->inctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error decrypting packet from %s (%s): %s", + n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL)); return; } - outpkt->len = outlen; + outpkt->len = outlen + outpad; inpkt = outpkt; } /* Check the sequence number */ - inpkt->len -= sizeof inpkt->seqno; + inpkt->len -= sizeof(inpkt->seqno); inpkt->seqno = ntohl(inpkt->seqno); if(replaywin) { if(inpkt->seqno != n->received_seqno + 1) { if(inpkt->seqno >= n->received_seqno + replaywin * 8) { if(n->farfuture++ < replaywin >> 2) { - logger(DEBUG_ALWAYS, LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)", - n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture); + ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)", + n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture); return; } - logger(DEBUG_ALWAYS, LOG_WARNING, "Lost %d packets from %s (%s)", - inpkt->seqno - n->received_seqno - 1, n->name, n->hostname); + + ifdebug(TRAFFIC) logger(LOG_WARNING, "Lost %d packets from %s (%s)", + inpkt->seqno - n->received_seqno - 1, n->name, n->hostname); memset(n->late, 0, replaywin); - } else if (inpkt->seqno <= n->received_seqno) { + } else if(inpkt->seqno <= n->received_seqno) { if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) { - logger(DEBUG_ALWAYS, LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d", - n->name, n->hostname, inpkt->seqno, n->received_seqno); + ifdebug(TRAFFIC) logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d", + n->name, n->hostname, inpkt->seqno, n->received_seqno); return; } } else { - for(int i = n->received_seqno + 1; i < inpkt->seqno; i++) + for(uint32_t i = n->received_seqno + 1; i < inpkt->seqno; i++) { n->late[(i / 8) % replaywin] |= 1 << i % 8; + } } } @@ -449,13 +378,13 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8); } - if(inpkt->seqno > n->received_seqno) + if(inpkt->seqno > n->received_seqno) { n->received_seqno = inpkt->seqno; + } - n->received++; - - if(n->received_seqno > MAX_SEQNO) - regenerate_key(); + if(n->received_seqno > MAX_SEQNO) { + keyexpires = 0; + } /* Decompress the packet */ @@ -464,207 +393,71 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { if(n->incompression) { outpkt = pkt[nextpkt++]; - if((outpkt->len = uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression)) < 0) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while uncompressing packet from %s (%s)", - n->name, n->hostname); + if(!(outpkt->len = uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression))) { + ifdebug(TRAFFIC) logger(LOG_ERR, "Error while uncompressing packet from %s (%s)", + n->name, n->hostname); return; } inpkt = outpkt; - origlen -= MTU/64 + 20; + origlen -= MTU / 64 + 20; } inpkt->priority = 0; - if(!inpkt->data[12] && !inpkt->data[13]) + if(!inpkt->data[12] && !inpkt->data[13]) { mtu_probe_h(n, inpkt, origlen); - else + } else { receive_packet(n, inpkt); + } } -void receive_tcppacket(connection_t *c, const char *buffer, int len) { +void receive_tcppacket(connection_t *c, const char *buffer, length_t len) { vpn_packet_t outpkt; - if(len > sizeof outpkt.data) + if(len > sizeof(outpkt.data)) { return; + } outpkt.len = len; - if(c->options & OPTION_TCPONLY) + + if(c->options & OPTION_TCPONLY) { outpkt.priority = 0; - else + } else { outpkt.priority = -1; + } + memcpy(outpkt.data, buffer, len); receive_packet(c->node, &outpkt); } -static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) { - if(!n->status.validkey) { - logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname); - if(!n->status.waitingforkey) - send_req_key(n); - else if(n->last_req_key + 10 < now.tv_sec) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "No key from %s after 10 seconds, restarting SPTPS", n->name); - sptps_stop(&n->sptps); - n->status.waitingforkey = false; - send_req_key(n); - } - return; - } - - uint8_t type = 0; - int offset = 0; - - if(!(origpkt->data[12] | origpkt->data[13])) { - sptps_send_record(&n->sptps, PKT_PROBE, (char *)origpkt->data, origpkt->len); - return; - } - - if(routing_mode == RMODE_ROUTER) - offset = 14; - else - type = PKT_MAC; - - if(origpkt->len < offset) - return; - - vpn_packet_t outpkt; - - if(n->outcompression) { - int len = compress_packet(outpkt.data + offset, origpkt->data + offset, origpkt->len - offset, n->outcompression); - if(len < 0) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname); - } else if(len < origpkt->len - offset) { - outpkt.len = len + offset; - origpkt = &outpkt; - type |= PKT_COMPRESSED; - } - } - - sptps_send_record(&n->sptps, type, (char *)origpkt->data + offset, origpkt->len - offset); - return; -} - -static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock) { - /* Latest guess */ - *sa = &n->address; - *sock = n->sock; - - /* If the UDP address is confirmed, use it. */ - if(n->status.udp_confirmed) - return; - - /* Send every third packet to n->address; that could be set - to the node's reflexive UDP address discovered during key - exchange. */ - - static int x = 0; - if(++x >= 3) { - x = 0; - return; - } - - /* Otherwise, address are found in edges to this node. - So we pick a random edge and a random socket. */ - - int i = 0; - int j = rand() % n->edge_tree->count; - edge_t *candidate = NULL; - - for splay_each(edge_t, e, n->edge_tree) { - if(i++ == j) { - candidate = e->reverse; - break; - } - } - - if(candidate) { - *sa = &candidate->address; - *sock = rand() % listen_sockets; - } - - /* Make sure we have a suitable socket for the chosen address */ - if(listen_socket[*sock].sa.sa.sa_family != (*sa)->sa.sa_family) { - for(int i = 0; i < listen_sockets; i++) { - if(listen_socket[i].sa.sa.sa_family == (*sa)->sa.sa_family) { - *sock = i; - break; - } - } - } -} - -static void choose_broadcast_address(const node_t *n, const sockaddr_t **sa, int *sock) { - static sockaddr_t broadcast_ipv4 = { - .in = { - .sin_family = AF_INET, - .sin_addr.s_addr = -1, - } - }; - - static sockaddr_t broadcast_ipv6 = { - .in6 = { - .sin6_family = AF_INET6, - .sin6_addr.s6_addr[0x0] = 0xff, - .sin6_addr.s6_addr[0x1] = 0x02, - .sin6_addr.s6_addr[0xf] = 0x01, - } - }; - - *sock = rand() % listen_sockets; - - if(listen_socket[*sock].sa.sa.sa_family == AF_INET6) { - if(localdiscovery_address.sa.sa_family == AF_INET6) { - localdiscovery_address.in6.sin6_port = n->prevedge->address.in.sin_port; - *sa = &localdiscovery_address; - } else { - broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port; - broadcast_ipv6.in6.sin6_scope_id = listen_socket[*sock].sa.in6.sin6_scope_id; - *sa = &broadcast_ipv6; - } - } else { - if(localdiscovery_address.sa.sa_family == AF_INET) { - localdiscovery_address.in.sin_port = n->prevedge->address.in.sin_port; - *sa = &localdiscovery_address; - } else { - broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port; - *sa = &broadcast_ipv4; - } - } -} - static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { vpn_packet_t pkt1, pkt2; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; vpn_packet_t *inpkt = origpkt; int nextpkt = 0; vpn_packet_t *outpkt; - int origlen = origpkt->len; - size_t outlen; -#if defined(SOL_IP) && defined(IP_TOS) - static int priority = 0; -#endif - int origpriority = origpkt->priority; + int origlen; + int outlen, outpad; + int origpriority; if(!n->status.reachable) { - logger(DEBUG_TRAFFIC, LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname); + ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname); return; } - if(n->status.sptps) - return send_sptps_packet(n, origpkt); - /* Make sure we have a valid key */ if(!n->status.validkey) { - logger(DEBUG_TRAFFIC, LOG_INFO, - "No valid key known yet for %s (%s), forwarding via TCP", - n->name, n->hostname); + ifdebug(TRAFFIC) logger(LOG_INFO, + "No valid key known yet for %s (%s), forwarding via TCP", + n->name, n->hostname); - if(n->last_req_key + 10 <= now.tv_sec) { + if(n->last_req_key + 10 <= now) { send_req_key(n); - n->last_req_key = now.tv_sec; + n->last_req_key = now; } send_tcppacket(n->nexthop->connection, origpkt); @@ -673,26 +466,30 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { } if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) { - logger(DEBUG_TRAFFIC, LOG_INFO, - "Packet for %s (%s) larger than minimum MTU, forwarding via %s", - n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP"); + ifdebug(TRAFFIC) logger(LOG_INFO, + "Packet for %s (%s) larger than minimum MTU, forwarding via %s", + n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP"); - if(n != n->nexthop) + if(n != n->nexthop) { send_packet(n->nexthop, origpkt); - else + } else { send_tcppacket(n->nexthop->connection, origpkt); + } return; } + origlen = inpkt->len; + origpriority = inpkt->priority; + /* Compress the packet */ if(n->outcompression) { outpkt = pkt[nextpkt++]; - if((outpkt->len = compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression)) < 0) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", - n->name, n->hostname); + if(!(outpkt->len = compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression))) { + ifdebug(TRAFFIC) logger(LOG_ERR, "Error while compressing packet to %s (%s)", + n->name, n->hostname); return; } @@ -702,353 +499,300 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { /* Add sequence number */ inpkt->seqno = htonl(++(n->sent_seqno)); - inpkt->len += sizeof inpkt->seqno; + inpkt->len += sizeof(inpkt->seqno); /* Encrypt the packet */ - if(cipher_active(n->outcipher)) { + if(n->outcipher) { outpkt = pkt[nextpkt++]; - outlen = MAXSIZE; - if(!cipher_encrypt(n->outcipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname); + if(!EVP_EncryptInit_ex(n->outctx, NULL, NULL, NULL, NULL) + || !EVP_EncryptUpdate(n->outctx, (unsigned char *) &outpkt->seqno, &outlen, + (unsigned char *) &inpkt->seqno, inpkt->len) + || !EVP_EncryptFinal_ex(n->outctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) { + ifdebug(TRAFFIC) logger(LOG_ERR, "Error while encrypting packet to %s (%s): %s", + n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL)); goto end; } - outpkt->len = outlen; + outpkt->len = outlen + outpad; inpkt = outpkt; } /* Add the message authentication code */ - if(digest_active(n->outdigest)) { - if(!digest_create(n->outdigest, &inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len)) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname); - goto end; - } + if(n->outdigest && n->outmaclength) { + HMAC(n->outdigest, n->outkey, n->outkeylength, (unsigned char *) &inpkt->seqno, + inpkt->len, (unsigned char *) &inpkt->seqno + inpkt->len, NULL); + inpkt->len += n->outmaclength; + } - inpkt->len += digest_length(n->outdigest); + /* Determine which socket we have to use */ + + if(n->address.sa.sa_family != listen_socket[n->sock].sa.sa.sa_family) { + for(int sock = 0; sock < listen_sockets; sock++) { + if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) { + n->sock = sock; + break; + } + } } /* Send the packet */ - const sockaddr_t *sa; + struct sockaddr *sa; + socklen_t sl; int sock; + sockaddr_t broadcast; /* Overloaded use of priority field: -1 means local broadcast */ - if(origpriority == -1 && n->prevedge) - choose_broadcast_address(n, &sa, &sock); - else - choose_udp_address(n, &sa, &sock); + if(origpriority == -1 && n->prevedge) { + sock = rand() % listen_sockets; + memset(&broadcast, 0, sizeof(broadcast)); -#if defined(SOL_IP) && defined(IP_TOS) - if(priorityinheritance && origpriority != priority - && listen_socket[n->sock].sa.sa.sa_family == AF_INET) { - priority = origpriority; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority); - if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); + if(listen_socket[sock].sa.sa.sa_family == AF_INET6) { + broadcast.in6.sin6_family = AF_INET6; + broadcast.in6.sin6_addr.s6_addr[0x0] = 0xff; + broadcast.in6.sin6_addr.s6_addr[0x1] = 0x02; + broadcast.in6.sin6_addr.s6_addr[0xf] = 0x01; + broadcast.in6.sin6_port = n->prevedge->address.in.sin_port; + broadcast.in6.sin6_scope_id = listen_socket[sock].sa.in6.sin6_scope_id; + } else { + broadcast.in.sin_family = AF_INET; + broadcast.in.sin_addr.s_addr = -1; + broadcast.in.sin_port = n->prevedge->address.in.sin_port; + } + + sa = &broadcast.sa; + sl = SALEN(broadcast.sa); + } else { + if(origpriority == -1) { + origpriority = 0; + } + + sa = &(n->address.sa); + sl = SALEN(n->address.sa); + sock = n->sock; } + + if(priorityinheritance && origpriority != listen_socket[n->sock].priority) { + listen_socket[n->sock].priority = origpriority; + + switch(listen_socket[n->sock].sa.sa.sa_family) { +#if defined(IP_TOS) + + case AF_INET: + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv4 outgoing packet priority to %d", origpriority); + + if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IP, IP_TOS, (void *)&origpriority, sizeof(origpriority))) { /* SO_PRIORITY doesn't seem to work */ + logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); + } + + break; +#endif +#if defined(IPV6_TCLASS) + + case AF_INET6: + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting IPv6 outgoing packet priority to %d", origpriority); + + if(setsockopt(listen_socket[n->sock].udp, IPPROTO_IPV6, IPV6_TCLASS, (void *)&origpriority, sizeof(origpriority))) { + logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); + } + + break; #endif - if(sendto(listen_socket[sock].udp.fd, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { + default: + break; + } + } + + if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, sa, sl) < 0 && !sockwouldblock(sockerrno)) { if(sockmsgsize(sockerrno)) { - if(n->maxmtu >= origlen) + if(n->maxmtu >= origlen) { n->maxmtu = origlen - 1; - if(n->mtu >= origlen) + } + + if(n->mtu >= origlen) { n->mtu = origlen - 1; - } else - logger(DEBUG_TRAFFIC, LOG_WARNING, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno)); + } + } else { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno)); + } } end: origpkt->len = origlen; } -bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) { - node_t *to = handle; - - /* Send it via TCP if it is a handshake packet, TCPOnly is in use, or this packet is larger than the MTU. */ - - if(type >= SPTPS_HANDSHAKE || ((myself->options | to->options) & OPTION_TCPONLY) || (type != PKT_PROBE && len > to->minmtu)) { - char buf[len * 4 / 3 + 5]; - b64encode(data, buf, len); - /* If no valid key is known yet, send the packets using ANS_KEY requests, - to ensure we get to learn the reflexive UDP address. */ - if(!to->status.validkey) { - to->incompression = myself->incompression; - return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, myself->name, to->name, buf, to->incompression); - } else { - return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_SPTPS, buf); - } - } - - /* Otherwise, send the packet via UDP */ - - const sockaddr_t *sa; - int sock; - - choose_udp_address(to, &sa, &sock); - - if(sendto(listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { - if(sockmsgsize(sockerrno)) { - if(to->maxmtu >= len) - to->maxmtu = len - 1; - if(to->mtu >= len) - to->mtu = len - 1; - } else { - logger(DEBUG_TRAFFIC, LOG_WARNING, "Error sending UDP SPTPS packet to %s (%s): %s", to->name, to->hostname, sockstrerror(sockerrno)); - return false; - } - } - - return true; -} - -bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t len) { - node_t *from = handle; - - if(type == SPTPS_HANDSHAKE) { - if(!from->status.validkey) { - from->status.validkey = true; - from->status.waitingforkey = false; - logger(DEBUG_META, LOG_INFO, "SPTPS key exchange with %s (%s) succesful", from->name, from->hostname); - } - return true; - } - - if(len > MTU) { - logger(DEBUG_ALWAYS, LOG_ERR, "Packet from %s (%s) larger than maximum supported size (%d > %d)", from->name, from->hostname, len, MTU); - return false; - } - - vpn_packet_t inpkt; - - if(type == PKT_PROBE) { - inpkt.len = len; - memcpy(inpkt.data, data, len); - mtu_probe_h(from, &inpkt, len); - return true; - } - - if(type & ~(PKT_COMPRESSED | PKT_MAC)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unexpected SPTPS record type %d len %d from %s (%s)", type, len, from->name, from->hostname); - return false; - } - - /* Check if we have the headers we need */ - if(routing_mode != RMODE_ROUTER && !(type & PKT_MAC)) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Received packet from %s (%s) without MAC header (maybe Mode is not set correctly)", from->name, from->hostname); - return false; - } else if(routing_mode == RMODE_ROUTER && (type & PKT_MAC)) { - logger(DEBUG_TRAFFIC, LOG_WARNING, "Received packet from %s (%s) with MAC header (maybe Mode is not set correctly)", from->name, from->hostname); - } - - int offset = (type & PKT_MAC) ? 0 : 14; - if(type & PKT_COMPRESSED) { - length_t ulen = uncompress_packet(inpkt.data + offset, (const uint8_t *)data, len, from->incompression); - if(ulen < 0) { - return false; - } else { - inpkt.len = ulen + offset; - } - if(inpkt.len > MAXSIZE) - abort(); - } else { - memcpy(inpkt.data + offset, data, len); - inpkt.len = len + offset; - } - - /* Generate the Ethernet packet type if necessary */ - if(offset) { - switch(inpkt.data[14] >> 4) { - case 4: - inpkt.data[12] = 0x08; - inpkt.data[13] = 0x00; - break; - case 6: - inpkt.data[12] = 0x86; - inpkt.data[13] = 0xDD; - break; - default: - logger(DEBUG_TRAFFIC, LOG_ERR, - "Unknown IP version %d while reading packet from %s (%s)", - inpkt.data[14] >> 4, from->name, from->hostname); - return false; - } - } - - receive_packet(from, &inpkt); - return true; -} - /* send a packet to the given vpn ip. */ -void send_packet(node_t *n, vpn_packet_t *packet) { +void send_packet(const node_t *n, vpn_packet_t *packet) { node_t *via; if(n == myself) { - if(overwrite_mac) - memcpy(packet->data, mymac.x, ETH_ALEN); - n->out_packets++; - n->out_bytes += packet->len; + if(overwrite_mac) { + memcpy(packet->data, mymac.x, ETH_ALEN); + } + devops.write(packet); return; } - logger(DEBUG_TRAFFIC, LOG_ERR, "Sending packet of %d bytes to %s (%s)", - packet->len, n->name, n->hostname); + ifdebug(TRAFFIC) logger(LOG_ERR, "Sending packet of %d bytes to %s (%s)", + packet->len, n->name, n->hostname); if(!n->status.reachable) { - logger(DEBUG_TRAFFIC, LOG_INFO, "Node %s (%s) is not reachable", - n->name, n->hostname); - return; - } - - n->out_packets++; - n->out_bytes += packet->len; - - if(n->status.sptps) { - send_sptps_packet(n, packet); + ifdebug(TRAFFIC) logger(LOG_INFO, "Node %s (%s) is not reachable", + n->name, n->hostname); return; } via = (packet->priority == -1 || n->via == myself) ? n->nexthop : n->via; if(via != n) - logger(DEBUG_TRAFFIC, LOG_INFO, "Sending packet to %s via %s (%s)", - n->name, via->name, n->via->hostname); + ifdebug(TRAFFIC) logger(LOG_INFO, "Sending packet to %s via %s (%s)", + n->name, via->name, n->via->hostname); if(packet->priority == -1 || ((myself->options | via->options) & OPTION_TCPONLY)) { - if(!send_tcppacket(via->connection, packet)) + if(!send_tcppacket(via->connection, packet)) { terminate_connection(via->connection, true); - } else + } + } else { send_udppacket(via, packet); + } } /* Broadcast a packet using the minimum spanning tree */ void broadcast_packet(const node_t *from, vpn_packet_t *packet) { + avl_node_t *node; + connection_t *c; + node_t *n; + // Always give ourself a copy of the packet. - if(from != myself) + if(from != myself) { send_packet(myself, packet); + } // In TunnelServer mode, do not forward broadcast packets. // The MST might not be valid and create loops. - if(tunnelserver || broadcast_mode == BMODE_NONE) + if(tunnelserver || broadcast_mode == BMODE_NONE) { return; + } - logger(DEBUG_TRAFFIC, LOG_INFO, "Broadcasting packet of %d bytes from %s (%s)", - packet->len, from->name, from->hostname); + ifdebug(TRAFFIC) logger(LOG_INFO, "Broadcasting packet of %d bytes from %s (%s)", + packet->len, from->name, from->hostname); switch(broadcast_mode) { - // In MST mode, broadcast packets travel via the Minimum Spanning Tree. - // This guarantees all nodes receive the broadcast packet, and - // usually distributes the sending of broadcast packets over all nodes. - case BMODE_MST: - for list_each(connection_t, c, connection_list) - if(c->status.active && c->status.mst && c != from->nexthop->connection) - send_packet(c->node, packet); - break; + // In MST mode, broadcast packets travel via the Minimum Spanning Tree. + // This guarantees all nodes receive the broadcast packet, and + // usually distributes the sending of broadcast packets over all nodes. + case BMODE_MST: + for(node = connection_tree->head; node; node = node->next) { + c = node->data; - // In direct mode, we send copies to each node we know of. - // However, this only reaches nodes that can be reached in a single hop. - // We don't have enough information to forward broadcast packets in this case. - case BMODE_DIRECT: - if(from != myself) - break; + if(c->status.active && c->status.mst && c != from->nexthop->connection) { + send_packet(c->node, packet); + } + } - for splay_each(node_t, n, node_tree) - if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n)) - send_packet(n, packet); - break; + break; - default: + // In direct mode, we send copies to each node we know of. + // However, this only reaches nodes that can be reached in a single hop. + // We don't have enough information to forward broadcast packets in this case. + case BMODE_DIRECT: + if(from != myself) { break; + } + + for(node = node_udp_tree->head; node; node = node->next) { + n = node->data; + + if(n->status.reachable && n != myself && ((n->via == myself && n->nexthop == n) || n->via == n)) { + send_packet(n, packet); + } + } + + break; + + default: + break; } } static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { + avl_node_t *node; + edge_t *e; node_t *n = NULL; - bool hard = false; static time_t last_hard_try = 0; - for splay_each(edge_t, e, edge_weight_tree) { - if(!e->to->status.reachable || e->to == myself) - continue; + for(node = edge_weight_tree->head; node; node = node->next) { + e = node->data; - if(sockaddrcmp_noport(from, &e->address)) { - if(last_hard_try == now.tv_sec) - continue; - hard = true; + if(e->to == myself) { + continue; } - if(!try_mac(e->to, pkt)) + if(last_hard_try == now && sockaddrcmp_noport(from, &e->address)) { continue; + } + + if(!try_mac(e->to, pkt)) { + continue; + } n = e->to; break; } - if(hard) - last_hard_try = now.tv_sec; - - last_hard_try = now.tv_sec; + last_hard_try = now; return n; } -void handle_incoming_vpn_data(void *data, int flags) { - listen_socket_t *ls = data; +void handle_incoming_vpn_data(int sock) { vpn_packet_t pkt; char *hostname; - sockaddr_t from = {{0}}; - socklen_t fromlen = sizeof from; + sockaddr_t from; + socklen_t fromlen = sizeof(from); node_t *n; - int len; - len = recvfrom(ls->udp.fd, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); + ssize_t len = recvfrom(listen_socket[sock].udp, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); + + if(len <= 0 || len > UINT16_MAX) { + if(len >= 0) { + logger(LOG_ERR, "Receiving packet with invalid size"); + } else if(!sockwouldblock(sockerrno)) { + logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno)); + } - if(len <= 0 || len > MAXSIZE) { - if(!sockwouldblock(sockerrno)) - logger(DEBUG_ALWAYS, LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno)); return; } pkt.len = len; - - sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ + sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ n = lookup_node_udp(&from); if(!n) { n = try_harder(&from, &pkt); - if(n) + + if(n) { update_node_udp(n, &from); - else if(debug_level >= DEBUG_PROTOCOL) { + } else ifdebug(PROTOCOL) { hostname = sockaddr2hostname(&from); - logger(DEBUG_PROTOCOL, LOG_WARNING, "Received UDP packet from unknown source %s", hostname); + logger(LOG_WARNING, "Received UDP packet from unknown source %s", hostname); free(hostname); return; - } - else + } else { return; + } } - n->sock = ls - listen_socket; + n->sock = sock; 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); - } -} diff --git a/src/net_setup.c b/src/net_setup.c index 0fedafa..f26007b 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -1,7 +1,7 @@ /* net_setup.c -- Setup. Copyright (C) 1998-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2017 Guus Sliepen 2006 Scott Lamb 2010 Brandon Black @@ -22,260 +22,220 @@ #include "system.h" -#include "cipher.h" +#include +#include +#include +#include +#include +#include + +#include "avl_tree.h" #include "conf.h" #include "connection.h" -#include "control.h" #include "device.h" -#include "digest.h" -#include "ecdsa.h" +#include "event.h" #include "graph.h" #include "logger.h" -#include "names.h" #include "net.h" #include "netutl.h" #include "process.h" #include "protocol.h" +#include "proxy.h" #include "route.h" -#include "rsa.h" #include "subnet.h" #include "utils.h" #include "xalloc.h" char *myport; -static io_t device_io; devops_t devops; -char *proxyhost; -char *proxyport; -char *proxyuser; -char *proxypass; -proxytype_t proxytype; -int autoconnect; -bool disablebuggypeers; - -char *scriptinterpreter; -char *scriptextension; - -bool node_read_ecdsa_public_key(node_t *n) { - if(ecdsa_active(n->ecdsa)) - return true; - - splay_tree_t *config_tree; - FILE *fp; - char *pubname = NULL; - char *p; - - init_configuration(&config_tree); - if(!read_host_config(config_tree, n->name)) - goto exit; - - /* First, check for simple ECDSAPublicKey statement */ - - if(get_config_string(lookup_config(config_tree, "ECDSAPublicKey"), &p)) { - n->ecdsa = ecdsa_set_base64_public_key(p); - free(p); - goto exit; - } - - /* Else, check for ECDSAPublicKeyFile statement and read it */ - - if(!get_config_string(lookup_config(config_tree, "ECDSAPublicKeyFile"), &pubname)) - xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, n->name); - - fp = fopen(pubname, "r"); - - if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error reading ECDSA public key file `%s': %s", pubname, strerror(errno)); - goto exit; - } - - n->ecdsa = ecdsa_read_pem_public_key(fp); - fclose(fp); - -exit: - exit_configuration(&config_tree); - free(pubname); - return n->ecdsa; -} - -bool read_ecdsa_public_key(connection_t *c) { - if(ecdsa_active(c->ecdsa)) - return true; - - FILE *fp; - char *fname; - char *p; - - if(!c->config_tree) { - init_configuration(&c->config_tree); - if(!read_host_config(c->config_tree, c->name)) - return false; - } - - /* First, check for simple ECDSAPublicKey statement */ - - if(get_config_string(lookup_config(c->config_tree, "ECDSAPublicKey"), &p)) { - c->ecdsa = ecdsa_set_base64_public_key(p); - free(p); - return c->ecdsa; - } - - /* Else, check for ECDSAPublicKeyFile statement and read it */ - - if(!get_config_string(lookup_config(c->config_tree, "ECDSAPublicKeyFile"), &fname)) - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name); - - fp = fopen(fname, "r"); - - if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error reading ECDSA public key file `%s': %s", - fname, strerror(errno)); - free(fname); - return false; - } - - c->ecdsa = ecdsa_read_pem_public_key(fp); - fclose(fp); - - if(!c->ecdsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Parsing ECDSA public key file `%s' failed.", fname); - free(fname); - return c->ecdsa; +#ifndef HAVE_RSA_SET0_KEY +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { + BN_free(r->n); + r->n = n; + BN_free(r->e); + r->e = e; + BN_free(r->d); + r->d = d; + return 1; } +#endif bool read_rsa_public_key(connection_t *c) { - if(ecdsa_active(c->ecdsa)) - return true; - FILE *fp; - char *fname; - char *n; + char *pubname; + char *hcfname; + char *key; + BIGNUM *n = NULL; + BIGNUM *e = NULL; + + if(!c->rsa_key) { + c->rsa_key = RSA_new(); +// RSA_blinding_on(c->rsa_key, NULL); + } /* First, check for simple PublicKey statement */ - if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &n)) { - c->rsa = rsa_set_hex_public_key(n, "FFFF"); - free(n); - return c->rsa; + if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) { + if((size_t)BN_hex2bn(&n, key) != strlen(key)) { + free(key); + logger(LOG_ERR, "Invalid PublicKey for %s!", c->name); + return false; + } + + free(key); + BN_hex2bn(&e, "FFFF"); + + if(!n || !e || RSA_set0_key(c->rsa_key, n, e, NULL) != 1) { + BN_free(e); + BN_free(n); + logger(LOG_ERR, "RSA_set0_key() failed with PublicKey for %s!", c->name); + return false; + } + + return true; } /* Else, check for PublicKeyFile statement and read it */ - if(!get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name); + if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &pubname)) { + fp = fopen(pubname, "r"); - fp = fopen(fname, "r"); + if(!fp) { + logger(LOG_ERR, "Error reading RSA public key file `%s': %s", pubname, strerror(errno)); + free(pubname); + return false; + } - if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno)); - free(fname); - return false; - } - - c->rsa = rsa_read_pem_public_key(fp); - fclose(fp); - - if(!c->rsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA public key file `%s' failed: %s", fname, strerror(errno)); - free(fname); - return c->rsa; -} - -static bool read_ecdsa_private_key(void) { - FILE *fp; - char *fname; - - /* Check for PrivateKeyFile statement and read it */ - - if(!get_config_string(lookup_config(config_tree, "ECDSAPrivateKeyFile"), &fname)) - xasprintf(&fname, "%s" SLASH "ecdsa_key.priv", confbase); - - fp = fopen(fname, "r"); - - 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 ?: "."); - free(fname); - return false; - } - -#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN) - struct stat s; - - if(fstat(fileno(fp), &s)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat ECDSA private key file `%s': %s'", fname, strerror(errno)); - free(fname); - return false; - } - - if(s.st_mode & ~0100700) - logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for ECDSA private key file `%s'!", fname); -#endif - - myself->connection->ecdsa = ecdsa_read_pem_private_key(fp); - fclose(fp); - - if(!myself->connection->ecdsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Reading ECDSA private key file `%s' failed: %s", fname, strerror(errno)); - free(fname); - return myself->connection->ecdsa; -} - -static bool read_invitation_key(void) { - FILE *fp; - char *fname; - - if(invitation_key) { - ecdsa_free(invitation_key); - invitation_key = NULL; - } - - xasprintf(&fname, "%s" SLASH "invitations" SLASH "ecdsa_key.priv", confbase); - - fp = fopen(fname, "r"); - - if(fp) { - invitation_key = ecdsa_read_pem_private_key(fp); + c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); fclose(fp); - if(!invitation_key) - logger(DEBUG_ALWAYS, LOG_ERR, "Reading ECDSA private key file `%s' failed: %s", fname, strerror(errno)); + + if(c->rsa_key) { + free(pubname); + return true; /* Woohoo. */ + } + + /* If it fails, try PEM_read_RSA_PUBKEY. */ + fp = fopen(pubname, "r"); + + if(!fp) { + logger(LOG_ERR, "Error reading RSA public key file `%s': %s", pubname, strerror(errno)); + free(pubname); + return false; + } + + c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + + if(c->rsa_key) { +// RSA_blinding_on(c->rsa_key, NULL); + free(pubname); + return true; + } + + logger(LOG_ERR, "Reading RSA public key file `%s' failed: %s", pubname, strerror(errno)); + free(pubname); + return false; } - free(fname); - return invitation_key; + /* Else, check if a harnessed public key is in the config file */ + + xasprintf(&hcfname, "%s/hosts/%s", confbase, c->name); + fp = fopen(hcfname, "r"); + + if(!fp) { + logger(LOG_ERR, "Error reading RSA public key file `%s': %s", hcfname, strerror(errno)); + free(hcfname); + return false; + } + + c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + + if(c->rsa_key) { + free(hcfname); + return true; + } + + /* Try again with PEM_read_RSA_PUBKEY. */ + + fp = fopen(hcfname, "r"); + + if(!fp) { + logger(LOG_ERR, "Error reading RSA public key file `%s': %s", hcfname, strerror(errno)); + free(hcfname); + return false; + } + + free(hcfname); + c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL); +// RSA_blinding_on(c->rsa_key, NULL); + fclose(fp); + + if(c->rsa_key) { + return true; + } + + logger(LOG_ERR, "No public key for %s specified!", c->name); + + return false; } static bool read_rsa_private_key(void) { FILE *fp; - char *fname; - char *n, *d; + char *fname, *key, *pubkey; + BIGNUM *n = NULL; + BIGNUM *e = NULL; + BIGNUM *d = NULL; - /* First, check for simple PrivateKey statement */ + if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) { + myself->connection->rsa_key = RSA_new(); - if(get_config_string(lookup_config(config_tree, "PrivateKey"), &d)) { - if(!get_config_string(lookup_config(config_tree, "PublicKey"), &n)) { - logger(DEBUG_ALWAYS, LOG_ERR, "PrivateKey used but no PublicKey found!"); - free(d); +// RSA_blinding_on(myself->connection->rsa_key, NULL); + if((size_t)BN_hex2bn(&d, key) != strlen(key)) { + logger(LOG_ERR, "Invalid PrivateKey for myself!"); + free(key); return false; } - myself->connection->rsa = rsa_set_hex_private_key(n, "FFFF", d); - free(n); - free(d); - return myself->connection->rsa; + + free(key); + + if(!get_config_string(lookup_config(config_tree, "PublicKey"), &pubkey)) { + BN_free(d); + logger(LOG_ERR, "PrivateKey used but no PublicKey found!"); + return false; + } + + if((size_t)BN_hex2bn(&n, pubkey) != strlen(pubkey)) { + free(pubkey); + BN_free(d); + logger(LOG_ERR, "Invalid PublicKey for myself!"); + return false; + } + + free(pubkey); + BN_hex2bn(&e, "FFFF"); + + if(!n || !e || !d || RSA_set0_key(myself->connection->rsa_key, n, e, d) != 1) { + BN_free(d); + BN_free(e); + BN_free(n); + logger(LOG_ERR, "RSA_set0_key() failed with PrivateKey for myself!"); + return false; + } + + return true; } - /* Else, check for PrivateKeyFile statement and read it */ - - if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) - xasprintf(&fname, "%s" SLASH "rsa_key.priv", confbase); + if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) { + xasprintf(&fname, "%s/rsa_key.priv", confbase); + } fp = fopen(fname, "r"); if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA private key file `%s': %s", - fname, strerror(errno)); + logger(LOG_ERR, "Error reading RSA private key file `%s': %s", + fname, strerror(errno)); free(fname); return false; } @@ -283,35 +243,28 @@ static bool read_rsa_private_key(void) { #if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN) struct stat s; - if(fstat(fileno(fp), &s)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno)); + if(!fstat(fileno(fp), &s)) { + if(s.st_mode & ~0100700) { + logger(LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname); + } + } else { + logger(LOG_WARNING, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno)); + } + +#endif + + myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + fclose(fp); + + if(!myself->connection->rsa_key) { + logger(LOG_ERR, "Reading RSA private key file `%s' failed: %s", + fname, strerror(errno)); free(fname); return false; } - if(s.st_mode & ~0100700) - logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname); -#endif - - myself->connection->rsa = rsa_read_pem_private_key(fp); - fclose(fp); - - if(!myself->connection->rsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA private key file `%s' failed: %s", fname, strerror(errno)); free(fname); - return myself->connection->rsa; -} - -static timeout_t keyexpire_timeout; - -static void keyexpire_handler(void *data) { - regenerate_key(); - timeout_set(data, &(struct timeval){keylifetime, rand() % 100000}); -} - -void regenerate_key(void) { - logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys"); - send_key_changed(); + return true; } /* @@ -321,29 +274,37 @@ void load_all_subnets(void) { DIR *dir; struct dirent *ent; char *dname; + char *fname; + avl_tree_t *config_tree; + config_t *cfg; + subnet_t *s, *s2; + node_t *n; - xasprintf(&dname, "%s" SLASH "hosts", confbase); + xasprintf(&dname, "%s/hosts", confbase); dir = opendir(dname); + if(!dir) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno)); + logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno)); free(dname); return; } while((ent = readdir(dir))) { - if(!check_id(ent->d_name)) + if(!check_id(ent->d_name)) { continue; + } - node_t *n = lookup_node(ent->d_name); - #ifdef _DIRENT_HAVE_D_TYPE + n = lookup_node(ent->d_name); +#ifdef _DIRENT_HAVE_D_TYPE //if(ent->d_type != DT_REG) - // continue; - #endif + // continue; +#endif - splay_tree_t *config_tree; + xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name); init_configuration(&config_tree); read_config_options(config_tree, ent->d_name); - read_host_config(config_tree, ent->d_name); + read_config_file(config_tree, fname); + free(fname); if(!n) { n = new_node(); @@ -351,11 +312,10 @@ void load_all_subnets(void) { 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)) + for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) { + if(!get_config_subnet(cfg, &s)) { continue; + } if((s2 = lookup_subnet(n, s))) { s2->expires = -1; @@ -370,67 +330,47 @@ void load_all_subnets(void) { closedir(dir); } -void load_all_nodes(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); - if(n) - continue; - - n = new_node(); - n->name = xstrdup(ent->d_name); - node_add(n); - } - - closedir(dir); -} - - char *get_name(void) { char *name = NULL; get_config_string(lookup_config(config_tree, "Name"), &name); - if(!name) + if(!name) { return NULL; + } if(*name == '$') { char *envname = getenv(name + 1); + char hostname[32] = ""; + if(!envname) { if(strcmp(name + 1, "HOST")) { - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid Name: environment variable %s does not exist\n", name + 1); + fprintf(stderr, "Invalid Name: environment variable %s does not exist\n", name + 1); + free(name); return false; } - char envname[32]; - if(gethostname(envname, 32)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", strerror(errno)); + + if(gethostname(hostname, sizeof(hostname)) || !*hostname) { + fprintf(stderr, "Could not get hostname: %s\n", strerror(errno)); + free(name); return false; } - envname[31] = 0; + + hostname[31] = 0; + envname = hostname; } + free(name); name = xstrdup(envname); + for(char *c = name; *c; c++) - if(!isalnum(*c)) + if(!isalnum(*c)) { *c = '_'; + } } if(!check_id(name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid name for myself!"); + logger(LOG_ERR, "Invalid name for myself!"); free(name); return false; } @@ -438,33 +378,76 @@ char *get_name(void) { return name; } -bool setup_myself_reloadable(void) { - char *proxy = NULL; - char *rmode = NULL; - char *fmode = NULL; - char *bmode = NULL; - char *afname = NULL; +/* + Configure node_t myself and set up the local sockets (listen only) +*/ +static bool setup_myself(void) { + config_t *cfg; + subnet_t *subnet; + char *name, *hostname, *mode, *afname, *cipher, *digest, *type; + char *fname = NULL; char *address = NULL; + char *proxy = NULL; char *space; + char *envp[5] = {0}; + struct addrinfo *ai, *aip, hint = {0}; bool choice; + int i, err; + int replaywin_int; + bool port_specified = false; - free(scriptinterpreter); - scriptinterpreter = NULL; - get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &scriptinterpreter); + myself = new_node(); + myself->connection = new_connection(); + myself->hostname = xstrdup("MYSELF"); + myself->connection->hostname = xstrdup("MYSELF"); - free(scriptextension); - if(!get_config_string(lookup_config(config_tree, "ScriptsExtension"), &scriptextension)) -#ifdef HAVE_MINGW - scriptextension = xstrdup(".bat"); -#else - scriptextension = xstrdup(""); -#endif + myself->connection->options = 0; + myself->connection->protocol_version = PROT_CURRENT; - get_config_string(lookup_config(config_tree, "Proxy"), &proxy); - if(proxy) { - if((space = strchr(proxy, ' '))) + if(!(name = get_name())) { + logger(LOG_ERR, "Name for tinc daemon required!"); + return false; + } + + /* Read tinc.conf and our own host config file */ + + myself->name = name; + myself->connection->name = xstrdup(name); + xasprintf(&fname, "%s/hosts/%s", confbase, name); + read_config_options(config_tree, name); + read_config_file(config_tree, fname); + free(fname); + + if(!read_rsa_private_key()) { + return false; + } + + if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) { + myport = xstrdup("655"); + } else { + port_specified = true; + } + + /* Ensure myport is numeric */ + + if(!atoi(myport)) { + struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM); + sockaddr_t sa; + + if(!ai || !ai->ai_addr) { + return false; + } + + free(myport); + memcpy(&sa, ai->ai_addr, ai->ai_addrlen); + sockaddr2str(&sa, NULL, &myport); + } + + if(get_config_string(lookup_config(config_tree, "Proxy"), &proxy)) { + if((space = strchr(proxy, ' '))) { *space++ = 0; + } if(!strcasecmp(proxy, "none")) { proxytype = PROXY_NONE; @@ -479,313 +462,348 @@ bool setup_myself_reloadable(void) { } else if(!strcasecmp(proxy, "exec")) { proxytype = PROXY_EXEC; } else { - logger(DEBUG_ALWAYS, LOG_ERR, "Unknown proxy type %s!", proxy); + logger(LOG_ERR, "Unknown proxy type %s!", proxy); + free(proxy); return false; } switch(proxytype) { - case PROXY_NONE: - default: - break; + case PROXY_NONE: + default: + break; - case PROXY_EXEC: - if(!space || !*space) { - logger(DEBUG_ALWAYS, LOG_ERR, "Argument expected for proxy type exec!"); - return false; - } - proxyhost = xstrdup(space); - break; + case PROXY_EXEC: + if(!space || !*space) { + logger(LOG_ERR, "Argument expected for proxy type exec!"); + free(proxy); + return false; + } - case PROXY_SOCKS4: - case PROXY_SOCKS4A: - case PROXY_SOCKS5: - case PROXY_HTTP: - proxyhost = space; - if(space && (space = strchr(space, ' '))) - *space++ = 0, proxyport = space; - if(space && (space = strchr(space, ' '))) - *space++ = 0, proxyuser = space; - if(space && (space = strchr(space, ' '))) - *space++ = 0, proxypass = space; - if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) { - logger(DEBUG_ALWAYS, LOG_ERR, "Host and port argument expected for proxy!"); - return false; - } - proxyhost = xstrdup(proxyhost); - proxyport = xstrdup(proxyport); - if(proxyuser && *proxyuser) - proxyuser = xstrdup(proxyuser); - if(proxypass && *proxypass) - proxypass = xstrdup(proxypass); - break; + proxyhost = xstrdup(space); + break; + + case PROXY_SOCKS4: + case PROXY_SOCKS4A: + case PROXY_SOCKS5: + case PROXY_HTTP: + proxyhost = space; + + if(space && (space = strchr(space, ' '))) { + *space++ = 0, proxyport = space; + } + + if(space && (space = strchr(space, ' '))) { + *space++ = 0, proxyuser = space; + } + + if(space && (space = strchr(space, ' '))) { + *space++ = 0, proxypass = space; + } + + if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) { + logger(LOG_ERR, "Host and port argument expected for proxy!"); + free(proxy); + return false; + } + + proxyhost = xstrdup(proxyhost); + proxyport = xstrdup(proxyport); + + if(proxyuser && *proxyuser) { + proxyuser = xstrdup(proxyuser); + } + + if(proxypass && *proxypass) { + proxypass = xstrdup(proxypass); + } + + break; } free(proxy); } - if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) - myself->options |= OPTION_INDIRECT; - - if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) - myself->options |= OPTION_TCPONLY; - - if(myself->options & OPTION_TCPONLY) - myself->options |= OPTION_INDIRECT; - - get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly); - get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery); - - memset(&localdiscovery_address, 0, sizeof localdiscovery_address); - if(get_config_string(lookup_config(config_tree, "LocalDiscoveryAddress"), &address)) { - struct addrinfo *ai = str2addrinfo(address, myport, SOCK_DGRAM); - free(address); - if(!ai) - return false; - memcpy(&localdiscovery_address, ai->ai_addr, ai->ai_addrlen); - } - - - if(get_config_string(lookup_config(config_tree, "Mode"), &rmode)) { - if(!strcasecmp(rmode, "router")) - routing_mode = RMODE_ROUTER; - else if(!strcasecmp(rmode, "switch")) - routing_mode = RMODE_SWITCH; - else if(!strcasecmp(rmode, "hub")) - routing_mode = RMODE_HUB; - else { - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid routing mode!"); - return false; - } - free(rmode); - } - - if(get_config_string(lookup_config(config_tree, "Forwarding"), &fmode)) { - if(!strcasecmp(fmode, "off")) - forwarding_mode = FMODE_OFF; - else if(!strcasecmp(fmode, "internal")) - forwarding_mode = FMODE_INTERNAL; - else if(!strcasecmp(fmode, "kernel")) - forwarding_mode = FMODE_KERNEL; - else { - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid forwarding mode!"); - return false; - } - free(fmode); - } - - choice = true; - get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice); - if(choice) - myself->options |= OPTION_PMTU_DISCOVERY; - - choice = true; - get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice); - if(choice) - myself->options |= OPTION_CLAMP_MSS; - - get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); - get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl); - if(get_config_string(lookup_config(config_tree, "Broadcast"), &bmode)) { - if(!strcasecmp(bmode, "no")) - broadcast_mode = BMODE_NONE; - else if(!strcasecmp(bmode, "yes") || !strcasecmp(bmode, "mst")) - broadcast_mode = BMODE_MST; - else if(!strcasecmp(bmode, "direct")) - broadcast_mode = BMODE_DIRECT; - else { - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid broadcast mode!"); - return false; - } - free(bmode); - } - -#if !defined(SOL_IP) || !defined(IP_TOS) - if(priorityinheritance) - logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "PriorityInheritance"); -#endif - - if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) - macexpire = 600; - - if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) { - if(maxtimeout <= 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Bogus maximum timeout!"); - return false; - } - } else - maxtimeout = 900; - - if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) { - if(!strcasecmp(afname, "IPv4")) - addressfamily = AF_INET; - else if(!strcasecmp(afname, "IPv6")) - addressfamily = AF_INET6; - else if(!strcasecmp(afname, "any")) - addressfamily = AF_UNSPEC; - else { - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid address family!"); - return false; - } - free(afname); - } - - get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames); - - if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) - keylifetime = 3600; - - get_config_int(lookup_config(config_tree, "AutoConnect"), &autoconnect); - - get_config_bool(lookup_config(config_tree, "DisableBuggyPeers"), &disablebuggypeers); - - read_invitation_key(); - - return true; -} - -/* - Configure node_t myself and set up the local sockets (listen only) -*/ -static bool setup_myself(void) { - char *name, *hostname, *cipher, *digest, *type; - char *address = NULL; - - if(!(name = get_name())) { - logger(DEBUG_ALWAYS, LOG_ERR, "Name for tinc daemon required!"); - return false; - } - - myself = new_node(); - myself->connection = new_connection(); - myself->name = name; - myself->connection->name = xstrdup(name); - read_host_config(config_tree, name); - - if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) - myport = xstrdup("655"); - - xasprintf(&myself->hostname, "MYSELF port %s", myport); - myself->connection->hostname = xstrdup(myself->hostname); - - myself->connection->options = 0; - myself->connection->protocol_major = PROT_MAJOR; - myself->connection->protocol_minor = PROT_MINOR; - - myself->options |= PROT_MINOR << 24; - - get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental); - - if(experimental && !read_ecdsa_private_key()) - return false; - - if(!read_rsa_private_key()) - return false; - - if(!atoi(myport)) { - struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM); - sockaddr_t sa; - if(!ai || !ai->ai_addr) - return false; - free(myport); - memcpy(&sa, ai->ai_addr, ai->ai_addrlen); - sockaddr2str(&sa, NULL, &myport); - } - /* Read in all the subnets specified in the host configuration file */ - for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) { - subnet_t *subnet; + cfg = lookup_config(config_tree, "Subnet"); - if(!get_config_subnet(cfg, &subnet)) + while(cfg) { + if(!get_config_subnet(cfg, &subnet)) { return false; + } subnet_add(myself, subnet); + + cfg = lookup_config_next(config_tree, cfg); } /* Check some options */ - if(!setup_myself_reloadable()) - return false; + if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) { + myself->options |= OPTION_INDIRECT; + } + if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) { + myself->options |= OPTION_TCPONLY; + } + + if(myself->options & OPTION_TCPONLY) { + myself->options |= OPTION_INDIRECT; + } + + get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly); get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets); get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver); + get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery); strictsubnets |= tunnelserver; - if(get_config_int(lookup_config(config_tree, "MaxConnectionBurst"), &max_connection_burst)) { - if(max_connection_burst <= 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "MaxConnectionBurst cannot be negative!"); + if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) { + if(!strcasecmp(mode, "router")) { + routing_mode = RMODE_ROUTER; + } else if(!strcasecmp(mode, "switch")) { + routing_mode = RMODE_SWITCH; + } else if(!strcasecmp(mode, "hub")) { + routing_mode = RMODE_HUB; + } else { + logger(LOG_ERR, "Invalid routing mode!"); + free(mode); return false; } + + free(mode); + } + + if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) { + if(!strcasecmp(mode, "off")) { + forwarding_mode = FMODE_OFF; + } else if(!strcasecmp(mode, "internal")) { + forwarding_mode = FMODE_INTERNAL; + } else if(!strcasecmp(mode, "kernel")) { + forwarding_mode = FMODE_KERNEL; + } else { + logger(LOG_ERR, "Invalid forwarding mode!"); + free(mode); + return false; + } + + free(mode); + } + + choice = !(myself->options & OPTION_TCPONLY); + get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice); + + if(choice) { + myself->options |= OPTION_PMTU_DISCOVERY; + } + + choice = true; + get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice); + + if(choice) { + myself->options |= OPTION_CLAMP_MSS; + } + + get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); + get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl); + + if(get_config_string(lookup_config(config_tree, "Broadcast"), &mode)) { + if(!strcasecmp(mode, "no")) { + broadcast_mode = BMODE_NONE; + } else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst")) { + broadcast_mode = BMODE_MST; + } else if(!strcasecmp(mode, "direct")) { + broadcast_mode = BMODE_DIRECT; + } else { + logger(LOG_ERR, "Invalid broadcast mode!"); + free(mode); + return false; + } + + free(mode); + } + +#if !defined(SOL_IP) || !defined(IP_TOS) + + if(priorityinheritance) { + logger(LOG_WARNING, "%s not supported on this platform for IPv4 connection", "PriorityInheritance"); + } + +#endif + +#if !defined(IPPROTO_IPV6) || !defined(IPV6_TCLASS) + + if(priorityinheritance) { + logger(LOG_WARNING, "%s not supported on this platform for IPv6 connection", "PriorityInheritance"); + } + +#endif + + if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) { + macexpire = 600; + } + + if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) { + if(maxtimeout <= 0) { + logger(LOG_ERR, "Bogus maximum timeout!"); + return false; + } + } else { + maxtimeout = 900; + } + + if(get_config_int(lookup_config(config_tree, "MinTimeout"), &mintimeout)) { + if(mintimeout < 0) { + logger(LOG_ERR, "Bogus minimum timeout!"); + return false; + } + + if(mintimeout > maxtimeout) { + logger(LOG_WARNING, "Minimum timeout (%d s) cannot be larger than maximum timeout (%d s). Correcting !", mintimeout, maxtimeout); + mintimeout = maxtimeout; + } + } else { + mintimeout = 0; } if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) { if(udp_rcvbuf <= 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "UDPRcvBuf cannot be negative!"); + logger(LOG_ERR, "UDPRcvBuf cannot be negative!"); return false; } } if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) { if(udp_sndbuf <= 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "UDPSndBuf cannot be negative!"); + logger(LOG_ERR, "UDPSndBuf cannot be negative!"); return false; } } - int replaywin_int; if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) { if(replaywin_int < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "ReplayWindow cannot be negative!"); + logger(LOG_ERR, "ReplayWindow cannot be negative!"); return false; } + replaywin = (unsigned)replaywin_int; - sptps_replaywin = replaywin; } + if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) { + if(!strcasecmp(afname, "IPv4")) { + addressfamily = AF_INET; + } else if(!strcasecmp(afname, "IPv6")) { + addressfamily = AF_INET6; + } else if(!strcasecmp(afname, "any")) { + addressfamily = AF_UNSPEC; + } else { + logger(LOG_ERR, "Invalid address family!"); + free(afname); + return false; + } + + free(afname); + } + + get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames); + /* Generate packet encryption key */ - if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) - cipher = xstrdup("blowfish"); + if(get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) { + if(!strcasecmp(cipher, "none")) { + myself->incipher = NULL; + } else { + myself->incipher = EVP_get_cipherbyname(cipher); - if(!(myself->incipher = cipher_open_by_name(cipher))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized cipher type!"); - return false; + if(!myself->incipher) { + logger(LOG_ERR, "Unrecognized cipher type!"); + free(cipher); + return false; + } + } + + free(cipher); + } else { + myself->incipher = EVP_aes_256_cbc(); } - free(cipher); + if(myself->incipher) { + myself->inkeylength = EVP_CIPHER_key_length(myself->incipher) + EVP_CIPHER_iv_length(myself->incipher); + } else { + myself->inkeylength = 1; + } - send_key_changed(); - timeout_add(&keyexpire_timeout, keyexpire_handler, &keyexpire_timeout, &(struct timeval){keylifetime, rand() % 100000}); + /* We need to use a stream mode for the meta protocol. Use AES for this, + but try to match the key size with the one from the cipher selected + by Cipher. + + If Cipher is set to none, still use a low level of encryption for the + meta protocol. + */ + + int keylen = myself->incipher ? EVP_CIPHER_key_length(myself->incipher) : 0; + + if(keylen <= 16) { + myself->connection->outcipher = EVP_aes_128_cfb(); + } else if(keylen <= 24) { + myself->connection->outcipher = EVP_aes_192_cfb(); + } else { + myself->connection->outcipher = EVP_aes_256_cfb(); + } + + if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) { + keylifetime = 3600; + } + + keyexpires = now + keylifetime; /* Check if we want to use message authentication codes... */ - int maclength = 4; - get_config_int(lookup_config(config_tree, "MACLength"), &maclength); + if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) { + if(!strcasecmp(digest, "none")) { + myself->indigest = NULL; + } else { + myself->indigest = EVP_get_digestbyname(digest); - if(maclength < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Bogus MAC length!"); - return false; + if(!myself->indigest) { + logger(LOG_ERR, "Unrecognized digest type!"); + free(digest); + return false; + } + } + + free(digest); + } else { + myself->indigest = EVP_sha256(); } - if(!get_config_string(lookup_config(config_tree, "Digest"), &digest)) - digest = xstrdup("sha1"); + myself->connection->outdigest = EVP_sha256(); - if(!(myself->indigest = digest_open_by_name(digest, maclength))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized digest type!"); - return false; + if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) { + if(myself->indigest) { + if(myself->inmaclength > EVP_MD_size(myself->indigest)) { + logger(LOG_ERR, "MAC length exceeds size of digest!"); + return false; + } else if(myself->inmaclength < 0) { + logger(LOG_ERR, "Bogus MAC length!"); + return false; + } + } + } else { + myself->inmaclength = 4; } - free(digest); + myself->connection->outmaclength = 0; /* Compression */ if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) { if(myself->incompression < 0 || myself->incompression > 11) { - logger(DEBUG_ALWAYS, LOG_ERR, "Bogus compression level!"); + logger(LOG_ERR, "Bogus compression level!"); return false; } - } else + } else { myself->incompression = 0; + } myself->connection->outcompression = 0; @@ -794,55 +812,63 @@ static bool setup_myself(void) { myself->nexthop = myself; myself->via = myself; myself->status.reachable = true; - myself->last_state_change = now.tv_sec; - myself->status.sptps = experimental; node_add(myself); graph(); - if(strictsubnets) + if(strictsubnets) { load_all_subnets(); - else if(autoconnect) - load_all_nodes(); + } /* Open device */ devops = os_devops; if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { - if(!strcasecmp(type, "dummy")) + if(!strcasecmp(type, "dummy")) { devops = dummy_devops; - else if(!strcasecmp(type, "raw_socket")) + } else if(!strcasecmp(type, "raw_socket")) { devops = raw_socket_devops; - else if(!strcasecmp(type, "multicast")) + } else if(!strcasecmp(type, "multicast")) { devops = multicast_devops; + } + #ifdef ENABLE_UML - else if(!strcasecmp(type, "uml")) + else if(!strcasecmp(type, "uml")) { devops = uml_devops; + } + #endif #ifdef ENABLE_VDE - else if(!strcasecmp(type, "vde")) + else if(!strcasecmp(type, "vde")) { devops = vde_devops; + } + #endif + free(type); } - if(!devops.setup()) + if(!devops.setup()) { return false; - - if(device_fd >= 0) - io_add(&device_io, handle_device_data, NULL, device_fd, IO_READ); + } /* 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[0], "NETNAME=%s", netname ? netname : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? device : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : ""); xasprintf(&envp[3], "NAME=%s", myself->name); +#ifdef HAVE_MINGW + Sleep(1000); +#endif +#ifdef HAVE_CYGWIN + sleep(1); +#endif execute_script("tinc-up", envp); - for(int i = 0; i < 4; i++) + for(i = 0; i < 4; i++) { free(envp[i]); + } /* Run subnet-up scripts for our own subnets */ @@ -850,42 +876,6 @@ static bool setup_myself(void) { /* Open sockets */ -#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; - sa.sun_family = AF_UNIX; - strncpy(sa.sun_path, unixsocketname, sizeof sa.sun_path); - - if(connect(unix_fd, (struct sockaddr *)&sa, sizeof sa) >= 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname); - return false; - } - - unlink(unixsocketname); - - mode_t mask = umask(0); - umask(mask | 077); - int result = bind(unix_fd, (struct sockaddr *)&sa, sizeof sa); - 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 - if(!do_detach && getenv("LISTEN_FDS")) { sockaddr_t sa; socklen_t salen; @@ -896,31 +886,33 @@ static bool setup_myself(void) { #endif if(listen_sockets > MAXSOCKETS) { - logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets"); + logger(LOG_ERR, "Too many listening sockets"); return false; } - for(int i = 0; i < listen_sockets; i++) { - salen = sizeof sa; + for(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)); + logger(LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno)); return false; } + listen_socket[i].tcp = i + 3; + #ifdef FD_CLOEXEC fcntl(i + 3, F_SETFD, FD_CLOEXEC); #endif - int udp_fd = setup_vpn_in_socket(&sa); - if(udp_fd < 0) + listen_socket[i].udp = setup_vpn_in_socket(&sa); + + if(listen_socket[i].udp < 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) { + ifdebug(CONNECTIONS) { hostname = sockaddr2hostname(&sa); - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname); + logger(LOG_NOTICE, "Listening on %s", hostname); free(hostname); } @@ -928,64 +920,71 @@ static bool setup_myself(void) { } } else { listen_sockets = 0; - config_t *cfg = lookup_config(config_tree, "BindToAddress"); + cfg = lookup_config(config_tree, "BindToAddress"); do { get_config_string(cfg, &address); - if(cfg) + + if(cfg) { cfg = lookup_config_next(config_tree, cfg); + } char *port = myport; if(address) { char *space = strchr(address, ' '); + if(space) { *space++ = 0; port = space; } - if(!strcmp(address, "*")) + if(!strcmp(address, "*")) { *address = 0; + } } - struct addrinfo *ai, hint = {0}; hint.ai_family = addressfamily; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = IPPROTO_TCP; hint.ai_flags = AI_PASSIVE; - int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai); +#if HAVE_DECL_RES_INIT + // ensure glibc reloads /etc/resolv.conf. + res_init(); +#endif + err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai); free(address); if(err || !ai) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err)); + logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", + gai_strerror(err)); return false; } - for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { + for(aip = ai; aip; aip = aip->ai_next) { if(listen_sockets >= MAXSOCKETS) { - logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets"); + logger(LOG_ERR, "Too many listening sockets"); return false; } - int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr); + listen_socket[listen_sockets].tcp = + setup_listen_socket((sockaddr_t *) aip->ai_addr); - if(tcp_fd < 0) - continue; - - int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); - - if(tcp_fd < 0) { - close(tcp_fd); + if(listen_socket[listen_sockets].tcp < 0) { continue; } - io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ); - io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ); + listen_socket[listen_sockets].udp = + setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); - if(debug_level >= DEBUG_CONNECTIONS) { + if(listen_socket[listen_sockets].udp < 0) { + continue; + } + + ifdebug(CONNECTIONS) { hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname); + logger(LOG_NOTICE, "Listening on %s", hostname); free(hostname); } @@ -997,15 +996,30 @@ static bool setup_myself(void) { } while(cfg); } - if(listen_sockets) - logger(DEBUG_ALWAYS, LOG_NOTICE, "Ready"); - else { - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to create any listening socket!"); + if(!listen_sockets) { + logger(LOG_ERR, "Unable to create any listening socket!"); return false; } - last_config_check = now.tv_sec; + /* If no Port option was specified, set myport to the port used by the first listening socket. */ + if(!port_specified) { + sockaddr_t sa; + socklen_t salen = sizeof(sa); + + if(!getsockname(listen_socket[0].udp, &sa.sa, &salen)) { + free(myport); + sockaddr2str(&sa, NULL, &myport); + + if(!myport) { + myport = xstrdup("655"); + } + } + } + + /* Done. */ + + logger(LOG_NOTICE, "Ready"); return true; } @@ -1013,6 +1027,9 @@ static bool setup_myself(void) { initialize network */ bool setup_network(void) { + now = time(NULL); + + init_events(); init_connections(); init_subnets(); init_nodes(); @@ -1023,19 +1040,25 @@ bool setup_network(void) { if(pinginterval < 1) { pinginterval = 86400; } - } else + } else { pinginterval = 60; + } - if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) + if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) { pingtimeout = 5; - if(pingtimeout < 1 || pingtimeout > pinginterval) + } + + if(pingtimeout < 1 || pingtimeout > pinginterval) { pingtimeout = pinginterval; + } - if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize)) + if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize)) { maxoutbufsize = 10 * MTU; + } - if(!setup_myself()) + if(!setup_myself()) { return false; + } return true; } @@ -1044,16 +1067,26 @@ bool setup_network(void) { close all open network connections */ void close_network_connections(void) { - for(list_node_t *node = connection_list->head, *next; node; node = next) { + avl_node_t *node, *next; + connection_t *c; + char *envp[5] = {0}; + int i; + + for(node = connection_tree->head; 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 = node->data; c->outgoing = NULL; terminate_connection(c, false); } + for(list_node_t *node = outgoing_list->head; node; node = node->next) { + outgoing_t *outgoing = node->data; + + if(outgoing->event) { + event_del(outgoing->event); + } + } + list_delete_list(outgoing_list); if(myself && myself->connection) { @@ -1062,22 +1095,14 @@ void close_network_connections(void) { free_connection(myself->connection); } - for(int i = 0; i < listen_sockets; i++) { - io_del(&listen_socket[i].tcp); - io_del(&listen_socket[i].udp); - close(listen_socket[i].tcp.fd); - close(listen_socket[i].udp.fd); + for(i = 0; i < listen_sockets; i++) { + close(listen_socket[i].tcp); + close(listen_socket[i].udp); } -#ifndef HAVE_MINGW - io_del(&unix_socket); - close(unix_socket.fd); -#endif - - char *envp[5] = {NULL}; - xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); - xasprintf(&envp[1], "DEVICE=%s", device ? : ""); - xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[0], "NETNAME=%s", netname ? netname : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? device : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : ""); xasprintf(&envp[3], "NAME=%s", myself->name); exit_requests(); @@ -1085,13 +1110,17 @@ void close_network_connections(void) { exit_subnets(); exit_nodes(); exit_connections(); + exit_events(); execute_script("tinc-down", envp); - if(myport) free(myport); + if(myport) { + free(myport); + } - for(int i = 0; i < 4; i++) + for(i = 0; i < 4; i++) { free(envp[i]); + } devops.close(); diff --git a/src/net_socket.c b/src/net_socket.c index ded9224..6195c16 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -1,7 +1,7 @@ /* net_socket.c -- Handle various kinds of sockets. Copyright (C) 1998-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2017 Guus Sliepen 2006 Scott Lamb 2009 Florian Forster @@ -22,16 +22,16 @@ #include "system.h" +#include "avl_tree.h" #include "conf.h" #include "connection.h" -#include "control_common.h" -#include "list.h" +#include "event.h" #include "logger.h" #include "meta.h" -#include "names.h" #include "net.h" #include "netutl.h" #include "protocol.h" +#include "proxy.h" #include "utils.h" #include "xalloc.h" @@ -41,17 +41,14 @@ #endif int addressfamily = AF_UNSPEC; +int mintimeout = 0; int maxtimeout = 900; int seconds_till_retry = 5; int udp_rcvbuf = 0; int udp_sndbuf = 0; -int max_connection_burst = 100; listen_socket_t listen_socket[MAXSOCKETS]; int listen_sockets; -#ifndef HAVE_MINGW -io_t unix_socket; -#endif list_t *outgoing_list = NULL; /* Setup sockets */ @@ -63,24 +60,31 @@ static void configure_tcp(connection_t *c) { int flags = fcntl(c->socket, F_GETFL); if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "fcntl for %s: %s", c->hostname, strerror(errno)); + logger(LOG_ERR, "fcntl for %s: %s", c->hostname, strerror(errno)); } + #elif defined(WIN32) unsigned long arg = 1; if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno)); + logger(LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno)); } + #endif #if defined(SOL_TCP) && defined(TCP_NODELAY) option = 1; - setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, sizeof option); + setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, sizeof(option)); #endif -#if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY) +#if defined(IP_TOS) && defined(IPTOS_LOWDELAY) option = IPTOS_LOWDELAY; - setsockopt(c->socket, SOL_IP, IP_TOS, (void *)&option, sizeof option); + setsockopt(c->socket, IPPROTO_IP, IP_TOS, (void *)&option, sizeof(option)); +#endif + +#if defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY) + option = IPTOS_LOWDELAY; + setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof(option)); #endif } @@ -92,22 +96,25 @@ static bool bind_to_interface(int sd) { int status; #endif /* defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) */ - if(!get_config_string (lookup_config (config_tree, "BindToInterface"), &iface)) + if(!get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) { return true; + } #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0; + free(iface); status = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)); + if(status) { - logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface, - strerror(errno)); + logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno)); return false; } + #else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */ - logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "BindToInterface"); + logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface"); #endif return true; @@ -122,7 +129,7 @@ int setup_listen_socket(const sockaddr_t *sa) { nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if(nfd < 0) { - logger(DEBUG_STATUS, LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno)); + ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno)); return -1; } @@ -133,43 +140,49 @@ int setup_listen_socket(const sockaddr_t *sa) { /* Optimize TCP settings */ option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option); + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option)); -#if defined(SOL_IPV6) && defined(IPV6_V6ONLY) - if(sa->sa.sa_family == AF_INET6) - setsockopt(nfd, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option); +#if defined(IPV6_V6ONLY) + + if(sa->sa.sa_family == AF_INET6) { + setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + +#else +#warning IPV6_V6ONLY not defined #endif - if(get_config_string - (lookup_config(config_tree, "BindToInterface"), &iface)) { + if(get_config_string(lookup_config(config_tree, "BindToInterface"), &iface)) { #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) struct ifreq ifr; - memset(&ifr, 0, sizeof ifr); + memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); + ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0; + free(iface); - if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof ifr)) { + if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) { closesocket(nfd); - logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to interface %s: %s", iface, - strerror(sockerrno)); + logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(sockerrno)); return -1; } + #else - logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "BindToInterface"); + logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface"); #endif } if(bind(nfd, &sa->sa, SALEN(sa->sa))) { closesocket(nfd); addrstr = sockaddr2hostname(sa); - logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno)); + logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno)); free(addrstr); return -1; } if(listen(nfd, 3)) { closesocket(nfd); - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno)); + logger(LOG_ERR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno)); return -1; } @@ -184,7 +197,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); if(nfd < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno)); + logger(LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno)); return -1; } @@ -198,70 +211,80 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { closesocket(nfd); - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl", - strerror(errno)); + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", + strerror(errno)); return -1; } } #elif defined(WIN32) { unsigned long arg = 1; + if(ioctlsocket(nfd, FIONBIO, &arg) != 0) { closesocket(nfd); - logger(DEBUG_ALWAYS, LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno)); + logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno)); return -1; } } #endif option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option); - setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof option); + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option)); + setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option)); - if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf))) - logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno)); + if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf))) { + logger(LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno)); + } - if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf))) - logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno)); + if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf))) { + logger(LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno)); + } + +#if defined(IPV6_V6ONLY) + + if(sa->sa.sa_family == AF_INET6) { + setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } -#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) - if(sa->sa.sa_family == AF_INET6) - setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option); #endif #if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT) #define IP_DONTFRAGMENT IP_DONTFRAG #endif -#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) + if(myself->options & OPTION_PMTU_DISCOVERY) { option = IP_PMTUDISC_DO; - setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option)); + setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option)); } -#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT) + +#elif defined(IP_DONTFRAGMENT) + if(myself->options & OPTION_PMTU_DISCOVERY) { option = 1; setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option)); } -#else -#warning No way to disable IPv4 fragmentation + #endif -#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) +#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) + if(myself->options & OPTION_PMTU_DISCOVERY) { option = IPV6_PMTUDISC_DO; - setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option)); + setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option)); } -#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG) + +#elif defined(IPV6_DONTFRAG) + if(myself->options & OPTION_PMTU_DISCOVERY) { option = 1; setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option)); } -#else -#warning No way to disable IPv6 fragmentation + #endif - if (!bind_to_interface(nfd)) { + if(!bind_to_interface(nfd)) { closesocket(nfd); return -1; } @@ -269,7 +292,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { if(bind(nfd, &sa->sa, SALEN(sa->sa))) { closesocket(nfd); addrstr = sockaddr2hostname(sa); - logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno)); + logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno)); free(addrstr); return -1; } @@ -277,26 +300,36 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { return nfd; } /* int setup_vpn_in_socket */ -static void retry_outgoing_handler(void *data) { - setup_outgoing_connection(data); -} - void retry_outgoing(outgoing_t *outgoing) { outgoing->timeout += 5; - if(outgoing->timeout > maxtimeout) + if(outgoing->timeout < mintimeout) { + outgoing->timeout = mintimeout; + } + + if(outgoing->timeout > maxtimeout) { outgoing->timeout = maxtimeout; + } - timeout_add(&outgoing->ev, retry_outgoing_handler, outgoing, &(struct timeval){outgoing->timeout, rand() % 100000}); + if(outgoing->event) { + event_del(outgoing->event); + } - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Trying to re-establish outgoing connection in %d seconds", outgoing->timeout); + outgoing->event = new_event(); + outgoing->event->handler = (event_handler_t) setup_outgoing_connection; + outgoing->event->time = now + outgoing->timeout; + outgoing->event->data = outgoing; + event_add(outgoing->event); + + ifdebug(CONNECTIONS) logger(LOG_NOTICE, + "Trying to re-establish outgoing connection in %d seconds", + outgoing->timeout); } void finish_connecting(connection_t *c) { - logger(DEBUG_CONNECTIONS, LOG_INFO, "Connected to %s (%s)", c->name, c->hostname); + ifdebug(CONNECTIONS) logger(LOG_INFO, "Connected to %s (%s)", c->name, c->hostname); - c->last_ping_time = now.tv_sec; - c->status.connecting = false; + c->last_ping_time = now; send_id(c); } @@ -306,14 +339,14 @@ static void do_outgoing_pipe(connection_t *c, char *command) { int fd[2]; if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not create socketpair: %s", strerror(errno)); + logger(LOG_ERR, "Could not create socketpair: %s\n", strerror(errno)); return; } if(fork()) { c->socket = fd[0]; close(fd[1]); - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Using proxy %s", command); + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Using proxy %s", command); return; } @@ -334,153 +367,189 @@ static void do_outgoing_pipe(connection_t *c, char *command) { setenv("REMOTEPORT", port, true); setenv("NODE", c->name, true); setenv("NAME", myself->name, true); - if(netname) + + if(netname) { setenv("NETNAME", netname, true); + } int result = system(command); - if(result < 0) - logger(DEBUG_ALWAYS, LOG_ERR, "Could not execute %s: %s", command, strerror(errno)); - else if(result) - logger(DEBUG_ALWAYS, LOG_ERR, "%s exited with non-zero status %d", command, result); + + if(result < 0) { + logger(LOG_ERR, "Could not execute %s: %s\n", command, strerror(errno)); + } else if(result) { + logger(LOG_ERR, "%s exited with non-zero status %d", command, result); + } + exit(result); #else - logger(DEBUG_ALWAYS, LOG_ERR, "Proxy type exec not supported on this platform!"); + logger(LOG_ERR, "Proxy type exec not supported on this platform!"); return; #endif } -static void handle_meta_write(connection_t *c) { - if(c->outbuf.len <= c->outbuf.offset) - return; - - ssize_t outlen = send(c->socket, c->outbuf.data + c->outbuf.offset, c->outbuf.len - c->outbuf.offset, 0); - if(outlen <= 0) { - if(!errno || errno == EPIPE) { - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname); - } else if(sockwouldblock(sockerrno)) { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Sending %d bytes to %s (%s) would block", c->outbuf.len - c->outbuf.offset, c->name, c->hostname); - return; - } else { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not send %d bytes of data to %s (%s): %s", c->outbuf.len - c->outbuf.offset, c->name, c->hostname, strerror(errno)); - } - - terminate_connection(c, c->status.active); - return; - } - - buffer_read(&c->outbuf, outlen); - if(!c->outbuf.len) - io_set(&c->io, IO_READ); -} - -static void handle_meta_io(void *data, int flags) { - connection_t *c = data; - - if(c->status.connecting) { - c->status.connecting = false; - - int result; - socklen_t len = sizeof result; - getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len); - - if(!result) - finish_connecting(c); - else { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(result)); - terminate_connection(c, false); - return; - } - } - - if(flags & IO_WRITE) - handle_meta_write(c); - else - handle_meta_connection_data(c); -} - -bool do_outgoing_connection(outgoing_t *outgoing) { - char *address, *port, *space; - struct addrinfo *proxyai = NULL; - int result; - -begin: - if(!outgoing->ai) { - if(!outgoing->cfg) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->name); - retry_outgoing(outgoing); +static bool is_valid_host_port(const char *host, const char *port) { + for(const char *p = host; *p; p++) + if(!isalnum(*p) && *p != '-' && *p != '.') { return false; } - get_config_string(outgoing->cfg, &address); + for(const char *p = port; *p; p++) + if(!isalnum(*p)) { + return false; + } + + return true; +} + +void do_outgoing_connection(connection_t *c) { + struct addrinfo *proxyai = NULL; + int result; + + if(!c->outgoing) { + logger(LOG_ERR, "do_outgoing_connection() for %s called without c->outgoing", c->name); + abort(); + } + +begin: + + if(!c->outgoing->ai) { + if(!c->outgoing->cfg) { + ifdebug(CONNECTIONS) logger(LOG_ERR, "Could not set up a meta connection to %s", + c->name); + c->status.remove = true; + retry_outgoing(c->outgoing); + c->outgoing = NULL; + return; + } + + char *address, *port, *space; + + get_config_string(c->outgoing->cfg, &address); space = strchr(address, ' '); + if(space) { port = xstrdup(space + 1); *space = 0; } else { - if(!get_config_string(lookup_config(outgoing->config_tree, "Port"), &port)) + if(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) { port = xstrdup("655"); + } } - outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); - free(address); - free(port); + c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); - outgoing->aip = outgoing->ai; - outgoing->cfg = lookup_config_next(outgoing->config_tree, outgoing->cfg); + // If we cannot resolve the address, maybe we are using a proxy that can? + if(!c->outgoing->ai && proxytype != PROXY_NONE && is_valid_host_port(address, port)) { + memset(&c->address, 0, sizeof(c->address)); + c->address.sa.sa_family = AF_UNKNOWN; + c->address.unknown.address = address; + c->address.unknown.port = port; + } else { + free(address); + free(port); + } + + c->outgoing->aip = c->outgoing->ai; + c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg); + + if(!c->outgoing->ai && proxytype != PROXY_NONE) { + goto connect; + } } - if(!outgoing->aip) { - if(outgoing->ai) - freeaddrinfo(outgoing->ai); - outgoing->ai = NULL; + if(!c->outgoing->aip) { + if(c->outgoing->ai) { + freeaddrinfo(c->outgoing->ai); + } + + c->outgoing->ai = NULL; goto begin; } - connection_t *c = new_connection(); - c->outgoing = outgoing; + memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen); + c->outgoing->aip = c->outgoing->aip->ai_next; - memcpy(&c->address, outgoing->aip->ai_addr, outgoing->aip->ai_addrlen); - outgoing->aip = outgoing->aip->ai_next; +connect: + + if(c->hostname) { + free(c->hostname); + } c->hostname = sockaddr2hostname(&c->address); - logger(DEBUG_CONNECTIONS, LOG_INFO, "Trying to connect to %s (%s)", outgoing->name, c->hostname); + ifdebug(CONNECTIONS) logger(LOG_INFO, "Trying to connect to %s (%s)", c->name, + c->hostname); if(!proxytype) { c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); - configure_tcp(c); } else if(proxytype == PROXY_EXEC) { + c->status.proxy_passed = true; do_outgoing_pipe(c, proxyhost); } else { proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM); + if(!proxyai) { - free_connection(c); goto begin; } - logger(DEBUG_CONNECTIONS, LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport); + + ifdebug(CONNECTIONS) logger(LOG_INFO, "Using proxy at %s port %s", proxyhost, proxyport); c->socket = socket(proxyai->ai_family, SOCK_STREAM, IPPROTO_TCP); - configure_tcp(c); } if(c->socket == -1) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno)); - free_connection(c); + ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno)); goto begin; } + if(proxytype != PROXY_EXEC) { + configure_tcp(c); + } + #ifdef FD_CLOEXEC fcntl(c->socket, F_SETFD, FD_CLOEXEC); #endif if(proxytype != PROXY_EXEC) { -#if defined(SOL_IPV6) && defined(IPV6_V6ONLY) +#if defined(IPV6_V6ONLY) int option = 1; - if(c->address.sa.sa_family == AF_INET6) - setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option); + + if(c->address.sa.sa_family == AF_INET6) { + setsockopt(c->socket, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + #endif bind_to_interface(c->socket); + + int b = -1; + + for(int i = 0; i < listen_sockets; i++) { + if(listen_socket[i].sa.sa.sa_family == c->address.sa.sa_family) { + if(b == -1) { + b = i; + } else { + b = -1; + break; + } + } + } + + if(b != -1) { + sockaddr_t sa = listen_socket[b].sa; + + if(sa.sa.sa_family == AF_INET) { + sa.in.sin_port = 0; + } else if(sa.sa.sa_family == AF_INET6) { + sa.in6.sin6_port = 0; + } + + if(bind(c->socket, &sa.sa, SALEN(sa.sa))) { + char *addrstr = sockaddr2hostname(&sa); + logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno)); + free(addrstr); + } + } } /* Connect */ @@ -494,115 +563,115 @@ begin: freeaddrinfo(proxyai); } - if(result == -1 && !sockinprogress(sockerrno)) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not connect to %s (%s): %s", outgoing->name, c->hostname, sockstrerror(sockerrno)); - free_connection(c); + now = time(NULL); + + if(result == -1) { + if(sockinprogress(sockerrno)) { + c->last_ping_time = now; + c->status.connecting = true; + return; + } + + closesocket(c->socket); + + ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, sockstrerror(sockerrno)); goto begin; } - /* Now that there is a working socket, fill in the rest and register this connection. */ + finish_connecting(c); - c->status.connecting = true; + return; +} + +void setup_outgoing_connection(outgoing_t *outgoing) { + connection_t *c; + node_t *n; + + outgoing->event = NULL; + + n = lookup_node(outgoing->name); + + if(n) + if(n->connection) { + ifdebug(CONNECTIONS) logger(LOG_INFO, "Already connected to %s", outgoing->name); + + n->connection->outgoing = outgoing; + return; + } + + c = new_connection(); c->name = xstrdup(outgoing->name); c->outcipher = myself->connection->outcipher; c->outdigest = myself->connection->outdigest; c->outmaclength = myself->connection->outmaclength; c->outcompression = myself->connection->outcompression; - c->last_ping_time = now.tv_sec; + + init_configuration(&c->config_tree); + + if(!read_connection_config(c)) { + free_connection(c); + outgoing->timeout = maxtimeout; + retry_outgoing(outgoing); + return; + } + + outgoing->cfg = lookup_config(c->config_tree, "Address"); + + if(!outgoing->cfg) { + logger(LOG_ERR, "No address specified for %s", c->name); + free_connection(c); + outgoing->timeout = maxtimeout; + retry_outgoing(outgoing); + return; + } + + c->outgoing = outgoing; + c->last_ping_time = now; connection_add(c); - io_add(&c->io, handle_meta_io, c, c->socket, IO_READ|IO_WRITE); - - return true; -} - -void setup_outgoing_connection(outgoing_t *outgoing) { - timeout_del(&outgoing->ev); - - node_t *n = lookup_node(outgoing->name); - - if(n && n->connection) { - logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", outgoing->name); - - n->connection->outgoing = outgoing; - return; - } - - init_configuration(&outgoing->config_tree); - read_host_config(outgoing->config_tree, outgoing->name); - outgoing->cfg = lookup_config(outgoing->config_tree, "Address"); - - if(!outgoing->cfg) { - logger(DEBUG_ALWAYS, LOG_ERR, "No address specified for %s", outgoing->name); - return; - } - - do_outgoing_connection(outgoing); + do_outgoing_connection(c); } /* accept a new tcp connect and create a new connection */ -void handle_new_meta_connection(void *data, int flags) { - listen_socket_t *l = data; +bool handle_new_meta_connection(int sock) { + static const int max_accept_burst = 10; + static int last_accept_burst; + static int last_accept_time; connection_t *c; sockaddr_t sa; int fd; - socklen_t len = sizeof sa; + socklen_t len = sizeof(sa); - fd = accept(l->tcp.fd, &sa.sa, &len); + fd = accept(sock, &sa.sa, &len); if(fd < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno)); - return; + logger(LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno)); + return false; + } + + if(last_accept_time == now) { + last_accept_burst++; + + if(last_accept_burst >= max_accept_burst) { + if(last_accept_burst == max_accept_burst) { + ifdebug(CONNECTIONS) logger(LOG_WARNING, "Throttling incoming connections"); + } + + tarpit(fd); + return false; + } + } else { + last_accept_burst = 0; + last_accept_time = now; } sockaddrunmap(&sa); - // Check if we get many connections from the same host - - static sockaddr_t prev_sa; - static time_t prev_time; - static int tarpit = -1; - - if(tarpit >= 0) { - closesocket(tarpit); - tarpit = -1; - } - - if(prev_time == now.tv_sec && !sockaddrcmp_noport(&sa, &prev_sa)) { - // if so, keep the connection open but ignore it completely. - tarpit = fd; - return; - } - - memcpy(&prev_sa, &sa, sizeof sa); - prev_time = now.tv_sec; - - // Check if we get many connections from different hosts - - static int connection_burst; - static int connection_burst_time; - - if(now.tv_sec - connection_burst_time > connection_burst) - connection_burst = 0; - else - connection_burst -= now.tv_sec - connection_burst_time; - - connection_burst_time = now.tv_sec; - connection_burst++; - - if(connection_burst >= max_connection_burst) { - connection_burst = max_connection_burst; - tarpit = fd; - return; - } - - // Accept the new connection - c = new_connection(); c->name = xstrdup(""); c->outcipher = myself->connection->outcipher; @@ -613,129 +682,52 @@ void handle_new_meta_connection(void *data, int flags) { c->address = sa; c->hostname = sockaddr2hostname(&sa); c->socket = fd; - c->last_ping_time = now.tv_sec; + c->last_ping_time = now; - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname); - - io_add(&c->io, handle_meta_io, c, c->socket, IO_READ); + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection from %s", c->hostname); configure_tcp(c); connection_add(c); c->allow_request = ID; - send_id(c); + + return true; } -#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(""); - 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); - - if(outgoing->ai) + if(outgoing->ai) { freeaddrinfo(outgoing->ai); + } - if(outgoing->config_tree) - exit_configuration(&outgoing->config_tree); - - if(outgoing->name) + if(outgoing->name) { free(outgoing->name); + } free(outgoing); } void try_outgoing_connections(void) { - /* If there is no outgoing list yet, create one. Otherwise, mark all outgoings as deleted. */ + static config_t *cfg = NULL; + char *name; + outgoing_t *outgoing; - if(!outgoing_list) { - outgoing_list = list_alloc((list_action_t)free_outgoing); - } else { - for list_each(outgoing_t, outgoing, outgoing_list) - outgoing->timeout = -1; - } + outgoing_list = list_alloc((list_action_t)free_outgoing); - /* Make sure there is one outgoing_t in the list for each ConnectTo. */ - - for(config_t *cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) { - char *name; + for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) { get_config_string(cfg, &name); if(!check_id(name)) { - logger(DEBUG_ALWAYS, LOG_ERR, - "Invalid name for outgoing connection in %s line %d", - cfg->file, cfg->line); + logger(LOG_ERR, + "Invalid name for outgoing connection in %s line %d", + cfg->file, cfg->line); free(name); continue; } - bool found = false; - - for list_each(outgoing_t, outgoing, outgoing_list) { - if(!strcmp(outgoing->name, name)) { - found = true; - outgoing->timeout = 0; - break; - } - } - - if(!found) { - outgoing_t *outgoing = xzalloc(sizeof *outgoing); - outgoing->name = name; - list_insert_tail(outgoing_list, outgoing); - setup_outgoing_connection(outgoing); - } + outgoing = xmalloc_and_zero(sizeof(*outgoing)); + outgoing->name = name; + list_insert_tail(outgoing_list, outgoing); + setup_outgoing_connection(outgoing); } - - /* Terminate any connections whose outgoing_t is to be deleted. */ - - for list_each(connection_t, c, connection_list) { - if(c->outgoing && c->outgoing->timeout == -1) { - c->outgoing = NULL; - logger(DEBUG_CONNECTIONS, LOG_INFO, "No more outgoing connection to %s", c->name); - terminate_connection(c, c->status.active); - } - } - - /* Delete outgoing_ts for which there is no ConnectTo. */ - - for list_each(outgoing_t, outgoing, outgoing_list) - if(outgoing->timeout == -1) - list_delete_node(outgoing_list, node); } diff --git a/src/netutl.c b/src/netutl.c index 989a152..abe3d87 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -1,7 +1,7 @@ /* netutl.c -- some supporting network utility code Copyright (C) 1998-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,16 +33,21 @@ bool hostnames = false; Return NULL on failure. */ struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype) { - struct addrinfo *ai, hint = {0}; + struct addrinfo *ai = NULL, hint = {0}; int err; hint.ai_family = addressfamily; hint.ai_socktype = socktype; +#if HAVE_DECL_RES_INIT + // ensure glibc reloads /etc/resolv.conf. + res_init(); +#endif err = getaddrinfo(address, service, &hint, &ai); if(err) { - logger(DEBUG_ALWAYS, LOG_WARNING, "Error looking up %s port %s: %s", address, service, err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err)); + logger(LOG_WARNING, "Error looking up %s port %s: %s", address, + service, gai_strerror(err)); return NULL; } @@ -50,8 +55,8 @@ struct addrinfo *str2addrinfo(const char *address, const char *service, int sock } sockaddr_t str2sockaddr(const char *address, const char *port) { - struct addrinfo *ai, hint = {0}; - sockaddr_t result = {{0}}; + struct addrinfo *ai = NULL, hint = {0}; + sockaddr_t result; int err; hint.ai_family = AF_UNSPEC; @@ -61,7 +66,8 @@ sockaddr_t str2sockaddr(const char *address, const char *port) { err = getaddrinfo(address, port, &hint, &ai); if(err || !ai) { - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Unknown type address %s port %s", address, port); + ifdebug(SCARY_THINGS) + logger(LOG_DEBUG, "Unknown type address %s port %s", address, port); result.sa.sa_family = AF_UNKNOWN; result.unknown.address = xstrdup(address); result.unknown.port = xstrdup(port); @@ -81,29 +87,38 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) { int err; if(sa->sa.sa_family == AF_UNKNOWN) { - if(addrstr) + if(addrstr) { *addrstr = xstrdup(sa->unknown.address); - if(portstr) + } + + if(portstr) { *portstr = xstrdup(sa->unknown.port); + } + return; } - err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof address, port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV); + err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); if(err) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while translating addresses: %s", err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err)); + logger(LOG_ERR, "Error while translating addresses: %s", + gai_strerror(err)); abort(); } scopeid = strchr(address, '%'); - if(scopeid) - *scopeid = '\0'; /* Descope. */ + if(scopeid) { + *scopeid = '\0'; /* Descope. */ + } - if(addrstr) + if(addrstr) { *addrstr = xstrdup(address); - if(portstr) + } + + if(portstr) { *portstr = xstrdup(port); + } } char *sockaddr2hostname(const sockaddr_t *sa) { @@ -117,10 +132,12 @@ char *sockaddr2hostname(const sockaddr_t *sa) { return str; } - err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof address, port, sizeof port, - hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV)); + err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), + hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV)); + if(err) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while looking up hostname: %s", err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err)); + logger(LOG_ERR, "Error while looking up hostname: %s", + gai_strerror(err)); } xasprintf(&str, "%s port %s", address, port); @@ -133,26 +150,27 @@ int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b) { result = a->sa.sa_family - b->sa.sa_family; - if(result) + if(result) { return result; + } - switch (a->sa.sa_family) { - case AF_UNSPEC: - return 0; + switch(a->sa.sa_family) { + case AF_UNSPEC: + return 0; - case AF_UNKNOWN: - return strcmp(a->unknown.address, b->unknown.address); + case AF_UNKNOWN: + return strcmp(a->unknown.address, b->unknown.address); - case AF_INET: - return memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); + case AF_INET: + return memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); - case AF_INET6: - return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); + case AF_INET6: + return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); - default: - logger(DEBUG_ALWAYS, LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!", - a->sa.sa_family); - abort(); + default: + logger(LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!", + a->sa.sa_family); + abort(); } } @@ -161,41 +179,45 @@ int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) { result = a->sa.sa_family - b->sa.sa_family; - if(result) + if(result) { return result; + } - switch (a->sa.sa_family) { - case AF_UNSPEC: - return 0; + switch(a->sa.sa_family) { + case AF_UNSPEC: + return 0; - case AF_UNKNOWN: - result = strcmp(a->unknown.address, b->unknown.address); + case AF_UNKNOWN: + result = strcmp(a->unknown.address, b->unknown.address); - if(result) - return result; + if(result) { + return result; + } - return strcmp(a->unknown.port, b->unknown.port); + return strcmp(a->unknown.port, b->unknown.port); - case AF_INET: - result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof a->in.sin_addr); + case AF_INET: + result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); - if(result) - return result; + if(result) { + return result; + } - return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof a->in.sin_port); + return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port)); - case AF_INET6: - result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof a->in6.sin6_addr); + case AF_INET6: + result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); - if(result) - return result; + if(result) { + return result; + } - return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof a->in6.sin6_port); + return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port)); - default: - logger(DEBUG_ALWAYS, LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!", - a->sa.sa_family); - abort(); + default: + logger(LOG_ERR, "sockaddrcmp() was called with unknown address family %d, exitting!", + a->sa.sa_family); + abort(); } } @@ -222,3 +244,104 @@ void sockaddrunmap(sockaddr_t *sa) { sa->in.sin_family = AF_INET; } } + +void sockaddr_setport(sockaddr_t *sa, const char *port) { + uint16_t portnum = htons(atoi(port)); + + if(!portnum) { + return; + } + + switch(sa->sa.sa_family) { + case AF_INET: + sa->in.sin_port = portnum; + break; + + case AF_INET6: + sa->in6.sin6_port = portnum; + break; + + case AF_UNKNOWN: + free(sa->unknown.port); + sa->unknown.port = xstrdup(port); + + default: + return; + } +} + +/* 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; +} diff --git a/src/netutl.h b/src/netutl.h index 471cae7..cc3ccab 100644 --- a/src/netutl.h +++ b/src/netutl.h @@ -1,7 +1,10 @@ +#ifndef TINC_NETUTL_H +#define TINC_NETUTL_H + /* netutl.h -- header file for netutl.c Copyright (C) 1998-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,21 +21,23 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_NETUTL_H__ -#define __TINC_NETUTL_H__ - #include "net.h" extern bool hostnames; -extern struct addrinfo *str2addrinfo(const char *, const char *, int) __attribute__ ((__malloc__)); -extern sockaddr_t str2sockaddr(const char *, const char *); -extern void sockaddr2str(const sockaddr_t *, char **, char **); -extern char *sockaddr2hostname(const sockaddr_t *) __attribute__ ((__malloc__)); -extern int sockaddrcmp(const sockaddr_t *, const sockaddr_t *); -extern int sockaddrcmp_noport(const sockaddr_t *, const sockaddr_t *); -extern void sockaddrunmap(sockaddr_t *); -extern void sockaddrfree(sockaddr_t *); -extern void sockaddrcpy(sockaddr_t *, const sockaddr_t *); +extern struct addrinfo *str2addrinfo(const char *address, const char *service, int socktype); +extern sockaddr_t str2sockaddr(const char *address, const char *port); +extern void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr); +extern char *sockaddr2hostname(const sockaddr_t *sa); +extern int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b); +extern int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b); +extern void sockaddrunmap(sockaddr_t *sa); +extern void sockaddrfree(sockaddr_t *sa); +extern void sockaddrcpy(sockaddr_t *dest, const sockaddr_t *src); +extern void sockaddr_setport(sockaddr_t *sa, const char *port); +extern int maskcmp(const void *a, const void *b, int masklen); +extern void maskcpy(void *dest, const void *src, int masklen, int len); +extern void mask(void *mask, int masklen, int len); +extern bool maskcheck(const void *mask, int masklen, int len); -#endif /* __TINC_NETUTL_H__ */ +#endif diff --git a/src/node.c b/src/node.c index aab83ca..03be21c 100644 --- a/src/node.c +++ b/src/node.c @@ -1,6 +1,6 @@ /* node.c -- node tree management - Copyright (C) 2001-2013 Guus Sliepen , + Copyright (C) 2001-2016 Guus Sliepen , 2001-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -20,18 +20,16 @@ #include "system.h" -#include "control_common.h" -#include "hash.h" +#include "avl_tree.h" #include "logger.h" #include "net.h" #include "netutl.h" #include "node.h" -#include "splay_tree.h" #include "utils.h" #include "xalloc.h" -splay_tree_t *node_tree; -static hash_t *node_udp_cache; +avl_tree_t *node_tree; /* Known nodes, sorted by name */ +avl_tree_t *node_udp_tree; /* Known nodes, sorted by address and port */ node_t *myself; @@ -39,22 +37,36 @@ static int node_compare(const node_t *a, const node_t *b) { return strcmp(a->name, b->name); } +static int node_udp_compare(const node_t *a, const node_t *b) { + return sockaddrcmp(&a->address, &b->address); +} + void init_nodes(void) { - node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node); - node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t)); + node_tree = avl_alloc_tree((avl_compare_t) node_compare, (avl_action_t) free_node); + node_udp_tree = avl_alloc_tree((avl_compare_t) node_udp_compare, NULL); } void exit_nodes(void) { - hash_free(node_udp_cache); - splay_delete_tree(node_tree); + avl_delete_tree(node_udp_tree); + avl_delete_tree(node_tree); } node_t *new_node(void) { - node_t *n = xzalloc(sizeof *n); + node_t *n = xmalloc_and_zero(sizeof(*n)); + + if(replaywin) { + n->late = xmalloc_and_zero(replaywin); + } - if(replaywin) n->late = xzalloc(replaywin); n->subnet_tree = new_subnet_tree(); n->edge_tree = new_edge_tree(); + n->inctx = EVP_CIPHER_CTX_new(); + n->outctx = EVP_CIPHER_CTX_new(); + + if(!n->inctx || !n->outctx) { + abort(); + } + n->mtu = MTU; n->maxmtu = MTU; @@ -62,101 +74,126 @@ node_t *new_node(void) { } void free_node(node_t *n) { - if(n->subnet_tree) - free_subnet_tree(n->subnet_tree); + if(n->inkey) { + free(n->inkey); + } - if(n->edge_tree) + if(n->outkey) { + free(n->outkey); + } + + if(n->subnet_tree) { + free_subnet_tree(n->subnet_tree); + } + + if(n->edge_tree) { free_edge_tree(n->edge_tree); + } sockaddrfree(&n->address); - cipher_close(n->incipher); - digest_close(n->indigest); - cipher_close(n->outcipher); - digest_close(n->outdigest); + EVP_CIPHER_CTX_free(n->outctx); + EVP_CIPHER_CTX_free(n->inctx); - ecdsa_free(n->ecdsa); - sptps_stop(&n->sptps); + if(n->mtuevent) { + event_del(n->mtuevent); + } - timeout_del(&n->mtutimeout); - - if(n->hostname) + if(n->hostname) { free(n->hostname); + } - if(n->name) + if(n->name) { free(n->name); + } - if(n->late) + if(n->late) { free(n->late); + } free(n); } void node_add(node_t *n) { - splay_insert(node_tree, n); + avl_insert(node_tree, n); } void node_del(node_t *n) { - for splay_each(subnet_t, s, n->subnet_tree) + avl_node_t *node, *next; + edge_t *e; + subnet_t *s; + + for(node = n->subnet_tree->head; node; node = next) { + next = node->next; + s = node->data; subnet_del(n, s); + } - for splay_each(edge_t, e, n->edge_tree) + for(node = n->edge_tree->head; node; node = next) { + next = node->next; + e = node->data; edge_del(e); + } - splay_delete(node_tree, n); + avl_delete(node_udp_tree, n); + avl_delete(node_tree, n); } node_t *lookup_node(char *name) { - node_t n = {NULL}; + node_t n = {0}; n.name = name; - return splay_search(node_tree, &n); + return avl_search(node_tree, &n); } node_t *lookup_node_udp(const sockaddr_t *sa) { - return hash_search(node_udp_cache, sa); + node_t n = {0}; + + n.address = *sa; + n.name = NULL; + + return avl_search(node_udp_tree, &n); } void update_node_udp(node_t *n, const sockaddr_t *sa) { if(n == myself) { - logger(DEBUG_ALWAYS, LOG_WARNING, "Trying to update UDP address of myself!"); + logger(LOG_WARNING, "Trying to update UDP address of myself!"); return; } - hash_insert(node_udp_cache, &n->address, NULL); + avl_delete(node_udp_tree, n); + + if(n->hostname) { + free(n->hostname); + } if(sa) { n->address = *sa; - n->sock = 0; - for(int i = 0; i < listen_sockets; i++) { - if(listen_socket[i].sa.sa.sa_family == sa->sa.sa_family) { - n->sock = i; - break; - } - } - hash_insert(node_udp_cache, sa, n); - free(n->hostname); n->hostname = sockaddr2hostname(&n->address); - logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); + avl_insert(node_udp_tree, n); + ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); + } else { + memset(&n->address, 0, sizeof(n->address)); + n->hostname = NULL; + ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s cleared", n->name); } } -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); +void dump_nodes(void) { + avl_node_t *node; + node_t *n; - 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); + logger(LOG_DEBUG, "Nodes:"); + + for(node = node_tree->head; node; node = node->next) { + n = node->data; + logger(LOG_DEBUG, " %s at %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s pmtu %d (min %d max %d)", + n->name, n->hostname, n->outcipher ? EVP_CIPHER_nid(n->outcipher) : 0, + n->outdigest ? EVP_MD_type(n->outdigest) : 0, n->outmaclength, n->outcompression, + n->options, bitfield_to_int(&n->status, sizeof(n->status)), n->nexthop ? n->nexthop->name : "-", + n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu); + } + + logger(LOG_DEBUG, "End of nodes."); } diff --git a/src/node.h b/src/node.h index e704ba8..b360fe5 100644 --- a/src/node.h +++ b/src/node.h @@ -1,6 +1,9 @@ +#ifndef TINC_NODE_H +#define TINC_NODE_H + /* node.h -- header for node.c - Copyright (C) 2001-2013 Guus Sliepen , + Copyright (C) 2001-2016 Guus Sliepen , 2001-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -18,26 +21,19 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_NODE_H__ -#define __TINC_NODE_H__ - -#include "splay_tree.h" -#include "cipher.h" +#include "avl_tree.h" #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) */ - unsigned int validkey:1; /* 1 if we currently have a valid key for him */ - unsigned int waitingforkey:1; /* 1 if we already sent out a request */ - unsigned int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ - unsigned int reachable:1; /* 1 if this node is reachable in the graph */ - unsigned int indirect:1; /* 1 if this node is not directly reachable by us */ - unsigned int sptps:1; /* 1 if this node supports SPTPS */ - unsigned int udp_confirmed:1; /* 1 if the address is one that we received UDP traffic on */ - unsigned int unused:24; + unsigned int unused_active: 1; /* 1 if active (not used for nodes) */ + unsigned int validkey: 1; /* 1 if we currently have a valid key for him */ + unsigned int unused_waitingforkey: 1; /* 1 if we already sent out a request */ + unsigned int visited: 1; /* 1 if this node has been visited by one of the graph algorithms */ + unsigned int reachable: 1; /* 1 if this node is reachable in the graph */ + unsigned int indirect: 1; /* 1 if this node is not directly reachable by us */ + unsigned int unused: 26; } node_status_t; typedef struct node_t { @@ -49,70 +45,62 @@ typedef struct node_t { char *hostname; /* the hostname of its real ip */ node_status_t status; - time_t last_state_change; time_t last_req_key; - ecdsa_t *ecdsa; /* His public ECDSA key */ - sptps_t sptps; + const EVP_CIPHER *incipher; /* Cipher type for UDP packets received from him */ + char *inkey; /* Cipher key and iv */ + int inkeylength; /* Cipher key and iv length */ + EVP_CIPHER_CTX *inctx; /* Cipher context */ - cipher_t *incipher; /* Cipher for UDP packets */ - digest_t *indigest; /* Digest for UDP packets */ + const EVP_CIPHER *outcipher; /* Cipher type for UDP packets sent to him*/ + char *outkey; /* Cipher key and iv */ + int outkeylength; /* Cipher key and iv length */ + EVP_CIPHER_CTX *outctx; /* Cipher context */ - cipher_t *outcipher; /* Cipher for UDP packets */ - digest_t *outdigest; /* Digest for UDP packets */ + const EVP_MD *indigest; /* Digest type for MAC of packets received from him */ + int inmaclength; /* Length of MAC */ + + const EVP_MD *outdigest; /* Digest type for MAC of packets sent to him*/ + int outmaclength; /* Length of MAC */ int incompression; /* Compressionlevel, 0 = no compression */ int outcompression; /* Compressionlevel, 0 = no compression */ - int distance; struct node_t *nexthop; /* nearest node from us to him */ 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 */ + avl_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 */ + avl_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) */ uint32_t sent_seqno; /* Sequence number last sent to this node */ uint32_t received_seqno; /* Sequence number last received from this node */ - uint32_t received; /* Total valid packets received from this node */ - uint32_t prev_received_seqno; - uint32_t prev_received; uint32_t farfuture; /* Packets in a row that have arrived from the far future */ - unsigned char* late; /* Bitfield marking late packets */ + unsigned char *late; /* Bitfield marking late packets */ length_t mtu; /* Maximum size of packets to send to this node */ length_t minmtu; /* Probed minimum MTU */ length_t maxmtu; /* Probed maximum MTU */ int mtuprobes; /* Number of probes */ - timeout_t mtutimeout; /* Probe event */ - struct timeval probe_time; /* Time the last probe was sent or received */ - int probe_counter; /* Number of probes received since last burst was sent */ - float rtt; /* Last measured round trip time */ - float bandwidth; /* Last measured bandwidth */ - float packetloss; /* Last measured packet loss rate */ - - uint64_t in_packets; - uint64_t in_bytes; - uint64_t out_packets; - uint64_t out_bytes; + event_t *mtuevent; /* Probe event */ } node_t; extern struct node_t *myself; -extern splay_tree_t *node_tree; +extern avl_tree_t *node_tree; +extern avl_tree_t *node_udp_tree; extern void init_nodes(void); extern void exit_nodes(void); -extern node_t *new_node(void) __attribute__ ((__malloc__)); -extern void free_node(node_t *); -extern void node_add(node_t *); -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 *); +extern node_t *new_node(void) __attribute__((__malloc__)); +extern void free_node(node_t *n); +extern void node_add(node_t *n); +extern void node_del(node_t *n); +extern node_t *lookup_node(char *name); +extern node_t *lookup_node_udp(const sockaddr_t *sa); +extern void update_node_udp(node_t *n, const sockaddr_t *sa); +extern void dump_nodes(void); -#endif /* __TINC_NODE_H__ */ +#endif diff --git a/src/openssl/.deps/.dirstamp b/src/openssl/.deps/.dirstamp deleted file mode 100644 index e69de29..0000000 diff --git a/src/openssl/.deps/cipher.Po b/src/openssl/.deps/cipher.Po deleted file mode 100644 index 05e8926..0000000 --- a/src/openssl/.deps/cipher.Po +++ /dev/null @@ -1,454 +0,0 @@ -openssl/cipher.o: openssl/cipher.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h /usr/include/openssl/rand.h \ - /usr/include/openssl/ossl_typ.h /usr/include/openssl/e_os2.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/err.h /usr/include/openssl/bio.h \ - /usr/include/openssl/crypto.h /usr/include/openssl/stack.h \ - /usr/include/openssl/safestack.h /usr/include/openssl/opensslv.h \ - /usr/include/openssl/symhacks.h /usr/include/openssl/lhash.h \ - /usr/include/openssl/evp.h /usr/include/openssl/objects.h \ - /usr/include/openssl/obj_mac.h /usr/include/openssl/asn1.h \ - /usr/include/openssl/bn.h openssl/../cipher.h openssl/../logger.h \ - openssl/../xalloc.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -/usr/include/openssl/rand.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/err.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/lhash.h: - -/usr/include/openssl/evp.h: - -/usr/include/openssl/objects.h: - -/usr/include/openssl/obj_mac.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -openssl/../cipher.h: - -openssl/../logger.h: - -openssl/../xalloc.h: diff --git a/src/openssl/.deps/crypto.Po b/src/openssl/.deps/crypto.Po deleted file mode 100644 index 7175d88..0000000 --- a/src/openssl/.deps/crypto.Po +++ /dev/null @@ -1,482 +0,0 @@ -openssl/crypto.o: openssl/crypto.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h /usr/include/openssl/rand.h \ - /usr/include/openssl/ossl_typ.h /usr/include/openssl/e_os2.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/evp.h /usr/include/openssl/symhacks.h \ - /usr/include/openssl/bio.h /usr/include/openssl/crypto.h \ - /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \ - /usr/include/openssl/opensslv.h /usr/include/openssl/objects.h \ - /usr/include/openssl/obj_mac.h /usr/include/openssl/asn1.h \ - /usr/include/openssl/bn.h /usr/include/openssl/engine.h \ - /usr/include/openssl/rsa.h /usr/include/openssl/dsa.h \ - /usr/include/openssl/dh.h /usr/include/openssl/ecdh.h \ - /usr/include/openssl/ec.h /usr/include/openssl/ecdsa.h \ - /usr/include/openssl/ui.h /usr/include/openssl/err.h \ - /usr/include/openssl/lhash.h /usr/include/openssl/x509.h \ - /usr/include/openssl/buffer.h /usr/include/openssl/sha.h \ - /usr/include/openssl/x509_vfy.h /usr/include/openssl/pkcs7.h \ - openssl/../crypto.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -/usr/include/openssl/rand.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/evp.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/objects.h: - -/usr/include/openssl/obj_mac.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -/usr/include/openssl/engine.h: - -/usr/include/openssl/rsa.h: - -/usr/include/openssl/dsa.h: - -/usr/include/openssl/dh.h: - -/usr/include/openssl/ecdh.h: - -/usr/include/openssl/ec.h: - -/usr/include/openssl/ecdsa.h: - -/usr/include/openssl/ui.h: - -/usr/include/openssl/err.h: - -/usr/include/openssl/lhash.h: - -/usr/include/openssl/x509.h: - -/usr/include/openssl/buffer.h: - -/usr/include/openssl/sha.h: - -/usr/include/openssl/x509_vfy.h: - -/usr/include/openssl/pkcs7.h: - -openssl/../crypto.h: diff --git a/src/openssl/.deps/digest.Po b/src/openssl/.deps/digest.Po deleted file mode 100644 index 6d30f41..0000000 --- a/src/openssl/.deps/digest.Po +++ /dev/null @@ -1,458 +0,0 @@ -openssl/digest.o: openssl/digest.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h openssl/../utils.h openssl/../xalloc.h \ - /usr/include/openssl/err.h /usr/include/openssl/e_os2.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/ossl_typ.h /usr/include/openssl/bio.h \ - /usr/include/openssl/crypto.h /usr/include/openssl/stack.h \ - /usr/include/openssl/safestack.h /usr/include/openssl/opensslv.h \ - /usr/include/openssl/symhacks.h /usr/include/openssl/lhash.h \ - /usr/include/openssl/hmac.h /usr/include/openssl/evp.h \ - /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h \ - /usr/include/openssl/asn1.h /usr/include/openssl/bn.h openssl/digest.h \ - openssl/../digest.h openssl/../logger.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -openssl/../utils.h: - -openssl/../xalloc.h: - -/usr/include/openssl/err.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/lhash.h: - -/usr/include/openssl/hmac.h: - -/usr/include/openssl/evp.h: - -/usr/include/openssl/objects.h: - -/usr/include/openssl/obj_mac.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -openssl/digest.h: - -openssl/../digest.h: - -openssl/../logger.h: diff --git a/src/openssl/.deps/ecdh.Po b/src/openssl/.deps/ecdh.Po deleted file mode 100644 index 96dcd00..0000000 --- a/src/openssl/.deps/ecdh.Po +++ /dev/null @@ -1,454 +0,0 @@ -openssl/ecdh.o: openssl/ecdh.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h /usr/include/openssl/err.h \ - /usr/include/openssl/e_os2.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/ossl_typ.h /usr/include/openssl/bio.h \ - /usr/include/openssl/crypto.h /usr/include/openssl/stack.h \ - /usr/include/openssl/safestack.h /usr/include/openssl/opensslv.h \ - /usr/include/openssl/symhacks.h /usr/include/openssl/lhash.h \ - /usr/include/openssl/ec.h /usr/include/openssl/asn1.h \ - /usr/include/openssl/bn.h /usr/include/openssl/ecdh.h \ - /usr/include/openssl/obj_mac.h openssl/../ecdh.h openssl/../logger.h \ - openssl/../utils.h openssl/../xalloc.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -/usr/include/openssl/err.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/lhash.h: - -/usr/include/openssl/ec.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -/usr/include/openssl/ecdh.h: - -/usr/include/openssl/obj_mac.h: - -openssl/../ecdh.h: - -openssl/../logger.h: - -openssl/../utils.h: - -openssl/../xalloc.h: diff --git a/src/openssl/.deps/ecdsa.Po b/src/openssl/.deps/ecdsa.Po deleted file mode 100644 index f6e3f65..0000000 --- a/src/openssl/.deps/ecdsa.Po +++ /dev/null @@ -1,487 +0,0 @@ -openssl/ecdsa.o: openssl/ecdsa.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h /usr/include/openssl/pem.h \ - /usr/include/openssl/e_os2.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/bio.h /usr/include/openssl/crypto.h \ - /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \ - /usr/include/openssl/opensslv.h /usr/include/openssl/ossl_typ.h \ - /usr/include/openssl/symhacks.h /usr/include/openssl/evp.h \ - /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h \ - /usr/include/openssl/asn1.h /usr/include/openssl/bn.h \ - /usr/include/openssl/x509.h /usr/include/openssl/buffer.h \ - /usr/include/openssl/ec.h /usr/include/openssl/ecdsa.h \ - /usr/include/openssl/ecdh.h /usr/include/openssl/rsa.h \ - /usr/include/openssl/dsa.h /usr/include/openssl/dh.h \ - /usr/include/openssl/sha.h /usr/include/openssl/x509_vfy.h \ - /usr/include/openssl/lhash.h /usr/include/openssl/pkcs7.h \ - /usr/include/openssl/pem2.h /usr/include/openssl/err.h \ - openssl/../logger.h openssl/../ecdsa.h openssl/../utils.h \ - openssl/../xalloc.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -/usr/include/openssl/pem.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/evp.h: - -/usr/include/openssl/objects.h: - -/usr/include/openssl/obj_mac.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -/usr/include/openssl/x509.h: - -/usr/include/openssl/buffer.h: - -/usr/include/openssl/ec.h: - -/usr/include/openssl/ecdsa.h: - -/usr/include/openssl/ecdh.h: - -/usr/include/openssl/rsa.h: - -/usr/include/openssl/dsa.h: - -/usr/include/openssl/dh.h: - -/usr/include/openssl/sha.h: - -/usr/include/openssl/x509_vfy.h: - -/usr/include/openssl/lhash.h: - -/usr/include/openssl/pkcs7.h: - -/usr/include/openssl/pem2.h: - -/usr/include/openssl/err.h: - -openssl/../logger.h: - -openssl/../ecdsa.h: - -openssl/../utils.h: - -openssl/../xalloc.h: diff --git a/src/openssl/.deps/ecdsagen.Po b/src/openssl/.deps/ecdsagen.Po deleted file mode 100644 index 51e34f5..0000000 --- a/src/openssl/.deps/ecdsagen.Po +++ /dev/null @@ -1,487 +0,0 @@ -openssl/ecdsagen.o: openssl/ecdsagen.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h /usr/include/openssl/pem.h \ - /usr/include/openssl/e_os2.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/bio.h /usr/include/openssl/crypto.h \ - /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \ - /usr/include/openssl/opensslv.h /usr/include/openssl/ossl_typ.h \ - /usr/include/openssl/symhacks.h /usr/include/openssl/evp.h \ - /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h \ - /usr/include/openssl/asn1.h /usr/include/openssl/bn.h \ - /usr/include/openssl/x509.h /usr/include/openssl/buffer.h \ - /usr/include/openssl/ec.h /usr/include/openssl/ecdsa.h \ - /usr/include/openssl/ecdh.h /usr/include/openssl/rsa.h \ - /usr/include/openssl/dsa.h /usr/include/openssl/dh.h \ - /usr/include/openssl/sha.h /usr/include/openssl/x509_vfy.h \ - /usr/include/openssl/lhash.h /usr/include/openssl/pkcs7.h \ - /usr/include/openssl/pem2.h /usr/include/openssl/err.h \ - openssl/../ecdsagen.h openssl/../ecdsa.h openssl/../utils.h \ - openssl/../xalloc.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -/usr/include/openssl/pem.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/evp.h: - -/usr/include/openssl/objects.h: - -/usr/include/openssl/obj_mac.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -/usr/include/openssl/x509.h: - -/usr/include/openssl/buffer.h: - -/usr/include/openssl/ec.h: - -/usr/include/openssl/ecdsa.h: - -/usr/include/openssl/ecdh.h: - -/usr/include/openssl/rsa.h: - -/usr/include/openssl/dsa.h: - -/usr/include/openssl/dh.h: - -/usr/include/openssl/sha.h: - -/usr/include/openssl/x509_vfy.h: - -/usr/include/openssl/lhash.h: - -/usr/include/openssl/pkcs7.h: - -/usr/include/openssl/pem2.h: - -/usr/include/openssl/err.h: - -openssl/../ecdsagen.h: - -openssl/../ecdsa.h: - -openssl/../utils.h: - -openssl/../xalloc.h: diff --git a/src/openssl/.deps/prf.Po b/src/openssl/.deps/prf.Po deleted file mode 100644 index aa2ae6d..0000000 --- a/src/openssl/.deps/prf.Po +++ /dev/null @@ -1,446 +0,0 @@ -openssl/prf.o: openssl/prf.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h /usr/include/openssl/obj_mac.h \ - openssl/digest.h /usr/include/openssl/evp.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/ossl_typ.h /usr/include/openssl/e_os2.h \ - /usr/include/openssl/symhacks.h /usr/include/openssl/bio.h \ - /usr/include/openssl/crypto.h /usr/include/openssl/stack.h \ - /usr/include/openssl/safestack.h /usr/include/openssl/opensslv.h \ - /usr/include/openssl/objects.h /usr/include/openssl/asn1.h \ - /usr/include/openssl/bn.h openssl/../digest.h openssl/../prf.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -/usr/include/openssl/obj_mac.h: - -openssl/digest.h: - -/usr/include/openssl/evp.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/objects.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -openssl/../digest.h: - -openssl/../prf.h: diff --git a/src/openssl/.deps/rsa.Po b/src/openssl/.deps/rsa.Po deleted file mode 100644 index c3ac6ac..0000000 --- a/src/openssl/.deps/rsa.Po +++ /dev/null @@ -1,482 +0,0 @@ -openssl/rsa.o: openssl/rsa.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h /usr/include/openssl/pem.h \ - /usr/include/openssl/e_os2.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/bio.h /usr/include/openssl/crypto.h \ - /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \ - /usr/include/openssl/opensslv.h /usr/include/openssl/ossl_typ.h \ - /usr/include/openssl/symhacks.h /usr/include/openssl/evp.h \ - /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h \ - /usr/include/openssl/asn1.h /usr/include/openssl/bn.h \ - /usr/include/openssl/x509.h /usr/include/openssl/buffer.h \ - /usr/include/openssl/ec.h /usr/include/openssl/ecdsa.h \ - /usr/include/openssl/ecdh.h /usr/include/openssl/rsa.h \ - /usr/include/openssl/dsa.h /usr/include/openssl/dh.h \ - /usr/include/openssl/sha.h /usr/include/openssl/x509_vfy.h \ - /usr/include/openssl/lhash.h /usr/include/openssl/pkcs7.h \ - /usr/include/openssl/pem2.h /usr/include/openssl/err.h \ - openssl/../logger.h openssl/../rsa.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -/usr/include/openssl/pem.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/evp.h: - -/usr/include/openssl/objects.h: - -/usr/include/openssl/obj_mac.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -/usr/include/openssl/x509.h: - -/usr/include/openssl/buffer.h: - -/usr/include/openssl/ec.h: - -/usr/include/openssl/ecdsa.h: - -/usr/include/openssl/ecdh.h: - -/usr/include/openssl/rsa.h: - -/usr/include/openssl/dsa.h: - -/usr/include/openssl/dh.h: - -/usr/include/openssl/sha.h: - -/usr/include/openssl/x509_vfy.h: - -/usr/include/openssl/lhash.h: - -/usr/include/openssl/pkcs7.h: - -/usr/include/openssl/pem2.h: - -/usr/include/openssl/err.h: - -openssl/../logger.h: - -openssl/../rsa.h: diff --git a/src/openssl/.deps/rsagen.Po b/src/openssl/.deps/rsagen.Po deleted file mode 100644 index 8c50bea..0000000 --- a/src/openssl/.deps/rsagen.Po +++ /dev/null @@ -1,484 +0,0 @@ -openssl/rsagen.o: openssl/rsagen.c /usr/include/stdc-predef.h \ - /usr/include/x86_64-linux-gnu/bits/predefs.h openssl/../system.h \ - openssl/../../config.h openssl/../have.h /usr/include/stdio.h \ - /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ - /usr/include/x86_64-linux-gnu/bits/wordsize.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs.h \ - /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h \ - /usr/include/x86_64-linux-gnu/bits/types.h \ - /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h \ - /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ - /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ - /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/include/stdlib.h \ - /usr/include/x86_64-linux-gnu/bits/waitflags.h \ - /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ - /usr/include/x86_64-linux-gnu/bits/endian.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap.h \ - /usr/include/x86_64-linux-gnu/bits/byteswap-16.h /usr/include/xlocale.h \ - /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ - /usr/include/x86_64-linux-gnu/sys/select.h \ - /usr/include/x86_64-linux-gnu/bits/select.h \ - /usr/include/x86_64-linux-gnu/bits/sigset.h \ - /usr/include/x86_64-linux-gnu/bits/time.h \ - /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ - /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ - /usr/include/x86_64-linux-gnu/bits/stdlib-float.h /usr/include/string.h \ - /usr/include/x86_64-linux-gnu/bits/string.h \ - /usr/include/x86_64-linux-gnu/bits/string2.h /usr/include/ctype.h \ - /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ - /usr/include/x86_64-linux-gnu/bits/siginfo.h \ - /usr/include/x86_64-linux-gnu/bits/sigaction.h \ - /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigstack.h \ - /usr/include/x86_64-linux-gnu/sys/ucontext.h \ - /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ - /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ - /usr/include/x86_64-linux-gnu/asm/errno.h \ - /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ - /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ - /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h \ - /usr/include/x86_64-linux-gnu/bits/uio.h \ - /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/unistd.h \ - /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ - /usr/include/x86_64-linux-gnu/bits/environments.h \ - /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h \ - /usr/include/inttypes.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h /usr/include/stdint.h \ - /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/syslog.h \ - /usr/include/x86_64-linux-gnu/sys/syslog.h \ - /usr/include/x86_64-linux-gnu/bits/syslog-path.h \ - /usr/include/x86_64-linux-gnu/sys/time.h \ - /usr/include/x86_64-linux-gnu/bits/timex.h \ - /usr/include/x86_64-linux-gnu/sys/stat.h \ - /usr/include/x86_64-linux-gnu/sys/file.h \ - /usr/include/x86_64-linux-gnu/sys/wait.h \ - /usr/include/x86_64-linux-gnu/sys/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctls.h \ - /usr/include/x86_64-linux-gnu/asm/ioctls.h \ - /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ - /usr/include/x86_64-linux-gnu/asm/ioctl.h \ - /usr/include/asm-generic/ioctl.h \ - /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ - /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ - /usr/include/x86_64-linux-gnu/sys/param.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h \ - /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h \ - /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ - /usr/include/x86_64-linux-gnu/bits/local_lim.h \ - /usr/include/linux/limits.h \ - /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ - /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ - /usr/include/x86_64-linux-gnu/bits/param.h /usr/include/linux/param.h \ - /usr/include/x86_64-linux-gnu/asm/param.h \ - /usr/include/asm-generic/param.h \ - /usr/include/x86_64-linux-gnu/sys/resource.h \ - /usr/include/x86_64-linux-gnu/bits/resource.h \ - /usr/include/x86_64-linux-gnu/sys/uio.h \ - /usr/include/x86_64-linux-gnu/sys/un.h \ - /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/dirent.h \ - /usr/include/x86_64-linux-gnu/bits/dirent.h /usr/include/netdb.h \ - /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket.h \ - /usr/include/x86_64-linux-gnu/bits/socket_type.h \ - /usr/include/x86_64-linux-gnu/asm/socket.h \ - /usr/include/asm-generic/socket.h \ - /usr/include/x86_64-linux-gnu/asm/sockios.h \ - /usr/include/asm-generic/sockios.h \ - /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ - /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/net/if.h \ - /usr/include/netinet/in_systm.h /usr/include/arpa/inet.h \ - /usr/include/netinet/ip.h /usr/include/netinet/tcp.h \ - /usr/include/netinet/ip6.h /usr/include/net/ethernet.h \ - /usr/include/linux/if_ether.h /usr/include/linux/types.h \ - /usr/include/x86_64-linux-gnu/asm/types.h \ - /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ - /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ - /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ - /usr/include/linux/stddef.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types.h \ - /usr/include/x86_64-linux-gnu/asm/posix_types_64.h \ - /usr/include/asm-generic/posix_types.h /usr/include/net/if_arp.h \ - /usr/include/netinet/ip_icmp.h /usr/include/netinet/icmp6.h \ - /usr/include/netinet/if_ether.h openssl/../dropin.h \ - openssl/../fake-getaddrinfo.h openssl/../fake-gai-errnos.h \ - openssl/../fake-getnameinfo.h /usr/include/openssl/pem.h \ - /usr/include/openssl/e_os2.h \ - /usr/include/x86_64-linux-gnu/openssl/opensslconf.h \ - /usr/include/openssl/bio.h /usr/include/openssl/crypto.h \ - /usr/include/openssl/stack.h /usr/include/openssl/safestack.h \ - /usr/include/openssl/opensslv.h /usr/include/openssl/ossl_typ.h \ - /usr/include/openssl/symhacks.h /usr/include/openssl/evp.h \ - /usr/include/openssl/objects.h /usr/include/openssl/obj_mac.h \ - /usr/include/openssl/asn1.h /usr/include/openssl/bn.h \ - /usr/include/openssl/x509.h /usr/include/openssl/buffer.h \ - /usr/include/openssl/ec.h /usr/include/openssl/ecdsa.h \ - /usr/include/openssl/ecdh.h /usr/include/openssl/rsa.h \ - /usr/include/openssl/dsa.h /usr/include/openssl/dh.h \ - /usr/include/openssl/sha.h /usr/include/openssl/x509_vfy.h \ - /usr/include/openssl/lhash.h /usr/include/openssl/pkcs7.h \ - /usr/include/openssl/pem2.h /usr/include/openssl/err.h \ - openssl/../logger.h openssl/../rsagen.h openssl/../rsa.h - -/usr/include/stdc-predef.h: - -/usr/include/x86_64-linux-gnu/bits/predefs.h: - -openssl/../system.h: - -openssl/../../config.h: - -openssl/../have.h: - -/usr/include/stdio.h: - -/usr/include/features.h: - -/usr/include/x86_64-linux-gnu/sys/cdefs.h: - -/usr/include/x86_64-linux-gnu/bits/wordsize.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs.h: - -/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stddef.h: - -/usr/include/x86_64-linux-gnu/bits/types.h: - -/usr/include/x86_64-linux-gnu/bits/typesizes.h: - -/usr/include/libio.h: - -/usr/include/_G_config.h: - -/usr/include/wchar.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h: - -/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: - -/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: - -/usr/include/x86_64-linux-gnu/bits/stdio.h: - -/usr/include/stdlib.h: - -/usr/include/x86_64-linux-gnu/bits/waitflags.h: - -/usr/include/x86_64-linux-gnu/bits/waitstatus.h: - -/usr/include/endian.h: - -/usr/include/x86_64-linux-gnu/bits/endian.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap.h: - -/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: - -/usr/include/xlocale.h: - -/usr/include/x86_64-linux-gnu/sys/types.h: - -/usr/include/time.h: - -/usr/include/x86_64-linux-gnu/sys/select.h: - -/usr/include/x86_64-linux-gnu/bits/select.h: - -/usr/include/x86_64-linux-gnu/bits/sigset.h: - -/usr/include/x86_64-linux-gnu/bits/time.h: - -/usr/include/x86_64-linux-gnu/sys/sysmacros.h: - -/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: - -/usr/include/alloca.h: - -/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: - -/usr/include/string.h: - -/usr/include/x86_64-linux-gnu/bits/string.h: - -/usr/include/x86_64-linux-gnu/bits/string2.h: - -/usr/include/ctype.h: - -/usr/include/signal.h: - -/usr/include/x86_64-linux-gnu/bits/signum.h: - -/usr/include/x86_64-linux-gnu/bits/siginfo.h: - -/usr/include/x86_64-linux-gnu/bits/sigaction.h: - -/usr/include/x86_64-linux-gnu/bits/sigcontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigstack.h: - -/usr/include/x86_64-linux-gnu/sys/ucontext.h: - -/usr/include/x86_64-linux-gnu/bits/sigthread.h: - -/usr/include/errno.h: - -/usr/include/x86_64-linux-gnu/bits/errno.h: - -/usr/include/linux/errno.h: - -/usr/include/x86_64-linux-gnu/asm/errno.h: - -/usr/include/asm-generic/errno.h: - -/usr/include/asm-generic/errno-base.h: - -/usr/include/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl.h: - -/usr/include/x86_64-linux-gnu/bits/fcntl-linux.h: - -/usr/include/x86_64-linux-gnu/bits/uio.h: - -/usr/include/x86_64-linux-gnu/bits/stat.h: - -/usr/include/unistd.h: - -/usr/include/x86_64-linux-gnu/bits/posix_opt.h: - -/usr/include/x86_64-linux-gnu/bits/environments.h: - -/usr/include/x86_64-linux-gnu/bits/confname.h: - -/usr/include/getopt.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdbool.h: - -/usr/include/inttypes.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h: - -/usr/include/stdint.h: - -/usr/include/x86_64-linux-gnu/bits/wchar.h: - -/usr/include/syslog.h: - -/usr/include/x86_64-linux-gnu/sys/syslog.h: - -/usr/include/x86_64-linux-gnu/bits/syslog-path.h: - -/usr/include/x86_64-linux-gnu/sys/time.h: - -/usr/include/x86_64-linux-gnu/bits/timex.h: - -/usr/include/x86_64-linux-gnu/sys/stat.h: - -/usr/include/x86_64-linux-gnu/sys/file.h: - -/usr/include/x86_64-linux-gnu/sys/wait.h: - -/usr/include/x86_64-linux-gnu/sys/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctls.h: - -/usr/include/x86_64-linux-gnu/asm/ioctls.h: - -/usr/include/asm-generic/ioctls.h: - -/usr/include/linux/ioctl.h: - -/usr/include/x86_64-linux-gnu/asm/ioctl.h: - -/usr/include/asm-generic/ioctl.h: - -/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: - -/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: - -/usr/include/x86_64-linux-gnu/sys/param.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/limits.h: - -/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed/syslimits.h: - -/usr/include/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: - -/usr/include/x86_64-linux-gnu/bits/local_lim.h: - -/usr/include/linux/limits.h: - -/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: - -/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: - -/usr/include/x86_64-linux-gnu/bits/param.h: - -/usr/include/linux/param.h: - -/usr/include/x86_64-linux-gnu/asm/param.h: - -/usr/include/asm-generic/param.h: - -/usr/include/x86_64-linux-gnu/sys/resource.h: - -/usr/include/x86_64-linux-gnu/bits/resource.h: - -/usr/include/x86_64-linux-gnu/sys/uio.h: - -/usr/include/x86_64-linux-gnu/sys/un.h: - -/usr/include/x86_64-linux-gnu/bits/sockaddr.h: - -/usr/include/dirent.h: - -/usr/include/x86_64-linux-gnu/bits/dirent.h: - -/usr/include/netdb.h: - -/usr/include/netinet/in.h: - -/usr/include/x86_64-linux-gnu/sys/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket.h: - -/usr/include/x86_64-linux-gnu/bits/socket_type.h: - -/usr/include/x86_64-linux-gnu/asm/socket.h: - -/usr/include/asm-generic/socket.h: - -/usr/include/x86_64-linux-gnu/asm/sockios.h: - -/usr/include/asm-generic/sockios.h: - -/usr/include/x86_64-linux-gnu/bits/in.h: - -/usr/include/rpc/netdb.h: - -/usr/include/x86_64-linux-gnu/bits/netdb.h: - -/usr/include/net/if.h: - -/usr/include/netinet/in_systm.h: - -/usr/include/arpa/inet.h: - -/usr/include/netinet/ip.h: - -/usr/include/netinet/tcp.h: - -/usr/include/netinet/ip6.h: - -/usr/include/net/ethernet.h: - -/usr/include/linux/if_ether.h: - -/usr/include/linux/types.h: - -/usr/include/x86_64-linux-gnu/asm/types.h: - -/usr/include/asm-generic/types.h: - -/usr/include/asm-generic/int-ll64.h: - -/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: - -/usr/include/asm-generic/bitsperlong.h: - -/usr/include/linux/posix_types.h: - -/usr/include/linux/stddef.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types.h: - -/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: - -/usr/include/asm-generic/posix_types.h: - -/usr/include/net/if_arp.h: - -/usr/include/netinet/ip_icmp.h: - -/usr/include/netinet/icmp6.h: - -/usr/include/netinet/if_ether.h: - -openssl/../dropin.h: - -openssl/../fake-getaddrinfo.h: - -openssl/../fake-gai-errnos.h: - -openssl/../fake-getnameinfo.h: - -/usr/include/openssl/pem.h: - -/usr/include/openssl/e_os2.h: - -/usr/include/x86_64-linux-gnu/openssl/opensslconf.h: - -/usr/include/openssl/bio.h: - -/usr/include/openssl/crypto.h: - -/usr/include/openssl/stack.h: - -/usr/include/openssl/safestack.h: - -/usr/include/openssl/opensslv.h: - -/usr/include/openssl/ossl_typ.h: - -/usr/include/openssl/symhacks.h: - -/usr/include/openssl/evp.h: - -/usr/include/openssl/objects.h: - -/usr/include/openssl/obj_mac.h: - -/usr/include/openssl/asn1.h: - -/usr/include/openssl/bn.h: - -/usr/include/openssl/x509.h: - -/usr/include/openssl/buffer.h: - -/usr/include/openssl/ec.h: - -/usr/include/openssl/ecdsa.h: - -/usr/include/openssl/ecdh.h: - -/usr/include/openssl/rsa.h: - -/usr/include/openssl/dsa.h: - -/usr/include/openssl/dh.h: - -/usr/include/openssl/sha.h: - -/usr/include/openssl/x509_vfy.h: - -/usr/include/openssl/lhash.h: - -/usr/include/openssl/pkcs7.h: - -/usr/include/openssl/pem2.h: - -/usr/include/openssl/err.h: - -openssl/../logger.h: - -openssl/../rsagen.h: - -openssl/../rsa.h: diff --git a/src/openssl/.dirstamp b/src/openssl/.dirstamp deleted file mode 100644 index e69de29..0000000 diff --git a/src/openssl/cipher.c b/src/openssl/cipher.c deleted file mode 100644 index c0307f8..0000000 --- a/src/openssl/cipher.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - cipher.c -- Symmetric block cipher handling - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include -#include - -#include "../cipher.h" -#include "../logger.h" -#include "../xalloc.h" - -struct cipher { - EVP_CIPHER_CTX ctx; - const EVP_CIPHER *cipher; - struct cipher_counter *counter; -}; - -typedef struct cipher_counter { - unsigned char counter[CIPHER_MAX_IV_SIZE]; - unsigned char block[CIPHER_MAX_IV_SIZE]; - int n; -} cipher_counter_t; - -static cipher_t *cipher_open(const EVP_CIPHER *evp_cipher) { - cipher_t *cipher = xzalloc(sizeof *cipher); - cipher->cipher = evp_cipher; - EVP_CIPHER_CTX_init(&cipher->ctx); - - return cipher; -} - -cipher_t *cipher_open_by_name(const char *name) { - const EVP_CIPHER *evp_cipher = EVP_get_cipherbyname(name); - if(!evp_cipher) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher name '%s'!", name); - return NULL; - } - - return cipher_open(evp_cipher); -} - -cipher_t *cipher_open_by_nid(int nid) { - const EVP_CIPHER *evp_cipher = EVP_get_cipherbynid(nid); - if(!evp_cipher) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher nid %d!", nid); - return NULL; - } - - return cipher_open(evp_cipher); -} - -cipher_t *cipher_open_blowfish_ofb(void) { - return cipher_open(EVP_bf_ofb()); -} - -void cipher_close(cipher_t *cipher) { - if(!cipher) - return; - - EVP_CIPHER_CTX_cleanup(&cipher->ctx); - free(cipher->counter); - free(cipher); -} - -size_t cipher_keylength(const cipher_t *cipher) { - if(!cipher || !cipher->cipher) - return 0; - - return cipher->cipher->key_len + cipher->cipher->block_size; -} - -bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) { - bool result; - - if(encrypt) - result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + cipher->cipher->key_len); - else - result = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + cipher->cipher->key_len); - - if(result) - return true; - - logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool cipher_set_key_from_rsa(cipher_t *cipher, void *key, size_t len, bool encrypt) { - bool result; - - if(encrypt) - result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - cipher->cipher->key_len, (unsigned char *)key + len - cipher->cipher->iv_len - cipher->cipher->key_len); - else - result = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - cipher->cipher->key_len, (unsigned char *)key + len - cipher->cipher->iv_len - cipher->cipher->key_len); - - if(result) - return true; - - logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool cipher_set_counter(cipher_t *cipher, const void *counter, size_t len) { - if(len > cipher->cipher->block_size - 4) { - logger(DEBUG_ALWAYS, LOG_ERR, "Counter too long"); - abort(); - } - - memcpy(cipher->counter->counter + cipher->cipher->block_size - len, counter, len); - memset(cipher->counter->counter, 0, 4); - cipher->counter->n = 0; - - return true; -} - -bool cipher_set_counter_key(cipher_t *cipher, void *key) { - int result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, NULL); - if(!result) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while setting key: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - if(!cipher->counter) - cipher->counter = xzalloc(sizeof *cipher->counter); - else - cipher->counter->n = 0; - - memcpy(cipher->counter->counter, (unsigned char *)key + cipher->cipher->key_len, cipher->cipher->block_size); - - return true; -} - -bool cipher_counter_xor(cipher_t *cipher, const void *indata, size_t inlen, void *outdata) { - if(!cipher->counter) { - logger(DEBUG_ALWAYS, LOG_ERR, "Counter not initialized"); - return false; - } - - const unsigned char *in = indata; - unsigned char *out = outdata; - - while(inlen--) { - // Encrypt the new counter value if we need it - if(!cipher->counter->n) { - int len; - if(!EVP_EncryptUpdate(&cipher->ctx, cipher->counter->block, &len, cipher->counter->counter, cipher->cipher->block_size)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - // Increase the counter value - for(int i = 0; i < cipher->cipher->block_size; i++) - if(++cipher->counter->counter[i]) - break; - } - - *out++ = *in++ ^ cipher->counter->counter[cipher->counter->n++]; - - if(cipher->counter->n >= cipher->cipher->block_size) - cipher->counter->n = 0; - } - - return true; -} - - -bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) { - if(oneshot) { - int len, pad; - if(EVP_EncryptInit_ex(&cipher->ctx, NULL, NULL, NULL, NULL) - && EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, indata, inlen) - && EVP_EncryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) { - if(outlen) *outlen = len + pad; - return true; - } - } else { - int len; - if(EVP_EncryptUpdate(&cipher->ctx, outdata, &len, indata, inlen)) { - if(outlen) *outlen = len; - return true; - } - } - - logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) { - if(oneshot) { - int len, pad; - if(EVP_DecryptInit_ex(&cipher->ctx, NULL, NULL, NULL, NULL) - && EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, indata, inlen) - && EVP_DecryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) { - if(outlen) *outlen = len + pad; - return true; - } - } else { - int len; - if(EVP_EncryptUpdate(&cipher->ctx, outdata, &len, indata, inlen)) { - if(outlen) *outlen = len; - return true; - } - } - - logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -int cipher_get_nid(const cipher_t *cipher) { - if(!cipher || !cipher->cipher) - return 0; - - return cipher->cipher->nid; -} - -bool cipher_active(const cipher_t *cipher) { - return cipher && cipher->cipher && cipher->cipher->nid != 0; -} diff --git a/src/openssl/cipher.o b/src/openssl/cipher.o deleted file mode 100644 index 3831ed8..0000000 Binary files a/src/openssl/cipher.o and /dev/null differ diff --git a/src/openssl/crypto.c b/src/openssl/crypto.c deleted file mode 100644 index 6c5cbc8..0000000 --- a/src/openssl/crypto.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - crypto.c -- Cryptographic miscellaneous functions and initialisation - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include -#include - -#include "../crypto.h" - -void crypto_init(void) { - RAND_load_file("/dev/urandom", 1024); - - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); - - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - - if(!RAND_status()) { - fprintf(stderr, "Not enough entropy for the PRNG!\n"); - abort(); - } -} - -void crypto_exit(void) { - EVP_cleanup(); -} - -void randomize(void *out, size_t outlen) { - RAND_pseudo_bytes(out, outlen); -} diff --git a/src/openssl/crypto.o b/src/openssl/crypto.o deleted file mode 100644 index cad569b..0000000 Binary files a/src/openssl/crypto.o and /dev/null differ diff --git a/src/openssl/digest.c b/src/openssl/digest.c deleted file mode 100644 index 0e600b9..0000000 --- a/src/openssl/digest.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - digest.c -- Digest handling - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" -#include "../utils.h" -#include "../xalloc.h" - -#include -#include - -#include "digest.h" -#include "../digest.h" -#include "../logger.h" - -static digest_t *digest_open(const EVP_MD *evp_md, int maclength) { - digest_t *digest = xzalloc(sizeof *digest); - digest->digest = evp_md; - - int digestlen = EVP_MD_size(digest->digest); - - if(maclength > digestlen || maclength < 0) - digest->maclength = digestlen; - else - digest->maclength = maclength; - - return digest; -} - -digest_t *digest_open_by_name(const char *name, int maclength) { - const EVP_MD *evp_md = EVP_get_digestbyname(name); - - if(!evp_md) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest name '%s'!", name); - return false; - } - - return digest_open(evp_md, maclength); -} - -digest_t *digest_open_by_nid(int nid, int maclength) { - const EVP_MD *evp_md = EVP_get_digestbynid(nid); - - if(!evp_md) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest nid %d!", nid); - return false; - } - - return digest_open(evp_md, maclength); -} - -digest_t *digest_open_sha1(int maclength) { - return digest_open(EVP_sha1(), maclength); -} - -bool digest_set_key(digest_t *digest, const void *key, size_t len) { - digest->key = xrealloc(digest->key, len); - memcpy(digest->key, key, len); - digest->keylength = len; - return true; -} - -void digest_close(digest_t *digest) { - if(!digest) - return; - - free(digest->key); - free(digest); -} - -bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) { - size_t len = EVP_MD_size(digest->digest); - unsigned char tmpdata[len]; - - if(digest->key) { - if(!HMAC(digest->digest, digest->key, digest->keylength, indata, inlen, tmpdata, NULL)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - } else { - EVP_MD_CTX ctx; - - if(!EVP_DigestInit(&ctx, digest->digest) - || !EVP_DigestUpdate(&ctx, indata, inlen) - || !EVP_DigestFinal(&ctx, tmpdata, NULL)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - } - - memcpy(outdata, tmpdata, digest->maclength); - return true; -} - -bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *cmpdata) { - size_t len = digest->maclength; - unsigned char outdata[len]; - - return digest_create(digest, indata, inlen, outdata) && !memcmp(cmpdata, outdata, digest->maclength); -} - -int digest_get_nid(const digest_t *digest) { - if(!digest || !digest->digest) - return 0; - - return digest->digest->type; -} - -size_t digest_keylength(const digest_t *digest) { - if(!digest || !digest->digest) - return 0; - - return digest->digest->md_size; -} - -size_t digest_length(const digest_t *digest) { - if(!digest) - return 0; - - return digest->maclength; -} - -bool digest_active(const digest_t *digest) { - return digest && digest->digest && digest->digest->type != 0; -} diff --git a/src/openssl/digest.h b/src/openssl/digest.h deleted file mode 100644 index 0a32707..0000000 --- a/src/openssl/digest.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - digest.h -- header file digest.c - Copyright (C) 2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_OPENSSL_DIGEST_H__ -#define __TINC_OPENSSL_DIGEST_H__ - -#include - -struct digest { - const EVP_MD *digest; - int maclength; - int keylength; - char *key; -}; - -#endif diff --git a/src/openssl/digest.o b/src/openssl/digest.o deleted file mode 100644 index 64e8d0d..0000000 Binary files a/src/openssl/digest.o and /dev/null differ diff --git a/src/openssl/ecdh.c b/src/openssl/ecdh.c deleted file mode 100644 index d997007..0000000 --- a/src/openssl/ecdh.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - ecdh.c -- Diffie-Hellman key exchange handling - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include -#include -#include - -#define __TINC_ECDH_INTERNAL__ -typedef EC_KEY ecdh_t; - -#include "../ecdh.h" -#include "../logger.h" -#include "../utils.h" -#include "../xalloc.h" - -ecdh_t *ecdh_generate_public(void *pubkey) { - ecdh_t *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1); - if(!ecdh) { - logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - if(!EC_KEY_generate_key(ecdh)) { - EC_KEY_free(ecdh); - logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - const EC_POINT *point = EC_KEY_get0_public_key(ecdh); - if(!point) { - EC_KEY_free(ecdh); - logger(DEBUG_ALWAYS, LOG_ERR, "Getting public key failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - size_t result = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL); - if(!result) { - EC_KEY_free(ecdh); - logger(DEBUG_ALWAYS, LOG_ERR, "Converting EC_POINT to binary failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - return ecdh; -} - -bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) { - EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(ecdh)); - if(!point) { - logger(DEBUG_ALWAYS, LOG_ERR, "EC_POINT_new() failed: %s", ERR_error_string(ERR_get_error(), NULL)); - EC_KEY_free(ecdh); - return false; - } - - int result = EC_POINT_oct2point(EC_KEY_get0_group(ecdh), point, pubkey, ECDH_SIZE, NULL); - if(!result) { - EC_POINT_free(point); - EC_KEY_free(ecdh); - logger(DEBUG_ALWAYS, LOG_ERR, "Converting binary to EC_POINT failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - result = ECDH_compute_key(shared, ECDH_SIZE, point, ecdh, NULL); - EC_POINT_free(point); - EC_KEY_free(ecdh); - - if(!result) { - logger(DEBUG_ALWAYS, LOG_ERR, "Computing Elliptic Curve Diffie-Hellman shared key failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - return true; -} - -void ecdh_free(ecdh_t *ecdh) { - if(ecdh) - EC_KEY_free(ecdh); -} diff --git a/src/openssl/ecdh.o b/src/openssl/ecdh.o deleted file mode 100644 index f7188b8..0000000 Binary files a/src/openssl/ecdh.o and /dev/null differ diff --git a/src/openssl/ecdsa.c b/src/openssl/ecdsa.c deleted file mode 100644 index bca89fc..0000000 --- a/src/openssl/ecdsa.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - ecdsa.c -- ECDSA key handling - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include - -#define __TINC_ECDSA_INTERNAL__ -typedef EC_KEY ecdsa_t; - -#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) { - ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1); - if(!ecdsa) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "EC_KEY_new_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - int len = strlen(p); - unsigned char pubkey[len / 4 * 3 + 3]; - const unsigned char *ppubkey = pubkey; - len = b64decode(p, (char *)pubkey, len); - - if(!o2i_ECPublicKey(&ecdsa, &ppubkey, len)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "o2i_ECPublicKey failed: %s", ERR_error_string(ERR_get_error(), NULL)); - EC_KEY_free(ecdsa); - return NULL; - } - - return ecdsa; -} - -char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) { - unsigned char *pubkey = NULL; - int len = i2o_ECPublicKey(ecdsa, &pubkey); - - char *base64 = xmalloc(len * 4 / 3 + 5); - b64encode((char *)pubkey, base64, len); - - free(pubkey); - - return base64; -} - -// Read PEM ECDSA keys - -ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) { - ecdsa_t *ecdsa = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL); - - if(!ecdsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA public key: %s", ERR_error_string(ERR_get_error(), NULL)); - - return ecdsa; -} - -ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) { - ecdsa_t *ecdsa = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL); - - if(!ecdsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA private key: %s", ERR_error_string(ERR_get_error(), NULL)); - - return ecdsa; -} - -size_t ecdsa_size(ecdsa_t *ecdsa) { - return ECDSA_size(ecdsa); -} - -// TODO: standardise output format? - -bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) { - unsigned int siglen = ECDSA_size(ecdsa); - - unsigned char hash[SHA512_DIGEST_LENGTH]; - SHA512(in, len, hash); - - memset(sig, 0, siglen); - - if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, ecdsa)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_sign() failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - return true; -} - -bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) { - unsigned int siglen = ECDSA_size(ecdsa); - - unsigned char hash[SHA512_DIGEST_LENGTH]; - SHA512(in, len, hash); - - if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, ecdsa)) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_verify() failed: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; - } - - return true; -} - -bool ecdsa_active(ecdsa_t *ecdsa) { - return ecdsa; -} - -void ecdsa_free(ecdsa_t *ecdsa) { - if(ecdsa) - EC_KEY_free(ecdsa); -} diff --git a/src/openssl/ecdsa.o b/src/openssl/ecdsa.o deleted file mode 100644 index bbdc905..0000000 Binary files a/src/openssl/ecdsa.o and /dev/null differ diff --git a/src/openssl/ecdsagen.c b/src/openssl/ecdsagen.c deleted file mode 100644 index 31e5847..0000000 --- a/src/openssl/ecdsagen.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - ecdsagen.c -- ECDSA key generation and export - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include -#include - -#define __TINC_ECDSA_INTERNAL__ -typedef EC_KEY ecdsa_t; - -#include "../ecdsagen.h" -#include "../utils.h" -#include "../xalloc.h" - -// Generate ECDSA key - -ecdsa_t *ecdsa_generate(void) { - ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1); - - if(!ecdsa || !EC_KEY_generate_key(ecdsa)) { - fprintf(stderr, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL)); - ecdsa_free(ecdsa); - return false; - } - - EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE); - EC_KEY_set_conv_form(ecdsa, POINT_CONVERSION_COMPRESSED); - - return ecdsa; -} - -// Write PEM ECDSA keys - -bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) { - BIO *out = BIO_new(BIO_s_file()); - if(!out) - return false; - BIO_set_fp(out, fp, BIO_NOCLOSE); - bool result = PEM_write_bio_EC_PUBKEY(out, ecdsa); - BIO_free(out); - return result; -} - -bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) { - BIO *out = BIO_new(BIO_s_file()); - if(!out) - return false; - BIO_set_fp(out, fp, BIO_NOCLOSE); - bool result = PEM_write_bio_ECPrivateKey(out, ecdsa, NULL, NULL, 0, NULL, NULL); - BIO_free(out); - return result; -} diff --git a/src/openssl/ecdsagen.o b/src/openssl/ecdsagen.o deleted file mode 100644 index ce79180..0000000 Binary files a/src/openssl/ecdsagen.o and /dev/null differ diff --git a/src/openssl/prf.c b/src/openssl/prf.c deleted file mode 100644 index 4f5a52b..0000000 --- a/src/openssl/prf.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - prf.c -- Pseudo-Random Function for key material generation - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include - -#include "digest.h" -#include "../digest.h" -#include "../prf.h" - -/* Generate key material from a master secret and a seed, based on RFC 4346 section 5. - We use SHA512 instead of MD5 and SHA1. - */ - -static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, ssize_t outlen) { - digest_t *digest = digest_open_by_nid(nid, -1); - - if(!digest) - return false; - - if(!digest_set_key(digest, secret, secretlen)) { - digest_close(digest); - return false; - } - - size_t len = digest_length(digest); - - /* Data is what the "inner" HMAC function processes. - It consists of the previous HMAC result plus the seed. - */ - - char data[len + seedlen]; - memset(data, 0, len); - memcpy(data + len, seed, seedlen); - - char hash[len]; - - while(outlen > 0) { - /* Inner HMAC */ - if(!digest_create(digest, data, len + seedlen, data)) { - digest_close(digest); - return false; - } - - /* Outer HMAC */ - if(!digest_create(digest, data, len + seedlen, hash)) { - digest_close(digest); - return false; - } - - /* XOR the results of the outer HMAC into the out buffer */ - for(int i = 0; i < len && i < outlen; i++) - *out++ ^= hash[i]; - - outlen -= len; - } - - digest_close(digest); - return true; -} - -bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) { - /* This construction allows us to easily switch back to a scheme where the PRF is calculated using two different digest algorithms. */ - memset(out, 0, outlen); - - return prf_xor(NID_sha512, secret, secretlen, seed, seedlen, out, outlen); -} diff --git a/src/openssl/prf.o b/src/openssl/prf.o deleted file mode 100644 index 10ca7c7..0000000 Binary files a/src/openssl/prf.o and /dev/null differ diff --git a/src/openssl/rsa.c b/src/openssl/rsa.c deleted file mode 100644 index 20bfb65..0000000 --- a/src/openssl/rsa.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - rsa.c -- RSA key handling - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include - -#define __TINC_RSA_INTERNAL__ -typedef RSA rsa_t; - -#include "../logger.h" -#include "../rsa.h" - -// Set RSA keys - -rsa_t *rsa_set_hex_public_key(char *n, char *e) { - rsa_t *rsa = RSA_new(); - if(!rsa) - return NULL; - - if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e)) { - RSA_free(rsa); - return false; - } - - return rsa; -} - -rsa_t *rsa_set_hex_private_key(char *n, char *e, char *d) { - rsa_t *rsa = RSA_new(); - if(!rsa) - return NULL; - - if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e) || BN_hex2bn(&rsa->d, d) != strlen(d)) { - RSA_free(rsa); - return false; - } - - return rsa; -} - -// Read PEM RSA keys - -rsa_t *rsa_read_pem_public_key(FILE *fp) { - rsa_t *rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); - - if(!rsa) - rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); - - if(!rsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL)); - - return rsa; -} - -rsa_t *rsa_read_pem_private_key(FILE *fp) { - rsa_t *rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); - - if(!rsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", ERR_error_string(ERR_get_error(), NULL)); - - return rsa; -} - -size_t rsa_size(rsa_t *rsa) { - return RSA_size(rsa); -} - -bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) { - if(RSA_public_encrypt(len, in, out, rsa, RSA_NO_PADDING) == len) - return true; - - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA encryption: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) { - if(RSA_private_decrypt(len, in, out, rsa, RSA_NO_PADDING) == len) - return true; - - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA decryption: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool rsa_active(rsa_t *rsa) { - return rsa; -} - -void rsa_free(rsa_t *rsa) { - if(rsa) - RSA_free(rsa); -} diff --git a/src/openssl/rsa.o b/src/openssl/rsa.o deleted file mode 100644 index 9a12d0c..0000000 Binary files a/src/openssl/rsa.o and /dev/null differ diff --git a/src/openssl/rsagen.c b/src/openssl/rsagen.c deleted file mode 100644 index 3a8c8ad..0000000 --- a/src/openssl/rsagen.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - rsagen.c -- RSA key generation and export - Copyright (C) 2008-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include - -#define __TINC_RSA_INTERNAL__ -typedef RSA rsa_t; - -#include "../logger.h" -#include "../rsagen.h" - -/* This function prettyprints the key generation process */ - -static void indicator(int a, int b, void *p) { - switch (a) { - case 0: - fprintf(stderr, "."); - break; - - case 1: - fprintf(stderr, "+"); - break; - - case 2: - fprintf(stderr, "-"); - break; - - case 3: - switch (b) { - case 0: - fprintf(stderr, " p\n"); - break; - - case 1: - fprintf(stderr, " q\n"); - break; - - default: - fprintf(stderr, "?"); - } - break; - - default: - fprintf(stderr, "?"); - } -} - -// Generate RSA key - -rsa_t *rsa_generate(size_t bits, unsigned long exponent) { - return RSA_generate_key(bits, exponent, indicator, NULL); -} - -// Write PEM RSA keys - -bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) { - return PEM_write_RSAPublicKey(fp, rsa); -} - -bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) { - return PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL); -} diff --git a/src/openssl/rsagen.o b/src/openssl/rsagen.o deleted file mode 100644 index 4d1c766..0000000 Binary files a/src/openssl/rsagen.o and /dev/null differ diff --git a/src/pidfile.c b/src/pidfile.c new file mode 100644 index 0000000..dd17267 --- /dev/null +++ b/src/pidfile.c @@ -0,0 +1,142 @@ +/* + pidfile.c - interact with pidfiles + Copyright (c) 1995 Martin Schulze + + This file is part of the sysklogd package, a kernel and system log daemon. + + 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. +*/ + +/* left unaltered for tinc -- Ivo Timmermans */ +/* + * Sat Aug 19 13:24:33 MET DST 1995: Martin Schulze + * First version (v0.2) released + */ + +#include "system.h" + +#include "pidfile.h" + +#ifndef HAVE_MINGW +/* read_pid + * + * Reads the specified pidfile and returns the read pid. + * 0 is returned if either there's no pidfile, it's empty + * or no pid can be read. + */ +pid_t read_pid(const char *pidfile) { + FILE *f; + long pid; + + if(!(f = fopen(pidfile, "r"))) { + return 0; + } + + if(fscanf(f, "%20ld", &pid) != 1) { + pid = 0; + } + + fclose(f); + return (pid_t)pid; +} + +/* check_pid + * + * Reads the pid using read_pid and looks up the pid in the process + * table (using /proc) to determine if the process already exists. If + * so the pid is returned, otherwise 0. + */ +pid_t check_pid(const char *pidfile) { + pid_t pid = read_pid(pidfile); + + /* Amazing ! _I_ am already holding the pid file... */ + if((!pid) || (pid == getpid())) { + return 0; + } + + /* + * The 'standard' method of doing this is to try and do a 'fake' kill + * of the process. If an ESRCH error is returned the process cannot + * be found -- GW + */ + /* But... errno is usually changed only on error.. */ + errno = 0; + + if(kill(pid, 0) && errno == ESRCH) { + return 0; + } + + return pid; +} + +/* write_pid + * + * Writes the pid to the specified file. If that fails 0 is + * returned, otherwise the pid. + */ +pid_t write_pid(const char *pidfile) { + FILE *f; + int fd; + pid_t pid; + + if((fd = open(pidfile, O_RDWR | O_CREAT, 0644)) == -1) { + return 0; + } + + if((f = fdopen(fd, "r+")) == NULL) { + close(fd); + return 0; + } + +#ifdef HAVE_FLOCK + + if(flock(fd, LOCK_EX | LOCK_NB) == -1) { + fclose(f); + return 0; + } + +#endif + + pid = getpid(); + + if(!fprintf(f, "%ld\n", (long)pid)) { + fclose(f); + return 0; + } + + fflush(f); + +#ifdef HAVE_FLOCK + + if(flock(fd, LOCK_UN) == -1) { + fclose(f); + return 0; + } + +#endif + fclose(f); + + return pid; +} + +/* remove_pid + * + * Remove the the specified file. The result from unlink(2) + * is returned + */ +int remove_pid(const char *pidfile) { + return unlink(pidfile); +} +#endif diff --git a/src/pidfile.h b/src/pidfile.h new file mode 100644 index 0000000..7d71cc2 --- /dev/null +++ b/src/pidfile.h @@ -0,0 +1,57 @@ +#ifndef TINC_PIDFILE_H +#define TINC_PIDFILE_H + +/* + pidfile.h - interact with pidfiles + Copyright (c) 1995 Martin Schulze + + This file is part of the sysklogd package, a kernel and system log daemon. + + 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 HAVE_MINGW +/* read_pid + * + * Reads the specified pidfile and returns the read pid. + * 0 is returned if either there's no pidfile, it's empty + * or no pid can be read. + */ +extern pid_t read_pid(const char *pidfile); + +/* check_pid + * + * Reads the pid using read_pid and looks up the pid in the process + * table (using /proc) to determine if the process already exists. If + * so 1 is returned, otherwise 0. + */ +extern pid_t check_pid(const char *pidfile); + +/* write_pid + * + * Writes the pid to the specified file. If that fails 0 is + * returned, otherwise the pid. + */ +extern pid_t write_pid(const char *pidfile); + +/* remove_pid + * + * Remove the the specified file. The result from unlink(2) + * is returned + */ +extern int remove_pid(const char *pidfile); +#endif + +#endif diff --git a/src/prf.h b/src/prf.h deleted file mode 100644 index ef4b99b..0000000 --- a/src/prf.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - prf.h -- header file for prf.c - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_PRF_H__ -#define __TINC_PRF_H__ - -extern bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) __attribute__ ((__warn_unused_result__)); - -#endif diff --git a/src/process.c b/src/process.c index cbb190a..13d1007 100644 --- a/src/process.c +++ b/src/process.c @@ -1,7 +1,7 @@ /* process.c -- process management functions Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2015 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,14 +22,12 @@ #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 "pidfile.h" #include "process.h" #include "subnet.h" #include "utils.h" @@ -37,101 +35,162 @@ /* If zero, don't detach from the terminal. */ bool do_detach = true; +bool sighup = false; bool sigalrm = false; +extern char *identname; +extern char *pidfilename; extern char **g_argv; extern bool use_logfile; +#ifndef HAVE_MINGW +static sigset_t emptysigset; +#endif + /* Some functions the less gifted operating systems might lack... */ #ifdef HAVE_MINGW +extern char *identname; +extern char *program_name; +extern char **g_argv; + 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) { +bool install_service(void) { char command[4096] = "\""; + char **argp; + bool space; 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())); + logger(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)); + GetCurrentDirectory(sizeof(command) - 1, command + 1); + strncat(command, "\\", sizeof(command) - strlen(command)); } - strncat(command, program_name, sizeof command - strlen(command)); + strncat(command, program_name, sizeof(command) - strlen(command)); - strncat(command, "\"", 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)); + for(argp = g_argv + 1; *argp; argp++) { + space = strchr(*argp, ' '); + strncat(command, " ", sizeof(command) - strlen(command)); - if(space) - strncat(command, "\"", sizeof command - strlen(command)); + if(space) { + strncat(command, "\"", sizeof(command) - strlen(command)); + } - strncat(command, *argp, sizeof command - strlen(command)); + strncat(command, *argp, sizeof(command) - strlen(command)); - if(space) - strncat(command, "\"", 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); + 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) + logger(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); + logger(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); + if(!StartService(service, 0, NULL)) { + logger(LOG_WARNING, "Could not start %s service: %s", identname, winerror(GetLastError())); + } else { + logger(LOG_INFO, "%s service started", identname); + } + + return true; +} + +bool remove_service(void) { + manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + if(!manager) { + logger(LOG_ERR, "Could not open service manager: %s", winerror(GetLastError())); + return false; + } + + service = OpenService(manager, identname, SERVICE_ALL_ACCESS); + + if(!service) { + logger(LOG_ERR, "Could not open %s service: %s", identname, winerror(GetLastError())); + return false; + } + + if(!ControlService(service, SERVICE_CONTROL_STOP, &status)) { + logger(LOG_ERR, "Could not stop %s service: %s", identname, winerror(GetLastError())); + } else { + logger(LOG_INFO, "%s service stopped", identname); + } + + if(!DeleteService(service)) { + logger(LOG_ERR, "Could not remove %s service: %s", identname, winerror(GetLastError())); + return false; + } + + logger(LOG_INFO, "%s service removed", 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; + case SERVICE_CONTROL_INTERROGATE: + SetServiceStatus(statushandle, &status); + return NO_ERROR; + + case SERVICE_CONTROL_STOP: + logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_STOP"); + break; + + case SERVICE_CONTROL_SHUTDOWN: + logger(LOG_NOTICE, "Got %s request", "SERVICE_CONTROL_SHUTDOWN"); + break; + + default: + logger(LOG_WARNING, "Got unexpected request %d", (int)request); + return ERROR_CALL_NOT_IMPLEMENTED; + } + + if(running) { + running = false; + status.dwWaitHint = 30000; + status.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(statushandle, &status); + return NO_ERROR; + } else { + status.dwWaitHint = 0; + status.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(statushandle, &status); + exit(1); } - event_exit(); - status.dwWaitHint = 30000; - status.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus(statushandle, &status); - return NO_ERROR; } -VOID WINAPI run_service(DWORD argc, LPTSTR* argv) { +VOID WINAPI run_service(DWORD argc, LPTSTR *argv) { extern int main2(int argc, char **argv); status.dwServiceType = SERVICE_WIN32; @@ -142,8 +201,8 @@ VOID WINAPI run_service(DWORD argc, LPTSTR* argv) { statushandle = RegisterServiceCtrlHandlerEx(identname, controlhandler, NULL); - if (!statushandle) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "RegisterServiceCtrlHandlerEx", winerror(GetLastError())); + if(!statushandle) { + logger(LOG_ERR, "System call `%s' failed: %s", "RegisterServiceCtrlHandlerEx", winerror(GetLastError())); } else { status.dwWaitHint = 30000; status.dwCurrentState = SERVICE_START_PENDING; @@ -172,9 +231,39 @@ bool init_service(void) { if(!StartServiceCtrlDispatcher(services)) { if(GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { return false; + } else { + logger(LOG_ERR, "System call `%s' failed: %s", "StartServiceCtrlDispatcher", winerror(GetLastError())); } - else - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "StartServiceCtrlDispatcher", winerror(GetLastError())); + } + + return true; +} +#endif + +#ifndef HAVE_MINGW +/* + check for an existing tinc for this net, and write pid to pidfile +*/ +static bool write_pidfile(void) { + pid_t pid; + + pid = check_pid(pidfilename); + + if(pid) { + if(netname) + fprintf(stderr, "A tincd is already running for net `%s' with pid %ld.\n", + netname, (long)pid); + else { + fprintf(stderr, "A tincd is already running with pid %ld.\n", (long)pid); + } + + return false; + } + + /* if it's locked, write-protected, or whatever */ + if(!write_pid(pidfilename)) { + fprintf(stderr, "Couldn't write pid file %s: %s\n", pidfilename, strerror(errno)); + return false; } return true; @@ -182,104 +271,408 @@ bool init_service(void) { #endif /* - Detach from current terminal + kill older tincd for this net +*/ +bool kill_other(int signal) { +#ifndef HAVE_MINGW + pid_t pid; + + pid = read_pid(pidfilename); + + if(!pid) { + if(netname) + fprintf(stderr, "No other tincd is running for net `%s'.\n", + netname); + else { + fprintf(stderr, "No other tincd is running.\n"); + } + + return false; + } + + errno = 0; /* No error, sometimes errno is only changed on error */ + + /* ESRCH is returned when no process with that pid is found */ + if(kill(pid, signal) && errno == ESRCH) { + if(netname) + fprintf(stderr, "The tincd for net `%s' is no longer running. ", + netname); + else { + fprintf(stderr, "The tincd is no longer running. "); + } + + fprintf(stderr, "Removing stale lock file.\n"); + remove_pid(pidfilename); + } + + return true; +#else + return remove_service(); +#endif +} + +/* + Detach from current terminal, write pidfile, kill parent */ bool detach(void) { + setup_signals(); + + /* First check if we can open a fresh new pidfile */ + #ifndef HAVE_MINGW - signal(SIGPIPE, SIG_IGN); - signal(SIGUSR1, SIG_IGN); - signal(SIGUSR2, SIG_IGN); - signal(SIGWINCH, SIG_IGN); + + if(!write_pidfile()) { + return false; + } + + /* If we succeeded in doing that, detach */ 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)); + fprintf(stderr, "Couldn't detach from terminal: %s", + strerror(errno)); return false; } + + /* Now UPDATE the pid in the pidfile, because we changed it... */ + + if(!write_pid(pidfilename)) { + fprintf(stderr, "Could not write pid file %s: %s\n", pidfilename, strerror(errno)); + return false; + } + #else - if(!statushandle) - exit(!install_service()); + + if(!statushandle) { + exit(install_service()); + } + #endif } - openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR)); + 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); + logger(LOG_NOTICE, "tincd %s starting, debug level %d", + VERSION, debug_level); return true; } +#ifdef HAVE_PUTENV +void unputenv(char *p) { + char *e = strchr(p, '='); + + if(!e) { + return; + } + + int len = e - p; +#ifndef HAVE_UNSETENV +#ifdef HAVE_MINGW + // Windows requires putenv("FOO=") to unset %FOO% + len++; +#endif +#endif + char var[len + 1]; + memcpy(var, p, len); + var[len] = 0; +#ifdef HAVE_UNSETENV + unsetenv(var); +#else + // We must keep what we putenv() around in memory. + // To do this without memory leaks, keep things in a list and reuse if possible. + static list_t list = {}; + + for(list_node_t *node = list.head; node; node = node->next) { + char *data = node->data; + + if(!strcmp(data, var)) { + putenv(data); + return; + } + } + + char *data = xstrdup(var); + list_insert_tail(&list, data); + putenv(data); +#endif +} +#else +void putenv(const char *p) {} +void unputenv(const char *p) {} +#endif + bool execute_script(const char *name, char **envp) { #ifdef HAVE_SYSTEM char *scriptname; - char *command; + char *interpreter = NULL; + config_t *cfg_interpreter; + int status, len, i; - xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension); + cfg_interpreter = lookup_config(config_tree, "ScriptsInterpreter"); +#ifndef HAVE_MINGW + len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name); +#else + + if(cfg_interpreter) { + len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name); + } else { + len = xasprintf(&scriptname, "\"%s/%s.bat\"", confbase, name); + } + +#endif + + if(len < 0) { + return false; + } + + scriptname[len - 1] = '\0'; /* First check if there is a script */ - - if(access(scriptname, F_OK)) { + if(access(scriptname + 1, F_OK)) { free(scriptname); return true; } - logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name); + // Custom scripts interpreter + if(get_config_string(cfg_interpreter, &interpreter)) { + // Force custom scripts interpreter allowing execution of scripts on android without execution flag (such as on /sdcard) + free(scriptname); + len = xasprintf(&scriptname, "%s \"%s/%s\"", interpreter, confbase, name); + free(interpreter); + + if(len < 0) { + return false; + } + } + + ifdebug(STATUS) logger(LOG_INFO, "Executing script %s", name); -#ifdef HAVE_PUTENV /* Set environment */ - for(int i = 0; envp[i]; i++) + for(i = 0; envp[i]; i++) { putenv(envp[i]); -#endif + } - if(scriptinterpreter) - xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname); - else - xasprintf(&command, "\"%s\"", scriptname); + scriptname[len - 1] = '\"'; + status = system(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); - } + for(i = 0; envp[i]; i++) { + unputenv(envp[i]); } if(status != -1) { #ifdef WEXITSTATUS - if(WIFEXITED(status)) { /* Child exited by itself */ + + 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)); + logger(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))); + } else if(WIFSIGNALED(status)) { /* Child was killed by a signal */ + logger(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); + } else { /* Something strange happened */ + logger(LOG_ERR, "Script %s terminated abnormally", name); return false; } + #endif } else { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno)); + logger(LOG_ERR, "System call `%s' failed: %s", "system", strerror(errno)); return false; } + #endif return true; } + + +/* + Signal handlers. +*/ + +#ifndef HAVE_MINGW +static RETSIGTYPE sigterm_handler(int a) { + (void)a; + logger(LOG_NOTICE, "Got %s signal", "TERM"); + + if(running) { + running = false; + } else { + exit(1); + } +} + +static RETSIGTYPE sigquit_handler(int a) { + (void)a; + logger(LOG_NOTICE, "Got %s signal", "QUIT"); + + if(running) { + running = false; + } else { + exit(1); + } +} + +static RETSIGTYPE fatal_signal_square(int a) { + logger(LOG_ERR, "Got another fatal signal %d (%s): not restarting.", a, + strsignal(a)); + exit(1); +} + +static RETSIGTYPE fatal_signal_handler(int a) { + struct sigaction act; + logger(LOG_ERR, "Got fatal signal %d (%s)", a, strsignal(a)); + + if(do_detach) { + logger(LOG_NOTICE, "Trying to re-execute in 5 seconds..."); + + act.sa_handler = fatal_signal_square; + act.sa_mask = emptysigset; + act.sa_flags = 0; + sigaction(SIGSEGV, &act, NULL); + + close_network_connections(); + sleep(5); + remove_pid(pidfilename); + execvp(g_argv[0], g_argv); + } else { + logger(LOG_NOTICE, "Not restarting."); + exit(1); + } +} + +static RETSIGTYPE sighup_handler(int a) { + (void)a; + logger(LOG_NOTICE, "Got %s signal", "HUP"); + sighup = true; +} + +static RETSIGTYPE sigint_handler(int a) { + (void)a; + static int saved_debug_level = -1; + + logger(LOG_NOTICE, "Got %s signal", "INT"); + + if(saved_debug_level != -1) { + logger(LOG_NOTICE, "Reverting to old debug level (%d)", + saved_debug_level); + debug_level = saved_debug_level; + saved_debug_level = -1; + } else { + logger(LOG_NOTICE, + "Temporarily setting debug level to 5. Kill me with SIGINT again to go back to level %d.", + debug_level); + saved_debug_level = debug_level; + debug_level = 5; + } +} + +static RETSIGTYPE sigalrm_handler(int a) { + (void)a; + logger(LOG_NOTICE, "Got %s signal", "ALRM"); + sigalrm = true; +} + +static RETSIGTYPE sigusr1_handler(int a) { + (void)a; + dump_connections(); +} + +static RETSIGTYPE sigusr2_handler(int a) { + (void)a; + devops.dump_stats(); + dump_nodes(); + dump_edges(); + dump_subnets(); +} + +static RETSIGTYPE sigwinch_handler(int a) { + (void)a; + do_purge = true; +} + +static RETSIGTYPE unexpected_signal_handler(int a) { + (void)a; + logger(LOG_WARNING, "Got unexpected signal %d (%s)", a, strsignal(a)); +} + +static RETSIGTYPE ignore_signal_handler(int a) { + (void)a; + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Ignored signal %d (%s)", a, strsignal(a)); +} + +static struct { + int signal; + void (*handler)(int); +} sighandlers[] = { + {SIGHUP, sighup_handler}, + {SIGTERM, sigterm_handler}, + {SIGQUIT, sigquit_handler}, + {SIGSEGV, fatal_signal_handler}, + {SIGBUS, fatal_signal_handler}, + {SIGILL, fatal_signal_handler}, + {SIGPIPE, ignore_signal_handler}, + {SIGINT, sigint_handler}, + {SIGUSR1, sigusr1_handler}, + {SIGUSR2, sigusr2_handler}, + {SIGCHLD, ignore_signal_handler}, + {SIGALRM, sigalrm_handler}, + {SIGWINCH, sigwinch_handler}, + {SIGABRT, SIG_DFL}, + {0, NULL} +}; +#endif + +void setup_signals(void) { +#ifndef HAVE_MINGW + int i; + struct sigaction act; + + sigemptyset(&emptysigset); + act.sa_handler = NULL; + act.sa_mask = emptysigset; + act.sa_flags = 0; + + /* Set a default signal handler for every signal, errors will be + ignored. */ + for(i = 1; i < NSIG; i++) { + if(!do_detach) { + act.sa_handler = SIG_DFL; + } else { + act.sa_handler = unexpected_signal_handler; + } + + sigaction(i, &act, NULL); + } + + /* If we didn't detach, allow coredumps */ + if(!do_detach) { + sighandlers[3].handler = SIG_DFL; + } + + /* Then, for each known signal that we want to catch, assign a + handler to the signal, with error checking this time. */ + for(i = 0; sighandlers[i].signal; i++) { + act.sa_handler = sighandlers[i].handler; + + if(sigaction(sighandlers[i].signal, &act, NULL) < 0) + fprintf(stderr, "Installing signal handler for signal %d (%s) failed: %s\n", + sighandlers[i].signal, strsignal(sighandlers[i].signal), + strerror(errno)); + } + +#endif +} diff --git a/src/process.h b/src/process.h index 0b296db..e775ac3 100644 --- a/src/process.h +++ b/src/process.h @@ -1,7 +1,10 @@ +#ifndef TINC_PROCESS_H +#define TINC_PROCESS_H + /* process.h -- header file for process.c Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2010 Guus Sliepen + 2000-2006 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,19 +21,17 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_PROCESS_H__ -#define __TINC_PROCESS_H__ - extern bool do_detach; +extern bool sighup; extern bool sigalrm; extern void setup_signals(void); -extern bool execute_script(const char *, char **); +extern bool execute_script(const char *name, char **envp); extern bool detach(void); -extern bool kill_other(int); +extern bool kill_other(int signal); #ifdef HAVE_MINGW extern bool init_service(void); #endif -#endif /* __TINC_PROCESS_H__ */ +#endif diff --git a/src/protocol.c b/src/protocol.c index 374c522..4f74d3b 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -1,7 +1,7 @@ /* protocol.c -- handle the meta-protocol, basic functions Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,38 +30,35 @@ bool tunnelserver = false; bool strictsubnets = false; -bool experimental = true; /* Jumptable for the request handlers */ -static bool (*request_handlers[])(connection_t *, const char *) = { - 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, - add_edge_h, del_edge_h, - key_changed_h, req_key_h, ans_key_h, tcppacket_h, control_h, +static bool (*request_handlers[])(connection_t *) = { + id_h, metakey_h, challenge_h, chal_reply_h, ack_h, + NULL, NULL, NULL, + ping_h, pong_h, + add_subnet_h, del_subnet_h, + add_edge_h, del_edge_h, + key_changed_h, req_key_h, ans_key_h, tcppacket_h, }; /* Request names */ static char (*request_name[]) = { - "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK", - "STATUS", "ERROR", "TERMREQ", - "PING", "PONG", - "ADD_SUBNET", "DEL_SUBNET", - "ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", "CONTROL", + "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK", + "STATUS", "ERROR", "TERMREQ", + "PING", "PONG", + "ADD_SUBNET", "DEL_SUBNET", + "ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", }; -static splay_tree_t *past_request_tree; +static avl_tree_t *past_request_tree; bool check_id(const char *id) { - if(!id || !*id) - return false; - for(; *id; id++) - if(!isalnum(*id) && *id != '_') + if(!isalnum(*id) && *id != '_') { return false; + } return true; } @@ -71,83 +68,104 @@ bool check_id(const char *id) { bool send_request(connection_t *c, const char *format, ...) { va_list args; - char request[MAXBUFSIZE]; - int len; + char buffer[MAXBUFSIZE]; + int len, request = 0; /* Use vsnprintf instead of vxasprintf: faster, no memory fragmentation, cleanup is automatic, and there is a limit on the input buffer anyway */ va_start(args, format); - len = vsnprintf(request, MAXBUFSIZE, format, args); + len = vsnprintf(buffer, sizeof(buffer), format, args); + buffer[sizeof(buffer) - 1] = 0; va_end(args); - if(len < 0 || len > MAXBUFSIZE - 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Output buffer overflow while sending request to %s (%s)", - c->name, c->hostname); + if(len < 0 || (size_t)len > sizeof(buffer) - 1) { + logger(LOG_ERR, "Output buffer overflow while sending request to %s (%s)", + c->name, c->hostname); return false; } - logger(DEBUG_META, LOG_DEBUG, "Sending %s to %s (%s): %s", request_name[atoi(request)], c->name, c->hostname, request); - - request[len++] = '\n'; - - if(c == everyone) { - broadcast_meta(NULL, request, len); - return true; - } else - return send_meta(c, request, len); -} - -void forward_request(connection_t *from, const char *request) { - logger(DEBUG_META, LOG_DEBUG, "Forwarding %s from %s (%s): %s", request_name[atoi(request)], from->name, from->hostname, request); - - // Create a temporary newline-terminated copy of the request - int len = strlen(request); - char tmp[len + 1]; - memcpy(tmp, request, len); - tmp[len] = '\n'; - broadcast_meta(from, tmp, sizeof tmp); -} - -bool receive_request(connection_t *c, const char *request) { - if(c->outgoing && proxytype == PROXY_HTTP && c->allow_request == ID) { - if(!request[0] || request[0] == '\r') - return true; - if(!strncasecmp(request, "HTTP/1.1 ", 9)) { - if(!strncmp(request + 9, "200", 3)) { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted"); - return true; - } else { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Proxy request rejected: %s", request + 9); - return false; - } - } + ifdebug(PROTOCOL) { + sscanf(buffer, "%d", &request); + ifdebug(META) + logger(LOG_DEBUG, "Sending %s to %s (%s): %s", + request_name[request], c->name, c->hostname, buffer); + else + logger(LOG_DEBUG, "Sending %s to %s (%s)", request_name[request], + c->name, c->hostname); } - int reqno = atoi(request); + buffer[len++] = '\n'; + + if(c == everyone) { + broadcast_meta(NULL, buffer, len); + return true; + } else { + return send_meta(c, buffer, len); + } +} + +void forward_request(connection_t *from) { + int request; + + ifdebug(PROTOCOL) { + sscanf(from->buffer, "%d", &request); + ifdebug(META) + logger(LOG_DEBUG, "Forwarding %s from %s (%s): %s", + request_name[request], from->name, from->hostname, + from->buffer); + else + logger(LOG_DEBUG, "Forwarding %s from %s (%s)", + request_name[request], from->name, from->hostname); + } + + from->buffer[from->reqlen - 1] = '\n'; + + broadcast_meta(from, from->buffer, from->reqlen); +} + +bool receive_request(connection_t *c) { + int request; + + if(sscanf(c->buffer, "%d", &request) == 1) { + if((request < 0) || (request >= LAST) || !request_handlers[request]) { + ifdebug(META) + logger(LOG_DEBUG, "Unknown request from %s (%s): %s", + c->name, c->hostname, c->buffer); + else + logger(LOG_ERR, "Unknown request from %s (%s)", + c->name, c->hostname); - if(reqno || *request == '0') { - if((reqno < 0) || (reqno >= LAST) || !request_handlers[reqno]) { - logger(DEBUG_META, LOG_DEBUG, "Unknown request from %s (%s): %s", c->name, c->hostname, request); return false; } else { - logger(DEBUG_META, LOG_DEBUG, "Got %s from %s (%s): %s", request_name[reqno], c->name, c->hostname, request); + ifdebug(PROTOCOL) { + ifdebug(META) + logger(LOG_DEBUG, "Got %s from %s (%s): %s", + request_name[request], c->name, c->hostname, + c->buffer); + else + logger(LOG_DEBUG, "Got %s from %s (%s)", + request_name[request], c->name, c->hostname); + } } - if((c->allow_request != ALL) && (c->allow_request != reqno)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unauthorized request from %s (%s)", c->name, c->hostname); + if((c->allow_request != ALL) && (c->allow_request != request)) { + logger(LOG_ERR, "Unauthorized request from %s (%s)", c->name, + c->hostname); return false; } - if(!request_handlers[reqno](c, request)) { + if(!request_handlers[request](c)) { /* Something went wrong. Probably scriptkiddies. Terminate. */ - logger(DEBUG_ALWAYS, LOG_ERR, "Error while processing %s from %s (%s)", request_name[reqno], c->name, c->hostname); + logger(LOG_ERR, "Error while processing %s from %s (%s)", + request_name[request], c->name, c->hostname); return false; } } else { - logger(DEBUG_ALWAYS, LOG_ERR, "Bogus data received from %s (%s)", c->name, c->hostname); + logger(LOG_ERR, "Bogus data received from %s (%s)", + c->name, c->hostname); return false; } @@ -159,55 +177,55 @@ static int past_request_compare(const past_request_t *a, const past_request_t *b } static void free_past_request(past_request_t *r) { - if(r->request) - free((char *)r->request); + if(r->request) { + free(r->request); + } free(r); } -static timeout_t past_request_timeout; - -static void age_past_requests(void *data) { - int left = 0, deleted = 0; - - for splay_each(past_request_t, p, past_request_tree) { - if(p->firstseen + pinginterval <= now.tv_sec) - splay_delete_node(past_request_tree, node), deleted++; - else - left++; - } - - if(left || deleted) - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Aging past requests: deleted %d, left %d", deleted, left); - - if(left) - timeout_set(&past_request_timeout, &(struct timeval){10, rand() % 100000}); +void init_requests(void) { + past_request_tree = avl_alloc_tree((avl_compare_t) past_request_compare, (avl_action_t) free_past_request); } -bool seen_request(const char *request) { - past_request_t *new, p = {NULL}; +void exit_requests(void) { + avl_delete_tree(past_request_tree); +} + +bool seen_request(char *request) { + past_request_t *new, p = {0}; p.request = request; - if(splay_search(past_request_tree, &p)) { - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Already seen request"); + if(avl_search(past_request_tree, &p)) { + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Already seen request"); return true; } else { - new = xmalloc(sizeof *new); + new = xmalloc(sizeof(*new)); new->request = xstrdup(request); - new->firstseen = now.tv_sec; - splay_insert(past_request_tree, new); - timeout_add(&past_request_timeout, age_past_requests, NULL, &(struct timeval){10, rand() % 100000}); + new->firstseen = now; + avl_insert(past_request_tree, new); return false; } } -void init_requests(void) { - past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request); -} +void age_past_requests(void) { + avl_node_t *node, *next; + past_request_t *p; + int left = 0, deleted = 0; -void exit_requests(void) { - splay_delete_tree(past_request_tree); + for(node = past_request_tree->head; node; node = next) { + next = node->next; + p = node->data; - timeout_del(&past_request_timeout); + if(p->firstseen + pinginterval <= now) { + avl_delete_node(past_request_tree, node), deleted++; + } else { + left++; + } + } + + if(left || deleted) + ifdebug(SCARY_THINGS) logger(LOG_DEBUG, "Aging past requests: deleted %d, left %d", + deleted, left); } diff --git a/src/protocol.h b/src/protocol.h index e771c54..a055f28 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,7 +1,10 @@ +#ifndef TINC_PROTOCOL_H +#define TINC_PROTOCOL_H + /* protocol.h -- header for protocol.c Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2015 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,15 +21,11 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_PROTOCOL_H__ -#define __TINC_PROTOCOL_H__ +/* Protocol version. Different versions are incompatible, + incompatible version have different protocols. + */ -#include "ecdsa.h" - -/* Protocol version. Different major versions are incompatible. */ - -#define PROT_MAJOR 17 -#define PROT_MINOR 3 /* Should not exceed 255! */ +#define PROT_CURRENT 17 /* Silly Windows */ @@ -37,6 +36,7 @@ /* Request numbers */ typedef enum request_t { + PROXY = -2, ALL = -1, /* Guardian for allow_request */ ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK, STATUS, ERROR, TERMREQ, @@ -45,23 +45,16 @@ typedef enum request_t { ADD_EDGE, DEL_EDGE, KEY_CHANGED, REQ_KEY, ANS_KEY, PACKET, - /* Tinc 1.1 requests */ - CONTROL, - REQ_PUBKEY, ANS_PUBKEY, - REQ_SPTPS, LAST /* Guardian for the highest request number */ } request_t; typedef struct past_request_t { - const char *request; + char *request; time_t firstseen; } past_request_t; extern bool tunnelserver; extern bool strictsubnets; -extern bool experimental; - -extern ecdsa_t *invitation_key; /* Maximum size of strings in a request. * scanf terminates %2048s with a NUL character, @@ -78,57 +71,50 @@ extern ecdsa_t *invitation_key; /* Basic functions */ -extern bool send_request(struct connection_t *, const char *, ...) __attribute__ ((__format__(printf, 2, 3))); -extern void forward_request(struct connection_t *, const char *); -extern bool receive_request(struct connection_t *, const char *); -extern bool check_id(const char *); +extern bool send_request(struct connection_t *c, const char *format, ...) __attribute__((__format__(printf, 2, 3))); +extern void forward_request(struct connection_t *c); +extern bool receive_request(struct connection_t *c); +extern bool check_id(const char *name); extern void init_requests(void); extern void exit_requests(void); -extern bool seen_request(const char *); +extern bool seen_request(char *request); +extern void age_past_requests(void); /* Requests */ -extern bool send_id(struct connection_t *); -extern bool send_metakey(struct connection_t *); -extern bool send_metakey_ec(struct connection_t *); -extern bool send_challenge(struct connection_t *); -extern bool send_chal_reply(struct connection_t *); -extern bool send_ack(struct connection_t *); -extern bool send_status(struct connection_t *, int, const char *); -extern bool send_error(struct connection_t *, int, const char *); -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 bool send_id(struct connection_t *c); +extern bool send_metakey(struct connection_t *c); +extern bool send_challenge(struct connection_t *c); +extern bool send_chal_reply(struct connection_t *c); +extern bool send_ack(struct connection_t *c); +extern bool send_ping(struct connection_t *c); +extern bool send_pong(struct connection_t *c); +extern bool send_add_subnet(struct connection_t *c, const struct subnet_t *subnet); +extern bool send_del_subnet(struct connection_t *c, const struct subnet_t *subnet); +extern bool send_add_edge(struct connection_t *c, const struct edge_t *e); +extern bool send_del_edge(struct connection_t *c, const struct edge_t *e); extern void send_key_changed(void); -extern bool send_req_key(struct node_t *); -extern bool send_ans_key(struct node_t *); -extern bool send_tcppacket(struct connection_t *, const struct vpn_packet_t *); +extern bool send_req_key(struct node_t *n); +extern bool send_ans_key(struct node_t *n); +extern bool send_tcppacket(struct connection_t *c, const struct vpn_packet_t *packet); /* Request handlers */ -extern bool id_h(struct connection_t *, const char *); -extern bool metakey_h(struct connection_t *, const char *); -extern bool challenge_h(struct connection_t *, const char *); -extern bool chal_reply_h(struct connection_t *, const char *); -extern bool ack_h(struct connection_t *, const char *); -extern bool status_h(struct connection_t *, const char *); -extern bool error_h(struct connection_t *, const char *); -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 *); +extern bool id_h(struct connection_t *c); +extern bool metakey_h(struct connection_t *c); +extern bool challenge_h(struct connection_t *c); +extern bool chal_reply_h(struct connection_t *c); +extern bool ack_h(struct connection_t *c); +extern bool ping_h(struct connection_t *c); +extern bool pong_h(struct connection_t *c); +extern bool add_subnet_h(struct connection_t *c); +extern bool del_subnet_h(struct connection_t *c); +extern bool add_edge_h(struct connection_t *c); +extern bool del_edge_h(struct connection_t *c); +extern bool key_changed_h(struct connection_t *c); +extern bool req_key_h(struct connection_t *c); +extern bool ans_key_h(struct connection_t *c); +extern bool tcppacket_h(struct connection_t *c); -#endif /* __TINC_PROTOCOL_H__ */ +#endif diff --git a/src/protocol_auth.c b/src/protocol_auth.c index f8a3cc3..15807c3 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -1,7 +1,7 @@ /* protocol_auth.c -- handle the meta-protocol, authentication Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,289 +20,49 @@ #include "system.h" +#include +#include +#include +#include + +#include "avl_tree.h" #include "conf.h" #include "connection.h" -#include "control.h" -#include "control_common.h" -#include "cipher.h" -#include "crypto.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 "sptps.h" +#include "proxy.h" #include "utils.h" #include "xalloc.h" -ecdsa_t *invitation_key = NULL; - -static bool send_proxyrequest(connection_t *c) { - switch(proxytype) { - case PROXY_HTTP: { - char *host; - char *port; - - sockaddr2str(&c->address, &host, &port); - send_request(c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port); - free(host); - free(port); - return true; - } - case PROXY_SOCKS4: { - if(c->address.sa.sa_family != AF_INET) { - logger(DEBUG_ALWAYS, LOG_ERR, "Cannot connect to an IPv6 host through a SOCKS 4 proxy!"); - return false; - } - char s4req[9 + (proxyuser ? strlen(proxyuser) : 0)]; - s4req[0] = 4; - s4req[1] = 1; - memcpy(s4req + 2, &c->address.in.sin_port, 2); - memcpy(s4req + 4, &c->address.in.sin_addr, 4); - if(proxyuser) - memcpy(s4req + 8, proxyuser, strlen(proxyuser)); - s4req[sizeof s4req - 1] = 0; - c->tcplen = 8; - return send_meta(c, s4req, sizeof s4req); - } - case PROXY_SOCKS5: { - int len = 3 + 6 + (c->address.sa.sa_family == AF_INET ? 4 : 16); - c->tcplen = 2; - if(proxypass) - len += 3 + strlen(proxyuser) + strlen(proxypass); - char s5req[len]; - int i = 0; - s5req[i++] = 5; - s5req[i++] = 1; - if(proxypass) { - s5req[i++] = 2; - s5req[i++] = 1; - s5req[i++] = strlen(proxyuser); - memcpy(s5req + i, proxyuser, strlen(proxyuser)); - i += strlen(proxyuser); - s5req[i++] = strlen(proxypass); - memcpy(s5req + i, proxypass, strlen(proxypass)); - i += strlen(proxypass); - c->tcplen += 2; - } else { - s5req[i++] = 0; - } - s5req[i++] = 5; - s5req[i++] = 1; - s5req[i++] = 0; - if(c->address.sa.sa_family == AF_INET) { - s5req[i++] = 1; - memcpy(s5req + i, &c->address.in.sin_addr, 4); - i += 4; - memcpy(s5req + i, &c->address.in.sin_port, 2); - i += 2; - c->tcplen += 10; - } else if(c->address.sa.sa_family == AF_INET6) { - s5req[i++] = 3; - memcpy(s5req + i, &c->address.in6.sin6_addr, 16); - i += 16; - memcpy(s5req + i, &c->address.in6.sin6_port, 2); - i += 2; - c->tcplen += 22; - } else { - logger(DEBUG_ALWAYS, LOG_ERR, "Address family %hx not supported for SOCKS 5 proxies!", c->address.sa.sa_family); - return false; - } - if(i > len) - abort(); - return send_meta(c, s5req, sizeof s5req); - } - case PROXY_SOCKS4A: - logger(DEBUG_ALWAYS, LOG_ERR, "Proxy type not implemented yet"); - return false; - case PROXY_EXEC: - return true; - default: - logger(DEBUG_ALWAYS, LOG_ERR, "Unknown proxy type"); - return false; - } -} - bool send_id(connection_t *c) { - gettimeofday(&c->start, NULL); - - int minor = 0; - - if(experimental) { - if(c->outgoing && !read_ecdsa_public_key(c)) - minor = 1; - else - minor = myself->connection->protocol_minor; + if(proxytype && c->outgoing && !c->status.proxy_passed) { + return send_proxyrequest(c); } - if(proxytype && c->outgoing) - if(!send_proxyrequest(c)) - return false; - - return send_request(c, "%d %s %d.%d", ID, myself->connection->name, myself->connection->protocol_major, minor); + return send_request(c, "%d %s %d", ID, myself->connection->name, + myself->connection->protocol_version); } -static bool finalize_invitation(connection_t *c, const char *data, uint16_t len) { - if(strchr(data, '\n')) { - logger(DEBUG_ALWAYS, LOG_ERR, "Received invalid key from invited node %s (%s)!\n", c->name, c->hostname); - return false; - } - - // Create a new host config file - char filename[PATH_MAX]; - snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, c->name); - if(!access(filename, F_OK)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Host config file for %s (%s) already exists!\n", c->name, c->hostname); - return false; - } - - FILE *f = fopen(filename, "w"); - if(!f) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error trying to create %s: %s\n", filename, strerror(errno)); - return false; - } - - fprintf(f, "ECDSAPublicKey = %s\n", data); - fclose(f); - - logger(DEBUG_CONNECTIONS, LOG_INFO, "Key succesfully received from %s (%s)", c->name, c->hostname); - return true; -} - -static bool receive_invitation_sptps(void *handle, uint8_t type, const char *data, uint16_t len) { - connection_t *c = handle; - - if(type == 128) - return true; - - if(type == 1 && c->status.invitation_used) - return finalize_invitation(c, data, len); - - if(type != 0 || len != 18 || c->status.invitation_used) - return false; - - char cookie[25]; - b64encode_urlsafe(data, cookie, 18); - - char filename[PATH_MAX], usedname[PATH_MAX]; - snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookie); - snprintf(usedname, sizeof usedname, "%s" SLASH "invitations" SLASH "%s.used", confbase, cookie); - - // Atomically rename the invitation file - if(rename(filename, usedname)) { - if(errno == ENOENT) - logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s tried to use non-existing invitation %s\n", c->hostname, cookie); - else - logger(DEBUG_ALWAYS, LOG_ERR, "Error trying to rename invitation %s\n", cookie); - return false; - } - - // Open the renamed file - FILE *f = fopen(usedname, "r"); - if(!f) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error trying to open invitation %s\n", cookie); - return false; - } - - // Read the new node's Name from the file - char buf[1024]; - fgets(buf, sizeof buf, f); - if(*buf) - buf[strlen(buf) - 1] = 0; - - len = strcspn(buf, " \t="); - char *name = buf + len; - name += strspn(name, " \t"); - if(*name == '=') { - name++; - name += strspn(name, " \t"); - } - buf[len] = 0; - - if(!*buf || !*name || strcasecmp(buf, "Name") || !check_id(name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid invitation file %s\n", cookie); - fclose(f); - return false; - } - - free(c->name); - c->name = xstrdup(name); - - // Send the node the contents of the invitation file - rewind(f); - size_t result; - while((result = fread(buf, 1, sizeof buf, f))) - sptps_send_record(&c->sptps, 0, buf, result); - sptps_send_record(&c->sptps, 1, buf, 0); - fclose(f); - unlink(usedname); - - c->status.invitation_used = true; - - logger(DEBUG_CONNECTIONS, LOG_INFO, "Invitation %s succesfully sent to %s (%s)", cookie, c->name, c->hostname); - return true; -} - -bool id_h(connection_t *c, const char *request) { +bool id_h(connection_t *c) { char name[MAX_STRING_SIZE]; - if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ID", c->name, - c->hostname); + if(sscanf(c->buffer, "%*d " MAX_STRING " %d", name, &c->protocol_version) != 2) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ID", c->name, + c->hostname); 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(""); - - return send_request(c, "%d %d %d", ACK, TINC_CTL_VERSION_CURRENT, getpid()); - } - - if(name[0] == '?') { - if(!invitation_key) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got invitation from %s but we don't have an invitation key", c->hostname); - return false; - } - - c->ecdsa = ecdsa_set_base64_public_key(name + 1); - if(!c->ecdsa) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad invitation from %s", c->hostname); - return false; - } - - c->status.invitation = true; - char *mykey = ecdsa_get_base64_public_key(invitation_key); - if(!mykey) - return false; - if(!send_request(c, "%d %s", ACK, mykey)) - return false; - free(mykey); - - c->protocol_minor = 2; - - return sptps_start(&c->sptps, c, false, false, invitation_key, c->ecdsa, "tinc invitation", 15, send_meta_sptps, receive_invitation_sptps); - } - /* Check if identity is a valid name */ - if(!check_id(name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ID", c->name, - c->hostname, "invalid name"); + if(!check_id(name) || !strcmp(name, myself->name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ID", c->name, + c->hostname, "invalid name"); return false; } @@ -310,92 +70,105 @@ bool id_h(connection_t *c, const char *request) { if(c->outgoing) { if(strcmp(c->name, name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s is %s instead of %s", c->hostname, name, - c->name); + logger(LOG_ERR, "Peer %s is %s instead of %s", c->hostname, name, + c->name); return false; } } else { - if(c->name) + if(c->name) { free(c->name); + } + c->name = xstrdup(name); } /* Check if version matches */ - if(c->protocol_major != myself->connection->protocol_major) { - logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) uses incompatible version %d.%d", - c->name, c->hostname, c->protocol_major, c->protocol_minor); + if(c->protocol_version != myself->connection->protocol_version) { + logger(LOG_ERR, "Peer %s (%s) uses incompatible version %d", + c->name, c->hostname, c->protocol_version); return false; } if(bypass_security) { - if(!c->config_tree) + if(!c->config_tree) { init_configuration(&c->config_tree); + } + c->allow_request = ACK; + + if(!c->outgoing) { + send_id(c); + } + return send_ack(c); } - if(!experimental) - c->protocol_minor = 0; - if(!c->config_tree) { init_configuration(&c->config_tree); - if(!read_host_config(c->config_tree, c->name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s had unknown identity (%s)", c->hostname, c->name); + if(!read_connection_config(c)) { + logger(LOG_ERR, "Peer %s had unknown identity (%s)", c->hostname, + c->name); return false; } - - if(experimental) - read_ecdsa_public_key(c); - } else { - if(c->protocol_minor && !ecdsa_active(c->ecdsa)) - c->protocol_minor = 1; } - /* Forbid version rollback for nodes whose ECDSA key we know */ - - if(ecdsa_active(c->ecdsa) && c->protocol_minor < 2) { - logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) tries to roll back protocol version to %d.%d", - c->name, c->hostname, c->protocol_major, c->protocol_minor); + if(!read_rsa_public_key(c)) { return false; } c->allow_request = METAKEY; - if(c->protocol_minor >= 2) { - c->allow_request = ACK; - char label[25 + strlen(myself->name) + strlen(c->name)]; - - if(c->outgoing) - snprintf(label, sizeof label, "tinc TCP key expansion %s %s", myself->name, c->name); - else - snprintf(label, sizeof label, "tinc TCP key expansion %s %s", c->name, myself->name); - - return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, sizeof label, send_meta_sptps, receive_meta_sptps); - } else { - return send_metakey(c); + if(!c->outgoing) { + send_id(c); } + + return send_metakey(c); +} + +static uint64_t byte_budget(const EVP_CIPHER *cipher) { + /* Hopefully some failsafe way to calculate the maximum amount of bytes to + send/receive with a given cipher before we might run into birthday paradox + attacks. Because we might use different modes, the block size of the mode + might be 1 byte. In that case, use the IV length. Ensure the whole thing + is limited to what can be represented with a 64 bits integer. + */ + + int ivlen = EVP_CIPHER_iv_length(cipher); + int blklen = EVP_CIPHER_block_size(cipher); + int len = blklen > 1 ? blklen : ivlen > 1 ? ivlen : 8; + int bits = len * 4 - 1; + return bits < 64 ? UINT64_C(1) << bits : UINT64_MAX; } bool send_metakey(connection_t *c) { - if(!read_rsa_public_key(c)) + bool x; + + int len = RSA_size(c->rsa_key); + + /* Allocate buffers for the meta key */ + + char buffer[2 * len + 1]; + + c->outkey = xrealloc(c->outkey, len); + + if(!c->outctx) { + c->outctx = EVP_CIPHER_CTX_new(); + + if(!c->outctx) { + abort(); + } + } + + /* Copy random data to the buffer */ + + if(1 != RAND_bytes((unsigned char *)c->outkey, len)) { + int err = ERR_get_error(); + logger(LOG_ERR, "Failed to generate meta key (%s)", ERR_error_string(err, NULL)); return false; + } - if(!(c->outcipher = cipher_open_blowfish_ofb())) - return false; - - if(!(c->outdigest = digest_open_sha1(-1))) - return false; - - size_t len = rsa_size(c->rsa); - char key[len]; - char enckey[len]; - char hexkey[2 * len + 1]; - - /* Create a random key */ - - randomize(key, len); /* The message we send must be smaller than the modulus of the RSA key. By definition, for a key of k bits, the following formula holds: @@ -407,14 +180,13 @@ bool send_metakey(connection_t *c) { This can be done by setting the most significant bit to zero. */ - key[0] &= 0x7F; + c->outkey[0] &= 0x7F; - if(!cipher_set_key_from_rsa(c->outcipher, key, len, true)) - return false; - - if(debug_level >= DEBUG_SCARY_THINGS) { - bin2hex(key, hexkey, len); - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Generated random meta key (unencrypted): %s", hexkey); + ifdebug(SCARY_THINGS) { + bin2hex(c->outkey, buffer, len); + buffer[len * 2] = '\0'; + logger(LOG_DEBUG, "Generated random meta key (unencrypted): %s", + buffer); } /* Encrypt the random data @@ -424,74 +196,144 @@ bool send_metakey(connection_t *c) { with a length equal to that of the modulus of the RSA key. */ - if(!rsa_public_encrypt(c->rsa, key, len, enckey)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error during encryption of meta key for %s (%s)", c->name, c->hostname); + if(RSA_public_encrypt(len, (unsigned char *)c->outkey, (unsigned char *)buffer, c->rsa_key, RSA_NO_PADDING) != len) { + logger(LOG_ERR, "Error during encryption of meta key for %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); return false; } /* Convert the encrypted random data to a hexadecimal formatted string */ - bin2hex(enckey, hexkey, len); + bin2hex(buffer, buffer, len); + buffer[len * 2] = '\0'; /* Send the meta key */ - bool result = send_request(c, "%d %d %d %d %d %s", METAKEY, - cipher_get_nid(c->outcipher), - digest_get_nid(c->outdigest), c->outmaclength, - c->outcompression, hexkey); + x = send_request(c, "%d %d %d %d %d %s", METAKEY, + c->outcipher ? EVP_CIPHER_nid(c->outcipher) : 0, + c->outdigest ? EVP_MD_type(c->outdigest) : 0, c->outmaclength, + c->outcompression, buffer); - c->status.encryptout = true; - return result; + /* Further outgoing requests are encrypted with the key we just generated */ + + if(c->outcipher) { + if(!EVP_EncryptInit(c->outctx, c->outcipher, + (unsigned char *)c->outkey + len - EVP_CIPHER_key_length(c->outcipher), + (unsigned char *)c->outkey + len - EVP_CIPHER_key_length(c->outcipher) - + EVP_CIPHER_iv_length(c->outcipher))) { + logger(LOG_ERR, "Error during initialisation of cipher for %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + c->outbudget = byte_budget(c->outcipher); + c->status.encryptout = true; + } + + return x; } -bool metakey_h(connection_t *c, const char *request) { - char hexkey[MAX_STRING_SIZE]; +bool metakey_h(connection_t *c) { + char buffer[MAX_STRING_SIZE]; int cipher, digest, maclength, compression; - size_t len = rsa_size(myself->connection->rsa); - char enckey[len]; - char key[len]; + int len; - if(sscanf(request, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, hexkey) != 5) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "METAKEY", c->name, c->hostname); + if(sscanf(c->buffer, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, buffer) != 5) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "METAKEY", c->name, + c->hostname); return false; } + len = RSA_size(myself->connection->rsa_key); + + /* Check if the length of the meta key is all right */ + + if(strlen(buffer) != (size_t)len * 2) { + logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength"); + return false; + } + + /* Allocate buffers for the meta key */ + + c->inkey = xrealloc(c->inkey, len); + + if(!c->inctx) { + c->inctx = EVP_CIPHER_CTX_new(); + + if(!c->inctx) { + abort(); + } + } + /* Convert the challenge from hexadecimal back to binary */ - int inlen = hex2bin(hexkey, enckey, sizeof enckey); - - /* Check if the length of the meta key is all right */ - - if(inlen != len) { - logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength"); + if(!hex2bin(buffer, buffer, len)) { + logger(LOG_ERR, "Got bad %s from %s(%s): %s", "METAKEY", c->name, c->hostname, "invalid key"); return false; } /* Decrypt the meta key */ - if(!rsa_private_decrypt(myself->connection->rsa, enckey, len, key)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error during decryption of meta key for %s (%s)", c->name, c->hostname); + if(RSA_private_decrypt(len, (unsigned char *)buffer, (unsigned char *)c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) { /* See challenge() */ + logger(LOG_ERR, "Error during decryption of meta key for %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); return false; } - if(debug_level >= DEBUG_SCARY_THINGS) { - bin2hex(key, hexkey, len); - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Received random meta key (unencrypted): %s", hexkey); + ifdebug(SCARY_THINGS) { + bin2hex(c->inkey, buffer, len); + buffer[len * 2] = '\0'; + logger(LOG_DEBUG, "Received random meta key (unencrypted): %s", buffer); } + /* All incoming requests will now be encrypted. */ + /* Check and lookup cipher and digest algorithms */ - if(!(c->incipher = cipher_open_by_nid(cipher)) || !cipher_set_key_from_rsa(c->incipher, key, len, false)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error during initialisation of cipher from %s (%s)", c->name, c->hostname); + if(cipher) { + c->incipher = EVP_get_cipherbynid(cipher); + + if(!c->incipher) { + logger(LOG_ERR, "%s (%s) uses unknown cipher!", c->name, c->hostname); + return false; + } + + if(!EVP_DecryptInit(c->inctx, c->incipher, + (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher), + (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher) - + EVP_CIPHER_iv_length(c->incipher))) { + logger(LOG_ERR, "Error during initialisation of cipher from %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + c->inbudget = byte_budget(c->incipher); + c->status.decryptin = true; + } else { + logger(LOG_ERR, "%s (%s) uses null cipher!", c->name, c->hostname); return false; } - if(!(c->indigest = digest_open_by_nid(digest, -1))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error during initialisation of digest from %s (%s)", c->name, c->hostname); + c->inmaclength = maclength; + + if(digest) { + c->indigest = EVP_get_digestbynid(digest); + + if(!c->indigest) { + logger(LOG_ERR, "Node %s (%s) uses unknown digest!", c->name, c->hostname); + return false; + } + + if(c->inmaclength > EVP_MD_size(c->indigest) || c->inmaclength < 0) { + logger(LOG_ERR, "%s (%s) uses bogus MAC length!", c->name, c->hostname); + return false; + } + } else { + logger(LOG_ERR, "%s (%s) uses null digest!", c->name, c->hostname); return false; } - c->status.decryptin = true; + c->incompression = compression; c->allow_request = CHALLENGE; @@ -499,88 +341,166 @@ bool metakey_h(connection_t *c, const char *request) { } bool send_challenge(connection_t *c) { - size_t len = rsa_size(c->rsa); - char buffer[len * 2 + 1]; + /* CHECKME: what is most reasonable value for len? */ - if(!c->hischallenge) - c->hischallenge = xrealloc(c->hischallenge, len); + int len = RSA_size(c->rsa_key); + + /* Allocate buffers for the challenge */ + + char buffer[2 * len + 1]; + + c->hischallenge = xrealloc(c->hischallenge, len); /* Copy random data to the buffer */ - randomize(c->hischallenge, len); + if(1 != RAND_bytes((unsigned char *)c->hischallenge, len)) { + int err = ERR_get_error(); + logger(LOG_ERR, "Failed to generate challenge (%s)", ERR_error_string(err, NULL)); + return false; // Do not send predictable challenges, let connection attempt fail. + } /* Convert to hex */ bin2hex(c->hischallenge, buffer, len); + buffer[len * 2] = '\0'; /* Send the challenge */ return send_request(c, "%d %s", CHALLENGE, buffer); } -bool challenge_h(connection_t *c, const char *request) { +bool challenge_h(connection_t *c) { char buffer[MAX_STRING_SIZE]; - size_t len = rsa_size(myself->connection->rsa); - size_t digestlen = digest_length(c->indigest); - char digest[digestlen]; + int len; - if(sscanf(request, "%*d " MAX_STRING, buffer) != 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CHALLENGE", c->name, c->hostname); + if(sscanf(c->buffer, "%*d " MAX_STRING, buffer) != 1) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "CHALLENGE", c->name, + c->hostname); return false; } - /* Convert the challenge from hexadecimal back to binary */ - - int inlen = hex2bin(buffer, buffer, sizeof buffer); + len = RSA_size(myself->connection->rsa_key); /* Check if the length of the challenge is all right */ - if(inlen != len) { - logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge length"); + if(strlen(buffer) != (size_t)len * 2) { + logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, + c->hostname, "wrong challenge length"); return false; } - /* Calculate the hash from the challenge we received */ + /* Allocate buffers for the challenge */ - if(!digest_create(c->indigest, buffer, len, digest)) + c->mychallenge = xrealloc(c->mychallenge, len); + + /* Convert the challenge from hexadecimal back to binary */ + + if(!hex2bin(buffer, c->mychallenge, len)) { + logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHALLENGE", c->name, c->hostname, "invalid challenge"); return false; - - /* Convert the hash to a hexadecimal formatted string */ - - bin2hex(digest, buffer, digestlen); - - /* Send the reply */ + } c->allow_request = CHAL_REPLY; - return send_request(c, "%d %s", CHAL_REPLY, buffer); + /* Rest is done by send_chal_reply() */ + + if(c->outgoing) { + return send_chal_reply(c); + } else { + return true; + } } -bool chal_reply_h(connection_t *c, const char *request) { - char hishash[MAX_STRING_SIZE]; +bool send_chal_reply(connection_t *c) { + char hash[EVP_MAX_MD_SIZE * 2 + 1]; + EVP_MD_CTX *ctx; - if(sscanf(request, "%*d " MAX_STRING, hishash) != 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CHAL_REPLY", c->name, - c->hostname); + /* Calculate the hash from the challenge we received */ + + ctx = EVP_MD_CTX_create(); + + if(!ctx) { + abort(); + } + + if(!EVP_DigestInit(ctx, c->indigest) + || !EVP_DigestUpdate(ctx, c->mychallenge, RSA_size(myself->connection->rsa_key)) + || !EVP_DigestFinal(ctx, (unsigned char *)hash, NULL)) { + EVP_MD_CTX_destroy(ctx); + logger(LOG_ERR, "Error during calculation of response for %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + EVP_MD_CTX_destroy(ctx); + + /* Convert the hash to a hexadecimal formatted string */ + + bin2hex(hash, hash, EVP_MD_size(c->indigest)); + hash[EVP_MD_size(c->indigest) * 2] = '\0'; + + /* Send the reply */ + + return send_request(c, "%d %s", CHAL_REPLY, hash); +} + +bool chal_reply_h(connection_t *c) { + char hishash[MAX_STRING_SIZE]; + char myhash[EVP_MAX_MD_SIZE]; + EVP_MD_CTX *ctx; + + if(sscanf(c->buffer, "%*d " MAX_STRING, hishash) != 1) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "CHAL_REPLY", c->name, + c->hostname); + return false; + } + + /* Check if the length of the hash is all right */ + + if(strlen(hishash) != (size_t)EVP_MD_size(c->outdigest) * 2) { + logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, + c->hostname, "wrong challenge reply length"); return false; } /* Convert the hash to binary format */ - int inlen = hex2bin(hishash, hishash, sizeof hishash); - - /* Check if the length of the hash is all right */ - - if(inlen != digest_length(c->outdigest)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge reply length"); + if(!hex2bin(hishash, hishash, EVP_MD_size(c->outdigest))) { + logger(LOG_ERR, "Got bad %s from %s(%s): %s", "CHAL_REPLY", c->name, c->hostname, "invalid hash"); return false; } + /* Calculate the hash from the challenge we sent */ - /* Verify the hash */ + ctx = EVP_MD_CTX_create(); + + if(!ctx) { + abort(); + } + + if(!EVP_DigestInit(ctx, c->outdigest) + || !EVP_DigestUpdate(ctx, c->hischallenge, RSA_size(c->rsa_key)) + || !EVP_DigestFinal(ctx, (unsigned char *)myhash, NULL)) { + EVP_MD_CTX_destroy(ctx); + logger(LOG_ERR, "Error during calculation of response from %s (%s): %s", + c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL)); + return false; + } + + EVP_MD_CTX_destroy(ctx); + + /* Verify the incoming hash with the calculated hash */ + + if(memcmp(hishash, myhash, EVP_MD_size(c->outdigest))) { + logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, + c->hostname, "wrong challenge reply"); + + ifdebug(SCARY_THINGS) { + bin2hex(myhash, hishash, SHA_DIGEST_LENGTH); + hishash[SHA_DIGEST_LENGTH * 2] = '\0'; + logger(LOG_DEBUG, "Expected challenge reply: %s", hishash); + } - if(!digest_verify(c->outdigest, c->hischallenge, rsa_size(c->rsa), hishash)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge reply"); return false; } @@ -588,31 +508,16 @@ bool chal_reply_h(connection_t *c, const char *request) { Send an acknowledgement with the rest of the information needed. */ - free(c->hischallenge); - c->hischallenge = NULL; c->allow_request = ACK; + if(!c->outgoing) { + send_chal_reply(c); + } + return send_ack(c); } -static bool send_upgrade(connection_t *c) { - /* Special case when protocol_minor is 1: the other end is ECDSA capable, - * but doesn't know our key yet. So send it now. */ - - char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa); - - if(!pubkey) - return false; - - bool result = send_request(c, "%d %s", ACK, pubkey); - free(pubkey); - return result; -} - bool send_ack(connection_t *c) { - if(c->protocol_minor == 1) - return send_upgrade(c); - /* ACK message contains rest of the information the other end needs to create node_t and edge_t structures. */ @@ -626,88 +531,72 @@ bool send_ack(connection_t *c) { /* Check some options */ - if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &choice) && choice) || myself->options & OPTION_INDIRECT) + if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &choice) && choice) || myself->options & OPTION_INDIRECT) { c->options |= OPTION_INDIRECT; + } - if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY) + if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &choice) && choice) || myself->options & OPTION_TCPONLY) { c->options |= OPTION_TCPONLY | OPTION_INDIRECT; + } - if(myself->options & OPTION_PMTU_DISCOVERY) + if(myself->options & OPTION_PMTU_DISCOVERY && !(c->options & OPTION_TCPONLY)) { c->options |= OPTION_PMTU_DISCOVERY; + } choice = myself->options & OPTION_CLAMP_MSS; get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice); - if(choice) + + if(choice) { c->options |= OPTION_CLAMP_MSS; + } get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight); - return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, (c->options & 0xffffff) | (experimental ? (PROT_MINOR << 24) : 0)); + return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options); } static void send_everything(connection_t *c) { + avl_node_t *node, *node2; + node_t *n; + subnet_t *s; + edge_t *e; + /* Send all known subnets and edges */ - if(disablebuggypeers) { - static struct { - vpn_packet_t pkt; - char pad[MAXBUFSIZE - MAXSIZE]; - } zeropkt; - - memset(&zeropkt, 0, sizeof zeropkt); - zeropkt.pkt.len = MAXBUFSIZE; - send_tcppacket(c, &zeropkt.pkt); - } - if(tunnelserver) { - for splay_each(subnet_t, s, myself->subnet_tree) + for(node = myself->subnet_tree->head; node; node = node->next) { + s = node->data; send_add_subnet(c, s); + } return; } - for splay_each(node_t, n, node_tree) { - for splay_each(subnet_t, s, n->subnet_tree) + for(node = node_tree->head; node; node = node->next) { + n = node->data; + + for(node2 = n->subnet_tree->head; node2; node2 = node2->next) { + s = node2->data; send_add_subnet(c, s); + } - for splay_each(edge_t, e, n->edge_tree) + for(node2 = n->edge_tree->head; node2; node2 = node2->next) { + e = node2->data; send_add_edge(c, e); + } } } -static bool upgrade_h(connection_t *c, const char *request) { - char pubkey[MAX_STRING_SIZE]; - - if(sscanf(request, "%*d " MAX_STRING, pubkey) != 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name, c->hostname); - return false; - } - - if(ecdsa_active(c->ecdsa) || read_ecdsa_public_key(c)) { - logger(DEBUG_ALWAYS, LOG_INFO, "Already have ECDSA public key from %s (%s), not upgrading.", c->name, c->hostname); - return false; - } - - logger(DEBUG_ALWAYS, LOG_INFO, "Got ECDSA public key from %s (%s), upgrading!", c->name, c->hostname); - append_config_file(c->name, "ECDSAPublicKey", pubkey); - c->allow_request = TERMREQ; - return send_termreq(c); -} - -bool ack_h(connection_t *c, const char *request) { - if(c->protocol_minor == 1) - return upgrade_h(c, request); - +bool ack_h(connection_t *c) { char hisport[MAX_STRING_SIZE]; - char *hisaddress; int weight, mtu; uint32_t options; node_t *n; bool choice; - if(sscanf(request, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name, - c->hostname); + if(sscanf(c->buffer, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name, + c->hostname); return false; } @@ -722,17 +611,8 @@ bool ack_h(connection_t *c, const char *request) { } else { if(n->connection) { /* Oh dear, we already have a connection to this node. */ - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Established a second connection with %s (%s), closing old connection", n->connection->name, n->connection->hostname); - - if(n->connection->outgoing) { - if(c->outgoing) - logger(DEBUG_ALWAYS, LOG_WARNING, "Two outgoing connections to the same node!"); - else - c->outgoing = n->connection->outgoing; - - n->connection->outgoing = NULL; - } - + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Established a second connection with %s (%s), closing old connection", + n->name, n->hostname); 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 */ graph(); @@ -741,23 +621,28 @@ bool ack_h(connection_t *c, const char *request) { n->connection = c; c->node = n; + if(!(c->options & options & OPTION_PMTU_DISCOVERY)) { c->options &= ~OPTION_PMTU_DISCOVERY; options &= ~OPTION_PMTU_DISCOVERY; } + c->options |= options; - if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu) + if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu) { n->mtu = mtu; + } - if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu) + if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu) { n->mtu = mtu; + } if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) { - if(choice) + if(choice) { c->options |= OPTION_CLAMP_MSS; - else + } else { c->options &= ~OPTION_CLAMP_MSS; + } } /* Activate this connection */ @@ -765,8 +650,8 @@ bool ack_h(connection_t *c, const char *request) { c->allow_request = ALL; c->status.active = true; - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection with %s (%s) activated", c->name, - c->hostname); + ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection with %s (%s) activated", c->name, + c->hostname); /* Send him everything we know */ @@ -777,9 +662,8 @@ bool ack_h(connection_t *c, const char *request) { c->edge = new_edge(); c->edge->from = myself; c->edge->to = n; - sockaddr2str(&c->address, &hisaddress, NULL); - c->edge->address = str2sockaddr(hisaddress, hisport); - free(hisaddress); + sockaddrcpy(&c->edge->address, &c->address); + sockaddr_setport(&c->edge->address, hisport); c->edge->weight = (weight + c->estimated_weight) / 2; c->edge->connection = c; c->edge->options = c->options; @@ -788,10 +672,11 @@ bool ack_h(connection_t *c, const char *request) { /* Notify everyone of the new edge */ - if(tunnelserver) + if(tunnelserver) { send_add_edge(c, c->edge); - else + } else { send_add_edge(everyone, c->edge); + } /* Run MST and SSSP algorithms */ diff --git a/src/protocol_edge.c b/src/protocol_edge.c index e285a6d..a1cf640 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -1,7 +1,7 @@ /* protocol_edge.c -- handle the meta-protocol, edges Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2012 Guus Sliepen + 2000-2016 Guus Sliepen 2009 Michael Tokarev This program is free software; you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include "system.h" +#include "avl_tree.h" #include "conf.h" #include "connection.h" #include "edge.h" @@ -41,15 +42,15 @@ bool send_add_edge(connection_t *c, const edge_t *e) { sockaddr2str(&e->address, &address, &port); x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(), - e->from->name, e->to->name, address, port, - e->options, e->weight); + e->from->name, e->to->name, address, port, + e->options, e->weight); free(address); free(port); return x; } -bool add_edge_h(connection_t *c, const char *request) { +bool add_edge_h(connection_t *c) { edge_t *e; node_t *from, *to; char from_name[MAX_STRING_SIZE]; @@ -60,23 +61,24 @@ bool add_edge_h(connection_t *c, const char *request) { uint32_t options; int weight; - if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d", - from_name, to_name, to_address, to_port, &options, &weight) != 6) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name, - c->hostname); + if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d", + from_name, to_name, to_address, to_port, &options, &weight) != 6) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name, + c->hostname); return false; } /* Check if names are valid */ - if(!check_id(from_name) || !check_id(to_name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, - c->hostname, "invalid name"); + if(!check_id(from_name) || !check_id(to_name) || !strcmp(from_name, to_name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, + c->hostname, "invalid name"); return false; } - if(seen_request(request)) + if(seen_request(c->buffer)) { return true; + } /* Lookup nodes */ @@ -84,12 +86,12 @@ bool add_edge_h(connection_t *c, const char *request) { to = lookup_node(to_name); if(tunnelserver && - from != myself && from != c->node && - to != myself && to != c->node) { + from != myself && from != c->node && + to != myself && to != c->node) { /* ignore indirect edge registrations for tunnelserver */ - logger(DEBUG_PROTOCOL, LOG_WARNING, - "Ignoring indirect %s from %s (%s)", - "ADD_EDGE", c->name, c->hostname); + ifdebug(PROTOCOL) logger(LOG_WARNING, + "Ignoring indirect %s from %s (%s)", + "ADD_EDGE", c->name, c->hostname); return true; } @@ -117,21 +119,34 @@ bool add_edge_h(connection_t *c, const char *request) { if(e) { if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { if(from == myself) { - logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", - "ADD_EDGE", c->name, c->hostname); + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", + "ADD_EDGE", c->name, c->hostname); send_add_edge(c, e); return true; } else { - logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not match existing entry", - "ADD_EDGE", c->name, c->hostname); - edge_del(e); - graph(); + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not match existing entry", + "ADD_EDGE", c->name, c->hostname); + e->options = options; + + if(sockaddrcmp(&e->address, &address)) { + sockaddrfree(&e->address); + e->address = address; + } + + if(e->weight != weight) { + avl_node_t *node = avl_unlink(edge_weight_tree, e); + e->weight = weight; + avl_insert_node(edge_weight_tree, node); + } + + goto done; } - } else + } else { return true; + } } else if(from == myself) { - logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist", - "ADD_EDGE", c->name, c->hostname); + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist", + "ADD_EDGE", c->name, c->hostname); contradicting_add_edge++; e = new_edge(); e->from = from; @@ -149,10 +164,12 @@ bool add_edge_h(connection_t *c, const char *request) { e->weight = weight; edge_add(e); +done: /* Tell the rest about the new edge */ - if(!tunnelserver) - forward_request(c, request); + if(!tunnelserver) { + forward_request(c); + } /* Run MST before or after we tell the rest? */ @@ -163,31 +180,32 @@ bool add_edge_h(connection_t *c, const char *request) { bool send_del_edge(connection_t *c, const edge_t *e) { return send_request(c, "%d %x %s %s", DEL_EDGE, rand(), - e->from->name, e->to->name); + e->from->name, e->to->name); } -bool del_edge_h(connection_t *c, const char *request) { +bool del_edge_h(connection_t *c) { edge_t *e; char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; node_t *from, *to; - if(sscanf(request, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "DEL_EDGE", c->name, - c->hostname); + if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "DEL_EDGE", c->name, + c->hostname); return false; } /* Check if names are valid */ - if(!check_id(from_name) || !check_id(to_name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name, - c->hostname, "invalid name"); + if(!check_id(from_name) || !check_id(to_name) || !strcmp(from_name, to_name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name, + c->hostname, "invalid name"); return false; } - if(seen_request(request)) + if(seen_request(c->buffer)) { return true; + } /* Lookup nodes */ @@ -195,24 +213,24 @@ bool del_edge_h(connection_t *c, const char *request) { to = lookup_node(to_name); if(tunnelserver && - from != myself && from != c->node && - to != myself && to != c->node) { + from != myself && from != c->node && + to != myself && to != c->node) { /* ignore indirect edge registrations for tunnelserver */ - logger(DEBUG_PROTOCOL, LOG_WARNING, - "Ignoring indirect %s from %s (%s)", - "DEL_EDGE", c->name, c->hostname); + ifdebug(PROTOCOL) logger(LOG_WARNING, + "Ignoring indirect %s from %s (%s)", + "DEL_EDGE", c->name, c->hostname); return true; } if(!from) { - logger(DEBUG_PROTOCOL, LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + ifdebug(PROTOCOL) logger(LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree", + "DEL_EDGE", c->name, c->hostname); return true; } if(!to) { - logger(DEBUG_PROTOCOL, LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + ifdebug(PROTOCOL) logger(LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree", + "DEL_EDGE", c->name, c->hostname); return true; } @@ -221,14 +239,14 @@ bool del_edge_h(connection_t *c, const char *request) { e = lookup_edge(from, to); if(!e) { - logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not appear in the edge tree", + "DEL_EDGE", c->name, c->hostname); return true; } if(e->from == myself) { - logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself", - "DEL_EDGE", c->name, c->hostname); + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself", + "DEL_EDGE", c->name, c->hostname); contradicting_del_edge++; send_add_edge(c, e); /* Send back a correction */ return true; @@ -236,8 +254,9 @@ bool del_edge_h(connection_t *c, const char *request) { /* Tell the rest about the deleted edge */ - if(!tunnelserver) - forward_request(c, request); + if(!tunnelserver) { + forward_request(c); + } /* Delete the edge */ @@ -251,9 +270,12 @@ bool del_edge_h(connection_t *c, const char *request) { if(!to->status.reachable) { e = lookup_edge(to, myself); + if(e) { - if(!tunnelserver) + if(!tunnelserver) { send_del_edge(everyone, e); + } + edge_del(e); } } diff --git a/src/protocol_key.c b/src/protocol_key.c index a3cf3f5..6140a53 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -1,7 +1,7 @@ /* protocol_key.c -- handle the meta-protocol, key exchange Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2016 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,423 +20,326 @@ #include "system.h" -#include "cipher.h" +#include +#include +#include + +#include "avl_tree.h" #include "connection.h" -#include "crypto.h" #include "logger.h" #include "net.h" #include "netutl.h" #include "node.h" -#include "prf.h" #include "protocol.h" -#include "sptps.h" #include "utils.h" #include "xalloc.h" static bool mykeyused = false; void send_key_changed(void) { + avl_node_t *node; + connection_t *c; + send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name); /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */ - for list_each(connection_t, c, connection_list) - if(c->status.active && c->node && c->node->status.reachable && !c->node->status.sptps) + for(node = connection_tree->head; node; node = node->next) { + c = node->data; + + if(c->status.active && c->node && c->node->status.reachable) { send_ans_key(c->node); - - /* Force key exchange for connections using SPTPS */ - - if(experimental) { - for splay_each(node_t, n, node_tree) - if(n->status.reachable && n->status.validkey && n->status.sptps) - sptps_force_kex(&n->sptps); + } } } -bool key_changed_h(connection_t *c, const char *request) { +bool key_changed_h(connection_t *c) { char name[MAX_STRING_SIZE]; node_t *n; - if(sscanf(request, "%*d %*x " MAX_STRING, name) != 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED", - c->name, c->hostname); + if(sscanf(c->buffer, "%*d %*x " MAX_STRING, name) != 1) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "KEY_CHANGED", + c->name, c->hostname); return false; } - if(seen_request(request)) + if(!check_id(name)) { + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "KEY_CHANGED", c->name, c->hostname, "invalid name"); + return false; + } + + if(seen_request(c->buffer)) { return true; + } n = lookup_node(name); if(!n) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist", - "KEY_CHANGED", c->name, c->hostname, name); + logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist", + "KEY_CHANGED", c->name, c->hostname, name); return true; } - if(!n->status.sptps) { - n->status.validkey = false; - n->last_req_key = 0; - } + n->status.validkey = false; + n->last_req_key = 0; /* Tell the others */ - if(!tunnelserver) - forward_request(c, request); + if(!tunnelserver) { + forward_request(c); + } return true; } -static bool send_initial_sptps_data(void *handle, uint8_t type, const char *data, size_t len) { - node_t *to = handle; - to->sptps.send_data = send_sptps_data; - char buf[len * 4 / 3 + 5]; - b64encode(data, buf, len); - return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf); -} - bool send_req_key(node_t *to) { - if(to->status.sptps) { - if(!node_read_ecdsa_public_key(to)) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "No ECDSA key known for %s (%s)", to->name, to->hostname); - send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY); - return true; - } - - if(to->sptps.label) - logger(DEBUG_ALWAYS, LOG_DEBUG, "send_req_key(%s) called while sptps->label != NULL!", to->name); - - char label[25 + strlen(myself->name) + strlen(to->name)]; - snprintf(label, sizeof label, "tinc UDP key expansion %s %s", myself->name, to->name); - sptps_stop(&to->sptps); - to->status.validkey = false; - to->status.waitingforkey = true; - to->last_req_key = now.tv_sec; - to->incompression = myself->incompression; - return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof label, send_initial_sptps_data, receive_sptps_record); - } - return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name); } -/* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */ - -static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, int reqno) { - switch(reqno) { - case REQ_PUBKEY: { - char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa); - send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey); - free(pubkey); - return true; - } - - case ANS_PUBKEY: { - if(node_read_ecdsa_public_key(from)) { - logger(DEBUG_PROTOCOL, LOG_WARNING, "Got ANS_PUBKEY from %s (%s) even though we already have his pubkey", from->name, from->hostname); - return true; - } - - char pubkey[MAX_STRING_SIZE]; - if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey"); - return true; - } - - logger(DEBUG_PROTOCOL, LOG_INFO, "Learned ECDSA public key from %s (%s)", from->name, from->hostname); - append_config_file(from->name, "ECDSAPublicKey", pubkey); - return true; - } - - case REQ_KEY: { - if(!node_read_ecdsa_public_key(from)) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "No ECDSA key known for %s (%s)", from->name, from->hostname); - send_request(from->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, from->name, REQ_PUBKEY); - return true; - } - - if(from->sptps.label) - logger(DEBUG_ALWAYS, LOG_DEBUG, "Got REQ_KEY from %s while we already started a SPTPS session!", from->name); - - char buf[MAX_STRING_SIZE]; - int len; - - if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS_START", from->name, from->hostname, "invalid SPTPS data"); - return true; - } - - char label[25 + strlen(from->name) + strlen(myself->name)]; - snprintf(label, sizeof label, "tinc UDP key expansion %s %s", from->name, myself->name); - sptps_stop(&from->sptps); - from->status.validkey = false; - from->status.waitingforkey = true; - from->last_req_key = now.tv_sec; - sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data, receive_sptps_record); - sptps_receive_data(&from->sptps, buf, len); - return true; - } - - case REQ_SPTPS: { - if(!from->status.validkey) { - logger(DEBUG_PROTOCOL, LOG_ERR, "Got REQ_SPTPS from %s (%s) but we don't have a valid key yet", from->name, from->hostname); - return true; - } - - char buf[MAX_STRING_SIZE]; - int len; - if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS", from->name, from->hostname, "invalid SPTPS data"); - return true; - } - sptps_receive_data(&from->sptps, buf, len); - return true; - } - - default: - logger(DEBUG_ALWAYS, LOG_ERR, "Unknown extended REQ_KEY request from %s (%s): %s", from->name, from->hostname, request); - return true; - } -} - -bool req_key_h(connection_t *c, const char *request) { +bool req_key_h(connection_t *c) { char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; node_t *from, *to; - int reqno = 0; - if(sscanf(request, "%*d " MAX_STRING " " MAX_STRING " %d", from_name, to_name, &reqno) < 2) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name, - c->hostname); + if(sscanf(c->buffer, "%*d " MAX_STRING " " MAX_STRING, from_name, to_name) != 2) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "REQ_KEY", c->name, + c->hostname); return false; } if(!check_id(from_name) || !check_id(to_name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name"); + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name"); return false; } from = lookup_node(from_name); if(!from) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", - "REQ_KEY", c->name, c->hostname, from_name); + logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", + "REQ_KEY", c->name, c->hostname, from_name); return true; } to = lookup_node(to_name); if(!to) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", - "REQ_KEY", c->name, c->hostname, to_name); + logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", + "REQ_KEY", c->name, c->hostname, to_name); return true; } /* Check if this key request is for us */ - if(to == myself) { /* Yes */ - /* Is this an extended REQ_KEY message? */ - if(experimental && reqno) - return req_key_ext_h(c, request, from, reqno); - - /* No, just send our key back */ - send_ans_key(from); + if(to == myself) { /* Yes, send our own key back */ + if(!send_ans_key(from)) { + return false; + } } else { - if(tunnelserver) - return true; - - if(!to->status.reachable) { - logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable", - "REQ_KEY", c->name, c->hostname, to_name); + if(tunnelserver) { return true; } - send_request(to->nexthop->connection, "%s", request); + if(!to->status.reachable) { + logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable", + "REQ_KEY", c->name, c->hostname, to_name); + return true; + } + + send_request(to->nexthop->connection, "%s", c->buffer); } return true; } bool send_ans_key(node_t *to) { - if(to->status.sptps) - abort(); - - size_t keylen = cipher_keylength(myself->incipher); - char key[keylen * 2 + 1]; - - cipher_close(to->incipher); - digest_close(to->indigest); - - to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher)); - to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest)); + // Set key parameters + to->incipher = myself->incipher; + to->inkeylength = myself->inkeylength; + to->indigest = myself->indigest; + to->inmaclength = myself->inmaclength; to->incompression = myself->incompression; - if(!to->incipher || !to->indigest) - abort(); + // Allocate memory for key + to->inkey = xrealloc(to->inkey, to->inkeylength); - randomize(key, keylen); - if(!cipher_set_key(to->incipher, key, false)) - abort(); - if(!digest_set_key(to->indigest, key, keylen)) - abort(); + // Create a new key + if(1 != RAND_bytes((unsigned char *)to->inkey, to->inkeylength)) { + int err = ERR_get_error(); + logger(LOG_ERR, "Failed to generate random for key (%s)", ERR_error_string(err, NULL)); + return false; // Do not send insecure keys, let connection attempt fail. + } - bin2hex(key, key, keylen); + if(to->incipher) { + EVP_DecryptInit_ex(to->inctx, to->incipher, NULL, (unsigned char *)to->inkey, (unsigned char *)to->inkey + EVP_CIPHER_key_length(to->incipher)); + } // Reset sequence number and late packet window mykeyused = true; to->received_seqno = 0; - to->received = 0; - if(replaywin) memset(to->late, 0, replaywin); + + if(replaywin) { + memset(to->late, 0, replaywin); + } + + // Convert to hexadecimal and send + char key[2 * to->inkeylength + 1]; + bin2hex(to->inkey, key, to->inkeylength); + key[to->inkeylength * 2] = '\0'; return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY, - myself->name, to->name, key, - cipher_get_nid(to->incipher), - digest_get_nid(to->indigest), - (int)digest_length(to->indigest), - to->incompression); + myself->name, to->name, key, + to->incipher ? EVP_CIPHER_nid(to->incipher) : 0, + to->indigest ? EVP_MD_type(to->indigest) : 0, to->inmaclength, + to->incompression); } -bool ans_key_h(connection_t *c, const char *request) { +bool ans_key_h(connection_t *c) { char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; char key[MAX_STRING_SIZE]; char address[MAX_STRING_SIZE] = ""; char port[MAX_STRING_SIZE] = ""; - int cipher, digest, maclength, compression, keylen; + int cipher, digest, maclength, compression; node_t *from, *to; - if(sscanf(request, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING, - from_name, to_name, key, &cipher, &digest, &maclength, - &compression, address, port) < 7) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name, - c->hostname); + if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING, + from_name, to_name, key, &cipher, &digest, &maclength, + &compression, address, port) < 7) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name, + c->hostname); return false; } if(!check_id(from_name) || !check_id(to_name)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name"); + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name"); return false; } from = lookup_node(from_name); if(!from) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", - "ANS_KEY", c->name, c->hostname, from_name); + logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list", + "ANS_KEY", c->name, c->hostname, from_name); return true; } to = lookup_node(to_name); if(!to) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", - "ANS_KEY", c->name, c->hostname, to_name); + logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list", + "ANS_KEY", c->name, c->hostname, to_name); return true; } /* Forward it if necessary */ if(to != myself) { - if(tunnelserver) - return true; - - if(!to->status.reachable) { - logger(DEBUG_ALWAYS, LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable", - "ANS_KEY", c->name, c->hostname, to_name); + if(tunnelserver) { return true; } - if(!*address && from->address.sa.sa_family != AF_UNSPEC) { + if(!to->status.reachable) { + logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable", + "ANS_KEY", c->name, c->hostname, to_name); + return true; + } + + if(!*address && from->address.sa.sa_family != AF_UNSPEC && to->minmtu) { char *address, *port; - logger(DEBUG_PROTOCOL, LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name); + ifdebug(PROTOCOL) logger(LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name); sockaddr2str(&from->address, &address, &port); - send_request(to->nexthop->connection, "%s %s %s", request, address, port); + send_request(to->nexthop->connection, "%s %s %s", c->buffer, address, port); free(address); free(port); return true; } - return send_request(to->nexthop->connection, "%s", request); + return send_request(to->nexthop->connection, "%s", c->buffer); } /* Don't use key material until every check has passed. */ - cipher_close(from->outcipher); - digest_close(from->outdigest); from->status.validkey = false; - if(compression < 0 || compression > 11) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname); - return true; - } - - from->outcompression = compression; - - /* SPTPS or old-style key exchange? */ - - if(from->status.sptps) { - char buf[strlen(key)]; - int len = b64decode(key, buf, strlen(key)); - - if(!len || !sptps_receive_data(&from->sptps, buf, len)) - logger(DEBUG_ALWAYS, LOG_ERR, "Error processing SPTPS data from %s (%s)", from->name, from->hostname); - - if(from->status.validkey) { - if(*address && *port) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); - sockaddr_t sa = str2sockaddr(address, port); - update_node_udp(from, &sa); - } - - if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY)) - send_mtu_probe(from); - } + /* Update our copy of the origin's packet key */ + from->outkey = xrealloc(from->outkey, strlen(key) / 2); + from->outkeylength = strlen(key) / 2; + if(!hex2bin(key, from->outkey, from->outkeylength)) { + logger(LOG_ERR, "Got bad %s from %s(%s): %s", "ANS_KEY", from->name, from->hostname, "invalid key"); return true; } /* Check and lookup cipher and digest algorithms */ - if(!(from->outcipher = cipher_open_by_nid(cipher))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname); - return false; + if(cipher) { + from->outcipher = EVP_get_cipherbynid(cipher); + + if(!from->outcipher) { + logger(LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, + from->hostname); + return true; + } + + if(from->outkeylength != EVP_CIPHER_key_length(from->outcipher) + EVP_CIPHER_iv_length(from->outcipher)) { + logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, + from->hostname); + return true; + } + } else { + if(from->outkeylength != 1) { + logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname); + return true; + } + + from->outcipher = NULL; } - if(!(from->outdigest = digest_open_by_nid(digest, maclength))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname); - return false; + from->outmaclength = maclength; + + if(digest) { + from->outdigest = EVP_get_digestbynid(digest); + + if(!from->outdigest) { + logger(LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, + from->hostname); + return true; + } + + if(from->outmaclength > EVP_MD_size(from->outdigest) || from->outmaclength < 0) { + logger(LOG_ERR, "Node %s (%s) uses bogus MAC length!", + from->name, from->hostname); + return true; + } + } else { + from->outdigest = NULL; } - if(maclength != digest_length(from->outdigest)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname); - return false; - } - - /* Process key */ - - keylen = hex2bin(key, key, sizeof key); - - if(keylen != cipher_keylength(from->outcipher)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname); + if(compression < 0 || compression > 11) { + logger(LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname); return true; } - /* Update our copy of the origin's packet key */ + from->outcompression = compression; - if(!cipher_set_key(from->outcipher, key, true)) - return false; - if(!digest_set_key(from->outdigest, key, keylen)) - return false; + if(from->outcipher) + if(!EVP_EncryptInit_ex(from->outctx, from->outcipher, NULL, (unsigned char *)from->outkey, (unsigned char *)from->outkey + EVP_CIPHER_key_length(from->outcipher))) { + logger(LOG_ERR, "Error during initialisation of key from %s (%s): %s", + from->name, from->hostname, ERR_error_string(ERR_get_error(), NULL)); + return true; + } from->status.validkey = true; from->sent_seqno = 0; if(*address && *port) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); + ifdebug(PROTOCOL) logger(LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); sockaddr_t sa = str2sockaddr(address, port); update_node_udp(from, &sa); } - if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY)) + if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent) { send_mtu_probe(from); + } return true; } diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 022438e..904ac3f 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -1,7 +1,7 @@ /* protocol_misc.c -- handle the meta-protocol, miscellaneous functions Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2012 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,70 +31,14 @@ int maxoutbufsize = 0; -/* Status and error notification routines */ - -bool send_status(connection_t *c, int statusno, const char *statusstring) { - if(!statusstring) - statusstring = "Status"; - - return send_request(c, "%d %d %s", STATUS, statusno, statusstring); -} - -bool status_h(connection_t *c, const char *request) { - int statusno; - char statusstring[MAX_STRING_SIZE]; - - if(sscanf(request, "%*d %d " MAX_STRING, &statusno, statusstring) != 2) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "STATUS", - c->name, c->hostname); - return false; - } - - logger(DEBUG_STATUS, LOG_NOTICE, "Status message from %s (%s): %d: %s", - c->name, c->hostname, statusno, statusstring); - - return true; -} - -bool send_error(connection_t *c, int err, const char *errstring) { - if(!errstring) - errstring = "Error"; - - return send_request(c, "%d %d %s", ERROR, err, errstring); -} - -bool error_h(connection_t *c, const char *request) { - int err; - char errorstring[MAX_STRING_SIZE]; - - if(sscanf(request, "%*d %d " MAX_STRING, &err, errorstring) != 2) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ERROR", - c->name, c->hostname); - return false; - } - - logger(DEBUG_ERROR, LOG_NOTICE, "Error message from %s (%s): %d: %s", - c->name, c->hostname, err, errorstring); - - return false; -} - -bool send_termreq(connection_t *c) { - return send_request(c, "%d", TERMREQ); -} - -bool termreq_h(connection_t *c, const char *request) { - return false; -} - bool send_ping(connection_t *c) { c->status.pinged = true; - c->last_ping_time = now.tv_sec; + c->last_ping_time = now; return send_request(c, "%d", PING); } -bool ping_h(connection_t *c, const char *request) { +bool ping_h(connection_t *c) { return send_pong(c); } @@ -102,16 +46,19 @@ bool send_pong(connection_t *c) { return send_request(c, "%d", PONG); } -bool pong_h(connection_t *c, const char *request) { +bool pong_h(connection_t *c) { c->status.pinged = false; - /* Succesful connection, reset timeout if this is an outgoing connection. */ + /* Successful connection, reset timeout if this is an outgoing connection. */ if(c->outgoing) { c->outgoing->timeout = 0; c->outgoing->cfg = NULL; - if(c->outgoing->ai) + + if(c->outgoing->ai) { freeaddrinfo(c->outgoing->ai); + } + c->outgoing->ai = NULL; c->outgoing->aip = NULL; } @@ -125,21 +72,23 @@ bool send_tcppacket(connection_t *c, const vpn_packet_t *packet) { /* If there already is a lot of data in the outbuf buffer, discard this packet. We use a very simple Random Early Drop algorithm. */ - if(2.0 * c->outbuf.len / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX) + if(2.0 * c->outbuflen / (float)maxoutbufsize - 1 > (float)rand() / (float)RAND_MAX) { return true; + } - if(!send_request(c, "%d %hd", PACKET, packet->len)) + if(!send_request(c, "%d %hd", PACKET, packet->len)) { return false; + } - return send_meta(c, (char *)packet->data, packet->len); + return send_meta(c, (char *)packet->data, packet->len) && flush_meta(c); } -bool tcppacket_h(connection_t *c, const char *request) { - short int len; +bool tcppacket_h(connection_t *c) { + length_t len; - if(sscanf(request, "%*d %hd", &len) != 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "PACKET", c->name, - c->hostname); + if(sscanf(c->buffer, "%*d %hu", &len) != 1) { + logger(LOG_ERR, "Got bad %s from %s (%s)", "PACKET", c->name, + c->hostname); return false; } diff --git a/src/protocol_subnet.c b/src/protocol_subnet.c index 06dafbc..2c4d08f 100644 --- a/src/protocol_subnet.c +++ b/src/protocol_subnet.c @@ -1,7 +1,7 @@ /* protocol_subnet.c -- handle the meta-protocol, subnets Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2012 Guus Sliepen + 2000-2009 Guus Sliepen 2009 Michael Tokarev This program is free software; you can redistribute it and/or modify @@ -35,42 +35,44 @@ bool send_add_subnet(connection_t *c, const subnet_t *subnet) { char netstr[MAXNETSTR]; - if(!net2str(netstr, sizeof netstr, subnet)) + 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) { +bool add_subnet_h(connection_t *c) { char subnetstr[MAX_STRING_SIZE]; char name[MAX_STRING_SIZE]; node_t *owner; - subnet_t s = {NULL}, *new, *old; + subnet_t s = {0}, *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); + if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) { + logger(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"); + logger(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"); + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_SUBNET", c->name, + c->hostname, "invalid subnet string"); return false; } - if(seen_request(request)) + if(seen_request(c->buffer)) { return true; + } /* Check if the owner of the new subnet is in the connection list */ @@ -78,8 +80,8 @@ bool add_subnet_h(connection_t *c, const char *request) { 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); + ifdebug(PROTOCOL) logger(LOG_WARNING, "Ignoring indirect %s from %s (%s) for %s", + "ADD_SUBNET", c->name, c->hostname, subnetstr); return true; } @@ -91,14 +93,15 @@ bool add_subnet_h(connection_t *c, const char *request) { /* Check if we already know this subnet */ - if(lookup_subnet(owner, &s)) + 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); + ifdebug(PROTOCOL) logger(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; @@ -107,17 +110,17 @@ bool add_subnet_h(connection_t *c, const char *request) { /* 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); + logger(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); + logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s", + "ADD_SUBNET", c->name, c->hostname, subnetstr); + forward_request(c); return true; } @@ -126,18 +129,19 @@ bool add_subnet_h(connection_t *c, const char *request) { *(new = new_subnet()) = s; subnet_add(owner, new); - if(owner->status.reachable) + if(owner->status.reachable) { subnet_update(owner, new, true); + } /* Tell the rest */ - if(!tunnelserver) - forward_request(c, request); + forward_request(c); /* Fast handoff of roaming MAC addresses */ - if(s.type == SUBNET_MAC && owner != myself && (old = lookup_subnet(myself, &s)) && old->expires) - old->expires = 1; + if(s.type == SUBNET_MAC && owner != myself && (old = lookup_subnet(myself, &s)) && old->expires) { + old->expires = now; + } return true; } @@ -145,42 +149,44 @@ bool add_subnet_h(connection_t *c, const char *request) { bool send_del_subnet(connection_t *c, const subnet_t *s) { char netstr[MAXNETSTR]; - if(!net2str(netstr, sizeof netstr, s)) + 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) { +bool del_subnet_h(connection_t *c) { char subnetstr[MAX_STRING_SIZE]; char name[MAX_STRING_SIZE]; node_t *owner; - subnet_t s = {NULL}, *find; + subnet_t s = {0}, *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); + if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) { + logger(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"); + logger(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"); + logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_SUBNET", c->name, + c->hostname, "invalid subnet string"); return false; } - if(seen_request(request)) + if(seen_request(c->buffer)) { return true; + } /* Check if the owner of the subnet being deleted is in the connection list */ @@ -188,14 +194,14 @@ bool del_subnet_h(connection_t *c, const char *request) { 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); + ifdebug(PROTOCOL) logger(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); + ifdebug(PROTOCOL) logger(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; } @@ -206,36 +212,42 @@ bool del_subnet_h(connection_t *c, const char *request) { 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); + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for %s which does not appear in his subnet tree", + "DEL_SUBNET", c->name, c->hostname, name); + + if(strictsubnets) { + forward_request(c); + } + return true; } /* 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); + ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself", + "DEL_SUBNET", c->name, c->hostname); send_add_subnet(c, find); return true; } - if(tunnelserver) + if(tunnelserver) { return true; + } /* Tell the rest */ - if(!tunnelserver) - forward_request(c, request); - if(strictsubnets) + forward_request(c); + + if(strictsubnets) { return true; + } /* Finally, delete it. */ - if(owner->status.reachable) + if(owner->status.reachable) { subnet_update(owner, find, false); + } subnet_del(owner, find); diff --git a/src/proxy.c b/src/proxy.c new file mode 100644 index 0000000..979626c --- /dev/null +++ b/src/proxy.c @@ -0,0 +1,366 @@ +/* + proxy.c -- Proxy handling functions. + Copyright (C) 2015-2017 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "system.h" + +#include "connection.h" +#include "logger.h" +#include "meta.h" +#include "netutl.h" +#include "protocol.h" +#include "proxy.h" +#include "utils.h" // + +proxytype_t proxytype; +char *proxyhost; +char *proxyport; +char *proxyuser; +char *proxypass; + +static void update_address_ipv4(connection_t *c, void *address, void *port) { + sockaddrfree(&c->address); + memset(&c->address, 0, sizeof(c->address)); + c->address.sa.sa_family = AF_INET; + + if(address) { + memcpy(&c->address.in.sin_addr, address, sizeof(ipv4_t)); + } + + if(port) { + memcpy(&c->address.in.sin_port, port, sizeof(uint16_t)); + } + + // OpenSSH -D returns all zero address, set it to 0.0.0.1 to prevent spamming ourselves. + if(!memcmp(&c->address.in.sin_addr, "\0\0\0\0", 4)) { + memcpy(&c->address.in.sin_addr, "\0\0\0\01", 4); + } +} + +static void update_address_ipv6(connection_t *c, void *address, void *port) { + sockaddrfree(&c->address); + memset(&c->address, 0, sizeof(c->address)); + c->address.sa.sa_family = AF_INET6; + + if(address) { + memcpy(&c->address.in6.sin6_addr, address, sizeof(ipv6_t)); + } + + if(port) { + memcpy(&c->address.in6.sin6_port, port, sizeof(uint16_t)); + } + + // OpenSSH -D returns all zero address, set it to 0100:: to prevent spamming ourselves. + if(!memcmp(&c->address.in6.sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)) { + memcpy(&c->address.in6.sin6_addr, "\01\0\0\0\0\0\0\0", 8); + } +} + +bool send_proxyrequest(connection_t *c) { + switch(proxytype) { + case PROXY_SOCKS4: + if(c->address.sa.sa_family != AF_INET) { + logger(LOG_ERR, "Can only connect to numeric IPv4 addresses through a SOCKS 4 proxy!"); + return false; + } + + // fallthrough + case PROXY_SOCKS4A: { + if(c->address.sa.sa_family != AF_INET && c->address.sa.sa_family != AF_UNKNOWN) { + logger(LOG_ERR, "Can only connect to IPv4 addresses or hostnames through a SOCKS 4a proxy!"); + return false; + } + + int len = 9; + + if(proxyuser) { + len += strlen(proxyuser); + } + + if(c->address.sa.sa_family == AF_UNKNOWN) { + len += 1 + strlen(c->address.unknown.address); + } + + char s4req[len]; + s4req[0] = 4; + s4req[1] = 1; + + if(c->address.sa.sa_family == AF_INET) { + memcpy(s4req + 2, &c->address.in.sin_port, 2); + memcpy(s4req + 4, &c->address.in.sin_addr, 4); + } else { + uint16_t port = htons(atoi(c->address.unknown.port)); + memcpy(s4req + 2, &port, 2); + memcpy(s4req + 4, "\0\0\0\1", 4); + strcpy(s4req + (9 + (proxyuser ? strlen(proxyuser) : 0)), c->address.unknown.address); + } + + if(proxyuser) { + strcpy(s4req + 8, proxyuser); + } else { + s4req[8] = 0; + } + + s4req[sizeof(s4req) - 1] = 0; + c->allow_request = PROXY; + return send_meta(c, s4req, sizeof(s4req)); + } + + case PROXY_SOCKS5: { + int len = 3 + 6; + + if(c->address.sa.sa_family == AF_INET) { + len += 4; + } else if(c->address.sa.sa_family == AF_INET6) { + len += 16; + } else if(c->address.sa.sa_family == AF_UNKNOWN) { + len += 1 + strlen(c->address.unknown.address); + } else { + logger(LOG_ERR, "Address family %x not supported for SOCKS 5 proxies!", c->address.sa.sa_family); + return false; + } + + if(proxypass) { + len += 3 + strlen(proxyuser) + strlen(proxypass); + } + + char s5req[len]; + int i = 0; + s5req[i++] = 5; + s5req[i++] = 1; + + if(proxypass) { + s5req[i++] = 2; + s5req[i++] = 1; + s5req[i++] = strlen(proxyuser); + strcpy(s5req + i, proxyuser); + i += strlen(proxyuser); + s5req[i++] = strlen(proxypass); + strcpy(s5req + i, proxypass); + i += strlen(proxypass); + } else { + s5req[i++] = 0; + } + + s5req[i++] = 5; + s5req[i++] = 1; + s5req[i++] = 0; + + if(c->address.sa.sa_family == AF_INET) { + s5req[i++] = 1; + memcpy(s5req + i, &c->address.in.sin_addr, 4); + i += 4; + memcpy(s5req + i, &c->address.in.sin_port, 2); + i += 2; + } else if(c->address.sa.sa_family == AF_INET6) { + s5req[i++] = 4; + memcpy(s5req + i, &c->address.in6.sin6_addr, 16); + i += 16; + memcpy(s5req + i, &c->address.in6.sin6_port, 2); + i += 2; + } else if(c->address.sa.sa_family == AF_UNKNOWN) { + s5req[i++] = 3; + int len = strlen(c->address.unknown.address); + s5req[i++] = len; + memcpy(s5req + i, c->address.unknown.address, len); + i += len; + uint16_t port = htons(atoi(c->address.unknown.port)); + memcpy(s5req + i, &port, 2); + i += 2; + } else { + logger(LOG_ERR, "Unknown address family while trying to connect to SOCKS5 proxy"); + return false; + } + + if(i > len) { + abort(); + } + + c->allow_request = PROXY; + return send_meta(c, s5req, sizeof(s5req)); + } + + case PROXY_HTTP: { + char *host; + char *port; + + sockaddr2str(&c->address, &host, &port); + send_request(c, "CONNECT %s:%s HTTP/1.1\r\n\r", host, port); + free(host); + free(port); + c->allow_request = PROXY; + return true; + } + + case PROXY_EXEC: + abort(); + + default: + logger(LOG_ERR, "Unknown proxy type"); + return false; + } +} + +int receive_proxy_meta(connection_t *c) { + switch(proxytype) { + case PROXY_SOCKS4: + case PROXY_SOCKS4A: + if(c->buflen < 8) { + return 0; + } + + if(c->buffer[0] == 0 && c->buffer[1] == 0x5a) { + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv4(c, c->buffer + 4, c->buffer + 2); + } + + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted"); + c->allow_request = ID; + c->status.proxy_passed = true; + send_id(c); + return 8; + } else { + logger(LOG_ERR, "Proxy request rejected"); + return -1; + } + + case PROXY_SOCKS5: + if(c->buflen < 2) { + return 0; + } + + if(c->buffer[0] != 0x05 || c->buffer[1] == (char)0xff) { + logger(LOG_ERR, "Proxy authentication method rejected"); + return -1; + } + + int offset = 2; + + if(c->buffer[1] == 0x02) { + if(c->buflen < 4) { + return 0; + } + + if(c->buffer[2] != 0x05 || c->buffer[3] != 0x00) { + logger(LOG_ERR, "Proxy username/password rejected"); + return -1; + } + + offset += 2; + } + + if(c->buflen - offset < 7) { + return 0; + } + + if(c->buffer[offset] != 0x05 || c->buffer[offset + 1] != 0x00) { + logger(LOG_ERR, "Proxy request rejected"); + return -1; + } + + int replen = offset + 6; + + switch(c->buffer[offset + 3]) { + case 0x01: // IPv4 + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv4(c, c->buffer + offset + 4, c->buffer + offset + 8); + } + + replen += 4; + break; + + case 0x03: // Hostname + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv4(c, "\0\0\0\1", "\0\0"); + } + + replen += ((uint8_t *)c->buffer)[offset + 4]; + break; + + case 0x04: // IPv6 + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv6(c, c->buffer + offset + 4, c->buffer + offset + 20); + } + + replen += 16; + break; + + default: + logger(LOG_ERR, "Proxy reply malformed"); + return -1; + } + + if(c->buflen < replen) { + return 0; + } else { + ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted"); + c->allow_request = ID; + c->status.proxy_passed = true; + send_id(c); + return replen; + } + + case PROXY_HTTP: { + char *p = memchr(c->buffer, '\n', c->buflen); + + if(!p || p - c->buffer >= c->buflen) { + return 0; + } + + while((p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer)))) { + if(p > c->buffer + 3 && !memcmp(p - 3, "\r\n\r\n", 4)) { + break; + } + } + + if(!p) { + return 0; + } + + if(c->buflen < 9) { + return 0; + } + + if(!strncasecmp(c->buffer, "HTTP/1.1 ", 9)) { + if(!strncmp(c->buffer + 9, "200", 3)) { + if(c->address.sa.sa_family == AF_UNKNOWN) { + update_address_ipv4(c, "\0\0\0\1", "\0\0"); + } + + logger(LOG_DEBUG, "Proxy request granted"); + replen = p + 1 - c->buffer; + c->allow_request = ID; + c->status.proxy_passed = true; + send_id(c); + return replen; + } else { + p = memchr(c->buffer, '\n', c->buflen); + p[-1] = 0; + logger(LOG_ERR, "Proxy request rejected: %s", c->buffer + 9); + return false; + } + } else { + logger(LOG_ERR, "Proxy reply malformed"); + return -1; + } + } + + default: + abort(); + } +} diff --git a/src/ecdh.h b/src/proxy.h similarity index 58% rename from src/ecdh.h rename to src/proxy.h index fbd4729..a96fc3d 100644 --- a/src/ecdh.h +++ b/src/proxy.h @@ -1,6 +1,9 @@ +#ifndef TINC_PROXY_H +#define TINC_PROXY_H + /* - ecdh.h -- header file for ecdh.c - Copyright (C) 2011-2013 Guus Sliepen + proxy.h -- header for proxy.c + Copyright (C) 2015 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,18 +20,24 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_ECDH_H__ -#define __TINC_ECDH_H__ +#include "connection.h" -#define ECDH_SIZE 67 -#define ECDH_SHARED_SIZE 66 +typedef enum proxytype_t { + PROXY_NONE = 0, + PROXY_SOCKS4, + PROXY_SOCKS4A, + PROXY_SOCKS5, + PROXY_HTTP, + PROXY_EXEC, +} proxytype_t; -#ifndef __TINC_ECDH_INTERNAL__ -typedef struct ecdh ecdh_t; -#endif +extern proxytype_t proxytype; +extern char *proxyhost; +extern char *proxyport; +extern char *proxyuser; +extern char *proxypass; -extern ecdh_t *ecdh_generate_public(void *pubkey) __attribute__ ((__malloc__)); -extern bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) __attribute__ ((__warn_unused_result__)); -extern void ecdh_free(ecdh_t *ecdh); +extern bool send_proxyrequest(struct connection_t *c); +extern int receive_proxy_meta(struct connection_t *c); #endif diff --git a/src/raw_socket_device.c b/src/raw_socket_device.c index 48954d5..f4ed694 100644 --- a/src/raw_socket_device.c +++ b/src/raw_socket_device.c @@ -1,7 +1,7 @@ /* device.c -- raw socket Copyright (C) 2002-2005 Ivo Timmermans, - 2002-2012 Guus Sliepen + 2002-2014 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,8 +32,8 @@ #include "route.h" #include "xalloc.h" -#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET) -static char *device_info; +#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET) && defined(SIOCGIFINDEX) +static const char *device_info = "raw_socket"; static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; @@ -42,45 +42,45 @@ static bool setup_device(void) { struct ifreq ifr; struct sockaddr_ll sa; - if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) + 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); + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + device = xstrdup(iface); + } + + if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) { + logger(LOG_ERR, "Could not open %s: %s", device_info, + strerror(errno)); + return false; + } #ifdef FD_CLOEXEC fcntl(device_fd, F_SETFD, FD_CLOEXEC); #endif + memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ); + ifr.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = 0; + if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) { close(device_fd); - logger(DEBUG_ALWAYS, LOG_ERR, "Can't find interface %s: %s", iface, - strerror(errno)); + logger(LOG_ERR, "Can't find interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno)); return false; } - memset(&sa, '0', sizeof sa); + 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)); + if(bind(device_fd, (struct sockaddr *) &sa, (socklen_t) sizeof(sa))) { + logger(LOG_ERR, "Could not bind %s to %s: %s", device, ifr.ifr_ifrn.ifrn_name, strerror(errno)); return false; } - logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info); + logger(LOG_INFO, "%s is a %s", device, device_info); return true; } @@ -93,31 +93,31 @@ static void close_device(void) { } static bool read_packet(vpn_packet_t *packet) { - int inlen; + int lenin; - 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)); + if((lenin = read(device_fd, packet->data, MTU)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); return false; } - packet->len = inlen; + packet->len = lenin; device_total_in += packet->len; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, - device_info); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); return true; } static bool write_packet(vpn_packet_t *packet) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", - packet->len, device_info); + ifdebug(TRAFFIC) logger(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)); + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, + strerror(errno)); return false; } @@ -127,9 +127,9 @@ static bool write_packet(vpn_packet_t *packet) { } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t raw_socket_devops = { @@ -143,7 +143,7 @@ const devops_t raw_socket_devops = { #else static bool not_supported(void) { - logger(DEBUG_ALWAYS, LOG_ERR, "Raw socket device not supported on this platform"); + logger(LOG_ERR, "Raw socket device not supported on this platform"); return false; } diff --git a/src/route.c b/src/route.c index 00ba4c0..f8b11bb 100644 --- a/src/route.c +++ b/src/route.c @@ -1,7 +1,8 @@ /* route.c -- routing Copyright (C) 2000-2005 Ivo Timmermans, - 2000-2013 Guus Sliepen + 2000-2017 Guus Sliepen + 2015-2016 Vittorio Gambaletta This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,13 +21,12 @@ #include "system.h" +#include "avl_tree.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" @@ -42,7 +42,6 @@ bool priorityinheritance = false; int macexpire = 600; bool overwrite_mac = false; mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}}; -bool pcap = false; /* Sizes of various headers */ @@ -59,8 +58,6 @@ static const size_t opt_size = sizeof(struct nd_opt_hdr); #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) { @@ -72,11 +69,13 @@ static uint16_t inet_checksum(void *data, int len, uint16_t prevsum) { len -= 2; } - if(len) + if(len) { checksum += *(uint8_t *)p; + } - while(checksum >> 16) + while(checksum >> 16) { checksum = (checksum & 0xFFFF) + (checksum >> 16); + } return ~checksum; } @@ -85,11 +84,12 @@ static bool ratelimit(int frequency) { static time_t lasttime = 0; static int count = 0; - if(lasttime == now.tv_sec) { - if(count >= frequency) + if(lasttime == now) { + if(count >= frequency) { return true; + } } else { - lasttime = now.tv_sec; + lasttime = now; count = 0; } @@ -99,153 +99,18 @@ static bool ratelimit(int frequency) { static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) { if(packet->len < length) { - logger(DEBUG_TRAFFIC, LOG_WARNING, "Got too short packet from %s (%s)", source->name, source->hostname); + ifdebug(TRAFFIC) logger(LOG_WARNING, "Got too short packet from %s (%s)", source->name, source->hostname); return false; - } else + } else { 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; - } + memcpy(&tmp, &packet->data[0], sizeof(tmp)); + memcpy(&packet->data[0], &packet->data[6], sizeof(tmp)); + memcpy(&packet->data[6], &tmp, sizeof(tmp)); } /* RFC 792 */ @@ -258,8 +123,9 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_ struct in_addr ip_dst; uint32_t oldlen; - if(ratelimit(3)) + if(ratelimit(3)) { return; + } /* Swap Ethernet source and destination addresses */ @@ -274,13 +140,40 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_ ip_src = ip.ip_src; ip_dst = ip.ip_dst; + /* Try to reply with an IP address assigned to the local machine */ + + if(type == ICMP_TIME_EXCEEDED && code == ICMP_EXC_TTL) { + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + if(sockfd != -1) { + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr = ip.ip_src; + + if(!connect(sockfd, (const struct sockaddr *) &addr, sizeof(addr))) { + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + socklen_t addrlen = sizeof(addr); + + if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) { + ip_dst = addr.sin_addr; + } + } + + close(sockfd); + } + } + oldlen = packet->len - ether_size; - if(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) + 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) + if(oldlen >= IP_MSS - ip_size - icmp_size) { oldlen = IP_MSS - ip_size - icmp_size; + } /* Copy first part of original contents to ICMP message */ @@ -321,6 +214,347 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, length_ send_packet(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; + + /* Try to reply with an IP address assigned to the local machine */ + + if(type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) { + int sockfd = socket(AF_INET6, SOCK_DGRAM, 0); + + if(sockfd != -1) { + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr = ip6.ip6_src; + + if(!connect(sockfd, (const struct sockaddr *) &addr, sizeof(addr))) { + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + socklen_t addrlen = sizeof(addr); + + if(!getsockname(sockfd, (struct sockaddr *) &addr, &addrlen) && addrlen <= sizeof(addr)) { + pseudo.ip6_src = addr.sin6_addr; + } + } + + close(sockfd); + } + } + + 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 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; + } +} + +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; + uint32_t csum = packet->data[start + 16] << 8 | packet->data[start + 17]; + + if(oldmss <= newmss) { + break; + } + + ifdebug(TRAFFIC) logger(LOG_INFO, "Clamping MSS of packet from %s to %s to %d", source->name, via->name, newmss); + + /* Update the MSS value and the checksum */ + packet->data[start + 22 + i] = newmss >> 8; + packet->data[start + 23 + i] = newmss & 0xff; + csum ^= 0xffff; + csum += oldmss ^ 0xffff; + csum += newmss; + csum = (csum & 0xffff) + (csum >> 16); + csum += csum >> 16; + csum ^= 0xffff; + packet->data[start + 16] = csum >> 8; + packet->data[start + 17] = csum; + break; + } +} + +static void learn_mac(mac_t *address) { + subnet_t *subnet; + avl_node_t *node; + connection_t *c; + + subnet = lookup_subnet_mac(myself, address); + + /* If we don't know this MAC address yet, store it */ + + if(!subnet) { + ifdebug(TRAFFIC) logger(LOG_INFO, "Learned new MAC address %x:%x:%x:%x:%x:%x", + 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 + 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(node = connection_tree->head; node; node = node->next) { + c = node->data; + + if(c->status.active) { + send_add_subnet(c, subnet); + } + } + } + + if(subnet->expires) { + subnet->expires = now + macexpire; + } +} + +void age_subnets(void) { + subnet_t *s; + connection_t *c; + avl_node_t *node, *next, *node2; + + for(node = myself->subnet_tree->head; node; node = next) { + next = node->next; + s = node->data; + + if(s->expires && s->expires <= now) { + ifdebug(TRAFFIC) { + char netstr[MAXNETSTR]; + + if(net2str(netstr, sizeof(netstr), s)) { + logger(LOG_INFO, "Subnet %s expired", netstr); + } + } + + for(node2 = connection_tree->head; node2; node2 = node2->next) { + c = node2->data; + + if(c->status.active) { + send_del_subnet(c, s); + } + } + + subnet_update(myself, s, false); + subnet_del(myself, s); + } + } +} + +static void route_broadcast(node_t *source, vpn_packet_t *packet) { + if(decrement_ttl && source != myself) + if(!do_decrement_ttl(source, packet)) { + return; + } + + broadcast_packet(source, packet); +} + /* RFC 791 */ static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t ether_size) { @@ -333,20 +567,21 @@ static void fragment_ipv4_packet(node_t *dest, vpn_packet_t *packet, length_t et memcpy(&ip, packet->data + ether_size, ip_size); fragment.priority = packet->priority; - if(ip.ip_hl != ip_size / 4) + 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)); + ifdebug(TRAFFIC) logger(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); + ifdebug(TRAFFIC) logger(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; + maxlen = (MAX(dest->mtu, 590) - ether_size - ip_size) & ~0x7; ip_off = ntohs(ip.ip_off); origf = ip_off & ~IP_OFFMASK; ip_off &= IP_OFFMASK; @@ -376,47 +611,60 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) { node_t *via; ipv4_t dest; - memcpy(&dest, &packet->data[30], sizeof 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]); + ifdebug(TRAFFIC) logger(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); + ifdebug(TRAFFIC) logger(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(!subnet->owner->status.reachable) { + route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_UNREACH); + return; + } - 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(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) { + route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO); + return; + } - if(priorityinheritance) + if(decrement_ttl && source != myself && subnet->owner != myself) + if(!do_decrement_ttl(source, packet)) { + return; + } + + 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); + ifdebug(TRAFFIC) logger(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(directonly && subnet->owner != via) { + route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_NET_ANO); + return; + } 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); + ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); + if(packet->data[20] & 0x40) { packet->len = MAX(via->mtu, 590); route_ipv4_unreachable(source, packet, ether_size, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); @@ -433,97 +681,19 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) { } static void route_ipv4(node_t *source, vpn_packet_t *packet) { - if(!checklength(source, packet, ether_size + ip_size)) + if(!checklength(source, packet, ether_size + ip_size)) { return; + } 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 + packet->data[30] == 255 && + packet->data[31] == 255 && + packet->data[32] == 255 && + packet->data[33] == 255))) { + route_broadcast(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) { @@ -531,48 +701,64 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) { node_t *via; ipv6_t dest; - memcpy(&dest, &packet->data[38], sizeof 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])); + ifdebug(TRAFFIC) logger(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); + ifdebug(TRAFFIC) logger(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(!subnet->owner->status.reachable) { + route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE); + return; + } - 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); + if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) { + route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); + return; + } + + if(decrement_ttl && source != myself && subnet->owner != myself) { + if(!do_decrement_ttl(source, packet)) { + return; + } + } + + if(priorityinheritance) { + packet->priority = ((packet->data[14] & 0x0f) << 4) | (packet->data[15] >> 4); + } 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); + ifdebug(TRAFFIC) logger(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(directonly && subnet->owner != via) { + route_ipv6_unreachable(source, packet, ether_size, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN); + return; + } 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); + ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); packet->len = MAX(via->mtu, 1294); route_ipv6_unreachable(source, packet, ether_size, ICMP6_PACKET_TOO_BIG, 0); return; @@ -594,19 +780,20 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) { bool has_opt; struct { - struct in6_addr ip6_src; - struct in6_addr ip6_dst; + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ uint32_t length; uint32_t next; } pseudo; - if(!checklength(source, packet, ether_size + ip6_size + ns_size)) + 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); + ifdebug(TRAFFIC) logger(LOG_WARNING, "Got neighbor solicitation request from %s (%s) while in router mode!", source->name, source->hostname); return; } @@ -614,19 +801,22 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) { memcpy(&ip6, packet->data + ether_size, ip6_size); memcpy(&ns, packet->data + ether_size + ip6_size, ns_size); - if(has_opt) + + 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) + 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"); + (has_opt && opt.nd_opt_type != ND_OPT_SOURCE_LINKADDR)) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: received unknown type neighbor solicitation request"); return; } @@ -634,23 +824,27 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) { pseudo.ip6_src = ip6.ip6_src; pseudo.ip6_dst = ip6.ip6_dst; - if(has_opt) + + if(has_opt) { pseudo.length = htonl(ns_size + opt_size + ETH_ALEN); - else + } else { pseudo.length = htonl(ns_size); + } + pseudo.next = htonl(IPPROTO_ICMPV6); /* Generate checksum */ - checksum = inet_checksum(&pseudo, sizeof pseudo, ~0); + 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"); + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: checksum error for neighbor solicitation request"); return; } @@ -659,54 +853,65 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) { 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])); + ifdebug(TRAFFIC) logger(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 */ + if(subnet->owner == myself) { + return; /* silently ignore */ + } + + if(decrement_ttl) + if(!do_decrement_ttl(source, packet)) { + return; + } /* 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 */ + 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_dst = ip6.ip6_src; /* swap destination and source protocol 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 */ + 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 */ + 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) + + if(has_opt) { pseudo.length = htonl(ns_size + opt_size + ETH_ALEN); - else + } else { pseudo.length = htonl(ns_size); + } + pseudo.next = htonl(IPPROTO_ICMPV6); /* Generate checksum */ - checksum = inet_checksum(&pseudo, sizeof pseudo, ~0); + 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); @@ -718,25 +923,29 @@ static void route_neighborsol(node_t *source, vpn_packet_t *packet) { memcpy(packet->data + ether_size, &ip6, ip6_size); memcpy(packet->data + ether_size + ip6_size, &ns, ns_size); - if(has_opt) + + 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)) + 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 + if(broadcast_mode && packet->data[38] == 255) { + route_broadcast(source, packet); + } else { route_ipv6_unicast(source, packet); + } } /* RFC 826 */ @@ -746,18 +955,20 @@ static void route_arp(node_t *source, vpn_packet_t *packet) { subnet_t *subnet; struct in_addr addr; - if(!checklength(source, packet, ether_size + arp_size)) + 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); + ifdebug(TRAFFIC) logger(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) + if(overwrite_mac) { memcpy(mymac.x, packet->data + ETH_ALEN, ETH_ALEN); + } /* Copy headers from packet to structs on the stack */ @@ -766,8 +977,8 @@ static void route_arp(node_t *source, vpn_packet_t *packet) { /* 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"); + arp.arp_hln != ETH_ALEN || arp.arp_pln != sizeof(addr) || ntohs(arp.arp_op) != ARPOP_REQUEST) { + ifdebug(TRAFFIC) logger(LOG_WARNING, "Cannot route packet: received unknown type ARP request"); return; } @@ -776,26 +987,32 @@ static void route_arp(node_t *source, vpn_packet_t *packet) { 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]); + ifdebug(TRAFFIC) logger(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 */ + 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 */ + if(decrement_ttl) + if(!do_decrement_ttl(source, packet)) { + return; + } - 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(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(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 */ + 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 */ @@ -813,42 +1030,54 @@ static void route_mac(node_t *source, vpn_packet_t *packet) { if(source == myself) { mac_t src; - memcpy(&src, &packet->data[6], sizeof src); + memcpy(&src, &packet->data[6], sizeof(src)); learn_mac(&src); } /* Lookup destination address */ - memcpy(&dest, &packet->data[0], sizeof dest); + memcpy(&dest, &packet->data[0], sizeof(dest)); subnet = lookup_subnet_mac(NULL, &dest); if(!subnet) { - broadcast_packet(source, packet); + route_broadcast(source, packet); return; } if(subnet->owner == source) { - logger(DEBUG_TRAFFIC, LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname); + ifdebug(TRAFFIC) logger(LOG_WARNING, "Packet looping back to %s (%s)!", source->name, source->hostname); return; } - if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) + if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself) { return; + } + + if(decrement_ttl && source != myself && subnet->owner != myself) + if(!do_decrement_ttl(source, packet)) { + 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]; + if(priorityinheritance) { + if(type == ETH_P_IP && packet->len >= ether_size + ip_size) { + packet->priority = packet->data[15]; + } else if(type == ETH_P_IPV6 && packet->len >= ether_size + ip6_size) { + packet->priority = ((packet->data[14] & 0x0f) << 4) | (packet->data[15] >> 4); + } + } // Handle packets larger than PMTU node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; - if(directonly && 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); + ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu); length_t ethlen = 14; if(type == ETH_P_8021Q) { @@ -863,6 +1092,7 @@ static void route_mac(node_t *source, vpn_packet_t *packet) { } else { fragment_ipv4_packet(via, packet, ethlen); } + return; } else if(type == ETH_P_IPV6 && packet->len > 1280 + ethlen) { packet->len = via->mtu; @@ -876,120 +1106,46 @@ static void route_mac(node_t *source, vpn_packet_t *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)) + if(!checklength(source, packet, ether_size)) { return; + } - if(decrement_ttl && source != myself) - if(!do_decrement_ttl(source, packet)) - return; + switch(routing_mode) { + case RMODE_ROUTER: { + uint16_t type = packet->data[12] << 8 | packet->data[13]; - 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; - } + switch(type) { + case ETH_P_ARP: + route_arp(source, packet); break; - case RMODE_SWITCH: - route_mac(source, packet); + case ETH_P_IP: + route_ipv4(source, packet); break; - case RMODE_HUB: - broadcast_packet(source, packet); + case ETH_P_IPV6: + route_ipv6(source, packet); break; + + default: + ifdebug(TRAFFIC) logger(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: + route_broadcast(source, packet); + break; } } diff --git a/src/route.h b/src/route.h index a0121d7..5b9e808 100644 --- a/src/route.h +++ b/src/route.h @@ -1,3 +1,6 @@ +#ifndef TINC_ROUTE_H +#define TINC_ROUTE_H + /* route.h -- header file for route.c Copyright (C) 2000-2005 Ivo Timmermans @@ -18,9 +21,6 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_ROUTE_H__ -#define __TINC_ROUTE_H__ - #include "net.h" #include "node.h" @@ -50,10 +50,10 @@ extern bool directonly; extern bool overwrite_mac; extern bool priorityinheritance; extern int macexpire; -extern bool pcap; extern mac_t mymac; -extern void route(struct node_t *, struct vpn_packet_t *); +extern void age_subnets(void); +extern void route(struct node_t *source, struct vpn_packet_t *packet); -#endif /* __TINC_ROUTE_H__ */ +#endif diff --git a/src/rsa.h b/src/rsa.h deleted file mode 100644 index f4290d4..0000000 --- a/src/rsa.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - rsa.h -- RSA key handling - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_RSA_H__ -#define __TINC_RSA_H__ - -#ifndef __TINC_RSA_INTERNAL__ -typedef struct rsa rsa_t; -#endif - -extern void rsa_free(rsa_t *rsa); -extern rsa_t *rsa_set_hex_public_key(char *n, char *e) __attribute__ ((__malloc__)); -extern rsa_t *rsa_set_hex_private_key(char *n, char *e, char *d) __attribute__ ((__malloc__)); -extern rsa_t *rsa_read_pem_public_key(FILE *fp) __attribute__ ((__malloc__)); -extern rsa_t *rsa_read_pem_private_key(FILE *fp) __attribute__ ((__malloc__)); -extern size_t rsa_size(rsa_t *rsa); -extern bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) __attribute__ ((__warn_unused_result__)); -extern bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) __attribute__ ((__warn_unused_result__)); - -#endif diff --git a/src/rsagen.h b/src/rsagen.h deleted file mode 100644 index 58ce29f..0000000 --- a/src/rsagen.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - rsagen.h -- RSA key generation and export - Copyright (C) 2008-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_RSAGEN_H__ -#define __TINC_RSAGEN_H__ - -#include "rsa.h" - -extern rsa_t *rsa_generate(size_t bits, unsigned long exponent) __attribute__ ((__malloc__)); -extern bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) __attribute__ ((__warn_unused_result__)); -extern bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) __attribute__ ((__warn_unused_result__)); - -#endif diff --git a/src/solaris/.deps/device.Po b/src/solaris/.deps/device.Po deleted file mode 100644 index 9ce06a8..0000000 --- a/src/solaris/.deps/device.Po +++ /dev/null @@ -1 +0,0 @@ -# dummy diff --git a/src/solaris/device.c b/src/solaris/device.c index 21ce73f..fa2e6e6 100644 --- a/src/solaris/device.c +++ b/src/solaris/device.c @@ -1,7 +1,8 @@ /* device.c -- Interaction with Solaris tun device Copyright (C) 2001-2005 Ivo Timmermans, - 2001-2013 Guus Sliepen + 2002-2010 OpenVPN Technologies, Inc. + 2001-2017 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,103 +24,295 @@ #include #include -#include +#include #include "../conf.h" #include "../device.h" #include "../logger.h" -#include "../names.h" #include "../net.h" +#include "../route.h" #include "../utils.h" #include "../xalloc.h" -#define DEFAULT_DEVICE "/dev/tun" +#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" +#define IP_DEVICE "/dev/udp" + +static enum { + DEVICE_TYPE_TUN, + DEVICE_TYPE_TAP, +} device_type = DEVICE_TYPE_TUN; int device_fd = -1; -static int ip_fd = -1, if_fd = -1; +static int if_fd = -1; +static int ip_fd = -1; char *device = NULL; char *iface = NULL; -static char *device_info = NULL; +static const char *device_info = NULL; -static uint64_t device_total_in = 0; -static uint64_t device_total_out = 0; +uint64_t device_total_in = 0; +uint64_t device_total_out = 0; static bool setup_device(void) { - int ppa; - char *ptr; + char *type; - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = xstrdup(DEFAULT_DEVICE); + 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((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device, strerror(errno)); + 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(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"; + } + + if(device_type == DEVICE_TYPE_TAP && routing_mode == RMODE_ROUTER) { + overwrite_mac = true; + } + + /* The following is black magic copied from OpenVPN. */ + + if((ip_fd = open(IP_DEVICE, O_RDWR, 0)) < 0) { + logger(LOG_ERR, "Could not open %s: %s\n", IP_DEVICE, strerror(errno)); return false; } -#ifdef FD_CLOEXEC - fcntl(device_fd, F_SETFD, FD_CLOEXEC); -#endif + if((device_fd = open(device, O_RDWR, 0)) < 0) { + logger(LOG_ERR, "Could not open %s: %s\n", device, strerror(errno)); + return false; + } - ppa = 0; + /* Get unit number. */ - ptr = device; - while(*ptr && !isdigit((int) *ptr)) + char *ptr = device; + get_config_string(lookup_config(config_tree, "Interface"), &ptr); + + while(*ptr && !isdigit(*ptr)) { ptr++; - ppa = atoi(ptr); - - if((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not open /dev/ip: %s", strerror(errno)); - return false; } -#ifdef FD_CLOEXEC - fcntl(ip_fd, F_SETFD, FD_CLOEXEC); -#endif + int ppa = atoi(ptr); /* Assign a new PPA and get its unit number. */ - if((ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Can't assign new interface: %s", strerror(errno)); - return false; + + 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(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(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 twice: %s", device, - strerror(errno)); + logger(LOG_ERR, "Could not open %s: %s\n", device, strerror(errno)); return false; } -#ifdef FD_CLOEXEC - fcntl(if_fd, F_SETFD, FD_CLOEXEC); -#endif - if(ioctl(if_fd, I_PUSH, "ip") < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Can't push IP module: %s", strerror(errno)); + logger(LOG_ERR, "Could not push IP module onto %s %s!", device_info, device); return false; } - /* 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, "Can't set PPA %d: %s", ppa, strerror(errno)); + 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(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(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(LOG_ERR, "Could not set PPA %d on %s %s!", ppa, device_info, device); + return false; + } + + if(ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) { + logger(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(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(LOG_ERR, "Could not push ARP module onto %s!", IP_DEVICE); + return false; + } + + /* Open arp_fd */ + if((arp_fd = open(device, O_RDWR, 0)) < 0) { + logger(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(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(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(LOG_ERR, "Could not link %s %s to IP", device_info, device); return false; } - if(ioctl(ip_fd, I_LINK, if_fd) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Can't link TUN device to IP: %s", strerror(errno)); + if(device_type == DEVICE_TYPE_TAP) { + if((arp_muxid = ioctl(ip_fd, I_PLINK, arp_fd)) < 0) { + logger(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(LOG_ERR, "Could not set multiplexor id for %s %s", device_info, device); return false; } - if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) - xasprintf(&iface, "tun%d", ppa); + close(if_fd); - device_info = "Solaris tun device"; +#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); + logger(LOG_INFO, "%s is a %s", device, device_info); return true; } static void close_device(void) { - close(if_fd); + 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); @@ -128,49 +321,93 @@ static void close_device(void) { } static bool read_packet(vpn_packet_t *packet) { - int inlen; + int result; + struct strbuf sbuf; + int f = 0; - 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(device_type) { + case DEVICE_TYPE_TUN: + sbuf.maxlen = MTU - 14; + sbuf.buf = (char *)packet->data + 14; - switch(packet->data[14] >> 4) { + if((result = getmsg(device_fd, NULL, &sbuf, &f)) < 0) { + logger(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; + default: + ifdebug(TRAFFIC) logger(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 = sbuf.len + 14; + break; + + case DEVICE_TYPE_TAP: + sbuf.maxlen = MTU; + sbuf.buf = (char *)packet->data; + + if((result = getmsg(device_fd, NULL, &sbuf, &f)) < 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno)); + return false; + } + + packet->len = sbuf.len; + break; + + default: + abort(); + } device_total_in += packet->len; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, - device_info); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, device_info); return true; } static bool write_packet(vpn_packet_t *packet) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", - packet->len, device_info); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s", packet->len, device_info); - 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; + struct strbuf sbuf; + + switch(device_type) { + case DEVICE_TYPE_TUN: + sbuf.len = packet->len - 14; + sbuf.buf = (char *)packet->data + 14; + + if(putmsg(device_fd, NULL, &sbuf, 0) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); + return false; + } + + break; + + case DEVICE_TYPE_TAP: + sbuf.len = packet->len; + sbuf.buf = (char *)packet->data; + + if(putmsg(device_fd, NULL, &sbuf, 0) < 0) { + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); + return false; + } + + break; + + default: + abort(); } device_total_out += packet->len; @@ -179,9 +416,9 @@ static bool write_packet(vpn_packet_t *packet) { } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t os_devops = { diff --git a/src/splay_tree.c b/src/splay_tree.c deleted file mode 100644 index bd0f06b..0000000 --- a/src/splay_tree.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - splay_tree.c -- splay tree and linked list convenience - Copyright (C) 2004-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "splay_tree.h" -#include "xalloc.h" - -/* Splay operation */ - -static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *result) { - splay_node_t left = {NULL}, right = {NULL}; - splay_node_t *leftbottom = &left, *rightbottom = &right, *child, *grandchild; - splay_node_t *root = tree->root; - int c; - - if(!root) { - if(result) - *result = 0; - return NULL; - } - - while((c = tree->compare(data, root->data))) { - if(c < 0 && (child = root->left)) { - c = tree->compare(data, child->data); - - if(c < 0 && (grandchild = child->left)) { - rightbottom->left = child; - child->parent = rightbottom; - rightbottom = child; - - if((root->left = child->right)) - child->right->parent = root; - - child->right = root; - root->parent = child; - - child->left = NULL; - grandchild->parent = NULL; - - root = grandchild; - } else if (c > 0 && (grandchild = child->right)) { - leftbottom->right = child; - child->parent = leftbottom; - leftbottom = child; - - child->right = NULL; - grandchild->parent = NULL; - - rightbottom->left = root; - root->parent = rightbottom; - rightbottom = root; - - root->left = NULL; - - root = grandchild; - } else { - rightbottom->left = root; - root->parent = rightbottom; - rightbottom = root; - - root->left = NULL; - child->parent = NULL; - - root = child; - break; - } - } else if(c > 0 && (child = root->right)) { - c = tree->compare(data, child->data); - - if(c > 0 && (grandchild = child->right)) { - leftbottom->right = child; - child->parent = leftbottom; - leftbottom = child; - - if((root->right = child->left)) - child->left->parent = root; - - child->left = root; - root->parent = child; - - child->right = NULL; - grandchild->parent = NULL; - - root = grandchild; - } else if (c < 0 && (grandchild = child->left)) { - rightbottom->left = child; - child->parent = rightbottom; - rightbottom = child; - - child->left = NULL; - grandchild->parent = NULL; - - leftbottom->right = root; - root->parent = leftbottom; - leftbottom = root; - - root->right = NULL; - - root = grandchild; - } else { - leftbottom->right = root; - root->parent = leftbottom; - leftbottom = root; - - root->right = NULL; - child->parent = NULL; - - root = child; - break; - } - } else { - break; - } - } - - /* Merge trees */ - - if(left.right) { - if(root->left) { - leftbottom->right = root->left; - root->left->parent = leftbottom; - } - root->left = left.right; - left.right->parent = root; - } - - if(right.left) { - if(root->right) { - rightbottom->left = root->right; - root->right->parent = rightbottom; - } - root->right = right.left; - right.left->parent = root; - } - - /* Return result */ - - tree->root = root; - if(result) - *result = c; - - return tree->root; -} - -static void splay_bottom_up(splay_tree_t *tree, splay_node_t *node) { - splay_node_t *parent, *grandparent, *greatgrandparent; - - while((parent = node->parent)) { - if(!(grandparent = parent->parent)) { /* zig */ - if(node == parent->left) { - if((parent->left = node->right)) - parent->left->parent = parent; - node->right = parent; - } else { - if((parent->right = node->left)) - parent->right->parent = parent; - node->left = parent; - } - - parent->parent = node; - node->parent = NULL; - } else { - greatgrandparent = grandparent->parent; - - if(node == parent->left && parent == grandparent->left) { /* left zig-zig */ - if((grandparent->left = parent->right)) - grandparent->left->parent = grandparent; - parent->right = grandparent; - grandparent->parent = parent; - - if((parent->left = node->right)) - parent->left->parent = parent; - node->right = parent; - parent->parent = node; - } else if(node == parent->right && parent == grandparent->right) { /* right zig-zig */ - if((grandparent->right = parent->left)) - grandparent->right->parent = grandparent; - parent->left = grandparent; - grandparent->parent = parent; - - if((parent->right = node->left)) - parent->right->parent = parent; - node->left = parent; - parent->parent = node; - } else if(node == parent->right && parent == grandparent->left) { /* left-right zig-zag */ - if((parent->right = node->left)) - parent->right->parent = parent; - node->left = parent; - parent->parent = node; - - if((grandparent->left = node->right)) - grandparent->left->parent = grandparent; - node->right = grandparent; - grandparent->parent = node; - } else { /* right-left zig-zag */ - if((parent->left = node->right)) - parent->left->parent = parent; - node->right = parent; - parent->parent = node; - - if((grandparent->right = node->left)) - grandparent->right->parent = grandparent; - node->left = grandparent; - grandparent->parent = node; - } - - if((node->parent = greatgrandparent)) { - if(grandparent == greatgrandparent->left) - greatgrandparent->left = node; - else - greatgrandparent->right = node; - } - } - } - - tree->root = node; -} - -/* (De)constructors */ - -splay_tree_t *splay_alloc_tree(splay_compare_t compare, splay_action_t delete) { - splay_tree_t *tree; - - tree = xzalloc(sizeof(splay_tree_t)); - tree->compare = compare; - tree->delete = delete; - - return tree; -} - -void splay_free_tree(splay_tree_t *tree) { - free(tree); -} - -splay_node_t *splay_alloc_node(void) { - return xzalloc(sizeof(splay_node_t)); -} - -void splay_free_node(splay_tree_t *tree, splay_node_t *node) { - if(node->data && tree->delete) - tree->delete(node->data); - - free(node); -} - -/* Searching */ - -void *splay_search(splay_tree_t *tree, const void *data) { - splay_node_t *node; - - node = splay_search_node(tree, data); - - return node ? node->data : NULL; -} - -void *splay_search_closest(splay_tree_t *tree, const void *data, int *result) { - splay_node_t *node; - - node = splay_search_closest_node(tree, data, result); - - return node ? node->data : NULL; -} - -void *splay_search_closest_smaller(splay_tree_t *tree, const void *data) { - splay_node_t *node; - - node = splay_search_closest_smaller_node(tree, data); - - return node ? node->data : NULL; -} - -void *splay_search_closest_greater(splay_tree_t *tree, const void *data) { - splay_node_t *node; - - node = splay_search_closest_greater_node(tree, data); - - return node ? node->data : NULL; -} - -splay_node_t *splay_search_node(splay_tree_t *tree, const void *data) { - splay_node_t *node; - int result; - - node = splay_search_closest_node(tree, data, &result); - - return result ? NULL : node; -} - -splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *tree, const void *data, int *result) { - splay_node_t *node; - int c; - - node = tree->root; - - if(!node) { - if(result) - *result = 0; - return NULL; - } - - for(;;) { - c = tree->compare(data, node->data); - - if(c < 0) { - if(node->left) - node = node->left; - else - break; - } else if(c > 0) { - if(node->right) - node = node->right; - else - break; - } else { - break; - } - } - - if(result) - *result = c; - return node; -} - -splay_node_t *splay_search_closest_node(splay_tree_t *tree, const void *data, int *result) { - return splay_top_down(tree, data, result); -} - -splay_node_t *splay_search_closest_smaller_node(splay_tree_t *tree, const void *data) { - splay_node_t *node; - int result; - - node = splay_search_closest_node(tree, data, &result); - - if(result < 0) - node = node->prev; - - return node; -} - -splay_node_t *splay_search_closest_greater_node(splay_tree_t *tree, const void *data) { - splay_node_t *node; - int result; - - node = splay_search_closest_node(tree, data, &result); - - if(result > 0) - node = node->next; - - return node; -} - -/* Insertion and deletion */ - -splay_node_t *splay_insert(splay_tree_t *tree, void *data) { - splay_node_t *closest, *new; - int result; - - if(!tree->root) { - new = splay_alloc_node(); - new->data = data; - splay_insert_top(tree, new); - } else { - closest = splay_search_closest_node(tree, data, &result); - - if(!result) - return NULL; - - new = splay_alloc_node(); - new->data = data; - - if(result < 0) - splay_insert_before(tree, closest, new); - else - splay_insert_after(tree, closest, new); - } - - return new; -} - -splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) { - splay_node_t *closest; - int result; - - node->left = node->right = node->parent = node->next = node->prev = NULL; - - if(!tree->root) - splay_insert_top(tree, node); - else { - closest = splay_search_closest_node(tree, node->data, &result); - - if(!result) - return NULL; - - if(result < 0) - splay_insert_before(tree, closest, node); - else - splay_insert_after(tree, closest, node); - } - - return node; -} - -void splay_insert_top(splay_tree_t *tree, splay_node_t *node) { - node->prev = node->next = node->left = node->right = node->parent = NULL; - tree->head = tree->tail = tree->root = node; - tree->count++; -} - -void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t *node) { - if(!before) { - if(tree->tail) - splay_insert_after(tree, tree->tail, node); - else - splay_insert_top(tree, node); - return; - } - - node->next = before; - if((node->prev = before->prev)) - before->prev->next = node; - else - tree->head = node; - before->prev = node; - - splay_bottom_up(tree, before); - - node->right = before; - before->parent = node; - if((node->left = before->left)) - before->left->parent = node; - before->left = NULL; - - node->parent = NULL; - tree->root = node; - tree->count++; -} - -void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *node) { - if(!after) { - if(tree->head) - splay_insert_before(tree, tree->head, node); - else - splay_insert_top(tree, node); - return; - } - - node->prev = after; - if((node->next = after->next)) - after->next->prev = node; - else - tree->tail = node; - after->next = node; - - splay_bottom_up(tree, after); - - node->left = after; - after->parent = node; - if((node->right = after->right)) - after->right->parent = node; - after->right = NULL; - - node->parent = NULL; - tree->root = node; - tree->count++; -} - -splay_node_t *splay_unlink(splay_tree_t *tree, void *data) { - splay_node_t *node; - - node = splay_search_node(tree, data); - - if(node) - splay_unlink_node(tree, node); - - return node; -} - -void splay_unlink_node(splay_tree_t *tree, splay_node_t *node) { - if(node->prev) - node->prev->next = node->next; - else - tree->head = node->next; - - if(node->next) - node->next->prev = node->prev; - else - tree->tail = node->prev; - - splay_bottom_up(tree, node); - - if(node->prev) { - node->left->parent = NULL; - tree->root = node->left; - if((node->prev->right = node->right)) - node->right->parent = node->prev; - } else if(node->next) { - tree->root = node->right; - node->right->parent = NULL; - } else { - tree->root = NULL; - } - - tree->count--; -} - -void splay_delete_node(splay_tree_t *tree, splay_node_t *node) { - splay_unlink_node(tree, node); - splay_free_node(tree, node); -} - -void splay_delete(splay_tree_t *tree, void *data) { - splay_node_t *node; - - node = splay_search_node(tree, data); - - if(node) - splay_delete_node(tree, node); -} - -/* Fast tree cleanup */ - -void splay_delete_tree(splay_tree_t *tree) { - for(splay_node_t *node = tree->head, *next; node; node = next) { - next = node->next; - splay_free_node(tree, node); - } - - splay_free_tree(tree); -} - -/* Tree walking */ - -void splay_foreach(const splay_tree_t *tree, splay_action_t action) { - for(splay_node_t *node = tree->head, *next; node; node = next) { - next = node->next; - action(node->data); - } -} - -void splay_foreach_node(const splay_tree_t *tree, splay_action_t action) { - for(splay_node_t *node = tree->head, *next; node; node = next) { - next = node->next; - action(node); - } -} diff --git a/src/splay_tree.h b/src/splay_tree.h deleted file mode 100644 index 5848870..0000000 --- a/src/splay_tree.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - splay_tree.h -- header file for splay_tree.c - Copyright (C) 2004-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - - -#ifndef __SPLAY_TREE_H__ -#define __SPLAY_TREE_H__ - -typedef struct splay_node_t { - - /* Linked list part */ - - struct splay_node_t *next; - struct splay_node_t *prev; - - /* Tree part */ - - struct splay_node_t *parent; - struct splay_node_t *left; - struct splay_node_t *right; - - /* Payload */ - - void *data; - -} splay_node_t; - -typedef int (*splay_compare_t)(const void *, const void *); -typedef void (*splay_action_t)(const void *); -typedef void (*splay_action_node_t)(const splay_node_t *); - -typedef struct splay_tree_t { - - /* Linked list part */ - - splay_node_t *head; - splay_node_t *tail; - - /* Tree part */ - - splay_node_t *root; - - splay_compare_t compare; - splay_action_t delete; - - int count; - -} splay_tree_t; - -/* (De)constructors */ - -extern splay_tree_t *splay_alloc_tree(splay_compare_t, splay_action_t) __attribute__ ((__malloc__)); -extern void splay_free_tree(splay_tree_t *); - -extern splay_node_t *splay_alloc_node(void) __attribute__ ((__malloc__)); -extern void splay_free_node(splay_tree_t *tree, splay_node_t *); - -/* Insertion and deletion */ - -extern splay_node_t *splay_insert(splay_tree_t *, void *); -extern splay_node_t *splay_insert_node(splay_tree_t *, splay_node_t *); - -extern void splay_insert_top(splay_tree_t *, splay_node_t *); -extern void splay_insert_before(splay_tree_t *, splay_node_t *, splay_node_t *); -extern void splay_insert_after(splay_tree_t *, splay_node_t *, splay_node_t *); - -extern splay_node_t *splay_unlink(splay_tree_t *, void *); -extern void splay_unlink_node(splay_tree_t *tree, splay_node_t *); -extern void splay_delete(splay_tree_t *, void *); -extern void splay_delete_node(splay_tree_t *, splay_node_t *); - -/* Fast tree cleanup */ - -extern void splay_delete_tree(splay_tree_t *); - -/* Searching */ - -extern void *splay_search(splay_tree_t *, const void *); -extern void *splay_search_closest(splay_tree_t *, const void *, int *); -extern void *splay_search_closest_smaller(splay_tree_t *, const void *); -extern void *splay_search_closest_greater(splay_tree_t *, const void *); - -extern splay_node_t *splay_search_node(splay_tree_t *, const void *); -extern splay_node_t *splay_search_closest_node(splay_tree_t *, const void *, int *); -extern splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *, const void *, int *); -extern splay_node_t *splay_search_closest_smaller_node(splay_tree_t *, const void *); -extern splay_node_t *splay_search_closest_greater_node(splay_tree_t *, const void *); - -/* Tree walking */ - -extern void splay_foreach(const splay_tree_t *, splay_action_t); -extern void splay_foreach_node(const splay_tree_t *, splay_action_t); - -#define splay_each(type, item, tree) (type *item = (type *)1; item; item = NULL) for(splay_node_t *node = (tree)->head, *next; item = node ? node->data : NULL, next = node ? node->next : NULL, node; node = next) - -#endif diff --git a/src/sptps.c b/src/sptps.c deleted file mode 100644 index 6869575..0000000 --- a/src/sptps.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - sptps.c -- Simple Peer-to-Peer Security - Copyright (C) 2011-2013 Guus Sliepen , - 2010 Brandon L. Black - - 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 "crypto.h" -#include "digest.h" -#include "ecdh.h" -#include "ecdsa.h" -#include "logger.h" -#include "prf.h" -#include "sptps.h" - -unsigned int sptps_replaywin = 16; - -/* - Nonce MUST be exchanged first (done) - Signatures MUST be done over both nonces, to guarantee the signature is fresh - Otherwise: if ECDHE key of one side is compromised, it can be reused! - - Add explicit tag to beginning of structure to distinguish the client and server when signing. (done) - - Sign all handshake messages up to ECDHE kex with long-term public keys. (done) - - HMACed KEX finished message to prevent downgrade attacks and prove you have the right key material (done by virtue of ECDSA over the whole ECDHE exchange?) - - Explicit close message needs to be added. - - Maybe do add some alert messages to give helpful error messages? Not more than TLS sends. - - Use counter mode instead of OFB. (done) - - Make sure ECC operations are fixed time (aka prevent side-channel attacks). -*/ - -void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap) { -} - -void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap) { - vfprintf(stderr, format, ap); - fputc('\n', stderr); -} - -void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap) = sptps_log_stderr; - -// Log an error message. -static bool error(sptps_t *s, int s_errno, const char *format, ...) { - if(format) { - va_list ap; - va_start(ap, format); - sptps_log(s, s_errno, format, ap); - va_end(ap); - } - - errno = s_errno; - return false; -} - -static void warning(sptps_t *s, const char *format, ...) { - va_list ap; - va_start(ap, format); - sptps_log(s, 0, format, ap); - va_end(ap); -} - -// Send a record (datagram version, accepts all record types, handles encryption and authentication). -static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const char *data, uint16_t len) { - char buffer[len + 23UL]; - - // Create header with sequence number, length and record type - uint32_t seqno = htonl(s->outseqno++); - uint16_t netlen = htons(len); - - memcpy(buffer, &netlen, 2); - memcpy(buffer + 2, &seqno, 4); - buffer[6] = type; - - // Add plaintext (TODO: avoid unnecessary copy) - memcpy(buffer + 7, data, len); - - if(s->outstate) { - // If first handshake has finished, encrypt and HMAC - if(!cipher_set_counter(s->outcipher, &seqno, sizeof seqno)) - return false; - - if(!cipher_counter_xor(s->outcipher, buffer + 6, len + 1UL, buffer + 6)) - return false; - - if(!digest_create(s->outdigest, buffer, len + 7UL, buffer + 7UL + len)) - return false; - - return s->send_data(s->handle, type, buffer + 2, len + 21UL); - } else { - // Otherwise send as plaintext - return s->send_data(s->handle, type, buffer + 2, len + 5UL); - } -} -// Send a record (private version, accepts all record types, handles encryption and authentication). -static bool send_record_priv(sptps_t *s, uint8_t type, const char *data, uint16_t len) { - if(s->datagram) - return send_record_priv_datagram(s, type, data, len); - - char buffer[len + 23UL]; - - // Create header with sequence number, length and record type - uint32_t seqno = htonl(s->outseqno++); - uint16_t netlen = htons(len); - - memcpy(buffer, &seqno, 4); - memcpy(buffer + 4, &netlen, 2); - buffer[6] = type; - - // Add plaintext (TODO: avoid unnecessary copy) - memcpy(buffer + 7, data, len); - - if(s->outstate) { - // If first handshake has finished, encrypt and HMAC - if(!cipher_counter_xor(s->outcipher, buffer + 4, len + 3UL, buffer + 4)) - return false; - - if(!digest_create(s->outdigest, buffer, len + 7UL, buffer + 7UL + len)) - return false; - - return s->send_data(s->handle, type, buffer + 4, len + 19UL); - } else { - // Otherwise send as plaintext - return s->send_data(s->handle, type, buffer + 4, len + 3UL); - } -} - -// Send an application record. -bool sptps_send_record(sptps_t *s, uint8_t type, const char *data, uint16_t len) { - // Sanity checks: application cannot send data before handshake is finished, - // and only record types 0..127 are allowed. - if(!s->outstate) - return error(s, EINVAL, "Handshake phase not finished yet"); - - if(type >= SPTPS_HANDSHAKE) - return error(s, EINVAL, "Invalid application record type"); - - return send_record_priv(s, type, data, len); -} - -// Send a Key EXchange record, containing a random nonce and an ECDHE public key. -static bool send_kex(sptps_t *s) { - size_t keylen = ECDH_SIZE; - - // Make room for our KEX message, which we will keep around since send_sig() needs it. - if(s->mykex) - abort(); - s->mykex = realloc(s->mykex, 1 + 32 + keylen); - if(!s->mykex) - return error(s, errno, strerror(errno)); - - // Set version byte to zero. - s->mykex[0] = SPTPS_VERSION; - - // Create a random nonce. - randomize(s->mykex + 1, 32); - - // Create a new ECDH public key. - if(!(s->ecdh = ecdh_generate_public(s->mykex + 1 + 32))) - return false; - - return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 1 + 32 + keylen); -} - -// Send a SIGnature record, containing an ECDSA signature over both KEX records. -static bool send_sig(sptps_t *s) { - size_t keylen = ECDH_SIZE; - size_t siglen = ecdsa_size(s->mykey); - - // Concatenate both KEX messages, plus tag indicating if it is from the connection originator, plus label - char msg[(1 + 32 + keylen) * 2 + 1 + s->labellen]; - char sig[siglen]; - - msg[0] = s->initiator; - memcpy(msg + 1, s->mykex, 1 + 32 + keylen); - memcpy(msg + 1 + 33 + keylen, s->hiskex, 1 + 32 + keylen); - memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen); - - // Sign the result. - if(!ecdsa_sign(s->mykey, msg, sizeof msg, sig)) - return false; - - // Send the SIG exchange record. - return send_record_priv(s, SPTPS_HANDSHAKE, sig, sizeof sig); -} - -// Generate key material from the shared secret created from the ECDHE key exchange. -static bool generate_key_material(sptps_t *s, const char *shared, size_t len) { - // Initialise cipher and digest structures if necessary - if(!s->outstate) { - s->incipher = cipher_open_by_name("aes-256-ecb"); - s->outcipher = cipher_open_by_name("aes-256-ecb"); - s->indigest = digest_open_by_name("sha256", 16); - s->outdigest = digest_open_by_name("sha256", 16); - if(!s->incipher || !s->outcipher || !s->indigest || !s->outdigest) - return false; - } - - // Allocate memory for key material - size_t keylen = digest_keylength(s->indigest) + digest_keylength(s->outdigest) + cipher_keylength(s->incipher) + cipher_keylength(s->outcipher); - - s->key = realloc(s->key, keylen); - if(!s->key) - return error(s, errno, strerror(errno)); - - // Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce - char seed[s->labellen + 64 + 13]; - strcpy(seed, "key expansion"); - if(s->initiator) { - memcpy(seed + 13, s->mykex + 1, 32); - memcpy(seed + 45, s->hiskex + 1, 32); - } else { - memcpy(seed + 13, s->hiskex + 1, 32); - memcpy(seed + 45, s->mykex + 1, 32); - } - memcpy(seed + 77, s->label, s->labellen); - - // Use PRF to generate the key material - if(!prf(shared, len, seed, s->labellen + 64 + 13, s->key, keylen)) - return false; - - return true; -} - -// Send an ACKnowledgement record. -static bool send_ack(sptps_t *s) { - return send_record_priv(s, SPTPS_HANDSHAKE, "", 0); -} - -// Receive an ACKnowledgement record. -static bool receive_ack(sptps_t *s, const char *data, uint16_t len) { - if(len) - return error(s, EIO, "Invalid ACK record length"); - - if(s->initiator) { - bool result - = cipher_set_counter_key(s->incipher, s->key) - && digest_set_key(s->indigest, s->key + cipher_keylength(s->incipher), digest_keylength(s->indigest)); - if(!result) - return false; - } else { - bool result - = cipher_set_counter_key(s->incipher, s->key + cipher_keylength(s->outcipher) + digest_keylength(s->outdigest)) - && digest_set_key(s->indigest, s->key + cipher_keylength(s->outcipher) + digest_keylength(s->outdigest) + cipher_keylength(s->incipher), digest_keylength(s->indigest)); - if(!result) - return false; - } - - free(s->key); - s->key = NULL; - s->instate = true; - - return true; -} - -// Receive a Key EXchange record, respond by sending a SIG record. -static bool receive_kex(sptps_t *s, const char *data, uint16_t len) { - // Verify length of the HELLO record - if(len != 1 + 32 + ECDH_SIZE) - return error(s, EIO, "Invalid KEX record length"); - - // Ignore version number for now. - - // Make a copy of the KEX message, send_sig() and receive_sig() need it - if(s->hiskex) - abort(); - s->hiskex = realloc(s->hiskex, len); - if(!s->hiskex) - return error(s, errno, strerror(errno)); - - memcpy(s->hiskex, data, len); - - return send_sig(s); -} - -// Receive a SIGnature record, verify it, if it passed, compute the shared secret and calculate the session keys. -static bool receive_sig(sptps_t *s, const char *data, uint16_t len) { - size_t keylen = ECDH_SIZE; - size_t siglen = ecdsa_size(s->hiskey); - - // Verify length of KEX record. - if(len != siglen) - return error(s, EIO, "Invalid KEX record length"); - - // Concatenate both KEX messages, plus tag indicating if it is from the connection originator - char msg[(1 + 32 + keylen) * 2 + 1 + s->labellen]; - - msg[0] = !s->initiator; - memcpy(msg + 1, s->hiskex, 1 + 32 + keylen); - memcpy(msg + 1 + 33 + keylen, s->mykex, 1 + 32 + keylen); - memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen); - - // Verify signature. - if(!ecdsa_verify(s->hiskey, msg, sizeof msg, data)) - return false; - - // Compute shared secret. - char shared[ECDH_SHARED_SIZE]; - if(!ecdh_compute_shared(s->ecdh, s->hiskex + 1 + 32, shared)) - return false; - s->ecdh = NULL; - - // Generate key material from shared secret. - if(!generate_key_material(s, shared, sizeof shared)) - return false; - - free(s->mykex); - free(s->hiskex); - - s->mykex = NULL; - s->hiskex = NULL; - - // Send cipher change record - if(s->outstate && !send_ack(s)) - return false; - - // TODO: only set new keys after ACK has been set/received - if(s->initiator) { - bool result - = cipher_set_counter_key(s->outcipher, s->key + cipher_keylength(s->incipher) + digest_keylength(s->indigest)) - && digest_set_key(s->outdigest, s->key + cipher_keylength(s->incipher) + digest_keylength(s->indigest) + cipher_keylength(s->outcipher), digest_keylength(s->outdigest)); - if(!result) - return false; - } else { - bool result - = cipher_set_counter_key(s->outcipher, s->key) - && digest_set_key(s->outdigest, s->key + cipher_keylength(s->outcipher), digest_keylength(s->outdigest)); - if(!result) - return false; - } - - return true; -} - -// Force another Key EXchange (for testing purposes). -bool sptps_force_kex(sptps_t *s) { - if(!s->outstate || s->state != SPTPS_SECONDARY_KEX) - return error(s, EINVAL, "Cannot force KEX in current state"); - - s->state = SPTPS_KEX; - return send_kex(s); -} - -// Receive a handshake record. -static bool receive_handshake(sptps_t *s, const char *data, uint16_t len) { - // Only a few states to deal with handshaking. - switch(s->state) { - case SPTPS_SECONDARY_KEX: - // We receive a secondary KEX request, first respond by sending our own. - if(!send_kex(s)) - return false; - case SPTPS_KEX: - // We have sent our KEX request, we expect our peer to sent one as well. - if(!receive_kex(s, data, len)) - return false; - s->state = SPTPS_SIG; - return true; - case SPTPS_SIG: - // If we already sent our secondary public ECDH key, we expect the peer to send his. - if(!receive_sig(s, data, len)) - return false; - if(s->outstate) - s->state = SPTPS_ACK; - else { - s->outstate = true; - if(!receive_ack(s, NULL, 0)) - return false; - s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); - s->state = SPTPS_SECONDARY_KEX; - } - - return true; - case SPTPS_ACK: - // We expect a handshake message to indicate transition to the new keys. - if(!receive_ack(s, data, len)) - return false; - s->receive_record(s->handle, SPTPS_HANDSHAKE, NULL, 0); - s->state = SPTPS_SECONDARY_KEX; - return true; - // TODO: split ACK into a VERify and ACK? - default: - return error(s, EIO, "Invalid session state %d", s->state); - } -} - -// Check datagram for valid HMAC -bool sptps_verify_datagram(sptps_t *s, const char *data, size_t len) { - if(!s->instate || len < 21) - return false; - - char buffer[len + 23]; - uint16_t netlen = htons(len - 21); - - memcpy(buffer, &netlen, 2); - memcpy(buffer + 2, data, len); - - return digest_verify(s->indigest, buffer, len - 14, buffer + len - 14); -} - -// Receive incoming data, datagram version. -static bool sptps_receive_data_datagram(sptps_t *s, const char *data, size_t len) { - if(len < (s->instate ? 21 : 5)) - return error(s, EIO, "Received short packet"); - - uint32_t seqno; - memcpy(&seqno, data, 4); - seqno = ntohl(seqno); - - if(!s->instate) { - if(seqno != s->inseqno) - return error(s, EIO, "Invalid packet seqno: %d != %d", seqno, s->inseqno); - - s->inseqno = seqno + 1; - - uint8_t type = data[4]; - - if(type != SPTPS_HANDSHAKE) - return error(s, EIO, "Application record received before handshake finished"); - - return receive_handshake(s, data + 5, len - 5); - } - - // Check HMAC. - uint16_t netlen = htons(len - 21); - - char buffer[len + 23]; - - memcpy(buffer, &netlen, 2); - memcpy(buffer + 2, data, len); - - if(!digest_verify(s->indigest, buffer, len - 14, buffer + len - 14)) - return error(s, EIO, "Invalid HMAC"); - - // Replay protection using a sliding window of configurable size. - // s->inseqno is expected sequence number - // seqno is received sequence number - // s->late[] is a circular buffer, a 1 bit means a packet has not been received yet - // The circular buffer contains bits for sequence numbers from s->inseqno - s->replaywin * 8 to (but excluding) s->inseqno. - if(s->replaywin) { - if(seqno != s->inseqno) { - if(seqno >= s->inseqno + s->replaywin * 8) { - // Prevent packets that jump far ahead of the queue from causing many others to be dropped. - if(s->farfuture++ < s->replaywin >> 2) - return error(s, EIO, "Packet is %d seqs in the future, dropped (%u)\n", seqno - s->inseqno, s->farfuture); - - // Unless we have seen lots of them, in which case we consider the others lost. - warning(s, "Lost %d packets\n", seqno - s->inseqno); - memset(s->late, 0, s->replaywin); - } else if (seqno < s->inseqno) { - // If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it. - if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8))) - return error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno); - } else { - // We missed some packets. Mark them in the bitmap as being late. - for(int i = s->inseqno; i < seqno; i++) - s->late[(i / 8) % s->replaywin] |= 1 << i % 8; - } - } - - // Mark the current packet as not being late. - s->late[(seqno / 8) % s->replaywin] &= ~(1 << seqno % 8); - s->farfuture = 0; - } - - if(seqno > s->inseqno) - s->inseqno = seqno + 1; - - if(!s->inseqno) - s->received = 0; - else - s->received++; - - // Decrypt. - memcpy(&seqno, buffer + 2, 4); - if(!cipher_set_counter(s->incipher, &seqno, sizeof seqno)) - return false; - if(!cipher_counter_xor(s->incipher, buffer + 6, len - 4, buffer + 6)) - return false; - - // Append a NULL byte for safety. - buffer[len - 14] = 0; - - uint8_t type = buffer[6]; - - if(type < SPTPS_HANDSHAKE) { - if(!s->instate) - return error(s, EIO, "Application record received before handshake finished"); - if(!s->receive_record(s->handle, type, buffer + 7, len - 21)) - return false; - } else if(type == SPTPS_HANDSHAKE) { - if(!receive_handshake(s, buffer + 7, len - 21)) - return false; - } else { - return error(s, EIO, "Invalid record type %d", type); - } - - return true; -} - -// Receive incoming data. Check if it contains a complete record, if so, handle it. -bool sptps_receive_data(sptps_t *s, const char *data, size_t len) { - if(!s->state) - return error(s, EIO, "Invalid session state zero"); - - if(s->datagram) - return sptps_receive_data_datagram(s, data, len); - - while(len) { - // First read the 2 length bytes. - if(s->buflen < 6) { - size_t toread = 6 - s->buflen; - if(toread > len) - toread = len; - - memcpy(s->inbuf + s->buflen, data, toread); - - s->buflen += toread; - len -= toread; - data += toread; - - // Exit early if we don't have the full length. - if(s->buflen < 6) - return true; - - // Decrypt the length bytes - - if(s->instate) { - if(!cipher_counter_xor(s->incipher, s->inbuf + 4, 2, &s->reclen)) - return false; - } else { - memcpy(&s->reclen, s->inbuf + 4, 2); - } - - s->reclen = ntohs(s->reclen); - - // If we have the length bytes, ensure our buffer can hold the whole request. - s->inbuf = realloc(s->inbuf, s->reclen + 23UL); - if(!s->inbuf) - return error(s, errno, strerror(errno)); - - // Add sequence number. - uint32_t seqno = htonl(s->inseqno++); - memcpy(s->inbuf, &seqno, 4); - - // Exit early if we have no more data to process. - if(!len) - return true; - } - - // Read up to the end of the record. - size_t toread = s->reclen + (s->instate ? 23UL : 7UL) - s->buflen; - if(toread > len) - toread = len; - - memcpy(s->inbuf + s->buflen, data, toread); - s->buflen += toread; - len -= toread; - data += toread; - - // If we don't have a whole record, exit. - if(s->buflen < s->reclen + (s->instate ? 23UL : 7UL)) - return true; - - // Check HMAC and decrypt. - if(s->instate) { - if(!digest_verify(s->indigest, s->inbuf, s->reclen + 7UL, s->inbuf + s->reclen + 7UL)) - return error(s, EIO, "Invalid HMAC"); - - if(!cipher_counter_xor(s->incipher, s->inbuf + 6UL, s->reclen + 1UL, s->inbuf + 6UL)) - return false; - } - - // Append a NULL byte for safety. - s->inbuf[s->reclen + 7UL] = 0; - - uint8_t type = s->inbuf[6]; - - if(type < SPTPS_HANDSHAKE) { - if(!s->instate) - return error(s, EIO, "Application record received before handshake finished"); - if(!s->receive_record(s->handle, type, s->inbuf + 7, s->reclen)) - return false; - } else if(type == SPTPS_HANDSHAKE) { - if(!receive_handshake(s, s->inbuf + 7, s->reclen)) - return false; - } else { - return error(s, EIO, "Invalid record type %d", type); - } - - s->buflen = 4; - } - - return true; -} - -// Start a SPTPS session. -bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) { - // Initialise struct sptps - memset(s, 0, sizeof *s); - - s->handle = handle; - s->initiator = initiator; - s->datagram = datagram; - s->mykey = mykey; - s->hiskey = hiskey; - s->replaywin = sptps_replaywin; - if(s->replaywin) { - s->late = malloc(s->replaywin); - if(!s->late) - return error(s, errno, strerror(errno)); - } - - s->label = malloc(labellen); - if(!s->label) - return error(s, errno, strerror(errno)); - - if(!datagram) { - s->inbuf = malloc(7); - if(!s->inbuf) - return error(s, errno, strerror(errno)); - s->buflen = 4; - memset(s->inbuf, 0, 4); - } - - memcpy(s->label, label, labellen); - s->labellen = labellen; - - s->send_data = send_data; - s->receive_record = receive_record; - - // Do first KEX immediately - s->state = SPTPS_KEX; - return send_kex(s); -} - -// Stop a SPTPS session. -bool sptps_stop(sptps_t *s) { - // Clean up any resources. - cipher_close(s->incipher); - cipher_close(s->outcipher); - digest_close(s->indigest); - digest_close(s->outdigest); - ecdh_free(s->ecdh); - free(s->inbuf); - free(s->mykex); - free(s->hiskex); - free(s->key); - free(s->label); - free(s->late); - memset(s, 0, sizeof *s); - return true; -} diff --git a/src/sptps.h b/src/sptps.h deleted file mode 100644 index 3a8e65f..0000000 --- a/src/sptps.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - sptps.h -- Simple Peer-to-Peer Security - Copyright (C) 2011-2013 Guus Sliepen , - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __SPTPS_H__ -#define __SPTPS_H__ - -#include "system.h" - -#include "cipher.h" -#include "digest.h" -#include "ecdh.h" -#include "ecdsa.h" - -#define SPTPS_VERSION 0 - -// Record types -#define SPTPS_HANDSHAKE 128 // Key exchange and authentication -#define SPTPS_ALERT 129 // Warning or error messages -#define SPTPS_CLOSE 130 // Application closed the connection - -// Key exchange states -#define SPTPS_KEX 1 // Waiting for the first Key EXchange record -#define SPTPS_SECONDARY_KEX 2 // Ready to receive a secondary Key EXchange record -#define SPTPS_SIG 3 // Waiting for a SIGnature record -#define SPTPS_ACK 4 // Waiting for an ACKnowledgement record - -typedef bool (*send_data_t)(void *handle, uint8_t type, const char *data, size_t len); -typedef bool (*receive_record_t)(void *handle, uint8_t type, const char *data, uint16_t len); - -typedef struct sptps { - bool initiator; - bool datagram; - int state; - - char *inbuf; - size_t buflen; - uint16_t reclen; - - bool instate; - cipher_t *incipher; - digest_t *indigest; - uint32_t inseqno; - uint32_t received; - unsigned int replaywin; - unsigned int farfuture; - char *late; - - bool outstate; - cipher_t *outcipher; - digest_t *outdigest; - uint32_t outseqno; - - ecdsa_t *mykey; - ecdsa_t *hiskey; - ecdh_t *ecdh; - - char *mykex; - char *hiskex; - char *key; - char *label; - size_t labellen; - - void *handle; - send_data_t send_data; - receive_record_t receive_record; -} sptps_t; - -extern unsigned int sptps_replaywin; -extern void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap); -extern void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap); -extern void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap); -extern bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record); -extern bool sptps_stop(sptps_t *s); -extern bool sptps_send_record(sptps_t *s, uint8_t type, const char *data, uint16_t len); -extern bool sptps_receive_data(sptps_t *s, const char *data, size_t len); -extern bool sptps_force_kex(sptps_t *s); -extern bool sptps_verify_datagram(sptps_t *s, const char *data, size_t len); - -#endif diff --git a/src/sptps_test.c b/src/sptps_test.c deleted file mode 100644 index 2ce9804..0000000 --- a/src/sptps_test.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - sptps_test.c -- Simple Peer-to-Peer Security test program - Copyright (C) 2011-2013 Guus Sliepen , - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include "crypto.h" -#include "ecdsa.h" -#include "sptps.h" -#include "utils.h" - -// Symbols necessary to link with logger.o -bool send_request(void *c, const char *msg, ...) { return false; } -struct list_t *connection_list = NULL; -bool send_meta(void *c, const char *msg , int len) { return false; } -char *logfilename = NULL; -struct timeval now; - -ecdsa_t *mykey, *hiskey; - -static bool send_data(void *handle, uint8_t type, const char *data, size_t len) { - char hex[len * 2 + 1]; - bin2hex(data, hex, len); - fprintf(stderr, "Sending %d bytes of data:\n%s\n", (int)len, hex); - const int *sock = handle; - if(send(*sock, data, len, 0) != len) - return false; - return true; -} - -static bool receive_record(void *handle, uint8_t type, const char *data, uint16_t len) { - fprintf(stderr, "Received type %d record of %hu bytes:\n", type, len); - fwrite(data, len, 1, stdout); - return true; -} - -int main(int argc, char *argv[]) { - bool initiator = false; - bool datagram = false; - - if(argc > 1 && !strcmp(argv[1], "-d")) { - datagram = true; - argc--; - argv++; - } - - if(argc < 4) { - fprintf(stderr, "Usage: %s [-d] my_ecdsa_key_file his_ecdsa_key_file [host] port\n", argv[0]); - return 1; - } - - if(argc > 4) - initiator = true; - -#ifdef HAVE_MINGW - static struct WSAData wsa_state; - if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) - return 1; -#endif - - struct addrinfo *ai, hint; - memset(&hint, 0, sizeof hint); - - hint.ai_family = AF_UNSPEC; - hint.ai_socktype = datagram ? SOCK_DGRAM : SOCK_STREAM; - hint.ai_protocol = datagram ? IPPROTO_UDP : IPPROTO_TCP; - hint.ai_flags = initiator ? 0 : AI_PASSIVE; - - if(getaddrinfo(initiator ? argv[3] : NULL, initiator ? argv[4] : argv[3], &hint, &ai) || !ai) { - fprintf(stderr, "getaddrinfo() failed: %s\n", strerror(errno)); - return 1; - } - - int sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if(sock < 0) { - fprintf(stderr, "Could not create socket: %s\n", strerror(errno)); - return 1; - } - - int one = 1; - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof one); - - if(initiator) { - if(connect(sock, ai->ai_addr, ai->ai_addrlen)) { - fprintf(stderr, "Could not connect to peer: %s\n", strerror(errno)); - return 1; - } - fprintf(stderr, "Connected\n"); - } else { - if(bind(sock, ai->ai_addr, ai->ai_addrlen)) { - fprintf(stderr, "Could not bind socket: %s\n", strerror(errno)); - return 1; - } - - if(!datagram) { - if(listen(sock, 1)) { - fprintf(stderr, "Could not listen on socket: %s\n", strerror(errno)); - return 1; - } - fprintf(stderr, "Listening...\n"); - - sock = accept(sock, NULL, NULL); - if(sock < 0) { - fprintf(stderr, "Could not accept connection: %s\n", strerror(errno)); - return 1; - } - } else { - fprintf(stderr, "Listening...\n"); - - char buf[65536]; - struct sockaddr addr; - socklen_t addrlen = sizeof addr; - - if(recvfrom(sock, buf, sizeof buf, MSG_PEEK, &addr, &addrlen) <= 0) { - fprintf(stderr, "Could not read from socket: %s\n", strerror(errno)); - return 1; - } - - if(connect(sock, &addr, addrlen)) { - fprintf(stderr, "Could not accept connection: %s\n", strerror(errno)); - return 1; - } - } - - fprintf(stderr, "Connected\n"); - } - - crypto_init(); - - FILE *fp = fopen(argv[1], "r"); - if(!(mykey = ecdsa_read_pem_private_key(fp))) - return 1; - fclose(fp); - - fp = fopen(argv[2], "r"); - if(!(hiskey = ecdsa_read_pem_public_key(fp))) - return 1; - fclose(fp); - - fprintf(stderr, "Keys loaded\n"); - - sptps_t s; - if(!sptps_start(&s, &sock, initiator, datagram, mykey, hiskey, "sptps_test", 10, send_data, receive_record)) - return 1; - - while(true) { - char buf[65535] = ""; - - fd_set fds; - FD_ZERO(&fds); -#ifndef HAVE_MINGW - FD_SET(0, &fds); -#endif - FD_SET(sock, &fds); - if(select(sock + 1, &fds, NULL, NULL, NULL) <= 0) - return 1; - - if(FD_ISSET(0, &fds)) { - ssize_t len = read(0, buf, sizeof buf); - if(len < 0) { - fprintf(stderr, "Could not read from stdin: %s\n", strerror(errno)); - return 1; - } - if(len == 0) - break; - if(buf[0] == '^') - sptps_send_record(&s, SPTPS_HANDSHAKE, NULL, 0); - else if(buf[0] == '$') { - sptps_force_kex(&s); - if(len > 1) - sptps_send_record(&s, 0, buf, len); - } else - if(!sptps_send_record(&s, buf[0] == '!' ? 1 : 0, buf, buf[0] == '\n' ? 0 : buf[0] == '*' ? sizeof buf : len)) - return 1; - } - - if(FD_ISSET(sock, &fds)) { - ssize_t len = recv(sock, buf, sizeof buf, 0); - if(len < 0) { - fprintf(stderr, "Could not read from socket: %s\n", strerror(errno)); - return 1; - } - if(len == 0) { - fprintf(stderr, "Connection terminated by peer.\n"); - break; - } - char hex[len * 2 + 1]; - bin2hex(buf, hex, len); - fprintf(stderr, "Received %d bytes of data:\n%s\n", (int)len, hex); - if(!sptps_receive_data(&s, buf, len)) - return 1; - } - } - - if(!sptps_stop(&s)) - return 1; - - return 0; -} diff --git a/src/subnet.c b/src/subnet.c index 3b98030..154fd80 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -1,6 +1,6 @@ /* subnet.c -- handle subnet lookups and lists - Copyright (C) 2000-2013 Guus Sliepen , + Copyright (C) 2000-2019 Guus Sliepen , 2000-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -20,12 +20,9 @@ #include "system.h" -#include "splay_tree.h" -#include "control_common.h" +#include "avl_tree.h" #include "device.h" -#include "hash.h" #include "logger.h" -#include "names.h" #include "net.h" #include "netutl.h" #include "node.h" @@ -36,50 +33,151 @@ /* lists type of subnet */ -splay_tree_t *subnet_tree; +avl_tree_t *subnet_tree; /* Subnet lookup cache */ -hash_t *ipv4_cache; -hash_t *ipv6_cache; -hash_t *mac_cache; +static ipv4_t cache_ipv4_address[2]; +static subnet_t *cache_ipv4_subnet[2]; +static bool cache_ipv4_valid[2]; +static int cache_ipv4_slot; + +static ipv6_t cache_ipv6_address[2]; +static subnet_t *cache_ipv6_subnet[2]; +static bool cache_ipv6_valid[2]; +static int cache_ipv6_slot; + +static mac_t cache_mac_address[2]; +static subnet_t *cache_mac_subnet[2]; +static bool cache_mac_valid[2]; +static int cache_mac_slot; void subnet_cache_flush(void) { - hash_clear(ipv4_cache); - hash_clear(ipv6_cache); - hash_clear(mac_cache); + cache_ipv4_valid[0] = cache_ipv4_valid[1] = false; + cache_ipv6_valid[0] = cache_ipv6_valid[1] = false; + cache_mac_valid[0] = cache_mac_valid[1] = false; +} + +/* 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(mac_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_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(LOG_ERR, "subnet_compare() was called with unknown subnet type %d, exitting!", + a->type); + exit(0); + } + + return 0; } /* Initialising trees */ void init_subnets(void) { - subnet_tree = splay_alloc_tree((splay_compare_t) subnet_compare, (splay_action_t) free_subnet); + subnet_tree = avl_alloc_tree((avl_compare_t) subnet_compare, (avl_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)); + subnet_cache_flush(); } void exit_subnets(void) { - splay_delete_tree(subnet_tree); - - hash_free(ipv4_cache); - hash_free(ipv6_cache); - hash_free(mac_cache); + avl_delete_tree(subnet_tree); } -splay_tree_t *new_subnet_tree(void) { - return splay_alloc_tree((splay_compare_t) subnet_compare, NULL); +avl_tree_t *new_subnet_tree(void) { + return avl_alloc_tree((avl_compare_t) subnet_compare, NULL); } -void free_subnet_tree(splay_tree_t *subnet_tree) { - splay_delete_tree(subnet_tree); +void free_subnet_tree(avl_tree_t *subnet_tree) { + avl_delete_tree(subnet_tree); } /* Allocating and freeing space for subnets */ subnet_t *new_subnet(void) { - return xzalloc(sizeof(subnet_t)); + return xmalloc_and_zero(sizeof(subnet_t)); } void free_subnet(subnet_t *subnet) { @@ -91,192 +189,477 @@ void free_subnet(subnet_t *subnet) { void subnet_add(node_t *n, subnet_t *subnet) { subnet->owner = n; - splay_insert(subnet_tree, subnet); - splay_insert(n->subnet_tree, subnet); + avl_insert(subnet_tree, subnet); + avl_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); + avl_delete(n->subnet_tree, subnet); + avl_delete(subnet_tree, subnet); subnet_cache_flush(); } +/* Ascii representation of subnets */ + +bool str2net(subnet_t *subnet, const char *subnetstr) { + char str[1024]; + strncpy(str, subnetstr, sizeof(str)); + str[sizeof(str) - 1] = 0; + int consumed; + + int weight = 10; + char *weight_separator = strchr(str, '#'); + + if(weight_separator) { + char *weight_str = weight_separator + 1; + + if(sscanf(weight_str, "%d%n", &weight, &consumed) < 1) { + return false; + } + + if(weight_str[consumed]) { + return false; + } + + *weight_separator = 0; + } + + int prefixlength = -1; + char *prefixlength_separator = strchr(str, '/'); + + if(prefixlength_separator) { + char *prefixlength_str = prefixlength_separator + 1; + + if(sscanf(prefixlength_str, "%d%n", &prefixlength, &consumed) < 1) { + return false; + } + + if(prefixlength_str[consumed]) { + return false; + } + + *prefixlength_separator = 0; + + if(prefixlength < 0) { + return false; + } + } + + uint16_t x[8]; + + if(sscanf(str, "%hx:%hx:%hx:%hx:%hx:%hx%n", &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &consumed) >= 6 && !str[consumed]) { + /* + Normally we should check that each part has two digits to prevent ambiguities. + However, in old tinc versions net2str() will aggressively return MAC addresses with one-digit parts, + so we have to accept them otherwise we would be unable to parse ADD_SUBNET messages. + */ + if(prefixlength >= 0) { + return false; + } + + subnet->type = SUBNET_MAC; + subnet->weight = weight; + + for(int i = 0; i < 6; i++) { + subnet->net.mac.address.x[i] = x[i]; + } + + return true; + } + + if(sscanf(str, "%hu.%hu.%hu.%hu%n", &x[0], &x[1], &x[2], &x[3], &consumed) >= 4 && !str[consumed]) { + if(prefixlength == -1) { + prefixlength = 32; + } + + if(prefixlength > 32) { + return false; + } + + subnet->type = SUBNET_IPV4; + subnet->net.ipv4.prefixlength = prefixlength; + 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; + } + + /* IPv6 */ + + char *last_colon = strrchr(str, ':'); + + if(last_colon && sscanf(last_colon, ":%hu.%hu.%hu.%hu%n", &x[0], &x[1], &x[2], &x[3], &consumed) >= 4 && !last_colon[consumed]) { + /* Dotted quad suffix notation, convert to standard IPv6 notation */ + for(int i = 0; i < 4; i++) + if(x[i] > 255) { + return false; + } + + snprintf(last_colon, sizeof(str) - (last_colon - str), ":%02x%02x:%02x%02x", x[0], x[1], x[2], x[3]); + } + + char *double_colon = strstr(str, "::"); + + if(double_colon) { + /* Figure out how many zero groups we need to expand */ + int zero_group_count = 8; + + for(const char *cur = str; *cur; cur++) + if(*cur != ':') { + zero_group_count--; + + while(cur[1] && cur[1] != ':') { + cur++; + } + } + + if(zero_group_count < 1) { + return false; + } + + /* Split the double colon in the middle to make room for zero groups */ + double_colon++; + memmove(double_colon + (zero_group_count * 2 - 1), double_colon, strlen(double_colon) + 1); + + /* Write zero groups in the resulting gap, overwriting the second colon */ + for(int i = 0; i < zero_group_count; i++) { + memcpy(&double_colon[i * 2], "0:", 2); + } + + /* Remove any leading or trailing colons */ + if(str[0] == ':') { + memmove(&str[0], &str[1], strlen(&str[1]) + 1); + } + + if(str[strlen(str) - 1] == ':') { + str[strlen(str) - 1] = 0; + } + } + + if(sscanf(str, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx%n", + &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], &consumed) >= 8 && !str[consumed]) { + if(prefixlength == -1) { + prefixlength = 128; + } + + if(prefixlength > 128) { + return false; + } + + subnet->type = SUBNET_IPV6; + subnet->net.ipv6.prefixlength = prefixlength; + subnet->weight = weight; + + for(int 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(LOG_ERR, "net2str() was called with netstr=%p, subnet=%p!", (void *)netstr, (void *)subnet); + return false; + } + + switch(subnet->type) { + case SUBNET_MAC: + snprintf(netstr, len, "%x:%x:%x:%x:%x:%x#%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, "%u.%u.%u.%u/%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, "%x:%x:%x:%x:%x:%x:%x:%x/%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(LOG_ERR, + "net2str() was called with unknown subnet type %d, exiting!", + subnet->type); + exit(0); + } + + return true; +} + /* Subnet lookup routines */ subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) { - return splay_search(owner->subnet_tree, subnet); + return avl_search(owner->subnet_tree, subnet); } subnet_t *lookup_subnet_mac(const node_t *owner, const mac_t *address) { - subnet_t *r = NULL; + subnet_t *p, *r = NULL; + avl_node_t *n; + int i; // Check if this address is cached - if((r = hash_search(mac_cache, address))) - return r; + for(i = 0; i < 2; i++) { + if(!cache_mac_valid[i]) { + continue; + } + + if(owner && cache_mac_subnet[i] && cache_mac_subnet[i]->owner != owner) { + continue; + } + + if(!memcmp(address, &cache_mac_address[i], sizeof(*address))) { + return cache_mac_subnet[i]; + } + } // 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; + for(n = owner ? owner->subnet_tree->head : subnet_tree->head; n; n = n->next) { + p = n->data; - if(!memcmp(address, &p->net.mac.address, sizeof *address)) { + if(!p || p->type != SUBNET_MAC) { + continue; + } + + if(!memcmp(address, &p->net.mac.address, sizeof(*address))) { r = p; - if(p->owner->status.reachable) + + if(p->owner->status.reachable) { break; + } } } // Cache the result - if(r) - hash_insert(mac_cache, address, r); + cache_mac_slot = !cache_mac_slot; + memcpy(&cache_mac_address[cache_mac_slot], address, sizeof(*address)); + cache_mac_subnet[cache_mac_slot] = r; + cache_mac_valid[cache_mac_slot] = true; return r; } subnet_t *lookup_subnet_ipv4(const ipv4_t *address) { - subnet_t *r = NULL; + subnet_t *p, *r = NULL; + avl_node_t *n; + int i; // Check if this address is cached - if((r = hash_search(ipv4_cache, address))) - return r; + for(i = 0; i < 2; i++) { + if(!cache_ipv4_valid[i]) { + continue; + } + + if(!memcmp(address, &cache_ipv4_address[i], sizeof(*address))) { + return cache_ipv4_subnet[i]; + } + } // Search all subnets for a matching one - for splay_each(subnet_t, p, subnet_tree) { - if(!p || p->type != SUBNET_IPV4) + for(n = subnet_tree->head; n; n = n->next) { + p = n->data; + + 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) + + if(p->owner->status.reachable) { break; + } } } // Cache the result - if(r) - hash_insert(ipv4_cache, address, r); + cache_ipv4_slot = !cache_ipv4_slot; + memcpy(&cache_ipv4_address[cache_ipv4_slot], address, sizeof(*address)); + cache_ipv4_subnet[cache_ipv4_slot] = r; + cache_ipv4_valid[cache_ipv4_slot] = true; return r; } subnet_t *lookup_subnet_ipv6(const ipv6_t *address) { - subnet_t *r = NULL; + subnet_t *p, *r = NULL; + avl_node_t *n; + int i; // Check if this address is cached - if((r = hash_search(ipv6_cache, address))) - return r; + for(i = 0; i < 2; i++) { + if(!cache_ipv6_valid[i]) { + continue; + } + + if(!memcmp(address, &cache_ipv6_address[i], sizeof(*address))) { + return cache_ipv6_subnet[i]; + } + } // Search all subnets for a matching one - for splay_each(subnet_t, p, subnet_tree) { - if(!p || p->type != SUBNET_IPV6) + for(n = subnet_tree->head; n; n = n->next) { + p = n->data; + + 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) + + if(p->owner->status.reachable) { break; + } } } // Cache the result - if(r) - hash_insert(ipv6_cache, address, r); + cache_ipv6_slot = !cache_ipv6_slot; + memcpy(&cache_ipv6_address[cache_ipv6_slot], address, sizeof(*address)); + cache_ipv6_subnet[cache_ipv6_slot] = r; + cache_ipv6_valid[cache_ipv6_slot] = true; return r; } void subnet_update(node_t *owner, subnet_t *subnet, bool up) { + avl_node_t *node; + int i; + char *envp[10] = {NULL}; 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[0], "NETNAME=%s", netname ? netname : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? device : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? iface : ""); xasprintf(&envp[3], "NODE=%s", owner->name); + xasprintf(&envp[4], "NAME=%s", myself->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); + // 5 and 6 are reserved for SUBNET and WEIGHT + xasprintf(&envp[7], "REMOTEADDRESS=%s", address); + xasprintf(&envp[8], "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)) + for(node = owner->subnet_tree->head; node; node = node->next) { + subnet = node->data; + + 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) + + if(weight) { *weight++ = 0; - else + } 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); + free(envp[5]); + free(envp[6]); + + xasprintf(&envp[5], "SUBNET=%s", netstr); + xasprintf(&envp[6], "WEIGHT=%s", weight); execute_script(name, envp); } } else { - if(net2str(netstr, sizeof netstr, subnet)) { + if(net2str(netstr, sizeof(netstr), subnet)) { // Strip the weight from the subnet, and put it in its own environment variable char *weight = strchr(netstr, '#'); - if(weight) + + if(weight) { *weight++ = 0; - else + } else { weight = empty; + } // Prepare the SUBNET and WEIGHT variables - xasprintf(&envp[4], "SUBNET=%s", netstr); - xasprintf(&envp[5], "WEIGHT=%s", weight); + xasprintf(&envp[5], "SUBNET=%s", netstr); + xasprintf(&envp[6], "WEIGHT=%s", weight); execute_script(name, envp); } } - for(int i = 0; envp[i] && i < 9; i++) + for(i = 0; i < 9; i++) { free(envp[i]); + } } -bool dump_subnets(connection_t *c) { - for splay_each(subnet_t, subnet, subnet_tree) { - char netstr[MAXNETSTR]; +void dump_subnets(void) { + char netstr[MAXNETSTR]; + subnet_t *subnet; + avl_node_t *node; - if(!net2str(netstr, sizeof netstr, subnet)) + logger(LOG_DEBUG, "Subnet list:"); + + for(node = subnet_tree->head; node; node = node->next) { + subnet = node->data; + + if(!net2str(netstr, sizeof(netstr), subnet)) { continue; + } - send_request(c, "%d %d %s %s", - CONTROL, REQ_DUMP_SUBNETS, - netstr, subnet->owner->name); + logger(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name); } - return send_request(c, "%d %d", CONTROL, REQ_DUMP_SUBNETS); + logger(LOG_DEBUG, "End of subnet list."); } diff --git a/src/subnet.h b/src/subnet.h index 9fd95b6..6fecca3 100644 --- a/src/subnet.h +++ b/src/subnet.h @@ -1,6 +1,9 @@ +#ifndef TINC_SUBNET_H +#define TINC_SUBNET_H + /* subnet.h -- header for subnet.c - Copyright (C) 2000-2012 Guus Sliepen , + Copyright (C) 2000-2009 Guus Sliepen , 2000-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify @@ -18,16 +21,13 @@ 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_TYPES, /* Guardian */ } subnet_type_t; typedef struct subnet_mac_t { @@ -47,11 +47,11 @@ typedef struct subnet_ipv6_t { #include "node.h" typedef struct subnet_t { - struct node_t *owner; /* the owner of this subnet */ + 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) */ + 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: */ @@ -64,29 +64,24 @@ typedef struct subnet_t { #define MAXNETSTR 64 -extern splay_tree_t *subnet_tree; +extern avl_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 subnet_t *new_subnet(void) __attribute__((__malloc__)); +extern void free_subnet(subnet_t *subnet); 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 avl_tree_t *new_subnet_tree(void) __attribute__((__malloc__)); +extern void free_subnet_tree(avl_tree_t *subnet_tree); +extern void subnet_add(struct node_t *owner, subnet_t *subnet); +extern void subnet_del(struct node_t *owner, subnet_t *subnet); +extern void subnet_update(struct node_t *owner, subnet_t *subnet, bool up); +extern bool net2str(char *netstr, int len, const subnet_t *subnet); +extern bool str2net(subnet_t *subnet, const char *netstr); +extern subnet_t *lookup_subnet(const struct node_t *owner, const subnet_t *subnet); +extern subnet_t *lookup_subnet_mac(const struct node_t *owner, const mac_t *address); +extern subnet_t *lookup_subnet_ipv4(const ipv4_t *address); +extern subnet_t *lookup_subnet_ipv6(const ipv6_t *address); +extern void dump_subnets(void); extern void subnet_cache_flush(void); -#endif /* __TINC_SUBNET_H__ */ +#endif diff --git a/src/subnet_parse.c b/src/subnet_parse.c deleted file mode 100644 index f980180..0000000 --- a/src/subnet_parse.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - subnet_parse.c -- handle subnet parsing - Copyright (C) 2000-2012 Guus Sliepen , - 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; -} diff --git a/src/system.h b/src/system.h index 7180b87..14db7f5 100644 --- a/src/system.h +++ b/src/system.h @@ -1,7 +1,10 @@ +#ifndef TINC_SYSTEM_H +#define TINC_SYSTEM_H + /* system.h -- system headers Copyright (C) 1998-2005 Ivo Timmermans - 2003-2013 Guus Sliepen + 2003-2006 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,19 +21,10 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_SYSTEM_H__ -#define __TINC_SYSTEM_H__ - -#include "../config.h" +#include "config.h" #include "have.h" -#ifndef HAVE_STDBOOL_H -typedef int bool; -#define true 1 -#define false 0 -#endif - #ifndef HAVE_STRSIGNAL # define strsignal(p) "" #endif @@ -43,4 +37,4 @@ typedef int bool; typedef int socklen_t; #endif -#endif /* __TINC_SYSTEM_H__ */ +#endif diff --git a/src/tincctl.c b/src/tincctl.c deleted file mode 100644 index 55e14e5..0000000 --- a/src/tincctl.c +++ /dev/null @@ -1,2389 +0,0 @@ -/* - tincctl.c -- Controlling a running tincd - Copyright (C) 2007-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#include - -#ifdef HAVE_READLINE -#include "readline/readline.h" -#include "readline/history.h" -#endif - -#include "xalloc.h" -#include "protocol.h" -#include "control_common.h" -#include "crypto.h" -#include "ecdsagen.h" -#include "info.h" -#include "invitation.h" -#include "names.h" -#include "rsagen.h" -#include "utils.h" -#include "tincctl.h" -#include "top.h" - -#ifdef HAVE_MINGW -#define SCRIPTEXTENSION ".bat" -#else -#define SCRIPTEXTENSION "" -#endif - -static char **orig_argv; -static int orig_argc; - -/* If nonzero, display usage information and exit. */ -static bool show_help = false; - -/* If nonzero, print the version on standard output and exit. */ -static bool show_version = false; - -static char *name = NULL; -static char controlcookie[1025]; -char *tinc_conf = NULL; -char *hosts_dir = NULL; -struct timeval now; - -// Horrible global variables... -static int pid = 0; -int fd = -1; -char line[4096]; -static int code; -static int req; -static int result; -static bool force = false; -bool tty = true; -bool confbasegiven = false; -bool netnamegiven = false; - -#ifdef HAVE_MINGW -static struct WSAData wsa_state; -#endif - -static struct option const long_options[] = { - {"config", required_argument, NULL, 'c'}, - {"net", required_argument, NULL, 'n'}, - {"help", no_argument, NULL, 1}, - {"version", no_argument, NULL, 2}, - {"pidfile", required_argument, NULL, 3}, - {"force", no_argument, NULL, 4}, - {NULL, 0, NULL, 0} -}; - -static void version(void) { - printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE, - VERSION, __DATE__, __TIME__, PROT_MAJOR, PROT_MINOR); - printf("Copyright (C) 1998-2012 Ivo Timmermans, Guus Sliepen and others.\n" - "See the AUTHORS file for a complete list.\n\n" - "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" - "and you are welcome to redistribute it under certain conditions;\n" - "see the file COPYING for details.\n"); -} - -static void usage(bool status) { - if(status) { - fprintf(stderr, "Try `%s --help\' for more information.\n", program_name); - } else { - printf("Usage: %s [options] command\n\n", program_name); - printf("Valid options are:\n" - " -c, --config=DIR Read configuration options from DIR.\n" - " -n, --net=NETNAME Connect to net NETNAME.\n" - " --pidfile=FILENAME Read control cookie from FILENAME.\n" - " --help Display this help and exit.\n" - " --version Output version information and exit.\n" - "\n" - "Valid commands are:\n" - " init [name] Create initial configuration files.\n" - " get VARIABLE Print current value of VARIABLE\n" - " set VARIABLE VALUE Set VARIABLE to VALUE\n" - " add VARIABLE VALUE Add VARIABLE with the given VALUE\n" - " del VARIABLE [VALUE] Remove VARIABLE [only ones with watching VALUE]\n" - " start [tincd options] Start tincd.\n" - " stop Stop tincd.\n" - " restart [tincd options] Restart tincd.\n" - " reload Partially reload configuration of running tincd.\n" - " pid Show PID of currently running tincd.\n" - " generate-keys [bits] Generate new RSA and ECDSA public/private keypairs.\n" - " generate-rsa-keys [bits] Generate a new RSA public/private keypair.\n" - " generate-ecdsa-keys Generate a new ECDSA public/private keypair.\n" - " dump Dump a list of one of the following things:\n" - " [reachable] nodes - all known nodes in the VPN\n" - " edges - all known connections in the VPN\n" - " subnets - all known subnets in the VPN\n" - " connections - all meta connections with ourself\n" - " [di]graph - graph of the VPN in dotty format\n" - " info NODE|SUBNET|ADDRESS Give information about a particular NODE, SUBNET or ADDRESS.\n" - " purge Purge unreachable nodes\n" - " debug N Set debug level\n" - " retry Retry all outgoing connections\n" - " disconnect NODE Close meta connection with NODE\n" -#ifdef HAVE_CURSES - " top Show real-time statistics\n" -#endif - " pcap [snaplen] Dump traffic in pcap format [up to snaplen bytes per packet]\n" - " log [level] Dump log output [up to the specified level]\n" - " export Export host configuration of local node to standard output\n" - " export-all Export all host configuration files to standard output\n" - " import [--force] Import host configuration file(s) from standard input\n" - " exchange [--force] Same as export followed by import\n" - " exchange-all [--force] Same as export-all followed by import\n" - " invite NODE [...] Generate an invitation for NODE\n" - " join INVITATION Join a VPN using an INVITIATION\n" - "\n"); - printf("Report bugs to tinc@tinc-vpn.org.\n"); - } -} - -static bool parse_options(int argc, char **argv) { - int r; - int option_index = 0; - - while((r = getopt_long(argc, argv, "+c:n:", long_options, &option_index)) != EOF) { - switch (r) { - case 0: /* long option */ - break; - - case 'c': /* config file */ - confbase = xstrdup(optarg); - confbasegiven = true; - break; - - case 'n': /* net name given */ - netname = xstrdup(optarg); - break; - - case 1: /* show help */ - show_help = true; - break; - - case 2: /* show version */ - show_version = true; - break; - - case 3: /* open control socket here */ - pidfilename = xstrdup(optarg); - break; - - case 4: /* force */ - force = true; - break; - - case '?': /* wrong options */ - usage(true); - return false; - - default: - break; - } - } - - 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; -} - -/* Open a file with the desired permissions, minus the umask. - Also, if we want to create an executable file, we call fchmod() - to set the executable bits. */ - -FILE *fopenmask(const char *filename, const char *mode, mode_t perms) { - mode_t mask = umask(0); - perms &= ~mask; - umask(~perms); - FILE *f = fopen(filename, mode); -#ifdef HAVE_FCHMOD - if((perms & 0444) && f) - fchmod(fileno(f), perms); -#endif - umask(mask); - return f; -} - -static void disable_old_keys(const char *filename, const char *what) { - char tmpfile[PATH_MAX] = ""; - char buf[1024]; - bool disabled = false; - bool block = false; - bool error = false; - FILE *r, *w; - - r = fopen(filename, "r"); - if(!r) - return; - - snprintf(tmpfile, sizeof tmpfile, "%s.tmp", filename); - - struct stat st = {.st_mode = 0600}; - fstat(fileno(r), &st); - w = fopenmask(tmpfile, "w", st.st_mode); - - while(fgets(buf, sizeof buf, r)) { - if(!block && !strncmp(buf, "-----BEGIN ", 11)) { - if((strstr(buf, " EC ") && strstr(what, "ECDSA")) || (strstr(buf, " RSA ") && strstr(what, "RSA"))) { - disabled = true; - block = true; - } - } - - bool ecdsapubkey = !strncasecmp(buf, "ECDSAPublicKey", 14) && strchr(" \t=", buf[14]) && strstr(what, "ECDSA"); - - if(ecdsapubkey) - disabled = true; - - if(w) { - if(block || ecdsapubkey) - fputc('#', w); - if(fputs(buf, w) < 0) { - error = true; - break; - } - } - - if(block && !strncmp(buf, "-----END ", 9)) - block = false; - } - - if(w) - if(fclose(w) < 0) - error = true; - if(ferror(r) || fclose(r) < 0) - error = true; - - if(disabled) { - if(!w || error) { - fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); - if(w) - unlink(tmpfile); - return; - } - -#ifdef HAVE_MINGW - // We cannot atomically replace files on Windows. - char bakfile[PATH_MAX] = ""; - snprintf(bakfile, sizeof bakfile, "%s.bak", filename); - if(rename(filename, bakfile) || rename(tmpfile, filename)) { - rename(bakfile, filename); -#else - if(rename(tmpfile, filename)) { -#endif - fprintf(stderr, "Warning: old key(s) found, remove them by hand!\n"); - } else { -#ifdef HAVE_MINGW - unlink(bakfile); -#endif - fprintf(stderr, "Warning: old key(s) found and disabled.\n"); - } - } - - unlink(tmpfile); -} - -static FILE *ask_and_open(const char *filename, const char *what, const char *mode, bool ask, mode_t perms) { - FILE *r; - char *directory; - char buf[PATH_MAX]; - char buf2[PATH_MAX]; - - /* Check stdin and stdout */ - if(ask && tty) { - /* Ask for a file and/or directory name. */ - fprintf(stdout, "Please enter a file to save %s to [%s]: ", what, filename); - fflush(stdout); - - if(fgets(buf, sizeof buf, stdin) == NULL) { - fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno)); - return NULL; - } - - size_t len = strlen(buf); - if(len) - buf[--len] = 0; - - if(len) - filename = buf; - } - -#ifdef HAVE_MINGW - if(filename[0] != '\\' && filename[0] != '/' && !strchr(filename, ':')) { -#else - if(filename[0] != '/') { -#endif - /* The directory is a relative path or a filename. */ - directory = get_current_dir_name(); - snprintf(buf2, sizeof buf2, "%s" SLASH "%s", directory, filename); - filename = buf2; - } - - disable_old_keys(filename, what); - - /* Open it first to keep the inode busy */ - - r = fopenmask(filename, mode, perms); - - if(!r) { - fprintf(stderr, "Error opening file `%s': %s\n", filename, strerror(errno)); - return NULL; - } - - return r; -} - -/* - Generate a public/private ECDSA keypair, and ask for a file to store - them in. -*/ -static bool ecdsa_keygen(bool ask) { - ecdsa_t *key; - FILE *f; - char *pubname, *privname; - - fprintf(stderr, "Generating ECDSA keypair:\n"); - - if(!(key = ecdsa_generate())) { - fprintf(stderr, "Error during key generation!\n"); - return false; - } else - fprintf(stderr, "Done.\n"); - - xasprintf(&privname, "%s" SLASH "ecdsa_key.priv", confbase); - f = ask_and_open(privname, "private ECDSA key", "a", ask, 0600); - free(privname); - - if(!f) - return false; - - if(!ecdsa_write_pem_private_key(key, f)) { - fprintf(stderr, "Error writing private key!\n"); - ecdsa_free(key); - fclose(f); - return false; - } - - fclose(f); - - if(name) - xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name); - else - xasprintf(&pubname, "%s" SLASH "ecdsa_key.pub", confbase); - - f = ask_and_open(pubname, "public ECDSA key", "a", ask, 0666); - free(pubname); - - if(!f) - return false; - - char *pubkey = ecdsa_get_base64_public_key(key); - fprintf(f, "ECDSAPublicKey = %s\n", pubkey); - free(pubkey); - - fclose(f); - ecdsa_free(key); - - return true; -} - -/* - Generate a public/private RSA keypair, and ask for a file to store - them in. -*/ -static bool rsa_keygen(int bits, bool ask) { - rsa_t *key; - FILE *f; - char *pubname, *privname; - - fprintf(stderr, "Generating %d bits keys:\n", bits); - - if(!(key = rsa_generate(bits, 0x10001))) { - fprintf(stderr, "Error during key generation!\n"); - return false; - } else - fprintf(stderr, "Done.\n"); - - xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase); - f = ask_and_open(privname, "private RSA key", "a", ask, 0600); - free(privname); - - if(!f) - return false; - - if(!rsa_write_pem_private_key(key, f)) { - fprintf(stderr, "Error writing private key!\n"); - fclose(f); - rsa_free(key); - return false; - } - - fclose(f); - - if(name) - xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name); - else - xasprintf(&pubname, "%s" SLASH "rsa_key.pub", confbase); - - f = ask_and_open(pubname, "public RSA key", "a", ask, 0666); - free(pubname); - - if(!f) - return false; - - if(!rsa_write_pem_public_key(key, f)) { - fprintf(stderr, "Error writing public key!\n"); - fclose(f); - rsa_free(key); - return false; - } - - fclose(f); - rsa_free(key); - - return true; -} - -char buffer[4096]; -size_t blen = 0; - -bool recvline(int fd, char *line, size_t len) { - char *newline = NULL; - - if(!fd) - abort(); - - while(!(newline = memchr(buffer, '\n', blen))) { - int result = recv(fd, buffer + blen, sizeof buffer - blen, 0); - if(result == -1 && errno == EINTR) - continue; - else if(result <= 0) - return false; - blen += result; - } - - if(newline - buffer >= len) - return false; - - len = newline - buffer; - - memcpy(line, buffer, len); - line[len] = 0; - memmove(buffer, newline + 1, blen - len - 1); - blen -= len + 1; - - return true; -} - -bool recvdata(int fd, char *data, size_t len) { - if(len == -1) - len = blen; - - while(blen < len) { - int result = recv(fd, buffer + blen, sizeof buffer - blen, 0); - if(result == -1 && errno == EINTR) - continue; - else if(result <= 0) - return false; - blen += result; - } - - memcpy(data, buffer, len); - memmove(buffer, buffer + len, blen - len); - blen -= len; - - return true; -} - -bool sendline(int fd, char *format, ...) { - static char buffer[4096]; - char *p = buffer; - int blen = 0; - va_list ap; - - va_start(ap, format); - blen = vsnprintf(buffer, sizeof buffer, format, ap); - va_end(ap); - - if(blen < 1 || blen >= sizeof buffer) - return false; - - buffer[blen] = '\n'; - blen++; - - while(blen) { - int result = send(fd, p, blen, 0); - if(result == -1 && errno == EINTR) - continue; - else if(result <= 0) - return false; - p += result; - blen -= result; - } - - return true; -} - -static void pcap(int fd, FILE *out, int snaplen) { - sendline(fd, "%d %d %d", CONTROL, REQ_PCAP, snaplen); - char data[9018]; - - struct { - uint32_t magic; - uint16_t major; - uint16_t minor; - uint32_t tz_offset; - uint32_t tz_accuracy; - uint32_t snaplen; - uint32_t ll_type; - } header = { - 0xa1b2c3d4, - 2, 4, - 0, 0, - snaplen ?: sizeof data, - 1, - }; - - struct { - uint32_t tv_sec; - uint32_t tv_usec; - uint32_t len; - uint32_t origlen; - } packet; - - struct timeval tv; - - fwrite(&header, sizeof header, 1, out); - fflush(out); - - char line[32]; - while(recvline(fd, line, sizeof line)) { - int code, req, len; - int n = sscanf(line, "%d %d %d", &code, &req, &len); - gettimeofday(&tv, NULL); - if(n != 3 || code != CONTROL || req != REQ_PCAP || len < 0 || len > sizeof data) - break; - if(!recvdata(fd, data, len)) - break; - packet.tv_sec = tv.tv_sec; - packet.tv_usec = tv.tv_usec; - packet.len = len; - packet.origlen = len; - fwrite(&packet, sizeof packet, 1, out); - fwrite(data, len, 1, out); - fflush(out); - } -} - -static void logcontrol(int fd, FILE *out, int level) { - sendline(fd, "%d %d %d", CONTROL, REQ_LOG, level); - char data[1024]; - char line[32]; - - while(recvline(fd, line, sizeof line)) { - int code, req, len; - int n = sscanf(line, "%d %d %d", &code, &req, &len); - if(n != 3 || code != CONTROL || req != REQ_LOG || len < 0 || len > sizeof data) - break; - if(!recvdata(fd, data, len)) - break; - fwrite(data, len, 1, out); - fputc('\n', out); - fflush(out); - } -} - -#ifdef HAVE_MINGW -static bool remove_service(void) { - SC_HANDLE manager = NULL; - SC_HANDLE service = NULL; - SERVICE_STATUS status = {0}; - - manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - if(!manager) { - fprintf(stderr, "Could not open service manager: %s\n", winerror(GetLastError())); - return false; - } - - service = OpenService(manager, identname, SERVICE_ALL_ACCESS); - - if(!service) { - fprintf(stderr, "Could not open %s service: %s\n", identname, winerror(GetLastError())); - return false; - } - - if(!ControlService(service, SERVICE_CONTROL_STOP, &status)) - fprintf(stderr, "Could not stop %s service: %s\n", identname, winerror(GetLastError())); - else - fprintf(stderr, "%s service stopped\n", identname); - - if(!DeleteService(service)) { - fprintf(stderr, "Could not remove %s service: %s\n", identname, winerror(GetLastError())); - return false; - } - - fprintf(stderr, "%s service removed\n", identname); - - return true; -} -#endif - -bool connect_tincd(bool verbose) { - if(fd >= 0) { - fd_set r; - FD_ZERO(&r); - FD_SET(fd, &r); - struct timeval tv = {0, 0}; - if(select(fd + 1, &r, NULL, NULL, &tv)) { - fprintf(stderr, "Previous connection to tincd lost, reconnecting.\n"); - close(fd); - fd = -1; - } else { - return true; - } - } - - FILE *f = fopen(pidfilename, "r"); - if(!f) { - if(verbose) - fprintf(stderr, "Could not open pid file %s: %s\n", pidfilename, strerror(errno)); - return false; - } - - char host[129]; - char port[129]; - - if(fscanf(f, "%20d %1024s %128s port %128s", &pid, controlcookie, host, port) != 4) { - if(verbose) - fprintf(stderr, "Could not parse pid file %s\n", pidfilename); - fclose(f); - return false; - } - - fclose(f); - -#ifdef HAVE_MINGW - if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) { - if(verbose) - fprintf(stderr, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError())); - return false; - } -#endif - -#ifndef HAVE_MINGW - struct sockaddr_un sa; - sa.sun_family = AF_UNIX; - strncpy(sa.sun_path, unixsocketname, sizeof sa.sun_path); - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(fd < 0) { - if(verbose) - fprintf(stderr, "Cannot create UNIX socket: %s\n", sockstrerror(sockerrno)); - return false; - } - - if(connect(fd, (struct sockaddr *)&sa, sizeof sa) < 0) { - if(verbose) - fprintf(stderr, "Cannot connect to UNIX socket %s: %s\n", unixsocketname, sockstrerror(sockerrno)); - close(fd); - fd = -1; - return false; - } -#else - struct addrinfo hints = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - .ai_flags = 0, - }; - - struct addrinfo *res = NULL; - - if(getaddrinfo(host, port, &hints, &res) || !res) { - if(verbose) - fprintf(stderr, "Cannot resolve %s port %s: %s", host, port, strerror(errno)); - return false; - } - - fd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP); - if(fd < 0) { - if(verbose) - fprintf(stderr, "Cannot create TCP socket: %s\n", sockstrerror(sockerrno)); - return false; - } - -#ifdef HAVE_MINGW - unsigned long arg = 0; - - if(ioctlsocket(fd, FIONBIO, &arg) != 0) { - if(verbose) - fprintf(stderr, "ioctlsocket failed: %s", sockstrerror(sockerrno)); - } -#endif - - if(connect(fd, res->ai_addr, res->ai_addrlen) < 0) { - if(verbose) - fprintf(stderr, "Cannot connect to %s port %s: %s\n", host, port, sockstrerror(sockerrno)); - close(fd); - fd = -1; - return false; - } - - freeaddrinfo(res); -#endif - - char data[4096]; - int version; - - if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %s %d", &code, data, &version) != 3 || code != 0) { - if(verbose) - fprintf(stderr, "Cannot read greeting from control socket: %s\n", sockstrerror(sockerrno)); - close(fd); - fd = -1; - return false; - } - - sendline(fd, "%d ^%s %d", ID, controlcookie, TINC_CTL_VERSION_CURRENT); - - if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &version, &pid) != 3 || code != 4 || version != TINC_CTL_VERSION_CURRENT) { - if(verbose) - fprintf(stderr, "Could not fully establish control socket connection\n"); - close(fd); - fd = -1; - return false; - } - - return true; -} - - -static int cmd_start(int argc, char *argv[]) { - if(connect_tincd(false)) { - if(netname) - fprintf(stderr, "A tincd is already running for net `%s' with pid %d.\n", netname, pid); - else - fprintf(stderr, "A tincd is already running with pid %d.\n", pid); - return 0; - } - - char *c; - char *slash = strrchr(program_name, '/'); - -#ifdef HAVE_MINGW - if ((c = strrchr(program_name, '\\')) > slash) - slash = c; -#endif - - if (slash++) - xasprintf(&c, "%.*stincd", (int)(slash - program_name), program_name); - else - c = "tincd"; - - int nargc = 0; - char **nargv = xzalloc((optind + argc) * sizeof *nargv); - - nargv[nargc++] = c; - for(int i = 1; i < optind; i++) - nargv[nargc++] = orig_argv[i]; - for(int i = 1; i < argc; i++) - nargv[nargc++] = argv[i]; - -#ifdef HAVE_MINGW - execvp(c, nargv); - fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno)); - return 1; -#else - pid_t pid = fork(); - if(pid == -1) { - fprintf(stderr, "Could not fork: %s\n", strerror(errno)); - free(nargv); - return 1; - } - - if(!pid) - exit(execvp(c, nargv)); - - free(nargv); - - int status = -1, result; -#ifdef SIGINT - signal(SIGINT, SIG_IGN); -#endif - result = waitpid(pid, &status, 0); -#ifdef SIGINT - signal(SIGINT, SIG_DFL); -#endif - - if(result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) { - fprintf(stderr, "Error starting %s\n", c); - return 1; - } - - return 0; -#endif -} - -static int cmd_stop(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - -#ifndef HAVE_MINGW - if(!connect_tincd(true)) { - if(pid) { - if(kill(pid, SIGTERM)) { - fprintf(stderr, "Could not send TERM signal to process with PID %u: %s\n", pid, strerror(errno)); - return 1; - } - - fprintf(stderr, "Sent TERM signal to process with PID %u.\n", pid); - waitpid(pid, NULL, 0); - return 0; - } - - return 1; - } - - sendline(fd, "%d %d", CONTROL, REQ_STOP); - - while(recvline(fd, line, sizeof line)) { - // Wait for tincd to close the connection... - } -#else - if(!remove_service()) - return 1; -#endif - close(fd); - pid = 0; - fd = -1; - - return 0; -} - -static int cmd_restart(int argc, char *argv[]) { - cmd_stop(1, argv); - return cmd_start(argc, argv); -} - -static int cmd_reload(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - sendline(fd, "%d %d", CONTROL, REQ_RELOAD); - if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RELOAD || result) { - fprintf(stderr, "Could not reload configuration.\n"); - return 1; - } - - return 0; - -} - -static int cmd_dump(int argc, char *argv[]) { - bool only_reachable = false; - - if(argc > 2 && !strcasecmp(argv[1], "reachable")) { - if(strcasecmp(argv[2], "nodes")) { - fprintf(stderr, "`reachable' only supported for nodes.\n"); - usage(true); - return 1; - } - only_reachable = true; - argv++; - argc--; - } - - if(argc != 2) { - fprintf(stderr, "Invalid number of arguments.\n"); - usage(true); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - int do_graph = 0; - - if(!strcasecmp(argv[1], "nodes")) - sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES); - else if(!strcasecmp(argv[1], "edges")) - sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES); - else if(!strcasecmp(argv[1], "subnets")) - sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS); - else if(!strcasecmp(argv[1], "connections")) - sendline(fd, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS); - else if(!strcasecmp(argv[1], "graph")) { - sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES); - sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES); - do_graph = 1; - } else if(!strcasecmp(argv[1], "digraph")) { - sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES); - sendline(fd, "%d %d", CONTROL, REQ_DUMP_EDGES); - do_graph = 2; - } else { - fprintf(stderr, "Unknown dump type '%s'.\n", argv[1]); - usage(true); - return 1; - } - - if(do_graph == 1) - printf("graph {\n"); - else if(do_graph == 2) - printf("digraph {\n"); - - while(recvline(fd, line, sizeof line)) { - char node1[4096], node2[4096]; - int n = sscanf(line, "%d %d %s %s", &code, &req, node1, node2); - if(n == 2) { - if(do_graph && req == REQ_DUMP_NODES) - continue; - else { - if(do_graph) - printf("}\n"); - return 0; - } - } - if(n < 2) - break; - - 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 cipher, digest, maclength, compression, distance, socket, weight; - short int pmtu, minmtu, maxmtu; - unsigned int options, status_int; - node_status_t status; - long int last_state_change; - - switch(req) { - case REQ_DUMP_NODES: { - int n = sscanf(line, "%*d %*d %s %s port %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", node, host, port, &cipher, &digest, &maclength, &compression, &options, &status_int, nexthop, via, &distance, &pmtu, &minmtu, &maxmtu, &last_state_change); - if(n != 16) { - fprintf(stderr, "Unable to parse node dump from tincd: %s\n", line); - return 1; - } - - memcpy(&status, &status_int, sizeof status); - - if(do_graph) { - const char *color = "black"; - if(!strcmp(host, "MYSELF")) - color = "green"; - else if(!status.reachable) - color = "red"; - else if(strcmp(via, node)) - color = "orange"; - else if(!status.validkey) - color = "black"; - else if(minmtu > 0) - color = "green"; - printf(" %s [label = \"%s\", color = \"%s\"%s];\n", node, node, color, strcmp(host, "MYSELF") ? "" : ", style = \"filled\""); - } else { - if(only_reachable && !status.reachable) - continue; - printf("%s at %s port %s cipher %d digest %d maclength %d compression %d options %x status %04x nexthop %s via %s distance %d pmtu %hd (min %hd max %hd)\n", - node, host, port, cipher, digest, maclength, compression, options, status_int, nexthop, via, distance, pmtu, minmtu, maxmtu); - } - } break; - - case REQ_DUMP_EDGES: { - int n = sscanf(line, "%*d %*d %s %s %s port %s %x %d", from, to, host, port, &options, &weight); - if(n != 6) { - fprintf(stderr, "Unable to parse edge dump from tincd.\n"); - return 1; - } - - if(do_graph) { - float w = 1 + 65536.0 / weight; - if(do_graph == 1 && strcmp(node1, node2) > 0) - printf(" %s -- %s [w = %f, weight = %f];\n", node1, node2, w, w); - else if(do_graph == 2) - printf(" %s -> %s [w = %f, weight = %f];\n", node1, node2, w, w); - } else { - printf("%s to %s at %s port %s options %x weight %d\n", from, to, host, port, options, weight); - } - } break; - - case REQ_DUMP_SUBNETS: { - int n = sscanf(line, "%*d %*d %s %s", subnet, node); - if(n != 2) { - fprintf(stderr, "Unable to parse subnet dump from tincd.\n"); - return 1; - } - printf("%s owner %s\n", strip_weight(subnet), node); - } break; - - case REQ_DUMP_CONNECTIONS: { - int n = sscanf(line, "%*d %*d %s %s port %s %x %d %x", node, host, port, &options, &socket, &status_int); - if(n != 6) { - fprintf(stderr, "Unable to parse connection dump from tincd.\n"); - return 1; - } - printf("%s at %s port %s options %x socket %d status %x\n", node, host, port, options, socket, status_int); - } break; - - default: - fprintf(stderr, "Unable to parse dump from tincd.\n"); - return 1; - } - } - - fprintf(stderr, "Error receiving dump.\n"); - return 1; -} - -static int cmd_purge(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - sendline(fd, "%d %d", CONTROL, REQ_PURGE); - if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_PURGE || result) { - fprintf(stderr, "Could not purge old information.\n"); - return 1; - } - - return 0; -} - -static int cmd_debug(int argc, char *argv[]) { - if(argc != 2) { - fprintf(stderr, "Invalid number of arguments.\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - int debuglevel = atoi(argv[1]); - int origlevel; - - sendline(fd, "%d %d %d", CONTROL, REQ_SET_DEBUG, debuglevel); - if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &origlevel) != 3 || code != CONTROL || req != REQ_SET_DEBUG) { - fprintf(stderr, "Could not set debug level.\n"); - return 1; - } - - fprintf(stderr, "Old level %d, new level %d.\n", origlevel, debuglevel); - return 0; -} - -static int cmd_retry(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - sendline(fd, "%d %d", CONTROL, REQ_RETRY); - if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_RETRY || result) { - fprintf(stderr, "Could not retry outgoing connections.\n"); - return 1; - } - - return 0; -} - -static int cmd_connect(int argc, char *argv[]) { - if(argc != 2) { - fprintf(stderr, "Invalid number of arguments.\n"); - return 1; - } - - if(!check_id(argv[1])) { - fprintf(stderr, "Invalid name for node.\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - sendline(fd, "%d %d %s", CONTROL, REQ_CONNECT, argv[1]); - if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_CONNECT || result) { - fprintf(stderr, "Could not connect to %s.\n", argv[1]); - return 1; - } - - return 0; -} - -static int cmd_disconnect(int argc, char *argv[]) { - if(argc != 2) { - fprintf(stderr, "Invalid number of arguments.\n"); - return 1; - } - - if(!check_id(argv[1])) { - fprintf(stderr, "Invalid name for node.\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - sendline(fd, "%d %d %s", CONTROL, REQ_DISCONNECT, argv[1]); - if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_DISCONNECT || result) { - fprintf(stderr, "Could not disconnect %s.\n", argv[1]); - return 1; - } - - return 0; -} - -static int cmd_top(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - -#ifdef HAVE_CURSES - if(!connect_tincd(true)) - return 1; - - top(fd); - return 0; -#else - fprintf(stderr, "This version of tinc was compiled without support for the curses library.\n"); - return 1; -#endif -} - -static int cmd_pcap(int argc, char *argv[]) { - if(argc > 2) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - pcap(fd, stdout, argc > 1 ? atoi(argv[1]) : 0); - return 0; -} - -#ifdef SIGINT -static void sigint_handler(int sig) { - fprintf(stderr, "\n"); - shutdown(fd, SHUT_RDWR); -} -#endif - -static int cmd_log(int argc, char *argv[]) { - if(argc > 2) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - -#ifdef SIGINT - signal(SIGINT, sigint_handler); -#endif - - logcontrol(fd, stdout, argc > 1 ? atoi(argv[1]) : -1); - -#ifdef SIGINT - signal(SIGINT, SIG_DFL); -#endif - - close(fd); - fd = -1; - return 0; -} - -static int cmd_pid(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!connect_tincd(true) && !pid) - return 1; - - printf("%d\n", pid); - return 0; -} - -int rstrip(char *value) { - int len = strlen(value); - while(len && strchr("\t\r\n ", value[len - 1])) - value[--len] = 0; - return len; -} - -char *get_my_name(bool verbose) { - FILE *f = fopen(tinc_conf, "r"); - if(!f) { - if(verbose) - fprintf(stderr, "Could not open %s: %s\n", tinc_conf, strerror(errno)); - return NULL; - } - - char buf[4096]; - char *value; - while(fgets(buf, sizeof buf, f)) { - int len = strcspn(buf, "\t ="); - value = buf + len; - value += strspn(value, "\t "); - if(*value == '=') { - value++; - value += strspn(value, "\t "); - } - if(!rstrip(value)) - continue; - buf[len] = 0; - if(strcasecmp(buf, "Name")) - continue; - if(*value) { - fclose(f); - return strdup(value); - } - } - - fclose(f); - if(verbose) - fprintf(stderr, "Could not find Name in %s.\n", tinc_conf); - return NULL; -} - -const var_t variables[] = { - /* Server configuration */ - {"AddressFamily", VAR_SERVER}, - {"AutoConnect", VAR_SERVER | VAR_SAFE}, - {"BindToAddress", VAR_SERVER | VAR_MULTIPLE}, - {"BindToInterface", VAR_SERVER}, - {"Broadcast", VAR_SERVER | VAR_SAFE}, - {"ConnectTo", VAR_SERVER | VAR_MULTIPLE | VAR_SAFE}, - {"DecrementTTL", VAR_SERVER}, - {"Device", VAR_SERVER}, - {"DeviceType", VAR_SERVER}, - {"DirectOnly", VAR_SERVER}, - {"ECDSAPrivateKeyFile", VAR_SERVER}, - {"ExperimentalProtocol", VAR_SERVER}, - {"Forwarding", VAR_SERVER}, - {"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE}, - {"Hostnames", VAR_SERVER}, - {"IffOneQueue", VAR_SERVER}, - {"Interface", VAR_SERVER}, - {"KeyExpire", VAR_SERVER}, - {"LocalDiscovery", VAR_SERVER}, - {"MACExpire", VAR_SERVER}, - {"MaxConnectionBurst", VAR_SERVER}, - {"MaxOutputBufferSize", VAR_SERVER}, - {"MaxTimeout", VAR_SERVER}, - {"Mode", VAR_SERVER | VAR_SAFE}, - {"Name", VAR_SERVER}, - {"PingInterval", VAR_SERVER}, - {"PingTimeout", VAR_SERVER}, - {"PriorityInheritance", VAR_SERVER}, - {"PrivateKey", VAR_SERVER | VAR_OBSOLETE}, - {"PrivateKeyFile", VAR_SERVER}, - {"ProcessPriority", VAR_SERVER}, - {"Proxy", VAR_SERVER}, - {"ReplayWindow", VAR_SERVER}, - {"ScriptsExtension", VAR_SERVER}, - {"ScriptsInterpreter", VAR_SERVER}, - {"StrictSubnets", VAR_SERVER}, - {"TunnelServer", VAR_SERVER}, - {"UDPRcvBuf", VAR_SERVER}, - {"UDPSndBuf", VAR_SERVER}, - {"VDEGroup", VAR_SERVER}, - {"VDEPort", VAR_SERVER}, - /* Host configuration */ - {"Address", VAR_HOST | VAR_MULTIPLE}, - {"Cipher", VAR_SERVER | VAR_HOST}, - {"ClampMSS", VAR_SERVER | VAR_HOST}, - {"Compression", VAR_SERVER | VAR_HOST}, - {"Digest", VAR_SERVER | VAR_HOST}, - {"ECDSAPublicKey", VAR_HOST}, - {"ECDSAPublicKeyFile", VAR_SERVER | VAR_HOST}, - {"IndirectData", VAR_SERVER | VAR_HOST}, - {"MACLength", VAR_SERVER | VAR_HOST}, - {"PMTU", VAR_SERVER | VAR_HOST}, - {"PMTUDiscovery", VAR_SERVER | VAR_HOST}, - {"Port", VAR_HOST}, - {"PublicKey", VAR_HOST | VAR_OBSOLETE}, - {"PublicKeyFile", VAR_SERVER | VAR_HOST | VAR_OBSOLETE}, - {"Subnet", VAR_HOST | VAR_MULTIPLE | VAR_SAFE}, - {"TCPOnly", VAR_SERVER | VAR_HOST}, - {"Weight", VAR_HOST | VAR_SAFE}, - {NULL, 0} -}; - -static int cmd_config(int argc, char *argv[]) { - if(argc < 2) { - fprintf(stderr, "Invalid number of arguments.\n"); - return 1; - } - - if(strcasecmp(argv[0], "config")) - argv--, argc++; - - int action = -2; - if(!strcasecmp(argv[1], "get")) { - argv++, argc--; - } else if(!strcasecmp(argv[1], "add")) { - argv++, argc--, action = 1; - } else if(!strcasecmp(argv[1], "del")) { - argv++, argc--, action = -1; - } else if(!strcasecmp(argv[1], "replace") || !strcasecmp(argv[1], "set") || !strcasecmp(argv[1], "change")) { - argv++, argc--, action = 0; - } - - if(argc < 2) { - fprintf(stderr, "Invalid number of arguments.\n"); - return 1; - } - - // Concatenate the rest of the command line - strncpy(line, argv[1], sizeof line - 1); - for(int i = 2; i < argc; i++) { - strncat(line, " ", sizeof line - 1 - strlen(line)); - strncat(line, argv[i], sizeof line - 1 - strlen(line)); - } - - // Liberal parsing into node name, variable name and value. - char *node = NULL; - char *variable; - char *value; - int len; - - len = strcspn(line, "\t ="); - value = line + len; - value += strspn(value, "\t "); - if(*value == '=') { - value++; - value += strspn(value, "\t "); - } - line[len] = '\0'; - variable = strchr(line, '.'); - if(variable) { - node = line; - *variable++ = 0; - } else { - variable = line; - } - - if(!*variable) { - fprintf(stderr, "No variable given.\n"); - return 1; - } - - if(action >= 0 && !*value) { - fprintf(stderr, "No value for variable given.\n"); - return 1; - } - - if(action < -1 && *value) - action = 0; - - /* Some simple checks. */ - bool found = false; - bool warnonremove = false; - - for(int i = 0; variables[i].name; i++) { - if(strcasecmp(variables[i].name, variable)) - continue; - - found = true; - variable = (char *)variables[i].name; - - /* Discourage use of obsolete variables. */ - - if(variables[i].type & VAR_OBSOLETE && action >= 0) { - if(force) { - fprintf(stderr, "Warning: %s is an obsolete variable!\n", variable); - } else { - fprintf(stderr, "%s is an obsolete variable! Use --force to use it anyway.\n", variable); - return 1; - } - } - - /* Don't put server variables in host config files */ - - if(node && !(variables[i].type & VAR_HOST) && action >= 0) { - if(force) { - fprintf(stderr, "Warning: %s is not a host configuration variable!\n", variable); - } else { - fprintf(stderr, "%s is not a host configuration variable! Use --force to use it anyway.\n", variable); - return 1; - } - } - - /* Should this go into our own host config file? */ - - if(!node && !(variables[i].type & VAR_SERVER)) { - node = get_my_name(true); - if(!node) - return 1; - } - - /* Change "add" into "set" for variables that do not allow multiple occurences. - Turn on warnings when it seems variables might be removed unintentionally. */ - - if(action == 1 && !(variables[i].type & VAR_MULTIPLE)) { - warnonremove = true; - action = 0; - } else if(action == 0 && (variables[i].type & VAR_MULTIPLE)) { - warnonremove = true; - } - - break; - } - - if(node && !check_id(node)) { - fprintf(stderr, "Invalid name for node.\n"); - return 1; - } - - if(!found) { - if(force || action < 0) { - fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable); - } else { - fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable); - return 1; - } - } - - // Open the right configuration file. - char *filename; - if(node) - xasprintf(&filename, "%s" SLASH "%s", hosts_dir, node); - else - filename = tinc_conf; - - FILE *f = fopen(filename, "r"); - if(!f) { - fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno)); - return 1; - } - - char *tmpfile = NULL; - FILE *tf = NULL; - - if(action >= -1) { - xasprintf(&tmpfile, "%s.config.tmp", filename); - tf = fopen(tmpfile, "w"); - if(!tf) { - fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno)); - fclose(f); - return 1; - } - } - - // Copy the file, making modifications on the fly, unless we are just getting a value. - char buf1[4096]; - char buf2[4096]; - bool set = false; - bool removed = false; - found = false; - - while(fgets(buf1, sizeof buf1, f)) { - buf1[sizeof buf1 - 1] = 0; - strncpy(buf2, buf1, sizeof buf2); - - // Parse line in a simple way - char *bvalue; - int len; - - len = strcspn(buf2, "\t ="); - bvalue = buf2 + len; - bvalue += strspn(bvalue, "\t "); - if(*bvalue == '=') { - bvalue++; - bvalue += strspn(bvalue, "\t "); - } - rstrip(bvalue); - buf2[len] = '\0'; - - // Did it match? - if(!strcasecmp(buf2, variable)) { - // Get - if(action < -1) { - found = true; - printf("%s\n", bvalue); - // Del - } else if(action == -1) { - if(!*value || !strcasecmp(bvalue, value)) { - removed = true; - continue; - } - // Set - } else if(action == 0) { - // Warn if "set" was used for variables that can occur multiple times - if(warnonremove && strcasecmp(bvalue, value)) - fprintf(stderr, "Warning: removing %s = %s\n", variable, bvalue); - - // Already set? Delete the rest... - if(set) - continue; - - // Otherwise, replace. - if(fprintf(tf, "%s = %s\n", variable, value) < 0) { - fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno)); - return 1; - } - set = true; - continue; - } - } - - if(action >= -1) { - // Copy original line... - if(fputs(buf1, tf) < 0) { - fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno)); - return 1; - } - - // Add newline if it is missing... - if(*buf1 && buf1[strlen(buf1) - 1] != '\n') { - if(fputc('\n', tf) < 0) { - fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno)); - return 1; - } - } - } - } - - // Make sure we read everything... - if(ferror(f) || !feof(f)) { - fprintf(stderr, "Error while reading from configuration file %s: %s\n", filename, strerror(errno)); - return 1; - } - - if(fclose(f)) { - fprintf(stderr, "Error closing configuration file %s: %s\n", filename, strerror(errno)); - return 1; - } - - // Add new variable if necessary. - if(action > 0 || (action == 0 && !set)) { - if(fprintf(tf, "%s = %s\n", variable, value) < 0) { - fprintf(stderr, "Error writing to temporary file %s: %s\n", tmpfile, strerror(errno)); - return 1; - } - } - - if(action < -1) { - if(!found) - fprintf(stderr, "No matching configuration variables found.\n"); - return 0; - } - - // Make sure we wrote everything... - if(fclose(tf)) { - fprintf(stderr, "Error closing temporary file %s: %s\n", tmpfile, strerror(errno)); - return 1; - } - - // Could we find what we had to remove? - if(action < 0 && !removed) { - remove(tmpfile); - fprintf(stderr, "No configuration variables deleted.\n"); - return *value; - } - - // Replace the configuration file with the new one -#ifdef HAVE_MINGW - if(remove(filename)) { - fprintf(stderr, "Error replacing file %s: %s\n", filename, strerror(errno)); - return 1; - } -#endif - if(rename(tmpfile, filename)) { - fprintf(stderr, "Error renaming temporary file %s to configuration file %s: %s\n", tmpfile, filename, strerror(errno)); - return 1; - } - - // Silently try notifying a running tincd of changes. - if(connect_tincd(false)) - sendline(fd, "%d %d", CONTROL, REQ_RELOAD); - - return 0; -} - -bool check_id(const char *name) { - if(!name || !*name) - return false; - - for(int i = 0; i < strlen(name); i++) { - if(!isalnum(name[i]) && name[i] != '_') - return false; - } - - return true; -} - -static bool try_bind(int port) { - struct addrinfo *ai = NULL; - struct addrinfo hint = { - .ai_flags = AI_PASSIVE, - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - }; - - char portstr[16]; - snprintf(portstr, sizeof portstr, "%d", port); - - if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) - return false; - - while(ai) { - int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); - if(!fd) - return false; - int result = bind(fd, ai->ai_addr, ai->ai_addrlen); - closesocket(fd); - if(result) - return false; - ai = ai->ai_next; - } - - return true; -} - -int check_port(char *name) { - if(try_bind(655)) - return 655; - - fprintf(stderr, "Warning: could not bind to port 655. "); - - for(int i = 0; i < 100; i++) { - int port = 0x1000 + (rand() & 0x7fff); - if(try_bind(port)) { - char *filename; - xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name); - FILE *f = fopen(filename, "a"); - free(filename); - if(!f) { - fprintf(stderr, "Please change tinc's Port manually.\n"); - return 0; - } - - fprintf(f, "Port = %d\n", port); - fclose(f); - fprintf(stderr, "Tinc will instead listen on port %d.\n", port); - return port; - } - } - - fprintf(stderr, "Please change tinc's Port manually.\n"); - return 0; -} - -static int cmd_init(int argc, char *argv[]) { - if(!access(tinc_conf, F_OK)) { - fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf); - return 1; - } - - if(argc > 2) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } else if(argc < 2) { - if(tty) { - char buf[1024]; - fprintf(stdout, "Enter the Name you want your tinc node to have: "); - fflush(stdout); - if(!fgets(buf, sizeof buf, stdin)) { - fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno)); - return 1; - } - int len = rstrip(buf); - if(!len) { - fprintf(stderr, "No name given!\n"); - return 1; - } - name = strdup(buf); - } else { - fprintf(stderr, "No Name given!\n"); - return 1; - } - } else { - name = strdup(argv[1]); - if(!*name) { - fprintf(stderr, "No Name given!\n"); - return 1; - } - } - - if(!check_id(name)) { - fprintf(stderr, "Invalid Name! Only a-z, A-Z, 0-9 and _ are allowed characters.\n"); - return 1; - } - - if(strcmp(confdir, confbase) && 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; - } - - if(mkdir(hosts_dir, 0777) && errno != EEXIST) { - fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno)); - return 1; - } - - FILE *f = fopen(tinc_conf, "w"); - if(!f) { - fprintf(stderr, "Could not create file %s: %s\n", tinc_conf, strerror(errno)); - return 1; - } - - fprintf(f, "Name = %s\n", name); - fclose(f); - - if(!rsa_keygen(2048, false) || !ecdsa_keygen(false)) - return 1; - - check_port(name); - -#ifndef HAVE_MINGW - char *filename; - xasprintf(&filename, "%s" SLASH "tinc-up", confbase); - if(access(filename, F_OK)) { - FILE *f = fopenmask(filename, "w", 0777); - if(!f) { - fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno)); - return 1; - } - fprintf(f, "#!/bin/sh\n\necho 'Unconfigured tinc-up script, please edit!'\n\n#ifconfig $INTERFACE netmask \n"); - fclose(f); - } -#endif - - return 0; - -} - -static int cmd_generate_keys(int argc, char *argv[]) { - if(argc > 2) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!name) - name = get_my_name(false); - - return !(rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true) && ecdsa_keygen(true)); -} - -static int cmd_generate_rsa_keys(int argc, char *argv[]) { - if(argc > 2) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!name) - name = get_my_name(false); - - return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true); -} - -static int cmd_generate_ecdsa_keys(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - if(!name) - name = get_my_name(false); - - return !ecdsa_keygen(true); -} - -static int cmd_help(int argc, char *argv[]) { - usage(false); - return 0; -} - -static int cmd_version(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - version(); - return 0; -} - -static int cmd_info(int argc, char *argv[]) { - if(argc != 2) { - fprintf(stderr, "Invalid number of arguments.\n"); - return 1; - } - - if(!connect_tincd(true)) - return 1; - - return info(fd, argv[1]); -} - -static const char *conffiles[] = { - "tinc.conf", - "tinc-up", - "tinc-down", - "subnet-up", - "subnet-down", - "host-up", - "host-down", - NULL, -}; - -static int cmd_edit(int argc, char *argv[]) { - if(argc != 2) { - fprintf(stderr, "Invalid number of arguments.\n"); - return 1; - } - - char *filename = NULL; - - if(strncmp(argv[1], "hosts" SLASH, 6)) { - for(int i = 0; conffiles[i]; i++) { - if(!strcmp(argv[1], conffiles[i])) { - xasprintf(&filename, "%s" SLASH "%s", confbase, argv[1]); - break; - } - } - } else { - argv[1] += 6; - } - - if(!filename) { - xasprintf(&filename, "%s" SLASH "%s", hosts_dir, argv[1]); - char *dash = strchr(argv[1], '-'); - if(dash) { - *dash++ = 0; - if((strcmp(dash, "up") && strcmp(dash, "down")) || !check_id(argv[1])) { - fprintf(stderr, "Invalid configuration filename.\n"); - return 1; - } - } - } - - char *command; -#ifndef HAVE_MINGW - xasprintf(&command, "\"%s\" \"%s\"", getenv("VISUAL") ?: getenv("EDITOR") ?: "vi", filename); -#else - xasprintf(&command, "edit \"%s\"", filename); -#endif - int result = system(command); - if(result) - return result; - - // Silently try notifying a running tincd of changes. - if(connect_tincd(false)) - sendline(fd, "%d %d", CONTROL, REQ_RELOAD); - - return 0; -} - -static int export(const char *name, FILE *out) { - char *filename; - xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name); - FILE *in = fopen(filename, "r"); - if(!in) { - fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno)); - return 1; - } - - fprintf(out, "Name = %s\n", name); - char buf[4096]; - while(fgets(buf, sizeof buf, in)) { - if(strcspn(buf, "\t =") != 4 || strncasecmp(buf, "Name", 4)) - fputs(buf, out); - } - - if(ferror(in)) { - fprintf(stderr, "Error while reading configuration file %s: %s\n", filename, strerror(errno)); - fclose(in); - return 1; - } - - fclose(in); - return 0; -} - -static int cmd_export(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - char *name = get_my_name(true); - if(!name) - return 1; - - int result = export(name, stdout); - if(!tty) - fclose(stdout); - - free(name); - return result; -} - -static int cmd_export_all(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - DIR *dir = opendir(hosts_dir); - if(!dir) { - fprintf(stderr, "Could not open host configuration directory %s: %s\n", hosts_dir, strerror(errno)); - return 1; - } - - bool first = true; - int result = 0; - struct dirent *ent; - - while((ent = readdir(dir))) { - if(!check_id(ent->d_name)) - continue; - - if(first) - first = false; - else - printf("#---------------------------------------------------------------#\n"); - - result |= export(ent->d_name, stdout); - } - - closedir(dir); - if(!tty) - fclose(stdout); - return result; -} - -static int cmd_import(int argc, char *argv[]) { - if(argc > 1) { - fprintf(stderr, "Too many arguments!\n"); - return 1; - } - - FILE *in = stdin; - FILE *out = NULL; - - char buf[4096]; - char name[4096]; - char *filename = NULL; - int count = 0; - bool firstline = true; - - while(fgets(buf, sizeof buf, in)) { - if(sscanf(buf, "Name = %s", name) == 1) { - firstline = false; - - if(!check_id(name)) { - fprintf(stderr, "Invalid Name in input!\n"); - return 1; - } - - if(out) - fclose(out); - - free(filename); - xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name); - - if(!force && !access(filename, F_OK)) { - fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename); - out = NULL; - continue; - } - - out = fopen(filename, "w"); - if(!out) { - fprintf(stderr, "Error creating configuration file %s: %s\n", filename, strerror(errno)); - return 1; - } - - count++; - continue; - } else if(firstline) { - fprintf(stderr, "Junk at the beginning of the input, ignoring.\n"); - firstline = false; - } - - - if(!strcmp(buf, "#---------------------------------------------------------------#\n")) - continue; - - if(out) { - if(fputs(buf, out) < 0) { - fprintf(stderr, "Error writing to host configuration file %s: %s\n", filename, strerror(errno)); - return 1; - } - } - } - - if(out) - fclose(out); - - if(count) { - fprintf(stderr, "Imported %d host configuration files.\n", count); - return 0; - } else { - fprintf(stderr, "No host configuration files imported.\n"); - return 1; - } -} - -static int cmd_exchange(int argc, char *argv[]) { - return cmd_export(argc, argv) ?: cmd_import(argc, argv); -} - -static int cmd_exchange_all(int argc, char *argv[]) { - return cmd_export_all(argc, argv) ?: cmd_import(argc, argv); -} - -static const struct { - const char *command; - int (*function)(int argc, char *argv[]); - bool hidden; -} commands[] = { - {"start", cmd_start}, - {"stop", cmd_stop}, - {"restart", cmd_restart}, - {"reload", cmd_reload}, - {"dump", cmd_dump}, - {"purge", cmd_purge}, - {"debug", cmd_debug}, - {"retry", cmd_retry}, - {"connect", cmd_connect}, - {"disconnect", cmd_disconnect}, - {"top", cmd_top}, - {"pcap", cmd_pcap}, - {"log", cmd_log}, - {"pid", cmd_pid}, - {"config", cmd_config, true}, - {"add", cmd_config}, - {"del", cmd_config}, - {"get", cmd_config}, - {"set", cmd_config}, - {"init", cmd_init}, - {"generate-keys", cmd_generate_keys}, - {"generate-rsa-keys", cmd_generate_rsa_keys}, - {"generate-ecdsa-keys", cmd_generate_ecdsa_keys}, - {"help", cmd_help}, - {"version", cmd_version}, - {"info", cmd_info}, - {"edit", cmd_edit}, - {"export", cmd_export}, - {"export-all", cmd_export_all}, - {"import", cmd_import}, - {"exchange", cmd_exchange}, - {"exchange-all", cmd_exchange_all}, - {"invite", cmd_invite}, - {"join", cmd_join}, - {NULL, NULL}, -}; - -#ifdef HAVE_READLINE -static char *complete_command(const char *text, int state) { - static int i; - - if(!state) - i = 0; - else - i++; - - while(commands[i].command) { - if(!commands[i].hidden && !strncasecmp(commands[i].command, text, strlen(text))) - return xstrdup(commands[i].command); - i++; - } - - return NULL; -} - -static char *complete_dump(const char *text, int state) { - const char *matches[] = {"reachable", "nodes", "edges", "subnets", "connections", "graph", NULL}; - static int i; - - if(!state) - i = 0; - else - i++; - - while(matches[i]) { - if(!strncasecmp(matches[i], text, strlen(text))) - return xstrdup(matches[i]); - i++; - } - - return NULL; -} - -static char *complete_config(const char *text, int state) { - static int i; - - if(!state) - i = 0; - else - i++; - - while(variables[i].name) { - char *dot = strchr(text, '.'); - if(dot) { - if((variables[i].type & VAR_HOST) && !strncasecmp(variables[i].name, dot + 1, strlen(dot + 1))) { - char *match; - xasprintf(&match, "%.*s.%s", (int)(dot - text), text, variables[i].name); - return match; - } - } else { - if(!strncasecmp(variables[i].name, text, strlen(text))) - return xstrdup(variables[i].name); - } - i++; - } - - return NULL; -} - -static char *complete_info(const char *text, int state) { - static int i; - if(!state) { - i = 0; - if(!connect_tincd(false)) - return NULL; - // Check the list of nodes - sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES); - sendline(fd, "%d %d", CONTROL, REQ_DUMP_SUBNETS); - } - - while(recvline(fd, line, sizeof line)) { - char item[4096]; - int n = sscanf(line, "%d %d %s", &code, &req, item); - if(n == 2) { - i++; - if(i >= 2) - break; - else - continue; - } - - if(n != 3) { - fprintf(stderr, "Unable to parse dump from tincd, n = %d, i = %d.\n", n, i); - break; - } - - if(!strncmp(item, text, strlen(text))) - return xstrdup(strip_weight(item)); - } - - return NULL; -} - -static char *complete_nothing(const char *text, int state) { - return NULL; -} - -static char **completion (const char *text, int start, int end) { - char **matches = NULL; - - if(!start) - matches = rl_completion_matches(text, complete_command); - else if(!strncasecmp(rl_line_buffer, "dump ", 5)) - matches = rl_completion_matches(text, complete_dump); - else if(!strncasecmp(rl_line_buffer, "add ", 4)) - matches = rl_completion_matches(text, complete_config); - else if(!strncasecmp(rl_line_buffer, "del ", 4)) - matches = rl_completion_matches(text, complete_config); - else if(!strncasecmp(rl_line_buffer, "get ", 4)) - matches = rl_completion_matches(text, complete_config); - else if(!strncasecmp(rl_line_buffer, "set ", 4)) - matches = rl_completion_matches(text, complete_config); - else if(!strncasecmp(rl_line_buffer, "info ", 5)) - matches = rl_completion_matches(text, complete_info); - - return matches; -} -#endif - -static int cmd_shell(int argc, char *argv[]) { - char *prompt; - xasprintf(&prompt, "%s> ", identname); - int result = 0; - char buf[4096]; - char *line = NULL; - int maxargs = argc + 16; - char **nargv = xmalloc(maxargs * sizeof *nargv); - - for(int i = 0; i < argc; i++) - nargv[i] = argv[i]; - -#ifdef HAVE_READLINE - rl_readline_name = "tinc"; - rl_completion_entry_function = complete_nothing; - rl_attempted_completion_function = completion; - rl_filename_completion_desired = 0; - char *copy = NULL; -#endif - - while(true) { -#ifdef HAVE_READLINE - if(tty) { - free(copy); - free(line); - rl_basic_word_break_characters = "\t\n "; - line = readline(prompt); - if(line) - copy = xstrdup(line); - } else { - line = fgets(buf, sizeof buf, stdin); - } -#else - if(tty) - fputs(prompt, stdout); - - line = fgets(buf, sizeof buf, stdin); -#endif - - if(!line) - break; - - /* Ignore comments */ - - if(*line == '#') - continue; - - /* Split */ - - int nargc = argc; - char *p = line + strspn(line, " \t\n"); - char *next = strtok(p, " \t\n"); - - while(p && *p) { - if(nargc >= maxargs) { - fprintf(stderr, "next %p '%s', p %p '%s'\n", next, next, p, p); - abort(); - maxargs *= 2; - nargv = xrealloc(nargv, maxargs * sizeof *nargv); - } - - nargv[nargc++] = p; - p = next; - next = strtok(NULL, " \t\n"); - } - - if(nargc == argc) - continue; - - if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit")) - return result; - - bool found = false; - - for(int i = 0; commands[i].command; i++) { - if(!strcasecmp(nargv[argc], commands[i].command)) { - result |= commands[i].function(nargc - argc - 1, nargv + argc + 1); - found = true; - break; - } - } - -#ifdef HAVE_READLINE - if(tty && found) - add_history(copy); -#endif - - if(!found) { - fprintf(stderr, "Unknown command `%s'.\n", nargv[argc]); - result |= 1; - } - } - - free(nargv); - - if(tty) - printf("\n"); - return result; -} - - -int main(int argc, char *argv[]) { - program_name = argv[0]; - orig_argv = argv; - orig_argc = argc; - - if(!parse_options(argc, argv)) - return 1; - - make_names(); - xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase); - xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase); - - if(show_version) { - version(); - return 0; - } - - if(show_help) { - usage(false); - return 0; - } - - srand(time(NULL)); - crypto_init(); - - tty = isatty(0) && isatty(1); - - if(optind >= argc) - return cmd_shell(argc, argv); - - for(int i = 0; commands[i].command; i++) { - if(!strcasecmp(argv[optind], commands[i].command)) - return commands[i].function(argc - optind, argv + optind); - } - - fprintf(stderr, "Unknown command `%s'.\n", argv[optind]); - usage(true); - return 1; -} diff --git a/src/tincctl.h b/src/tincctl.h deleted file mode 100644 index e636887..0000000 --- a/src/tincctl.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - tincctl.h -- header for tincctl.c. - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_TINCCTL_H__ -#define __TINC_TINCCTL_H__ - -extern bool tty; -extern char line[4096]; -extern int fd; -extern char buffer[4096]; -extern size_t blen; -extern bool confbasegiven; -extern char *tinc_conf; -extern char *hosts_dir; - -#define VAR_SERVER 1 /* Should be in tinc.conf */ -#define VAR_HOST 2 /* Can be in host config file */ -#define VAR_MULTIPLE 4 /* Multiple statements allowed */ -#define VAR_OBSOLETE 8 /* Should not be used anymore */ -#define VAR_SAFE 16 /* Variable is safe when accepting invitations */ - -typedef struct { - const char *name; - int type; -} var_t; - -extern const var_t variables[]; - -extern int rstrip(char *value); -extern char *get_my_name(bool verbose); -extern bool connect_tincd(bool verbose); -extern bool sendline(int fd, char *format, ...); -extern bool recvline(int fd, char *line, size_t len); -extern int check_port(char *name); -extern FILE *fopenmask(const char *filename, const char *mode, mode_t perms); - -#endif - diff --git a/src/tincd.c b/src/tincd.c index 3d6db8b..066ad9c 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -1,7 +1,7 @@ /* tincd.c -- the main file for tincd Copyright (C) 1998-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2019 Guus Sliepen 2008 Max Rijevski 2009 Michael Tokarev 2010 Julien Muchembled @@ -33,6 +33,15 @@ #include #endif +#include +#include +#include +#include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include + #ifdef HAVE_LZO #include LZO1X_H #endif @@ -43,14 +52,17 @@ #include #endif +#ifdef HAVE_GETOPT_LONG #include +#else +#include "getopt.h" +#endif + +#include "pidfile.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" @@ -58,41 +70,51 @@ #include "utils.h" #include "xalloc.h" +/* The name this program was run with. */ +char *program_name = NULL; + /* If nonzero, display usage information and exit. */ -static bool show_help = false; +bool show_help = false; /* If nonzero, print the version on standard output and exit. */ -static bool show_version = false; +bool show_version = false; + +/* If nonzero, it will attempt to kill a running tincd and exit. */ +int kill_tincd = 0; + +/* If nonzero, generate public/private keypair for this host/net. */ +int generate_keys = 0; /* If nonzero, use null ciphers and skip all key exchanges. */ bool bypass_security = false; -#ifdef HAVE_MLOCKALL /* If nonzero, disable swapping for this process. */ -static bool do_mlock = false; -#endif +bool do_mlock = false; -#ifndef HAVE_MINGW /* If nonzero, chroot to netdir after startup. */ static bool do_chroot = false; /* If !NULL, do setuid to given user after startup */ 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 */ +char *identname = NULL; /* program name for syslog */ +char *pidfilename = NULL; /* pid file location */ +char *logfilename = NULL; /* log file location */ +char **g_argv; /* a copy of the cmdline arguments */ static int status = 1; static struct option const long_options[] = { {"config", required_argument, NULL, 'c'}, + {"kill", optional_argument, NULL, 'k'}, {"net", required_argument, NULL, 'n'}, {"help", no_argument, NULL, 1}, {"version", no_argument, NULL, 2}, {"no-detach", no_argument, NULL, 'D'}, + {"generate-keys", optional_argument, NULL, 'K'}, {"debug", optional_argument, NULL, 'd'}, {"bypass-security", no_argument, NULL, 3}, {"mlock", no_argument, NULL, 'L'}, @@ -113,26 +135,23 @@ int main2(int argc, char **argv); static void usage(bool status) { if(status) fprintf(stderr, "Try `%s --help\' for more information.\n", - program_name); + program_name); else { printf("Usage: %s [option]...\n\n", program_name); - 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" - " -n, --net=NETNAME Connect to net NETNAME.\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 - " -R, --chroot chroot to NET dir at startup.\n" - " -U, --user=USER setuid to given USER at startup.\n" -#endif - " --help Display this help and exit.\n" - " --version Output version information and exit.\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" + " -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n" + " -n, --net=NETNAME Connect to net NETNAME.\n" + " -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n" + " -L, --mlock Lock tinc into main memory.\n" + " --logfile[=FILENAME] Write log entries to a logfile.\n" + " --pidfile=FILENAME Write PID to FILENAME.\n" + " -o, --option=[HOST.]KEY=VALUE Set global/host configuration value.\n" + " -R, --chroot chroot to NET dir at startup.\n" + " -U, --user=USER setuid to given USER at startup.\n" + " --help Display this help and exit.\n" + " --version Output version information and exit.\n\n"); printf("Report bugs to tinc@tinc-vpn.org.\n"); } } @@ -145,93 +164,193 @@ static bool parse_options(int argc, char **argv) { cmdline_conf = list_alloc((list_action_t)free_config); - while((r = getopt_long(argc, argv, "c:DLd::n:o:RU:", long_options, &option_index)) != EOF) { - switch (r) { - case 0: /* long option */ - break; + while((r = getopt_long(argc, argv, "c:DLd::k::n:o:K::RU:", long_options, &option_index)) != EOF) { + switch(r) { + case 0: /* long option */ + break; - case 'c': /* config file */ - 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]); - return false; -#else - do_mlock = true; - break; -#endif - - case 'd': /* increase debug level */ - if(!optarg && optind < argc && *argv[optind] != '-') - optarg = argv[optind++]; - if(optarg) - debug_level = atoi(optarg); - else - debug_level++; - break; - - case 'n': /* net name given */ - netname = xstrdup(optarg); - break; - - case 'o': /* option */ - cfg = parse_config_line(optarg, NULL, ++lineno); - if (!cfg) - return false; - list_insert_tail(cmdline_conf, cfg); - break; - -#ifdef HAVE_MINGW - case 'R': - case 'U': - logger(DEBUG_ALWAYS, LOG_ERR, "The %s option is not supported on this platform.", argv[optind - 1]); - return false; -#else - case 'R': /* chroot to NETNAME dir */ - do_chroot = true; - break; - - case 'U': /* setuid to USER */ - switchuser = optarg; - break; -#endif - - case 1: /* show help */ - show_help = true; - break; - - case 2: /* show version */ - show_version = true; - break; - - case 3: /* bypass security */ - 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 */ + case 'c': /* config file */ + if(confbase) { + fprintf(stderr, "Only one configuration directory can be given.\n"); usage(true); return false; + } - default: - break; + confbase = xstrdup(optarg); + break; + + case 'D': /* no detach */ + do_detach = false; + break; + + case 'L': /* no detach */ +#ifndef HAVE_MLOCKALL + logger(LOG_ERR, "%s not supported on this platform", "mlockall()"); + return false; +#else + do_mlock = true; + break; +#endif + + case 'd': /* increase debug level */ + if(!optarg && optind < argc && *argv[optind] != '-') { + optarg = argv[optind++]; + } + + if(optarg) { + debug_level = atoi(optarg); + } else { + debug_level++; + } + + break; + + case 'k': /* kill old tincds */ +#ifndef HAVE_MINGW + if(!optarg && optind < argc && *argv[optind] != '-') { + optarg = argv[optind++]; + } + + if(optarg) { + if(!strcasecmp(optarg, "HUP")) { + kill_tincd = SIGHUP; + } else if(!strcasecmp(optarg, "TERM")) { + kill_tincd = SIGTERM; + } else if(!strcasecmp(optarg, "KILL")) { + kill_tincd = SIGKILL; + } else if(!strcasecmp(optarg, "USR1")) { + kill_tincd = SIGUSR1; + } else if(!strcasecmp(optarg, "USR2")) { + kill_tincd = SIGUSR2; + } else if(!strcasecmp(optarg, "WINCH")) { + kill_tincd = SIGWINCH; + } else if(!strcasecmp(optarg, "INT")) { + kill_tincd = SIGINT; + } else if(!strcasecmp(optarg, "ALRM")) { + kill_tincd = SIGALRM; + } else if(!strcasecmp(optarg, "ABRT")) { + kill_tincd = SIGABRT; + } else { + kill_tincd = atoi(optarg); + + if(!kill_tincd) { + fprintf(stderr, "Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n", + optarg); + usage(true); + return false; + } + } + } else { + kill_tincd = SIGTERM; + } + +#else + kill_tincd = 1; +#endif + break; + + case 'n': /* net name given */ + + /* netname "." is special: a "top-level name" */ + if(netname) { + fprintf(stderr, "Only one netname can be given.\n"); + usage(true); + return false; + } + + if(optarg && strcmp(optarg, ".")) { + netname = xstrdup(optarg); + } + + break; + + case 'o': /* option */ + cfg = parse_config_line(optarg, NULL, ++lineno); + + if(!cfg) { + return false; + } + + list_insert_tail(cmdline_conf, cfg); + break; + + case 'K': /* generate public/private keypair */ + if(!optarg && optind < argc && *argv[optind] != '-') { + optarg = argv[optind++]; + } + + if(optarg) { + generate_keys = atoi(optarg); + + if(generate_keys < 512) { + fprintf(stderr, "Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n", + optarg); + usage(true); + return false; + } + + generate_keys &= ~7; /* Round it to bytes */ + } else { + generate_keys = 2048; + } + + break; + + case 'R': /* chroot to NETNAME dir */ + do_chroot = true; + break; + + case 'U': /* setuid to USER */ + switchuser = optarg; + break; + + case 1: /* show help */ + show_help = true; + break; + + case 2: /* show version */ + show_version = true; + break; + + case 3: /* bypass security */ + 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) { + if(logfilename) { + fprintf(stderr, "Only one logfile can be given.\n"); + usage(true); + return false; + } + + logfilename = xstrdup(optarg); + } + + break; + + case 5: /* write PID to a file */ + if(pidfilename) { + fprintf(stderr, "Only one pidfile can be given.\n"); + usage(true); + return false; + } + + pidfilename = xstrdup(optarg); + break; + + case '?': + usage(true); + return false; + + default: + break; } } @@ -241,62 +360,278 @@ static bool parse_options(int argc, char **argv) { return false; } - if(!netname && (netname = getenv("NETNAME"))) - netname = xstrdup(netname); + return true; +} - /* netname "." is special: a "top-level name" */ +/* This function prettyprints the key generation process */ - if(netname && (!*netname || !strcmp(netname, "."))) { - free(netname); - netname = NULL; +static int indicator(int a, int b, BN_GENCB *cb) { + (void)cb; + + switch(a) { + case 0: + fprintf(stderr, "."); + break; + + case 1: + fprintf(stderr, "+"); + break; + + case 2: + fprintf(stderr, "-"); + break; + + case 3: + switch(b) { + case 0: + fprintf(stderr, " p\n"); + break; + + case 1: + fprintf(stderr, " q\n"); + break; + + default: + fprintf(stderr, "?"); + } + + break; + + default: + fprintf(stderr, "?"); } - if(netname && (strpbrk(netname, "\\/") || *netname == '.')) { - fprintf(stderr, "Invalid character in netname!\n"); + return 1; +} + +#ifndef HAVE_BN_GENCB_NEW +BN_GENCB *BN_GENCB_new(void) { + return xmalloc_and_zero(sizeof(BN_GENCB)); +} + +void BN_GENCB_free(BN_GENCB *cb) { + free(cb); +} +#endif + +/* + Generate a public/private RSA keypair, and ask for a file to store + them in. +*/ +static bool keygen(int bits) { + BIGNUM *e = NULL; + RSA *rsa_key; + FILE *f; + char filename[PATH_MAX]; + BN_GENCB *cb; + int result; + + fprintf(stderr, "Generating %d bits keys:\n", bits); + + cb = BN_GENCB_new(); + + if(!cb) { + abort(); + } + + BN_GENCB_set(cb, indicator, NULL); + + rsa_key = RSA_new(); + + if(BN_hex2bn(&e, "10001") == 0) { + abort(); + } + + if(!rsa_key || !e) { + abort(); + } + + result = RSA_generate_key_ex(rsa_key, bits, e, cb); + + BN_free(e); + BN_GENCB_free(cb); + + if(!result) { + fprintf(stderr, "Error during key generation!\n"); + RSA_free(rsa_key); + return false; + } else { + fprintf(stderr, "Done.\n"); + } + + snprintf(filename, sizeof(filename), "%s/rsa_key.priv", confbase); + f = ask_and_open(filename, "private RSA key"); + + if(!f) { + RSA_free(rsa_key); return false; } +#ifdef HAVE_FCHMOD + /* Make it unreadable for others. */ + fchmod(fileno(f), 0600); +#endif + + fputc('\n', f); + PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); + fclose(f); + + char *name = get_name(); + + if(name) { + snprintf(filename, sizeof(filename), "%s/hosts/%s", confbase, name); + free(name); + } else { + snprintf(filename, sizeof(filename), "%s/rsa_key.pub", confbase); + } + + f = ask_and_open(filename, "public RSA key"); + + if(!f) { + RSA_free(rsa_key); + return false; + } + + fputc('\n', f); + PEM_write_RSAPublicKey(f, rsa_key); + fclose(f); + + RSA_free(rsa_key); + return true; } -static bool drop_privs(void) { -#ifndef HAVE_MINGW +/* + Set all files and paths according to netname +*/ +static void make_names(void) { +#ifdef HAVE_MINGW + HKEY key; + char installdir[1024] = ""; + DWORD len = sizeof(installdir); +#endif + + 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)) { + if(!confbase) { + if(netname) { + xasprintf(&confbase, "%s/%s", installdir, netname); + } else { + xasprintf(&confbase, "%s", installdir); + } + } + + if(!logfilename) { + xasprintf(&logfilename, "%s/tinc.log", confbase); + } + } + + RegCloseKey(key); + + if(*installdir) { + return; + } + } + +#endif + + if(!pidfilename) { + xasprintf(&pidfilename, RUNSTATEDIR "/%s.pid", identname); + } + + if(!logfilename) { + xasprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname); + } + + if(netname) { + if(!confbase) { + xasprintf(&confbase, CONFDIR "/tinc/%s", netname); + } else { + logger(LOG_INFO, "Both netname and configuration directory given, using the latter..."); + } + } else { + if(!confbase) { + xasprintf(&confbase, CONFDIR "/tinc"); + } + } +} + +static void free_names() { + free(identname); + free(netname); + free(pidfilename); + free(logfilename); + free(confbase); +} + +static bool drop_privs() { +#ifdef HAVE_MINGW + + if(switchuser) { + logger(LOG_ERR, "%s not supported on this platform", "-U"); + return false; + } + + if(do_chroot) { + logger(LOG_ERR, "%s not supported on this platform", "-R"); + return false; + } + +#else uid_t uid = 0; - if (switchuser) { + + if(switchuser) { struct passwd *pw = getpwnam(switchuser); - if (!pw) { - logger(DEBUG_ALWAYS, LOG_ERR, "unknown user `%s'", switchuser); + + if(!pw) { + logger(LOG_ERR, "unknown user `%s'", switchuser); return false; } + uid = pw->pw_uid; - if (initgroups(switchuser, pw->pw_gid) != 0 || - setgid(pw->pw_gid) != 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", + + if(initgroups(switchuser, pw->pw_gid) != 0 || + setgid(pw->pw_gid) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "initgroups", strerror(errno)); return false; } -#ifndef __ANDROID__ + +#ifndef ANDROID // Not supported in android NDK endgrent(); endpwent(); #endif } - if (do_chroot) { + + if(do_chroot) { tzset(); /* for proper timestamps in logs */ - if (chroot(confbase) != 0 || chdir("/") != 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", + + if(chroot(confbase) != 0 || chdir("/") != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "chroot", strerror(errno)); return false; } + free(confbase); confbase = xstrdup(""); } - if (switchuser) - if (setuid(uid) != 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", + + if(switchuser) + if(setuid(uid) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "setuid", strerror(errno)); return false; } + #endif return true; } @@ -313,19 +648,17 @@ static bool drop_privs(void) { int main(int argc, char **argv) { program_name = argv[0]; - if(!parse_options(argc, argv)) + 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); - printf("Copyright (C) 1998-2013 Ivo Timmermans, Guus Sliepen and others.\n" - "See the AUTHORS file for a complete list.\n\n" - "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" - "and you are welcome to redistribute it under certain conditions;\n" - "see the file COPYING for details.\n"); + printf("%s version %s\n", PACKAGE, VERSION); + printf("Copyright (C) 1998-2019 Ivo Timmermans, Guus Sliepen and others.\n" + "See the AUTHORS file for a complete list.\n\n" + "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" + "and you are welcome to redistribute it under certain conditions;\n" + "see the file COPYING for details.\n"); return 0; } @@ -335,46 +668,65 @@ int main(int argc, char **argv) { return 0; } -#ifdef HAVE_MINGW - if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError())); - return 1; - } -#endif + make_names(); - openlogger("tinc", use_logfile?LOGMODE_FILE:LOGMODE_STDERR); + if(kill_tincd) { + return !kill_other(kill_tincd); + } + + openlogger("tinc", use_logfile ? LOGMODE_FILE : LOGMODE_STDERR); g_argv = argv; - if(getenv("LISTEN_PID") && atoi(getenv("LISTEN_PID")) == getpid()) + if(getenv("LISTEN_PID") && atoi(getenv("LISTEN_PID")) == getpid()) { do_detach = false; + } + #ifdef HAVE_UNSETENV unsetenv("LISTEN_PID"); #endif init_configuration(&config_tree); - /* Slllluuuuuuurrrrp! */ +#ifndef OPENSSL_NO_ENGINE + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); +#endif - gettimeofday(&now, NULL); - srand(now.tv_sec + now.tv_usec); - crypto_init(); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + OpenSSL_add_all_algorithms(); +#endif - if(!read_server_config()) - return 1; + if(generate_keys) { + read_server_config(); + return !keygen(generate_keys); + } -#ifdef HAVE_LZO - if(lzo_init() != LZO_E_OK) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error initializing LZO compressor!"); + if(!read_server_config()) { return 1; } + +#ifdef HAVE_LZO + + if(lzo_init() != LZO_E_OK) { + logger(LOG_ERR, "Error initializing LZO compressor!"); + return 1; + } + #endif #ifdef HAVE_MINGW - if(!do_detach || !init_service()) - return main2(argc, argv); - else + + if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) { + logger(LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError())); return 1; + } + + if(!do_detach || !init_service()) { + return main2(argc, argv); + } else { + return 1; + } } int main2(int argc, char **argv) { @@ -383,27 +735,28 @@ int main2(int argc, char **argv) { #endif char *priority = NULL; - if(!detach()) + 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. * No need to do that in parent as it's very short-lived. */ if(do_mlock && mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "mlockall", - strerror(errno)); + logger(LOG_ERR, "System call `%s' failed: %s", "mlockall", + strerror(errno)); return 1; } + #endif /* Setup sockets and open device. */ - if(!setup_network()) - goto end_nonet; - - if(!init_control()) - goto end_nonet; + if(!setup_network()) { + goto end; + } /* Initiate all outgoing connections. */ @@ -413,29 +766,33 @@ int main2(int argc, char **argv) { if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) { if(!strcasecmp(priority, "Normal")) { - if (setpriority(NORMAL_PRIORITY_CLASS) != 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setpriority", strerror(errno)); + if(setpriority(NORMAL_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); goto end; } } else if(!strcasecmp(priority, "Low")) { - if (setpriority(BELOW_NORMAL_PRIORITY_CLASS) != 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setpriority", strerror(errno)); + if(setpriority(BELOW_NORMAL_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); goto end; } } else if(!strcasecmp(priority, "High")) { - if (setpriority(HIGH_PRIORITY_CLASS) != 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setpriority", strerror(errno)); + if(setpriority(HIGH_PRIORITY_CLASS) != 0) { + logger(LOG_ERR, "System call `%s' failed: %s", + "setpriority", strerror(errno)); goto end; } } else { - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid priority `%s`!", priority); + logger(LOG_ERR, "Invalid priority `%s`!", priority); goto end; } } /* drop privileges */ - if (!drop_privs()) + if(!drop_privs()) { goto end; + } /* Start main loop. It only exits when tinc is killed. */ @@ -443,23 +800,30 @@ int main2(int argc, char **argv) { /* Shutdown properly. */ - if(debug_level >= DEBUG_CONNECTIONS) - devops.dump_stats(); + ifdebug(CONNECTIONS) + devops.dump_stats(); close_network_connections(); end: - exit_control(); + logger(LOG_NOTICE, "Terminating"); -end_nonet: - logger(DEBUG_ALWAYS, LOG_NOTICE, "Terminating"); +#ifndef HAVE_MINGW + remove_pid(pidfilename); +#endif free(priority); - crypto_exit(); +#if OPENSSL_VERSION_NUMBER < 0x10100000L + EVP_cleanup(); + ERR_free_strings(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif +#endif exit_configuration(&config_tree); - free(cmdline_conf); + list_delete_list(cmdline_conf); free_names(); return status; diff --git a/src/top.c b/src/top.c deleted file mode 100644 index b1ab40c..0000000 --- a/src/top.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - top.c -- Show real-time statistics from a running tincd - Copyright (C) 2011-2013 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "system.h" - -#ifdef HAVE_CURSES - -#include - -#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 void update(int fd) { - sendline(fd, "%d %d", CONTROL, REQ_DUMP_TRAFFIC); - 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) - break; - - if(n != 7) { - endwin(); - fprintf(stderr, "Error receiving traffic information\n"); - exit(1); - } - - 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; - } -} - -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; - - 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) { - update(fd); - 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 diff --git a/src/top.h b/src/top.h deleted file mode 100644 index b3a264d..0000000 --- a/src/top.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - top.h -- header for top.c. - Copyright (C) 2011 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_TOP_H__ -#define __TINC_TOP_H__ - -extern void top(int fd); - -#endif - diff --git a/src/uml_device.c b/src/uml_device.c index d06832b..66de431 100644 --- a/src/uml_device.c +++ b/src/uml_device.c @@ -1,7 +1,7 @@ /* device.c -- UML network socket Copyright (C) 2002-2005 Ivo Timmermans, - 2002-2013 Guus Sliepen + 2002-2012 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,7 +24,6 @@ #include "conf.h" #include "device.h" -#include "names.h" #include "net.h" #include "logger.h" #include "utils.h" @@ -36,7 +35,10 @@ static int request_fd = -1; static int data_fd = -1; static int write_fd = -1; static int state = 0; -static char *device_info; +static const char *device_info = "UML network socket"; + +extern char *identname; +extern volatile bool running; static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; @@ -44,10 +46,10 @@ static uint64_t device_total_out = 0; enum request_type { REQ_NEW_CONTROL }; static struct request { - uint32_t magic; - uint32_t version; - enum request_type type; - struct sockaddr_un sock; + uint32_t magic; + uint32_t version; + enum request_type type; + struct sockaddr_un sock; } request; static struct sockaddr_un data_sun; @@ -62,16 +64,15 @@ static bool setup_device(void) { } name; struct timeval tv; - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - xasprintf(&device, LOCALSTATEDIR "/run/%s.umlsocket", identname); + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + xasprintf(&device, RUNSTATEDIR "/%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(); + logger(LOG_ERR, "Could not open write %s: %s", device_info, strerror(errno)); + running = false; return false; } @@ -79,17 +80,17 @@ static bool setup_device(void) { fcntl(write_fd, F_SETFD, FD_CLOEXEC); #endif - setsockopt(write_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); + setsockopt(write_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if(fcntl(write_fd, F_SETFL, O_NONBLOCK) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); - event_exit(); + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + running = false; 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(); + logger(LOG_ERR, "Could not open data %s: %s", device_info, strerror(errno)); + running = false; return false; } @@ -97,11 +98,11 @@ static bool setup_device(void) { fcntl(data_fd, F_SETFD, FD_CLOEXEC); #endif - setsockopt(data_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); + setsockopt(data_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if(fcntl(data_fd, F_SETFL, O_NONBLOCK) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); - event_exit(); + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + running = false; return false; } @@ -110,17 +111,17 @@ static bool setup_device(void) { gettimeofday(&tv, NULL); name.usecs = tv.tv_usec; data_sun.sun_family = AF_UNIX; - memcpy(&data_sun.sun_path, &name, sizeof name); + 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(); + if(bind(data_fd, (struct sockaddr *)&data_sun, sizeof(data_sun)) < 0) { + logger(LOG_ERR, "Could not bind data %s: %s", device_info, strerror(errno)); + running = false; 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)); + logger(LOG_ERR, "Could not open %s: %s", device_info, + strerror(errno)); return false; } @@ -128,155 +129,162 @@ static bool setup_device(void) { fcntl(device_fd, F_SETFD, FD_CLOEXEC); #endif - setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); + setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + logger(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)); + strncpy(listen_sun.sun_path, device, sizeof(listen_sun.sun_path)); + + if(bind(listen_fd, (struct sockaddr *)&listen_sun, sizeof(listen_sun)) < 0) { + logger(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)); + logger(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); + logger(LOG_INFO, "%s is a %s", device, device_info); - if(routing_mode == RMODE_ROUTER) + if(routing_mode == RMODE_ROUTER) { overwrite_mac = true; + } return true; } void close_device(void) { - if(listen_fd >= 0) + if(listen_fd >= 0) { close(listen_fd); + } - if(request_fd >= 0) + if(request_fd >= 0) { close(request_fd); + } - if(data_fd >= 0) + if(data_fd >= 0) { close(data_fd); + } - if(write_fd >= 0) + if(write_fd >= 0) { close(write_fd); + } unlink(device); free(device); - if(iface) free(iface); + free(iface); } static bool read_packet(vpn_packet_t *packet) { - int inlen; + int lenin; switch(state) { - case 0: { - struct sockaddr sa; - socklen_t salen = sizeof sa; + 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; - } + request_fd = accept(listen_fd, &sa, &salen); + + if(request_fd < 0) { + logger(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); + 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; - + if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) { + logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + running = false; 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; - } + close(listen_fd); + listen_fd = -1; + device_fd = request_fd; + state = 1; - 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; - } + 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; + case 1: { + if((lenin = read(request_fd, &request, sizeof(request))) != sizeof request) { + logger(LOG_ERR, "Error while reading request from %s %s: %s", device_info, + device, strerror(errno)); + running = false; 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; - - device_total_in += packet->len; - - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, - device_info); - - return true; + if(request.magic != 0xfeedface || request.version != 3 || request.type != REQ_NEW_CONTROL) { + logger(LOG_ERR, "Unknown magic %x, version %d, request type %d from %s %s", + request.magic, request.version, request.type, device_info, device); + running = false; + return false; } - default: - logger(DEBUG_ALWAYS, LOG_ERR, "Invalid value for state variable in " __FILE__); - abort(); + if(connect(write_fd, (struct sockaddr *)&request.sock, sizeof(request.sock)) < 0) { + logger(LOG_ERR, "Could not bind write %s: %s", device_info, strerror(errno)); + running = false; + return false; + } + + write(request_fd, &data_sun, sizeof(data_sun)); + device_fd = data_fd; + + logger(LOG_INFO, "Connection with UML established"); + + state = 2; + return false; + } + + case 2: { + if((lenin = read(data_fd, packet->data, MTU)) <= 0) { + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, + device, strerror(errno)); + running = false; + return false; + } + + packet->len = lenin; + + device_total_in += packet->len; + + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, + device_info); + + return true; + } + + default: + logger(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); + ifdebug(TRAFFIC) logger(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); + ifdebug(TRAFFIC) logger(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(); + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); + running = false; } return false; @@ -288,9 +296,9 @@ static bool write_packet(vpn_packet_t *packet) { } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t uml_devops = { diff --git a/src/utils.c b/src/utils.c index edaa354..70a5c99 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,7 +1,7 @@ /* utils.c -- gathering of some stupid small functions Copyright (C) 1999-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2014 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,128 +24,34 @@ #include "utils.h" static const char hexadecimals[] = "0123456789ABCDEF"; -static const char base64_original[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char base64_urlsafe[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; -static const char base64_decode[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -}; static int charhex2bin(char c) { - if(isdigit(c)) + if(isdigit(c)) { return c - '0'; - else + } else { return toupper(c) - 'A' + 10; + } } -int hex2bin(const char *src, char *dst, int length) { - int i; - for(i = 0; i < length && isxdigit(src[i * 2]) && isxdigit(src[i * 2 + 1]); i++) +bool hex2bin(char *src, char *dst, int length) { + for(int i = 0; i < length; i++) { + if(!isxdigit(src[i * 2]) || !isxdigit(src[i * 2 + 1])) { + return false; + } + dst[i] = charhex2bin(src[i * 2]) * 16 + charhex2bin(src[i * 2 + 1]); - return i; + } + + return true; } -int bin2hex(const char *src, char *dst, int length) { - for(int i = length - 1; i >= 0; i--) { +void bin2hex(char *src, char *dst, int length) { + int i; + + for(i = length - 1; i >= 0; i--) { dst[i * 2 + 1] = hexadecimals[(unsigned char) src[i] & 15]; dst[i * 2] = hexadecimals[(unsigned char) src[i] >> 4]; } - dst[length * 2] = 0; - return length * 2; -} - -int b64decode(const char *src, char *dst, int length) { - int i; - uint32_t triplet = 0; - unsigned char *udst = (unsigned char *)dst; - - for(i = 0; i < length / 3 * 4 && src[i]; i++) { - triplet |= base64_decode[src[i] & 0xff] << (6 * (i & 3)); - if((i & 3) == 3) { - if(triplet & 0xff000000U) - return 0; - udst[0] = triplet & 0xff; triplet >>= 8; - udst[1] = triplet & 0xff; triplet >>= 8; - udst[2] = triplet; - triplet = 0; - udst += 3; - } - } - if(triplet & 0xff000000U) - return 0; - if((i & 3) == 3) { - udst[0] = triplet & 0xff; triplet >>= 8; - udst[1] = triplet & 0xff; - return i / 4 * 3 + 2; - } else if((i & 3) == 2) { - udst[0] = triplet & 0xff; - return i / 4 * 3 + 1; - } else { - return i / 4 * 3; - } -} - -static int b64encode_internal(const char *src, char *dst, int length, const char *alphabet) { - uint32_t triplet; - const unsigned char *usrc = (unsigned char *)src; - int si = length / 3 * 3; - int di = length / 3 * 4; - - switch(length % 3) { - case 2: - triplet = usrc[si] | usrc[si + 1] << 8; - dst[di] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 1] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 2] = alphabet[triplet]; - dst[di + 3] = 0; - length = di + 2; - break; - case 1: - triplet = usrc[si]; - dst[di] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 1] = alphabet[triplet]; - dst[di + 2] = 0; - length = di + 1; - break; - default: - dst[di] = 0; - length = di; - break; - } - - while(si > 0) { - di -= 4; - si -= 3; - triplet = usrc[si] | usrc[si + 1] << 8 | usrc[si + 2] << 16; - dst[di] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 1] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 2] = alphabet[triplet & 63]; triplet >>= 6; - dst[di + 3] = alphabet[triplet]; - } - - return length; -} - -int b64encode(const char *src, char *dst, int length) { - return b64encode_internal(src, dst, length, base64_original); -} - -int b64encode_urlsafe(const char *src, char *dst, int length) { - return b64encode_internal(src, dst, length, base64_urlsafe); } #if defined(HAVE_MINGW) || defined(HAVE_CYGWIN) @@ -158,13 +64,14 @@ const char *winerror(int err) { ptr = buf + sprintf(buf, "(%d) ", err); - if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), ptr, sizeof(buf) - (ptr - buf), NULL)) { - strncpy(buf, "(unable to format errormessage)", sizeof(buf)); + if(!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), ptr, sizeof(buf) - (ptr - buf), NULL)) { + strcpy(ptr, "(unable to format errormessage)"); }; - if((ptr = strchr(buf, '\r'))) + if((ptr = strchr(buf, '\r'))) { *ptr = '\0'; + } return buf; } @@ -172,8 +79,27 @@ const char *winerror(int err) { unsigned int bitfield_to_int(const void *bitfield, size_t size) { unsigned int value = 0; - if(size > sizeof value) - size = sizeof value; + + if(size > sizeof(value)) { + size = sizeof(value); + } + memcpy(&value, bitfield, size); return value; } + +/** + * As memcmp(), but constant-time. + * Returns 0 when data is equal, non-zero otherwise. + */ +int memcmp_constant_time(const void *a, const void *b, size_t size) { + const uint8_t *a1 = a, *b1 = b; + int ret = 0; + size_t i; + + for(i = 0; i < size; i++) { + ret |= *a1++ ^ *b1++; + } + + return ret; +} diff --git a/src/utils.h b/src/utils.h index 85d6bf2..7952025 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,7 +1,10 @@ +#ifndef TINC_UTILS_H +#define TINC_UTILS_H + /* utils.h -- header file for utils.c Copyright (C) 1999-2005 Ivo Timmermans - 2000-2013 Guus Sliepen + 2000-2014 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,34 +21,30 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef __TINC_UTILS_H__ -#define __TINC_UTILS_H__ +extern bool hex2bin(char *src, char *dst, int length); +extern void bin2hex(char *src, char *dst, int length); -extern int hex2bin(const char *src, char *dst, int length); -extern int bin2hex(const char *src, char *dst, int length); - -extern int b64encode(const char *src, char *dst, int length); -extern int b64encode_urlsafe(const char *src, char *dst, int length); -extern int b64decode(const char *src, char *dst, int length); +#if defined(HAVE_MINGW) || defined(HAVE_CYGWIN) +extern const char *winerror(int); +#endif #ifdef HAVE_MINGW -extern const char *winerror(int); #define strerror(x) ((x)>0?strerror(x):winerror(GetLastError())) #define sockerrno WSAGetLastError() #define sockstrerror(x) winerror(x) #define sockwouldblock(x) ((x) == WSAEWOULDBLOCK || (x) == WSAEINTR) #define sockmsgsize(x) ((x) == WSAEMSGSIZE) #define sockinprogress(x) ((x) == WSAEINPROGRESS || (x) == WSAEWOULDBLOCK) -#define sockinuse(x) ((x) == WSAEADDRINUSE) #else #define sockerrno errno #define sockstrerror(x) strerror(x) #define sockwouldblock(x) ((x) == EWOULDBLOCK || (x) == EINTR) #define sockmsgsize(x) ((x) == EMSGSIZE) #define sockinprogress(x) ((x) == EINPROGRESS) -#define sockinuse(x) ((x) == EADDRINUSE) #endif extern unsigned int bitfield_to_int(const void *bitfield, size_t size); -#endif /* __TINC_UTILS_H__ */ +int memcmp_constant_time(const void *a, const void *b, size_t size); + +#endif diff --git a/src/vde_device.c b/src/vde_device.c index 446ca16..6d854a6 100644 --- a/src/vde_device.c +++ b/src/vde_device.c @@ -1,6 +1,6 @@ /* device.c -- VDE plug - Copyright (C) 2013 Guus Sliepen + Copyright (C) 2012 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,7 +23,6 @@ #include "conf.h" #include "device.h" -#include "names.h" #include "net.h" #include "logger.h" #include "utils.h" @@ -34,7 +33,10 @@ static struct vdepluglib plug; static struct vdeconn *conn = NULL; static int port = 0; static char *group = NULL; -static char *device_info; +static const char *device_info = "VDE socket"; + +extern char *identname; +extern volatile bool running; static uint64_t device_total_in = 0; static uint64_t device_total_out = 0; @@ -43,12 +45,13 @@ static bool setup_device(void) { libvdeplug_dynopen(plug); if(!plug.dl_handle) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not open libvdeplug library!"); + logger(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"); + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { + xasprintf(&device, RUNSTATEDIR "/vde.ctl"); + } get_config_string(lookup_config(config_tree, "Interface"), &iface); @@ -56,8 +59,6 @@ static bool setup_device(void) { get_config_string(lookup_config(config_tree, "VDEGroup"), &group); - device_info = "VDE socket"; - struct vde_open_args args = { .port = port, .group = group, @@ -65,8 +66,9 @@ static bool setup_device(void) { }; conn = plug.vde_open(device, identname, &args); + if(!conn) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not open VDE socket %s", device); + logger(LOG_ERR, "Could not open VDE socket %s", device); return false; } @@ -76,20 +78,23 @@ static bool setup_device(void) { fcntl(device_fd, F_SETFD, FD_CLOEXEC); #endif - logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info); + logger(LOG_INFO, "%s is a %s", device, device_info); - if(routing_mode == RMODE_ROUTER) + if(routing_mode == RMODE_ROUTER) { overwrite_mac = true; + } return true; } static void close_device(void) { - if(conn) + if(conn) { plug.vde_close(conn); + } - if(plug.dl_handle) + if(plug.dl_handle) { libvdeplug_dynclose(plug); + } free(device); @@ -98,15 +103,16 @@ static void close_device(void) { 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(); + logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno)); + running = false; return false; } packet->len = lenin; device_total_in += packet->len; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, device_info); + ifdebug(TRAFFIC) logger(LOG_DEBUG, "Read packet of %d bytes from %s", packet->len, device_info); return true; } @@ -114,8 +120,8 @@ static bool read_packet(vpn_packet_t *packet) { 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(); + logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno)); + running = false; } return false; @@ -127,9 +133,9 @@ static bool write_packet(vpn_packet_t *packet) { } static void dump_device_stats(void) { - logger(DEBUG_ALWAYS, LOG_DEBUG, "Statistics for %s %s:", device_info, device); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); - logger(DEBUG_ALWAYS, LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); + logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device); + logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in); + logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out); } const devops_t vde_devops = { diff --git a/src/xalloc.h b/src/xalloc.h index 28960fb..cda0871 100644 --- a/src/xalloc.h +++ b/src/xalloc.h @@ -1,7 +1,10 @@ +#ifndef TINC_XALLOC_H +#define TINC_XALLOC_H + /* - xalloc.h -- malloc and related fuctions with out of memory checking + xalloc.h -- malloc and related functions with out of memory checking Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. - Copyright (C) 2011-2013 Guus Sliepen + Copyright (C) 2011-2017 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,58 +18,74 @@ 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., Foundation, - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ -#ifndef __TINC_XALLOC_H__ -#define __TINC_XALLOC_H__ - -static inline void *xmalloc(size_t n) __attribute__ ((__malloc__)); +static inline void *xmalloc(size_t n) __attribute__((__malloc__)); static inline void *xmalloc(size_t n) { void *p = malloc(n); - if(!p) + + if(!p) { abort(); + } + return p; } -static inline void *xzalloc(size_t n) __attribute__ ((__malloc__)); -static inline void *xzalloc(size_t n) { +static inline void *xmalloc_and_zero(size_t n) __attribute__((__malloc__)); +static inline void *xmalloc_and_zero(size_t n) { void *p = calloc(1, n); - if(!p) + + if(!p) { abort(); + } + return p; } static inline void *xrealloc(void *p, size_t n) { p = realloc(p, n); - if(!p) + + if(!p) { abort(); + } + return p; } -static inline char *xstrdup(const char *s) __attribute__ ((__malloc__)); +static inline char *xstrdup(const char *s) __attribute__((__malloc__)); static inline char *xstrdup(const char *s) { char *p = strdup(s); - if(!p) + + if(!p) { abort(); + } + return p; } static inline int xvasprintf(char **strp, const char *fmt, va_list ap) { #ifdef HAVE_MINGW char buf[1024]; - int result = vsnprintf(buf, sizeof buf, fmt, ap); - if(result < 0) + int result = vsnprintf(buf, sizeof(buf), fmt, ap); + + if(result < 0) { abort(); + } + *strp = xstrdup(buf); #else int result = vasprintf(strp, fmt, ap); - if(result < 0) + + if(result < 0) { abort(); + } + #endif return result; } -static inline int xasprintf(char **strp, const char *fmt, ...) __attribute__ ((__format__(printf, 2, 3))); +static inline int xasprintf(char **strp, const char *fmt, ...) __attribute__((__format__(printf, 2, 3))); static inline int xasprintf(char **strp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); diff --git a/systemd/Makefile.am b/systemd/Makefile.am new file mode 100644 index 0000000..dac2b73 --- /dev/null +++ b/systemd/Makefile.am @@ -0,0 +1,18 @@ +EXTRA_DIST = tinc.service.in tinc@.service.in + +CLEANFILES = tinc.service tinc@.service + +if WITH_SYSTEMD +systemddir = @systemd_path@ +nodist_systemd_DATA = tinc.service tinc@.service +endif + +substitute = sed \ + -e s,'@sbindir\@',"$(sbindir)",g \ + -e s,'@sysconfdir\@',"$(sysconfdir)",g + +tinc.service: $(srcdir)/tinc.service.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc.service.in > $@ + +tinc@.service: $(srcdir)/tinc@.service.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc@.service.in > $@ diff --git a/gui/Makefile.in b/systemd/Makefile.in similarity index 76% rename from gui/Makefile.in rename to systemd/Makefile.in index 52c86ab..e27e947 100644 --- a/gui/Makefile.in +++ b/systemd/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.13.3 from Makefile.am. +# Makefile.in generated by automake 1.16.2 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2020 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -78,20 +88,42 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -subdir = gui -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(dist_bin_SCRIPTS) +subdir = systemd ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \ - $(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/lzo.m4 \ - $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \ - $(top_srcdir)/m4/zlib.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/ax_append_flag.m4 \ + $(top_srcdir)/m4/ax_cflags_warn_all.m4 \ + $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_require_defined.m4 $(top_srcdir)/m4/lzo.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -119,28 +151,10 @@ am__uninstall_files_from_dir = { \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } -am__installdirs = "$(DESTDIR)$(bindir)" -SCRIPTS = $(dist_bin_SCRIPTS) -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -SOURCES = -DIST_SOURCES = -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac +am__installdirs = "$(DESTDIR)$(systemddir)" +DATA = $(nodist_systemd_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -154,7 +168,6 @@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ -CURSES_LIBS = @CURSES_LIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ @@ -170,12 +183,8 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ -LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ @@ -188,8 +197,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -RANLIB = @RANLIB@ -READLINE_LIBS = @READLINE_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ @@ -236,16 +243,24 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ +systemd_path = @systemd_path@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -dist_bin_SCRIPTS = tinc-gui -extra_DIST = README.gui +EXTRA_DIST = tinc.service.in tinc@.service.in +CLEANFILES = tinc.service tinc@.service +@WITH_SYSTEMD_TRUE@systemddir = @systemd_path@ +@WITH_SYSTEMD_TRUE@nodist_systemd_DATA = tinc.service tinc@.service +substitute = sed \ + -e s,'@sbindir\@',"$(sbindir)",g \ + -e s,'@sysconfdir\@',"$(sysconfdir)",g + all: all-am .SUFFIXES: @@ -258,17 +273,16 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gui/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu systemd/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu gui/Makefile -.PRECIOUS: Makefile + $(AUTOMAKE) --gnu systemd/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -279,56 +293,27 @@ $(top_srcdir)/configure: $(am__configure_deps) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): -install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) +install-nodist_systemdDATA: $(nodist_systemd_DATA) @$(NORMAL_INSTALL) - @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + @list='$(nodist_systemd_DATA)'; test -n "$(systemddir)" || list=; \ if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + echo " $(MKDIR_P) '$(DESTDIR)$(systemddir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(systemddir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ - done | \ - sed -e 'p;s,.*/,,;n' \ - -e 'h;s|.*|.|' \ - -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ - $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ - { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ - if ($$2 == $$4) { files[d] = files[d] " " $$1; \ - if (++n[d] == $(am__install_max)) { \ - print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ - else { print "f", d "/" $$4, $$1 } } \ - END { for (d in files) print "f", d, files[d] }' | \ - while read type dir files; do \ - if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ - test -z "$$files" || { \ - echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ - $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ - } \ - ; done + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(systemddir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(systemddir)" || exit $$?; \ + done -uninstall-dist_binSCRIPTS: +uninstall-nodist_systemdDATA: @$(NORMAL_UNINSTALL) - @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ - files=`for p in $$list; do echo "$$p"; done | \ - sed -e 's,.*/,,;$(transform)'`; \ - dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) - -installcheck-dist_binSCRIPTS: $(dist_bin_SCRIPTS) - bad=0; pid=$$$$; list="$(dist_bin_SCRIPTS)"; for p in $$list; do \ - case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ - *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ - esac; \ - f=`echo "$$p" | sed 's,^.*/,,;$(transform)'`; \ - for opt in --help --version; do \ - if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \ - 2>c$${pid}_.err &2; bad=1; fi; \ - done; \ - done; rm -f c$${pid}_.???; exit $$bad + @list='$(nodist_systemd_DATA)'; test -n "$(systemddir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(systemddir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: @@ -336,7 +321,10 @@ ctags CTAGS: cscope cscopelist: -distdir: $(DISTFILES) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ @@ -368,9 +356,9 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile $(SCRIPTS) +all-am: Makefile $(DATA) installdirs: - for dir in "$(DESTDIR)$(bindir)"; do \ + for dir in "$(DESTDIR)$(systemddir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -395,6 +383,7 @@ install-strip: mostlyclean-generic: clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) @@ -423,13 +412,13 @@ info: info-am info-am: -install-data-am: +install-data-am: install-nodist_systemdDATA install-dvi: install-dvi-am install-dvi-am: -install-exec-am: install-dist_binSCRIPTS +install-exec-am: install-html: install-html-am @@ -449,7 +438,7 @@ install-ps: install-ps-am install-ps-am: -installcheck-am: installcheck-dist_binSCRIPTS +installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile @@ -467,23 +456,30 @@ ps: ps-am ps-am: -uninstall-am: uninstall-dist_binSCRIPTS +uninstall-am: uninstall-nodist_systemdDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ - install-data-am install-dist_binSCRIPTS install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-nodist_systemdDATA \ install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am \ - installcheck-dist_binSCRIPTS installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ - pdf-am ps ps-am tags-am uninstall uninstall-am \ - uninstall-dist_binSCRIPTS + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-nodist_systemdDATA +.PRECIOUS: Makefile + + +tinc.service: $(srcdir)/tinc.service.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc.service.in > $@ + +tinc@.service: $(srcdir)/tinc@.service.in + $(AM_V_GEN)$(substitute) $(srcdir)/tinc@.service.in > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/systemd/tinc.service.in b/systemd/tinc.service.in new file mode 100644 index 0000000..b671042 --- /dev/null +++ b/systemd/tinc.service.in @@ -0,0 +1,20 @@ +# This is a mostly empty service, but allows commands like stop, start, reload +# to propagate to all tinc@ service instances. + +[Unit] +Description=Tinc VPN +Documentation=info:tinc +Documentation=man:tinc(8) man:tinc.conf(5) +Documentation=http://tinc-vpn.org/docs/ +After=network.target +Wants=network.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/true +ExecReload=/bin/true +WorkingDirectory=@sysconfdir@/tinc + +[Install] +WantedBy=multi-user.target diff --git a/systemd/tinc@.service.in b/systemd/tinc@.service.in new file mode 100644 index 0000000..8fbf551 --- /dev/null +++ b/systemd/tinc@.service.in @@ -0,0 +1,20 @@ +[Unit] +Description=Tinc net %i +Documentation=info:tinc +Documentation=man:tinc(8) man:tinc.conf(5) +Documentation=http://tinc-vpn.org/docs/ +PartOf=tinc.service +ReloadPropagatedFrom=tinc.service + +[Service] +Type=simple +WorkingDirectory=@sysconfdir@/tinc/%i +ExecStart=@sbindir@/tincd -n %i -D +ExecReload=@sbindir@/tincd -n %i -kHUP +KillMode=mixed +Restart=on-failure +RestartSec=5 +TimeoutStopSec=5 + +[Install] +WantedBy=tinc.service