cdns_rs/a_sync/
common.rs

1/*-
2 * cdns-rs - a simple sync/async DNS query library
3 * 
4 * Copyright (C) 2020  Aleksandr Morozov
5 * 
6 * Copyright 2025 Aleksandr Morozov
7 * 
8 * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
9 * the European Commission - subsequent versions of the EUPL (the "Licence").
10 * 
11 * You may not use this work except in compliance with the Licence.
12 * 
13 * You may obtain a copy of the Licence at:
14 * 
15 *    https://joinup.ec.europa.eu/software/page/eupl
16 * 
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
20 * Licence for the specific language governing permissions and limitations
21 * under the Licence.
22 */
23
24/*
25                                1  1  1  1  1  1
26  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
27+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
28                    | ID |
29+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
30|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
31+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
32                    | QDCOUNT |
33+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
34                    | ANCOUNT |
35+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
36                    | NSCOUNT |
37+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
38                    | ARCOUNT |
39+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
40
41                                1  1  1  1  1  1
42  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
43+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44|                                               |
45/                       QNAME                   /
46/                                               /
47+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
48|                       QTYPE                   |
49+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
50|                       QCLASS                  |
51+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
52
53*/
54
55/// This file contains the common structures and constants of DNS protocol and 
56/// other parts of the code. Also it contains a parser from/to network packet.
57
58use 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
73/// Verifies the sequence of labels coding and copies data from pkt to
74/// buffer.
75/// 
76/// # Arguments
77/// 
78/// * `pkt` - a reference to the [Cursor]
79/// 
80/// # Returns 
81/// 
82/// * [CDnsResult] with data copied to new [Vec][u8]
83pub 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    // temporary store the position of the cursor
114    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    /*pkt.set_position(qname_s);
125    
126    // creating buffer for QNAME
127    let mut req: Vec<u8> = vec![0_u8; (cur_pos - qname_s) as usize];
128    pkt.read_exact(&mut req).map_err(map_read_err)?;
129
130    // restore position
131    pkt.set_position(cur_pos);*/
132    
133
134    return Ok(pkt.get_ref()[qname_s..cur_pos].to_vec());
135}
136
137
138/// This function converts a QNAME (encoded domains) to the String FQDN.
139#[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 p_comp: u8 = 0;
145    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        // reading word from pkt to detect the type of message
159       // p_comp = comp;
160        comp = BoAsyncReadExt::read_u8(pkt).await.map_err(map_read_err)?;
161
162        /*if p_comp > 0 && comp > 0
163        {
164            output.push('.');
165        }*/
166
167        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;// | pkt.read_u8().map_err(map_read_err)? as u16;
177            let offset2: u16 = BoAsyncReadExt::read_u8(pkt).await.map_err(map_read_err)? as u16;
178
179            let offset = offset1 | offset2;
180
181            //println!("debug: 1: {} 2: {} offset: {}", offset1, offset2, offset);
182
183            // C0 0...
184            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            // save current cursor position
194            let cur_pos = pkt.position();
195            pkt.set_position(offset as u64);
196
197            // converting the name to FQDN
198            output.push(name2str(pkt, None).await?);
199            //output.push_str(cache.get(&offset).ok_or_else(|| internal_error_map!(CDnsErrorType::InternalError, "cache mismatch"))?);
200
201            // restoring cursor positon
202            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    } // loop
244}
245
246impl DnsRdata
247{
248    /// Reads the RData from pkt and converts it into QType container
249    /// 
250    /// # Arguments
251    /// 
252    /// * `pkt` - a [Cursor] mutable reference to raw DNS reply data
253    /// 
254    /// * `rlen` - a length of RData section
255    /// 
256    /// * `qtype` - a [QType] reference to the response answer Qtype
257    /// 
258    /// # Returns
259    /// 
260    /// * [CDnsResult] with Self or error
261    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                // read 4 bytes (octets)
269                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                // read rlen bytes (octets)
280                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                                // primary name server
325                                pnm: name2str(pkt, None).await?, 
326                                // responsible authority mailbox
327                                ram: name2str(pkt, None).await?,
328                                // serial number
329                                serial: BoAsyncReadExt::read_u32::<BigEndian>(pkt).await.map_err(map_read_err)?,
330                                // refresh interval
331                                interv_refr: BoAsyncReadExt::read_u32::<BigEndian>(pkt).await.map_err(map_read_err)?,
332                                // retry interval
333                                interv_retry: BoAsyncReadExt::read_u32::<BigEndian>(pkt).await.map_err(map_read_err)?,
334                                // expire limit
335                                expire_limit: BoAsyncReadExt::read_u32::<BigEndian>(pkt).await.map_err(map_read_err)?,
336                                // minimum TTL
337                                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];//pkt.get_ref()[s..s+rlen as usize].to_vec();
349                IoAsyncReadExt::read_exact(pkt, &mut data).await.map_err(map_read_err)?;
350             
351                pkt.set_position(npos);
352                //   pkt.set_position((s+rlen as usize) as u64);
353                /*QType::MD | QType::MF | QType::SOA | QType::MB | QType::MG | 
354            QType::MR | QType::NULL | QType::WKS | QType::HINFO | QType::TXT |
355            QType::AFSDB | QType::KEY | QType::CERT | QType::DS | QType::RRSIG |
356            QType::NSEC | QType::DNSKEY | QType::NSEC3 | QType::NSEC3PARAM | 
357            QType::CDS | QType::CDNSKEY | QType::OPENPGPKEY  */
358
359                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
398//unsafe impl Send for DnsRequestAnswer{}
399
400impl 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    /// Parses the raw data from received packet.
413    /// 
414    /// # Arguments
415    /// 
416    /// * `ans` - the received data
417    async 
418    fn async_parse(ans: &[u8]) -> CDnsResult<Self>
419    {
420        // creating cursor
421        let mut pkt = Cursor::new(ans);
422
423        // parsing header
424        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        // todo!("what about truncated messages");
442
443        // check if there is no more than 1 answer
444        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       /*else if header.ancount > 1
452        {
453            internal_error!(
454                CDnsErrorType::DnsRespose, 
455                "too many responses = '{}', multiple responses are not supported", 
456                header.ancount
457            );
458        }*/
459        /*else if header.ancount == 0 && header.status.contains(StatusBits::RESP_NOERROR) == true
460        {
461            internal_error!(CDnsErrorType::DnsRespose, "answer count: 0 while response contains no error");
462        }*/
463        
464        // reading request
465        //let cur_offset = pkt.position();
466    
467        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        // reading authoritative section if any
487        for _ in 0..header.nscount
488        {
489            ns_list.push(DnsResponsePayload::async_new(&mut pkt).await?);
490        }
491
492        // reading additional if any
493        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        // let vd = d.to_vec();
571
572            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            //let vd = d.to_vec();
625
626            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}