16 Commits

Author SHA1 Message Date
gbucchino aa64b8f160 update code 2025-02-01 16:58:29 +00:00
gbucchino 1436099101 Update 2025-01-31 18:36:55 +00:00
gbucchino c775f97f3c Update 2025-01-30 18:55:58 +00:00
gbucchino 8210e56090 update 2025-01-30 10:51:23 +00:00
gbucchino edda1c6860 update 2025-01-30 10:19:38 +00:00
gbucchino 0a910af5bb Update 2025-01-29 20:13:31 +01:00
gbucchino 6aa1eed6ee Update 2025-01-29 15:05:09 +01:00
gbucchino b57efa5cad Update project 2025-01-28 20:27:03 +01:00
gbucchino 9a67b4f32c Update project 2025-01-26 18:52:33 +01:00
gbucchino eeb15e8f7b Update project 2025-01-23 16:49:49 +01:00
gbucchino 408ad6aef3 Update project 2025-01-22 19:25:57 +01:00
gbucchino 08ece6a46e Update project 2025-01-21 21:04:27 +01:00
gbucchino 157577613a Update 2025-01-20 09:02:18 +01:00
gbucchino 9712681972 Update project 2025-01-19 18:27:25 +01:00
gbucchino 65258eb429 Update project 2025-01-16 16:44:27 +01:00
gbucchino 2cb21c1f55 Get answer 2025-01-15 16:26:53 +01:00
14 changed files with 96055 additions and 113882 deletions
+3 -2
View File
@@ -1,12 +1,13 @@
GCC=gcc
CL=clang-11
CFLAGS=-Wall
LIBS=-lbpf
LIBS=-L../libbpf/src -l:libbpf.a -lelf -lz
#LIBS=-lbpf
all: dns-trace.ebpf.o dns-trace
dns-trace.ebpf.o: src/dns-trace.ebpf.c
$(CL) -g -O2 -target bpf -c src/dns-trace.ebpf.c -o src/dns-trace.ebpf.o
$(CL) -g -O2 -target bpf -D __TARGET_ARCH_x86_64 -D __BPF_TRACING__ -L../libbpf/src -l:libbpf.a -c src/dns-trace.ebpf.c -o src/dns-trace.ebpf.o
dns-trace: src/dns-trace.c
$(GCC) $(CFLAGS) src/dns-trace.c -o dns-trace $(LIBS)
+18
View File
@@ -0,0 +1,18 @@
# Introduction
## Requirements
First, you need to install these packages:
```
apt-get install bpftool clang libbpf-dev gcc-multilib
```
Clone the project and compile it:
```
$ git clone https://github.com/libbpf/libbpf/
cd libbpf/src && make
```
After that, you can execute the program:
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+28 -9
View File
@@ -3,6 +3,13 @@
#define QNAME_SIZE 128
#define REQ_QUERY 0x00
#define REQ_ANSWER 0x01
/* See section 2.3.4 RFC 1035 */
#define MAX_UDP_PAYLOAD 512
#define MAx_NAME_LEN 255
struct dnshdr {
uint16_t transactionID;
uint16_t flags;
@@ -12,19 +19,31 @@ struct dnshdr {
uint16_t nbAdditionalRRs;
};
/*struct dns_query {
char *name;
uint16_t type;
uint16_t class;
};*/
struct event {
uint32_t saddr;
uint32_t client;
int dport;
int sport;
uint16_t tid;
int req_type;
char qname[QNAME_SIZE];
int class;
int type;
uint16_t class;
uint16_t type;
uint16_t numAns;
unsigned char buf[MAX_UDP_PAYLOAD]; // On stocke la data au format size + data
};
struct query_section{
char qname[QNAME_SIZE];
size_t qname_len;
uint16_t class;
uint16_t type;
};
struct dns_answer {
char data[512];
uint16_t class;
uint16_t type;
uint32_t ttl;
};
#endif
+153 -34
View File
@@ -101,93 +101,211 @@ static int open_raw_sock(const char *name)
return sock;
}
static void mapClass(const int class){
static char *mapReqType(const int req){
char *tmp = malloc(8);
if (tmp == NULL)
return NULL;
switch(req){
case 0x00:
strncpy(tmp, "Query", 6);
break;
case 0x01:
strncpy(tmp, "Answer", 7);
break;
default:
strncpy(tmp, "Unknown", 8);
};
return tmp;
}
static char *mapClass(const int class){
char *tmp = malloc(8);
if (tmp == NULL)
return NULL;
memset(tmp, 0, 8);
switch(class){
case 1:
printf("IN\n");
strncpy(tmp, "IN", 3);
break;
case 2:
printf("CS\n");
strncpy(tmp, "CS", 3);
break;
case 3:
printf("CH\n");
strncpy(tmp, "CH", 3);
break;
case 4:
printf("HS\n");
strncpy(tmp, "HS", 3);
break;
default:
printf("Unknown\n");
strncpy(tmp, "Unknown", 8);
break;
}
return tmp;
}
static void mapType(const int type){
static char *mapType(const int type){
char *tmp = malloc(8);
if (tmp == NULL)
return NULL;
/*
* type DNS defined in RFC:
* https://datatracker.ietf.org/doc/html/rfc1035#section-3.2.2
* https://datatracker.ietf.org/doc/html/rfc3596
*/
switch(type){
case 1:
printf("A");
strncpy(tmp, "A", 2);
break;
case 2:
printf("NS");
strncpy(tmp, "NS", 3);
break;
case 3:
printf("MD");
strncpy(tmp, "MD", 3);
break;
case 4:
printf("MF");
strncpy(tmp, "MF", 3);
break;
case 5:
printf("CNAME");
strncpy(tmp, "CNAME", 6);
break;
case 6:
printf("SOA");
strncpy(tmp, "SOA", 4);
break;
case 7:
printf("MB");
strncpy(tmp, "MB", 3);
break;
case 8:
printf("MG");
strncpy(tmp, "MG", 3);
break;
case 9:
printf("MR");
strncpy(tmp, "MR", 3);
break;
case 10:
printf("NULL");
strncpy(tmp, "NULL", 5);
break;
case 11:
printf("WKS");
strncpy(tmp, "WKS", 4);
break;
case 12:
printf("PTR");
strncpy(tmp, "PTR", 4);
break;
case 13:
printf("HINFO");
strncpy(tmp, "HINFO", 6);
break;
case 14:
printf("MINFO");
strncpy(tmp, "MINFO", 6);
break;
case 15:
printf("MX");
strncpy(tmp, "MX", 3);
break;
case 16:
printf("TXT");
strncpy(tmp, "TXT", 4);
break;
case 28:
strncpy(tmp, "AAAA", 5);
break;
default:
printf("Unknown\n");
strncpy(tmp, "Unknown", 8);
break;
}
printf("\n");
return tmp;
}
static void print_query(struct event *s_event){
char *req_type, *class, *type;
printf("%s:%-10d", inet_ntoa(*(struct in_addr*)&s_event->client), s_event->dport);
printf("%-5x", s_event->tid);
req_type = mapReqType(s_event->req_type);
printf("%-10s", req_type);
free(req_type);
printf("%-30s", s_event->qname);
class = mapClass(s_event->class);
printf("%-5s", class);
free(class);
type = mapType(s_event->type);
printf("%-5s", type);
free(type);
}
static void get_labels(unsigned char *buf, char *qname){
int pos = 0;
while (*buf++ != '\0') {
if((*buf >= 'a' && *buf <= 'z') || (*buf >= 'A' && *buf <= 'Z'))
*(qname + pos) = *buf;
else if (*buf >= '0' && *buf <= '9')
*(qname + pos) = *buf;
else
*(qname + pos) = '.';
pos++;
}
qname[pos - 1] = '\0';
}
int handle_event(void *ctx, void *data, size_t data_sz){
struct event *s_event = (struct event*)data;
printf("IP: %s\n", inet_ntoa(*(struct in_addr*)&s_event->saddr));
printf("dport: %d\n", s_event->dport);
printf("sport: %d\n", s_event->sport);
printf("qname: %s\n", s_event->qname);
printf("Class: ");
mapClass(s_event->class);
printf("Type: ");
mapType(s_event->type);
if (s_event->req_type == REQ_QUERY){
print_query(s_event);
}
if (s_event->req_type == REQ_ANSWER){
int pos = 0;
/*for (int i = 0; i < 50; i++)
printf("%d ", s_event->buf[i]);
printf("\n");*/
for (int i = 0; i < s_event->numAns; i++){
print_query(s_event);
uint16_t msg = s_event->buf[pos++];
msg |= s_event->buf[pos++] << 8;
uint16_t type = s_event->buf[pos++];
type |= s_event->buf[pos++] << 8;
uint16_t class = s_event->buf[pos++];
class |= s_event->buf[pos++] << 8;
uint32_t ttl = s_event->buf[pos++];
ttl |= s_event->buf[pos++] << 8;
ttl |= s_event->buf[pos++] << 16;
ttl |= s_event->buf[pos++] << 24;
uint16_t size = s_event->buf[pos++];
size |= s_event->buf[pos++] << 8;
type = ntohs(type);
class = ntohs(class);
ttl = ntohl(ttl);
size = ntohs(size);
if (type == 1) { // -> A
uint32_t ip = s_event->buf[pos] + (s_event->buf[pos+1] << 8) + (s_event->buf[pos+2] << 16) + (s_event->buf[pos+3] << 24);
printf("%s (%d)%5d", inet_ntoa(*(struct in_addr*)&ip), type, ttl);
}
if (type == 5) { // -> CNAME
char cname[size];
get_labels(s_event->buf + pos, cname);
printf("%s ", cname);
}
if (type == 28){ // -> AAAA
int p = 0;
for (int i = 0; i < size; i++){
if (i % 2 == 0)
printf("%x", s_event->buf[pos + p++]);
else{
if (i<size - 1)
printf("%x:", s_event->buf[pos + p++]);
else
printf("%x", s_event->buf[pos + p++]);
}
}
}
pos += size;
printf("\n");
}
}
printf("\n");
return 0;
}
int main(int argc, char *argv[]){
@@ -234,7 +352,8 @@ int main(int argc, char *argv[]){
bpf_program__attach(programSkb);
// int sock = open_raw_sock("wlp0s20f3");
int sock = open_raw_sock("enx98e743c667fc");
//int sock = open_raw_sock("enx98e743c667fc");
int sock = open_raw_sock("lo");
printf("Socket: %d\n", sock);
int prog_fd = bpf_program__fd(programSkb);
printf("Program fd: %d\n", prog_fd);
+255 -105
View File
@@ -2,6 +2,7 @@
#define __TARGET_ARCH_x86
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include <linux/if_ether.h>
@@ -28,21 +29,12 @@ struct {
__uint(max_entries, 256 * 1024 /* 256kb */);
} m_data SEC(".maps");
/*
* This function get the query field and the return the length of it
*/
static size_t get_query(struct __sk_buff *skb, struct event *s_event, uint16_t *class, uint16_t *type, size_t tlen){
size_t len;
char buf[QNAME_SIZE] = {0};
int index = 0;
int qname_len = 0; // Full length of the qname field
char qname[QNAME_SIZE] = {0};
char *c;
bpf_skb_load_bytes(skb, tlen, &buf, 41);
c = buf;
static size_t get_labels(struct __sk_buff *skb, size_t offset, struct event *s_event){
char c;
int qname_len = 0;
bpf_skb_load_bytes(skb, offset, &c, 1); // Get the first byte, which is the length
int pos = 1;
/*
* The qname is composed by a the number of bytes then follow by the label
* For instance, for the qname www.bucchino.org,
@@ -52,127 +44,312 @@ static size_t get_query(struct __sk_buff *skb, struct event *s_event, uint16_t *
* For instance, the result is:
* 03 77 77 77 08 62 75 63 63 68 69 6e 6f 03 6f 72 67 00
*/
while (*(c++) != '\0') {
if(*c >= 'a' && *c <= 'z')
s_event->qname[index] = *c;
else if(*c >= 'A' && *c <= 'Z')
s_event->qname[index] = *c;
while (c != '\0') {
bpf_skb_load_bytes(skb, offset + pos++, &c, 1);
if(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
s_event->qname[qname_len] = c;
else if(c >= '0' && c <= '9')
s_event->qname[qname_len] = c;
else
s_event->qname[index] = '.';
index++;
s_event->qname[qname_len] = '.';
qname_len++;
if (pos == 128 || c == '\0')
break;
}
s_event->qname[--index] = '\0';
qname_len++; // For the null character
bpf_printk("%s (%d) %d", s_event->qname, index, qname_len);
s_event->qname[qname_len - 1] = '\0';
qname_len++;
// dquery->qname_len = qname_len;
// bpf_printk("qname: %s", s_event->qname);
// bpf_printk("qname len: %d", qname_len);
return qname_len;
}
/*
* This function get the query field and the return the length of it
*/
static size_t get_query_section(struct __sk_buff *skb, struct event *s_event, uint8_t offset){
size_t len;
size_t qname_len = 0; // Full length of the qname field
uint16_t class, type;
offset += sizeof(struct dnshdr);
qname_len = get_labels(skb, offset, s_event);
// Get class and type
len = qname_len;
bpf_skb_load_bytes(skb, tlen + qname_len, type, sizeof(uint16_t));
bpf_skb_load_bytes(skb, offset + qname_len, &type, sizeof(uint16_t));
s_event->type = ntohs(type);
len += 2;
bpf_skb_load_bytes(skb, tlen + qname_len + 2, class, sizeof(uint16_t));
bpf_skb_load_bytes(skb, offset + qname_len + 2, &class, sizeof(uint16_t));
s_event->class = ntohs(class);
len += 2;
return len;
}
static unsigned int get_answer(struct __sk_buff *skb, struct event *s_event, size_t tlen, unsigned int index){
unsigned char buf[2] = {0}; // Need to be unsigned, otherwise, the result is fffff
unsigned int offset = index;
// Get the 2 first bytes to identify if it's a message compression or not
if(bpf_skb_load_bytes(skb, tlen, &buf, 2) < 0)
return 0;
tlen += 2; // For the message compression
/*
* According to the RFC 1035 (https://datatracker.ietf.org/doc/html/rfc1035#section-4.1.4)
* In the section 4.1.4, message compression, the first two bits are set at 11 (0xc),
* that's means, it's a pointer.
* For instance, the two bytes 0xc00c, 0xc (11) it's the pointer and 0x00c is the position in the DNS header
*/
if (buf[0] == 0xc0){
/*
* I cannot read the labels, because the eBPF verifier considerate as a infinity loop
*/
/*
* According to the RFC 1035, the structure of answer is like that:
* https://datatracker.ietf.org/doc/html/rfc1035#section-4.1.3
*/
// Get the class and type
if ((void*)(offset) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
return 0;
bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint16_t));
uint16_t type = s_event->buf[0] + (s_event->buf[1] << 8);
tlen += 2;
if ((void*)(offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
return 0;
//offset += 2;
// For class
if(bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint16_t)) < 0)
return 0;
tlen += 2;
if ((void*)(offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
return 0;
// Get ttl
if(bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint32_t)) < 0)
return 0;
if ((void*)(offset += 4) >= MAX_UDP_PAYLOAD - sizeof(uint32_t))
return 0;
tlen += 4;
// Get data size
uint16_t size;
bpf_skb_load_bytes(skb, tlen, &size, sizeof(uint16_t));
bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint16_t));
if ((void*)(offset += 2) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
return 0;
tlen += 2;
uint32_t data;
if (s_event->type == 1) { // -> A
bpf_skb_load_bytes(skb, tlen, s_event->buf + offset, sizeof(uint32_t));
}
if ((void*)(offset += ntohs(size)) >= MAX_UDP_PAYLOAD - sizeof(uint16_t))
return 0;
tlen += ntohs(size);
}
else {
// get_labels(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr), s_event);
}
bpf_printk("End offset: %d", offset);
return offset;
}
/*
* https://datatracker.ietf.org/doc/html/rfc1035
*/
static int dnsquery(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, struct udphdr udp, int dport, int sport){
struct event *s_event;
struct dnshdr dns = {0};
char saddr[32];
uint16_t class, type;
// bpf_printk("udp len: %d", ntohs(udp.len));
struct query_section dquery = {0};
/* Get DNS header */
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr), &dns, sizeof(struct dnshdr));
// Check OpCode
uint16_t qr = ntohs(dns.flags) & 0xF000; // Get the QR code: 0 -> query, 1 -> response
/* If it's not a query, we do not continue */
if(qr != 0x0)
return 0;
if (ntohs(dns.nbQuestions) == 0)
return 0;
s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0);
if (!s_event)
return 0;
s_event->req_type = REQ_QUERY;
/* Get IP header */
s_event->saddr = ip.saddr;
s_event->client = ip.saddr;
/* Get DNS header */
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr), &dns, sizeof(struct dnshdr));
s_event->tid = ntohs(dns.transactionID);
if (ntohs(dns.nbQuestions) == 0){
bpf_ringbuf_discard(s_event, 0);
return 0;
}
bpf_printk("tid: %x", ntohs(dns.transactionID)); // Use as key map
bpf_printk("nb question: %d", ntohs(dns.nbQuestions));
//struct dns_query dquery;
//bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr), &dquery, sizeof(struct dns_query));
// bpf_printk("size: %d %d %d", tlen, skb->len, (skb->len - tlen));
//dlen = (skb->len - tlen);
//bpf_printk("DNS packet len: %d", dlen);
//qlen = dlen - sizeof(struct dnshdr);
//bpf_printk("size: %d %d", sizeof(struct dnshdr), qlen);
/* Get the query structure */
size_t tlen = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr);
size_t query_len = get_query(skb, s_event, &class, &type, tlen);
/* Get the query section */
uint8_t tlen = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr);
size_t query_len = get_query_section(skb, s_event, tlen);
// https://docs.cilium.io/en/stable/reference-guides/bpf/progtypes/
s_event->dport = dport;
s_event->sport = sport;
s_event->class = ntohs(class);
s_event->type = ntohs(type);
//if(bpf_probe_read_user_str(&s_event->qname, sizeof(s_event->qname), qname) < 0)
// bpf_printk("Failed to copy qname");
// Add to map
bpf_ringbuf_submit(s_event, 0);
return 0;
}
static int dnsanswer(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, struct udphdr udp, int dport, int sport){
return 0;
static void dnsanswer_old(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp, int dport, int sport){
char buf[256] = {0}; // Max dns domain name length
//__u16 udplen = 0U;
// Check with ip.len
//const __u32 tot_len = ntohs(ip.tot_len);
// __u32 payload_len = (ntohs(ip.tot_len) - sizeof(struct iphdr) - sizeof(struct udphdr));
__u32 payload_len = (ntohs(ip.tot_len) - sizeof(struct iphdr) - sizeof(struct udphdr)) & 0xff;
if (payload_len > skb->len)
return;
bpf_printk("payload len %d", payload_len);
if (payload_len <= -1) {
bpf_printk("payload len %d", payload_len);
}
// Get udp len
//udplen = ntohs(udp.len);
//bpf_printk("udp len: %d", udplen);
//if (udplen <= 0)
// return 0;
/*if (offset + udplen > skb->len) {
bpf_printk("outbound");
plen = sizeof(struct dnshdr);
}*/
/*long err = bpf_skb_load_bytes(skb, offset, &buf, payload_len);
if(err < 0){
bpf_printk("failed");
// bpf_ringbuf_discard(s_event, 0);
return;
}*/
// Cast to dnshdr
// dns = (struct dnshdr*)buf;
}
static void dnsanswer(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp, int dport, int sport){
struct event *s_event;
struct dnshdr dns;
uint16_t tid = 0U;
uint32_t offset = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr);
size_t tlen = ntohs(udp.len);
int index = 0;
if (tlen < 0 || tlen >= 256)
return;
bpf_printk("udp len: %d", tlen);
// Load dns header
if (bpf_skb_load_bytes(skb, offset, &dns, sizeof(struct dnshdr)) < 0)
return;
// Check OpCode
uint16_t qr = ntohs(dns.flags) & 0xF000; // Get the QR code: 0 -> query, 1 -> response
if(qr != 0x8000) // Not a response, we do not continue
return;
if (ntohs(dns.nbQuestions) == 0)
return;
s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0);
if (!s_event)
return;
s_event->req_type = REQ_ANSWER;
/* Get IP header */
s_event->client = ip.daddr;
s_event->dport = dport;
s_event->sport = sport;
/* Get the Transaction ID */
s_event->tid = ntohs(dns.transactionID);
/* Get the query section */
size_t query_len = get_query_section(skb, s_event, offset);
/* Get answer section */
uint16_t ans = ntohs(dns.nbAnswerRRs);
if (ans <= 0){
bpf_ringbuf_discard(s_event, 0);
return;
}
/*if (ans > 0){
s_event->numAns = ans;
}*/
s_event->numAns = ans;
// Load query and answer
/*
* Load query and answers
* It's a little dirty to do that, to load byte by byte,
* otherwise, I have an issue with the eBPF verifier
*/
offset += sizeof(struct dnshdr) + query_len;
//offset += 2; // We bypass message compression
while (index < tlen){
bpf_skb_load_bytes(skb, offset + index, s_event->buf + index, 1);
index++;
}
bpf_ringbuf_submit(s_event, 0);
//if(bpf_skb_load_bytes(skb, offset, &buf, tlen) < 0)
// bpf_printk("Failed");
}
/*
* skb -> http://oldvger.kernel.org/~davem/skb_data.html
*/
SEC("socket")
int detect_dns(struct __sk_buff *skb) {
//void *data = (void *)(long)skb->data;
//void *data_end = (void *)(long)skb->data_end;
//struct ethhdr *eth = data;
struct ethhdr eth = {0};
struct iphdr ip = {0};
struct udphdr udp = {0};
unsigned long long h_proto, p;
unsigned long long dport;
unsigned long long sport;
__u32 h_proto, p;
__u32 dport;
__u32 sport;
//if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) > data_end)
// return 0;
//bpf_skb_load_bytes(skb, 12, &p, 2);
if (skb->len < sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr))
return 0;
bpf_skb_load_bytes(skb, 0, &eth, sizeof(struct ethhdr));
p = eth.h_proto;
if (ntohs(p) != ETH_P_IP)
return 0;
// bpf_printk("ip: %d",ntohs(p));
//ip = (struct iphdr*)(data + sizeof(struct ethhdr));
bpf_skb_load_bytes(skb, sizeof(struct ethhdr), &ip, sizeof(struct iphdr));
//bpf_skb_load_bytes(data, sizeof(struct ethhdr), ip, sizeof(struct ip));
h_proto = ip.protocol;
// If not UDP packet
if (h_proto != 17)
return 0;
// bpf_printk("proto: %d", h_proto);
//udp = (struct udphdr*)(data + sizeof(struct ethhdr) + sizeof(struct iphdr));
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr), &udp, sizeof(struct udphdr));
if (udp.len == 0)
return 0;
// Check if DNS port
dport = ntohs(udp.dest);
sport = ntohs(udp.source);
@@ -180,35 +357,8 @@ int detect_dns(struct __sk_buff *skb) {
if (dport == 53)
dnsquery(skb, eth, ip, udp, dport, sport);
else if(sport == 53)
bpf_printk("Response");
dnsanswer(skb, ip, udp, dport, sport);
return 0;
}
/*SEC("xdp")
int detect_dns(struct xdp_md *ctx){
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
struct iphdr *ip;
struct udphdr *udp;
__u16 h_proto;
__u16 dport;
if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) > data_end)
return XDP_DROP;
ip = (struct iphdr*)(data + sizeof(struct ethhdr));
udp = (struct udphdr*)(data + sizeof(struct ethhdr) + sizeof(struct iphdr));
h_proto = ip->protocol;
// If not UDP packet
if (h_proto != 17)
return XDP_PASS;
// Check if DNS port
dport = udp->dest;
bpf_printk("Dport: %d", (dport));
return XDP_PASS;
}*/
char LICENSE[] SEC("license") = "GPL";
Binary file not shown.
View File
+95390 -113538
View File
File diff suppressed because it is too large Load Diff
Executable
BIN
View File
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
#include <stdio.h>
int main(void){
char buf[128] = "Hello world!";
char t = 'a';
//char *c = buf;
char *c = &t;
printf("%c\n", *c);
*c = buf[0];
printf("%c\n", *c);
return 0;
}