mirror of https://github.com/oxen-io/lokinet
Merge branch 'master' of https://github.com/loki-project/loki-network
This commit is contained in:
commit
742a0b8da7
|
@ -29,3 +29,4 @@ SpacesInParentheses: 'false'
|
|||
SpacesInSquareBrackets: 'false'
|
||||
Standard: Cpp11
|
||||
UseTab: Never
|
||||
SortIncludes: false
|
|
@ -226,6 +226,11 @@ if(ANDROID)
|
|||
set(ANDROID_PLATFORM_SRC llarp/android/ifaddrs.c)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(ISOLATE_PROC_SRC llarp/linux/netns.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
set(LIB_PLATFORM_SRC
|
||||
# for outpug
|
||||
llarp/logger.cpp
|
||||
|
@ -243,6 +248,8 @@ set(LIB_PLATFORM_SRC
|
|||
llarp/threadpool.cpp
|
||||
# for android shim
|
||||
${ANDROID_PLATFORM_SRC}
|
||||
# process isolation implementation
|
||||
${ISOLATE_PROC_SRC}
|
||||
# tun
|
||||
${LIBTUNTAP_SRC}
|
||||
# win32 inline procs
|
||||
|
@ -438,6 +445,9 @@ else()
|
|||
endif(NOT HAVE_CXX17_FILESYSTEM)
|
||||
add_library(llarpplatform-static STATIC ${LIB_PLATFORM_SRC})
|
||||
target_link_libraries(llarpplatform-static ${THREAD_LIB})
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
target_link_libraries(llarpplatform-static -lcap)
|
||||
endif()
|
||||
if(NOT HAVE_CXX17_FILESYSTEM)
|
||||
target_link_libraries(${STATIC_LIB} ${LIBS} backport-static llarpplatform-static)
|
||||
else()
|
||||
|
|
|
@ -104,6 +104,7 @@ main(int argc, char *argv[])
|
|||
|
||||
// --generate /path/to/file.signed
|
||||
// --update /path/to/file.signed
|
||||
// --verify /path/to/file.signed
|
||||
// printf("has [%d]options\n", argc);
|
||||
if(argc < 2)
|
||||
{
|
||||
|
@ -111,7 +112,7 @@ main(int argc, char *argv[])
|
|||
"please specify: \n"
|
||||
"--generate with a path to a router contact file\n"
|
||||
"--update with a path to a router contact file\n"
|
||||
"--list \n"
|
||||
"--list path to nodedb skiplist\n"
|
||||
"--import with a path to a router contact file\n"
|
||||
"--export a hex formatted public key\n"
|
||||
"--locate a hex formatted public key\n"
|
||||
|
@ -120,9 +121,11 @@ main(int argc, char *argv[])
|
|||
"--hex a base32 formatted public key\n"
|
||||
"--localInfo \n"
|
||||
"--read with a path to a router contact file\n"
|
||||
"--verify with a path to a router contact file\n"
|
||||
"\n");
|
||||
return 0;
|
||||
}
|
||||
bool haveRequiredOptions = false;
|
||||
bool genMode = false;
|
||||
bool updMode = false;
|
||||
bool listMode = false;
|
||||
|
@ -131,6 +134,7 @@ main(int argc, char *argv[])
|
|||
bool locateMode = false;
|
||||
bool findMode = false;
|
||||
bool localMode = false;
|
||||
bool verifyMode = false;
|
||||
bool readMode = false;
|
||||
bool toHexMode = false;
|
||||
bool toB32Mode = false;
|
||||
|
@ -138,29 +142,29 @@ main(int argc, char *argv[])
|
|||
char *conffname;
|
||||
char defaultConfName[] = "daemon.ini";
|
||||
conffname = defaultConfName;
|
||||
char *rcfname;
|
||||
char defaultRcName[] = "other.signed";
|
||||
rcfname = defaultRcName;
|
||||
bool haveRequiredOptions = false;
|
||||
char *rcfname = nullptr;
|
||||
char *nodesdir = nullptr;
|
||||
while(1)
|
||||
{
|
||||
static struct option long_options[] = {
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"config", required_argument, 0, 'c'},
|
||||
{"logLevel", required_argument, 0, 'o'},
|
||||
{"generate", required_argument, 0, 'g'},
|
||||
{"update", required_argument, 0, 'u'},
|
||||
{"list", no_argument, 0, 'l'},
|
||||
{"list", required_argument, 0, 'l'},
|
||||
{"import", required_argument, 0, 'i'},
|
||||
{"export", required_argument, 0, 'e'},
|
||||
{"locate", required_argument, 0, 'q'},
|
||||
{"find", required_argument, 0, 'f'},
|
||||
{"find", required_argument, 0, 'F'},
|
||||
{"localInfo", no_argument, 0, 'n'},
|
||||
{"read", required_argument, 0, 'r'},
|
||||
{"b32", required_argument, 0, 'b'},
|
||||
{"hex", required_argument, 0, 'h'},
|
||||
{"verify", required_argument, 0, 'V'},
|
||||
{0, 0, 0, 0}};
|
||||
int option_index = 0;
|
||||
c = getopt_long(argc, argv, "c:o:g:lu:i:e:q:f:nr:b:h:", long_options,
|
||||
c = getopt_long(argc, argv, "c:f:o:g:lu:i:e:q:F:nr:b:h:V:", long_options,
|
||||
&option_index);
|
||||
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
|
||||
if(c == -1)
|
||||
|
@ -198,53 +202,53 @@ main(int argc, char *argv[])
|
|||
llarp::SetLogLevel(llarp::eLogError);
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
rcfname = optarg;
|
||||
verifyMode = true;
|
||||
break;
|
||||
case 'f':
|
||||
rcfname = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
haveRequiredOptions = true;
|
||||
listMode = true;
|
||||
nodesdir = optarg;
|
||||
listMode = true;
|
||||
break;
|
||||
case 'i':
|
||||
// printf ("option -g with value `%s'\n", optarg);
|
||||
rcfname = optarg;
|
||||
haveRequiredOptions = true;
|
||||
importMode = true;
|
||||
nodesdir = optarg;
|
||||
importMode = true;
|
||||
break;
|
||||
case 'e':
|
||||
// printf ("option -g with value `%s'\n", optarg);
|
||||
rcfname = optarg;
|
||||
haveRequiredOptions = true;
|
||||
exportMode = true;
|
||||
rcfname = optarg;
|
||||
exportMode = true;
|
||||
break;
|
||||
case 'q':
|
||||
// printf ("option -g with value `%s'\n", optarg);
|
||||
rcfname = optarg;
|
||||
haveRequiredOptions = true;
|
||||
locateMode = true;
|
||||
rcfname = optarg;
|
||||
locateMode = true;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
rcfname = optarg;
|
||||
haveRequiredOptions = true;
|
||||
findMode = true;
|
||||
break;
|
||||
case 'g':
|
||||
// printf ("option -g with value `%s'\n", optarg);
|
||||
rcfname = optarg;
|
||||
haveRequiredOptions = true;
|
||||
genMode = true;
|
||||
rcfname = optarg;
|
||||
genMode = true;
|
||||
break;
|
||||
case 'u':
|
||||
// printf ("option -u with value `%s'\n", optarg);
|
||||
rcfname = optarg;
|
||||
haveRequiredOptions = true;
|
||||
updMode = true;
|
||||
rcfname = optarg;
|
||||
updMode = true;
|
||||
break;
|
||||
case 'n':
|
||||
haveRequiredOptions = true;
|
||||
localMode = true;
|
||||
localMode = true;
|
||||
break;
|
||||
case 'r':
|
||||
rcfname = optarg;
|
||||
haveRequiredOptions = true;
|
||||
readMode = true;
|
||||
rcfname = optarg;
|
||||
readMode = true;
|
||||
break;
|
||||
case 'b':
|
||||
rcfname = optarg;
|
||||
|
@ -257,34 +261,142 @@ main(int argc, char *argv[])
|
|||
toHexMode = true;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
printf("Bad option: %c\n", c);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#undef MIN
|
||||
if(!haveRequiredOptions)
|
||||
if(!haveRequiredOptions)
|
||||
{
|
||||
llarp::LogError("Parameters dont all have their required parameters.\n");
|
||||
return 0;
|
||||
}
|
||||
printf("parsed options\n");
|
||||
if(!genMode && !updMode && !listMode && !importMode && !exportMode
|
||||
&& !locateMode && !localMode && !readMode && !findMode && !toB32Mode
|
||||
&& !toHexMode)
|
||||
{
|
||||
llarp::LogError(
|
||||
"I don't know what to do, no generate or update parameter\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = llarp_main_init(conffname, !TESTNET);
|
||||
if(!ctx)
|
||||
{
|
||||
llarp::LogError("Cant set up context");
|
||||
return 0;
|
||||
}
|
||||
signal(SIGINT, handle_signal);
|
||||
|
||||
llarp_rc tmp;
|
||||
|
||||
if(verifyMode)
|
||||
{
|
||||
llarp::LogError("Parameters dont all have their required parameters.\n");
|
||||
return 0;
|
||||
}
|
||||
printf("parsed options\n");
|
||||
if(!genMode && !updMode && !listMode && !importMode && !exportMode
|
||||
&& !locateMode && !localMode && !readMode && !findMode && !toB32Mode
|
||||
&& !toHexMode)
|
||||
{
|
||||
llarp::LogError(
|
||||
"I don't know what to do, no generate or update parameter\n");
|
||||
llarp_crypto crypto;
|
||||
llarp_crypto_libsodium_init(&crypto);
|
||||
llarp_rc rc;
|
||||
if(!llarp_rc_read(rcfname, &rc))
|
||||
{
|
||||
std::cout << "failed to read " << rcfname << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if(!llarp_rc_verify_sig(&crypto, &rc))
|
||||
{
|
||||
std::cout << rcfname << " has invalid signature" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if(!llarp_rc_is_public_router(&rc))
|
||||
{
|
||||
std::cout << rcfname << " is not a public router";
|
||||
if(llarp_ai_list_size(rc.addrs) == 0)
|
||||
{
|
||||
std::cout << " because it has no public addresses";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
return 1;
|
||||
}
|
||||
llarp::PubKey pubkey(rc.pubkey);
|
||||
llarp::PubKey enckey(rc.enckey);
|
||||
|
||||
std::cout << "router identity and dht routing key: " << pubkey << std::endl;
|
||||
std::cout << "router encryption key: " << enckey << std::endl;
|
||||
|
||||
if(rc.HasNick())
|
||||
std::cout << "router nickname: " << rc.Nick() << std::endl;
|
||||
|
||||
std::cout << "advertised addresses: ";
|
||||
llarp_ai_list_iter a_itr;
|
||||
a_itr.user = nullptr;
|
||||
a_itr.visit = [](llarp_ai_list_iter *, llarp_ai *addrInfo) -> bool {
|
||||
llarp::Addr addr(*addrInfo);
|
||||
std::cout << addr << " ";
|
||||
return true;
|
||||
};
|
||||
llarp_ai_list_iterate(rc.addrs, &a_itr);
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "advertised exits: ";
|
||||
|
||||
if(llarp_xi_list_size(rc.exits))
|
||||
{
|
||||
llarp_xi_list_iter e_itr;
|
||||
e_itr.user = nullptr;
|
||||
e_itr.visit = [](llarp_xi_list_iter *, llarp_xi *xi) -> bool {
|
||||
std::cout << *xi << " ";
|
||||
return true;
|
||||
};
|
||||
llarp_xi_list_iterate(rc.exits, &e_itr);
|
||||
}
|
||||
else
|
||||
std::cout << "none";
|
||||
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx = llarp_main_init(conffname, !TESTNET);
|
||||
if(!ctx)
|
||||
if(importMode)
|
||||
{
|
||||
llarp::LogError("Cant set up context");
|
||||
if(rcfname == nullptr)
|
||||
{
|
||||
std::cout << "no file to import" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
llarp_crypto crypto;
|
||||
llarp_crypto_libsodium_init(&crypto);
|
||||
auto nodedb = llarp_nodedb_new(&crypto);
|
||||
if(!llarp_nodedb_ensure_dir(nodesdir))
|
||||
{
|
||||
std::cout << "failed to ensure " << nodesdir << strerror(errno)
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
llarp_nodedb_set_dir(nodedb, nodesdir);
|
||||
llarp_rc rc;
|
||||
if(!llarp_rc_read(rcfname, &rc))
|
||||
{
|
||||
std::cout << "failed to read " << rcfname << " " << strerror(errno)
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!llarp_rc_verify_sig(&crypto, &rc))
|
||||
{
|
||||
std::cout << rcfname << " has invalid signature" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!llarp_nodedb_put_rc(nodedb, &rc))
|
||||
{
|
||||
std::cout << "failed to store " << strerror(errno) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "imported " << llarp::PubKey(rc.pubkey) << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
signal(SIGINT, handle_signal);
|
||||
|
||||
llarp_rc tmp;
|
||||
if(genMode)
|
||||
{
|
||||
printf("Creating [%s]\n", rcfname);
|
||||
|
@ -355,26 +467,22 @@ main(int argc, char *argv[])
|
|||
// write file
|
||||
llarp_rc_write(&tmp, our_rc_file_out.string().c_str());
|
||||
}
|
||||
if(listMode)
|
||||
{
|
||||
llarp_main_loadDatabase(ctx);
|
||||
llarp_nodedb_iter iter;
|
||||
iter.visit = printNode;
|
||||
llarp_main_iterateDatabase(ctx, iter);
|
||||
}
|
||||
if(importMode)
|
||||
{
|
||||
llarp_main_loadDatabase(ctx);
|
||||
llarp::LogInfo("Loading ", rcfname);
|
||||
llarp_rc rc;
|
||||
llarp_rc_clear(&rc);
|
||||
if(!llarp_rc_read(rcfname, &rc))
|
||||
|
||||
if(listMode)
|
||||
{
|
||||
llarp::LogError("Can't load RC");
|
||||
return 0;
|
||||
llarp_crypto crypto;
|
||||
llarp_crypto_libsodium_init(&crypto);
|
||||
auto nodedb = llarp_nodedb_new(&crypto);
|
||||
llarp_nodedb_iter itr;
|
||||
itr.visit = [](llarp_nodedb_iter *i) -> bool {
|
||||
std::cout << llarp::PubKey(i->rc->pubkey) << std::endl;
|
||||
return true;
|
||||
};
|
||||
if(llarp_nodedb_load_dir(nodedb, nodesdir) > 0)
|
||||
llarp_nodedb_iterate_all(nodedb, itr);
|
||||
llarp_nodedb_free(&nodedb);
|
||||
return 0;
|
||||
}
|
||||
llarp_main_putDatabase(ctx, &rc);
|
||||
}
|
||||
if(exportMode)
|
||||
{
|
||||
llarp_main_loadDatabase(ctx);
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef LLARP_BITS_HPP
|
||||
#define LLARP_BITS_HPP
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace bits
|
||||
{
|
||||
template < typename Int_t >
|
||||
constexpr size_t
|
||||
count_bits(const Int_t& i)
|
||||
{
|
||||
return i == 0 ? 0
|
||||
: ((i & 0x01) == 0x01) ? 1UL + count_bits(i >> 1)
|
||||
: count_bits(i >> 1);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr size_t
|
||||
__count_array_bits(const T& array, size_t idx)
|
||||
{
|
||||
return idx < sizeof(T)
|
||||
? count_bits(array[idx]) + __count_array_bits(array, idx + 1)
|
||||
: 0;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr size_t
|
||||
count_array_bits(const T& array)
|
||||
{
|
||||
return __count_array_bits(array, 0);
|
||||
}
|
||||
} // namespace bits
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -3,6 +3,10 @@
|
|||
#include <llarp/buffer.h>
|
||||
#include <llarp/crypto.h>
|
||||
#include <llarp/net.h>
|
||||
#ifdef __cplusplus
|
||||
#include <iostream>
|
||||
#include <llarp/bits.hpp>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* exit_info.h
|
||||
|
@ -10,18 +14,47 @@
|
|||
* utilities for handling exits on the llarp network
|
||||
*/
|
||||
|
||||
struct llarp_xi;
|
||||
|
||||
bool
|
||||
llarp_xi_bdecode(struct llarp_xi *xi, llarp_buffer_t *buf);
|
||||
bool
|
||||
llarp_xi_bencode(const struct llarp_xi *xi, llarp_buffer_t *buf);
|
||||
|
||||
/// Exit info model
|
||||
struct llarp_xi
|
||||
{
|
||||
struct in6_addr address;
|
||||
struct in6_addr netmask;
|
||||
byte_t pubkey[PUBKEYSIZE];
|
||||
};
|
||||
|
||||
bool
|
||||
llarp_xi_bdecode(struct llarp_xi *xi, llarp_buffer_t *buf);
|
||||
bool
|
||||
llarp_xi_bencode(struct llarp_xi *xi, llarp_buffer_t *buf);
|
||||
#ifdef __cplusplus
|
||||
bool
|
||||
BEncode(llarp_buffer_t *buf) const
|
||||
{
|
||||
return llarp_xi_bencode(this, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
BDecode(llarp_buffer_t *buf)
|
||||
{
|
||||
return llarp_xi_bdecode(this, buf);
|
||||
}
|
||||
|
||||
friend std::ostream &
|
||||
operator<<(std::ostream &out, const llarp_xi &xi)
|
||||
{
|
||||
char tmp[128] = {0};
|
||||
if(inet_ntop(AF_INET6, &xi.address, tmp, sizeof(tmp)))
|
||||
out << std::string(tmp);
|
||||
else
|
||||
return out;
|
||||
out << std::string("/");
|
||||
return out << std::to_string(
|
||||
llarp::bits::count_array_bits(xi.netmask.s6_addr));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
struct llarp_xi_list;
|
||||
|
||||
|
@ -43,6 +76,9 @@ llarp_xi_list_pushback(struct llarp_xi_list *l, struct llarp_xi *xi);
|
|||
void
|
||||
llarp_xi_list_copy(struct llarp_xi_list *dst, struct llarp_xi_list *src);
|
||||
|
||||
size_t
|
||||
llarp_xi_list_size(const struct llarp_xi_list *l);
|
||||
|
||||
void
|
||||
llarp_xi_copy(struct llarp_xi *dst, struct llarp_xi *src);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define LLARP_IP_HPP
|
||||
#include <llarp/buffer.h>
|
||||
#include <llarp/time.h>
|
||||
#include <llarp/net.hpp>
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h> // FreeBSD needs this for uchar for ip.h
|
||||
#include <netinet/in.h>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef LLARP_LINUX_NETNS_HPP
|
||||
#define LLARP_LINUX_NETNS_HPP
|
||||
#ifdef __linux__
|
||||
namespace llarp
|
||||
{
|
||||
namespace linux
|
||||
{
|
||||
/// switch current process to use network namepsace by name
|
||||
/// returns true if successfully switched otherwise returns false
|
||||
bool
|
||||
NetNSSwitch(const char* name);
|
||||
} // namespace linux
|
||||
} // namespace llarp
|
||||
#else
|
||||
#error "Don't include this file"
|
||||
#endif
|
||||
#endif
|
|
@ -139,24 +139,21 @@ namespace llarp
|
|||
friend std::ostream&
|
||||
operator<<(std::ostream& out, const Addr& a)
|
||||
{
|
||||
char tmp[128] = {0};
|
||||
socklen_t sz;
|
||||
char tmp[128] = {0};
|
||||
const void* ptr = nullptr;
|
||||
if(a.af() == AF_INET6)
|
||||
{
|
||||
out << "[";
|
||||
sz = sizeof(sockaddr_in6);
|
||||
ptr = a.addr6();
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = sizeof(sockaddr_in);
|
||||
ptr = a.addr4();
|
||||
}
|
||||
#ifndef _MSC_VER
|
||||
if(inet_ntop(a.af(), ptr, tmp, sz))
|
||||
if(inet_ntop(a.af(), ptr, tmp, sizeof(tmp)))
|
||||
#else
|
||||
if(inet_ntop(a.af(), (void*)ptr, tmp, sz))
|
||||
if(inet_ntop(a.af(), (void*)ptr, tmp, sizeof(tmp)))
|
||||
#endif
|
||||
{
|
||||
out << tmp;
|
||||
|
|
|
@ -25,6 +25,9 @@ llarp_nodedb_free(struct llarp_nodedb **n);
|
|||
bool
|
||||
llarp_nodedb_ensure_dir(const char *dir);
|
||||
|
||||
void
|
||||
llarp_nodedb_set_dir(struct llarp_nodedb *n, const char *dir);
|
||||
|
||||
/// load entire nodedb from fs skiplist at dir
|
||||
ssize_t
|
||||
llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir);
|
||||
|
|
|
@ -47,6 +47,12 @@ struct llarp_rc
|
|||
return llarp_rc_bdecode(this, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
HasNick() const
|
||||
{
|
||||
return nickname[0] != 0;
|
||||
}
|
||||
|
||||
std::string
|
||||
Nick() const
|
||||
{
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
#endif
|
||||
|
||||
#ifndef LLARP_VERSION_MIN
|
||||
#define LLARP_VERSION_MIN "0"
|
||||
#define LLARP_VERSION_MIN "1"
|
||||
#endif
|
||||
|
||||
#ifndef LLARP_VERSION_PATCH
|
||||
#define LLARP_VERSION_PATCH "3"
|
||||
#define LLARP_VERSION_PATCH "0"
|
||||
#endif
|
||||
|
||||
#ifndef LLARP_VERSION_NUM
|
||||
|
|
|
@ -64,8 +64,8 @@ namespace llarp
|
|||
// discard entry
|
||||
return true;
|
||||
#else
|
||||
// writefile
|
||||
return false;
|
||||
// writefile
|
||||
return false;
|
||||
#endif
|
||||
});
|
||||
/// reset errno
|
||||
|
|
|
@ -153,8 +153,8 @@ struct llarp_win32_loop : public llarp_ev_loop
|
|||
++idx;
|
||||
} while(::GetQueuedCompletionStatus(iocpfd, &iolen, &ev_id, &qdata, ms));
|
||||
|
||||
// tick_listeners inlined since win32 does not
|
||||
// implement ev_tun
|
||||
// tick_listeners inlined since win32 does not
|
||||
// implement ev_tun
|
||||
for(auto& l : udp_listeners)
|
||||
{
|
||||
if(l->tick)
|
||||
|
|
|
@ -53,8 +53,16 @@ llarp_xi_list_iterate(struct llarp_xi_list *l, struct llarp_xi_list_iter *iter)
|
|||
return;
|
||||
}
|
||||
|
||||
size_t
|
||||
llarp_xi_list_size(const struct llarp_xi_list *l)
|
||||
{
|
||||
if(l)
|
||||
return l->list.size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
llarp_xi_bencode(struct llarp_xi *xi, llarp_buffer_t *buff)
|
||||
llarp_xi_bencode(const struct llarp_xi *xi, llarp_buffer_t *buff)
|
||||
{
|
||||
char addr_buff[128] = {0};
|
||||
const char *addr;
|
||||
|
|
35
llarp/fs.hpp
35
llarp/fs.hpp
|
@ -1,6 +1,6 @@
|
|||
#ifndef LLARP_FS_HPP
|
||||
#define LLARP_FS_HPP
|
||||
|
||||
#include <functional>
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define PATH_SEP "\\"
|
||||
#else
|
||||
|
@ -24,4 +24,37 @@ namespace fs = std::filesystem;
|
|||
namespace fs = cpp17::filesystem;
|
||||
#endif
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
typedef std::function< bool(const fs::path &) > PathVisitor;
|
||||
typedef std::function< void(const fs::path &, PathVisitor) > PathIter;
|
||||
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
|
||||
static PathIter IterDir = [](const fs::path &path, PathVisitor visit) {
|
||||
fs::directory_iterator i(path);
|
||||
auto itr = fs::begin(i);
|
||||
while(itr != fs::end(i))
|
||||
{
|
||||
fs::path p = path / *itr;
|
||||
if(!visit(p))
|
||||
return;
|
||||
++itr;
|
||||
}
|
||||
};
|
||||
#else
|
||||
static PathIter IterDir = [](const fs::path &path, PathVisitor visit) {
|
||||
fs::directory_iterator i(path);
|
||||
auto itr = i.begin();
|
||||
while(itr != itr.end())
|
||||
{
|
||||
fs::path p = path / *itr;
|
||||
if(!visit(p))
|
||||
return;
|
||||
++itr;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
} // namespace util
|
||||
} // namespace llarp
|
||||
#endif // end LLARP_FS_HPP
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace llarp
|
|||
#undef MIN
|
||||
#endif
|
||||
memcpy(buf, pkt.base, sz);
|
||||
llarp::DumpBufferHex(pkt);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,319 @@
|
|||
|
||||
#include <asm/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <sys/capability.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <llarp/linux/netns.hpp>
|
||||
#include <llarp/logger.hpp>
|
||||
#ifndef MS_REC
|
||||
#define MS_REC (16384)
|
||||
#endif
|
||||
#include "fs.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace linux
|
||||
{
|
||||
static const char netns_rundir[] = "/var/run/netns";
|
||||
static const char netns_etcdir[] = "/etc/netns";
|
||||
|
||||
static bool
|
||||
GetCGroups2MountPoint(fs::path& cgroups2_mount)
|
||||
{
|
||||
std::string mountpoint;
|
||||
std::ifstream inf;
|
||||
inf.open("/proc/mounts");
|
||||
if(!inf.is_open())
|
||||
{
|
||||
llarp::LogError("failed to open /proc/mounts");
|
||||
return false;
|
||||
}
|
||||
std::string line;
|
||||
while(std::getline(inf, line))
|
||||
{
|
||||
std::string part;
|
||||
std::stringstream parts;
|
||||
parts.str(line);
|
||||
// discard
|
||||
std::getline(parts, part);
|
||||
// mount point
|
||||
std::getline(parts, part);
|
||||
mountpoint = part;
|
||||
// type
|
||||
std::getline(parts, part);
|
||||
if(part == "cgroup2")
|
||||
{
|
||||
// found cgroup2 mountpoint
|
||||
cgroups2_mount = mountpoint;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
llarp::LogError("cannot find cgroups2 in /proc/mounts");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetNetNS(std::string& netns)
|
||||
{
|
||||
auto nfd = open("/proc/self/ns/net", O_RDONLY);
|
||||
if(nfd < 0)
|
||||
{
|
||||
llarp::LogError(
|
||||
"Failed to get our own netns, could not open /proc/self/ns/net");
|
||||
return false;
|
||||
}
|
||||
struct stat netst;
|
||||
if(::fstat(nfd, &netst) < 0)
|
||||
{
|
||||
close(nfd);
|
||||
llarp::LogError("stat of netns failed: ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
close(nfd);
|
||||
fs::path run_dir = netns_rundir;
|
||||
bool foundIt = false;
|
||||
// find corrosponding file for netns
|
||||
llarp::util::IterDir(run_dir, [&](const fs::path& f) -> bool {
|
||||
struct stat fst;
|
||||
if(::stat(f.string().c_str(), &fst) >= 0)
|
||||
{
|
||||
if(fst.st_dev == netst.st_dev && fst.st_ino == netst.st_ino)
|
||||
{
|
||||
// found it
|
||||
foundIt = true;
|
||||
netns = f.filename().string();
|
||||
// break iteration
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// continue iteration
|
||||
return true;
|
||||
});
|
||||
return foundIt;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetVRFPath(std::string& path)
|
||||
{
|
||||
char p[256] = {0};
|
||||
snprintf(p, sizeof(p), "/proc/%d/cgroup", getpid());
|
||||
std::ifstream inf;
|
||||
inf.open(p);
|
||||
if(!inf.is_open())
|
||||
{
|
||||
llarp::LogError("could not open '", p, "': ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
path = "";
|
||||
std::string line;
|
||||
while(std::getline(inf, line))
|
||||
{
|
||||
auto pos = line.find("::/");
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
line = line.substr(pos + 2);
|
||||
pos = line.find("/vrf");
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
path = line.substr(pos);
|
||||
if(path == "/")
|
||||
path = "";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
ResetVRF()
|
||||
{
|
||||
fs::path cgroups2_mount;
|
||||
if(!GetCGroups2MountPoint(cgroups2_mount))
|
||||
{
|
||||
llarp::LogError("could not find cgroup2 mount point, is it mounted?");
|
||||
return false;
|
||||
}
|
||||
std::string netns;
|
||||
if(!GetNetNS(netns))
|
||||
{
|
||||
llarp::LogError("could not get our netns: ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
std::string vrfpath;
|
||||
if(!GetVRFPath(vrfpath))
|
||||
{
|
||||
llarp::LogError("could not determine vrf cgroup path: ",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
fs::path cgroup_path =
|
||||
cgroups2_mount / vrfpath / netns / "vrf" / "default";
|
||||
std::error_code ec;
|
||||
if(!fs::exists(cgroup_path, ec))
|
||||
{
|
||||
if(!fs::create_directories(cgroup_path, ec))
|
||||
{
|
||||
llarp::LogError("could not create '", cgroup_path.string(),
|
||||
"': ", ec);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(ec)
|
||||
{
|
||||
llarp::LogError("Could not check '", cgroup_path.string(), "': ", ec);
|
||||
return false;
|
||||
}
|
||||
cgroup_path /= "cgroup.procs";
|
||||
auto fd = open(cgroup_path.string().c_str(), O_RDWR | O_APPEND);
|
||||
if(fd < 0)
|
||||
{
|
||||
llarp::LogError("could not open '", cgroup_path.string(),
|
||||
"': ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
bool success = true;
|
||||
std::string pid = std::to_string(getpid());
|
||||
if(write(fd, pid.c_str(), pid.size()) < 0)
|
||||
{
|
||||
llarp::LogError("failed to join cgroup");
|
||||
success = false;
|
||||
}
|
||||
close(fd);
|
||||
return success;
|
||||
}
|
||||
|
||||
/// bind network namespace paths into /etc/
|
||||
static bool
|
||||
BindNetworkNS(const char* name)
|
||||
{
|
||||
fs::path etc_dir = netns_etcdir;
|
||||
etc_dir /= name;
|
||||
std::error_code ec;
|
||||
if(!fs::exists(etc_dir, ec))
|
||||
{
|
||||
errno = 0;
|
||||
llarp::LogInfo(etc_dir, " does not exist, skipping");
|
||||
return true;
|
||||
}
|
||||
bool didFail = false;
|
||||
llarp::util::IterDir(etc_dir, [&](const fs::path& f) -> bool {
|
||||
if(fs::is_regular_file(f))
|
||||
{
|
||||
fs::path netns_path = "/etc";
|
||||
netns_path /= f.filename();
|
||||
if(mount(f.string().c_str(), netns_path.string().c_str(), "none",
|
||||
MS_BIND, nullptr)
|
||||
< 0)
|
||||
{
|
||||
llarp::LogError("failed to bind '", f.string(), "' to '",
|
||||
netns_path.string(), "': ", strerror(errno));
|
||||
didFail = true;
|
||||
}
|
||||
}
|
||||
// continue iteration
|
||||
return true;
|
||||
});
|
||||
return !didFail;
|
||||
}
|
||||
|
||||
static void
|
||||
DropCap()
|
||||
{
|
||||
if(getuid() != 0 && geteuid() != 0)
|
||||
{
|
||||
cap_t capabilities;
|
||||
cap_value_t net_admin = CAP_NET_ADMIN;
|
||||
cap_flag_t inheritable = CAP_INHERITABLE;
|
||||
cap_flag_value_t is_set;
|
||||
|
||||
capabilities = cap_get_proc();
|
||||
if(!capabilities)
|
||||
exit(EXIT_FAILURE);
|
||||
if(cap_get_flag(capabilities, net_admin, inheritable, &is_set) != 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if(is_set == CAP_CLEAR)
|
||||
{
|
||||
if(cap_clear(capabilities) != 0)
|
||||
exit(EXIT_FAILURE);
|
||||
if(cap_set_proc(capabilities) != 0)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cap_free(capabilities);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
NetNSSwitch(const char* name)
|
||||
{
|
||||
fs::path netns_path = netns_rundir;
|
||||
netns_path /= name;
|
||||
auto nsfd = open(netns_path.string().c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if(nsfd < 0)
|
||||
{
|
||||
llarp::LogError("Failed to open network namespace '", name,
|
||||
"': ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if(setns(nsfd, CLONE_NEWNET) < 0)
|
||||
{
|
||||
llarp::LogError("Failed to enter network namespace '", name,
|
||||
"': ", strerror(errno));
|
||||
close(nsfd);
|
||||
return false;
|
||||
}
|
||||
close(nsfd);
|
||||
if(unshare(CLONE_NEWNS) < 0)
|
||||
{
|
||||
llarp::LogError("unshare failed: ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
// dont let any mount points prop back to parent
|
||||
// iproute2 source does this
|
||||
if(mount("", "/", "none", MS_SLAVE | MS_REC, nullptr))
|
||||
{
|
||||
llarp::LogError("mount --make-rslave failed: ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
unsigned long mountflags = 0;
|
||||
// ensaure /sys not mounted
|
||||
if(umount2("/sys", MNT_DETACH) < 0)
|
||||
{
|
||||
struct statvfs fsstat;
|
||||
if(statvfs("/sys", &fsstat) == 0)
|
||||
{
|
||||
if(fsstat.f_flag & ST_RDONLY)
|
||||
mountflags = MS_RDONLY;
|
||||
}
|
||||
}
|
||||
// mount sysfs for our namespace
|
||||
if(mount(name, "/sys", "sysfs", mountflags, nullptr) < 0)
|
||||
{
|
||||
llarp::LogError("failed to mount sysfs: ", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
if(!BindNetworkNS(name))
|
||||
{
|
||||
llarp::LogError("failed to bind namespace directories");
|
||||
return false;
|
||||
}
|
||||
if(!ResetVRF())
|
||||
{
|
||||
llarp::LogError("failed to reset vrf");
|
||||
return false;
|
||||
}
|
||||
DropCap();
|
||||
return true;
|
||||
}
|
||||
} // namespace linux
|
||||
} // namespace llarp
|
|
@ -112,9 +112,9 @@ struct llarp_nodedb
|
|||
const char *hexname =
|
||||
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(pubkey, ftmp);
|
||||
std::string hexString(hexname);
|
||||
hexString += RC_FILE_EXT;
|
||||
std::string skiplistDir;
|
||||
skiplistDir += hexString[hexString.length() - 1];
|
||||
hexString += RC_FILE_EXT;
|
||||
fs::path filepath = nodePath / skiplistDir / hexString;
|
||||
return filepath.string();
|
||||
}
|
||||
|
@ -184,20 +184,11 @@ struct llarp_nodedb
|
|||
loadSubdir(const fs::path &dir)
|
||||
{
|
||||
ssize_t sz = 0;
|
||||
fs::directory_iterator i(dir);
|
||||
#if defined(CPP17) && defined(USE_CXX17_FILESYSTEM)
|
||||
auto itr = fs::begin(i);
|
||||
while(itr != fs::end(i))
|
||||
#else
|
||||
auto itr = i.begin();
|
||||
while(itr != itr.end())
|
||||
#endif
|
||||
{
|
||||
if(fs::is_regular_file(itr->path()) && loadfile(*itr))
|
||||
llarp::util::IterDir(dir, [&](const fs::path &f) -> bool {
|
||||
if(fs::is_regular_file(f) && loadfile(f))
|
||||
sz++;
|
||||
|
||||
++itr;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
@ -375,6 +366,12 @@ llarp_nodedb_ensure_dir(const char *dir)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
llarp_nodedb_set_dir(struct llarp_nodedb *n, const char *dir)
|
||||
{
|
||||
n->nodePath = dir;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir)
|
||||
{
|
||||
|
@ -383,7 +380,7 @@ llarp_nodedb_load_dir(struct llarp_nodedb *n, const char *dir)
|
|||
{
|
||||
return -1;
|
||||
}
|
||||
n->nodePath = dir;
|
||||
llarp_nodedb_set_dir(n, dir);
|
||||
return n->Load(dir);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace llarp
|
|||
{
|
||||
llarp::LogInfo("isolating network to namespace ", m_NetNS);
|
||||
m_IsolatedWorker = llarp_init_isolated_net_threadpool(
|
||||
m_Name.c_str(), &SetupIsolatedNetwork, &RunIsolatedMainLoop, this);
|
||||
m_NetNS.c_str(), &SetupIsolatedNetwork, &RunIsolatedMainLoop, this);
|
||||
m_IsolatedLogic = llarp_init_single_process_logic(m_IsolatedWorker);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/wait.h>
|
||||
#include <llarp/linux/netns.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -113,30 +113,23 @@ namespace llarp
|
|||
void
|
||||
IsolatedPool::Spawn(size_t workers, const char *name)
|
||||
{
|
||||
#ifdef __linux__
|
||||
IsolatedPool *self = this;
|
||||
self->m_IsolatedName = name;
|
||||
self->IsolatedName = name;
|
||||
self->m_IsolatedWorkers = workers;
|
||||
m_isolated = new std::thread([self] {
|
||||
if(unshare(self->m_flags) == -1)
|
||||
if(!self->IsolateCurrentProcess())
|
||||
{
|
||||
llarp::LogError("unshared failed: ", strerror(errno));
|
||||
llarp::LogError("isolation failed: ", strerror(errno));
|
||||
self->Fail();
|
||||
return;
|
||||
}
|
||||
else
|
||||
llarp::LogInfo("spawning isolated environment");
|
||||
self->Pool::Spawn(self->m_IsolatedWorkers, self->IsolatedName);
|
||||
if(self->Isolated())
|
||||
{
|
||||
llarp::LogInfo("spawning isolated environment");
|
||||
self->Pool::Spawn(self->m_IsolatedWorkers, self->m_IsolatedName);
|
||||
if(self->Isolated())
|
||||
{
|
||||
self->MainLoop();
|
||||
}
|
||||
self->MainLoop();
|
||||
}
|
||||
});
|
||||
#else
|
||||
llarp::LogError("isolated processes not supported on your platform");
|
||||
Pool::Spawn(workers, name);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -151,27 +144,51 @@ namespace llarp
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
NetIsolatedPool::NetIsolatedPool(
|
||||
_NetIsolatedPool::_NetIsolatedPool(
|
||||
std::function< bool(void *, bool) > setupNet,
|
||||
std::function< void(void *) > runMain, void *user)
|
||||
: IsolatedPool(CLONE_NEWNET)
|
||||
: IsolatedPool(0)
|
||||
|
||||
{
|
||||
m_NetSetup = setupNet;
|
||||
m_RunMain = runMain;
|
||||
m_user = user;
|
||||
}
|
||||
#else
|
||||
NetIsolatedPool::NetIsolatedPool(
|
||||
std::function< bool(void *, bool) > setupNet,
|
||||
std::function< void(void *) > runMain, void *user)
|
||||
: IsolatedPool(0)
|
||||
|
||||
#ifdef __linux__
|
||||
struct LinuxNetNSIsolatedPool : public _NetIsolatedPool
|
||||
{
|
||||
m_NetSetup = setupNet;
|
||||
m_RunMain = runMain;
|
||||
m_user = user;
|
||||
}
|
||||
LinuxNetNSIsolatedPool(std::function< bool(void *, bool) > setup,
|
||||
std::function< void(void *) > run, void *user)
|
||||
: _NetIsolatedPool(setup, run, user)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
IsolateNetwork()
|
||||
{
|
||||
return llarp::linux::NetNSSwitch(IsolatedName);
|
||||
}
|
||||
};
|
||||
|
||||
typedef LinuxNetNSIsolatedPool NetIsolatedPool;
|
||||
#define NET_ISOLATION_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
struct FreeBSDJailedThreadPool : public _NetIsolatedPool
|
||||
{
|
||||
bool
|
||||
IsolateNetwork()
|
||||
{
|
||||
// TODO: implement me
|
||||
return false;
|
||||
}
|
||||
};
|
||||
typedef FreeBSDJailedThreadPool NetIsolatedPool;
|
||||
#define NET_ISOLATION_SUPPORTED
|
||||
#endif
|
||||
|
||||
} // namespace thread
|
||||
} // namespace llarp
|
||||
|
||||
|
@ -186,9 +203,17 @@ struct llarp_threadpool
|
|||
setup_net_func setup = nullptr,
|
||||
run_main_func runmain = nullptr, void *user = nullptr)
|
||||
{
|
||||
#ifdef NET_ISOLATION_SUPPORTED
|
||||
if(isolate)
|
||||
impl = new llarp::thread::NetIsolatedPool(setup, runmain, user);
|
||||
else
|
||||
#else
|
||||
if(isolate)
|
||||
{
|
||||
llarp::LogError("network isolation not supported");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
impl = new llarp::thread::Pool();
|
||||
impl->Spawn(workers, name);
|
||||
}
|
||||
|
|
|
@ -66,6 +66,17 @@ namespace llarp
|
|||
void
|
||||
Join();
|
||||
|
||||
/// isolate current thread
|
||||
/// return true for success
|
||||
/// return false for failure
|
||||
/// set errno on fail
|
||||
/// override me in subclass
|
||||
virtual bool
|
||||
IsolateCurrentProcess()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// override me to do specific setups after isolation
|
||||
// return true for success
|
||||
virtual bool
|
||||
|
@ -82,8 +93,8 @@ namespace llarp
|
|||
|
||||
std::thread* m_isolated = nullptr;
|
||||
int m_flags;
|
||||
int m_IsolatedWorkers = 0;
|
||||
const char* m_IsolatedName = nullptr;
|
||||
int m_IsolatedWorkers = 0;
|
||||
const char* IsolatedName = nullptr;
|
||||
|
||||
virtual void
|
||||
MainLoop()
|
||||
|
@ -91,10 +102,20 @@ namespace llarp
|
|||
}
|
||||
};
|
||||
|
||||
struct NetIsolatedPool : public IsolatedPool
|
||||
struct _NetIsolatedPool : public IsolatedPool
|
||||
{
|
||||
NetIsolatedPool(std::function< bool(void*, bool) > setupNet,
|
||||
std::function< void(void*) > runMain, void* user);
|
||||
_NetIsolatedPool(std::function< bool(void*, bool) > setupNet,
|
||||
std::function< void(void*) > runMain, void* user);
|
||||
|
||||
/// implement me per platform
|
||||
virtual bool
|
||||
IsolateNetwork() = 0;
|
||||
|
||||
bool
|
||||
IsolateCurrentProcess()
|
||||
{
|
||||
return IsolateNetwork();
|
||||
}
|
||||
|
||||
bool
|
||||
Isolated()
|
||||
|
|
Loading…
Reference in New Issue