Skip to content

Commit e7fe3e5

Browse files
committed
dns name
1 parent e9ebab7 commit e7fe3e5

18 files changed

+140
-42
lines changed

.mk/bc.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ define MAPS
3434
"additional_flow_metrics":"per_cpu_hash",
3535
"packet_record":"ringbuf",
3636
"dns_flows":"hash",
37+
"dns_parse_buffer_map":"percpu_array",
3738
"global_counters":"per_cpu_array",
3839
"filter_map":"lpm_trie",
3940
"peer_filter_map":"lpm_trie",

bpf/dns_tracker.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#define DNS_DEFAULT_PORT 53
1010
#define DNS_QR_FLAG 0x8000
11+
#define DNS_OPCODE_MASK 0x7800
12+
#define DNS_RCODE_MASK 0x0F
1113
#define UDP_MAXMSG 512
1214

1315
// See https://www.rfc-editor.org/rfc/rfc1035 4.1.1. Header section format
@@ -108,6 +110,14 @@ static __always_inline int track_dns_packet(struct __sk_buff *skb, pkt_info *pkt
108110
}
109111
pkt->dns_id = dns_id;
110112
pkt->dns_flags = flags;
113+
114+
// Copy raw QNAME bytes (label-encoded) and let userspace decode to dotted form
115+
__builtin_memset(pkt->dns_name, 0, DNS_NAME_MAX_LEN);
116+
u32 qname_off = dns_offset + sizeof(struct dns_header);
117+
// Best-effort fixed-size copy; safe for verifier (constant size)
118+
(void)bpf_skb_load_bytes(skb, qname_off, pkt->dns_name, DNS_NAME_MAX_LEN - 1);
119+
// Ensure null-termination
120+
pkt->dns_name[DNS_NAME_MAX_LEN - 1] = '\0';
111121
} // end of dns response
112122
}
113123
return ret;

bpf/flows.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ static inline void update_dns(additional_metrics *extra_metrics, pkt_info *pkt,
118118
extra_metrics->dns_record.id = pkt->dns_id;
119119
extra_metrics->dns_record.flags = pkt->dns_flags;
120120
extra_metrics->dns_record.latency = pkt->dns_latency;
121+
__builtin_memcpy(extra_metrics->dns_record.name, pkt->dns_name, DNS_NAME_MAX_LEN);
121122
}
122123
if (dns_errno != 0) {
123124
extra_metrics->dns_record.errno = dns_errno;
@@ -253,6 +254,7 @@ static inline int flow_monitor(struct __sk_buff *skb, u8 direction) {
253254
new_metrics.dns_record.id = pkt.dns_id;
254255
new_metrics.dns_record.flags = pkt.dns_flags;
255256
new_metrics.dns_record.latency = pkt.dns_latency;
257+
__builtin_memcpy(new_metrics.dns_record.name, pkt.dns_name, DNS_NAME_MAX_LEN);
256258
new_metrics.dns_record.errno = dns_errno;
257259
long ret =
258260
bpf_map_update_elem(&additional_flow_metrics, &id, &new_metrics, BPF_NOEXIST);

bpf/types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ typedef __u64 u64;
7070
#define OBSERVED_DIRECTION_BOTH 3
7171

7272
#define MAX_PAYLOAD_SIZE 256
73+
#define DNS_NAME_MAX_LEN 32
7374

7475
// according to field 61 in https://www.iana.org/assignments/ipfix/ipfix.xhtml
7576
typedef enum direction_t {
@@ -123,6 +124,7 @@ typedef struct additional_metrics_t {
123124
u16 id;
124125
u16 flags;
125126
u8 errno;
127+
char name[DNS_NAME_MAX_LEN];
126128
} dns_record;
127129
struct pkt_drops_t {
128130
u64 bytes;
@@ -192,6 +194,7 @@ typedef struct pkt_info_t {
192194
u16 dns_id;
193195
u16 dns_flags;
194196
u64 dns_latency;
197+
char dns_name[DNS_NAME_MAX_LEN];
195198
} pkt_info;
196199

197200
// Structure for payload metadata

pkg/decode/decode_protobuf.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,46 @@ const (
2626
type Protobuf struct {
2727
}
2828

29+
// dnsRawNameToDotted parses a label-encoded DNS QNAME (raw bytes copied from kernel)
30+
// into a dotted string. Stops on NUL, compression pointer, or bounds.
31+
func dnsRawNameToDotted(rawI8 []int8) string {
32+
// Convert to byte slice up to first NUL
33+
b := make([]byte, 0, len(rawI8))
34+
for i := 0; i < len(rawI8); i++ {
35+
if rawI8[i] == 0 { // NUL terminator placed in kernel copy
36+
break
37+
}
38+
b = append(b, byte(rawI8[i]))
39+
}
40+
if len(b) == 0 {
41+
return ""
42+
}
43+
out := make([]byte, 0, len(b))
44+
i := 0
45+
first := true
46+
for i < len(b) {
47+
l := int(b[i])
48+
if l == 0 {
49+
break
50+
}
51+
// Stop on compression pointer (0xC0xx) since we didn't follow it in kernel
52+
if (l & 0xC0) == 0xC0 {
53+
break
54+
}
55+
i++
56+
if i+l > len(b) {
57+
break
58+
}
59+
if !first {
60+
out = append(out, '.')
61+
}
62+
first = false
63+
out = append(out, b[i:i+l]...)
64+
i += l
65+
}
66+
return string(out)
67+
}
68+
2969
func NewProtobuf() (*Protobuf, error) {
3070
log.Debugf("entering NewProtobuf")
3171
return &Protobuf{}, nil
@@ -120,6 +160,9 @@ func RecordToMap(fr *model.Record) config.GenericMap {
120160
out["DnsFlags"] = fr.Metrics.AdditionalMetrics.DnsRecord.Flags
121161
out["DnsFlagsResponseCode"] = DNSRcodeToStr(uint32(fr.Metrics.AdditionalMetrics.DnsRecord.Flags) & 0xF)
122162
out["DnsLatencyMs"] = fr.DNSLatency.Milliseconds()
163+
if name := dnsRawNameToDotted(fr.Metrics.AdditionalMetrics.DnsRecord.Name[:]); name != "" {
164+
out["DnsName"] = name
165+
}
123166
}
124167

125168
if fr.Metrics.AdditionalMetrics.PktDrops.LatestDropCause != 0 {

pkg/ebpf/bpf_arm64_bpfel.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/ebpf/bpf_arm64_bpfel.o

2.48 KB
Binary file not shown.

pkg/ebpf/bpf_powerpc_bpfel.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/ebpf/bpf_powerpc_bpfel.o

2.48 KB
Binary file not shown.

pkg/ebpf/bpf_s390_bpfeb.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)