Get answer

This commit is contained in:
gbucchino 2025-01-15 16:26:53 +01:00
parent 1051b50931
commit 2cb21c1f55
3 changed files with 61 additions and 2 deletions

@ -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

@ -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;
}

Binary file not shown.