initial windows server port. Requires Windows 2000 Server or later.

- updated CMake build script
- builds with Microsoft C++ 19.1x. such builds require Windows 8.1 or later
  unless you have the .NET Server 2003-toolset (v141_xp)
- windows port requires a C++17 compiler since cpp17::filesystem is POSIX-only
- HAVE_CXX17_FILESYSTEM manual toggle in CMake. You must manually specify where
  std::[experimental::]filesystem is defined in LDFLAGS or CMAKE_x_LINKER_FLAGS.
- IPv6 support can be added at any time, and the windows sdk still has that
  inline getaddrinfo(3) if it can't find a suitable IPv6 stack.
- inline code for mingw-w64: there's a few bits and pieces still missing simply because
  mingw-w64 derives its windows sdk from wine and reactos, and then writing all the newer
  stuff into it by hand straight from the MSDN manpages.
- misc. C++11 stuff (nullptr and friends)
- Internal file handling code takes UTF-8 or plain 8-bit text, NTFS is UTF-16, so
  std::filesystem::path::c_str() is wchar_t. That's no good unless you first
  call std::filesystem::path::string().
- implemented getifaddrs(3) and if_nametoindex(3) on top of GetAdapters[Info|Addresses](2).
- updated readme with new info

BONUS: may implement Solaris/illumos IOCP someday...

-despair86
pull/7/head
despair86 6 years ago
parent 7622f6cef1
commit bdc54835c2

@ -13,21 +13,32 @@ endmacro(add_cxxflags)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if (WIN32 AND NOT MINGW)
CHECK_CXX_COMPILER_FLAG("/std:c++17" COMPILER_SUPPORTS_CXX17)
else()
CHECK_CXX_COMPILER_FLAG("-std=c++17" COMPILER_SUPPORTS_CXX17)
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
endif()
option(HAVE_CXX17_FILESYSTEM "Enable if your C++ compiler and runtime library implements std::[experimental::]filesystem" OFF)
if(COMPILER_SUPPORTS_CXX11 AND NOT HAVE_CXX17_FILESYSTEM)
add_cxxflags("-std=c++11")
elseif(COMPILER_SUPPORTS_CXX17)
elseif(COMPILER_SUPPORTS_CXX17 AND HAVE_CXX17_FILESYSTEM)
if (WIN32 AND NOT MINGW)
add_cxxflags("/std:c++17")
else()
add_cxxflags("-std=c++17")
endif()
add_definitions(-DUSE_CXX17_FILESYSTEM)
else()
message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 or C++17 support. Please use a different C++ compiler.")
endif()
# attempting to fix linux gcc 7.2 which COMPILER_SUPPORTS_CXX17 but doesn't have filesystem.h
include(CheckIncludeFileCXX)
CHECK_INCLUDE_FILE_CXX(filesystem.h HAVE_STD_FS)
if(ANDROID)
set(THREAD_LIB "-pthread")
# finally removed pthread dependency for MSC++
elseif(WIN32 AND NOT MINGW)
set(THREAD_LIB)
else()
set(THREAD_LIB pthread)
endif()
@ -44,11 +55,18 @@ else()
set(WITH_STATIC ON)
endif()
if (UNIX OR MINGW OR APPLE)
add_cflags("-Wall")
add_cxxflags("-Wall")
endif()
set(DEBUG_FLAGS "-g")
if (WIN32 AND NOT MINGW)
set(OPTIMIZE_FLAGS "-Od")
set(DEBUG_FLAGS "-ZI")
else()
set(OPTIMIZE_FLAGS "-O0")
set(DEBUG_FLAGS "-g")
endif()
if(ASAN)
set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
@ -69,14 +87,18 @@ if(SHADOW)
include(ShadowTools)
add_cxxflags("-fno-inline -fno-strict-aliasing")
add_cflags("-fno-inline -fno-strict-aliasing")
add_definitions(-DTESTNET=true)
add_definitions(-DSHADOW_TESTNET)
include_directories(${SHADOW_ROOT}/include)
endif()
if (WIN32 AND NOT MINGW)
add_cflags("-wd4996 -wd4244 -MP ${OPTIMIZE_FLAGS}")
add_cxxflags("-wd4996 -wd4244 -MP ${OPTIMIZE_FLAGS}")
else()
add_cflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
add_cxxflags("-Wall -Wno-deprecated-declarations ${OPTIMIZE_FLAGS}")
endif()
if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
add_cflags("${DEBUG_FLAGS}")
@ -116,14 +138,18 @@ endif()
set(LIBS ${SODIUM_LIB} ${THREAD_LIB})
set(LIB llarp)
set(LIB lokinet)
set(SHARED_LIB ${LIB})
set(STATIC_LIB ${LIB}-static)
set(TT_ROOT vendor/libtuntap-master)
add_definitions(-D${CMAKE_SYSTEM_NAME})
if (UNIX)
add_definitions(-DUNIX)
endif()
if(UNIX)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-linux.c)
@ -131,22 +157,26 @@ if(UNIX)
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-openbsd.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-netbsd.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" or ${CMAKE_SYSTEM_NAME} MATCHES "DragonFly")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-freebsd.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-darwin.c ${TT_ROOT}/tuntap-unix-bsd.c)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "DragonFly")
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-unix-freebsd.c ${TT_ROOT}/tuntap-unix-bsd.c)
else()
message(FATAL_ERROR "Your operating system is not supported yet")
endif()
elseif(WIN32 OR MINGW)
set(LIBTUNTAP_IMPL ${TT_ROOT}/tuntap-windows.c)
else()
message(FATAL_ERROR "What operating system _are_ you building on/for?")
endif(UNIX)
if(TUNTAP)
set(LIBTUNTAP_SRC
${TT_ROOT}/tuntap.c
${TT_ROOT}/tuntap_log.c
if (UNIX)
${TT_ROOT}/tuntap-unix.c
endif()
${LIBTUNTAP_IMPL})
else()
set(LIBTUNTAP_SRC "")
@ -198,6 +228,11 @@ set(LIB_PLATFORM_SRC
llarp/threadpool.cpp
# for android shim
${ANDROID_PLATFORM_SRC}
# win32 inline procs
llarp/win32_inet.c
llarp/win32_intrnl.c
contrib/msc/getopt.c
contrib/msc/getopt1.c
)
@ -303,12 +338,16 @@ set(STATIC_LIB ${LIB}-static)
# TODO: exclude this from includes and expose stuff properly for rcutil
include_directories(llarp)
include_directories(include)
include_directories(vendor/cppbackport-master/lib)
#include_directories(/usr/local/include)
include_directories(${sodium_INCLUDE_DIR})
if (WIN32 AND NOT MINGW)
include_directories(contrib/msc/include)
link_directories(contrib/msc/lib)
endif()
if(SHADOW)
add_shadow_plugin(shadow-plugin-${SHARED_LIB} ${EXE_SRC} ${LIB_SRC})
target_link_libraries(shadow-plugin-${SHARED_LIB} ${LIBS})
@ -330,62 +369,62 @@ else()
if(WITH_STATIC)
add_library(${STATIC_LIB} STATIC ${LIB_SRC})
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
if(NOT HAVE_CXX17_FILESYSTEM)
add_library(backport-static STATIC ${CPP_BACKPORT_SRC})
endif(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
endif(NOT HAVE_CXX17_FILESYSTEM)
add_library(llarpplatform-static STATIC ${LIB_PLATFORM_SRC})
target_link_libraries(llarpplatform-static ${THREAD_LIB})
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
if(NOT HAVE_CXX17_FILESYSTEM)
target_link_libraries(${STATIC_LIB} ${LIBS} backport-static llarpplatform-static)
else()
target_link_libraries(${STATIC_LIB} ${LIBS} llarpplatform-static)
endif(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
endif(NOT HAVE_CXX17_FILESYSTEM)
if(NOT WITH_SHARED)
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
if(NOT HAVE_CXX17_FILESYSTEM)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static)
if (MINGW)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} backport-static llarpplatform-static ws2_32 iphlpapi)
endif(MINGW)
else()
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static)
if (MINGW)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32)
target_link_libraries(${EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
target_link_libraries(${CLIENT_EXE} ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
target_link_libraries(rcutil ${STATIC_LINK_LIBS} ${STATIC_LIB} llarpplatform-static ws2_32 iphlpapi)
endif(MINGW)
endif(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
endif(NOT HAVE_CXX17_FILESYSTEM)
if (MINGW)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32 stdc++fs)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB} ws2_32 iphlpapi)
endif(MINGW)
target_link_libraries(dns ${STATIC_LIB} llarpplatform-static ${THREAD_LIB})
endif(NOT WITH_SHARED)
endif(WITH_STATIC)
if(WITH_SHARED)
if(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
if(HAVE_CXX17_FILESYSTEM)
set(LIB_SRC ${LIB_SRC} ${CPP_BACKPORT_SRC})
endif(COMPILER_SUPPORTS_CXX11 AND NOT COMPILER_SUPPORTS_CXX17 OR ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR NOT HAVE_STD_FS)
endif(HAVE_CXX17_FILESYSTEM)
add_library(${SHARED_LIB} SHARED ${LIB_SRC} ${LIB_PLATFORM_SRC})
if (MINGW)
set(${LIBS} ${LIBS} ws2_32 stdc++fs)
set(${LIBS} ${LIBS} ws2_32 stdc++fs iphlpapi)
elseif(WIN32)
set(${LIBS} ${LIBS} ws2_32)
set(${LIBS} ${LIBS} ws2_32 iphlpapi)
endif(MINGW)
target_link_libraries(${SHARED_LIB} ${LIBS} ${THREAD_LIB})
target_link_libraries(${EXE} ${SHARED_LIB})

File diff suppressed because it is too large Load Diff

@ -0,0 +1,190 @@
#ifdef _MSC_VER
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "getopt.h"
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */
#endif /* _MSC_VER */

@ -0,0 +1,157 @@
#ifdef _MSC_VER
/* Declarations for getopt.
Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
# if defined __STDC__ && __STDC__
const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
# ifndef __need_getopt
extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int __argc, char *const *__argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
# endif
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */
#endif /* _MSC_VER */

@ -1,7 +1,9 @@
#include <getopt.h>
#include <signal.h>
#include <stdio.h> /* fprintf, printf */
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <llarp.h>
#include <llarp/logic.h>
@ -13,6 +15,16 @@
#include <thread> // for multithreaded version
#include <vector>
// keep this once jeff reenables concurrency
#ifdef _MSC_VER
extern "C" void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName);
#endif
#ifdef _WIN32
#define uint UINT
#endif
#if(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__)
#include <pthread_np.h>
#endif
@ -122,6 +134,7 @@ main(int argc, char *argv[])
logic = llarp_init_single_process_logic(worker);
llarp_ev_loop_run_single_process(netloop, worker, logic);
llarp::LogInfo("singlethread end");
llarp_ev_loop_free(&netloop);
}
else
@ -150,7 +163,11 @@ main(int argc, char *argv[])
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000; // 1 sec
#ifndef _WIN32
if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
#else
if(setsockopt(m_sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) < 0)
#endif
{
perror("Error");
}

@ -3,6 +3,11 @@
#include <signal.h>
#include <string>
#ifdef _WIN32
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
#define MIN wmin
#endif
struct llarp_main *ctx = 0;
void

@ -1,8 +1,8 @@
#include <getopt.h>
#include <llarp.h>
#include <signal.h>
#include "logger.hpp"
#include <getopt.h>
#include <llarp/router_contact.h>
#include <llarp/time.h>
@ -278,14 +278,23 @@ main(int argc, char *argv[])
// "encryption.key")
fs::path encryption_keyfile = "encryption.key";
llarp::SecretKey encryption;
llarp_findOrCreateEncryption(&crypt, encryption_keyfile.c_str(),
#ifdef _WIN32
llarp_findOrCreateEncryption(&crypt, encryption_keyfile.string().c_str(),
&encryption);
#else
llarp_findOrCreateEncryption(&crypt, encryption_keyfile.c_str(),
&encryption);
#endif
llarp_rc_set_pubenckey(&tmp, llarp::seckey_topublic(encryption));
// get identity public sig key
fs::path ident_keyfile = "identity.key";
byte_t identity[SECKEYSIZE];
#ifdef _WIN32
llarp_findOrCreateIdentity(&crypt, ident_keyfile.string().c_str(), identity);
#else
llarp_findOrCreateIdentity(&crypt, ident_keyfile.c_str(), identity);
#endif
llarp_rc_set_pubsigkey(&tmp, llarp::seckey_topublic(identity));
// this causes a segfault
@ -293,7 +302,11 @@ main(int argc, char *argv[])
// set filename
fs::path our_rc_file = rcfname;
// write file
#ifdef _WIN32
llarp_rc_write(&tmp, our_rc_file.string().c_str());
#else
llarp_rc_write(&tmp, our_rc_file.c_str());
#endif
// release memory for tmp lists
llarp_rc_free(&tmp);
}
@ -311,7 +324,11 @@ main(int argc, char *argv[])
llarp_crypto_libsodium_init(&crypt);
fs::path ident_keyfile = "identity.key";
byte_t identity[SECKEYSIZE];
#ifdef _WIN32
llarp_findOrCreateIdentity(&crypt, ident_keyfile.string().c_str(), identity);
#else
llarp_findOrCreateIdentity(&crypt, ident_keyfile.c_str(), identity);
#endif
// get identity public key
uint8_t *pubkey = llarp::seckey_topublic(identity);
llarp_rc_set_pubsigkey(&rc, pubkey);
@ -320,7 +337,11 @@ main(int argc, char *argv[])
// set filename
fs::path our_rc_file_out = "update_debug.rc";
// write file
#ifdef _WIN32
llarp_rc_write(&tmp, our_rc_file_out.string().c_str());
#else
llarp_rc_write(&tmp, our_rc_file_out.c_str());
#endif
}
if(listMode)
{

@ -1,9 +1,13 @@
#ifndef LLARP_CODEL_QUEUE_HPP
#define LLARP_CODEL_QUEUE_HPP
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/time.h>
#include <llarp/logger.hpp>
#include <llarp/threading.hpp>
#include <algorithm>
#include <cmath>
#include <functional>

@ -5,6 +5,11 @@
#include <sys/types.h> // for uint & ssize_t
#include <map> // for udp DNS tracker
/* non-cygnus does not have this type */
#ifdef _WIN32
#define uint UINT
#endif
#ifdef __cplusplus
extern "C"
{

@ -6,15 +6,12 @@
#include <inttypes.h>
#include <string.h>
#if defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/endian.h>
#elif defined(__linux__) || defined(__FreeBSD_kernel__) \
|| defined(__OpenBSD__) || defined(__GLIBC__)
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GLIBC__)
#include <endian.h>
#elif defined(__APPLE__) && defined(__MACH__)
#include <libkern/OSByteOrder.h>
#define htobe16(x) OSSwapHostToBigInt16(x)
#define htole16(x) OSSwapHostToLittleInt16(x)
#define be16toh(x) OSSwapBigToHostInt16(x)
@ -29,7 +26,26 @@
#define htole64(x) OSSwapHostToLittleInt64(x)
#define be64toh(x) OSSwapBigToHostInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x)
#elif defined(_WIN32)
#include <winsock2.h>
#define htobe16(x) htons(x)
#define htole16(x) (x)
#define be16toh(x) ntohs(x)
#define le16toh(x) (x)
#define htobe32(x) htonl(x)
#define htole32(x) (x)
#define be32toh(x) ntohl(x)
#define le32toh(x) (x)
#define htobe64(x) \
(((uint64_t)htonl(((uint32_t)(((uint64_t)(x)) >> 32)))) \
| (((uint64_t)htonl(((uint32_t)(x)))) << 32))
#define htole64(x) (x)
#define be64toh(x) \
(((uint64_t)ntohl(((uint32_t)(((uint64_t)(x)) >> 32)))) \
| (((uint64_t)ntohl(((uint32_t)(x)))) << 32))
#define le64toh(x) (x)
#else
#define NEEDS_LOCAL_ENDIAN
#include <cstdint>

@ -1,8 +1,12 @@
#ifndef LLARP_EV_H
#define LLARP_EV_H
#if defined(__MINGW32__)
#if defined(__MINGW32__) || defined(_WIN32)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#ifndef ssize_t
#define ssize_t long
#endif
#else
#include <netinet/in.h>
#include <sys/socket.h>
@ -12,10 +16,10 @@
#include <stdlib.h>
/**
* ev.h
*
* event handler (cross platform high performance event system for IO)
*/
* ev.h
*
* event handler (cross platform high performance event system for IO)
*/
// forward declare
struct llarp_threadpool;

@ -1,6 +1,5 @@
#ifndef LLARP_LOGGER_HPP
#define LLARP_LOGGER_HPP
#include <llarp/time.h>
#include <ctime>
#include <iomanip>
@ -8,6 +7,11 @@
#include <llarp/threading.hpp>
#include <sstream>
#include <string>
#ifdef _WIN32
#define VC_EXTRALEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
namespace llarp
{
@ -28,6 +32,14 @@ namespace llarp
std::mutex access;
Logger() : Logger(std::cout, "unnamed")
{
#ifdef _WIN32
DWORD mode_flags;
HANDLE fd1 = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(fd1, &mode_flags);
// since release SDKs don't have ANSI escape support yet
mode_flags |= 0x0004;
SetConsoleMode(fd1, mode_flags);
#endif
}
Logger(std::ostream& o, const std::string& name) : nodeName(name), out(o)
@ -108,7 +120,6 @@ namespace llarp
_Log(llarp::eLogWarn, LOG_TAG, __LINE__, x, ##__VA_ARGS__)
#define LogError(x, ...) \
_Log(llarp::eLogError, LOG_TAG, __LINE__, x, ##__VA_ARGS__)
#define LogDebugTag(tag, x, ...) \
_Log(llarp::eLogDebug, tag, __LINE__, x, ##__VA_ARGS__)
#define LogInfoTag(tag, x, ...) \
@ -121,5 +132,4 @@ namespace llarp
#ifndef LOG_TAG
#define LOG_TAG "default"
#endif
#endif

@ -1,8 +1,27 @@
#ifndef LLARP_NET_H
#define LLARP_NET_H
#if defined(__MINGW32__)
#if defined(_WIN32) || defined(__MINGW32__)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
// because this shit is not defined for Windows NT reeeee
#ifndef _MSC_VER
#ifdef __cplusplus
extern "C" {
#endif
const char*
inet_ntop(int af, const void* src, char* dst, size_t size);
int
inet_pton(int af, const char* src, void* dst);
#ifdef __cplusplus
}
#endif
#endif
#ifndef ssize_t
#define ssize_t long
#endif
typedef unsigned short in_port_t;
typedef unsigned int in_addr_t;
#else
#include <arpa/inet.h>
#include <netinet/in.h>

@ -121,7 +121,11 @@ namespace llarp
sz = sizeof(sockaddr_in);
ptr = a.addr4();
}
#ifndef _MSC_VER
if(inet_ntop(a.af(), ptr, tmp, sz))
#else
if(inet_ntop(a.af(), (void*)ptr, tmp,sz))
#endif
{
out << tmp;
if(a.af() == AF_INET6)
@ -148,22 +152,22 @@ namespace llarp
switch(af())
{
case AF_INET:
dst = (void*)&((sockaddr_in*)other)->sin_addr.s_addr;
src = (void*)&_addr.sin6_addr.s6_addr[12];
ptr = &((sockaddr_in*)other)->sin_port;
dst = (void*)&((sockaddr_in*)other)->sin_addr.s_addr;
src = (void*)&_addr.sin6_addr.s6_addr[12];
ptr = &((sockaddr_in*)other)->sin_port;
slen = sizeof(in_addr);
break;
case AF_INET6:
dst = (void*)((sockaddr_in6*)other)->sin6_addr.s6_addr;
src = (void*)_addr.sin6_addr.s6_addr;
ptr = &((sockaddr_in6*)other)->sin6_port;
dst = (void*)((sockaddr_in6*)other)->sin6_addr.s6_addr;
src = (void*)_addr.sin6_addr.s6_addr;
ptr = &((sockaddr_in6*)other)->sin6_port;
slen = sizeof(in6_addr);
break;
default:
return;
}
memcpy(dst, src, slen);
*ptr = htons(port());
*ptr = htons(port());
other->sa_family = af();
}
@ -216,7 +220,7 @@ namespace llarp
isPrivate()
{
in_addr_t addr = this->addr4()->s_addr;
unsigned byte = ntohl(addr);
unsigned byte = ntohl(addr);
unsigned byte1 = byte >> 24 & 0xff;
unsigned byte2 = (0x00ff0000 & byte >> 16);
return (byte1 == 10 || (byte1 == 192 && byte2 == 168)

@ -1,7 +1,7 @@
#ifndef LLARP_THREADING_HPP
#define LLARP_THREADING_HPP
#include <mutex>
#if defined(__MINGW32__)
#if defined(__MINGW32__) && !defined(_GLIBCXX_HAS_GTHREADS)
#include <llarp/win32/threads/mingw.condition_variable.h>
#include <llarp/win32/threads/mingw.mutex.h>
#include <llarp/win32/threads/mingw.thread.h>

@ -1,5 +1,7 @@
#include "address_info.hpp"
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include <llarp/bencode.h>
#include <llarp/mem.h>
#include <llarp/string.h>
@ -120,8 +122,12 @@ llarp_ai_list_iter_bencode(struct llarp_ai_list_iter *iter, struct llarp_ai *ai)
bool
llarp_ai_bdecode(struct llarp_ai *ai, llarp_buffer_t *buff)
{
#ifndef _MSC_VER
struct dict_reader reader = {
.buffer = nullptr, .user = ai, .on_key = &llarp_ai_decode_key};
#else
struct dict_reader reader = { nullptr, ai, &llarp_ai_decode_key };
#endif
return bencode_read_dict(buff, &reader);
}
@ -174,8 +180,13 @@ llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
if(!bencode_start_list(buff))
return false;
#ifndef _MSC_VER
struct llarp_ai_list_iter ai_itr = {
.user = buff, .list = nullptr, .visit = &llarp_ai_list_iter_bencode};
#else
struct llarp_ai_list_iter ai_itr = {buff, nullptr,
&llarp_ai_list_iter_bencode};
#endif
llarp_ai_list_iterate(l, &ai_itr);
return bencode_end(buff);
}
@ -255,7 +266,12 @@ llarp_ai_list_index(struct llarp_ai_list *l, ssize_t idx, struct llarp_ai *dst)
bool
llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff)
{
#ifndef _MSC_VER
struct list_reader r = {
.buffer = nullptr, .user = l, .on_item = &llarp_ai_list_bdecode_item};
#else
struct list_reader r = {
nullptr, l, &llarp_ai_list_bdecode_item};
#endif
return bencode_read_list(buff, &r);
}

@ -3,6 +3,9 @@
#include <stdarg.h>
#include <stdio.h>
#ifndef ssize_t
#define ssize_t long
#endif
size_t
llarp_buffer_size_left(llarp_buffer_t buff)
{

@ -2,7 +2,9 @@
#include <llarp.h>
#include <llarp/logger.h>
#include <signal.h>
#ifndef _MSC_VER
#include <sys/param.h> // for MIN
#endif
#include <llarp.hpp>
#include "logger.hpp"
#include "math.h"
@ -12,6 +14,16 @@
#include <pthread_np.h>
#endif
// keep this once jeff reenables concurrency
#ifdef _MSC_VER
extern "C" void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName);
#endif
#ifdef _WIN32
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
#define MIN wmin
#endif
namespace llarp
{
@ -188,6 +200,7 @@ namespace llarp
}
else
{
llarp::LogInfo("running mainloop");
return llarp_ev_loop_run(mainloop, logic);
}
@ -202,11 +215,14 @@ namespace llarp
llarp::LogInfo("SIGINT");
SigINT();
}
// TODO(despair): implement hot-reloading config on NT
#ifndef _WIN32
if(sig == SIGHUP)
{
llarp::LogInfo("SIGHUP");
ReloadConfig();
}
#endif
}
void
@ -289,194 +305,194 @@ extern "C"
struct llarp_main *
llarp_main_init(const char *fname, bool multiProcess)
{
if(!fname)
fname = "daemon.ini";
char *var = getenv("LLARP_DEBUG");
if(var && *var == '1')
{
cSetLogLevel(eLogDebug);
}
llarp_main *m = new llarp_main;
m->ctx.reset(new llarp::Context());
m->ctx->singleThreaded = !multiProcess;
if(!m->ctx->LoadConfig(fname))
{
m->ctx->Close();
delete m;
return nullptr;
}
return m;
if(!fname)
fname = "daemon.ini";
char *var = getenv("LLARP_DEBUG");
if(var && *var == '1')
{
cSetLogLevel(eLogDebug);
}
llarp_main *m = new llarp_main;
m->ctx.reset(new llarp::Context());
m->ctx->singleThreaded = !multiProcess;
if(!m->ctx->LoadConfig(fname))
{
m->ctx->Close();
delete m;
return nullptr;
}
return m;
}
void
llarp_main_signal(struct llarp_main *ptr, int sig)
{
ptr->ctx->HandleSignal(sig);
ptr->ctx->HandleSignal(sig);
}
int
llarp_main_setup(struct llarp_main *ptr)
{
return ptr->ctx->Setup();
return ptr->ctx->Setup();
}
int
llarp_main_run(struct llarp_main *ptr)
{
return ptr->ctx->Run();
return ptr->ctx->Run();
}
void
llarp_main_abort(struct llarp_main *ptr)
{
llarp_logic_stop_timer(ptr->ctx->router->logic);
llarp_logic_stop_timer(ptr->ctx->router->logic);
}
int
llarp_main_loadDatabase(struct llarp_main *ptr)
{
return ptr->ctx->LoadDatabase();
return ptr->ctx->LoadDatabase();
}
int
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i)
{
return ptr->ctx->IterateDatabase(i);
return ptr->ctx->IterateDatabase(i);
}
bool
llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc)
{
return ptr->ctx->PutDatabase(rc);
return ptr->ctx->PutDatabase(rc);
}
struct llarp_rc *
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk)
{
return ptr->ctx->GetDatabase(pk);
return ptr->ctx->GetDatabase(pk);
}
struct llarp_rc *
llarp_main_getLocalRC(struct llarp_main *ptr)
{
//
/*
llarp_config_iterator iter;
iter.user = this;
iter.visit = &iter_config;
llarp_config_iter(ctx->config, &iter);
*/
llarp_rc *rc = new llarp_rc;
llarp_rc_new(rc);
llarp::LogInfo("Loading ", ptr->ctx->conatctFile);
if(llarp_rc_read(ptr->ctx->conatctFile, rc))
return rc;
else
return nullptr;
//
/*
llarp_config_iterator iter;
iter.user = this;
iter.visit = &iter_config;
llarp_config_iter(ctx->config, &iter);
*/
llarp_rc *rc = new llarp_rc;
llarp_rc_new(rc);
llarp::LogInfo("Loading ", ptr->ctx->conatctFile);
if(llarp_rc_read(ptr->ctx->conatctFile, rc))
return rc;
else
return nullptr;
}
void
llarp_main_checkOnline(void *u, uint64_t orig, uint64_t left)
{
// llarp::LogInfo("checkOnline - check ", left);
if(left)
return;
struct check_online_request *request =
static_cast< struct check_online_request * >(u);
// llarp::LogDebug("checkOnline - running");
// llarp::LogInfo("checkOnline - DHT nodes ",
// request->ptr->ctx->router->dht->impl.nodes->nodes.size());
request->online = false;
request->nodes = request->ptr->ctx->router->dht->impl.nodes->nodes.size();
if(request->ptr->ctx->router->dht->impl.nodes->nodes.size())
{
// llarp::LogInfo("checkOnline - Going to say we're online");
request->online = true;
}
request->hook(request);
// reschedue our self
llarp_main_queryDHT(request);
// llarp::LogInfo("checkOnline - check ", left);
if(left)
return;
struct check_online_request *request =
static_cast< struct check_online_request * >(u);
// llarp::LogDebug("checkOnline - running");
// llarp::LogInfo("checkOnline - DHT nodes ",
// request->ptr->ctx->router->dht->impl.nodes->nodes.size());
request->online = false;
request->nodes = request->ptr->ctx->router->dht->impl.nodes->nodes.size();
if(request->ptr->ctx->router->dht->impl.nodes->nodes.size())
{
// llarp::LogInfo("checkOnline - Going to say we're online");
request->online = true;
}
request->hook(request);
// reschedue our self
llarp_main_queryDHT(request);
}
void
llarp_main_queryDHT_online(struct check_online_request *request)
{
// Info("llarp_main_queryDHT_online: ", request->online ? "online" :
// "offline");
if(request->online && !request->first)
{
request->first = true;
llarp::LogInfo("llarp_main_queryDHT_online - We're online");
llarp::LogInfo("llarp_main_queryDHT_online - Querying DHT");
llarp_dht_lookup_router(request->ptr->ctx->router->dht, request->job);
}
// Info("llarp_main_queryDHT_online: ", request->online ? "online" :
// "offline");
if(request->online && !request->first)
{
request->first = true;
llarp::LogInfo("llarp_main_queryDHT_online - We're online");
llarp::LogInfo("llarp_main_queryDHT_online - Querying DHT");
llarp_dht_lookup_router(request->ptr->ctx->router->dht, request->job);
}
}
void
llarp_main_queryDHT(struct check_online_request *request)
{
// llarp::LogInfo("llarp_main_queryDHT - setting up timer");
request->hook = &llarp_main_queryDHT_online;
llarp_logic_call_later(request->ptr->ctx->router->logic,
{1000, request, &llarp_main_checkOnline});
// llarp_dht_lookup_router(ptr->ctx->router->dht, job);
// llarp::LogInfo("llarp_main_queryDHT - setting up timer");
request->hook = &llarp_main_queryDHT_online;
llarp_logic_call_later(request->ptr->ctx->router->logic,
{1000, request, &llarp_main_checkOnline});
// llarp_dht_lookup_router(ptr->ctx->router->dht, job);
}
void
llarp_main_free(struct llarp_main *ptr)
{
delete ptr;
delete ptr;
}
const char *
handleBaseCmdLineArgs(int argc, char *argv[])
{
const char *conffname = "daemon.ini";
int c;
while(1)
const char *conffname = "daemon.ini";
int c;
while(1)
{
static struct option long_options[] = {
{"config", required_argument, 0, 'c'},
{"logLevel", required_argument, 0, 'o'},
{0, 0, 0, 0}};
int option_index = 0;
c = getopt_long(argc, argv, "c:o:", long_options, &option_index);
if(c == -1)
break;
switch(c)
{
static struct option long_options[] = {
{"config", required_argument, 0, 'c'},
{"logLevel", required_argument, 0, 'o'},
{0, 0, 0, 0}};
int option_index = 0;
c = getopt_long(argc, argv, "c:o:", long_options, &option_index);
if(c == -1)
case 0:
break;
switch(c)
{
case 0:
break;
case 'c':
conffname = optarg;
break;
case 'o':
case 'c':
conffname = optarg;
break;
case 'o':
if(strncmp(optarg, "debug", MIN(strlen(optarg), (unsigned long)5))
== 0)
{
cSetLogLevel(eLogDebug);
}
else if(strncmp(optarg, "info", MIN(strlen(optarg), (unsigned long)4))
== 0)
{
cSetLogLevel(eLogInfo);
}
else if(strncmp(optarg, "warn", MIN(strlen(optarg), (unsigned long)4))
== 0)
{
cSetLogLevel(eLogWarn);
}
{
cSetLogLevel(eLogDebug);
}
else if(strncmp(optarg, "info", MIN(strlen(optarg), (unsigned long)4))
== 0)
{
cSetLogLevel(eLogInfo);
}
else if(strncmp(optarg, "warn", MIN(strlen(optarg), (unsigned long)4))
== 0)
{
cSetLogLevel(eLogWarn);
}
else if(strncmp(optarg, "error",
MIN(strlen(optarg), (unsigned long)5))
== 0)
{
cSetLogLevel(eLogError);
}
break;
default:
break;
}
== 0)
{
cSetLogLevel(eLogError);
}
break;
default:
break;
}
return conffname;
}
return conffname;
}
}

@ -26,7 +26,7 @@ namespace llarp
if(crypto_scalarmult_curve25519(shared, usSec, themPub))
return false;
crypto_generichash_init(&h, NULL, 0U, outsz);
crypto_generichash_init(&h, nullptr, 0U, outsz);
crypto_generichash_update(&h, client_pk, 32);
crypto_generichash_update(&h, server_pk, 32);
crypto_generichash_update(&h, shared, 32);

@ -2,6 +2,10 @@
#include "dnsd.hpp" // for llarp_handle_dnsd_recvfrom, dnsc
#include "logger.hpp"
#ifdef _WIN32
#define uint UINT
#endif
extern "C"
{
uint16_t

@ -2,15 +2,19 @@
#include <llarp/dns.h>
#include "buffer.hpp"
#include <netdb.h> /* getaddrinfo, getnameinfo */
#ifndef _WIN32
#include <arpa/inet.h>
#include <netdb.h> /* getaddrinfo, getnameinfo */
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include <stdlib.h> /* exit */
#include <string.h> /* memset */
#include <sys/socket.h>
#include <sys/types.h>
#ifndef _MSC_VER
#include <unistd.h> /* close */
#include <arpa/inet.h>
#include <netinet/in.h>
#endif
#include <cstdio>
@ -75,7 +79,7 @@ build_dns_packet(char *url, uint16_t id, uint16_t reqType)
{
dnsQuery->request[dnsQuery->length++] = word[i];
}
word = strtok(NULL, ".");
word = strtok(nullptr, ".");
}
dnsQuery->request[dnsQuery->length++] = 0x00; // End of the host name
@ -130,7 +134,7 @@ raw_resolve_host(const char *url)
{
dnsQuery.request[dnsQuery.length++] = word[i];
}
word = strtok(NULL, ".");
word = strtok(nullptr, ".");
}
dnsQuery.request[dnsQuery.length++] = 0x00; // End of the host name
@ -162,7 +166,11 @@ raw_resolve_host(const char *url)
// uint16_t RDLENGTH; // The length of the RDATA field
// uint16_t MSGID;
#ifndef _WIN32
int sockfd;
#else
SOCKET sockfd;
#endif
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0)
@ -179,8 +187,13 @@ raw_resolve_host(const char *url)
size = sizeof(addr);
// hexdump("sending packet", &dnsQuery.request, dnsQuery.length);
#ifdef _WIN32
ret = sendto(sockfd, (const char *)dns_packet->request, dns_packet->length, 0,
(struct sockaddr *)&addr, size);
#else
ret = sendto(sockfd, dns_packet->request, dns_packet->length, 0,
(struct sockaddr *)&addr, size);
#endif
delete dns_packet;
if(ret < 0)
{
@ -190,8 +203,13 @@ raw_resolve_host(const char *url)
// llarp::LogInfo("Sent\n");
memset(&buffer, 0, DNC_BUF_SIZE);
ret = recvfrom(sockfd, buffer, DNC_BUF_SIZE, 0, (struct sockaddr *)&addr,
&size);
#ifdef _WIN32
ret = recvfrom(sockfd, (char *)buffer, DNC_BUF_SIZE, 0,
(struct sockaddr *)&addr, &size);
#else
ret = recvfrom(sockfd, buffer, DNC_BUF_SIZE, 0,
(struct sockaddr *)&addr, &size);
#endif
if(ret < 0)
{
llarp::LogWarn("Error Receiving Response");
@ -200,7 +218,11 @@ raw_resolve_host(const char *url)
// hexdump("received packet", &buffer, ret);
#ifndef _WIN32
close(sockfd);
#else
closesocket(sockfd);
#endif
rcode = (buffer[3] & 0x0F);
@ -210,7 +232,7 @@ raw_resolve_host(const char *url)
// printf("%0x %0x %0x %0x\n", buffer[4], buffer[5], tempBuf[0], tempBuf[1]);
// QDCOUNT = (uint16_t) strtol(tempBuf, NULL, 16);
// QDCOUNT = (uint16_t) strtol(tempBuf, nullptr, 16);
QDCOUNT = (uint16_t)buffer[4] * 0x100 + buffer[5];
llarp::LogDebug("entries in question section: %u\n", QDCOUNT);
ANCOUNT = (uint16_t)buffer[6] * 0x100 + buffer[7];

@ -5,6 +5,11 @@
#include "llarp/net.hpp"
#include "logger.hpp"
#ifdef _WIN32
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
#define MIN wmin
#endif
dns_tracker dns_udp_tracker;
ssize_t
@ -14,7 +19,11 @@ raw_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
int *fd = (int *)sock;
// how do we get to these??
socklen_t addrLen = sizeof(struct sockaddr_in);
#ifdef _WIN32
return sendto(*fd, (const char *)buffer, length, 0, from, addrLen);
#else
return sendto(*fd, buffer, length, 0, from, addrLen);
#endif
}
ssize_t

@ -5,11 +5,11 @@
#ifdef __linux__
#include "ev_epoll.hpp"
#endif
#if(__APPLE__ && __MACH__)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || (__APPLE__ && __MACH__)
#include "ev_kqueue.hpp"
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include "ev_kqueue.hpp"
#if defined(_WIN32) || defined(_WIN64) || defined(__NT__)
#include "ev_win32.hpp"
#endif
void
@ -18,11 +18,17 @@ llarp_ev_loop_alloc(struct llarp_ev_loop **ev)
#ifdef __linux__
*ev = new llarp_epoll_loop;
#endif
#if(__APPLE__ && __MACH__)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || (__APPLE__ && __MACH__)
*ev = new llarp_kqueue_loop;
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
*ev = new llarp_kqueue_loop;
#if defined(_WIN32) || defined(_WIN64) || defined(__NT__)
*ev = new llarp_win32_loop;
#endif
// a) I assume that the libre fork of Solaris is still
// 5.10, and b) the current commercial version is 5.11, naturally.
// -despair86
#if defined(__SunOS_5_10) || defined(__SunOS_5_11)
*ev = new llarp_sun_iocp_loop;
#endif
(*ev)->init();
}

@ -2,15 +2,22 @@
#define LLARP_EV_HPP
#include <llarp/ev.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <list>
namespace llarp
{
struct ev_io
{
#ifndef _WIN32
int fd;
ev_io(int f) : fd(f){};
#else
SOCKET fd;
ev_io(SOCKET f) : fd(f){};
#endif
virtual int
read(void* buf, size_t sz) = 0;
@ -18,7 +25,11 @@ namespace llarp
sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
virtual ~ev_io()
{
#ifndef _WIN32
::close(fd);
#else
closesocket(fd);
#endif
};
};
}; // namespace llarp

@ -3,13 +3,7 @@
#include <llarp/buffer.h>
#include <llarp/net.h>
#if __FreeBSD__ || __OpenBSD__ || __NetBSD__
// kqueue / kevent
#include <sys/event.h>
#include <sys/time.h>
#endif
#if(__APPLE__ && __MACH__)
#if __FreeBSD__ || __OpenBSD__ || __NetBSD__ || (__APPLE && __MACH__)
// kqueue / kevent
#include <sys/event.h>
#include <sys/time.h>
@ -111,7 +105,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
struct kevent events[1024];
int result;
byte_t readbuf[2048];
result = kevent(kqueuefd, NULL, 0, events, 1024, NULL);
result = kevent(kqueuefd, nullptr, 0, events, 1024, nullptr);
// result: 0 is a timeout
if(result > 0)
{
@ -145,7 +139,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
byte_t readbuf[2048];
do
{
result = kevent(kqueuefd, NULL, 0, events, 1024, NULL);
result = kevent(kqueuefd, nullptr, 0, events, 1024, nullptr);
// result: 0 is a timeout
if(result > 0)
{
@ -241,9 +235,8 @@ struct llarp_kqueue_loop : public llarp_ev_loop
bool
close_ev(llarp::ev_io* ev)
{
// printf("closing_ev [%x] fd[%d]\n", ev, ev->fd);
EV_SET(&change, ev->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
return kevent(kqueuefd, &change, 1, NULL, 0, NULL) == -1;
EV_SET(&change, ev->fd, EVFILT_READ, EV_DELETE, 0, 0, nullptr);
return kevent(kqueuefd, &change, 1, nullptr, 0, nullptr) == -1;
}
bool
@ -255,7 +248,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
llarp::udp_listener* listener = new llarp::udp_listener(fd, l);
EV_SET(&change, fd, EVFILT_READ, EV_ADD, 0, 0, listener);
if(kevent(kqueuefd, &change, 1, NULL, 0, NULL) == -1)
if(kevent(kqueuefd, &change, 1, nullptr, 0, nullptr) == -1)
{
l->impl = nullptr;
delete listener;

@ -0,0 +1,214 @@
#ifndef EV_WIN32_HPP
#define EV_WIN32_HPP
#include <llarp/buffer.h>
#include <llarp/net.h>
#include <windows.h>
#include <cstdio>
#include "ev.hpp"
#include "logger.hpp"
#include <llarp/net.hpp>
namespace llarp
{
struct udp_listener : public ev_io
{
llarp_udp_io* udp;
// we receive queued data in the OVERLAPPED data field,
// much like the pipefds in the UNIX kqueue and loonix
// epoll handles
// 0 is the read port, 1 is the write port
WSAOVERLAPPED portfds[2] = {0};
udp_listener(SOCKET fd, llarp_udp_io* u) : ev_io(fd), udp(u){};
~udp_listener()
{
}
virtual int
read(void* buf, size_t sz)
{
sockaddr_in6 src;
socklen_t slen = sizeof(sockaddr_in6);
sockaddr* addr = (sockaddr*)&src;
WSABUF wbuf = {sz, static_cast< char* >(buf)};
// WSARecvFrom
int ret =
::WSARecvFrom(fd, &wbuf, sz, nullptr, 0, addr, &slen, &portfds[0], nullptr);
if(ret == -1)
return -1;
udp->recvfrom(udp, addr, buf, ret);
return 0;
}
virtual int
sendto(const sockaddr* to, const void* data, size_t sz)
{
socklen_t slen;
WSABUF wbuf = {sz, (char*)data};
switch(to->sa_family)
{
case AF_INET:
slen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
slen = sizeof(struct sockaddr_in6);
break;
default:
return -1;
}
// WSASendTo
ssize_t sent =
::WSASendTo(fd, &wbuf, sz, nullptr, 0, to, slen, &portfds[1], nullptr);
if(sent == -1)
{
llarp::LogWarn(strerror(errno));
}
return sent;
}
};
}; // namespace llarp
struct llarp_win32_loop : public llarp_ev_loop
{
HANDLE iocpfd;
llarp_win32_loop() : iocpfd(INVALID_HANDLE_VALUE)
{
WSADATA wsockd;
int err;
// So, what I was told last time was that we can defer
// loading winsock2 up to this point, as we reach this ctor
// early on during daemon startup.
err = ::WSAStartup(MAKEWORD(2, 2), &wsockd);
if(err)
perror("Failed to start Windows Sockets");
}
~llarp_win32_loop()
{
if(iocpfd != INVALID_HANDLE_VALUE)
::CloseHandle(iocpfd);
::WSACleanup();
}
bool
init()
{
if(iocpfd == INVALID_HANDLE_VALUE)
iocpfd = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
if(iocpfd != INVALID_HANDLE_VALUE)
return true; // we don't have a socket to attach to this IOCP yet
return false;
}
int
tick(int ms)
{
return 0;
}
int
run()
{
return 0;
}
SOCKET
udp_bind(const sockaddr* addr)
{
socklen_t slen;
switch(addr->sa_family)
{
case AF_INET:
slen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
slen = sizeof(struct sockaddr_in6);
break;
default:
return INVALID_SOCKET;
}
SOCKET fd = ::WSASocket(addr->sa_family, SOCK_DGRAM, 0, nullptr, 0,
WSA_FLAG_OVERLAPPED);
if(fd == INVALID_SOCKET)
{
perror("WSASocket()");
return -1;
}
if(addr->sa_family == AF_INET6)
{
// enable dual stack explicitly
int dual = 1;
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&dual, sizeof(dual))== -1)
{
// failed
perror("setsockopt()");
closesocket(fd);
return INVALID_SOCKET;
}
}
llarp::Addr a(*addr);
llarp::LogDebug("bind to ", a);
if(bind(fd, addr, slen) == -1)
{
perror("bind()");
closesocket(fd);
return INVALID_SOCKET;
}
return fd;
}
bool
close_ev(llarp::ev_io* ev)
{
// On Windows, just close the socket to decrease the iocp refcount
return closesocket(ev->fd) == 0;
}
bool
udp_listen(llarp_udp_io* l, const sockaddr* src)
{
SOCKET fd = udp_bind(src);
if(fd == INVALID_SOCKET)
return false;
llarp::udp_listener* listener = new llarp::udp_listener(fd, l);
if(!::CreateIoCompletionPort(reinterpret_cast< HANDLE >(fd), iocpfd, 0, 0))
{
delete listener;
return false;
}
l->impl = listener;
udp_listeners.push_back(l);
return true;
}
bool
udp_close(llarp_udp_io* l)
{
bool ret = false;
llarp::udp_listener* listener =
static_cast< llarp::udp_listener* >(l->impl);
if(listener)
{
ret = close_ev(listener);
l->impl = nullptr;
delete listener;
udp_listeners.remove(l);
}
return ret;
}
void
stop()
{
// do nothing, we dispose of the IOCP in destructor
}
};
#endif

@ -1,4 +1,7 @@
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include <llarp/bencode.h>
#include <llarp/exit_info.h>
#include <llarp/mem.h>

@ -1,4 +1,7 @@
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#include <llarp/bencode.h>
#include <llarp/exit_route.h>
#include <llarp/string.h>

@ -8,15 +8,20 @@
#endif
#include "filesystem.h"
// mingw32 in the only one that doesn't use cpp17::filesystem
#if defined(__MINGW32__)
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
// win32 is the only one that doesn't use cpp17::filesystem
// because cpp17::filesystem is unimplemented for Windows
// -despair86
#if defined(__MINGW32__) || defined(_MSC_VER)
namespace fs = std::experimental::filesystem;
#else
namespace fs = std::filesystem;
#endif // end win32
#else
// not CPP17 needs this
// openbsd needs this
// linux gcc 7.2 needs this
namespace fs = cpp17::filesystem;
#endif // end mingw32
#endif
#endif // end LLARP_FS_HPP

@ -40,7 +40,7 @@ namespace ini
{
struct Level
{
Level() : parent(NULL), depth(0)
Level() : parent(nullptr), depth(0)
{
}
Level(Level *p) : parent(p), depth(0)
@ -156,7 +156,7 @@ namespace ini
Parser::err(const char *s)
{
char buf[256];
sprintf(buf, "%s on line #%ld", s, ln_);
sprintf(buf, "%s on line #%d", s, ln_);
throw std::runtime_error(buf);
}
@ -210,8 +210,7 @@ namespace ini
size_t depth;
std::string sname;
parseSLine(sname, depth);
Level *lp = NULL;
Level *lp = nullptr;
Level *parent = &l;
if(depth > l.depth + 1)
err("section with wrong depth");

@ -1,3 +1,7 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include "llarp/iwp/frame_state.hpp"
#include "buffer.hpp"
#include "llarp/crypto.hpp"
@ -7,6 +11,7 @@
#include "llarp/logger.hpp"
#include "mem.hpp"
#include "router.hpp"
#include <algorithm>
llarp_router *
frame_state::Router()

@ -1,3 +1,6 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/iwp.h>
#include <llarp/crypto.hpp>
#include <llarp/iwp/server.hpp>
@ -6,6 +9,7 @@
#include "buffer.hpp"
#include "link/encoder.hpp"
#include "llarp/ev.h" // for handle_frame_encrypt
#include <algorithm>
static void
handle_crypto_outbound(void *u)

@ -28,7 +28,7 @@ namespace llarp
DumpBuffer(const T &buff)
{
size_t idx = 0;
printf("buffer of size %ld\n", buff.sz);
printf("buffer of size %u\n", buff.sz);
while(idx < buff.sz)
{
if(buff.base + idx == buff.cur)

@ -2,13 +2,12 @@
#include "str.hpp"
#ifdef ANDROID
#include "android/ifaddrs.h"
#else
#include <ifaddrs.h>
#endif
#ifndef _WIN32
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#endif
#include <cstdio>
#include "logger.hpp"
@ -42,6 +41,692 @@ operator<(const in6_addr& a, const in6_addr& b)
return memcmp(&a, &b, sizeof(in6_addr)) < 0;
}
#ifdef _WIN32
#include <assert.h>
#include <errno.h>
#include <strsafe.h>
#include <iphlpapi.h>
// current strategy: mingw 32-bit builds call an inlined version of the function
// microsoft c++ and mingw 64-bit builds call the normal function
#define DEFAULT_BUFFER_SIZE 15000
// the inline monkey patch for downlevel platforms
#ifndef _MSC_VER
extern "C" DWORD FAR PASCAL
_GetAdaptersAddresses(ULONG Family, ULONG Flags, PVOID Reserved,
PIP_ADAPTER_ADDRESSES pAdapterAddresses,
PULONG pOutBufLen);
#endif
// in any case, we still need to implement some form of
// getifaddrs(3) with compatible semantics on NT...
// daemon.ini section [bind] will have something like
// [bind]
// Ethernet=1090
// inside, since that's what we use in windows to refer to
// network interfaces
struct llarp_nt_ifaddrs_t
{
struct llarp_nt_ifaddrs_t* ifa_next; /* Pointer to the next structure. */
char* ifa_name; /* Name of this network interface. */
unsigned int ifa_flags; /* Flags as from SIOCGIFFLAGS ioctl. */
struct sockaddr* ifa_addr; /* Network address of this interface. */
struct sockaddr* ifa_netmask; /* Netmask of this interface. */
};
// internal struct
struct _llarp_nt_ifaddrs_t
{
struct llarp_nt_ifaddrs_t _ifa;
char _name[256];
struct sockaddr_storage _addr;
struct sockaddr_storage _netmask;
};
static inline void*
_llarp_nt_heap_alloc(const size_t n_bytes)
{
/* Does not appear very safe with re-entrant calls on XP */
return HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, n_bytes);
}
static inline void
_llarp_nt_heap_free(void* mem)
{
HeapFree(GetProcessHeap(), 0, mem);
}
#define llarp_nt_new0(struct_type, n_structs) \
((struct_type*)malloc((size_t)sizeof(struct_type) * (size_t)(n_structs)))
int
llarp_nt_sockaddr_pton(const char* src, struct sockaddr* dst)
{
struct addrinfo hints = {0}, *result = nullptr;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_NUMERICHOST;
const int status = getaddrinfo(src, nullptr, &hints, &result);
if(!status)
{
memcpy(dst, result->ai_addr, result->ai_addrlen);
freeaddrinfo(result);
return 1;
}
return 0;
}
/* NB: IP_ADAPTER_INFO size varies size due to sizeof (time_t), the API assumes
* 4-byte datatype whilst compiler uses an 8-byte datatype. Size can be forced
* with -D_USE_32BIT_TIME_T with side effects to everything else.
*
* Only supports IPv4 addressing similar to SIOCGIFCONF socket option.
*
* Interfaces that are not "operationally up" will return the address 0.0.0.0,
* this includes adapters with static IP addresses but with disconnected cable.
* This is documented under the GetIpAddrTable API. Interface status can only
* be determined by the address, a separate flag is introduced with the
* GetAdapterAddresses API.
*
* The IPv4 loopback interface is not included.
*
* Available in Windows 2000 and Wine 1.0.
*/
static bool
_llarp_nt_getadaptersinfo(struct llarp_nt_ifaddrs_t** ifap)
{
DWORD dwRet;
ULONG ulOutBufLen = DEFAULT_BUFFER_SIZE;
PIP_ADAPTER_INFO pAdapterInfo = nullptr;
PIP_ADAPTER_INFO pAdapter = nullptr;
/* loop to handle interfaces coming online causing a buffer overflow
* between first call to list buffer length and second call to enumerate.
*/
for(unsigned i = 3; i; i--)
{
#ifdef DEBUG
fprintf(stderr, "IP_ADAPTER_INFO buffer length %lu bytes.\n", ulOutBufLen);
#endif
pAdapterInfo = (IP_ADAPTER_INFO*)_llarp_nt_heap_alloc(ulOutBufLen);
dwRet = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
if(ERROR_BUFFER_OVERFLOW == dwRet)
{
_llarp_nt_heap_free(pAdapterInfo);
pAdapterInfo = nullptr;
}
else
{
break;
}
}
switch(dwRet)
{
case ERROR_SUCCESS: /* NO_ERROR */
break;
case ERROR_BUFFER_OVERFLOW:
errno = ENOBUFS;
if(pAdapterInfo)
_llarp_nt_heap_free(pAdapterInfo);
return false;
default:
errno = dwRet;
#ifdef DEBUG
fprintf(stderr, "system call failed: %lu\n", GetLastError());
#endif
if(pAdapterInfo)
_llarp_nt_heap_free(pAdapterInfo);
return false;
}
/* count valid adapters */
int n = 0, k = 0;
for(pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next)
{
for(IP_ADDR_STRING* pIPAddr = &pAdapter->IpAddressList; pIPAddr;
pIPAddr = pIPAddr->Next)
{
/* skip null adapters */
if(strlen(pIPAddr->IpAddress.String) == 0)
continue;
++n;
}
}
#ifdef DEBUG
fprintf(stderr, "GetAdaptersInfo() discovered %d interfaces.\n", n);
#endif
/* contiguous block for adapter list */
struct _llarp_nt_ifaddrs_t* ifa =
llarp_nt_new0(struct _llarp_nt_ifaddrs_t, n);
struct _llarp_nt_ifaddrs_t* ift = ifa;
/* now populate list */
for(pAdapter = pAdapterInfo; pAdapter; pAdapter = pAdapter->Next)
{
for(IP_ADDR_STRING* pIPAddr = &pAdapter->IpAddressList; pIPAddr;
pIPAddr = pIPAddr->Next)
{
/* skip null adapters */
if(strlen(pIPAddr->IpAddress.String) == 0)
continue;
/* address */
ift->_ifa.ifa_addr = (struct sockaddr*)&ift->_addr;
assert(1 == llarp_nt_sockaddr_pton(pIPAddr->IpAddress.String,ift->_ifa.ifa_addr));
/* name */
#ifdef DEBUG
fprintf(stderr, "name:%s IPv4 index:%lu\n", pAdapter->AdapterName,
pAdapter->Index);
#endif
ift->_ifa.ifa_name = ift->_name;
StringCchCopyN(ift->_ifa.ifa_name, 128, pAdapter->AdapterName, 128);
/* flags: assume up, broadcast and multicast */
ift->_ifa.ifa_flags = IFF_UP | IFF_BROADCAST | IFF_MULTICAST;
if(pAdapter->Type == MIB_IF_TYPE_LOOPBACK)
ift->_ifa.ifa_flags |= IFF_LOOPBACK;
/* netmask */
ift->_ifa.ifa_netmask = (sockaddr*)&ift->_netmask;
assert(1 == llarp_nt_sockaddr_pton(pIPAddr->IpMask.String, ift->_ifa.ifa_netmask));
/* next */
if(k++ < (n - 1))
{
ift->_ifa.ifa_next = (struct llarp_nt_ifaddrs_t*)(ift + 1);
ift = (struct _llarp_nt_ifaddrs_t*)(ift->_ifa.ifa_next);
}
}
}
if(pAdapterInfo)
_llarp_nt_heap_free(pAdapterInfo);
*ifap = (struct llarp_nt_ifaddrs_t*)ifa;
return true;
}
/* Supports both IPv4 and IPv6 addressing. The size of IP_ADAPTER_ADDRESSES
* changes between Windows XP, XP SP1, and Vista with additional members.
*
* Interfaces that are not "operationally up" will typically return a host
* IP address with the defined IPv4 link-local prefix 169.254.0.0/16.
* Adapters with a static configured IP address but down will return both
* the IPv4 link-local prefix and the static address.
*
* It is easier to say "not up" rather than "down" as this API returns six
* effective down status values: down, testing, unknown, dormant, not present,
* and lower layer down.
*
* Available in Windows XP and Wine 1.3.
*
* NOTE(despair): an inline implementation is provided, much like
* getaddrinfo(3) for old hosts. See "win32_intrnl.*"
*/
#ifdef _MSC_VER
static bool
_llarp_nt_getadaptersaddresses(struct llarp_nt_ifaddrs_t** ifap)
{
DWORD dwSize = DEFAULT_BUFFER_SIZE, dwRet;
IP_ADAPTER_ADDRESSES *pAdapterAddresses = nullptr, *adapter;
/* loop to handle interfaces coming online causing a buffer overflow
* between first call to list buffer length and second call to enumerate.
*/
for(unsigned i = 3; i; i--)
{
#ifdef DEBUG
fprintf(stderr, "IP_ADAPTER_ADDRESSES buffer length %lu bytes.\n", dwSize);
#endif
pAdapterAddresses = (IP_ADAPTER_ADDRESSES*)_llarp_nt_heap_alloc(dwSize);
#if defined(_MSC_VER) || defined(_WIN64)
dwRet = GetAdaptersAddresses(AF_UNSPEC,
/* requires Windows XP SP1 */
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_DNS_SERVER
| GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
#else
dwRet = _GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_ANYCAST
| GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME
| GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
#endif
if(ERROR_BUFFER_OVERFLOW == dwRet)
{
_llarp_nt_heap_free(pAdapterAddresses);
pAdapterAddresses = nullptr;
}
else
{
break;
}
}
switch(dwRet)
{
case ERROR_SUCCESS:
break;
case ERROR_BUFFER_OVERFLOW:
errno = ENOBUFS;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return FALSE;
default:
errno = _doserrno;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return FALSE;
}
/* count valid adapters */
int n = 0, k = 0;
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
for(IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress;
unicast; unicast = unicast->Next)
{
/* ensure IP adapter */
if(AF_INET != unicast->Address.lpSockaddr->sa_family
&& AF_INET6 != unicast->Address.lpSockaddr->sa_family)
{
continue;
}
++n;
}
}
/* contiguous block for adapter list */
struct _llarp_nt_ifaddrs_t* ifa =
llarp_nt_new0(struct _llarp_nt_ifaddrs_t, n);
struct _llarp_nt_ifaddrs_t* ift = ifa;
/* now populate list */
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
int unicastIndex = 0;
for(IP_ADAPTER_UNICAST_ADDRESS *unicast = adapter->FirstUnicastAddress;
unicast; unicast = unicast->Next, ++unicastIndex)
{
/* ensure IP adapter */
if(AF_INET != unicast->Address.lpSockaddr->sa_family
&& AF_INET6 != unicast->Address.lpSockaddr->sa_family)
{
continue;
}
/* address */
ift->_ifa.ifa_addr = (sockaddr*)&ift->_addr;
memcpy(ift->_ifa.ifa_addr, unicast->Address.lpSockaddr,
unicast->Address.iSockaddrLength);
/* name */
#ifdef DEBUG
fprintf(stderr, "name:%s IPv4 index:%lu IPv6 index:%lu\n",
adapter->AdapterName, adapter->IfIndex, adapter->Ipv6IfIndex);
#endif
ift->_ifa.ifa_name = ift->_name;
StringCchCopyN(ift->_ifa.ifa_name, 256, adapter->AdapterName, 256);
/* flags */
ift->_ifa.ifa_flags = 0;
if(IfOperStatusUp == adapter->OperStatus)
ift->_ifa.ifa_flags |= IFF_UP;
if(IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)
ift->_ifa.ifa_flags |= IFF_LOOPBACK;
if(!(adapter->Flags & IP_ADAPTER_NO_MULTICAST))
ift->_ifa.ifa_flags |= IFF_MULTICAST;
/* netmask */
ift->_ifa.ifa_netmask = (sockaddr*)&ift->_netmask;
/* pre-Vista must hunt for matching prefix in linked list, otherwise use
* OnLinkPrefixLength from IP_ADAPTER_UNICAST_ADDRESS structure.
* FirstPrefix requires Windows XP SP1, from SP1 to pre-Vista provides a
* single adapter prefix for each IP address. Vista and later provides
* host IP address prefix, subnet IP address, and subnet broadcast IP
* address. In addition there is a multicast and broadcast address
* prefix.
*/
ULONG prefixLength = 0;
#if defined(_WIN32) && (_WIN32_WINNT >= 0x0600)
/* For a unicast IPv4 address, any value greater than 32 is an illegal
* value. For a unicast IPv6 address, any value greater than 128 is an
* illegal value. A value of 255 is commonly used to represent an illegal
* value.
*
* Windows 7 SP1 returns 64 for Teredo links which is incorrect.
*/
#define IN6_IS_ADDR_TEREDO(addr) \
(((const uint32_t*)(addr))[0] == ntohl(0x20010000))
if(AF_INET6 == unicast->Address.lpSockaddr->sa_family &&
/* TunnelType only applies to one interface on the adapter and no
* convenient method is provided to determine which.
*/
TUNNEL_TYPE_TEREDO == adapter->TunnelType &&
/* Test the interface with the known Teredo network prefix.
*/
IN6_IS_ADDR_TEREDO(
&((struct sockaddr_in6*)(unicast->Address.lpSockaddr))->sin6_addr)
&&
/* Test that this version is actually wrong, subsequent releases from
* Microsoft may resolve the issue.
*/
32 != unicast->OnLinkPrefixLength)
{
#ifdef DEBUG
fprintf(stderr,
"IPv6 Teredo tunneling adapter %s prefix length is an "
"illegal value %lu, overriding to 32.\n",
adapter->AdapterName, unicast->OnLinkPrefixLength);
#endif
prefixLength = 32;
}
else
prefixLength = unicast->OnLinkPrefixLength;
#else
/* The order of linked IP_ADAPTER_UNICAST_ADDRESS structures pointed to by
* the FirstUnicastAddress member does not have any relationship with the
* order of linked IP_ADAPTER_PREFIX structures pointed to by the
* FirstPrefix member.
*
* Example enumeration:
* [ no subnet ]
* ::1/128 - address
* ff00::%1/8 - multicast (no IPv6 broadcast)
* 127.0.0.0/8 - subnet
* 127.0.0.1/32 - address
* 127.255.255.255/32 - subnet broadcast
* 224.0.0.0/4 - multicast
* 255.255.255.255/32 - broadcast
*
* Which differs from most adapters listing three IPv6:
* fe80::%10/64 - subnet
* fe80::51e9:5fe5:4202:325a%10/128 - address
* ff00::%10/8 - multicast
*
* !IfOperStatusUp IPv4 addresses are skipped:
* fe80::%13/64 - subnet
* fe80::d530:946d:e8df:8c91%13/128 - address
* ff00::%13/8 - multicast
* [ no subnet ]
* [ no address ]
* 224.0.0.0/4 - multicast
* 255.255.255.255/32 - broadcast
*
* On PTP links no multicast or broadcast addresses are returned:
* [ no subnet ]
* fe80::5efe:10.203.9.30/128 - address
* [ no multicast ]
* [ no multicast ]
* [ no broadcast ]
*
* Active primary IPv6 interfaces are a bit overloaded:
* ::/0 - default route
* 2001::/32 - global subnet
* 2001:0:4137:9e76:2443:d6:ba87:1a2a/128 - global address
* fe80::/64 - link-local subnet
* fe80::2443:d6:ba87:1a2a/128 - link-local address
* ff00::/8 - multicast
*/
#define IN_LINKLOCAL(a) ((((uint32_t)(a)) & 0xaffff0000) == 0xa9fe0000)
for(IP_ADAPTER_PREFIX* prefix = adapter->FirstPrefix; prefix;
prefix = prefix->Next)
{
LPSOCKADDR lpSockaddr = prefix->Address.lpSockaddr;
if(lpSockaddr->sa_family != unicast->Address.lpSockaddr->sa_family)
continue;
/* special cases */
/* RFC2863: IPv4 interface not up */
if(AF_INET == lpSockaddr->sa_family
&& adapter->OperStatus != IfOperStatusUp)
{
/* RFC3927: link-local IPv4 always has 16-bit CIDR */
if(IN_LINKLOCAL(
ntohl(((struct sockaddr_in*)(unicast->Address.lpSockaddr))
->sin_addr.s_addr)))
{
#ifdef DEBUG
fprintf(stderr,
"Assuming 16-bit prefix length for link-local IPv4 "
"adapter %s.\n",
adapter->AdapterName);
#endif
prefixLength = 16;
}
else
{
#ifdef DEBUG
fprintf(stderr, "Prefix length unavailable for IPv4 adapter %s.\n",
adapter->AdapterName);
#endif
}
break;
}
/* default IPv6 route */
if(AF_INET6 == lpSockaddr->sa_family && 0 == prefix->PrefixLength
&& IN6_IS_ADDR_UNSPECIFIED(
&((struct sockaddr_in6*)(lpSockaddr))->sin6_addr))
{
#ifdef DEBUG
fprintf(stderr,
"Ingoring unspecified address prefix on IPv6 adapter %s.\n",
adapter->AdapterName);
#endif
continue;
}
/* Assume unicast address for first prefix of operational adapter */
if(AF_INET == lpSockaddr->sa_family)
assert(!IN_MULTICAST(
ntohl(((struct sockaddr_in*)(lpSockaddr))->sin_addr.s_addr)));
if(AF_INET6 == lpSockaddr->sa_family)
assert(!IN6_IS_ADDR_MULTICAST(
&((struct sockaddr_in6*)(lpSockaddr))->sin6_addr));
/* Assume subnet or host IP address for XP backward compatibility */
prefixLength = prefix->PrefixLength;
break;
}
#endif /* defined( _WIN32 ) && ( _WIN32_WINNT >= 0x0600 ) */
/* map prefix to netmask */
ift->_ifa.ifa_netmask->sa_family = unicast->Address.lpSockaddr->sa_family;
switch(unicast->Address.lpSockaddr->sa_family)
{
case AF_INET:
if(0 == prefixLength || prefixLength > 32)
{
#ifdef DEBUG
fprintf(stderr,
"IPv4 adapter %s prefix length is an illegal value "
"%lu, overriding to 32.\n",
adapter->AdapterName, prefixLength);
#endif
prefixLength = 32;
}
/* NB: left-shift of full bit-width is undefined in C standard. */
((struct sockaddr_in*)ift->_ifa.ifa_netmask)->sin_addr.s_addr =
htonl(0xffffffffU << (32 - prefixLength));
break;
case AF_INET6:
if(0 == prefixLength || prefixLength > 128)
{
#ifdef DEBUG
fprintf(stderr,
"IPv6 adapter %s prefix length is an illegal value "
"%lu, overriding to 128.\n",
adapter->AdapterName, prefixLength);
#endif
prefixLength = 128;
}
for(LONG i = prefixLength, j = 0; i > 0; i -= 8, ++j)
{
((struct sockaddr_in6*)ift->_ifa.ifa_netmask)
->sin6_addr.s6_addr[j] =
i >= 8 ? 0xff : (ULONG)((0xffU << (8 - i)) & 0xffU);
}
break;
}
/* next */
if(k++ < (n - 1))
{
ift->_ifa.ifa_next = (struct llarp_nt_ifaddrs_t*)(ift + 1);
ift = (struct _llarp_nt_ifaddrs_t*)(ift->_ifa.ifa_next);
}
}
}
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
*ifap = (struct llarp_nt_ifaddrs_t*)ifa;
return TRUE;
}
#endif
// an implementation of if_nametoindex(3) based on GetAdapterIndex(2)
// with a fallback to GetAdaptersAddresses(2) commented out for now
// unless it becomes evident that the first codepath fails in certain
// edge cases?
static unsigned
_llarp_nt_getadaptersaddresses_nametoindex(const char* ifname)
{
ULONG ifIndex;
DWORD /* dwSize = 4096,*/ dwRet;
// IP_ADAPTER_ADDRESSES *pAdapterAddresses = nullptr, *adapter;
char szAdapterName[256];
if(!ifname)
return 0;
StringCchCopyN(szAdapterName, sizeof(szAdapterName), ifname, 256);
dwRet = GetAdapterIndex((LPWSTR)szAdapterName, &ifIndex);
if(!dwRet)
return ifIndex;
else
return 0;
#if 0
/* fallback to finding index via iterating adapter list */
/* loop to handle interfaces coming online causing a buffer overflow
* between first call to list buffer length and second call to enumerate.
*/
for(unsigned i = 3; i; i--)
{
pAdapterAddresses = (IP_ADAPTER_ADDRESSES*)_llarp_nt_heap_alloc(dwSize);
#ifdef _MSC_VER
dwRet = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER
| GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
#else
dwRet = _GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_DNS_SERVER
| GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_MULTICAST,
nullptr, pAdapterAddresses, &dwSize);
#endif
if(ERROR_BUFFER_OVERFLOW == dwRet)
{
_llarp_nt_heap_free(pAdapterAddresses);
pAdapterAddresses = nullptr;
}
else
{
break;
}
}
switch(dwRet)
{
case ERROR_SUCCESS:
break;
case ERROR_BUFFER_OVERFLOW:
errno = ENOBUFS;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
default:
errno = _doserrno;
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
}
for(adapter = pAdapterAddresses; adapter; adapter = adapter->Next)
{
if(0 == strcmp(szAdapterName, adapter->AdapterName))
{
//ifIndex = AF_INET6 == iffamily ? adapter->Ipv6IfIndex : adapter->IfIndex;
_llarp_nt_heap_free(pAdapterAddresses);
return ifIndex;
}
}
if(pAdapterAddresses)
_llarp_nt_heap_free(pAdapterAddresses);
return 0;
#endif
}
// the emulated getifaddrs(3) itself.
static bool
llarp_nt_getifaddrs(struct llarp_nt_ifaddrs_t** ifap)
{
assert(nullptr != ifap);
#ifdef DEBUG
fprintf(stderr, "llarp_nt_getifaddrs (ifap:%p error:%p)\n", (void*)ifap,(void*)errno);
#endif
#ifdef _MSC_VER
return _llarp_nt_getadaptersaddresses(ifap);
#else
return _llarp_nt_getadaptersinfo(ifap);
#endif
}
static void
llarp_nt_freeifaddrs(struct llarp_nt_ifaddrs_t* ifa)
{
if(!ifa)
return;
free(ifa);
}
// emulated if_nametoindex(3)
static unsigned
llarp_nt_if_nametoindex(const char* ifname)
{
if(!ifname)
return 0;
return _llarp_nt_getadaptersaddresses_nametoindex(ifname);
}
// fix up names for win32
#define ifaddrs llarp_nt_ifaddrs_t
#define getifaddrs llarp_nt_getifaddrs
#define freeifaddrs llarp_nt_freeifaddrs
#define if_nametoindex llarp_nt_if_nametoindex
#endif
// jeff's original code
bool
llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
{
@ -51,7 +736,11 @@ llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
if(af == AF_INET)
sl = sizeof(sockaddr_in);
#ifndef _WIN32
if(getifaddrs(&ifa) == -1)
#else
if(!getifaddrs(&ifa))
#endif
return false;
ifaddrs* i = ifa;
while(i)
@ -86,7 +775,6 @@ llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
freeifaddrs(ifa);
return found;
}
namespace llarp
{
bool
@ -94,8 +782,11 @@ namespace llarp
{
ifaddrs* ifa = nullptr;
bool found = false;
#ifndef _WIN32
if(getifaddrs(&ifa) == -1)
#else
if(!getifaddrs(&ifa))
#endif
return false;
ifaddrs* i = ifa;
while(i)

@ -109,7 +109,11 @@ struct llarp_nodedb
const char *hexname =
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(pubkey, ftmp);
std::string hexString(hexname);
#ifdef _WIN32
std::string filepath = nodePath.string();
#else
std::string filepath = nodePath;
#endif
filepath.append(PATH_SEP);
filepath.append(&hexString[hexString.length() - 1]);
filepath.append(PATH_SEP);
@ -182,7 +186,7 @@ struct llarp_nodedb
{
ssize_t sz = 0;
fs::directory_iterator i(dir);
#if __has_include(<filesystem>) && !defined(__OpenBSD__)
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
auto itr = fs::begin(i);
while(itr != fs::end(i))
#else
@ -190,7 +194,7 @@ struct llarp_nodedb
while(itr != itr.end())
#endif
{
if(fs::is_regular_file(itr->symlink_status()) && loadfile(*itr))
if(fs::is_regular_file(itr->path()) && loadfile(*itr))
sz++;
++itr;
@ -210,7 +214,11 @@ struct llarp_nodedb
#endif
llarp_rc rc;
llarp_rc_clear(&rc);
#ifdef _WIN32
if(!llarp_rc_read(fpath.string().c_str(), &rc))
#else
if(!llarp_rc_read(fpath.c_str(), &rc))
#endif
{
llarp::LogError("Signature read failed", fpath);
return false;
@ -348,6 +356,7 @@ llarp_nodedb_ensure_dir(const char *dir)
{
fs::path path(dir);
std::error_code ec;
if(!fs::exists(dir, ec))
fs::create_directories(path, ec);
@ -359,6 +368,11 @@ llarp_nodedb_ensure_dir(const char *dir)
for(const char &ch : skiplist_subdirs)
{
// this seems to be a problem on all targets
// perhaps cpp17::fs is just as screwed-up
// attempting to create a folder with no name
if(!ch)
return true;
std::string p;
p += ch;
fs::path sub = path / p;

@ -1,10 +1,10 @@
#include "router.hpp"
#include <llarp/iwp.h>
#include <llarp/proto.h>
#include <llarp/link_message.hpp>
#include "llarp/iwp/establish_job.hpp"
#include "llarp/iwp/server.hpp"
#include "llarp/iwp/session.hpp"
#include "router.hpp"
#include "buffer.hpp"
#include "encode.hpp"
@ -166,7 +166,11 @@ llarp_router::try_connect(fs::path rcfile)
{
llarp_rc remote;
llarp_rc_new(&remote);
#ifdef _WIN32
if(!llarp_rc_read(rcfile.string().c_str(), &remote))
#else
if(!llarp_rc_read(rcfile.c_str(), &remote))
#endif
{
llarp::LogError("failure to decode or verify of remote RC");
return;
@ -196,14 +200,24 @@ llarp_router::EnsureIdentity()
{
if(!EnsureEncryptionKey())
return false;
#ifdef _WIN32
return llarp_findOrCreateIdentity(&crypto, ident_keyfile.string().c_str(),
identity);
#else
return llarp_findOrCreateIdentity(&crypto, ident_keyfile.c_str(), identity);
#endif
}
bool
llarp_router::EnsureEncryptionKey()
{
#ifdef _WIN32
return llarp_findOrCreateEncryption(
&crypto, encryption_keyfile.string().c_str(), &this->encryption);
#else
return llarp_findOrCreateEncryption(&crypto, encryption_keyfile.c_str(),
&this->encryption);
#endif
}
void
@ -233,7 +247,11 @@ llarp_router::SaveRC()
if(llarp_rc_bencode(&rc, &buf))
{
#ifdef _WIN32
std::ofstream f(our_rc_file.string());
#else
std::ofstream f(our_rc_file);
#endif
if(f.is_open())
{
f.write((char *)buf.base, buf.cur - buf.base);
@ -754,7 +772,15 @@ llarp_router::InitOutboundLink()
{
if(outboundLink)
return true;
#ifdef __MINGW32__
llarp_iwp_args args = {
.crypto = &crypto,
.logic = logic,
.cryptoworker = tp,
.router = this,
.keyfile = transport_keyfile.string().c_str(),
};
#elif !defined(_MSC_VER)
llarp_iwp_args args = {
.crypto = &crypto,
.logic = logic,
@ -762,6 +788,11 @@ llarp_router::InitOutboundLink()
.router = this,
.keyfile = transport_keyfile.c_str(),
};
#else
llarp_iwp_args args = {
&crypto, logic, tp, this, transport_keyfile.string().c_str(),
};
#endif
auto link = new(std::nothrow) llarp_link(args);
@ -913,7 +944,11 @@ llarp_rc_read(const char *fpath, llarp_rc *result)
printf("File[%s] not found\n", fpath);
return false;
}
#ifdef _WIN32
std::ifstream f(our_rc_file.string(), std::ios::binary);
#else
std::ifstream f(our_rc_file, std::ios::binary);
#endif
if(!f.is_open())
{
printf("Can't open file [%s]\n", fpath);
@ -933,7 +968,7 @@ llarp_rc_read(const char *fpath, llarp_rc *result)
llarp::Zero(result, sizeof(llarp_rc));
if(!llarp_rc_bdecode(result, &buf))
{
printf("Can't decode [%s]\n", fpath);
llarp::LogError("Can't decode ", fpath);
return false;
}
return true;
@ -967,7 +1002,11 @@ llarp_rc_write(struct llarp_rc *rc, const char *fpath)
if(llarp_rc_bencode(rc, &buf))
{
#ifdef _WIN32
std::ofstream f(our_rc_file.string(), std::ios::binary);
#else
std::ofstream f(our_rc_file, std::ios::binary);
#endif
if(f.is_open())
{
f.write((char *)buf.base, buf.cur - buf.base);
@ -1039,13 +1078,21 @@ llarp_findOrCreateIdentity(llarp_crypto *crypto, const char *fpath,
{
llarp::LogInfo("generating new identity key");
crypto->identity_keygen(secretkey);
#ifdef _WIN32
std::ofstream f(path.string(), std::ios::binary);
#else
std::ofstream f(path, std::ios::binary);
#endif
if(f.is_open())
{
f.write((char *)secretkey, SECKEYSIZE);
}
}
#ifdef _WIN32
std::ifstream f(path.string(), std::ios::binary);
#else
std::ifstream f(path, std::ios::binary);
#endif
if(f.is_open())
{
f.read((char *)secretkey, SECKEYSIZE);
@ -1067,13 +1114,21 @@ llarp_findOrCreateEncryption(llarp_crypto *crypto, const char *fpath,
{
llarp::LogInfo("generating new encryption key");
crypto->encryption_keygen(*encryption);
#ifdef _WIN32
std::ofstream f(path.string(), std::ios::binary);
#else
std::ofstream f(path, std::ios::binary);
#endif
if(f.is_open())
{
f.write((char *)encryption, SECKEYSIZE);
}
}
#ifdef _WIN32
std::ifstream f(path.string(), std::ios::binary);
#else
std::ifstream f(path, std::ios::binary);
#endif
if(f.is_open())
{
f.read((char *)encryption, SECKEYSIZE);
@ -1130,6 +1185,15 @@ namespace llarp
if(!StrEq(key, "*"))
{
llarp::LogInfo("interface specific binding activated");
#ifdef __MINGW32__
llarp_iwp_args args = {
.crypto = &self->crypto,
.logic = self->logic,
.cryptoworker = self->tp,
.router = self,
.keyfile = self->transport_keyfile.string().c_str(),
};
#elif !defined(_MSC_VER)
llarp_iwp_args args = {
.crypto = &self->crypto,
.logic = self->logic,
@ -1137,6 +1201,15 @@ namespace llarp
.router = self,
.keyfile = self->transport_keyfile.c_str(),
};
#else
llarp_iwp_args args = {
&self->crypto,
self->logic,
self->tp,
self,
self->transport_keyfile.string().c_str(),
};
#endif
link = new(std::nothrow) llarp_link(args);

@ -1,3 +1,7 @@
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/service.hpp>
#include "buffer.hpp"
#include "fs.hpp"

@ -1,5 +1,7 @@
#include "threadpool.hpp"
#ifndef _MSC_VER
#include <pthread.h>
#endif
#include <cstring>
#include <llarp/time.h>
@ -11,6 +13,12 @@
#include <pthread_np.h>
#endif
#ifdef _MSC_VER
#include <windows.h>
extern "C" void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName);
#endif
namespace llarp
{
namespace thread
@ -27,8 +35,10 @@ namespace llarp
pthread_setname_np(name);
#elif(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__)
pthread_set_name_np(pthread_self(), name);
#else
#elif !defined(_MSC_VER) || !defined(_WIN32)
pthread_setname_np(pthread_self(), name);
#else
SetThreadName(GetCurrentThreadId(),name);
#endif
}
for(;;)

@ -0,0 +1,312 @@
#if defined(__MINGW32__) && !defined(_WIN64)
/*
* Contains routines missing from WS2_32.DLL until 2006, if yer using
* Microsoft C/C++, then this code is irrelevant, as the official
* Platform SDK already links against these routines in the correct
* libraries.
*
* -despair86 30/07/18
*/
#include <assert.h>
#include <llarp/net.h>
#include <windows.h>
#include <iphlpapi.h>
#include "win32_intrnl.h"
const char *
inet_ntop(int af, const void *src, char *dst, size_t size)
{
int address_length;
DWORD string_length = size;
struct sockaddr_storage sa;
struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
memset(&sa, 0, sizeof(sa));
switch(af)
{
case AF_INET:
address_length = sizeof(struct sockaddr_in);
sin->sin_family = af;
memcpy(&sin->sin_addr, src, sizeof(struct in_addr));
break;
case AF_INET6:
address_length = sizeof(struct sockaddr_in6);
sin6->sin6_family = af;
memcpy(&sin6->sin6_addr, src, sizeof(struct in6_addr));
break;
default:
return NULL;
}
if(WSAAddressToString((LPSOCKADDR)&sa, address_length, NULL, dst,
&string_length)
== 0)
{
return dst;
}
return NULL;
}
int
inet_pton(int af, const char *src, void *dst)
{
int address_length;
struct sockaddr_storage sa;
struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
switch(af)
{
case AF_INET:
address_length = sizeof(struct sockaddr_in);
break;
case AF_INET6:
address_length = sizeof(struct sockaddr_in6);
break;
default:
return -1;
}
if(WSAStringToAddress((LPTSTR)src, af, NULL, (LPSOCKADDR)&sa, &address_length)
== 0)
{
switch(af)
{
case AF_INET:
memcpy(dst, &sin->sin_addr, sizeof(struct in_addr));
break;
case AF_INET6:
memcpy(dst, &sin6->sin6_addr, sizeof(struct in6_addr));
break;
}
return 1;
}
return 0;
}
typedef struct _InterfaceIndexTable
{
DWORD numIndexes;
IF_INDEX indexes[1];
} InterfaceIndexTable;
// windows 2000
// todo(despair86): implement IPv6 detection using
// the ipv6 preview stack/adv net pack from 1999/2001
DWORD FAR PASCAL
_GetAdaptersAddresses(ULONG Family, ULONG Flags, PVOID Reserved,
PIP_ADAPTER_ADDRESSES pAdapterAddresses,
PULONG pOutBufLen)
{
InterfaceIndexTable *indexTable;
IFInfo ifInfo;
int i;
ULONG ret, requiredSize = 0;
PIP_ADAPTER_ADDRESSES currentAddress;
PUCHAR currentLocation;
HANDLE tcpFile;
if(!pOutBufLen)
return ERROR_INVALID_PARAMETER;
if(Reserved)
return ERROR_INVALID_PARAMETER;
indexTable = getInterfaceIndexTable();
if(!indexTable)
return ERROR_NOT_ENOUGH_MEMORY;
ret = openTcpFile(&tcpFile, FILE_READ_DATA);
if(!NT_SUCCESS(ret))
return ERROR_NO_DATA;
for(i = indexTable->numIndexes; i >= 0; i--)
{
if(NT_SUCCESS(
getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
/* The whole struct */
requiredSize += sizeof(IP_ADAPTER_ADDRESSES);
/* Friendly name */
if(!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
requiredSize +=
strlen((char *)ifInfo.if_info.ent.if_descr) + 1; // FIXME
/* Adapter name */
requiredSize += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
/* Unicast address */
if(!(Flags & GAA_FLAG_SKIP_UNICAST))
requiredSize += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
/* FIXME: Implement multicast, anycast, and dns server stuff */
/* FIXME: Implement dns suffix and description */
requiredSize += 2 * sizeof(WCHAR);
/* We're only going to implement what's required for XP SP0 */
}
}
#ifdef DEBUG
fprintf(stderr, "size: %ld, requiredSize: %ld\n", *pOutBufLen, requiredSize);
#endif
if(!pAdapterAddresses || *pOutBufLen < requiredSize)
{
*pOutBufLen = requiredSize;
closeTcpFile(tcpFile);
free(indexTable);
return ERROR_BUFFER_OVERFLOW;
}
RtlZeroMemory(pAdapterAddresses, requiredSize);
/* Let's set up the pointers */
currentAddress = pAdapterAddresses;
for(i = indexTable->numIndexes; i >= 0; i--)
{
if(NT_SUCCESS(
getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
currentLocation =
(PUCHAR)currentAddress + (ULONG_PTR)sizeof(IP_ADAPTER_ADDRESSES);
/* FIXME: Friendly name */
if(!(Flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
{
currentAddress->FriendlyName = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
}
/* Adapter name */
currentAddress->AdapterName = (PVOID)currentLocation;
currentLocation += strlen((char *)ifInfo.if_info.ent.if_descr) + 1;
/* Unicast address */
if(!(Flags & GAA_FLAG_SKIP_UNICAST))
{
currentAddress->FirstUnicastAddress = (PVOID)currentLocation;
currentLocation += sizeof(IP_ADAPTER_UNICAST_ADDRESS);
currentAddress->FirstUnicastAddress->Address.lpSockaddr =
(PVOID)currentLocation;
currentLocation += sizeof(struct sockaddr);
}
/* FIXME: Implement multicast, anycast, and dns server stuff */
/* FIXME: Implement dns suffix and description */
currentAddress->DnsSuffix = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
currentAddress->Description = (PVOID)currentLocation;
currentLocation += sizeof(WCHAR);
currentAddress->Next = (PVOID)currentLocation;
/* Terminate the last address correctly */
if(i == 0)
currentAddress->Next = NULL;
/* We're only going to implement what's required for XP SP0 */
currentAddress = currentAddress->Next;
}
}
/* Now again, for real this time */
currentAddress = pAdapterAddresses;
for(i = indexTable->numIndexes; i >= 0; i--)
{
if(NT_SUCCESS(
getIPAddrEntryForIf(tcpFile, NULL, indexTable->indexes[i], &ifInfo)))
{
/* Make sure we're not looping more than we hoped for */
assert(currentAddress);
/* Alignment information */
currentAddress->Length = sizeof(IP_ADAPTER_ADDRESSES);
currentAddress->IfIndex = indexTable->indexes[i];
/* Adapter name */
strcpy(currentAddress->AdapterName, (char *)ifInfo.if_info.ent.if_descr);
if(!(Flags & GAA_FLAG_SKIP_UNICAST))
{
currentAddress->FirstUnicastAddress->Length =
sizeof(IP_ADAPTER_UNICAST_ADDRESS);
currentAddress->FirstUnicastAddress->Flags = 0; // FIXME
currentAddress->FirstUnicastAddress->Next =
NULL; // FIXME: Support more than one address per adapter
currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family =
AF_INET;
memcpy(currentAddress->FirstUnicastAddress->Address.lpSockaddr->sa_data,
&ifInfo.ip_addr.iae_addr, sizeof(ifInfo.ip_addr.iae_addr));
currentAddress->FirstUnicastAddress->Address.iSockaddrLength =
sizeof(ifInfo.ip_addr.iae_addr) + sizeof(USHORT);
currentAddress->FirstUnicastAddress->PrefixOrigin =
IpPrefixOriginOther; // FIXME
currentAddress->FirstUnicastAddress->SuffixOrigin =
IpPrefixOriginOther; // FIXME
currentAddress->FirstUnicastAddress->DadState =
IpDadStatePreferred; // FIXME
currentAddress->FirstUnicastAddress->ValidLifetime =
0xFFFFFFFF; // FIXME
currentAddress->FirstUnicastAddress->PreferredLifetime =
0xFFFFFFFF; // FIXME
currentAddress->FirstUnicastAddress->LeaseLifetime =
0xFFFFFFFF; // FIXME
}
/* FIXME: Implement multicast, anycast, and dns server stuff */
currentAddress->FirstAnycastAddress = NULL;
currentAddress->FirstMulticastAddress = NULL;
currentAddress->FirstDnsServerAddress = NULL;
/* FIXME: Implement dns suffix, description, and friendly name */
currentAddress->DnsSuffix[0] = UNICODE_NULL;
currentAddress->Description[0] = UNICODE_NULL;
currentAddress->FriendlyName[0] = UNICODE_NULL;
/* Physical Address */
memcpy(currentAddress->PhysicalAddress, ifInfo.if_info.ent.if_physaddr,
ifInfo.if_info.ent.if_physaddrlen);
currentAddress->PhysicalAddressLength = ifInfo.if_info.ent.if_physaddrlen;
/* Flags */
currentAddress->Flags = 0; // FIXME
/* MTU */
currentAddress->Mtu = ifInfo.if_info.ent.if_mtu;
/* Interface type */
currentAddress->IfType = ifInfo.if_info.ent.if_type;
/* Operational status */
if(ifInfo.if_info.ent.if_operstatus >= IF_OPER_STATUS_CONNECTING)
currentAddress->OperStatus = IfOperStatusUp;
else
currentAddress->OperStatus = IfOperStatusDown;
/* We're only going to implement what's required for XP SP0 */
/* Move to the next address */
currentAddress = currentAddress->Next;
}
}
closeTcpFile(tcpFile);
free(indexTable);
return NO_ERROR;
}
#elif _MSC_VER
/* just a comment */
static void* unused;
#endif

@ -0,0 +1,534 @@
#if defined(__MINGW32__) && !defined(_WIN64)
/*
* All the user-mode scaffolding necessary to backport GetAdaptersAddresses(2))
* to the NT 5.x series. See further comments for any limitations.
*
* -despair86 30/07/18
*/
#include <assert.h>
#include <stdio.h>
#include <windows.h>
#include <winternl.h>
#include <tdi.h>
#include "win32_intrnl.h"
const PWCHAR TcpFileName = L"\\Device\\Tcp";
// from ntdll.dll
typedef void(FAR PASCAL *pRtlInitUString)(UNICODE_STRING *, const WCHAR *);
typedef NTSTATUS(FAR PASCAL *pNTOpenFile)(HANDLE *, ACCESS_MASK,
OBJECT_ATTRIBUTES *,
IO_STATUS_BLOCK *, ULONG, ULONG);
typedef NTSTATUS(FAR PASCAL *pNTClose)(HANDLE);
#define FSCTL_TCP_BASE FILE_DEVICE_NETWORK
#define _TCP_CTL_CODE(Function, Method, Access) \
CTL_CODE(FSCTL_TCP_BASE, Function, Method, Access)
#define IOCTL_TCP_QUERY_INFORMATION_EX \
_TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef struct _InterfaceIndexTable
{
DWORD numIndexes;
DWORD numAllocated;
DWORD indexes[1];
} InterfaceIndexTable;
NTSTATUS
tdiGetMibForIfEntity(HANDLE tcpFile, TDIEntityID *ent,
IFEntrySafelySized *entry)
{
TCP_REQUEST_QUERY_INFORMATION_EX req = {{{0}}};
NTSTATUS status = 0;
DWORD returnSize;
#ifdef DEBUG
fprintf(stderr, "TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n", (int)tcpFile,
(int)ent->tei_instance);
#endif
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = 1;
req.ID.toi_entity = *ent;
status =
DeviceIoControl(tcpFile, IOCTL_TCP_QUERY_INFORMATION_EX, &req,
sizeof(req), entry, sizeof(*entry), &returnSize, NULL);
if(!status)
{
perror("IOCTL Failed\n");
return 0xc0000001;
}
fprintf(stderr,
"TdiGetMibForIfEntity() => {\n"
" if_index ....................... %lx\n"
" if_type ........................ %lx\n"
" if_mtu ......................... %ld\n"
" if_speed ....................... %lx\n"
" if_physaddrlen ................. %ld\n",
entry->ent.if_index, entry->ent.if_type, entry->ent.if_mtu,
entry->ent.if_speed, entry->ent.if_physaddrlen);
fprintf(stderr,
" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n"
" if_descr ....................... %s\n",
entry->ent.if_physaddr[0] & 0xff, entry->ent.if_physaddr[1] & 0xff,
entry->ent.if_physaddr[2] & 0xff, entry->ent.if_physaddr[3] & 0xff,
entry->ent.if_physaddr[4] & 0xff, entry->ent.if_physaddr[5] & 0xff,
entry->ent.if_descr);
fprintf(stderr, "} status %08lx\n", status);
return 0;
}
static NTSTATUS
tdiGetSetOfThings(HANDLE tcpFile, DWORD toiClass, DWORD toiType, DWORD toiId,
DWORD teiEntity, DWORD teiInstance, DWORD fixedPart,
DWORD entrySize, PVOID *tdiEntitySet, PDWORD numEntries)
{
TCP_REQUEST_QUERY_INFORMATION_EX req = {{{0}}};
PVOID entitySet = 0;
NTSTATUS status = 0;
DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES,
arraySize = entrySize * MAX_TDI_ENTITIES;
req.ID.toi_class = toiClass;
req.ID.toi_type = toiType;
req.ID.toi_id = toiId;
req.ID.toi_entity.tei_entity = teiEntity;
req.ID.toi_entity.tei_instance = teiInstance;
/* There's a subtle problem here...
* If an interface is added at this exact instant, (as if by a PCMCIA
* card insertion), the array will still not have enough entries after
* have allocated it after the first DeviceIoControl call.
*
* We'll get around this by repeating until the number of interfaces
* stabilizes.
*/
do
{
status =
DeviceIoControl(tcpFile, IOCTL_TCP_QUERY_INFORMATION_EX, &req,
sizeof(req), 0, 0, &allocationSizeForEntityArray, NULL);
if(!status)
return 0xc0000001;
arraySize = allocationSizeForEntityArray;
entitySet = HeapAlloc(GetProcessHeap(), 0, arraySize);
if(!entitySet)
{
status = ((NTSTATUS)0xC000009A);
return status;
}
status = DeviceIoControl(tcpFile, IOCTL_TCP_QUERY_INFORMATION_EX, &req,
sizeof(req), entitySet, arraySize,
&allocationSizeForEntityArray, NULL);
/* This is why we have the loop -- we might have added an adapter */
if(arraySize == allocationSizeForEntityArray)
break;
HeapFree(GetProcessHeap(), 0, entitySet);
entitySet = 0;
if(!status)
return 0xc0000001;
} while(TRUE); /* We break if the array we received was the size we
* expected. Therefore, we got here because it wasn't */
*numEntries = (arraySize - fixedPart) / entrySize;
*tdiEntitySet = entitySet;
return 0;
}
static NTSTATUS
tdiGetEntityIDSet(HANDLE tcpFile, TDIEntityID **entitySet,
PDWORD numEntities)
{
NTSTATUS status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_GENERIC,
INFO_TYPE_PROVIDER,
ENTITY_LIST_ID,
GENERIC_ENTITY,
0,
0,
sizeof(TDIEntityID),
(PVOID *)entitySet,
numEntities);
return status;
}
NTSTATUS
tdiGetIpAddrsForIpEntity(HANDLE tcpFile, TDIEntityID *ent, IPAddrEntry **addrs,
PDWORD numAddrs)
{
NTSTATUS status;
fprintf(stderr,"TdiGetIpAddrsForIpEntity(tcpFile 0x%p, entityId 0x%lx)\n", tcpFile,
ent->tei_instance);
status = tdiGetSetOfThings(tcpFile, INFO_CLASS_PROTOCOL, INFO_TYPE_PROVIDER,
0x102, CL_NL_ENTITY,
ent->tei_instance, 0, sizeof(IPAddrEntry),
(PVOID *)addrs, numAddrs);
return status;
}
static VOID
tdiFreeThingSet(PVOID things)
{
HeapFree(GetProcessHeap(), 0, things);
}
NTSTATUS
openTcpFile(PHANDLE tcpFile, ACCESS_MASK DesiredAccess)
{
UNICODE_STRING fileName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
pRtlInitUString _RtlInitUnicodeString;
pNTOpenFile _NTOpenFile;
HANDLE ntdll;
ntdll = GetModuleHandle("ntdll.dll");
_RtlInitUnicodeString = (pRtlInitUString)GetProcAddress(ntdll, "RtlInitUnicodeString");
_NTOpenFile = (pNTOpenFile)GetProcAddress(ntdll, "NtOpenFile");
_RtlInitUnicodeString(&fileName, TcpFileName);
InitializeObjectAttributes(&objectAttributes, &fileName, OBJ_CASE_INSENSITIVE,
NULL, NULL);
status = _NTOpenFile(tcpFile, DesiredAccess | SYNCHRONIZE, &objectAttributes,
&ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
/* String does not need to be freed: it points to the constant
* string we provided */
if(!NT_SUCCESS(status))
*tcpFile = INVALID_HANDLE_VALUE;
return status;
}
VOID
closeTcpFile(HANDLE h)
{
pNTClose _NTClose;
HANDLE ntdll = GetModuleHandle("ntdll.dll");
_NTClose = (pNTClose)GetProcAddress(ntdll, "NtClose");
assert(h != INVALID_HANDLE_VALUE);
_NTClose(h);
}
BOOL
isLoopback(HANDLE tcpFile, TDIEntityID *loop_maybe)
{
IFEntrySafelySized entryInfo;
NTSTATUS status;
status = tdiGetMibForIfEntity(tcpFile, loop_maybe, &entryInfo);
return NT_SUCCESS(status)
&& (entryInfo.ent.if_type == IFENT_SOFTWARE_LOOPBACK);
}
BOOL
isIpEntity(HANDLE tcpFile, TDIEntityID *ent)
{
return (ent->tei_entity == CL_NL_ENTITY || ent->tei_entity == CO_NL_ENTITY);
}
NTSTATUS
getNthIpEntity(HANDLE tcpFile, DWORD index, TDIEntityID *ent)
{
DWORD numEntities = 0;
DWORD numRoutes = 0;
TDIEntityID *entitySet = 0;
NTSTATUS status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
int i;
if(!NT_SUCCESS(status))
return status;
for(i = 0; i < numEntities; i++)
{
if(isIpEntity(tcpFile, &entitySet[i]))
{
fprintf(stderr, "Entity %d is an IP Entity\n", i);
if(numRoutes == index)
break;
else
numRoutes++;
}
}
if(numRoutes == index && i < numEntities)
{
fprintf(stderr,"Index %lu is entity #%d - %04lx:%08lx\n", index, i,
entitySet[i].tei_entity, entitySet[i].tei_instance);
memcpy(ent, &entitySet[i], sizeof(*ent));
tdiFreeThingSet(entitySet);
return 0;
}
else
{
tdiFreeThingSet(entitySet);
return 0xc000001;
}
}
BOOL
isInterface(TDIEntityID *if_maybe)
{
return if_maybe->tei_entity == IF_ENTITY;
}
NTSTATUS
getInterfaceInfoSet(HANDLE tcpFile, IFInfo **infoSet, PDWORD numInterfaces)
{
DWORD numEntities;
TDIEntityID *entIDSet = NULL;
NTSTATUS status = tdiGetEntityIDSet(tcpFile, &entIDSet, &numEntities);
IFInfo *infoSetInt = 0;
int curInterf = 0, i;
if(!NT_SUCCESS(status))
{
fprintf(stderr, "getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n", status);
return status;
}
infoSetInt = HeapAlloc(GetProcessHeap(), 0, sizeof(IFInfo) * numEntities);
if(infoSetInt)
{
for(i = 0; i < numEntities; i++)
{
if(isInterface(&entIDSet[i]))
{
infoSetInt[curInterf].entity_id = entIDSet[i];
status = tdiGetMibForIfEntity(tcpFile, &entIDSet[i],
&infoSetInt[curInterf].if_info);
fprintf(stderr, "tdiGetMibForIfEntity: %08lx\n", status);
if(NT_SUCCESS(status))
{
DWORD numAddrs;
IPAddrEntry *addrs;
TDIEntityID ip_ent;
int j;
status = getNthIpEntity(tcpFile, curInterf, &ip_ent);
if(NT_SUCCESS(status))
status =
tdiGetIpAddrsForIpEntity(tcpFile, &ip_ent, &addrs, &numAddrs);
for(j = 0; NT_SUCCESS(status) && j < numAddrs; j++)
{
fprintf(stderr, "ADDR %d: index %ld (target %ld)\n", j, addrs[j].iae_index,
infoSetInt[curInterf].if_info.ent.if_index);
if(addrs[j].iae_index == infoSetInt[curInterf].if_info.ent.if_index)
{
memcpy(&infoSetInt[curInterf].ip_addr, &addrs[j],
sizeof(addrs[j]));
curInterf++;
break;
}
}
if(NT_SUCCESS(status))
tdiFreeThingSet(addrs);
}
}
}
tdiFreeThingSet(entIDSet);
if(NT_SUCCESS(status))
{
*infoSet = infoSetInt;
*numInterfaces = curInterf;
}
else
{
HeapFree(GetProcessHeap(), 0, infoSetInt);
}
return status;
}
else
{
tdiFreeThingSet(entIDSet);
return ((NTSTATUS)0xC000009A);
}
}
NTSTATUS
getInterfaceInfoByName(HANDLE tcpFile, char *name, IFInfo *info)
{
IFInfo *ifInfo;
DWORD numInterfaces;
int i;
NTSTATUS status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
if(NT_SUCCESS(status))
{
for(i = 0; i < numInterfaces; i++)
{
if(!strcmp((PCHAR)ifInfo[i].if_info.ent.if_descr, name))
{
memcpy(info, &ifInfo[i], sizeof(*info));
break;
}
}
HeapFree(GetProcessHeap(), 0, ifInfo);
return i < numInterfaces ? 0 : 0xc0000001;
}
return status;
}
NTSTATUS
getInterfaceInfoByIndex(HANDLE tcpFile, DWORD index, IFInfo *info)
{
IFInfo *ifInfo;
DWORD numInterfaces;
NTSTATUS status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
int i;
if(NT_SUCCESS(status))
{
for(i = 0; i < numInterfaces; i++)
{
if(ifInfo[i].if_info.ent.if_index == index)
{
memcpy(info, &ifInfo[i], sizeof(*info));
break;
}
}
HeapFree(GetProcessHeap(), 0, ifInfo);
return i < numInterfaces ? 0 : 0xc0000001;
}
return status;
}
NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile, char *name, DWORD index, IFInfo *ifInfo)
{
NTSTATUS status = name ? getInterfaceInfoByName(tcpFile, name, ifInfo)
: getInterfaceInfoByIndex(tcpFile, index, ifInfo);
if(!NT_SUCCESS(status))
{
fprintf(stderr,"getIPAddrEntryForIf returning %lx\n", status);
}
return status;
}
InterfaceIndexTable *
getInterfaceIndexTableInt(BOOL nonLoopbackOnly)
{
DWORD numInterfaces, curInterface = 0;
int i;
IFInfo *ifInfo;
InterfaceIndexTable *ret = 0;
HANDLE tcpFile;
NTSTATUS status = openTcpFile(&tcpFile, FILE_READ_DATA);
if(NT_SUCCESS(status))
{
status = getInterfaceInfoSet(tcpFile, &ifInfo, &numInterfaces);
fprintf(stderr,"InterfaceInfoSet: %08lx, %04lx:%08lx\n", status,
ifInfo->entity_id.tei_entity, ifInfo->entity_id.tei_instance);
if(NT_SUCCESS(status))
{
ret = (InterfaceIndexTable *)calloc(
1, sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
if(ret)
{
ret->numAllocated = numInterfaces;
fprintf(stderr,"NumInterfaces = %ld\n", numInterfaces);
for(i = 0; i < numInterfaces; i++)
{
fprintf(stderr,"Examining interface %d\n", i);
if(!nonLoopbackOnly || !isLoopback(tcpFile, &ifInfo[i].entity_id))
{
fprintf(stderr,"Interface %d matches (%ld)\n", i, curInterface);
ret->indexes[curInterface++] = ifInfo[i].if_info.ent.if_index;
}
}
ret->numIndexes = curInterface;
}
tdiFreeThingSet(ifInfo);
}
closeTcpFile(tcpFile);
}
return ret;
}
InterfaceIndexTable *
getInterfaceIndexTable(void)
{
return getInterfaceIndexTableInt(FALSE);
}
#endif
/*
* We need this in the Microsoft C/C++ port, as we're not using Pthreads, and jeff insists
* on naming the threads at runtime.
* Apparently throwing exception 1080890248 is only visible when running under a machine
* code monitor.
*
* -despair86 30/07/18
*/
#ifdef _MSC_VER
#include <windows.h>
#define EXCEPTION_SET_THREAD_NAME ((DWORD)0x406D1388)
typedef struct _THREADNAME_INFO
{
DWORD dwType; /* must be 0x1000 */
LPCSTR szName; /* pointer to name (in user addr space) */
DWORD dwThreadID; /* thread ID (-1=caller thread) */
DWORD dwFlags; /* reserved for future use, must be zero */
} THREADNAME_INFO;
void
SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
{
THREADNAME_INFO info;
DWORD infosize;
info.dwType = 0x1000;
info.szName = szThreadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
infosize = sizeof(info) / sizeof(DWORD);
__try
{
RaiseException(EXCEPTION_SET_THREAD_NAME, 0, infosize, (DWORD *)&info);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
#endif

@ -0,0 +1,111 @@
#ifndef WIN32_INTRNL_H
#define WIN32_INTRNL_H
/* if yer using Microsoft C++, then downlevel platforms are irrelevant to you */
#if defined(__MINGW32__) && !defined(_WIN64)
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
#include <tdiinfo.h>
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned int uint;
/* forward declare, each module has their own idea of what this is */
typedef struct _InterfaceIndexTable InterfaceIndexTable;
typedef struct IFEntry
{
ulong if_index;
ulong if_type;
ulong if_mtu;
ulong if_speed;
ulong if_physaddrlen;
uchar if_physaddr[8];
ulong if_adminstatus;
ulong if_operstatus;
ulong if_lastchange;
ulong if_inoctets;
ulong if_inucastpkts;
ulong if_innucastpkts;
ulong if_indiscards;
ulong if_inerrors;
ulong if_inunknownprotos;
ulong if_outoctets;
ulong if_outucastpkts;
ulong if_outnucastpkts;
ulong if_outdiscards;
ulong if_outerrors;
ulong if_outqlen;
ulong if_descrlen;
uchar if_descr[1];
} IFEntry;
typedef struct IPAddrEntry
{
ulong iae_addr;
ulong iae_index;
ulong iae_mask;
ulong iae_bcastaddr;
ulong iae_reasmsize;
ushort iae_context;
ushort iae_pad;
} IPAddrEntry;
typedef union _IFEntrySafelySized {
CHAR MaxSize[sizeof(DWORD) + sizeof(IFEntry) + 128 + 1];
IFEntry ent;
} IFEntrySafelySized;
#ifndef IFENT_SOFTWARE_LOOPBACK
#define IFENT_SOFTWARE_LOOPBACK 24 /* This is an SNMP constant from rfc1213 */
#endif /*IFENT_SOFTWARE_LOOPBACK*/
/* Encapsulates information about an interface */
typedef struct _IFInfo
{
TDIEntityID entity_id;
IFEntrySafelySized if_info;
IPAddrEntry ip_addr;
} IFInfo;
/* functions */
NTSTATUS
openTcpFile(PHANDLE tcpFile, ACCESS_MASK DesiredAccess);
VOID
closeTcpFile(HANDLE h);
BOOL
isLoopback(HANDLE tcpFile, TDIEntityID* loop_maybe);
BOOL
isIpEntity(HANDLE tcpFile, TDIEntityID* ent);
NTSTATUS
getNthIpEntity(HANDLE tcpFile, DWORD index, TDIEntityID* ent);
BOOL
isInterface(TDIEntityID* if_maybe);
NTSTATUS
getInterfaceInfoSet(HANDLE tcpFile, IFInfo** infoSet, PDWORD numInterfaces);
NTSTATUS
getInterfaceInfoByName(HANDLE tcpFile, char* name, IFInfo* info);
NTSTATUS
getInterfaceInfoByIndex(HANDLE tcpFile, DWORD index, IFInfo* info);
NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile, char* name, DWORD index, IFInfo* ifInfo);
InterfaceIndexTable*
getInterfaceIndexTableInt(BOOL nonLoopbackOnly);
InterfaceIndexTable*
getInterfaceIndexTable(void);
#endif
#endif

@ -3,31 +3,79 @@
Lokinet is a private, decentralized and Sybil resistant overlay network for the internet, it uses a new routing protocol called LLARP (Low latency anonymous routing protocol)
You can learn more about the high level design of LLARP [here](doc/high-level.txt)
And you can read the LLARP protocol specification [here](doc/proto_v0.txt)
## Building
# or your OS or distro's package manager
$ sudo apt install build-essential libtool autoconf cmake git
$ git clone --recursive https://github.com/loki-project/lokinet-builder
$ cd lokinet-builder
$ make
## Building on Windows (mingw-w64 native, or wow64/linux/unix cross-compiler)
#i686 or x86_64
#if cross-compiling from anywhere other than wow64, export CC and CXX to
#$ARCH-w64-mingw32-g[cc++] respectively
$ pacman -Sy base-devel mingw-w64-$ARCH-toolchain git libtool autoconf cmake
$ git clone --recursive https://github.com/loki-project/lokinet-builder
$ cd lokinet-builder
$ make ensure sodium
$ cd build
$ cmake ../deps/llarp -DSODIUM_LIBRARIES=./prefix/lib/libsodium.a -DSODIUM_INCLUDE_DIR=./prefix/include -G "Unix Makefiles" -DHAVE_CXX17_FILESYSTEM=ON
$ make
$ cp llarpd ../lokinet.exe
## Building on Windows using Microsoft C/C++ (Visual Studio 2017)
* clone https://github.com/loki-project/lokinet-builder from git-bash or whatever git browser you use
* open `%CLONE_PATH%/lokinet-builder/deps/sodium/builds/msvc/vs2017/libsodium.sln` and build one of the targets
* create a `build` folder in `%CLONE_PATH%/lokinet-builder`
* run cmake-gui from `%CLONE_PATH%/lokinet-builder/deps/llarp` as the source directory
* define `SODIUM_LIB` to `%CLONE_PATH%/lokinet-builder/deps/sodium/bin/win32/%CONFIG%/%TOOLSET%/%TARGET%/libsodium.lib`
* define `SODIUM_INCLUDE_DIR` to `%CLONE_PATH%/lokinet-builder/deps/sodium/src/libsodium/include`
* define `HAVE_CXX17_FILESYSTEM` to `TRUE`
* select `Visual Studio 2017 15 %ARCH%` as the generator
* enter a custom toolset if desired (usually `v141_xp`)
* generate the developer studio project files and open in the IDE
* select a configuration
* press F7 to build everything
## Running
$ ./lokinet
or press `Debug`/`Local Windows Debugger` in the visual studio standard toolbar
### Development
Please note development builds are likely to be unstable
Please note development builds are likely to be unstable.
Build requirements:
##### Build requirements:
* CMake
* ninja
* libsodium >= 1.0.14
* ninja (for unit testing with Google Tests)
* libsodium >= 1.0.14 (included here)
* c++ 11 capable C++ compiler
* if you have C++17 `<filesystem>` or `<experimental/filesystem>` declared and defined in your platform's C++ toolchain, re-run CMake (in `lokinet-builder/build`) with `-DHAVE_CXX17_FILESYSTEM=ON`.
* since each platform seems to have its own idea of where `std::[experimental::]filesystem` is defined, you will need to manually specify its library in `LDFLAGS` or `CMAKE_x_LINKER_FLAGS` as well.
##### Windows:
* Mingw-w64 is recommended for 32 or 64-bit builds.
* It *is* possible to compile with Microsoft C++ (v19 or later from VS2015+).
* `cpp17::filesystem` in `vendor/cppbackport-master` is not available for Windows.
#### Boxed warning
<div style="border:5px solid #f00;padding:5px">
<p>Inbound sessions are unsupported on Windows Server systems.</p>
<p><strong><em>Ignore this warning at your own peril.</em></strong></p>
</div>
Building a debug build:
##### Building a debug build:
#in lokinet-builder/
$ cd build
$ make

@ -30,18 +30,21 @@
#ifndef PBL_CPP_FILESYSTEM_H
#define PBL_CPP_FILESYSTEM_H
#include "version.h"
#if _MSC_VER >= 1910
#define CPP17
#define CPP11
#define CPP14
#endif
// linux gcc 7.2 has CPP17 but doesn't have filesystem.h
#if defined(CPP17) && !defined(__OpenBSD__) && __has_include(<filesystem>)
#include "version.h"
#if defined(__MINGW32__)
// mingw32 needs experimental
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
#if defined(__MINGW32__) || defined(_MSC_VER)
// win32 needs experimental
#include <experimental/filesystem>
#else
#include <filesystem>
#endif
#else
// OpenBSD needs this
// MacOS llvm 3.8 needs this
@ -61,6 +64,6 @@
#include "fs/remove.h"
#include "fs/rename.h"
#include "fs/tempdir.h"
#endif // if not cpp17 and not openbsd
#endif // if not cpp17 and not openbsd
#endif // PBL_CPP_FILESYSTEM_H

@ -64,7 +64,8 @@ namespace
{
t = file_type::fifo;
}
else if ( S_ISLNK(m) )
#ifndef _WIN32 // these only work on cygnus or msys2!
else if(S_ISLNK(m))
{
t = file_type::symlink;
}
@ -72,9 +73,8 @@ namespace
{
t = file_type::socket;
}
#endif
return ::cpp17::filesystem::file_status(t, p);
}
}
@ -156,13 +156,15 @@ file_status symlink_status(const path& path_)
if ( !path_.empty() )
{
struct stat st;
if ( ::lstat(path_.c_str(), &st) == 0 )
#ifndef _WIN32
if(::lstat(path_.c_str(), &st) == 0)
#else
if(::stat(path_.c_str(), &st) == 0)
#endif
{
return from_mode_t(st.st_mode);
}
}
return file_status();
}

Loading…
Cancel
Save