From: Guus Sliepen Date: Wed, 16 Sep 2009 17:55:47 +0000 (+0200) Subject: Merge branch 'master' into 1.1 X-Git-Tag: import-tinc-1.1~592 X-Git-Url: http://git.meshlink.io/?p=meshlink;a=commitdiff_plain;h=075e6828a7533e7daa790225f17aa6bb39703278;hp=9b129c07e273ae113f3c67a9feeee82e8146f3a1 Merge branch 'master' into 1.1 Conflicts: have.h lib/dropin.c lib/fake-getaddrinfo.c lib/pidfile.c src/Makefile.am src/bsd/device.c src/conf.c src/connection.c src/connection.h src/graph.c src/mingw/device.c src/net.c src/net_setup.c src/node.c src/protocol_key.c src/protocol_misc.c src/tincd.c --- diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..2ecad8df --- /dev/null +++ b/COPYING @@ -0,0 +1,289 @@ +Copyright (C) 1998-2009 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 +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. + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/THANKS b/THANKS index 2daa8f16..ed57da59 100644 --- a/THANKS +++ b/THANKS @@ -8,6 +8,7 @@ We would like to thank the following people for their contributions to tinc: * Cris van Pelt * Enrique Zanardi * Flynn Marquardt +* Grzegorz Dymarek * Hans Bayle * Ivo van Dong * James MacLean diff --git a/configure.in b/configure.in index 456b9b23..0561af8b 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ AC_DEFINE([__USE_BSD], 1, [Enable BSD extensions]) ALL_LINGUAS="nl" dnl Checks for programs. -AC_PROG_CC +AC_PROG_CC_C99 AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S @@ -72,6 +72,20 @@ case $host_os in ;; esac +AC_ARG_ENABLE(tunemu, + AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]), + [ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu]) + tunemu=true + ] +) + +AC_ARG_WITH(windows2000, + AS_HELP_STRING([--with-windows2000], [compile with support for Windows 2000. This disables support for tunneling over existing IPv6 networks.]), + [AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])] +) + +AM_CONDITIONAL(TUNEMU, test "$tunemu" = true) + AC_CACHE_SAVE if test -d /sw/include ; then @@ -134,7 +148,7 @@ AC_CHECK_FUNC(gethostbyname, [], [ AC_CHECK_LIB(nsl, gethostbyname) ]) -AC_CHECK_FUNCS([freeaddrinfo gai_strerror getaddrinfo getnameinfo inet_aton], +AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo], [], [], [#include "have.h"] ) diff --git a/have.h b/have.h index e0652a9d..43a9147a 100644 --- a/have.h +++ b/have.h @@ -31,6 +31,17 @@ #include #include +#ifdef HAVE_MINGW +#ifdef WITH_WINDOWS2000 +#define WINVER Windows2000 +#else +#define WINVER WindowsXP +#endif +#include +#include +#include +#endif + #ifdef HAVE_STDBOOL_H #include #endif @@ -164,13 +175,4 @@ #include #endif -#ifdef HAVE_MINGW -#include -#include -#endif - -#ifdef HAVE_LIBEVENT -#include -#endif - #endif /* __TINC_SYSTEM_H__ */ diff --git a/lib/dropin.c b/lib/dropin.c index 773fe488..4ad32378 100644 --- a/lib/dropin.c +++ b/lib/dropin.c @@ -124,25 +124,34 @@ char *get_current_dir_name(void) { #ifndef HAVE_ASPRINTF int asprintf(char **buf, const char *fmt, ...) { - int status; + int result; va_list ap; + va_start(ap, fmt); + result = vasprintf(buf, fmt, ap); + va_end(ap); + return result; +} + +int vasprintf(char **buf, const char *fmt, va_list ap) { + int status; + va_list aq; int len; len = 4096; *buf = xmalloc(len); - va_start(ap, fmt); - status = vsnprintf(*buf, len, fmt, ap); - va_end(ap); + va_copy(aq, ap); + status = vsnprintf(*buf, len, fmt, aq); + va_end(aq); if(status >= 0) *buf = xrealloc(*buf, status + 1); if(status > len - 1) { len = status; - va_start(ap, fmt); - status = vsnprintf(*buf, len, fmt, ap); - va_end(ap); + va_copy(aq, ap); + status = vsnprintf(*buf, len, fmt, aq); + va_end(aq); } return status; @@ -156,15 +165,3 @@ int gettimeofday(struct timeval *tv, void *tz) { return 0; } #endif - -#ifndef HAVE_RANDOM -#include - -long int random(void) { - long int x; - - RAND_pseudo_bytes((unsigned char *)&x, sizeof(x)); - - return x; -} -#endif diff --git a/lib/dropin.h b/lib/dropin.h index eabc4c4d..8c2e94a3 100644 --- a/lib/dropin.h +++ b/lib/dropin.h @@ -36,19 +36,11 @@ extern char *get_current_dir_name(void); #ifndef HAVE_ASPRINTF extern int asprintf(char **, const char *, ...); -#endif - -#ifndef HAVE_GETNAMEINFO -extern int getnameinfo(const struct sockaddr *sa, size_t salen, char *host, - size_t hostlen, char *serv, size_t servlen, int flags); +extern int vasprintf(char **, const char *, va_list ap); #endif #ifndef HAVE_GETTIMEOFDAY extern int gettimeofday(struct timeval *, void *); #endif -#ifndef HAVE_RANDOM -extern long int random(void); -#endif - #endif /* __DROPIN_H__ */ diff --git a/lib/fake-getaddrinfo.c b/lib/fake-getaddrinfo.c index 0c27025b..df3d3476 100644 --- a/lib/fake-getaddrinfo.c +++ b/lib/fake-getaddrinfo.c @@ -16,7 +16,8 @@ #include "fake-getaddrinfo.h" #include "xalloc.h" -#ifndef HAVE_GAI_STRERROR + +#if !HAVE_DECL_GAI_STRERROR char *gai_strerror(int ecode) { switch (ecode) { case EAI_NODATA: @@ -31,7 +32,7 @@ char *gai_strerror(int ecode) { } #endif /* !HAVE_GAI_STRERROR */ -#ifndef HAVE_FREEADDRINFO +#if !HAVE_DECL_FREEADDRINFO void freeaddrinfo(struct addrinfo *ai) { struct addrinfo *next; @@ -43,7 +44,7 @@ void freeaddrinfo(struct addrinfo *ai) { } #endif /* !HAVE_FREEADDRINFO */ -#ifndef HAVE_GETADDRINFO +#if !HAVE_DECL_GETADDRINFO static struct addrinfo *malloc_ai(uint16_t port, uint32_t addr) { struct addrinfo *ai; diff --git a/lib/fake-getaddrinfo.h b/lib/fake-getaddrinfo.h index d2b46f62..d31a89a1 100644 --- a/lib/fake-getaddrinfo.h +++ b/lib/fake-getaddrinfo.h @@ -33,16 +33,16 @@ struct addrinfo { }; #endif /* !HAVE_STRUCT_ADDRINFO */ -#ifndef HAVE_GETADDRINFO +#if !HAVE_DECL_GETADDRINFO int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res); #endif /* !HAVE_GETADDRINFO */ -#ifndef HAVE_GAI_STRERROR +#if !HAVE_DECL_GAI_STRERROR char *gai_strerror(int ecode); #endif /* !HAVE_GAI_STRERROR */ -#ifndef HAVE_FREEADDRINFO +#if !HAVE_DECL_FREEADDRINFO void freeaddrinfo(struct addrinfo *ai); #endif /* !HAVE_FREEADDRINFO */ diff --git a/lib/fake-getnameinfo.c b/lib/fake-getnameinfo.c index 05f0875a..1eba4925 100644 --- a/lib/fake-getnameinfo.c +++ b/lib/fake-getnameinfo.c @@ -14,7 +14,7 @@ #include "fake-getnameinfo.h" #include "fake-getaddrinfo.h" -#ifndef HAVE_GETNAMEINFO +#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) { struct sockaddr_in *sin = (struct sockaddr_in *)sa; diff --git a/lib/fake-getnameinfo.h b/lib/fake-getnameinfo.h index 0f0b4bcc..02ac77a1 100644 --- a/lib/fake-getnameinfo.h +++ b/lib/fake-getnameinfo.h @@ -3,7 +3,7 @@ #ifndef _FAKE_GETNAMEINFO_H #define _FAKE_GETNAMEINFO_H -#ifndef HAVE_GETNAMEINFO +#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); #endif /* !HAVE_GETNAMEINFO */ diff --git a/lib/utils.c b/lib/utils.c index beabfeaf..1d46630b 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -96,3 +96,10 @@ const char *winerror(int err) { } #endif +unsigned int bitfield_to_int(void *bitfield, size_t size) { + unsigned int value = 0; + if(size > sizeof value) + size = sizeof value; + memcpy(&value, bitfield, size); + return value; +} diff --git a/lib/utils.h b/lib/utils.h index 04c4ddbd..ce726482 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -43,4 +43,6 @@ extern const char *winerror(int); #define strerror(x) ((x)>0?strerror(x):winerror(GetLastError())) #endif +extern unsigned int bitfield_to_int(void *bitfield, size_t size); + #endif /* __TINC_UTILS_H__ */ diff --git a/lib/xalloc.h b/lib/xalloc.h index 7cb486a2..51f99bdf 100644 --- a/lib/xalloc.h +++ b/lib/xalloc.h @@ -24,3 +24,6 @@ void *xcalloc PARAMS ((size_t n, size_t s)); void *xrealloc PARAMS ((void *p, size_t n)) __attribute__ ((__malloc__)); char *xstrdup PARAMS ((const char *s)) __attribute__ ((__malloc__)); + +extern int xasprintf(char **strp, const char *fmt, ...); +extern int xvasprintf(char **strp, const char *fmt, va_list ap); diff --git a/lib/xmalloc.c b/lib/xmalloc.c index d02f41b9..51356e46 100644 --- a/lib/xmalloc.c +++ b/lib/xmalloc.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #if STDC_HEADERS # include @@ -138,3 +140,21 @@ xcalloc (n, s) } #endif /* NOT_USED */ + +int xasprintf(char **strp, const char *fmt, ...) { + int result; + va_list ap; + va_start(ap, fmt); + result = xvasprintf(strp, fmt, ap); + va_end(ap); + return result; +} + +int xvasprintf(char **strp, const char *fmt, va_list ap) { + int result = vasprintf(strp, fmt, ap); + if(result < 0) { + fprintf(stderr, "vasprintf() failed: %s\n", strerror(errno)); + exit(xalloc_exit_failure); + } + return result; +} diff --git a/src/Makefile.am b/src/Makefile.am index ed110e9f..db90897f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,10 @@ tincd_SOURCES = cipher.c conf.c connection.c control.c crypto.c digest.c edge.c tincctl_SOURCES = tincctl.c rsagen.c +if TUNEMU +tincd_SOURCES += bsd/tunemu.c +endif + nodist_tincd_SOURCES = device.c DEFAULT_INCLUDES = @@ -18,10 +22,14 @@ DEFAULT_INCLUDES = INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib noinst_HEADERS = cipher.h conf.h connection.h control.h crypto.h device.h digest.h edge.h graph.h logger.h meta.h net.h netutl.h node.h process.h \ - protocol.h route.h rsa.h rsagen.h subnet.h + protocol.h route.h rsa.h rsagen.h subnet.h bsd/tunemu.h LIBS = @LIBS@ @LIBGCRYPT_LIBS@ @LIBINTL@ +if TUNEMU +LIBS += -lpcap +endif + tincd_LDADD = \ $(top_builddir)/lib/libvpn.a diff --git a/src/bsd/device.c b/src/bsd/device.c index 1066858b..872ad92f 100644 --- a/src/bsd/device.c +++ b/src/bsd/device.c @@ -29,12 +29,19 @@ #include "utils.h" #include "xalloc.h" +#ifdef HAVE_TUNEMU +#include "bsd/tunemu.h" +#endif + #define DEFAULT_DEVICE "/dev/tun0" typedef enum device_type { DEVICE_TYPE_TUN, DEVICE_TYPE_TUNIFHEAD, DEVICE_TYPE_TAP, +#ifdef HAVE_TUNEMU + DEVICE_TYPE_TUNEMU, +#endif } device_type_t; int device_fd = -1; @@ -43,7 +50,9 @@ char *iface = NULL; static char *device_info = NULL; static int device_total_in = 0; static int device_total_out = 0; -#if defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) +#if defined(TUNEMU) +static device_type_t device_type = DEVICE_TYPE_TUNEMU; +#elif defined(HAVE_OPENBSD) || defined(HAVE_FREEBSD) static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD; #else static device_type_t device_type = DEVICE_TYPE_TUN; @@ -60,14 +69,13 @@ bool setup_device(void) { if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) iface = xstrdup(rindex(device, '/') ? rindex(device, '/') + 1 : device); - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { - logger(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return false; - } - if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { if(!strcasecmp(type, "tun")) /* use default */; +#ifdef HAVE_TUNEMU + else if(!strcasecmp(type, "tunemu")) + device_type = DEVICE_TYPE_TUNEMU; +#endif else if(!strcasecmp(type, "tunnohead")) device_type = DEVICE_TYPE_TUN; else if(!strcasecmp(type, "tunifhead")) @@ -83,6 +91,23 @@ bool setup_device(void) { device_type = DEVICE_TYPE_TAP; } + switch(device_type) { +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: { + char dynamic_name[256] = ""; + device_fd = tunemu_open(dynamic_name); + } + break; +#endif + default: + device_fd = open(device, O_RDWR | O_NONBLOCK); + } + + if(device_fd < 0) { + logger(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return false; + } + switch(device_type) { default: device_type = DEVICE_TYPE_TUN; @@ -129,6 +154,11 @@ bool setup_device(void) { overwrite_mac = true; device_info = _("Generic BSD tap device"); break; +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: + device_info = _("BSD tunemu device"); + break; +#endif } logger(LOG_INFO, _("%s is a %s"), device, device_info); @@ -139,7 +169,15 @@ bool setup_device(void) { void close_device(void) { cp(); - close(device_fd); + switch(device_type) { +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: + tunemu_close(device_fd); + break; +#endif + default: + close(device_fd); + } free(device); free(iface); @@ -152,7 +190,16 @@ bool read_packet(vpn_packet_t *packet) { switch(device_type) { case DEVICE_TYPE_TUN: - if((inlen = read(device_fd, packet->data + 14, MTU - 14)) <= 0) { +#ifdef HAVE_TUNEMU + case DEVICE_TYPE_TUNEMU: + if(device_type == DEVICE_TYPE_TUNEMU) + inlen = tunemu_read(device_fd, packet->data + 14, MTU - 14); + else +#else + inlen = read(device_fd, packet->data + 14, MTU - 14); +#endif + + if(inlen <= 0) { logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); return false; @@ -228,6 +275,7 @@ bool read_packet(vpn_packet_t *packet) { ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); + logger(LOG_INFO, "E:fd_read"); return true; } @@ -283,6 +331,16 @@ bool write_packet(vpn_packet_t *packet) { } break; +#ifdef HAVE_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; } diff --git a/src/bsd/tunemu.c b/src/bsd/tunemu.c new file mode 100644 index 00000000..f532b04f --- /dev/null +++ b/src/bsd/tunemu.c @@ -0,0 +1,386 @@ +/* + * tunemu - Tun device emulation for Darwin + * Copyright (C) 2009 Friedrich Schöller + * + * 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 . + * + */ + +#include "tunemu.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PPPPROTO_CTL 1 + +#define PPP_IP 0x21 +#define PPP_IPV6 0x57 + +#define SC_LOOP_TRAFFIC 0x00000200 + +#define PPPIOCNEWUNIT _IOWR('t', 62, int) +#define PPPIOCSFLAGS _IOW('t', 89, int) +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) +#define PPPIOCATTCHAN _IOW('t', 56, int) +#define PPPIOCGCHAN _IOR('t', 55, int) +#define PPPIOCCONNECT _IOW('t', 58, int) +#define PPPIOCGUNIT _IOR('t', 86, int) + +struct sockaddr_ppp +{ + u_int8_t ppp_len; + u_int8_t ppp_family; + u_int16_t ppp_proto; + u_int32_t ppp_cookie; +}; + +enum NPmode +{ + NPMODE_PASS, + NPMODE_DROP, + NPMODE_ERROR, + NPMODE_QUEUE +}; + +struct npioctl +{ + int protocol; + enum NPmode mode; +}; + +#define PPP_KEXT_PATH "/System/Library/Extensions/PPP.kext" + +#define ERROR_BUFFER_SIZE 1024 + +char tunemu_error[ERROR_BUFFER_SIZE]; + +static int pcap_use_count = 0; +static pcap_t *pcap = NULL; + +static int data_buffer_length = 0; +static char *data_buffer = NULL; + +static void tun_error(char *format, ...) +{ + va_list vl; + va_start(vl, format); + vsnprintf(tunemu_error, ERROR_BUFFER_SIZE, format, vl); + va_end(vl); +} + +static void tun_noerror() +{ + *tunemu_error = 0; +} + +static void closeall() +{ + int fd = getdtablesize(); + while (fd--) + close(fd); + + open("/dev/null", O_RDWR, 0); + dup(0); + dup(0); +} + +static int ppp_load_kext() +{ + int pid = fork(); + if (pid < 0) + { + tun_error("fork for ppp kext: %s", strerror(errno)); + return -1; + } + + if (pid == 0) + { + closeall(); + execle("/sbin/kextload", "kextload", PPP_KEXT_PATH, NULL, NULL); + exit(1); + } + + int status; + while (waitpid(pid, &status, 0) < 0) + { + if (errno == EINTR) + continue; + + tun_error("waitpid for ppp kext: %s", strerror(errno)); + return -1; + } + + if (WEXITSTATUS(status) != 0) + { + tun_error("could not load ppp kext \"%s\"", PPP_KEXT_PATH); + return -1; + } + + tun_noerror(); + return 0; +} + +static int ppp_new_instance() +{ + // create ppp socket + int ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL); + if (ppp_sockfd < 0) + { + if (ppp_load_kext() < 0) + return -1; + + ppp_sockfd = socket(PF_PPP, SOCK_RAW, PPPPROTO_CTL); + if (ppp_sockfd < 0) + { + tun_error("creating ppp socket: %s", strerror(errno)); + return -1; + } + } + + // connect to ppp procotol + struct sockaddr_ppp pppaddr; + pppaddr.ppp_len = sizeof(struct sockaddr_ppp); + pppaddr.ppp_family = AF_PPP; + pppaddr.ppp_proto = PPPPROTO_CTL; + pppaddr.ppp_cookie = 0; + if (connect(ppp_sockfd, (struct sockaddr *)&pppaddr, sizeof(struct sockaddr_ppp)) < 0) + { + tun_error("connecting ppp socket: %s", strerror(errno)); + close(ppp_sockfd); + return -1; + } + + tun_noerror(); + return ppp_sockfd; +} + +static int ppp_new_unit(int *unit_number) +{ + int fd = ppp_new_instance(); + if (fd < 0) + return -1; + + // create ppp unit + if (ioctl(fd, PPPIOCNEWUNIT, unit_number) < 0) + { + tun_error("creating ppp unit: %s", strerror(errno)); + close(fd); + return -1; + } + + tun_noerror(); + return fd; +} + +static int ppp_setup_unit(int unit_fd) +{ + // send traffic to program + int flags = SC_LOOP_TRAFFIC; + if (ioctl(unit_fd, PPPIOCSFLAGS, &flags) < 0) + { + tun_error("setting ppp loopback mode: %s", strerror(errno)); + return -1; + } + + // allow packets + struct npioctl npi; + npi.protocol = PPP_IP; + npi.mode = NPMODE_PASS; + if (ioctl(unit_fd, PPPIOCSNPMODE, &npi) < 0) + { + tun_error("starting ppp unit: %s", strerror(errno)); + return -1; + } + + tun_noerror(); + return 0; +} + +static int open_pcap() +{ + if (pcap != NULL) + { + pcap_use_count++; + return 0; + } + + char errbuf[PCAP_ERRBUF_SIZE]; + pcap = pcap_open_live("lo0", BUFSIZ, 0, 1, errbuf); + pcap_use_count = 1; + + if (pcap == NULL) + { + tun_error("opening pcap: %s", errbuf); + return -1; + } + + tun_noerror(); + return 0; +} + +static void close_pcap() +{ + if (pcap == NULL) + return; + + pcap_use_count--; + if (pcap_use_count == 0) + { + pcap_close(pcap); + pcap = NULL; + } +} + +static void allocate_data_buffer(int size) +{ + if (data_buffer_length < size) + { + free(data_buffer); + data_buffer_length = size; + data_buffer = malloc(data_buffer_length); + } +} + +static void make_device_name(tunemu_device device, int unit_number) +{ + snprintf(device, sizeof(tunemu_device), "ppp%d", unit_number); +} + +static int check_device_name(tunemu_device device) +{ + if (strlen(device) < 4) + return -1; + + int unit_number = atoi(device + 3); + if (unit_number < 0 || unit_number > 999) + return -1; + + tunemu_device compare; + make_device_name(compare, unit_number); + + if (strcmp(device, compare) != 0) + return -1; + + return 0; +} + +int tunemu_open(tunemu_device device) +{ + int ppp_unit_number = -1; + if (device[0] != 0) + { + if (check_device_name(device) < 0) + { + tun_error("invalid device name \"%s\"", device); + return -1; + } + + ppp_unit_number = atoi(device + 3); + } + + int ppp_unit_fd = ppp_new_unit(&ppp_unit_number); + if (ppp_unit_fd < 0) + return -1; + + if (ppp_setup_unit(ppp_unit_fd) < 0) + { + close(ppp_unit_fd); + return -1; + } + + if (open_pcap() < 0) + { + close(ppp_unit_fd); + return -1; + } + + make_device_name(device, ppp_unit_number); + + return ppp_unit_fd; +} + +int tunemu_close(int ppp_sockfd) +{ + int ret = close(ppp_sockfd); + + if (ret == 0) + close_pcap(); + + return ret; +} + +int tunemu_read(int ppp_sockfd, char *buffer, int length) +{ + allocate_data_buffer(length + 2); + + length = read(ppp_sockfd, data_buffer, length + 2); + if (length < 0) + { + tun_error("reading packet: %s", strerror(errno)); + return length; + } + tun_noerror(); + + length -= 2; + if (length < 0) + return 0; + + memcpy(buffer, data_buffer + 2, length); + + return length; +} + +int tunemu_write(int ppp_sockfd, char *buffer, int length) +{ + allocate_data_buffer(length + 4); + + data_buffer[0] = 0x02; + data_buffer[1] = 0x00; + data_buffer[2] = 0x00; + data_buffer[3] = 0x00; + + memcpy(data_buffer + 4, buffer, length); + + if (pcap == NULL) + { + tun_error("pcap not open"); + return -1; + } + + length = pcap_inject(pcap, data_buffer, length + 4); + if (length < 0) + { + tun_error("injecting packet: %s", pcap_geterr(pcap)); + return length; + } + tun_noerror(); + + length -= 4; + if (length < 0) + return 0; + + return length; +} diff --git a/src/bsd/tunemu.h b/src/bsd/tunemu.h new file mode 100644 index 00000000..42b1785b --- /dev/null +++ b/src/bsd/tunemu.h @@ -0,0 +1,32 @@ +/* + * tunemu - Tun device emulation for Darwin + * Copyright (C) 2009 Friedrich Schöller + * + * 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 . + * + */ + +#ifndef TUNEMU_H +#define TUNEMU_H + +typedef char tunemu_device[7]; + +extern char tunemu_error[]; + +int tunemu_open(tunemu_device dev); +int tunemu_close(int fd); +int tunemu_read(int fd, char *buffer, int length); +int tunemu_write(int fd, char *buffer, int length); + +#endif diff --git a/src/conf.c b/src/conf.c index 77942597..827da681 100644 --- a/src/conf.c +++ b/src/conf.c @@ -401,7 +401,7 @@ bool read_server_config() { cp(); - asprintf(&fname, "%s/tinc.conf", confbase); + xasprintf(&fname, "%s/tinc.conf", confbase); x = read_config_file(config_tree, fname); if(x == -1) { /* System error: complain */ diff --git a/src/connection.c b/src/connection.c index 230ec4ed..4a2ba4c0 100644 --- a/src/connection.c +++ b/src/connection.c @@ -37,7 +37,7 @@ splay_tree_t *connection_tree; /* Meta connections */ connection_t *broadcast; static int connection_compare(const connection_t *a, const connection_t *b) { - return (void *)a - (void *)b; + return a < b ? -1 : a == b ? 0 : 1; } void init_connections(void) { @@ -115,7 +115,7 @@ int dump_connections(struct evbuffer *out) { if(evbuffer_add_printf(out, _(" %s at %s options %lx socket %d status %04x\n"), c->name, c->hostname, c->options, c->socket, - c->status.value) == -1) + bitfield_to_int(&c->status, sizeof c->status)) == -1) return errno; } @@ -128,7 +128,7 @@ bool read_connection_config(connection_t *c) { cp(); - asprintf(&fname, "%s/hosts/%s", confbase, c->name); + xasprintf(&fname, "%s/hosts/%s", confbase, c->name); x = read_config_file(c->config_tree, fname); free(fname); diff --git a/src/connection.h b/src/connection.h index 08778bf3..e44af0b0 100644 --- a/src/connection.h +++ b/src/connection.h @@ -32,8 +32,7 @@ #define OPTION_TCPONLY 0x0002 #define OPTION_PMTU_DISCOVERY 0x0004 -typedef union connection_status_t { - struct { +typedef struct connection_status_t { int pinged:1; /* sent ping */ int active:1; /* 1 if active.. */ int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ @@ -44,8 +43,6 @@ typedef union connection_status_t { int decryptin:1; /* 1 if we have to decrypt incoming traffic */ int mst:1; /* 1 if this connection is part of a minimum spanning tree */ int unused:23; - }; - uint32_t value; } connection_status_t; #include "edge.h" diff --git a/src/graph.c b/src/graph.c index 4e060b7f..f2e546ee 100644 --- a/src/graph.c +++ b/src/graph.c @@ -57,6 +57,7 @@ #include "process.h" #include "subnet.h" #include "utils.h" +#include "xalloc.h" /* Implementation of Kruskal's algorithm. Running time: O(E) @@ -359,18 +360,20 @@ void check_reachability() { n->minmtu = 0; n->mtuprobes = 0; - asprintf(&envp[0], "NETNAME=%s", netname ? : ""); - asprintf(&envp[1], "DEVICE=%s", device ? : ""); - asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); - asprintf(&envp[3], "NODE=%s", n->name); + event_del(&n->mtuevent); + + xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[3], "NODE=%s", n->name); sockaddr2str(&n->address, &address, &port); - asprintf(&envp[4], "REMOTEADDRESS=%s", address); - asprintf(&envp[5], "REMOTEPORT=%s", port); + xasprintf(&envp[4], "REMOTEADDRESS=%s", address); + xasprintf(&envp[5], "REMOTEPORT=%s", port); envp[6] = NULL; execute_script(n->status.reachable ? "host-up" : "host-down", envp); - asprintf(&name, + xasprintf(&name, n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", n->name); execute_script(name, envp); diff --git a/src/meta.c b/src/meta.c index 82dde3a5..6054427c 100644 --- a/src/meta.c +++ b/src/meta.c @@ -35,6 +35,11 @@ bool send_meta(connection_t *c, const char *buffer, int length) { cp(); + if(!c) { + logger(LOG_ERR, _("send_meta() called with NULL pointer!")); + abort(); + } + ifdebug(META) logger(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length, c->name, c->hostname); diff --git a/src/mingw/device.c b/src/mingw/device.c index 915256f5..2334af39 100644 --- a/src/mingw/device.c +++ b/src/mingw/device.c @@ -34,7 +34,7 @@ #include "mingw/common.h" -int device_fd = 0; +int device_fd = -1; static HANDLE device_handle = INVALID_HANDLE_VALUE; char *device = NULL; char *iface = NULL; @@ -45,63 +45,24 @@ static int device_total_out = 0; extern char *myport; -static struct packetbuf { - uint8_t data[MTU]; - length_t len; -} *bufs; - -static int nbufs = 64; - static DWORD WINAPI tapreader(void *bla) { - int sock, err, status; - struct addrinfo *ai; - struct addrinfo hint = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - .ai_flags = 0, - }; - unsigned char bufno = 0; + int status; long len; OVERLAPPED overlapped; - - /* Open a socket to the parent process */ - - err = getaddrinfo(NULL, myport, &hint, &ai); - - if(err || !ai) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(errno)); - return -1; - } - - sock = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); - - if(sock < 0) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "socket", strerror(errno)); - freeaddrinfo(ai); - return -1; - } - - if(connect(sock, ai->ai_addr, ai->ai_addrlen)) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "connect", strerror(errno)); - freeaddrinfo(ai); - return -1; - } - - freeaddrinfo(ai); + vpn_packet_t packet; logger(LOG_DEBUG, _("Tap reader running")); /* Read from tap device and send to parent */ overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - + for(;;) { overlapped.Offset = 0; overlapped.OffsetHigh = 0; ResetEvent(overlapped.hEvent); - status = ReadFile(device_handle, bufs[bufno].data, MTU, &len, &overlapped); + status = ReadFile(device_handle, packet.data, MTU, &len, &overlapped); if(!status) { if(GetLastError() == ERROR_IO_PENDING) { @@ -115,11 +76,11 @@ static DWORD WINAPI tapreader(void *bla) { } } - bufs[bufno].len = len; - if(send(sock, &bufno, 1, 0) <= 0) - return -1; - if(++bufno >= nbufs) - bufno = 0; + EnterCriticalSection(&mutex); + packet.len = len; + packet.priority = 0; + route(myself, &packet); + LeaveCriticalSection(&mutex); } } @@ -239,44 +200,6 @@ bool setup_device(void) { overwrite_mac = 1; } - /* Set up ringbuffer */ - - get_config_int(lookup_config(config_tree, "RingBufferSize"), &nbufs); - if(nbufs <= 1) - nbufs = 1; - else if(nbufs > 256) - nbufs = 256; - - bufs = xmalloc_and_zero(nbufs * sizeof *bufs); - - /* Create a listening socket */ - - err = getaddrinfo(NULL, myport, &hint, &ai); - - if(err || !ai) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(errno)); - return false; - } - - sock = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); - - if(sock < 0) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "socket", strerror(errno)); - return false; - } - - if(bind(sock, ai->ai_addr, ai->ai_addrlen)) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "bind", strerror(errno)); - return false; - } - - freeaddrinfo(ai); - - if(listen(sock, 1)) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno)); - return false; - } - /* Start the tap reader */ thread = CreateThread(NULL, 0, tapreader, NULL, 0, NULL); @@ -286,15 +209,6 @@ bool setup_device(void) { return false; } - /* Wait for the tap reader to connect back to us */ - - if((device_fd = accept(sock, NULL, 0)) == -1) { - logger(LOG_ERR, _("System call `%s' failed: %s"), "accept", strerror(errno)); - return false; - } - - closesocket(sock); - /* Set media status for newer TAP-Win32 devices */ status = true; @@ -317,25 +231,7 @@ void close_device(void) { } bool read_packet(vpn_packet_t *packet) { - unsigned char bufno; - - cp(); - - if((recv(device_fd, &bufno, 1, 0)) <= 0) { - logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, - device, strerror(errno)); - return false; - } - - packet->len = bufs[bufno].len; - memcpy(packet->data, bufs[bufno].data, bufs[bufno].len); - - device_total_in += packet->len; - - ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, - device_info); - - return true; + return false; } bool write_packet(vpn_packet_t *packet) { diff --git a/src/net.h b/src/net.h index a28f4785..57e9d8db 100644 --- a/src/net.h +++ b/src/net.h @@ -149,6 +149,8 @@ extern int reload_configuration(void); #ifndef HAVE_MINGW #define closesocket(s) close(s) +#else +extern CRITICAL_SECTION mutex; #endif #endif /* __TINC_NET_H__ */ diff --git a/src/net_packet.c b/src/net_packet.c index 8bf41c39..77e29c0a 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -65,6 +65,11 @@ static void send_mtu_probe_handler(int fd, short events, void *data) { n->mtuprobes++; + if(!n->status.reachable) { + logger(LOG_DEBUG, _("Trying to send MTU probe to unreachable node %s (%s)"), n->name, n->hostname); + return; + } + if(n->mtuprobes >= 10 && !n->minmtu) { ifdebug(TRAFFIC) logger(LOG_INFO, _("No response to MTU probes from %s (%s)"), n->name, n->hostname); return; @@ -77,7 +82,7 @@ static void send_mtu_probe_handler(int fd, short events, void *data) { return; } - len = n->minmtu + 1 + random() % (n->maxmtu - n->minmtu); + len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); if(len < 64) len = 64; @@ -302,6 +307,11 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { cp(); + if(!n->status.reachable) { + ifdebug(TRAFFIC) logger(LOG_INFO, _("Trying to send UDP packet to unreachable node %s (%s)"), n->name, n->hostname); + return; + } + /* Make sure we have a valid key */ if(!n->status.validkey) { @@ -319,9 +329,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { return; } - if(n->options & OPTION_PMTU_DISCOVERY && !n->minmtu && (inpkt->data[12] | inpkt->data[13])) { + if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) { ifdebug(TRAFFIC) logger(LOG_INFO, - _("No minimum MTU established yet for %s (%s), forwarding via TCP"), + _("Packet for %s (%s) larger than minimum MTU, forwarding via TCP"), n->name, n->hostname); send_tcppacket(n->nexthop->connection, origpkt); @@ -510,7 +520,8 @@ void handle_incoming_vpn_data(int sock, short events, void *data) pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); if(pkt.len < 0) { - logger(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); + if(errno != EAGAIN && errno != EINTR) + logger(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); return; } diff --git a/src/net_setup.c b/src/net_setup.c index 224bdf61..623eb185 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -108,7 +108,7 @@ bool read_rsa_private_key() { /* Else, check for PrivateKeyFile statement and read it */ if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) - asprintf(&fname, "%s/rsa_key.priv", confbase); + xasprintf(&fname, "%s/rsa_key.priv", confbase); fp = fopen(fname, "r"); @@ -178,8 +178,8 @@ bool setup_myself(void) { myself->connection = new_connection(); init_configuration(&myself->connection->config_tree); - asprintf(&myself->hostname, _("MYSELF")); - asprintf(&myself->connection->hostname, _("MYSELF")); + xasprintf(&myself->hostname, _("MYSELF")); + xasprintf(&myself->connection->hostname, _("MYSELF")); myself->connection->options = 0; myself->connection->protocol_version = PROT_CURRENT; @@ -207,7 +207,7 @@ bool setup_myself(void) { return false; if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport)) - asprintf(&myport, "655"); + xasprintf(&myport, "655"); /* Read in all the subnets specified in the host configuration file */ @@ -256,9 +256,12 @@ bool setup_myself(void) { } else routing_mode = RMODE_ROUTER; - if(routing_mode == RMODE_ROUTER) - if(!get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice) || choice) - myself->options |= OPTION_PMTU_DISCOVERY; + // Enable PMTUDiscovery by default if we are in router mode. + + choice = routing_mode == RMODE_ROUTER; + get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice); + if(choice) + myself->options |= OPTION_PMTU_DISCOVERY; get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); @@ -297,7 +300,7 @@ bool setup_myself(void) { /* Generate packet encryption key */ if(!get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) - cipher = xstrdup("blowfish"); + cipher = xstrdup("aes256"); if(!cipher_open_by_name(&myself->incipher, cipher)) { logger(LOG_ERR, _("Unrecognized cipher type!")); @@ -312,7 +315,7 @@ bool setup_myself(void) { /* Check if we want to use message authentication codes... */ if(!get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest)) - digest = xstrdup("sha1"); + digest = xstrdup("sha256"); int maclength = 4; get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &maclength); @@ -362,10 +365,10 @@ bool setup_myself(void) { } /* Run tinc-up script to further initialize the tap interface */ - asprintf(&envp[0], "NETNAME=%s", netname ? : ""); - asprintf(&envp[1], "DEVICE=%s", device ? : ""); - asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); - asprintf(&envp[3], "NAME=%s", myself->name); + xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[3], "NAME=%s", myself->name); envp[4] = NULL; execute_script("tinc-up", envp); @@ -523,10 +526,10 @@ void close_network_connections(void) { close(listen_socket[i].udp); } - asprintf(&envp[0], "NETNAME=%s", netname ? : ""); - asprintf(&envp[1], "DEVICE=%s", device ? : ""); - asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); - asprintf(&envp[3], "NAME=%s", myself->name); + xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[3], "NAME=%s", myself->name); envp[4] = NULL; exit_requests(); diff --git a/src/net_socket.c b/src/net_socket.c index 2dfaa2f0..47a41684 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -362,7 +362,7 @@ begin: get_config_string(c->outgoing->cfg, &address); if(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) - asprintf(&port, "655"); + xasprintf(&port, "655"); c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); free(address); diff --git a/src/netutl.c b/src/netutl.c index 39cd7907..480b716b 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -124,7 +124,7 @@ char *sockaddr2hostname(const sockaddr_t *sa) { cp(); if(sa->sa.sa_family == AF_UNKNOWN) { - asprintf(&str, _("%s port %s"), sa->unknown.address, sa->unknown.port); + xasprintf(&str, _("%s port %s"), sa->unknown.address, sa->unknown.port); return str; } @@ -135,7 +135,7 @@ char *sockaddr2hostname(const sockaddr_t *sa) { gai_strerror(err)); } - asprintf(&str, _("%s port %s"), address, port); + xasprintf(&str, _("%s port %s"), address, port); return str; } diff --git a/src/node.c b/src/node.c index 6df236a1..ebd2c7c2 100644 --- a/src/node.c +++ b/src/node.c @@ -131,8 +131,8 @@ void node_del(node_t *n) { edge_del(e); } - splay_delete(node_tree, n); splay_delete(node_udp_tree, n); + splay_delete(node_tree, n); } node_t *lookup_node(char *name) { @@ -166,12 +166,12 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) if(sa) { n->address = *sa; n->hostname = sockaddr2hostname(&n->address); - splay_delete(node_udp_tree, n); splay_insert(node_udp_tree, n); logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname); } else { memset(&n->address, 0, sizeof n->address); - logger(LOG_DEBUG, "UDP address of %s cleared", n->name); + n->hostname = 0; + ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s cleared", n->name); } } @@ -186,7 +186,7 @@ int dump_nodes(struct evbuffer *out) { if(evbuffer_add_printf(out, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s distance %d pmtu %d (min %d max %d)\n"), n->name, n->hostname, cipher_get_nid(&n->outcipher), digest_get_nid(&n->outdigest), digest_length(&n->outdigest), n->outcompression, - n->options, *(uint32_t *)&n->status, n->nexthop ? n->nexthop->name : "-", + 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) == -1) return errno; } diff --git a/src/node.h b/src/node.h index 82294a7f..37ba073e 100644 --- a/src/node.h +++ b/src/node.h @@ -32,17 +32,14 @@ #include "list.h" #include "subnet.h" -typedef union node_status_t { - struct { - int unused_active:1; /* 1 if active (not used for nodes) */ - int validkey:1; /* 1 if we currently have a valid key for him */ - int waitingforkey:1; /* 1 if we already sent out a request */ - int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ - int reachable:1; /* 1 if this node is reachable in the graph */ - int indirect:1; /* 1 if this node is not directly reachable by us */ - int unused:26; - }; - uint32_t value; +typedef struct node_status_t { + int unused_active:1; /* 1 if active (not used for nodes) */ + int validkey:1; /* 1 if we currently have a valid key for him */ + int waitingforkey:1; /* 1 if we already sent out a request */ + int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ + int reachable:1; /* 1 if this node is reachable in the graph */ + int indirect:1; /* 1 if this node is not directly reachable by us */ + int unused:26; } node_status_t; typedef struct node_t { diff --git a/src/process.c b/src/process.c index 29cd486d..546570aa 100644 --- a/src/process.c +++ b/src/process.c @@ -261,28 +261,29 @@ bool detach(void) { bool execute_script(const char *name, char **envp) { #ifdef HAVE_SYSTEM int status, len; - struct stat s; char *scriptname, *p; int i; cp(); #ifndef HAVE_MINGW - len = asprintf(&scriptname, "\"%s/%s\"", confbase, name); + len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name); #else - len = asprintf(&scriptname, "\"%s/%s.bat\"", confbase, name); + len = xasprintf(&scriptname, "\"%s/%s.bat\"", confbase, name); #endif if(len < 0) return false; scriptname[len - 1] = '\0'; +#ifndef HAVE_TUNEMU /* First check if there is a script */ - if(stat(scriptname + 1, &s)) { + if(access(scriptname + 1, F_OK)) { free(scriptname); return true; } +#endif ifdebug(STATUS) logger(LOG_INFO, _("Executing script %s"), name); @@ -405,7 +406,7 @@ void setup_signals(void) { /* Set a default signal handler for every signal, errors will be ignored. */ - for(i = 0; i < NSIG; i++) { + for(i = 1; i < NSIG; i++) { if(!do_detach) act.sa_handler = SIG_DFL; else diff --git a/src/protocol.c b/src/protocol.c index 24ba88b9..50f6fe73 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -73,7 +73,7 @@ bool send_request(connection_t *c, const char *format, ...) { cp(); - /* Use vsnprintf instead of vasprintf: faster, no memory + /* Use vsnprintf instead of vxasprintf: faster, no memory fragmentation, cleanup is automatic, and there is a limit on the input buffer anyway */ diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 35776116..92d31dbd 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -44,7 +44,7 @@ bool send_add_edge(connection_t *c, const edge_t *e) { sockaddr2str(&e->address, &address, &port); - x = send_request(c, "%d %lx %s %s %s %s %lx %d", ADD_EDGE, random(), + x = send_request(c, "%d %x %s %s %s %s %lx %d", ADD_EDGE, rand(), e->from->name, e->to->name, address, port, e->options, e->weight); free(address); @@ -175,7 +175,7 @@ bool add_edge_h(connection_t *c, char *request) { bool send_del_edge(connection_t *c, const edge_t *e) { cp(); - return send_request(c, "%d %lx %s %s", DEL_EDGE, random(), + return send_request(c, "%d %x %s %s", DEL_EDGE, rand(), e->from->name, e->to->name); } diff --git a/src/protocol_key.c b/src/protocol_key.c index 2a0f2301..60e9d736 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -46,7 +46,7 @@ bool send_key_changed() { if(!mykeyused) return true; - return send_request(broadcast, "%d %lx %s", KEY_CHANGED, random(), myself->name); + return send_request(broadcast, "%d %x %s", KEY_CHANGED, rand(), myself->name); } bool key_changed_h(connection_t *c, char *request) { diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 02e38598..b8d2f67d 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -154,7 +154,7 @@ bool send_tcppacket(connection_t *c, 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->buffer->output->off / (double)maxoutbufsize - 1 > drand48()) + if(2.0 * c->buffer->output->off / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX) return true; if(!send_request(c, "%d %hd", PACKET, packet->len)) diff --git a/src/protocol_subnet.c b/src/protocol_subnet.c index e5927213..9c5b04c8 100644 --- a/src/protocol_subnet.c +++ b/src/protocol_subnet.c @@ -42,7 +42,7 @@ bool send_add_subnet(connection_t *c, const subnet_t *subnet) if(!net2str(netstr, sizeof netstr, subnet)) return false; - return send_request(c, "%d %lx %s %s", ADD_SUBNET, random(), subnet->owner->name, netstr); + return send_request(c, "%d %x %s %s", ADD_SUBNET, rand(), subnet->owner->name, netstr); } bool add_subnet_h(connection_t *c, char *request) @@ -161,7 +161,7 @@ bool send_del_subnet(connection_t *c, const subnet_t *s) if(!net2str(netstr, sizeof netstr, s)) return false; - return send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr); + return send_request(c, "%d %x %s %s", DEL_SUBNET, rand(), s->owner->name, netstr); } bool del_subnet_h(connection_t *c, char *request) diff --git a/src/route.c b/src/route.c index 8acabb1b..da37473c 100644 --- a/src/route.c +++ b/src/route.c @@ -97,6 +97,13 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) { } else return true; } + +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(int fd, short events, void *data) { @@ -175,40 +182,6 @@ static void learn_mac(mac_t *address) } } -static void route_mac(node_t *source, vpn_packet_t *packet) -{ - subnet_t *subnet; - mac_t dest; - - cp(); - - - /* Learn source address */ - - if(source == myself) { - mac_t src; - memcpy(&src, &packet->data[6], sizeof src); - learn_mac(&src); - } - - /* Lookup destination address */ - - memcpy(&dest, &packet->data[0], sizeof dest); - subnet = lookup_subnet_mac(&dest); - - if(!subnet) { - broadcast_packet(source, packet); - return; - } - - if(subnet->owner == source) { - ifdebug(TRAFFIC) logger(LOG_WARNING, _("Packet looping back to %s (%s)!"), source->name, source->hostname); - return; - } - - send_packet(subnet->owner, packet); -} - /* RFC 792 */ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t type, uint8_t code) @@ -225,6 +198,10 @@ static void route_ipv4_unreachable(node_t *source, vpn_packet_t *packet, uint8_t cp(); + /* Swap Ethernet source and destination addresses */ + + swap_mac_addresses(packet); + /* Copy headers from packet into properly aligned structs on the stack */ memcpy(&ip, packet->data + ether_size, ip_size); @@ -421,6 +398,10 @@ static void route_ipv6_unreachable(node_t *source, vpn_packet_t *packet, uint8_t cp(); + /* 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); @@ -758,6 +739,63 @@ static void route_arp(node_t *source, vpn_packet_t *packet) send_packet(source, packet); } +static void route_mac(node_t *source, vpn_packet_t *packet) +{ + subnet_t *subnet; + mac_t dest; + + cp(); + + + /* Learn source address */ + + if(source == myself) { + mac_t src; + memcpy(&src, &packet->data[6], sizeof src); + learn_mac(&src); + } + + /* Lookup destination address */ + + memcpy(&dest, &packet->data[0], sizeof dest); + subnet = lookup_subnet_mac(&dest); + + if(!subnet) { + broadcast_packet(source, packet); + return; + } + + if(subnet->owner == source) { + ifdebug(TRAFFIC) logger(LOG_WARNING, _("Packet looping back to %s (%s)!"), source->name, source->hostname); + return; + } + + // Handle packets larger than PMTU + + node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via; + + if(via && packet->len > via->mtu && via != myself) { + 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); + uint16_t type = packet->data[12] << 8 | packet->data[13]; + if(type == ETH_P_IP) { + if(packet->data[20] & 0x40) { + packet->len = via->mtu; + route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED); + } else { + fragment_ipv4_packet(via, packet); + } + return; + } else if(type == ETH_P_IPV6) { + packet->len = via->mtu; + route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0); + return; + } + } + + send_packet(subnet->owner, packet); +} + + void route(node_t *source, vpn_packet_t *packet) { cp(); @@ -768,9 +806,8 @@ void route(node_t *source, vpn_packet_t *packet) switch (routing_mode) { case RMODE_ROUTER: { - uint16_t type; + uint16_t type = packet->data[12] << 8 | packet->data[13]; - type = ntohs(*((uint16_t *)(&packet->data[12]))); switch (type) { case ETH_P_ARP: route_arp(source, packet); diff --git a/src/solaris/device.c b/src/solaris/device.c index 295a2f88..a258e34e 100644 --- a/src/solaris/device.c +++ b/src/solaris/device.c @@ -99,7 +99,7 @@ bool setup_device(void) { } if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) - asprintf(&iface, "tun%d", ppa); + xasprintf(&iface, "tun%d", ppa); device_info = _("Solaris tun device"); diff --git a/src/subnet.c b/src/subnet.c index 75fe31f8..057550ab 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -476,24 +476,23 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) void subnet_update(node_t *owner, subnet_t *subnet, bool up) { splay_node_t *node; int i; - char *envp[8]; - char netstr[MAXNETSTR + 7] = "SUBNET="; + char *envp[9] = {0}; + char netstr[MAXNETSTR]; char *name, *address, *port; + char empty[] = ""; + + // Prepare environment variables to be passed to the script - asprintf(&envp[0], "NETNAME=%s", netname ? : ""); - asprintf(&envp[1], "DEVICE=%s", device ? : ""); - asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); - asprintf(&envp[3], "NODE=%s", owner->name); + xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); + xasprintf(&envp[1], "DEVICE=%s", device ? : ""); + xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + xasprintf(&envp[3], "NODE=%s", owner->name); if(owner != myself) { sockaddr2str(&owner->address, &address, &port); - asprintf(&envp[4], "REMOTEADDRESS=%s", address); - asprintf(&envp[5], "REMOTEPORT=%s", port); - envp[6] = netstr; - envp[7] = NULL; - } else { - envp[4] = netstr; - envp[5] = NULL; + // 4 and 5 are reserved for SUBNET and WEIGHT + xasprintf(&envp[6], "REMOTEADDRESS=%s", address); + xasprintf(&envp[7], "REMOTEPORT=%s", port); } name = up ? "subnet-up" : "subnet-down"; @@ -501,22 +500,44 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) { if(!subnet) { for(node = owner->subnet_tree->head; node; node = node->next) { subnet = node->data; - if(!net2str(netstr + 7, sizeof netstr - 7, subnet)) + 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 + 7, '#'); + if(weight) + *weight++ = 0; + else + weight = empty; + + // Prepare the SUBNET and WEIGHT variables + if(envp[4]) + free(envp[4]); + if(envp[5]) + free(envp[5]); + xasprintf(&envp[4], "SUBNET=%s", netstr); + xasprintf(&envp[5], "WEIGHT=%s", weight); + execute_script(name, envp); } } else { - if(net2str(netstr + 7, sizeof netstr - 7, subnet)) + if(net2str(netstr + 7, sizeof netstr - 7, subnet)) { + // Strip the weight from the subnet, and put it in its own environment variable + char *weight = strchr(netstr + 7, '#'); + if(weight) + *weight++ = 0; + else + weight = empty; + + // Prepare the SUBNET and WEIGHT variables + xasprintf(&envp[4], "SUBNET=%s", netstr); + xasprintf(&envp[5], "WEIGHT=%s", weight); + execute_script(name, envp); + } } - for(i = 0; i < (owner != myself ? 6 : 4); i++) + for(i = 0; envp[i] && i < 9; i++) free(envp[i]); - - if(owner != myself) { - free(address); - free(port); - } } int dump_subnets(struct evbuffer *out) diff --git a/src/tincctl.c b/src/tincctl.c index 814800e8..92796b6b 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -440,7 +440,7 @@ int main(int argc, char *argv[], char *envp[]) { // First handle commands that don't involve connecting to a running tinc daemon. if(!strcasecmp(argv[optind], "generate-keys")) { - return !keygen(optind > argc ? atoi(argv[optind + 1]) : 1024); + return !keygen(optind > argc ? atoi(argv[optind + 1]) : 2048); } if(!strcasecmp(argv[optind], "start")) { diff --git a/src/tincd.c b/src/tincd.c index 76053a00..48f5faf8 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -102,6 +102,7 @@ static struct option const long_options[] = { #ifdef HAVE_MINGW static struct WSAData wsa_state; +CRITICAL_SECTION mutex; #endif static void usage(bool status) @@ -218,7 +219,7 @@ static void make_names(void) #endif if(netname) - asprintf(&identname, "tinc.%s", netname); + xasprintf(&identname, "tinc.%s", netname); else identname = xstrdup("tinc"); @@ -226,12 +227,12 @@ static void make_names(void) if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\tinc", 0, KEY_READ, &key)) { if(!RegQueryValueEx(key, NULL, 0, 0, installdir, &len)) { if(!logfilename) - asprintf(&logfilename, "%s/log/%s.log", identname); + xasprintf(&logfilename, "%s/log/%s.log", identname); if(!confbase) { if(netname) - asprintf(&confbase, "%s/%s", installdir, netname); + xasprintf(&confbase, "%s/%s", installdir, netname); else - asprintf(&confbase, "%s", installdir); + xasprintf(&confbase, "%s", installdir); } } RegCloseKey(key); @@ -241,19 +242,19 @@ static void make_names(void) #endif if(!controlsocketname) - asprintf(&controlsocketname, "%s/run/%s.control/socket", LOCALSTATEDIR, identname); + xasprintf(&controlsocketname, "%s/run/%s.control/socket", LOCALSTATEDIR, identname); if(!logfilename) - asprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname); + xasprintf(&logfilename, LOCALSTATEDIR "/log/%s.log", identname); if(netname) { if(!confbase) - asprintf(&confbase, CONFDIR "/tinc/%s", netname); + xasprintf(&confbase, CONFDIR "/tinc/%s", netname); else logger(LOG_INFO, _("Both netname and configuration directory given, using the latter...")); } else { if(!confbase) - asprintf(&confbase, CONFDIR "/tinc"); + xasprintf(&confbase, CONFDIR "/tinc"); } } @@ -314,7 +315,7 @@ static bool drop_privs() { } #ifdef HAVE_MINGW -# define setpriority(level) SetPriorityClass(GetCurrentProcess(), level); +# define setpriority(level) SetPriorityClass(GetCurrentProcess(), level) #else # define NORMAL_PRIORITY_CLASS 0 # define BELOW_NORMAL_PRIORITY_CLASS 10 @@ -393,6 +394,8 @@ int main(int argc, char **argv) int main2(int argc, char **argv) { + InitializeCriticalSection(&mutex); + EnterCriticalSection(&mutex); #endif if(!detach()) diff --git a/src/uml_socket/device.c b/src/uml_socket/device.c index 30194d9c..ec9dcb1e 100644 --- a/src/uml_socket/device.c +++ b/src/uml_socket/device.c @@ -70,7 +70,7 @@ bool setup_device(void) { cp(); if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - asprintf(&device, LOCALSTATEDIR "/run/%s.umlsocket", identname); + xasprintf(&device, LOCALSTATEDIR "/run/%s.umlsocket", identname); get_config_string(lookup_config(config_tree, "Interface"), &iface);