Merge remote-tracking branch 'ryan/master'

pull/18/head
Jeff Becker 6 years ago
commit 7b0860aec0
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -155,7 +155,7 @@ endif()
if(JEMALLOC)
set(MALLOC_LIB jemalloc)
endif()
set(LIBS ${SODIUM_LIB} ${THREAD_LIB} ${MALLOC_LIB})
if(HAVE_CXX17_FILESYSTEM)
set(LIBS ${LIBS} stdc++fs)
@ -319,7 +319,6 @@ set(NTRU_SRC
crypto/libntrup/src/ntru.cpp
)
set(UTP_SRC
libutp/utp_callbacks.cpp
libutp/utp_utils.cpp
@ -349,6 +348,8 @@ set(LIB_SRC
llarp/dns.cpp
llarp/dnsc.cpp
llarp/dnsd.cpp
llarp/dns_iptracker.cpp
llarp/dns_dotlokilookup.cpp
llarp/encode.cpp
llarp/encrypted_frame.cpp
llarp/exit_info.cpp
@ -405,6 +406,8 @@ set(DNS_SRC
llarp/dns.cpp
llarp/dnsc.cpp
llarp/dnsd.cpp
llarp/dns_iptracker.cpp
llarp/dns_dotlokilookup.cpp
llarp/net.cpp
daemon/dns.cpp
)
@ -445,6 +448,8 @@ set(ANDROID_LIB ${LIB}android)
include_directories(llarp)
include_directories(include)
include_directories(vendor/cppbackport-master/lib)
# Neuro Linux box hack:
include_directories(/usr/local/include)
include_directories(${sodium_INCLUDE_DIR})
if (MSVC)

@ -1,6 +1,7 @@
#include <libntrup/ntru.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdio.h> // printf
#if __AVX2__
#include <cpuid.h>
@ -77,4 +78,4 @@ extern "C"
{
return __crypto_kem_keypair(pk, sk);
}
}
}

@ -1,20 +1,15 @@
#include <getopt.h>
#include <signal.h>
#include <stdio.h> /* fprintf, printf */
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <llarp.h>
#include <llarp/logic.h>
#include "dnsd.hpp"
#include "ev.hpp"
#include "llarp/net.hpp"
#include "logger.hpp"
#include <llarp/dns_iptracker.hpp>
#include <llarp/dnsd.hpp>
#include <llarp/dns_dotlokilookup.hpp>
#include <thread> // for multithreaded version
#include <vector>
#include <llarp/threading.hpp> // for multithreaded version (multiplatorm)
#include <signal.h> // Linux needs this for SIGINT
// keep this once jeff reenables concurrency
#ifdef _MSC_VER
extern "C" void
@ -29,6 +24,11 @@ SetThreadName(DWORD dwThreadID, LPCSTR szThreadName);
#include <pthread_np.h>
#endif
// CHECK: is multiprocess still a thing?
#ifndef TESTNET
#define TESTNET 0
#endif
struct llarp_main *ctx = 0;
bool done = false;
@ -37,20 +37,11 @@ handle_signal(int sig)
{
printf("got SIGINT\n");
done = true;
// if using router, signal it
if(ctx)
llarp_main_signal(ctx, sig);
}
sockaddr *
hookChecker(std::string name, struct dnsd_context *context)
{
llarp::LogInfo("Hooked ", name);
// cast your context->user;
return nullptr;
}
// FIXME: make configurable
#define SERVER "8.8.8.8"
#define PORT 53
struct dns_relay_config
{
std::string upstream_host;
@ -83,7 +74,9 @@ int
main(int argc, char *argv[])
{
int code = 1;
llarp::LogInfo("Starting up server");
char cwd[1024];
getcwd(cwd, sizeof(cwd));
llarp::LogInfo("Starting up server at ", cwd);
const char *conffname = handleBaseCmdLineArgs(argc, argv);
dns_relay_config dnsr_config;
@ -91,13 +84,12 @@ main(int argc, char *argv[])
dnsr_config.upstream_port = 53;
llarp_config *config_reader;
llarp_new_config(&config_reader);
// ctx = llarp_main_init(conffname, multiThreaded);
if(llarp_load_config(config_reader, conffname))
{
llarp_free_config(&config_reader);
llarp::LogError("failed to load config file ", conffname);
return false;
return 0;
}
llarp_config_iterator iter;
iter.user = &dnsr_config;
@ -105,20 +97,83 @@ main(int argc, char *argv[])
llarp_config_iter(config_reader, &iter);
llarp::LogInfo("config [", conffname, "] loaded");
const uint16_t server_port = 53;
dns_iptracker_init();
// llarp::SetLogLevel(llarp::eLogDebug);
if(1)
{
// libev version w/router context
ctx = llarp_main_init(conffname, !TESTNET);
if(!ctx)
{
llarp::LogError("Cant set up context");
return 0;
}
llarp_main_setup(ctx);
signal(SIGINT, handle_signal);
struct dnsd_context dnsd;
if(!llarp_main_init_dnsd(ctx, &dnsd, server_port,
(const char *)dnsr_config.upstream_host.c_str(),
dnsr_config.upstream_port))
{
llarp::LogError("Couldnt init dns daemon");
}
// Configure intercept
dnsd.intercept = &llarp_dotlokilookup_handler;
dotLokiLookup dll;
// should be a function...
// dll.tunEndpoint = main_router_getFirstTunEndpoint(ctx);
// dll.ip_tracker = &g_dns_iptracker;
llarp_main_init_dotLokiLookup(ctx, &dll);
dnsd.user = &dll;
// check tun set up
llarp_tun_io *tun = main_router_getRange(ctx);
llarp::LogDebug("TunNetmask: ", tun->netmask);
llarp::LogDebug("TunIfAddr: ", tun->ifaddr);
// configure dns_ip_tracker to use this
// well our routes table should already be set up
// mark our TunIfAddr as used
if(tun)
{
struct sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr(tun->ifaddr);
addr.sin_family = AF_INET;
llarp::Addr tunIp(addr);
llarp::LogDebug("llarp::TunIfAddr: ", tunIp);
dns_iptracker_setup_dotLokiLookup(&dll, tunIp);
dns_iptracker_setup(tunIp);
}
else
{
llarp::LogWarn("No tun interface, can't look up .loki");
}
// run system and wait
llarp_main_run(ctx);
llarp_main_free(ctx);
}
else if(0)
{
// libev version
llarp_ev_loop *netloop = nullptr;
llarp_threadpool *worker = nullptr;
llarp_logic *logic = nullptr;
llarp_ev_loop_alloc(&netloop);
llarp_ev_loop_alloc(&netloop); // set up netio worker
worker = llarp_init_same_process_threadpool();
logic = llarp_init_single_process_logic(worker); // set up logic worker
// configure main netloop
struct dnsd_context dnsd;
if(!llarp_dnsd_init(&dnsd, netloop, "*", 1053,
if(!llarp_dnsd_init(&dnsd, logic, netloop, "*", server_port,
(const char *)dnsr_config.upstream_host.c_str(),
dnsr_config.upstream_port))
{
@ -127,11 +182,9 @@ main(int argc, char *argv[])
return 0;
}
// Configure intercept
dnsd.intercept = &hookChecker;
dnsd.intercept = &llarp_dotlokilookup_handler;
llarp::LogInfo("singlethread start");
worker = llarp_init_same_process_threadpool();
logic = llarp_init_single_process_logic(worker);
llarp_ev_loop_run_single_process(netloop, worker, logic);
llarp::LogInfo("singlethread end");
@ -139,13 +192,32 @@ main(int argc, char *argv[])
}
else
{
// need this for timer stuff
llarp_threadpool *worker = nullptr;
llarp_logic *logic = nullptr;
worker = llarp_init_same_process_threadpool();
logic = llarp_init_single_process_logic(worker); // set up logic worker
// configure main netloop
struct dnsd_context dnsd;
if(!llarp_dnsd_init(&dnsd, logic, nullptr, "*", server_port,
(const char *)dnsr_config.upstream_host.c_str(),
dnsr_config.upstream_port))
{
// llarp::LogError("failed to initialize dns subsystem");
llarp::LogError("Couldnt init dns daemon");
return 0;
}
// Configure intercept
dnsd.intercept = &llarp_dotlokilookup_handler;
struct sockaddr_in m_address;
int m_sockfd;
m_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
m_address.sin_family = AF_INET;
m_address.sin_addr.s_addr = INADDR_ANY;
m_address.sin_port = htons(1053);
m_address.sin_port = htons(server_port);
int rbind = bind(m_sockfd, (struct sockaddr *)&m_address,
sizeof(struct sockaddr_in));

@ -13,9 +13,12 @@
#include "llarp/net.hpp"
#include "router.hpp"
struct llarp_main *ctx = 0;
#include <llarp/messages/dht.hpp>
//#include <llarp/dht/messages/findintro.hpp>
//#include <llarp/routing_endpoint.hpp>
//#include <llarp/crypt.hpp> // for llarp::pubkey
llarp_main *sllarp = nullptr;
struct llarp_main *ctx = 0;
void
handle_signal(int sig)
@ -41,7 +44,6 @@ displayRC(const llarp::RouterContact &rc)
// fwd declr
struct check_online_request;
/*
void
HandleDHTLocate(llarp_router_lookup_job *job)
{
@ -49,7 +51,7 @@ HandleDHTLocate(llarp_router_lookup_job *job)
if(job->found)
{
// save to nodedb?
displayRC(&job->result);
displayRC(job->result);
}
// shutdown router
@ -64,7 +66,6 @@ HandleDHTLocate(llarp_router_lookup_job *job)
// still need to exit this logic thread...
llarp_main_abort(ctx);
}
*/
int
main(int argc, char *argv[])
@ -90,22 +91,29 @@ main(int argc, char *argv[])
"--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"
"--locate a hex formatted public key\n"
"--find a base32 formatted service address\n"
"--b32 a hex formatted public key\n"
"--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 genMode = false;
bool updMode = false;
bool listMode = false;
bool importMode = false;
bool exportMode = false;
bool locateMode = false;
bool localMode = false;
bool verifyMode = false;
bool readMode = false;
bool haveRequiredOptions = false;
bool genMode = false;
bool updMode = false;
bool listMode = false;
bool importMode = false;
bool exportMode = false;
bool locateMode = false;
bool findMode = false;
bool localMode = false;
bool verifyMode = false;
bool readMode = false;
bool toHexMode = false;
bool toB32Mode = false;
int c;
char *conffname;
char defaultConfName[] = "daemon.ini";
@ -126,12 +134,15 @@ main(int argc, char *argv[])
{"import", required_argument, 0, 'i'},
{"export", required_argument, 0, 'e'},
{"locate", required_argument, 0, 'q'},
{"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, "f:c:o:g:lu:i:e:q:nr:V:", 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)
@ -195,6 +206,11 @@ main(int argc, char *argv[])
rcfname = optarg;
locateMode = true;
break;
case 'F':
rcfname = optarg;
haveRequiredOptions = true;
findMode = true;
break;
case 'g':
// printf ("option -g with value `%s'\n", optarg);
rcfname = optarg;
@ -212,12 +228,48 @@ main(int argc, char *argv[])
rcfname = optarg;
readMode = true;
break;
case 'b':
rcfname = optarg;
haveRequiredOptions = true;
toB32Mode = true;
break;
case 'h':
rcfname = optarg;
haveRequiredOptions = true;
toHexMode = true;
break;
default:
printf("Bad option: %c\n", c);
return -1;
}
}
#undef MIN
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 1;
}
ctx = llarp_main_init(conffname, !TESTNET);
if(!ctx)
{
llarp::LogError("Cant set up context");
return 1;
}
signal(SIGINT, handle_signal);
llarp::RouterContact tmp;
if(verifyMode)
{
llarp_crypto crypto;
@ -274,6 +326,8 @@ main(int argc, char *argv[])
return 0;
}
// is this Neuro or Jeff's?
// this is the only one...
if(listMode)
{
llarp_crypto crypto;
@ -331,21 +385,6 @@ main(int argc, char *argv[])
return 0;
}
if(!genMode && !updMode && !listMode && !importMode && !exportMode
&& !locateMode && !localMode && !readMode)
{
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);
if(genMode)
{
printf("Creating [%s]\n", rcfname);
@ -384,10 +423,185 @@ main(int argc, char *argv[])
fs::path our_rc_file = rcfname;
// write file
rc.Write(our_rc_file.string().c_str());
// llarp_rc_write(&tmp, our_rc_file.string().c_str());
// release memory for tmp lists
// llarp_rc_free(&tmp);
}
if(updMode)
{
printf("rcutil.cpp - Loading [%s]\n", rcfname);
llarp::RouterContact tmp;
// llarp_rc_clear(&rc);
rc.Clear();
// FIXME: new rc api
// llarp_rc_read(rcfname, &rc);
// set updated timestamp
rc.last_updated = llarp_time_now_ms();
// load longterm identity
llarp_crypto crypt;
// no longer used?
// llarp_crypto_libsodium_init(&crypt);
llarp::SecretKey identityKey; // FIXME: Jeff requests we use this
fs::path ident_keyfile = "identity.key";
byte_t identity[SECKEYSIZE];
llarp_findOrCreateIdentity(&crypt, ident_keyfile.string().c_str(),
identity);
// FIXME: update RC API
// get identity public key
// const uint8_t *pubkey = llarp::seckey_topublic(identity);
// FIXME: update RC API
// llarp_rc_set_pubsigkey(&rc, pubkey);
// // FIXME: update RC API
// llarp_rc_sign(&crypt, identity, &rc);
// set filename
fs::path our_rc_file_out = "update_debug.rc";
// write file
// FIXME: update RC API
// rc.Write(our_rc_file.string().c_str());
// llarp_rc_write(&tmp, our_rc_file_out.string().c_str());
}
if(listMode)
{
llarp_crypto crypto;
// no longer used?
// llarp_crypto_libsodium_init(&crypto);
llarp_crypto_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;
}
if(exportMode)
{
llarp_main_loadDatabase(ctx);
// llarp::LogInfo("Looking for string: ", rcfname);
llarp::PubKey binaryPK;
llarp::HexDecode(rcfname, binaryPK.data());
llarp::LogInfo("Looking for binary: ", binaryPK);
llarp::RouterContact *rc = llarp_main_getDatabase(ctx, binaryPK.data());
if(!rc)
{
llarp::LogError("Can't load RC from database");
}
std::string filename(rcfname);
filename.append(".signed");
llarp::LogInfo("Writing out: ", filename);
// FIXME: update RC API
// rc.Write(our_rc_file.string().c_str());
// llarp_rc_write(rc, filename.c_str());
}
if(locateMode)
{
llarp::LogInfo("Going online");
llarp_main_setup(ctx);
llarp::PubKey binaryPK;
llarp::HexDecode(rcfname, binaryPK.data());
llarp::LogInfo("Queueing job");
llarp_router_lookup_job *job = new llarp_router_lookup_job;
job->iterative = true;
job->found = false;
job->hook = &HandleDHTLocate;
// llarp_rc_new(&job->result);
memcpy(job->target, binaryPK, PUBKEYSIZE); // set job's target
// create query DHT request
check_online_request *request = new check_online_request;
request->ptr = ctx;
request->job = job;
request->online = false;
request->nodes = 0;
request->first = false;
llarp_main_queryDHT(request);
llarp::LogInfo("Processing");
// run system and wait
llarp_main_run(ctx);
}
if(findMode)
{
llarp::LogInfo("Going online");
llarp_main_setup(ctx);
llarp::LogInfo("Please find ", rcfname);
std::string str(rcfname);
llarp::service::Tag tag(rcfname);
llarp::LogInfo("Tag ", tag);
llarp::service::Address addr;
str = str.append(".loki");
llarp::LogInfo("Prestring ", str);
bool res = addr.FromString(str.c_str());
llarp::LogInfo(res ? "Success" : "not a base32 string");
// Base32Decode(rcfname, addr);
llarp::LogInfo("Addr ", addr);
llarp::routing::DHTMessage *msg = new llarp::routing::DHTMessage();
// uint64_t txid, const llarp::service::Address& addr
// FIXME: new API?
// msg->M.push_back(new llarp::dht::FindIntroMessage(tag, 1));
// I guess we may need a router to get any replies
llarp::LogInfo("Processing");
// run system and wait
llarp_main_run(ctx);
}
if(localMode)
{
// FIXME: update llarp_main_getLocalRC
// llarp::RouterContact *rc = llarp_main_getLocalRC(ctx);
// displayRC(rc);
// delete it
}
{
if(rc.Read(rcfname))
displayRC(rc);
}
if(toB32Mode)
{
llarp::LogInfo("Converting hex string ", rcfname);
std::string str(rcfname);
llarp::PubKey binaryPK;
// llarp::service::Address::FromString
llarp::HexDecode(rcfname, binaryPK.data());
char tmp[(1 + 32) * 2] = {0};
std::string b32 = llarp::Base32Encode(binaryPK, tmp);
llarp::LogInfo("to base32 ", b32);
}
if(toHexMode)
{
llarp::service::Address addr;
llarp::Base32Decode(rcfname, addr);
llarp::LogInfo("Converting base32 string ", addr);
// llarp::service::Address::ToString
char ftmp[68] = {0};
const char *hexname =
llarp::HexEncode< llarp::service::Address, decltype(ftmp) >(addr, ftmp);
llarp::LogInfo("to hex ", hexname);
}
// it's a unique_ptr, should clean up itself
// llarp_main_free(ctx);
return 0; // success
}

@ -7,6 +7,10 @@
#include <llarp/version.h>
#ifdef __cplusplus
#include <llarp/service/address.hpp> // for service::address
#include <llarp/handlers/tun.hpp> // for handlers
#include <llarp/service/endpoint.hpp>
extern "C"
{
#endif
@ -44,10 +48,11 @@ extern "C"
/// put RC into nodeDB
bool
llarp_main_putDatabase(struct llarp_main *ptr, struct llarp_rc *rc);
llarp_main_putDatabase(struct llarp_main *ptr,
struct llarp::RouterContact &rc);
/// get RC from nodeDB
struct llarp_rc *
llarp::RouterContact *
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk);
// fwd declr
@ -66,11 +71,27 @@ extern "C"
check_online_request_hook_func hook;
};
/// get RC from DHT
/// get RC from DHT but wait until online
void
llarp_main_queryDHT(struct check_online_request *request);
struct llarp_rc *
/// get RC from DHT
void
llarp_main_queryDHT_RC(struct llarp_main *ptr,
struct llarp_router_lookup_job *job);
/// set up DNS libs with a context
bool
llarp_main_init_dnsd(struct llarp_main *ptr, struct dnsd_context *dnsd,
uint16_t server_port, const char *upstream_host,
uint16_t upstream_port);
/// set up dotLokiLookup with logic for setting timers
bool
llarp_main_init_dotLokiLookup(struct llarp_main *ptr,
struct dotLokiLookup *dll);
llarp::RouterContact *
llarp_main_getLocalRC(struct llarp_main *ptr);
void
@ -80,6 +101,22 @@ extern "C"
handleBaseCmdLineArgs(int argc, char *argv[]);
#ifdef __cplusplus
llarp::handlers::TunEndpoint *
main_router_getFirstTunEndpoint(struct llarp_main *ptr);
llarp_tun_io *
main_router_getRange(struct llarp_main *ptr);
/// map an ip to a hidden service address
bool
main_router_mapAddress(struct llarp_main *ptr,
const llarp::service::Address &addr, uint32_t ip);
/// info of possible path usage
bool
main_router_prefetch(struct llarp_main *ptr,
const llarp::service::Address &addr);
}
#endif
#endif

@ -39,9 +39,9 @@ namespace llarp
IterateDatabase(struct llarp_nodedb_iter i);
bool
PutDatabase(struct llarp_rc *rc);
PutDatabase(struct llarp::RouterContact &rc);
struct llarp_rc *
llarp::RouterContact *
GetDatabase(const byte_t *pk);
int

@ -3,6 +3,8 @@
#include <llarp/buffer.h>
#include <llarp/router.h>
#include <llarp/crypto.hpp>
#include <llarp/router_contact.hpp>
/**
* dht.h
@ -24,6 +26,26 @@ llarp_dht_context_free(struct llarp_dht_context* dht);
void
llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key);
// remove this? dns needs it atm
struct llarp_router_lookup_job;
typedef void (*llarp_router_lookup_handler)(struct llarp_router_lookup_job*);
struct llarp_router_lookup_job
{
/// can be anything but usually a class context for hook
void* user;
llarp_router_lookup_handler hook;
struct llarp_dht_context* dht;
// byte_t target[PUBKEYSIZE];
llarp::PubKey target;
bool found;
// make sure you initialize addr and exits
llarp::RouterContact result;
bool iterative;
};
// end dns requirement
/// start allowing dht participation on a context
void
llarp_dht_allow_transit(struct llarp_dht_context* ctx);
@ -33,4 +55,8 @@ llarp_dht_allow_transit(struct llarp_dht_context* ctx);
void
__llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id);
void
llarp_dht_lookup_router(struct llarp_dht_context* ctx,
struct llarp_router_lookup_job* job);
#endif

@ -3,7 +3,6 @@
#include <llarp/ev.h> // for sockaadr
#include <sys/types.h> // for uint & ssize_t
#include <map> // for udp DNS tracker
/* non-cygnus does not have this type */
#ifdef _WIN32
@ -31,40 +30,12 @@ extern "C"
// struct dnsd_question_request;
struct dnsc_answer_request;
// dnsc can work over any UDP socket
// however we can't ignore udp->user
// we need to be able to reference the request (being a request or response)
// bottom line is we can't use udp->user
// so we'll need to track all incoming and outgoing requests
struct dns_tracker;
// struct dns_tracker;
// should we pass by llarp::Addr
// not as long as we're supporting raw
typedef void (*dnsc_answer_hook_func)(dnsc_answer_request *request);
struct sockaddr *
raw_resolve_host(const char *url);
/// async resolve hostname
bool
llarp_resolve_host(struct dnsc_context *dns, const char *url,
dnsc_answer_hook_func resolved, void *user);
void
llarp_host_resolved(dnsc_answer_request *request);
/*
// XXX: these should be internal and not exposed
void
llarp_handle_recvfrom(struct llarp_udp_io *udp, const struct sockaddr *saddr,
const void *buf, ssize_t sz);
void
raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, const void
*buf, ssize_t sz);
*/
#ifdef __cplusplus
}
#endif

@ -5,14 +5,27 @@
#include <sys/types.h> // for uint & ssize_t
#include <map>
#include <string>
#include <vector>
#include <sys/socket.h>
#include <llarp/net.hpp> // for llarp::Addr
// dnsc can work over any UDP socket
// however we can't ignore udp->user
// we need to be able to reference the request (being a request or response)
// bottom line is we can't use udp->user
// so we'll need to track all incoming and outgoing requests
struct dns_tracker
{
// uint c_responses;
uint c_requests;
std::map< uint, dnsc_answer_request * > client_request;
// request has to be a pointer
std::unordered_map< uint, std::unique_ptr< dnsc_answer_request > > client_request;
// FIXME: support multiple dns server contexts
dnsd_context *dnsd;
// rn we need 1 tracker per DNSd and each DNSd needs it's own IP
//std::map< llarp::Addr, std::unique_ptr< dnsc_answer_request > > dnsds;
// std::map< uint, dnsd_question_request * > daemon_request;
};
@ -55,6 +68,15 @@ struct dns_msg_answer
uint8_t *rData;
};
struct dns_packet
{
struct dns_msg_header *header;
std::vector< std::unique_ptr< dns_msg_question > > questions;
std::vector< std::unique_ptr< dns_msg_answer > > answers;
std::vector< std::unique_ptr< dns_msg_answer > > auth_rrs;
std::vector< std::unique_ptr< dns_msg_answer > > additional_rrs;
};
extern "C"
{
uint16_t
@ -83,7 +105,7 @@ extern "C"
void
llarp_handle_dns_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *saddr, const void *buf,
const struct sockaddr *addr, const void *buf,
ssize_t sz);
}
#endif

@ -0,0 +1,40 @@
#ifndef LIBLLARP_DNS_DOTLOKILOOKUP_HPP
#define LIBLLARP_DNS_DOTLOKILOOKUP_HPP
#include <llarp/service/address.hpp>
//#include <llarp/service.hpp>
//#include <llarp/service/endpoint.hpp>
//#include <llarp/handlers/tun.hpp>
//#include <llarp/handlers/tun.hpp>
#include "dnsd.hpp"
typedef bool (*map_address_hook_func)(const llarp::service::Address &addr,
uint32_t ip);
/// dotLokiLookup
struct dotLokiLookup
{
/// for timers (MAYBEFIXME? maybe we decouple this, yes pls have a generic
/// passed in)
struct llarp_logic *logic;
/// which ip tracker to use
struct dns_iptracker *ip_tracker;
/// tunEndpoint
// llarp::handlers::TunEndpoint *tunEndpoint; // is this even needed here?
void *user;
// pointer to tunendpoint properties?
// need a way to reference
// 1. mapaddress
map_address_hook_func map_address_handler;
// std::function< bool(const llarp::service::Address &addr, uint32_t ip),
// llarp::handlers::TunEndpoint * > callback;
// 2. prefetch
};
dnsd_query_hook_response *
llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from,
struct dnsd_question_request *request);
#endif

@ -0,0 +1,51 @@
#ifndef LIBLLARP_DNSIPTRACKER_HPP
#define LIBLLARP_DNSIPTRACKER_HPP
#include <llarp/net.hpp>
#include <map>
#include <vector>
#include <llarp/service/address.hpp>
#include "dns_dotlokilookup.hpp"
// either a request or response?
// neither, it's a result set row
struct dns_pointer
{
struct sockaddr *hostResult;
llarp::service::Address b32addr;
};
struct ip_range
{
uint8_t octet2;
uint8_t octet3;
// FIXME: we're not consecutive
uint8_t left;
std::unordered_map< uint8_t, dns_pointer * > used;
};
struct dns_iptracker
{
struct privatesInUse interfaces;
struct privatesInUse used_privates;
std::vector< std::unique_ptr <ip_range> > used_ten_ips;
std::vector< std::unique_ptr <ip_range> > used_seven_ips;
std::vector< std::unique_ptr <ip_range> > used_nine_ips;
};
void
dns_iptracker_init();
bool
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll, llarp::Addr tunGatewayIp);
bool
dns_iptracker_setup(llarp::Addr tunGatewayIp);
struct dns_pointer *
dns_iptracker_get_free();
struct dns_pointer *
dns_iptracker_get_free(dns_iptracker *iptracker);
#endif

@ -0,0 +1,88 @@
#ifndef LIBLLARP_DNSC_HPP
#define LIBLLARP_DNSC_HPP
#include <llarp/ev.h> // for sockaadr
#include "dns.hpp" // get protocol structs
// internal, non-public functions
// well dnsc init/stop are public...
struct dnsc_answer_request;
/// hook function to handle an dns client request
// should we pass by llarp::Addr
// not as long as we're supporting raw
typedef void (*dnsc_answer_hook_func)(dnsc_answer_request *request);
/// struct for dns client requests
struct dnsc_answer_request
{
/// sock type
void *sock; // pts to udp...
/// customizable (used for hook (outer request))
void *user;
/// storage
dns_msg_question question;
/// hook
dnsc_answer_hook_func resolved;
/// result
bool found;
struct sockaddr result;
std::string revDNS;
// a reference to dnsc_context incase of multiple contexts
struct dnsc_context *context;
};
/// event handler for processing DNS responses
void
llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *addr, const void *buf,
ssize_t sz);
/// generic handler for processing DNS responses
void
raw_handle_recvfrom(int *sockfd, const struct sockaddr *addr, const void *buf,
ssize_t sz);
/// DNS client context (one needed per upstream DNS server)
struct dnsc_context
{
/// Target: DNS server hostname/port to use
// FIXME: ipv6 it & make it a vector
sockaddr *server;
/// tracker
struct dns_tracker *tracker;
/// sock type
void *sock;
// where to create the new sockets
struct llarp_udp_io *udp;
/// We will likely need something for timing events (timeouts)
struct llarp_logic *logic;
};
/// async resolve a hostname using generic socks
void
raw_resolve_host(struct dnsc_context *dnsc, const char *url,
dnsc_answer_hook_func resolved, void *user);
/// async resolve a hostname using llarp platform framework
bool
llarp_resolve_host(struct dnsc_context *dns, const char *url,
dnsc_answer_hook_func resolved, void *user);
/// cleans up request structure allocations
void
llarp_host_resolved(dnsc_answer_request *request);
/// initialize dns subsystem and bind socket
/// returns true on bind success otherwise returns false
bool
llarp_dnsc_init(struct dnsc_context *dnsc, struct llarp_logic *logic,
struct llarp_udp_io *udp, const char *dnsc_hostname,
uint16_t dnsc_port);
/// shutdowns any events, and deallocates for this context
bool
llarp_dnsc_stop(struct dnsc_context *dnsc);
#endif

@ -0,0 +1,93 @@
#ifndef LIBLLARP_DNSD_HPP
#define LIBLLARP_DNSD_HPP
#include <llarp/ev.h> // for sockaadr
#include <string>
#include "dns.hpp" // question and dnsc
#include "dnsc.hpp"
// fwd declaration
struct dnsd_context;
/// sendto hook functor
typedef ssize_t (*sendto_dns_hook_func)(void *sock, const struct sockaddr *from,
const void *buffer, size_t length);
/// DNS server query request
struct dnsd_question_request
{
/// sock type
void *user;
// raw or llarp subsystem
bool llarp;
/// request id
int id;
/// question being asked
dns_msg_question question;
// request source socket
struct sockaddr *from;
sendto_dns_hook_func sendto_hook; // sendto hook tbh
// maybe a reference to dnsd_context incase of multiple
dnsd_context *context; // or you can access it via user (udp)
};
// FIXME: made better as a two way structure, collapse the request and response
// together
struct dnsd_query_hook_response
{
/// turn off communication
bool dontSendResponse;
/// turn off recursion
bool dontLookUp;
/// potential address
sockaddr *returnThis;
};
/// intercept query hook functor
typedef dnsd_query_hook_response *(*intercept_query_hook)(
std::string name, const struct sockaddr *from,
struct dnsd_question_request *request);
/// DNS Server context
struct dnsd_context
{
/// DNS daemon socket to listen on
struct llarp_udp_io udp;
/// udp tracker
struct dns_tracker *tracker;
/// upstream DNS client context to use
dnsc_context client;
/// custom data for intercept query hook (used for configuration of hook)
void *user;
/// hook function for intercepting dns requests
intercept_query_hook intercept;
};
/// udp event handler
void
llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *addr, const void *buf,
ssize_t sz);
/// for hook functions to use
void
writecname_dnss_response(std::string cname, const struct sockaddr *from,
dnsd_question_request *request);
void
writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from,
dnsd_question_request *request);
/// initialize dns subsystem and bind socket
/// returns true on bind success otherwise returns false
bool
llarp_dnsd_init(struct dnsd_context *dnsd, struct llarp_logic *logic,
struct llarp_ev_loop *netloop, const char *dnsd_ifname,
uint16_t dnsd_port, const char *dnsc_hostname,
uint16_t dnsc_port);
/// shutdowns any events, and deallocates for this context
bool
llarp_dnsd_stop(struct dnsd_context *dnsd);
#endif

@ -46,7 +46,7 @@ struct llarp_xi
operator<<(std::ostream &out, const llarp_xi &xi)
{
char tmp[128] = {0};
if(inet_ntop(AF_INET6, (void*)&xi.address, tmp, sizeof(tmp)))
if(inet_ntop(AF_INET6, (void *)&xi.address, tmp, sizeof(tmp)))
out << std::string(tmp);
else
return out;

@ -5,6 +5,9 @@
#include <llarp/ip.hpp>
#include <llarp/service/endpoint.hpp>
#include <llarp/threading.hpp>
#include <llarp/dnsd.hpp> // for relay
#include <llarp/dns_dotlokilookup.hpp> // for lookup
#include <llarp/dns_iptracker.hpp> // for tracker
namespace llarp
{
@ -110,16 +113,22 @@ namespace llarp
/// up interface
std::promise< bool > m_TunSetupResult;
#endif
/// maps ip to service address
/// DNS server per tun
struct dnsd_context dnsd;
/// DNS loki lookup subsystem configuration (also holds optional iptracker
/// for netns)
struct dotLokiLookup dll;
/// maps ip to service address (host byte order)
std::unordered_map< uint32_t, service::Address > m_IPToAddr;
/// maps service address to ip
/// maps service address to ip (host byte order)
std::unordered_map< service::Address, uint32_t, service::Address::Hash >
m_AddrToIP;
/// maps ip address to timestamp last active
std::unordered_map< uint32_t, llarp_time_t > m_IPActivity;
/// our ip address
/// our ip address (host byte order)
uint32_t m_OurIP;
/// next ip address to allocate
/// next ip address to allocate (host byte order)
uint32_t m_NextIP;
/// highest ip address to allocate
uint32_t m_MaxIP;

@ -3,29 +3,83 @@
#include <llarp/buffer.h>
#include <llarp/time.h>
#include <llarp/net.hpp>
#ifdef _WIN32
#ifndef _WIN32
#include <sys/types.h> // FreeBSD needs this for uchar for ip.h
#include <netinet/in.h>
#include <netinet/ip.h>
#else
#include <winsock2.h>
// Apparently this does not seem to be located _anywhere_ in the windows sdk???
// -despair86
typedef struct ip_hdr
{
unsigned char
ip_header_len : 4; // 4-bit header length (in 32-bit words) normally=5
// (Means 20 Bytes may be 24 also)
unsigned char ip_version : 4; // 4-bit IPv4 version
unsigned char ip_tos; // IP type of service
unsigned short ip_total_length; // Total length
unsigned short ip_id; // Unique identifier
unsigned char ip_frag_offset : 5; // Fragment offset field
unsigned char ip_more_fragment : 1;
unsigned char ip_dont_fragment : 1;
unsigned char ip_reserved_zero : 1;
unsigned char ip_frag_offset1; // fragment offset
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR;
#define iphdr IPV4_HDR
#define saddr ip_srcaddr
#define daddr ip_destaddr
#define check ip_checksum
#define ihl ip_header_len
#define ip_version version
#endif
#include <memory>
#if !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) \
&& !defined(__FreeBSD__)
#define iphdr ip
#define saddr ip_src.s_addr
#define daddr ip_dst.s_addr
#define ip_version ip_v
#define check ip_sum
#define ihl ip_hl
#endif
struct ip_header
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
unsigned int ihl : 4;
unsigned int version : 4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
unsigned int version : 4;
unsigned int ihl : 4;
#else
# error "Please fix <bits/endian.h>"
#error "Please fix <bits/endian.h>"
#endif
#if defined(__linux__)
#define ip_version version
#endif
uint8_t tos;
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;
uint8_t ttl;
uint8_t protocol;
uint16_t check;
uint32_t saddr;
uint32_t daddr;
uint8_t tos;
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;
uint8_t ttl;
uint8_t protocol;
uint16_t check;
uint32_t saddr;
uint32_t daddr;
};
namespace llarp

@ -137,16 +137,20 @@ namespace llarp
LogAppend(ss, std::forward< TArgs >(args)...);
#ifndef ANDROID
ss << (char)27 << "[0;0m";
#endif
_glog.out << ss.str() << std::endl;
#else
{
#ifdef ANDROID
std::unique_lock< std::mutex > lock(_glog.access);
tag = "LOKINET|" + tag;
__android_log_write(ANDROID_LOG_INFO, tag.c_str(), ss.str().c_str());
#else
//__android_log_write(ANDROID_LOG_INFO, "LOKINET", ss.str().c_str());
llarp::util::Lock lock(_glog.access);
_glog.out << ss.str() << std::endl;
#endif
}
#endif
#ifdef SHADOW_TESTNET
_glog.out << "\n" << std::flush;
#endif
}
} // namespace llarp
@ -170,4 +174,5 @@ namespace llarp
#ifndef LOG_TAG
#define LOG_TAG "default"
#endif
#endif

@ -4,8 +4,16 @@
#include <llarp/net.h>
#include <functional>
#include <iostream>
#include "logger.hpp"
#include "mem.hpp"
#include <stdlib.h> // for itoa
// for addrinfo
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
bool
operator==(const sockaddr& a, const sockaddr& b);
@ -24,10 +32,21 @@ operator<(const in6_addr& a, const in6_addr& b);
bool
operator==(const in6_addr& a, const in6_addr& b);
struct privatesInUse
{
bool ten; // 16m ips
bool oneSeven; // 1m ips
bool oneNine; // 65k ips
};
struct privatesInUse
llarp_getPrivateIfs();
namespace llarp
{
struct Addr
{
// network order
sockaddr_in6 _addr;
sockaddr_in _addr4;
~Addr(){};
@ -74,6 +93,81 @@ namespace llarp
return (const in_addr*)&_addr.sin6_addr.s6_addr[12];
}
Addr(const char* str)
{
llarp::Zero(&_addr, sizeof(sockaddr_in6));
struct addrinfo hint, *res = NULL;
int ret;
memset(&hint, '\0', sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(str, NULL, &hint, &res);
if(ret)
{
llarp::LogError("failed to determine address family: ", str);
return;
}
if(res->ai_family == AF_INET6)
{
llarp::LogError("IPv6 address not supported yet", str);
return;
}
else if(res->ai_family != AF_INET)
{
llarp::LogError("Address family not supported yet", str);
return;
}
struct in_addr* addr = &_addr4.sin_addr;
if(inet_aton(str, addr) == 0)
{
llarp::LogError("failed to parse ", str);
return;
}
_addr.sin6_family = res->ai_family;
_addr4.sin_family = res->ai_family;
_addr4.sin_port = htons(0);
#if((__APPLE__ && __MACH__) || __FreeBSD__)
_addr4.sin_len = sizeof(in_addr);
#endif
// set up SIIT
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
addrptr[11] = 0xff;
addrptr[10] = 0xff;
memcpy(12 + addrptr, &addr->s_addr, sizeof(in_addr));
freeaddrinfo(res);
}
Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four)
{
llarp::Zero(&_addr, sizeof(sockaddr_in6));
struct in_addr* addr = &_addr4.sin_addr;
unsigned char* ip = (unsigned char*)&(addr->s_addr);
_addr.sin6_family = AF_INET; // set ipv4 mode
_addr4.sin_family = AF_INET;
_addr4.sin_port = htons(0);
#if((__APPLE__ && __MACH__) || __FreeBSD__)
_addr4.sin_len = sizeof(in_addr);
#endif
ip[0] = one;
ip[1] = two;
ip[2] = three;
ip[3] = four;
// set up SIIT
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
addrptr[11] = 0xff;
addrptr[10] = 0xff;
memcpy(12 + addrptr, &addr->s_addr, sizeof(in_addr));
}
Addr(const AddressInfo& other)
{
memcpy(addr6(), other.ip.s6_addr, 16);
@ -204,19 +298,26 @@ namespace llarp
switch(af())
{
case AF_INET:
dst = (void*)&((sockaddr_in*)other)->sin_addr.s_addr;
src = (void*)&_addr.sin6_addr.s6_addr[12];
ptr = &((sockaddr_in*)other)->sin_port;
slen = sizeof(in_addr);
{
sockaddr_in* ipv4_dst = (sockaddr_in*)other;
dst = (void*)&ipv4_dst->sin_addr.s_addr;
src = (void*)&_addr4.sin_addr.s_addr;
ptr = &((sockaddr_in*)other)->sin_port;
slen = sizeof(in_addr);
break;
}
case AF_INET6:
{
dst = (void*)((sockaddr_in6*)other)->sin6_addr.s6_addr;
src = (void*)_addr.sin6_addr.s6_addr;
ptr = &((sockaddr_in6*)other)->sin6_port;
slen = sizeof(in6_addr);
break;
}
default:
{
return;
}
}
memcpy(dst, src, slen);
*ptr = htons(port());
@ -288,6 +389,18 @@ namespace llarp
return *this;
}
uint32_t
tohl()
{
return ntohl(addr4()->s_addr);
}
uint32_t
ton()
{
return addr4()->s_addr;
}
bool
sameAddr(const Addr& other) const
{
@ -300,6 +413,37 @@ namespace llarp
return !(*this == other);
}
inline uint32_t
getHostLong()
{
in_addr_t addr = this->addr4()->s_addr;
uint32_t byte = ntohl(addr);
return byte;
};
bool
isTenPrivate(uint32_t byte)
{
uint8_t byte1 = byte >> 24 & 0xff;
return byte1 == 10;
}
bool
isOneSevenPrivate(uint32_t byte)
{
uint8_t byte1 = byte >> 24 & 0xff;
uint8_t byte2 = (0x00ff0000 & byte >> 16);
return byte1 == 172 && (byte2 >= 16 || byte2 <= 31);
}
bool
isOneNinePrivate(uint32_t byte)
{
uint8_t byte1 = byte >> 24 & 0xff;
uint8_t byte2 = (0x00ff0000 & byte >> 16);
return byte1 == 192 && byte2 == 168;
}
socklen_t
SockLen() const
{
@ -309,15 +453,13 @@ namespace llarp
return sizeof(sockaddr_in6);
}
// Neuro: can't const this, not sure why...
bool
isPrivate() const
isPrivate()
{
in_addr_t addr = this->addr4()->s_addr;
unsigned byte = ntohl(addr);
unsigned byte1 = (byte >> 24) & 0xff;
unsigned byte2 = (0x00ff0000 & byte) >> 16;
return (byte1 == 10 || (byte1 == 192 && byte2 == 168)
|| (byte1 == 172 && (byte2 >= 16 || byte2 <= 31)));
uint32_t byte = this->getHostLong();
return this->isTenPrivate(byte) || this->isOneSevenPrivate(byte)
|| this->isOneNinePrivate(byte);
}
bool

@ -4,6 +4,7 @@
#include <llarp/service/config.hpp>
#include <llarp/service/endpoint.hpp>
#include <unordered_map>
#include <llarp/handlers/tun.hpp>
namespace llarp
{
@ -18,6 +19,26 @@ namespace llarp
void
Tick();
/// DRY refactor
llarp::service::Endpoint *
getFirstEndpoint();
/// DRY refactor
llarp::handlers::TunEndpoint *
getFirstTun();
/// punch a hole to get ip range from first tun endpoint
llarp_tun_io *
getRange();
/// hint at possible path usage and trigger building early
bool
Prefetch(const llarp::service::Address &addr);
/// punch a hole open for DNS to add mappings
bool
MapAddress(const llarp::service::Address &addr, uint32_t ip);
bool
AddEndpoint(const Config::section_t &conf);

@ -129,7 +129,11 @@ bencode_read_list(llarp_buffer_t* buff, struct list_reader* r)
{
r->buffer = buff;
if(*r->buffer->cur != 'l') // ensure is a list
{
llarp::LogWarn("bencode::bencode_read_list - expecting list got ",
*r->buffer->cur);
return false;
}
r->buffer->cur++;
while(llarp_buffer_size_left(*r->buffer) && *r->buffer->cur != 'e')

@ -6,10 +6,11 @@
#include <sys/param.h> // for MIN
#endif
#include <llarp.hpp>
#include "logger.hpp"
#include "math.h"
#include "router.hpp"
#include <llarp/dnsd.hpp>
#include <llarp/dns_dotlokilookup.hpp>
#if(__FreeBSD__) || (__OpenBSD__) || (__NetBSD__)
#include <pthread_np.h>
#endif
@ -112,6 +113,28 @@ namespace llarp
return 1;
}
int
Context::IterateDatabase(struct llarp_nodedb_iter i)
{
return llarp_nodedb_iterate_all(nodedb, i);
}
bool
Context::PutDatabase(struct llarp::RouterContact &rc)
{
// FIXME
// return llarp_nodedb_put_rc(nodedb, rc);
return false;
}
llarp::RouterContact *
Context::GetDatabase(const byte_t *pk)
{
// FIXME
// return llarp_nodedb_get_rc(nodedb, pk);
return nullptr;
}
int
Context::Setup()
{
@ -304,12 +327,160 @@ extern "C"
llarp_logic_stop_timer(ptr->ctx->router->logic);
}
void
llarp_main_queryDHT_RC(struct llarp_main *ptr,
struct llarp_router_lookup_job *job)
{
llarp_dht_lookup_router(ptr->ctx->router->dht, job);
}
bool
llarp_main_init_dnsd(struct llarp_main *ptr, struct dnsd_context *dnsd,
uint16_t server_port, const char *upstream_host,
uint16_t upstream_port)
{
return llarp_dnsd_init(dnsd, ptr->ctx->logic, ptr->ctx->mainloop, "*",
server_port, upstream_host, upstream_port);
}
bool
llarp_main_init_dotLokiLookup(struct llarp_main *ptr,
struct dotLokiLookup *dll)
{
dll->logic = ptr->ctx->logic;
return true;
}
void
llarp_main_free(struct llarp_main *ptr)
{
delete ptr;
}
int
llarp_main_loadDatabase(struct llarp_main *ptr)
{
return ptr->ctx->LoadDatabase();
}
int
llarp_main_iterateDatabase(struct llarp_main *ptr, struct llarp_nodedb_iter i)
{
return ptr->ctx->IterateDatabase(i);
}
bool
llarp_main_putDatabase(struct llarp_main *ptr, llarp::RouterContact &rc)
{
return ptr->ctx->PutDatabase(rc);
}
llarp::RouterContact *
llarp_main_getDatabase(struct llarp_main *ptr, byte_t *pk)
{
return ptr->ctx->GetDatabase(pk);
}
llarp::RouterContact *
llarp_main_getLocalRC(struct llarp_main *ptr)
{
//
/*
llarp_config_iterator iter;
iter.user = this;
iter.visit = &iter_config;
llarp_config_iter(ctx->config, &iter);
*/
// llarp_rc *rc = new llarp_rc;
llarp::RouterContact *rc = new llarp::RouterContact;
// llarp_rc_new(rc);
// llarp::LogInfo("FIXME: Loading ", ptr->ctx->conatctFile);
// FIXME
/*
if(llarp_rc_read(ptr->ctx->conatctFile, rc))
return rc;
else
*/
return nullptr;
}
void
llarp_main_checkOnline(void *u, uint64_t orig, uint64_t left)
{
// llarp::Info("checkOnline - check ", left);
if(left)
return;
struct check_online_request *request =
static_cast< struct check_online_request * >(u);
// llarp::Debug("checkOnline - running");
// llarp::Info("checkOnline - DHT nodes ",
// request->ptr->ctx->router->dht->impl.nodes->nodes.size());
request->online = false;
request->nodes = request->ptr->ctx->router->dht->impl.nodes->nodes.size();
if(request->ptr->ctx->router->dht->impl.nodes->nodes.size())
{
// llarp::Info("checkOnline - Going to say we're online");
request->online = true;
}
request->hook(request);
// reschedue our self
llarp_main_queryDHT(request);
}
void
llarp_main_queryDHT_online(struct check_online_request *request)
{
// Info("llarp_main_queryDHT_online: ", request->online ? "online" :
// "offline");
if(request->online && !request->first)
{
request->first = true;
llarp::LogInfo("llarp_main_queryDHT_online - We're online");
llarp::LogInfo("llarp_main_queryDHT_online - Querying DHT");
llarp_dht_lookup_router(request->ptr->ctx->router->dht, request->job);
}
}
void
llarp_main_queryDHT(struct check_online_request *request)
{
// llarp::Info("llarp_main_queryDHT - setting up timer");
request->hook = &llarp_main_queryDHT_online;
llarp_logic_call_later(request->ptr->ctx->router->logic,
{1000, request, &llarp_main_checkOnline});
// llarp_dht_lookup_router(ptr->ctx->router->dht, job);
}
bool
main_router_mapAddress(struct llarp_main *ptr,
const llarp::service::Address &addr, uint32_t ip)
{
auto *endpoint = &ptr->ctx->router->hiddenServiceContext;
return endpoint->MapAddress(addr, ip);
}
bool
main_router_prefetch(struct llarp_main *ptr,
const llarp::service::Address &addr)
{
auto *endpoint = &ptr->ctx->router->hiddenServiceContext;
return endpoint->Prefetch(addr);
}
llarp::handlers::TunEndpoint *
main_router_getFirstTunEndpoint(struct llarp_main *ptr)
{
auto *endpoint = &ptr->ctx->router->hiddenServiceContext;
return endpoint->getFirstTun();
}
llarp_tun_io *
main_router_getRange(struct llarp_main *ptr)
{
auto *endpoint = &ptr->ctx->router->hiddenServiceContext;
return endpoint->getRange();
}
const char *
handleBaseCmdLineArgs(int argc, char *argv[])
{

@ -28,31 +28,94 @@ namespace iwp
gen_intro(void *user)
{
iwp_async_intro *intro = static_cast< iwp_async_intro * >(user);
#ifdef neuroCryptoDebug
char ftmp[68] = {0};
const char *hexname = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(
intro->remote_pubkey, ftmp);
llarp::LogDebug("gen_intro remote_pubkey: ", hexname);
#endif
llarp::SharedSecret sharedkey;
llarp::ShortHash e_k;
llarp_crypto *crypto = intro->iwp->crypto;
byte_t tmp[64];
// S = TKE(a.k, b.k, n)
crypto->transport_dh_client(sharedkey, intro->remote_pubkey,
intro->secretkey, intro->nonce);
#ifdef neuroCryptoDebug
char ftmpShared[68] = {0};
const char *hexShared =
llarp::HexEncode< llarp::SharedSecret, decltype(ftmpShared) >(
sharedkey, ftmpShared);
llarp::LogDebug("gen_intro sharedkey ", hexShared);
#endif
byte_t tmp[64];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
llarp::SymmNonce n;
// copy nonce
memcpy(n, intro->nonce, 32); // was 24 bytes
/*
char ftmpN[68] = {0};
const char *hexN =
llarp::HexEncode< llarp::SymmNonce, decltype(ftmpN) >(n, ftmpN);
llarp::LogDebug("gen_intro nonce ", hexN);
*/
// e_k = HS(b.k + n)
llarp::ShortHash e_k;
memcpy(tmp, intro->remote_pubkey, 32);
memcpy(tmp + 32, intro->nonce, 32);
crypto->shorthash(e_k, buf);
#ifdef neuroCryptoDebug
char ftmpEk[68] = {0};
const char *hexEk =
llarp::HexEncode< llarp::ShortHash, decltype(ftmpEk) >(e_k, ftmpEk);
llarp::LogDebug("gen_intro e_k ", hexEk, " used ", strlen(hexEk));
#endif
// put nonce
memcpy(intro->buf + 32, intro->nonce, 32);
// e = SE(a.k, e_k, n[0:24])
memcpy(intro->buf + 64, llarp::seckey_topublic(intro->secretkey), 32);
#ifdef neuroCryptoDebug
char ftmpSk[68] = {0};
const char *hexSk = llarp::HexEncode< llarp::PubKey, decltype(ftmpSk) >(
intro->secretkey, ftmpSk);
llarp::LogDebug("gen_intro SK ", hexSk);
char ftmpSkPub[68] = {0};
const char *hexSkPub =
llarp::HexEncode< llarp::PubKey, decltype(ftmpSkPub) >(
llarp::seckey_topublic(intro->secretkey), ftmpSkPub);
llarp::LogDebug("gen_intro SK pub ", hexSkPub);
#endif
buf.base = intro->buf + 64;
buf.cur = buf.base;
buf.sz = 32;
crypto->xchacha20(buf, e_k, intro->nonce);
// h = MDS( n + e + w0, S)
buf.base = intro->buf + 32;
buf.cur = buf.base;
buf.sz = intro->sz - 32;
crypto->hmac(intro->buf, buf, sharedkey);
#ifdef neuroCryptoDebug
char ftmpHmac[68] = {0}; // probably could be 65
const char *hexHmac = llarp::HexEncode< llarp::PubKey, decltype(ftmpHmac) >(
intro->buf, ftmpHmac);
llarp::LogDebug("gen_intro Hmac ", hexHmac);
#endif
// inform result
// intro->hook(intro);
llarp_logic_queue_job(intro->iwp->logic, {intro, &inform_intro});
@ -68,6 +131,14 @@ namespace iwp
llarp::SharedSecret h;
byte_t tmp[64];
const auto OurPK = llarp::seckey_topublic(intro->secretkey);
#ifdef neuroCryptoDebug
char ftmp[68] = {0};
const char *hexPk =
llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(OurPK, ftmp);
llarp::LogDebug("intro OurPK ", hexPk);
#endif
// e_k = HS(b.k + n)
memcpy(tmp, OurPK, 32);
memcpy(tmp + 32, intro->nonce, 32);
@ -77,11 +148,33 @@ namespace iwp
buf.base = intro->remote_pubkey;
buf.cur = buf.base;
buf.sz = 32;
// was using remote_pubkey directly (use buffer wrapper? directly?)
// memcpy(intro->remote_pubkey, intro->buf + 64, 32);
memcpy(buf.base, intro->buf + 64, 32);
crypto->xchacha20(buf, e_K, intro->nonce);
#ifdef neuroCryptoDebug
llarp::LogInfo("handshake from ", llarp::RouterID(intro->remote_pubkey));
char ftmp2[68] = {0};
const char *hexRemotePK = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(
intro->remote_pubkey, ftmp2);
llarp::LogDebug("intro remote_pubkey ", hexRemotePK);
#endif
// S = TKE(a.k, b.k, n)
crypto->transport_dh_server(sharedkey, intro->remote_pubkey,
intro->secretkey, intro->nonce);
#ifdef neuroCryptoDebug
char ftmpShared[68] = {0};
const char *hexShared =
llarp::HexEncode< llarp::PubKey, decltype(ftmpShared) >(sharedkey,
ftmpShared);
llarp::LogDebug("intro sharedkey ", hexShared);
#endif
// h = MDS( n + e + w2, S)
buf.base = intro->buf + 32;
buf.cur = buf.base;
@ -89,6 +182,7 @@ namespace iwp
crypto->hmac(h, buf, sharedkey);
if(memcmp(h, intro->buf, 32))
{
llarp::LogWarn("intro HMAC failure");
// hmac fail
delete[] intro->buf;
intro->buf = nullptr;
@ -353,11 +447,19 @@ iwp_decrypt_frame(struct iwp_async_frame *frame)
crypto->hmac(digest, buf, frame->sessionkey);
// check hmac
frame->success = memcmp(digest, hmac, 32) == 0;
if(!frame->success)
{
// [", digest, "] vs [", hmac, "]
llarp::LogWarn("crypto_async::iwp_decrypt_frame failed to decrypt");
//} else {
// llarp::Debug("crypto_async::iwp_decrypt_frame decrypted");
}
// x = SE(S, p, n[0:24])
buf.base = body;
buf.cur = buf.base;
buf.sz = frame->sz - 64;
crypto->xchacha20(buf, frame->sessionkey, nonce);
return frame->success;
}

@ -39,10 +39,40 @@ namespace llarp
const uint8_t *n)
{
llarp::SharedSecret dh_result;
char ftmpPk[68] = {0};
const char *hexPk =
llarp::HexEncode< llarp::PubKey, decltype(ftmpPk) >(pk, ftmpPk);
llarp::LogDebug("PK :", hexPk);
char ftmpSk[68] = {0};
const char *hexSk =
llarp::HexEncode< llarp::PubKey, decltype(ftmpSk) >(sk, ftmpSk);
llarp::LogDebug("SK :", hexSk);
char ftmpSkPub[68] = {0};
const char *hexSkPub =
llarp::HexEncode< llarp::PubKey, decltype(ftmpSkPub) >(
llarp::seckey_topublic(sk), ftmpSkPub);
llarp::LogDebug("SK pub :", hexSkPub);
if(dh(dh_result, llarp::seckey_topublic(sk), pk, pk, sk))
{
return crypto_generichash(shared, 32, n, 32, dh_result, 32) != -1;
char ftmpResult[68] = {0};
const char *hexResult =
llarp::HexEncode< llarp::SharedSecret, decltype(ftmpResult) >(
dh_result, ftmpResult);
llarp::LogDebug("Result :", hexResult);
bool res = crypto_generichash(shared, 32, n, 32, dh_result, 32) != -1;
char ftmpShared[68] = {0};
const char *hexShared =
llarp::HexEncode< llarp::SharedSecret, decltype(ftmpShared) >(
shared, ftmpShared);
llarp::LogDebug("Shared :", hexShared);
return res;
}
llarp::LogWarn("crypto::dh_client - dh failed");
return false;
}
@ -55,6 +85,7 @@ namespace llarp
{
return crypto_generichash(shared, 32, n, 32, dh_result, 32) != -1;
}
llarp::LogWarn("crypto::dh_server - dh failed");
return false;
}

@ -38,3 +38,18 @@ llarp_dht_context_start(struct llarp_dht_context *ctx, const byte_t *key)
{
ctx->impl.Init(key, ctx->parent, 20000);
}
void
llarp_dht_lookup_router(struct llarp_dht_context *ctx,
struct llarp_router_lookup_job *job)
{
job->dht = ctx;
job->found = false;
job->result.Clear();
// llarp_rc_clear(&job->result);
llarp::LogError("implement me llarp_dht_lookup_router");
/*
llarp_logic_queue_job(ctx->parent->logic,
{job, &llarp::dht::Context::queue_router_lookup});
*/
}

@ -1,8 +1,38 @@
#include <llarp/endian.h>
#include <string.h>
#include "dnsd.hpp" // for llarp_handle_dnsd_recvfrom, dnsc
#include "logger.hpp"
#include <llarp/dnsd.hpp> // for llarp_handle_dnsd_recvfrom, dnsc
#include <llarp/logger.hpp>
/*
<domain-name> is a domain name represented as a series of labels, and
terminated by a label with zero length. <character-string> is a single
length octet followed by that number of characters. <character-string>
is treated as binary information, and can be up to 256 characters in
length (including the length octet).
*/
std::string
getDNSstring(const char *buffer)
{
std::string str = "";
uint8_t length = *buffer++;
// printf("dnsStringLen[%d]\n", length);
// llarp::LogInfo("dnsStringLen ", length);
if(!length)
return str;
while(length != 0)
{
for(int i = 0; i < length; i++)
{
char c = *buffer++;
str.append(1, c);
}
length = *buffer++;
if(length != 0)
str.append(1, '.');
}
return str;
}
// lets just remove uint
#ifdef _WIN32
#define uint UINT
#endif
@ -17,7 +47,6 @@ extern "C"
return value;
}
// uint32_t
uint32_t
get32bits(const char *&buffer) throw()
{
@ -31,7 +60,7 @@ extern "C"
{
dns_msg_header *hdr = new dns_msg_header;
hdr->id = get16bits(buffer);
uint fields = get16bits(buffer);
uint16_t fields = get16bits(buffer);
uint8_t lFields = (fields & 0x00FF) >> 0;
uint8_t hFields = (fields & 0xFF00) >> 8;
// hdr->qr = fields & 0x8000;
@ -58,6 +87,9 @@ extern "C"
decode_question(const char *buffer)
{
dns_msg_question *question = new dns_msg_question;
std::string m_qName = getDNSstring(buffer);
// buffer += m_qName.size() + 1;
/*
std::string m_qName = "";
int length = *buffer++;
// llarp::LogInfo("qNamLen", length);
@ -72,6 +104,7 @@ extern "C"
if(length != 0)
m_qName.append(1, '.');
}
*/
question->name = m_qName;
question->type = get16bits(buffer);
question->qClass = get16bits(buffer);
@ -82,7 +115,34 @@ extern "C"
decode_answer(const char *buffer)
{
dns_msg_answer *answer = new dns_msg_answer;
answer->type = get16bits(buffer);
// skip for now until we can handle compressed labels
/*
std::string aName = getDNSstring((char *)buffer);
buffer += aName.size() + 1;
*/
/*
llarp_buffer_t bob;
bob.base = (unsigned char *)buffer;
bob.sz = 12;
llarp::DumpBuffer(bob);
*/
char hex_buffer[12 * 3 + 1];
hex_buffer[12 * 3] = 0;
for(unsigned int j = 0; j < 10; j++)
sprintf(&hex_buffer[3 * j], "%02X ", buffer[j]);
llarp::LogDebug("First 12 bytes: ", hex_buffer);
uint8_t first = *buffer++;
// llarp::LogInfo("decode - first", std::to_string(first));
// SOA hack
if(first != 12 && first != 14) // 0x0c (c0 0c) 0
{
llarp::LogDebug("decode - first isnt 12, stepping back");
buffer--; // rewind buffer one byte
}
answer->type = get16bits(buffer);
// assert(answer->type < 259);
if(answer->type > 259)
{
@ -95,10 +155,48 @@ extern "C"
{
answer->rData = new uint8_t[answer->rdLen];
memcpy(answer->rData, buffer, answer->rdLen);
buffer += answer->rdLen; // advance the length
}
else
{
llarp::LogWarn("Unknown Type ", answer->type);
llarp::LogDebug("Got type ", answer->type);
switch(answer->type)
{
case 5:
buffer += answer->rdLen; // advance the length
break;
case 6: // type 6 = SOA
{
// 2 names, then 4x 32bit
std::string mname = getDNSstring((char *)buffer);
std::string rname = getDNSstring((char *)buffer);
uint32_t serial = get32bits(buffer);
uint32_t refresh = get32bits(buffer);
uint32_t retry = get32bits(buffer);
uint32_t expire = get32bits(buffer);
uint32_t minimum = get32bits(buffer);
llarp::LogInfo("mname : ", mname);
llarp::LogInfo("rname : ", rname);
llarp::LogDebug("serial : ", serial);
llarp::LogDebug("refresh : ", refresh);
llarp::LogDebug("retry : ", retry);
llarp::LogDebug("expire : ", expire);
llarp::LogDebug("minimum : ", minimum);
}
break;
case 12:
{
std::string revname = getDNSstring((char *)buffer);
llarp::LogInfo("revDNSname: ", revname);
answer->rData = new uint8_t[answer->rdLen + 1];
memcpy(answer->rData, revname.c_str(), answer->rdLen);
}
break;
default:
buffer += answer->rdLen; // advance the length
llarp::LogWarn("Unknown Type ", answer->type);
break;
}
}
return answer;
}
@ -137,7 +235,7 @@ extern "C"
// llarp::LogInfo("start ", start, " domain size ", domain.size());
*buffer++ = domain.size() - start; // last label length octet
for(uint i = start; i < domain.size(); i++)
for(size_t i = start; i < domain.size(); i++)
{
*buffer++ = domain[i]; // last label octets
// llarp::LogInfo("Writing ", domain[i], " at ", i);
@ -148,7 +246,7 @@ extern "C"
void
llarp_handle_dns_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *saddr, const void *buf,
const struct sockaddr *addr, const void *buf,
ssize_t sz)
{
unsigned char *castBuf = (unsigned char *)buf;
@ -160,25 +258,25 @@ extern "C"
if(hdr->qr)
{
llarp::LogDebug("handling as dnsc answer");
llarp_handle_dnsc_recvfrom(udp, saddr, buf, sz);
llarp_handle_dnsc_recvfrom(udp, addr, buf, sz);
}
else
{
llarp::LogDebug("handling as dnsd question");
llarp_handle_dnsd_recvfrom(udp, saddr, buf, sz);
llarp_handle_dnsd_recvfrom(udp, addr, buf, sz);
}
/*
llarp::LogInfo("msg op ", hdr->opcode);
llarp::LogInfo("msg rc ", hdr->rcode);
for(uint i = 0; i < hdr->qdCount; i++)
for(uint8_t i = 0; i < hdr->qdCount; i++)
{
dns_msg_question *question = decode_question((const char*)castBuf);
llarp::LogInfo("Read a question");
castBuf += question->name.length() + 8;
}
for(uint i = 0; i < hdr->anCount; i++)
for(uint8_t i = 0; i < hdr->anCount; i++)
{
dns_msg_answer *answer = decode_answer((const char*)castBuf);
llarp::LogInfo("Read an answer");
@ -186,4 +284,4 @@ extern "C"
}
*/
}
}
}

@ -0,0 +1,154 @@
#include <llarp/dns_dotlokilookup.hpp>
#include <llarp/handlers/tun.hpp>
std::string const default_chars =
"abcdefghijklmnaoqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
#include <random>
std::string
random_string(size_t len = 15, std::string const &allowed_chars = default_chars)
{
std::mt19937_64 gen{std::random_device()()};
std::uniform_int_distribution< size_t > dist{0, allowed_chars.length() - 1};
std::string ret;
std::generate_n(std::back_inserter(ret), len,
[&] { return allowed_chars[dist(gen)]; });
return ret;
}
struct check_query_simple_request
{
const struct sockaddr *from; // source
dnsd_question_request *request;
};
std::unordered_map< std::string, struct dnsd_query_hook_response * >
loki_tld_lookup_cache;
void
llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
{
if(left)
return;
// struct check_query_request *request = static_cast< struct
// check_query_request * >(u);
struct check_query_simple_request *qr =
static_cast< struct check_query_simple_request * >(u);
dotLokiLookup *dll = (dotLokiLookup *)qr->request->context->user;
if(!dll)
{
llarp::LogError("DNSd dotLokiLookup is not configured");
return;
}
// we do have result
// if so send that
// else
// if we have a free private ip, send that
struct dns_pointer *free_private = dns_iptracker_get_free(dll->ip_tracker);
if(free_private)
{
// do mapping
llarp::service::Address addr;
if(!addr.FromString(qr->request->question.name))
{
llarp::LogWarn("Could not base32 decode address: ",
qr->request->question.name);
delete qr;
return;
}
in_addr ip_address = ((sockaddr_in *)free_private->hostResult)->sin_addr;
llarp::handlers::TunEndpoint *tunEndpoint =
(llarp::handlers::TunEndpoint *)dll->user;
bool mapResult = tunEndpoint->MapAddress(addr, ntohl(ip_address.s_addr));
/*
bool mapResult = main_router_mapAddress(
ctx, addr,
ntohl(ip_address.s_addr)); // maybe ntohl on the s_addr
*/
if(!mapResult)
{
delete qr;
return;
}
// make a dnsd_query_hook_response for the cache
dnsd_query_hook_response *response = new dnsd_query_hook_response;
response->dontLookUp = true;
response->dontSendResponse = false;
response->returnThis = free_private->hostResult;
llarp::LogInfo("Saving ", qr->request->question.name);
loki_tld_lookup_cache[qr->request->question.name] = response;
// FIXME: flush cache to disk
// on crash we'll need to bring up all the same IPs we assigned before...
writesend_dnss_response(free_private->hostResult, qr->from, qr->request);
delete qr;
return;
}
// else
llarp::LogInfo("Sending cname to delay");
writecname_dnss_response(
random_string(49, "abcdefghijklmnopqrstuvwxyz") + "bob.loki", qr->from,
qr->request);
delete qr;
}
dnsd_query_hook_response *
llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from,
struct dnsd_question_request *request)
{
dnsd_query_hook_response *response = new dnsd_query_hook_response;
// dotLokiLookup *dll = (dotLokiLookup
// *)request->context->user;
response->dontLookUp = false;
response->dontSendResponse = false;
response->returnThis = nullptr;
llarp::LogDebug("Hooked ", name);
std::string lName = name;
std::transform(lName.begin(), lName.end(), lName.begin(), ::tolower);
// FIXME: probably should just read the last 5 bytes
if(lName.find(".loki") != std::string::npos)
{
llarp::LogInfo("Detect Loki Lookup for ", lName);
auto cache_check = loki_tld_lookup_cache.find(lName);
if(cache_check != loki_tld_lookup_cache.end())
{
// was in cache
llarp::LogInfo("Reused address from LokiLookupCache");
// FIXME: avoid the allocation if you could
delete response;
return cache_check->second;
}
// decode string into HS addr
llarp::service::Address addr;
if(!addr.FromString(lName))
{
llarp::LogWarn("Could not base32 decode address");
response->dontSendResponse = true;
return response;
}
llarp::LogInfo("Got address ", addr);
// start path build early (if you're looking it up, you're probably going to
// use it)
// main_router_prefetch(ctx, addr);
// schedule future response
check_query_simple_request *qr = new check_query_simple_request;
qr->from = from;
qr->request = request;
// nslookup on osx is about 5 sec before a retry, 2s on linux
llarp_logic_call_later(request->context->client.logic,
{2000, qr, &llarp_dotlokilookup_checkQuery});
response->dontSendResponse = true;
}
return response;
}

@ -0,0 +1,191 @@
#include <llarp/dns_iptracker.hpp>
dns_iptracker g_dns_iptracker;
void
dns_iptracker_init()
{
/*
g_dns_iptracker.interfaces = llarp_getPrivateIfs();
llarp::LogInfo("Interface uses 10.x.x.x? ",
g_dns_iptracker.interfaces.ten ? "Yes" : "No");
g_dns_iptracker.used_privates = g_dns_iptracker.interfaces;
llarp::LogInfo("We used 10.x.x.x? ",
g_dns_iptracker.used_privates.ten ? "Yes" : "No");
*/
// disable all possibilities unless you setup a tunGateway
g_dns_iptracker.used_privates.ten = true;
g_dns_iptracker.used_privates.oneSeven = true;
g_dns_iptracker.used_privates.oneNine = true;
}
// not sure we want tunGatewayIP... we'll know when we get further
bool
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll, llarp::Addr tunGatewayIp)
{
dll->ip_tracker = &g_dns_iptracker;
return true;
}
// FIXME: pass in b32addr of client
bool
dns_iptracker_setup(llarp::Addr tunGatewayIp)
{
struct in_addr *addr = tunGatewayIp.addr4();
unsigned char *ip = (unsigned char *)&(addr->s_addr);
llarp::LogInfo("iptracker setup: (", std::to_string(ip[0]), ").[",
std::to_string(ip[1]), '.', std::to_string(ip[2]), "].",
std::to_string(ip[3]));
std::unique_ptr<ip_range> range(new ip_range);
range->octet2 = ip[1]; // 2nd octet
range->octet3 = ip[2]; // 3rd octet
// FIXME: look up any static mappings to discount
range->left = 252;
// 4th octet, probably 1, set it
struct dns_pointer *result = new dns_pointer;
result->hostResult = new sockaddr;
tunGatewayIp.CopyInto(result->hostResult);
// result->b32addr = ; // FIXME: should be our HS addr
range->used[ip[3]] = result; // claim tun IP
// save tun range in tracker
// FIXME: forcing one and only one range
if(ip[0] == 10)
{
g_dns_iptracker.used_ten_ips.push_back(std::move(range));
g_dns_iptracker.used_privates.ten = false;
}
else if(ip[0] == 172)
{
g_dns_iptracker.used_seven_ips.push_back(std::move(range));
g_dns_iptracker.used_privates.oneSeven = false;
}
else if(ip[0] == 192)
{
g_dns_iptracker.used_nine_ips.push_back(std::move(range));
g_dns_iptracker.used_privates.oneNine = false;
}
else
{
return false;
}
return true;
}
inline struct dns_pointer *
dns_iptracker_allocate_range(std::unique_ptr<ip_range> &range, uint8_t first)
{
// we have an IP
llarp::LogDebug("Range has ", (unsigned int)range->left, " ips left");
range->left--; // use it up
struct dns_pointer *result = new dns_pointer;
llarp::Addr ip(first, range->octet2, range->octet3,
range->left + 2); // why plus 2? to start at .2
llarp::LogDebug("Allocated ", ip);
result->hostResult = new sockaddr;
ip.CopyInto(result->hostResult);
// make an address and place into this sockaddr
range->used[range->left + 2] = result;
return result;
}
struct dns_pointer *
dns_iptracker_check_range(std::vector< std::unique_ptr<ip_range> > &ranges, uint8_t first)
{
// tens not all used up
if(ranges.size())
{
// FIXME: maybe find_if where left not 0
// find a range
for(auto it = ranges.begin(); it != ranges.end(); ++it)
{
if((*it)->left)
{
struct dns_pointer *result = dns_iptracker_allocate_range(*it, first);
if(!(*it)->left)
{
// all used up
// FIXME: are there any more octets available?
}
return result;
}
}
}
else
{
// create one
std::unique_ptr<ip_range> new_range(new ip_range);
new_range->octet2 = 0;
switch(first)
{
case 172:
{
// FIXME: goes up to 31...
new_range->octet2 = 16;
break;
}
case 192:
{
new_range->octet2 = 168;
break;
}
}
new_range->octet3 = 0; // FIXME: counter (0-255)
// CHECK: planning a /24 but maybe that's too wide for broadcasts
new_range->left = 252; // 0 is net, 1 is gw, 255 is broadcast
ranges.push_back(std::move(new_range));
// don't need to check if we're out since this is fresh range
return dns_iptracker_allocate_range(new_range, first);
}
return nullptr;
}
struct dns_pointer *
dns_iptracker_get_free()
{
return dns_iptracker_get_free(&g_dns_iptracker);
}
struct dns_pointer *
dns_iptracker_get_free(dns_iptracker *iptracker)
{
llarp::LogInfo("We used 10.x.x.x? ",
iptracker->used_privates.ten ? "Yes" : "No");
if(!iptracker->used_privates.ten)
{
struct dns_pointer *test =
dns_iptracker_check_range(iptracker->used_ten_ips, 10);
if(test)
{
return test;
}
}
llarp::LogInfo("We used 172.16.x.x? ",
iptracker->used_privates.oneSeven ? "Yes" : "No");
if(!iptracker->used_privates.oneSeven)
{
struct dns_pointer *test =
dns_iptracker_check_range(iptracker->used_seven_ips, 172);
if(test)
{
return test;
}
}
llarp::LogInfo("We used 192.168.x.x? ",
iptracker->used_privates.oneNine ? "Yes" : "No");
if(!iptracker->used_privates.oneNine)
{
struct dns_pointer *test =
dns_iptracker_check_range(iptracker->used_nine_ips, 192);
if(test)
{
return test;
}
}
return nullptr;
}

@ -1,6 +1,4 @@
#include "dnsc.hpp"
#include <llarp/dns.h>
#include "buffer.hpp"
#include <llarp/dnsc.hpp>
#ifndef _WIN32
#include <arpa/inet.h>
@ -16,18 +14,17 @@
#include <unistd.h> /* close */
#endif
#include <cstdio>
#include <algorithm> // for std::find_if
#include <llarp/net.hpp> // for llarp::Addr
#include <llarp/logger.hpp>
#include <stdio.h> // sprintf
#include <llarp/dns.h>
#include "llarp/net.hpp" // for llarp::Addr
#include "logger.hpp"
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
// FIXME: make configurable
#define SERVER "8.8.8.8"
#define PORT 53
dns_tracker dns_udp_tracker;
#define DNC_BUF_SIZE 512
// a question to be asked remotely
/// a question to be asked remotely (the actual bytes to send on the wire)
// header, question
struct dns_query
{
@ -37,6 +34,7 @@ struct dns_query
// uint16_t reqType;
};
/// build a DNS question packet
struct dns_query *
build_dns_packet(char *url, uint16_t id, uint16_t reqType)
{
@ -69,7 +67,8 @@ build_dns_packet(char *url, uint16_t id, uint16_t reqType)
// llarp::LogDebug("Asking DNS server %s about %s", SERVER, dnsQuery->url);
char *strTemp = strdup(url);
word = strtok(strTemp, ".");
word = strtok(strTemp, ".");
while(word)
{
// llarp::LogDebug("parsing hostname: \"%s\" is %zu characters", word,
@ -81,7 +80,6 @@ build_dns_packet(char *url, uint16_t id, uint16_t reqType)
}
word = strtok(nullptr, ".");
}
dnsQuery->request[dnsQuery->length++] = 0x00; // End of the host name
dnsQuery->request[dnsQuery->length++] =
0x00; // 0x0001 - Query is a Type A query (host address)
@ -92,240 +90,57 @@ build_dns_packet(char *url, uint16_t id, uint16_t reqType)
return dnsQuery;
}
struct sockaddr *
raw_resolve_host(const char *url)
dns_query *
answer_request_alloc(struct dnsc_context *dnsc, void *sock, const char *url,
dnsc_answer_hook_func resolved, void *user)
{
// char *sUrl = strdup(url);
// struct dns_query dnsQuery;
dns_query *dns_packet = build_dns_packet((char *)url, 0xDB42, 1);
/*
dnsQuery.length = 12;
dnsQuery.url = sUrl;
dnsQuery.reqType = 0x01;
// dnsQuery.request = { 0xDB, 0x42, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
// 0x00, 0x00, 0x00 };
dnsQuery.request[0] = 0xDB;
dnsQuery.request[1] = 0x42;
dnsQuery.request[2] = 0x01;
dnsQuery.request[3] = 0x00;
dnsQuery.request[4] = 0x00;
dnsQuery.request[5] = 0x01;
dnsQuery.request[6] = 0x00;
dnsQuery.request[7] = 0x00;
dnsQuery.request[8] = 0x00;
dnsQuery.request[9] = 0x00;
dnsQuery.request[10] = 0x00;
dnsQuery.request[11] = 0x00;
*/
// char *word;
unsigned int i;
llarp::LogDebug("Asking DNS server ", SERVER, " about ", url);
// dnsQuery.reqType = 0x01;
/*
word = strtok(sUrl, ".");
while(word)
{
llarp::LogDebug("parsing hostname: \"%s\" is %zu characters\n", word,
strlen(word));
dnsQuery.request[dnsQuery.length++] = strlen(word);
for(i = 0; i < strlen(word); i++)
{
dnsQuery.request[dnsQuery.length++] = word[i];
}
word = strtok(nullptr, ".");
}
dnsQuery.request[dnsQuery.length++] = 0x00; // End of the host name
dnsQuery.request[dnsQuery.length++] =
0x00; // 0x0001 - Query is a Type A query (host address)
dnsQuery.request[dnsQuery.length++] = dnsQuery.reqType;
dnsQuery.request[dnsQuery.length++] =
0x00; // 0x0001 - Query is class IN (Internet address)
dnsQuery.request[dnsQuery.length++] = 0x01;
*/
struct sockaddr_in addr;
// int socket;
ssize_t ret;
int rcode;
socklen_t size;
int ip = 0;
// int length;
unsigned char buffer[DNC_BUF_SIZE];
// unsigned char tempBuf[3];
uint16_t QDCOUNT; // No. of items in Question Section
uint16_t ANCOUNT; // No. of items in Answer Section
uint16_t NSCOUNT; // No. of items in Authority Section
uint16_t ARCOUNT; // No. of items in Additional Section
// uint16_t QCLASS; // Specifies the class of the query
uint16_t ATYPE; // Specifies the meaning of the data in the RDATA field
// uint16_t ACLASS; // Specifies the class of the data in the RDATA field
// uint32_t TTL; // The number of seconds the results can be cached
// uint16_t RDLENGTH; // The length of the RDATA field
// uint16_t MSGID;
#ifndef _WIN32
int sockfd;
#else
SOCKET sockfd;
#endif
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0)
{
llarp::LogWarn("Error creating socket!\n");
return nullptr;
}
// socket = sockfd;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(SERVER);
addr.sin_port = htons(PORT);
size = sizeof(addr);
// hexdump("sending packet", &dnsQuery.request, dnsQuery.length);
#ifdef _WIN32
ret = sendto(sockfd, (const char *)dns_packet->request, dns_packet->length, 0,
(struct sockaddr *)&addr, size);
#else
ret = sendto(sockfd, dns_packet->request, dns_packet->length, 0,
(struct sockaddr *)&addr, size);
#endif
delete dns_packet;
if(ret < 0)
{
llarp::LogWarn("Error Sending Request");
return nullptr;
}
// llarp::LogInfo("Sent\n");
memset(&buffer, 0, DNC_BUF_SIZE);
#ifdef _WIN32
ret = recvfrom(sockfd, (char *)buffer, DNC_BUF_SIZE, 0,
(struct sockaddr *)&addr, &size);
#else
ret = recvfrom(sockfd, buffer, DNC_BUF_SIZE, 0, (struct sockaddr *)&addr,
&size);
#endif
if(ret < 0)
dnsc_answer_request *request = new dnsc_answer_request;
if(!request)
{
llarp::LogWarn("Error Receiving Response");
llarp::LogError("Couldn't make dnsc request");
return nullptr;
}
request->sock = sock;
request->user = user;
request->resolved = resolved;
request->found = false;
request->context = dnsc;
// hexdump("received packet", &buffer, ret);
char *sUrl = strdup(url);
request->question.name = (char *)sUrl;
#ifndef _WIN32
close(sockfd);
#else
closesocket(sockfd);
#endif
rcode = (buffer[3] & 0x0F);
// tempBuf[0] = buffer[4];
// tempBuf[1] = buffer[5];
// tempBuf[2] = '\0';
// printf("%0x %0x %0x %0x\n", buffer[4], buffer[5], tempBuf[0], tempBuf[1]);
// QDCOUNT = (uint16_t) strtol(tempBuf, nullptr, 16);
QDCOUNT = (uint16_t)buffer[4] * 0x100 + buffer[5];
llarp::LogDebug("entries in question section: %u\n", QDCOUNT);
ANCOUNT = (uint16_t)buffer[6] * 0x100 + buffer[7];
llarp::LogDebug("records in answer section: %u\n", ANCOUNT);
NSCOUNT = (uint16_t)buffer[8] * 0x100 + buffer[9];
llarp::LogDebug("name server resource record count: %u\n", NSCOUNT);
ARCOUNT = (uint16_t)buffer[10] * 0x100 + buffer[11];
llarp::LogDebug("additional records count: %u\n", ARCOUNT);
/*
llarp::LogDebug("query type: %u\n", dnsQuery.reqType);
QCLASS = (uint16_t)dnsQuery.request[dnsQuery.length - 2] * 0x100
+ dnsQuery.request[dnsQuery.length - 1];
llarp::LogDebug("query class: %u\n", QCLASS);
length = dnsQuery.length + 1; // to skip 0xc00c
ATYPE = (uint16_t)buffer[length + 1] * 0x100 + buffer[length + 2];
llarp::LogDebug("answer type: %u\n", ATYPE);
ACLASS = (uint16_t)buffer[length + 3] * 0x100 + buffer[length + 4];
llarp::LogDebug("answer class: %u\n", ACLASS);
TTL = (uint32_t)buffer[length + 5] * 0x1000000 + buffer[length + 6] * 0x10000
+ buffer[length + 7] * 0x100 + buffer[length + 8];
llarp::LogDebug("seconds to cache: %u\n", TTL);
RDLENGTH = (uint16_t)buffer[length + 9] * 0x100 + buffer[length + 10];
llarp::LogDebug("bytes in answer: %u\n", RDLENGTH);
MSGID = (uint16_t)buffer[0] * 0x100 + buffer[1];
llarp::LogDebug("answer msg id: %u\n", MSGID);
*/
if(rcode == 2)
{
llarp::LogWarn("nameserver %s returned SERVFAIL:\n", SERVER);
llarp::LogWarn(
" the name server was unable to process this query due to a\n "
"problem with the name server.\n");
return nullptr;
}
else if(rcode == 3)
// leave 256 bytes available
if(request->question.name.size() > 255)
{
llarp::LogWarn("nameserver %s returned NXDOMAIN for ", SERVER);
llarp::LogWarn(
" the domain name referenced in the query does not exist\n");
// size_t diff = request->question.name.size() - 255;
// request->question.name = request->question.name.substr(diff); // get the
// rightmost 255 bytes
llarp::LogWarn("dnsc request question too long");
return nullptr;
}
request->question.type = strstr(url, "in-addr.arpa") != nullptr ? 12 : 1;
request->question.qClass = 1;
/* search for and print IPv4 addresses */
// if(dnsQuery.reqType == 0x01)
if(1)
{
llarp::LogDebug("DNS server's answer is: (type#=%u):", ATYPE);
// printf("IPv4 address(es) for %s:\n", dnsQuery.url);
for(i = 0; i < ret; i++)
{
if(buffer[i] == 0xC0 && buffer[i + 3] == 0x01)
{
ip++;
i += 12; /* ! += buf[i+1]; */
llarp::LogDebug(" %u.%u.%u.%u\n", buffer[i], buffer[i + 1],
buffer[i + 2], buffer[i + 3]);
struct sockaddr *g_addr = new sockaddr;
g_addr->sa_family = AF_INET;
#if((__APPLE__ && __MACH__) || __FreeBSD__)
g_addr->sa_len = sizeof(in_addr);
#endif
struct in_addr *addr = &((struct sockaddr_in *)g_addr)->sin_addr;
unsigned char *ip;
// have ip point to s_addr
ip = (unsigned char *)&(addr->s_addr);
ip[0] = buffer[i + 0];
ip[1] = buffer[i + 1];
ip[2] = buffer[i + 2];
ip[3] = buffer[i + 3];
// register our self with the tracker
dns_tracker *tracker = request->context->tracker;
uint16_t id = ++tracker->c_requests;
if(id == 65535)
id = 0;
tracker->client_request[id] = std::unique_ptr<dnsc_answer_request>(request);
return g_addr;
}
}
dns_query *dns_packet = build_dns_packet(
(char *)request->question.name.c_str(), id, request->question.type);
if(!ip)
{
llarp::LogWarn(" No IPv4 address found in the DNS response!\n");
return nullptr;
}
}
return nullptr;
return dns_packet;
}
// FIXME: make first a std_unique
/// generic dnsc handler
void
llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *saddr, const void *buf,
ssize_t sz)
generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
const struct sockaddr *saddr, const void *buf,
ssize_t sz)
{
// lock_t lock(m_dnsc_Mutex);
// llarp::LogInfo("got a response, udp user is ", udp->user);
unsigned char *castBuf = (unsigned char *)buf;
@ -333,11 +148,6 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
dns_msg_header *hdr = decode_hdr((const char *)castBuf);
llarp::LogDebug("Header got client responses for id: ", hdr->id);
// if we sent this out, then there's an id
struct dns_tracker *tracker = (struct dns_tracker *)udp->user;
struct dnsc_answer_request *request = tracker->client_request[hdr->id];
if(!request)
{
llarp::LogError(
@ -359,17 +169,17 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
// hexdump("received packet", &buffer, ret);
/*
uint16_t QDCOUNT; // No. of items in Question Section
uint16_t ANCOUNT; // No. of items in Answer Section
uint16_t NSCOUNT; // No. of items in Authority Section
uint16_t ARCOUNT; // No. of items in Additional Section
uint16_t QCLASS; // Specifies the class of the query
uint16_t ATYPE; // Specifies the meaning of the data in the RDATA field
uint16_t ACLASS; // Specifies the class of the data in the RDATA field
uint32_t TTL; // The number of seconds the results can be cached
uint16_t RDLENGTH; // The length of the RDATA field
uint16_t MSGID;
*/
uint16_t QDCOUNT; // No. of items in Question Section
uint16_t ANCOUNT; // No. of items in Answer Section
uint16_t NSCOUNT; // No. of items in Authority Section
uint16_t ARCOUNT; // No. of items in Additional Section
uint16_t QCLASS; // Specifies the class of the query
uint16_t ATYPE; // Specifies the meaning of the data in the RDATA field
uint16_t ACLASS; // Specifies the class of the data in the RDATA field
uint32_t TTL; // The number of seconds the results can be cached
uint16_t RDLENGTH; // The length of the RDATA field
uint16_t MSGID;
*/
uint8_t rcode;
// int length;
@ -396,13 +206,13 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
// we may need to parse question first
/*
dns_msg_question *question = decode_question((const char *)castBuf);
llarp::LogInfo("que name ", question->name);
castBuf += question->name.length() + 8;
dns_msg_question *question = decode_question((const char *)castBuf);
llarp::LogInfo("que name ", question->name);
castBuf += question->name.length() + 8;
dns_msg_answer *answer = decode_answer((const char *)castBuf);
castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
*/
dns_msg_answer *answer = decode_answer((const char *)castBuf);
castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
*/
// FIXME: only handling one atm
dns_msg_question *question = nullptr;
@ -410,57 +220,105 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
{
question = decode_question((const char *)castBuf);
llarp::LogDebug("Read a question");
castBuf += question->name.length() + 8;
// 1 dot: 1 byte for length + length
// 4 bytes for class/type
castBuf += question->name.length() + 1 + 4;
castBuf += 2; // skip answer label
}
// FIXME: only handling one atm
std::vector< dns_msg_answer * > answers;
dns_msg_answer *answer = nullptr;
for(uint i = 0; i < hdr->anCount; i++)
{
answer = decode_answer((const char *)castBuf);
llarp::LogDebug("Read an answer");
castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
answers.push_back(answer);
llarp::LogDebug("Read an answer ", answer->type, " for ",
request->question.name);
// llarp::LogInfo("Read an answer. Label Len: ", answer->name.length(), "
// rdLen: ", answer->rdLen);
// name + Type (2) + Class (2) + TTL (4) + rdLen (2) + rdData + skip next
// answer label (1) first 2 was answer->name.length() if lbl is ref and type
// 1: it should be 16 bytes long l0 + t2 + c2 + t4 + l2 + rd4 (14) + l2
// (2)
castBuf += 0 + 2 + 2 + 4 + 2 + answer->rdLen;
castBuf += 2; // skip answer label
uint8_t first = *castBuf;
if(first != 0)
{
llarp::LogDebug("next byte isnt 12, skipping ahead one byte. ",
std::to_string(first));
castBuf++;
}
// prevent reading past the end of the packet
auto diff = castBuf - (unsigned char *)buf;
llarp::LogDebug("Read answer, bytes left ", diff);
if(diff > sz)
{
llarp::LogWarn("Would read past end of dns packet. for ",
request->question.name);
break;
}
}
// handle authority records (usually no answers with these, so we'll just
// stomp) usually NS records tho
for(uint i = 0; i < hdr->nsCount; i++)
{
answer = decode_answer((const char *)castBuf);
// answers.push_back(answer);
llarp::LogDebug("Read an authority");
castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
}
/*
size_t i = 0;
for(auto it = answers.begin(); it != answers.end(); ++it)
{
llarp::LogInfo("Answer #", i, " class: [", (*it)->aClass, "] type: [",
(*it)->type,
"] rdlen[", (*it)->rdLen, "]");
i++;
}
*/
// dns_msg_answer *answer2 = decode_answer((const char*)castBuf);
// castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
// llarp::LogDebug("query type: %u\n", dnsQuery->reqType);
/*
QCLASS = (uint16_t)dnsQuery->request[dnsQuery->length - 2] * 0x100
+ dnsQuery->request[dnsQuery->length - 1];
llarp::LogInfo("query class: ", QCLASS);
length = dnsQuery->length + 1; // to skip 0xc00c
// printf("length [%d] from [%d]\n", length, buffer.base);
ATYPE = (uint16_t)buffer[length + 1] * 0x100 + buffer[length + 2];
llarp::LogInfo("answer type: ", ATYPE);
ACLASS = (uint16_t)buffer[length + 3] * 0x100 + buffer[length + 4];
llarp::LogInfo("answer class: ", ACLASS);
TTL = (uint32_t)buffer[length + 5] * 0x1000000 + buffer[length + 6] * 0x10000
+ buffer[length + 7] * 0x100 + buffer[length + 8];
llarp::LogInfo("seconds to cache: ", TTL);
RDLENGTH = (uint16_t)buffer[length + 9] * 0x100 + buffer[length + 10];
llarp::LogInfo("bytes in answer: ", RDLENGTH);
MSGID = (uint16_t)buffer[0] * 0x100 + buffer[1];
// llarp::LogDebug("answer msg id: %u\n", MSGID);
*/
QCLASS = (uint16_t)dnsQuery->request[dnsQuery->length - 2] * 0x100
+ dnsQuery->request[dnsQuery->length - 1];
llarp::LogInfo("query class: ", QCLASS);
length = dnsQuery->length + 1; // to skip 0xc00c
// printf("length [%d] from [%d]\n", length, buffer.base);
ATYPE = (uint16_t)buffer[length + 1] * 0x100 + buffer[length + 2];
llarp::LogInfo("answer type: ", ATYPE);
ACLASS = (uint16_t)buffer[length + 3] * 0x100 + buffer[length + 4];
llarp::LogInfo("answer class: ", ACLASS);
TTL = (uint32_t)buffer[length + 5] * 0x1000000 + buffer[length + 6] * 0x10000
+ buffer[length + 7] * 0x100 + buffer[length + 8];
llarp::LogInfo("seconds to cache: ", TTL);
RDLENGTH = (uint16_t)buffer[length + 9] * 0x100 + buffer[length + 10];
llarp::LogInfo("bytes in answer: ", RDLENGTH);
MSGID = (uint16_t)buffer[0] * 0x100 + buffer[1];
// llarp::LogDebug("answer msg id: %u\n", MSGID);
*/
llarp::Addr upstreamAddr(*request->context->server);
if(answer == nullptr)
{
llarp::LogWarn("nameserver ", SERVER, " didnt return any answers:");
llarp::LogWarn("nameserver ", upstreamAddr, " didnt return any answers:");
request->resolved(request);
return;
}
if(answer->type == 5)
{
llarp::LogInfo("Last answer is a cname, advancing to first");
answer = answers.front();
}
llarp::LogDebug("ans class ", answer->aClass);
llarp::LogDebug("ans type ", answer->type);
@ -468,15 +326,15 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
llarp::LogDebug("ans rdlen ", answer->rdLen);
/*
llarp::LogInfo("ans2 class ", answer2->aClass);
llarp::LogInfo("ans2 type ", answer2->type);
llarp::LogInfo("ans2 ttl ", answer2->ttl);
llarp::LogInfo("ans2 rdlen ", answer2->rdLen);
*/
llarp::LogInfo("ans2 class ", answer2->aClass);
llarp::LogInfo("ans2 type ", answer2->type);
llarp::LogInfo("ans2 ttl ", answer2->ttl);
llarp::LogInfo("ans2 rdlen ", answer2->rdLen);
*/
if(rcode == 2)
{
llarp::LogWarn("nameserver ", SERVER, " returned SERVFAIL:");
llarp::LogWarn("nameserver ", upstreamAddr, " returned SERVFAIL:");
llarp::LogWarn(
" the name server was unable to process this query due to a problem "
"with the name server.");
@ -485,7 +343,7 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
}
else if(rcode == 3)
{
llarp::LogWarn("nameserver ", SERVER,
llarp::LogWarn("nameserver ", upstreamAddr,
" returned NXDOMAIN for: ", request->question.name);
llarp::LogWarn(" the domain name referenced in the query does not exist");
request->resolved(request);
@ -530,26 +388,149 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
return;
}
}
else if(request->question.type == 12)
{
llarp::LogInfo("Resolving PTR");
request->found = true;
request->revDNS = std::string((char *)answer->rData);
request->resolved(request);
return;
}
}
void
raw_resolve_host(struct dnsc_context *dnsc, const char *url,
dnsc_answer_hook_func resolved, void *user)
{
dns_query *dns_packet =
answer_request_alloc(dnsc, nullptr, url, resolved, user);
if(!dns_packet)
{
llarp::LogError("Couldn't make dnsc packet");
return;
}
// char *word;
llarp::Addr upstreamAddr(*dnsc->server);
llarp::LogDebug("Asking DNS server ", upstreamAddr, " about ", url);
struct sockaddr_in addr;
ssize_t ret;
socklen_t size;
// int length;
unsigned char buffer[DNC_BUF_SIZE];
#ifndef _WIN32
int sockfd;
#else
SOCKET sockfd;
#endif
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0)
{
llarp::LogWarn("Error creating socket!\n");
return;
}
// socket = sockfd;
sockaddr_in *dnscSock = ((sockaddr_in *)dnsc->server);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = dnscSock->sin_addr.s_addr;
addr.sin_port = dnscSock->sin_port;
size = sizeof(addr);
// hexdump("sending packet", &dnsQuery.request, dnsQuery.length);
#ifdef _WIN32
ret = sendto(sockfd, (const char *)dns_packet->request, dns_packet->length, 0,
(struct sockaddr *)&addr, size);
#else
ret = sendto(sockfd, (const char *)dns_packet->request, dns_packet->length, 0,
(struct sockaddr *)&addr, size);
#endif
delete dns_packet;
if(ret < 0)
{
llarp::LogWarn("Error Sending Request");
return;
}
llarp::LogInfo("Sent");
memset(&buffer, 0, DNC_BUF_SIZE);
llarp::LogInfo("Waiting for recv");
// Timeout?
ret = recvfrom(sockfd, buffer, DNC_BUF_SIZE, 0, (struct sockaddr *)&addr,
&size);
llarp::LogInfo("recv done ", size);
if(ret < 0)
{
llarp::LogWarn("Error Receiving Response");
return;
}
llarp::LogInfo("closing new socket\n");
// hexdump("received packet", &buffer, ret);
#ifndef _WIN32
close(sockfd);
#else
closesocket(sockfd);
#endif
unsigned char *castBuf = (unsigned char *)buffer;
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
dns_msg_header *hdr = decode_hdr((const char *)castBuf);
llarp::LogInfo("response header says it belongs to id #", hdr->id);
// if we sent this out, then there's an id
struct dns_tracker *tracker = (struct dns_tracker *)dnsc->tracker;
generic_handle_dnsc_recvfrom(tracker->client_request[hdr->id].get(), nullptr, castBuf, size);
}
/// intermediate udp_io handler
void
llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *saddr, const void *buf,
ssize_t sz)
{
unsigned char *castBuf = (unsigned char *)buf;
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
dns_msg_header *hdr = decode_hdr((const char *)castBuf);
llarp::LogDebug("Header got client responses for id: ", hdr->id);
// if we sent this out, then there's an id
struct dns_tracker *tracker = (struct dns_tracker *)udp->user;
struct dnsc_answer_request *request = tracker->client_request[hdr->id].get();
// sometimes we'll get double responses
if(request)
{
generic_handle_dnsc_recvfrom(request, saddr, buf, sz);
}
else
{
llarp::LogWarn("Ignoring multiple responses on ID #", hdr->id);
}
}
bool
llarp_resolve_host(struct dnsc_context *dnsc, const char *url,
dnsc_answer_hook_func resolved, void *user)
{
dnsc_answer_request *request = new dnsc_answer_request;
request->sock = (void *)&dnsc->udp;
request->user = user;
request->resolved = resolved;
request->found = false;
request->context = dnsc;
char *sUrl = strdup(url);
request->question.name = sUrl;
request->question.type = 1;
request->question.qClass = 1;
dns_query *dns_packet =
answer_request_alloc(dnsc, &dnsc->udp, url, resolved, user);
if(!dns_packet)
{
llarp::LogError("Couldn't make dnsc packet");
return false;
}
// register request with udp response tracker
dns_tracker *tracker = (dns_tracker *)dnsc->udp->user;
// dns_tracker *tracker = (dns_tracker *)dnsc->udp->user;
/*
uint16_t length = 0;
@ -583,12 +564,11 @@ llarp_resolve_host(struct dnsc_context *dnsc, const char *url,
memcpy(bytes + 12, &request->question, qLen);
*/
uint16_t id = ++tracker->c_requests;
tracker->client_request[id] = request;
// uint16_t id = ++tracker->c_requests;
// tracker->client_request[id] = request;
// llarp::LogInfo("Sending request #", tracker->c_requests, " ", length, "
// bytes");
dns_query *dns_packet = build_dns_packet((char *)url, id, 1);
// ssize_t ret = llarp_ev_udp_sendto(dnsc->udp, dnsc->server, bytes, length);
ssize_t ret = llarp_ev_udp_sendto(dnsc->udp, dnsc->server,
dns_packet->request, dns_packet->length);
@ -605,12 +585,27 @@ llarp_resolve_host(struct dnsc_context *dnsc, const char *url,
void
llarp_host_resolved(dnsc_answer_request *request)
{
delete request;
dns_tracker *tracker = (dns_tracker *)request->context->tracker;
auto val = std::find_if(
tracker->client_request.begin(), tracker->client_request.end(),
[request](std::pair<const uint, std::unique_ptr < dnsc_answer_request > > &element) {
return element.second.get() == request;
});
if(val != tracker->client_request.end())
{
tracker->client_request[val->first].reset();
}
else
{
llarp::LogWarn("Couldn't disable ", request);
}
//delete request;
}
bool
llarp_dnsc_init(struct dnsc_context *dnsc, struct llarp_udp_io *udp,
const char *dnsc_hostname, uint16_t dnsc_port)
llarp_dnsc_init(struct dnsc_context *dnsc, struct llarp_logic *logic,
struct llarp_udp_io *udp, const char *dnsc_hostname,
uint16_t dnsc_port)
{
sockaddr_in *trgaddr = new sockaddr_in;
trgaddr->sin_addr.s_addr = inet_addr(dnsc_hostname);
@ -618,6 +613,8 @@ llarp_dnsc_init(struct dnsc_context *dnsc, struct llarp_udp_io *udp,
trgaddr->sin_family = AF_INET;
dnsc->server = (sockaddr *)trgaddr;
dnsc->udp = udp;
dnsc->tracker = &dns_udp_tracker;
dnsc->logic = logic;
return true;
}

@ -1,61 +0,0 @@
#ifndef LIBLLARP_DNSC_HPP
#define LIBLLARP_DNSC_HPP
#include <llarp/ev.h> // for sockaadr
#include "dns.hpp" // get protocol structs
// internal, non-public functions
// well dnsc init/stop are public...
struct dnsc_answer_request;
// should we pass by llarp::Addr
// not as long as we're supporting raw
typedef void (*dnsc_answer_hook_func)(dnsc_answer_request *request);
// FIXME: separate generic from llarp
struct dnsc_answer_request
{
/// sock type
void *sock; // pts to udp...
/// customizable (used for hook (outer request))
void *user;
/// storage
dns_msg_question question;
/// hook
dnsc_answer_hook_func resolved;
/// result
bool found;
struct sockaddr result;
// a reference to dnsc_context incase of multiple contexts
struct dnsc_context *context;
};
void
llarp_handle_dnsc_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *saddr, const void *buf,
ssize_t sz);
void
raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, const void *buf,
ssize_t sz);
struct dnsc_context
{
/// Target: DNS server hostname/port to use
// FIXME: ipv6 it
sockaddr *server;
// where to create the new sockets
struct llarp_udp_io *udp;
};
/// initialize dns subsystem and bind socket
/// returns true on bind success otherwise returns false
bool
llarp_dnsc_init(struct dnsc_context *dnsc, struct llarp_udp_io *udp,
const char *dnsc_hostname, uint16_t dnsc_port);
bool
llarp_dnsc_stop(struct dnsc_context *dnsc);
#endif

@ -1,17 +1,13 @@
#include "dnsd.hpp"
#include <llarp/dns.h>
#include <string>
#include "ev.hpp"
#include "llarp/net.hpp"
#include "logger.hpp"
#include <llarp/dnsd.hpp>
#include <llarp/net.hpp>
extern dns_tracker dns_udp_tracker;
#ifdef _WIN32
#define wmin(x, y) (((x) < (y)) ? (x) : (y))
#define MIN wmin
#endif
dns_tracker dns_udp_tracker;
ssize_t
raw_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
const void *buffer, size_t length)
@ -22,7 +18,7 @@ raw_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
#ifdef _WIN32
return sendto(*fd, (const char *)buffer, length, 0, from, addrLen);
#else
return sendto(*fd, buffer, length, 0, from, addrLen);
return sendto(*fd, (const char *)buffer, length, 0, from, addrLen);
#endif
}
@ -44,10 +40,154 @@ llarp_sendto_dns_hook_func(void *sock, const struct sockaddr *from,
return llarp_ev_udp_sendto(udp, from, buffer, length);
}
bool
forward_dns_request(std::string request)
void
write404_dnss_response(const struct sockaddr *from,
dnsd_question_request *request)
{
const size_t BUFFER_SIZE = 1024 + (request->question.name.size() * 2);
char buf[BUFFER_SIZE];
memset(buf, 0, BUFFER_SIZE);
char *write_buffer = buf;
char *bufferBegin = buf;
// build header
put16bits(write_buffer, request->id);
int fields = (1 << 15); // QR => message type, 1 = response
fields += (0 << 14); // I think opcode is always 0
fields += 3; // response code (3 => not found, 0 = Ok)
put16bits(write_buffer, fields);
put16bits(write_buffer, 1); // QD (number of questions)
put16bits(write_buffer, 1); // AN (number of answers)
put16bits(write_buffer, 0); // NS (number of auth RRs)
put16bits(write_buffer, 0); // AR (number of Additional RRs)
// code question
code_domain(write_buffer, request->question.name);
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
// code answer
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, 1); // rdLength
*write_buffer++ = 0; // write a null byte
uint out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending 404, ", out_bytes, " bytes");
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
request->sendto_hook(request->user, from, buf, out_bytes);
}
void
writecname_dnss_response(std::string cname, const struct sockaddr *from,
dnsd_question_request *request)
{
const size_t BUFFER_SIZE = 1024 + (request->question.name.size() * 2);
char buf[BUFFER_SIZE];
memset(buf, 0, BUFFER_SIZE);
char *write_buffer = buf;
char *bufferBegin = buf;
// build header
put16bits(write_buffer, request->id);
int fields = (1 << 15); // QR => message type, 1 = response
fields += (0 << 14); // I think opcode is always 0
fields += 0; // response code (3 => not found, 0 = Ok)
// fields |= 1UL << 7; // RA recursion available
// fields |= 1UL << 8; // RD recursion desired
// fields |= 1UL << 9; // 9 is truncate, forces TCP
put16bits(write_buffer, fields);
put16bits(write_buffer, 1); // QD (number of questions)
put16bits(write_buffer, 1); // AN (number of answers)
put16bits(write_buffer, 1); // NS (number of auth RRs)
put16bits(write_buffer, 1); // AR (number of Additional RRs)
// code question
code_domain(write_buffer, request->question.name);
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
// code answer
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
put16bits(write_buffer, 5); // cname
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, cname.length() + 2); // rdLength
code_domain(write_buffer, cname); // com, type=6, ttl=0
// location of cname
//*write_buffer++ = ip[0];
//*write_buffer++ = ip[1];
// write auth RR
code_domain(write_buffer, cname); // com, type=6, ttl=0
put16bits(write_buffer, 2); // NS
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
std::string local("ns1.loki");
put16bits(write_buffer, local.length() + 2); // rdLength
code_domain(write_buffer, local); // com, type=6, ttl=0
// write addl RR
code_domain(write_buffer, local); // com, type=6, ttl=0
put16bits(write_buffer, 1); // A
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, 4); // rdLength
*write_buffer++ = 127;
*write_buffer++ = 0;
*write_buffer++ = 0;
*write_buffer++ = 1;
uint out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending cname, ", out_bytes, " bytes");
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
request->sendto_hook(request->user, from, buf, out_bytes);
}
void
writesend_dnss_revresponse(std::string reverse, const struct sockaddr *from,
dnsd_question_request *request)
{
return true;
const size_t BUFFER_SIZE = 1024 + (request->question.name.size() * 2);
char buf[BUFFER_SIZE];
memset(buf, 0, BUFFER_SIZE);
char *write_buffer = buf;
char *bufferBegin = buf;
// build header
put16bits(write_buffer, request->id);
int fields = (1 << 15); // QR => message type, 1 = response
fields += (0 << 14); // I think opcode is always 0
fields += 0; // response code (3 => not found, 0 = Ok)
put16bits(write_buffer, fields);
put16bits(write_buffer, 1); // QD (number of questions)
put16bits(write_buffer, 1); // AN (number of answers)
put16bits(write_buffer, 0); // NS (number of auth RRs)
put16bits(write_buffer, 0); // AR (number of Additional RRs)
// code question
code_domain(write_buffer, request->question.name);
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
// code answer
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, reverse.length() + 2); // rdLength
code_domain(write_buffer, reverse);
uint out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending reverse: ", reverse, " ", out_bytes, " bytes");
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
request->sendto_hook(request->user, from, buf, out_bytes);
}
// FIXME: we need an DNS answer not a sockaddr
@ -56,15 +196,16 @@ void
writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from,
dnsd_question_request *request)
{
// lock_t lock(m_dnsd2_Mutex);
// llarp::Addr test(*from);
// llarp::LogInfo("from ", test);
if(!hostRes)
{
llarp::LogWarn("Failed to resolve");
// FIXME: actually return correct packet
llarp::LogWarn("Failed to resolve ", request->question.name);
write404_dnss_response(from, request);
return;
}
const size_t BUFFER_SIZE = 1024;
const size_t BUFFER_SIZE = 1024 + (request->question.name.size() * 2);
char buf[BUFFER_SIZE];
memset(buf, 0, BUFFER_SIZE);
char *write_buffer = buf;
@ -87,6 +228,7 @@ writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from,
put16bits(write_buffer, request->question.qClass);
// code answer
llarp::LogDebug("Sending question name: ", request->question.name);
code_domain(write_buffer, request->question.name); // com, type=6, ttl=0
put16bits(write_buffer, request->question.type);
put16bits(write_buffer, request->question.qClass);
@ -97,31 +239,43 @@ writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from,
unsigned char *ip = (unsigned char *)&sin->sin_addr.s_addr;
put16bits(write_buffer, 4); // rdLength
llarp::LogDebug("Sending ip: ", std::to_string(ip[0]), '.',
std::to_string(ip[1]), '.', std::to_string(ip[2]), '.',
std::to_string(ip[3]));
*write_buffer++ = ip[0];
*write_buffer++ = ip[1];
*write_buffer++ = ip[2];
*write_buffer++ = ip[3];
uint out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending ", out_bytes, " bytes");
llarp::LogDebug("Sending found, ", out_bytes, " bytes");
// struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
request->hook(request->user, from, buf, out_bytes);
request->sendto_hook(request->user, from, buf, out_bytes);
}
void
handle_dnsc_result(dnsc_answer_request *client_request)
{
// llarp::LogInfo("phase2 client ", client_request);
// writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr
// *from, dnsd_question_request *request)
dnsd_question_request *server_request =
(dnsd_question_request *)client_request->user;
// llarp::Addr test(*server_request->from);
// llarp::LogInfo("server request sock ", server_request->from, " is ", test);
// llarp::LogInfo("phase2 server ", server_request);
writesend_dnss_response(
client_request->found ? &client_request->result : nullptr,
server_request->from, server_request);
if(!server_request)
{
llarp::LogError("Couldn't map client requser user to a server request");
return;
}
// llarp::LogDebug("handle_dnsc_result - client request question type",
// std::to_string(client_request->question.type));
if(client_request->question.type == 12)
{
writesend_dnss_revresponse(client_request->revDNS, server_request->from,
server_request);
}
else
{
writesend_dnss_response(
client_request->found ? &client_request->result : nullptr,
server_request->from, server_request);
}
llarp_host_resolved(client_request);
}
@ -130,7 +284,6 @@ void
handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from,
dnsd_question_request *request)
{
// lock_t lock(m_dnsd_Mutex);
const size_t HDR_OFFSET = 12;
const char *p_buffer = buffer;
@ -138,12 +291,10 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from,
llarp::LogDebug("dnsd rcode ", rcode);
dns_msg_header *msg = decode_hdr(p_buffer);
// llarp::LogInfo("DNS_MSG size", sizeof(dns_msg));
p_buffer += HDR_OFFSET;
request->id = msg->id;
std::string m_qName = "";
int length = *p_buffer++;
// llarp::LogInfo("qNamLen", length);
while(length != 0)
{
for(int i = 0; i < length; i++)
@ -159,9 +310,6 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from,
request->question.type = get16bits(p_buffer);
request->question.qClass = get16bits(p_buffer);
// request->m_qName = m_qName;
// request->m_qType = request->question.type;
// request->m_qClass = request->question.qClass;
llarp::LogDebug("qName ", request->question.name);
llarp::LogDebug("qType ", request->question.type);
llarp::LogDebug("qClass ", request->question.qClass);
@ -173,66 +321,92 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from,
llarp::LogInfo("DNS request from ", test2);
*/
sockaddr *fromCopy =
new sockaddr(*from); // make our own sockaddr that won't get cleaned up
if(request->context->intercept)
{
sockaddr *intercept =
request->context->intercept(request->question.name, request->context);
// llarp::Addr test(*from);
// llarp::LogInfo("from ", test);
dnsd_query_hook_response *intercept =
request->context->intercept(request->question.name, fromCopy, request);
// if(!forward_dns_request(m_qName))
if(intercept != nullptr)
{
// told that hook will handle overrides
sockaddr *fromCopy = new sockaddr(*from);
writesend_dnss_response(intercept, fromCopy, request);
return;
llarp::LogDebug("hook returned a response");
if(intercept->dontSendResponse)
{
llarp::LogDebug("HOOKED: Not sending a response");
return;
}
if(intercept->dontLookUp == true && intercept->returnThis)
{
llarp::LogDebug("HOOKED: sending an immediate override");
// told that hook will handle overrides
writesend_dnss_response(intercept->returnThis, fromCopy, request);
return;
}
}
}
sockaddr *hostRes = nullptr;
// FIXME: check request and context's client
if(!request->context)
{
llarp::LogError("dnsd request context was not a dnsd context");
writesend_dnss_response(nullptr, fromCopy, request);
return;
}
/*
struct dns_tracker *tracker = (struct dns_tracker *)request->context->tracker;
if (!tracker)
{
llarp::LogError("dnsd request context tracker was not a dns_tracker");
sockaddr *fromCopy = new sockaddr(*from);
writesend_dnss_response(nullptr, fromCopy, request);
return;
}
dnsd_context *dnsd = tracker->dnsd;
if (!dnsd)
{
llarp::LogError("tracker dnsd was not a dnsd context");
sockaddr *fromCopy = new sockaddr(*from);
writesend_dnss_response(nullptr, fromCopy, request);
return;
}
*/
if(request->llarp)
{
// llarp::Addr anIp;
// llarp::LogInfo("Checking server request ", request);
struct llarp_udp_io *udp = (struct llarp_udp_io *)request->user;
struct dns_tracker *tracker = (struct dns_tracker *)udp->user;
dnsd_context *dnsd = tracker->dnsd;
// dnsd_context *dnsd = (dnsd_context *)udp->user;
// llarp::LogInfo("Server request UDP ", request->user);
// llarp::LogInfo("server request hook ", request->hook);
// llarp::LogInfo("UDP ", udp);
// hostRes = llarp_resolveHost(udp->parent, m_qName.c_str());
llarp_resolve_host(&dnsd->client, m_qName.c_str(), &handle_dnsc_result,
(void *)request);
// make async request
llarp_resolve_host(&request->context->client, m_qName.c_str(),
&handle_dnsc_result, (void *)request);
}
else
{
hostRes = raw_resolve_host(m_qName.c_str());
llarp::Addr anIp(*hostRes);
llarp::LogDebug("DNSc got ", anIp);
// writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr
// *from, dnsd_question_request *request)
sockaddr *fromCopy = new sockaddr(*from);
writesend_dnss_response(hostRes, fromCopy, request);
// make raw/sync request
raw_resolve_host(&request->context->client, m_qName.c_str(),
&handle_dnsc_result, (void *)request);
}
}
void
llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *paddr, const void *buf,
const struct sockaddr *saddr, const void *buf,
ssize_t sz)
{
// lock_t lock(m_dnsd3_Mutex);
// llarp_link *link = static_cast< llarp_link * >(udp->user);
llarp::LogDebug("llarp Received Bytes ", sz);
if(!dns_udp_tracker.dnsd)
{
llarp::LogError("No tracker set in dnsd context");
return;
}
// create new request
dnsd_question_request *llarp_dns_request = new dnsd_question_request;
// llarp::LogInfo("Creating server request ", &llarp_dns_request);
// llarp::LogInfo("Server UDP address ", udp);
llarp_dns_request->context = dns_udp_tracker.dnsd;
// make a copy of the sockaddr
llarp_dns_request->from = new sockaddr(*paddr);
llarp_dns_request->context = dns_udp_tracker.dnsd; // set context
llarp_dns_request->from =
new sockaddr(*saddr); // make a copy of the sockaddr
llarp_dns_request->user = (void *)udp;
llarp_dns_request->llarp = true;
// set sock hook
llarp_dns_request->hook = &llarp_sendto_dns_hook_func;
llarp_dns_request->sendto_hook =
&llarp_sendto_dns_hook_func; // set sock hook
// llarp::LogInfo("Server request's UDP ", llarp_dns_request->user);
handle_recvfrom((char *)buf, sz, llarp_dns_request->from, llarp_dns_request);
@ -242,19 +416,26 @@ void
raw_handle_recvfrom(int *sockfd, const struct sockaddr *saddr, const void *buf,
ssize_t sz)
{
llarp::LogInfo("raw Received Bytes ", sz);
if(!dns_udp_tracker.dnsd)
{
llarp::LogError("No tracker set in dnsd context");
return;
}
dnsd_question_request *llarp_dns_request = new dnsd_question_request;
llarp_dns_request->from = (struct sockaddr *)saddr;
llarp_dns_request->user = (void *)sockfd;
llarp_dns_request->llarp = false;
llarp_dns_request->hook = &raw_sendto_dns_hook_func;
handle_recvfrom((char *)buf, sz, saddr, llarp_dns_request);
llarp_dns_request->context = dns_udp_tracker.dnsd; // set context
llarp_dns_request->from =
new sockaddr(*saddr); // make a copy of the sockaddr
llarp_dns_request->user = (void *)sockfd;
llarp_dns_request->llarp = false;
llarp_dns_request->sendto_hook = &raw_sendto_dns_hook_func;
handle_recvfrom((char *)buf, sz, llarp_dns_request->from, llarp_dns_request);
}
bool
llarp_dnsd_init(struct dnsd_context *dnsd, struct llarp_ev_loop *netloop,
const char *dnsd_ifname, uint16_t dnsd_port,
const char *dnsc_hostname, uint16_t dnsc_port)
llarp_dnsd_init(struct dnsd_context *dnsd, struct llarp_logic *logic,
struct llarp_ev_loop *netloop, const char *dnsd_ifname,
uint16_t dnsd_port, const char *dnsc_hostname,
uint16_t dnsc_port)
{
struct sockaddr_in bindaddr;
bindaddr.sin_addr.s_addr = inet_addr("0.0.0.0");
@ -267,15 +448,26 @@ llarp_dnsd_init(struct dnsd_context *dnsd, struct llarp_ev_loop *netloop,
dns_udp_tracker.dnsd = dnsd;
dnsd->intercept = nullptr;
dnsd->tracker = &dns_udp_tracker; // register global tracker with context
// dnsd->logic = logic; // set logic worker for timers
dnsd->intercept = nullptr; // set default intercepter
// configure dns client
if(!llarp_dnsc_init(&dnsd->client, &dnsd->udp, dnsc_hostname, dnsc_port))
if(!llarp_dnsc_init(&dnsd->client, logic, &dnsd->udp, dnsc_hostname,
dnsc_port))
{
llarp::LogError("Couldnt init dns client");
return false;
}
return llarp_ev_add_udp(netloop, &dnsd->udp, (const sockaddr *)&bindaddr)
!= -1;
if(netloop)
{
llarp::LogInfo("DNSd binding to port 53");
return llarp_ev_add_udp(netloop, &dnsd->udp, (const sockaddr *)&bindaddr)
!= -1;
}
else
{
return true;
}
}

@ -1,62 +0,0 @@
#ifndef LIBLLARP_DNSD_HPP
#define LIBLLARP_DNSD_HPP
#include <llarp/ev.h> // for sockaadr
#include <string>
#include "dns.hpp" // question and dnsc
#include "dnsc.hpp"
struct dnsd_context;
typedef ssize_t (*sendto_dns_hook_func)(void *sock, const struct sockaddr *from,
const void *buffer, size_t length);
struct dnsd_question_request
{
/// sock type
void *user;
// raw or llarp subsystem
bool llarp;
/// request id
int id;
/// question being asked
dns_msg_question question;
// request source socket
struct sockaddr *from;
sendto_dns_hook_func hook; // sendto hook tbh
// maybe a reference to dnsd_context incase of multiple
dnsd_context *context; // or you can access it via user (udp)
};
// we could have passed in the source sockaddr in case you wanted to
// handle the response yourself
typedef sockaddr *(*intercept_query_hook)(std::string name,
struct dnsd_context *context);
struct dnsd_context
{
/// DNS daemon socket to listen on
struct llarp_udp_io udp;
dnsc_context client;
/// custom data for intercept query hook
void *user;
/// hook function for intercepting dns requests
intercept_query_hook intercept;
};
void
llarp_handle_dnsd_recvfrom(struct llarp_udp_io *udp,
const struct sockaddr *paddr, const void *buf,
ssize_t sz);
/// initialize dns subsystem and bind socket
/// returns true on bind success otherwise returns false
bool
llarp_dnsd_init(struct dnsd_context *dnsd, struct llarp_ev_loop *netloop,
const char *dnsd_ifname, uint16_t dnsd_port,
const char *dnsc_hostname, uint16_t dnsc_port);
bool
llarp_dnsd_stop(struct dnsd_context *dnsd);
#endif

@ -38,7 +38,7 @@ namespace llarp
read(void* buf, size_t sz)
{
sockaddr_in6 src;
socklen_t slen = sizeof(src);
socklen_t slen = sizeof(sockaddr_in6);
sockaddr* addr = (sockaddr*)&src;
ssize_t ret = ::recvfrom(fd, buf, sz, 0, addr, &slen);
if(ret == -1)

@ -2,6 +2,9 @@
#define __USE_MINGW_ANSI_STDIO 1
#include <llarp/handlers/tun.hpp>
#include "router.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
namespace llarp
{
@ -16,14 +19,25 @@ namespace llarp
tunif.netmask = DefaultTunNetmask;
strncpy(tunif.ifaddr, DefaultTunSrcAddr, sizeof(tunif.ifaddr) - 1);
strncpy(tunif.ifname, DefaultTunIfname, sizeof(tunif.ifname) - 1);
tunif.tick = nullptr;
tunif.before_write = &tunifBeforeWrite;
tunif.recvpkt = &tunifRecvPkt;
tunif.tick = nullptr;
tunif.before_write = &tunifBeforeWrite;
tunif.recvpkt = &tunifRecvPkt;
this->dll.ip_tracker = nullptr;
this->dll.user = this;
// this->dll.callback = std::bind(&TunEndpoint::MapAddress, this);
}
bool
TunEndpoint::SetOption(const std::string &k, const std::string &v)
{
if(k == "nameresolver")
{
// we probably can set the property since the config will load before
// the relay is set up
// strncpy(tunif.ifname, v.c_str(), sizeof(tunif.ifname) - 1);
llarp::LogInfo(Name() + " would be setting DNS resolver to ", v);
return true;
}
if(k == "mapaddr")
{
auto pos = v.find(":");
@ -82,11 +96,21 @@ namespace llarp
llarp::LogInfo(Name() + " set ifaddr to ", addr, " with netmask ",
tunif.netmask);
strncpy(tunif.ifaddr, addr.c_str(), sizeof(tunif.ifaddr) - 1);
// set up address in dotLokiLookup
struct sockaddr_in s_addr;
s_addr.sin_addr.s_addr = inet_addr(tunif.ifaddr);
s_addr.sin_family = AF_INET;
llarp::Addr tunIp(s_addr);
// related to dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp);
dns_iptracker_setup(tunIp); // claim GW IP to make sure it's not inuse
return true;
}
return Endpoint::SetOption(k, v);
}
/// ip should be in host byte order
bool
TunEndpoint::MapAddress(const service::Address &addr, uint32_t ip)
{
@ -98,7 +122,7 @@ namespace llarp
return false;
}
llarp::LogInfo(Name() + " map ", addr.ToString(), " to ",
inet_ntoa({ip}));
inet_ntoa({htonl(ip)}));
m_IPToAddr.insert(std::make_pair(ip, addr));
m_AddrToIP.insert(std::make_pair(addr, ip));
MarkIPActiveForever(ip);
@ -119,6 +143,15 @@ namespace llarp
// set up networking in currrent thread if we are not isolated
if(!SetupNetworking())
return false;
llarp::LogInfo("Setting up global DNS IP tracker");
llarp::Addr tunIp;
dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp);
}
else
{
llarp::LogInfo("Setting up per netns DNS IP tracker");
this->dll.ip_tracker = new dns_iptracker;
}
// wait for result for network setup
llarp::LogInfo("waiting for tun interface...");
@ -142,15 +175,62 @@ namespace llarp
llarp::LogError(Name(), " failed to set up tun interface");
return false;
}
m_OurIP = ntohl(inet_addr(tunif.ifaddr));
struct addrinfo hint, *res = NULL;
int ret;
memset(&hint, '\0', sizeof hint);
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(tunif.ifaddr, NULL, &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)
{
llarp::LogError(Name(),
" failed to set up tun interface, we don't support "
"IPv6 format");
return false;
}
freeaddrinfo(res);
struct in_addr addr; // network byte order
if(inet_aton(tunif.ifaddr, &addr) == 0)
{
llarp::LogError(Name(), " failed to set up tun interface, cant parse ",
tunif.ifaddr);
return false;
}
llarp::Addr lAddr(tunif.ifaddr);
m_OurIP = lAddr.tohl();
m_NextIP = m_OurIP;
uint32_t mask = tunif.netmask;
uint32_t baseaddr = (htonl(m_OurIP) & netmask_ipv4_bits(mask));
m_MaxIP = (htonl(baseaddr) | ~htonl(netmask_ipv4_bits(mask)));
char buf[128] = {0};
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ",
inet_ntop(AF_INET, &m_OurIP, buf, sizeof(buf)));
uint32_t baseaddr = (m_OurIP & netmask_ipv4_bits(mask));
m_MaxIP = htonl(htonl(baseaddr) | ~htonl(netmask_ipv4_bits(mask)));
char buf[128] = {0};
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", lAddr);
llarp::LogInfo(Name(), " allocated up to ",
inet_ntop(AF_INET, &m_MaxIP, buf, sizeof(buf)));
@ -165,6 +245,15 @@ namespace llarp
#ifndef _WIN32
m_TunSetupResult.set_value(result);
#endif
if(!llarp_dnsd_init(&this->dnsd, EndpointLogic(), EndpointNetLoop(),
tunif.ifname, 53, "8.8.8.8", 53))
{
llarp::LogError("Couldnt init dns daemon");
}
// configure hook for .loki lookup
dnsd.intercept = &llarp_dotlokilookup_handler;
// set dotLokiLookup (this->dll) configuration
dnsd.user = &this->dll;
return result;
}

@ -1,6 +1,7 @@
/**
* The MIT License (MIT)
* Copyright (c) <2015> <carriez.md@gmail.com>
* Copyright (c) <2018> <rtharp@customwebapps.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to

@ -796,6 +796,55 @@ llarp_getifaddr(const char* ifname, int af, struct sockaddr* addr)
freeifaddrs(ifa);
return found;
}
struct privatesInUse
llarp_getPrivateIfs()
{
struct privatesInUse result;
result.ten = false;
result.oneSeven = false;
result.oneNine = false;
ifaddrs* ifa = nullptr;
#ifndef _WIN32
if(getifaddrs(&ifa) == -1)
#else
if(!getifaddrs(&ifa))
#endif
return result;
ifaddrs* i = ifa;
while(i)
{
if(i->ifa_addr && i->ifa_addr->sa_family == AF_INET)
{
// llarp::LogInfo("scanning ", i->ifa_name, " af: ",
// std::to_string(i->ifa_addr->sa_family));
llarp::Addr test(*i->ifa_addr);
uint32_t byte = test.getHostLong();
if(test.isTenPrivate(byte))
{
llarp::LogDebug("private interface ", i->ifa_name, " ", test, " found");
result.ten = true;
}
else if(test.isOneSevenPrivate(byte))
{
llarp::LogDebug("private interface ", i->ifa_name, " ", test, " found");
result.oneSeven = true;
}
else if(test.isOneNinePrivate(byte))
{
llarp::LogDebug("private interface ", i->ifa_name, " ", test, " found");
result.oneNine = true;
}
}
i = i->ifa_next;
}
if(ifa)
freeifaddrs(ifa);
return result;
}
namespace llarp
{
bool

@ -251,7 +251,7 @@ llarp_router::try_connect(fs::path rcfile)
}
}
else
llarp::LogError("failed to verify signature of RC", rcfile);
llarp::LogError("failed to verify signature of RC ", rcfile);
}
bool

@ -1,3 +1,4 @@
#include <algorithm>
#include <llarp/service/address.hpp>
namespace llarp
@ -19,7 +20,10 @@ namespace llarp
if(pos == std::string::npos)
return false;
auto sub = str.substr(0, pos);
// make sure it's lowercase
std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower);
;
return Base32Decode(sub, *this);
}
} // namespace service
} // namespace llarp
} // namespace llarp

@ -1,5 +1,6 @@
#include <llarp/handlers/tun.hpp>
#include <llarp/service/context.hpp>
#include <llarp/service/endpoint.hpp>
namespace llarp
{
@ -30,6 +31,81 @@ namespace llarp
}
}
llarp::service::Endpoint *
Context::getFirstEndpoint()
{
if(!m_Endpoints.size())
{
llarp::LogError("No endpoints found");
return nullptr;
}
auto firstEndpoint = m_Endpoints.begin();
auto *uniqueEndpoint = &firstEndpoint->second;
return uniqueEndpoint->get();
}
llarp::handlers::TunEndpoint *
Context::getFirstTun()
{
llarp::service::Endpoint *endpointer = this->getFirstEndpoint();
if(!endpointer)
{
return nullptr;
}
llarp::handlers::TunEndpoint *tunEndpoint =
dynamic_cast< llarp::handlers::TunEndpoint * >(endpointer);
return tunEndpoint;
}
llarp_tun_io *
Context::getRange()
{
llarp::handlers::TunEndpoint *tunEndpoint = this->getFirstTun();
if(!tunEndpoint)
{
llarp::LogError("No tunnel endpoint found");
return nullptr;
}
return &tunEndpoint->tunif;
}
bool
Context::Prefetch(const llarp::service::Address &addr)
{
llarp::handlers::TunEndpoint *tunEndpoint = this->getFirstTun();
if(!tunEndpoint)
{
llarp::LogError("No tunnel endpoint found");
return false;
}
// HiddenServiceAddresslookup *lookup = new
// HiddenServiceEndpoint(tunEndpoint, callback, addr,
// tunEndpoint->GenTXID());
return tunEndpoint->EnsurePathToService(
addr, [](Address addr, void *ctx) {}, 10000);
}
bool
Context::MapAddress(const llarp::service::Address &addr, uint32_t ip)
{
if(!m_Endpoints.size())
{
llarp::LogError("No endpoints found");
return false;
}
auto firstEndpoint = m_Endpoints.begin();
auto *uniqueEndpoint = &firstEndpoint->second;
llarp::service::Endpoint *endpointer = uniqueEndpoint->get();
llarp::handlers::TunEndpoint *tunEndpoint =
dynamic_cast< llarp::handlers::TunEndpoint * >(endpointer);
if(!tunEndpoint)
{
llarp::LogError("No tunnel endpoint found");
return false;
}
return tunEndpoint->MapAddress(addr, ip);
}
bool
Context::AddEndpoint(const Config::section_t &conf)
{

@ -277,6 +277,9 @@ namespace llarp
void
Endpoint::PutLookup(IServiceLookup* lookup, uint64_t txid)
{
// std::unique_ptr< service::IServiceLookup > ptr(lookup);
// m_PendingLookups.insert(std::make_pair(txid, ptr));
// m_PendingLookups[txid] = std::move(ptr);
m_PendingLookups.insert(
std::make_pair(txid, std::unique_ptr< IServiceLookup >(lookup)));
}

@ -174,6 +174,12 @@ namespace llarp
#if defined(__FreeBSD__)
struct FreeBSDJailedThreadPool : public _NetIsolatedPool
{
FreeBSDJailedThreadPool(std::function< bool(void *, bool) > setup,
std::function< void(void *) > run, void *user)
: _NetIsolatedPool(setup, run, user)
{
}
bool
IsolateNetwork()
{

@ -71,7 +71,7 @@ namespace llarp
{
}
void
virtual void
Spawn(size_t workers, const char* name);
void

@ -6,6 +6,32 @@ You can learn more about the high level design of LLARP [here](doc/high-level.tx
And you can read the LLARP protocol specification [here](doc/proto_v0.txt)
## Building
$ sudo apt install build-essential libtool autoconf cmake git
$ git clone --recursive https://github.com/loki-project/lokinet-builder
$ cd lokinet-builder
$ make
## Running
$ ./lokinet
### Development
Please note development builds are likely to be unstable
Build requirements:
* CMake
* ninja
* libsodium >= 1.0.14
* c++ 11 capable C++ compiler (gcc 7.x+, llvm 3.8+)
Building a debug build:
## Building

@ -261,7 +261,8 @@ tuntap_sys_set_ifname(struct device *dev, const char *ifname, size_t len)
{
struct ifreq ifr;
char *newname;
strlcpy(ifr.ifr_name, dev->ifname, IF_NAMESIZE);
//(void)strncpy(ifr.ifr_name, dev->if_name, IF_NAMESIZE);
strlcpy(ifr.ifr_name, dev->if_name, IF_NAMESIZE);
newname = strdup(ifname);
if(newname == NULL)
@ -269,10 +270,10 @@ tuntap_sys_set_ifname(struct device *dev, const char *ifname, size_t len)
tuntap_log(TUNTAP_LOG_ERR, "no memory to set ifname");
return -1;
}
ifr.ifr_data = newname;
if(ioctl(dev->ctrl_sock, SIOCSIFNAME, &ifr) == -1)
{
if (ioctl(dev->ctrl_sock, SIOCSIFNAME, &ifr) == -1)
{
perror(NULL);
free(newname);
tuntap_log(TUNTAP_LOG_ERR, "Can't set interface name");
return -1;

@ -129,7 +129,21 @@ extern "C"
errval = inet_pton(AF_INET, addr, &(baddr4));
if(errval == 1)
{
#ifdef __FreeBSD__
t_tun_in_addr daddr4;
errval = inet_pton(AF_INET, daddr, &(daddr4));
if(errval == 1)
{
return tuntap_sys_set_ipv4_tun(dev, &baddr4, &daddr4, mask);
}
else
{
llarp::LogError("invalid s4dest address: ", addr);
return -1;
}
#else
return tuntap_sys_set_ipv4(dev, &baddr4, mask);
#endif
}
else if(errval == 0)
{

Loading…
Cancel
Save