diff --git a/include/llarp/dns_dotlokilookup.hpp b/include/llarp/dns_dotlokilookup.hpp index e41378fcb..d864b38f5 100644 --- a/include/llarp/dns_dotlokilookup.hpp +++ b/include/llarp/dns_dotlokilookup.hpp @@ -17,7 +17,9 @@ struct dotLokiLookup { /// for timers (MAYBEFIXME? maybe we decouple this, yes pls have a generic /// passed in) + // we can use DNSc for access to the logic struct llarp_logic *logic; + /// which ip tracker to use struct dns_iptracker *ip_tracker; diff --git a/include/llarp/handlers/tun.hpp b/include/llarp/handlers/tun.hpp index a4cecfea0..47a629570 100644 --- a/include/llarp/handlers/tun.hpp +++ b/include/llarp/handlers/tun.hpp @@ -80,6 +80,10 @@ namespace llarp static void handleTickTun(void* u); + /// get a service address for ip address + service::Address + ObtainAddrForIP(huint32_t ip); + protected: typedef llarp::util::CoDelQueue< net::IPv4Packet, net::IPv4Packet::GetTime, net::IPv4Packet::PutTime, @@ -92,6 +96,7 @@ namespace llarp /// return true if we have a remote loki address for this ip address bool HasRemoteForIP(huint32_t ipv4) const; + /// get ip address for service address unconditionally huint32_t ObtainIPForAddr(const service::Address& addr); diff --git a/include/llarp/net.hpp b/include/llarp/net.hpp index 1c18e59a5..01b0a069d 100644 --- a/include/llarp/net.hpp +++ b/include/llarp/net.hpp @@ -76,7 +76,7 @@ namespace llarp constexpr bool operator <(huint32_t x) const { return h < x.h; } constexpr bool operator ==(huint32_t x) const { return h == x.h; } - + struct Hash { inline size_t @@ -272,7 +272,7 @@ namespace llarp { // network order sockaddr_in6 _addr; - sockaddr_in _addr4; // why do we even have this? + sockaddr_in _addr4; // why do we even have this? favor cpu over memory ~Addr(){}; Addr(){}; diff --git a/llarp/dns_dotlokilookup.cpp b/llarp/dns_dotlokilookup.cpp index 4e33a7984..990edaf48 100644 --- a/llarp/dns_dotlokilookup.cpp +++ b/llarp/dns_dotlokilookup.cpp @@ -43,7 +43,8 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left) if(!dll) { llarp::LogError("DNSd dotLokiLookup is not configured"); - // FIXME: send 404 + write404_dnss_response(qr->from, qr->request); + delete qr; return; } @@ -56,7 +57,7 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left) { llarp::LogWarn("Could not base32 decode address: ", qr->request->question.name); - // FIXME: send 404 + write404_dnss_response(qr->from, qr->request); delete qr; return; } @@ -64,7 +65,9 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left) auto itr = loki_tld_lookup_cache.find(addr.ToString()); if(itr != loki_tld_lookup_cache.end()) { + llarp::LogDebug("Found in .loki lookup cache"); writesend_dnss_response(itr->second->returnThis, qr->from, qr->request); + delete qr; return; } @@ -93,13 +96,16 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left) if(!routerHiddenServiceContext) { llarp::LogWarn("dotLokiLookup user isnt a service::Context: ", dll->user); + write404_dnss_response(qr->from, qr->request); + delete qr; return; } bool mapResult = routerHiddenServiceContext->MapAddressAll( addr, free_private->hostResult); if(!mapResult) { - // FIXME: send 404 + llarp::LogWarn("dotLokiLookup failed to map address"); + write404_dnss_response(qr->from, qr->request); delete qr; return; } @@ -129,22 +135,158 @@ llarp_dotlokilookup_checkQuery(void *u, uint64_t orig, uint64_t left) delete qr; } +std::vector< std::string > +split(std::string str) +{ + size_t pos = 0; + std::string token; + std::string s(str); + std::vector< std::string > tokens; + while((pos = s.find(".")) != std::string::npos) + { + token = s.substr(0, pos); + // llarp::LogInfo("token [", token, "]"); + tokens.push_back(token); + s.erase(0, pos + 1); + } + token = s.substr(0, pos); + tokens.push_back(token); + // llarp::LogInfo("token [", token, "]"); + return tokens; +} + +struct reverse_handler_iter_context +{ + std::string lName; + const struct sockaddr *from; + const struct dnsd_question_request *request; +}; + +bool +ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg) +{ + reverse_handler_iter_context *context = + (reverse_handler_iter_context *)endpointCfg->user; + // llarp::LogInfo("context ", context->request->question.name); + // llarp::LogInfo("Checking ", lName); + llarp::handlers::TunEndpoint *tunEndpoint = + (llarp::handlers::TunEndpoint *)endpointCfg->endpoint; + if(!tunEndpoint) + { + llarp::LogError("No tunnel endpoint found"); + return true; // still continue + } + // llarp::LogInfo("for ", tunEndpoint->tunif.ifaddr); + std::string checkStr(tunEndpoint->tunif.ifaddr); + std::vector< std::string > tokensSearch = split(context->lName); + std::vector< std::string > tokensCheck = split(checkStr); + + // well the tunif is just one ip on a network range... + // support "b._dns-sd._udp.0.0.200.10.in-addr.arpa" + size_t searchTokens = tokensSearch.size(); + std::string searchIp = tokensSearch[searchTokens - 3] + "." + + tokensSearch[searchTokens - 4] + "." + tokensSearch[searchTokens - 5] + + "." + tokensSearch[searchTokens - 6]; + std::string checkIp = tokensCheck[0] + "." + tokensCheck[1] + "." + + tokensCheck[2] + "." + tokensCheck[3]; + llarp::LogDebug(searchIp, " vs ", checkIp); + + llarp::IPRange range = llarp::iprange_ipv4( + stoi(tokensCheck[0]), stoi(tokensCheck[1]), stoi(tokensCheck[2]), + stoi(tokensCheck[3]), tunEndpoint->tunif.netmask); // create range + // hack atm to work around limitations in ipaddr_ipv4_bits and llarp::IPRange + llarp::huint32_t searchIPv4_fixed = llarp::ipaddr_ipv4_bits( + stoi(tokensSearch[searchTokens - 6]), + stoi(tokensSearch[searchTokens - 5]), + stoi(tokensSearch[searchTokens - 4]), + stoi(tokensSearch[searchTokens + - 3])); // create ip (llarp::Addr is untrustworthy atm) + 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) + + // 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(), " = ", + inRange ? "inRange" : "not match"); + + if(inRange) + { + llarp::service::Address addr = + tunEndpoint->ObtainAddrForIP(searchIPv4_fixed); + if(addr.ToString() + == "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy.loki") + { + write404_dnss_response(context->from, + (dnsd_question_request *)context->request); + } + else + { + writesend_dnss_revresponse(addr.ToString(), context->from, + (dnsd_question_request *)context->request); + } + return false; + } + return true; // we don't do anything with the result yet +} + dnsd_query_hook_response * llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from, struct dnsd_question_request *const 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; + 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); + // llarp::LogDebug("Transformed ", lName); - // FIXME: probably should just read the last 5 bytes - if(lName.find(".loki") != std::string::npos) + // 253.0.200.10.in-addr.arpa + if(lName.find(".in-addr.arpa") != std::string::npos) + { + // llarp::LogDebug("Checking ", lName); + 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; + } + // llarp::LogDebug("Starting rev iter for ", lName); + // which range? + // for each tun interface + struct reverse_handler_iter_context context; + context.lName = lName; + context.from = from; + context.request = request; + + struct llarp::service::Context::endpoint_iter i; + i.user = &context; + i.index = 0; + i.visit = &ReverseHandlerIter; + bool res = routerHiddenServiceContext->iterate(i); + if(!res) + { + llarp::LogInfo("Reverse is ours"); + response->dontSendResponse = true; // should have already sent it + } + else + { + llarp::LogInfo("Reverse is not ours"); + } + } + else if((lName.length() > 5 && lName.substr(lName.length() - 5, 5) == ".loki") + || (lName.length() > 6 + && lName.substr(lName.length() - 6, 6) == ".loki.")) { llarp::LogInfo("Detect Loki Lookup for ", lName); auto cache_check = loki_tld_lookup_cache.find(lName); @@ -179,7 +321,7 @@ llarp_dotlokilookup_handler(std::string name, const struct sockaddr *from, llarp_logic_call_later(request->context->client.logic, {2000, qr, &llarp_dotlokilookup_checkQuery}); - response->dontSendResponse = true; + response->dontSendResponse = true; // will send it shortly } return response; } diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index b02b48eae..b42c52525 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -134,6 +134,7 @@ namespace llarp } llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", inet_ntoa({nip.n})); + m_IPToAddr.insert(std::make_pair(ip, addr)); m_AddrToIP.insert(std::make_pair(addr, ip)); MarkIPActiveForever(ip); @@ -351,6 +352,22 @@ namespace llarp return true; } + service::Address + TunEndpoint::ObtainAddrForIP(huint32_t ip) + { + auto itr = m_IPToAddr.find(ip); + 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()); + return addr; + } + // found + return itr->second; + } + huint32_t TunEndpoint::ObtainIPForAddr(const service::Address &addr) { diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index 2d46026d2..0bed35de1 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -64,8 +64,8 @@ namespace llarp while(itr != m_Endpoints.end()) { i.endpoint = itr->second.get(); - i.visit(&i); - + if(!i.visit(&i)) + return false; // advance i.index++; itr++; @@ -136,7 +136,7 @@ namespace llarp } bool - MappAddressAllIter(struct Context::endpoint_iter *endpointCfg) + MapAddressAllIter(struct Context::endpoint_iter *endpointCfg) { Context::mapAddressAll_context *context = (Context::mapAddressAll_context *)endpointCfg->user; @@ -145,7 +145,7 @@ namespace llarp if(!tunEndpoint) { llarp::LogError("No tunnel endpoint found"); - return false; + return true; // still continue } return tunEndpoint->MapAddress(context->serviceAddr, context->localPrivateIpAddr.xtohl()); @@ -162,7 +162,7 @@ namespace llarp struct Context::endpoint_iter i; i.user = &context; i.index = 0; - i.visit = &MappAddressAllIter; + i.visit = &MapAddressAllIter; return this->iterate(i); } diff --git a/test/net_unittest.cpp b/test/net_unittest.cpp index 8e102e6e2..99b7a4ca7 100644 --- a/test/net_unittest.cpp +++ b/test/net_unittest.cpp @@ -5,12 +5,25 @@ struct NetTest : public ::testing::Test { }; -TEST_F(NetTest, TestRangeContains) +TEST_F(NetTest, TestRangeContains8) { ASSERT_TRUE(llarp::iprange_ipv4(10, 0, 0, 0, 8) .Contains(llarp::ipaddr_ipv4_bits(10, 40, 11, 6))); } +TEST_F(NetTest, TestRangeContains24) +{ + ASSERT_TRUE(llarp::iprange_ipv4(10, 200, 0, 1, 24) + .Contains(llarp::ipaddr_ipv4_bits(10, 200, 0, 253))); +} + +TEST_F(NetTest, TestRangeContainsFail) +{ + ASSERT_TRUE(!llarp::iprange_ipv4(192, 168, 0, 1, 24) + .Contains(llarp::ipaddr_ipv4_bits(10, 200, 0, 253))); +} + + TEST_F(NetTest, TestIPv4Netmask) { ASSERT_TRUE(llarp::xhtonl(llarp::netmask_ipv4_bits(8))