ip: endianess swaps aren't needed, a bit of renaming and tweaking

Also `make format`.
pull/38/head^2
cathugger 6 years ago committed by Jeff Becker
parent c8f870392f
commit 73e6141023
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -160,11 +160,11 @@ namespace llarp
// update ip packet (after packet gets out of network)
void
UpdatePacketOnDst(huint32_t nSrcIP, huint32_t nDstIP);
UpdateIPv4PacketOnDst(huint32_t newSrcIP, huint32_t newDstIP);
// update ip packet (before packet gets inserted into network)
void
UpdatePacketOnSrc();
UpdateIPv4PacketOnSrc();
};
} // namespace net

@ -570,7 +570,6 @@ struct llarp_ev_loop
{
byte_t readbuf[EV_READ_BUF_SZ] = {0};
llarp_time_t _now = 0;
virtual bool
init() = 0;
virtual int

@ -305,7 +305,7 @@ namespace llarp
// prepare packet for insertion into network
// this includes clearing IP addresses, recalculating checksums, etc
pkt.UpdatePacketOnSrc();
pkt.UpdateIPv4PacketOnSrc();
if(!SendToOrQueue(itr->second, pkt.Buffer(), service::eProtocolTraffic))
{
@ -341,7 +341,7 @@ namespace llarp
return false;
}
// update packet to use proper addresses, recalc checksums
pkt.UpdatePacketOnDst(themIP, usIP);
pkt.UpdateIPv4PacketOnDst(themIP, usIP);
return true;
}))

@ -68,15 +68,16 @@ namespace llarp
}
#endif
static uint16_t
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)
static nuint16_t
deltaIPv4Checksum(nuint16_t old_sum, nuint32_t old_src_ip,
nuint32_t old_dst_ip, nuint32_t new_src_ip,
nuint32_t new_dst_ip)
{
#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))
#define ADDIPCS(x) ((uint32_t)(x.n & 0xFFff) + (uint32_t)(x.n >> 16))
#define SUBIPCS(x) ((uint32_t)((~x.n) & 0xFFff) + (uint32_t)((~x.n) >> 16))
uint32_t sum = ntohs(old_sum) + ADDIPCS(old_src_ip) + ADDIPCS(old_dst_ip)
+ SUBIPCS(new_src_ip) + SUBIPCS(new_dst_ip);
uint32_t sum = uint32_t(old_sum.n) + ADDIPCS(old_src_ip)
+ ADDIPCS(old_dst_ip) + SUBIPCS(new_src_ip) + SUBIPCS(new_dst_ip);
#undef ADDIPCS
#undef SUBIPCS
@ -86,61 +87,64 @@ namespace llarp
sum = (sum & 0xFFff) + (sum >> 16);
sum += sum >> 16;
return htons(uint16_t(sum & 0xFFff));
return nuint16_t{uint16_t(sum & 0xFFff)};
}
static void
checksumDstTCP(byte_t *pld, size_t psz, size_t fragoff, size_t chksumoff,
huint32_t oSrcIP, huint32_t oDstIP, huint32_t nSrcIP,
huint32_t nDstIP)
checksumDstIPv4TCP(byte_t *pld, size_t psz, size_t fragoff,
size_t chksumoff, nuint32_t oSrcIP, nuint32_t oDstIP,
nuint32_t nSrcIP, nuint32_t nDstIP)
{
if(fragoff > chksumoff)
return;
uint16_t *check = (uint16_t *)(pld + chksumoff - fragoff);
auto check = (nuint16_t *)(pld + chksumoff - fragoff);
*check = deltachksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP);
*check = deltaIPv4Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP);
// usually, TCP checksum field cannot be 0xFFff,
// because one's complement addition cannot result in 0x0000,
// and there's inversion in the end;
// emulate that.
if(*check == 0xFFff)
*check = 0x0000;
if(check->n == 0xFFff)
check->n = 0x0000;
}
static void
checksumDstUDP(const ip_header *ohdr, byte_t *pld, size_t psz,
size_t fragoff, huint32_t oSrcIP, huint32_t oDstIP,
huint32_t nSrcIP, huint32_t nDstIP)
checksumDstIPv4UDP(byte_t *pld, size_t psz, size_t fragoff,
nuint32_t oSrcIP, nuint32_t oDstIP, nuint32_t nSrcIP,
nuint32_t nDstIP)
{
if(fragoff > 6)
return;
uint16_t *check = (uint16_t *)(pld + 6);
if(*check == 0x0000)
auto check = (nuint16_t *)(pld + 6);
if(check->n == 0x0000)
return; // 0 is used to indicate "no checksum", don't change
*check = deltachksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP);
*check = deltaIPv4Checksum(*check, oSrcIP, oDstIP, nSrcIP, nDstIP);
// 0 is used to indicate "no checksum"
// 0xFFff and 0 are equivalent in one's complement math
// 0xFFff + 1 = 0x10000 -> 0x0001 (same as 0 + 1)
// infact it's impossible to get 0 with such addition,
// when starting from non-0 value.
// inside deltachksum we don't invert so it's safe to skip check there
// if(*check == 0x0000)
// *check = 0xFFff;
// if(check->n == 0x0000)
// check->n = 0xFFff;
}
void
IPv4Packet::UpdatePacketOnDst(huint32_t nSrcIP, huint32_t nDstIP)
IPv4Packet::UpdateIPv4PacketOnDst(huint32_t newSrcIP, huint32_t newDstIP)
{
auto hdr = Header();
auto oSrcIP = xntohl(nuint32_t{hdr->saddr});
auto oDstIP = xntohl(nuint32_t{hdr->daddr});
auto oSrcIP = nuint32_t{hdr->saddr};
auto oDstIP = nuint32_t{hdr->daddr};
auto nSrcIP = xhtonl(newSrcIP);
auto nDstIP = xhtonl(newDstIP);
// IPv4 checksum
hdr->check = deltachksum(hdr->check, oSrcIP, oDstIP, nSrcIP, nDstIP);
auto v4chk = (nuint16_t *)&(hdr->check);
*v4chk = deltaIPv4Checksum(*v4chk, oSrcIP, oDstIP, nSrcIP, nDstIP);
// L4 checksum
auto ihs = size_t(hdr->ihl * 4);
@ -154,73 +158,75 @@ namespace llarp
switch(hdr->protocol)
{
case 6: // TCP
checksumDstTCP(pld, psz, fragoff, 16, oSrcIP, oDstIP, nSrcIP,
nDstIP);
checksumDstIPv4TCP(pld, psz, fragoff, 16, oSrcIP, oDstIP, nSrcIP,
nDstIP);
break;
case 17: // UDP
case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition
checksumDstUDP(hdr, pld, psz, fragoff, oSrcIP, oDstIP, nSrcIP,
nDstIP);
checksumDstIPv4UDP(pld, psz, fragoff, oSrcIP, oDstIP, nSrcIP,
nDstIP);
break;
case 33: // DCCP
checksumDstTCP(pld, psz, fragoff, 6, oSrcIP, oDstIP, nSrcIP,
nDstIP);
checksumDstIPv4TCP(pld, psz, fragoff, 6, oSrcIP, oDstIP, nSrcIP,
nDstIP);
break;
}
}
// write new IP addresses
hdr->saddr = xhtonl(nSrcIP).n;
hdr->daddr = xhtonl(nDstIP).n;
hdr->saddr = nSrcIP.n;
hdr->daddr = nDstIP.n;
}
static void
checksumSrcTCP(byte_t *pld, size_t psz, size_t fragoff, size_t chksumoff,
huint32_t oSrcIP, huint32_t oDstIP)
checksumSrcIPv4TCP(byte_t *pld, size_t psz, size_t fragoff,
size_t chksumoff, nuint32_t oSrcIP, nuint32_t oDstIP)
{
if(fragoff > chksumoff)
return;
uint16_t *check = (uint16_t *)(pld + chksumoff - fragoff);
auto check = (nuint16_t *)(pld + chksumoff - fragoff);
*check = deltachksum(*check, oSrcIP, oDstIP, huint32_t{0}, huint32_t{0});
*check =
deltaIPv4Checksum(*check, oSrcIP, oDstIP, nuint32_t{0}, nuint32_t{0});
// usually, TCP checksum field cannot be 0xFFff,
// because one's complement addition cannot result in 0x0000,
// and there's inversion in the end;
// emulate that.
if(*check == 0xFFff)
*check = 0x0000;
if(check->n == 0xFFff)
check->n = 0x0000;
}
static void
checksumSrcUDP(const ip_header *ohdr, byte_t *pld, size_t psz,
size_t fragoff, huint32_t oSrcIP, huint32_t oDstIP)
checksumSrcIPv4UDP(byte_t *pld, size_t psz, size_t fragoff,
nuint32_t oSrcIP, nuint32_t oDstIP)
{
if(fragoff > 6)
return;
uint16_t *check = (uint16_t *)(pld + 6);
if(*check == 0x0000)
auto check = (nuint16_t *)(pld + 6);
if(check->n == 0x0000)
return; // 0 is used to indicate "no checksum", don't change
*check = deltachksum(*check, oSrcIP, oDstIP, huint32_t{0}, huint32_t{0});
*check =
deltaIPv4Checksum(*check, oSrcIP, oDstIP, nuint32_t{0}, nuint32_t{0});
// 0 is used to indicate "no checksum"
// 0xFFff and 0 are equivalent in one's complement math
// 0xFFff + 1 = 0x10000 -> 0x0001 (same as 0 + 1)
// infact it's impossible to get 0 with such addition,
// when starting from non-0 value.
// inside deltachksum we don't invert so it's safe to skip check there
// if(*check == 0x0000)
// *check = 0xFFff;
// if(check->n == 0x0000)
// check->n = 0xFFff;
}
void
IPv4Packet::UpdatePacketOnSrc()
IPv4Packet::UpdateIPv4PacketOnSrc()
{
auto hdr = Header();
auto oSrcIP = xntohl(nuint32_t{hdr->saddr});
auto oDstIP = xntohl(nuint32_t{hdr->daddr});
auto oSrcIP = nuint32_t{hdr->saddr};
auto oDstIP = nuint32_t{hdr->daddr};
// L4
auto ihs = size_t(hdr->ihl * 4);
@ -234,21 +240,22 @@ namespace llarp
switch(hdr->protocol)
{
case 6: // TCP
checksumSrcTCP(pld, psz, fragoff, 16, oSrcIP, oDstIP);
checksumSrcIPv4TCP(pld, psz, fragoff, 16, oSrcIP, oDstIP);
break;
case 17: // UDP
case 136: // UDP-Lite
checksumSrcUDP(hdr, pld, psz, fragoff, oSrcIP, oDstIP);
checksumSrcIPv4UDP(pld, psz, fragoff, oSrcIP, oDstIP);
break;
case 33: // DCCP
checksumSrcTCP(pld, psz, fragoff, 6, oSrcIP, oDstIP);
checksumSrcIPv4TCP(pld, psz, fragoff, 6, oSrcIP, oDstIP);
break;
}
}
// IPv4
hdr->check =
deltachksum(hdr->check, oSrcIP, oDstIP, huint32_t{0}, huint32_t{0});
auto v4chk = (nuint16_t *)&(hdr->check);
*v4chk =
deltaIPv4Checksum(*v4chk, oSrcIP, oDstIP, nuint32_t{0}, nuint32_t{0});
// clear addresses
hdr->saddr = 0;

Loading…
Cancel
Save