1 #include <linux/bpf.h> 2 #include <linux/in.h> 3 #include <linux/if_ether.h> 4 #include <linux/if_packet.h> 5 #include <linux/if_vlan.h> 6 #include <linux/ip.h> 7 #include <bpf/bpf_helpers.h> 8 9 struct { 10 __uint(type, BPF_MAP_TYPE_HASH); 11 __uint(key_size, sizeof(unsigned int)); 12 __uint(value_size, sizeof(unsigned int)); 13 __uint(max_entries, 4096); 14 __uint(pinning, LIBBPF_PIN_BY_NAME); 15 } rules SEC(".maps"); 16 17 18 19 SEC("xdp") 20 int xdp_ipv4_firewalling(struct xdp_md *ctx) 21 { 22 void *data_end = (void *)(long)ctx->data_end; 23 void *data = (void *)(long)ctx->data; 24 struct ethhdr *eth = data; 25 struct iphdr *iph; 26 u16 h_proto; 27 u64 nh_off; 28 unsigned int sip=0; 29 unsigned int m = 0xffffffff; 30 unsigned int *value = NULL; 31 int i; 32 33 nh_off = sizeof(*eth); 34 if (data + nh_off > data_end) return XDP_PASS; 35 36 h_proto = eth->h_proto; 37 38 if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { 39 struct vlan_hdr *vhdr; 40 41 vhdr = data + nh_off; 42 nh_off += sizeof(struct vlan_hdr); 43 if (data + nh_off > data_end) 44 return XDP_PASS; 45 h_proto = vhdr->h_vlan_encapsulated_proto; 46 } 47 if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { 48 struct vlan_hdr *vhdr; 49 50 vhdr = data + nh_off; 51 nh_off += sizeof(struct vlan_hdr); 52 if (data + nh_off > data_end) 53 return XDP_PASS; 54 h_proto = vhdr->h_vlan_encapsulated_proto; 55 } 56 if (h_proto != htons(ETH_P_IP)) return XDP_PASS; 57 if (data + nh_off + sizeof(*iph) > data_end) return XDP_PASS; 58 iph = data + nh_off; 59 60 61 sip = iph->saddr; 62 sip = (sip>>24) | (((sip>>16)&0xff)<<8) | (((sip>>8)&0xff)<<16) | ((sip&0xff)<<24); 63 // cat /sys/kernel/debug/tracing/trace_pipe 64 // bpf_printk("capture source ip %x\n", sip); 65 for (i=0; i<31; i++) { 66 sip &= m; 67 value=bpf_map_lookup_elem(&rules, &sip); 68 if (value) { 69 if (*value) return XDP_DROP; 70 return XDP_PASS; 71 } 72 m<<=1; 73 } 74 return XDP_PASS; 75 } 76 77 char LICENSE[] SEC("license") = "Dual BSD/GPL"; 78 79