#pragma once #include #include #include #include #include "eth.h" #include "span_writer.h" namespace ipv4 { using ip4_addr = std::array; struct __attribute__((packed)) header { eth::header eth; uint8_t ver_ihl; uint8_t dscp_ecn; uint16_t total_len; uint16_t identification; uint16_t flags_frag; uint8_t ttl; uint8_t protocol; uint16_t checksum; ip4_addr src; ip4_addr dst; size_t ip_header_len() const { return (ver_ihl & 0x0F) * 4; } size_t ip_total_len() const { return __builtin_bswap16(total_len); } const uint8_t* ip_start() const { return reinterpret_cast(&ver_ihl); } uint8_t* ip_start() { return reinterpret_cast(&ver_ihl); } }; static_assert(sizeof(header) == 34); struct __attribute__((packed)) udp_header { header ip; uint16_t src_port; uint16_t dst_port; uint16_t length; uint16_t checksum; }; static_assert(sizeof(udp_header) == 42); uint16_t checksum(const void* data, size_t len); void handle(std::span frame, span_writer& tx, eth::mac_addr our_mac, ip4_addr our_ip, ip4_addr subnet_broadcast, std::function)> send_raw, std::function, span_writer&)> handle_udp); } // namespace ipv4