dns_parser_revived/rdata/
mx.rs

1use crate::{Error, Name};
2use byteorder::{BigEndian, ByteOrder};
3
4#[derive(Debug, Clone, Copy)]
5pub struct Record<'a> {
6    pub preference: u16,
7    pub exchange: Name<'a>,
8}
9
10impl<'a> super::Record<'a> for Record<'a> {
11    const TYPE: isize = 15;
12
13    fn parse(rdata: &'a [u8], original: &'a [u8]) -> super::RDataResult<'a> {
14        if rdata.len() < 3 {
15            return Err(Error::WrongRdataLength);
16        }
17        let record = Record {
18            preference: BigEndian::read_u16(&rdata[..2]),
19            exchange: Name::scan(&rdata[2..], original)?,
20        };
21        Ok(super::RData::MX(record))
22    }
23}
24
25#[cfg(test)]
26mod test {
27
28    use super::*;
29    use crate::Class as C;
30    use crate::Opcode::*;
31    use crate::QueryClass as QC;
32    use crate::QueryType as QT;
33    use crate::RData;
34    use crate::ResponseCode::NoError;
35    use crate::{Header, Packet};
36
37    #[test]
38    fn parse_response() {
39        let response = b"\xe3\xe8\x81\x80\x00\x01\x00\x05\x00\x00\x00\x00\
40            \x05gmail\x03com\x00\x00\x0f\x00\x01\xc0\x0c\x00\x0f\x00\x01\
41            \x00\x00\x04|\x00\x1b\x00\x05\rgmail-smtp-in\x01l\x06google\xc0\
42            \x12\xc0\x0c\x00\x0f\x00\x01\x00\x00\x04|\x00\t\x00\
43            \n\x04alt1\xc0)\xc0\x0c\x00\x0f\x00\x01\x00\x00\x04|\
44            \x00\t\x00(\x04alt4\xc0)\xc0\x0c\x00\x0f\x00\x01\x00\
45            \x00\x04|\x00\t\x00\x14\x04alt2\xc0)\xc0\x0c\x00\x0f\
46            \x00\x01\x00\x00\x04|\x00\t\x00\x1e\x04alt3\xc0)";
47        let packet = Packet::parse(response).unwrap();
48        assert_eq!(
49            packet.header,
50            Header {
51                id: 58344,
52                query: false,
53                opcode: StandardQuery,
54                authoritative: false,
55                truncated: false,
56                recursion_desired: true,
57                recursion_available: true,
58                authenticated_data: false,
59                checking_disabled: false,
60                response_code: NoError,
61                questions: 1,
62                answers: 5,
63                nameservers: 0,
64                additional: 0,
65            }
66        );
67        assert_eq!(packet.questions.len(), 1);
68        assert_eq!(packet.questions[0].qtype, QT::MX);
69        assert_eq!(packet.questions[0].qclass, QC::IN);
70        assert_eq!(&packet.questions[0].qname.to_string()[..], "gmail.com");
71        assert_eq!(packet.answers.len(), 5);
72        let items = [
73            (5, "gmail-smtp-in.l.google.com"),
74            (10, "alt1.gmail-smtp-in.l.google.com"),
75            (40, "alt4.gmail-smtp-in.l.google.com"),
76            (20, "alt2.gmail-smtp-in.l.google.com"),
77            (30, "alt3.gmail-smtp-in.l.google.com"),
78        ];
79        for (i, item) in items.iter().enumerate() {
80            assert_eq!(&packet.answers[i].name.to_string()[..], "gmail.com");
81            assert_eq!(packet.answers[i].cls, C::IN);
82            assert_eq!(packet.answers[i].ttl, 1148);
83            match packet.answers[i].data {
84                RData::MX(Record {
85                    preference,
86                    exchange,
87                }) => {
88                    assert_eq!(preference, item.0);
89                    assert_eq!(exchange.to_string(), (item.1).to_string());
90                }
91                ref x => panic!("Wrong rdata {:?}", x),
92            }
93        }
94    }
95}