Add IGMP, prepend_buffer/parse_buffer, split UDP header, discovery tests, test all
This commit is contained in:
@@ -5,6 +5,10 @@
|
||||
#include "eth.h"
|
||||
#include "arp.h"
|
||||
#include "ipv4.h"
|
||||
#include "udp.h"
|
||||
#include "igmp.h"
|
||||
#include "parse_buffer.h"
|
||||
#include "prepend_buffer.h"
|
||||
#include "w6300.h"
|
||||
#include "debug_log.h"
|
||||
|
||||
@@ -23,58 +27,40 @@ void net_send_raw(std::span<const uint8_t> data) {
|
||||
}
|
||||
|
||||
static void handle_udp(std::span<const uint8_t> frame, span_writer& tx) {
|
||||
if (frame.size() < sizeof(ipv4::udp_header)) return;
|
||||
auto& pkt = *reinterpret_cast<const ipv4::udp_header*>(frame.data());
|
||||
parse_buffer pb(frame);
|
||||
auto* eth_hdr = pb.consume<eth::header>();
|
||||
auto* ip = pb.consume<ipv4::header>();
|
||||
if (!ip) return;
|
||||
|
||||
if (pkt.dst_port != PICOMAP_PORT) return;
|
||||
size_t options_len = ip->header_len() - sizeof(ipv4::header);
|
||||
if (options_len > 0 && !pb.skip(options_len)) return;
|
||||
|
||||
auto* uhdr = pb.consume<udp::header>();
|
||||
if (!uhdr) return;
|
||||
if (uhdr->dst_port != PICOMAP_PORT) return;
|
||||
if (!msg_handler) return;
|
||||
|
||||
size_t udp_len = __builtin_bswap16(pkt.length);
|
||||
if (udp_len < 8) return;
|
||||
if (sizeof(eth::header) + pkt.ip.ip_total_len() < sizeof(ipv4::udp_header) + udp_len - 8) return;
|
||||
size_t udp_len = __builtin_bswap16(uhdr->length);
|
||||
if (udp_len < sizeof(udp::header)) return;
|
||||
size_t payload_len = udp_len - sizeof(udp::header);
|
||||
if (pb.remaining_size() < payload_len) return;
|
||||
|
||||
size_t payload_len = udp_len - 8;
|
||||
eth::mac_addr dst_mac = eth_hdr->src;
|
||||
ipv4::ip4_addr dst_ip = ip->src;
|
||||
uint16_t dst_port = uhdr->src_port;
|
||||
|
||||
eth::mac_addr dst_mac = pkt.ip.eth.src;
|
||||
ipv4::ip4_addr dst_ip = pkt.ip.src;
|
||||
uint16_t dst_port = pkt.src_port;
|
||||
|
||||
msg_handler(frame.subspan(sizeof(ipv4::udp_header), payload_len),
|
||||
msg_handler(pb.remaining().subspan(0, payload_len),
|
||||
[dst_mac, dst_ip, dst_port](std::span<const uint8_t> resp_data) {
|
||||
size_t ip_total = 20 + 8 + resp_data.size();
|
||||
size_t reply_len = sizeof(eth::header) + ip_total;
|
||||
uint8_t reply_buf[1514];
|
||||
if (reply_len > sizeof(reply_buf)) return;
|
||||
|
||||
auto& rip = *reinterpret_cast<ipv4::header*>(reply_buf);
|
||||
rip.eth.dst = dst_mac;
|
||||
rip.eth.src = state.mac;
|
||||
rip.eth.ethertype = eth::ETH_IPV4;
|
||||
rip.ver_ihl = 0x45;
|
||||
rip.dscp_ecn = 0;
|
||||
rip.total_len = __builtin_bswap16(ip_total);
|
||||
rip.identification = 0;
|
||||
rip.flags_frag = 0;
|
||||
rip.ttl = 64;
|
||||
rip.protocol = 17;
|
||||
rip.checksum = 0;
|
||||
rip.src = state.ip;
|
||||
rip.dst = dst_ip;
|
||||
rip.checksum = ipv4::checksum(rip.ip_start(), 20);
|
||||
|
||||
auto& rudp = *reinterpret_cast<ipv4::udp_header*>(reply_buf);
|
||||
rudp.src_port = PICOMAP_PORT;
|
||||
rudp.dst_port = dst_port;
|
||||
rudp.length = __builtin_bswap16(8 + resp_data.size());
|
||||
rudp.checksum = 0;
|
||||
|
||||
memcpy(reply_buf + sizeof(ipv4::udp_header), resp_data.data(), resp_data.size());
|
||||
net_send_raw({reply_buf, reply_len});
|
||||
prepend_buffer<1514> buf;
|
||||
buf.append_copy(resp_data);
|
||||
udp::prepend(buf, dst_mac, state.mac, state.ip, dst_ip,
|
||||
PICOMAP_PORT, dst_port, resp_data.size());
|
||||
net_send_raw(buf.span());
|
||||
});
|
||||
}
|
||||
|
||||
static bool mac_match(const eth::mac_addr& dst) {
|
||||
return dst == state.mac || dst == eth::MAC_BROADCAST;
|
||||
return dst == state.mac || dst == eth::MAC_BROADCAST || igmp::is_member_mac(dst);
|
||||
}
|
||||
|
||||
static void process_frame(std::span<const uint8_t> frame, span_writer& tx) {
|
||||
@@ -121,6 +107,8 @@ bool net_init() {
|
||||
w6300::open_socket(raw_socket, w6300::protocol::macraw, w6300::sock_flag::none);
|
||||
w6300::set_interrupt_mask(w6300::ik_sock_0);
|
||||
|
||||
igmp::join(igmp::PICOMAP_DISCOVERY_GROUP, state.mac, state.ip, net_send_raw);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user