xref: /linux-tools/ebpf/kernel-samples-bpf/ipfirewall_kern.c (revision de922be4e919572d28577568db563e691d5e7702)
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