#include #include #include #include #include #include #include #define SEC(NAME) __attribute__((section(NAME), used)) #define trace_printk(fmt, ...) do { \ char _fmt[] = fmt; \ bpf_trace_printk(_fmt, sizeof(_fmt), ##__VA_ARGS__); \ } while (0) static int (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) = (void *) BPF_FUNC_trace_printk; static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) = (void *) BPF_FUNC_skb_store_bytes; int modudp(struct __sk_buff *skb); SEC("modudp") int main_modup(struct __sk_buff *skb) { /* We will access all data through pointers to structs */ void *data = (void *)(long)skb->data; void *data_end = (void *)(long)skb->data_end; if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) > data_end) return TC_ACT_UNSPEC; /* for easy access we re-use the Kernel's struct definitions */ struct ethhdr *eth = data; struct iphdr *ip = (data + sizeof(struct ethhdr)); struct udphdr *udp = (data + sizeof(struct ethhdr) + sizeof(struct iphdr)); /* Only actual IP packets are allowed */ if (eth->h_proto != __constant_htons(ETH_P_IP)) return TC_ACT_OK; /* We handle only UDP traffic */ if (ip->protocol != IPPROTO_UDP) return TC_ACT_OK; __be16 port = __constant_htons(2048); if (udp->dest != port && udp->source != port) return TC_ACT_OK; __be16 size = __constant_htons(1); if (udp->len < size) return TC_ACT_OK; /* Let's grab the IP addresses. * They are 32-bit, so it is easy to access */ __u32 src_ip = ip->saddr; __u32 dst_ip = ip->daddr; trace_printk("[action] IP Packet, proto= %d, src= %lu, dst= %lu\n", ip->protocol, src_ip, dst_ip); char c = '_'; int off = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr); bpf_skb_store_bytes(skb, off, &c, sizeof(c), BPF_F_RECOMPUTE_CSUM); return TC_ACT_UNSPEC; } char __license[] SEC("license") = "GPL";