1use std::{
2 collections::HashSet,
3 convert::TryInto,
4 fmt::Debug,
5 net::{IpAddr, Ipv4Addr, Ipv6Addr},
6 sync::LazyLock,
7};
8use vector_lib::emit;
9
10use base64::prelude::{Engine as _, BASE64_STANDARD};
11use bytes::Bytes;
12use chrono::{TimeZone, Utc};
13use dnsmsg_parser::{dns_message_parser::DnsParserOptions, ede::EDE};
14use hickory_proto::{
15 rr::domain::Name,
16 serialize::binary::{BinDecodable, BinDecoder},
17};
18use prost::Message;
19use snafu::Snafu;
20use vrl::{owned_value_path, path};
21
22use vector_lib::{
23 event::{LogEvent, Value},
24 Error, Result,
25};
26
27#[allow(warnings, clippy::all, clippy::pedantic, clippy::nursery)]
28mod dnstap_proto {
29 include!(concat!(env!("OUT_DIR"), "/dnstap.rs"));
30}
31
32use crate::{internal_events::DnstapParseWarning, schema::DNSTAP_VALUE_PATHS};
33use dnstap_proto::{
34 message::Type as DnstapMessageType, Dnstap, Message as DnstapMessage, SocketFamily,
35 SocketProtocol,
36};
37use vector_lib::config::log_schema;
38use vector_lib::lookup::lookup_v2::ValuePath;
39use vector_lib::lookup::PathPrefix;
40
41use dnsmsg_parser::{
42 dns_message::{
43 DnsRecord, EdnsOptionEntry, OptPseudoSection, QueryHeader, QueryQuestion, UpdateHeader,
44 ZoneInfo,
45 },
46 dns_message_parser::DnsMessageParser,
47};
48
49#[derive(Debug, Snafu)]
50enum DnstapParserError {
51 #[snafu(display("Unsupported DNSTap message type: {}", "dnstap_message_type_id"))]
52 UnsupportedDnstapMessageTypeError { dnstap_message_type_id: i32 },
53}
54
55static DNSTAP_MESSAGE_REQUEST_TYPE_IDS: LazyLock<HashSet<i32>> = LazyLock::new(|| {
56 vec![
57 DnstapMessageType::AuthQuery as i32,
58 DnstapMessageType::ResolverQuery as i32,
59 DnstapMessageType::ClientQuery as i32,
60 DnstapMessageType::ForwarderQuery as i32,
61 DnstapMessageType::StubQuery as i32,
62 DnstapMessageType::ToolQuery as i32,
63 DnstapMessageType::UpdateQuery as i32,
64 ]
65 .into_iter()
66 .collect()
67});
68static DNSTAP_MESSAGE_RESPONSE_TYPE_IDS: LazyLock<HashSet<i32>> = LazyLock::new(|| {
69 vec![
70 DnstapMessageType::AuthResponse as i32,
71 DnstapMessageType::ResolverResponse as i32,
72 DnstapMessageType::ClientResponse as i32,
73 DnstapMessageType::ForwarderResponse as i32,
74 DnstapMessageType::StubResponse as i32,
75 DnstapMessageType::ToolResponse as i32,
76 DnstapMessageType::UpdateResponse as i32,
77 ]
78 .into_iter()
79 .collect()
80});
81
82#[derive(Default)]
83pub struct DnstapParser;
84
85impl DnstapParser {
86 fn insert<'a, V>(
87 event: &mut LogEvent,
88 prefix: impl ValuePath<'a>,
89 path: impl ValuePath<'a>,
90 value: V,
91 ) -> Option<Value>
92 where
93 V: Into<Value> + Debug,
94 {
95 event.insert((PathPrefix::Event, prefix.concat(path)), value)
96 }
97
98 pub fn parse(
99 event: &mut LogEvent,
100 frame: Bytes,
101 parsing_options: DnsParserOptions,
102 ) -> Result<()> {
103 let proto_msg = Dnstap::decode(frame.clone())?;
105 let root = owned_value_path!();
106 if let Some(server_id) = proto_msg.identity {
107 DnstapParser::insert(
108 event,
109 &root,
110 &DNSTAP_VALUE_PATHS.server_identity,
111 String::from_utf8(server_id.clone()).unwrap_or_default(),
112 );
113 }
114
115 if let Some(version) = proto_msg.version {
116 DnstapParser::insert(
117 event,
118 &root,
119 &DNSTAP_VALUE_PATHS.server_version,
120 String::from_utf8(version).unwrap_or_default(),
121 );
122 }
123
124 if let Some(extra) = proto_msg.extra {
125 DnstapParser::insert(
126 event,
127 &root,
128 &DNSTAP_VALUE_PATHS.extra,
129 String::from_utf8(extra).unwrap_or_default(),
130 );
131 }
132
133 let dnstap_data_type_id: i32 = proto_msg.r#type;
134 let mut need_raw_data = false;
135 DnstapParser::insert(
136 event,
137 &root,
138 &DNSTAP_VALUE_PATHS.data_type_id,
139 dnstap_data_type_id,
140 );
141
142 if let Some(dnstap_data_type) = to_dnstap_data_type(dnstap_data_type_id) {
143 DnstapParser::insert(
144 event,
145 &root,
146 &DNSTAP_VALUE_PATHS.data_type,
147 dnstap_data_type.clone(),
148 );
149
150 if dnstap_data_type == "Message" {
151 if let Some(message) = proto_msg.message {
152 if let Err(err) =
153 DnstapParser::parse_dnstap_message(event, &root, message, parsing_options)
154 {
155 emit!(DnstapParseWarning { error: &err });
156 need_raw_data = true;
157 DnstapParser::insert(
158 event,
159 &root,
160 &DNSTAP_VALUE_PATHS.error,
161 err.to_string(),
162 );
163 }
164 }
165 }
166 } else {
167 emit!(DnstapParseWarning {
168 error: format!("Unknown dnstap data type: {dnstap_data_type_id}")
169 });
170 need_raw_data = true;
171 }
172
173 if need_raw_data {
174 DnstapParser::insert(
175 event,
176 &root,
177 &DNSTAP_VALUE_PATHS.raw_data,
178 BASE64_STANDARD.encode(&frame),
179 );
180 }
181
182 Ok(())
183 }
184
185 fn parse_dnstap_message<'a>(
186 event: &mut LogEvent,
187 prefix: impl ValuePath<'a>,
188 dnstap_message: DnstapMessage,
189 parsing_options: DnsParserOptions,
190 ) -> Result<()> {
191 if let Some(socket_family) = dnstap_message.socket_family {
192 DnstapParser::parse_dnstap_message_socket_family(
193 event,
194 prefix.clone(),
195 socket_family,
196 &dnstap_message,
197 )?;
198 }
199
200 if let Some(query_zone) = dnstap_message.query_zone.as_ref() {
201 let mut decoder: BinDecoder = BinDecoder::new(query_zone);
202 match Name::read(&mut decoder) {
203 Ok(raw_data) => {
204 DnstapParser::insert(
205 event,
206 prefix.clone(),
207 &DNSTAP_VALUE_PATHS.query_zone,
208 raw_data.to_utf8(),
209 );
210 }
211 Err(error) => return Err(Error::from(error.to_string())),
212 }
213 }
214
215 let dnstap_message_type_id = dnstap_message.r#type;
216 DnstapParser::insert(
217 event,
218 prefix.clone(),
219 &DNSTAP_VALUE_PATHS.message_type_id,
220 dnstap_message_type_id,
221 );
222
223 DnstapParser::insert(
224 event,
225 prefix.clone(),
226 &DNSTAP_VALUE_PATHS.message_type,
227 to_dnstap_message_type(dnstap_message_type_id),
228 );
229
230 if let Some(query_time_sec) = dnstap_message.query_time_sec {
231 DnstapParser::parse_dnstap_message_time(
232 event,
233 prefix.clone(),
234 query_time_sec,
235 dnstap_message.query_time_nsec,
236 dnstap_message_type_id,
237 dnstap_message.query_message.as_ref(),
238 &DNSTAP_MESSAGE_REQUEST_TYPE_IDS,
239 )?;
240 }
241
242 if let Some(response_time_sec) = dnstap_message.response_time_sec {
243 DnstapParser::parse_dnstap_message_time(
244 event,
245 prefix.clone(),
246 response_time_sec,
247 dnstap_message.response_time_nsec,
248 dnstap_message_type_id,
249 dnstap_message.response_message.as_ref(),
250 &DNSTAP_MESSAGE_RESPONSE_TYPE_IDS,
251 )?;
252 }
253
254 DnstapParser::parse_dnstap_message_type(
255 event,
256 prefix.clone(),
257 dnstap_message_type_id,
258 dnstap_message,
259 parsing_options,
260 )?;
261
262 Ok(())
263 }
264
265 fn parse_dnstap_message_type<'a>(
266 event: &mut LogEvent,
267 prefix: impl ValuePath<'a>,
268 dnstap_message_type_id: i32,
269 dnstap_message: DnstapMessage,
270 parsing_options: DnsParserOptions,
271 ) -> Result<()> {
272 match dnstap_message_type_id {
273 1..=12 => {
274 if let Some(query_message) = dnstap_message.query_message {
275 let mut query_message_parser =
276 DnsMessageParser::with_options(query_message, parsing_options.clone());
277 if let Err(error) = DnstapParser::parse_dns_query_message(
278 event,
279 prefix.concat(&DNSTAP_VALUE_PATHS.request_message),
280 &mut query_message_parser,
281 ) {
282 DnstapParser::log_raw_dns_message(
283 event,
284 prefix.concat(&DNSTAP_VALUE_PATHS.request_message),
285 query_message_parser.raw_message(),
286 );
287
288 return Err(error);
289 };
290 }
291
292 if let Some(response_message) = dnstap_message.response_message {
293 let mut response_message_parser =
294 DnsMessageParser::with_options(response_message, parsing_options);
295 if let Err(error) = DnstapParser::parse_dns_query_message(
296 event,
297 prefix.concat(&DNSTAP_VALUE_PATHS.response_message),
298 &mut response_message_parser,
299 ) {
300 DnstapParser::log_raw_dns_message(
301 event,
302 prefix.concat(&DNSTAP_VALUE_PATHS.response_message),
303 response_message_parser.raw_message(),
304 );
305
306 return Err(error);
307 };
308 }
309 }
310 13 | 14 => {
311 if let Some(update_request_message) = dnstap_message.query_message {
312 let mut update_request_message_parser = DnsMessageParser::with_options(
313 update_request_message,
314 parsing_options.clone(),
315 );
316 if let Err(error) = DnstapParser::parse_dns_update_message(
317 event,
318 &DNSTAP_VALUE_PATHS.request_message,
319 &mut update_request_message_parser,
320 ) {
321 DnstapParser::log_raw_dns_message(
322 event,
323 &DNSTAP_VALUE_PATHS.request_message,
324 update_request_message_parser.raw_message(),
325 );
326
327 return Err(error);
328 };
329 }
330
331 if let Some(update_response_message) = dnstap_message.response_message {
332 let mut update_response_message_parser =
333 DnsMessageParser::with_options(update_response_message, parsing_options);
334 if let Err(error) = DnstapParser::parse_dns_update_message(
335 event,
336 &DNSTAP_VALUE_PATHS.response_message,
337 &mut update_response_message_parser,
338 ) {
339 DnstapParser::log_raw_dns_message(
340 event,
341 &DNSTAP_VALUE_PATHS.response_message,
342 update_response_message_parser.raw_message(),
343 );
344
345 return Err(error);
346 };
347 }
348 }
349 _ => {
350 return Err(Box::new(
351 DnstapParserError::UnsupportedDnstapMessageTypeError {
352 dnstap_message_type_id,
353 },
354 ));
355 }
356 }
357
358 Ok(())
359 }
360
361 fn parse_dnstap_message_time<'a>(
362 event: &mut LogEvent,
363 prefix: impl ValuePath<'a>,
364 time_sec: u64,
365 time_nsec: Option<u32>,
366 dnstap_message_type_id: i32,
367 message: Option<&Vec<u8>>,
368 type_ids: &HashSet<i32>,
369 ) -> Result<()> {
370 if time_sec > i64::MAX as u64 {
371 return Err(Error::from("Cannot parse timestamp"));
372 }
373
374 let (time_in_nanosec, query_time_nsec) = match time_nsec {
375 Some(nsec) => {
376 if let Some(time_in_ns) = (time_sec as i64)
377 .checked_mul(1_000_000_000)
378 .and_then(|v| v.checked_add(nsec as i64))
379 {
380 (time_in_ns, nsec)
381 } else {
382 return Err(Error::from("Cannot parse timestamp"));
383 }
384 }
385 None => {
386 if let Some(time_in_ns) = (time_sec as i64).checked_mul(1_000_000_000) {
387 (time_in_ns, 0)
388 } else {
389 return Err(Error::from("Cannot parse timestamp"));
390 }
391 }
392 };
393
394 if type_ids.contains(&dnstap_message_type_id) {
395 DnstapParser::log_time(event, prefix.clone(), time_in_nanosec, "ns");
396 let timestamp = Utc
397 .timestamp_opt(time_sec.try_into().unwrap(), query_time_nsec)
398 .single()
399 .ok_or("Invalid timestamp")?;
400 if let Some(timestamp_key) = log_schema().timestamp_key() {
401 DnstapParser::insert(event, prefix.clone(), timestamp_key, timestamp);
402 }
403 }
404
405 if message.is_none() {
406 DnstapParser::log_time(
407 event,
408 prefix.concat(&DNSTAP_VALUE_PATHS.request_message),
409 time_in_nanosec,
410 "ns",
411 );
412 }
413 Ok(())
414 }
415
416 fn parse_dnstap_message_socket_family<'a>(
417 event: &mut LogEvent,
418 prefix: impl ValuePath<'a>,
419 socket_family: i32,
420 dnstap_message: &DnstapMessage,
421 ) -> Result<()> {
422 DnstapParser::insert(
423 event,
424 prefix.clone(),
425 &DNSTAP_VALUE_PATHS.socket_family,
426 to_socket_family_name(socket_family)?.to_string(),
427 );
428
429 if let Some(socket_protocol) = dnstap_message.socket_protocol {
430 DnstapParser::insert(
431 event,
432 prefix.clone(),
433 &DNSTAP_VALUE_PATHS.socket_protocol,
434 to_socket_protocol_name(socket_protocol)?.to_string(),
435 );
436 }
437
438 if let Some(query_address) = dnstap_message.query_address.as_ref() {
439 let source_address = if socket_family == 1 {
440 if query_address.len() < 4 {
441 return Err(Error::from("Cannot parse query_address"));
442 }
443 let address_buffer: [u8; 4] = query_address[0..4].try_into()?;
444 IpAddr::V4(Ipv4Addr::from(address_buffer))
445 } else {
446 if query_address.len() < 16 {
447 return Err(Error::from("Cannot parse query_address"));
448 }
449 let address_buffer: [u8; 16] = query_address[0..16].try_into()?;
450 IpAddr::V6(Ipv6Addr::from(address_buffer))
451 };
452
453 DnstapParser::insert(
454 event,
455 prefix.clone(),
456 &DNSTAP_VALUE_PATHS.query_address,
457 source_address.to_string(),
458 );
459 }
460
461 if let Some(query_port) = dnstap_message.query_port {
462 DnstapParser::insert(
463 event,
464 prefix.clone(),
465 &DNSTAP_VALUE_PATHS.query_port,
466 query_port,
467 );
468 }
469
470 if let Some(response_address) = dnstap_message.response_address.as_ref() {
471 let response_addr = if socket_family == 1 {
472 if response_address.len() < 4 {
473 return Err(Error::from("Cannot parse response_address"));
474 }
475 let address_buffer: [u8; 4] = response_address[0..4].try_into()?;
476 IpAddr::V4(Ipv4Addr::from(address_buffer))
477 } else {
478 if response_address.len() < 16 {
479 return Err(Error::from("Cannot parse response_address"));
480 }
481 let address_buffer: [u8; 16] = response_address[0..16].try_into()?;
482 IpAddr::V6(Ipv6Addr::from(address_buffer))
483 };
484
485 DnstapParser::insert(
486 event,
487 prefix.clone(),
488 &DNSTAP_VALUE_PATHS.response_address,
489 response_addr.to_string(),
490 );
491 }
492
493 if let Some(response_port) = dnstap_message.response_port {
494 DnstapParser::insert(
495 event,
496 prefix.clone(),
497 &DNSTAP_VALUE_PATHS.response_port,
498 response_port,
499 );
500 };
501 Ok(())
502 }
503
504 fn log_time<'a>(
505 event: &mut LogEvent,
506 prefix: impl ValuePath<'a>,
507 time: i64,
508 time_precision: &str,
509 ) {
510 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.time, time);
511 DnstapParser::insert(
512 event,
513 prefix.clone(),
514 &DNSTAP_VALUE_PATHS.time_precision,
515 time_precision.to_string(),
516 );
517 }
518
519 fn log_raw_dns_message<'a>(
520 event: &mut LogEvent,
521 prefix: impl ValuePath<'a>,
522 raw_dns_message: &[u8],
523 ) {
524 DnstapParser::insert(
525 event,
526 prefix.clone(),
527 &DNSTAP_VALUE_PATHS.raw_data,
528 BASE64_STANDARD.encode(raw_dns_message),
529 );
530 }
531
532 fn parse_dns_query_message<'a>(
533 event: &mut LogEvent,
534 prefix: impl ValuePath<'a>,
535 dns_message_parser: &mut DnsMessageParser,
536 ) -> Result<()> {
537 let msg = dns_message_parser.parse_as_query_message()?;
538
539 DnstapParser::insert(
540 event,
541 prefix.clone(),
542 &DNSTAP_VALUE_PATHS.response_code,
543 msg.response_code,
544 );
545
546 if let Some(response) = msg.response {
547 DnstapParser::insert(
548 event,
549 prefix.clone(),
550 &DNSTAP_VALUE_PATHS.response,
551 response.to_string(),
552 );
553 }
554
555 DnstapParser::log_dns_query_message_header(
556 event,
557 prefix.concat(&DNSTAP_VALUE_PATHS.header),
558 &msg.header,
559 );
560
561 DnstapParser::log_dns_query_message_query_section(
562 event,
563 prefix.concat(&DNSTAP_VALUE_PATHS.question_section),
564 &msg.question_section,
565 );
566
567 DnstapParser::log_dns_message_record_section(
568 event,
569 prefix.concat(&DNSTAP_VALUE_PATHS.answer_section),
570 &msg.answer_section,
571 );
572
573 DnstapParser::log_dns_message_record_section(
574 event,
575 prefix.concat(&DNSTAP_VALUE_PATHS.authority_section),
576 &msg.authority_section,
577 );
578
579 DnstapParser::log_dns_message_record_section(
580 event,
581 prefix.concat(&DNSTAP_VALUE_PATHS.additional_section),
582 &msg.additional_section,
583 );
584
585 DnstapParser::log_edns(
586 event,
587 prefix.concat(&DNSTAP_VALUE_PATHS.opt_pseudo_section),
588 &msg.opt_pseudo_section,
589 );
590
591 Ok(())
592 }
593
594 fn log_dns_query_message_header<'a>(
595 event: &mut LogEvent,
596 prefix: impl ValuePath<'a>,
597 header: &QueryHeader,
598 ) {
599 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.id, header.id);
600 DnstapParser::insert(
601 event,
602 prefix.clone(),
603 &DNSTAP_VALUE_PATHS.opcode,
604 header.opcode,
605 );
606 DnstapParser::insert(
607 event,
608 prefix.clone(),
609 &DNSTAP_VALUE_PATHS.rcode,
610 u16::from(header.rcode),
611 );
612 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.qr, header.qr);
613 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.aa, header.aa);
614 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.tc, header.tc);
615 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.rd, header.rd);
616 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.ra, header.ra);
617 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.ad, header.ad);
618 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.cd, header.cd);
619 DnstapParser::insert(
620 event,
621 prefix.clone(),
622 &DNSTAP_VALUE_PATHS.question_count,
623 header.question_count,
624 );
625 DnstapParser::insert(
626 event,
627 prefix.clone(),
628 &DNSTAP_VALUE_PATHS.answer_count,
629 header.answer_count,
630 );
631 DnstapParser::insert(
632 event,
633 prefix.clone(),
634 &DNSTAP_VALUE_PATHS.authority_count,
635 header.authority_count,
636 );
637 DnstapParser::insert(
638 event,
639 prefix.clone(),
640 &DNSTAP_VALUE_PATHS.ar_count,
641 header.additional_count,
642 );
643 }
644
645 fn log_dns_query_message_query_section<'a>(
646 event: &mut LogEvent,
647 prefix: impl ValuePath<'a>,
648 questions: &[QueryQuestion],
649 ) {
650 for (i, query) in questions.iter().enumerate() {
651 let index_segment = path!(i as isize);
652 DnstapParser::log_dns_query_question(event, prefix.concat(index_segment), query);
653 }
654 }
655
656 fn log_dns_query_question<'a>(
657 event: &mut LogEvent,
658 prefix: impl ValuePath<'a>,
659 question: &QueryQuestion,
660 ) {
661 DnstapParser::insert(
662 event,
663 prefix.clone(),
664 &DNSTAP_VALUE_PATHS.domain_name,
665 question.name.clone(),
666 );
667 if let Some(record_type) = question.record_type.clone() {
668 DnstapParser::insert(
669 event,
670 prefix.clone(),
671 &DNSTAP_VALUE_PATHS.question_type,
672 record_type,
673 );
674 }
675 DnstapParser::insert(
676 event,
677 prefix.clone(),
678 &DNSTAP_VALUE_PATHS.question_type_id,
679 question.record_type_id,
680 );
681 DnstapParser::insert(
682 event,
683 prefix.clone(),
684 &DNSTAP_VALUE_PATHS.class,
685 question.class.clone(),
686 );
687 }
688
689 fn parse_dns_update_message<'a>(
690 event: &mut LogEvent,
691 prefix: impl ValuePath<'a>,
692 dns_message_parser: &mut DnsMessageParser,
693 ) -> Result<()> {
694 let msg = dns_message_parser.parse_as_update_message()?;
695
696 DnstapParser::insert(
697 event,
698 prefix.clone(),
699 &DNSTAP_VALUE_PATHS.response_code,
700 msg.response_code,
701 );
702
703 if let Some(response) = msg.response {
704 DnstapParser::insert(
705 event,
706 prefix.clone(),
707 &DNSTAP_VALUE_PATHS.response,
708 response.to_string(),
709 );
710 }
711
712 DnstapParser::log_dns_update_message_header(
713 event,
714 prefix.concat(&DNSTAP_VALUE_PATHS.header),
715 &msg.header,
716 );
717
718 DnstapParser::log_dns_update_message_zone_section(
719 event,
720 prefix.concat(&DNSTAP_VALUE_PATHS.zone_section),
721 &msg.zone_to_update,
722 );
723
724 DnstapParser::log_dns_message_record_section(
725 event,
726 prefix.concat(&DNSTAP_VALUE_PATHS.prerequisite_section),
727 &msg.prerequisite_section,
728 );
729
730 DnstapParser::log_dns_message_record_section(
731 event,
732 prefix.concat(&DNSTAP_VALUE_PATHS.update_section),
733 &msg.update_section,
734 );
735
736 DnstapParser::log_dns_message_record_section(
737 event,
738 prefix.concat(&DNSTAP_VALUE_PATHS.additional_section),
739 &msg.additional_section,
740 );
741
742 Ok(())
743 }
744
745 fn log_dns_update_message_header<'a>(
746 event: &mut LogEvent,
747 prefix: impl ValuePath<'a>,
748 header: &UpdateHeader,
749 ) {
750 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.id, header.id);
751
752 DnstapParser::insert(
753 event,
754 prefix.clone(),
755 &DNSTAP_VALUE_PATHS.opcode,
756 header.opcode,
757 );
758
759 DnstapParser::insert(
760 event,
761 prefix.clone(),
762 &DNSTAP_VALUE_PATHS.rcode,
763 u16::from(header.rcode),
764 );
765
766 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.qr, header.qr);
767
768 DnstapParser::insert(
769 event,
770 prefix.clone(),
771 &DNSTAP_VALUE_PATHS.zone_count,
772 header.zone_count,
773 );
774
775 DnstapParser::insert(
776 event,
777 prefix.clone(),
778 &DNSTAP_VALUE_PATHS.prerequisite_count,
779 header.prerequisite_count,
780 );
781
782 DnstapParser::insert(
783 event,
784 prefix.clone(),
785 &DNSTAP_VALUE_PATHS.update_count,
786 header.update_count,
787 );
788
789 DnstapParser::insert(
790 event,
791 prefix.clone(),
792 &DNSTAP_VALUE_PATHS.ad_count,
793 header.additional_count,
794 );
795 }
796
797 fn log_dns_update_message_zone_section<'a>(
798 event: &mut LogEvent,
799 prefix: impl ValuePath<'a>,
800 zone: &ZoneInfo,
801 ) {
802 DnstapParser::insert(
803 event,
804 prefix.clone(),
805 &DNSTAP_VALUE_PATHS.zone_name,
806 zone.name.clone(),
807 );
808 if let Some(zone_type) = zone.zone_type.clone() {
809 DnstapParser::insert(
810 event,
811 prefix.clone(),
812 &DNSTAP_VALUE_PATHS.zone_type,
813 zone_type,
814 );
815 }
816 DnstapParser::insert(
817 event,
818 prefix.clone(),
819 &DNSTAP_VALUE_PATHS.zone_type_id,
820 zone.zone_type_id,
821 );
822 DnstapParser::insert(
823 event,
824 prefix.clone(),
825 &DNSTAP_VALUE_PATHS.zone_class,
826 zone.class.clone(),
827 );
828 }
829
830 fn log_edns<'a>(
831 event: &mut LogEvent,
832 prefix: impl ValuePath<'a>,
833 opt_section: &Option<OptPseudoSection>,
834 ) {
835 if let Some(edns) = opt_section {
836 DnstapParser::insert(
837 event,
838 prefix.clone(),
839 &DNSTAP_VALUE_PATHS.extended_rcode,
840 edns.extended_rcode,
841 );
842 DnstapParser::insert(
843 event,
844 prefix.clone(),
845 &DNSTAP_VALUE_PATHS.version,
846 edns.version,
847 );
848 DnstapParser::insert(
849 event,
850 prefix.clone(),
851 &DNSTAP_VALUE_PATHS.do_flag,
852 edns.dnssec_ok,
853 );
854 DnstapParser::insert(
855 event,
856 prefix.clone(),
857 &DNSTAP_VALUE_PATHS.udp_max_payload_size,
858 edns.udp_max_payload_size,
859 );
860 DnstapParser::log_edns_ede(event, prefix.concat(&DNSTAP_VALUE_PATHS.ede), &edns.ede);
861 DnstapParser::log_edns_options(
862 event,
863 prefix.concat(&DNSTAP_VALUE_PATHS.options),
864 &edns.options,
865 );
866 }
867 }
868
869 fn log_edns_ede<'a>(event: &mut LogEvent, prefix: impl ValuePath<'a>, options: &[EDE]) {
870 options.iter().enumerate().for_each(|(i, entry)| {
871 let index_segment = path!(i as isize);
872 DnstapParser::log_edns_ede_entry(event, prefix.concat(index_segment), entry);
873 });
874 }
875
876 fn log_edns_ede_entry<'a>(event: &mut LogEvent, prefix: impl ValuePath<'a>, entry: &EDE) {
877 DnstapParser::insert(
878 event,
879 prefix.clone(),
880 &DNSTAP_VALUE_PATHS.info_code,
881 entry.info_code(),
882 );
883 if let Some(purpose) = entry.purpose() {
884 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.purpose, purpose);
885 }
886 if let Some(extra_text) = entry.extra_text() {
887 DnstapParser::insert(
888 event,
889 prefix.clone(),
890 &DNSTAP_VALUE_PATHS.extra_text,
891 extra_text,
892 );
893 }
894 }
895
896 fn log_edns_options<'a>(
897 event: &mut LogEvent,
898 prefix: impl ValuePath<'a>,
899 options: &[EdnsOptionEntry],
900 ) {
901 options.iter().enumerate().for_each(|(i, opt)| {
902 let index_segment = path!(i as isize);
903 DnstapParser::log_edns_opt(event, prefix.concat(index_segment), opt);
904 });
905 }
906
907 fn log_edns_opt<'a>(event: &mut LogEvent, prefix: impl ValuePath<'a>, opt: &EdnsOptionEntry) {
908 DnstapParser::insert(
909 event,
910 prefix.clone(),
911 &DNSTAP_VALUE_PATHS.opt_code,
912 opt.opt_code,
913 );
914 DnstapParser::insert(
915 event,
916 prefix.clone(),
917 &DNSTAP_VALUE_PATHS.opt_name,
918 opt.opt_name.clone(),
919 );
920 DnstapParser::insert(
921 event,
922 prefix.clone(),
923 &DNSTAP_VALUE_PATHS.opt_data,
924 opt.opt_data.clone(),
925 );
926 }
927
928 fn log_dns_message_record_section<'a>(
929 event: &mut LogEvent,
930 prefix: impl ValuePath<'a>,
931 records: &[DnsRecord],
932 ) {
933 for (i, record) in records.iter().enumerate() {
934 let index_segment = path!(i as isize);
935 DnstapParser::log_dns_record(event, prefix.concat(index_segment), record);
936 }
937 }
938
939 fn log_dns_record<'a>(event: &mut LogEvent, prefix: impl ValuePath<'a>, record: &DnsRecord) {
940 DnstapParser::insert(
941 event,
942 prefix.clone(),
943 &DNSTAP_VALUE_PATHS.domain_name,
944 record.name.clone(),
945 );
946 if let Some(record_type) = record.record_type.clone() {
947 DnstapParser::insert(
948 event,
949 prefix.clone(),
950 &DNSTAP_VALUE_PATHS.record_type,
951 record_type,
952 );
953 }
954 DnstapParser::insert(
955 event,
956 prefix.clone(),
957 &DNSTAP_VALUE_PATHS.record_type_id,
958 record.record_type_id,
959 );
960 DnstapParser::insert(event, prefix.clone(), &DNSTAP_VALUE_PATHS.ttl, record.ttl);
961 DnstapParser::insert(
962 event,
963 prefix.clone(),
964 &DNSTAP_VALUE_PATHS.class,
965 record.class.clone(),
966 );
967 if let Some(rdata) = &record.rdata {
968 DnstapParser::insert(
969 event,
970 prefix.clone(),
971 &DNSTAP_VALUE_PATHS.rdata,
972 rdata.to_string(),
973 );
974 };
975 if let Some(rdata_bytes) = &record.rdata_bytes {
976 DnstapParser::insert(
977 event,
978 prefix.clone(),
979 &DNSTAP_VALUE_PATHS.rdata_bytes,
980 BASE64_STANDARD.encode(rdata_bytes),
981 );
982 };
983 }
984}
985
986fn to_socket_family_name(socket_family: i32) -> Result<&'static str> {
987 if socket_family == SocketFamily::Inet as i32 {
988 Ok("INET")
989 } else if socket_family == SocketFamily::Inet6 as i32 {
990 Ok("INET6")
991 } else {
992 Err(Error::from(format!(
993 "Unknown socket family: {socket_family}"
994 )))
995 }
996}
997
998fn to_socket_protocol_name(socket_protocol: i32) -> Result<&'static str> {
999 if socket_protocol == SocketProtocol::Udp as i32 {
1000 Ok("UDP")
1001 } else if socket_protocol == SocketProtocol::Tcp as i32 {
1002 Ok("TCP")
1003 } else if socket_protocol == SocketProtocol::Dot as i32 {
1004 Ok("DOT")
1005 } else if socket_protocol == SocketProtocol::Doh as i32 {
1006 Ok("DOH")
1007 } else if socket_protocol == SocketProtocol::DnsCryptUdp as i32 {
1008 Ok("DNSCryptUDP")
1009 } else if socket_protocol == SocketProtocol::DnsCryptTcp as i32 {
1010 Ok("DNSCryptTCP")
1011 } else {
1012 Err(Error::from(format!(
1013 "Unknown socket protocol: {socket_protocol}"
1014 )))
1015 }
1016}
1017
1018fn to_dnstap_data_type(data_type_id: i32) -> Option<String> {
1019 match data_type_id {
1020 1 => Some(String::from("Message")),
1021 _ => None,
1022 }
1023}
1024
1025fn to_dnstap_message_type(type_id: i32) -> String {
1026 match type_id {
1027 1 => String::from("AuthQuery"),
1028 2 => String::from("AuthResponse"),
1029 3 => String::from("ResolverQuery"),
1030 4 => String::from("ResolverResponse"),
1031 5 => String::from("ClientQuery"),
1032 6 => String::from("ClientResponse"),
1033 7 => String::from("ForwarderQuery"),
1034 8 => String::from("ForwarderResponse"),
1035 9 => String::from("StubQuery"),
1036 10 => String::from("StubResponse"),
1037 11 => String::from("ToolQuery"),
1038 12 => String::from("ToolResponse"),
1039 13 => String::from("UpdateQuery"),
1040 14 => String::from("UpdateResponse"),
1041 _ => format!("Unknown dnstap message type: {type_id}"),
1042 }
1043}
1044
1045#[cfg(test)]
1046mod tests {
1047 use super::*;
1048 use chrono::DateTime;
1049 use dnsmsg_parser::dns_message_parser::DnsParserOptions;
1050 use std::{collections::BTreeMap, vec};
1051
1052 #[test]
1053 fn test_parse_dnstap_data_with_query_message() {
1054 let mut log_event = LogEvent::default();
1055 let raw_dnstap_data = "ChVqYW1lcy1WaXJ0dWFsLU1hY2hpbmUSC0JJTkQgOS4xNi4zcnoIAxACGAEiEAAAAAAAAA\
1056 AAAAAAAAAAAAAqECABBQJwlAAAAAAAAAAAADAw8+0CODVA7+zq9wVNMU3WNlI2kwIAAAABAAAAAAABCWZhY2Vib29rMQNjb\
1057 20AAAEAAQAAKQIAAACAAAAMAAoACOxjCAG9zVgzWgUDY29tAHgB";
1058 let dnstap_data = BASE64_STANDARD
1059 .decode(raw_dnstap_data)
1060 .expect("Invalid base64 encoded data.");
1061 let parse_result = DnstapParser::parse(
1062 &mut log_event,
1063 Bytes::from(dnstap_data),
1064 DnsParserOptions::default(),
1065 );
1066 assert!(parse_result.is_ok());
1067
1068 let expected_map: BTreeMap<&str, Value> = BTreeMap::from([
1069 ("dataType", Value::Bytes(Bytes::from("Message"))),
1070 ("dataTypeId", Value::Integer(1)),
1071 ("messageType", Value::Bytes(Bytes::from("ResolverQuery"))),
1072 ("messageTypeId", Value::Integer(3)),
1073 ("queryZone", Value::Bytes(Bytes::from("com."))),
1074 ("requestData.fullRcode", Value::Integer(0)),
1075 ("requestData.header.aa", Value::Boolean(false)),
1076 ("requestData.header.ad", Value::Boolean(false)),
1077 ("requestData.header.anCount", Value::Integer(0)),
1078 ("requestData.header.arCount", Value::Integer(1)),
1079 ("requestData.header.cd", Value::Boolean(false)),
1080 ("requestData.header.id", Value::Integer(37634)),
1081 ("requestData.header.nsCount", Value::Integer(0)),
1082 ("requestData.header.opcode", Value::Integer(0)),
1083 ("requestData.header.qdCount", Value::Integer(1)),
1084 ("requestData.header.qr", Value::Integer(0)),
1085 ("requestData.header.ra", Value::Boolean(false)),
1086 ("requestData.header.rcode", Value::Integer(0)),
1087 ("requestData.header.rd", Value::Boolean(false)),
1088 ("requestData.header.tc", Value::Boolean(false)),
1089 ("requestData.opt.do", Value::Boolean(true)),
1090 ("requestData.opt.ednsVersion", Value::Integer(0)),
1091 ("requestData.opt.extendedRcode", Value::Integer(0)),
1092 ("requestData.opt.options[0].optCode", Value::Integer(10)),
1093 (
1094 "requestData.opt.options[0].optName",
1095 Value::Bytes(Bytes::from("Cookie")),
1096 ),
1097 (
1098 "requestData.opt.options[0].optValue",
1099 Value::Bytes(Bytes::from("7GMIAb3NWDM=")),
1100 ),
1101 ("requestData.opt.udpPayloadSize", Value::Integer(512)),
1102 (
1103 "requestData.question[0].class",
1104 Value::Bytes(Bytes::from("IN")),
1105 ),
1106 (
1107 "requestData.question[0].domainName",
1108 Value::Bytes(Bytes::from("facebook1.com.")),
1109 ),
1110 (
1111 "requestData.question[0].questionType",
1112 Value::Bytes(Bytes::from("A")),
1113 ),
1114 ("requestData.question[0].questionTypeId", Value::Integer(1)),
1115 (
1116 "requestData.rcodeName",
1117 Value::Bytes(Bytes::from("NoError")),
1118 ),
1119 (
1120 "responseAddress",
1121 Value::Bytes(Bytes::from("2001:502:7094::30")),
1122 ),
1123 ("responsePort", Value::Integer(53)),
1124 (
1125 "serverId",
1126 Value::Bytes(Bytes::from("james-Virtual-Machine")),
1127 ),
1128 ("serverVersion", Value::Bytes(Bytes::from("BIND 9.16.3"))),
1129 ("socketFamily", Value::Bytes(Bytes::from("INET6"))),
1130 ("socketProtocol", Value::Bytes(Bytes::from("UDP"))),
1131 ("sourceAddress", Value::Bytes(Bytes::from("::"))),
1132 ("sourcePort", Value::Integer(46835)),
1133 ("time", Value::Integer(1_593_489_007_920_014_129)),
1134 ("timePrecision", Value::Bytes(Bytes::from("ns"))),
1135 (
1136 "timestamp",
1137 Value::Timestamp(
1138 Utc.from_utc_datetime(
1139 &DateTime::parse_from_rfc3339("2020-06-30T03:50:07.920014129Z")
1140 .unwrap()
1141 .naive_utc(),
1142 ),
1143 ),
1144 ),
1145 ]);
1146
1147 for (exp_key, exp_value) in expected_map {
1149 let value = log_event.get(exp_key).unwrap();
1150 assert_eq!(*value, exp_value);
1151 }
1152 }
1153
1154 #[test]
1155 fn test_parse_dnstap_data_lowercase_hostnames() {
1156 let mut log_event = LogEvent::default();
1157 let mut lowercase_log_event = LogEvent::default();
1158 let raw_dnstap_data = "Cgw2NzNiNWZiZWI5MmESMkJJTkQgOS4xOC4yMS0xK3VidW50dTIyLjA0LjErZGViLnN1cnkub3JnKzEtVWJ1bnR1cqkBCAYQARgBIgQKWQUeKgQKWQUqMMitAjg1YLXQp68GbZ9tBw9ygwGInoGAAAEABAAAAAEGVmVjdG9yA0RldgAAAQABwAwAAQABAAAAPAAEEvVWOMAMAAEAAQAAADwABBL1VnnADAABAAEAAAA8AAQS9VYSwAwAAQABAAAAPAAEEvVWWQAAKQTQAAAAAAAcAAoAGERDbSN8uKngAQAAAGXp6DXs0fbpv0n9F3gB";
1159 let dnstap_data = BASE64_STANDARD
1160 .decode(raw_dnstap_data)
1161 .expect("Invalid base64 encoded data.");
1162 let parse_result = DnstapParser::parse(
1163 &mut lowercase_log_event,
1164 Bytes::from(dnstap_data.clone()),
1165 DnsParserOptions {
1166 lowercase_hostnames: true,
1167 },
1168 );
1169 let no_lowercase_result = DnstapParser::parse(
1170 &mut log_event,
1171 Bytes::from(dnstap_data),
1172 DnsParserOptions::default(),
1173 );
1174 assert!(parse_result.is_ok());
1175 assert!(no_lowercase_result.is_ok());
1176
1177 let no_lowercase_expected: BTreeMap<&str, Value> = BTreeMap::from([
1178 ("dataType", Value::Bytes(Bytes::from("Message"))),
1179 ("dataTypeId", Value::Integer(1)),
1180 (
1181 "responseData.answers[0].domainName",
1182 Value::Bytes(Bytes::from("Vector.Dev.")),
1183 ),
1184 (
1185 "responseData.question[0].domainName",
1186 Value::Bytes(Bytes::from("Vector.Dev.")),
1187 ),
1188 ]);
1189 let expected_map: BTreeMap<&str, Value> = BTreeMap::from([
1190 ("dataType", Value::Bytes(Bytes::from("Message"))),
1191 ("dataTypeId", Value::Integer(1)),
1192 (
1193 "responseData.answers[0].domainName",
1194 Value::Bytes(Bytes::from("vector.dev.")),
1195 ),
1196 (
1197 "responseData.question[0].domainName",
1198 Value::Bytes(Bytes::from("vector.dev.")),
1199 ),
1200 ]);
1201
1202 for (exp_key, exp_value) in no_lowercase_expected {
1204 let value = log_event.get(exp_key).unwrap();
1205 assert_eq!(*value, exp_value);
1206 }
1207 for (exp_key, exp_value) in expected_map {
1208 let value = lowercase_log_event.get(exp_key).unwrap();
1209 assert_eq!(*value, exp_value);
1210 }
1211 }
1212
1213 #[test]
1214 fn test_parse_dnstap_data_with_ede_options() {
1215 let mut log_event = LogEvent::default();
1216 let raw_dnstap_data = "ChVqYW1lcy1WaXJ0dWFsLU1hY2hpbmUSC0JJTkQgOS4xNi4zGgBy5wEIAxACGAEiEAAAAAAAAAAAAAAAAAAAAAAqECABBQJwlAAAAAAAAAAAADAw8+0CODVA7+zq9wVNMU3WNlI2kwIAAAABAAAAAAABCWZhY2Vib29rMQNjb20AAAEAAQAAKQIAAACAAAAMAAoACOxjCAG9zVgzWgUDY29tAGAAbQAAAAByZLM4AAAAAQAAAAAAAQJoNQdleGFtcGxlA2NvbQAABgABAAApBNABAUAAADkADwA1AAlubyBTRVAgbWF0Y2hpbmcgdGhlIERTIGZvdW5kIGZvciBkbnNzZWMtZmFpbGVkLm9yZy54AQ==";
1217 let dnstap_data = BASE64_STANDARD
1218 .decode(raw_dnstap_data)
1219 .expect("Invalid base64 encoded data.");
1220 let parse_result = DnstapParser::parse(
1221 &mut log_event,
1222 Bytes::from(dnstap_data),
1223 DnsParserOptions::default(),
1224 );
1225 assert!(parse_result.is_ok());
1226
1227 let expected_map: BTreeMap<&str, Value> = BTreeMap::from([
1228 ("responseData.opt.ede[0].infoCode", Value::Integer(9)),
1229 (
1230 "responseData.opt.ede[0].purpose",
1231 Value::Bytes(Bytes::from("DNSKEY Missing")),
1232 ),
1233 (
1234 "responseData.opt.ede[0].extraText",
1235 Value::Bytes(Bytes::from(
1236 "no SEP matching the DS found for dnssec-failed.org.",
1237 )),
1238 ),
1239 ]);
1240
1241 for (exp_key, exp_value) in expected_map {
1243 let value = log_event.get(exp_key).unwrap();
1244 assert_eq!(*value, exp_value);
1245 }
1246 }
1247
1248 #[test]
1249 fn test_parse_dnstap_data_with_update_message() {
1250 let mut log_event = LogEvent::default();
1251 let raw_dnstap_data = "ChVqYW1lcy1WaXJ0dWFsLU1hY2hpbmUSC0JJTkQgOS4xNi4zcmsIDhABGAEiBH8AAA\
1252 EqBH8AAAEwrG44AEC+iu73BU14gfofUh1wi6gAAAEAAAAAAAAHZXhhbXBsZQNjb20AAAYAAWC+iu73BW0agDwvch1wi6gAA\
1253 AEAAAAAAAAHZXhhbXBsZQNjb20AAAYAAXgB";
1254 let dnstap_data = BASE64_STANDARD
1255 .decode(raw_dnstap_data)
1256 .expect("Invalid base64 encoded data.");
1257 let parse_result = DnstapParser::parse(
1258 &mut log_event,
1259 Bytes::from(dnstap_data),
1260 DnsParserOptions::default(),
1261 );
1262 assert!(parse_result.is_ok());
1263
1264 let expected_map: BTreeMap<&str, Value> = BTreeMap::from([
1265 ("dataType", Value::Bytes(Bytes::from("Message"))),
1266 ("dataTypeId", Value::Integer(1)),
1267 ("messageType", Value::Bytes(Bytes::from("UpdateResponse"))),
1268 ("messageTypeId", Value::Integer(14)),
1269 ("requestData.fullRcode", Value::Integer(0)),
1270 ("requestData.header.adCount", Value::Integer(0)),
1271 ("requestData.header.id", Value::Integer(28811)),
1272 ("requestData.header.opcode", Value::Integer(5)),
1273 ("requestData.header.prCount", Value::Integer(0)),
1274 ("requestData.header.qr", Value::Integer(1)),
1275 ("requestData.header.rcode", Value::Integer(0)),
1276 ("requestData.header.upCount", Value::Integer(0)),
1277 ("requestData.header.zoCount", Value::Integer(1)),
1278 (
1279 "requestData.rcodeName",
1280 Value::Bytes(Bytes::from("NoError")),
1281 ),
1282 ("requestData.zone.zClass", Value::Bytes(Bytes::from("IN"))),
1283 (
1284 "requestData.zone.zName",
1285 Value::Bytes(Bytes::from("example.com.")),
1286 ),
1287 ("requestData.zone.zType", Value::Bytes(Bytes::from("SOA"))),
1288 ("requestData.zone.zTypeId", Value::Integer(6)),
1289 ("responseAddress", Value::Bytes(Bytes::from("127.0.0.1"))),
1290 ("responseData.fullRcode", Value::Integer(0)),
1291 ("responseData.header.adCount", Value::Integer(0)),
1292 ("responseData.header.id", Value::Integer(28811)),
1293 ("responseData.header.opcode", Value::Integer(5)),
1294 ("responseData.header.prCount", Value::Integer(0)),
1295 ("responseData.header.qr", Value::Integer(1)),
1296 ("responseData.header.rcode", Value::Integer(0)),
1297 ("responseData.header.upCount", Value::Integer(0)),
1298 ("responseData.header.zoCount", Value::Integer(1)),
1299 (
1300 "responseData.rcodeName",
1301 Value::Bytes(Bytes::from("NoError")),
1302 ),
1303 ("responseData.zone.zClass", Value::Bytes(Bytes::from("IN"))),
1304 (
1305 "responseData.zone.zName",
1306 Value::Bytes(Bytes::from("example.com.")),
1307 ),
1308 ("responseData.zone.zType", Value::Bytes(Bytes::from("SOA"))),
1309 ("responseData.zone.zTypeId", Value::Integer(6)),
1310 ("responsePort", Value::Integer(0)),
1311 (
1312 "serverId",
1313 Value::Bytes(Bytes::from("james-Virtual-Machine")),
1314 ),
1315 ("serverVersion", Value::Bytes(Bytes::from("BIND 9.16.3"))),
1316 ("socketFamily", Value::Bytes(Bytes::from("INET"))),
1317 ("socketProtocol", Value::Bytes(Bytes::from("UDP"))),
1318 ("sourceAddress", Value::Bytes(Bytes::from("127.0.0.1"))),
1319 ("sourcePort", Value::Integer(14124)),
1320 ("time", Value::Integer(1_593_541_950_792_494_106)),
1321 ("timePrecision", Value::Bytes(Bytes::from("ns"))),
1322 (
1323 "timestamp",
1324 Value::Timestamp(
1325 Utc.from_utc_datetime(
1326 &DateTime::parse_from_rfc3339("2020-06-30T18:32:30.792494106Z")
1327 .unwrap()
1328 .naive_utc(),
1329 ),
1330 ),
1331 ),
1332 ]);
1333
1334 for (exp_key, exp_value) in expected_map {
1336 let value = log_event.get(exp_key).unwrap();
1337 assert_eq!(*value, exp_value);
1338 }
1339 }
1340
1341 #[test]
1342 fn test_parse_dnstap_data_with_invalid_data() {
1343 let mut log_event = LogEvent::default();
1344 let e = DnstapParser::parse(
1345 &mut log_event,
1346 Bytes::from(vec![1, 2, 3]),
1347 DnsParserOptions::default(),
1348 )
1349 .expect_err("Expected TrustDnsError.");
1350 assert!(e.to_string().contains("Protobuf message"));
1351 }
1352
1353 #[test]
1354 fn test_parse_dnstap_data_with_invalid_timestamp() {
1355 fn test_one_timestamp_parse(time_sec: u64, time_nsec: Option<u32>) -> Result<()> {
1356 let mut event = LogEvent::default();
1357 let root = owned_value_path!();
1358 let type_ids = HashSet::from([1]);
1359 DnstapParser::parse_dnstap_message_time(
1360 &mut event, &root, time_sec, time_nsec, 1, None, &type_ids,
1361 )
1362 }
1363 assert!(test_one_timestamp_parse(1337, Some(42)).is_ok());
1365 assert!(test_one_timestamp_parse(u64::MAX, Some(42)).is_err());
1367 assert!(test_one_timestamp_parse(u64::MAX, None).is_err());
1368 assert!(test_one_timestamp_parse(i64::MAX as u64, Some(42)).is_err());
1370 assert!(test_one_timestamp_parse(i64::MAX as u64, None).is_err());
1371 assert!(
1373 test_one_timestamp_parse((i64::MAX / 1_000_000_000) as u64, Some(u32::MAX)).is_err()
1374 );
1375 assert!(test_one_timestamp_parse(96, Some(1616928816)).is_err());
1377 }
1378
1379 #[test]
1380 fn test_parse_dnstap_message_socket_family_bad_addr() {
1381 fn test_one_input(socket_family: i32, msg: DnstapMessage) -> Result<()> {
1383 let mut event = LogEvent::default();
1384 let root = owned_value_path!();
1385 DnstapParser::parse_dnstap_message_socket_family(&mut event, &root, socket_family, &msg)
1386 }
1387 {
1389 let message = DnstapMessage {
1390 query_address: Some(vec![]),
1391 ..Default::default()
1392 };
1393 assert!(test_one_input(1, message).is_err());
1394 }
1395 {
1396 let message = DnstapMessage {
1397 query_address: Some(vec![]),
1398 ..Default::default()
1399 };
1400 assert!(test_one_input(2, message).is_err());
1401 }
1402
1403 {
1404 let message = DnstapMessage {
1405 response_address: Some(vec![]),
1406 ..Default::default()
1407 };
1408 assert!(test_one_input(1, message).is_err());
1409 }
1410 {
1411 let message = DnstapMessage {
1412 response_address: Some(vec![]),
1413 ..Default::default()
1414 };
1415 assert!(test_one_input(2, message).is_err());
1416 }
1417 }
1418
1419 #[test]
1420 fn test_get_socket_family_name() {
1421 assert_eq!("INET", to_socket_family_name(1).unwrap());
1422 assert_eq!("INET6", to_socket_family_name(2).unwrap());
1423 assert!(to_socket_family_name(3).is_err());
1424 }
1425
1426 #[test]
1427 fn test_get_socket_protocol_name() {
1428 assert_eq!("UDP", to_socket_protocol_name(1).unwrap());
1429 assert_eq!("TCP", to_socket_protocol_name(2).unwrap());
1430 assert_eq!("DOT", to_socket_protocol_name(3).unwrap());
1431 assert_eq!("DOH", to_socket_protocol_name(4).unwrap());
1432 assert_eq!("DNSCryptUDP", to_socket_protocol_name(5).unwrap());
1433 assert_eq!("DNSCryptTCP", to_socket_protocol_name(6).unwrap());
1434 assert!(to_socket_protocol_name(7).is_err());
1435 }
1436}