diff --git a/include/llarp.h b/include/llarp.h index 848f64861..b5e2aa36c 100644 --- a/include/llarp.h +++ b/include/llarp.h @@ -108,7 +108,7 @@ extern "C" llarp_tun_io * main_router_getRange(struct llarp_main *ptr); - /// map an ip to a hidden service address + /// map an (host byte order) ip to a hidden service address bool main_router_mapAddress(struct llarp_main *ptr, const llarp::service::Address &addr, uint32_t ip); diff --git a/include/llarp/handlers/tun.hpp b/include/llarp/handlers/tun.hpp index 270b1d15f..7245c78c1 100644 --- a/include/llarp/handlers/tun.hpp +++ b/include/llarp/handlers/tun.hpp @@ -33,7 +33,7 @@ namespace llarp TickTun(llarp_time_t now); bool - MapAddress(const service::Address& remote, uint32_t ip); + MapAddress(const service::Address& remote, huint32_t ip); bool Start(); @@ -91,18 +91,18 @@ namespace llarp PacketQueue_t m_NetworkToUserPktQueue; /// return true if we have a remote loki address for this ip address bool - HasRemoteForIP(const uint32_t& ipv4) const; + HasRemoteForIP(huint32_t ipv4) const; /// get ip address for service address unconditionally - uint32_t + huint32_t ObtainIPForAddr(const service::Address& addr); /// mark this address as active void - MarkIPActive(uint32_t ip); + MarkIPActive(huint32_t ip); /// mark this address as active forever void - MarkIPActiveForever(uint32_t ip); + MarkIPActiveForever(huint32_t ip); void FlushSend(); @@ -120,18 +120,18 @@ namespace llarp struct dotLokiLookup dll; /// maps ip to service address (host byte order) - std::unordered_map< uint32_t, service::Address > m_IPToAddr; + std::unordered_map< huint32_t, service::Address > m_IPToAddr; /// maps service address to ip (host byte order) - std::unordered_map< service::Address, uint32_t, service::Address::Hash > + std::unordered_map< service::Address, huint32_t, service::Address::Hash > m_AddrToIP; /// maps ip address to timestamp last active - std::unordered_map< uint32_t, llarp_time_t > m_IPActivity; + std::unordered_map< huint32_t, llarp_time_t > m_IPActivity; /// our ip address (host byte order) - uint32_t m_OurIP; + huint32_t m_OurIP; /// next ip address to allocate (host byte order) - uint32_t m_NextIP; - /// highest ip address to allocate - uint32_t m_MaxIP; + huint32_t m_NextIP; + /// highest ip address to allocate (host byte order) + huint32_t m_MaxIP; }; } // namespace handlers } // namespace llarp diff --git a/include/llarp/ip.hpp b/include/llarp/ip.hpp index 2e5fcf3ec..ade2471a0 100644 --- a/include/llarp/ip.hpp +++ b/include/llarp/ip.hpp @@ -129,28 +129,28 @@ namespace llarp return (ip_header*)&buf[0]; } - inline uint32_t + inline huint32_t src() { - return ntohl(Header()->saddr); + return huint32_t{ntohl(Header()->saddr)}; } - inline uint32_t + inline huint32_t dst() { - return ntohl(Header()->daddr); + return huint32_t{ntohl(Header()->daddr)}; } inline void - src(uint32_t ip) + src(huint32_t ip) { - Header()->saddr = htonl(ip); + Header()->saddr = htonl(ip.h); } inline void - dst(uint32_t ip) + dst(huint32_t ip) { - Header()->daddr = htonl(ip); + Header()->daddr = htonl(ip.h); } // update ip packet checksum (after packet gets out of network) diff --git a/include/llarp/net.hpp b/include/llarp/net.hpp index 5a8350a55..8f7392bf9 100644 --- a/include/llarp/net.hpp +++ b/include/llarp/net.hpp @@ -49,6 +49,79 @@ struct privatesInUse struct privatesInUse llarp_getPrivateIfs(); +namespace llarp +{ + struct huint32_t; + struct nuint32_t; + + // clang-format off + + struct huint32_t + { + uint32_t h; + + //inline operator nuint32_t() const { return xhtonl(*this); } + constexpr huint32_t operator &(huint32_t x) const { return huint32_t{h & x.h}; } + constexpr huint32_t operator |(huint32_t x) const { return huint32_t{h | x.h}; } + constexpr huint32_t operator ~() const { return huint32_t{~h}; } + inline huint32_t operator ++() { ++h; return *this; } + inline huint32_t operator --() { --h; return *this; } + constexpr bool operator <(huint32_t x) const { return h < x.h; } + constexpr bool operator ==(huint32_t x) const { return h == x.h; } + }; + + struct nuint32_t + { + uint32_t n; + + //inline operator huint32_t() const { return xntohl(*this); } + constexpr nuint32_t operator &(nuint32_t x) const { return nuint32_t{n & x.n}; } + constexpr nuint32_t operator |(nuint32_t x) const { return nuint32_t{n | x.n}; } + constexpr nuint32_t operator ~() const { return nuint32_t{~n}; } + inline nuint32_t operator ++() { ++n; return *this; } + inline nuint32_t operator --() { --n; return *this; } + constexpr bool operator <(nuint32_t x) const { return n < x.n; } + constexpr bool operator ==(nuint32_t x) const { return n == x.n; } + }; + + // clang-format on + + static inline huint32_t + xntohl(nuint32_t x) + { + return huint32_t{ntohl(x.n)}; + } + + static inline nuint32_t + xhtonl(huint32_t x) + { + return nuint32_t{htonl(x.h)}; + } +} // namespace llarp + +namespace std +{ + template <> + struct hash< llarp::huint32_t > + { + inline size_t + operator()(llarp::huint32_t x) const + { + return hash< uint32_t >{}(x.h); + } + }; + + template <> + struct hash< llarp::nuint32_t > + { + inline size_t + operator()(llarp::nuint32_t x) const + { + return hash< uint32_t >{}(x.n); + } + }; +} // namespace std + namespace llarp { struct Addr @@ -434,18 +507,30 @@ namespace llarp return *this; } - uint32_t - tohl() + inline uint32_t + tohl() const { return ntohl(addr4()->s_addr); } - uint32_t - ton() + 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}; + } + sockaddr* getSockAddr() { diff --git a/include/llarp/service/context.hpp b/include/llarp/service/context.hpp index ac699cdd7..7758c84a8 100644 --- a/include/llarp/service/context.hpp +++ b/include/llarp/service/context.hpp @@ -1,6 +1,7 @@ #ifndef LLARP_SERVICE_CONTEXT_HPP #define LLARP_SERVICE_CONTEXT_HPP #include +#include #include #include #include @@ -58,7 +59,7 @@ namespace llarp /// punch a hole open for DNS to add mappings /// ip is in network order bool - MapAddress(const llarp::service::Address &addr, uint32_t ip); + MapAddress(const llarp::service::Address &addr, huint32_t ip); bool MapAddressAll(const llarp::service::Address &addr, diff --git a/llarp/context.cpp b/llarp/context.cpp index 6ecd6f70e..6882161e8 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -461,7 +461,7 @@ extern "C" const llarp::service::Address &addr, uint32_t ip) { auto *endpoint = &ptr->ctx->router->hiddenServiceContext; - return endpoint->MapAddress(addr, ip); + return endpoint->MapAddress(addr, llarp::huint32_t{ip}); } bool diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 1503a723c..109109ba1 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -69,7 +69,7 @@ namespace llarp llarp::LogError("cannot map to invalid ip ", ip_str); return false; } - return MapAddress(addr, ntohl(ip.s_addr)); + return MapAddress(addr, huint32_t{ntohl(ip.s_addr)}); } if(k == "ifname") { @@ -120,17 +120,20 @@ namespace llarp /// ip should be in host byte order bool - TunEndpoint::MapAddress(const service::Address &addr, uint32_t ip) + 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()) { - llarp::LogWarn(inet_ntoa({ip}), " already mapped to ", + // 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()); return false; } llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", - inet_ntoa({htonl(ip)})); + inet_ntoa({nip.n})); m_IPToAddr.insert(std::make_pair(ip, addr)); m_AddrToIP.insert(std::make_pair(addr, ip)); MarkIPActiveForever(ip); @@ -175,12 +178,12 @@ namespace llarp #endif } - constexpr uint32_t + constexpr huint32_t netmask_ipv4_bits(uint32_t netmask) { - return (32 - netmask) - ? (1 << (32 - (netmask + 1))) | netmask_ipv4_bits(netmask + 1) - : 0; + return (32 - netmask) ? (huint32_t{((uint32_t)1 << (32 - (netmask + 1)))} + | netmask_ipv4_bits(netmask + 1)) + : huint32_t{0}; } bool @@ -239,12 +242,12 @@ namespace llarp llarp::Addr lAddr(tunif.ifaddr); - m_OurIP = lAddr.tohl(); - m_NextIP = m_OurIP; - uint32_t mask = tunif.netmask; + m_OurIP = lAddr.xtohl(); + m_NextIP = m_OurIP; + auto xmask = netmask_ipv4_bits(tunif.netmask); - uint32_t baseaddr = (m_OurIP & netmask_ipv4_bits(mask)); - m_MaxIP = htonl(htonl(baseaddr) | ~htonl(netmask_ipv4_bits(mask))); + auto baseaddr = m_OurIP & xmask; + m_MaxIP = baseaddr | ~xmask; char buf[128] = {0}; llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", lAddr); @@ -305,15 +308,15 @@ namespace llarp if(itr == m_IPToAddr.end()) { llarp::LogWarn(Name(), " has no endpoint for ", - inet_ntoa({htonl(pkt.dst())})); + inet_ntoa({xhtonl(pkt.dst()).n})); return true; } // prepare packet for insertion into network pkt.UpdateChecksumsOnSrc(); // clear addresses - pkt.src(0); - pkt.dst(0); + pkt.src(huint32_t{0}); + pkt.dst(huint32_t{0}); if(!SendToOrQueue(itr->second, pkt.Buffer(), service::eProtocolTraffic)) { @@ -326,9 +329,9 @@ namespace llarp bool TunEndpoint::ProcessDataMessage(service::ProtocolMessage *msg) { - uint32_t themIP = ObtainIPForAddr(msg->sender.Addr()); - uint32_t usIP = m_OurIP; - auto buf = llarp::Buffer(msg->payload); + auto themIP = ObtainIPForAddr(msg->sender.Addr()); + auto usIP = m_OurIP; + auto buf = llarp::Buffer(msg->payload); if(m_NetworkToUserPktQueue.EmplaceIf( [buf, themIP, usIP](net::IPv4Packet &pkt) -> bool { // do packet info rewrite here @@ -342,15 +345,16 @@ namespace llarp })) llarp::LogDebug(Name(), " handle data message ", msg->payload.size(), - " bytes from ", inet_ntoa({htonl(themIP)})); + " bytes from ", inet_ntoa({xhtonl(themIP).n})); return true; } - uint32_t + huint32_t TunEndpoint::ObtainIPForAddr(const service::Address &addr) { llarp_time_t now = llarp_time_now_ms(); - uint32_t nextIP = 0; + huint32_t nextIP = {0}; + { // previously allocated address auto itr = m_AddrToIP.find(addr); @@ -374,7 +378,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({htonl(nextIP)})); + inet_ntoa({xhtonl(nextIP).n})); MarkIPActive(nextIP); return nextIP; } @@ -383,7 +387,7 @@ namespace llarp // we are full // expire least active ip // TODO: prevent DoS - std::pair< uint32_t, llarp_time_t > oldest = {0, 0}; + std::pair< huint32_t, llarp_time_t > oldest = {huint32_t{0}, 0}; // find oldest entry auto itr = m_IPActivity.begin(); @@ -411,19 +415,19 @@ namespace llarp } bool - TunEndpoint::HasRemoteForIP(const uint32_t &ip) const + TunEndpoint::HasRemoteForIP(huint32_t ip) const { return m_IPToAddr.find(ip) != m_IPToAddr.end(); } void - TunEndpoint::MarkIPActive(uint32_t ip) + TunEndpoint::MarkIPActive(huint32_t ip) { m_IPActivity[ip] = std::max(llarp_time_now_ms(), m_IPActivity[ip]); } void - TunEndpoint::MarkIPActiveForever(uint32_t ip) + TunEndpoint::MarkIPActiveForever(huint32_t ip) { m_IPActivity[ip] = std::numeric_limits< uint64_t >::max(); } diff --git a/llarp/ip.cpp b/llarp/ip.cpp index 6472e143e..5f493a64b 100644 --- a/llarp/ip.cpp +++ b/llarp/ip.cpp @@ -29,11 +29,11 @@ namespace llarp } static uint32_t - ipchksum_pseudoIPv4(uint32_t src_ip_n, uint32_t dst_ip_n, uint8_t proto, + ipchksum_pseudoIPv4(nuint32_t src_ip, nuint32_t dst_ip, uint8_t proto, uint16_t innerlen) { #define IPCS(x) ((uint32_t)(x & 0xFFFF) + (uint32_t)(x >> 16)) - uint32_t sum = IPCS(src_ip_n) + IPCS(dst_ip_n) + (uint32_t)proto + uint32_t sum = IPCS(src_ip.n) + IPCS(dst_ip.n) + (uint32_t)proto + (uint32_t)htons(innerlen); #undef IPCS return sum; @@ -58,15 +58,14 @@ namespace llarp } static uint16_t - deltachksum(uint16_t old_sum, uint32_t old_src_ip_h, uint32_t old_dst_ip_h, - uint32_t new_src_ip_h, uint32_t new_dst_ip_h) + deltachksum(uint16_t old_sum, huint32_t old_src_ip, huint32_t old_dst_ip, + huint32_t new_src_ip, huint32_t new_dst_ip) { -#define ADDIPCS(x) ((uint32_t)(x & 0xFFFF) + (uint32_t)(x >> 16)) -#define SUBIPCS(x) ((uint32_t)((~x) & 0xFFFF) + (uint32_t)((~x) >> 16)) +#define ADDIPCS(x) ((uint32_t)(x.h & 0xFFFF) + (uint32_t)(x.h >> 16)) +#define SUBIPCS(x) ((uint32_t)((~x.h) & 0xFFFF) + (uint32_t)((~x.h) >> 16)) - uint32_t sum = ntohs(old_sum) + ADDIPCS(old_src_ip_h) - + ADDIPCS(old_dst_ip_h) + SUBIPCS(new_src_ip_h) - + SUBIPCS(new_dst_ip_h); + uint32_t sum = ntohs(old_sum) + ADDIPCS(old_src_ip) + ADDIPCS(old_dst_ip) + + SUBIPCS(new_src_ip) + SUBIPCS(new_dst_ip); #undef ADDIPCS #undef SUBIPCS @@ -89,8 +88,9 @@ namespace llarp uint16_t *check = (uint16_t *)(pkt + hlen + 16); - *check = deltachksum(*check, 0, 0, ntohl(hdr->saddr), - ntohl(hdr->daddr)); + *check = deltachksum(*check, huint32_t{0}, huint32_t{0}, + xntohl(nuint32_t{hdr->saddr}), + xntohl(nuint32_t{hdr->daddr})); }}, {// UDP 17, @@ -103,8 +103,9 @@ namespace llarp if(*check == 0x0000) return; // don't change zero - *check = deltachksum(*check, 0, 0, ntohl(hdr->saddr), - ntohl(hdr->daddr)); + *check = deltachksum(*check, huint32_t{0}, huint32_t{0}, + xntohl(nuint32_t{hdr->saddr}), + xntohl(nuint32_t{hdr->daddr})); if(*check == 0x0000) *check = 0xFFff; } @@ -119,11 +120,14 @@ namespace llarp *check = 0; // zero checksum before calculation - auto cs = ipchksum(pkt + hlen, sz - hlen, - ipchksum_pseudoIPv4(0, 0, 17, sz - hlen)); + auto cs = + ipchksum(pkt + hlen, sz - hlen, + ipchksum_pseudoIPv4(nuint32_t{0}, nuint32_t{0}, + 17, sz - hlen)); - auto mod_cs = deltachksum(cs, 0, 0, ntohl(hdr->saddr), - ntohl(hdr->daddr)); + auto mod_cs = deltachksum(cs, huint32_t{0}, huint32_t{0}, + xntohl(nuint32_t{hdr->saddr}), + xntohl(nuint32_t{hdr->daddr})); if(cs != 0x0000 && cs != 0xFFff) { @@ -145,8 +149,9 @@ namespace llarp auto hdr = Header(); // IPv4 checksum - hdr->check = - deltachksum(hdr->check, 0, 0, ntohl(hdr->saddr), ntohl(hdr->daddr)); + hdr->check = deltachksum(hdr->check, huint32_t{0}, huint32_t{0}, + xntohl(nuint32_t{hdr->saddr}), + xntohl(nuint32_t{hdr->daddr})); // L4 checksum auto proto = hdr->protocol; @@ -167,8 +172,9 @@ namespace llarp uint16_t *check = (uint16_t *)(pkt + hlen + 16); - *check = deltachksum(*check, ntohl(hdr->saddr), - ntohl(hdr->daddr), 0, 0); + *check = deltachksum(*check, xntohl(nuint32_t{hdr->saddr}), + xntohl(nuint32_t{hdr->daddr}), huint32_t{0}, + huint32_t{0}); }}, {// UDP 17, @@ -181,8 +187,9 @@ namespace llarp if(*check == 0x0000) return; // don't change zero - *check = deltachksum(*check, ntohl(hdr->saddr), - ntohl(hdr->daddr), 0, 0); + *check = deltachksum(*check, xntohl(nuint32_t{hdr->saddr}), + xntohl(nuint32_t{hdr->daddr}), + huint32_t{0}, huint32_t{0}); if(*check == 0x0000) *check = 0xFFff; } @@ -197,12 +204,14 @@ namespace llarp *check = 0; // zero checksum before calculation - auto cs = ipchksum(pkt + hlen, sz - hlen, - ipchksum_pseudoIPv4(hdr->saddr, hdr->daddr, - 17, sz - hlen)); + auto cs = ipchksum( + pkt + hlen, sz - hlen, + ipchksum_pseudoIPv4(nuint32_t{hdr->saddr}, + nuint32_t{hdr->daddr}, 17, sz - hlen)); - auto mod_cs = deltachksum(cs, ntohl(hdr->saddr), - ntohl(hdr->daddr), 0, 0); + auto mod_cs = deltachksum(cs, xntohl(nuint32_t{hdr->saddr}), + xntohl(nuint32_t{hdr->daddr}), + huint32_t{0}, huint32_t{0}); if(cs != 0x0000 && cs != 0xFFff) { @@ -231,8 +240,9 @@ namespace llarp } // IPv4 - hdr->check = - deltachksum(hdr->check, ntohl(hdr->saddr), ntohl(hdr->daddr), 0, 0); + hdr->check = deltachksum(hdr->check, xntohl(nuint32_t{hdr->saddr}), + xntohl(nuint32_t{hdr->daddr}), huint32_t{0}, + huint32_t{0}); } } // namespace net } // namespace llarp diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index c463a9fa1..2d46026d2 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -115,7 +115,7 @@ namespace llarp } bool - Context::MapAddress(const llarp::service::Address &addr, uint32_t ip) + Context::MapAddress(const llarp::service::Address &addr, huint32_t ip) { if(!m_Endpoints.size()) { @@ -148,7 +148,7 @@ namespace llarp return false; } return tunEndpoint->MapAddress(context->serviceAddr, - context->localPrivateIpAddr.tohl()); + context->localPrivateIpAddr.xtohl()); } bool