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