diff --git a/src/common.h b/src/common.h index 58b056f..5af0e01 100644 --- a/src/common.h +++ b/src/common.h @@ -25,6 +25,14 @@ struct event { char qname[QNAME_SIZE]; int class; int type; + char ans[32]; +}; + +struct dns_answer { + uint16_t tid; + char qname[QNAME_SIZE]; + char ip[32]; + int ttl; }; #endif diff --git a/src/dns-trace.ebpf.c b/src/dns-trace.ebpf.c index 0d0ef93..a3e46b8 100644 --- a/src/dns-trace.ebpf.c +++ b/src/dns-trace.ebpf.c @@ -28,6 +28,14 @@ struct { __uint(max_entries, 256 * 1024 /* 256kb */); } m_data SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 32768); // pid_max -> https://linux.die.net/man/5/proc + __type(key, uint16_t); + __type(value, struct dns_answer); +} m_tid SEC(".maps"); + + /* * This function get the query field and the return the length of it */ @@ -84,6 +92,7 @@ static int dnsquery(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, s struct dnshdr dns = {0}; char saddr[32]; uint16_t class, type; + //struct dns_answer s_dnsanswer; // bpf_printk("udp len: %d", ntohs(udp.len)); s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0); @@ -101,7 +110,6 @@ static int dnsquery(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, s return 0; } - bpf_printk("tid: %x", ntohs(dns.transactionID)); // Use as key map bpf_printk("nb question: %d", ntohs(dns.nbQuestions)); @@ -134,6 +142,49 @@ static int dnsquery(struct __sk_buff *skb, struct ethhdr eth, struct iphdr ip, s } static int dnsanswer(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}; + uint16_t tid = 0; + struct dns_answer s_dnsanswer; + + /* Get DNS header */ + bpf_skb_load_bytes(skb, sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr), &dns, sizeof(struct dnshdr)); + + s_event = bpf_ringbuf_reserve(&m_data, sizeof(*s_event), 0); + if (!s_event) + return 0; + + /* Get the Transaction ID */ + tid = ntohs(dns.transactionID); + bpf_printk("tid: %x", tid); + + /* + * 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 query response */ + size_t tlen = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct dnshdr); + uint16_t class, type; + size_t query_len = get_query(skb, s_event, &class, &type, tlen); + bpf_printk("answer qname: %s", s_event->qname); + + /* Get the answer */ + + bpf_ringbuf_submit(s_event, 0); + return 0; } SEC("socket") @@ -180,7 +231,7 @@ 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, eth, ip, udp, dport, sport); return 0; } diff --git a/src/dns-trace.ebpf.o b/src/dns-trace.ebpf.o index 5b9f491..bdd94b2 100644 Binary files a/src/dns-trace.ebpf.o and b/src/dns-trace.ebpf.o differ