domain/base/message.rs
1//! Accessing existing DNS messages.
2//!
3//! This module defines a number of types for processing the content of a DNS
4//! message in wire format. Because many components of the message are of
5//! varying length, this can only be done iteratively. The type [`Message`]
6//! wraps an octets sequence containing a complete message. It provides access
7//! to the four sections of the message via additional types.
8//!
9//! For details, see the [`Message`] type.
10//!
11//! [`Message`]: struct.Message.html
12
13use super::dig_printer::DigPrinter;
14use super::header::{Header, HeaderCounts, HeaderSection};
15use super::iana::{Class, OptRcode, Rcode, Rtype};
16use super::message_builder::{AdditionalBuilder, AnswerBuilder, PushError};
17use super::name::ParsedName;
18use super::opt::{Opt, OptRecord};
19use super::question::Question;
20use super::rdata::{ParseAnyRecordData, ParseRecordData};
21use super::record::{ComposeRecord, ParsedRecord, Record};
22use super::wire::{Composer, ParseError};
23use crate::rdata::rfc1035::Cname;
24use core::marker::PhantomData;
25use core::{fmt, mem};
26use octseq::{Octets, OctetsFrom, Parser};
27
28//------------ Message -------------------------------------------------------
29
30/// A DNS message.
31///
32/// This type wraps an octets sequence containing the complete wire-format DNS
33/// message and allows access to the various components of the message.
34///
35/// You create a message by passing an octets sequence to the [`from_octets`]
36/// associate function which does some basic sanity checks and, if they
37/// succeed, returns a message for the sequence. All further parsing happens
38/// lazily when you access more of the message. This means that a message is
39/// not necessarily well-formatted and further parsing may fail later on.
40///
41/// Section 4 of [RFC 1035] defines DNS messages as being divded into five
42/// sections named header, question, answer, authority, and additional.
43///
44/// The header section is of a fixed sized and can be accessed at any time
45/// through the methods given under [Header Section]. Most likely, you will
46/// be interested in the first part of the header which is
47/// returned by the [`header`] method. The second part of the header
48/// section contains the number of entries in the following four sections
49/// and is of less interest as there are more sophisticated ways of accessing
50/// these sections. If you do care, you can get access through
51/// [`header_counts`].
52///
53/// The meaning of the next four sections depends on the type of message as
54/// described by the [opcode] field of the header. Since the most common
55/// type is a query, the sections are named after their function in this type
56/// and the following description will focus on it.
57///
58/// The question section contains what was asked of the DNS by a query. It
59/// contains a number of questions that consist of a domain name, a record
60/// type, and class. A query asks for all records of the given record type
61/// that are owned by the domain name within the class. In queries, there will
62/// be exactly one question. With other opcodes, there may be multiple
63/// questions.
64///
65/// You can acquire an iterator over the questions through the [`question`]
66/// method. It returns a [`QuestionSection`] value that is an iterator over
67/// questions. Since a single question is such a common case, there is a
68/// convenience method [`first_question`] that returns the first question
69/// only.
70///
71/// The following three section all contain DNS resource records. In
72/// queries, they are empty in a request and may or may not contain records
73/// in a response. The *answer* section contains all the records that answer
74/// the given question. The *authority* section contains records declaring
75/// which name server provided authoritative information for the question,
76/// and the *additional* section can contain records that the name server
77/// thought might be useful for processing the question. For instance, if you
78/// trying to find out the mail server of a domain by asking for MX records,
79/// you likely also want the IP addresses for the server, so the name server
80/// may include these right away and free of charge.
81///
82/// There are functions to access all three sections directly: [`answer`],
83/// [`authority`], and [`additional`]. Each method returns a value of type
84/// [RecordSection] which acts as an iterator over the records in the
85/// section. Since there are no pointers to where the later sections start,
86/// accessing them directly means iterating over the previous sections. This
87/// is why it is more efficitent to call [`RecordSection::next_section`] to
88/// progress to a later section. Alternatively, you can use the message’s
89/// [`sections`] method that gives you all four sections at once with the
90/// minimal amount of iterating necessary.
91///
92/// When iterating over the record section, you will receive values of type
93/// [`ParsedRecord`], an intermediary type that only parsed the parts common
94/// to all records. In order to access the data of the record, you will want
95/// to convert it into a [`Record`] which is generic over the actual record
96/// type data. This can be done via [`ParsedRecord::into_record`].
97///
98/// Alternatively, you can trade the record section for one that only returns
99/// the types you are interested in via the [`RecordSection::limit_to`]
100/// method. The iterator returned by that method will quietly skip over all
101/// records that aren’t of the type you are interested in.
102///
103/// So, if you want to iterate over the MX records in the answer section, you
104/// would do something like this:
105///
106/// ```
107/// use domain::base::Message;
108/// use domain::rdata::Mx;
109///
110/// # let octets = b"\0\0\0\0\0\0\0\0\0\0\0\0".as_slice();
111/// let msg = Message::from_octets(octets).unwrap();
112/// for record in msg.answer().unwrap().limit_to::<Mx<_>>() {
113/// if let Ok(record) = record {
114/// // Do something with the record ...
115/// }
116/// }
117/// ```
118///
119/// The `limit_to` method takes the record type as a type argument. Many
120/// record types, like [`Mx`], are generic over octet sequences but the
121/// compiler generally can figure out the concrete type itself, so in most
122/// cases you get away with the underscore there.
123///
124/// Note how the iterator doesn’t actually return records but results of
125/// records and parse errors. This is because only now can it check whether
126/// the record is actually properly formatted. An error signals that something
127/// went wrong while parsing. If only the record data is broken, the message
128/// remains useful and parsing can continue with the next record. If the
129/// message is fully broken, the next iteration will return `None` to signal
130/// that.
131///
132/// [`additional`]: #method.additional
133/// [`answer`]: #method.answer
134/// [`authority`]: #method.authority
135/// [`first_question`]: #method.first_question
136/// [`from_octets`]: #method.from_octets
137/// [`header`]: #method.header
138/// [`header_counts`]: #method.header_counts
139/// [`question`]: #method.question
140/// [`sections`]: #method.sections
141/// [`Mx`]: ../../rdata/rfc1035/struct.Mx.html
142/// [`ParsedRecord`]: ../record/struct.ParsedRecord.html
143/// [`ParsedRecord::into_record`]: ../record/struct.ParsedRecord.html#method.into_record
144/// [`QuestionSection`]: struct.QuestionSection.html
145/// [`Record`]: ../record/struct.Record.html
146/// [`RecordSection`]: struct.RecordSection.html
147/// [`RecordSection::limit_to`]: ../struct.RecordSection.html#method.limit_to
148/// [`RecordSection::next_section`]: ../struct.RecordSection.html#method.next_section
149/// [Header Section]: #header-section
150/// [rdata]: ../../rdata/index.html
151/// [opcode]: ../iana/opcode/enum.Opcode.html
152/// [RFC 1035]: https://tools.ietf.org/html/rfc1035
153#[derive(Clone, Copy)]
154#[repr(transparent)]
155pub struct Message<Octs: ?Sized> {
156 octets: Octs,
157}
158
159/// # Creation and Conversion
160///
161impl<Octs> Message<Octs> {
162 /// Creates a message from an octets sequence.
163 ///
164 /// This fails if the slice is too short to even contain a complete
165 /// header section. No further checks are done, though, so if this
166 /// function returns ok, the message may still be broken with other
167 /// methods returning errors later one.
168 pub fn from_octets(octets: Octs) -> Result<Self, ShortMessage>
169 where
170 Octs: AsRef<[u8]>,
171 {
172 Message::check_slice(octets.as_ref())?;
173 Ok(unsafe { Self::from_octets_unchecked(octets) })
174 }
175
176 /// Creates a message from octets, returning the octets if it fails.
177 pub fn try_from_octets(octets: Octs) -> Result<Self, Octs>
178 where
179 Octs: AsRef<[u8]>,
180 {
181 if Message::check_slice(octets.as_ref()).is_err() {
182 Err(octets)
183 } else {
184 Ok(unsafe { Self::from_octets_unchecked(octets) })
185 }
186 }
187
188 /// Creates a message from a bytes value without checking.
189 ///
190 /// # Safety
191 ///
192 /// The methods for header access rely on the octets being at least as
193 /// long as a header. If the sequence is shorter, the behavior is
194 /// undefined.
195 pub(super) unsafe fn from_octets_unchecked(octets: Octs) -> Self {
196 Message { octets }
197 }
198}
199
200impl Message<[u8]> {
201 /// Creates a message from an octets slice.
202 ///
203 /// This fails if the slice is too short to even contain a complete
204 /// header section. No further checks are done, though, so if this
205 /// function returns ok, the message may still be broken with other
206 /// methods returning errors later one.
207 pub fn from_slice(slice: &[u8]) -> Result<&Self, ShortMessage> {
208 Message::check_slice(slice)?;
209 Ok(unsafe { Self::from_slice_unchecked(slice) })
210 }
211
212 /// Creates a message from a bytes value without checking.
213 ///
214 /// # Safety
215 ///
216 /// The methods for header access rely on the octets being at least as
217 /// long as a header. If the sequence is shorter, the behavior is
218 /// undefined.
219 unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
220 // SAFETY: Message has repr(transparent)
221 mem::transmute(slice)
222 }
223
224 /// Checks that the slice can be used for a message.
225 fn check_slice(slice: &[u8]) -> Result<(), ShortMessage> {
226 if slice.len() < mem::size_of::<HeaderSection>() {
227 Err(ShortMessage(()))
228 } else {
229 Ok(())
230 }
231 }
232}
233
234impl<Octs: ?Sized> Message<Octs> {
235 /// Returns a reference to the underlying octets sequence.
236 pub fn as_octets(&self) -> &Octs {
237 &self.octets
238 }
239
240 /// Converts the message into the underlying octets sequence.
241 pub fn into_octets(self) -> Octs
242 where
243 Octs: Sized,
244 {
245 self.octets
246 }
247
248 /// Returns a slice to the underlying octets sequence.
249 pub fn as_slice(&self) -> &[u8]
250 where
251 Octs: AsRef<[u8]>,
252 {
253 self.octets.as_ref()
254 }
255
256 /// Returns a mutable slice to the underlying octets sequence.
257 ///
258 /// Because it is possible to utterly break the message using this slice,
259 /// the method is private.
260 fn as_slice_mut(&mut self) -> &mut [u8]
261 where
262 Octs: AsMut<[u8]>,
263 {
264 self.octets.as_mut()
265 }
266
267 /// Returns a message for a slice of the octets sequence.
268 pub fn for_slice(&self) -> &Message<[u8]>
269 where
270 Octs: AsRef<[u8]>,
271 {
272 unsafe { Message::from_slice_unchecked(self.octets.as_ref()) }
273 }
274
275 /// Returns a message for a slice reference.
276 pub fn for_slice_ref(&self) -> Message<&[u8]>
277 where
278 Octs: AsRef<[u8]>,
279 {
280 unsafe { Message::from_octets_unchecked(self.octets.as_ref()) }
281 }
282}
283
284/// # Header Section
285///
286impl<Octs: AsRef<[u8]> + ?Sized> Message<Octs> {
287 /// Returns the message header.
288 pub fn header(&self) -> Header {
289 *Header::for_message_slice(self.as_slice())
290 }
291
292 /// Returns a mutable reference to the message header.
293 pub fn header_mut(&mut self) -> &mut Header
294 where
295 Octs: AsMut<[u8]>,
296 {
297 Header::for_message_slice_mut(self.as_slice_mut())
298 }
299
300 /// Returns the header counts of the message.
301 pub fn header_counts(&self) -> HeaderCounts {
302 *HeaderCounts::for_message_slice(self.as_slice())
303 }
304
305 /// Returns the entire header section.
306 pub fn header_section(&self) -> HeaderSection {
307 *HeaderSection::for_message_slice(self.as_slice())
308 }
309
310 /// Returns whether the rcode of the header is NoError.
311 pub fn no_error(&self) -> bool {
312 self.header().rcode() == Rcode::NOERROR
313 }
314
315 /// Returns whether the rcode of the header is one of the error values.
316 pub fn is_error(&self) -> bool {
317 self.header().rcode() != Rcode::NOERROR
318 }
319}
320
321/// # Access to Sections
322///
323impl<Octs: Octets + ?Sized> Message<Octs> {
324 /// Returns the question section.
325 pub fn question(&self) -> QuestionSection<'_, Octs> {
326 QuestionSection::new(&self.octets)
327 }
328
329 /// Returns the zone section of an UPDATE message.
330 ///
331 /// This is identical to `self.question()`.
332 pub fn zone(&self) -> QuestionSection<'_, Octs> {
333 self.question()
334 }
335
336 /// Returns the answer section.
337 ///
338 /// Iterates over the question section in order to access the answer
339 /// section. If you are accessing the question section anyway, using
340 /// its [`next_section`] method may be more efficient.
341 ///
342 /// [`next_section`]: ../struct.QuestionSection.html#method.next_section
343 pub fn answer(&self) -> Result<RecordSection<'_, Octs>, ParseError> {
344 self.question().next_section()
345 }
346
347 /// Returns the prerequisite section of an UPDATE message.
348 ///
349 /// This is identical to `self.answer()`.
350 pub fn prerequisite(
351 &self,
352 ) -> Result<RecordSection<'_, Octs>, ParseError> {
353 self.answer()
354 }
355
356 /// Returns the authority section.
357 ///
358 /// Iterates over both the question and the answer sections to determine
359 /// the start of the authority section. If you are already accessing the
360 /// answer section, using [`next_section`] on it is more efficient.
361 ///
362 /// [`next_section`]: ../struct.RecordSection.html#method.next_section
363 pub fn authority(&self) -> Result<RecordSection<'_, Octs>, ParseError> {
364 Ok(self.answer()?.next_section()?.unwrap())
365 }
366
367 /// Returns the update section of an UPDATE message.
368 ///
369 /// This is identical to `self.authority()`.
370 pub fn update(&self) -> Result<RecordSection<'_, Octs>, ParseError> {
371 self.authority()
372 }
373
374 /// Returns the additional section.
375 ///
376 /// Iterates over all three previous sections to determine the start of
377 /// the additional section. If you are already accessing the
378 /// authority section, using [`next_section`] on it is more efficient.
379 ///
380 /// [`next_section`]: ../struct.RecordSection.html#method.next_section
381 pub fn additional(&self) -> Result<RecordSection<'_, Octs>, ParseError> {
382 Ok(self.authority()?.next_section()?.unwrap())
383 }
384
385 /// Returns all four sections in one fell swoop.
386 #[allow(clippy::type_complexity)]
387 pub fn sections(
388 &self,
389 ) -> Result<
390 (
391 QuestionSection<'_, Octs>,
392 RecordSection<'_, Octs>,
393 RecordSection<'_, Octs>,
394 RecordSection<'_, Octs>,
395 ),
396 ParseError,
397 > {
398 let question = self.question();
399 let answer = question.next_section()?;
400 let authority = answer.next_section()?.unwrap();
401 let additional = authority.next_section()?.unwrap();
402 Ok((question, answer, authority, additional))
403 }
404
405 /// Returns an iterator over the records in the message.
406 ///
407 /// The iterator’s item is a pair of a [`ParsedRecord`] and the
408 /// [`Section`] it was found in.
409 ///
410 /// As is customary, this iterator is also accessible via the
411 /// `IntoIterator` trait on a reference to the message.
412 ///
413 /// [`ParsedRecord`]: ../record/struct.ParsedRecord.html
414 /// [`Section`]: enum.Section.html
415 pub fn iter(&self) -> MessageIter<'_, Octs> {
416 self.into_iter()
417 }
418}
419
420/// # Helpers for Common Tasks
421///
422impl<Octs: Octets + ?Sized> Message<Octs> {
423 /// Returns whether this is the answer to some other message.
424 ///
425 /// The method checks whether the ID fields of the headers are the same,
426 /// whether the QR flag is set in this message, and whether the questions
427 /// are the same.
428 pub fn is_answer<Other: Octets + ?Sized>(
429 &self,
430 query: &Message<Other>,
431 ) -> bool {
432 if !self.header().qr()
433 || self.header().id() != query.header().id()
434 || self.header_counts().qdcount()
435 != query.header_counts().qdcount()
436 {
437 false
438 } else {
439 self.question() == query.question()
440 }
441 }
442
443 /// Returns whether the message has a question that is either AXFR or
444 /// IXFR.
445 pub fn is_xfr(&self) -> bool {
446 self.first_question()
447 .map(|q| matches!(q.qtype(), Rtype::AXFR | Rtype::IXFR))
448 .unwrap_or_default()
449 }
450
451 /// Returns the first question, if there is any.
452 ///
453 /// The method will return `None` both if there are no questions or if
454 /// parsing fails.
455 pub fn first_question(
456 &self,
457 ) -> Option<Question<ParsedName<Octs::Range<'_>>>> {
458 match self.question().next() {
459 None | Some(Err(..)) => None,
460 Some(Ok(question)) => Some(question),
461 }
462 }
463
464 /// Returns the sole question of the message.
465 ///
466 /// This is like [`first_question`] but returns an error if there isn’t
467 /// exactly one question or there is a parse error.
468 ///
469 /// [`first_question`]: #method.first_question
470 pub fn sole_question(
471 &self,
472 ) -> Result<Question<ParsedName<Octs::Range<'_>>>, ParseError> {
473 match self.header_counts().qdcount() {
474 0 => return Err(ParseError::form_error("no question")),
475 1 => {}
476 _ => return Err(ParseError::form_error("multiple questions")),
477 }
478 self.question().next().unwrap()
479 }
480
481 /// Returns the query type of the first question, if any.
482 pub fn qtype(&self) -> Option<Rtype> {
483 self.first_question().map(|x| x.qtype())
484 }
485
486 /// Returns whether the message contains answers of a given type.
487 pub fn contains_answer<'s, Data>(&'s self) -> bool
488 where
489 Data: ParseRecordData<'s, Octs>,
490 {
491 let answer = match self.answer() {
492 Ok(answer) => answer,
493 Err(..) => return false,
494 };
495 answer.limit_to::<Data>().next().is_some()
496 }
497
498 /// Resolves the canonical name of the answer.
499 ///
500 /// The CNAME record allows a domain name to be an alias for a different
501 /// name. Aliases may be chained. The ‘canonical name’ referred to be the
502 /// method’s name is the last name in this chain. A recursive resolver
503 /// will support a stub resolver in figuring out this canonical name by
504 /// including all necessary CNAME records in its answer. This method can
505 /// be used on such an answer to determine the canonical name. As such,
506 /// it will only consider CNAMEs present in the message’s answer section.
507 ///
508 /// It starts with the question name and follows CNAME records until there
509 /// is no next CNAME in the chain and then returns the last CNAME.
510 ///
511 /// If the message doesn’t have a question, if there is a parse error, or
512 /// if there is a CNAME loop the method returns `None`.
513 //
514 // Loop detection is done by breaking off after ANCOUNT + 1 steps -- if
515 // there is more steps then there is records in the answer section we
516 // must have a loop. While the ANCOUNT could be unreasonably large, the
517 // iterator would break off in this case and we break out with a None
518 // right away.
519 pub fn canonical_name(&self) -> Option<ParsedName<Octs::Range<'_>>> {
520 let question = self.first_question()?;
521 let mut name = question.into_qname();
522 let answer = match self.answer() {
523 Ok(answer) => answer.limit_to::<Cname<_>>(),
524 Err(_) => return None,
525 };
526
527 for _ in 0..self.header_counts().ancount() + 1 {
528 let mut found = false;
529 for record in answer.clone() {
530 let record = match record {
531 Ok(record) => record,
532 Err(_) => continue,
533 };
534 if *record.owner() == name {
535 name = record.into_data().into_cname();
536 found = true;
537 break;
538 }
539 }
540 if !found {
541 return Some(name);
542 }
543 }
544
545 None
546 }
547
548 /// Returns the OPT record from the message, if there is one.
549 pub fn opt(&self) -> Option<OptRecord<Octs::Range<'_>>> {
550 match self.additional() {
551 Ok(section) => match section.limit_to::<Opt<_>>().next() {
552 Some(Ok(rr)) => Some(OptRecord::from(rr)),
553 _ => None,
554 },
555 Err(_) => None,
556 }
557 }
558
559 /// Returns the last additional record from the message.
560 ///
561 /// The method tries to parse the last record of the additional section
562 /// as the provided record type. If that succeeds, it returns that
563 /// parsed record.
564 ///
565 /// If the last record is of the wrong type or parsing fails, returns
566 /// `None`.
567 pub fn get_last_additional<'s, Data: ParseRecordData<'s, Octs>>(
568 &'s self,
569 ) -> Option<Record<ParsedName<Octs::Range<'s>>, Data>> {
570 let mut section = match self.additional() {
571 Ok(section) => section,
572 Err(_) => return None,
573 };
574 loop {
575 match section.count {
576 Err(_) => return None,
577 Ok(0) => return None,
578 Ok(1) => break,
579 _ => {}
580 }
581 let _ = section.next();
582 }
583 let record = match ParsedRecord::parse(&mut section.parser) {
584 Ok(record) => record,
585 Err(_) => return None,
586 };
587 let record = match record.into_record() {
588 Ok(Some(record)) => record,
589 _ => return None,
590 };
591 Some(record)
592 }
593
594 /// Drops the last additional record from the message.
595 ///
596 /// Does so by decreasing the ’arcount.’ Does, however, not change the
597 /// underlying octet sequence.
598 ///
599 /// # Panics
600 ///
601 /// The method panics if the additional section is empty.
602 pub fn remove_last_additional(&mut self)
603 where
604 Octs: AsMut<[u8]>,
605 {
606 HeaderCounts::for_message_slice_mut(self.octets.as_mut())
607 .dec_arcount();
608 }
609
610 /// Copy records from a message into the target message builder.
611 ///
612 /// The method uses `op` to process records from all record sections
613 /// before inserting, caller can use this closure to filter or manipulate
614 /// records before inserting.
615 pub fn copy_records<'s, R, F, T, O>(
616 &'s self,
617 target: T,
618 mut op: F,
619 ) -> Result<AdditionalBuilder<O>, CopyRecordsError>
620 where
621 Octs: Octets,
622 R: ComposeRecord + 's,
623 F: FnMut(ParsedRecord<'s, Octs>) -> Option<R>,
624 T: Into<AnswerBuilder<O>>,
625 O: Composer,
626 {
627 let mut source = self.answer()?;
628 let mut target = target.into();
629 for rr in &mut source {
630 let rr = rr?;
631 if let Some(rr) = op(rr) {
632 target.push(rr).map_err(CopyRecordsError::Push)?;
633 }
634 }
635
636 let mut source = source.next_section()?.unwrap();
637 let mut target = target.authority();
638 for rr in &mut source {
639 let rr = rr?;
640 if let Some(rr) = op(rr) {
641 target.push(rr).map_err(CopyRecordsError::Push)?;
642 }
643 }
644
645 let source = source.next_section()?.unwrap();
646 let mut target = target.additional();
647 for rr in source {
648 let rr = rr?;
649 if let Some(rr) = op(rr) {
650 target.push(rr).map_err(CopyRecordsError::Push)?;
651 }
652 }
653
654 Ok(target)
655 }
656
657 /// Get the extended rcode of a message or the normal rcode converted
658 /// to an extended rcode if no opt record is present.
659 pub fn opt_rcode(&self) -> OptRcode {
660 self.opt()
661 .map(|opt| opt.rcode(self.header()))
662 .unwrap_or_else(|| self.header().rcode().into())
663 }
664}
665
666/// # Printing
667impl<Octs: AsRef<[u8]>> Message<Octs> {
668 /// Create a wrapper that displays the message in a dig style
669 ///
670 /// The dig style resembles a zonefile format (see also [`ZonefileFmt`]),
671 /// with additional lines that are commented out that contain information
672 /// about the header, OPT record and more.
673 ///
674 /// [`ZonefileFmt`]: super::zonefile_fmt::ZonefileFmt
675 pub fn display_dig_style(&self) -> impl core::fmt::Display + '_ {
676 DigPrinter { msg: self }
677 }
678}
679
680//--- AsRef
681
682// Octs here can’t be ?Sized or it’ll conflict with AsRef<[u8]> below.
683// But [u8] is covered by that impl anyway, so no harm done.
684//
685impl<Octs> AsRef<Octs> for Message<Octs> {
686 fn as_ref(&self) -> &Octs {
687 &self.octets
688 }
689}
690
691impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for Message<Octs> {
692 fn as_ref(&self) -> &[u8] {
693 self.octets.as_ref()
694 }
695}
696
697impl<Octs: AsRef<[u8]> + ?Sized> AsRef<Message<[u8]>> for Message<Octs> {
698 fn as_ref(&self) -> &Message<[u8]> {
699 unsafe { Message::from_slice_unchecked(self.octets.as_ref()) }
700 }
701}
702
703//--- OctetsFrom
704
705impl<Octs, SrcOcts> OctetsFrom<Message<SrcOcts>> for Message<Octs>
706where
707 Octs: OctetsFrom<SrcOcts>,
708{
709 type Error = Octs::Error;
710
711 fn try_octets_from(
712 source: Message<SrcOcts>,
713 ) -> Result<Self, Self::Error> {
714 Octs::try_octets_from(source.octets)
715 .map(|octets| unsafe { Self::from_octets_unchecked(octets) })
716 }
717}
718
719//--- IntoIterator
720
721impl<'a, Octs: Octets + ?Sized> IntoIterator for &'a Message<Octs> {
722 type Item = Result<(ParsedRecord<'a, Octs>, Section), ParseError>;
723 type IntoIter = MessageIter<'a, Octs>;
724
725 fn into_iter(self) -> Self::IntoIter {
726 MessageIter {
727 inner: self.answer().ok(),
728 }
729 }
730}
731
732//--- Debug
733
734impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Message<Octs> {
735 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
736 f.debug_struct("Message")
737 .field("id", &self.header().id())
738 .field("qr", &self.header().qr())
739 .field("opcode", &self.header().opcode())
740 .field("flags", &self.header().flags())
741 .field("rcode", &self.header().rcode())
742 .field("qdcount", &self.header_counts().qdcount())
743 .field("ancount", &self.header_counts().ancount())
744 .field("nscount", &self.header_counts().nscount())
745 .field("arcount", &self.header_counts().arcount())
746 .finish()
747 }
748}
749
750//------------ QuestionSection ----------------------------------------------
751
752/// An iterator over the question section of a DNS message.
753///
754/// The iterator’s item is the result of trying to parse the question. In case
755/// of a parse error, `next` will return an error once and `None` after that.
756///
757/// You can create a value of this type through [`Message::question`]. Use the
758/// [`answer`] or [`next_section`] methods on a question section to proceed
759/// to an iterator over the answer section.
760///
761/// [`Message::question`]: struct.Message.html#method.question
762/// [`answer`]: #method.answer
763/// [`next_section`]: #method.next_section
764#[derive(Debug)]
765pub struct QuestionSection<'a, Octs: ?Sized> {
766 /// The parser for generating the questions.
767 parser: Parser<'a, Octs>,
768
769 /// The remaining number of questions.
770 ///
771 /// The `Result` is here to monitor an error during iteration.
772 /// It is used to fuse the iterator after an error and is also returned
773 /// by `answer()` should that be called after an error.
774 count: Result<u16, ParseError>,
775}
776
777impl<'a, Octs: Octets + ?Sized> QuestionSection<'a, Octs> {
778 /// Creates a new question section from a reference to the message octets.
779 fn new(octets: &'a Octs) -> Self {
780 let mut parser = Parser::from_ref(octets);
781 parser.advance(mem::size_of::<HeaderSection>()).unwrap();
782 QuestionSection {
783 count: Ok(
784 HeaderCounts::for_message_slice(parser.as_slice()).qdcount()
785 ),
786 parser,
787 }
788 }
789
790 /// Returns the current position relative to the beginning of the message.
791 #[must_use]
792 pub fn pos(&self) -> usize {
793 self.parser.pos()
794 }
795
796 /// Proceeds to the answer section.
797 ///
798 /// Skips over any remaining questions and then converts itself into the
799 /// first [`RecordSection`].
800 ///
801 /// [`RecordSection`]: struct.RecordSection.html
802 pub fn answer(mut self) -> Result<RecordSection<'a, Octs>, ParseError> {
803 while self.next().is_some() {}
804 let _ = self.count?;
805 Ok(RecordSection::new(self.parser, Section::first()))
806 }
807
808 /// Proceeds to the answer section.
809 ///
810 /// This is identical to [`answer`][Self::answer] and is here for
811 /// consistency.
812 pub fn next_section(self) -> Result<RecordSection<'a, Octs>, ParseError> {
813 self.answer()
814 }
815}
816
817//--- Clone and Clone
818
819impl<Octs: ?Sized> Clone for QuestionSection<'_, Octs> {
820 fn clone(&self) -> Self {
821 *self
822 }
823}
824
825impl<Octs: ?Sized> Copy for QuestionSection<'_, Octs> {}
826
827//--- Iterator
828
829impl<'a, Octs: Octets + ?Sized> Iterator for QuestionSection<'a, Octs> {
830 type Item = Result<Question<ParsedName<Octs::Range<'a>>>, ParseError>;
831
832 fn next(&mut self) -> Option<Self::Item> {
833 match self.count {
834 Ok(count) if count > 0 => match Question::parse(&mut self.parser)
835 {
836 Ok(question) => {
837 self.count = Ok(count - 1);
838 Some(Ok(question))
839 }
840 Err(err) => {
841 self.count = Err(err);
842 Some(Err(err))
843 }
844 },
845 _ => None,
846 }
847 }
848}
849
850//--- PartialEq
851
852impl<'o, Octs, Other> PartialEq<QuestionSection<'o, Other>>
853 for QuestionSection<'_, Octs>
854where
855 Octs: Octets + ?Sized,
856 Other: Octets + ?Sized,
857{
858 fn eq(&self, other: &QuestionSection<'o, Other>) -> bool {
859 let mut me = *self;
860 let mut other = *other;
861 loop {
862 match (me.next(), other.next()) {
863 (Some(Ok(left)), Some(Ok(right))) => {
864 if left != right {
865 return false;
866 }
867 }
868 (None, None) => return true,
869 _ => return false,
870 }
871 }
872 }
873}
874
875//------------ Section -------------------------------------------------------
876
877/// A helper type enumerating the three kinds of record sections.
878///
879/// See the documentation of [`Message`] for what the three sections are.
880///
881/// [`Message`]: struct.Message.html
882#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)]
883pub enum Section {
884 Answer,
885 Authority,
886 Additional,
887}
888
889impl Section {
890 /// Returns the first section.
891 #[must_use]
892 pub fn first() -> Self {
893 Section::Answer
894 }
895
896 /// Returns the correct record count for this section.
897 fn count(self, counts: HeaderCounts) -> u16 {
898 match self {
899 Section::Answer => counts.ancount(),
900 Section::Authority => counts.nscount(),
901 Section::Additional => counts.arcount(),
902 }
903 }
904
905 /// Returns the value for the following section or `None` if this is last.
906 pub(crate) fn next_section(self) -> Option<Self> {
907 match self {
908 Section::Answer => Some(Section::Authority),
909 Section::Authority => Some(Section::Additional),
910 Section::Additional => None,
911 }
912 }
913}
914
915//------------ RecordSection -----------------------------------------------
916
917/// An iterator over the records in one of the three record sections.
918///
919/// The iterator’s item is the result of parsing a raw record represented by
920/// [`ParsedRecord`]. This type will allow access to an unparsed record. It
921/// can be converted into a concrete [`Record`] via its [`into_record`]
922/// method. If parsing the raw record fails, the iterator will return an
923/// error once and `None` after that.
924///
925/// Alternatively, you can trade in a value of this type into a
926/// [`RecordIter`] that iterates over [`Record`]s of a specific type by
927/// calling the [`limit_to`] method. In particular, you can use this together
928/// with [`AllRecordData`] to acquire an iterator that parses all known
929/// record types.
930///
931/// `RecordSection` values cannot be created directly. You can get one either
932/// by calling the method for the section in question of a [`Message`] value
933/// or by proceeding from another section via its `next_section` method.
934///
935/// [`limit_to`]: #method.limit_to
936/// [`AllRecordData`]: ../../rdata/enum.AllRecordData.html
937/// [`Message`]: struct.Message.html
938/// [`ParseRecord`]: ../record/struct.ParsedRecord.html
939/// [`Record`]: ../record/struct.Record.html
940/// [`RecordIter`]: struct.RecordIter.html
941/// [`into_record`]: ../record/struct.ParsedRecord.html#method.into_record
942#[derive(Debug)]
943pub struct RecordSection<'a, Octs: ?Sized> {
944 /// The parser for generating the records.
945 parser: Parser<'a, Octs>,
946
947 /// Which section are we, really?
948 section: Section,
949
950 /// The remaining number of records.
951 ///
952 /// The `Result` is here to monitor an error during iteration.
953 /// It is used to fuse the iterator after an error and is also returned
954 /// by `answer()` should that be called after an error.
955 count: Result<u16, ParseError>,
956}
957
958impl<'a, Octs: Octets + ?Sized> RecordSection<'a, Octs> {
959 /// Creates a new section from a parser.
960 ///
961 /// The parser must be positioned at the beginning of this section.
962 fn new(parser: Parser<'a, Octs>, section: Section) -> Self {
963 RecordSection {
964 count: Ok(section
965 .count(*HeaderCounts::for_message_slice(parser.as_slice()))),
966 section,
967 parser,
968 }
969 }
970
971 /// Returns the current position relative to the beginning of the message.
972 #[must_use]
973 pub fn pos(&self) -> usize {
974 self.parser.pos()
975 }
976
977 /// Trades `self` in for an iterator limited to a concrete record type.
978 ///
979 /// The record type is given through its record data type. Since the data
980 /// is being parsed, this type must implement [`ParseRecordData`]. For
981 /// record data types that are generic over domain name types, this is
982 /// normally achieved by giving them a [`ParsedName`]. As a convenience,
983 /// type aliases for all the fundamental record data types exist in the
984 /// [domain::rdata::parsed] module.
985 ///
986 /// The returned limited iterator will continue at the current position
987 /// of `self`. It will *not* start from the beginning of the section.
988 ///
989 /// [`ParseRecordData`]: ../rdata/trait.ParseRecordData.html
990 /// [`ParsedName`]: ../name/struct.ParsedName.html
991 /// [domain::rdata::parsed]: ../../rdata/parsed/index.html
992 #[must_use]
993 pub fn limit_to<Data: ParseRecordData<'a, Octs>>(
994 self,
995 ) -> RecordIter<'a, Octs, Data> {
996 RecordIter::new(self, false)
997 }
998
999 /// Trades `self` in for an iterator limited to a type in IN class.
1000 ///
1001 /// Behaves exactly like [`limit_to`] but skips over records that are not
1002 /// of class IN.
1003 ///
1004 /// [`limit_to`]: #method.limit_to
1005 #[must_use]
1006 pub fn limit_to_in<Data: ParseRecordData<'a, Octs>>(
1007 self,
1008 ) -> RecordIter<'a, Octs, Data> {
1009 RecordIter::new(self, true)
1010 }
1011
1012 /// Trades `self` for an interator over all the record.
1013 #[must_use]
1014 pub fn into_records<Data: ParseAnyRecordData<'a, Octs>>(
1015 self,
1016 ) -> AnyRecordIter<'a, Octs, Data> {
1017 AnyRecordIter::new(self)
1018 }
1019
1020 /// Proceeds to the next section if there is one.
1021 ///
1022 /// Returns an error if parsing has failed and the message is unusable
1023 /// now.
1024 pub fn next_section(mut self) -> Result<Option<Self>, ParseError> {
1025 let section = match self.section.next_section() {
1026 Some(section) => section,
1027 None => return Ok(None),
1028 };
1029 while self.skip_next().is_some() {}
1030 let _ = self.count?;
1031 Ok(Some(RecordSection::new(self.parser, section)))
1032 }
1033
1034 /// Skip the next record.
1035 fn skip_next(&mut self) -> Option<Result<(), ParseError>> {
1036 match self.count {
1037 Ok(count) if count > 0 => {
1038 match ParsedRecord::skip(&mut self.parser) {
1039 Ok(_) => {
1040 self.count = Ok(count - 1);
1041 Some(Ok(()))
1042 }
1043 Err(err) => {
1044 self.count = Err(err);
1045 Some(Err(err))
1046 }
1047 }
1048 }
1049 _ => None,
1050 }
1051 }
1052}
1053
1054//--- Clone and Copy
1055
1056impl<Octs: ?Sized> Clone for RecordSection<'_, Octs> {
1057 fn clone(&self) -> Self {
1058 *self
1059 }
1060}
1061
1062impl<Octs: ?Sized> Copy for RecordSection<'_, Octs> {}
1063
1064//--- Iterator
1065
1066impl<'a, Octs: Octets + ?Sized> Iterator for RecordSection<'a, Octs> {
1067 type Item = Result<ParsedRecord<'a, Octs>, ParseError>;
1068
1069 fn next(&mut self) -> Option<Self::Item> {
1070 match self.count {
1071 Ok(count) if count > 0 => {
1072 match ParsedRecord::parse(&mut self.parser) {
1073 Ok(record) => {
1074 self.count = Ok(count - 1);
1075 Some(Ok(record))
1076 }
1077 Err(err) => {
1078 self.count = Err(err);
1079 Some(Err(err))
1080 }
1081 }
1082 }
1083 _ => None,
1084 }
1085 }
1086}
1087
1088//------------ MessageIter ---------------------------------------------------
1089
1090/// An iterator over the records of a message.
1091pub struct MessageIter<'a, Octs: ?Sized> {
1092 inner: Option<RecordSection<'a, Octs>>,
1093}
1094
1095impl<'a, Octs: Octets + ?Sized> Iterator for MessageIter<'a, Octs> {
1096 type Item = Result<(ParsedRecord<'a, Octs>, Section), ParseError>;
1097
1098 fn next(&mut self) -> Option<Self::Item> {
1099 // Try to get next record from current section
1100 match self.inner {
1101 Some(ref mut inner) => {
1102 let item = inner.next();
1103 if let Some(item) = item {
1104 return Some(item.map(|item| (item, inner.section)));
1105 }
1106 }
1107 None => return None,
1108 }
1109
1110 // Advance to next section if possible, and retry
1111 let inner = self.inner.take()?;
1112 match inner.next_section() {
1113 Ok(section) => {
1114 self.inner = section;
1115 self.next()
1116 }
1117 Err(err) => Some(Err(err)),
1118 }
1119 }
1120}
1121
1122//------------ RecordIter ----------------------------------------------------
1123
1124/// An iterator over specific records of a record section of a DNS message.
1125///
1126/// The iterator’s item type is the result of trying to parse a record.
1127/// It silently skips over all records that `Data` cannot or does not want to
1128/// parse. If parsing the record data fails, the iterator will return an
1129/// error but can continue with the next record. If parsing the entire record
1130/// fails the item will be an error and subsequent attempts to continue will
1131/// also produce errors. This case can be distinguished from an error while
1132/// parsing the record data by [`next_section`] returning an error, too.
1133///
1134/// You can create a value of this type through the
1135/// [`RecordSection::limit_to`] method.
1136///
1137/// [`next_section`]: #method.next_section
1138/// [`RecordSection::limit_to`]: struct.RecordSection.html#method.limit_to
1139#[derive(Debug)]
1140pub struct RecordIter<'a, Octs: ?Sized, Data> {
1141 section: RecordSection<'a, Octs>,
1142 in_only: bool,
1143 marker: PhantomData<Data>,
1144}
1145
1146impl<'a, Octs, Data> RecordIter<'a, Octs, Data>
1147where
1148 Octs: Octets + ?Sized,
1149 Data: ParseRecordData<'a, Octs>,
1150{
1151 /// Creates a new record iterator.
1152 fn new(section: RecordSection<'a, Octs>, in_only: bool) -> Self {
1153 RecordIter {
1154 section,
1155 in_only,
1156 marker: PhantomData,
1157 }
1158 }
1159
1160 /// Trades the limited iterator for the full iterator.
1161 ///
1162 /// The returned iterator will continue right after the last record
1163 /// previously returned.
1164 #[must_use]
1165 pub fn unwrap(self) -> RecordSection<'a, Octs> {
1166 self.section
1167 }
1168
1169 /// Proceeds to the next section if there is one.
1170 ///
1171 /// Returns an error if parsing the message has failed. Returns
1172 /// `Ok(None)` if this iterator was already on the additional section.
1173 pub fn next_section(
1174 self,
1175 ) -> Result<Option<RecordSection<'a, Octs>>, ParseError> {
1176 self.section.next_section()
1177 }
1178}
1179
1180//--- Clone
1181
1182impl<Octs: ?Sized, Data> Clone for RecordIter<'_, Octs, Data> {
1183 fn clone(&self) -> Self {
1184 RecordIter {
1185 section: self.section,
1186 in_only: self.in_only,
1187 marker: PhantomData,
1188 }
1189 }
1190}
1191
1192//--- Iterator
1193
1194impl<'a, Octs, Data> Iterator for RecordIter<'a, Octs, Data>
1195where
1196 Octs: Octets + ?Sized,
1197 Data: ParseRecordData<'a, Octs>,
1198{
1199 type Item = Result<Record<ParsedName<Octs::Range<'a>>, Data>, ParseError>;
1200
1201 fn next(&mut self) -> Option<Self::Item> {
1202 loop {
1203 let record = match self.section.next() {
1204 Some(Ok(record)) => record,
1205 Some(Err(err)) => return Some(Err(err)),
1206 None => return None,
1207 };
1208 if self.in_only && record.class() != Class::IN {
1209 continue;
1210 }
1211 match record.into_record() {
1212 Ok(Some(record)) => return Some(Ok(record)),
1213 Err(err) => return Some(Err(err)),
1214 Ok(None) => {}
1215 }
1216 }
1217 }
1218}
1219
1220//------------ AnyRecordIter -------------------------------------------------
1221
1222/// An iterator over the records of a record section of a DNS message.
1223///
1224/// The iterator’s item type is the result of trying to parse a record.
1225/// If parsing the record data fails, the iterator will return an
1226/// error but can continue with the next record. If parsing the entire record
1227/// fails the item will be an error and subsequent attempts to continue will
1228/// also produce errors. This case can be distinguished from an error while
1229/// parsing the record data by [`next_section`] returning an error, too.
1230///
1231/// [`next_section`]: Self::next_section
1232#[derive(Debug)]
1233pub struct AnyRecordIter<'a, Octs: ?Sized, Data> {
1234 section: RecordSection<'a, Octs>,
1235 marker: PhantomData<Data>,
1236}
1237
1238impl<'a, Octs, Data> AnyRecordIter<'a, Octs, Data>
1239where
1240 Octs: Octets + ?Sized,
1241 Data: ParseAnyRecordData<'a, Octs>,
1242{
1243 /// Creates a new record iterator.
1244 fn new(section: RecordSection<'a, Octs>) -> Self {
1245 Self {
1246 section,
1247 marker: PhantomData,
1248 }
1249 }
1250
1251 /// Trades the limited iterator for the full iterator.
1252 ///
1253 /// The returned iterator will continue right after the last record
1254 /// previously returned.
1255 #[must_use]
1256 pub fn unwrap(self) -> RecordSection<'a, Octs> {
1257 self.section
1258 }
1259
1260 /// Proceeds to the next section if there is one.
1261 ///
1262 /// Returns an error if parsing the message has failed. Returns
1263 /// `Ok(None)` if this iterator was already on the additional section.
1264 pub fn next_section(
1265 self,
1266 ) -> Result<Option<RecordSection<'a, Octs>>, ParseError> {
1267 self.section.next_section()
1268 }
1269}
1270
1271//--- Clone
1272
1273impl<Octs: ?Sized, Data> Clone for AnyRecordIter<'_, Octs, Data> {
1274 fn clone(&self) -> Self {
1275 Self {
1276 section: self.section,
1277 marker: PhantomData,
1278 }
1279 }
1280}
1281
1282//--- Iterator
1283
1284impl<'a, Octs, Data> Iterator for AnyRecordIter<'a, Octs, Data>
1285where
1286 Octs: Octets + ?Sized,
1287 Data: ParseAnyRecordData<'a, Octs>,
1288{
1289 type Item = Result<Record<ParsedName<Octs::Range<'a>>, Data>, ParseError>;
1290
1291 fn next(&mut self) -> Option<Self::Item> {
1292 let record = match self.section.next() {
1293 Some(Ok(record)) => record,
1294 Some(Err(err)) => return Some(Err(err)),
1295 None => return None,
1296 };
1297 Some(record.into_any_record())
1298 }
1299}
1300//============ Error Types ===================================================
1301
1302//------------ ShortMessage --------------------------------------------------
1303
1304/// A message was too short to even contain the header.
1305#[derive(Clone, Copy, Debug)]
1306pub struct ShortMessage(());
1307
1308impl fmt::Display for ShortMessage {
1309 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1310 f.write_str("short message")
1311 }
1312}
1313
1314#[cfg(feature = "std")]
1315impl std::error::Error for ShortMessage {}
1316
1317//------------ CopyRecordsError ----------------------------------------------
1318
1319/// An error occurrd while copying records.
1320#[derive(Clone, Copy, Debug)]
1321pub enum CopyRecordsError {
1322 /// Parsing the source message failed.
1323 Parse(ParseError),
1324
1325 /// Not enough space in the target.
1326 Push(PushError),
1327}
1328
1329//--- From
1330
1331impl From<ParseError> for CopyRecordsError {
1332 fn from(err: ParseError) -> Self {
1333 CopyRecordsError::Parse(err)
1334 }
1335}
1336
1337impl From<PushError> for CopyRecordsError {
1338 fn from(err: PushError) -> Self {
1339 CopyRecordsError::Push(err)
1340 }
1341}
1342
1343//--- Display and Error
1344
1345impl fmt::Display for CopyRecordsError {
1346 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1347 match *self {
1348 CopyRecordsError::Parse(ref err) => err.fmt(f),
1349 CopyRecordsError::Push(ref err) => err.fmt(f),
1350 }
1351 }
1352}
1353
1354#[cfg(feature = "std")]
1355impl std::error::Error for CopyRecordsError {}
1356
1357//============ Testing =======================================================
1358
1359#[cfg(test)]
1360mod test {
1361 use super::*;
1362 #[cfg(feature = "std")]
1363 use crate::base::message_builder::MessageBuilder;
1364 #[cfg(feature = "std")]
1365 use crate::base::name::Name;
1366 #[cfg(feature = "std")]
1367 use crate::rdata::{AllRecordData, Ns};
1368 #[cfg(feature = "std")]
1369 use std::vec::Vec;
1370
1371 // Helper for test cases
1372 #[cfg(feature = "std")]
1373 fn get_test_message() -> Message<Vec<u8>> {
1374 let msg = MessageBuilder::new_vec();
1375 let mut msg = msg.answer();
1376 msg.push((
1377 Name::vec_from_str("foo.example.com.").unwrap(),
1378 86000,
1379 Cname::new(Name::vec_from_str("baz.example.com.").unwrap()),
1380 ))
1381 .unwrap();
1382 let mut msg = msg.authority();
1383 msg.push((
1384 Name::vec_from_str("bar.example.com.").unwrap(),
1385 86000,
1386 Ns::new(Name::vec_from_str("baz.example.com.").unwrap()),
1387 ))
1388 .unwrap();
1389 msg.into_message()
1390 }
1391
1392 #[test]
1393 fn short_message() {
1394 assert!(Message::from_octets(&[0u8; 11]).is_err());
1395 assert!(Message::from_octets(&[0u8; 12]).is_ok());
1396 }
1397
1398 #[test]
1399 #[cfg(feature = "std")]
1400 fn canonical_name() {
1401 use crate::rdata::A;
1402
1403 // Message without CNAMEs.
1404 let mut msg = MessageBuilder::new_vec().question();
1405 msg.push((Name::vec_from_str("example.com.").unwrap(), Rtype::A))
1406 .unwrap();
1407 let msg_ref = msg.as_message();
1408 assert_eq!(
1409 Name::vec_from_str("example.com.").unwrap(),
1410 msg_ref.canonical_name().unwrap()
1411 );
1412
1413 // Message with CNAMEs.
1414 let mut msg = msg.answer();
1415 msg.push((
1416 Name::vec_from_str("bar.example.com.").unwrap(),
1417 86000,
1418 Cname::new(Name::vec_from_str("baz.example.com.").unwrap()),
1419 ))
1420 .unwrap();
1421 msg.push((
1422 Name::vec_from_str("example.com.").unwrap(),
1423 86000,
1424 Cname::new(Name::vec_from_str("foo.example.com.").unwrap()),
1425 ))
1426 .unwrap();
1427 msg.push((
1428 Name::vec_from_str("foo.example.com.").unwrap(),
1429 86000,
1430 Cname::new(Name::vec_from_str("bar.example.com.").unwrap()),
1431 ))
1432 .unwrap();
1433 let msg_ref = msg.as_message();
1434 assert_eq!(
1435 Name::vec_from_str("baz.example.com.").unwrap(),
1436 msg_ref.canonical_name().unwrap()
1437 );
1438
1439 // CNAME loop.
1440 msg.push((
1441 Name::vec_from_str("baz.example.com").unwrap(),
1442 86000,
1443 Cname::new(Name::vec_from_str("foo.example.com").unwrap()),
1444 ))
1445 .unwrap();
1446 assert!(msg.as_message().canonical_name().is_none());
1447 msg.push((
1448 Name::vec_from_str("baz.example.com").unwrap(),
1449 86000,
1450 A::from_octets(127, 0, 0, 1),
1451 ))
1452 .unwrap();
1453 assert!(msg.as_message().canonical_name().is_none());
1454 }
1455
1456 #[test]
1457 #[cfg(feature = "std")]
1458 fn message_iterator() {
1459 let msg = get_test_message();
1460 let mut iter = msg.iter();
1461
1462 // Check that it returns a record from first section
1463 let (_rr, section) = iter.next().unwrap().unwrap();
1464 assert_eq!(Section::Answer, section);
1465
1466 // Check that it advances to next section
1467 let (_rr, section) = iter.next().unwrap().unwrap();
1468 assert_eq!(Section::Authority, section);
1469 }
1470
1471 #[test]
1472 #[cfg(feature = "std")]
1473 fn copy_records() {
1474 let msg = get_test_message();
1475 let target = MessageBuilder::new_vec().question();
1476 let res = msg.copy_records(target.answer(), |rr| {
1477 if let Ok(Some(rr)) =
1478 rr.into_record::<AllRecordData<_, ParsedName<_>>>()
1479 {
1480 if rr.rtype() == Rtype::CNAME {
1481 return Some(rr);
1482 }
1483 }
1484 None
1485 });
1486
1487 assert!(res.is_ok());
1488 if let Ok(target) = res {
1489 let msg = target.into_message();
1490 assert_eq!(1, msg.header_counts().ancount());
1491 assert_eq!(0, msg.header_counts().arcount());
1492 }
1493 }
1494}