3 #include <linux/types.h>
4 #include <uapi/linux/tcp.h>
5 #include <uapi/linux/udp.h>
6 #include <uapi/linux/ip.h>
7 #include <uapi/linux/ipv6.h>
11 unsigned id :16; /* query identification number */
12 #if BYTE_ORDER == BIG_ENDIAN
13 /* fields in third byte */
14 unsigned qr: 1; /* response flag */
15 unsigned opcode: 4; /* purpose of message */
16 unsigned aa: 1; /* authoritative answer */
17 unsigned tc: 1; /* truncated message */
18 unsigned rd: 1; /* recursion desired */
19 /* fields in fourth byte */
20 unsigned ra: 1; /* recursion available */
21 unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
22 unsigned ad: 1; /* authentic data from named */
23 unsigned cd: 1; /* checking disabled by resolver */
24 unsigned rcode :4; /* response code */
25 #elif BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
26 /* fields in third byte */
27 unsigned rd :1; /* recursion desired */
28 unsigned tc :1; /* truncated message */
29 unsigned aa :1; /* authoritative answer */
30 unsigned opcode :4; /* purpose of message */
31 unsigned qr :1; /* response flag */
32 /* fields in fourth byte */
33 unsigned rcode :4; /* response code */
34 unsigned cd: 1; /* checking disabled by resolver */
35 unsigned ad: 1; /* authentic data from named */
36 unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
37 unsigned ra :1; /* recursion available */
40 unsigned qdcount :16; /* number of question entries */
41 unsigned ancount :16; /* number of answer entries */
42 unsigned nscount :16; /* number of authority entries */
43 unsigned arcount :16; /* number of resource entries */
63 #define IP_OFFSET 0x1FFF
65 BPF_TABLE("hash", u32, u64, v4filter, 1024);
66 BPF_TABLE("hash", struct KeyV6, u64, v6filter, 1024);
67 BPF_TABLE("hash", struct QNameKey, struct QNameValue, qnamefilter, 1024);
69 int bpf_dns_filter(struct __sk_buff *skb) {
72 int nh_off = BPF_LL_OFF + ETH_HLEN;
74 if (skb->protocol == ntohs(0x0800)) {
76 int off = nh_off + offsetof(struct iphdr, saddr);
77 key = load_word(skb, off);
79 u64* counter = v4filter.lookup(&key);
81 __sync_fetch_and_add(counter, 1);
86 if (load_half(skb, (nh_off + (int32_t)offsetof(struct iphdr, frag_off)) & (IP_MF | IP_OFFSET))) {
91 ip_proto = load_byte(skb, nh_off + offsetof(struct iphdr, protocol));
92 proto_off = nh_off + sizeof(struct iphdr);
94 else if (skb->protocol == ntohs(0x86DD)) {
96 int off = nh_off + offsetof(struct ipv6hdr, saddr);
97 key.src[0] = load_byte(skb, off++);
98 key.src[1] = load_byte(skb, off++);
99 key.src[2] = load_byte(skb, off++);
100 key.src[3] = load_byte(skb, off++);
101 key.src[4] = load_byte(skb, off++);
102 key.src[5] = load_byte(skb, off++);
103 key.src[6] = load_byte(skb, off++);
104 key.src[7] = load_byte(skb, off++);
105 key.src[8] = load_byte(skb, off++);
106 key.src[9] = load_byte(skb, off++);
107 key.src[10] = load_byte(skb, off++);
108 key.src[11] = load_byte(skb, off++);
109 key.src[12] = load_byte(skb, off++);
110 key.src[13] = load_byte(skb, off++);
111 key.src[14] = load_byte(skb, off++);
112 key.src[15] = load_byte(skb, off++);
114 u64* counter = v6filter.lookup(&key);
116 __sync_fetch_and_add(counter, 1);
120 ip_proto = load_byte(skb, nh_off + offsetof(struct ipv6hdr, nexthdr));
121 proto_off = nh_off + sizeof(struct ipv6hdr);
124 /* neither IPv4 not IPv6, well */
129 if (ip_proto == IPPROTO_TCP) {
133 int dns_off = proto_off + sizeof(struct udphdr);
134 int qname_off = dns_off + sizeof(struct dnsheader);
136 struct QNameKey qkey = { 0 };
137 int32_t labellen = 0;
140 #define FILL_ONE_KEY \
141 temp = load_byte(skb, qname_off + idx); \
143 if (labellen < 0) { \
145 if (labellen == 0) { \
149 qkey.qname[idx] = temp; \
445 u16 qtype = load_half(skb, (qname_off + idx));
448 struct QNameValue* qvalue = qnamefilter.lookup(&qkey);
450 (qvalue->qtype == 255 || qtype == qvalue->qtype)) {
451 __sync_fetch_and_add(&qvalue->counter, 1);