1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/bpf.h> 3 #include <bpf/bpf_helpers.h> 4 #include <bpf/bpf_endian.h> 5 6 #include <linux/ip.h> 7 #include <linux/in.h> 8 #include <linux/if_ether.h> 9 #include <linux/pkt_cls.h> 10 #include <stdbool.h> 11 12 int lookup_status; 13 bool test_xdp; 14 bool tcp_skc; 15 16 #define CUR_NS BPF_F_CURRENT_NETNS 17 18 static void socket_lookup(void *ctx, void *data_end, void *data) 19 { 20 struct ethhdr *eth = data; 21 struct bpf_sock_tuple *tp; 22 struct bpf_sock *sk; 23 struct iphdr *iph; 24 int tplen; 25 26 if (eth + 1 > data_end) 27 return; 28 29 if (eth->h_proto != bpf_htons(ETH_P_IP)) 30 return; 31 32 iph = (struct iphdr *)(eth + 1); 33 if (iph + 1 > data_end) 34 return; 35 36 tp = (struct bpf_sock_tuple *)&iph->saddr; 37 tplen = sizeof(tp->ipv4); 38 if ((void *)tp + tplen > data_end) 39 return; 40 41 switch (iph->protocol) { 42 case IPPROTO_TCP: 43 if (tcp_skc) 44 sk = bpf_skc_lookup_tcp(ctx, tp, tplen, CUR_NS, 0); 45 else 46 sk = bpf_sk_lookup_tcp(ctx, tp, tplen, CUR_NS, 0); 47 break; 48 case IPPROTO_UDP: 49 sk = bpf_sk_lookup_udp(ctx, tp, tplen, CUR_NS, 0); 50 break; 51 default: 52 return; 53 } 54 55 lookup_status = 0; 56 57 if (sk) { 58 bpf_sk_release(sk); 59 lookup_status = 1; 60 } 61 } 62 63 SEC("tc") 64 int tc_socket_lookup(struct __sk_buff *skb) 65 { 66 void *data_end = (void *)(long)skb->data_end; 67 void *data = (void *)(long)skb->data; 68 69 if (test_xdp) 70 return TC_ACT_UNSPEC; 71 72 socket_lookup(skb, data_end, data); 73 return TC_ACT_UNSPEC; 74 } 75 76 SEC("xdp") 77 int xdp_socket_lookup(struct xdp_md *xdp) 78 { 79 void *data_end = (void *)(long)xdp->data_end; 80 void *data = (void *)(long)xdp->data; 81 82 if (!test_xdp) 83 return XDP_PASS; 84 85 socket_lookup(xdp, data_end, data); 86 return XDP_PASS; 87 } 88 89 char _license[] SEC("license") = "GPL"; 90