13 Commits

Author SHA1 Message Date
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 96054 additions and 113832 deletions
+3 -2
View File
@@ -1,12 +1,13 @@
GCC=gcc GCC=gcc
CL=clang-11 CL=clang-11
CFLAGS=-Wall CFLAGS=-Wall
LIBS=-lbpf LIBS=-L../libbpf/src -l:libbpf.a -lelf -lz
#LIBS=-lbpf
all: dns-trace.ebpf.o dns-trace all: dns-trace.ebpf.o dns-trace
dns-trace.ebpf.o: src/dns-trace.ebpf.c 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 dns-trace: src/dns-trace.c
$(GCC) $(CFLAGS) src/dns-trace.c -o dns-trace $(LIBS) $(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 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 { struct dnshdr {
uint16_t transactionID; uint16_t transactionID;
uint16_t flags; uint16_t flags;
@@ -12,19 +19,31 @@ struct dnshdr {
uint16_t nbAdditionalRRs; uint16_t nbAdditionalRRs;
}; };
/*struct dns_query {
char *name;
uint16_t type;
uint16_t class;
};*/
struct event { struct event {
uint32_t saddr; uint32_t client;
int dport; int dport;
int sport; int sport;
uint16_t tid;
int req_type;
char qname[QNAME_SIZE]; char qname[QNAME_SIZE];
int class; uint16_t class;
int type; 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 #endif
+114 -35
View File
@@ -101,93 +101,171 @@ static int open_raw_sock(const char *name)
return sock; 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){ switch(class){
case 1: case 1:
printf("IN\n"); strncpy(tmp, "IN", 3);
break; break;
case 2: case 2:
printf("CS\n"); strncpy(tmp, "CS", 3);
break; break;
case 3: case 3:
printf("CH\n"); strncpy(tmp, "CH", 3);
break; break;
case 4: case 4:
printf("HS\n"); strncpy(tmp, "HS", 3);
break; break;
default: default:
printf("Unknown\n"); strncpy(tmp, "Unknown", 8);
break; 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){ switch(type){
case 1: case 1:
printf("A"); strncpy(tmp, "A", 2);
break; break;
case 2: case 2:
printf("NS"); strncpy(tmp, "NS", 3);
break; break;
case 3: case 3:
printf("MD"); strncpy(tmp, "MD", 3);
break; break;
case 4: case 4:
printf("MF"); strncpy(tmp, "MF", 3);
break; break;
case 5: case 5:
printf("CNAME"); strncpy(tmp, "CNAME", 6);
break; break;
case 6: case 6:
printf("SOA"); strncpy(tmp, "SOA", 4);
break; break;
case 7: case 7:
printf("MB"); strncpy(tmp, "MB", 3);
break; break;
case 8: case 8:
printf("MG"); strncpy(tmp, "MG", 3);
break; break;
case 9: case 9:
printf("MR"); strncpy(tmp, "MR", 3);
break; break;
case 10: case 10:
printf("NULL"); strncpy(tmp, "NULL", 5);
break; break;
case 11: case 11:
printf("WKS"); strncpy(tmp, "WKS", 4);
break; break;
case 12: case 12:
printf("PTR"); strncpy(tmp, "PTR", 4);
break; break;
case 13: case 13:
printf("HINFO"); strncpy(tmp, "HINFO", 6);
break; break;
case 14: case 14:
printf("MINFO"); strncpy(tmp, "MINFO", 6);
break; break;
case 15: case 15:
printf("MX"); strncpy(tmp, "MX", 3);
break; break;
case 16: case 16:
printf("TXT"); strncpy(tmp, "TXT", 4);
break;
case 28:
strncpy(tmp, "AAAA", 5);
break; break;
default: default:
printf("Unknown\n"); strncpy(tmp, "Unknown", 8);
break; 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);
}
int handle_event(void *ctx, void *data, size_t data_sz){ int handle_event(void *ctx, void *data, size_t data_sz){
struct event *s_event = (struct event*)data; struct event *s_event = (struct event*)data;
printf("IP: %s\n", inet_ntoa(*(struct in_addr*)&s_event->saddr)); if (s_event->req_type == REQ_QUERY){
printf("dport: %d\n", s_event->dport); print_query(s_event);
printf("sport: %d\n", s_event->sport); }
printf("qname: %s\n", s_event->qname); if (s_event->req_type == REQ_ANSWER){
printf("Class: "); int pos = 0;
mapClass(s_event->class); //for(int i = 0; i < 32; i++)
printf("Type: "); // printf("%d ", s_event->buf[i]);
mapType(s_event->type); //printf("\n");
for (int i = 0; i < s_event->numAns; i++){
print_query(s_event);
uint16_t type2 = (s_event->buf[pos++]) + (s_event->buf[pos++] << 8);
uint16_t class2 = (s_event->buf[pos++]) + (s_event->buf[pos++] << 8);
uint32_t ttl2 = (s_event->buf[pos++]) + (s_event->buf[pos++] << 8) + (s_event->buf[pos++] << 16) + (s_event->buf[pos++] << 24);
uint16_t size2 = (s_event->buf[pos++]) + (s_event->buf[pos++] << 8);
type2 = ntohs(type2);
class2 = ntohs(class2);
ttl2 = ntohl(ttl2);
size2 = ntohs(size2);
if (type2 == 1) {// -> A
uint32_t ip = s_event->buf[pos++] + (s_event->buf[pos++] << 8) + (s_event->buf[pos++] << 16) + (s_event->buf[pos++] << 24);
printf("%s (%d)%5d", inet_ntoa(*(struct in_addr*)&ip), type2, ttl2);
}
if (type2 == 28){ // -> AAAA
}
printf("\n"); printf("\n");
printf("%d\n", pos);
}
}
printf("\n");
return 0; return 0;
} }
int main(int argc, char *argv[]){ int main(int argc, char *argv[]){
@@ -233,8 +311,9 @@ int main(int argc, char *argv[]){
} }
bpf_program__attach(programSkb); bpf_program__attach(programSkb);
//int sock = open_raw_sock("wlp0s20f3"); // 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); printf("Socket: %d\n", sock);
int prog_fd = bpf_program__fd(programSkb); int prog_fd = bpf_program__fd(programSkb);
printf("Program fd: %d\n", prog_fd); printf("Program fd: %d\n", prog_fd);
+293 -54
View File
@@ -2,6 +2,7 @@
#define __TARGET_ARCH_x86 #define __TARGET_ARCH_x86
#include <linux/bpf.h> #include <linux/bpf.h>
#include <bpf/bpf_helpers.h> #include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_tracing.h> #include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h> #include <bpf/bpf_core_read.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
@@ -28,19 +29,45 @@ struct {
__uint(max_entries, 256 * 1024 /* 256kb */); __uint(max_entries, 256 * 1024 /* 256kb */);
} m_data SEC(".maps"); } m_data SEC(".maps");
/* struct {
* This function get the query field and the return the length of it __uint(type, BPF_MAP_TYPE_HASH);
*/ __uint(max_entries, 32768);
static size_t get_query(struct __sk_buff *skb, struct event *s_event, uint16_t *class, uint16_t *type, size_t tlen){ __type(key, uint16_t);
size_t len; __type(value, struct dns_answer);
char buf[QNAME_SIZE] = {0}; } m_tid SEC(".maps");
int index = 0;
int qname_len = 0; // Full length of the qname field static size_t get_labels2(struct __sk_buff *skb, size_t offset, struct event *s_event){
char qname[QNAME_SIZE] = {0}; char c;
int qname_len = 0;
//bpf_printk("labels off: %d", offset);
bpf_skb_load_bytes(skb, offset, &c, 1); // Get the first byte, which is the length
int pos = 1;
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
s_event->qname[qname_len] = '.';
qname_len++;
if (pos == 128 || c == '\0')
break;
}
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;
}
static size_t get_labels(struct __sk_buff *skb, size_t offset, size_t end, struct event *s_event, struct query_section *s_query){
//size_t len;
char buf[256] = {0};
char *c; char *c;
int index = 0;
size_t qname_len = 0; // Full length of the qname field
bpf_skb_load_bytes(skb, offset, &buf, 41);
bpf_skb_load_bytes(skb, tlen, &buf, 41);
c = buf; c = buf;
/* /*
@@ -64,93 +91,302 @@ static size_t get_query(struct __sk_buff *skb, struct event *s_event, uint16_t *
} }
s_event->qname[--index] = '\0'; s_event->qname[--index] = '\0';
qname_len++; // For the null character qname_len++; // For the null character
bpf_printk("%s (%d) %d", s_event->qname, index, qname_len); bpf_printk("qname: %s", s_event->qname);
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_labels2(skb, offset, s_event);
// Get class and type // Get class and type
len = qname_len; 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; 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; len += 2;
return len; 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_labels2(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 * 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){ 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 event *s_event;
struct dnshdr dns = {0}; struct dnshdr dns = {0};
char saddr[32]; struct query_section dquery = {0};
uint16_t class, type;
// bpf_printk("udp len: %d", ntohs(udp.len)); /* 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); s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0);
if (!s_event) if (!s_event)
return 0; return 0;
s_event->req_type = REQ_QUERY;
/* Get IP header */ /* Get IP header */
s_event->saddr = ip.saddr; s_event->client = ip.saddr;
/* Get DNS header */ s_event->tid = ntohs(dns.transactionID);
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr), &dns, sizeof(struct dnshdr));
if (ntohs(dns.nbQuestions) == 0){ /* Get the query section */
bpf_ringbuf_discard(s_event, 0); uint8_t tlen = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr);
return 0; size_t query_len = get_query_section(skb, s_event, tlen);
}
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);
// https://docs.cilium.io/en/stable/reference-guides/bpf/progtypes/ // https://docs.cilium.io/en/stable/reference-guides/bpf/progtypes/
s_event->dport = dport; s_event->dport = dport;
s_event->sport = sport; 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); bpf_ringbuf_submit(s_event, 0);
return 0; return 0;
} }
static int dnsanswer(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, struct udphdr udp, int dport, int sport){ static void dnsanswer_old(struct __sk_buff *skb, struct iphdr ip, struct udphdr udp, int dport, int sport){
return 0; 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;
} }
/*
TODO: je recupere tout le skb->data, grace au skb->len
grace a ca, j'aurai tout le payload udp et toute les donnees dns
je pourrai facilement parcourir les data
*/
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);
// Load dns header
if (bpf_skb_load_bytes(skb, offset, &dns, 12) < 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){
/*
* We get a least the 5 last answer
* In the RFC 1035 (https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.4) the max udp payload is 512 bytes
* The program limit size of the answer
*/
offset += sizeof(struct dnshdr) + query_len; // For the pos in the answer section in the skb
unsigned int offset_ans = 0;
for (uint16_t i = 0; i < ans; i++){
offset_ans += get_answer(skb, s_event, offset, offset_ans);
offset += offset_ans + 2; // +2 for the message compression
//offset_ans += offset_ans;
// For eBPF verifier, to be sure we leave the loop
if (i == ans || i == 5 || offset_ans >= 512)
break;
}
s_event->numAns = ans;
}
if (ntohs(dns.nbAuthorityRRs) > 0){
}
/*
* In the user space, if the haven't have the answer, we can have an error
* The solution is to push to the ring buffer and the answer is store in
* the struct event
* Or, we push to the ring buffer and the query only with the map
* but, if we haven't have the answer, we need print the query
*/
/*
Pour recuperer les infos:
1 - dans le getquery, on push dans le ringbuffer et dans le userspace, on recupere aussi la reponse
mais si la reponse, nous l'avons pas encore, ca fail et dans le get answer on push dans une map
2 - on push dans le ring buffer quand on a la reponse avec la requette car c'est dans le field query
cependant, si on a pas la reponse, on n'aura jamais la query
3 - dans le get query et get answer, on push dans le ring buffer et tout est store dans le struct event
*/
/* Get the answer */
bpf_ringbuf_submit(s_event, 0);
}
/*
* skb -> http://oldvger.kernel.org/~davem/skb_data.html
*/
SEC("socket") SEC("socket")
int detect_dns(struct __sk_buff *skb) { int detect_dns(struct __sk_buff *skb) {
//void *data = (void *)(long)skb->data; //void *data = (void *)(long)skb->data;
//void *data_end = (void *)(long)skb->data_end; //void *data_end = (void *)(long)skb->data_end;
//struct ethhdr *eth = data; //struct ethhdr *eth2 = data;
struct ethhdr eth = {0}; struct ethhdr eth = {0};
struct iphdr ip = {0}; struct iphdr ip = {0};
struct udphdr udp = {0}; struct udphdr udp = {0};
unsigned long long h_proto, p; __u32 h_proto, p;
unsigned long long dport; __u32 dport;
unsigned long long sport; __u32 sport;
//if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) > data_end) //if (data + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) > data_end)
// return 0; // return 0;
if (skb->len < sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr))
return 0;
//bpf_skb_load_bytes(skb, 12, &p, 2); //bpf_skb_load_bytes(skb, 12, &p, 2);
bpf_skb_load_bytes(skb, 0, &eth, sizeof(struct ethhdr)); bpf_skb_load_bytes(skb, 0, &eth, sizeof(struct ethhdr));
p = eth.h_proto; p = eth.h_proto;
@@ -173,6 +409,9 @@ int detect_dns(struct __sk_buff *skb) {
bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr), &udp, sizeof(struct udphdr)); 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 // Check if DNS port
dport = ntohs(udp.dest); dport = ntohs(udp.dest);
sport = ntohs(udp.source); sport = ntohs(udp.source);
@@ -180,7 +419,7 @@ int detect_dns(struct __sk_buff *skb) {
if (dport == 53) if (dport == 53)
dnsquery(skb, eth, ip, udp, dport, sport); dnsquery(skb, eth, ip, udp, dport, sport);
else if(sport == 53) else if(sport == 53)
bpf_printk("Response"); dnsanswer(skb, ip, udp, dport, sport);
return 0; return 0;
} }
Binary file not shown.
View File
+95432 -113580
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;
}