#include "arp.h" namespace arp { static constexpr uint16_t ARP_HTYPE_ETH = __builtin_bswap16(1); static constexpr uint16_t ARP_PTYPE_IPV4 = __builtin_bswap16(0x0800); static constexpr uint16_t ARP_OP_REQUEST = __builtin_bswap16(1); static constexpr uint16_t ARP_OP_REPLY = __builtin_bswap16(2); void handle(std::span frame, span_writer& tx, eth::mac_addr our_mac, ipv4::ip4_addr our_ip, std::function)> send_raw) { if (frame.size() < sizeof(packet)) return; auto& pkt = *reinterpret_cast(frame.data()); if (pkt.htype != ARP_HTYPE_ETH) return; if (pkt.ptype != ARP_PTYPE_IPV4) return; if (pkt.hlen != 6 || pkt.plen != 4) return; if (pkt.oper != ARP_OP_REQUEST) return; if (pkt.tpa != our_ip) return; if (sizeof(packet) > tx.capacity()) return; auto& reply = *reinterpret_cast(tx.data()); reply = {}; reply.eth.dst = pkt.eth.src; reply.eth.src = our_mac; reply.eth.ethertype = eth::ETH_ARP; reply.htype = ARP_HTYPE_ETH; reply.ptype = ARP_PTYPE_IPV4; reply.hlen = 6; reply.plen = 4; reply.oper = ARP_OP_REPLY; reply.sha = our_mac; reply.spa = our_ip; reply.tha = pkt.sha; reply.tpa = pkt.spa; send_raw({tx.data(), sizeof(packet)}); } } // namespace arp