This commit is contained in:
Ryan Tharp 2018-09-06 00:32:06 +00:00
commit 742a0b8da7
22 changed files with 752 additions and 136 deletions

View File

@ -29,3 +29,4 @@ SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
Standard: Cpp11
UseTab: Never
SortIncludes: false

View File

@ -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()

View File

@ -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);

35
include/llarp/bits.hpp Normal file
View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -47,6 +47,12 @@ struct llarp_rc
return llarp_rc_bdecode(this, buf);
}
bool
HasNick() const
{
return nickname[0] != 0;
}
std::string
Nick() const
{

View File

@ -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

View File

@ -64,8 +64,8 @@ namespace llarp
// discard entry
return true;
#else
// writefile
return false;
// writefile
return false;
#endif
});
/// reset errno

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -17,7 +17,6 @@ namespace llarp
#undef MIN
#endif
memcpy(buf, pkt.base, sz);
llarp::DumpBufferHex(pkt);
return true;
}

319
llarp/linux/netns.cpp Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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()

View File

@ -1 +1 @@
something something traffic shape
traffic correlation nation