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 *
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);

@ -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

@ -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)

@ -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()
{

@ -1,6 +1,7 @@
#ifndef LLARP_SERVICE_CONTEXT_HPP
#define LLARP_SERVICE_CONTEXT_HPP
#include <llarp/router.h>
#include <llarp/net.hpp>
#include <llarp/service/config.hpp>
#include <llarp/service/endpoint.hpp>
#include <unordered_map>
@ -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,

@ -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

@ -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();
}

@ -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

@ -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

Loading…
Cancel
Save