1 /* 2 * dns_matching.c Drop DNS packets requesting DNS name contained in hash map 3 * For Linux, uses BCC, eBPF. See .py file. 4 * 5 * Copyright (c) 2016 Rudi Floren. 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of version 2 of the GNU General Public 8 * License as published by the Free Software Foundation. 9 * 10 * 11-May-2016 Rudi Floren Created this. 11 */ 12 13 #include <uapi/linux/bpf.h> 14 #include <uapi/linux/if_ether.h> 15 #include <uapi/linux/if_packet.h> 16 #include <uapi/linux/ip.h> 17 #include <uapi/linux/in.h> 18 #include <uapi/linux/udp.h> 19 #include <bcc/proto.h> 20 21 #define ETH_LEN 14 22 23 struct dns_hdr_t 24 { 25 uint16_t id; 26 uint16_t flags; 27 uint16_t qdcount; 28 uint16_t ancount; 29 uint16_t nscount; 30 uint16_t arcount; 31 } BPF_PACKET_HEADER; 32 33 34 struct dns_query_flags_t 35 { 36 uint16_t qtype; 37 uint16_t qclass; 38 } BPF_PACKET_HEADER; 39 40 struct dns_char_t 41 { 42 char c; 43 } BPF_PACKET_HEADER; 44 45 struct Key { 46 unsigned char p[255]; 47 }; 48 49 struct Leaf { 50 // Not really needed in this example 51 unsigned char p[4]; 52 }; 53 54 BPF_HASH(cache, struct Key, struct Leaf, 128); 55 56 int dns_matching(struct __sk_buff *skb) 57 { 58 u8 *cursor = 0; 59 struct Key key = {}; 60 // Check of ethernet/IP frame. 61 struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); 62 if(ethernet->type == ETH_P_IP) { 63 64 // Check for UDP. 65 struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); 66 u16 hlen_bytes = ip->hlen << 2; 67 if(ip->nextp == IPPROTO_UDP) { 68 69 // Check for Port 53, DNS packet. 70 struct udp_t *udp = cursor_advance(cursor, sizeof(*udp)); 71 if(udp->dport == 53){ 72 73 struct dns_hdr_t *dns_hdr = cursor_advance(cursor, sizeof(*dns_hdr)); 74 75 // Do nothing if packet is not a request. 76 if((dns_hdr->flags >>15) != 0) { 77 // Exit if this packet is not a request. 78 return -1; 79 } 80 81 u16 i = 0; 82 struct dns_char_t *c; 83 #pragma unroll 84 for(i = 0; i<255;i++){ 85 c = cursor_advance(cursor, 1); 86 if (c->c == 0) 87 break; 88 key.p[i] = c->c; 89 } 90 91 struct Leaf * lookup_leaf = cache.lookup(&key); 92 93 // If DNS name is contained in our map, keep the packet 94 if(lookup_leaf) { 95 bpf_trace_printk("Matched1\n"); 96 return -1; 97 } 98 } 99 } 100 } 101 // Drop the packet 102 return 0; 103 } 104