mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
Kernel: Convert TCP pseudo-headers through a union
This keeps us from tripping strict aliasing, which previously made TCP connections inoperable when building without `-fsanitize=undefined` or `-fno-strict-aliasing`.
This commit is contained in:
parent
7cd99572be
commit
24f956c739
|
@ -360,31 +360,35 @@ bool TCPSocket::should_delay_next_ack() const
|
|||
|
||||
NetworkOrdered<u16> TCPSocket::compute_tcp_checksum(IPv4Address const& source, IPv4Address const& destination, TCPPacket const& packet, u16 payload_size)
|
||||
{
|
||||
struct [[gnu::packed]] PseudoHeader {
|
||||
IPv4Address source;
|
||||
IPv4Address destination;
|
||||
u8 zero;
|
||||
u8 protocol;
|
||||
NetworkOrdered<u16> payload_size;
|
||||
union PseudoHeader {
|
||||
struct [[gnu::packed]] {
|
||||
IPv4Address source;
|
||||
IPv4Address destination;
|
||||
u8 zero;
|
||||
u8 protocol;
|
||||
NetworkOrdered<u16> payload_size;
|
||||
} header;
|
||||
u16 raw[6];
|
||||
};
|
||||
static_assert(sizeof(PseudoHeader) == 12);
|
||||
|
||||
PseudoHeader pseudo_header { source, destination, 0, (u8)IPv4Protocol::TCP, packet.header_size() + payload_size };
|
||||
PseudoHeader pseudo_header { .header = { source, destination, 0, (u8)IPv4Protocol::TCP, packet.header_size() + payload_size } };
|
||||
|
||||
u32 checksum = 0;
|
||||
auto raw_pseudo_header = bit_cast<u16*>(&pseudo_header);
|
||||
auto* raw_pseudo_header = pseudo_header.raw;
|
||||
for (size_t i = 0; i < sizeof(pseudo_header) / sizeof(u16); ++i) {
|
||||
checksum += AK::convert_between_host_and_network_endian(raw_pseudo_header[i]);
|
||||
if (checksum > 0xffff)
|
||||
checksum = (checksum >> 16) + (checksum & 0xffff);
|
||||
}
|
||||
auto raw_packet = bit_cast<u16*>(&packet);
|
||||
auto* raw_packet = bit_cast<u16*>(&packet);
|
||||
for (size_t i = 0; i < packet.header_size() / sizeof(u16); ++i) {
|
||||
checksum += AK::convert_between_host_and_network_endian(raw_packet[i]);
|
||||
if (checksum > 0xffff)
|
||||
checksum = (checksum >> 16) + (checksum & 0xffff);
|
||||
}
|
||||
VERIFY(packet.data_offset() * 4 == packet.header_size());
|
||||
auto raw_payload = bit_cast<u16*>(packet.payload());
|
||||
auto* raw_payload = bit_cast<u16*>(packet.payload());
|
||||
for (size_t i = 0; i < payload_size / sizeof(u16); ++i) {
|
||||
checksum += AK::convert_between_host_and_network_endian(raw_payload[i]);
|
||||
if (checksum > 0xffff)
|
||||
|
|
Loading…
Reference in a new issue