1use crate::core::MtopError;
2use crate::dns::bytes::{read_be_u16, read_be_u32, write_be_u16, write_be_u32};
3use crate::dns::core::{RecordClass, RecordType};
4use crate::dns::name::Name;
5use crate::dns::rdata::RecordData;
6use std::fmt;
7use std::io::{Read, Seek, Write};
8
9#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
10#[repr(transparent)]
11pub struct MessageId(u16);
12
13impl MessageId {
14 pub fn random() -> Self {
15 Self(rand::random())
16 }
17
18 pub fn size(&self) -> usize {
19 2
20 }
21}
22
23impl From<u16> for MessageId {
24 fn from(value: u16) -> Self {
25 Self(value)
26 }
27}
28
29impl From<MessageId> for u16 {
30 fn from(value: MessageId) -> Self {
31 value.0
32 }
33}
34
35impl fmt::Display for MessageId {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 fmt::Display::fmt(&self.0, f)
38 }
39}
40
41#[derive(Debug, Clone, Eq, PartialEq)]
42pub struct Message {
43 id: MessageId,
44 flags: Flags,
45 questions: Vec<Question>,
46 answers: Vec<Record>,
47 authority: Vec<Record>,
48 extra: Vec<Record>,
49}
50
51impl Message {
52 pub fn new(id: MessageId, flags: Flags) -> Self {
53 Self {
54 id,
55 flags,
56 questions: Vec::new(),
57 answers: Vec::new(),
58 authority: Vec::new(),
59 extra: Vec::new(),
60 }
61 }
62
63 pub fn size(&self) -> usize {
64 self.id.size()
65 + self.flags.size()
66 + (2 * 4) + self.questions.iter().map(Question::size).sum::<usize>()
68 + self.answers.iter().map(Record::size).sum::<usize>()
69 + self.authority.iter().map(Record::size).sum::<usize>()
70 + self.extra.iter().map(Record::size).sum::<usize>()
71 }
72
73 pub fn id(&self) -> MessageId {
74 self.id
75 }
76
77 #[must_use]
78 pub fn set_id(mut self, id: MessageId) -> Self {
79 self.id = id;
80 self
81 }
82
83 pub fn flags(&self) -> Flags {
84 self.flags
85 }
86
87 #[must_use]
88 pub fn set_flags(mut self, flags: Flags) -> Self {
89 self.flags = flags;
90 self
91 }
92
93 pub fn questions(&self) -> &[Question] {
94 &self.questions
95 }
96
97 #[must_use]
98 pub fn add_question(mut self, q: Question) -> Self {
99 self.questions.push(q);
100 self
101 }
102
103 pub fn answers(&self) -> &[Record] {
104 &self.answers
105 }
106
107 #[must_use]
108 pub fn add_answer(mut self, r: Record) -> Self {
109 self.answers.push(r);
110 self
111 }
112
113 pub fn authority(&self) -> &[Record] {
114 &self.authority
115 }
116
117 #[must_use]
118 pub fn add_authority(mut self, r: Record) -> Self {
119 self.authority.push(r);
120 self
121 }
122
123 pub fn extra(&self) -> &[Record] {
124 &self.extra
125 }
126
127 #[must_use]
128 pub fn add_extra(mut self, r: Record) -> Self {
129 self.extra.push(r);
130 self
131 }
132
133 fn header(&self) -> Header {
134 assert!(self.questions.len() < usize::from(u16::MAX));
135 assert!(self.answers.len() < usize::from(u16::MAX));
136 assert!(self.authority.len() < usize::from(u16::MAX));
137 assert!(self.extra.len() < usize::from(u16::MAX));
138
139 Header {
140 id: self.id,
141 flags: self.flags,
142 num_questions: u16::try_from(self.questions.len()).unwrap(),
143 num_answers: u16::try_from(self.answers.len()).unwrap(),
144 num_authority: u16::try_from(self.authority.len()).unwrap(),
145 num_extra: u16::try_from(self.extra.len()).unwrap(),
146 }
147 }
148
149 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
150 where
151 T: Write,
152 {
153 let header = self.header();
154 header.write_network_bytes(&mut buf)?;
155
156 for q in &self.questions {
157 q.write_network_bytes(&mut buf)?;
158 }
159
160 for r in &self.answers {
161 r.write_network_bytes(&mut buf)?;
162 }
163
164 for r in &self.authority {
165 r.write_network_bytes(&mut buf)?;
166 }
167
168 for r in &self.extra {
169 r.write_network_bytes(&mut buf)?;
170 }
171
172 Ok(())
173 }
174
175 pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
176 where
177 T: Read + Seek,
178 {
179 let header = Header::read_network_bytes(&mut buf)?;
180
181 let mut questions = Vec::new();
182 for _ in 0..header.num_questions {
183 questions.push(Question::read_network_bytes(&mut buf)?);
184 }
185
186 let mut answers = Vec::new();
187 for _ in 0..header.num_answers {
188 answers.push(Record::read_network_bytes(&mut buf)?);
189 }
190
191 let mut authority = Vec::new();
192 for _ in 0..header.num_authority {
193 authority.push(Record::read_network_bytes(&mut buf)?);
194 }
195
196 let mut extra = Vec::new();
197 for _ in 0..header.num_extra {
198 extra.push(Record::read_network_bytes(&mut buf)?);
199 }
200
201 Ok(Self {
202 id: header.id,
203 flags: header.flags,
204 questions,
205 answers,
206 authority,
207 extra,
208 })
209 }
210}
211
212#[derive(Debug, Clone, Eq, PartialEq)]
213struct Header {
214 id: MessageId,
215 flags: Flags,
216 num_questions: u16,
217 num_answers: u16,
218 num_authority: u16,
219 num_extra: u16,
220}
221
222impl Header {
223 fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
224 where
225 T: Write,
226 {
227 write_be_u16(&mut buf, self.id.into())?;
228 write_be_u16(&mut buf, self.flags.as_u16())?;
229 write_be_u16(&mut buf, self.num_questions)?;
230 write_be_u16(&mut buf, self.num_answers)?;
231 write_be_u16(&mut buf, self.num_authority)?;
232 write_be_u16(&mut buf, self.num_extra)
233 }
234
235 fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
236 where
237 T: Read,
238 {
239 let id = MessageId::from(read_be_u16(&mut buf)?);
240 let flags = Flags::try_from(read_be_u16(&mut buf)?)?;
241 let num_questions = read_be_u16(&mut buf)?;
242 let num_answers = read_be_u16(&mut buf)?;
243 let num_authority = read_be_u16(&mut buf)?;
244 let num_extra = read_be_u16(&mut buf)?;
245
246 Ok(Header {
247 id,
248 flags,
249 num_questions,
250 num_answers,
251 num_authority,
252 num_extra,
253 })
254 }
255}
256
257#[derive(Default, Copy, Clone, Eq, PartialEq)]
258#[repr(transparent)]
259pub struct Flags(u16);
260
261impl Flags {
262 const MASK_QR: u16 = 0b1000_0000_0000_0000; const MASK_OP: u16 = 0b0111_1000_0000_0000; const MASK_AA: u16 = 0b0000_0100_0000_0000; const MASK_TC: u16 = 0b0000_0010_0000_0000; const MASK_RD: u16 = 0b0000_0001_0000_0000; const MASK_RA: u16 = 0b0000_0000_1000_0000; const MASK_RC: u16 = 0b0000_0000_0000_1111; const OFFSET_QR: usize = 15;
271 const OFFSET_OP: usize = 11;
272 const OFFSET_AA: usize = 10;
273 const OFFSET_TC: usize = 9;
274 const OFFSET_RD: usize = 8;
275 const OFFSET_RA: usize = 7;
276 const OFFSET_RC: usize = 0;
277
278 pub fn size(&self) -> usize {
279 2
280 }
281
282 pub fn is_query(&self) -> bool {
283 !(self.0 & Self::MASK_QR) > 0
284 }
285
286 #[must_use]
287 pub fn set_query(self) -> Self {
288 Flags(self.0 & !Self::MASK_QR)
289 }
290
291 pub fn is_response(&self) -> bool {
292 self.0 & Self::MASK_QR > 0
293 }
294
295 #[must_use]
296 pub fn set_response(self) -> Self {
297 Flags(self.0 | Self::MASK_QR)
298 }
299
300 pub fn get_op_code(&self) -> Operation {
301 Operation::try_from((self.0 & Self::MASK_OP) >> Self::OFFSET_OP).unwrap()
302 }
303
304 #[must_use]
305 pub fn set_op_code(self, op: Operation) -> Self {
306 let op = (op as u16) << Self::OFFSET_OP;
307 Flags(self.0 | op)
308 }
309
310 pub fn is_authoritative(&self) -> bool {
311 self.0 & Self::MASK_AA > 0
312 }
313
314 #[must_use]
315 pub fn set_authoritative(self) -> Self {
316 Flags(self.0 | Self::MASK_AA)
317 }
318
319 pub fn is_truncated(&self) -> bool {
320 self.0 & Self::MASK_TC > 0
321 }
322
323 #[must_use]
324 pub fn set_truncated(self) -> Self {
325 Flags(self.0 | Self::MASK_TC)
326 }
327
328 pub fn is_recursion_desired(&self) -> bool {
329 self.0 & Self::MASK_RD > 0
330 }
331
332 #[must_use]
333 pub fn set_recursion_desired(self) -> Self {
334 Flags(self.0 | Self::MASK_RD)
335 }
336
337 pub fn is_recursion_available(&self) -> bool {
338 self.0 & Self::MASK_RA > 0
339 }
340
341 #[must_use]
342 pub fn set_recursion_available(self) -> Self {
343 Flags(self.0 | Self::MASK_RA)
344 }
345
346 pub fn get_response_code(&self) -> ResponseCode {
347 ResponseCode::try_from((self.0 & Self::MASK_RC) >> Self::OFFSET_RC).unwrap()
348 }
349
350 #[must_use]
351 pub fn set_response_code(self, code: ResponseCode) -> Self {
352 let code = (code as u16) << Self::OFFSET_RC;
353 Flags(self.0 | code)
354 }
355
356 pub fn as_u16(&self) -> u16 {
357 self.0
358 }
359}
360
361impl TryFrom<u16> for Flags {
362 type Error = MtopError;
363
364 fn try_from(value: u16) -> Result<Self, Self::Error> {
365 let _op = Operation::try_from((value & Self::MASK_OP) >> Self::OFFSET_OP)?;
369 let _rc = ResponseCode::try_from((value & Self::MASK_RC) >> Self::OFFSET_RC)?;
370 Ok(Flags(value))
371 }
372}
373
374impl fmt::Debug for Flags {
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376 let qr = (self.0 & Self::MASK_QR) >> Self::OFFSET_QR;
377 let op = Operation::try_from((self.0 & Self::MASK_OP) >> Self::OFFSET_OP).unwrap();
378 let aa = (self.0 & Self::MASK_AA) >> Self::OFFSET_AA;
379 let tc = (self.0 & Self::MASK_TC) >> Self::OFFSET_TC;
380 let rd = (self.0 & Self::MASK_RD) >> Self::OFFSET_RD;
381 let ra = (self.0 & Self::MASK_RA) >> Self::OFFSET_RA;
382 let rc = ResponseCode::try_from((self.0 & Self::MASK_RC) >> Self::OFFSET_RC).unwrap();
383
384 write!(
385 f,
386 "Flags{{qr = {qr}, op = {op:?}, aa = {aa}, tc = {tc}, rd = {rd}, ra = {ra}, rc = {rc:?}}}"
387 )
388 }
389}
390
391#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
392#[repr(u16)]
393pub enum ResponseCode {
394 #[default]
395 NoError = 0,
396 FormatError = 1,
397 ServerFailure = 2,
398 NameError = 3,
399 NotImplemented = 4,
400 Refused = 5,
401 YxDomain = 6,
402 YxRrSet = 7,
403 NxRrSet = 8,
404 NotAuth = 9,
405 NotZone = 10,
406 BadVersion = 16,
407}
408
409impl fmt::Display for ResponseCode {
410 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
411 fmt::Debug::fmt(self, f)
412 }
413}
414
415impl TryFrom<u16> for ResponseCode {
416 type Error = MtopError;
417
418 fn try_from(value: u16) -> Result<Self, Self::Error> {
419 match value {
420 0 => Ok(ResponseCode::NoError),
421 1 => Ok(ResponseCode::FormatError),
422 2 => Ok(ResponseCode::ServerFailure),
423 3 => Ok(ResponseCode::NameError),
424 4 => Ok(ResponseCode::NotImplemented),
425 5 => Ok(ResponseCode::Refused),
426 6 => Ok(ResponseCode::YxDomain),
427 7 => Ok(ResponseCode::YxRrSet),
428 8 => Ok(ResponseCode::NxRrSet),
429 9 => Ok(ResponseCode::NotAuth),
430 10 => Ok(ResponseCode::NotZone),
431 16 => Ok(ResponseCode::BadVersion),
432 _ => Err(MtopError::runtime(format!(
433 "invalid or unsupported response code {}",
434 value
435 ))),
436 }
437 }
438}
439
440#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
441#[repr(u16)]
442pub enum Operation {
443 #[default]
444 Query = 0,
445 IQuery = 1,
446 Status = 2,
447 Notify = 4,
448 Update = 5,
449}
450
451impl TryFrom<u16> for Operation {
452 type Error = MtopError;
453
454 fn try_from(value: u16) -> Result<Self, Self::Error> {
455 match value {
456 0 => Ok(Operation::Query),
457 1 => Ok(Operation::IQuery),
458 2 => Ok(Operation::Status),
459 4 => Ok(Operation::Notify),
460 5 => Ok(Operation::Update),
461 _ => Err(MtopError::runtime(format!(
462 "invalid or unsupported operation {}",
463 value
464 ))),
465 }
466 }
467}
468
469#[derive(Debug, Clone, Eq, PartialEq)]
470pub struct Question {
471 name: Name,
472 qtype: RecordType,
473 qclass: RecordClass,
474}
475
476impl Question {
477 pub fn new(name: Name, qtype: RecordType) -> Self {
478 Self {
479 name,
480 qtype,
481 qclass: RecordClass::INET,
482 }
483 }
484
485 pub fn size(&self) -> usize {
486 self.name.size() + self.qtype.size() + self.qclass.size()
487 }
488
489 #[must_use]
490 pub fn set_qclass(mut self, qclass: RecordClass) -> Self {
491 self.qclass = qclass;
492 self
493 }
494
495 pub fn name(&self) -> &Name {
496 &self.name
497 }
498
499 pub fn qtype(&self) -> RecordType {
500 self.qtype
501 }
502
503 pub fn qclass(&self) -> RecordClass {
504 self.qclass
505 }
506
507 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
508 where
509 T: Write,
510 {
511 self.name.write_network_bytes(&mut buf)?;
512 write_be_u16(&mut buf, self.qtype.into())?;
513 write_be_u16(&mut buf, self.qclass.into())
514 }
515
516 pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
517 where
518 T: Read + Seek,
519 {
520 let name = Name::read_network_bytes(&mut buf)?;
521 let qtype = RecordType::from(read_be_u16(&mut buf)?);
522 let qclass = RecordClass::from(read_be_u16(&mut buf)?);
523 Ok(Self { name, qtype, qclass })
524 }
525}
526
527#[derive(Debug, Clone, Eq, PartialEq)]
528pub struct Record {
529 name: Name,
530 rtype: RecordType,
531 rclass: RecordClass,
532 ttl: u32,
533 rdata: RecordData,
534}
535
536impl Record {
537 pub fn new(name: Name, rtype: RecordType, rclass: RecordClass, ttl: u32, rdata: RecordData) -> Self {
538 Self {
539 name,
540 rtype,
541 rclass,
542 ttl,
543 rdata,
544 }
545 }
546
547 pub fn size(&self) -> usize {
548 self.name.size()
549 + self.rtype.size()
550 + self.rclass.size()
551 + 4 + 2 + self.rdata.size()
554 }
555
556 pub fn name(&self) -> &Name {
557 &self.name
558 }
559
560 pub fn rtype(&self) -> RecordType {
561 self.rtype
562 }
563
564 pub fn rclass(&self) -> RecordClass {
565 self.rclass
566 }
567
568 pub fn ttl(&self) -> u32 {
569 self.ttl
570 }
571
572 pub fn rdata(&self) -> &RecordData {
573 &self.rdata
574 }
575
576 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
577 where
578 T: Write,
579 {
580 let size = self.rdata.size();
582 assert!(
583 u16::try_from(size).is_ok(),
584 "rdata length of {} bytes exceeds max of {} bytes",
585 size,
586 u16::MAX
587 );
588
589 self.name.write_network_bytes(&mut buf)?;
590 write_be_u16(&mut buf, self.rtype.into())?;
591 write_be_u16(&mut buf, self.rclass.into())?;
592 write_be_u32(&mut buf, self.ttl)?;
593 write_be_u16(&mut buf, u16::try_from(size).unwrap())?;
594 self.rdata.write_network_bytes(&mut buf)
595 }
596
597 pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
598 where
599 T: Read + Seek,
600 {
601 let name = Name::read_network_bytes(&mut buf)?;
602 let rtype = RecordType::from(read_be_u16(&mut buf)?);
603 let rclass = RecordClass::from(read_be_u16(&mut buf)?);
604 let ttl = read_be_u32(&mut buf)?;
605 let rdata_len = read_be_u16(&mut buf)?;
606 let rdata = RecordData::read_network_bytes(rtype, rdata_len, &mut buf)?;
607
608 Ok(Self {
609 name,
610 rtype,
611 rclass,
612 ttl,
613 rdata,
614 })
615 }
616}
617
618#[cfg(test)]
619mod test {
620 use super::{Flags, Header, Message, MessageId, Operation, Question, Record, ResponseCode};
621 use crate::dns::core::{RecordClass, RecordType};
622 use crate::dns::name::Name;
623 use crate::dns::rdata::{RecordData, RecordDataA, RecordDataSRV};
624 use std::io::Cursor;
625 use std::net::Ipv4Addr;
626 use std::str::FromStr;
627
628 #[rustfmt::skip]
629 #[test]
630 fn test_message_write_network_bytes() {
631 let question = Question::new(Name::from_str("_cache._tcp.example.com.").unwrap(), RecordType::SRV);
632 let answer_rdata = RecordData::SRV(RecordDataSRV::new(
633 10,
634 10,
635 11211,
636 Name::from_str("cache01.example.com.").unwrap(),
637 ));
638 let answer = Record::new(
639 Name::from_str("_cache._tcp.example.com.").unwrap(),
640 RecordType::SRV,
641 RecordClass::INET,
642 300,
643 answer_rdata,
644 );
645 let extra_rdata = RecordData::A(RecordDataA::new(Ipv4Addr::new(127, 0, 0, 100)));
646 let extra = Record::new(
647 Name::from_str("cache01.example.com.").unwrap(),
648 RecordType::A,
649 RecordClass::INET,
650 60,
651 extra_rdata,
652 );
653
654 let message = Message::new(
655 MessageId::from(65333), Flags::default()
656 .set_response()
657 .set_op_code(Operation::Query)
658 .set_response_code(ResponseCode::NoError))
659 .add_question(question)
660 .add_answer(answer)
661 .add_extra(extra);
662
663 let mut cur = Cursor::new(Vec::new());
664 message.write_network_bytes(&mut cur).unwrap();
665 let buf = cur.into_inner();
666
667 assert_eq!(
668 vec![
669 255, 53, 128, 0, 0, 1, 0, 1, 0, 0, 0, 1, 6, 95, 99, 97, 99, 104, 101, 4, 95, 116, 99, 112, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 33, 0, 1, 6, 95, 99, 97, 99, 104, 101, 4, 95, 116, 99, 112, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 33, 0, 1, 0, 0, 1, 44, 0, 27, 0, 10, 0, 10, 43, 203, 7, 99, 97, 99, 104, 101, 48, 49, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 7, 99, 97, 99, 104, 101, 48, 49, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 1, 0, 1, 0, 0, 0, 60, 0, 4, 127, 0, 0, 100, ],
729 buf,
730 );
731 }
732
733 #[rustfmt::skip]
734 #[test]
735 fn test_message_read_network_bytes() {
736 let cur = Cursor::new(vec![
737 255, 53, 128, 0, 0, 1, 0, 1, 0, 0, 0, 1, 6, 95, 99, 97, 99, 104, 101, 4, 95, 116, 99, 112, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 33, 0, 1, 6, 95, 99, 97, 99, 104, 101, 4, 95, 116, 99, 112, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 33, 0, 1, 0, 0, 1, 44, 0, 27, 0, 10, 0, 10, 43, 203, 7, 99, 97, 99, 104, 101, 48, 49, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 7, 99, 97, 99, 104, 101, 48, 49, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 1, 0, 1, 0, 0, 0, 60, 0, 4, 127, 0, 0, 100, ]);
797
798 let message = Message::read_network_bytes(cur).unwrap();
799 assert_eq!(MessageId::from(65333), message.id());
800 assert_eq!(
801 Flags::default()
802 .set_response()
803 .set_response_code(ResponseCode::NoError)
804 .set_op_code(Operation::Query),
805 message.flags()
806 );
807
808 let questions = message.questions();
809 assert_eq!("_cache._tcp.example.com.", questions[0].name().to_string());
810 assert_eq!(RecordType::SRV, questions[0].qtype());
811 assert_eq!(RecordClass::INET, questions[0].qclass());
812
813 let answers = message.answers();
814 assert_eq!("_cache._tcp.example.com.", answers[0].name().to_string());
815 assert_eq!(RecordType::SRV, answers[0].rtype());
816 assert_eq!(RecordClass::INET, answers[0].rclass());
817 assert_eq!(300, answers[0].ttl());
818
819 if let RecordData::SRV(rd) = answers[0].rdata() {
820 assert_eq!(10, rd.weight());
821 assert_eq!(10, rd.priority());
822 assert_eq!(11211, rd.port());
823 assert_eq!("cache01.example.com.", rd.target().to_string());
824 } else {
825 panic!("unexpected record data type: {:?}", answers[0].rdata());
826 }
827
828 let extra = message.extra();
829 assert_eq!("cache01.example.com.", extra[0].name().to_string());
830 assert_eq!(RecordType::A, extra[0].rtype());
831 assert_eq!(RecordClass::INET, extra[0].rclass());
832 assert_eq!(60, extra[0].ttl());
833
834 if let RecordData::A(rd) = extra[0].rdata() {
835 assert_eq!(Ipv4Addr::new(127, 0, 0, 100), rd.addr());
836 } else {
837 panic!("unexpected record data type: {:?}", extra[0].rdata());
838 }
839 }
840
841 #[rustfmt::skip]
842 #[test]
843 fn test_header_write_network_bytes() {
844 let h = Header {
845 id: MessageId::from(65333),
846 flags: Flags::default().set_recursion_desired(),
847 num_questions: 1,
848 num_answers: 2,
849 num_authority: 3,
850 num_extra: 4,
851 };
852 let mut cur = Cursor::new(Vec::new());
853 h.write_network_bytes(&mut cur).unwrap();
854 let buf = cur.into_inner();
855
856 assert_eq!(
857 vec![
858 255, 53, 1, 0, 0, 1, 0, 2, 0, 3, 0, 4, ],
865 buf,
866 );
867 }
868
869 #[rustfmt::skip]
870 #[test]
871 fn test_header_read_network_bytes() {
872 let cur = Cursor::new(vec![
873 255, 53, 1, 0, 0, 1, 0, 2, 0, 3, 0, 4, ]);
880
881 let h = Header::read_network_bytes(cur).unwrap();
882 assert_eq!(MessageId::from(65333), h.id);
883 assert_eq!(Flags::default().set_recursion_desired(), h.flags);
884 assert_eq!(1, h.num_questions);
885 assert_eq!(2, h.num_answers);
886 assert_eq!(3, h.num_authority);
887 assert_eq!(4, h.num_extra);
888 }
889
890 #[test]
891 fn test_flags() {
892 let f = Flags::default().set_query();
893 assert!(f.is_query());
894
895 let f = Flags::default().set_response();
896 assert!(f.is_response());
897
898 let f = Flags::default().set_op_code(Operation::Notify);
899 assert_eq!(Operation::Notify, f.get_op_code());
900
901 let f = Flags::default().set_authoritative();
902 assert!(f.is_authoritative());
903
904 let f = Flags::default().set_truncated();
905 assert!(f.is_truncated());
906
907 let f = Flags::default().set_recursion_desired();
908 assert!(f.is_recursion_desired());
909
910 let f = Flags::default().set_recursion_available();
911 assert!(f.is_recursion_available());
912
913 let f = Flags::default().set_response_code(ResponseCode::ServerFailure);
914 assert_eq!(ResponseCode::ServerFailure, f.get_response_code());
915
916 let f = Flags::default()
917 .set_query()
918 .set_recursion_desired()
919 .set_op_code(Operation::Query);
920 assert!(f.is_query());
921 assert!(f.is_recursion_desired());
922 assert_eq!(Operation::Query, f.get_op_code());
923 }
924
925 #[rustfmt::skip]
926 #[test]
927 fn test_question_write_network_bytes() {
928 let q = Question::new(Name::from_str("example.com.").unwrap(), RecordType::AAAA);
929 let size = q.size();
930 let mut cur = Cursor::new(Vec::new());
931 q.write_network_bytes(&mut cur).unwrap();
932 let buf = cur.into_inner();
933
934 assert_eq!(
935 vec![
936 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 28, 0, 1, ],
944 buf,
945 );
946 assert_eq!(size, buf.len());
947 }
948
949 #[rustfmt::skip]
950 #[test]
951 fn test_question_read_network_bytes() {
952 let cur = Cursor::new(vec![
953 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 28, 0, 1, ]);
961
962 let size = cur.get_ref().len();
963 let q = Question::read_network_bytes(cur).unwrap();
964 assert_eq!("example.com.", q.name().to_string());
965 assert_eq!(RecordType::AAAA, q.qtype());
966 assert_eq!(RecordClass::INET, q.qclass());
967 assert_eq!(size, q.size());
968 }
969
970 #[rustfmt::skip]
971 #[test]
972 fn test_record_write_network_bytes() {
973 let rr = Record::new(
974 Name::from_str("www.example.com.").unwrap(),
975 RecordType::A,
976 RecordClass::INET,
977 300,
978 RecordData::A(RecordDataA::new(Ipv4Addr::new(127, 0, 0, 100))),
979 );
980 let size = rr.size();
981 let mut cur = Cursor::new(Vec::new());
982 rr.write_network_bytes(&mut cur).unwrap();
983 let buf = cur.into_inner();
984
985 assert_eq!(
986 vec![
987 3, 119, 119, 119, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 1, 0, 1, 0, 0, 1, 44, 0, 4, 127, 0, 0, 100, ],
1000 buf,
1001 );
1002 assert_eq!(size, buf.len());
1003 }
1004
1005 #[rustfmt::skip]
1006 #[test]
1007 fn test_record_read_network_bytes() {
1008 let cur = Cursor::new(vec![
1009 3, 119, 119, 119, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 1, 0, 1, 0, 0, 1, 44, 0, 4, 127, 0, 0, 100, ]);
1022
1023 let size = cur.get_ref().len();
1024 let rr = Record::read_network_bytes(cur).unwrap();
1025 assert_eq!("www.example.com.", rr.name().to_string());
1026 assert_eq!(RecordType::A, rr.rtype());
1027 assert_eq!(RecordClass::INET, rr.rclass());
1028 assert_eq!(300, rr.ttl());
1029 if let RecordData::A(rd) = rr.rdata() {
1030 assert_eq!(Ipv4Addr::new(127, 0, 0, 100), rd.addr());
1031 } else {
1032 panic!("unexpected rdata type: {:?}", rr.rdata());
1033 }
1034 assert_eq!(size, rr.size());
1035 }
1036}