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