1use std::{collections::BTreeMap, sync::LazyLock};
2
3use vector_lib::lookup::{owned_value_path, OwnedValuePath};
4use vrl::btreemap;
5use vrl::value::{
6 kind::{Collection, Field},
7 Kind,
8};
9
10#[derive(Debug, Default, Clone)]
11pub struct DnstapEventSchema;
12
13impl DnstapEventSchema {
14 pub(crate) fn request_message_schema_definition(&self) -> Collection<Field> {
16 let mut result: BTreeMap<Field, Kind> = BTreeMap::new();
17 result.insert(
18 DNSTAP_VALUE_PATHS.time.to_string().into(),
19 Kind::integer().or_undefined(),
20 );
21
22 result.insert(
23 DNSTAP_VALUE_PATHS.time.to_string().into(),
24 Kind::integer().or_undefined(),
25 );
26 result.insert(
27 DNSTAP_VALUE_PATHS.time_precision.to_string().into(),
28 Kind::bytes().or_undefined(),
29 );
30 result.insert(
31 DNSTAP_VALUE_PATHS.time_precision.to_string().into(),
32 Kind::bytes().or_undefined(),
33 );
34 result.insert(
35 DNSTAP_VALUE_PATHS.response_code.to_string().into(),
36 Kind::integer().or_undefined(),
37 );
38 result.insert(
39 DNSTAP_VALUE_PATHS.response_code.to_string().into(),
40 Kind::integer().or_undefined(),
41 );
42 result.insert(
43 DNSTAP_VALUE_PATHS.response.to_string().into(),
44 Kind::bytes().or_undefined(),
45 );
46 result.insert(
47 DNSTAP_VALUE_PATHS.response.to_string().into(),
48 Kind::bytes().or_undefined(),
49 );
50
51 let mut schema = DnsQueryHeaderSchema::schema_definition();
52 schema.merge(DnsUpdateHeaderSchema::schema_definition(), true);
53
54 result.insert(
55 DNSTAP_VALUE_PATHS.header.to_string().into(),
56 Kind::object(schema).or_undefined(),
57 );
58
59 result.insert(
60 DNSTAP_VALUE_PATHS.zone_section.to_string().into(),
61 Kind::object(DnsUpdateZoneInfoSchema::schema_definition()).or_undefined(),
62 );
63
64 result.insert(
65 DNSTAP_VALUE_PATHS.question_section.to_string().into(),
66 Kind::array(Collection::from_unknown(Kind::object(
67 DnsQueryQuestionSchema::schema_definition(),
68 )))
69 .or_undefined(),
70 );
71
72 result.insert(
73 DNSTAP_VALUE_PATHS.answer_section.to_string().into(),
74 Kind::array(Collection::from_unknown(Kind::object(
75 DnsRecordSchema::schema_definition(),
76 )))
77 .or_undefined(),
78 );
79
80 result.insert(
81 DNSTAP_VALUE_PATHS.authority_section.to_string().into(),
82 Kind::array(Collection::from_unknown(Kind::object(
83 DnsRecordSchema::schema_definition(),
84 )))
85 .or_undefined(),
86 );
87
88 result.insert(
89 DNSTAP_VALUE_PATHS.additional_section.to_string().into(),
90 Kind::array(Collection::from_unknown(Kind::object(
91 DnsRecordSchema::schema_definition(),
92 )))
93 .or_undefined(),
94 );
95
96 result.insert(
97 DNSTAP_VALUE_PATHS.opt_pseudo_section.to_string().into(),
98 Kind::object(DnsMessageOptPseudoSectionSchema::schema_definition()).or_undefined(),
99 );
100
101 result.insert(
102 DNSTAP_VALUE_PATHS.raw_data.to_string().into(),
103 Kind::bytes().or_undefined(),
104 );
105
106 result.insert(
107 DNSTAP_VALUE_PATHS.prerequisite_section.to_string().into(),
108 Kind::array(Collection::from_unknown(Kind::object(
109 DnsRecordSchema::schema_definition(),
110 )))
111 .or_undefined(),
112 );
113
114 result.insert(
115 DNSTAP_VALUE_PATHS.update_section.to_string().into(),
116 Kind::array(Collection::from_unknown(Kind::object(
117 DnsRecordSchema::schema_definition(),
118 )))
119 .or_undefined(),
120 );
121
122 result.insert(
123 DNSTAP_VALUE_PATHS.additional_section.to_string().into(),
124 Kind::array(Collection::from_unknown(Kind::object(
125 DnsRecordSchema::schema_definition(),
126 )))
127 .or_undefined(),
128 );
129
130 result.into()
131 }
132
133 fn root_schema_definition(
135 &self,
136 schema: vector_lib::schema::Definition,
137 ) -> vector_lib::schema::Definition {
138 schema
139 .optional_field(&DNSTAP_VALUE_PATHS.server_identity, Kind::bytes(), None)
140 .optional_field(&DNSTAP_VALUE_PATHS.server_version, Kind::bytes(), None)
141 .optional_field(&DNSTAP_VALUE_PATHS.extra, Kind::bytes(), None)
142 .with_event_field(&DNSTAP_VALUE_PATHS.data_type_id, Kind::integer(), None)
143 .optional_field(&DNSTAP_VALUE_PATHS.data_type, Kind::bytes(), None)
144 .optional_field(&DNSTAP_VALUE_PATHS.error, Kind::bytes(), None)
145 .optional_field(&DNSTAP_VALUE_PATHS.raw_data, Kind::bytes(), None)
146 .optional_field(&DNSTAP_VALUE_PATHS.time, Kind::integer(), None)
147 .optional_field(&DNSTAP_VALUE_PATHS.time_precision, Kind::bytes(), None)
148 }
149
150 pub fn message_schema_definition(
152 &self,
153 schema: vector_lib::schema::Definition,
154 ) -> vector_lib::schema::Definition {
155 schema
156 .optional_field(&DNSTAP_VALUE_PATHS.socket_family, Kind::bytes(), None)
157 .optional_field(&DNSTAP_VALUE_PATHS.socket_protocol, Kind::bytes(), None)
158 .optional_field(&DNSTAP_VALUE_PATHS.query_address, Kind::bytes(), None)
159 .optional_field(&DNSTAP_VALUE_PATHS.query_port, Kind::integer(), None)
160 .optional_field(&DNSTAP_VALUE_PATHS.response_address, Kind::bytes(), None)
161 .optional_field(&DNSTAP_VALUE_PATHS.response_port, Kind::integer(), None)
162 .optional_field(&DNSTAP_VALUE_PATHS.query_zone, Kind::bytes(), None)
163 .with_event_field(&DNSTAP_VALUE_PATHS.message_type_id, Kind::integer(), None)
164 .optional_field(&DNSTAP_VALUE_PATHS.message_type, Kind::bytes(), None)
165 .optional_field(
166 &DNSTAP_VALUE_PATHS.request_message,
167 Kind::object(self.request_message_schema_definition()),
168 None,
169 )
170 .optional_field(
171 &DNSTAP_VALUE_PATHS.response_message,
172 Kind::object(self.request_message_schema_definition()),
173 None,
174 )
175 }
176
177 pub fn schema_definition(
179 &self,
180 schema: vector_lib::schema::Definition,
181 ) -> vector_lib::schema::Definition {
182 self.root_schema_definition(self.message_schema_definition(schema))
183 }
184}
185
186#[derive(Debug, Clone)]
188pub struct DnstapPaths {
189 pub server_identity: OwnedValuePath,
191 pub server_version: OwnedValuePath,
192 pub extra: OwnedValuePath,
193 pub data_type: OwnedValuePath,
194 pub data_type_id: OwnedValuePath,
195 pub time: OwnedValuePath,
196 pub time_precision: OwnedValuePath,
197 pub error: OwnedValuePath,
198 pub raw_data: OwnedValuePath,
199
200 pub socket_family: OwnedValuePath,
202 pub socket_protocol: OwnedValuePath,
203 pub query_address: OwnedValuePath,
204 pub query_port: OwnedValuePath,
205 pub response_address: OwnedValuePath,
206 pub response_port: OwnedValuePath,
207 pub query_zone: OwnedValuePath,
208 pub message_type: OwnedValuePath,
209 pub message_type_id: OwnedValuePath,
210 pub request_message: OwnedValuePath,
211 pub response_message: OwnedValuePath,
212
213 pub response_code: OwnedValuePath,
215 pub response: OwnedValuePath,
216 pub header: OwnedValuePath,
217 pub question_section: OwnedValuePath,
218 pub answer_section: OwnedValuePath,
219 pub authority_section: OwnedValuePath,
220 pub additional_section: OwnedValuePath,
221 pub opt_pseudo_section: OwnedValuePath,
222
223 pub zone_section: OwnedValuePath,
225 pub prerequisite_section: OwnedValuePath,
226 pub update_section: OwnedValuePath,
227
228 pub id: OwnedValuePath,
230 pub opcode: OwnedValuePath,
231 pub rcode: OwnedValuePath,
232 pub qr: OwnedValuePath,
233
234 pub aa: OwnedValuePath,
236 pub tc: OwnedValuePath,
237 pub rd: OwnedValuePath,
238 pub ra: OwnedValuePath,
239 pub ad: OwnedValuePath,
240 pub cd: OwnedValuePath,
241 pub question_count: OwnedValuePath,
242 pub answer_count: OwnedValuePath,
243 pub authority_count: OwnedValuePath,
244 pub ar_count: OwnedValuePath,
245
246 pub zone_count: OwnedValuePath,
248 pub prerequisite_count: OwnedValuePath,
249 pub update_count: OwnedValuePath,
250 pub ad_count: OwnedValuePath,
251
252 pub extended_rcode: OwnedValuePath,
254 pub version: OwnedValuePath,
255 pub do_flag: OwnedValuePath,
256 pub udp_max_payload_size: OwnedValuePath,
257 pub ede: OwnedValuePath,
258 pub options: OwnedValuePath,
259
260 pub info_code: OwnedValuePath,
262 pub purpose: OwnedValuePath,
263 pub extra_text: OwnedValuePath,
264
265 pub opt_code: OwnedValuePath,
267 pub opt_name: OwnedValuePath,
268 pub opt_data: OwnedValuePath,
269
270 pub domain_name: OwnedValuePath,
272 pub record_type: OwnedValuePath,
273 pub record_type_id: OwnedValuePath,
274 pub ttl: OwnedValuePath,
275 pub class: OwnedValuePath,
276 pub rdata: OwnedValuePath,
277 pub rdata_bytes: OwnedValuePath,
278
279 pub question_type: OwnedValuePath,
281 pub question_type_id: OwnedValuePath,
282
283 pub zone_name: OwnedValuePath,
285 pub zone_class: OwnedValuePath,
286 pub zone_type: OwnedValuePath,
287 pub zone_type_id: OwnedValuePath,
288}
289
290pub static DNSTAP_VALUE_PATHS: LazyLock<DnstapPaths> = LazyLock::new(|| DnstapPaths {
292 server_identity: owned_value_path!("serverId"),
293 server_version: owned_value_path!("serverVersion"),
294 extra: owned_value_path!("extraInfo"),
295 data_type: owned_value_path!("dataType"),
296 data_type_id: owned_value_path!("dataTypeId"),
297 time: owned_value_path!("time"),
298 time_precision: owned_value_path!("timePrecision"),
299 error: owned_value_path!("error"),
300 raw_data: owned_value_path!("rawData"),
301 socket_family: owned_value_path!("socketFamily"),
302 socket_protocol: owned_value_path!("socketProtocol"),
303 query_address: owned_value_path!("sourceAddress"),
304 query_port: owned_value_path!("sourcePort"),
305 response_address: owned_value_path!("responseAddress"),
306 response_port: owned_value_path!("responsePort"),
307 query_zone: owned_value_path!("queryZone"),
308 message_type: owned_value_path!("messageType"),
309 message_type_id: owned_value_path!("messageTypeId"),
310 request_message: owned_value_path!("requestData"),
311 response_message: owned_value_path!("responseData"),
312 response_code: owned_value_path!("fullRcode"),
313 response: owned_value_path!("rcodeName"),
314 header: owned_value_path!("header"),
315 question_section: owned_value_path!("question"),
316 answer_section: owned_value_path!("answers"),
317 authority_section: owned_value_path!("authority"),
318 additional_section: owned_value_path!("additional"),
319 opt_pseudo_section: owned_value_path!("opt"),
320 zone_section: owned_value_path!("zone"),
321 prerequisite_section: owned_value_path!("prerequisite"),
322 update_section: owned_value_path!("update"),
323 id: owned_value_path!("id"),
324 opcode: owned_value_path!("opcode"),
325 rcode: owned_value_path!("rcode"),
326 qr: owned_value_path!("qr"),
327 aa: owned_value_path!("aa"),
328 tc: owned_value_path!("tc"),
329 rd: owned_value_path!("rd"),
330 ra: owned_value_path!("ra"),
331 ad: owned_value_path!("ad"),
332 cd: owned_value_path!("cd"),
333 question_count: owned_value_path!("qdCount"),
334 answer_count: owned_value_path!("anCount"),
335 authority_count: owned_value_path!("nsCount"),
336 ar_count: owned_value_path!("arCount"),
337 zone_count: owned_value_path!("zoCount"),
338 prerequisite_count: owned_value_path!("prCount"),
339 update_count: owned_value_path!("upCount"),
340 ad_count: owned_value_path!("adCount"),
341 extended_rcode: owned_value_path!("extendedRcode"),
342 version: owned_value_path!("ednsVersion"),
343 do_flag: owned_value_path!("do"),
344 udp_max_payload_size: owned_value_path!("udpPayloadSize"),
345 ede: owned_value_path!("ede"),
346 options: owned_value_path!("options"),
347 info_code: owned_value_path!("infoCode"),
348 purpose: owned_value_path!("purpose"),
349 extra_text: owned_value_path!("extraText"),
350 opt_code: owned_value_path!("optCode"),
351 opt_name: owned_value_path!("optName"),
352 opt_data: owned_value_path!("optValue"),
353 record_type: owned_value_path!("recordType"),
354 record_type_id: owned_value_path!("recordTypeId"),
355 ttl: owned_value_path!("ttl"),
356 class: owned_value_path!("class"),
357 rdata: owned_value_path!("rData"),
358 rdata_bytes: owned_value_path!("rDataBytes"),
359 domain_name: owned_value_path!("domainName"),
360 question_type: owned_value_path!("questionType"),
361 question_type_id: owned_value_path!("questionTypeId"),
362 zone_name: owned_value_path!("zName"),
363 zone_class: owned_value_path!("zClass"),
364 zone_type: owned_value_path!("zType"),
365 zone_type_id: owned_value_path!("zTypeId"),
366});
367
368#[derive(Debug, Default, Clone)]
369pub struct DnsQueryHeaderSchema;
370
371impl DnsQueryHeaderSchema {
372 pub fn schema_definition() -> Collection<Field> {
373 btreemap! {
374 DNSTAP_VALUE_PATHS.id.to_string() => Kind::integer(),
375 DNSTAP_VALUE_PATHS.opcode.to_string() => Kind::integer(),
376 DNSTAP_VALUE_PATHS.rcode.to_string() => Kind::integer(),
377 DNSTAP_VALUE_PATHS.qr.to_string() => Kind::integer(),
378 DNSTAP_VALUE_PATHS.aa.to_string() => Kind::boolean(),
379 DNSTAP_VALUE_PATHS.tc.to_string() => Kind::boolean(),
380 DNSTAP_VALUE_PATHS.rd.to_string() => Kind::boolean(),
381 DNSTAP_VALUE_PATHS.ra.to_string() => Kind::boolean(),
382 DNSTAP_VALUE_PATHS.ad.to_string() => Kind::boolean(),
383 DNSTAP_VALUE_PATHS.cd.to_string() => Kind::boolean(),
384 DNSTAP_VALUE_PATHS.ar_count.to_string() => Kind::integer().or_undefined(),
385 DNSTAP_VALUE_PATHS.question_count.to_string() => Kind::integer().or_undefined(),
386 DNSTAP_VALUE_PATHS.answer_count.to_string() => Kind::integer().or_undefined(),
387 DNSTAP_VALUE_PATHS.authority_count.to_string() => Kind::integer().or_undefined(),
388 }
389 .into()
390 }
391}
392
393#[derive(Debug, Default, Clone)]
394pub struct DnsUpdateHeaderSchema;
395
396impl DnsUpdateHeaderSchema {
397 pub fn schema_definition() -> Collection<Field> {
398 btreemap! {
399 DNSTAP_VALUE_PATHS.id.to_string() => Kind::integer(),
400 DNSTAP_VALUE_PATHS.opcode.to_string() => Kind::integer(),
401 DNSTAP_VALUE_PATHS.rcode.to_string() => Kind::integer(),
402 DNSTAP_VALUE_PATHS.qr.to_string() => Kind::integer(),
403 DNSTAP_VALUE_PATHS.zone_count.to_string() => Kind::integer().or_undefined(),
404 DNSTAP_VALUE_PATHS.prerequisite_count.to_string() => Kind::integer().or_undefined(),
405 DNSTAP_VALUE_PATHS.update_count.to_string() => Kind::integer().or_undefined(),
406 DNSTAP_VALUE_PATHS.ad_count.to_string() => Kind::integer().or_undefined(),
407 }
408 .into()
409 }
410}
411
412#[derive(Debug, Default, Clone)]
413pub struct DnsMessageOptPseudoSectionSchema;
414
415impl DnsMessageOptPseudoSectionSchema {
416 pub fn schema_definition() -> Collection<Field> {
417 btreemap! {
418 DNSTAP_VALUE_PATHS.extended_rcode.to_string() => Kind::integer(),
419 DNSTAP_VALUE_PATHS.version.to_string() => Kind::integer(),
420 DNSTAP_VALUE_PATHS.do_flag.to_string() => Kind::boolean(),
421 DNSTAP_VALUE_PATHS.udp_max_payload_size.to_string() => Kind::integer(),
422 DNSTAP_VALUE_PATHS.options.to_string() => Kind::array(
423 Collection::from_unknown(Kind::object(DnsMessageOptionSchema::schema_definition()))
424 ).or_undefined(),
425 }
426 .into()
427 }
428}
429
430#[derive(Debug, Default, Clone)]
431pub struct DnsMessageEdeOptionSchema;
432
433impl DnsMessageEdeOptionSchema {
434 pub fn schema_definition() -> Collection<Field> {
435 btreemap! {
436 DNSTAP_VALUE_PATHS.info_code.to_string() => Kind::integer(),
437 DNSTAP_VALUE_PATHS.purpose.to_string() => Kind::bytes(),
438 DNSTAP_VALUE_PATHS.extra_text.to_string() => Kind::bytes(),
439 }
440 .into()
441 }
442}
443
444#[derive(Debug, Default, Clone)]
445pub struct DnsMessageOptionSchema;
446
447impl DnsMessageOptionSchema {
448 pub fn schema_definition() -> Collection<Field> {
449 btreemap! {
450 DNSTAP_VALUE_PATHS.opt_code.to_string() => Kind::integer(),
451 DNSTAP_VALUE_PATHS.opt_name.to_string() => Kind::bytes(),
452 DNSTAP_VALUE_PATHS.opt_data.to_string() => Kind::bytes(),
453 }
454 .into()
455 }
456}
457
458#[derive(Debug, Default, Clone)]
459pub struct DnsRecordSchema;
460
461impl DnsRecordSchema {
462 pub fn schema_definition() -> Collection<Field> {
463 btreemap! {
464 DNSTAP_VALUE_PATHS.domain_name.to_string() => Kind::bytes(),
465 DNSTAP_VALUE_PATHS.record_type.to_string() => Kind::bytes().or_undefined(),
466 DNSTAP_VALUE_PATHS.record_type_id.to_string() => Kind::integer(),
467 DNSTAP_VALUE_PATHS.ttl.to_string() => Kind::integer(),
468 DNSTAP_VALUE_PATHS.class.to_string() => Kind::bytes(),
469 DNSTAP_VALUE_PATHS.rdata.to_string() => Kind::bytes(),
470 DNSTAP_VALUE_PATHS.rdata_bytes.to_string() => Kind::bytes().or_undefined(),
471 }
472 .into()
473 }
474}
475
476#[derive(Debug, Default, Clone)]
477pub struct DnsQueryQuestionSchema;
478
479impl DnsQueryQuestionSchema {
480 pub fn schema_definition() -> Collection<Field> {
481 btreemap! {
482 DNSTAP_VALUE_PATHS.class.to_string() => Kind::bytes(),
483 DNSTAP_VALUE_PATHS.domain_name.to_string() => Kind::bytes(),
484 DNSTAP_VALUE_PATHS.question_type.to_string() => Kind::bytes(),
485 DNSTAP_VALUE_PATHS.question_type_id.to_string() => Kind::integer(),
486 }
487 .into()
488 }
489}
490
491#[derive(Debug, Default, Clone)]
492pub struct DnsUpdateZoneInfoSchema;
493
494impl DnsUpdateZoneInfoSchema {
495 pub fn schema_definition() -> Collection<Field> {
496 btreemap! {
497 DNSTAP_VALUE_PATHS.zone_name.to_string() => Kind::bytes(),
498 DNSTAP_VALUE_PATHS.zone_type.to_string() => Kind::bytes().or_undefined(),
499 DNSTAP_VALUE_PATHS.zone_type_id.to_string() => Kind::integer(),
500 DNSTAP_VALUE_PATHS.zone_class.to_string() => Kind::bytes(),
501 }
502 .into()
503 }
504}