// Linux XDP filter to pair with an AF_XDP receiver and an XSKMAP loader.
// The published source is IPv4; change DEST_PORT to your verified UDP port.
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>

#define DEST_PORT 9000
#define MAX_PAYLOAD 1228
#define SOURCE_IPV4 0x4082285a // 203.23.178.228 in host byte order

struct {
    __uint(type, BPF_MAP_TYPE_XSKMAP);
    __uint(max_entries, 64);
    __type(key, __u32);
    __type(value, __u32);
} xsks_map SEC(".maps");

SEC("xdp")
int shred_receiver_redirect(struct xdp_md *ctx) {
    void *data = (void *)(long)ctx->data;
    void *end = (void *)(long)ctx->data_end;
    struct ethhdr *eth = data;
    if ((void *)(eth + 1) > end || eth->h_proto != bpf_htons(ETH_P_IP))
        return XDP_PASS;

    struct iphdr *ip = (void *)(eth + 1);
    if ((void *)(ip + 1) > end || ip->ihl < 5 || ip->protocol != IPPROTO_UDP)
        return XDP_PASS;
    if (ip->saddr != bpf_htonl(SOURCE_IPV4))
        return XDP_PASS;
    // Fragmented IPv4 packets require kernel reassembly, not this fast path.
    if (ip->frag_off & bpf_htons(0x3fff))
        return XDP_PASS;

    __u32 ihl = (__u32)ip->ihl * 4;
    struct udphdr *udp = (void *)ip + ihl;
    if ((void *)(udp + 1) > end || udp->dest != bpf_htons(DEST_PORT))
        return XDP_PASS;
    __u16 udp_len = bpf_ntohs(udp->len);
    if (udp_len < sizeof(*udp) || udp_len - sizeof(*udp) > MAX_PAYLOAD)
        return XDP_PASS;
    if ((void *)udp + udp_len > end)
        return XDP_PASS;

    // A userspace loader must insert its AF_XDP socket at rx_queue_index.
    // An empty map entry falls back to the ordinary kernel receive path.
    return bpf_redirect_map(&xsks_map, ctx->rx_queue_index, XDP_PASS);
}

char LICENSE[] SEC("license") = "GPL";
