1use std::{io::{Cursor, Read, Write}, mem::size_of, net::{Ipv4Addr, Ipv6Addr}};
59use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
60
61use crate::error::*;
62use crate::{internal_error, internal_error_map};
63
64
65pub use crate::common::*;
66
67pub
78fn pkt2name(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Vec<u8>>
79{
80 let qname_s = pkt.position() as usize;
81
82 loop
83 {
84 let cnt = pkt.read_u8().map_err(map_read_err)?;
85
86 if cnt == 0
87 {
88 break;
89 }
90 else
91 {
92 for _ in 0..cnt
93 {
94 let c = pkt.read_u8().map_err(map_read_err)?;
95 if c == 0
96 {
97 internal_error!(
98 CDnsErrorType::DnsResponse,
99 "incorrectly encoded QNAME in response, found '0' at offset: '{}'",
100 pkt.position()
101 );
102 }
103 }
104 }
105 }
106
107 let cur_pos = pkt.position() as usize;
109
110 if (cur_pos - qname_s) <= 1
111 {
112 internal_error!(
113 CDnsErrorType::DnsResponse,
114 "read name is too short"
115 );
116 }
117
118 return Ok(pkt.get_ref()[qname_s..cur_pos].to_vec());
129}
130
131
132pub
134fn name2str(pkt: &mut Cursor<&[u8]>, mut opt_rdlen: Option<u16>) -> CDnsResult<String>
135{
136 let cur_in_pos = pkt.position();
137 let mut comp: u8;
139 let mut output: Vec<String> = Vec::with_capacity(6);
140
141 loop
142 {
143 if let Some(rdlen) = opt_rdlen
144 {
145 if pkt.position() - cur_in_pos >= rdlen as u64
146 {
147 return Ok(output.join("."));
148 }
149 }
150
151 comp = pkt.read_u8().map_err(map_read_err)?;
154
155 let msb = comp & 0xC0;
161
162 if msb == 0xC0
163 {
164 if opt_rdlen.is_none() == true
165 {
166 opt_rdlen = Some(2);
167 }
168
169 let offset1: u16 = ((comp & !0xC0) as u16) << 8;let offset2: u16 = pkt.read_u8().map_err(map_read_err)? as u16;
171
172 let offset = offset1 | offset2;
173
174 if offset as usize >= pkt.get_ref().len()
178 {
179 internal_error!(
180 CDnsErrorType::DnsResponse,
181 "incoreclty formated packet: offset: '{}' > len: '{}'",
182 offset, pkt.get_ref().len()
183 );
184 }
185
186 let cur_pos = pkt.position();
188 pkt.set_position(offset as u64);
189
190 output.push(name2str(pkt, None)?);
192 pkt.set_position(cur_pos);
196 }
197 else if msb == 0x00
198 {
199 if comp == 0
200 {
201 if let Some(rdlen) = opt_rdlen
202 {
203 let dif = pkt.position() - cur_in_pos;
204
205 if rdlen as u64 != dif
206 {
207 internal_error!(CDnsErrorType::DnsResponse, "incorrect rdlen: '{}', exp: '{}'", rdlen, dif);
208 }
209 }
210
211 return Ok(output.join("."));
212 }
213 else
214 {
215 let mut tmp: String = String::with_capacity(comp as usize);
216
217 for _ in 0..comp
218 {
219 let c = pkt.read_u8().map_err(map_read_err)?;
220 if c == 0
221 {
222 internal_error!(CDnsErrorType::DnsResponse, "protocol violation, incorrectly encoded QNAME in response");
223 }
224
225 tmp.push(c as char);
226 }
227
228 output.push(tmp);
229 }
230 }
231 else
232 {
233 internal_error!(CDnsErrorType::DnsResponse, "incorrect compression: {:x}", msb);
234 }
235
236 } }
238
239
240impl DnsRdata
241{
242 fn convert(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: &QType) -> CDnsResult<Self>
256 {
257 match &qtype
258 {
259 QType::A =>
260 {
261 if rlen != 4
263 {
264 internal_error!(CDnsErrorType::DnsResponse, "ipv4 len expected: '4', got: '{}'", rlen);
265 }
266
267 let ip = pkt.read_u32::<BigEndian>().map_err(map_read_err)?;
268 return Ok(Self::A{ ip: Ipv4Addr::from(ip) });
269 },
270 QType::AAAA =>
271 {
272 if rlen != 16
274 {
275 internal_error!(CDnsErrorType::DnsResponse, "ipv6 len expected: '16', got: '{}'", rlen);
276 }
277
278 let ip = pkt.read_u128::<BigEndian>().map_err(map_read_err)?;
279 return Ok(Self::AAAA{ ip: Ipv6Addr::from(ip) });
280 },
281 QType::MX =>
282 {
283 return Ok(
284 Self::MX
285 {
286 preference: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
287 exchange: name2str(pkt, Some(rlen - 2))?,
288 }
289 );
290 },
291 QType::CNAME =>
292 {
293 return Ok(
294 Self::CNAME{ fqdn: name2str(pkt, Some(rlen))? }
295 );
296 },
297 QType::PTR =>
298 {
299 return Ok(
300 Self::PTR{ fqdn: name2str(pkt, Some(rlen))? }
301 );
302 },
303 QType::NS =>
304 {
305 return Ok(
306 Self::NS{ fqdn: name2str(pkt, Some(rlen))? }
307 );
308 },
309 QType::SOA =>
310 {
311 return Ok(
312 Self::SOA
313 {
314 soa:
315 DnsSoa
316 {
317 pnm: name2str(pkt, None)?,
319 ram: name2str(pkt, None)?,
321 serial: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
323 interv_refr: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
325 interv_retry: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
327 expire_limit: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
329 min_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
331 }
332 }
333 );
334 },
335 _ =>
336 {
337 let ipos = pkt.position();
338 let npos: u64 = pkt.position() + rlen as u64;
339 let buf_size = npos - ipos;
340
341 let mut data: Vec<u8> = vec![0_u8; buf_size as usize];pkt.read_exact(&mut data).map_err(map_read_err)?;
343
344 pkt.set_position(npos);
345 return Ok(Self::UNKNOWN{ data: data });
353 }
354 }
355 }
356}
357
358
359impl DnsResponsePayload
360{
361 fn new(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Self>
362 {
363 let name = name2str(pkt, None)?;
364 let qtype = QType::u16_to_type(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
365 let qclass = QClass::u16_to_class(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
366 let ttl = pkt.read_i32::<BigEndian>().map_err(map_read_err)?;
367 let rdlength = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
368 let rdata = DnsRdata::convert(pkt, rdlength, &qtype)?;
369
370 return Ok(
371 DnsResponsePayload
372 {
373 name: name,
374 dtype: qtype,
375 class: qclass,
376 ttl: ttl,
377 rdlength: rdlength,
378 rdata: rdata,
379 }
380 );
381 }
382}
383
384
385impl TryFrom<&[u8]> for DnsRequestAnswer
386{
387 type Error = CDnsError;
388
389 fn try_from(value: &[u8]) -> Result<Self, Self::Error>
390 {
391 return DnsRequestAnswer::parse(value);
392 }
393}
394
395impl DnsRequestAnswer
396{
397 fn parse(ans: &[u8]) -> CDnsResult<Self>
403 {
404 let mut pkt = Cursor::new(ans);
406
407 let id = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
409
410 let status = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
411
412 let header =
413 DnsHeader
414 {
415 id: id,
416 status: StatusBits::from_bits(status).ok_or_else(||
417 internal_error_map!(CDnsErrorType::DnsResponse, "unknown status bits: '{}'", status)
418 )?,
419 qdcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
420 ancount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
421 nscount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
422 arcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
423 };
424
425 if header.status.contains(StatusBits::QR_RESP) == false
429 {
430 internal_error!(
431 CDnsErrorType::DnsResponse,
432 "incorret QR flag in STATUS register of response, expected 1 got 0"
433 );
434 }
435 let request =
452 DnsRequestPayload
453 {
454 qname: pkt2name(&mut pkt)?,
455 qtype: QType::u16_to_qtype(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
456 qclass: QClass::u16_to_qclass(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
457 };
458
459 let mut an_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.ancount as usize);
460 let mut rr_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.arcount as usize);
461 let mut ns_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.nscount as usize);
462
463 for _ in 0..header.ancount
464 {
465 an_list.push(DnsResponsePayload::new(&mut pkt)?);
466 }
467
468 for _ in 0..header.nscount
470 {
471 ns_list.push(DnsResponsePayload::new(&mut pkt)?);
472 }
473
474 for _ in 0..header.arcount
476 {
477 rr_list.push(DnsResponsePayload::new(&mut pkt)?);
478 }
479
480 return Ok(
481 DnsRequestAnswer
482 {
483 header: header,
484 request: request,
485 response: an_list,
486 additional: rr_list,
487 authoratives: ns_list,
488 }
489 );
490 }
491}
492
493impl DnsRequestHeader
494{
495 pub
496 fn to_bytes(&self) -> CDnsResult<Vec<u8>>
497 {
498 let pkt_size: usize = size_of::<DnsHeader>() + self.payload.qname.len() + 4;
499
500 let mut pkt = Cursor::new(vec![0_u8; pkt_size]);
501
502 pkt.write_u16::<BigEndian>(self.header.id).map_err(map_read_err)?;
503 pkt.write_u16::<BigEndian>(self.header.status.bits()).map_err(map_read_err)?;
504 pkt.write_u16::<BigEndian>(self.header.qdcount).map_err(map_read_err)?;
505 pkt.write_u16::<BigEndian>(self.header.ancount).map_err(map_read_err)?;
506 pkt.write_u16::<BigEndian>(self.header.nscount).map_err(map_read_err)?;
507 pkt.write_u16::<BigEndian>(self.header.arcount).map_err(map_read_err)?;
508
509 pkt.write(self.payload.qname.as_slice()).map_err(map_read_err)?;
512 pkt.write_u16::<BigEndian>(self.payload.qtype.into()).map_err(map_read_err)?;
513 pkt.write_u16::<BigEndian>(self.payload.qclass.into()).map_err(map_read_err)?;
514 return Ok(pkt.into_inner());
517 }
518}
519
520
521#[test]
522fn test_pkt2name()
523{
524 use std::time::Instant;
525
526 fn prepare(d: &[u8]) -> Cursor<&[u8]>
527 {
528 return Cursor::new(d);
531 }
532
533 let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
534
535 let mut cur1 = prepare(t1);
536
537 let now = Instant::now();
538 let r1 = pkt2name(&mut cur1);
539 let elapsed = now.elapsed();
540 println!("Elapsed: {:.2?}", elapsed);
541
542 assert_eq!(r1.is_ok(), true);
543 assert_eq!(r1.as_ref().unwrap(), t1);
544
545 let t2 =
546 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
547 \x30\x30\x03\x6e\x65\x74\x00";
548
549 let mut cur2 = prepare(t2);
550 let now = Instant::now();
551 let r2 = pkt2name(&mut cur2);
552 let elapsed = now.elapsed();
553 println!("Elapsed: {:.2?}", elapsed);
554
555 assert_eq!(r2.is_ok(), true);
556 assert_eq!(r2.as_ref().unwrap(), t2);
557
558 let t3 =
559 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
560 \x30\x30\x03\x6e\x65\x74";
561
562 let r3 = pkt2name(&mut prepare(t3));
563
564 assert_eq!(r3.is_ok(), false);
565
566 let t4 =
567 b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
568 \x30\x30\x03\x6e\x65\x74";
569
570 let r4 = pkt2name(&mut prepare(t4));
571
572 assert_eq!(r4.is_ok(), false);
573}
574
575#[test]
576fn test_qname2str()
577{
578 use std::time::Instant;
579
580 fn prepare(d: &[u8]) -> Cursor<&[u8]>
581 {
582 return Cursor::new(d);
585 }
586
587 let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
588
589 let mut cur1 = prepare(t1);
590 let now = Instant::now();
591 let r1 = name2str(&mut cur1, None);
592 let elapsed = now.elapsed();
593 println!("Elapsed: {:.2?}", elapsed);
594
595 assert_eq!(r1.is_ok(), true);
596 assert_eq!(r1.as_ref().unwrap(), "dns.google");
597
598 let t2 =
599 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
600 \x30\x30\x03\x6e\x65\x74\x00";
601
602 let mut cur2 = prepare(t2);
603
604 let now = Instant::now();
605 let r2 = name2str(&mut cur2, None);
606 let elapsed = now.elapsed();
607 println!("Elapsed: {:.2?}", elapsed);
608
609 assert_eq!(r2.is_ok(), true);
610 assert_eq!(r2.as_ref().unwrap(), "mad07s09-in-x0e.1e100.net");
611
612 let t3 =
613 b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
614 \x30\x30\x03\x6e\x65\x74";
615
616 let r3 = name2str(&mut prepare(t3), None);
617
618 assert_eq!(r3.is_ok(), false);
619
620 let t4 =
621 b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
622 \x30\x30\x03\x6e\x65\x74";
623
624 let r4 = name2str(&mut prepare(t4), None);
625
626 assert_eq!(r4.is_ok(), false);
627}
628
629#[test]
630fn test_response_parser()
631{
632 use std::time::Instant;
633
634 let pkt =
635 b"\x15\xc8\x81\x80\x00\x01\x00\x01\x00\x00\x00\x02\x01\x38\x01\x38\
636 \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
637 \x61\x00\x00\x0c\x00\x01\xc0\x0c\x00\x0c\x00\x01\x00\x01\x35\xf0\
638 \x00\x0c\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00\xc0\x32\
639 \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x08\x08\xc0\x32\
640 \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x04\x04";
641
642 let dummy =
643 DnsRequestHeader
644 {
645 header: DnsHeader {id: 0x15c8, ..Default::default()},
646 payload: DnsRequestPayload
647 {
648 qname: b"\x01\x38\x01\x38\x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\x61\x00".to_vec(),
649 qtype: QType::PTR,
650 qclass: QClass::IN,
651 }
652 };
653
654 let now = Instant::now();
655 let ans = DnsRequestAnswer::try_from(pkt.as_slice());
656 let elapsed = now.elapsed();
657 println!("Elapsed: {:.2?}", elapsed);
658
659 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
660
661 let ans = ans.unwrap();
662
663 let verif = ans.verify(&dummy);
664 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
665
666 assert_eq!(ans.header.id, 0x15c8);
667 assert_eq!(ans.header.ancount, 1);
668 assert_eq!(ans.header.arcount, 2);
669 assert_eq!(ans.header.nscount, 0);
670 assert_eq!(ans.header.qdcount, 1);
671
672 assert_eq!(ans.response[0].rdata, DnsRdata::PTR{ fqdn: "dns.google".to_string() });
673 assert_eq!(ans.response[0].name, "8.8.8.8.in-addr.arpa".to_string());
674 assert_eq!(ans.response[0].dtype, QType::PTR);
675 assert_eq!(ans.response[0].class, QClass::IN);
676 assert_eq!(ans.response[0].ttl, 79344);
677 assert_eq!(ans.response[0].rdlength, 12);
678
679 assert_eq!(ans.additional[0].rdata, DnsRdata::A{ ip: "8.8.8.8".parse().unwrap() });
680 assert_eq!(ans.additional[0].name, "dns.google".to_string());
681 assert_eq!(ans.additional[0].ttl, 232);
682 assert_eq!(ans.additional[0].dtype, QType::A);
683 assert_eq!(ans.additional[0].class, QClass::IN);
684 assert_eq!(ans.additional[1].rdata, DnsRdata::A{ ip: "8.8.4.4".parse().unwrap() });
685 assert_eq!(ans.additional[1].name, "dns.google".to_string());
686 assert_eq!(ans.additional[1].ttl, 232);
687 assert_eq!(ans.additional[1].dtype, QType::A);
688 assert_eq!(ans.additional[1].class, QClass::IN);
689}
690
691#[test]
692fn test_response2()
693{
694 use std::time::Instant;
695
696 let pkt =
697 b"\x4b\x38\x81\x80\x00\x01\x00\x05\x00\x00\x00\x00\x05\x67\x6d\x61\
698 \x69\x6c\x03\x63\x6f\x6d\x00\x00\x0f\x00\x01\xc0\x0c\x00\x0f\x00\
699 \x01\x00\x00\x0b\x55\x00\x1b\x00\x05\x0d\x67\x6d\x61\x69\x6c\x2d\
700 \x73\x6d\x74\x70\x2d\x69\x6e\x01\x6c\x06\x67\x6f\x6f\x67\x6c\x65\
701 \xc0\x12\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x0a\
702 \x04\x61\x6c\x74\x31\xc0\x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\
703 \x55\x00\x09\x00\x1e\x04\x61\x6c\x74\x33\xc0\x29\xc0\x0c\x00\x0f\
704 \x00\x01\x00\x00\x0b\x55\x00\x09\x00\x14\x04\x61\x6c\x74\x32\xc0\
705 \x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x28\x04\
706 \x61\x6c\x74\x34\xc0\x29";
707
708 let dummy =
709 DnsRequestHeader
710 {
711 header: DnsHeader {id: 0x4b38, ..Default::default()},
712 payload: DnsRequestPayload
713 {
714 qname: b"\x05\x67\x6d\x61\x69\x6c\x03\x63\x6f\x6d\x00".to_vec(),
715 qtype: QType::MX,
716 qclass: QClass::IN,
717 }
718 };
719
720 let now = Instant::now();
721 let ans = DnsRequestAnswer::try_from(pkt.as_slice());
722 let elapsed = now.elapsed();
723 println!("Elapsed: {:.2?}", elapsed);
724
725 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
726 let ans = ans.unwrap();
727
728 let verif = ans.verify(&dummy);
729 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
730
731 assert_eq!(ans.header.id, 0x4b38);
732 assert_eq!(ans.header.ancount, 5);
733 assert_eq!(ans.header.arcount, 0);
734 assert_eq!(ans.header.nscount, 0);
735 assert_eq!(ans.header.qdcount, 1);
736
737 assert_eq!(ans.response[0].rdata, DnsRdata::MX{ preference: 5, exchange: "gmail-smtp-in.l.google.com".to_string() });
738 assert_eq!(ans.response[0].name, "gmail.com".to_string());
739 assert_eq!(ans.response[0].dtype, QType::MX);
740 assert_eq!(ans.response[0].class, QClass::IN);
741 assert_eq!(ans.response[0].ttl, 2901);
742 assert_eq!(ans.response[0].rdlength, 27);
743
744 assert_eq!(ans.response[1].rdata, DnsRdata::MX{ preference: 10, exchange: "alt1.gmail-smtp-in.l.google.com".to_string() });
745 assert_eq!(ans.response[1].name, "gmail.com".to_string());
746 assert_eq!(ans.response[1].dtype, QType::MX);
747 assert_eq!(ans.response[1].class, QClass::IN);
748 assert_eq!(ans.response[1].ttl, 2901);
749 assert_eq!(ans.response[1].rdlength, 9);
750
751 assert_eq!(ans.response[2].rdata, DnsRdata::MX{ preference: 30, exchange: "alt3.gmail-smtp-in.l.google.com".to_string() });
752 assert_eq!(ans.response[2].name, "gmail.com".to_string());
753 assert_eq!(ans.response[2].dtype, QType::MX);
754 assert_eq!(ans.response[2].class, QClass::IN);
755 assert_eq!(ans.response[2].ttl, 2901);
756 assert_eq!(ans.response[2].rdlength, 9);
757
758 assert_eq!(ans.response[3].rdata, DnsRdata::MX{ preference: 20, exchange: "alt2.gmail-smtp-in.l.google.com".to_string() });
759 assert_eq!(ans.response[3].name, "gmail.com".to_string());
760 assert_eq!(ans.response[3].dtype, QType::MX);
761 assert_eq!(ans.response[3].class, QClass::IN);
762 assert_eq!(ans.response[3].ttl, 2901);
763 assert_eq!(ans.response[3].rdlength, 9);
764
765 assert_eq!(ans.response[4].rdata, DnsRdata::MX{ preference: 40, exchange: "alt4.gmail-smtp-in.l.google.com".to_string() });
766 assert_eq!(ans.response[4].name, "gmail.com".to_string());
767 assert_eq!(ans.response[4].dtype, QType::MX);
768 assert_eq!(ans.response[4].class, QClass::IN);
769 assert_eq!(ans.response[4].ttl, 2901);
770 assert_eq!(ans.response[4].rdlength, 9);
771}
772
773
774#[test]
775fn test_response3()
776{
777 use std::time::Instant;
778
779 let pkt =
780b"\xd0\x79\x81\x80\x00\x01\x00\x17\x00\x00\x00\x00\x06\x72\
781\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x00\xff\x00\x01\xc0\x0c\x00\
782\x06\x00\x01\x00\x00\x0e\x10\x00\x30\x04\x6e\x73\x32\x31\x07\x63\
783\x6c\x6f\x75\x64\x6e\x73\x03\x6e\x65\x74\x00\x07\x73\x75\x70\x70\
784\x6f\x72\x74\xc0\x2c\x78\x77\xe2\xf1\x00\x00\x1c\x20\x00\x00\x07\
785\x08\x00\x12\x75\x00\x00\x00\x0e\x10\xc0\x0c\x00\x2e\x00\x01\x00\
786\x00\x0e\x10\x00\x5d\x00\x06\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
787\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
788\x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\xa9\xa2\x2a\x08\x3c\x78\xb9\
789\xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\x22\x96\x45\x59\x36\x1f\x69\
790\x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\x11\x1a\x72\x00\x56\x89\x26\
791\x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\x68\x75\x05\x3d\x90\xed\x1e\
792\x0f\xfc\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x02\xc0\x27\
793\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\
794\x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\
795\x04\x6e\x73\x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\
796\x10\x00\x08\x05\x70\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x02\x00\
797\x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\x32\x34\xc0\x2c\xc0\
798\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\x04\x6e\x73\x32\x34\
799\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\
800\x6e\x73\x32\x31\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\
801\x00\x07\x04\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x2e\x00\x01\x00\
802\x00\x0e\x10\x00\x5d\x00\x02\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
803\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
804\x6b\x00\xd1\xc5\x6c\xf1\xfb\xd0\x75\xf1\x38\x20\x28\x80\x4c\xe0\
805\x59\xa5\xa8\xab\x84\x79\xd8\x37\x48\xa7\xa5\x3f\x08\x9b\x4c\xca\
806\x40\x2b\xcb\x2c\xda\xcc\xc2\x18\xad\x07\x9e\xf8\x4e\x17\x8d\xb1\
807\x2b\x2d\xa2\xa6\x17\xdb\x55\x30\xbc\xa2\xb9\xa0\x01\x71\x01\xe5\
808\xdc\x4f\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xd9\x14\
809\x70\xd0\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x01\
810\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\
811\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xf8\x57\x68\xf0\xad\
812\x9e\xfb\x3a\x0f\x66\xbd\xcc\x48\xe7\x29\x0a\xf4\xd8\xf6\xbe\xbc\
813\x04\x76\x02\x27\x64\xf2\xc9\x42\x6d\x75\x54\x83\x0a\x11\xda\x0a\
814\x02\x6b\x8c\xf1\x65\xc4\x21\x44\xea\x89\x09\x01\xc8\xa1\xe2\x11\
815\x8f\xed\x67\x39\x69\x33\xdd\x97\x22\x1a\xd3\xc0\x0c\x00\x0f\x00\
816\x01\x00\x00\x0e\x10\x00\x11\x00\x0a\x04\x6d\x61\x69\x6c\x04\x6e\
817\x69\x78\x64\x03\x6f\x72\x67\x00\xc0\x0c\x00\x2e\x00\x01\x00\x00\
818\x0e\x10\x00\x5d\x00\x0f\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\
819\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\
820\x00\xd4\xdd\x07\xd9\xb6\xb2\xba\x57\xa9\x1d\x3b\xaa\x6c\x55\xc4\
821\x3d\x73\x79\xea\x74\xfe\xd7\x23\x0c\xb4\xab\x8f\x4b\x1f\xd9\x8a\
822\xb2\x4a\x5c\xad\x3e\x8e\x4a\x85\xbb\xbd\x75\xf2\x47\x2c\xa8\x89\
823\x21\x75\x89\xb1\x12\xc4\xd2\xf7\x40\x06\x52\x57\x83\x8a\xaa\x7b\
824\x75\xc0\x0c\x00\x10\x00\x01\x00\x00\x0e\x10\x00\x34\x33\x76\x3d\
825\x73\x70\x66\x31\x20\x2b\x6d\x78\x20\x2b\x61\x3a\x6d\x61\x69\x6c\
826\x2e\x6e\x69\x78\x64\x2e\x6f\x72\x67\x20\x69\x70\x34\x3a\x32\x31\
827\x37\x2e\x32\x30\x2e\x31\x31\x32\x2e\x32\x30\x38\x20\x2d\x61\x6c\
828\x6c\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x10\x0d\
829\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\
830\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xd1\x6c\xd1\xf4\x3b\xe0\
831\x44\xba\xfe\xe9\xdb\x82\xbd\x89\x5f\xa1\x07\x72\xdd\x47\xad\x4e\
832\x91\xd5\xc3\xfe\x3e\x39\x74\xdb\x50\x50\x19\x6c\x3f\x6c\xb7\xa8\
833\x01\x03\x6a\xf5\xa7\xf3\x9b\xf7\x76\xd4\xff\xa3\xd5\x43\xfc\xec\
834\xa9\x89\x24\xf8\xd2\xb6\x76\xd4\x20\xbc\xc0\x0c\x00\x30\x00\x01\
835\x00\x00\x0e\x10\x00\x44\x01\x01\x03\x0d\xf3\x87\xe2\x7c\x2b\x82\
836\x40\x72\x7c\xfd\xc9\x2b\xe8\x22\xd6\xa9\x40\xc0\xab\x03\x25\x7d\
837\x92\xae\xf3\x17\x71\x82\x67\xc6\xcd\xb6\x4b\x11\x62\xc6\xfa\x06\
838\xec\x4c\x9f\xd9\xe6\xaf\x5c\x3d\xe4\x32\xde\x11\x1b\x09\x13\xe3\
839\xd0\xba\x66\xd1\xbc\x32\xdb\x13\xd7\x1d\xc0\x0c\x00\x30\x00\x01\
840\x00\x00\x0e\x10\x00\x44\x01\x00\x03\x0d\xd4\x43\xde\x96\xe5\xea\
841\x0a\xf9\x5d\x4f\x72\x88\x9c\xd9\x9c\xf7\xa6\x3f\x12\xd7\xf3\xea\
842\x8a\x6b\x44\x4c\x79\x23\x81\x94\x43\xa3\xbd\x9e\xb8\xde\xfe\x8c\
843\xe6\x21\xe3\x8a\x71\xba\x05\xd2\x0f\x98\x5b\xfc\x7e\x72\x8c\xe9\
844\x9a\xc0\x49\x00\xca\xd5\x62\x93\x7f\x03\xc0\x0c\x00\x2e\x00\x01\
845\x00\x00\x0e\x10\x00\x5d\x00\x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\
846\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\
847\x73\x6b\x00\xc0\x93\x23\x1d\xcb\x1e\x79\xfe\x7c\x40\x3e\xd4\x33\
848\x5f\xed\x69\x8e\x7d\x75\xff\x73\x6b\x24\x71\x8f\x50\xf8\xe0\x49\
849\xce\x5f\x62\x0c\x8c\xb3\x06\x8f\x26\xea\x20\xa0\xe3\x71\xe0\xa1\
850\x8b\xe0\x4a\x2f\x1d\x4b\x79\x2c\x52\x6b\xa4\x43\xb5\x70\x27\x01\
851\xb0\x63\x47\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\
852\x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x97\
853\x18\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x41\x87\x75\x1d\
854\x30\x44\xd1\x94\x40\xd4\xe6\x40\x98\x62\x94\x53\xad\x53\xe2\xed\
855\xc0\xc0\xb7\xa3\x20\x15\xae\x59\xbb\x97\x45\xfb\x0e\xbf\x70\xf3\
856\xb1\x24\x79\xe8\x85\x6c\x2a\x66\x10\xb6\x75\x99\x7b\x77\x78\x65\
857\xa6\x67\x8d\x59\xa6\x14\xf7\xe6\x77\xab\x53\x9c\xc0\x0c\x00\x33\
858\x00\x01\x00\x00\x02\x58\x00\x0d\x01\x00\x00\x0a\x08\x90\xc7\xf1\
859\x74\x0b\x0c\xfb\x34\xc0\x0c\x00\x2e\x00\x01\x00\x00\x02\x58\x00\
860\x5d\x00\x33\x0d\x02\x00\x00\x00\x00\x61\xf2\xaf\x39\x61\xcb\x22\
861\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xc4\x4d\
862\x00\x48\x9c\x86\x49\xac\x8d\x03\x28\x23\xac\xec\xf5\x5b\xb6\xe5\
863\x2f\xf6\xae\xaa\x01\x5a\x66\x52\xf7\x43\xc3\xb1\xe5\xef\xe5\xbf\
864\x5f\x71\x5d\xa1\x57\x64\x66\x5e\xa1\x6f\x96\xa8\xcd\x48\x85\xe4\
865\x20\xe2\xfb\xb0\xc1\x00\x47\x72\xc8\x72\x98\xc7\x41\xd9";
866
867 let dummy =
868 DnsRequestHeader
869 {
870 header: DnsHeader {id: 0xd079, ..Default::default()},
871 payload: DnsRequestPayload
872 {
873 qname: b"\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00".to_vec(),
874 qtype: QType::ALL,
875 qclass: QClass::IN,
876 }
877 };
878
879 let now = Instant::now();
880 let ans = DnsRequestAnswer::try_from(pkt.as_slice());
881 let elapsed = now.elapsed();
882 println!("Elapsed: {:.2?}", elapsed);
883
884 assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
885 let ans = ans.unwrap();
886
887 let verif = ans.verify(&dummy);
888 assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
889
890 assert_eq!(ans.header.id, 0xd079);
891 assert_eq!(ans.header.ancount, 23);
892 assert_eq!(ans.header.arcount, 0);
893 assert_eq!(ans.header.nscount, 0);
894 assert_eq!(ans.header.qdcount, 1);
895
896 let ansord = &ans.response[0];
897 assert_eq!(
898 ansord.rdata,
899 DnsRdata::SOA
900 {
901 soa:
902 DnsSoa
903 {
904 pnm: "ns21.cloudns.net".to_string(),
905 ram: "support.cloudns.net".to_string(),
906 serial: 2021122801,
907 interv_refr: 7200,
908 interv_retry: 1800,
909 expire_limit: 1209600,
910 min_ttl: 3600
911 }
912 }
913 );
914 assert_eq!(ansord.name, "relkom.sk".to_string());
915 assert_eq!(ansord.dtype, QType::SOA);
916 assert_eq!(ansord.class, QClass::IN);
917 assert_eq!(ansord.ttl, 3600);
918 assert_eq!(ansord.rdlength, 48);
919
920 let a1 =
921b"\x00\x06\x0d\x02\
922\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\
923\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\
924\xa9\xa2\x2a\x08\x3c\x78\xb9\xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\
925\x22\x96\x45\x59\x36\x1f\x69\x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\
926\x11\x1a\x72\x00\x56\x89\x26\x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\
927\x68\x75\x05\x3d\x90\xed\x1e\x0f\xfc";
928
929 let ansord = &ans.response[1];
930 assert_eq!(ansord.rdata, DnsRdata::UNKNOWN{ data: a1.to_vec() });
931 assert_eq!(ansord.name, "relkom.sk".to_string());
932 assert_eq!(ansord.dtype, QType::RRSIG);
933 assert_eq!(ansord.class, QClass::IN);
934 assert_eq!(ansord.ttl, 3600);
935 assert_eq!(ansord.rdlength, 93);
936
937 let ansord = &ans.response[2];
938 assert_eq!(ansord.rdata, DnsRdata::NS{ fqdn: "ns21.cloudns.net".to_string() });
939 assert_eq!(ansord.name, "relkom.sk".to_string());
940 assert_eq!(ansord.dtype, QType::NS);
941 assert_eq!(ansord.class, QClass::IN);
942 assert_eq!(ansord.ttl, 3600);
943 assert_eq!(ansord.rdlength, 2);
944}
945
946
947#[test]
948fn test_request()
949{
950 use std::time::Instant;
951 use std::net::IpAddr;
952
953 let ipp = IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8));
954 let test = QDnsName::from(&ipp);
955
956
957 let now = Instant::now();
958
959 let req = DnsRequestHeader::construct_lookup(test, QType::PTR);
960
961 let elapsed = now.elapsed();
962 println!("Elapsed: {:.2?}", elapsed);
963
964 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
965
966 let pkt = req.unwrap().to_bytes();
967 assert_eq!(pkt.is_ok(), true);
968 let pkt = pkt.unwrap();
969
970 let ctrl =
971 b"\x15\xc8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x38\x01\x38\
972 \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
973 \x61\x00\x00\x0c\x00\x01";
974
975 assert_eq!(&pkt[2..], &ctrl[2..]);
976}
977
978#[test]
979fn test_request_1()
980{
981 use std::time::Instant;
982 use std::net::IpAddr;
983
984 let ipp = IpAddr::V4("100.150.111.80".parse().unwrap());
985 let test = QDnsName::from(&ipp);
986
987 let now = Instant::now();
988
989 let req = DnsRequestHeader::construct_lookup(test, QType::PTR);
990
991 let elapsed = now.elapsed();
992 println!("Elapsed: {:.2?}", elapsed);
993
994 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
995
996 let pkt = req.unwrap().to_bytes();
997 assert_eq!(pkt.is_ok(), true);
998 let pkt = pkt.unwrap();
999
1000 let ctrl =
1001 b"\x74\xa1\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x38\x30\x03\
1002 \x31\x31\x31\x03\x31\x35\x30\x03\x31\x30\x30\x07\x69\x6e\x2d\x61\
1003 \x64\x64\x72\x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
1004
1005 assert_eq!(&pkt[2..], &ctrl[2..]);
1006}
1007
1008#[test]
1009fn test_request6()
1010{
1011 use std::time::Instant;
1012 use std::net::IpAddr;
1013
1014 let ipp = IpAddr::V6("2a00:1450:4003:802::200e".parse().unwrap());
1015 let test = QDnsName::from(&ipp);
1016
1017 let now = Instant::now();
1018
1019 let req = DnsRequestHeader::construct_lookup(test, QType::PTR);
1020
1021 let elapsed = now.elapsed();
1022 println!("Elapsed: {:.2?}", elapsed);
1023
1024 assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
1025
1026 let pkt = req.unwrap().to_bytes();
1027 assert_eq!(pkt.is_ok(), true);
1028 let pkt = pkt.unwrap();
1029
1030 let ctrl =
1031 b"\xee\xec\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x65\x01\x30\
1032 \x01\x30\x01\x32\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\
1033 \x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x32\x01\x30\
1034 \x01\x38\x01\x30\x01\x33\x01\x30\x01\x30\x01\x34\x01\x30\x01\x35\
1035 \x01\x34\x01\x31\x01\x30\x01\x30\x01\x61\x01\x32\x03\x69\x70\x36\
1036 \x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
1037
1038 assert_eq!(&pkt[2..], &ctrl[2..]);
1039}
1040