Skip to content

Commit e7874a2

Browse files
committed
dns name
1 parent e9ebab7 commit e7874a2

19 files changed

+292
-42
lines changed

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: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/netobserv/flowlogs-pipeline/pkg/config"
99
"github.com/netobserv/netobserv-ebpf-agent/pkg/model"
1010
"github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow"
11+
"github.com/netobserv/netobserv-ebpf-agent/pkg/utils"
1112

1213
"github.com/mdlayher/ethernet"
1314
log "github.com/sirupsen/logrus"
@@ -120,6 +121,9 @@ func RecordToMap(fr *model.Record) config.GenericMap {
120121
out["DnsFlags"] = fr.Metrics.AdditionalMetrics.DnsRecord.Flags
121122
out["DnsFlagsResponseCode"] = DNSRcodeToStr(uint32(fr.Metrics.AdditionalMetrics.DnsRecord.Flags) & 0xF)
122123
out["DnsLatencyMs"] = fr.DNSLatency.Milliseconds()
124+
if name := utils.DNSRawNameToDotted(fr.Metrics.AdditionalMetrics.DnsRecord.Name[:]); name != "" {
125+
out["DnsName"] = name
126+
}
123127
}
124128

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

pkg/decode/decode_protobuf_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/netobserv/flowlogs-pipeline/pkg/config"
88
"github.com/netobserv/netobserv-ebpf-agent/pkg/pbflow"
9+
"github.com/netobserv/netobserv-ebpf-agent/pkg/utils"
910

1011
"github.com/stretchr/testify/assert"
1112
"google.golang.org/protobuf/types/known/durationpb"
@@ -62,6 +63,7 @@ func TestPBFlowToMap(t *testing.T) {
6263
PktDropLatestDropCause: 4,
6364
DnsLatency: durationpb.New(someDuration),
6465
DnsId: 1,
66+
DnsName: "www.example.com",
6567
DnsFlags: 0x80,
6668
DnsErrno: 0,
6769
TimeFlowRtt: durationpb.New(someDuration),
@@ -129,6 +131,7 @@ func TestPBFlowToMap(t *testing.T) {
129131
"PktDropLatestDropCause": "SKB_DROP_REASON_PKT_TOO_SMALL",
130132
"DnsLatencyMs": someDuration.Milliseconds(),
131133
"DnsId": uint16(1),
134+
"DnsName": "www.example.com",
132135
"DnsFlags": uint16(0x80),
133136
"DnsFlagsResponseCode": "NoError",
134137
"TimeFlowRttNs": someDuration.Nanoseconds(),
@@ -157,3 +160,117 @@ func TestPBFlowToMap(t *testing.T) {
157160
"IPSecStatus": "success",
158161
}, out)
159162
}
163+
164+
func TestDnsRawNameToDotted(t *testing.T) {
165+
tests := []struct {
166+
name string
167+
input []int8
168+
expected string
169+
}{
170+
{
171+
name: "empty input",
172+
input: []int8{},
173+
expected: "",
174+
},
175+
{
176+
name: "null terminated empty",
177+
input: []int8{0},
178+
expected: "",
179+
},
180+
{
181+
name: "simple single label",
182+
input: []int8{3, 'a', 'b', 'c', 0},
183+
expected: "abc",
184+
},
185+
{
186+
name: "multiple labels",
187+
input: []int8{3, 'a', 'b', 'c', 3, 'd', 'e', 'f', 0},
188+
expected: "abc.def",
189+
},
190+
{
191+
name: "root domain",
192+
input: []int8{0},
193+
expected: "",
194+
},
195+
{
196+
name: "realistic domain name",
197+
input: []int8{3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0},
198+
expected: "www.example.com",
199+
},
200+
{
201+
name: "compression pointer stops parsing",
202+
input: []int8{3, 'a', 'b', 'c', -64, 0x12, 0}, // 0xC0 = -64 in int8
203+
expected: "abc",
204+
},
205+
{
206+
name: "compression pointer at start",
207+
input: []int8{-64, 0x12}, // 0xC0 = -64 in int8
208+
expected: "",
209+
},
210+
{
211+
name: "length exceeds buffer",
212+
input: []int8{10, 'a', 'b', 'c'},
213+
expected: "",
214+
},
215+
{
216+
name: "zero length label",
217+
input: []int8{0, 3, 'a', 'b', 'c', 0},
218+
expected: "",
219+
},
220+
{
221+
name: "null terminator in middle",
222+
input: []int8{3, 'a', 'b', 0, 3, 'd', 'e', 'f', 0},
223+
expected: "",
224+
},
225+
{
226+
name: "single character labels",
227+
input: []int8{1, 'a', 1, 'b', 1, 'c', 0},
228+
expected: "a.b.c",
229+
},
230+
{
231+
name: "long label",
232+
input: []int8{10, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 0},
233+
expected: "abcdefghij",
234+
},
235+
{
236+
name: "mixed case",
237+
input: []int8{3, 'A', 'b', 'C', 3, 'D', 'e', 'F', 0},
238+
expected: "AbC.DeF",
239+
},
240+
{
241+
name: "numbers and special chars",
242+
input: []int8{5, 't', 'e', 's', 't', '1', 3, 'a', 'b', 'c', 0},
243+
expected: "test1.abc",
244+
},
245+
{
246+
name: "incomplete label at end",
247+
input: []int8{3, 'a', 'b', 'c', 5, 'd', 'e'},
248+
expected: "abc",
249+
},
250+
{
251+
name: "multiple compression pointers",
252+
input: []int8{3, 'a', 'b', 'c', -64, 0x12, -64, 0x34, 0}, // 0xC0 = -64 in int8
253+
expected: "abc",
254+
},
255+
{
256+
name: "very long input with early null",
257+
input: func() []int8 {
258+
result := make([]int8, 1000)
259+
result[0] = 3
260+
result[1] = 'a'
261+
result[2] = 'b'
262+
result[3] = 'c'
263+
result[4] = 0
264+
return result
265+
}(),
266+
expected: "abc",
267+
},
268+
}
269+
270+
for _, tt := range tests {
271+
t.Run(tt.name, func(t *testing.T) {
272+
result := utils.DNSRawNameToDotted(tt.input)
273+
assert.Equal(t, tt.expected, result)
274+
})
275+
}
276+
}

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)