diff --git a/ChangeLog b/ChangeLog index d906b29..0f3aeef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,142 @@ +commit 44834d030464bbe1f7733caba8d96c678f1d6cf2 +Author: Guus Sliepen +Date: Sun Nov 1 16:24:39 2009 +0100 + + Releasing 1.0.11. + +commit d331f04e4598824afc7de33ac1228cf441ae9872 +Author: Guus Sliepen +Date: Sun Nov 1 15:57:28 2009 +0100 + + Start a tinc service if it already exists. + +commit 6f6f426b353596edca77829c0477268fc2fc1925 +Author: Guus Sliepen +Date: Tue Oct 27 23:53:49 2009 +0100 + + Fast handoff of roaming MAC addresses. + + In switch mode, if a known MAC address is claimed by a second node before it + expired at the first node, it is likely that this is because a computer has + roamed from the LAN of the first node to that of the second node. To ensure + packets for that computer are routed to the second node, the first node should + delete its corresponding Subnet as soon as possible, without waiting for the + normal expiry timeout. + +commit e00b44cb98e4d50a0d426048ba01dbd80bcb5941 +Author: Guus Sliepen +Date: Sun Oct 25 01:40:07 2009 +0200 + + Move socket error interpretation to utils.h. + +commit c11dc8079b60d9f8c5b1c7e8fecd90d0fac5a20c +Author: Guus Sliepen +Date: Sun Oct 25 00:50:09 2009 +0200 + + Use WSAGetLastError() to determine cause of network errors on Windows. + + This reduces log spam and lets path MTU discovery work faster. + +commit 1bca167b7e24a9cb00ad6130c24f0bb60e208f1f +Author: Michael Tokarev +Date: Sun Oct 18 21:27:24 2009 +0400 + + Remove localedir leftovers. + +commit c3acae034c4da2d1c70f31b852b14ca098c0eeb9 +Author: Guus Sliepen +Date: Sat Oct 24 22:32:35 2009 +0200 + + Use IP_DONTFRAGMENT instead of IP_MTU_DISCOVER on Windows. + + This ensures the DF bit on outgoing UDP packets gets set on Windows when path + MTU discovery is enabled, reducing fragmentation. + +commit 242c4e2ca67d0b5c78dfe6e68a5ddcd27be1de99 +Author: Guus Sliepen +Date: Sat Oct 24 21:53:01 2009 +0200 + + Forward packets to not directly reachable hosts via UDP if possible. + + If MTU probing discovered a node was not reachable via UDP, packets for it were + forwarded to the next hop, but always via TCP, even if the next hop was + reachable via UDP. This is now fixed by retrying to send the packet using + send_packet() if the destination is not the same as the nexthop. + +commit d922db253cd098bc038449e5c591cc94c1019952 +Author: Guus Sliepen +Date: Sat Oct 24 21:35:40 2009 +0200 + + Make maxmtu equal to minmtu when fixing the path MTU to a node. + + This ensures MTU probes used to ping nodes are not too large, and prevents + restarting MTU probing unnecessarily. + +commit a8f7fccbc2b5f1c4c39fc2804abaa358b31a5080 +Author: Guus Sliepen +Date: Sat Oct 24 21:32:06 2009 +0200 + + Always reply to MTU probes via UDP. + + It could sometime happen that a node would return MTU probes via TCP, which + does not make a lot of sense. + +commit cddcdc9af34afb388a8e4bdfff6882f568b98313 +Author: Guus Sliepen +Date: Sat Oct 24 20:54:44 2009 +0200 + + Allow UDP packets with an address different from the corresponding TCP connection. + +commit 5cbddc68bade0d1f8ded1b784bb27bb44c5dc5dc +Author: Guus Sliepen +Date: Sat Oct 24 16:15:24 2009 +0200 + + Use uint32_t instead of long int for connection options. + + Options should have a fixed width anyway, but this also fixes a possible MinGW + compiler bug where %lx tries to print a 64 bit value, even though a long int is + only 32 bits. + +commit 468f393c4fabf9223a1bd15adfb3906cde90d547 +Author: Guus Sliepen +Date: Sat Oct 24 16:05:12 2009 +0200 + + Add dummy device. + +commit b6543af7626403516b5fc54c24b11d3a242a2992 +Author: Guus Sliepen +Date: Tue Oct 20 22:39:07 2009 +0200 + + Clarify and increase level of log message about MTU probes to unreachable nodes. + +commit 43a6e786648fb666a9b7be8f05c8a173031c9110 +Author: Guus Sliepen +Date: Tue Oct 20 22:33:16 2009 +0200 + + Handle weighted Subnets in switch and hub modes. + + We now handle MAC Subnets in exactly the same way as IPv4 and IPv6 Subnets. + This also fixes a problem that causes unncessary broadcasting of unicast + packets in VPNs where some daemons run 1.0.10 and some run other versions. + +commit 3a925479c2883a6a9711f7b6931863d7f2a2c09b +Author: Guus Sliepen +Date: Tue Oct 20 22:22:59 2009 +0200 + + Starting to work towards 1.0.11. + +commit 35af4051c3749cd2c2137a7eb57171a1fbb12af7 +Author: Guus Sliepen +Date: Tue Oct 20 22:14:47 2009 +0200 + + Fix a possible crash when sending the HUP signal. + + When the HUP signal is sent while some outgoing connections have not been made + yet, or are being retried, a NULL pointer could be dereferenced resulting in + tinc crashing. We fix this by more careful handling of outgoing_ts, and by + deleting all connections that have not been fully activated yet at the HUP + signal is received. + commit 8c267d3d558ac97a4ce7381a37abb6cc4b46b133 Author: Guus Sliepen Date: Sun Oct 18 16:45:13 2009 +0200 diff --git a/NEWS b/NEWS index b0a5533..330efbc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,20 @@ +Version 1.0.11 Nov 1 2009 + + * Fixed potential crash when the HUP signal is sent. + + * Fixes handling of weighted Subnets in switch and hub modes, preventing + unnecessary broadcasts. + + * Works around a MinGW bug that caused packets to Windows nodes to always be + sent via TCP. + + * Improvements to the PMTU discovery code, especially on Windows. + + * Use UDP again in certain cases where 1.0.10 was too conservative and fell + back to TCP unnecessarily. + + * Allow fast roaming of hosts to other nodes in a switched VPN. + Version 1.0.10 Oct 18 2009 * Fixed potential crashes during shutdown and (in rare conditions) when other diff --git a/README b/README index a8fff17..8f76b15 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is the README file for tinc version 1.0.10. Installation +This is the README file for tinc version 1.0.11. Installation instructions may be found in the INSTALL file. tinc is Copyright (C) 1998-2009 by: @@ -55,7 +55,7 @@ should be changed into "Device", and "Device" should be changed into Compatibility ------------- -Version 1.0.10 is compatible with 1.0pre8, 1.0 and later, but not with older +Version 1.0.11 is compatible with 1.0pre8, 1.0 and later, but not with older versions of tinc. diff --git a/config.log b/config.log new file mode 100644 index 0000000..0a2b3a7 --- /dev/null +++ b/config.log @@ -0,0 +1,859 @@ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by configure, which was +generated by GNU Autoconf 2.64. Invocation command line was + + $ /scratch/users/guus/backports/tinc-1.0.11/./configure --build=i486-linux-gnu --prefix=/usr --includedir=${prefix}/include --mandir=${prefix}/share/man --infodir=${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --libexecdir=${prefix}/lib/tinc --disable-maintainer-mode --disable-dependency-tracking --srcdir=. + +## --------- ## +## Platform. ## +## --------- ## + +hostname = haplo +uname -m = x86_64 +uname -r = 2.6.32.7 +uname -s = Linux +uname -v = #1 SMP PREEMPT Mon Feb 1 16:35:39 CET 2010 + +/usr/bin/uname -p = unknown +/bin/uname -X = unknown + +/bin/arch = unknown +/usr/bin/arch -k = unknown +/usr/convex/getsysinfo = unknown +/usr/bin/hostinfo = unknown +/bin/machine = unknown +/usr/bin/oslevel = unknown +/bin/universe = unknown + +PATH: /usr/sbin +PATH: /usr/bin +PATH: /sbin +PATH: /bin +PATH: /usr/bin/X11 + + +## ----------- ## +## Core tests. ## +## ----------- ## + +configure:2282: checking for a BSD-compatible install +configure:2350: result: /usr/bin/install -c +configure:2361: checking whether build environment is sane +configure:2411: result: yes +configure:2552: checking for a thread-safe mkdir -p +configure:2591: result: /bin/mkdir -p +configure:2604: checking for gawk +configure:2634: result: no +configure:2604: checking for mawk +configure:2620: found /usr/bin/mawk +configure:2631: result: mawk +configure:2642: checking whether make sets $(MAKE) +configure:2664: result: yes +configure:2747: checking whether to enable maintainer-specific portions of Makefiles +configure:2756: result: no +configure:2785: checking for style of include used by make +configure:2813: result: GNU +configure:2883: checking for gcc +configure:2910: result: cc +configure:3139: checking for C compiler version +configure:3148: cc --version >&5 +cc (Debian 4.3.2-1.1) 4.3.2 +Copyright (C) 2008 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. + +configure:3159: $? = 0 +configure:3148: cc -v >&5 +Using built-in specs. +Target: i486-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.2-1.1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-cld --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu +Thread model: posix +gcc version 4.3.2 (Debian 4.3.2-1.1) +configure:3159: $? = 0 +configure:3148: cc -V >&5 +cc: '-V' option must have argument +configure:3159: $? = 1 +configure:3148: cc -qversion >&5 +cc: unrecognized option '-qversion' +cc: no input files +configure:3159: $? = 1 +configure:3181: checking for C compiler default output file name +configure:3203: cc -g -O2 -g -Wall -O2 conftest.c >&5 +configure:3207: $? = 0 +configure:3244: result: a.out +configure:3260: checking whether the C compiler works +configure:3269: ./a.out +configure:3273: $? = 0 +configure:3288: result: yes +configure:3295: checking whether we are cross compiling +configure:3297: result: no +configure:3300: checking for suffix of executables +configure:3307: cc -o conftest -g -O2 -g -Wall -O2 conftest.c >&5 +configure:3311: $? = 0 +configure:3333: result: +configure:3339: checking for suffix of object files +configure:3361: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:3365: $? = 0 +configure:3386: result: o +configure:3390: checking whether we are using the GNU C compiler +configure:3409: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:3409: $? = 0 +configure:3418: result: yes +configure:3427: checking whether cc accepts -g +configure:3447: cc -c -g conftest.c >&5 +configure:3447: $? = 0 +configure:3488: result: yes +configure:3505: checking for cc option to accept ISO C89 +configure:3569: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:3569: $? = 0 +configure:3582: result: none needed +configure:3604: checking dependency style of cc +configure:3714: result: none +configure:3735: checking how to run the C preprocessor +configure:3766: cc -E conftest.c +configure:3766: $? = 0 +configure:3780: cc -E conftest.c +conftest.c:11:28: error: ac_nonexistent.h: No such file or directory +configure:3780: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define PACKAGE "tinc" +| #define VERSION "1.0.11" +| /* end confdefs.h. */ +| #include +configure:3805: result: cc -E +configure:3825: cc -E conftest.c +configure:3825: $? = 0 +configure:3839: cc -E conftest.c +conftest.c:11:28: error: ac_nonexistent.h: No such file or directory +configure:3839: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define PACKAGE "tinc" +| #define VERSION "1.0.11" +| /* end confdefs.h. */ +| #include +configure:3868: checking for grep that handles long lines and -e +configure:3926: result: /bin/grep +configure:3931: checking for egrep +configure:3993: result: /bin/grep -E +configure:3998: checking for ANSI C header files +configure:4018: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4018: $? = 0 +configure:4091: cc -o conftest -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4091: $? = 0 +configure:4091: ./conftest +configure:4091: $? = 0 +configure:4102: result: yes +configure:4115: checking for sys/types.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4115: checking for sys/stat.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4115: checking for stdlib.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4115: checking for string.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4115: checking for memory.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4115: checking for strings.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4115: checking for inttypes.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4115: checking for stdint.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4115: checking for unistd.h +configure:4115: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4115: $? = 0 +configure:4115: result: yes +configure:4129: checking minix/config.h usability +configure:4129: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +conftest.c:54:26: error: minix/config.h: No such file or directory +configure:4129: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define PACKAGE "tinc" +| #define VERSION "1.0.11" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| /* end confdefs.h. */ +| #include +| #ifdef HAVE_SYS_TYPES_H +| # include +| #endif +| #ifdef HAVE_SYS_STAT_H +| # include +| #endif +| #ifdef STDC_HEADERS +| # include +| # include +| #else +| # ifdef HAVE_STDLIB_H +| # include +| # endif +| #endif +| #ifdef HAVE_STRING_H +| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #ifdef HAVE_STRINGS_H +| # include +| #endif +| #ifdef HAVE_INTTYPES_H +| # include +| #endif +| #ifdef HAVE_STDINT_H +| # include +| #endif +| #ifdef HAVE_UNISTD_H +| # include +| #endif +| #include +configure:4129: result: no +configure:4129: checking minix/config.h presence +configure:4129: cc -E conftest.c +conftest.c:21:26: error: minix/config.h: No such file or directory +configure:4129: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define PACKAGE "tinc" +| #define VERSION "1.0.11" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| /* end confdefs.h. */ +| #include +configure:4129: result: no +configure:4129: checking for minix/config.h +configure:4129: result: no +configure:4150: checking whether it is safe to define __EXTENSIONS__ +configure:4168: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4168: $? = 0 +configure:4175: result: yes +configure:4196: checking for cc option to accept ISO C99 +configure:4345: cc -c -g -O2 -g -Wall -O2 conftest.c >&5 +conftest.c:77: error: expected ';', ',' or ')' before 'text' +conftest.c: In function 'main': +conftest.c:129: warning: implicit declaration of function 'test_restrict' +conftest.c:131: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'newvar' +conftest.c:131: error: 'newvar' undeclared (first use in this function) +conftest.c:131: error: (Each undeclared identifier is reported only once +conftest.c:131: error: for each function it appears in.) +conftest.c:141: error: 'for' loop initial declaration used outside C99 mode +configure:4345: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define PACKAGE "tinc" +| #define VERSION "1.0.11" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define __USE_BSD 1 +| /* end confdefs.h. */ +| #include +| #include +| #include +| #include +| #include +| +| // Check varargs macros. These examples are taken from C99 6.10.3.5. +| #define debug(...) fprintf (stderr, __VA_ARGS__) +| #define showlist(...) puts (#__VA_ARGS__) +| #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +| static void +| test_varargs_macros (void) +| { +| int x = 1234; +| int y = 5678; +| debug ("Flag"); +| debug ("X = %d\n", x); +| showlist (The first, second, and third items.); +| report (x>y, "x is %d but y is %d", x, y); +| } +| +| // Check long long types. +| #define BIG64 18446744073709551615ull +| #define BIG32 4294967295ul +| #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +| #if !BIG_OK +| your preprocessor is broken; +| #endif +| #if BIG_OK +| #else +| your preprocessor is broken; +| #endif +| static long long int bignum = -9223372036854775807LL; +| static unsigned long long int ubignum = BIG64; +| +| struct incomplete_array +| { +| int datasize; +| double data[]; +| }; +| +| struct named_init { +| int number; +| const wchar_t *name; +| double average; +| }; +| +| typedef const char *ccp; +| +| static inline int +| test_restrict (ccp restrict text) +| { +| // See if C++-style comments work. +| // Iterate through items via the restricted pointer. +| // Also check for declarations in for loops. +| for (unsigned int i = 0; *(text+i) != '\0'; ++i) +| continue; +| return 0; +| } +| +| // Check varargs and va_copy. +| static void +| test_varargs (const char *format, ...) +| { +| va_list args; +| va_start (args, format); +| va_list args_copy; +| va_copy (args_copy, args); +| +| const char *str; +| int number; +| float fnumber; +| +| while (*format) +| { +| switch (*format++) +| { +| case 's': // string +| str = va_arg (args_copy, const char *); +| break; +| case 'd': // int +| number = va_arg (args_copy, int); +| break; +| case 'f': // float +| fnumber = va_arg (args_copy, double); +| break; +| default: +| break; +| } +| } +| va_end (args_copy); +| va_end (args); +| } +| +| int +| main () +| { +| +| // Check bool. +| _Bool success = false; +| +| // Check restrict. +| if (test_restrict ("String literal") == 0) +| success = true; +| char *restrict newvar = "Another string"; +| +| // Check varargs. +| test_varargs ("s, d' f .", "string", 65, 34.234); +| test_varargs_macros (); +| +| // Check flexible array members. +| struct incomplete_array *ia = +| malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); +| ia->datasize = 10; +| for (int i = 0; i < ia->datasize; ++i) +| ia->data[i] = i * 1.234; +| +| // Check named initializers. +| struct named_init ni = { +| .number = 34, +| .name = L"Test wide string", +| .average = 543.34343, +| }; +| +| ni.number = 58; +| +| int dynamic_array[ni.number]; +| dynamic_array[ni.number - 1] = 543; +| +| // work around unused variable warnings +| return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' +| || dynamic_array[ni.number - 1] != 543); +| +| ; +| return 0; +| } +configure:4345: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4345: $? = 0 +configure:4365: result: -std=gnu99 +configure:4378: checking how to run the C preprocessor +configure:4448: result: cc -E +configure:4468: cc -E conftest.c +configure:4468: $? = 0 +configure:4482: cc -E conftest.c +conftest.c:27:28: error: ac_nonexistent.h: No such file or directory +configure:4482: $? = 1 +configure: failed program was: +| /* confdefs.h */ +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define PACKAGE_URL "" +| #define PACKAGE "tinc" +| #define VERSION "1.0.11" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define __EXTENSIONS__ 1 +| #define _ALL_SOURCE 1 +| #define _GNU_SOURCE 1 +| #define _POSIX_PTHREAD_SEMANTICS 1 +| #define _TANDEM_SOURCE 1 +| #define __USE_BSD 1 +| /* end confdefs.h. */ +| #include +configure:4511: checking whether ln -s works +configure:4515: result: yes +configure:4565: checking for ranlib +configure:4581: found /usr/bin/ranlib +configure:4592: result: ranlib +configure:4620: checking build system type +configure:4634: result: i486-pc-linux-gnu +configure:4654: checking host system type +configure:4667: result: i486-pc-linux-gnu +configure:4865: checking for ANSI C header files +configure:4969: result: yes +configure:4980: checking stdbool.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking stdbool.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for stdbool.h +configure:4980: result: yes +configure:4980: checking syslog.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking syslog.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for syslog.h +configure:4980: result: yes +configure:4980: checking sys/file.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking sys/file.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for sys/file.h +configure:4980: result: yes +configure:4980: checking sys/ioctl.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking sys/ioctl.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for sys/ioctl.h +configure:4980: result: yes +configure:4980: checking sys/mman.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking sys/mman.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for sys/mman.h +configure:4980: result: yes +configure:4980: checking sys/param.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking sys/param.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for sys/param.h +configure:4980: result: yes +configure:4980: checking sys/socket.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking sys/socket.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for sys/socket.h +configure:4980: result: yes +configure:4980: checking sys/time.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking sys/time.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for sys/time.h +configure:4980: result: yes +configure:4980: checking sys/uio.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking sys/uio.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for sys/uio.h +configure:4980: result: yes +configure:4980: checking sys/wait.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking sys/wait.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for sys/wait.h +configure:4980: result: yes +configure:4980: checking netdb.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking netdb.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for netdb.h +configure:4980: result: yes +configure:4980: checking arpa/inet.h usability +configure:4980: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking arpa/inet.h presence +configure:4980: cc -E conftest.c +configure:4980: $? = 0 +configure:4980: result: yes +configure:4980: checking for arpa/inet.h +configure:4980: result: yes +configure:4994: checking for net/if.h +configure:4994: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +configure:4994: $? = 0 +configure:4994: result: yes +configure:4994: checking for net/if_types.h +configure:4994: cc -std=gnu99 -c -g -O2 -g -Wall -O2 conftest.c >&5 +conftest.c:45:26: error: net/if_types.h: No such file or directory + +## ---------------- ## +## Cache variables. ## +## ---------------- ## + +ac_cv_build=i486-pc-linux-gnu +ac_cv_c_compiler_gnu=yes +ac_cv_env_CC_set=set +ac_cv_env_CC_value=cc +ac_cv_env_CFLAGS_set=set +ac_cv_env_CFLAGS_value='-g -O2 -g -Wall -O2' +ac_cv_env_CPPFLAGS_set=set +ac_cv_env_CPPFLAGS_value= +ac_cv_env_CPP_set= +ac_cv_env_CPP_value= +ac_cv_env_LDFLAGS_set=set +ac_cv_env_LDFLAGS_value= +ac_cv_env_LIBS_set= +ac_cv_env_LIBS_value= +ac_cv_env_build_alias_set=set +ac_cv_env_build_alias_value=i486-linux-gnu +ac_cv_env_host_alias_set= +ac_cv_env_host_alias_value= +ac_cv_env_target_alias_set= +ac_cv_env_target_alias_value= +ac_cv_header_arpa_inet_h=yes +ac_cv_header_inttypes_h=yes +ac_cv_header_memory_h=yes +ac_cv_header_minix_config_h=no +ac_cv_header_net_if_h=yes +ac_cv_header_netdb_h=yes +ac_cv_header_stdbool_h=yes +ac_cv_header_stdc=yes +ac_cv_header_stdint_h=yes +ac_cv_header_stdlib_h=yes +ac_cv_header_string_h=yes +ac_cv_header_strings_h=yes +ac_cv_header_sys_file_h=yes +ac_cv_header_sys_ioctl_h=yes +ac_cv_header_sys_mman_h=yes +ac_cv_header_sys_param_h=yes +ac_cv_header_sys_socket_h=yes +ac_cv_header_sys_stat_h=yes +ac_cv_header_sys_time_h=yes +ac_cv_header_sys_types_h=yes +ac_cv_header_sys_uio_h=yes +ac_cv_header_sys_wait_h=yes +ac_cv_header_syslog_h=yes +ac_cv_header_unistd_h=yes +ac_cv_host=i486-pc-linux-gnu +ac_cv_objext=o +ac_cv_path_EGREP='/bin/grep -E' +ac_cv_path_GREP=/bin/grep +ac_cv_path_install='/usr/bin/install -c' +ac_cv_path_mkdir=/bin/mkdir +ac_cv_prog_AWK=mawk +ac_cv_prog_CPP='cc -E' +ac_cv_prog_ac_ct_CC=cc +ac_cv_prog_ac_ct_RANLIB=ranlib +ac_cv_prog_cc_c89= +ac_cv_prog_cc_c99=-std=gnu99 +ac_cv_prog_cc_g=yes +ac_cv_prog_make_make_set=yes +ac_cv_safe_to_define___extensions__=yes +am_cv_CC_dependencies_compiler_type=none + +## ----------------- ## +## Output variables. ## +## ----------------- ## + +ACLOCAL='${SHELL} /scratch/users/guus/backports/tinc-1.0.11/missing --run aclocal-1.11' +ALLOCA='' +AMDEPBACKSLASH='' +AMDEP_FALSE='' +AMDEP_TRUE='#' +AMTAR='${SHELL} /scratch/users/guus/backports/tinc-1.0.11/missing --run tar' +AUTOCONF='${SHELL} /scratch/users/guus/backports/tinc-1.0.11/missing --run autoconf' +AUTOHEADER='${SHELL} /scratch/users/guus/backports/tinc-1.0.11/missing --run autoheader' +AUTOMAKE='${SHELL} /scratch/users/guus/backports/tinc-1.0.11/missing --run automake-1.11' +AWK='mawk' +CC='cc -std=gnu99' +CCDEPMODE='depmode=none' +CFLAGS='-g -O2 -g -Wall -O2' +CPP='cc -E' +CPPFLAGS='' +CYGPATH_W='echo' +DEFS='' +DEPDIR='.deps' +ECHO_C='' +ECHO_N='-n' +ECHO_T='' +EGREP='/bin/grep -E' +EXEEXT='' +GREP='/bin/grep' +INCLUDES='' +INSTALL_DATA='${INSTALL} -m 644' +INSTALL_PROGRAM='${INSTALL}' +INSTALL_SCRIPT='${INSTALL}' +INSTALL_STRIP_PROGRAM='$(install_sh) -c -s' +LDFLAGS='' +LIBOBJS='' +LIBS='' +LN_S='ln -s' +LTLIBOBJS='' +MAINT='#' +MAINTAINER_MODE_FALSE='' +MAINTAINER_MODE_TRUE='#' +MAKEINFO='${SHELL} /scratch/users/guus/backports/tinc-1.0.11/missing --run makeinfo' +MKDIR_P='/bin/mkdir -p' +OBJEXT='o' +PACKAGE='tinc' +PACKAGE_BUGREPORT='' +PACKAGE_NAME='' +PACKAGE_STRING='' +PACKAGE_TARNAME='' +PACKAGE_URL='' +PACKAGE_VERSION='' +PATH_SEPARATOR=':' +RANLIB='ranlib' +SET_MAKE='' +SHELL='/bin/sh' +STRIP='' +TUNEMU_FALSE='' +TUNEMU_TRUE='#' +VERSION='1.0.11' +ac_ct_CC='cc' +am__EXEEXT_FALSE='' +am__EXEEXT_TRUE='' +am__fastdepCC_FALSE='' +am__fastdepCC_TRUE='#' +am__include='include' +am__isrc='' +am__leading_dot='.' +am__quote='' +am__tar='${AMTAR} chof - "$$tardir"' +am__untar='${AMTAR} xf -' +bindir='${exec_prefix}/bin' +build='i486-pc-linux-gnu' +build_alias='i486-linux-gnu' +build_cpu='i486' +build_os='linux-gnu' +build_vendor='pc' +datadir='${datarootdir}' +datarootdir='${prefix}/share' +docdir='${datarootdir}/doc/${PACKAGE}' +dvidir='${docdir}' +exec_prefix='NONE' +host='i486-pc-linux-gnu' +host_alias='' +host_cpu='i486' +host_os='linux-gnu' +host_vendor='pc' +htmldir='${docdir}' +includedir='${prefix}/include' +infodir='${prefix}/share/info' +install_sh='${SHELL} /scratch/users/guus/backports/tinc-1.0.11/install-sh' +libdir='${exec_prefix}/lib' +libexecdir='${prefix}/lib/tinc' +localedir='${datarootdir}/locale' +localstatedir='/var' +mandir='${prefix}/share/man' +mkdir_p='/bin/mkdir -p' +oldincludedir='/usr/include' +pdfdir='${docdir}' +prefix='/usr' +program_transform_name='s,x,x,' +psdir='${docdir}' +sbindir='${exec_prefix}/sbin' +sharedstatedir='${prefix}/com' +sysconfdir='/etc' +target_alias='' + +## ----------- ## +## confdefs.h. ## +## ----------- ## + +/* confdefs.h */ +#define PACKAGE_NAME "" +#define PACKAGE_TARNAME "" +#define PACKAGE_VERSION "" +#define PACKAGE_STRING "" +#define PACKAGE_BUGREPORT "" +#define PACKAGE_URL "" +#define PACKAGE "tinc" +#define VERSION "1.0.11" +#define STDC_HEADERS 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_UNISTD_H 1 +#define __EXTENSIONS__ 1 +#define _ALL_SOURCE 1 +#define _GNU_SOURCE 1 +#define _POSIX_PTHREAD_SEMANTICS 1 +#define _TANDEM_SOURCE 1 +#define __USE_BSD 1 +#define HAVE_LINUX 1 +#define STDC_HEADERS 1 +#define HAVE_STDBOOL_H 1 +#define HAVE_SYSLOG_H 1 +#define HAVE_SYS_FILE_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_MMAN_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_UIO_H 1 +#define HAVE_SYS_WAIT_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_ARPA_INET_H 1 +#define HAVE_NET_IF_H 1 + +configure: caught signal 2 +configure: exit 1 diff --git a/configure b/configure index 331668f..21baffb 100755 --- a/configure +++ b/configure @@ -2701,7 +2701,7 @@ fi # Define the identity of the package. PACKAGE=tinc - VERSION=1.0.10 + VERSION=1.0.11 cat >>confdefs.h <<_ACEOF diff --git a/configure.in b/configure.in index efe9a8a..21a5818 100644 --- a/configure.in +++ b/configure.in @@ -3,7 +3,7 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) AC_INIT AC_CONFIG_SRCDIR([src/tincd.c]) -AM_INIT_AUTOMAKE(tinc, 1.0.10) +AM_INIT_AUTOMAKE(tinc, 1.0.11) AC_CONFIG_HEADERS([config.h]) AM_MAINTAINER_MODE diff --git a/debian/changelog b/debian/changelog index 5947c75..288fb55 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,19 @@ +tinc (1.0.11-1~bpo50+1) lenny-backports; urgency=low + + * Rebuild for lenny-backports. + + -- Guus Sliepen Thu, 04 Feb 2010 19:03:00 +0000 + +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. diff --git a/debian/postinst b/debian/postinst index 7fccffd..5233dae 100644 --- a/debian/postinst +++ b/debian/postinst @@ -63,7 +63,7 @@ case "$1" in fi if [ "$RET" = "true" ] ; then - invoke-rc.d tinc start + invoke-rc.d tinc restart else echo "I have not stopped or restarted the tinc daemon. You should do this" echo "yourself whenever you're ready; type \`\`invoke-rc.d tinc restart''." diff --git a/debian/prerm b/debian/prerm index 8b579ac..30347c0 100644 --- a/debian/prerm +++ b/debian/prerm @@ -3,7 +3,7 @@ set -e # Automatically added by dh_installinit, edited for use with debconf -if [ -x "/etc/init.d/tinc" ]; then +if [ -x "/etc/init.d/tinc" -a "$1" != "upgrade" ]; then if [ -e /usr/share/debconf/confmodule ] ; then . /usr/share/debconf/confmodule db_get tinc/restart_on_upgrade diff --git a/debian/rules b/debian/rules index 1b9abe4..7272f93 100755 --- a/debian/rules +++ b/debian/rules @@ -13,6 +13,9 @@ clean:: build/tinc:: cd doc && $(MAKE) texi2html binary-post-install/tinc:: - mv -v doc/tinc/*.html debian/$(cdbs_curpkg)/usr/share/doc/$(cdbs_curpkg)/ + # Guess where texi2html installed its output today... + [ -f doc/tinc/tinc.html ] \ + && mv -v doc/tinc/*.html debian/$(cdbs_curpkg)/usr/share/doc/$(cdbs_curpkg)/ \ + || mv -v doc/*.html debian/$(cdbs_curpkg)/usr/share/doc/$(cdbs_curpkg)/ rm -f debian/$(cdbs_curpkg)/usr/share/info/dir* cd debian/$(cdbs_curpkg)/usr/share/doc/$(cdbs_curpkg)/ && tar xzf ../../../../../../doc/sample-config.tar.gz && mv sample-config examples && rm -rf examples/CVS examples/hosts/CVS diff --git a/doc/tinc.info b/doc/tinc.info index fe5c670..8af5678 100644 --- a/doc/tinc.info +++ b/doc/tinc.info @@ -5,7 +5,7 @@ START-INFO-DIR-ENTRY * tinc: (tinc). The tinc Manual. END-INFO-DIR-ENTRY - This is the info manual for tinc version 1.0.10, a Virtual Private + This is the info manual for tinc version 1.0.11, a Virtual Private Network daemon. Copyright (C) 1998-2009 Ivo Timmermans, Guus Sliepen diff --git a/lib/utils.h b/lib/utils.h index c6fb180..4456616 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -27,6 +27,17 @@ extern void bin2hex(char *src, char *dst, int length); #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) +#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) #endif extern unsigned int bitfield_to_int(void *bitfield, size_t size); diff --git a/src/Makefile.am b/src/Makefile.am index bdd1a3f..491f011 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,9 +30,7 @@ endif tincd_LDADD = \ $(top_builddir)/lib/libvpn.a -localedir = $(datadir)/locale - -AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" +AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" dist-hook: rm -f `find . -type l` diff --git a/src/Makefile.in b/src/Makefile.in index 6bae860..1f9e7f5 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -166,7 +166,7 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ -localedir = $(datadir)/locale +localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ @@ -197,7 +197,7 @@ noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h logger.h me tincd_LDADD = \ $(top_builddir)/lib/libvpn.a -AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALEDIR=\"$(localedir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" +AM_CFLAGS = @CFLAGS@ -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" all: all-am .SUFFIXES: diff --git a/src/connection.c b/src/connection.c index 6e942f8..9a26ec9 100644 --- a/src/connection.c +++ b/src/connection.c @@ -120,7 +120,7 @@ void dump_connections(void) { for(node = connection_tree->head; node; node = node->next) { c = node->data; - logger(LOG_DEBUG, " %s at %s options %lx socket %d status %04x outbuf %d/%d/%d", + 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); } diff --git a/src/connection.h b/src/connection.h index 24c95f4..b3a7e33 100644 --- a/src/connection.h +++ b/src/connection.h @@ -56,7 +56,7 @@ typedef struct connection_t { int protocol_version; /* used protocol */ int socket; /* socket used for this connection */ - long int options; /* options for this connection */ + uint32_t options; /* options for this connection */ connection_status_t status; /* status info */ int estimated_weight; /* estimation for the weight of the edge for this connection */ struct timeval start; /* time this connection was started, used for above estimation */ diff --git a/src/edge.c b/src/edge.c index 9e1b31e..e42dbd1 100644 --- a/src/edge.c +++ b/src/edge.c @@ -118,7 +118,7 @@ void dump_edges(void) { 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 %lx weight %d", + 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); } diff --git a/src/edge.h b/src/edge.h index dc5cf46..4c65213 100644 --- a/src/edge.h +++ b/src/edge.h @@ -31,7 +31,7 @@ typedef struct edge_t { struct node_t *to; sockaddr_t address; - long int options; /* options turned on for 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 */ diff --git a/src/event.h b/src/event.h index 345a5f9..da2e741 100644 --- a/src/event.h +++ b/src/event.h @@ -27,7 +27,7 @@ extern avl_tree_t *event_tree; typedef void (*event_handler_t)(void *); -typedef struct { +typedef struct event { time_t time; int id; event_handler_t handler; diff --git a/src/meta.c b/src/meta.c index 21400f2..4c52464 100644 --- a/src/meta.c +++ b/src/meta.c @@ -94,15 +94,13 @@ bool flush_meta(connection_t *c) { c->name, c->hostname); } else if(errno == EINTR) { continue; -#ifdef EWOULDBLOCK - } else if(errno == EWOULDBLOCK) { + } else if(sockwouldblock(sockerrno)) { ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Flushing %d bytes to %s (%s) would block", c->outbuflen, c->name, c->hostname); return true; -#endif } else { logger(LOG_ERR, "Flushing meta data to %s (%s) failed: %s", c->name, - c->hostname, strerror(errno)); + c->hostname, sockstrerror(sockerrno)); } return false; @@ -149,11 +147,11 @@ bool receive_meta(connection_t *c) { if(!lenin || !errno) { ifdebug(CONNECTIONS) logger(LOG_NOTICE, "Connection closed by %s (%s)", c->name, c->hostname); - } else if(errno == EINTR) + } else if(sockwouldblock(sockerrno)) return true; else logger(LOG_ERR, "Metadata socket read error for %s (%s): %s", - c->name, c->hostname, strerror(errno)); + c->name, c->hostname, sockstrerror(sockerrno)); return false; } diff --git a/src/net.c b/src/net.c index 3197036..3f17083 100644 --- a/src/net.c +++ b/src/net.c @@ -303,7 +303,7 @@ static void check_network_activity(fd_set * readset, fd_set * writeset) { else { ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Error while connecting to %s (%s): %s", - c->name, c->hostname, strerror(result)); + c->name, c->hostname, sockstrerror(result)); closesocket(c->socket); do_outgoing_connection(c); continue; @@ -369,9 +369,8 @@ int main_loop(void) { #endif if(r < 0) { - if(errno != EINTR && errno != EAGAIN) { - logger(LOG_ERR, "Error while waiting for input: %s", - strerror(errno)); + if(!sockwouldblock(sockerrno)) { + logger(LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno)); dump_connections(); return 1; } @@ -431,7 +430,7 @@ int main_loop(void) { if(sighup) { connection_t *c; - avl_node_t *node; + avl_node_t *node, *next; char *fname; struct stat s; @@ -447,6 +446,31 @@ int main_loop(void) { 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) { diff --git a/src/net.h b/src/net.h index 31438e5..fe4b54b 100644 --- a/src/net.h +++ b/src/net.h @@ -98,6 +98,7 @@ typedef struct outgoing_t { struct config_t *cfg; struct addrinfo *ai; struct addrinfo *aip; + struct event *event; } outgoing_t; extern list_t *outgoing_list; diff --git a/src/net_packet.c b/src/net_packet.c index 7a73ef5..e501153 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -46,10 +46,6 @@ #include "utils.h" #include "xalloc.h" -#ifdef WSAEMSGSIZE -#define EMSGSIZE WSAEMSGSIZE -#endif - int keylifetime = 0; int keyexpires = 0; static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS]; @@ -72,7 +68,7 @@ void send_mtu_probe(node_t *n) { n->mtuevent = NULL; if(!n->status.reachable || !n->status.validkey) { - logger(LOG_DEBUG, "Trying to send MTU probe to unreachable 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; } @@ -91,6 +87,10 @@ void send_mtu_probe(node_t *n) { } if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) { + if(n->minmtu > n->maxmtu) + n->minmtu = n->maxmtu; + else + n->maxmtu = n->minmtu; n->mtu = n->minmtu; 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; @@ -135,7 +135,7 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { if(!packet->data[0]) { packet->data[0] = 1; - send_packet(n, packet); + send_udppacket(n, packet); } else { if(len > n->maxmtu) len = n->maxmtu; @@ -365,10 +365,13 @@ 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])) { ifdebug(TRAFFIC) logger(LOG_INFO, - "Packet for %s (%s) larger than minimum MTU, forwarding via TCP", - n->name, n->hostname); + "Packet for %s (%s) larger than minimum MTU, forwarding via %s", + n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP"); - send_tcppacket(n->nexthop->connection, origpkt); + if(n != n->nexthop) + send_packet(n->nexthop, origpkt); + else + send_tcppacket(n->nexthop->connection, origpkt); return; } @@ -442,14 +445,14 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { } #endif - if((sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0) { - if(errno == EMSGSIZE) { + if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) { + if(sockmsgsize(sockerrno)) { if(n->maxmtu >= origlen) n->maxmtu = origlen - 1; if(n->mtu >= origlen) n->mtu = origlen - 1; } else - logger(LOG_ERR, "Error sending packet to %s (%s): %s", n->name, n->hostname, strerror(errno)); + logger(LOG_ERR, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno)); } end: @@ -521,12 +524,16 @@ 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; + static time_t last_hard_try = 0; for(node = edge_weight_tree->head; node; node = node->next) { e = node->data; - if(sockaddrcmp_noport(from, &e->address)) - continue; + if(sockaddrcmp_noport(from, &e->address)) { + if(last_hard_try == now) + continue; + last_hard_try = now; + } if(!n) n = e->to; @@ -551,8 +558,8 @@ void handle_incoming_vpn_data(int sock) { pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); if(pkt.len < 0) { - if(errno != EAGAIN && errno != EINTR) - logger(LOG_ERR, "Receiving packet failed: %s", strerror(errno)); + if(!sockwouldblock(sockerrno)) + logger(LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno)); return; } diff --git a/src/net_setup.c b/src/net_setup.c index a08981f..cbf631f 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -541,10 +541,17 @@ void close_network_connections(void) { for(node = connection_tree->head; node; node = next) { next = node->next; c = node->data; - c->outgoing = false; + 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) { diff --git a/src/net_socket.c b/src/net_socket.c index 7189025..46e0532 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -36,10 +36,6 @@ #include -#ifdef WSAEINPROGRESS -#define EINPROGRESS WSAEINPROGRESS -#endif - /* Needed on Mac OS/X */ #ifndef SOL_TCP #define SOL_TCP IPPROTO_TCP @@ -68,7 +64,7 @@ static void configure_tcp(connection_t *c) { unsigned long arg = 1; if(ioctlsocket(c->socket, FIONBIO, &arg) != 0) { - logger(LOG_ERR, "ioctlsocket for %s: WSA error %d", c->hostname, WSAGetLastError()); + logger(LOG_ERR, "ioctlsocket for %s: %d", c->hostname, sockstrerror(sockerrno)); } #endif @@ -157,8 +153,7 @@ static bool bind_to_address(connection_t *c) { if(status) { - logger(LOG_ERR, "Can't bind to %s/tcp: %s", node, - strerror(errno)); + logger(LOG_ERR, "Can't bind to %s/tcp: %s", node, sockstrerror(sockerrno)); } else ifdebug(CONNECTIONS) { logger(LOG_DEBUG, "Successfully bound outgoing " "TCP socket to %s", node); @@ -179,7 +174,7 @@ int setup_listen_socket(const sockaddr_t *sa) { nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if(nfd < 0) { - ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", strerror(errno)); + ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno)); return -1; } @@ -204,7 +199,7 @@ int setup_listen_socket(const sockaddr_t *sa) { if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) { closesocket(nfd); logger(LOG_ERR, "Can't bind to interface %s: %s", iface, - strerror(errno)); + strerror(sockerrno)); return -1; } #else @@ -215,16 +210,14 @@ int setup_listen_socket(const sockaddr_t *sa) { if(bind(nfd, &sa->sa, SALEN(sa->sa))) { closesocket(nfd); addrstr = sockaddr2hostname(sa); - logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, - strerror(errno)); + logger(LOG_ERR, "Can't bind to %s/tcp: %s", addrstr, sockstrerror(sockerrno)); free(addrstr); return -1; } if(listen(nfd, 3)) { closesocket(nfd); - logger(LOG_ERR, "System call `%s' failed: %s", "listen", - strerror(errno)); + logger(LOG_ERR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno)); return -1; } @@ -239,7 +232,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); if(nfd < 0) { - logger(LOG_ERR, "Creating UDP socket failed: %s", strerror(errno)); + logger(LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno)); return -1; } @@ -259,8 +252,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { unsigned long arg = 1; if(ioctlsocket(nfd, FIONBIO, &arg) != 0) { closesocket(nfd); - logger(LOG_ERR, "Call to `%s' failed: WSA error %d", "ioctlsocket", - WSAGetLastError()); + logger(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno)); return -1; } } @@ -279,6 +271,11 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { option = IP_PMTUDISC_DO; setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, &option, sizeof(option)); } +#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT) + if(myself->options & OPTION_PMTU_DISCOVERY) { + option = 1; + setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, &option, sizeof(option)); + } #endif #if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) @@ -296,8 +293,7 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { if(bind(nfd, &sa->sa, SALEN(sa->sa))) { closesocket(nfd); addrstr = sockaddr2hostname(sa); - logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr, - strerror(errno)); + logger(LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno)); free(addrstr); return -1; } @@ -306,18 +302,18 @@ int setup_vpn_in_socket(const sockaddr_t *sa) { } /* int setup_vpn_in_socket */ void retry_outgoing(outgoing_t *outgoing) { - event_t *event; - outgoing->timeout += 5; if(outgoing->timeout > maxtimeout) outgoing->timeout = maxtimeout; - event = new_event(); - event->handler = (event_handler_t) setup_outgoing_connection; - event->time = now + outgoing->timeout; - event->data = outgoing; - event_add(event); + if(outgoing->event) + event_del(outgoing->event); + 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", @@ -338,6 +334,11 @@ void do_outgoing_connection(connection_t *c) { char *address, *port; 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) { @@ -345,6 +346,7 @@ begin: c->name); c->status.remove = true; retry_outgoing(c->outgoing); + c->outgoing = NULL; return; } @@ -382,9 +384,7 @@ begin: c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if(c->socket == -1) { - ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, - strerror(errno)); - + ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno)); goto begin; } @@ -406,18 +406,14 @@ begin: result = connect(c->socket, &c->address.sa, SALEN(c->address.sa)); if(result == -1) { - if(errno == EINPROGRESS -#if defined(WIN32) && !defined(O_NONBLOCK) - || WSAGetLastError() == WSAEWOULDBLOCK -#endif - ) { + if(sockinprogress(sockerrno)) { c->status.connecting = true; return; } closesocket(c->socket); - ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, strerror(errno)); + ifdebug(CONNECTIONS) logger(LOG_ERR, "%s: %s", c->hostname, sockstrerror(sockerrno)); goto begin; } @@ -431,6 +427,8 @@ void setup_outgoing_connection(outgoing_t *outgoing) { connection_t *c; node_t *n; + outgoing->event = NULL; + n = lookup_node(outgoing->name); if(n) @@ -480,8 +478,7 @@ bool handle_new_meta_connection(int sock) { fd = accept(sock, &sa.sa, &len); if(fd < 0) { - logger(LOG_ERR, "Accepting a new connection failed: %s", - strerror(errno)); + logger(LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno)); return false; } @@ -525,18 +522,7 @@ void try_outgoing_connections(void) { static config_t *cfg = NULL; char *name; outgoing_t *outgoing; - connection_t *c; - avl_node_t *node; - if(outgoing_list) { - for(node = connection_tree->head; node; node = node->next) { - c = node->data; - c->outgoing = NULL; - } - - list_delete_list(outgoing_list); - } - outgoing_list = list_alloc((list_action_t)free_outgoing); for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) { diff --git a/src/node.c b/src/node.c index c1f1219..b323dca 100644 --- a/src/node.c +++ b/src/node.c @@ -162,7 +162,7 @@ void dump_nodes(void) { 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 %lx status %04x nexthop %s via %s pmtu %d (min %d max %d)", + 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 ? n->outcipher->nid : 0, n->outdigest ? n->outdigest->type : 0, n->outmaclength, n->outcompression, n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-", diff --git a/src/node.h b/src/node.h index 619baa9..a621a0a 100644 --- a/src/node.h +++ b/src/node.h @@ -39,7 +39,7 @@ typedef struct node_status_t { typedef struct node_t { char *name; /* name of this node */ - long int options; /* options turned on for this node */ + uint32_t options; /* options turned on for this node */ sockaddr_t address; /* his real (internet) ip to send UDP packets to */ char *hostname; /* the hostname of its real ip */ diff --git a/src/process.c b/src/process.c index 01ebe49..6d0e499 100644 --- a/src/process.c +++ b/src/process.c @@ -103,13 +103,18 @@ bool install_service(void) { command, NULL, NULL, NULL, NULL, NULL); if(!service) { - logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(GetLastError())); - return false; + DWORD lasterror = GetLastError(); + logger(LOG_ERR, "Could not create %s service: %s", identname, winerror(lasterror)); + if(lasterror != ERROR_SERVICE_EXISTS) + return false; } - ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description); - - logger(LOG_INFO, "%s service installed", identname); + if(service) { + ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &description); + logger(LOG_INFO, "%s service installed", identname); + } else { + service = OpenService(manager, identname, SERVICE_ALL_ACCESS); + } if(!StartService(service, 0, NULL)) logger(LOG_WARNING, "Could not start %s service: %s", identname, winerror(GetLastError())); diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 24f591a..c2df4cd 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -455,7 +455,7 @@ bool send_ack(connection_t *c) { get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight); - return send_request(c, "%d %s %d %lx", ACK, myport, c->estimated_weight, c->options); + return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options); } static void send_everything(connection_t *c) { @@ -494,10 +494,10 @@ bool ack_h(connection_t *c) { char hisport[MAX_STRING_SIZE]; char *hisaddress, *dummy; int weight, mtu; - long int options; + uint32_t options; node_t *n; - if(sscanf(c->buffer, "%*d " MAX_STRING " %d %lx", hisport, &weight, &options) != 3) { + 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; diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 9d43922..300333b 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -41,7 +41,7 @@ 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 %lx %d", ADD_EDGE, rand(), + 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); free(address); @@ -58,10 +58,10 @@ bool add_edge_h(connection_t *c) { char to_address[MAX_STRING_SIZE]; char to_port[MAX_STRING_SIZE]; sockaddr_t address; - long int options; + uint32_t options; int weight; - if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d", + 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); diff --git a/src/protocol_subnet.c b/src/protocol_subnet.c index f7ce53b..ba75c89 100644 --- a/src/protocol_subnet.c +++ b/src/protocol_subnet.c @@ -45,7 +45,7 @@ bool add_subnet_h(connection_t *c) { char subnetstr[MAX_STRING_SIZE]; char name[MAX_STRING_SIZE]; node_t *owner; - subnet_t s = {0}, *new; + subnet_t s = {0}, *new, *old; 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, @@ -142,6 +142,11 @@ bool add_subnet_h(connection_t *c) { if(!tunnelserver) 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 = now; + return true; } diff --git a/src/route.c b/src/route.c index 2da781e..5c69671 100644 --- a/src/route.c +++ b/src/route.c @@ -117,6 +117,7 @@ static void learn_mac(mac_t *address) { subnet->type = SUBNET_MAC; subnet->expires = now + macexpire; subnet->net.mac.address = *address; + subnet->weight = 10; subnet_add(myself, subnet); /* And tell all other tinc daemons it's our MAC */ diff --git a/src/subnet.c b/src/subnet.c index ef4e59e..3d1168d 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -47,9 +47,15 @@ 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() { 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 */ @@ -324,15 +330,46 @@ subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) { } subnet_t *lookup_subnet_mac(const mac_t *address) { - subnet_t *p, subnet = {0}; + subnet_t *p, *r = NULL, subnet = {0}; + avl_node_t *n; + int i; + + // Check if this address is cached + + for(i = 0; i < 2; i++) { + if(!cache_mac_valid[i]) + continue; + if(!memcmp(address, &cache_mac_address[i], sizeof *address)) + return cache_mac_subnet[i]; + } + + // Search all subnets for a matching one subnet.type = SUBNET_MAC; subnet.net.mac.address = *address; subnet.owner = NULL; - p = avl_search(subnet_tree, &subnet); + for(n = subnet_tree->head; n; n = n->next) { + p = n->data; + + if(!p || p->type != subnet.type) + continue; - return p; + if(!memcmp(address, &p->net.mac.address, sizeof *address)) { + r = p; + if(p->owner->status.reachable) + break; + } + } + + // Cache the result + + 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) {