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