Struct domain::base::message::Message

source ·
pub struct Message<Octs: ?Sized> { /* private fields */ }
Expand description

A DNS message.

This type wraps an octets sequence containing the complete wire-format DNS message and allows access to the various components of the message.

You create a message by passing an octets sequence to the from_octets associate function which does some basic sanity checks and, if they succeed, returns a message for the sequence. All further parsing happens lazily when you access more of the message. This means that a message is not necessarily well-formatted and further parsing may fail later on.

Section 4 of RFC 1035 defines DNS messages as being divded into five sections named header, question, answer, authority, and additional.

The header section is of a fixed sized and can be accessed at any time through the methods given under Header Section. Most likely, you will be interested in the first part of the header which is returned by the header method. The second part of the header section contains the number of entries in the following four sections and is of less interest as there are more sophisticated ways of accessing these sections. If you do care, you can get access through header_counts.

The meaning of the next four sections depends on the type of message as described by the opcode field of the header. Since the most common type is a query, the sections are named after their function in this type and the following description will focus on it.

The question section contains what was asked of the DNS by a query. It contains a number of questions that consist of a domain name, a record type, and class. A query asks for all records of the given record type that are owned by the domain name within the class. In queries, there will be exactly one question. With other opcodes, there may be multiple questions.

You can acquire an iterator over the questions through the question method. It returns a QuestionSection value that is an iterator over questions. Since a single question is such a common case, there is a convenience method first_question that returns the first question only.

The following three section all contain DNS resource records. In queries, they are empty in a request and may or may not contain records in a response. The answer section contains all the records that answer the given question. The authority section contains records declaring which name server provided authoritative information for the question, and the additional section can contain records that the name server thought might be useful for processing the question. For instance, if you trying to find out the mail server of a domain by asking for MX records, you likely also want the IP addresses for the server, so the name server may include these right away and free of charge.

There are functions to access all three sections directly: answer, authority, and additional. Each method returns a value of type RecordSection which acts as an iterator over the records in the section. Since there are no pointers to where the later sections start, accessing them directly means iterating over the previous sections. This is why it is more efficitent to call RecordSection::next_section to progress to a later section. Alternatively, you can use the message’s sections method that gives you all four sections at once with the minimal amount of iterating necessary.

When iterating over the record section, you will receive values of type ParsedRecord, an intermediary type that only parsed the parts common to all records. In order to access the data of the record, you will want to convert it into a Record which is generic over the actual record type data. This can be done via ParsedRecord::into_record.

Alternatively, you can trade the record section for one that only returns the types you are interested in via the RecordSection::limit_to method. The iterator returned by that method will quietly skip over all records that aren’t of the type you are interested in.

So, if you want to iterate over the MX records in the answer section, you would do something like this:

use domain::base::Message;
use domain::rdata::Mx;

let msg = Message::from_octets(octets).unwrap();
for record in msg.answer().unwrap().limit_to::<Mx<_>>() {
    if let Ok(record) = record {
        // Do something with the record ...
    }
}

The limit_to method takes the record type as a type argument. Many record types, like Mx, are generic over octet sequences but the compiler generally can figure out the concrete type itself, so in most cases you get away with the underscore there.

Note how the iterator doesn’t actually return records but results of records and parse errors. This is because only now can it check whether the record is actually properly formatted. An error signals that something went wrong while parsing. If only the record data is broken, the message remains useful and parsing can continue with the next record. If the message is fully broken, the next iteration will return None to signal that.

Implementations§

source§

impl<Octs> Message<Octs>

source

pub fn from_octets(octets: Octs) -> Result<Self, ShortMessage>where Octs: AsRef<[u8]>,

Creates a message from an octets sequence.

This fails if the slice is too short to even contain a complete header section. No further checks are done, though, so if this function returns ok, the message may still be broken with other methods returning errors later one.

source§

impl Message<[u8]>

source

pub fn from_slice(slice: &[u8]) -> Result<&Self, ShortMessage>

Creates a message from an octets slice.

This fails if the slice is too short to even contain a complete header section. No further checks are done, though, so if this function returns ok, the message may still be broken with other methods returning errors later one.

source§

impl<Octs: ?Sized> Message<Octs>

source

pub fn as_octets(&self) -> &Octs

Returns a reference to the underlying octets sequence.

source

pub fn into_octets(self) -> Octswhere Octs: Sized,

Converts the message into the underlying octets sequence.

source

pub fn as_slice(&self) -> &[u8] where Octs: AsRef<[u8]>,

Returns a slice to the underlying octets sequence.

source

pub fn for_slice(&self) -> &Message<[u8]>where Octs: AsRef<[u8]>,

Returns a message for a slice of the octets sequence.

source§

impl<Octs: AsRef<[u8]> + ?Sized> Message<Octs>

source

pub fn header(&self) -> Header

Returns the message header.

source

pub fn header_mut(&mut self) -> &mut Headerwhere Octs: AsMut<[u8]>,

Returns a mutable reference to the message header.

source

pub fn header_counts(&self) -> HeaderCounts

Returns the header counts of the message.

source

pub fn header_section(&self) -> HeaderSection

Returns the entire header section.

source

pub fn no_error(&self) -> bool

Returns whether the rcode of the header is NoError.

source

pub fn is_error(&self) -> bool

Returns whether the rcode of the header is one of the error values.

source§

impl<Octs: Octets + ?Sized> Message<Octs>

source

pub fn question(&self) -> QuestionSection<'_, Octs>

Returns the question section.

source

pub fn zone(&self) -> QuestionSection<'_, Octs>

Returns the zone section of an UPDATE message.

This is identical to self.question().

source

pub fn answer(&self) -> Result<RecordSection<'_, Octs>, ParseError>

Returns the answer section.

Iterates over the question section in order to access the answer section. If you are accessing the question section anyway, using its next_section method may be more efficient.

source

pub fn prerequisite(&self) -> Result<RecordSection<'_, Octs>, ParseError>

Returns the prerequisite section of an UPDATE message.

This is identical to self.answer().

source

pub fn authority(&self) -> Result<RecordSection<'_, Octs>, ParseError>

Returns the authority section.

Iterates over both the question and the answer sections to determine the start of the authority section. If you are already accessing the answer section, using next_section on it is more efficient.

source

pub fn update(&self) -> Result<RecordSection<'_, Octs>, ParseError>

Returns the update section of an UPDATE message.

This is identical to self.authority().

source

pub fn additional(&self) -> Result<RecordSection<'_, Octs>, ParseError>

Returns the additional section.

Iterates over all three previous sections to determine the start of the additional section. If you are already accessing the authority section, using next_section on it is more efficient.

source

pub fn sections( &self ) -> Result<(QuestionSection<'_, Octs>, RecordSection<'_, Octs>, RecordSection<'_, Octs>, RecordSection<'_, Octs>), ParseError>

Returns all four sections in one fell swoop.

source

pub fn iter(&self) -> MessageIter<'_, Octs>

Returns an iterator over the records in the message.

The iterator’s item is a pair of a ParsedRecord and the Section it was found in.

As is customary, this iterator is also accessible via the IntoIterator trait on a reference to the message.

source§

impl<Octs: Octets + ?Sized> Message<Octs>

source

pub fn is_answer<Other: Octets>(&self, query: &Message<Other>) -> bool

Returns whether this is the answer to some other message.

The method checks whether the ID fields of the headers are the same, whether the QR flag is set in this message, and whether the questions are the same.

source

pub fn first_question(&self) -> Option<Question<ParsedDname<Octs::Range<'_>>>>

Returns the first question, if there is any.

The method will return None both if there are no questions or if parsing fails.

source

pub fn sole_question( &self ) -> Result<Question<ParsedDname<Octs::Range<'_>>>, ParseError>

Returns the sole question of the message.

This is like first_question but returns an error if there isn’t exactly one question or there is a parse error.

source

pub fn qtype(&self) -> Option<Rtype>

Returns the query type of the first question, if any.

source

pub fn contains_answer<'s, Data>(&'s self) -> boolwhere Data: ParseRecordData<'s, Octs>,

Returns whether the message contains answers of a given type.

source

pub fn canonical_name(&self) -> Option<ParsedDname<Octs::Range<'_>>>

Resolves the canonical name of the answer.

The CNAME record allows a domain name to be an alias for a different name. Aliases may be chained. The ‘canonical name’ referred to be the method’s name is the last name in this chain. A recursive resolver will support a stub resolver in figuring out this canonical name by including all necessary CNAME records in its answer. This method can be used on such an answer to determine the canonical name. As such, it will only consider CNAMEs present in the message’s answer section.

It starts with the question name and follows CNAME records until there is no next CNAME in the chain and then returns the last CNAME.

If the message doesn’t have a question, if there is a parse error, or if there is a CNAME loop the method returns None.

source

pub fn opt(&self) -> Option<OptRecord<Octs::Range<'_>>>

Returns the OPT record from the message, if there is one.

source

pub fn get_last_additional<'s, Data: ParseRecordData<'s, Octs>>( &'s self ) -> Option<Record<ParsedDname<Octs::Range<'s>>, Data>>

Returns the last additional record from the message.

The method tries to parse the last record of the additional section as the provided record type. If that succeeds, it returns that parsed record.

If the last record is of the wrong type or parsing fails, returns None.

source

pub fn remove_last_additional(&mut self)where Octs: AsMut<[u8]>,

Drops the last additional record from the message.

Does so by decreasing the ’arcount.’ Does, however, not change the underlying octet sequence.

Panics

The method panics if the additional section is empty.

source

pub fn copy_records<'s, R, F, T, O>( &'s self, target: T, op: F ) -> Result<AdditionalBuilder<O>, CopyRecordsError>where Octs: Octets, R: ComposeRecord + 's, F: FnMut(ParsedRecord<'s, Octs>) -> Option<R>, T: Into<AnswerBuilder<O>>, O: Composer,

Copy records from a message into the target message builder.

The method uses op to process records from all record sections before inserting, caller can use this closure to filter or manipulate records before inserting.

Trait Implementations§

source§

impl<Octs: AsRef<[u8]> + ?Sized> AsRef<[u8]> for Message<Octs>

source§

fn as_ref(&self) -> &[u8]

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl AsRef<Message<Bytes>> for Answer

source§

fn as_ref(&self) -> &Message<Bytes>

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<Octs> AsRef<Octs> for Message<Octs>

source§

fn as_ref(&self) -> &Octs

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<Octs: Clone + ?Sized> Clone for Message<Octs>

source§

fn clone(&self) -> Message<Octs>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<Octs: AsRef<[u8]> + ?Sized> Debug for Message<Octs>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<Message<Bytes>> for Answer

source§

fn from(message: Message<Bytes>) -> Self

Converts to this type from the input type.
source§

impl<'a, Octs: Octets + ?Sized> IntoIterator for &'a Message<Octs>

§

type Item = Result<(ParsedRecord<'a, Octs>, Section), ParseError>

The type of the elements being iterated over.
§

type IntoIter = MessageIter<'a, Octs>

Which kind of iterator are we turning this into?
source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
source§

impl<Octs, SrcOcts> OctetsFrom<Message<SrcOcts>> for Message<Octs>where Octs: OctetsFrom<SrcOcts>,

§

type Error = <Octs as OctetsFrom<SrcOcts>>::Error

source§

fn try_octets_from(source: Message<SrcOcts>) -> Result<Self, Self::Error>

Performs the conversion.
source§

impl<Octs: Copy + ?Sized> Copy for Message<Octs>

Auto Trait Implementations§

§

impl<Octs: ?Sized> RefUnwindSafe for Message<Octs>where Octs: RefUnwindSafe,

§

impl<Octs: ?Sized> Send for Message<Octs>where Octs: Send,

§

impl<Octs: ?Sized> Sync for Message<Octs>where Octs: Sync,

§

impl<Octs: ?Sized> Unpin for Message<Octs>where Octs: Unpin,

§

impl<Octs: ?Sized> UnwindSafe for Message<Octs>where Octs: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<Source, Target> OctetsInto<Target> for Sourcewhere Target: OctetsFrom<Source>,

§

type Error = <Target as OctetsFrom<Source>>::Error

source§

fn try_octets_into( self ) -> Result<Target, <Source as OctetsInto<Target>>::Error>

Performs the conversion.
source§

fn octets_into(self) -> Targetwhere Self::Error: Into<Infallible>,

Performs an infallible conversion.
source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

source§

fn vzip(self) -> V