Files
picomap/firmware/lib/arp.cpp

42 lines
1.3 KiB
C++

#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<const uint8_t> frame, span_writer& tx,
eth::mac_addr our_mac, ipv4::ip4_addr our_ip,
std::function<void(std::span<const uint8_t>)> send_raw) {
if (frame.size() < sizeof(packet)) return;
auto& pkt = *reinterpret_cast<const packet*>(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<packet*>(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