Merge remote-tracking branch 'origin/dev' into disable-doh-using-isp-backdoor-provided-by-mozilla-thanks-from-nsa

pull/870/head
Jeff Becker 5 years ago
commit 64548ade2f
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -41,6 +41,10 @@ endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
# No in-source building
include(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out-of-source build. Create a build directory and run 'cmake ${CMAKE_SOURCE_DIR} [options]'.")
include(cmake/basic_definitions.cmake)
if(MSVC_VERSION)
@ -138,13 +142,6 @@ endif(WOW64_CROSS_COMPILE OR WIN64_CROSS_COMPILE)
if(DEBIAN)
add_definitions(-DDEBIAN)
elseif(NOT ANDROID AND NOT NON_PC_TARGET)
if (NOT USE_AVX2)
# Public binary releases
set(CRYPTO_FLAGS -march=nocona -mtune=core2 -mfpmath=sse)
else()
set(CRYPTO_FLAGS -march=haswell -mtune=native -mfpmath=sse)
endif()
endif()
# only needed if using AVX2
@ -167,8 +164,8 @@ endif()
if (NOT MSVC OR NOT MSVC_VERSION)
add_compile_options(${OPTIMIZE_FLAGS} ${CRYPTO_FLAGS})
endif()
add_subdirectory(${ABSEIL_DIR})
add_subdirectory(vendor/gtest)
add_subdirectory(${ABSEIL_DIR})
if (FS_LIB STREQUAL "cppbackport")
add_subdirectory(vendor)
@ -233,9 +230,6 @@ enable_testing()
if (NOT SHADOW)
add_subdirectory(test)
if(ANDROID)
add_library(${ANDROID_LIB} SHARED jni/lokinet_android.cpp)
set_property(TARGET ${ANDROID_LIB} PROPERTY CXX_STANDARD 14)
add_log_tag(${ANDROID_LIB})
target_link_libraries(${ANDROID_LIB} ${STATIC_LIB} ${LIBS})
add_subdirectory(jni)
endif(ANDROID)
endif()

@ -16,6 +16,8 @@ BUILD_TYPE ?= Debug
PYTHON ?= python
PYTHON3 ?= python3
FORMAT ?= clang-format
SETCAP ?= which setcap && setcap cap_net_admin,cap_net_bind_service=+eip
SHADOW_ROOT ?= $(HOME)/.shadow
@ -252,11 +254,11 @@ abyss: debug
$(ABYSS_EXE)
format:
clang-format -i $$(find jni daemon llarp include libabyss | grep -E '\.[h,c](pp)?$$')
$(FORMAT) -i $$(find jni daemon llarp include libabyss | grep -E '\.[h,c](pp)?$$')
format-verify: format
(type clang-format)
clang-format --version
(type $(FORMAT))
$(FORMAT) --version
git diff --quiet || (echo 'Please run make format!!' && git --no-pager diff ; exit 1)
analyze-config: clean

@ -33,20 +33,16 @@ import android.widget.TextView;
public class LokiNetActivity extends Activity {
private static final String TAG = "lokinet-activity";
private TextView textView;
private static final String DefaultBootstrapURL = "https://i2p.rocks/bootstrap.signed";
private static final String DefaultBootstrapURL = "https://seed.lokinet.org/bootstrap.signed";
private AsyncBootstrap bootstrapper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// copy assets
//String conf = copyFileAsset("daemon.ini");
textView = new TextView(this);
setContentView(textView);
Lokinet_JNI.loadLibraries();
System.loadLibrary("lokinetandroid");
}

@ -5,4 +5,5 @@ import android.net.VpnService;
public class LokinetService extends VpnService
{
}

@ -1,44 +0,0 @@
package network.loki.lokinet;
public class Lokinet_JNI {
public static final String STATUS_OK = "ok";
public static native String getABICompiledWith();
/**
* returns error info if failed
* returns "ok" if daemon initialized and started okay
*/
public static native String startLokinet(String config);
/**
* stop daemon if running
*/
public static native void stopLokinet();
/** get interface address we want */
public static native String getIfAddr();
/** get interface address range we want */
public static native int getIfRange();
/**
* change network status
*/
public static native void onNetworkStateChanged(boolean isConnected);
/**
* set vpn network interface fd pair
* @param rfd the file descriptor of read end
* @param wfd the file descriptor of the write end
*/
public static native void setVPNFileDescriptor(int rfd, int wfd);
/**
* load jni libraries
*/
public static void loadLibraries() {
System.loadLibrary("lokinetandroid");
}
}

@ -21,8 +21,6 @@ public class NetworkStateChangeReceiver extends BroadcastReceiver {
boolean isConnected = activeNetworkInfo!=null && activeNetworkInfo.isConnected();
// https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html?hl=ru
// boolean isWiFi = activeNetworkInfo!=null && (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
Lokinet_JNI.onNetworkStateChanged(isConnected);
} catch (Throwable tr) {
Log.d(TAG,"",tr);
}

@ -0,0 +1,39 @@
# - MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
# MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license:
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage)
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource)
if (_insource)
message(SEND_ERROR "${_errorMessage}")
message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.")
endif (_insource)
endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD)

@ -1,6 +1,6 @@
set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
set(TOOLCHAIN_SUFFIX "")
set(TOOLCHAIN_SUFFIX "-posix")
set(WIN64_CROSS_COMPILE ON)
set(TOOLCHAIN_PATHS

@ -14,6 +14,7 @@
#include <cxxopts.hpp>
#include <string>
#include <iostream>
#include <future>
#ifdef _WIN32
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
@ -85,12 +86,12 @@ resolvePath(std::string conffname)
/// this sets up, configures and runs the main context
static void
run_main_context(std::string conffname, bool multiThreaded, bool backgroundMode)
run_main_context(std::string conffname, llarp_main_runtime_opts opts)
{
// this is important, can downgrade from Info though
llarp::LogDebug("Running from: ", fs::current_path().string());
llarp::LogInfo("Using config file: ", conffname);
ctx = llarp_main_init(conffname.c_str(), multiThreaded);
ctx = llarp_main_init(conffname.c_str());
int code = 1;
if(ctx)
{
@ -102,7 +103,7 @@ run_main_context(std::string conffname, bool multiThreaded, bool backgroundMode)
code = llarp_main_setup(ctx);
llarp::util::SetThreadName("llarp-mainloop");
if(code == 0)
code = llarp_main_run(ctx, backgroundMode);
code = llarp_main_run(ctx, opts);
llarp_main_free(ctx);
}
exit_code.set_value(code);
@ -111,11 +112,11 @@ run_main_context(std::string conffname, bool multiThreaded, bool backgroundMode)
int
main(int argc, char *argv[])
{
bool multiThreaded = true;
llarp_main_runtime_opts opts;
const char *singleThreadVar = getenv("LLARP_SHADOW");
if(singleThreadVar && std::string(singleThreadVar) == "1")
{
multiThreaded = false;
opts.singleThreaded = true;
}
#ifdef _WIN32
@ -148,12 +149,10 @@ main(int argc, char *argv[])
options.parse_positional("config");
// clang-format on
bool genconfigOnly = false;
bool asRouter = false;
bool overWrite = false;
bool backgroundMode = false;
bool genconfigOnly = false;
bool asRouter = false;
bool overWrite = false;
std::string conffname; // suggestions: confFName? conf_fname?
try
{
auto result = options.parse(argc, argv);
@ -178,7 +177,7 @@ main(int argc, char *argv[])
if(result.count("version"))
{
std::cout << LLARP_VERSION << std::endl;
std::cout << llarp_version() << std::endl;
return 0;
}
@ -189,7 +188,7 @@ main(int argc, char *argv[])
if(result.count("background") > 0)
{
backgroundMode = true;
opts.background = true;
}
if(result.count("force") > 0)
@ -315,8 +314,7 @@ main(int argc, char *argv[])
return 0;
}
std::thread main_thread{
std::bind(&run_main_context, conffname, multiThreaded, backgroundMode)};
std::thread main_thread{std::bind(&run_main_context, conffname, opts)};
auto ftr = exit_code.get_future();
do
{
@ -324,11 +322,9 @@ main(int argc, char *argv[])
} while(ftr.wait_for(std::chrono::seconds(1)) != std::future_status::ready);
main_thread.join();
const auto code = ftr.get();
#ifdef _WIN32
::WSACleanup();
#endif
const auto code = ftr.get();
exit(code);
return code;
}

@ -1,15 +1,8 @@
#ifndef LLARP_H_
#define LLARP_H_
#include <stdint.h>
#include <unistd.h>
#ifdef __cplusplus
#include <constants/version.hpp>
#include <ev/ev.h>
#include <handlers/tun.hpp> // for handlers
#include <service/address.hpp> // for service::address
#include <service/endpoint.hpp>
#include <util/thread/logic.hpp>
#include <util/mem.h>
extern "C"
{
#endif
@ -27,106 +20,211 @@ extern "C"
/// llarp application context for C api
struct llarp_main;
/// initialize application context and load config
struct llarp_main *
llarp_main_init(const char *fname, bool multiProcess);
/// handle signal for main context
void
llarp_main_signal(struct llarp_main *ptr, int sig);
/// give main context a vpn file descriptor pair (android/ios)
void
llarp_main_inject_vpn_fd(struct llarp_main *m, int rfd, int wfd);
/// runtime options for main context from cli
struct llarp_main_runtime_opts
{
bool background = false;
bool debug = false;
bool singleThreaded = false;
};
/// setup main context, returns 0 on success
int
llarp_main_setup(struct llarp_main *ptr);
/// llarp_application config
struct llarp_config;
/// run main context, returns 0 on success, blocks until program end
int
llarp_main_run(struct llarp_main *ptr, bool backgroundMode);
/// get default config for current platform
struct llarp_config *
llarp_default_config();
/// free main context and end all operations
/// free previously allocated configuration
void
llarp_main_free(struct llarp_main *ptr);
llarp_config_free(struct llarp_config *);
/// packet writer to send packets to lokinet internals
struct llarp_vpn_writer_pipe;
/// packet reader to recv packets from lokinet internals
struct llarp_vpn_reader_pipe;
/// vpn io api
/// all hooks called in native code
/// for use with a vpn interface managed by external code
/// the external vpn interface MUST be up and have addresses set
struct llarp_vpn_io
{
/// private implementation
void *impl;
/// user data
void *user;
/// hook set by user called by lokinet core when lokinet is done with the
/// vpn io
void (*closed)(struct llarp_vpn_io *);
/// hook set by user called from lokinet core after attempting to inject
/// into endpoint passed a bool set to true if we were injected otherwise
/// set to false
void (*injected)(struct llarp_vpn_io *, bool);
/// hook set by user called every event loop tick
void (*tick)(struct llarp_vpn_io *);
};
#ifdef __cplusplus
/// info about the network interface that we give to lokinet core
struct llarp_vpn_ifaddr_info
{
/// name of the network interface
char ifname[64];
/// interface's address as string
char ifaddr[128];
/// netmask number of bits set
uint8_t netmask;
};
/// initialize llarp_vpn_io private implementation
/// returns false if either parameter is nullptr
bool
llarp_vpn_io_init(struct llarp_main *m, struct llarp_vpn_io *io);
/// get the packet pipe for writing IP packets to lokinet internals
/// returns nullptr if llarp_vpn_io is nullptr or not initialized
struct llarp_vpn_pkt_writer *
llarp_vpn_io_packet_writer(struct llarp_vpn_io *io);
/// get the packet pipe for reading IP packets from lokinet internals
/// returns nullptr if llarp_vpn_io is nullptr or not initialized
struct llarp_vpn_pkt_reader *
llarp_vpn_io_packet_reader(struct llarp_vpn_io *io);
/// blocking read on packet reader from lokinet internals
/// returns -1 on error, returns size of packet read
/// thread safe
ssize_t
llarp_vpn_io_readpkt(struct llarp_vpn_pkt_reader *r, unsigned char *dst,
size_t dstlen);
/// blocking write on packet writer to lokinet internals
/// returns false if we can't write this packet
/// return true if we wrote this packet
/// thread safe
bool
llarp_vpn_io_writepkt(struct llarp_vpn_pkt_writer *w, unsigned char *pktbuf,
size_t pktlen);
/// close vpn io and free private implementation after done
/// operation is async and calls llarp_vpn_io.closed after fully closed
/// after fully closed the llarp_vpn_io MUST be re-initialized by
/// llarp_vpn_io_init if it is to be used again
void
llarp_main_abort(struct llarp_main *ptr);
llarp_vpn_io_close_async(struct llarp_vpn_io *io);
/// get the default endpoint's name for injection
const char *
handleBaseCmdLineArgs(int argc, char *argv[]);
llarp_main_get_default_endpoint_name(struct llarp_main *m);
/// load nodeDB into memory
int
llarp_main_loadDatabase(struct llarp_main *ptr);
/// iterator on nodedb entries
int
llarp_main_iterateDatabase(struct llarp_main *ptr,
struct llarp_nodedb_iter i);
/// give main context a vpn io for mobile when it is reader to do io with
/// associated info tries to give the vpn io to endpoint with name epName a
/// deferred call to llarp_vpn_io.injected is queued unconditionally
/// thread safe
bool
llarp_main_inject_vpn_by_name(struct llarp_main *m, const char *epName,
struct llarp_vpn_io *io,
struct llarp_vpn_ifaddr_info info);
/// give main context a vpn io on its default endpoint
static bool
llarp_main_inject_default_vpn(struct llarp_main *m, struct llarp_vpn_io *io,
struct llarp_vpn_ifaddr_info info)
{
return llarp_main_inject_vpn_by_name(
m, llarp_main_get_default_endpoint_name(m), io, info);
}
/// put RC into nodeDB
/// load config from file by name
/// allocates new config and puts it into c
/// return false on failure
bool
llarp_main_putDatabase(struct llarp_main *ptr,
struct llarp::RouterContact &rc);
llarp_config_load_file(const char *fname, struct llarp_config **c);
// fwd declr
struct check_online_request;
/// loads config from file by name
/// uses already allocated config
/// return false on failure
bool
llarp_config_read_file(struct llarp_config *c, const char *f);
/// check_online_request hook definition
typedef void (*check_online_request_hook_func)(struct check_online_request *);
/// make a main context from configuration
/// copies config contents
struct llarp_main *
llarp_main_init_from_config(struct llarp_config *conf);
struct check_online_request
/// initialize application context and load config
static struct llarp_main *
llarp_main_init(const char *fname)
{
struct llarp_main *ptr;
struct llarp_router_lookup_job *job;
bool online;
size_t nodes;
bool first;
check_online_request_hook_func hook;
};
struct llarp_main *m = 0;
struct llarp_config *conf = 0;
if(!llarp_config_load_file(fname, &conf))
return 0;
if(conf == NULL)
return 0;
m = llarp_main_init_from_config(conf);
llarp_config_free(conf);
return m;
}
/// initialize applicatin context with all defaults
static struct llarp_main *
llarp_main_default_init()
{
struct llarp_main *m;
struct llarp_config *conf;
conf = llarp_default_config();
if(conf == 0)
return 0;
m = llarp_main_init_from_config(conf);
llarp_config_free(conf);
return m;
}
/// (re)configure main context
/// return true if (re)configuration was successful
bool
llarp_main_configure(struct llarp_main *ptr, struct llarp_config *conf);
/// get RC from DHT but wait until online
void
llarp_main_queryDHT(struct check_online_request *request);
/// return true if this main context is running
/// return false otherwise
bool
llarp_main_is_running(struct llarp_main *ptr);
/// get RC from DHT
/// handle signal for main context
void
llarp_main_queryDHT_RC(struct llarp_main *ptr,
struct llarp_router_lookup_job *job);
llarp_main_signal(struct llarp_main *ptr, int sig);
/// set up DNS libs with a context
bool
llarp_main_init_dnsd(struct llarp_main *ptr, struct dnsd_context *dnsd,
const llarp::Addr &dnsd_sockaddr,
const llarp::Addr &dnsc_sockaddr);
/// setup main context, returns 0 on success
int
llarp_main_setup(struct llarp_main *ptr);
/// set up dotLokiLookup with logic for setting timers
bool
llarp_main_init_dotLokiLookup(struct llarp_main *ptr,
struct dotLokiLookup *dll);
/// run main context, returns 0 on success, blocks until program end
int
llarp_main_run(struct llarp_main *ptr, struct llarp_main_runtime_opts opts);
/// tell main context to stop and wait for complete stop
/// after calling this you can call llarp_main_free safely
void
llarp_main_stop(struct llarp_main *ptr);
/// free main context and end all operations
void
llarp_main_free(struct llarp_main *ptr);
llarp::RouterContact *
llarp_main_getLocalRC(struct llarp_main *ptr);
/// get RC from nodeDB
llarp::RouterContact *
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk);
/// get version string
const char *
llarp_version();
llarp_tun_io *
main_router_getRange(struct llarp_main *ptr);
/// return sizeof(llarp_main); for jni
size_t
llarp_main_size();
/// map an (host byte order) ip to a hidden service address
bool
main_router_mapAddress(struct llarp_main *ptr,
const llarp::service::Address &addr, uint32_t ip);
/// return sizeof(llarp_config); for jni
size_t
llarp_config_size();
/// info of possible path usage
bool
main_router_prefetch(struct llarp_main *ptr,
const llarp::service::Address &addr);
#ifdef __cplusplus
}
#endif
#endif

@ -1,6 +1,6 @@
#ifndef LLARP_HPP
#define LLARP_HPP
#include <llarp.h>
#include <util/fs.hpp>
#include <util/types.hpp>
#include <ev/ev.hpp>
@ -43,6 +43,10 @@ namespace llarp
struct Context
{
/// get context from main pointer
static Context *
Get(llarp_main *);
Context();
~Context();
@ -71,24 +75,32 @@ namespace llarp
int
LoadDatabase();
int
IterateDatabase(llarp_nodedb_iter &i);
bool
PutDatabase(struct llarp::RouterContact &rc);
llarp::RouterContact *
GetDatabase(const byte_t *pk);
int
Setup();
int
Run(bool daemonMode);
Run(llarp_main_runtime_opts opts);
void
HandleSignal(int sig);
bool
Configure();
/// close async
void
CloseAsync();
/// wait until closed and done
void
Wait();
/// call a function in logic thread
/// return true if queued for calling
/// return false if not queued for calling
bool
CallSafe(std::function< void(void) > f);
private:
void
SetPIDFile(const std::string &fname);
@ -99,9 +111,6 @@ namespace llarp
void
RemovePIDFile() const;
bool
Configure();
void
SigINT();
@ -116,10 +125,8 @@ namespace llarp
std::string configfile;
std::string pidfile;
std::unique_ptr< std::promise< void > > closeWaiter;
};
} // namespace llarp
llarp::Context *
llarp_main_get_context(llarp_main *m);
#endif

@ -35,11 +35,9 @@
#if !defined Linux
#include <netinet/in.h>
#endif
#if defined Linux
#include <linux/if.h>
#else
#include <net/if.h>
#endif
#if defined Linux
#include <netinet/in.h>
#elif defined(iOS)

@ -0,0 +1,10 @@
set(ANDROID_SRC
lokinet_config.cpp
lokinet_daemon.cpp
lokinet_vpn.cpp
)
add_library(${ANDROID_LIB} SHARED ${ANDROID_SRC})
set_property(TARGET ${ANDROID_LIB} PROPERTY CXX_STANDARD 14)
add_log_tag(${ANDROID_LIB})
target_link_libraries(${ANDROID_LIB} ${STATIC_LIB} ${LIBS})

@ -1,237 +0,0 @@
#include <llarp.h>
#include <config/config.hpp>
#include <util/fs.hpp>
#include <llarp.hpp>
#include <router/router.hpp>
#include <jni.h>
#include <signal.h>
#include <memory>
#include <thread>
struct AndroidMain
{
llarp_main* m_impl = nullptr;
std::thread* m_thread = nullptr;
std::string configFile;
/// set configuration and ensure files
bool
Configure(const char* conf, const char* basedir)
{
configFile = conf;
return llarp_ensure_config(conf, basedir, false, false);
}
/// reload config on runtime
bool
ReloadConfig()
{
if(!m_impl)
return false;
llarp_main_signal(m_impl, SIGHUP);
return true;
}
/// start daemon thread
bool
Start()
{
if(m_impl || m_thread)
return true;
m_impl = llarp_main_init(configFile.c_str(), true);
if(m_impl == nullptr)
return false;
if(llarp_main_setup(m_impl, false))
{
llarp_main_free(m_impl);
m_impl = nullptr;
return false;
}
m_thread = new std::thread(std::bind(&AndroidMain::Run, this));
return true;
}
/// return true if we are running
bool
Running() const
{
return m_impl != nullptr && m_thread != nullptr;
}
/// blocking run
void
Run()
{
if(llarp_main_run(m_impl))
{
// on error
llarp::LogError("daemon run fail");
llarp_main* ptr = m_impl;
m_impl = nullptr;
llarp_main_signal(ptr, SIGINT);
llarp_main_free(ptr);
}
}
const char*
GetIfAddr()
{
std::string addr;
if(m_impl)
{
auto* ctx = llarp_main_get_context(m_impl);
if(!ctx)
return "";
ctx->router->hiddenServiceContext().ForEachService(
[&addr](const std::string&,
const llarp::service::Endpoint_ptr& ep) -> bool {
if(addr.empty())
{
if(ep->HasIfAddr())
{
// TODO: v4
const auto ip = ep->GetIfAddr();
if(ip.h)
{
addr = ip.ToString();
return false;
}
}
}
return true;
});
}
return addr.c_str();
}
int
GetIfRange() const
{
if(m_impl)
{
auto* ctx = llarp_main_get_context(m_impl);
if(!ctx)
return -1;
}
return -1;
}
void
SetVPN_FD(int rfd, int wfd)
{
(void)rfd;
(void)wfd;
// if(m_impl)
// llarp_main_inject_vpn_fd(m_impl, rfd, wfd);
}
/// stop daemon thread
void
Stop()
{
if(m_impl)
llarp_main_signal(m_impl, SIGINT);
m_thread->join();
delete m_thread;
m_thread = nullptr;
if(m_impl)
llarp_main_free(m_impl);
m_impl = nullptr;
}
typedef std::unique_ptr< AndroidMain > Ptr;
};
static AndroidMain::Ptr daemon_ptr(new AndroidMain());
extern "C"
{
JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_getABICompiledWith(JNIEnv* env, jclass)
{
// TODO: fixme
return env->NewStringUTF("android");
}
JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_startLokinet(JNIEnv* env, jclass,
jstring configfile)
{
if(daemon_ptr->Running())
return env->NewStringUTF("already running");
std::string conf;
fs::path basepath;
{
const char* nativeString = env->GetStringUTFChars(configfile, JNI_FALSE);
conf += std::string(nativeString);
env->ReleaseStringUTFChars(configfile, nativeString);
basepath = fs::path(conf).parent_path();
}
if(daemon_ptr->Configure(conf.c_str(), basepath.string().c_str()))
{
if(daemon_ptr->Start())
return env->NewStringUTF("ok");
else
return env->NewStringUTF("failed to start daemon");
}
else
return env->NewStringUTF("failed to configure daemon");
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_stopLokinet(JNIEnv*, jclass)
{
if(daemon_ptr->Running())
{
daemon_ptr->Stop();
}
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_setVPNFileDescriptor(JNIEnv*, jclass,
jint rfd,
jint wfd)
{
daemon_ptr->SetVPN_FD(rfd, wfd);
}
JNIEXPORT jstring JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_getIfAddr(JNIEnv* env, jclass)
{
if(daemon_ptr)
return env->NewStringUTF(daemon_ptr->GetIfAddr());
else
return env->NewStringUTF("");
}
JNIEXPORT jint JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_getIfRange(JNIEnv*, jclass)
{
if(daemon_ptr)
return daemon_ptr->GetIfRange();
else
return -1;
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_Lokinet_1JNI_onNetworkStateChanged(
JNIEnv*, jclass, jboolean isConnected)
{
if(isConnected)
{
if(!daemon_ptr->Running())
{
if(!daemon_ptr->Start())
{
// TODO: do some kind of callback here
}
}
}
else if(daemon_ptr->Running())
{
daemon_ptr->Stop();
}
}
}

@ -0,0 +1,37 @@
#include "network_loki_lokinet_LokinetConfig.h"
#include <llarp.hpp>
#include "lokinet_jni_common.hpp"
extern "C"
{
JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv* env, jclass)
{
llarp_config* conf = llarp_default_config();
if(conf == nullptr)
return nullptr;
return env->NewDirectByteBuffer(conf, llarp_config_size());
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv* env, jclass, jobject buf)
{
llarp_config_free(FromBuffer< llarp_config >(env, buf));
}
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv* env, jobject self,
jstring fname)
{
llarp_config* conf = GetImpl< llarp_config >(env, self);
if(conf == nullptr)
return JNI_FALSE;
return VisitStringAsStringView< jboolean >(
env, fname, [conf](llarp::string_view val) -> jboolean {
const auto filename = llarp::string_view_string(val);
if(llarp_config_read_file(conf, filename.c_str()))
return JNI_TRUE;
return JNI_FALSE;
});
}
}

@ -0,0 +1,83 @@
#include "network_loki_lokinet_LokinetDaemon.h"
#include "lokinet_jni_common.hpp"
#include "lokinet_jni_vpnio.hpp"
#include <llarp.h>
extern "C"
{
JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetDaemon_Obtain(JNIEnv *env, jclass)
{
llarp_main *ptr = llarp_main_default_init();
if(ptr == nullptr)
return nullptr;
return env->NewDirectByteBuffer(ptr, llarp_main_size());
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetDaemon_Free(JNIEnv *env, jclass, jobject buf)
{
llarp_main *ptr = FromBuffer< llarp_main >(env, buf);
llarp_main_free(ptr);
}
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv *env, jobject self,
jobject conf)
{
llarp_main *ptr = GetImpl< llarp_main >(env, self);
llarp_config *config = GetImpl< llarp_config >(env, conf);
if(ptr == nullptr || config == nullptr)
return JNI_FALSE;
if(llarp_main_configure(ptr, config))
return JNI_TRUE;
return llarp_main_setup(ptr) == 0 ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv *env, jobject self)
{
static llarp_main_runtime_opts opts;
llarp_main *ptr = GetImpl< llarp_main >(env, self);
if(ptr == nullptr)
return -1;
return llarp_main_run(ptr, opts);
}
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv *env, jobject self)
{
llarp_main *ptr = GetImpl< llarp_main >(env, self);
return (ptr != nullptr && llarp_main_is_running(ptr)) ? JNI_TRUE
: JNI_FALSE;
}
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv *env, jobject self)
{
llarp_main *ptr = GetImpl< llarp_main >(env, self);
if(ptr == nullptr)
return JNI_FALSE;
if(not llarp_main_is_running(ptr))
return JNI_FALSE;
llarp_main_stop(ptr);
return llarp_main_is_running(ptr) ? JNI_FALSE : JNI_TRUE;
}
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv *env, jobject self,
jobject vpn)
{
llarp_main *ptr = GetImpl< llarp_main >(env, self);
lokinet_jni_vpnio *impl = GetImpl< lokinet_jni_vpnio >(env, vpn);
if(ptr == nullptr || impl == nullptr)
return JNI_FALSE;
if(impl->info.netmask == 0)
return JNI_FALSE;
if(not impl->Init(ptr))
return JNI_FALSE;
return llarp_main_inject_default_vpn(ptr, &impl->io, impl->info)
? JNI_TRUE
: JNI_FALSE;
}
}

@ -0,0 +1,85 @@
#ifndef LOKINET_JNI_COMMON_HPP
#define LOKINET_JNI_COMMON_HPP
#include <jni.h>
#include <util/string_view.hpp>
#include <functional>
/// visit string as native bytes
/// jvm uses some unholy encoding internally so we convert it to utf-8
template < typename T, typename V >
static T
VisitStringAsStringView(JNIEnv* env, jobject str, V visit)
{
const jclass stringClass = env->GetObjectClass(str);
const jmethodID getBytes =
env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
const jstring charsetName = env->NewStringUTF("UTF-8");
const jbyteArray stringJbytes =
(jbyteArray)env->CallObjectMethod(str, getBytes, charsetName);
env->DeleteLocalRef(charsetName);
const size_t length = env->GetArrayLength(stringJbytes);
jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
T result = visit(llarp::string_view((const char*)pBytes, length));
env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
env->DeleteLocalRef(stringJbytes);
return std::move(result);
}
/// cast jni buffer to T *
template < typename T >
static T*
FromBuffer(JNIEnv* env, jobject o)
{
if(o == nullptr)
return nullptr;
return static_cast< T* >(env->GetDirectBufferAddress(o));
}
/// get T * from object member called membername
template < typename T >
static T*
FromObjectMember(JNIEnv* env, jobject self, const char* membername)
{
jclass cl = env->GetObjectClass(self);
jfieldID name = env->GetFieldID(cl, membername, "Ljava/nio/Buffer;");
jobject buffer = env->GetObjectField(self, name);
return FromBuffer< T >(env, buffer);
}
/// visit object string member called membername as bytes
template < typename T, typename V >
static T
VisitObjectMemberStringAsStringView(JNIEnv* env, jobject self,
const char* membername, V v)
{
jclass cl = env->GetObjectClass(self);
jfieldID name = env->GetFieldID(cl, membername, "Ljava/lang/String;");
jobject str = env->GetObjectField(self, name);
return VisitStringAsStringView< T, V >(env, str, v);
}
/// get object member int called membername
template < typename Int_t >
Int_t
GetObjectMemberAsInt(JNIEnv* env, jobject self, const char* membername)
{
jclass cl = env->GetObjectClass(self);
jfieldID name = env->GetFieldID(cl, membername, "I");
return env->GetIntField(self, name);
}
/// get implementation on jni type
template < typename T >
T*
GetImpl(JNIEnv* env, jobject self)
{
return FromObjectMember< T >(env, self, "impl");
}
#endif

@ -0,0 +1,150 @@
#ifndef LOKINET_JNI_VPNIO_HPP
#define LOKINET_JNI_VPNIO_HPP
#include <llarp.h>
#include <memory>
#include <future>
#include <util/string_view.hpp>
#include <algorithm>
#include <jni.h>
namespace lokinet
{
struct VPNIO
{
static VPNIO *
Get(llarp_vpn_io *vpn)
{
return static_cast< VPNIO * >(vpn->user);
}
virtual ~VPNIO() = default;
llarp_vpn_io io;
llarp_vpn_ifaddr_info info{{0}, {0}, 0};
std::unique_ptr< std::promise< void > > closeWaiter;
void
Closed()
{
if(closeWaiter)
closeWaiter->set_value();
}
virtual void
InjectSuccess() = 0;
virtual void
InjectFail() = 0;
virtual void
Tick() = 0;
VPNIO()
{
io.impl = nullptr;
io.user = this;
io.closed = [](llarp_vpn_io *vpn) { VPNIO::Get(vpn)->Closed(); };
io.injected = [](llarp_vpn_io *vpn, bool good) {
VPNIO *ptr = VPNIO::Get(vpn);
if(good)
ptr->InjectSuccess();
else
ptr->InjectFail();
};
io.tick = [](llarp_vpn_io *vpn) { VPNIO::Get(vpn)->Tick(); };
}
bool
Init(llarp_main *ptr)
{
if(Ready())
return false;
return llarp_vpn_io_init(ptr, &io);
}
bool
Ready() const
{
return io.impl != nullptr;
}
void
Close()
{
if(not Ready())
return;
if(closeWaiter)
return;
closeWaiter = std::make_unique< std::promise< void > >();
llarp_vpn_io_close_async(&io);
closeWaiter->get_future().wait();
closeWaiter.reset();
io.impl = nullptr;
}
llarp_vpn_pkt_reader *
Reader()
{
return llarp_vpn_io_packet_reader(&io);
}
llarp_vpn_pkt_writer *
Writer()
{
return llarp_vpn_io_packet_writer(&io);
}
ssize_t
ReadPacket(void *dst, size_t len)
{
if(not Ready())
return -1;
unsigned char *buf = (unsigned char *)dst;
return llarp_vpn_io_readpkt(Reader(), buf, len);
}
bool
WritePacket(void *pkt, size_t len)
{
if(not Ready())
return false;
unsigned char *buf = (unsigned char *)pkt;
return llarp_vpn_io_writepkt(Writer(), buf, len);
}
void
SetIfName(llarp::string_view val)
{
const auto sz = std::min(val.size(), sizeof(info.ifname));
std::copy_n(val.data(), sz, info.ifname);
}
void
SetIfAddr(llarp::string_view val)
{
const auto sz = std::min(val.size(), sizeof(info.ifaddr));
std::copy_n(val.data(), sz, info.ifaddr);
}
};
} // namespace lokinet
struct lokinet_jni_vpnio : public lokinet::VPNIO
{
void
InjectSuccess() override
{
}
void
InjectFail() override
{
}
void
Tick() override
{
}
};
#endif

@ -0,0 +1,86 @@
#include "network_loki_lokinet_LokinetVPN.h"
#include "lokinet_jni_vpnio.hpp"
#include "lokinet_jni_common.hpp"
#include <net/ip.hpp>
extern "C"
{
JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetVPN_PacketSize(JNIEnv *, jclass)
{
return llarp::net::IPPacket::MaxSize;
}
JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetVPN_Alloc(JNIEnv *env, jclass)
{
lokinet_jni_vpnio *vpn = new lokinet_jni_vpnio();
return env->NewDirectByteBuffer(vpn, sizeof(lokinet_jni_vpnio));
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_Free(JNIEnv *env, jclass, jobject buf)
{
lokinet_jni_vpnio *vpn = FromBuffer< lokinet_jni_vpnio >(env, buf);
if(vpn == nullptr)
return;
delete vpn;
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv *env, jobject self)
{
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self);
if(vpn)
{
vpn->Close();
}
}
JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv *env, jobject self,
jobject pkt)
{
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self);
if(vpn == nullptr)
return -1;
void *pktbuf = env->GetDirectBufferAddress(pkt);
auto pktlen = env->GetDirectBufferCapacity(pkt);
if(pktbuf == nullptr)
return -1;
return vpn->ReadPacket(pktbuf, pktlen);
}
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv *env, jobject self,
jobject pkt)
{
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self);
if(vpn == nullptr)
return false;
void *pktbuf = env->GetDirectBufferAddress(pkt);
auto pktlen = env->GetDirectBufferCapacity(pkt);
if(pktbuf == nullptr)
return false;
return vpn->WritePacket(pktbuf, pktlen);
}
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv *env, jobject self,
jobject info)
{
lokinet_jni_vpnio *vpn = GetImpl< lokinet_jni_vpnio >(env, self);
if(vpn == nullptr)
return;
VisitObjectMemberStringAsStringView< bool >(
env, info, "ifaddr", [vpn](llarp::string_view val) -> bool {
vpn->SetIfAddr(val);
return true;
});
VisitObjectMemberStringAsStringView< bool >(
env, info, "ifname", [vpn](llarp::string_view val) -> bool {
vpn->SetIfName(val);
return true;
});
vpn->info.netmask = GetObjectMemberAsInt< uint8_t >(env, info, "netmask");
}
}

@ -0,0 +1,38 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class network_loki_lokinet_LokinetConfig */
#ifndef _Included_network_loki_lokinet_LokinetConfig
#define _Included_network_loki_lokinet_LokinetConfig
#ifdef __cplusplus
extern "C"
{
#endif
/*
* Class: network_loki_lokinet_LokinetConfig
* Method: Obtain
* Signature: ()Ljava/nio/Buffer;
*/
JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetConfig_Obtain(JNIEnv *, jclass);
/*
* Class: network_loki_lokinet_LokinetConfig
* Method: Free
* Signature: (Ljava/nio/Buffer;)V
*/
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetConfig_Free(JNIEnv *, jclass, jobject);
/*
* Class: network_loki_lokinet_LokinetConfig
* Method: Load
* Signature: (Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetConfig_Load(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,70 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class network_loki_lokinet_LokinetDaemon */
#ifndef _Included_network_loki_lokinet_LokinetDaemon
#define _Included_network_loki_lokinet_LokinetDaemon
#ifdef __cplusplus
extern "C"
{
#endif
/*
* Class: network_loki_lokinet_LokinetDaemon
* Method: Obtain
* Signature: ()Ljava/nio/Buffer;
*/
JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetDaemon_Obtain(JNIEnv *, jclass);
/*
* Class: network_loki_lokinet_LokinetDaemon
* Method: Free
* Signature: (Ljava/nio/Buffer;)V
*/
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetDaemon_Free(JNIEnv *, jclass, jobject);
/*
* Class: network_loki_lokinet_LokinetDaemon
* Method: Configure
* Signature: (Lnetwork/loki/lokinet/LokinetConfig;)Z
*/
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_Configure(JNIEnv *, jobject, jobject);
/*
* Class: network_loki_lokinet_LokinetDaemon
* Method: Mainloop
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetDaemon_Mainloop(JNIEnv *, jobject);
/*
* Class: network_loki_lokinet_LokinetDaemon
* Method: IsRunning
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_IsRunning(JNIEnv *, jobject);
/*
* Class: network_loki_lokinet_LokinetDaemon
* Method: Stop
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_Stop(JNIEnv *, jobject);
/*
* Class: network_loki_lokinet_LokinetDaemon
* Method: InjectVPN
* Signature: (Lnetwork/loki/lokinet/LokinetVPN;)Z
*/
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetDaemon_InjectVPN(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,69 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class network_loki_lokinet_LokinetVPN */
#ifndef _Included_network_loki_lokinet_LokinetVPN
#define _Included_network_loki_lokinet_LokinetVPN
#ifdef __cplusplus
extern "C"
{
#endif
/*
* Class: network_loki_lokinet_LokinetVPN
* Method: PacketSize
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetVPN_PacketSize(JNIEnv *, jclass);
/*
* Class: network_loki_lokinet_LokinetVPN
* Method: Alloc
* Signature: ()Ljava/nio/Buffer;
*/
JNIEXPORT jobject JNICALL
Java_network_loki_lokinet_LokinetVPN_Alloc(JNIEnv *, jclass);
/*
* Class: network_loki_lokinet_LokinetVPN
* Method: Free
* Signature: (Ljava/nio/Buffer;)V
*/
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_Free(JNIEnv *, jclass, jobject);
/*
* Class: network_loki_lokinet_LokinetVPN
* Method: Stop
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_Stop(JNIEnv *, jobject);
/*
* Class: network_loki_lokinet_LokinetVPN
* Method: ReadPkt
* Signature: (Ljava/nio/ByteBuffer;)I
*/
JNIEXPORT jint JNICALL
Java_network_loki_lokinet_LokinetVPN_ReadPkt(JNIEnv *, jobject, jobject);
/*
* Class: network_loki_lokinet_LokinetVPN
* Method: WritePkt
* Signature: (Ljava/nio/ByteBuffer;)Z
*/
JNIEXPORT jboolean JNICALL
Java_network_loki_lokinet_LokinetVPN_WritePkt(JNIEnv *, jobject, jobject);
/*
* Class: network_loki_lokinet_LokinetVPN
* Method: SetInfo
* Signature: (Lnetwork/loki/lokinet/LokinetVPN/VPNInfo;)V
*/
JNIEXPORT void JNICALL
Java_network_loki_lokinet_LokinetVPN_SetInfo(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,14 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class network_loki_lokinet_LokinetVPN_VPNInfo */
#ifndef _Included_network_loki_lokinet_LokinetVPN_VPNInfo
#define _Included_network_loki_lokinet_LokinetVPN_VPNInfo
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __cplusplus
}
#endif
#endif

@ -78,6 +78,7 @@ set(LIB_PLATFORM_SRC
# for networking
ev/ev.cpp
ev/pipe.cpp
ev/vpnio.cpp
net/ip.cpp
net/net.cpp
net/net_addr.cpp
@ -137,7 +138,6 @@ set(LIB_SRC
crypto/crypto_libsodium.cpp
crypto/crypto_noop.cpp
crypto/crypto.cpp
crypto/ec.cpp
crypto/encrypted_frame.cpp
crypto/encrypted.cpp
crypto/types.cpp

@ -1,5 +1,5 @@
#include <llarp.hpp>
#include <llarp.h>
#include <constants/version.hpp>
#include <config/config.hpp>
#include <crypto/crypto_libsodium.hpp>
@ -7,8 +7,10 @@
#include <dht/context.hpp>
#include <dnsd.hpp>
#include <ev/ev.hpp>
#include <ev/vpnio.hpp>
#include <nodedb.hpp>
#include <router/router.hpp>
#include <service/context.hpp>
#include <util/logging/logger.h>
#include <util/meta/memfn.hpp>
#include <util/metrics/json_publisher.hpp>
@ -34,6 +36,12 @@ namespace llarp
m_scheduler->stop();
}
bool
Context::CallSafe(std::function< void(void) > f)
{
return logic && logic->queue_func(std::move(f));
}
void
Context::progress()
{
@ -45,11 +53,14 @@ namespace llarp
{
logic = std::make_shared< Logic >();
// llarp::LogInfo("loading config at ", configfile);
if(!config->Load(configfile.c_str()))
if(configfile.size())
{
config.release();
llarp::LogError("failed to load config file ", configfile);
return false;
if(!config->Load(configfile.c_str()))
{
config.release();
llarp::LogError("failed to load config file ", configfile);
return false;
}
}
// System config
@ -176,22 +187,6 @@ __ ___ ____ _ _ ___ _ _ ____
return 1;
}
bool
Context::PutDatabase(__attribute__((unused)) struct llarp::RouterContact &rc)
{
// FIXME
// return llarp_nodedb_put_rc(nodedb, rc);
return false;
}
llarp::RouterContact *
Context::GetDatabase(__attribute__((unused)) const byte_t *pk)
{
// FIXME
// return llarp_nodedb_get_rc(nodedb, pk);
return nullptr;
}
int
Context::Setup()
{
@ -222,7 +217,7 @@ __ ___ ____ _ _ ___ _ _ ____
}
int
Context::Run(bool backgroundMode)
Context::Run(llarp_main_runtime_opts opts)
{
if(router == nullptr)
{
@ -236,7 +231,7 @@ __ ___ ____ _ _ ___ _ _ ____
if(!router->StartJsonRpc())
return 1;
if(!backgroundMode)
if(!opts.background)
{
if(!router->Run())
return 2;
@ -245,10 +240,34 @@ __ ___ ____ _ _ ___ _ _ ____
// run net io thread
llarp::LogInfo("running mainloop");
llarp_ev_loop_run_single_process(mainloop, logic);
// waits for router graceful stop
if(closeWaiter)
{
// inform promise if called by CloseAsync
closeWaiter->set_value();
}
return 0;
}
void
Context::CloseAsync()
{
/// already closing
if(closeWaiter)
return;
if(CallSafe(std::bind(&Context::HandleSignal, this, SIGTERM)))
closeWaiter = std::make_unique< std::promise< void > >();
}
void
Context::Wait()
{
if(closeWaiter)
{
closeWaiter->get_future().wait();
closeWaiter.reset();
}
}
bool
Context::WritePIDFile() const
{
@ -377,37 +396,87 @@ __ ___ ____ _ _ ___ _ _ ____
struct llarp_main
{
llarp_main(llarp_config *conf);
~llarp_main() = default;
std::unique_ptr< llarp::Context > ctx;
};
llarp::Context *
llarp_main_get_context(llarp_main *m)
struct llarp_config
{
return m->ctx.get();
}
llarp::Config impl;
llarp_config() = default;
llarp_config(const llarp_config *other) : impl(other->impl)
{
}
};
extern "C"
{
size_t
llarp_main_size()
{
return sizeof(llarp_main);
}
size_t
llarp_config_size()
{
return sizeof(llarp_config);
}
struct llarp_config *
llarp_default_config()
{
llarp_config *conf = new llarp_config();
#ifdef ANDROID
// put andrid config overrides here
#endif
#ifdef IOS
// put IOS config overrides here
#endif
return conf;
}
void
llarp_config_free(struct llarp_config *conf)
{
if(conf)
delete conf;
}
struct llarp_main *
llarp_main_init(const char *fname, bool multiProcess)
llarp_main_init_from_config(struct llarp_config *conf)
{
(void)multiProcess;
if(!fname)
fname = "daemon.ini";
char *var = getenv("LLARP_DEBUG");
if(var && *var == '1')
{
cSetLogLevel(eLogDebug);
}
auto *m = new llarp_main;
m->ctx = std::make_unique< llarp::Context >();
if(!m->ctx->LoadConfig(fname))
{
m->ctx->Close();
delete m;
if(conf == nullptr)
return nullptr;
llarp_main *m = new llarp_main(conf);
if(m->ctx->Configure())
return m;
delete m;
return nullptr;
}
bool
llarp_config_read_file(struct llarp_config *conf, const char *fname)
{
if(conf == nullptr)
return false;
return conf->impl.Load(fname);
}
bool
llarp_config_load_file(const char *fname, struct llarp_config **conf)
{
llarp_config *c = new llarp_config();
if(c->impl.Load(fname))
{
*conf = c;
return true;
}
return m;
delete c;
*conf = nullptr;
return false;
}
void
@ -424,47 +493,97 @@ extern "C"
}
int
llarp_main_run(struct llarp_main *ptr, bool backgroundMode)
llarp_main_run(struct llarp_main *ptr, struct llarp_main_runtime_opts opts)
{
if(!ptr)
{
llarp::LogError("No ptr passed in");
return 1;
}
return ptr->ctx->Run(backgroundMode);
return ptr->ctx->Run(opts);
}
void
llarp_main_abort(struct llarp_main *ptr)
const char *
llarp_version()
{
ptr->ctx->router->logic()->stop_timer();
return LLARP_VERSION;
}
void
llarp_main_queryDHT_RC(struct llarp_main *ptr,
struct llarp_router_lookup_job *job)
ssize_t
llarp_vpn_io_readpkt(struct llarp_vpn_pkt_reader *r, unsigned char *dst,
size_t dstlen)
{
llarp_dht_lookup_router(ptr->ctx->router->dht(), job);
if(r == nullptr)
return -1;
if(not r->queue.enabled())
return -1;
auto pkt = r->queue.popFront();
ManagedBuffer mbuf = pkt.ConstBuffer();
const llarp_buffer_t &buf = mbuf;
if(buf.sz > dstlen || buf.sz == 0)
return -1;
std::copy_n(buf.base, buf.sz, dst);
return buf.sz;
}
bool
llarp_main_init_dnsd(struct llarp_main *ptr, struct dnsd_context *dnsd,
const llarp::Addr &dnsd_sockaddr,
const llarp::Addr &dnsc_sockaddr)
llarp_vpn_io_writepkt(struct llarp_vpn_pkt_writer *w, unsigned char *pktbuf,
size_t pktlen)
{
return llarp_dnsd_init(dnsd, ptr->ctx->logic.get(),
ptr->ctx->mainloop.get(), dnsd_sockaddr,
dnsc_sockaddr);
if(pktlen == 0 || pktbuf == nullptr)
return false;
if(w == nullptr)
return false;
llarp_vpn_pkt_queue::Packet_t pkt;
llarp_buffer_t buf(pktbuf, pktlen);
if(not pkt.Load(buf))
return false;
return w->queue.pushBack(std::move(pkt))
== llarp::thread::QueueReturn::Success;
}
bool
llarp_main_init_dotLokiLookup(struct llarp_main *ptr,
struct dotLokiLookup *dll)
llarp_main_inject_vpn_by_name(struct llarp_main *ptr, const char *name,
struct llarp_vpn_io *io,
struct llarp_vpn_ifaddr_info info)
{
(void)ptr;
(void)dll;
// TODO: gut me
return false;
if(name == nullptr || io == nullptr)
return false;
if(ptr == nullptr || ptr->ctx == nullptr || ptr->ctx->router == nullptr)
return false;
auto ep = ptr->ctx->router->hiddenServiceContext().GetEndpointByName(name);
return ep && ep->InjectVPN(io, info);
}
void
llarp_vpn_io_close_async(struct llarp_vpn_io *io)
{
if(io == nullptr || io->impl == nullptr)
return;
static_cast< llarp_vpn_io_impl * >(io->impl)->AsyncClose();
}
bool
llarp_vpn_io_init(struct llarp_main *ptr, struct llarp_vpn_io *io)
{
if(io == nullptr || ptr == nullptr)
return false;
llarp_vpn_io_impl *impl = new llarp_vpn_io_impl(ptr, io);
io->impl = impl;
return true;
}
struct llarp_vpn_pkt_writer *
llarp_vpn_io_packet_writer(struct llarp_vpn_io *io)
{
if(io == nullptr || io->impl == nullptr)
return nullptr;
llarp_vpn_io_impl *vpn = static_cast< llarp_vpn_io_impl * >(io->impl);
return &vpn->writer;
}
struct llarp_vpn_pkt_reader *
llarp_vpn_io_packet_reader(struct llarp_vpn_io *io)
{
if(io == nullptr || io->impl == nullptr)
return nullptr;
llarp_vpn_io_impl *vpn = static_cast< llarp_vpn_io_impl * >(io->impl);
return &vpn->reader;
}
void
@ -473,49 +592,52 @@ extern "C"
delete ptr;
}
int
llarp_main_loadDatabase(struct llarp_main *ptr)
const char *
llarp_main_get_default_endpoint_name(struct llarp_main *)
{
return ptr->ctx->LoadDatabase();
return "default";
}
const char *
handleBaseCmdLineArgs(int argc, char *argv[])
{
// clang-format off
cxxopts::Options options(
"lokinet",
"Lokinet is a private, decentralized and IP based overlay network for the internet"
);
options.add_options()
("c,config", "Config file", cxxopts::value< std::string >()->default_value("daemon.ini"))
("o,logLevel", "logging level");
// clang-format on
auto result = options.parse(argc, argv);
std::string logLevel = result["logLevel"].as< std::string >();
if(logLevel == "debug")
{
cSetLogLevel(eLogDebug);
}
else if(logLevel == "info")
{
cSetLogLevel(eLogInfo);
}
else if(logLevel == "warn")
{
cSetLogLevel(eLogWarn);
}
else if(logLevel == "error")
{
cSetLogLevel(eLogError);
}
void
llarp_main_stop(struct llarp_main *ptr)
{
if(ptr == nullptr)
return;
ptr->ctx->CloseAsync();
ptr->ctx->Wait();
}
// this isn't thread safe, but reconfiguring during run is likely unsafe
// either way
static std::string confname = result["config"].as< std::string >();
bool
llarp_main_configure(struct llarp_main *ptr, struct llarp_config *conf)
{
if(ptr == nullptr || conf == nullptr)
return false;
// give new config
ptr->ctx->config.reset(new llarp::Config(conf->impl));
return ptr->ctx->Configure();
}
return confname.c_str();
bool
llarp_main_is_running(struct llarp_main *ptr)
{
return ptr && ptr->ctx->router && ptr->ctx->router->IsRunning();
}
}
llarp_main::llarp_main(llarp_config *conf)
: ctx(new llarp::Context())
{
ctx->config.reset(new llarp::Config(conf->impl));
}
namespace llarp
{
Context *
Context::Get(llarp_main *m)
{
if(m == nullptr || m->ctx == nullptr)
return nullptr;
return m->ctx.get();
}
} // namespace llarp

@ -13,8 +13,6 @@ extern "C"
sodium_init(void);
}
#include "ec.hpp"
namespace llarp
{
namespace sodium
@ -156,91 +154,6 @@ namespace llarp
!= -1;
}
using ec_scalar = AlignedBuffer< 32 >;
struct s_comm final
: public AlignedBuffer< LongHash::SIZE + (ec_scalar::SIZE * 2) >
{
byte_t *
H()
{
return data();
}
byte_t *
K()
{
return data() + LongHash::SIZE;
}
byte_t *
C()
{
return data() + LongHash::SIZE + ec_scalar::SIZE;
}
};
static inline bool
IsNonZero(const byte_t *s)
{
return (((int)(s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7]
| s[8] | s[9] | s[10] | s[11] | s[12] | s[13] | s[14]
| s[15] | s[16] | s[17] | s[18] | s[19] | s[20] | s[21]
| s[22] | s[23] | s[24] | s[25] | s[26] | s[27] | s[28]
| s[29] | s[30] | s[31])
- 1)
>> 8)
+ 1;
}
static inline bool
less32(const unsigned char *k0, const unsigned char *k1)
{
for(int n = 31; n >= 0; --n)
{
if(k0[n] < k1[n])
return true;
if(k0[n] > k1[n])
return false;
}
return false;
}
static void
rand32_unbais(byte_t *k)
{
// l = 2^252 + 27742317777372353535851937790883648493.
// it fits 15 in 32 bytes
static const unsigned char limit[32] = {
0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82,
0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0};
do
{
randombytes(k, 32);
} while(!IsNonZero(k) && !less32(k, limit));
sc25519_reduce32(k);
}
static bool
check_key(const byte_t *k)
{
ge25519_p3 p;
return ge25519_frombytes_vartime(&p, k) == 0;
}
template < typename T, size_t outsz = ec_scalar::SIZE >
static inline bool
hash_to_scalar(const T &in, byte_t *out)
{
if(crypto_generichash_blake2b(out, outsz, in.data(), in.size(), nullptr,
0)
== -1)
return false;
sc25519_reduce32(out);
return true;
}
static bool
hash(uint8_t *result, const llarp_buffer_t &buff)
{
@ -253,71 +166,28 @@ namespace llarp
CryptoLibSodium::sign(Signature &sig, const SecretKey &secret,
const llarp_buffer_t &buf)
{
s_comm tmp;
if(!hash(tmp.H(), buf))
return false;
ge25519_p3 tmp3;
ec_scalar K;
const PubKey pk = secret.toPublic();
std::copy_n(pk.begin(), pk.size(), tmp.K());
do
{
rand32_unbais(K.data());
if(((const uint32_t *)(K.data()))[7]
== 0) // we don't want tiny numbers here
continue;
ge25519_scalarmult_base(&tmp3, K.data());
ge25519_p3_tobytes(tmp.C(), &tmp3);
hash_to_scalar(tmp, sig.C());
if(!IsNonZero(sig.C()))
continue;
sc25519_mulsub(sig.R(), sig.C(), secret.data(), K.data());
if(!IsNonZero(sig.R()))
continue;
return true;
} while(true);
return crypto_sign_detached(sig.data(), nullptr, buf.base, buf.sz,
secret.data())
!= -1;
}
bool
CryptoLibSodium::verify(const PubKey &pub, const llarp_buffer_t &buf,
const Signature &sig)
{
s_comm tmp;
ge25519_p2 tmp2;
ge25519_p3 tmp3;
ec_scalar C;
std::copy_n(pub.begin(), pub.size(), tmp.K());
if(!hash(tmp.H(), buf))
return false;
if(ge25519_frombytes_vartime(&tmp3, pub.data()) != 0)
return false;
if(sc25519_check(sig.C()) != 0 || sc25519_check(sig.R()) != 0
|| !IsNonZero(sig.C()))
return false;
ge25519_double_scalarmult_base_vartime(&tmp2, sig.C(), &tmp3, sig.R());
ge25519_tobytes(tmp.C(), &tmp2);
static const ec_scalar infinity{{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
if(memcmp(tmp.C(), &infinity, 32) == 0)
return false;
hash_to_scalar(tmp, C.data());
sc25519_sub(C.data(), C.data(), sig.C());
return !IsNonZero(C.data());
return crypto_sign_verify_detached(sig.data(), buf.base, buf.sz,
pub.data())
!= -1;
}
bool
CryptoLibSodium::seed_to_secretkey(llarp::SecretKey &secret,
const llarp::IdentitySecret &seed)
{
if(sc25519_check(seed.data()) != 0)
return false;
ge25519_p3 A;
std::copy_n(seed.begin(), 32, secret.begin());
ge25519_scalarmult_base(&A, seed.data());
byte_t *pub = secret.data() + 32;
ge25519_p3_tobytes(pub, &A);
return true;
PubKey pk;
return crypto_sign_ed25519_seed_keypair(pk.data(), secret.data(),
seed.data())
!= -1;
}
void
@ -335,16 +205,18 @@ namespace llarp
void
CryptoLibSodium::identity_keygen(llarp::SecretKey &keys)
{
llarp::IdentitySecret seed;
rand32_unbais(seed.data());
seed_to_secretkey(keys, seed);
PubKey pk;
int result = crypto_sign_keypair(pk.data(), keys.data());
assert(result != -1);
const PubKey sk_pk = keys.toPublic();
assert(pk == sk_pk);
}
void
CryptoLibSodium::encryption_keygen(llarp::SecretKey &keys)
{
auto d = keys.data();
rand32_unbais(d);
randbytes(d, 32);
crypto_scalarmult_curve25519_base(d + 32, d);
}

@ -52,6 +52,7 @@ namespace llarp
bool
verify(const PubKey &, const llarp_buffer_t &,
const Signature &) override;
/// seed to secretkey
bool
seed_to_secretkey(llarp::SecretKey &,

File diff suppressed because it is too large Load Diff

@ -1,46 +0,0 @@
#ifndef LLARP_CRYPTO_EC_HPP
#define LLARP_CRYPTO_EC_HPP
#include "types.hpp"
extern "C"
{
#include <sodium/private/ed25519_ref10.h>
}
namespace llarp
{
namespace sodium
{
void
sc25519_reduce32(byte_t *s);
/*
Input:
a[0]+256*a[1]+...+256^31*a[31] = a
b[0]+256*b[1]+...+256^31*b[31] = b
c[0]+256*c[1]+...+256^31*c[31] = c
Output:
s[0]+256*s[1]+...+256^31*s[31] = (c-ab) mod l
where l = 2^252 + 27742317777372353535851937790883648493.
*/
void
sc25519_mulsub(byte_t *s, const byte_t *a, const byte_t *b,
const byte_t *c);
void
sc25519_sub(byte_t *, const byte_t *, const byte_t *);
int
ge25519_frombytes_vartime(ge25519_p3 *, const byte_t *);
int
sc25519_check(const byte_t *);
void
ge25519_double_scalarmult_base_vartime(ge25519_p2 *, const byte_t *,
const ge25519_p3 *, const byte_t *);
} // namespace sodium
} // namespace llarp
#endif

@ -20,6 +20,7 @@ typedef SSIZE_T ssize_t;
#else
#include <netinet/in.h>
#include <sys/socket.h>
#include <net/net_if.hpp>
#endif
#include <memory>

@ -1,6 +1,7 @@
#include <ev/ev_libuv.hpp>
#include <net/net_addr.hpp>
#include <util/thread/logic.hpp>
#include <util/thread/queue.hpp>
#include <cstring>
@ -24,6 +25,33 @@ namespace libuv
/// tcp connection glue between llarp and libuv
struct conn_glue : public glue
{
using WriteBuffer_t = std::vector< char >;
struct WriteEvent
{
WriteBuffer_t data;
uv_write_t request;
WriteEvent() = default;
explicit WriteEvent(WriteBuffer_t buf) : data(std::move(buf))
{
request.data = this;
}
uv_buf_t
Buffer()
{
return uv_buf_init(data.data(), data.size());
}
uv_write_t*
Request()
{
return &request;
}
};
uv_tcp_t m_Handle;
uv_connect_t m_Connect;
uv_check_t m_Ticker;
@ -31,11 +59,11 @@ namespace libuv
llarp_tcp_acceptor* const m_Accept;
llarp_tcp_conn m_Conn;
llarp::Addr m_Addr;
std::deque< std::vector< char > > m_WriteQueue;
llarp::thread::Queue< WriteBuffer_t > m_WriteQueue;
uv_async_t m_WriteNotify;
conn_glue(uv_loop_t* loop, llarp_tcp_connecter* tcp, const sockaddr* addr)
: m_TCP(tcp), m_Accept(nullptr), m_Addr(*addr)
: m_TCP(tcp), m_Accept(nullptr), m_Addr(*addr), m_WriteQueue(32)
{
m_Connect.data = this;
m_Handle.data = this;
@ -43,24 +71,29 @@ namespace libuv
uv_tcp_init(loop, &m_Handle);
m_Ticker.data = this;
uv_check_init(loop, &m_Ticker);
m_Conn.close = &ExplicitClose;
m_Conn.write = &ExplicitWrite;
m_Conn.close = &ExplicitClose;
m_Conn.write = &ExplicitWrite;
m_WriteNotify.data = this;
uv_async_init(loop, &m_WriteNotify, &OnShouldWrite);
}
conn_glue(uv_loop_t* loop, llarp_tcp_acceptor* tcp, const sockaddr* addr)
: m_TCP(nullptr), m_Accept(tcp), m_Addr(*addr)
: m_TCP(nullptr), m_Accept(tcp), m_Addr(*addr), m_WriteQueue(32)
{
m_Connect.data = nullptr;
m_Handle.data = this;
uv_tcp_init(loop, &m_Handle);
m_Ticker.data = this;
uv_check_init(loop, &m_Ticker);
m_Accept->close = &ExplicitCloseAccept;
m_Conn.write = nullptr;
m_Conn.closed = nullptr;
m_Accept->close = &ExplicitCloseAccept;
m_Conn.write = nullptr;
m_Conn.closed = nullptr;
m_WriteNotify.data = this;
uv_async_init(loop, &m_WriteNotify, &OnShouldWrite);
}
conn_glue(conn_glue* parent) : m_TCP(nullptr), m_Accept(nullptr)
conn_glue(conn_glue* parent)
: m_TCP(nullptr), m_Accept(nullptr), m_WriteQueue(32)
{
m_Connect.data = nullptr;
m_Conn.close = &ExplicitClose;
@ -69,6 +102,8 @@ namespace libuv
uv_tcp_init(parent->m_Handle.loop, &m_Handle);
m_Ticker.data = this;
uv_check_init(parent->m_Handle.loop, &m_Ticker);
m_WriteNotify.data = this;
uv_async_init(parent->m_Handle.loop, &m_WriteNotify, &OnShouldWrite);
}
static void
@ -177,32 +212,50 @@ namespace libuv
static void
OnWritten(uv_write_t* req, int status)
{
conn_glue* conn = static_cast< conn_glue* >(req->data);
if(status)
WriteEvent* ev = static_cast< WriteEvent* >(req->data);
if(status == 0)
{
llarp::LogError("write failed on tcp: ", uv_strerror(status));
conn->Close();
llarp::LogDebug("wrote ", ev->data.size());
}
else
Call(conn->Stream(), std::bind(&conn_glue::DrainOne, conn));
delete req;
{
llarp::LogDebug("write fail");
}
delete ev;
}
void
DrainOne()
int
WriteAsync(char* data, size_t sz)
{
m_WriteQueue.pop_front();
if(uv_is_closing((const uv_handle_t*)&m_Handle))
return -1;
if(uv_is_closing((const uv_handle_t*)&m_WriteNotify))
return -1;
WriteBuffer_t buf(sz);
std::copy_n(data, sz, buf.begin());
if(m_WriteQueue.pushBack(std::move(buf))
== llarp::thread::QueueReturn::Success)
{
uv_async_send(&m_WriteNotify);
return sz;
}
return -1;
}
int
WriteAsync(char* data, size_t sz)
void
FlushWrite()
{
m_WriteQueue.emplace_back(sz);
std::copy_n(data, sz, m_WriteQueue.back().begin());
auto buf = uv_buf_init(m_WriteQueue.back().data(), sz);
auto* req = new uv_write_t();
req->data = this;
return uv_write(req, Stream(), &buf, 1, &OnWritten) == 0 ? sz : 0;
while(not m_WriteQueue.empty())
{
auto data = m_WriteQueue.popFront();
WriteEvent* ev = new WriteEvent(std::move(data));
auto buf = ev->Buffer();
if(uv_write(ev->Request(), Stream(), &buf, 1, &OnWritten) != 0)
{
Close();
return;
}
}
}
static void
@ -249,15 +302,25 @@ namespace libuv
delete shut;
}
static void
OnWriteClosed(uv_handle_t* h)
{
conn_glue* conn = static_cast< conn_glue* >(h->data);
auto* shut = new uv_shutdown_t();
shut->data = conn;
uv_shutdown(shut, conn->Stream(), &OnShutdown);
}
void
Close() override
{
if(uv_is_closing((uv_handle_t*)&m_WriteNotify))
return;
llarp::LogDebug("close tcp connection");
m_WriteQueue.disable();
uv_close((uv_handle_t*)&m_WriteNotify, &OnWriteClosed);
uv_check_stop(&m_Ticker);
uv_read_stop(Stream());
auto* shut = new uv_shutdown_t();
shut->data = this;
uv_shutdown(shut, Stream(), &OnShutdown);
}
static void
@ -274,6 +337,12 @@ namespace libuv
}
}
static void
OnShouldWrite(uv_async_t* h)
{
static_cast< conn_glue* >(h->data)->FlushWrite();
}
static void
OnTick(uv_check_t* t)
{
@ -714,20 +783,19 @@ namespace libuv
bool
Loop::init()
{
m_Impl.reset(uv_loop_new());
if(uv_loop_init(m_Impl.get()) == -1)
if(uv_loop_init(&m_Impl) == -1)
return false;
m_Impl->data = this;
uv_loop_configure(m_Impl.get(), UV_LOOP_BLOCK_SIGNAL, SIGPIPE);
m_Impl.data = this;
uv_loop_configure(&m_Impl, UV_LOOP_BLOCK_SIGNAL, SIGPIPE);
m_TickTimer.data = this;
m_Run.store(true);
return uv_timer_init(m_Impl.get(), &m_TickTimer) != -1;
return uv_timer_init(&m_Impl, &m_TickTimer) != -1;
}
void
Loop::update_time()
{
uv_update_time(m_Impl.get());
uv_update_time(&m_Impl);
}
bool
@ -745,7 +813,7 @@ namespace libuv
bool
Loop::tcp_connect(llarp_tcp_connecter* tcp, const sockaddr* addr)
{
auto* impl = new conn_glue(m_Impl.get(), tcp, addr);
auto* impl = new conn_glue(&m_Impl, tcp, addr);
tcp->impl = impl;
if(impl->ConnectAsync())
return true;
@ -764,14 +832,14 @@ namespace libuv
Loop::tick(int ms)
{
uv_timer_start(&m_TickTimer, &OnTickTimeout, ms, 0);
uv_run(m_Impl.get(), UV_RUN_ONCE);
uv_run(&m_Impl, UV_RUN_ONCE);
return 0;
}
void
Loop::stop()
{
uv_stop(m_Impl.get());
uv_stop(&m_Impl);
llarp::LogInfo("stopping event loop");
m_Run.store(false);
CloseAll();
@ -782,7 +850,7 @@ namespace libuv
{
llarp::LogInfo("Closing all handles");
uv_walk(
m_Impl.get(),
&m_Impl,
[](uv_handle_t* h, void*) {
if(uv_is_closing(h))
return;
@ -804,7 +872,7 @@ namespace libuv
bool
Loop::udp_listen(llarp_udp_io* udp, const sockaddr* src)
{
auto* impl = new udp_glue(m_Impl.get(), udp, src);
auto* impl = new udp_glue(&m_Impl, udp, src);
udp->impl = impl;
if(impl->Bind())
{
@ -817,7 +885,7 @@ namespace libuv
bool
Loop::add_ticker(std::function< void(void) > func)
{
auto* ticker = new ticker_glue(m_Impl.get(), func);
auto* ticker = new ticker_glue(&m_Impl, func);
if(ticker->Start())
{
return true;
@ -843,7 +911,7 @@ namespace libuv
{
auto* glue = new tun_glue(tun);
tun->impl = glue;
if(glue->Init(m_Impl.get()))
if(glue->Init(&m_Impl))
{
return true;
}
@ -854,7 +922,7 @@ namespace libuv
bool
Loop::tcp_listen(llarp_tcp_acceptor* tcp, const sockaddr* addr)
{
auto* glue = new conn_glue(m_Impl.get(), tcp, addr);
auto* glue = new conn_glue(&m_Impl, tcp, addr);
tcp->impl = glue;
if(glue->Server())
return true;
@ -866,7 +934,7 @@ namespace libuv
bool
Loop::add_pipe(llarp_ev_pkt_pipe* p)
{
auto* glue = new pipe_glue(m_Impl.get(), p);
auto* glue = new pipe_glue(&m_Impl, p);
if(glue->Start())
return true;
delete glue;

@ -104,16 +104,7 @@ namespace libuv
}
private:
struct DestructLoop
{
void
operator()(uv_loop_t* l) const
{
uv_loop_close(l);
}
};
std::unique_ptr< uv_loop_t, DestructLoop > m_Impl;
uv_loop_t m_Impl;
uv_timer_t m_TickTimer;
std::atomic< bool > m_Run;
std::shared_ptr< llarp::Logic > m_Logic;

@ -0,0 +1,31 @@
#include <ev/vpnio.hpp>
#include <llarp.hpp>
#include <router/abstractrouter.hpp>
#include <util/thread/logic.hpp>
void
llarp_vpn_io_impl::AsyncClose()
{
reader.queue.disable();
writer.queue.disable();
CallSafe(std::bind(&llarp_vpn_io_impl::Expunge, this));
}
void
llarp_vpn_io_impl::CallSafe(std::function< void(void) > f)
{
llarp::Context* ctx = llarp::Context::Get(ptr);
if(ctx && ctx->CallSafe(f))
return;
else if(ctx == nullptr || ctx->logic == nullptr)
f();
}
void
llarp_vpn_io_impl::Expunge()
{
parent->impl = nullptr;
if(parent->closed)
parent->closed(parent);
delete this;
}

@ -0,0 +1,51 @@
#ifndef LLARP_EV_VPNIO_HPP
#define LLARP_EV_VPNIO_HPP
#include <net/ip.hpp>
#include <util/thread/queue.hpp>
#include <functional>
struct llarp_main;
struct llarp_vpn_io;
struct llarp_vpn_pkt_queue
{
using Packet_t = llarp::net::IPPacket;
llarp::thread::Queue< Packet_t > queue;
llarp_vpn_pkt_queue() : queue(1024){};
~llarp_vpn_pkt_queue() = default;
};
struct llarp_vpn_pkt_writer : public llarp_vpn_pkt_queue
{
};
struct llarp_vpn_pkt_reader : public llarp_vpn_pkt_queue
{
};
struct llarp_vpn_io_impl
{
llarp_vpn_io_impl(llarp_main* p, llarp_vpn_io* io) : ptr(p), parent(io)
{
}
~llarp_vpn_io_impl() = default;
llarp_main* ptr;
llarp_vpn_io* parent;
llarp_vpn_pkt_writer writer;
llarp_vpn_pkt_reader reader;
void
AsyncClose();
private:
void
CallSafe(std::function< void(void) > f);
void
Expunge();
};
#endif

@ -24,10 +24,12 @@ namespace llarp
{
namespace handlers
{
static llarp_fd_promise *
get_tun_fd_promise(llarp_tun_io *tun)
void
TunEndpoint::FlushToUser(std::function< bool(net::IPPacket &) > send)
{
return static_cast< TunEndpoint * >(tun->user)->Promise.get();
m_ExitMap.ForEachValue([](const auto &exit) { exit->FlushDownstream(); });
// flush network to user
m_NetworkToUserPktQueue.Process(send);
}
static void
@ -38,7 +40,7 @@ namespace llarp
}
TunEndpoint::TunEndpoint(const std::string &nickname, AbstractRouter *r,
service::Context *parent)
service::Context *parent, bool lazyVPN)
: service::Endpoint(nickname, r, parent)
, m_UserToNetworkPktQueue(nickname + "_sendq", r->netloop(),
r->netloop())
@ -47,22 +49,19 @@ namespace llarp
, m_Resolver(std::make_shared< dns::Proxy >(
r->netloop(), r->logic(), r->netloop(), r->logic(), this))
{
std::fill(tunif.ifaddr, tunif.ifaddr + sizeof(tunif.ifaddr), 0);
std::fill(tunif.ifname, tunif.ifname + sizeof(tunif.ifname), 0);
tunif.netmask = 0;
#ifdef ANDROID
tunif.get_fd_promise = &get_tun_fd_promise;
Promise.reset(new llarp_fd_promise(&m_VPNPromise));
#else
tunif.get_fd_promise = nullptr;
#endif
tunif.user = this;
// eh this shouldn't do anything on windows anyway
tunif.tick = &tunifTick;
tunif.before_write = &tunifBeforeWrite;
tunif.recvpkt = &tunifRecvPkt;
if(not lazyVPN)
{
tunif.reset(new llarp_tun_io());
std::fill(tunif->ifaddr, tunif->ifaddr + sizeof(tunif->ifaddr), 0);
std::fill(tunif->ifname, tunif->ifname + sizeof(tunif->ifname), 0);
tunif->netmask = 0;
tunif->get_fd_promise = nullptr;
tunif->user = this;
// eh this shouldn't do anything on windows anyway
tunif->tick = &tunifTick;
tunif->before_write = &tunifBeforeWrite;
tunif->recvpkt = &tunifRecvPkt;
}
}
util::StatusObject
@ -241,18 +240,18 @@ namespace llarp
}
return MapAddress(addr, ipv6, false);
}
if(k == "ifname")
if(k == "ifname" && tunif)
{
if(v.length() >= sizeof(tunif.ifname))
if(v.length() >= sizeof(tunif->ifname))
{
llarp::LogError(Name() + " ifname '", v, "' is too long");
return false;
}
strncpy(tunif.ifname, v.c_str(), sizeof(tunif.ifname) - 1);
llarp::LogInfo(Name() + " setting ifname to ", tunif.ifname);
strncpy(tunif->ifname, v.c_str(), sizeof(tunif->ifname) - 1);
llarp::LogInfo(Name() + " setting ifname to ", tunif->ifname);
return true;
}
if(k == "ifaddr")
if(k == "ifaddr" && tunif)
{
std::string addr;
m_UseV6 = addr.find(":") != std::string::npos;
@ -268,8 +267,8 @@ namespace llarp
#endif
if(num > 0)
{
tunif.netmask = num;
addr = v.substr(0, pos);
tunif->netmask = num;
addr = v.substr(0, pos);
}
else
{
@ -280,14 +279,14 @@ namespace llarp
else
{
if(m_UseV6)
tunif.netmask = 128;
tunif->netmask = 128;
else
tunif.netmask = 32;
tunif->netmask = 32;
addr = v;
}
llarp::LogInfo(Name() + " set ifaddr to ", addr, " with netmask ",
tunif.netmask);
strncpy(tunif.ifaddr, addr.c_str(), sizeof(tunif.ifaddr) - 1);
tunif->netmask);
strncpy(tunif->ifaddr, addr.c_str(), sizeof(tunif->ifaddr) - 1);
return true;
}
return Endpoint::SetOption(k, v);
@ -585,80 +584,120 @@ namespace llarp
bool
TunEndpoint::SetupTun()
{
lazy_vpn vpn;
huint32_t ip;
auto loop = EndpointNetLoop();
if(!llarp_ev_add_tun(loop.get(), &tunif))
{
llarp::LogError(Name(),
" failed to set up tun interface: ", tunif.ifaddr,
" on ", tunif.ifname);
return false;
}
struct addrinfo hint, *res = nullptr;
int ret;
memset(&hint, 0, sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(tunif.ifaddr, nullptr, &hint, &res);
if(ret)
{
llarp::LogError(Name(),
" failed to set up tun interface, cant determine "
"family from ",
tunif.ifaddr);
return false;
}
/*
// output is in network byte order
unsigned char buf[sizeof(struct in6_addr)];
int s = inet_pton(res->ai_family, tunif.ifaddr, buf);
if (s <= 0)
{
llarp::LogError(Name(), " failed to set up tun interface, cant parse
", tunif.ifaddr); return false;
}
*/
if(res->ai_family == AF_INET6)
if(tunif == nullptr)
{
m_UseV6 = true;
}
llarp::LogInfo(Name(), " waiting for vpn to start");
vpn = m_LazyVPNPromise.get_future().get();
vpnif = vpn.io;
if(vpnif == nullptr)
{
llarp::LogError(Name(), " failed to recieve vpn interface");
return false;
}
llarp::LogInfo(Name(), " got vpn interface");
auto self = shared_from_this();
// function to queue a packet to send to vpn interface
auto sendpkt = [self](net::IPPacket &pkt) -> bool {
// drop if no endpoint
auto impl = self->GetVPNImpl();
// drop if no vpn interface
if(impl == nullptr)
return true;
// drop if queue to vpn not enabled
if(not impl->reader.queue.enabled())
return true;
// drop if queue to vpn full
if(impl->reader.queue.full())
return true;
// queue to reader
impl->reader.queue.pushBack(pkt);
return false;
};
// event loop ticker
auto ticker = [self, sendpkt]() {
TunEndpoint *ep = self.get();
const bool running = not ep->IsStopped();
auto impl = ep->GetVPNImpl();
if(impl)
{
/// get packets from vpn
while(not impl->writer.queue.empty())
{
// queue it to be sent over lokinet
auto pkt = impl->writer.queue.popFront();
if(running)
ep->m_UserToNetworkPktQueue.Emplace(pkt);
}
}
freeaddrinfo(res);
if(m_UseV6)
{
llarp::LogInfo(Name(), " using IPV6");
// process packets queued from vpn
if(running)
{
ep->Flush();
ep->FlushToUser(sendpkt);
}
// if impl has a tick function call it
if(impl && impl->parent && impl->parent->tick)
impl->parent->tick(impl->parent);
};
if(not loop->add_ticker(ticker))
{
llarp::LogError(Name(), " failed to add vpn to event loop");
if(vpnif->injected)
vpnif->injected(vpnif, false);
return false;
}
}
else
{
struct in_addr addr; // network byte order
if(inet_aton(tunif.ifaddr, &addr) == 0)
if(!llarp_ev_add_tun(loop.get(), tunif.get()))
{
llarp::LogError(Name(),
" failed to set up tun interface, cant parse ",
tunif.ifaddr);
" failed to set up tun interface: ", tunif->ifaddr,
" on ", tunif->ifname);
return false;
}
}
huint32_t ip;
if(ip.FromString(tunif.ifaddr))
const char *ifname;
const char *ifaddr;
unsigned char netmask;
if(tunif)
{
ifname = tunif->ifname;
ifaddr = tunif->ifaddr;
netmask = tunif->netmask;
}
else
{
ifname = vpn.info.ifname;
ifaddr = vpn.info.ifaddr;
netmask = vpn.info.netmask;
}
if(ip.FromString(ifaddr))
{
m_OurIP = net::IPPacket::ExpandV4(ip);
m_OurRange.netmask_bits = netmask_ipv6_bits(tunif.netmask + 96);
m_OurRange.netmask_bits = netmask_ipv6_bits(netmask + 96);
}
else if(m_OurIP.FromString(tunif.ifaddr))
else if(m_OurIP.FromString(ifaddr))
{
m_OurRange.netmask_bits = netmask_ipv6_bits(tunif.netmask);
m_OurRange.netmask_bits = netmask_ipv6_bits(netmask);
m_UseV6 = true;
}
else
{
LogError(Name(), " invalid interface address given, ifaddr=", ifaddr);
if(vpnif && vpnif->injected)
vpnif->injected(vpnif, false);
return false;
}
m_NextIP = m_OurIP;
m_OurRange.addr = m_OurIP;
m_MaxIP = m_OurRange.HighestAddr();
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ",
m_OurIP);
llarp::LogInfo(Name(), " set ", ifname, " to have address ", m_OurIP);
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ",
m_OurRange);
@ -667,6 +706,10 @@ namespace llarp
{
m_OnUp->NotifyAsync(NotifyParams());
}
if(vpnif && vpnif->injected)
{
vpnif->injected(vpnif, true);
}
return true;
}
@ -676,7 +719,8 @@ namespace llarp
auto env = Endpoint::NotifyParams();
env.emplace("IP_ADDR", m_OurIP.ToString());
env.emplace("IF_ADDR", m_OurRange.ToString());
env.emplace("IF_NAME", tunif.ifname);
if(tunif)
env.emplace("IF_NAME", tunif->ifname);
std::string strictConnect;
for(const auto &addr : m_StrictConnectAddrs)
strictConnect += addr.ToString() + " ";
@ -929,20 +973,17 @@ namespace llarp
TunEndpoint::tunifBeforeWrite(llarp_tun_io *tun)
{
// called in the isolated network thread
auto *self = static_cast< TunEndpoint * >(tun->user);
// flush user to network
self->EndpointLogic()->queue_func(
std::bind(&TunEndpoint::FlushSend, self));
// flush exit traffic queues if it's there
self->EndpointLogic()->queue_func([self] {
self->m_ExitMap.ForEachValue(
[](const auto &exit) { exit->FlushDownstream(); });
});
// flush network to user
self->m_NetworkToUserPktQueue.Process([tun](net::IPPacket &pkt) {
auto *self = static_cast< TunEndpoint * >(tun->user);
auto sendpkt = [self, tun](net::IPPacket &pkt) -> bool {
if(!llarp_ev_tun_async_write(tun, pkt.Buffer()))
llarp::LogWarn("packet dropped");
});
{
llarp::LogWarn(self->Name(), " packet dropped");
return true;
}
return false;
};
self->EndpointLogic()->queue_func(std::bind(
&TunEndpoint::FlushToUser, self->shared_from_this(), sendpkt));
}
void

@ -3,6 +3,7 @@
#include <dns/server.hpp>
#include <ev/ev.h>
#include <ev/vpnio.hpp>
#include <net/ip.hpp>
#include <net/net.hpp>
#include <service/endpoint.hpp>
@ -20,7 +21,7 @@ namespace llarp
public std::enable_shared_from_this< TunEndpoint >
{
TunEndpoint(const std::string& nickname, AbstractRouter* r,
llarp::service::Context* parent);
llarp::service::Context* parent, bool lazyVPN = false);
~TunEndpoint() override;
path::PathSet_ptr
@ -114,8 +115,17 @@ namespace llarp
bool
HasLocalIP(const huint128_t& ip) const;
llarp_tun_io tunif;
std::unique_ptr< llarp_fd_promise > Promise;
std::unique_ptr< llarp_tun_io > tunif;
llarp_vpn_io* vpnif = nullptr;
bool
InjectVPN(llarp_vpn_io* io, llarp_vpn_ifaddr_info info)
{
if(tunif)
return false;
m_LazyVPNPromise.set_value(lazy_vpn{info, io});
return true;
}
/// called before writing to tun interface
static void
@ -206,6 +216,14 @@ namespace llarp
m_SNodes;
private:
llarp_vpn_io_impl*
GetVPNImpl()
{
if(vpnif && vpnif->impl)
return static_cast< llarp_vpn_io_impl* >(vpnif->impl);
return nullptr;
}
bool
QueueInboundPacketForExit(const llarp_buffer_t& buf)
{
@ -255,12 +273,6 @@ namespace llarp
reply(*query);
delete query;
}
#ifndef WIN32
/// handles fd injection force android
std::promise< std::pair< int, int > > m_VPNPromise;
#endif
/// our dns resolver
std::shared_ptr< dns::Proxy > m_Resolver;
@ -283,6 +295,18 @@ namespace llarp
std::vector< llarp::Addr > m_StrictConnectAddrs;
/// use v6?
bool m_UseV6;
struct lazy_vpn
{
llarp_vpn_ifaddr_info info;
llarp_vpn_io* io;
};
std::promise< lazy_vpn > m_LazyVPNPromise;
/// send packets on endpoint to user using send function
/// send function returns true to indicate stop iteration and do codel
/// drop
void
FlushToUser(std::function< bool(net::IPPacket&) > sendfunc);
};
} // namespace handlers
} // namespace llarp

@ -90,20 +90,24 @@ namespace llarp
if(pkt.sz > sizeof(buf))
return false;
sz = pkt.sz;
memcpy(buf, pkt.base, sz);
std::copy_n(pkt.base, sz, buf);
return true;
}
llarp_buffer_t
ManagedBuffer
IPPacket::ConstBuffer() const
{
return {buf, sz};
const byte_t *ptr = buf;
llarp_buffer_t b(ptr, sz);
return ManagedBuffer(b);
}
llarp_buffer_t
ManagedBuffer
IPPacket::Buffer()
{
return {buf, sz};
byte_t *ptr = buf;
llarp_buffer_t b(ptr, sz);
return ManagedBuffer(b);
}
huint32_t

@ -116,10 +116,10 @@ namespace llarp
size_t sz;
byte_t buf[MaxSize];
llarp_buffer_t
ManagedBuffer
Buffer();
llarp_buffer_t
ManagedBuffer
ConstBuffer() const;
bool

@ -1,33 +1,18 @@
#include <net/net.hpp>
#include <net/net_if.hpp>
#ifdef ANDROID
#include <android/ifaddrs.h>
#endif
#ifndef _WIN32
#include <arpa/inet.h>
#endif
#ifndef ANDROID
#include <ifaddrs.h>
#endif
// Work around for broken glibc/linux header definitions in xenial that makes
// including both net/if.h (which we need for if_nametoindex) and linux/if.h
// (which tuntap.h includes) impossible. When we stop supporting xenial we can
// remove this mess and just include net/if.h here.
#if defined(Linux) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 23
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) \
&& LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
#define _NET_IF_H 1
#include <linux/if.h>
extern "C" unsigned int
if_nametoindex(const char* __ifname) __THROW;
#endif
#else
#include <net/if.h>
#endif
#endif
#include <net/net_addr.hpp>
#include <net/ip.hpp>
#include <util/logging/logger.hpp>

@ -0,0 +1,26 @@
#ifndef LLARP_NET_NET_IF_HPP
#define LLARP_NET_NET_IF_HPP
#ifndef _WIN32
// this file is a shim include for #include <net/if.h>
// Work around for broken glibc/linux header definitions in xenial that makes
// including both net/if.h (which we need for if_nametoindex) and linux/if.h
// (which tuntap.h includes) impossible. When we stop supporting xenial we can
// remove this mess and just include net/if.h here.
#if defined(Linux) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 23
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) \
&& LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
#define _NET_IF_H 1
#ifndef IFNAMSIZ
#define IFNAMSIZ (16)
#endif
#include <linux/if.h>
extern "C" unsigned int
if_nametoindex(const char* __ifname) __THROW;
#endif
#else
#include <net/if.h>
#endif
#endif
#endif

@ -132,6 +132,9 @@ namespace llarp
virtual bool
Run() = 0;
virtual bool
IsRunning() const = 0;
/// stop running the router logic gracefully
virtual void
Stop() = 0;

@ -33,6 +33,8 @@ namespace llarp
void
RCLookupHandler::SetRouterWhitelist(const std::vector< RouterID > &routers)
{
if(routers.empty())
return;
util::Lock l(&_mutex);
whitelistRouters.clear();

@ -1040,6 +1040,12 @@ namespace llarp
return _running;
}
bool
Router::IsRunning() const
{
return _running;
}
llarp_time_t
Router::Uptime() const
{

@ -310,6 +310,9 @@ namespace llarp
bool
InitServiceNode();
bool
IsRunning() const override;
/// return true if we are running in service node mode
bool
IsServiceNode() const;

@ -71,39 +71,41 @@ namespace llarp
HandleJSONResult(const nlohmann::json& result) override
{
PubkeyList_t keys;
if(!result.is_object())
if(not result.is_object())
{
LogWarn("Invalid result: not an object");
handler({}, false);
return false;
}
const auto itr = result.find("keys");
const auto itr = result.find("service_node_states");
if(itr == result.end())
{
LogWarn("Invalid result: no keys member");
LogWarn("Invalid result: no service_node_states member");
handler({}, false);
return false;
}
if(!itr.value().is_array())
if(not itr.value().is_array())
{
LogWarn("Invalid result: keys is not an array");
LogWarn("Invalid result: service_node_states is not an array");
handler({}, false);
return false;
}
for(const auto item : itr.value())
{
if(item.is_string())
{
keys.emplace_back();
std::string str = item.get< std::string >();
if(!Base32Decode(str, keys.back()))
{
LogWarn("Invalid key: ", str);
keys.pop_back();
}
}
if(not item.is_object())
continue;
if(not item.value("active", false))
continue;
if(not item.value("funded", false))
continue;
const std::string pk = item.value("pubkey_ed25519", "");
if(pk.empty())
continue;
PubKey k;
if(k.FromString(pk))
keys.emplace_back(std::move(k));
}
handler(keys, true);
handler(keys, not keys.empty());
return true;
}
@ -147,7 +149,10 @@ namespace llarp
AsyncUpdatePubkeyList()
{
LogInfo("Updating service node list");
QueueRPC("get_all_service_nodes_keys", nlohmann::json::object(),
nlohmann::json params = {
{"fields",
{{"pubkey_ed25519", true}, {"active", true}, {"funded", true}}}};
QueueRPC("get_n_service_nodes", std::move(params),
util::memFn(&CallerImpl::NewAsyncUpdatePubkeyListConn, this));
}

@ -20,23 +20,18 @@ namespace llarp
{"tun",
[](const std::string &nick, AbstractRouter *r,
service::Context *c) -> service::Endpoint_ptr {
return std::make_shared< handlers::TunEndpoint >(nick, r, c);
return std::make_shared< handlers::TunEndpoint >(nick, r, c,
false);
}},
{"android-tun",
[](const std::string &, AbstractRouter *,
service::Context *) -> service::Endpoint_ptr {
return nullptr;
/// SOOOOOOON (tm)
// return std::make_shared<handlers::AndroidTunEndpoint>(nick,
// r, c);
{"android",
[](const std::string &nick, AbstractRouter *r,
service::Context *c) -> service::Endpoint_ptr {
return std::make_shared< handlers::TunEndpoint >(nick, r, c, true);
}},
{"ios-tun",
[](const std::string &, AbstractRouter *,
service::Context *) -> service::Endpoint_ptr {
return nullptr;
/// SOOOOOOON (tm)
// return std::make_shared<handlers::IOSTunEndpoint>(nick, r,
// c);
{"ios",
[](const std::string &nick, AbstractRouter *r,
service::Context *c) -> service::Endpoint_ptr {
return std::make_shared< handlers::TunEndpoint >(nick, r, c, true);
}},
{"null",
[](const std::string &nick, AbstractRouter *r,
@ -133,12 +128,22 @@ namespace llarp
return m_Endpoints.size() ? true : false;
}
static const char *
DefaultEndpointType()
{
#ifdef ANDROID
return "android";
#else
return "tun";
#endif
}
bool
Context::AddDefaultEndpoint(
const std::unordered_multimap< std::string, std::string > &opts)
{
Config::section_values_t configOpts;
configOpts.push_back({"type", "tun"});
configOpts.push_back({"type", DefaultEndpointType()});
{
auto itr = opts.begin();
while(itr != opts.end())
@ -167,6 +172,15 @@ namespace llarp
return true;
}
Endpoint_ptr
Context::GetEndpointByName(const std::string &name)
{
auto itr = m_Endpoints.find(name);
if(itr != m_Endpoints.end())
return itr->second;
return nullptr;
}
bool
Context::AddEndpoint(const Config::section_t &conf, bool autostart)
{
@ -180,7 +194,7 @@ namespace llarp
}
}
// extract type
std::string endpointType = "tun";
std::string endpointType = DefaultEndpointType();
std::string keyfile;
for(const auto &option : conf.second)
{

@ -51,6 +51,9 @@ namespace llarp
bool
RemoveEndpoint(const std::string &name);
Endpoint_ptr
GetEndpointByName(const std::string &name);
bool
StartAll();

@ -1,6 +1,6 @@
#ifndef LLARP_SERVICE_ENDPOINT_HPP
#define LLARP_SERVICE_ENDPOINT_HPP
#include <llarp.h>
#include <dht/messages/gotrouter.hpp>
#include <ev/ev.h>
#include <exit/session.hpp>
@ -105,6 +105,14 @@ namespace llarp
return false;
}
/// inject vpn io
/// return false if not supported
virtual bool
InjectVPN(llarp_vpn_io*, llarp_vpn_ifaddr_info)
{
return false;
}
/// get our ifaddr if it is set
virtual huint128_t
GetIfAddr() const
@ -254,9 +262,6 @@ namespace llarp
bool
ShouldBundleRC() const override;
static void
HandlePathDead(void*);
/// return true if we have a convotag as an exit session
/// or as a hidden service session
/// set addr and issnode

@ -15,6 +15,13 @@ namespace llarp
}
};
TEST_F(IdentityKeyTest, TestKeyGen)
{
SecretKey secret;
crypto.identity_keygen(secret);
ASSERT_FALSE(secret.IsZero());
}
TEST_F(IdentityKeyTest, TestSignVerify)
{
SecretKey secret;
@ -23,7 +30,7 @@ namespace llarp
random.Randomize();
Signature sig;
llarp_buffer_t buf(random);
const llarp_buffer_t buf(random);
ASSERT_TRUE(crypto.sign(sig, secret, buf));
ASSERT_TRUE(crypto.verify(secret.toPublic(), buf, sig));
random.Randomize();

@ -25,6 +25,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <tuntap.h>
#ifdef __sun
#define BSD_COMP
#define TUNSDEBUG _IOW('t', 90, int)
@ -39,6 +41,7 @@
#if defined(Linux)
#include <linux/if_tun.h>
#include <linux/if_ether.h>
#include <linux/if.h>
#else
#include <net/if.h>
@ -62,7 +65,6 @@
#include <time.h>
#include <unistd.h>
#include <tuntap.h>
int
tuntap_start(struct device *dev, int mode, int tun)
@ -380,7 +382,7 @@ tuntap_set_debug(struct device *dev, int set)
}
#ifndef Darwin
if(ioctl(dev->tun_fd, TUNSDEBUG, &set) == -1)
if(ioctl(dev->tun_fd, TUNSETDEBUG, &set) == -1)
{
switch(set)
{

Loading…
Cancel
Save