uint32_t byte ordering type safety

pull/23/head
cathugger 6 years ago
parent aa988a6fa4
commit 4971fae171

@ -108,7 +108,7 @@ extern "C"
llarp_tun_io * llarp_tun_io *
main_router_getRange(struct llarp_main *ptr); 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 bool
main_router_mapAddress(struct llarp_main *ptr, main_router_mapAddress(struct llarp_main *ptr,
const llarp::service::Address &addr, uint32_t ip); const llarp::service::Address &addr, uint32_t ip);

@ -33,7 +33,7 @@ namespace llarp
TickTun(llarp_time_t now); TickTun(llarp_time_t now);
bool bool
MapAddress(const service::Address& remote, uint32_t ip); MapAddress(const service::Address& remote, huint32_t ip);
bool bool
Start(); Start();
@ -91,18 +91,18 @@ namespace llarp
PacketQueue_t m_NetworkToUserPktQueue; PacketQueue_t m_NetworkToUserPktQueue;
/// return true if we have a remote loki address for this ip address /// return true if we have a remote loki address for this ip address
bool bool
HasRemoteForIP(const uint32_t& ipv4) const; HasRemoteForIP(huint32_t ipv4) const;
/// get ip address for service address unconditionally /// get ip address for service address unconditionally
uint32_t huint32_t
ObtainIPForAddr(const service::Address& addr); ObtainIPForAddr(const service::Address& addr);
/// mark this address as active /// mark this address as active
void void
MarkIPActive(uint32_t ip); MarkIPActive(huint32_t ip);
/// mark this address as active forever /// mark this address as active forever
void void
MarkIPActiveForever(uint32_t ip); MarkIPActiveForever(huint32_t ip);
void void
FlushSend(); FlushSend();
@ -120,18 +120,18 @@ namespace llarp
struct dotLokiLookup dll; struct dotLokiLookup dll;
/// maps ip to service address (host byte order) /// 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) /// 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; m_AddrToIP;
/// maps ip address to timestamp last active /// 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) /// our ip address (host byte order)
uint32_t m_OurIP; huint32_t m_OurIP;
/// next ip address to allocate (host byte order) /// next ip address to allocate (host byte order)
uint32_t m_NextIP; huint32_t m_NextIP;
/// highest ip address to allocate /// highest ip address to allocate (host byte order)
uint32_t m_MaxIP; huint32_t m_MaxIP;
}; };
} // namespace handlers } // namespace handlers
} // namespace llarp } // namespace llarp

@ -129,28 +129,28 @@ namespace llarp
return (ip_header*)&buf[0]; return (ip_header*)&buf[0];
} }
inline uint32_t inline huint32_t
src() src()
{ {
return ntohl(Header()->saddr); return huint32_t{ntohl(Header()->saddr)};
} }
inline uint32_t inline huint32_t
dst() dst()
{ {
return ntohl(Header()->daddr); return huint32_t{ntohl(Header()->daddr)};
} }
inline void inline void
src(uint32_t ip) src(huint32_t ip)
{ {
Header()->saddr = htonl(ip); Header()->saddr = htonl(ip.h);
} }
inline void 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) // update ip packet checksum (after packet gets out of network)

@ -49,6 +49,79 @@ struct privatesInUse
struct privatesInUse struct privatesInUse
llarp_getPrivateIfs(); 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 namespace llarp
{ {
struct Addr struct Addr
@ -434,18 +507,30 @@ namespace llarp
return *this; return *this;
} }
uint32_t inline uint32_t
tohl() tohl() const
{ {
return ntohl(addr4()->s_addr); return ntohl(addr4()->s_addr);
} }
uint32_t inline huint32_t
ton() xtohl() const
{
return huint32_t{ntohl(addr4()->s_addr)};
}
inline uint32_t
ton() const
{ {
return addr4()->s_addr; return addr4()->s_addr;
} }
inline nuint32_t
xtonl() const
{
return nuint32_t{addr4()->s_addr};
}
sockaddr* sockaddr*
getSockAddr() getSockAddr()
{ {

@ -1,6 +1,7 @@
#ifndef LLARP_SERVICE_CONTEXT_HPP #ifndef LLARP_SERVICE_CONTEXT_HPP
#define LLARP_SERVICE_CONTEXT_HPP #define LLARP_SERVICE_CONTEXT_HPP
#include <llarp/router.h> #include <llarp/router.h>
#include <llarp/net.hpp>
#include <llarp/service/config.hpp> #include <llarp/service/config.hpp>
#include <llarp/service/endpoint.hpp> #include <llarp/service/endpoint.hpp>
#include <unordered_map> #include <unordered_map>
@ -58,7 +59,7 @@ namespace llarp
/// punch a hole open for DNS to add mappings /// punch a hole open for DNS to add mappings
/// ip is in network order /// ip is in network order
bool bool
MapAddress(const llarp::service::Address &addr, uint32_t ip); MapAddress(const llarp::service::Address &addr, huint32_t ip);
bool bool
MapAddressAll(const llarp::service::Address &addr, MapAddressAll(const llarp::service::Address &addr,

@ -461,7 +461,7 @@ extern "C"
const llarp::service::Address &addr, uint32_t ip) const llarp::service::Address &addr, uint32_t ip)
{ {
auto *endpoint = &ptr->ctx->router->hiddenServiceContext; auto *endpoint = &ptr->ctx->router->hiddenServiceContext;
return endpoint->MapAddress(addr, ip); return endpoint->MapAddress(addr, llarp::huint32_t{ip});
} }
bool bool

@ -69,7 +69,7 @@ namespace llarp
llarp::LogError("cannot map to invalid ip ", ip_str); llarp::LogError("cannot map to invalid ip ", ip_str);
return false; return false;
} }
return MapAddress(addr, ntohl(ip.s_addr)); return MapAddress(addr, huint32_t{ntohl(ip.s_addr)});
} }
if(k == "ifname") if(k == "ifname")
{ {
@ -120,17 +120,20 @@ namespace llarp
/// ip should be in host byte order /// ip should be in host byte order
bool 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); auto itr = m_IPToAddr.find(ip);
if(itr != m_IPToAddr.end()) 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()); itr->second.ToString());
return false; return false;
} }
llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", llarp::LogInfo(Name() + " map ", addr.ToString(), " to ",
inet_ntoa({htonl(ip)})); inet_ntoa({nip.n}));
m_IPToAddr.insert(std::make_pair(ip, addr)); m_IPToAddr.insert(std::make_pair(ip, addr));
m_AddrToIP.insert(std::make_pair(addr, ip)); m_AddrToIP.insert(std::make_pair(addr, ip));
MarkIPActiveForever(ip); MarkIPActiveForever(ip);
@ -175,12 +178,12 @@ namespace llarp
#endif #endif
} }
constexpr uint32_t constexpr huint32_t
netmask_ipv4_bits(uint32_t netmask) netmask_ipv4_bits(uint32_t netmask)
{ {
return (32 - netmask) return (32 - netmask) ? (huint32_t{((uint32_t)1 << (32 - (netmask + 1)))}
? (1 << (32 - (netmask + 1))) | netmask_ipv4_bits(netmask + 1) | netmask_ipv4_bits(netmask + 1))
: 0; : huint32_t{0};
} }
bool bool
@ -239,12 +242,12 @@ namespace llarp
llarp::Addr lAddr(tunif.ifaddr); llarp::Addr lAddr(tunif.ifaddr);
m_OurIP = lAddr.tohl(); m_OurIP = lAddr.xtohl();
m_NextIP = m_OurIP; m_NextIP = m_OurIP;
uint32_t mask = tunif.netmask; auto xmask = netmask_ipv4_bits(tunif.netmask);
uint32_t baseaddr = (m_OurIP & netmask_ipv4_bits(mask)); auto baseaddr = m_OurIP & xmask;
m_MaxIP = htonl(htonl(baseaddr) | ~htonl(netmask_ipv4_bits(mask))); m_MaxIP = baseaddr | ~xmask;
char buf[128] = {0}; char buf[128] = {0};
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", lAddr); llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", lAddr);
@ -305,15 +308,15 @@ namespace llarp
if(itr == m_IPToAddr.end()) if(itr == m_IPToAddr.end())
{ {
llarp::LogWarn(Name(), " has no endpoint for ", llarp::LogWarn(Name(), " has no endpoint for ",
inet_ntoa({htonl(pkt.dst())})); inet_ntoa({xhtonl(pkt.dst()).n}));
return true; return true;
} }
// prepare packet for insertion into network // prepare packet for insertion into network
pkt.UpdateChecksumsOnSrc(); pkt.UpdateChecksumsOnSrc();
// clear addresses // clear addresses
pkt.src(0); pkt.src(huint32_t{0});
pkt.dst(0); pkt.dst(huint32_t{0});
if(!SendToOrQueue(itr->second, pkt.Buffer(), service::eProtocolTraffic)) if(!SendToOrQueue(itr->second, pkt.Buffer(), service::eProtocolTraffic))
{ {
@ -326,9 +329,9 @@ namespace llarp
bool bool
TunEndpoint::ProcessDataMessage(service::ProtocolMessage *msg) TunEndpoint::ProcessDataMessage(service::ProtocolMessage *msg)
{ {
uint32_t themIP = ObtainIPForAddr(msg->sender.Addr()); auto themIP = ObtainIPForAddr(msg->sender.Addr());
uint32_t usIP = m_OurIP; auto usIP = m_OurIP;
auto buf = llarp::Buffer(msg->payload); auto buf = llarp::Buffer(msg->payload);
if(m_NetworkToUserPktQueue.EmplaceIf( if(m_NetworkToUserPktQueue.EmplaceIf(
[buf, themIP, usIP](net::IPv4Packet &pkt) -> bool { [buf, themIP, usIP](net::IPv4Packet &pkt) -> bool {
// do packet info rewrite here // do packet info rewrite here
@ -342,15 +345,16 @@ namespace llarp
})) }))
llarp::LogDebug(Name(), " handle data message ", msg->payload.size(), llarp::LogDebug(Name(), " handle data message ", msg->payload.size(),
" bytes from ", inet_ntoa({htonl(themIP)})); " bytes from ", inet_ntoa({xhtonl(themIP).n}));
return true; return true;
} }
uint32_t huint32_t
TunEndpoint::ObtainIPForAddr(const service::Address &addr) TunEndpoint::ObtainIPForAddr(const service::Address &addr)
{ {
llarp_time_t now = llarp_time_now_ms(); llarp_time_t now = llarp_time_now_ms();
uint32_t nextIP = 0; huint32_t nextIP = {0};
{ {
// previously allocated address // previously allocated address
auto itr = m_AddrToIP.find(addr); auto itr = m_AddrToIP.find(addr);
@ -374,7 +378,7 @@ namespace llarp
m_AddrToIP.insert(std::make_pair(addr, nextIP)); m_AddrToIP.insert(std::make_pair(addr, nextIP));
m_IPToAddr.insert(std::make_pair(nextIP, addr)); m_IPToAddr.insert(std::make_pair(nextIP, addr));
llarp::LogInfo(Name(), " mapped ", addr, " to ", llarp::LogInfo(Name(), " mapped ", addr, " to ",
inet_ntoa({htonl(nextIP)})); inet_ntoa({xhtonl(nextIP).n}));
MarkIPActive(nextIP); MarkIPActive(nextIP);
return nextIP; return nextIP;
} }
@ -383,7 +387,7 @@ namespace llarp
// we are full // we are full
// expire least active ip // expire least active ip
// TODO: prevent DoS // 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 // find oldest entry
auto itr = m_IPActivity.begin(); auto itr = m_IPActivity.begin();
@ -411,19 +415,19 @@ namespace llarp
} }
bool bool
TunEndpoint::HasRemoteForIP(const uint32_t &ip) const TunEndpoint::HasRemoteForIP(huint32_t ip) const
{ {
return m_IPToAddr.find(ip) != m_IPToAddr.end(); return m_IPToAddr.find(ip) != m_IPToAddr.end();
} }
void void
TunEndpoint::MarkIPActive(uint32_t ip) TunEndpoint::MarkIPActive(huint32_t ip)
{ {
m_IPActivity[ip] = std::max(llarp_time_now_ms(), m_IPActivity[ip]); m_IPActivity[ip] = std::max(llarp_time_now_ms(), m_IPActivity[ip]);
} }
void void
TunEndpoint::MarkIPActiveForever(uint32_t ip) TunEndpoint::MarkIPActiveForever(huint32_t ip)
{ {
m_IPActivity[ip] = std::numeric_limits< uint64_t >::max(); m_IPActivity[ip] = std::numeric_limits< uint64_t >::max();
} }

@ -29,11 +29,11 @@ namespace llarp
} }
static uint32_t 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) uint16_t innerlen)
{ {
#define IPCS(x) ((uint32_t)(x & 0xFFFF) + (uint32_t)(x >> 16)) #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); + (uint32_t)htons(innerlen);
#undef IPCS #undef IPCS
return sum; return sum;
@ -58,15 +58,14 @@ namespace llarp
} }
static uint16_t static uint16_t
deltachksum(uint16_t old_sum, uint32_t old_src_ip_h, uint32_t old_dst_ip_h, deltachksum(uint16_t old_sum, huint32_t old_src_ip, huint32_t old_dst_ip,
uint32_t new_src_ip_h, uint32_t new_dst_ip_h) huint32_t new_src_ip, huint32_t new_dst_ip)
{ {
#define ADDIPCS(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) & 0xFFFF) + (uint32_t)((~x) >> 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) uint32_t sum = ntohs(old_sum) + ADDIPCS(old_src_ip) + ADDIPCS(old_dst_ip)
+ ADDIPCS(old_dst_ip_h) + SUBIPCS(new_src_ip_h) + SUBIPCS(new_src_ip) + SUBIPCS(new_dst_ip);
+ SUBIPCS(new_dst_ip_h);
#undef ADDIPCS #undef ADDIPCS
#undef SUBIPCS #undef SUBIPCS
@ -89,8 +88,9 @@ namespace llarp
uint16_t *check = (uint16_t *)(pkt + hlen + 16); uint16_t *check = (uint16_t *)(pkt + hlen + 16);
*check = deltachksum(*check, 0, 0, ntohl(hdr->saddr), *check = deltachksum(*check, huint32_t{0}, huint32_t{0},
ntohl(hdr->daddr)); xntohl(nuint32_t{hdr->saddr}),
xntohl(nuint32_t{hdr->daddr}));
}}, }},
{// UDP {// UDP
17, 17,
@ -103,8 +103,9 @@ namespace llarp
if(*check == 0x0000) if(*check == 0x0000)
return; // don't change zero return; // don't change zero
*check = deltachksum(*check, 0, 0, ntohl(hdr->saddr), *check = deltachksum(*check, huint32_t{0}, huint32_t{0},
ntohl(hdr->daddr)); xntohl(nuint32_t{hdr->saddr}),
xntohl(nuint32_t{hdr->daddr}));
if(*check == 0x0000) if(*check == 0x0000)
*check = 0xFFff; *check = 0xFFff;
} }
@ -119,11 +120,14 @@ namespace llarp
*check = 0; // zero checksum before calculation *check = 0; // zero checksum before calculation
auto cs = ipchksum(pkt + hlen, sz - hlen, auto cs =
ipchksum_pseudoIPv4(0, 0, 17, sz - hlen)); 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), auto mod_cs = deltachksum(cs, huint32_t{0}, huint32_t{0},
ntohl(hdr->daddr)); xntohl(nuint32_t{hdr->saddr}),
xntohl(nuint32_t{hdr->daddr}));
if(cs != 0x0000 && cs != 0xFFff) if(cs != 0x0000 && cs != 0xFFff)
{ {
@ -145,8 +149,9 @@ namespace llarp
auto hdr = Header(); auto hdr = Header();
// IPv4 checksum // IPv4 checksum
hdr->check = hdr->check = deltachksum(hdr->check, huint32_t{0}, huint32_t{0},
deltachksum(hdr->check, 0, 0, ntohl(hdr->saddr), ntohl(hdr->daddr)); xntohl(nuint32_t{hdr->saddr}),
xntohl(nuint32_t{hdr->daddr}));
// L4 checksum // L4 checksum
auto proto = hdr->protocol; auto proto = hdr->protocol;
@ -167,8 +172,9 @@ namespace llarp
uint16_t *check = (uint16_t *)(pkt + hlen + 16); uint16_t *check = (uint16_t *)(pkt + hlen + 16);
*check = deltachksum(*check, ntohl(hdr->saddr), *check = deltachksum(*check, xntohl(nuint32_t{hdr->saddr}),
ntohl(hdr->daddr), 0, 0); xntohl(nuint32_t{hdr->daddr}), huint32_t{0},
huint32_t{0});
}}, }},
{// UDP {// UDP
17, 17,
@ -181,8 +187,9 @@ namespace llarp
if(*check == 0x0000) if(*check == 0x0000)
return; // don't change zero return; // don't change zero
*check = deltachksum(*check, ntohl(hdr->saddr), *check = deltachksum(*check, xntohl(nuint32_t{hdr->saddr}),
ntohl(hdr->daddr), 0, 0); xntohl(nuint32_t{hdr->daddr}),
huint32_t{0}, huint32_t{0});
if(*check == 0x0000) if(*check == 0x0000)
*check = 0xFFff; *check = 0xFFff;
} }
@ -197,12 +204,14 @@ namespace llarp
*check = 0; // zero checksum before calculation *check = 0; // zero checksum before calculation
auto cs = ipchksum(pkt + hlen, sz - hlen, auto cs = ipchksum(
ipchksum_pseudoIPv4(hdr->saddr, hdr->daddr, pkt + hlen, sz - hlen,
17, sz - hlen)); ipchksum_pseudoIPv4(nuint32_t{hdr->saddr},
nuint32_t{hdr->daddr}, 17, sz - hlen));
auto mod_cs = deltachksum(cs, ntohl(hdr->saddr), auto mod_cs = deltachksum(cs, xntohl(nuint32_t{hdr->saddr}),
ntohl(hdr->daddr), 0, 0); xntohl(nuint32_t{hdr->daddr}),
huint32_t{0}, huint32_t{0});
if(cs != 0x0000 && cs != 0xFFff) if(cs != 0x0000 && cs != 0xFFff)
{ {
@ -231,8 +240,9 @@ namespace llarp
} }
// IPv4 // IPv4
hdr->check = hdr->check = deltachksum(hdr->check, xntohl(nuint32_t{hdr->saddr}),
deltachksum(hdr->check, ntohl(hdr->saddr), ntohl(hdr->daddr), 0, 0); xntohl(nuint32_t{hdr->daddr}), huint32_t{0},
huint32_t{0});
} }
} // namespace net } // namespace net
} // namespace llarp } // namespace llarp

@ -115,7 +115,7 @@ namespace llarp
} }
bool 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()) if(!m_Endpoints.size())
{ {
@ -148,7 +148,7 @@ namespace llarp
return false; return false;
} }
return tunEndpoint->MapAddress(context->serviceAddr, return tunEndpoint->MapAddress(context->serviceAddr,
context->localPrivateIpAddr.tohl()); context->localPrivateIpAddr.xtohl());
} }
bool bool

Loading…
Cancel
Save