42 lines
1.3 KiB
C++
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
|