mirror of https://github.com/oxen-io/lokinet
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
This commit is contained in:
parent
7622f6cef1
commit
bdc54835c2
113
CMakeLists.txt
113
CMakeLists.txt
|
@ -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
|
||||
|
|
18
llarp/ev.cpp
18
llarp/ev.cpp
|
@ -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();
|
||||
}
|
||||
|
|
11
llarp/ev.hpp
11
llarp/ev.hpp
|
@ -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>
|
||||
|
|
13
llarp/fs.hpp
13
llarp/fs.hpp
|
@ -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)
|
||||
|
|
703
llarp/net.cpp
703
llarp/net.cpp
|
@ -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
|
58
readme.md
58
readme.md
|
@ -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:
|
||||
|
||||
Building a debug build:
|
||||
* 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:
|
||||
|
||||
#in lokinet-builder/
|
||||
$ cd build
|
||||
$ make
|
|
@ -30,18 +30,21 @@
|
|||
#ifndef PBL_CPP_FILESYSTEM_H
|
||||
#define PBL_CPP_FILESYSTEM_H
|
||||
|
||||
#if _MSC_VER >= 1910
|
||||
#define CPP17
|
||||
#define CPP11
|
||||
#define CPP14
|
||||
#endif
|
||||
|
||||
#include "version.h"
|
||||
|
||||
// linux gcc 7.2 has CPP17 but doesn't have filesystem.h
|
||||
#if defined(CPP17) && !defined(__OpenBSD__) && __has_include(<filesystem>)
|
||||
|
||||
#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…
Reference in New Issue