1*01748996SDavid Wei // SPDX-License-Identifier: GPL-2.0 2*01748996SDavid Wei #include <linux/bpf.h> 3*01748996SDavid Wei #include <linux/pkt_cls.h> 4*01748996SDavid Wei #include <linux/if_ether.h> 5*01748996SDavid Wei #include <linux/ipv6.h> 6*01748996SDavid Wei #include <linux/in6.h> 7*01748996SDavid Wei #include <bpf/bpf_endian.h> 8*01748996SDavid Wei #include <bpf/bpf_helpers.h> 9*01748996SDavid Wei 10*01748996SDavid Wei #define TC_ACT_OK 0 11*01748996SDavid Wei #define ETH_P_IPV6 0x86DD 12*01748996SDavid Wei 13*01748996SDavid Wei #define ctx_ptr(field) ((void *)(long)(field)) 14*01748996SDavid Wei 15*01748996SDavid Wei #define v6_p64_equal(a, b) (a.s6_addr32[0] == b.s6_addr32[0] && \ 16*01748996SDavid Wei a.s6_addr32[1] == b.s6_addr32[1]) 17*01748996SDavid Wei 18*01748996SDavid Wei volatile __u32 netkit_ifindex; 19*01748996SDavid Wei volatile __u8 ipv6_prefix[16]; 20*01748996SDavid Wei 21*01748996SDavid Wei SEC("tc/ingress") 22*01748996SDavid Wei int tc_redirect_peer(struct __sk_buff *skb) 23*01748996SDavid Wei { 24*01748996SDavid Wei void *data_end = ctx_ptr(skb->data_end); 25*01748996SDavid Wei void *data = ctx_ptr(skb->data); 26*01748996SDavid Wei struct in6_addr *peer_addr; 27*01748996SDavid Wei struct ipv6hdr *ip6h; 28*01748996SDavid Wei struct ethhdr *eth; 29*01748996SDavid Wei 30*01748996SDavid Wei peer_addr = (struct in6_addr *)ipv6_prefix; 31*01748996SDavid Wei 32*01748996SDavid Wei if (skb->protocol != bpf_htons(ETH_P_IPV6)) 33*01748996SDavid Wei return TC_ACT_OK; 34*01748996SDavid Wei 35*01748996SDavid Wei eth = data; 36*01748996SDavid Wei if ((void *)(eth + 1) > data_end) 37*01748996SDavid Wei return TC_ACT_OK; 38*01748996SDavid Wei 39*01748996SDavid Wei ip6h = data + sizeof(struct ethhdr); 40*01748996SDavid Wei if ((void *)(ip6h + 1) > data_end) 41*01748996SDavid Wei return TC_ACT_OK; 42*01748996SDavid Wei 43*01748996SDavid Wei if (!v6_p64_equal(ip6h->daddr, (*peer_addr))) 44*01748996SDavid Wei return TC_ACT_OK; 45*01748996SDavid Wei 46*01748996SDavid Wei return bpf_redirect_peer(netkit_ifindex, 0); 47*01748996SDavid Wei } 48*01748996SDavid Wei 49*01748996SDavid Wei char __license[] SEC("license") = "GPL"; 50