Merge remote-tracking branch 'ryan/master'

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

@ -236,6 +236,9 @@ set(LIB_PLATFORM_SRC
llarp/mem.cpp
# for networking
llarp/ev.cpp
llarp/net.cpp
llarp/net_addr.cpp
llarp/net_inaddr.cpp
# for timer
llarp/time.cpp
# for logic
@ -408,7 +411,6 @@ set(LIB_SRC
llarp/ip.cpp
llarp/link_intro.cpp
llarp/link_message.cpp
llarp/net.cpp
llarp/nodedb.cpp
llarp/path.cpp
llarp/pathbuilder.cpp
@ -490,6 +492,9 @@ set(CLIENT_SRC
include_directories(include)
# TODO: exclude this from includes and expose stuff properly for rcutil
include_directories(llarp)
#include_directories(include)
#include_directories(vendor/cppbackport-master/lib)
#include_directories(${sodium_INCLUDE_DIR})
set(RC_EXE rcutil)
set(DNS_EXE dns)

@ -71,7 +71,6 @@ release-configure: clean
mkdir -p '$(BUILD_ROOT)'
$(CONFIG_CMD) -DSTATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release -DRELEASE_MOTTO="$(shell cat motto.txt)" -DCMAKE_C_COMPILER=$(CC) -DCMAKE_CXX_COMPILER=$(CXX) -DCMAKE_ASM_FLAGS='$(ASFLAGS)' -DCMAKE_C_FLAGS='$(CFLAGS)' -DCMAKE_CXX_FLAGS='$(CXXFLAGS)'
debug: debug-configure
$(MAKE) -C $(BUILD_ROOT)
cp $(EXE) lokinet
@ -157,3 +156,13 @@ install:
rm -f $(PREFIX)/bin/lokinet-bootstrap
cp $(REPO)/lokinet-bootstrap $(PREFIX)/bin/lokinet-bootstrap
chmod 755 $(PREFIX)/bin/lokinet-bootstrap
setcap cap_net_admin=+eip $(PREFIX)/bin/lokinet
fuzz-configure: clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Fuzz -DCMAKE_C_COMPILER=afl-gcc -DCMAKE_CXX_COMPILER=afl-g++
fuzz-build: fuzz-configure
ninja
fuzz: fuzz-build
$(EXE)

@ -11,7 +11,7 @@
#include <sys/socket.h>
#endif
#include <llarp/net.hpp> // for llarp::Addr
#include <llarp/net.hpp> // for llarp::Addr , llarp::huint32_t
struct dnsd_context;
@ -85,7 +85,7 @@ struct dns_packet
};
std::string
getDNSstring(const char *buffer);
getDNSstring(const char *const buffer, uint32_t *pos);
void
code_domain(char *&buffer, const std::string &domain) throw();
@ -102,10 +102,10 @@ extern "C"
decode_hdr(const char *buffer);
dns_msg_question *
decode_question(const char *buffer);
decode_question(const char *buffer, uint32_t *pos);
dns_msg_answer *
decode_answer(const char *buffer);
decode_answer(const char *const buffer, uint32_t *pos);
void
put16bits(char *&buffer, uint16_t value) throw();

@ -11,7 +11,7 @@
// neither, it's a result set row
struct dns_pointer
{
llarp::Addr hostResult;
llarp::huint32_t hostResult;
llarp::service::Address b32addr;
// we could store the timeout at which we expect it to be available
// or a list of pending requests for it
@ -32,16 +32,19 @@ struct dns_iptracker
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;
// make it easier to find a entry
std::vector< std::unique_ptr< dns_pointer > > map;
};
void
dns_iptracker_init();
bool
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll, llarp::Addr tunGatewayIp);
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll,
llarp::huint32_t tunGatewayIp);
bool
dns_iptracker_setup(dns_iptracker *iptracker, llarp::Addr tunGatewayIp);
dns_iptracker_setup(dns_iptracker *iptracker, llarp::huint32_t tunGatewayIp);
struct dns_pointer *
dns_iptracker_get_free();

@ -41,7 +41,7 @@ struct dnsc_answer_request
dnsc_answer_hook_func resolved;
/// result
bool found;
llarp::Addr result;
llarp::huint32_t result;
std::string revDNS;
// a reference to dnsc_context incase of multiple contexts
struct dnsc_context *context;
@ -81,12 +81,14 @@ struct dnsc_context
/// async resolve a hostname using generic socks
void
raw_resolve_host(struct dnsc_context *const dnsc, const char *url,
dnsc_answer_hook_func resolved, void *const user);
dnsc_answer_hook_func resolved, void *const user,
uint16_t type);
/// async resolve a hostname using llarp platform framework
bool
llarp_resolve_host(struct dnsc_context *const dns, const char *url,
dnsc_answer_hook_func resolved, void *const user);
dnsc_answer_hook_func resolved, void *const user,
uint16_t type);
/// cleans up request structure allocations
void

@ -45,7 +45,7 @@ struct dnsd_query_hook_response
/// turn off recursion
bool dontLookUp;
/// potential address
sockaddr *returnThis; // FIXME: llarp::Addr
llarp::huint32_t *returnThis;
};
/// builds and fires a request based based on llarp_udp_io udp event
@ -74,7 +74,7 @@ writecname_dnss_response(std::string cname, const struct sockaddr *from,
/// send an A record found response
void
writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from,
writesend_dnss_response(llarp::huint32_t *hostRes, const struct sockaddr *from,
dnsd_question_request *request);
// FIXME: llarp::Addr

@ -43,6 +43,12 @@ namespace llarp
udp_recv_from(llarp_udp_io* udp, const sockaddr* from, const void* buf,
const ssize_t sz)
{
if(!udp)
{
llarp::LogWarn("no udp set");
return;
}
// maybe chekc from too?
static_cast< ILinkLayer* >(udp->user)->RecvFrom(*from, buf, sz);
}

@ -77,6 +77,17 @@ namespace llarp
constexpr bool operator <(huint32_t x) const { return h < x.h; }
constexpr bool operator ==(huint32_t x) const { return h == x.h; }
friend std::ostream&
operator<<(std::ostream& out, const huint32_t& a)
{
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&a.h, tmp, INET_ADDRSTRLEN))
{
out << tmp;
}
return out;
}
struct Hash
{
inline size_t
@ -107,6 +118,17 @@ namespace llarp
constexpr bool operator <(nuint32_t x) const { return n < x.n; }
constexpr bool operator ==(nuint32_t x) const { return n == x.n; }
friend std::ostream&
operator<<(std::ostream& out, const nuint32_t& a)
{
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&a.n, tmp, INET_ADDRSTRLEN))
{
out << tmp;
}
return out;
}
struct Hash
{
inline size_t
@ -134,6 +156,17 @@ namespace llarp
constexpr bool operator <(huint16_t x) const { return h < x.h; }
constexpr bool operator ==(huint16_t x) const { return h == x.h; }
friend std::ostream&
operator<<(std::ostream& out, const huint16_t& a)
{
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&a.h, tmp, INET_ADDRSTRLEN))
{
out << tmp;
}
return out;
}
struct Hash
{
inline size_t
@ -161,6 +194,17 @@ namespace llarp
constexpr bool operator <(nuint16_t x) const { return n < x.n; }
constexpr bool operator ==(nuint16_t x) const { return n == x.n; }
friend std::ostream&
operator<<(std::ostream& out, const nuint16_t& a)
{
char tmp[INET_ADDRSTRLEN] = {0};
if(inet_ntop(AF_INET, (void*)&a.n, tmp, INET_ADDRSTRLEN))
{
out << tmp;
}
return out;
}
struct Hash
{
inline size_t
@ -210,14 +254,15 @@ namespace llarp
return (addr & netmask_bits) == (ip & netmask_bits);
}
std::string
ToString() const
friend std::ostream&
operator<<(std::ostream& out, const IPRange& a)
{
char strbuf[32] = {0};
char netbuf[32] = {0};
inet_ntop(AF_INET, &addr, strbuf, sizeof(strbuf));
inet_ntop(AF_INET, &netmask_bits, netbuf, sizeof(netbuf));
return std::string(strbuf) + "/" + std::string(netbuf);
inet_ntop(AF_INET, &a.addr, strbuf, sizeof(strbuf));
inet_ntop(AF_INET, &a.netmask_bits, netbuf, sizeof(netbuf));
out << std::string(strbuf) + "/" + std::string(netbuf);
return out;
}
};
@ -268,512 +313,7 @@ namespace llarp
bool
IsBogonRange(const in6_addr& host, const in6_addr& mask);
struct Addr
{
// network order
sockaddr_in6 _addr;
sockaddr_in _addr4; // why do we even have this? favor cpu over memory
~Addr(){};
Addr(){};
Addr(const Addr& other)
{
memcpy(&_addr, &other._addr, sizeof(sockaddr_in6));
memcpy(&_addr4, &other._addr4, sizeof(sockaddr_in));
}
void
port(uint16_t port)
{
if(af() == AF_INET)
{
_addr4.sin_port = htons(port);
}
_addr.sin6_port = htons(port);
}
in6_addr*
addr6()
{
return (in6_addr*)&_addr.sin6_addr.s6_addr[0];
}
in_addr*
addr4()
{
return (in_addr*)&_addr.sin6_addr.s6_addr[12];
}
const in6_addr*
addr6() const
{
return (const in6_addr*)&_addr.sin6_addr.s6_addr[0];
}
const in_addr*
addr4() const
{
return (const in_addr*)&_addr.sin6_addr.s6_addr[12];
}
Addr(const std::string str)
{
this->from_char_array(str.c_str());
}
Addr(const std::string str, const uint16_t p_port)
{
this->from_char_array(str.c_str());
this->port(p_port);
}
Addr(string_view addr_str, string_view port_str)
{
this->from_char_array(llarp::string_view_string(addr_str).c_str());
this->port(std::stoi(llarp::string_view_string(port_str)));
}
bool
from_char_array(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 false;
}
if(res->ai_family == AF_INET6)
{
llarp::LogError("IPv6 address not supported yet", str);
return false;
}
else if(res->ai_family != AF_INET)
{
llarp::LogError("Address family not supported yet", str);
return false;
}
// put it in _addr4
struct in_addr* addr = &_addr4.sin_addr;
if(inet_aton(str, addr) == 0)
{
llarp::LogError("failed to parse ", str);
return false;
}
_addr.sin6_family = res->ai_family;
_addr4.sin_family = res->ai_family;
_addr4.sin_port = 0; // save a call, 0 is 0 no matter how u arrange it
#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);
return true;
}
Addr(const char* str)
{
this->from_char_array(str);
}
bool
from_4int(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 = 0;
#if((__APPLE__ && __MACH__) || __FreeBSD__)
_addr4.sin_len = sizeof(in_addr);
#endif
// FIXME: watch endian
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));
// copy ipv6 SIIT into _addr4
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
return true;
}
Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four)
{
this->from_4int(one, two, three, four);
}
Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four, const uint16_t p_port)
{
this->from_4int(one, two, three, four);
this->port(p_port);
}
Addr(const AddressInfo& other)
{
memcpy(addr6(), other.ip.s6_addr, 16);
_addr.sin6_port = htons(other.port);
if(ipv6_is_siit(other.ip))
{
_addr4.sin_family = AF_INET;
_addr4.sin_port = htons(other.port);
_addr.sin6_family = AF_INET;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
}
else
_addr.sin6_family = AF_INET6;
}
Addr(const sockaddr_in& other)
{
llarp::Zero(&_addr, sizeof(sockaddr_in6));
_addr.sin6_family = AF_INET;
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
uint16_t* port = &_addr.sin6_port;
// SIIT
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
sizeof(in_addr));
addrptr[11] = 0xff;
addrptr[10] = 0xff;
*port = ((sockaddr_in*)(&other))->sin_port;
_addr4.sin_family = AF_INET;
_addr4.sin_port = *port;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
}
Addr(const sockaddr_in6& other)
{
memcpy(addr6(), other.sin6_addr.s6_addr, 16);
_addr.sin6_port = htons(other.sin6_port);
auto ptr = &_addr.sin6_addr.s6_addr[0];
// TODO: detect SIIT better
if(ptr[11] == 0xff && ptr[10] == 0xff && ptr[9] == 0 && ptr[8] == 0
&& ptr[7] == 0 && ptr[6] == 0 && ptr[5] == 0 && ptr[4] == 0
&& ptr[3] == 0 && ptr[2] == 0 && ptr[1] == 0 && ptr[0] == 0)
{
_addr4.sin_family = AF_INET;
_addr4.sin_port = htons(other.sin6_port);
_addr.sin6_family = AF_INET;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
}
else
_addr.sin6_family = AF_INET6;
}
Addr(const sockaddr& other)
{
llarp::Zero(&_addr, sizeof(sockaddr_in6));
_addr.sin6_family = other.sa_family;
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
uint16_t* port = &_addr.sin6_port;
switch(other.sa_family)
{
case AF_INET:
// SIIT
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
sizeof(in_addr));
addrptr[11] = 0xff;
addrptr[10] = 0xff;
*port = ((sockaddr_in*)(&other))->sin_port;
_addr4.sin_family = AF_INET;
_addr4.sin_port = *port;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
break;
case AF_INET6:
memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr.s6_addr,
16);
*port = ((sockaddr_in6*)(&other))->sin6_port;
break;
// TODO : sockaddr_ll
default:
break;
}
}
std::string
ToString() const
{
std::stringstream ss;
ss << (*this);
return std::string(ss.str().c_str());
}
friend std::ostream&
operator<<(std::ostream& out, const Addr& a)
{
char tmp[128] = {0};
const void* ptr = nullptr;
if(a.af() == AF_INET6)
{
out << "[";
ptr = a.addr6();
}
else
{
ptr = a.addr4();
}
if(inet_ntop(a.af(), ptr, tmp, sizeof(tmp)))
{
out << tmp;
if(a.af() == AF_INET6)
out << "]";
}
return out << ":" << a.port();
}
operator const sockaddr*() const
{
if(af() == AF_INET)
return (const sockaddr*)&_addr4;
else
return (const sockaddr*)&_addr;
}
operator sockaddr*() const
{
if(af() == AF_INET)
return (sockaddr*)&_addr4;
else
return (sockaddr*)&_addr;
}
void
CopyInto(sockaddr* other) const
{
void *dst, *src;
in_port_t* ptr;
size_t slen;
switch(af())
{
case AF_INET:
{
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());
other->sa_family = af();
}
int
af() const
{
return _addr.sin6_family;
}
uint16_t
port() const
{
return ntohs(_addr.sin6_port);
}
bool
operator<(const Addr& other) const
{
if(af() == AF_INET && other.af() == AF_INET)
return port() < other.port() || addr4()->s_addr < other.addr4()->s_addr;
else
return port() < other.port() || *addr6() < *other.addr6()
|| af() < other.af();
}
bool
operator==(const Addr& other) const
{
if(af() == AF_INET && other.af() == AF_INET)
return port() == other.port()
&& addr4()->s_addr == other.addr4()->s_addr;
else
return af() == other.af() && memcmp(addr6(), other.addr6(), 16) == 0
&& port() == other.port();
}
Addr&
operator=(const sockaddr& other)
{
llarp::Zero(&_addr, sizeof(sockaddr_in6));
_addr.sin6_family = other.sa_family;
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
uint16_t* port = &_addr.sin6_port;
switch(other.sa_family)
{
case AF_INET:
// SIIT
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
sizeof(in_addr));
addrptr[11] = 0xff;
addrptr[10] = 0xff;
*port = ((sockaddr_in*)(&other))->sin_port;
_addr4.sin_family = AF_INET;
_addr4.sin_port = *port;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
break;
case AF_INET6:
memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr.s6_addr,
16);
*port = ((sockaddr_in6*)(&other))->sin6_port;
break;
// TODO : sockaddr_ll
default:
break;
}
return *this;
}
inline uint32_t
tohl() const
{
return ntohl(addr4()->s_addr);
}
inline huint32_t
xtohl() const
{
return huint32_t{ntohl(addr4()->s_addr)};
}
inline uint32_t
ton() const
{
return addr4()->s_addr;
}
inline nuint32_t
xtonl() const
{
return nuint32_t{addr4()->s_addr};
}
bool
sameAddr(const Addr& other) const
{
return memcmp(addr6(), other.addr6(), 16) == 0;
}
bool
operator!=(const Addr& other) const
{
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;
}
/// return true if our ipv4 address is a bogon
/// TODO: ipv6
bool
IsBogon() const
{
return IsIPv4Bogon(xtohl());
}
socklen_t
SockLen() const
{
if(af() == AF_INET)
return sizeof(sockaddr_in);
else
return sizeof(sockaddr_in6);
}
bool
isPrivate() const
{
return IsBogon();
}
bool
isLoopback() const
{
return (ntohl(addr4()->s_addr)) >> 24 == 127;
}
struct Hash
{
std::size_t
operator()(Addr const& a) const noexcept
{
if(a.af() == AF_INET)
{
return a.port() ^ a.addr4()->s_addr;
}
static const uint8_t empty[16] = {0};
return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port();
}
};
}; // namespace llarp
struct Addr; // fwd declr
bool
AllInterfaces(int af, Addr& addr);
@ -796,4 +336,7 @@ namespace llarp
} // namespace llarp
#include <llarp/net_inaddr.hpp>
#include <llarp/net_addr.hpp>
#endif

@ -0,0 +1,173 @@
#ifndef LLARP_NET_ADDR_HPP
#define LLARP_NET_ADDR_HPP
#include <string>
#include <llarp/net.h>
#include <llarp/address_info.hpp>
#include <llarp/string_view.hpp>
#include <llarp/net.hpp>
namespace llarp
{
// fwd declr
struct huint32_t;
struct nuint32_t;
// real work
struct Addr
{
// network order
sockaddr_in6 _addr;
sockaddr_in _addr4; // why do we even have this? favor cpu over memory
~Addr();
Addr();
Addr(const Addr& other);
void
port(uint16_t port);
in6_addr*
addr6();
in_addr*
addr4();
const in6_addr*
addr6() const;
const in_addr*
addr4() const;
Addr(const std::string str);
Addr(const std::string str, const uint16_t p_port);
Addr(string_view addr_str, string_view port_str);
bool
from_char_array(const char* str);
Addr(const char* str);
bool
from_4int(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four);
Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four);
Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four, const uint16_t p_port);
Addr(const AddressInfo& other);
Addr(const sockaddr_in& other);
Addr(const sockaddr_in6& other);
Addr(const sockaddr& other);
std::string
ToString() const;
friend std::ostream&
operator<<(std::ostream& out, const Addr& a);
operator const sockaddr*() const;
operator sockaddr*() const;
void
CopyInto(sockaddr* other) const;
int
af() const;
uint16_t
port() const;
bool
operator<(const Addr& other) const;
bool
operator==(const Addr& other) const;
Addr&
operator=(const sockaddr& other);
inline uint32_t
tohl() const
{
return ntohl(addr4()->s_addr);
}
inline huint32_t
xtohl() const
{
return huint32_t{ntohl(addr4()->s_addr)};
}
inline uint32_t
ton() const
{
return addr4()->s_addr;
}
inline nuint32_t
xtonl() const
{
return nuint32_t{addr4()->s_addr};
}
bool
sameAddr(const Addr& other) const;
bool
operator!=(const Addr& other) const;
inline uint32_t
getHostLong()
{
in_addr_t addr = this->addr4()->s_addr;
uint32_t byte = ntohl(addr);
return byte;
};
bool
isTenPrivate(uint32_t byte);
bool
isOneSevenPrivate(uint32_t byte);
bool
isOneNinePrivate(uint32_t byte);
/// return true if our ipv4 address is a bogon
/// TODO: ipv6
bool
IsBogon() const;
socklen_t
SockLen() const;
bool
isPrivate() const;
bool
isLoopback() const;
struct Hash
{
std::size_t
operator()(Addr const& a) const noexcept
{
if(a.af() == AF_INET)
{
return a.port() ^ a.addr4()->s_addr;
}
static const uint8_t empty[16] = {0};
return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port();
}
};
}; // end struct
} // namespace llarp
#endif

@ -0,0 +1,81 @@
#ifndef LLARP_NET_INADDR_HPP
#define LLARP_NET_INADDR_HPP
#include <llarp/net.hpp>
namespace llarp
{
/// IPv4 or IPv6 holder
struct inAddr
{
// unsigned char s6_addr[16];
struct in6_addr _addr; // store in network order
/// zero out
void
reset();
/// from char*
bool
from_char_array(const char* str);
/// convert from SIIT to IPv4 Mode
void
fromSIIT();
/// convert from IPv4 Mode to SIIT
void
toSIIT();
/// not IPv4 Mode (an actual IPv6 address)
inline bool
isIPv6Mode() const;
/// IPv4 mode (not SIIT)
bool
isIPv4Mode() const;
/// clear out bytes 5-15 (Last 12 bytes)
/// This is how inet_pton works with IPv4 addresses
void
setIPv4Mode();
/// make debugging/testing easier
void
hexDebug();
//
// IPv4 specific functions
//
/// make ipv4 in_addr struct
in_addr
toIAddr();
/// set an IPv4 addr
void
from4int(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four);
/// set from an net-order uint32_t
void
fromN32(nuint32_t in);
/// set from an host-order uint32_t
void
fromH32(huint32_t in);
/// output as net-order uint32_t
nuint32_t
toN32();
/// output as host-order uint32_t
huint32_t
toH32();
//
// IPv6 specific functions
//
// coming soon
};
} // namespace llarp
#endif

@ -55,6 +55,9 @@ namespace llarp
bool
iterate(struct endpoint_iter &i);
huint32_t
GetIpForAddr(const llarp::service::Address &addr);
/// hint at possible path usage and trigger building early
bool
Prefetch(const llarp::service::Address &addr);

@ -76,6 +76,7 @@ namespace llarp
auto pathset = ctx->impl.router->paths.GetLocalPathSet(pathID);
return pathset && pathset->HandleGotRouterMessage(this);
}
// not relayed
TXOwner owner(From, txid);
if(dht.pendingExploreLookups.HasPendingLookupFrom(owner))
@ -88,12 +89,16 @@ namespace llarp
}
return true;
}
// not explore lookup
if(!dht.pendingRouterLookups.HasPendingLookupFrom(owner))
{
llarp::LogWarn("Unwarrented GRM from ", From, " txid=", txid);
return false;
}
// no pending lookup
llarp::LogInfo("DHT no pending lookup");
if(R.size() == 1)
dht.pendingRouterLookups.Found(owner, R[0].pubkey, {R[0]});
else

@ -2,6 +2,28 @@
#include <llarp/dnsd.hpp> // for llarp_handle_dnsd_recvfrom, dnsc
#include <llarp/logger.hpp>
void
hexDump(const char *buffer, uint16_t size)
{
char hex_buffer[size * 3 + 1];
hex_buffer[size * 3] = 0;
for(unsigned int j = 0; j < size; j++)
sprintf(&hex_buffer[3 * j], "%02X ", buffer[j]);
std::string str(hex_buffer);
llarp::LogInfo("First ", size, " bytes: ", str);
}
void
hexDumpAt(const char *const buffer, uint32_t pos, uint16_t size)
{
char hex_buffer[size * 3 + 1];
hex_buffer[size * 3] = 0;
for(unsigned int j = 0; j < size; j++)
sprintf(&hex_buffer[3 * j], "%02X ", buffer[pos + j]);
std::string str(hex_buffer);
llarp::LogInfo(pos, " ", size, " bytes: ", str);
}
/*
<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
@ -10,25 +32,62 @@
length (including the length octet).
*/
std::string
getDNSstring(const char *buffer)
getDNSstring(const char *const buffer, uint32_t *pos)
{
std::string str = "";
uint8_t length = *buffer++;
std::string str = "";
const char *moveable = buffer;
moveable += *pos;
uint8_t length = *moveable++;
(*pos)++;
if(length == 0xc0)
{
uint8_t cPos = *moveable++;
(*pos)++;
uint32_t cPos32 = cPos;
// llarp::LogInfo("Found reference at ", std::to_string(cPos));
return getDNSstring(buffer, &cPos32);
}
// hexDump(moveable, length);
// hexDump(buffer, length);
// printf("dnsStringLen[%d]\n", length);
// llarp::LogInfo("dnsStringLen ", length);
// llarp::LogInfo("dnsStringLen ", std::to_string(length));
if(!length)
return str;
while(length != 0)
{
// llarp::LogInfo("Reading ", std::to_string(length));
for(int i = 0; i < length; i++)
{
char c = *buffer++;
char c = *moveable++;
(*pos)++;
str.append(1, c);
}
length = *buffer++;
if(*moveable == '\xc0')
{
moveable++;
(*pos)++; // forward one char
uint8_t cPos = *moveable; // read char
uint32_t cPos32 = cPos;
// llarp::LogInfo("Remaining [", str, "] is an reference at ", (int)cPos);
std::string addl = getDNSstring(buffer, &cPos32);
// llarp::LogInfo("Addl str [", addl, "]");
str += "." + addl;
// llarp::LogInfo("Final str [", str, "]");
(*pos)++; // move past reference
return str;
}
length = *moveable++;
(*pos)++;
if(length > 64)
llarp::LogError("bug detected");
// else
// hexDump(buffer, length);
// llarp::LogInfo("NextLen ", std::to_string(length));
if(length != 0)
str.append(1, '.');
}
// llarp::LogInfo("Returning ", str);
return str;
}
@ -113,12 +172,23 @@ extern "C"
}
dns_msg_question *
decode_question(const char *buffer)
decode_question(const char *buffer, uint32_t *pos)
{
// char *start = (char *)buffer;
dns_msg_question *question = new dns_msg_question;
std::string m_qName = getDNSstring(buffer);
buffer += m_qName.length() + 2; // + length byte & ending terminator
// uint32_t start = *pos;
std::string m_qName = getDNSstring(buffer, pos);
llarp::LogDebug("Got question name: ", m_qName);
// llarp::LogInfo("Started at ", std::to_string(start), " ended at: ",
// std::to_string(*pos)); llarp::LogInfo("Advancing question buffer by ",
// std::to_string(*pos)); buffer += (*pos) - start; buffer +=
// m_qName.length() + 2; // + length byte & ending terminator
const char *moveable = buffer;
moveable += *pos; // advance to position
// hexDump(moveable, 4);
// printf("Now0 at [%d]\n", buffer - start);
// buffer += m_qName.size() + 1;
/*
@ -138,15 +208,20 @@ extern "C"
}
*/
question->name = m_qName;
question->type = get16bits(buffer);
question->type = get16bits(moveable);
(*pos) += 2;
// printf("Now1 at [%d]\n", buffer - start);
question->qClass = get16bits(buffer);
question->qClass = get16bits(moveable);
(*pos) += 2;
// printf("Now2 at [%d]\n", buffer - start);
llarp::LogDebug("Type ", std::to_string(question->type), " Class ",
std::to_string(question->qClass));
// hexDump(moveable, 4);
return question;
}
dns_msg_answer *
decode_answer(const char *buffer)
decode_answer(const char *const buffer, uint32_t *pos)
{
dns_msg_answer *answer = new dns_msg_answer;
// skip for now until we can handle compressed labels
@ -162,42 +237,95 @@ extern "C"
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);
// hexDump(buffer, 10);
uint8_t first = *buffer++;
// llarp::LogInfo("decode - first", std::to_string(first));
const char *moveable = buffer;
// llarp::LogDebug("Advancing to pos ", std::to_string(*pos));
moveable += (*pos); // advance to position
// hexDumpAt(buffer, (*pos) - 2, 12);
// hexDump(moveable, 12);
if(*moveable == '\xc0')
{
// hexDump(moveable, 12);
// hexDumpAt(buffer, *pos, 12);
// hexDump(moveable, 2);
moveable++;
(*pos)++;
uint8_t readAt = *moveable;
uint32_t readAt32 = readAt;
// llarp::LogInfo("Ref, skip. Read ", readAt32);
// hexDumpAt(buffer, readAt, 2);
answer->name = getDNSstring(buffer, &readAt32);
moveable++;
(*pos)++;
// hexDump(moveable, 10);
// hexDumpAt(buffer, *pos, 10);
}
else
{
// get DNSString?
llarp::LogWarn("Need to parse string");
}
/*
hexDump(moveable, 10);
uint8_t first = *moveable++; (*pos)++;
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
moveable--; (*pos)--; // rewind buffer one byte
}
answer->type = get16bits(buffer);
*/
// hexDump(moveable, 10);
answer->type = get16bits(moveable);
(*pos) += 2;
llarp::LogDebug("Answer Type: ", answer->type);
// assert(answer->type < 259);
if(answer->type > 259)
{
llarp::LogWarn("Answer type is off the charts");
}
answer->aClass = get16bits(buffer);
answer->ttl = get32bits(buffer);
answer->rdLen = get16bits(buffer);
answer->aClass = get16bits(moveable);
(*pos) += 2;
llarp::LogDebug("Answer Class: ", answer->aClass);
answer->ttl = get32bits(moveable);
(*pos) += 4;
llarp::LogDebug("Answer TTL: ", answer->ttl);
answer->rdLen = get16bits(moveable);
(*pos) += 2;
llarp::LogDebug("Answer rdL: ", answer->rdLen, " at ",
std::to_string(*pos));
// uint32_t cPos = moveable - buffer;
// llarp::LogInfo("pos at ", std::to_string(*pos), " calculated: ",
// std::to_string(cPos));
// hexDump(moveable, answer->rdLen);
// hexDumpAt(buffer, *pos, answer->rdLen);
if(answer->rdLen == 4)
{
answer->rData = new uint8_t[answer->rdLen];
memcpy(answer->rData, buffer, answer->rdLen);
buffer += answer->rdLen; // advance the length
memcpy(answer->rData, moveable, answer->rdLen);
llarp::LogDebug("Read ", std::to_string(answer->rData[0]), ".",
std::to_string(answer->rData[1]), ".",
std::to_string(answer->rData[2]), ".",
std::to_string(answer->rData[3]));
moveable += answer->rdLen;
(*pos) += answer->rdLen; // advance the length
}
else
{
llarp::LogDebug("Got type ", answer->type);
// FIXME: move this out of here, this shouldn't be responsible for decode
switch(answer->type)
{
case 5:
buffer += answer->rdLen; // advance the length
moveable += answer->rdLen;
(*pos) += answer->rdLen; // advance the length
break;
case 6: // type 6 = SOA
{
@ -223,18 +351,51 @@ extern "C"
llarp::LogDebug("expire : ", expire);
llarp::LogDebug("minimum : ", minimum);
*/
moveable += answer->rdLen;
(*pos) += answer->rdLen; // advance the length
}
break;
case 12:
{
std::string revname = getDNSstring((char *)buffer);
std::string revname = getDNSstring(buffer, pos);
llarp::LogInfo("revDNSname: ", revname);
answer->rData = new uint8_t[answer->rdLen + 1];
memcpy(answer->rData, revname.c_str(), answer->rdLen);
moveable += answer->rdLen;
(*pos) += answer->rdLen; // advance the length
}
break;
case 15:
{
uint16_t priority = get16bits(moveable);
(*pos) += 2;
std::string revname = getDNSstring(buffer, pos);
llarp::LogInfo("MX: ", revname, " @ ", priority);
// answer->rData = new uint8_t[revname.length() + 1];
// memcpy(answer->rData, revname.c_str(), answer->rdLen);
answer->rData = (uint8_t *)strdup(revname.c_str());
moveable += answer->rdLen - 2; // advance the length
// llarp::LogInfo("leaving at ", std::to_string(*pos));
// hexDumpAt(buffer, *pos, 5);
// hexDump(moveable, 5);
}
break;
case 16:
{
// hexDump(buffer, 5);
// std::string revname = getDNSstring((char *)buffer);
llarp::LogInfo("TXT: size: ", answer->rdLen);
answer->rData = new uint8_t[answer->rdLen + 1];
memcpy(answer->rData, moveable + 1, answer->rdLen - 1);
answer->rData[answer->rdLen - 1] = 0; // terminate string
moveable += answer->rdLen;
(*pos) += answer->rdLen; // advance the length
}
break;
// type 28 AAAA
default:
buffer += answer->rdLen; // advance the length
moveable += answer->rdLen;
(*pos) += answer->rdLen; // advance the length
llarp::LogWarn("Unknown Type ", answer->type);
break;
}

@ -79,6 +79,50 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
// in_addr ip_address = ((sockaddr_in *)free_private->hostResult)->sin_addr;
llarp::service::Context *routerHiddenServiceContext =
(llarp::service::Context *)dll->user;
if(!routerHiddenServiceContext)
{
llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user);
write404_dnss_response(qr->from, qr->request);
delete qr;
return;
}
llarp::huint32_t *tunIp =
new llarp::huint32_t(routerHiddenServiceContext->GetIpForAddr(addr));
if(!tunIp->h)
{
llarp::LogWarn("dotLokiLookup failed to map address");
write404_dnss_response(qr->from, qr->request);
delete qr;
return;
}
/*
bool mapResult = routerHiddenServiceContext->MapAddressAll(
addr, free_private->hostResult);
if(!mapResult)
{
llarp::LogWarn("dotLokiLookup failed to map address");
write404_dnss_response(qr->from, qr->request);
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;
// llarp::Addr test(*free_private->hostResult.getSockAddr());
// llarp::LogInfo("IP Test: ", test);
// response->returnThis = &free_private->hostResult;
response->returnThis = tunIp;
llarp::LogInfo("Saving ", qr->request->question.name);
loki_tld_lookup_cache[qr->request->question.name] = response;
// we can't delete response now...
/*
llarp::handlers::TunEndpoint *tunEndpoint =
(llarp::handlers::TunEndpoint *)dll->user;
@ -94,8 +138,6 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
return;
}
*/
llarp::service::Context *routerHiddenServiceContext =
(llarp::service::Context *)dll->user;
llarp::huint32_t foundAddr;
if(!routerHiddenServiceContext->FindBestAddressFor(addr, foundAddr))
{
@ -112,12 +154,12 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left)
loki_tld_lookup_cache[addr.ToString()]=response;
*/
// we can't delete response now...
sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = llarp::xhtonl(foundAddr).n;
// sockaddr_in saddr;
// saddr.sin_family = AF_INET;
// saddr.sin_addr.s_addr = llarp::xhtonl(foundAddr).n;
// FIXME: flush cache to disk
// on crash we'll need to bring up all the same IPs we assigned before...
writesend_dnss_response((sockaddr *)&saddr, qr->from, qr->request);
writesend_dnss_response(&foundAddr, qr->from, qr->request);
delete qr;
return;
}
@ -186,21 +228,19 @@ ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg)
stoi(tokensSearch[searchTokens - 6]),
stoi(tokensSearch[searchTokens - 5]),
stoi(tokensSearch[searchTokens - 4]),
stoi(tokensSearch[searchTokens
- 3])); // create ip (llarp::Addr is untrustworthy atm)
stoi(tokensSearch[searchTokens - 3])); // create ip
llarp::huint32_t searchIPv4_search = llarp::ipaddr_ipv4_bits(
stoi(tokensSearch[searchTokens - 3]),
stoi(tokensSearch[searchTokens - 4]),
stoi(tokensSearch[searchTokens - 5]),
stoi(tokensSearch[searchTokens
- 6])); // create ip (llarp::Addr is untrustworthy atm)
stoi(tokensSearch[searchTokens - 6])); // create ip
// bool inRange = range.Contains(searchAddr.xtohl());
bool inRange = range.Contains(searchIPv4_search);
llarp::Addr searchAddr(searchIp);
llarp::Addr checkAddr(checkIp);
llarp::LogDebug(searchAddr, " vs ", range.ToString(), " = ",
llarp::LogDebug(searchAddr, " vs ", range, " = ",
inRange ? "inRange" : "not match");
if(inRange)
@ -214,6 +254,7 @@ ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg)
}
else
{
// llarp::LogInfo("Returning [", addr.ToString(), "]");
writesend_dnss_revresponse(addr.ToString(), context->from,
(dnsd_question_request *)context->request);
}
@ -262,7 +303,7 @@ llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from,
bool res = routerHiddenServiceContext->iterate(i);
if(!res)
{
llarp::LogInfo("Reverse is ours");
llarp::LogDebug("Reverse is ours");
response->dontSendResponse = true; // should have already sent it
}
else
@ -295,6 +336,15 @@ llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from,
}
llarp::LogDebug("Base32 decoded address ", addr);
dotLokiLookup *dll = (dotLokiLookup *)request->context->user;
llarp::service::Context *routerHiddenServiceContext =
(llarp::service::Context *)dll->user;
if(!routerHiddenServiceContext)
{
llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user);
return response;
}
// start path build early (if you're looking it up, you're probably going to
// use it)
// main_router_prefetch(ctx, addr);
@ -303,6 +353,15 @@ llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from,
check_query_simple_request *qr = new check_query_simple_request;
qr->from = from;
qr->request = request;
auto tun = routerHiddenServiceContext->getFirstTun();
if(tun->HasPathToService(addr))
{
llarp_dotlokilookup_checkQuery(qr, 0, 0);
response->dontSendResponse = true; // will send it shortly
return response;
}
// 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});

@ -23,7 +23,8 @@ dns_iptracker_init()
// not sure we want tunGatewayIP... we'll know when we get further
bool
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll, llarp::Addr tunGatewayIp)
dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll,
llarp::huint32_t tunGatewayIp)
{
dll->ip_tracker = &g_dns_iptracker;
return true;
@ -31,12 +32,13 @@ dns_iptracker_setup_dotLokiLookup(dotLokiLookup *dll, llarp::Addr tunGatewayIp)
// FIXME: pass in b32addr of client
bool
dns_iptracker_setup(dns_iptracker *iptracker, llarp::Addr tunGatewayIp)
dns_iptracker_setup(dns_iptracker *iptracker, llarp::huint32_t tunGatewayIp)
{
if(!iptracker)
iptracker = &g_dns_iptracker; // FIXME: god forgive I'm tired
struct in_addr *addr = tunGatewayIp.addr4();
unsigned char *ip = (unsigned char *)&(addr->s_addr);
// struct in_addr *addr = tunGatewayIp.addr4();
// unsigned char *ip = (unsigned char *)&(addr->s_addr);
unsigned char *ip = (unsigned char *)&(tunGatewayIp.h);
llarp::LogInfo("iptracker setup: (", std::to_string(ip[0]), ").[",
std::to_string(ip[1]), '.', std::to_string(ip[2]), "].",
@ -90,7 +92,7 @@ dns_iptracker_allocate_range(std::unique_ptr< ip_range > &range, uint8_t first)
llarp::LogDebug("Allocated ", ip);
// result->hostResult = new sockaddr;
// ip.CopyInto(result->hostResult);
result->hostResult = ip;
result->hostResult = ip.xtohl();
// make an address and place into this sockaddr
range->used[range->left + 2] = result;

@ -93,7 +93,7 @@ build_dns_packet(char *url, uint16_t id, uint16_t reqType)
dns_query *
answer_request_alloc(struct dnsc_context *dnsc, void *sock, const char *url,
dnsc_answer_hook_func resolved, void *user)
dnsc_answer_hook_func resolved, void *user, uint16_t type)
{
std::unique_ptr< dnsc_answer_request > request(new dnsc_answer_request);
if(!request)
@ -121,7 +121,7 @@ answer_request_alloc(struct dnsc_context *dnsc, void *sock, const char *url,
llarp::LogWarn("dnsc request question too long");
return nullptr;
}
request->question.type = strstr(url, "in-addr.arpa") != nullptr ? 12 : 1;
request->question.type = type;
request->question.qClass = 1;
// register our self with the tracker
@ -157,6 +157,7 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
// llarp::LogInfo("got a response, udp user is ", udp->user);
unsigned char *castBuf = (unsigned char *)buf;
char *const castBufc = (char *const)buf;
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
dns_msg_header *hdr = decode_hdr((const char *)castBuf);
@ -228,15 +229,16 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
*/
// FIXME: only handling one atm
uint32_t pos = 12; // just set after header
dns_msg_question *question = nullptr;
for(uint32_t i = 0; i < hdr->qdCount; i++)
{
question = decode_question((const char *)castBuf);
llarp::LogDebug("Read a question");
question = decode_question(castBufc, &pos);
llarp::LogDebug("Read a question, now at ", std::to_string(pos));
// 1 dot: 1 byte for length + length
// 4 bytes for class/type
castBuf += question->name.length() + 1 + 4;
castBuf += 2; // skip answer label
// castBuf += question->name.length() + 1 + 4;
// castBuf += 2; // skip answer label
}
// FIXME: only handling one atm
@ -244,16 +246,18 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
dns_msg_answer *answer = nullptr;
for(uint32_t i = 0; i < hdr->anCount; i++)
{
answer = decode_answer((const char *)castBuf);
// pos = 0; // reset pos
answer = decode_answer(castBufc, &pos);
answers.push_back(answer);
llarp::LogDebug("Read an answer ", answer->type, " for ",
request->question.name);
request->question.name, ", now at ", std::to_string(pos));
// 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;
@ -263,7 +267,9 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
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)
@ -272,16 +278,33 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
// request->question.name);
break;
}
*/
if(pos > sz)
{
llarp::LogWarn("Would read past end of dns packet. for ",
request->question.name);
break;
}
/*
uint8_t first = castBufc[pos];
if(first != 0)
{
llarp::LogInfo("next byte isnt 12, skipping ahead one byte. ",
std::to_string(first));
pos++;
}
*/
}
// handle authority records (usually no answers with these, so we'll just
// stomp) usually NS records tho
for(uint32_t i = 0; i < hdr->nsCount; i++)
{
answer = decode_answer((const char *)castBuf);
// pos = 0; // reset pos
answer = decode_answer(castBufc, &pos);
// answers.push_back(answer);
llarp::LogDebug("Read an authority");
castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
// castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
}
/*
@ -335,6 +358,8 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
answer = answers.front();
}
llarp::LogDebug("qus type ", question->type);
llarp::LogDebug("ans class ", answer->aClass);
llarp::LogDebug("ans type ", answer->type);
llarp::LogDebug("ans ttl ", answer->ttl);
@ -347,6 +372,7 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
llarp::LogInfo("ans2 rdlen ", answer2->rdLen);
*/
llarp::LogDebug("rcode ", std::to_string(rcode));
if(rcode == 2)
{
llarp::LogWarn("nameserver ", upstreamAddr, " returned SERVFAIL:");
@ -369,11 +395,14 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
/* search for and print IPv4 addresses */
// if(dnsQuery->reqType == 0x01)
llarp::LogDebug("request question type: ",
std::to_string(request->question.type));
if(request->question.type == 1)
{
// llarp::LogInfo("DNS server's answer is: (type#=", ATYPE, "):");
llarp::LogDebug("IPv4 address(es) for ", request->question.name, ":");
// llarp::LogDebug("Answer rdLen ", std::to_string(answer->rdLen));
if(answer->rdLen == 4)
{
/*
@ -390,8 +419,19 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
ip[2] = answer->rData[2];
ip[3] = answer->rData[3];
*/
/*
request->result.from_4int(answer->rData[0], answer->rData[1],
answer->rData[2], answer->rData[3]);
*/
// llarp::LogDebug("Passing back IPv4: ",
// std::to_string(answer->rData[3]), ".",
// std::to_string(answer->rData[2]),
// ".", std::to_string(answer->rData[1]), ".",
// std::to_string(answer->rData[0]));
request->result =
llarp::ipaddr_ipv4_bits(answer->rData[3], answer->rData[2],
answer->rData[1], answer->rData[0]);
// llarp::Addr test(request->result);
// llarp::LogDebug(request->result);
@ -415,14 +455,43 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
request->resolved(request);
return;
}
else if(request->question.type == 15)
{
llarp::LogDebug("Resolving MX");
request->found = true;
request->result.h = 99;
request->revDNS = std::string((char *)answer->rData);
delete answer->rData;
request->resolved(request);
return;
}
else if(request->question.type == 16)
{
llarp::LogDebug("Resolving TXT");
request->found = true;
request->revDNS = std::string((char *)answer->rData);
request->resolved(request);
return;
}
else if(request->question.type == 28)
{
llarp::LogDebug("Resolving AAAA");
return;
}
llarp::LogWarn("Unhandled question type ", request->question.type);
}
void
raw_resolve_host(struct dnsc_context *const dnsc, const char *url,
dnsc_answer_hook_func resolved, void *const user)
dnsc_answer_hook_func resolved, void *const user,
uint16_t type)
{
if(strstr(url, "in-addr.arpa") != nullptr)
{
type = 12;
}
dns_query *dns_packet =
answer_request_alloc(dnsc, nullptr, url, resolved, user);
answer_request_alloc(dnsc, nullptr, url, resolved, user, type);
if(!dns_packet)
{
llarp::LogError("Couldn't make dnsc packet");
@ -511,6 +580,10 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *const udp,
const struct sockaddr *saddr, const void *buf,
const ssize_t sz)
{
if(!saddr)
{
llarp::LogWarn("saddr isnt set");
}
unsigned char *castBuf = (unsigned char *)buf;
// auto buffer = llarp::StackBuffer< decltype(castBuf) >(castBuf);
dns_msg_header *hdr = decode_hdr((const char *)castBuf);
@ -534,11 +607,18 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *const udp,
bool
llarp_resolve_host(struct dnsc_context *const dnsc, const char *url,
dnsc_answer_hook_func resolved, void *const user)
dnsc_answer_hook_func resolved, void *const user,
uint16_t type)
{
// FIXME: probably can be stack allocated
/*
if (strstr(url, "in-addr.arpa") != nullptr)
{
type = 12;
}
*/
dns_query *dns_packet =
answer_request_alloc(dnsc, &dnsc->udp, url, resolved, user);
answer_request_alloc(dnsc, &dnsc->udp, url, resolved, user, type);
if(!dns_packet)
{
llarp::LogError("Couldn't make dnsc packet");

@ -188,7 +188,7 @@ writesend_dnss_revresponse(std::string reverse, const struct sockaddr *from,
// FIXME: we need an DNS answer not a sockaddr
// otherwise ttl, type and class can't be relayed correctly
void
writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from,
writesend_dnss_response(llarp::huint32_t *hostRes, const struct sockaddr *from,
dnsd_question_request *request)
{
// llarp::Addr test(*from);
@ -229,7 +229,12 @@ writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from,
put16bits(write_buffer, request->question.qClass);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, 4); // rdLength
// put32bits(write_buffer, xhtonl(*hostRes).n);
put32bits(write_buffer, hostRes->h);
// has to be a string of 4 bytes
/*
struct sockaddr_in *sin = (struct sockaddr_in *)hostRes;
unsigned char *ip = (unsigned char *)&sin->sin_addr.s_addr;
@ -241,6 +246,95 @@ writesend_dnss_response(struct sockaddr *hostRes, const struct sockaddr *from,
*write_buffer++ = ip[1];
*write_buffer++ = ip[2];
*write_buffer++ = ip[3];
*/
uint32_t out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending found, ", 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_mxresponse(uint16_t priority, std::string mx,
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)
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
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);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, 2 + (mx.size() + 2)); // rdLength
put16bits(write_buffer, priority); // priority
code_domain(write_buffer, mx); //
uint32_t out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending found, ", 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_txtresponse(std::string txt, 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)
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
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);
put32bits(write_buffer, 1); // ttl
put16bits(write_buffer, txt.size() + 2); // rdLength
*write_buffer = txt.size(); // write size
write_buffer++;
code_domain(write_buffer, txt); //
uint32_t out_bytes = write_buffer - bufferBegin;
llarp::LogDebug("Sending found, ", out_bytes, " bytes");
@ -265,11 +359,27 @@ handle_dnsc_result(dnsc_answer_request *client_request)
writesend_dnss_revresponse(client_request->revDNS, server_request->from,
server_request);
}
else if(client_request->question.type == 15)
{
writesend_dnss_mxresponse(client_request->result.h, client_request->revDNS,
server_request->from, server_request);
}
else if(client_request->question.type == 16)
{
llarp::LogInfo("Writing TXT ", client_request->revDNS);
writesend_dnss_txtresponse(client_request->revDNS, server_request->from,
server_request);
}
else
{
struct sockaddr *useHostRes = nullptr;
if(client_request->question.type != 1)
{
llarp::LogInfo("Returning type ", client_request->question.type,
" as standard");
}
llarp::huint32_t *useHostRes = nullptr;
if(client_request->found)
useHostRes = client_request->result;
useHostRes = &client_request->result;
writesend_dnss_response(useHostRes, server_request->from, server_request);
}
llarp_host_resolved(client_request);
@ -384,13 +494,15 @@ handle_recvfrom(const char *buffer, ssize_t nbytes, const struct sockaddr *from,
{
// make async request
llarp_resolve_host(&request->context->client, m_qName.c_str(),
&handle_dnsc_result, (void *)request);
&handle_dnsc_result, (void *)request,
request->question.type);
}
else
{
// make raw/sync request
raw_resolve_host(&request->context->client, m_qName.c_str(),
&handle_dnsc_result, (void *)request);
&handle_dnsc_result, (void *)request,
request->question.type);
}
}

@ -173,7 +173,14 @@ namespace llarp
return -1;
}
if(ret > sz)
{
llarp::LogWarn("ret > sz");
return -1;
}
if(!addr)
{
llarp::LogWarn("no source addr");
}
// Addr is the source
udp->recvfrom(udp, addr, buf, ret);
return 0;

@ -51,7 +51,7 @@ namespace llarp
if(pos == std::string::npos)
{
llarp::LogError("Cannot map address ", v,
" invalid format, expects "
" invalid format, missing colon (:), expects "
"address.loki:ip.address.goes.here");
return false;
}
@ -105,31 +105,29 @@ namespace llarp
strncpy(tunif.ifaddr, addr.c_str(), sizeof(tunif.ifaddr) - 1);
// set up address in dotLokiLookup
llarp::Addr tunIp(tunif.ifaddr);
// llarp::Addr tunIp(tunif.ifaddr);
llarp::huint32_t tunIpV4;
tunIpV4.h = inet_addr(tunif.ifaddr);
// related to dns_iptracker_setup_dotLokiLookup(&this->dll, tunIp);
dns_iptracker_setup(this->dll.ip_tracker,
tunIp); // claim GW IP to make sure it's not inuse
dns_iptracker_setup(
this->dll.ip_tracker,
tunIpV4); // 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, huint32_t ip)
{
nuint32_t nip = xhtonl(ip);
auto itr = m_IPToAddr.find(ip);
if(itr != m_IPToAddr.end())
{
// XXX is calling inet_ntoa safe in this context? it's MP-unsafe
llarp::LogWarn(inet_ntoa({nip.n}), " already mapped to ",
itr->second.ToString());
llarp::LogWarn(ip, " already mapped to ", itr->second.ToString());
return false;
}
llarp::LogInfo(Name() + " map ", addr.ToString(), " to ",
inet_ntoa({nip.n}));
llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", ip);
m_IPToAddr.insert(std::make_pair(ip, addr));
m_AddrToIP.insert(std::make_pair(addr, ip));
@ -149,11 +147,13 @@ namespace llarp
if(!NetworkIsIsolated())
{
llarp::LogInfo("Setting up global DNS IP tracker");
llarp::Addr tunIp(tunif.ifaddr);
llarp::huint32_t tunIpV4;
tunIpV4.h = inet_addr(tunif.ifaddr);
dns_iptracker_setup_dotLokiLookup(
&this->dll, tunIp); // just set ups dll to use global iptracker
dns_iptracker_setup(this->dll.ip_tracker,
tunIp); // claim GW IP to make sure it's not inuse
&this->dll, tunIpV4); // just set ups dll to use global iptracker
dns_iptracker_setup(
this->dll.ip_tracker,
tunIpV4); // claim GW IP to make sure it's not inuse
// set up networking in currrent thread if we are not isolated
if(!SetupNetworking())
@ -162,12 +162,15 @@ namespace llarp
else
{
llarp::LogInfo("Setting up per netns DNS IP tracker");
llarp::huint32_t tunIpV4;
tunIpV4.h = inet_addr(tunif.ifaddr);
llarp::Addr tunIp(tunif.ifaddr);
this->dll.ip_tracker = new dns_iptracker;
dns_iptracker_setup_dotLokiLookup(
&this->dll, tunIp); // just set ups dll to use global iptracker
dns_iptracker_setup(this->dll.ip_tracker,
tunIp); // claim GW IP to make sure it's not inuse
&this->dll, tunIpV4); // just set ups dll to use global iptracker
dns_iptracker_setup(
this->dll.ip_tracker,
tunIpV4); // claim GW IP to make sure it's not inuse
}
// wait for result for network setup
llarp::LogInfo("waiting for tun interface...");
@ -237,11 +240,9 @@ namespace llarp
auto baseaddr = m_OurIP & xmask;
m_MaxIP = baseaddr | ~xmask;
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)));
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP);
return true;
}
@ -298,8 +299,7 @@ namespace llarp
auto itr = m_IPToAddr.find(pkt.dst());
if(itr == m_IPToAddr.end())
{
llarp::LogWarn(Name(), " has no endpoint for ",
inet_ntoa({xhtonl(pkt.dst()).n}));
llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst());
return true;
}
@ -318,9 +318,11 @@ namespace llarp
bool
TunEndpoint::ProcessDataMessage(service::ProtocolMessage *msg)
{
// llarp::LogInfo("got packet from ", msg->sender.Addr());
auto themIP = ObtainIPForAddr(msg->sender.Addr());
auto usIP = m_OurIP;
auto buf = llarp::Buffer(msg->payload);
// llarp::LogInfo("themIP ", themIP);
auto usIP = m_OurIP;
auto buf = llarp::Buffer(msg->payload);
if(m_NetworkToUserPktQueue.EmplaceIf(
[buf, themIP, usIP](net::IPv4Packet &pkt) -> bool {
// load
@ -346,7 +348,7 @@ namespace llarp
}))
llarp::LogDebug(Name(), " handle data message ", msg->payload.size(),
" bytes from ", inet_ntoa({xhtonl(themIP).n}));
" bytes from ", themIP);
return true;
}
@ -357,9 +359,8 @@ namespace llarp
if(itr == m_IPToAddr.end())
{
// not found
// llarp::Addr test(ip); // "/", test,
service::Address addr;
llarp::LogWarn(" not found in tun map. Sending ", addr.ToString());
llarp::LogWarn(ip, " not found in tun map. Sending ", addr.ToString());
return addr;
}
// found
@ -394,8 +395,7 @@ namespace llarp
{
m_AddrToIP.insert(std::make_pair(addr, nextIP));
m_IPToAddr.insert(std::make_pair(nextIP, addr));
llarp::LogInfo(Name(), " mapped ", addr, " to ",
inet_ntoa({xhtonl(nextIP).n}));
llarp::LogInfo(Name(), " mapped ", addr, " to ", nextIP);
MarkIPActive(nextIP);
return nextIP;
}

@ -94,6 +94,11 @@ namespace llarp
bool
InboundMessageParser::ProcessFrom(ILinkSession* src, llarp_buffer_t buf)
{
if(!src)
{
llarp::LogWarn("no link session");
return false;
}
reader.user = this;
reader.on_key = &OnKey;
from = src;

@ -11,6 +11,9 @@
#include <cstdio>
#include "logger.hpp"
//#include <llarp/net_inaddr.hpp>
#include <llarp/net_addr.hpp>
bool
operator==(const sockaddr& a, const sockaddr& b)
{

@ -0,0 +1,486 @@
#include <llarp/net_addr.hpp>
#include <llarp/net.hpp>
#include <llarp/string_view.hpp>
// for addrinfo
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#define inet_aton(x, y) inet_pton(AF_INET, x, y)
#endif
llarp::Addr::operator const sockaddr*() const
{
if(af() == AF_INET)
return (const sockaddr*)&_addr4;
else
return (const sockaddr*)&_addr;
}
llarp::Addr::operator sockaddr*() const
{
if(af() == AF_INET)
return (sockaddr*)&_addr4;
else
return (sockaddr*)&_addr;
}
bool
llarp::Addr::operator<(const Addr& other) const
{
if(af() == AF_INET && other.af() == AF_INET)
return port() < other.port() || addr4()->s_addr < other.addr4()->s_addr;
else
return port() < other.port() || *addr6() < *other.addr6()
|| af() < other.af();
}
bool
llarp::Addr::operator==(const Addr& other) const
{
if(af() == AF_INET && other.af() == AF_INET)
return port() == other.port() && addr4()->s_addr == other.addr4()->s_addr;
else
return af() == other.af() && memcmp(addr6(), other.addr6(), 16) == 0
&& port() == other.port();
}
namespace llarp
{
Addr::Addr(){};
Addr::~Addr(){};
Addr::Addr(const Addr& other)
{
memcpy(&_addr, &other._addr, sizeof(sockaddr_in6));
memcpy(&_addr4, &other._addr4, sizeof(sockaddr_in));
}
void
Addr::port(uint16_t port)
{
if(af() == AF_INET)
{
_addr4.sin_port = htons(port);
}
_addr.sin6_port = htons(port);
}
in6_addr*
Addr::addr6()
{
return (in6_addr*)&_addr.sin6_addr.s6_addr[0];
}
in_addr*
Addr::addr4()
{
return (in_addr*)&_addr.sin6_addr.s6_addr[12];
}
const in6_addr*
Addr::addr6() const
{
return (const in6_addr*)&_addr.sin6_addr.s6_addr[0];
}
const in_addr*
Addr::addr4() const
{
return (const in_addr*)&_addr.sin6_addr.s6_addr[12];
}
Addr::Addr(const std::string str)
{
this->from_char_array(str.c_str());
}
Addr::Addr(const std::string str, const uint16_t p_port)
{
this->from_char_array(str.c_str());
this->port(p_port);
}
Addr::Addr(string_view addr_str, string_view port_str)
{
this->from_char_array(llarp::string_view_string(addr_str).c_str());
this->port(std::stoi(llarp::string_view_string(port_str)));
}
bool
Addr::from_char_array(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 false;
}
if(res->ai_family == AF_INET6)
{
llarp::LogError("IPv6 address not supported yet", str);
return false;
}
else if(res->ai_family != AF_INET)
{
llarp::LogError("Address family not supported yet", str);
return false;
}
// put it in _addr4
struct in_addr* addr = &_addr4.sin_addr;
if(inet_aton(str, addr) == 0)
{
llarp::LogError("failed to parse ", str);
return false;
}
_addr.sin6_family = res->ai_family;
_addr4.sin_family = res->ai_family;
_addr4.sin_port = 0; // save a call, 0 is 0 no matter how u arrange it
#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);
return true;
}
Addr::Addr(const char* str)
{
this->from_char_array(str);
}
bool
Addr::from_4int(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 = 0;
#if((__APPLE__ && __MACH__) || __FreeBSD__)
_addr4.sin_len = sizeof(in_addr);
#endif
// FIXME: watch endian
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));
// copy ipv6 SIIT into _addr4
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
return true;
}
Addr::Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four)
{
this->from_4int(one, two, three, four);
}
Addr::Addr(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four, const uint16_t p_port)
{
this->from_4int(one, two, three, four);
this->port(p_port);
}
Addr::Addr(const AddressInfo& other)
{
memcpy(addr6(), other.ip.s6_addr, 16);
_addr.sin6_port = htons(other.port);
if(ipv6_is_siit(other.ip))
{
_addr4.sin_family = AF_INET;
_addr4.sin_port = htons(other.port);
_addr.sin6_family = AF_INET;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
}
else
_addr.sin6_family = AF_INET6;
}
Addr::Addr(const sockaddr_in& other)
{
llarp::Zero(&_addr, sizeof(sockaddr_in6));
_addr.sin6_family = AF_INET;
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
uint16_t* port = &_addr.sin6_port;
// SIIT
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
sizeof(in_addr));
addrptr[11] = 0xff;
addrptr[10] = 0xff;
*port = ((sockaddr_in*)(&other))->sin_port;
_addr4.sin_family = AF_INET;
_addr4.sin_port = *port;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
}
Addr::Addr(const sockaddr_in6& other)
{
memcpy(addr6(), other.sin6_addr.s6_addr, 16);
_addr.sin6_port = htons(other.sin6_port);
auto ptr = &_addr.sin6_addr.s6_addr[0];
// TODO: detect SIIT better
if(ptr[11] == 0xff && ptr[10] == 0xff && ptr[9] == 0 && ptr[8] == 0
&& ptr[7] == 0 && ptr[6] == 0 && ptr[5] == 0 && ptr[4] == 0
&& ptr[3] == 0 && ptr[2] == 0 && ptr[1] == 0 && ptr[0] == 0)
{
_addr4.sin_family = AF_INET;
_addr4.sin_port = htons(other.sin6_port);
_addr.sin6_family = AF_INET;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
}
else
_addr.sin6_family = AF_INET6;
}
Addr::Addr(const sockaddr& other)
{
llarp::Zero(&_addr, sizeof(sockaddr_in6));
_addr.sin6_family = other.sa_family;
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
uint16_t* port = &_addr.sin6_port;
switch(other.sa_family)
{
case AF_INET:
// SIIT
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
sizeof(in_addr));
addrptr[11] = 0xff;
addrptr[10] = 0xff;
*port = ((sockaddr_in*)(&other))->sin_port;
_addr4.sin_family = AF_INET;
_addr4.sin_port = *port;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
break;
case AF_INET6:
memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr.s6_addr,
16);
*port = ((sockaddr_in6*)(&other))->sin6_port;
break;
// TODO : sockaddr_ll
default:
break;
}
}
std::string
Addr::ToString() const
{
std::stringstream ss;
ss << (*this);
return std::string(ss.str().c_str());
}
std::ostream&
operator<<(std::ostream& out, const Addr& a)
{
char tmp[128] = {0};
const void* ptr = nullptr;
if(a.af() == AF_INET6)
{
out << "[";
ptr = a.addr6();
}
else
{
ptr = a.addr4();
}
if(inet_ntop(a.af(), (void*)ptr, tmp, sizeof(tmp)))
{
out << tmp;
if(a.af() == AF_INET6)
out << "]";
}
return out << ":" << a.port();
}
void
Addr::CopyInto(sockaddr* other) const
{
void *dst, *src;
in_port_t* ptr;
size_t slen;
switch(af())
{
case AF_INET:
{
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());
other->sa_family = af();
}
int
Addr::af() const
{
return _addr.sin6_family;
}
uint16_t
Addr::port() const
{
return ntohs(_addr.sin6_port);
}
Addr&
Addr::operator=(const sockaddr& other)
{
llarp::Zero(&_addr, sizeof(sockaddr_in6));
_addr.sin6_family = other.sa_family;
uint8_t* addrptr = _addr.sin6_addr.s6_addr;
uint16_t* port = &_addr.sin6_port;
switch(other.sa_family)
{
case AF_INET:
// SIIT
memcpy(12 + addrptr, &((const sockaddr_in*)(&other))->sin_addr,
sizeof(in_addr));
addrptr[11] = 0xff;
addrptr[10] = 0xff;
*port = ((sockaddr_in*)(&other))->sin_port;
_addr4.sin_family = AF_INET;
_addr4.sin_port = *port;
memcpy(&_addr4.sin_addr.s_addr, addr4(), sizeof(in_addr));
break;
case AF_INET6:
memcpy(addrptr, &((const sockaddr_in6*)(&other))->sin6_addr.s6_addr,
16);
*port = ((sockaddr_in6*)(&other))->sin6_port;
break;
// TODO : sockaddr_ll
default:
break;
}
return *this;
}
bool
Addr::sameAddr(const Addr& other) const
{
return memcmp(addr6(), other.addr6(), 16) == 0;
}
bool
Addr::operator!=(const Addr& other) const
{
return !(*this == other);
}
bool
Addr::isTenPrivate(uint32_t byte)
{
uint8_t byte1 = byte >> 24 & 0xff;
return byte1 == 10;
}
bool
Addr::isOneSevenPrivate(uint32_t byte)
{
uint8_t byte1 = byte >> 24 & 0xff;
uint8_t byte2 = (0x00ff0000 & byte) >> 16;
return byte1 == 172 && (byte2 >= 16 || byte2 <= 31);
}
bool
Addr::isOneNinePrivate(uint32_t byte)
{
uint8_t byte1 = byte >> 24 & 0xff;
uint8_t byte2 = (0x00ff0000 & byte) >> 16;
return byte1 == 192 && byte2 == 168;
}
/// return true if our ipv4 address is a bogon
/// TODO: ipv6
bool
Addr::IsBogon() const
{
return IsIPv4Bogon(xtohl());
}
socklen_t
Addr::SockLen() const
{
if(af() == AF_INET)
return sizeof(sockaddr_in);
else
return sizeof(sockaddr_in6);
}
bool
Addr::isPrivate() const
{
return IsBogon();
}
bool
Addr::isLoopback() const
{
return (ntohl(addr4()->s_addr)) >> 24 == 127;
}
struct Hash
{
std::size_t
operator()(Addr const& a) const noexcept
{
if(a.af() == AF_INET)
{
return a.port() ^ a.addr4()->s_addr;
}
static const uint8_t empty[16] = {0};
return (a.af() + memcmp(a.addr6(), empty, 16)) ^ a.port();
}
}; // end struct Hash
} // namespace llarp

@ -0,0 +1,230 @@
#include <llarp/net_inaddr.hpp>
std::ostream&
operator<<(std::ostream& out, const llarp::inAddr& a)
{
char tmp[128] = {0};
if(a.isIPv6Mode())
{
out << "[";
}
if(inet_ntop(a.isIPv4Mode() ? AF_INET : AF_INET6, (void*)&a._addr, tmp,
sizeof(tmp)))
{
out << tmp;
if(a.isIPv6Mode())
out << "]";
}
return out;
}
namespace llarp
{
void
inAddr::reset()
{
llarp::Zero(&this->_addr, sizeof(in6_addr));
}
bool
inAddr::from_char_array(const char* str)
{
this->reset();
// maybe refactor the family detection out
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 false;
}
if(res->ai_family != AF_INET && res->ai_family != AF_INET6)
{
llarp::LogError("Address family not supported yet", str);
return false;
}
// convert detected-family (ipv4 or ipv6) str to in6_addr
/*
if (res->ai_family == AF_INET)
{
freeaddrinfo(res);
// get IPv4
struct in_addr addr; // basically a uint32_t network order
if(inet_aton(str, &addr) == 0)
{
llarp::LogError("failed to parse ", str);
return false;
}
nuint32_t result;
result.n = addr.s_addr;
this->fromN32(result);
return true;
}
*/
ret = inet_pton(res->ai_family, str, &this->_addr);
// inet_pton won't set SIIT
// this->hexDebug();
freeaddrinfo(res);
if(ret <= 0)
{
if(ret == 0)
{
llarp::LogWarn("Not in presentation format");
return false;
}
else
{
llarp::LogWarn("inet_pton failure");
return false;
}
}
return true;
}
void
inAddr::fromSIIT()
{
if(ipv6_is_siit(this->_addr))
{
this->_addr.s6_addr[0] = this->_addr.s6_addr[12];
this->_addr.s6_addr[1] = this->_addr.s6_addr[13];
this->_addr.s6_addr[2] = this->_addr.s6_addr[14];
this->_addr.s6_addr[3] = this->_addr.s6_addr[15];
this->setIPv4Mode();
}
}
void
inAddr::toSIIT()
{
if(!ipv6_is_siit(this->_addr))
{
this->_addr.s6_addr[10] = 0xff;
this->_addr.s6_addr[11] = 0xff;
this->_addr.s6_addr[12] = this->_addr.s6_addr[0];
this->_addr.s6_addr[13] = this->_addr.s6_addr[1];
this->_addr.s6_addr[14] = this->_addr.s6_addr[2];
this->_addr.s6_addr[15] = this->_addr.s6_addr[3];
llarp::Zero(&this->_addr, sizeof(in6_addr) - 6);
}
}
inline bool
inAddr::isIPv6Mode() const
{
return !this->isIPv4Mode();
}
bool
inAddr::isIPv4Mode() const
{
return ipv6_is_siit(this->_addr)
|| (this->_addr.s6_addr[4] == 0 && this->_addr.s6_addr[5] == 0
&& this->_addr.s6_addr[6] == 0 && this->_addr.s6_addr[7] == 0
&& this->_addr.s6_addr[8] == 0 && this->_addr.s6_addr[9] == 0
&& this->_addr.s6_addr[10] == 0 && this->_addr.s6_addr[11] == 0
&& this->_addr.s6_addr[12] == 0 && this->_addr.s6_addr[13] == 0
&& this->_addr.s6_addr[14] == 0 && this->_addr.s6_addr[15] == 0);
}
void
inAddr::setIPv4Mode()
{
// keep first 4
// llarp::Zero(&this->_addr + 4, sizeof(in6_addr) - 4);
this->_addr.s6_addr[4] = 0;
this->_addr.s6_addr[5] = 0;
this->_addr.s6_addr[6] = 0;
this->_addr.s6_addr[7] = 0;
this->_addr.s6_addr[8] = 0;
this->_addr.s6_addr[9] = 0;
this->_addr.s6_addr[10] = 0;
this->_addr.s6_addr[11] = 0;
this->_addr.s6_addr[12] = 0;
this->_addr.s6_addr[13] = 0;
this->_addr.s6_addr[14] = 0;
this->_addr.s6_addr[15] = 0;
}
void
inAddr::hexDebug()
{
char hex_buffer[16 * 3 + 1];
hex_buffer[16 * 3] = 0;
for(unsigned int j = 0; j < 16; j++)
sprintf(&hex_buffer[3 * j], "%02X ", this->_addr.s6_addr[j]);
printf("in6_addr: [%s]\n", hex_buffer);
}
//
// IPv4 specific functions
//
in_addr
inAddr::toIAddr()
{
in_addr res;
res.s_addr = toN32().n;
return res;
}
void
inAddr::from4int(const uint8_t one, const uint8_t two, const uint8_t three,
const uint8_t four)
{
this->reset();
this->setIPv4Mode();
// Network byte order
this->_addr.s6_addr[0] = one;
this->_addr.s6_addr[1] = two;
this->_addr.s6_addr[2] = three;
this->_addr.s6_addr[3] = four;
}
void
inAddr::fromN32(nuint32_t in)
{
this->reset();
this->setIPv4Mode();
memcpy(&this->_addr, &in.n, sizeof(uint32_t));
}
void
inAddr::fromH32(huint32_t in)
{
this->fromN32(xhtonl(in));
}
nuint32_t
inAddr::toN32()
{
nuint32_t result;
result.n = 0; // return 0 for IPv6
if(this->isIPv4Mode())
{
memcpy(&result.n, &this->_addr, sizeof(uint32_t));
}
return result;
}
huint32_t
inAddr::toH32()
{
return xntohl(this->toN32());
}
//
// IPv6 specific functions
//
} // namespace llarp

@ -138,6 +138,11 @@ namespace llarp
{
RouterID remote = ctx->path->Upstream();
auto router = ctx->user->router;
if(!router)
{
llarp::LogError("null router");
return;
}
if(!router->SendToOrQueue(remote, &ctx->LRCM))
{
llarp::LogError("failed to send LRCM");

@ -139,8 +139,9 @@ namespace llarp
void
PathSet::AddPath(Path* path)
{
m_Paths.insert(
std::make_pair(std::make_pair(path->Upstream(), path->RXID()), path));
auto upstream = path->Upstream(); // RouterID
auto RXID = path->RXID(); // PathID
m_Paths.insert(std::make_pair(std::make_pair(upstream, RXID), path));
}
void

@ -138,6 +138,20 @@ namespace llarp
addr, [](Address addr, void *ctx) {}, 10000);
}
huint32_t
Context::GetIpForAddr(const llarp::service::Address &addr)
{
llarp::handlers::TunEndpoint *tunEndpoint = this->getFirstTun();
if(!tunEndpoint)
{
huint32_t zero;
zero.h = 0;
llarp::LogError("No tunnel endpoint found");
return zero;
}
return tunEndpoint->ObtainIPForAddr(addr);
}
bool
Context::MapAddress(const llarp::service::Address &addr, huint32_t ip)
{

@ -1,10 +1,107 @@
#include <gtest/gtest.h>
#include <llarp/net.hpp>
#include <llarp/net_inaddr.hpp>
struct NetTest : public ::testing::Test
{
};
TEST_F(NetTest, TestinAddrFrom4Int)
{
llarp::inAddr test;
test.from4int(127, 0, 0, 1);
char str[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL) {
ASSERT_TRUE(false);
}
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
}
TEST_F(NetTest, TestinAddrFromStr)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
char str[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL) {
ASSERT_TRUE(false);
}
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
}
TEST_F(NetTest, TestinAddrReset)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
test.reset();
char str[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET, &test._addr, str, INET6_ADDRSTRLEN) == NULL) {
ASSERT_TRUE(false);
}
ASSERT_TRUE(strcmp("0.0.0.0", str) == 0);
}
TEST_F(NetTest, TestinAddrModeSet)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
//test.hexDebug();
ASSERT_TRUE(test.isIPv4Mode());
// corrupt it
test._addr.s6_addr[10] = 0xfe;
test._addr.s6_addr[11] = 0xfe;
test.setIPv4Mode();
//test.hexDebug();
ASSERT_TRUE(test.isIPv4Mode());
}
TEST_F(NetTest, TestinAddrSIIT)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
test.toSIIT();
//test.hexDebug();
ASSERT_TRUE(llarp::ipv6_is_siit(test._addr));
test.fromSIIT();
//test.hexDebug();
ASSERT_TRUE(!llarp::ipv6_is_siit(test._addr));
}
TEST_F(NetTest, TestinAddrN32)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
llarp::nuint32_t netOrder = test.toN32();
llarp::inAddr test2;
test2.fromN32(netOrder);
char str[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET, &test2._addr, str, INET6_ADDRSTRLEN) == NULL) {
ASSERT_TRUE(false);
}
//printf("[%s]\n", str);
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
}
TEST_F(NetTest, TestinAddrH32)
{
llarp::inAddr test;
test.from_char_array("127.0.0.1");
llarp::huint32_t netOrder = test.toH32();
llarp::inAddr test2;
test2.fromH32(netOrder);
char str[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET, &test2._addr, str, INET6_ADDRSTRLEN) == NULL) {
ASSERT_TRUE(false);
}
//printf("[%s]\n", str);
ASSERT_TRUE(strcmp("127.0.0.1", str) == 0);
}
TEST_F(NetTest, TestRangeContains8)
{
ASSERT_TRUE(llarp::iprange_ipv4(10, 0, 0, 0, 8)

@ -61,7 +61,8 @@ TEST_F(DNSTest, TestDecodeDNSstring)
{
char *buffer = (char *)this->buf;
buffer += 12; // skip header
std::string res = getDNSstring(buffer);
uint32_t pos = 0;
std::string res = getDNSstring(buffer, &pos);
ASSERT_TRUE(res == "loki.network");
}
@ -125,7 +126,8 @@ TEST_F(DNSTest, TestDecodeQuestion)
{
char *buffer = (char *)this->buf;
buffer += 12; // skip header
dns_msg_question *question = decode_question(buffer);
uint32_t pos = 0;
dns_msg_question *question = decode_question(buffer, &pos);
//printf("name[%s]", question->name.c_str());
//printf("type[%d]", question->type);
//printf("qClass[%d]", question->qClass);
@ -137,19 +139,20 @@ TEST_F(DNSTest, TestDecodeQuestion)
TEST_F(DNSTest, TestDecodeAnswer)
{
char *buffer = (char *)this->buf;
buffer += 12; // skip header
const char * const buffer = (const char * const)this->buf;
uint32_t pos = 12;
std::string url = "loki.network";
buffer += url.length() + 1 + 4;
buffer += 2; // FIXME: skip answer label
dns_msg_answer *answer = decode_answer(buffer);
pos += url.length() + 2 + 4; // skip question (string + 2 shorts)
dns_msg_answer *answer = decode_answer(buffer, &pos);
/*
printf("type[%d]", answer->type);
printf("aClass[%d]", answer->aClass);
printf("ttl[%d]", answer->ttl);
printf("rdLen[%d]", answer->rdLen);
printf("[%zu].[%zu].[%zu].[%zu]", answer->rData[0], answer->rData[1], answer->rData[2], answer->rData[3]);
printf("[%hhu].[%hhu].[%hhu].[%hhu]", answer->rData[0], answer->rData[1], answer->rData[2], answer->rData[3]);
*/
ASSERT_TRUE(answer->name == url);
ASSERT_TRUE(answer->type == 1);
ASSERT_TRUE(answer->aClass == 1);
ASSERT_TRUE(answer->ttl == 2123);

@ -55,8 +55,10 @@ TEST_F(llarpDNSdTest, TestNxDomain)
TEST_F(llarpDNSdTest, TestAResponse)
{
sockaddr hostRes;
llarp::Zero(&hostRes, sizeof(sockaddr));
llarp::huint32_t hostRes;
llarp::Zero(&hostRes.h, sizeof(uint32_t));
//sockaddr hostRes;
//llarp::Zero(&hostRes, sizeof(sockaddr));
writesend_dnss_response(&hostRes, nullptr, &test_request);
ASSERT_TRUE(g_length == 58);
std::string expected_output = "00 00 FFF00 00 01 00 01 00 00 00 00 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 6B 00 00 01 00 01 04 6C 6F 6B 69 07 6E 65 74 77 6F 72 6B 00 00 01 00 01 00 00 00 01 00 04 00 00 00 00 ";

Loading…
Cancel
Save