cdns_rs/
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::{cmp::Ordering, fmt::{self}, io::{Cursor, Read, Write}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, path::Path, sync::{Arc, LazyLock, OnceLock}, time::Duration};
59use std::borrow::Borrow;
60use std::hash::{Hash, Hasher};
61
62use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
63
64use crate::{cfg_host_parser::HostnameEntry, error::*, internal_error_map, query_private::QDnsReq};
65use crate::internal_error;
66
67/// A location on the disk where resolv.conf is located
68pub const RESOLV_CFG_PATH: &'static str = "/etc/resolv.conf";
69
70/// A hosts file location on disk
71pub const HOST_CFG_PATH: &'static str = "/etc/hosts";
72
73pub static RESOLV_CFG_PATH_P: LazyLock<&'static Path> = LazyLock::new(|| {Path::new(RESOLV_CFG_PATH)});
74pub static HOST_CFG_PATH_P: LazyLock<&'static Path> = LazyLock::new(|| {Path::new(HOST_CFG_PATH)});
75
76pub static GLOBALS: OnceLock<CDdnsGlobals> = OnceLock::new();
77
78/// A nsswitch location
79pub const NSSWITCH_CFG_PATH: &'static str = "/etc/nsswitch.conf";
80
81const IN_ADDR_ARPA: &[u8] = b"\x07in-addr\x04arpa\x00";
82const IN_ADDR6_ARPA: &[u8] = b"\x03ip6\x04arpa\x00";
83
84pub const DEF_USERAGENT: &'static str = concat!("CDNS-RS/", env!("CARGO_PKG_VERSION"));
85pub const DEF_TLS_PORT: u16 = 853;
86pub const DEF_HTTPS_PORT: u16 = 443;
87
88/// Default BIND for IPv4
89pub const IPV4_BIND_ALL: IpAddr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
90/// Default BIND for IPv6
91pub const IPV6_BIND_ALL: IpAddr = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
92
93#[derive(Debug)]
94pub struct CDdnsGlobals
95{
96     pub tcp_timeout: Option<Duration>,
97}
98
99impl CDdnsGlobals
100{
101    /// Many threads may call `init_once` concurrently with different initializing functions, 
102    /// but it is guaranteed that only one function will be executed.
103    pub 
104    fn init_once(globals: CDdnsGlobals)
105    {
106        GLOBALS.get_or_init(|| globals);
107
108        return;
109    }
110
111    pub 
112    fn get_tcp_conn_timeout() -> Option<Duration>
113    {
114        return GLOBALS.get().map_or(None, |f| f.tcp_timeout);
115    }
116}
117
118#[inline]
119pub 
120fn bind_all(ip_addr: IpAddr) -> SocketAddr
121{
122    match ip_addr
123    {
124        IpAddr::V4(_) => 
125            SocketAddr::from((IPV4_BIND_ALL, 0)),
126        IpAddr::V6(_) => 
127            SocketAddr::from((IPV6_BIND_ALL, 0)),
128    }
129}
130
131pub 
132fn pkt2string_exact(pkt: &mut Cursor<&[u8]>, rdlen: u16) -> CDnsResult<String>
133{
134    let mut new_string = vec![0_u8; rdlen as usize];
135
136    
137    pkt.read_exact(&mut new_string).map_err(map_read_err)?;
138
139
140    return 
141        String::from_utf8(new_string)
142            .map_err(|e| 
143                internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
144            );
145}
146
147pub 
148fn pkt2vec(pkt: &mut Cursor<&[u8]>, rdlen: Option<u16>) -> CDnsResult<Vec<u8>>
149{
150    if let Some(rdl) = rdlen
151    {
152        let mut new_buf = vec![0_u8; rdl as usize];
153
154        
155        pkt.read_exact(&mut new_buf).map_err(map_read_err)?;
156
157
158        return Ok(new_buf);
159    }
160    else
161    {
162        let mut new_buf = Vec::new();
163
164        pkt.read_to_end(&mut new_buf).map_err(map_read_err)?;
165
166        return Ok(new_buf);
167    }
168}
169
170/// Verifies the sequence of labels coding and copies data from pkt to
171/// buffer.
172/// 
173/// # Arguments
174/// 
175/// * `pkt` - a reference to the [Cursor]
176/// 
177/// # Returns 
178/// 
179/// * [CDnsResult] with data copied to new [Vec][u8]
180pub 
181fn pkt2name(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Vec<u8>>
182{
183    let qname_s = pkt.position() as usize;
184
185    loop
186    {
187        let cnt = pkt.read_u8().map_err(map_read_err)?;
188
189        if cnt == 0
190        {
191            break;
192        }
193        else
194        {
195            for _ in 0..cnt
196            {
197                let c = pkt.read_u8().map_err(map_read_err)?;
198                if c == 0
199                {
200                    internal_error!(
201                        CDnsErrorType::DnsResponse, 
202                        "incorrectly encoded QNAME in response, found '0' at offset: '{}'",
203                        pkt.position()
204                    );
205                }
206            }
207        }
208    }
209
210    // temporary store the position of the cursor
211    let cur_pos = pkt.position() as usize;
212
213    if (cur_pos - qname_s) <= 1
214    {
215        internal_error!(
216            CDnsErrorType::DnsResponse, 
217            "read name is too short"
218        );
219    }
220
221    /*pkt.set_position(qname_s);
222    
223    // creating buffer for QNAME
224    let mut req: Vec<u8> = vec![0_u8; (cur_pos - qname_s) as usize];
225    pkt.read_exact(&mut req).map_err(map_read_err)?;
226
227    // restore position
228    pkt.set_position(cur_pos);*/
229    
230
231    return Ok(pkt.get_ref()[qname_s..cur_pos].to_vec());
232}
233
234
235/// This function converts a QNAME (encoded domains) to the String FQDN.
236pub 
237fn name2str(pkt: &mut Cursor<&[u8]>, mut opt_rdlen: Option<u16>) -> CDnsResult<String>
238{
239    let cur_in_pos = pkt.position();
240    //let mut p_comp: u8 = 0;
241    let mut comp: u8;
242    let mut output: Vec<String> = Vec::with_capacity(6);
243
244    loop
245    {
246        if let Some(rdlen) = opt_rdlen
247        {
248            if pkt.position() - cur_in_pos >= rdlen as u64
249            {
250                return Ok(output.join("."));
251            }
252        }
253
254        // reading word from pkt to detect the type of message
255       // p_comp = comp;
256        comp = pkt.read_u8().map_err(map_read_err)?;
257
258        /*if p_comp > 0 && comp > 0
259        {
260            output.push('.');
261        }*/
262
263        let msb = comp & 0xC0;
264
265        if msb == 0xC0
266        {
267            if opt_rdlen.is_none() == true
268            {
269                opt_rdlen = Some(2);
270            }
271
272            let offset1: u16 = ((comp & !0xC0) as u16) << 8;// | pkt.read_u8().map_err(map_read_err)? as u16;
273            let offset2: u16 = pkt.read_u8().map_err(map_read_err)? as u16;
274
275            let offset = offset1 | offset2;
276
277            //println!("debug: 1: {} 2: {} offset: {}", offset1, offset2, offset);
278
279            // C0 0...
280            if offset as usize >= pkt.get_ref().len()
281            {
282                internal_error!(
283                    CDnsErrorType::DnsResponse, 
284                    "incoreclty formated packet: offset: '{}' > len: '{}'", 
285                    offset, pkt.get_ref().len()
286                );
287            }
288
289            // save current cursor position
290            let cur_pos = pkt.position();
291            pkt.set_position(offset as u64);
292
293            // converting the name to FQDN
294            output.push(name2str(pkt, None)?);
295            //output.push_str(cache.get(&offset).ok_or_else(|| internal_error_map!(CDnsErrorType::InternalError, "cache mismatch"))?);
296
297            // restoring cursor positon
298            pkt.set_position(cur_pos);
299        }
300        else if msb == 0x00 
301        {
302            if comp == 0
303            {
304                if let Some(rdlen) = opt_rdlen
305                {
306                    let dif = pkt.position() - cur_in_pos;
307
308                    if rdlen as u64 != dif
309                    {
310                        internal_error!(CDnsErrorType::DnsResponse, "incorrect rdlen: '{}', exp: '{}'", rdlen, dif);
311                    }
312                }
313
314                return Ok(output.join("."));
315            }
316            else
317            {
318                let mut tmp: Vec<u8> = Vec::with_capacity(comp as usize);
319
320                for _ in 0..comp
321                {
322                    let c = pkt.read_u8().map_err(map_read_err)?;
323                    if c == 0
324                    {
325                        internal_error!(CDnsErrorType::DnsResponse, "protocol violation, incorrectly encoded QNAME in response");
326                    }
327
328                    tmp.push(c);
329                }
330
331                output
332                    .push(
333                        String::from_utf8(tmp)
334                            .map_err(|e| 
335                                internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
336                            )?
337                    );
338            }
339        }
340        else
341        {
342            internal_error!(CDnsErrorType::DnsResponse, "incorrect compression: {:x}", msb);
343        }
344
345    } // loop
346}
347
348
349/// Converts a part of the octec of IP to printable hex i.e valid range is from
350/// 0 up to 15 will be converted to 0x30..0x39 and 'a'..'f'.
351/// 
352/// # Arguments
353/// 
354/// * `b` - a part of the octec
355/// 
356/// # Returns
357/// 
358/// * u8 an ASCII representation
359/// 
360/// # Throws
361/// 
362/// Panic when input b >= 16
363pub 
364fn byte2hexchar(b: u8) -> u8
365{
366    match b
367    {
368        0..=9 => return '0' as u8 + b,
369        10..=15 => return 'a' as u8 + (b - 10),
370        _ => panic!("out of hex range!")
371    }
372}
373
374/// Converts [IpAddr] to sequence of bytes coded specially for the payload
375/// of package.
376/// 
377/// # Arguments
378/// 
379/// * `ip` - the argument with IP address
380/// 
381/// # Returns
382/// 
383/// * [CDnsResult] with vector of coded data
384pub 
385fn ip2pkt(ip: &IpAddr) -> CDnsResult<Vec<u8>>
386{    
387    match *ip
388    {
389        IpAddr::V4(ref ipv4) =>
390            return ipv4_pkt(ipv4),
391        IpAddr::V6(ref ipv6) =>
392            return ipv6_pkt(ipv6)
393    };
394}
395
396const MAX_NAME_LEN: usize = 63;
397
398pub 
399fn ipv4_pkt(ip: &Ipv4Addr) -> CDnsResult<Vec<u8>>
400{    
401
402    // pre allocate space
403    let mut out: Vec<u8> = Vec::with_capacity(16 + IN_ADDR_ARPA.len());
404    
405    let mut octets = ip.octets();
406    octets.reverse();
407
408    for oct in octets
409    {
410        let str_oct = oct.to_string();
411
412        if str_oct.len() > 3
413        {
414            internal_error!(
415                CDnsErrorType::InternalError, 
416                "domain component too long, len: '{}' oct: '{}'", 
417                str_oct.len(), str_oct
418            );
419        }
420
421        let ln: u8 = str_oct.len() as u8;
422
423        out.push(ln);
424        out.extend(str_oct.as_bytes());
425    }
426
427    out.extend(IN_ADDR_ARPA);
428
429    return Ok(out);
430}
431
432pub 
433fn ipv6_pkt(ip: &Ipv6Addr) -> CDnsResult<Vec<u8>>
434{    
435    // pre allocate space
436    let mut out: Vec<u8> = Vec::with_capacity(32 + IN_ADDR6_ARPA.len());
437    
438    let mut octets = ip.octets();
439    octets.reverse();
440
441    for oct in octets
442    {
443        let h_oct = byte2hexchar((oct & 0xF0) >> 4);
444        //format!("{:x}", (oct & 0xF0) >> 4);
445        let l_oct = byte2hexchar(oct & 0x0F);
446        //format!("{:x}", oct & 0x0F);
447
448        //let ln: u8 = str_oct.len() as u8;
449
450        out.push(1);
451        out.push(l_oct);
452        //out.extend(l_oct.as_bytes());
453        out.push(1);
454        out.push(h_oct);
455    }
456
457    out.extend(IN_ADDR6_ARPA);
458
459    return Ok(out);
460}
461
462pub 
463fn name2pkt(name: &str) -> CDnsResult<Vec<u8>>
464{    
465    // pre allocate space
466    let mut out: Vec<u8> = Vec::with_capacity(name.len() + 2);
467    
468    for n in name.split(".")
469    {
470        if n.len() >= MAX_NAME_LEN
471        {
472            internal_error!(CDnsErrorType::InternalError, "name too long: '{}' in: '{}'", n.len(), name);
473        }
474
475        out.push((n.len() & 0xFF) as u8);
476        out.extend(n.as_bytes());
477    }
478
479    out.push(0);
480
481    return Ok(out);
482}
483
484
485/// A two octet code which specifies the type of the query.
486/// TYPE fields are used in resource records.  Note that these types are a
487/// subset of QTYPEs.
488/// QTYPE fields appear in the question part of a query.  QTYPES are a
489/// superset of TYPEs, hence all TYPEs are valid QTYPEs.
490#[repr(u16)]
491#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
492pub enum QType
493{
494    /// 1 a host address
495    A = 1,
496    /// 2 an authoritative name server
497    NS = 2,
498    /// 3 a mail destination (Obsolete - use MX)
499    MD = 3,
500    /// 4 a mail forwarder (Obsolete - use MX)
501    MF = 4,
502    /// 5 the canonical name for an alias
503    CNAME = 5,
504    /// 6 marks the start of a zone of authority
505    SOA = 6,
506    /// 7 a mailbox domain name (EXPERIMENTAL)
507    MB = 7,
508    /// 8 a mail group member (EXPERIMENTAL)
509    MG = 8,
510    /// 9 a mail rename domain name (EXPERIMENTAL)
511    MR = 9,
512    /// 10 a null RR (EXPERIMENTAL)
513    NULL = 10,
514    /// 11 a well known service description
515    WKS = 11,
516    /// 12 a domain name pointer
517    PTR = 12,
518    /// 13 host information
519    HINFO = 13,
520    /// 14 mailbox or mail list information
521    MINFO = 14,
522    /// 15 mail exchange
523    MX = 15,
524    /// 16 text strings
525    TXT = 16,
526    /// 18 AFS database record 
527    AFSDB = 18,
528    /// 25 Key record
529    KEY = 25,
530    /// 28 IPv6 address record
531    AAAA = 28,
532    /// 33 Service record
533    SRV = 33,
534    /// 37 Certificate records
535    CERT = 37,
536    /// 43 Delegation signer
537    DS = 43,
538    /// 46 DNSSEC signature
539    RRSIG = 46,
540    /// 47 Next Secure record
541    NSEC = 47,
542    /// DNS Key record
543    DNSKEY = 48,
544    /// 50 Next Secure record version 3
545    NSEC3 = 50,
546    /// 51 NSEC3 parameters
547    NSEC3PARAM = 51,
548    /// 59 Child DS 
549    CDS = 59,
550    /// 60 Child copy of DNSKEY record, for transfer to parent
551    CDNSKEY = 60,
552    /// OpenPGP public key record 
553    OPENPGPKEY = 61,
554    // ---- QTYPE ----
555    /// 252 A request for a transfer of an entire zone
556    AXFR = 252,
557    /// 253 A request for mailbox-related records (MB, MG or MR)
558    MAILB = 253,
559    /// 254 A request for mail agent RRs (Obsolete - see MX)
560    MAILA = 254,
561    /// 256 Uniform Resource Identifier RFC 7553
562    URI = 256,
563    /// 257 Certification Authority Authorization 
564    CAA = 257,
565    /// *
566    ALL = 255,
567    /// 32769 DNSSEC Lookaside Validation record
568    DLV = 32769,
569}
570
571impl Default for QType
572{
573    fn default() -> Self 
574    {
575        return Self::A;    
576    }
577}
578
579
580impl Into<u16> for QType
581{
582    fn into(self) -> u16 
583    {
584        return self as u16;
585    }
586}
587
588impl fmt::Display for QType
589{
590    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
591    {
592        match *self
593        {
594            Self::A          => write!(f, "A"),
595            Self::NS         => write!(f, "NS"),
596            Self::MD         => write!(f, "MD"),
597            Self::MF         => write!(f, "MF"),
598            Self::CNAME      => write!(f, "CNAME"),
599            Self::SOA        => write!(f, "SOA"),
600            Self::MB         => write!(f, "MB"),
601            Self::MG         => write!(f, "MG"),
602            Self::MR         => write!(f, "MR"),
603            Self::NULL       => write!(f, "NULL"),
604            Self::WKS        => write!(f, "WKS"),
605            Self::PTR        => write!(f, "PTR"),
606            Self::HINFO      => write!(f, "HINFO"),
607            Self::MINFO      => write!(f, "MINFO"),
608            Self::MX         => write!(f, "MX"),
609            Self::TXT        => write!(f, "TXT"),
610            Self::AFSDB      => write!(f, "AFSDB"),
611            Self::KEY        => write!(f, "KEY"),
612            Self::AAAA       => write!(f, "AAAA"),
613            Self::SRV        => write!(f, "SRV"),
614            Self::CERT       => write!(f, "CERT"),
615            Self::DS         => write!(f, "DS"),
616            Self::RRSIG      => write!(f, "RRSIG"),
617            Self::NSEC       => write!(f, "NSEC"),
618            Self::DNSKEY     => write!(f, "DNSKEY"),
619            Self::NSEC3      => write!(f, "NSEC"),
620            Self::NSEC3PARAM => write!(f, "NSEC3PARAM"),
621            Self::CDS        => write!(f, "CDS"),
622            Self::CDNSKEY    => write!(f, "CDNSKEY"),
623            Self::OPENPGPKEY => write!(f, "OPENPGPKEY"),
624            Self::AXFR       => write!(f, "AXFR"),
625            Self::MAILB      => write!(f, "MAILB"),
626            Self::MAILA      => write!(f, "MAILA"),
627            Self::CAA        => write!(f, "CAA"),
628            Self::ALL        => write!(f, "ALL"),
629            Self::DLV        => write!(f, "DLV"),
630            Self::URI        => write!(f, "URI"),
631        }
632    }
633}
634
635
636impl QType
637{
638    pub 
639    fn ipaddr_match(&self, ip: &IpAddr) -> bool
640    {
641        match *self
642        {
643            Self::A => return ip.is_ipv4(),
644            Self::AAAA => return ip.is_ipv6(),
645            _ => false,
646        }
647    }
648
649    pub 
650    fn u16_to_qtype(value: u16) -> CDnsResult<QType>
651    {
652        match value
653        {
654            x if x == Self::AXFR as u16    => return Ok(Self::AXFR),
655            x if x == Self::MAILB as u16   => return Ok(Self::MAILB),
656            x if x == Self::MAILA as u16   => return Ok(Self::MAILA),
657            x if x == Self::ALL as u16     => return Ok(Self::ALL),
658            x if x == Self::DLV as u16     => return Ok(Self::DLV),
659            _ => return Self::u16_to_type(value),
660        }
661    }
662
663    pub 
664    fn u16_to_type(value: u16) -> CDnsResult<QType>
665    {
666
667        match value
668        {
669            x if x == Self::A as u16            => return Ok(Self::A),
670            x if x == Self::NS as u16           => return Ok(Self::NS),
671            x if x == Self::MD as u16           => return Ok(Self::MD),
672            x if x == Self::MF as u16           => return Ok(Self::MF),
673            x if x == Self::CNAME as u16        => return Ok(Self::CNAME),
674            x if x == Self::SOA as u16          => return Ok(Self::SOA),
675            x if x == Self::MB as u16           => return Ok(Self::MB),
676            x if x == Self::MG as u16           => return Ok(Self::MG),
677            x if x == Self::MR as u16           => return Ok(Self::MR),
678            x if x == Self::NULL as u16         => return Ok(Self::NULL),
679            x if x == Self::WKS as u16          => return Ok(Self::WKS),
680            x if x == Self::PTR as u16          => return Ok(Self::PTR),
681            x if x == Self::HINFO as u16        => return Ok(Self::HINFO),
682            x if x == Self::MINFO as u16        => return Ok(Self::MINFO),
683            x if x == Self::MX as u16           => return Ok(Self::MX),
684            x if x == Self::TXT as u16          => return Ok(Self::TXT),
685            x if x == Self::AFSDB as u16        => return Ok(Self::AFSDB),
686            x if x == Self::KEY as u16          => return Ok(Self::KEY),
687            x if x == Self::AAAA as u16         => return Ok(Self::AAAA),
688            x if x == Self::CERT as u16         => return Ok(Self::CERT),
689            x if x == Self::DS as u16           => return Ok(Self::DS),
690            x if x == Self::RRSIG as u16        => return Ok(Self::RRSIG),
691            x if x == Self::NSEC as u16         => return Ok(Self::NSEC),
692            x if x == Self::DNSKEY as u16       => return Ok(Self::DNSKEY),
693            x if x == Self::NSEC3 as u16        => return Ok(Self::NSEC3),
694            x if x == Self::NSEC3PARAM as u16   => return Ok(Self::NSEC3PARAM),
695            x if x == Self::CDS as u16          => return Ok(Self::CDS),
696            x if x == Self::CDNSKEY as u16      => return Ok(Self::CDNSKEY),
697            x if x == Self::OPENPGPKEY as u16   => return Ok(Self::OPENPGPKEY),
698            _ => internal_error!(CDnsErrorType::DnsResponse, "unknown request record type: '{}'", value),
699        }
700    }
701}
702
703
704/// A two octet code that specifies the class of the query.
705/// 
706/// 
707#[repr(u16)]
708#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
709pub enum QClass
710{
711    /// the Internet 1
712    IN = 1,
713    /// the CSNET class (Obsolete) 2
714    CS = 2,
715    /// the CHAOS class 3
716    CH = 3,
717    /// Hesiod [Dyer 87] 4
718    HS = 4,
719    
720    //  --- QClass
721    /// any class 255
722    ALL = 255,
723}
724
725impl fmt::Display for QClass
726{
727    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
728    {
729        match *self
730        {
731            Self::IN  => write!(f, "IN"),
732            Self::CS  => write!(f, "CS"),
733            Self::CH  => write!(f, "CH"),
734            Self::HS  => write!(f, "HS"),
735            Self::ALL => write!(f, "ALL"),
736        }
737    }
738}
739
740impl Default for QClass
741{
742    fn default() -> Self 
743    {
744        return Self::IN;    
745    }
746}
747
748impl Into<u16> for QClass
749{
750    fn into(self) -> u16 
751    {
752        return self as u16;
753    }
754}
755
756impl QClass
757{
758    /// Converts u16 to enum [QClass].
759    /// 
760    /// QCLASS fields appear in the question part of a query.  QCLASS are a
761    /// superset of CLASSes, hence all CLASSes are valid QCLASSes.
762    pub 
763    fn u16_to_qclass(value: u16) -> CDnsResult<QClass>
764    {
765        match value
766        {
767            x if x == QClass::ALL as u16 => return Ok(QClass::ALL),
768            _ => Self::u16_to_class(value),
769        }
770    }
771
772    /// Converts u16 to enum [QClass], but for the response part of a query.
773    pub 
774    fn u16_to_class(value: u16) -> CDnsResult<QClass>
775    {
776        match value
777        {
778            x if x == QClass::IN as u16 => return Ok(QClass::IN),
779            x if x == QClass::CS as u16 => return Ok(QClass::CS),
780            x if x == QClass::CH as u16 => return Ok(QClass::CH),
781            x if x == QClass::HS as u16 => return Ok(QClass::HS),
782            _ => internal_error!(CDnsErrorType::DnsResponse, "unknown QCLASS type: '{}'", value),
783        }
784    }
785}
786
787// (req.status & !StatusBits::OPCODE_STANDARD) | ...
788// () 
789
790bitflags! {     
791    /// Flags  which control the status of th DNS query    
792    #[derive(Default, Debug, Copy, Clone, PartialEq, Eq)] 
793    pub struct StatusBits: u16  
794    {     
795        // Pkt type Request/Result R/W    
796        /// A request/response bit, when 1 - response
797        const QR_RESP           = 0x8000;
798
799        // Request Type (Write only)
800        /// a standard query (QUERY) USE inverse to reset
801        const OPCODE_STANDARD   = 0x87FF;
802        /// an inverse query (IQUERY)
803        const OPCODE_IQUERY     = 0x0040;
804        /// a server status request (STATUS)
805        const OPCODE_STATUS     = 0x0020;
806        // reserved for future use 3-15
807        // 0x4000 .. 0x0800
808
809        /// AA  Authoritative Answer (Read only)
810        /// Authoritative Answer - this bit is valid in responses,
811        /// and specifies that the responding name server is an
812        /// authority for the domain name in question section.
813        const AUTH_ANSWER       = 0x0400;
814
815        /// TrunCation (Read only)
816        /// TrunCation - specifies that this message was truncated
817        /// due to length greater than that permitted on the transmission channel.
818        const TRUN_CATION       = 0x0200;
819
820        /// RD Recursion desired (write only)
821        /// Recursion Desired - this bit may be set in a query and
822        /// is copied into the response.  If RD is set, it directs
823        /// the name server to pursue the query recursively.
824        /// Recursive query support is optional.
825        const RECURSION_DESIRED = 0x0100;
826
827        /// RA Recursion available (read only)
828        /// Recursion Available - this be is set or cleared in a
829        /// response, and denotes whether recursive query support is
830        /// available in the name server.
831        const RECURSION_AVAIL   = 0x0080;
832
833        /// Z Zero reserver
834        /// Reserved for future use.  Must be zero in all queries
835        /// and responses.
836        const RSERVER0          = 0x0040; 
837
838        const ANSWER_AUTHN      = 0x0020; 
839        const NON_AUTH_DATA     = 0x0010; 
840
841        // RCODE response code 
842
843        /// No error condition
844        const RESP_NOERROR      = 0x0000; 
845        /// Format error - The name server was unable to interpret the query.
846        const RESP_FORMERR      = 0x0001; 
847        /// Server failure - The name server was unable to process this query due to a
848        /// problem with the name server.
849        const RESP_SERVFAIL     = 0x0002; 
850        /// Name Error - Meaningful only for responses from an authoritative name
851        /// server, this code signifies that the domain name referenced in the query does
852        /// not exist.
853        const RESP_NXDOMAIN     = 0x0003;
854        /// Not Implemented - The name server does not support the requested kind of query.
855        const RESP_NOT_IMPL     = 0x0004; 
856        /// Refused - The name server refuses to perform the specified operation for
857        /// policy reasons.
858        const RESP_REFUSED      = 0x0005; 
859        // ..= 0x000F
860    }
861}
862
863/// An structure for the target in request.
864/// Implements From for [IpAddr], [Ipv4Addr], [Ipv6Addr], [str]
865/// In case if IP address is in the human readable 'string' format
866/// it will be stored as Name. And later the code will try to convert it
867/// to IP address before returing as string.
868#[derive(Clone, Debug, Hash, PartialEq, Eq)]
869pub enum QDnsName
870{
871    IpV4(Ipv4Addr),
872    IpV6(Ipv6Addr),
873    Name(Arc<String>),
874}
875
876impl fmt::Display for QDnsName
877{
878    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
879    {
880        match self
881        {
882            QDnsName::IpV4(ipv4_addr) => 
883                write!(f, "{}", ipv4_addr),
884            QDnsName::IpV6(ipv6_addr) => 
885                write!(f, "{}", ipv6_addr),
886            QDnsName::Name(name) => 
887                write!(f, "{}", name),
888        }
889    }
890}
891
892impl QDnsName
893{
894    /// Answers if current type is IpV4.
895    /// But does not performs check if Name is an IP in str format
896    pub
897    fn is_ipv4(&self) -> bool
898    {
899        match *self
900        {
901            Self::IpV4(_) => return true,
902            _ => return false,
903        }
904    }
905
906    /// Answers if current type is IpV6.
907    /// But does not performs check if Name is an IP in str format
908    pub 
909    fn is_ipv6(&self) -> bool
910    {
911        match *self
912        {
913            Self::IpV6(_) => return true,
914            _ => return false,
915        }
916    }
917
918    /// Answers if current type is IpV4 or IpV6.
919    /// But does not performs check if Name is an IP in str format
920    pub 
921    fn is_ip(&self) -> bool
922    {
923        match *self
924        {
925            Self::IpV4(_) => return true,
926            Self::IpV6(_) => return true,
927            _ => return false,
928        }
929    }
930
931    /// Returns the type of the IP address version in [QType] format.
932    pub 
933    fn get_ip_qtype(&self) -> Option<QType>
934    {
935        match *self
936        {
937            Self::IpV4(_) => return Some(QType::A),
938            Self::IpV6(_) => return Some(QType::AAAA),
939            Self::Name(_) =>
940            {
941                return None;
942            }
943        }
944    }
945}
946
947
948impl PartialEq<str> for QDnsName
949{
950    fn eq(&self, other: &str) -> bool 
951    {
952        match *self
953        {
954            Self::Name(ref name) => 
955                return name.as_str() == other,
956            Self::IpV4(ref ip) =>
957            {
958                if let Ok(other_ip) = other.parse::<Ipv4Addr>()
959                {   
960                    return &other_ip == ip;
961                }
962                
963                return false;
964            },
965            Self::IpV6(ref ip) =>
966            {
967                if let Ok(other_ip) = other.parse::<Ipv6Addr>()
968                {
969                    return &other_ip == ip;
970                }
971
972                return false;
973            }
974        }
975    }
976}
977
978/*
979impl From<&IpAddr> for QDnsName
980{
981    fn from(ip: &IpAddr) -> Self 
982    {
983        match *ip
984        {
985            IpAddr::V4(ref ip) => 
986                return Self::IpV4(ip.clone()),
987            IpAddr::V6(ref ip) => 
988                return Self::IpV6(ip.clone()),
989        }
990    }
991}
992*/
993
994impl From<&IpAddr> for QDnsName
995{
996    fn from(ip: &IpAddr) -> Self
997    {
998        match *ip
999        {
1000            IpAddr::V4(ref ip) => 
1001                return Self::IpV4(ip.clone()),
1002            IpAddr::V6(ref ip) => 
1003                return Self::IpV6(ip.clone()),
1004        }
1005    }
1006}
1007
1008impl From<IpAddr> for QDnsName
1009{
1010    fn from(ip: IpAddr) -> Self
1011    {
1012        match ip
1013        {
1014            IpAddr::V4(ip) => 
1015                return Self::IpV4(ip),
1016            IpAddr::V6(ip) => 
1017                return Self::IpV6(ip),
1018        }
1019    }
1020}
1021
1022impl From<&Ipv4Addr> for QDnsName
1023{
1024    fn from(ip: &Ipv4Addr) -> Self
1025    {
1026        return Self::IpV4(ip.clone());
1027    }
1028}
1029
1030impl From<Ipv4Addr> for QDnsName
1031{
1032    fn from(ip: Ipv4Addr) -> Self
1033    {
1034        return Self::IpV4(ip);
1035    }
1036}
1037
1038impl From<&Ipv6Addr> for QDnsName
1039{
1040    fn from(ip: &Ipv6Addr) -> Self
1041    {
1042        return Self::IpV6(ip.clone());
1043    }
1044}
1045
1046impl From<Ipv6Addr> for QDnsName
1047{
1048    fn from(ip: Ipv6Addr) -> Self
1049    {
1050        return Self::IpV6(ip);
1051    }
1052}
1053
1054impl From<&str> for QDnsName
1055{
1056    fn from(name: &str) -> Self
1057    {
1058        let ipp = name.parse::<IpAddr>();
1059        if ipp.is_err()
1060        {
1061            return Self::Name(Arc::new(name.to_string()));
1062        }
1063        else
1064        {
1065            return QDnsName::from(ipp.unwrap());
1066        }
1067    }
1068}
1069
1070impl TryFrom<QDnsName> for Vec<u8>
1071{
1072    type Error = CDnsError;
1073
1074    fn try_from(qns: QDnsName) -> Result<Self, Self::Error> 
1075    {
1076        match qns
1077        {
1078            QDnsName::IpV4(ref ip) =>
1079            {
1080                return ipv4_pkt(ip);
1081            },
1082            QDnsName::IpV6(ref ip) =>
1083            {
1084                return ipv6_pkt(ip);
1085            },
1086            QDnsName::Name(ref name) =>
1087            {
1088                if let Ok(ip) = name.parse::<Ipv4Addr>()
1089                {   
1090                    return ipv4_pkt(&ip);
1091                }
1092                else if let Ok(ip) = name.parse::<Ipv6Addr>()
1093                {
1094                    return ipv6_pkt(&ip);
1095                }
1096                else
1097                {
1098                    return name2pkt(name);
1099                }
1100            }
1101        }
1102    }
1103}
1104
1105impl TryFrom<&QDnsName> for Vec<u8>
1106{
1107    type Error = CDnsError;
1108
1109    fn try_from(qns: &QDnsName) -> Result<Self, Self::Error> 
1110    {
1111        match qns
1112        {
1113            QDnsName::IpV4(ip) =>
1114            {
1115                return ipv4_pkt(ip);
1116            },
1117            QDnsName::IpV6(ip) =>
1118            {
1119                return ipv6_pkt(ip);
1120            },
1121            QDnsName::Name(name) =>
1122            {
1123                if let Ok(ip) = name.parse::<Ipv4Addr>()
1124                {   
1125                    return ipv4_pkt(&ip);
1126                }
1127                else if let Ok(ip) = name.parse::<Ipv6Addr>()
1128                {
1129                    return ipv6_pkt(&ip);
1130                }
1131                else
1132                {
1133                    return name2pkt(name);
1134                }
1135            }
1136        }
1137    }
1138}
1139
1140impl From<&QDnsName> for String
1141{
1142    fn from(dnsname: &QDnsName) -> Self 
1143    {
1144        match *dnsname
1145        {
1146            QDnsName::IpV4(ref ip) =>
1147            {
1148                return ip.to_string();
1149            },
1150            QDnsName::IpV6(ref ip) =>
1151            {
1152                return ip.to_string();
1153            },
1154            QDnsName::Name(ref name) =>
1155            {
1156                return name.to_string();
1157            }
1158        }
1159    }
1160}
1161
1162
1163impl TryFrom<&QDnsName> for IpAddr
1164{
1165    type Error = CDnsError;
1166    fn try_from(value: &QDnsName) -> Result<Self, Self::Error> 
1167    {
1168        match *value
1169        {
1170            QDnsName::IpV4(ref ip) =>
1171            {
1172                return Ok(IpAddr::V4(ip.clone()));
1173            },
1174            QDnsName::IpV6(ref ip) =>
1175            {
1176                return Ok(IpAddr::V6(ip.clone()));
1177            },
1178            QDnsName::Name(ref name) =>
1179            {
1180                if let Ok(ip) = name.parse::<Ipv4Addr>()
1181                {   
1182                    return Ok(IpAddr::V4(ip.clone()));
1183                }
1184                else if let Ok(ip) = name.parse::<Ipv6Addr>()
1185                {
1186                    return Ok(IpAddr::V6(ip.clone()));
1187                }
1188                else
1189                {
1190                    internal_error!(CDnsErrorType::InternalError, "not ip address!")
1191                }
1192            }
1193        }
1194    }
1195}
1196
1197
1198impl TryFrom<QDnsName> for IpAddr
1199{
1200    type Error = CDnsError;
1201    fn try_from(value: QDnsName) -> Result<Self, Self::Error> 
1202    {
1203        match value
1204        {
1205            QDnsName::IpV4(ip) =>
1206            {
1207                return Ok(IpAddr::V4(ip));
1208            },
1209            QDnsName::IpV6(ip) =>
1210            {
1211                return Ok(IpAddr::V6(ip));
1212            },
1213            QDnsName::Name(ref name) =>
1214            {
1215                if let Ok(ip) = name.parse::<Ipv4Addr>()
1216                {   
1217                    return Ok(IpAddr::V4(ip));
1218                }
1219                else if let Ok(ip) = name.parse::<Ipv6Addr>()
1220                {
1221                    return Ok(IpAddr::V6(ip));
1222                }
1223                else
1224                {
1225                    internal_error!(CDnsErrorType::InternalError, "not ip address!")
1226                }
1227            }
1228        }
1229    }
1230}
1231
1232#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1233pub struct DnsHeader
1234{
1235    /// A 16 bit identifier assigned by the program that
1236    /// generates any kind of query.
1237    pub id: u16,
1238
1239    /// Query control flags
1240    pub status: StatusBits,
1241
1242    /// an unsigned 16 bit integer specifying the number of
1243    /// entries in the question section.
1244    pub qdcount: u16,
1245
1246    /// an unsigned 16 bit integer specifying the number of
1247    /// resource records in the answer section.
1248    pub ancount: u16,
1249
1250    /// an unsigned 16 bit integer specifying the number of name
1251    /// server resource records in the authority records
1252    /// section.
1253    pub nscount: u16,
1254
1255    /// an unsigned 16 bit integer specifying the number of
1256    /// resource records in the additional records section.
1257    pub arcount: u16,
1258}
1259
1260impl fmt::Display for DnsHeader
1261{
1262    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1263    {
1264        write!(f, "ID:{} Status:{:?}, qdcnt:{}, ancnt:{}, nscnt:{}, arcnt:{}",
1265            self.id, self.status, self.qdcount, self.ancount, self.nscount, self.arcount)
1266    }
1267}
1268
1269
1270#[derive(Clone, Debug, Default, PartialEq, Eq)]
1271pub struct DnsRequestAnswer
1272{
1273    /// request header
1274    pub req_header: DnsRequestHeader,
1275    /// Resonse section
1276    pub response: Vec<DnsResponsePayload>,
1277    /// Additional RR
1278    pub additional: Vec<DnsResponsePayload>,
1279    /// Authortative nameservers
1280    pub authoratives: Vec<DnsResponsePayload>,
1281}
1282
1283impl DnsRequestAnswer
1284{
1285    #[inline]
1286    pub 
1287    fn get_req_id(&self) -> u16
1288    {
1289        return self.req_header.get_id();
1290    }
1291
1292    /// Validates the content
1293    /// 
1294    /// # Arguments
1295    /// 
1296    /// * `req` - a request which was sent 
1297    pub 
1298    fn verify(&self, req: &DnsRequestHeader) -> CDnsResult<()>
1299    {
1300        if self.get_req_id() != req.get_id()
1301        {
1302            internal_error!(
1303                CDnsErrorType::DnsResponse, 
1304                "request and response ID did not match: '{}' != '{}'", 
1305                req.header.id, self.get_req_id()
1306            );
1307        }
1308
1309        // check if request matches with what we sent previously
1310        if self.req_header.payload != req.payload
1311        {
1312            internal_error!(CDnsErrorType::DnsResponse, 
1313                "received request section is different from sent");
1314        }
1315        else if req.payload.qtype != QType::ALL
1316        {
1317            // check qtype matches requested. (is it correct?)
1318            if req.payload.qtype != self.req_header.payload.qtype
1319            {
1320                internal_error!(
1321                    CDnsErrorType::DnsResponse, 
1322                    "requested QTYPE differ received TYPE: '{}' != '{}'", 
1323                    req.payload.qtype, 
1324                    self.req_header.payload.qtype
1325                );
1326            }
1327        }
1328        else if self.req_header.header.status.contains(StatusBits::TRUN_CATION) == true
1329        {
1330            internal_error!(CDnsErrorType::MessageTruncated, 
1331                "DNS response was truncated, aborting processing");
1332        }
1333
1334        return Ok(());
1335    }
1336
1337    /// Parses the raw data from received packet.
1338    /// 
1339    /// # Arguments
1340    /// 
1341    /// * `ans` - the received data
1342    pub(crate) 
1343    fn parse(ans: &[u8]) -> CDnsResult<Self>
1344    {
1345        // creating cursor
1346        let mut pkt = Cursor::new(ans);
1347
1348        // parsing header
1349        let id = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1350
1351        let status = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1352
1353        let header = 
1354            DnsHeader
1355            {
1356                id: id,
1357                status: StatusBits::from_bits(status).ok_or_else(|| 
1358                    internal_error_map!(CDnsErrorType::DnsResponse, "unknown status bits: '{}'", status)
1359                )?,
1360                qdcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1361                ancount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1362                nscount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1363                arcount: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1364            };
1365
1366        // todo!("what about truncated messages");
1367
1368        // check if there is no more than 1 answer
1369        if header.status.contains(StatusBits::QR_RESP) == false
1370        {
1371            internal_error!(
1372                CDnsErrorType::DnsResponse, 
1373                "incorret QR flag in STATUS register of response, expected 1 got 0"
1374            );
1375        }
1376       /*else if header.ancount > 1
1377        {
1378            internal_error!(
1379                CDnsErrorType::DnsRespose, 
1380                "too many responses = '{}', multiple responses are not supported", 
1381                header.ancount
1382            );
1383        }*/
1384        /*else if header.ancount == 0 && header.status.contains(StatusBits::RESP_NOERROR) == true
1385        {
1386            internal_error!(CDnsErrorType::DnsRespose, "answer count: 0 while response contains no error");
1387        }*/
1388        
1389        // reading request
1390        //let cur_offset = pkt.position();
1391    
1392        let request = 
1393            DnsRequestPayload
1394            {
1395                qname: pkt2name(&mut pkt)?,
1396                qtype: QType::u16_to_qtype(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
1397                qclass: QClass::u16_to_qclass(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?,
1398            };
1399
1400        let mut an_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.ancount as usize);
1401        let mut rr_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.arcount as usize);
1402        let mut ns_list: Vec<DnsResponsePayload> = Vec::with_capacity(header.nscount as usize);
1403
1404        for _ in 0..header.ancount
1405        {
1406            an_list.push(DnsResponsePayload::new(&mut pkt)?);
1407        }
1408        
1409        // reading authoritative section if any
1410        for _ in 0..header.nscount
1411        {
1412            ns_list.push(DnsResponsePayload::new(&mut pkt)?);
1413        }
1414
1415        // reading additional if any
1416        for _ in 0..header.arcount
1417        {
1418            rr_list.push(DnsResponsePayload::new(&mut pkt)?);
1419        }
1420
1421        return Ok(
1422            DnsRequestAnswer
1423            {
1424                req_header: DnsRequestHeader{ header, payload: request },
1425                response: an_list,
1426                additional: rr_list,
1427                authoratives: ns_list,
1428            }
1429        );
1430    }
1431
1432}
1433
1434#[derive(Clone, Debug, Default)]
1435pub struct DnsRequestHeader
1436{
1437    /// request header
1438    pub header: DnsHeader,
1439    /// Query content
1440    pub payload: DnsRequestPayload,
1441}
1442
1443impl Eq for DnsRequestHeader {}
1444
1445impl PartialEq for DnsRequestHeader
1446{
1447    fn eq(&self, other: &DnsRequestHeader) -> bool 
1448    {
1449        return self.header.id == other.header.id && self.payload == other.payload;
1450    }
1451}
1452
1453impl Ord for DnsRequestHeader 
1454{
1455    fn cmp(&self, other: &Self) -> Ordering 
1456    {
1457        // Sort in reverse order
1458        return self.header.id.cmp(&other.header.id);
1459    }
1460}
1461
1462impl PartialOrd for DnsRequestHeader 
1463{
1464    fn partial_cmp(&self, other: &Self) -> Option<Ordering> 
1465    {
1466        return Some(self.cmp(other));
1467    }
1468}
1469
1470impl Hash for DnsRequestHeader
1471{
1472    fn hash<H: Hasher>(&self, state: &mut H) 
1473    {
1474        self.header.id.hash(state);
1475        self.payload.hash(state);
1476    }
1477}
1478
1479impl Borrow<u16> for DnsRequestHeader
1480{
1481    fn borrow(&self) -> &u16 
1482    {
1483        return &self.header.id;
1484    }
1485}
1486
1487impl TryFrom<&QDnsReq> for DnsRequestHeader
1488{
1489    type Error = CDnsError;
1490
1491    fn try_from(value: &QDnsReq) -> Result<Self, Self::Error> 
1492    {
1493        return DnsRequestHeader::construct_lookup(value);//qrec.get_req_name().clone(), *qrec.get_type());
1494    }
1495}
1496
1497impl fmt::Display for DnsRequestHeader
1498{
1499    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1500    {
1501        write!(f, "Header: {}, Status: {}", self.header, self.payload)
1502    }
1503}
1504
1505
1506impl DnsRequestHeader
1507{
1508    pub 
1509    fn regenerate_id(&mut self)
1510    {
1511        self.header.id = rand::random();
1512    }
1513
1514    pub 
1515    fn get_id(&self) -> u16
1516    {
1517        return self.header.id;
1518    }
1519
1520   /* pub 
1521    fn from_qdns_req(qrec: &QDnsReq) -> CDnsResult<Self>
1522    {
1523        return DnsRequestHeader::construct_lookup(qrec.get_req_name().clone(), *qrec.get_type());
1524    }
1525    */
1526
1527    pub 
1528    fn derive(&self) -> Self
1529    {
1530        let header = 
1531            DnsHeader
1532            {
1533                id: rand::random(),
1534                status: self.header.status,
1535                qdcount: self.header.qdcount,
1536                ancount: self.header.ancount,
1537                nscount: self.header.nscount,
1538                arcount: self.header.arcount,
1539            };
1540
1541        return DnsRequestHeader{ header: header, payload: self.payload.clone() };
1542    }
1543
1544    /// Constructs the request from input.
1545    pub
1546    fn construct_lookup(qreq: &QDnsReq) -> CDnsResult<DnsRequestHeader>
1547    {        
1548        // preparing status register
1549        let mut status: StatusBits = StatusBits::empty();
1550        status = (status & !StatusBits::OPCODE_STANDARD) | StatusBits::RECURSION_DESIRED;
1551
1552        // constructing request structure
1553        let mut req: DnsRequestHeader = DnsRequestHeader{ ..Default::default() };
1554
1555        req.header.id = rand::random();
1556        req.header.status = status;
1557        req.header.qdcount = 1;
1558
1559        // creating payload request
1560        req.payload = DnsRequestPayload::new(qreq.get_req_name().try_into()?, *qreq.get_type(), QClass::IN);
1561
1562        return Ok(req);
1563    }
1564    
1565    pub 
1566    fn to_bytes(&self, append_len: bool) -> CDnsResult<Vec<u8>>
1567    {
1568        let mut pkt_size: usize = size_of::<DnsHeader>() + self.payload.qname.len() + 4; 
1569
1570        if append_len == true
1571        {
1572            pkt_size += 2;
1573        }
1574
1575        let mut pkt = Cursor::new(vec![0_u8; pkt_size]);
1576
1577        if append_len == true
1578        {
1579            pkt.write_u16::<BigEndian>((pkt_size-2) as u16).map_err(map_read_err)?;
1580        }
1581
1582        pkt.write_u16::<BigEndian>(self.header.id).map_err(map_read_err)?;
1583        pkt.write_u16::<BigEndian>(self.header.status.bits()).map_err(map_read_err)?;
1584        pkt.write_u16::<BigEndian>(self.header.qdcount).map_err(map_read_err)?;
1585        pkt.write_u16::<BigEndian>(self.header.ancount).map_err(map_read_err)?;
1586        pkt.write_u16::<BigEndian>(self.header.nscount).map_err(map_read_err)?;
1587        pkt.write_u16::<BigEndian>(self.header.arcount).map_err(map_read_err)?;
1588
1589        //for p in self.payload.iter()
1590        //{
1591            pkt.write(self.payload.qname.as_slice()).map_err(map_read_err)?;
1592            pkt.write_u16::<BigEndian>(self.payload.qtype.into()).map_err(map_read_err)?;
1593            pkt.write_u16::<BigEndian>(self.payload.qclass.into()).map_err(map_read_err)?;
1594        //}
1595
1596        return Ok(pkt.into_inner());
1597    }
1598}
1599
1600/// A request payload with (request) lines.
1601#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
1602pub struct DnsRequestPayload
1603{
1604    /// a domain name represented as a sequence of labels
1605    pub qname: Vec<u8>,
1606
1607    /// a two octet code which specifies the type of the query.
1608    pub qtype: QType,
1609    
1610    /// a two octet code that specifies the class of the query.
1611    pub qclass: QClass,
1612}
1613
1614impl fmt::Display for DnsRequestPayload
1615{
1616    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1617    {
1618        write!(f, "qname:{:?} qtype:{}, qclass:{}", self.qname, self.qtype, self.qclass)
1619    }
1620}
1621
1622impl DnsRequestPayload
1623{
1624    pub 
1625    fn new(qname: Vec<u8>, qtype: QType, qclass: QClass) -> Self
1626    {
1627        return DnsRequestPayload{ qname: qname, qtype: qtype.into(), qclass: qclass.into() };
1628    }
1629}
1630
1631/// A response section
1632#[derive(Clone, Debug, Default, Eq, PartialEq)]
1633pub struct DnsResponsePayload
1634{
1635    // A domain name that was queried, in the same format as the QNAME in the question
1636    pub name: String,
1637    /// Two octets containing one of th type codes.
1638    pub dtype: QType,
1639    /// Two octets which specify the class of the data in the RDATA field
1640    pub class: QClass,
1641    /// specifies the time interval that the resource record may be cached before the source
1642    /// of the information should again be consulted
1643    pub ttl: i32,
1644    /// specifies the length in octets of the RDATA field
1645    pub rdlength: u16,
1646    /// a variable length string of octets that describes the resource
1647    pub rdata: DnsRdata,
1648}
1649
1650impl DnsResponsePayload
1651{
1652    /// Creates a record from [HostnameEntry], but only for types like
1653    /// A, AAAA, PTR
1654    pub(crate)
1655    fn new_local(dtype: QType, data: &HostnameEntry) -> Option<Vec<Self>>
1656    {
1657        match dtype
1658        {
1659            QType::A => 
1660            {
1661                let mut out: Vec<Self> = Vec::with_capacity(1);
1662
1663                let IpAddr::V4(ipv4) = data.get_ip()
1664                else { return None; };
1665
1666                out.push(
1667                    DnsResponsePayload
1668                    {
1669                        name: data.get_hostnames()[0].to_string(),
1670                        dtype: dtype,
1671                        class: QClass::IN,
1672                        ttl: i32::MAX,
1673                        rdlength: 0,
1674                        rdata: RecordA::wrap(RecordA{ ip: ipv4.clone()}),
1675                    }
1676                );
1677
1678                return Some(out);
1679            },
1680            QType::AAAA => 
1681            {
1682                let mut out: Vec<Self> = Vec::with_capacity(1);
1683
1684                let IpAddr::V6(ipv6) = data.get_ip()
1685                else { return None };
1686
1687                out.push(
1688                    DnsResponsePayload
1689                    {
1690                        name: data.get_hostnames()[0].to_string(),
1691                        dtype: dtype,
1692                        class: QClass::IN,
1693                        ttl: i32::MAX,
1694                        rdlength: 0,
1695                        rdata: RecordAAAA::wrap(RecordAAAA{ ip: ipv6.clone() }),
1696                    }
1697                );
1698
1699                return Some(out);
1700            },
1701            QType::PTR => 
1702            {
1703                let mut out: Vec<Self> = Vec::with_capacity(data.get_hostnames().len());
1704
1705                // copy all hostnames from the list
1706                for h in data.get_hostnames_iter()
1707                {
1708                    out.push(
1709                        DnsResponsePayload
1710                        {
1711                            name: [data.get_ip().to_string().as_str(), ".in-addr.arpa"].concat(),
1712                            dtype: dtype,
1713                            class: QClass::IN,
1714                            ttl: i32::MAX,
1715                            rdlength: 0,
1716                            rdata: RecordPTR::wrap( RecordPTR { fqdn: h.clone() }),
1717                        }
1718                    );
1719                }
1720            
1721                return Some(out);
1722            },
1723            _ => 
1724                return None
1725        }
1726        
1727    }
1728
1729    fn new(pkt: &mut Cursor<&[u8]>) -> CDnsResult<Self>
1730    {
1731        let name = name2str(pkt, None)?;
1732        let qtype = QType::u16_to_type(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
1733        let qclass = QClass::u16_to_class(pkt.read_u16::<BigEndian>().map_err(map_read_err)?)?;
1734        let ttl = pkt.read_i32::<BigEndian>().map_err(map_read_err)?;
1735        let rdlength = pkt.read_u16::<BigEndian>().map_err(map_read_err)?;
1736        let rdata = DnsRdata::convert(pkt, rdlength, qtype)?;
1737
1738        return Ok(
1739            DnsResponsePayload
1740            {
1741                name: name,
1742                dtype: qtype,
1743                class: qclass,
1744                ttl: ttl,
1745                rdlength: rdlength,
1746                rdata: rdata,
1747            }
1748        );
1749    }
1750
1751    pub 
1752    fn get_rdata(&self) -> &DnsRdata
1753    {
1754        return &self.rdata;
1755    }
1756
1757    pub 
1758    fn borrow_rdata(self) -> DnsRdata
1759    {
1760        return self.rdata;
1761    }
1762}
1763
1764/*impl Default for DnsResponsePayload
1765{
1766    fn default() -> Self 
1767    {
1768        return Self::Empty;    
1769    }
1770}*/
1771
1772impl fmt::Display for DnsResponsePayload
1773{
1774    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1775    {
1776        write!(f, "{} {} {} {} {}", 
1777            self.name, self.dtype, self.class, self.ttl, self.rdata)  
1778    }
1779}
1780
1781
1782/// Trait for decoding DNS record structures from bytes read over the wire.
1783pub trait RecordReader: Sized 
1784{
1785
1786    /// A [QType] a record type for current instance
1787    const REC_TYPE: QType;
1788
1789    /// A data size
1790    const RLEN: u16;
1791
1792    /// Read at most `len` bytes from the given `Cursor`. This cursor travels
1793    /// throughout the complete data — by this point, we have read the entire
1794    /// response into a buffer.
1795    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>;
1796
1797    fn wrap(self) -> DnsRdata;
1798}
1799
1800#[derive(Clone, Debug, Eq, PartialEq)]
1801pub struct RecordA
1802{
1803    pub ip: Ipv4Addr
1804}
1805
1806impl RecordReader for RecordA
1807{
1808    const REC_TYPE: QType = QType::A;
1809
1810    const RLEN: u16 = 4;
1811
1812    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
1813    {
1814        // read 4 bytes (octets)
1815        if rlen != Self::RLEN
1816        {
1817            internal_error!(CDnsErrorType::DnsResponse, "RecordA len expected: '4', got: '{}'", rlen);
1818        }
1819        else if qtype != Self::REC_TYPE
1820        {
1821            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1822        }
1823
1824        let ip = pkt.read_u32::<BigEndian>().map_err(map_read_err)?;
1825
1826        return Ok(Self{ip: Ipv4Addr::from(ip) });
1827    }
1828
1829    fn wrap(self) -> DnsRdata 
1830    {
1831        return DnsRdata::A(self);
1832    }
1833}
1834
1835impl fmt::Display for RecordA
1836{
1837    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1838    {
1839        write!(f, "{}   {}", Self::REC_TYPE, self.ip)
1840    }
1841}
1842
1843
1844#[derive(Clone, Debug, Eq, PartialEq)]
1845pub struct RecordAAAA
1846{
1847    pub ip: Ipv6Addr
1848}
1849
1850impl RecordReader for RecordAAAA
1851{
1852    const REC_TYPE: QType = QType::AAAA;
1853
1854    const RLEN: u16 = 16;
1855
1856    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
1857    {
1858        if rlen != Self::RLEN
1859        {
1860            internal_error!(CDnsErrorType::DnsResponse, "RecordAAAA len expected: '{}', got: '{}'", Self::RLEN, rlen);
1861        }
1862        else if qtype != Self::REC_TYPE
1863        {
1864            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1865        }
1866
1867        let ip = pkt.read_u128::<BigEndian>().map_err(map_read_err)?;
1868        
1869        return Ok(Self{ ip: Ipv6Addr::from(ip) });
1870    }
1871
1872    fn wrap(self) -> DnsRdata 
1873    {
1874        return DnsRdata::AAAA(self);
1875    }
1876}
1877
1878impl fmt::Display for RecordAAAA
1879{
1880    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1881    {
1882        write!(f, "{}   {}", Self::REC_TYPE, self.ip)
1883    }
1884}
1885
1886#[derive(Clone, Debug, Eq, PartialEq)]
1887pub struct RecordPTR
1888{
1889    pub fqdn: String
1890}
1891
1892impl RecordReader for RecordPTR
1893{
1894    const REC_TYPE: QType = QType::PTR;
1895
1896    const RLEN: u16 = 0;
1897
1898    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
1899    {
1900        if qtype != Self::REC_TYPE
1901        {
1902            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1903        }
1904
1905        return Ok(
1906            Self{ fqdn: name2str(pkt, Some(rlen))? }
1907        );
1908    }
1909
1910    fn wrap(self) -> DnsRdata 
1911    {
1912        return DnsRdata::PTR(self);
1913    }
1914}
1915
1916impl fmt::Display for RecordPTR
1917{
1918    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1919    {
1920        write!(f, "{}   {}", Self::REC_TYPE, self.fqdn)
1921    }
1922}
1923
1924#[derive(Clone, Debug, Eq, PartialEq)]
1925pub struct RecordMX
1926{
1927    pub preference: u16, 
1928    pub exchange: String
1929}
1930
1931impl RecordReader for RecordMX
1932{
1933    const REC_TYPE: QType = QType::MX;
1934
1935    const RLEN: u16 = 2;
1936
1937    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
1938    {
1939        if rlen <= Self::RLEN
1940        {
1941            internal_error!(CDnsErrorType::DnsResponse, "RecordMX len expected: '{}', got: '{}'", Self::RLEN, rlen);
1942        }
1943        else if qtype != Self::REC_TYPE
1944        {
1945            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1946        }
1947
1948        return Ok(
1949            Self
1950            { 
1951                preference: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
1952                exchange: name2str(pkt, Some(rlen - 2))?,
1953            }
1954        );
1955    }
1956
1957    fn wrap(self) -> DnsRdata 
1958    {
1959        return DnsRdata::MX(self);
1960    }
1961}
1962
1963impl fmt::Display for RecordMX
1964{
1965    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1966    {
1967        write!(f, "{}   {} {}", Self::REC_TYPE, self.preference, self.exchange)
1968    }
1969}
1970
1971#[derive(Clone, Debug, Eq, PartialEq)]
1972pub struct RecordCNAME
1973{
1974    pub fqdn: String
1975}
1976
1977impl RecordReader for RecordCNAME
1978{
1979    const REC_TYPE: QType = QType::CNAME;
1980
1981    const RLEN: u16 = 0;
1982
1983    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
1984    {
1985        if qtype != Self::REC_TYPE
1986        {
1987            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
1988        }
1989
1990        return Ok(
1991            Self{ fqdn: name2str(pkt, Some(rlen))? }
1992        );
1993    }
1994
1995    fn wrap(self) -> DnsRdata 
1996    {
1997        return DnsRdata::CNAME(self);
1998    }
1999}
2000
2001impl fmt::Display for RecordCNAME
2002{
2003    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2004    {
2005        write!(f, "{}   {}", Self::REC_TYPE, self.fqdn)
2006    }
2007}
2008
2009#[derive(Clone, Debug, Eq, PartialEq)]
2010pub struct RecordNS
2011{
2012    pub fqdn: String
2013}
2014
2015impl RecordReader for RecordNS
2016{
2017    const REC_TYPE: QType = QType::NS;
2018
2019    const RLEN: u16 = 0;
2020
2021    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
2022    {
2023        if qtype != Self::REC_TYPE
2024        {
2025            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2026        }
2027
2028        return Ok(
2029            Self{ fqdn: name2str(pkt, Some(rlen))? }
2030        );
2031    }
2032
2033    fn wrap(self) -> DnsRdata 
2034    {
2035        return DnsRdata::NS(self);
2036    }
2037}
2038
2039impl fmt::Display for RecordNS
2040{
2041    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2042    {
2043        write!(f, "{}   {}", Self::REC_TYPE, self.fqdn)
2044    }
2045}
2046
2047#[derive(Clone, Debug, Eq, PartialEq)]
2048pub struct RecordSOA
2049{
2050    /// primary name server
2051    pub pnm: String, 
2052    /// responsible authority mailbox
2053    pub ram: String,
2054    /// serial number
2055    pub serial: u32,
2056    /// refresh interval
2057    pub interv_refr: u32,
2058    /// retry interval
2059    pub interv_retry: u32,
2060    /// expire limit
2061    pub expire_limit: u32,
2062    /// minimum TTL
2063    pub min_ttl: u32,
2064}
2065
2066impl RecordReader for RecordSOA
2067{
2068    const REC_TYPE: QType = QType::SOA;
2069
2070    const RLEN: u16 = 0;
2071
2072    fn read(pkt: &mut Cursor<&[u8]>, _rlen: u16, qtype: QType) -> CDnsResult<Self> 
2073    {
2074        if qtype != Self::REC_TYPE
2075        {
2076            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2077        }
2078
2079        return Ok(
2080            Self
2081            { 
2082                // primary name server
2083                pnm: name2str(pkt, None)?, 
2084                // responsible authority mailbox
2085                ram: name2str(pkt, None)?,
2086                // serial number
2087                serial: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2088                // refresh interval
2089                interv_refr: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2090                // retry interval
2091                interv_retry: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2092                // expire limit
2093                expire_limit: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2094                // minimum TTL
2095                min_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2096            }
2097        );
2098    }
2099
2100    fn wrap(self) -> DnsRdata 
2101    {
2102        return DnsRdata::SOA(self);
2103    }
2104}
2105
2106impl fmt::Display for RecordSOA
2107{
2108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2109    {
2110        write!(f, "{}   {} {} {} {} {} {} {}", Self::REC_TYPE, self.pnm, self.ram, self.serial, 
2111            self.interv_refr, self.interv_retry, self.expire_limit, self.min_ttl)
2112    }
2113}
2114
2115#[derive(Clone, Debug, Eq, PartialEq)]
2116pub struct RecordSRV
2117{
2118    /// the priority of the target host, lower value means more preferred.
2119    pub priority: u16,
2120
2121    /// A relative weight for records with the same priority, higher value 
2122    /// means higher chance of getting picked.
2123    pub weight: u16,
2124
2125    /// the TCP or UDP port on which the service is to be found.
2126    pub port: u16,
2127
2128    /// the canonical hostname of the machine providing the service, ending in a dot.
2129    pub target: String,
2130}
2131
2132impl RecordReader for RecordSRV
2133{
2134    const REC_TYPE: QType = QType::SRV;
2135
2136    const RLEN: u16 = 0;
2137
2138    fn read(pkt: &mut Cursor<&[u8]>, _rlen: u16, qtype: QType) -> CDnsResult<Self> 
2139    {
2140        if qtype != Self::REC_TYPE
2141        {
2142            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2143        }
2144
2145        return Ok(
2146            Self
2147            { 
2148                priority: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2149                weight: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2150                port: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2151                target: name2str(pkt, None)?,
2152            }
2153        );
2154    }
2155
2156    fn wrap(self) -> DnsRdata 
2157    {
2158        return DnsRdata::SRV(self);
2159    }
2160}
2161
2162impl fmt::Display for RecordSRV
2163{
2164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2165    {
2166        write!(f, "{}   {} {} {} \"{}\"", Self::REC_TYPE, self.priority, self.weight, self.port, self.target)
2167    }
2168}
2169
2170#[derive(Clone, Debug, Eq, PartialEq)]
2171pub struct RecordTXT
2172{
2173    /// The character-strings.
2174    pub txt_strings: String,
2175}
2176
2177impl RecordReader for RecordTXT
2178{
2179    const REC_TYPE: QType = QType::TXT;
2180
2181    const RLEN: u16 = 2;
2182
2183    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
2184    {
2185        if rlen <= Self::RLEN
2186        {
2187            internal_error!(CDnsErrorType::DnsResponse, "RecordTXT len expected: '{}' >, got: '{}'", Self::RLEN, rlen);
2188        }
2189        else if qtype != Self::REC_TYPE
2190        {
2191            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2192        }
2193
2194        let mut read_length = 0;
2195        
2196
2197        let dmod = ((rlen % 255) > 0) as u16;
2198        let cap = rlen / 255 + dmod;
2199
2200        let mut txt_datas = Vec::<String>::with_capacity(cap as usize);
2201    
2202        while read_length < rlen
2203        {
2204            let mut txt_data = Vec::new();
2205
2206            loop
2207            {
2208                let blk_size = pkt.read_u8().map_err(map_read_err)?;
2209
2210                read_length += blk_size as u16 + 1;
2211
2212                let mut new_txt = Vec::with_capacity(blk_size as usize);//vec![0_u8; blk_size as usize];//Vec::with_capacity(blk_size as usize);// vec![0_u8; blk_size as usize];
2213                unsafe { new_txt.set_len(blk_size as usize); }
2214
2215                pkt.read_exact(&mut new_txt).map_err(map_read_err)?;
2216
2217                txt_data.push(new_txt);
2218
2219                if blk_size < 255
2220                {
2221                    break;
2222                }
2223            }
2224
2225            if txt_data.is_empty() == true
2226            {
2227                internal_error!(
2228                    CDnsErrorType::DnsResponse, 
2229                    "unexpected EOF in TXT rec cur position: '{}', data_length: '{}', read: '{}'",
2230                    pkt.position(), rlen, read_length
2231                );
2232            }
2233
2234            let data = txt_data.concat();
2235
2236            txt_datas.push(
2237                String::from_utf8(data)
2238                    .map_err(|e|
2239                        internal_error_map!(CDnsErrorType::InternalError, "UTF-8 decode error, {}", e)
2240                    )?
2241                );
2242        }
2243
2244        return Ok(
2245            Self
2246            { 
2247                txt_strings: txt_datas.concat()
2248            }
2249        );
2250    }
2251
2252    fn wrap(self) -> DnsRdata 
2253    {
2254        return DnsRdata::TXT(self);
2255    }
2256}
2257
2258impl fmt::Display for RecordTXT
2259{
2260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2261    {
2262        write!(f, "{}   {}", Self::REC_TYPE, self.txt_strings)
2263    }
2264}
2265
2266#[derive(Clone, Debug, Eq, PartialEq)]
2267pub struct RecordURI
2268{
2269    /// the priority of the target host, lower value means more preferred.
2270    pub priority: u16,
2271
2272    /// A relative weight for records with the same priority, higher value 
2273    /// means higher chance of getting picked.
2274    pub weight: u16,
2275
2276    /// This field holds the URI of the target, enclosed in double-quote characters ('"'),
2277    /// where the URI is as specified in RFC 3986
2278    pub target: String,
2279}
2280
2281impl RecordReader for RecordURI
2282{
2283    const REC_TYPE: QType = QType::URI;
2284
2285    const RLEN: u16 = 4;
2286
2287    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
2288    {
2289        if rlen <= Self::RLEN
2290        {
2291            internal_error!(CDnsErrorType::DnsResponse, "RecordURI len expected: '{}' >, got: '{}'", Self::RLEN, rlen);
2292        }
2293        else if qtype != Self::REC_TYPE
2294        {
2295            internal_error!(CDnsErrorType::DnsResponse, "expexted '{}', got: '{}'", Self::REC_TYPE, qtype);
2296        }
2297
2298        return Ok(
2299            Self
2300            { 
2301                priority: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2302                weight: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2303                target: pkt2string_exact(pkt, rlen - 4)?,
2304            }
2305        );
2306    }
2307
2308    fn wrap(self) -> DnsRdata 
2309    {
2310        return DnsRdata::URI(self);
2311    }
2312}
2313
2314impl fmt::Display for RecordURI
2315{
2316    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2317    {
2318        write!(f, "{}   {} {} \"{}\"", Self::REC_TYPE, self.priority, self.weight, self.target)
2319    }
2320}
2321
2322// https://www.ietf.org/rfc/rfc4034.txt
2323
2324#[derive(Clone, Debug, Eq, PartialEq)]
2325pub struct RecordRRSIG
2326{
2327    type_cov: u16,
2328    alg: u8,
2329    labels: u8,
2330    orig_ttl: u32,
2331    sig_exp: u32,
2332    sig_inc: u32,
2333    keytag: u16,
2334    sig_name: String,
2335    key: Vec<u8>,
2336}
2337
2338impl RecordReader for RecordRRSIG
2339{
2340    const REC_TYPE: QType = QType::RRSIG;
2341
2342    const RLEN: u16 = 19;
2343
2344    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, _qtype: QType) -> CDnsResult<Self> 
2345    {
2346        let data = vec![0_u8; rlen as usize];
2347
2348        let pos = pkt.position();
2349
2350        let mut res = 
2351            Self
2352            {
2353                type_cov: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2354                alg: pkt.read_u8().map_err(map_read_err)?,
2355                labels: pkt.read_u8().map_err(map_read_err)?,
2356                orig_ttl: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2357                sig_exp: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2358                sig_inc: pkt.read_u32::<BigEndian>().map_err(map_read_err)?,
2359                keytag: pkt.read_u16::<BigEndian>().map_err(map_read_err)?,
2360                sig_name: name2str(pkt,None)?,
2361                key: Vec::new(),
2362            };
2363
2364        let left_rdlen = rlen - (pkt.position() - pos) as u16;
2365        res.key = pkt2vec(pkt, Some(left_rdlen))?;
2366
2367        return Ok(res);
2368    }
2369
2370    fn wrap(self) -> DnsRdata 
2371    {
2372        return DnsRdata::RRSIG(self);
2373    }
2374}
2375
2376impl fmt::Display for RecordRRSIG
2377{
2378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2379    {
2380        write!(f, "{}   {} {} {} {} {} {} {} {} {}", 
2381            Self::REC_TYPE, self.type_cov, self.alg, self.labels, self.orig_ttl,
2382            self.sig_exp, self.sig_inc, self.keytag, self.sig_name, 
2383            self.key.iter().map(|k| format!("{:02X}", k)).collect::<Vec<String>>().concat()
2384        )
2385    }
2386}
2387
2388#[derive(Clone, Debug, Eq, PartialEq)]
2389pub struct RecordOther
2390{
2391    // record type
2392    pub qtype: QType,
2393
2394    // raw data
2395    pub data: Vec<u8>
2396}
2397
2398impl RecordReader for RecordOther
2399{
2400    const REC_TYPE: QType = QType::ALL;
2401
2402    const RLEN: u16 = 0;
2403
2404    fn read(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self> 
2405    {
2406        let mut data = vec![0_u8; rlen as usize];
2407
2408        pkt.read_exact(&mut data).map_err(map_read_err)?;
2409
2410        return Ok(
2411            Self
2412            { 
2413                qtype: qtype,
2414                data: data,
2415            }
2416        );
2417    }
2418
2419    fn wrap(self) -> DnsRdata 
2420    {
2421        return DnsRdata::OTHER(self);
2422    }
2423}
2424
2425impl fmt::Display for RecordOther
2426{
2427    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2428    {
2429        write!(f, "{}   RAW:", self.qtype)?;
2430
2431        for d in self.data.iter()
2432        {
2433            write!(f, "{:X}", d)?;
2434        }
2435
2436        return Ok(());
2437    }
2438}
2439
2440pub(crate)
2441fn sanitize_str_unicode(st: &str) -> String
2442{
2443    let mut out = String::with_capacity(st.len());
2444
2445    for c in st.chars()
2446    {
2447        if c.is_alphanumeric() == true ||
2448            c.is_ascii_punctuation() == true ||
2449            c == ' '
2450        {
2451            out.push(c);
2452        }
2453        else
2454        {
2455            let mut buf = [0_u8; 4];
2456            c.encode_utf8(&mut buf);
2457
2458            let formatted: String = 
2459                buf[0..c.len_utf8()].into_iter()
2460                    .map(|c| format!("\\x{:02x}", c))
2461                    .collect();
2462
2463            out.push_str(&formatted);
2464        }
2465    }
2466
2467    return out;
2468}
2469
2470#[derive(Clone, Debug, Eq, PartialEq)]
2471pub enum DnsRdata
2472{
2473    None,
2474    A(RecordA),
2475    NS(RecordNS),
2476    CNAME(RecordCNAME),
2477    SOA(RecordSOA),
2478    PTR(RecordPTR),
2479    MX(RecordMX),
2480    TXT(RecordTXT),
2481    AAAA(RecordAAAA), 
2482    SRV(RecordSRV),
2483    URI(RecordURI),    
2484    RRSIG(RecordRRSIG),
2485    OTHER(RecordOther),
2486}
2487
2488impl fmt::Display for DnsRdata
2489{
2490    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
2491    {
2492        match self
2493        {
2494            Self::None => 
2495                write!(f, "No record"),
2496            Self::A(ip) => 
2497                write!(f, "{}", ip),
2498            Self::NS(ns) => 
2499                write!(f, "{}", ns),
2500            Self::AAAA(aaaa) => 
2501                write!(f, "{}", aaaa),
2502            Self::MX(mx) =>
2503                write!(f, "{}", mx),
2504            Self::CNAME(cname) => 
2505                write!(f, "{}", cname),
2506            Self::PTR(ptr) => 
2507                write!(f, "{}", ptr),
2508            Self::SOA(soa) => 
2509                write!(f, "{}", soa),
2510            Self::TXT(txt) => 
2511                write!(f, "{}", txt),
2512            Self::SRV(srv) => 
2513                write!(f, "{}", srv),
2514            Self::URI(uri) =>
2515                write!(f, "{}", uri),
2516            Self::RRSIG(rrsig) =>
2517                write!(f, "{}", rrsig),
2518            Self::OTHER(other) => 
2519                write!(f, "{}", other),
2520        }
2521    }
2522}
2523
2524impl Default for DnsRdata
2525{
2526    fn default() -> Self 
2527    {
2528        return Self::None;   
2529    }
2530}
2531
2532impl DnsRdata
2533{
2534    #[inline]
2535    pub 
2536    fn is_some(&self) -> bool
2537    {
2538        return *self != Self::None;
2539    }
2540}
2541
2542
2543impl DnsRdata
2544{
2545    /// Reads the RData from pkt and converts it into QType container
2546    /// 
2547    /// # Arguments
2548    /// 
2549    /// * `pkt` - a [Cursor] mutable reference to raw DNS reply data
2550    /// 
2551    /// * `rlen` - a length of RData section
2552    /// 
2553    /// * `qtype` - a [QType] reference to the response answer Qtype
2554    /// 
2555    /// # Returns
2556    /// 
2557    /// * [CDnsResult] with Self or error
2558    pub 
2559    fn convert(pkt: &mut Cursor<&[u8]>, rlen: u16, qtype: QType) -> CDnsResult<Self>
2560    {
2561        match qtype
2562        {
2563            RecordA::REC_TYPE => 
2564                return Ok(RecordA::wrap(RecordA::read(pkt, rlen, qtype)?)),
2565            RecordAAAA::REC_TYPE => 
2566                return Ok(RecordAAAA::wrap(RecordAAAA::read(pkt, rlen, qtype)?)),
2567            RecordPTR::REC_TYPE => 
2568                return Ok(RecordPTR::wrap(RecordPTR::read(pkt, rlen, qtype)?)),
2569            RecordMX::REC_TYPE =>
2570                return Ok(RecordMX::wrap(RecordMX::read(pkt, rlen, qtype)?)),
2571            RecordCNAME::REC_TYPE =>
2572                return Ok(RecordCNAME::wrap(RecordCNAME::read(pkt, rlen, qtype)?)),
2573            RecordSOA::REC_TYPE =>
2574                return Ok(RecordSOA::wrap(RecordSOA::read(pkt, rlen, qtype)?)),
2575            RecordSRV::REC_TYPE => 
2576                return Ok(RecordSRV::wrap(RecordSRV::read(pkt, rlen, qtype)?)),
2577            RecordTXT::REC_TYPE =>
2578                return Ok(RecordTXT::wrap(RecordTXT::read(pkt, rlen, qtype)?)),
2579            RecordURI::REC_TYPE =>
2580                return Ok(RecordURI::wrap(RecordURI::read(pkt, rlen, qtype)?)),
2581            RecordNS::REC_TYPE => 
2582                return Ok(RecordNS::wrap(RecordNS::read(pkt, rlen, qtype)?)),
2583            RecordRRSIG::REC_TYPE =>
2584                return Ok(RecordRRSIG::wrap(RecordRRSIG::read(pkt, rlen, qtype)?)),
2585            _ =>
2586                return Ok(RecordOther::wrap(RecordOther::read(pkt, rlen, qtype)?)),
2587        }
2588    }
2589
2590    pub 
2591    fn get_ip(&self) -> Option<IpAddr>
2592    {
2593        match self
2594        {
2595            Self::A(a) => return Some(IpAddr::V4(a.ip)),
2596            Self::AAAA(a) => return Some(IpAddr::V6(a.ip)),
2597            _ => return None
2598        }
2599    }
2600}
2601
2602#[cfg(test)]
2603mod tests
2604{
2605    use std::io::Cursor;
2606
2607    use crate::common::*;
2608
2609
2610
2611    #[test]
2612    fn test_pkt2name()
2613    {
2614        use std::time::Instant;
2615    
2616        fn prepare(d: &[u8]) -> Cursor<&[u8]>
2617        {
2618           // let vd = d.to_vec();
2619    
2620            return Cursor::new(d);
2621        }
2622    
2623        let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
2624    
2625        let mut cur1 = prepare(t1);
2626    
2627        let now = Instant::now();
2628        let r1 = pkt2name(&mut cur1);
2629        let elapsed = now.elapsed();
2630        println!("Elapsed: {:.2?}", elapsed);
2631    
2632        assert_eq!(r1.is_ok(), true);
2633        assert_eq!(r1.as_ref().unwrap(), t1);
2634    
2635        let t2 = 
2636        b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2637        \x30\x30\x03\x6e\x65\x74\x00";
2638    
2639        let mut cur2 = prepare(t2);
2640        let now = Instant::now();
2641        let r2 = pkt2name(&mut cur2);
2642        let elapsed = now.elapsed();
2643        println!("Elapsed: {:.2?}", elapsed);
2644    
2645        assert_eq!(r2.is_ok(), true);
2646        assert_eq!(r2.as_ref().unwrap(), t2);
2647    
2648        let t3 = 
2649        b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2650        \x30\x30\x03\x6e\x65\x74";
2651    
2652        let r3 = pkt2name(&mut prepare(t3));
2653    
2654        assert_eq!(r3.is_ok(), false);
2655    
2656        let t4 = 
2657        b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2658        \x30\x30\x03\x6e\x65\x74";
2659    
2660        let r4 = pkt2name(&mut prepare(t4));
2661    
2662        assert_eq!(r4.is_ok(), false);
2663    }
2664    
2665    #[test]
2666    fn test_qname2str()
2667    {
2668        use std::time::Instant;
2669    
2670        fn prepare(d: &[u8]) -> Cursor<&[u8]>
2671        {
2672            //let vd = d.to_vec();
2673    
2674            return Cursor::new(d);
2675        }
2676    
2677        let t1 = b"\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00";
2678    
2679        let mut cur1 = prepare(t1);
2680        let now = Instant::now();
2681        let r1 = name2str(&mut cur1, None);
2682        let elapsed = now.elapsed();
2683        println!("Elapsed: {:.2?}", elapsed);
2684    
2685        assert_eq!(r1.is_ok(), true);
2686        assert_eq!(r1.as_ref().unwrap(), "dns.google");
2687    
2688        let t2 = 
2689        b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2690        \x30\x30\x03\x6e\x65\x74\x00";
2691    
2692        let mut cur2 = prepare(t2);
2693    
2694        let now = Instant::now();
2695        let r2 = name2str(&mut cur2, None);
2696        let elapsed = now.elapsed();
2697        println!("Elapsed: {:.2?}", elapsed);
2698    
2699        assert_eq!(r2.is_ok(), true);
2700        assert_eq!(r2.as_ref().unwrap(), "mad07s09-in-x0e.1e100.net");
2701    
2702        let t3 = 
2703        b"\x0f\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2704        \x30\x30\x03\x6e\x65\x74";
2705    
2706        let r3 = name2str(&mut prepare(t3), None);
2707    
2708        assert_eq!(r3.is_ok(), false);
2709    
2710        let t4 = 
2711        b"\x10\x6d\x61\x64\x30\x37\x73\x30\x39\x2d\x69\x6e\x2d\x78\x30\x65\x05\x31\x65\x31\
2712        \x30\x30\x03\x6e\x65\x74";
2713    
2714        let r4 = name2str(&mut prepare(t4), None);
2715    
2716        assert_eq!(r4.is_ok(), false);
2717    }
2718    
2719    #[test]
2720    fn test_response_parser()
2721    {
2722        use std::time::Instant;
2723    
2724        let pkt = 
2725        b"\x15\xc8\x81\x80\x00\x01\x00\x01\x00\x00\x00\x02\x01\x38\x01\x38\
2726        \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
2727        \x61\x00\x00\x0c\x00\x01\xc0\x0c\x00\x0c\x00\x01\x00\x01\x35\xf0\
2728        \x00\x0c\x03\x64\x6e\x73\x06\x67\x6f\x6f\x67\x6c\x65\x00\xc0\x32\
2729        \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x08\x08\xc0\x32\
2730        \x00\x01\x00\x01\x00\x00\x00\xe8\x00\x04\x08\x08\x04\x04";
2731    
2732        let dummy = 
2733            DnsRequestHeader
2734            {
2735                header: DnsHeader {id: 0x15c8, ..Default::default()},
2736                payload: DnsRequestPayload
2737                    {
2738                        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(),
2739                        qtype: QType::PTR,
2740                        qclass: QClass::IN, 
2741                    }
2742            };
2743    
2744        let now = Instant::now();
2745        let ans = DnsRequestAnswer::parse(pkt.as_slice());
2746        let elapsed = now.elapsed();
2747        println!("Elapsed: {:.2?}", elapsed);
2748    
2749        assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2750        
2751        let ans = ans.unwrap();
2752    
2753        let verif = ans.verify(&dummy);
2754        assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2755    
2756        assert_eq!(ans.req_header.header.id, 0x15c8);
2757        assert_eq!(ans.req_header.header.ancount, 1);
2758        assert_eq!(ans.req_header.header.arcount, 2);
2759        assert_eq!(ans.req_header.header.nscount, 0);
2760        assert_eq!(ans.req_header.header.qdcount, 1);
2761    
2762        assert_eq!(ans.response[0].rdata, RecordPTR::wrap(RecordPTR { fqdn: "dns.google".to_string() }) );
2763        assert_eq!(ans.response[0].name, "8.8.8.8.in-addr.arpa".to_string());
2764        assert_eq!(ans.response[0].dtype, QType::PTR);
2765        assert_eq!(ans.response[0].class, QClass::IN);
2766        assert_eq!(ans.response[0].ttl, 79344);
2767        assert_eq!(ans.response[0].rdlength, 12);
2768    
2769        assert_eq!(ans.additional[0].rdata, RecordA::wrap(RecordA { ip: "8.8.8.8".parse().unwrap() }) );
2770        assert_eq!(ans.additional[0].name, "dns.google".to_string());
2771        assert_eq!(ans.additional[0].ttl, 232);
2772        assert_eq!(ans.additional[0].dtype, QType::A);
2773        assert_eq!(ans.additional[0].class, QClass::IN);
2774
2775        assert_eq!(ans.additional[1].rdata, RecordA::wrap(RecordA { ip: "8.8.4.4".parse().unwrap() }) );
2776        assert_eq!(ans.additional[1].name, "dns.google".to_string());
2777        assert_eq!(ans.additional[1].ttl, 232);
2778        assert_eq!(ans.additional[1].dtype, QType::A);
2779        assert_eq!(ans.additional[1].class, QClass::IN);
2780    }
2781    
2782    #[test]
2783    fn test_response2()
2784    {
2785        use std::time::Instant;
2786    
2787        let pkt = 
2788        b"\x4b\x38\x81\x80\x00\x01\x00\x05\x00\x00\x00\x00\x05\x67\x6d\x61\
2789        \x69\x6c\x03\x63\x6f\x6d\x00\x00\x0f\x00\x01\xc0\x0c\x00\x0f\x00\
2790        \x01\x00\x00\x0b\x55\x00\x1b\x00\x05\x0d\x67\x6d\x61\x69\x6c\x2d\
2791        \x73\x6d\x74\x70\x2d\x69\x6e\x01\x6c\x06\x67\x6f\x6f\x67\x6c\x65\
2792        \xc0\x12\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x0a\
2793        \x04\x61\x6c\x74\x31\xc0\x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\
2794        \x55\x00\x09\x00\x1e\x04\x61\x6c\x74\x33\xc0\x29\xc0\x0c\x00\x0f\
2795        \x00\x01\x00\x00\x0b\x55\x00\x09\x00\x14\x04\x61\x6c\x74\x32\xc0\
2796        \x29\xc0\x0c\x00\x0f\x00\x01\x00\x00\x0b\x55\x00\x09\x00\x28\x04\
2797        \x61\x6c\x74\x34\xc0\x29";
2798    
2799        let dummy = 
2800            DnsRequestHeader
2801            {
2802                header: DnsHeader {id: 0x4b38, ..Default::default()},
2803                payload: DnsRequestPayload
2804                    {
2805                        qname: b"\x05\x67\x6d\x61\x69\x6c\x03\x63\x6f\x6d\x00".to_vec(),
2806                        qtype: QType::MX,
2807                        qclass: QClass::IN, 
2808                    }
2809            };
2810    
2811        let now = Instant::now();
2812        let ans = DnsRequestAnswer::parse(pkt.as_slice());
2813        let elapsed = now.elapsed();
2814        println!("Elapsed: {:.2?}", elapsed);
2815    
2816        assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2817        let ans = ans.unwrap();
2818    
2819        let verif = ans.verify(&dummy);
2820        assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2821    
2822        assert_eq!(ans.req_header.header.id, 0x4b38);
2823        assert_eq!(ans.req_header.header.ancount, 5);
2824        assert_eq!(ans.req_header.header.arcount, 0);
2825        assert_eq!(ans.req_header.header.nscount, 0);
2826        assert_eq!(ans.req_header.header.qdcount, 1);
2827    
2828        assert_eq!(ans.response[0].rdata, RecordMX::wrap(RecordMX { preference: 5, exchange: "gmail-smtp-in.l.google.com".to_string() }) );
2829        assert_eq!(ans.response[0].name, "gmail.com".to_string());
2830        assert_eq!(ans.response[0].dtype, QType::MX);
2831        assert_eq!(ans.response[0].class, QClass::IN);
2832        assert_eq!(ans.response[0].ttl, 2901);
2833        assert_eq!(ans.response[0].rdlength, 27);
2834    
2835        assert_eq!(ans.response[1].rdata, RecordMX::wrap(RecordMX { preference: 10, exchange: "alt1.gmail-smtp-in.l.google.com".to_string() }) );
2836        assert_eq!(ans.response[1].name, "gmail.com".to_string());
2837        assert_eq!(ans.response[1].dtype, QType::MX);
2838        assert_eq!(ans.response[1].class, QClass::IN);
2839        assert_eq!(ans.response[1].ttl, 2901);
2840        assert_eq!(ans.response[1].rdlength, 9);
2841    
2842        assert_eq!(ans.response[2].rdata, RecordMX::wrap(RecordMX { preference: 30, exchange: "alt3.gmail-smtp-in.l.google.com".to_string() }) );
2843        assert_eq!(ans.response[2].name, "gmail.com".to_string());
2844        assert_eq!(ans.response[2].dtype, QType::MX);
2845        assert_eq!(ans.response[2].class, QClass::IN);
2846        assert_eq!(ans.response[2].ttl, 2901);
2847        assert_eq!(ans.response[2].rdlength, 9);
2848    
2849        assert_eq!(ans.response[3].rdata, RecordMX::wrap(RecordMX { preference: 20, exchange: "alt2.gmail-smtp-in.l.google.com".to_string() }) );
2850        assert_eq!(ans.response[3].name, "gmail.com".to_string());
2851        assert_eq!(ans.response[3].dtype, QType::MX);
2852        assert_eq!(ans.response[3].class, QClass::IN);
2853        assert_eq!(ans.response[3].ttl, 2901);
2854        assert_eq!(ans.response[3].rdlength, 9);
2855    
2856        assert_eq!(ans.response[4].rdata, RecordMX::wrap(RecordMX { preference: 40, exchange: "alt4.gmail-smtp-in.l.google.com".to_string() }) );
2857        assert_eq!(ans.response[4].name, "gmail.com".to_string());
2858        assert_eq!(ans.response[4].dtype, QType::MX);
2859        assert_eq!(ans.response[4].class, QClass::IN);
2860        assert_eq!(ans.response[4].ttl, 2901);
2861        assert_eq!(ans.response[4].rdlength, 9);
2862    }
2863    
2864    
2865    #[test]
2866    fn test_response3()
2867    {
2868        use std::time::Instant;
2869    
2870        let pkt = 
2871    b"\xd0\x79\x81\x80\x00\x01\x00\x17\x00\x00\x00\x00\x06\x72\
2872    \x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x00\xff\x00\x01\xc0\x0c\x00\
2873    \x06\x00\x01\x00\x00\x0e\x10\x00\x30\x04\x6e\x73\x32\x31\x07\x63\
2874    \x6c\x6f\x75\x64\x6e\x73\x03\x6e\x65\x74\x00\x07\x73\x75\x70\x70\
2875    \x6f\x72\x74\xc0\x2c\x78\x77\xe2\xf1\x00\x00\x1c\x20\x00\x00\x07\
2876    \x08\x00\x12\x75\x00\x00\x00\x0e\x10\xc0\x0c\x00\x2e\x00\x01\x00\
2877    \x00\x0e\x10\x00\x5d\x00\x06\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
2878    \x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
2879    \x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\xa9\xa2\x2a\x08\x3c\x78\xb9\
2880    \xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\x22\x96\x45\x59\x36\x1f\x69\
2881    \x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\x11\x1a\x72\x00\x56\x89\x26\
2882    \x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\x68\x75\x05\x3d\x90\xed\x1e\
2883    \x0f\xfc\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x02\xc0\x27\
2884    \xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\
2885    \x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\
2886    \x04\x6e\x73\x32\x33\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\
2887    \x10\x00\x08\x05\x70\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x02\x00\
2888    \x01\x00\x00\x0e\x10\x00\x08\x05\x70\x6e\x73\x32\x34\xc0\x2c\xc0\
2889    \x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x07\x04\x6e\x73\x32\x34\
2890    \xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\x00\x08\x05\x70\
2891    \x6e\x73\x32\x31\xc0\x2c\xc0\x0c\x00\x02\x00\x01\x00\x00\x0e\x10\
2892    \x00\x07\x04\x6e\x73\x32\x32\xc0\x2c\xc0\x0c\x00\x2e\x00\x01\x00\
2893    \x00\x0e\x10\x00\x5d\x00\x02\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\
2894    \x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\
2895    \x6b\x00\xd1\xc5\x6c\xf1\xfb\xd0\x75\xf1\x38\x20\x28\x80\x4c\xe0\
2896    \x59\xa5\xa8\xab\x84\x79\xd8\x37\x48\xa7\xa5\x3f\x08\x9b\x4c\xca\
2897    \x40\x2b\xcb\x2c\xda\xcc\xc2\x18\xad\x07\x9e\xf8\x4e\x17\x8d\xb1\
2898    \x2b\x2d\xa2\xa6\x17\xdb\x55\x30\xbc\xa2\xb9\xa0\x01\x71\x01\xe5\
2899    \xdc\x4f\xc0\x0c\x00\x01\x00\x01\x00\x00\x0e\x10\x00\x04\xd9\x14\
2900    \x70\xd0\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x01\
2901    \x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\
2902    \x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xf8\x57\x68\xf0\xad\
2903    \x9e\xfb\x3a\x0f\x66\xbd\xcc\x48\xe7\x29\x0a\xf4\xd8\xf6\xbe\xbc\
2904    \x04\x76\x02\x27\x64\xf2\xc9\x42\x6d\x75\x54\x83\x0a\x11\xda\x0a\
2905    \x02\x6b\x8c\xf1\x65\xc4\x21\x44\xea\x89\x09\x01\xc8\xa1\xe2\x11\
2906    \x8f\xed\x67\x39\x69\x33\xdd\x97\x22\x1a\xd3\xc0\x0c\x00\x0f\x00\
2907    \x01\x00\x00\x0e\x10\x00\x11\x00\x0a\x04\x6d\x61\x69\x6c\x04\x6e\
2908    \x69\x78\x64\x03\x6f\x72\x67\x00\xc0\x0c\x00\x2e\x00\x01\x00\x00\
2909    \x0e\x10\x00\x5d\x00\x0f\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\
2910    \x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\
2911    \x00\xd4\xdd\x07\xd9\xb6\xb2\xba\x57\xa9\x1d\x3b\xaa\x6c\x55\xc4\
2912    \x3d\x73\x79\xea\x74\xfe\xd7\x23\x0c\xb4\xab\x8f\x4b\x1f\xd9\x8a\
2913    \xb2\x4a\x5c\xad\x3e\x8e\x4a\x85\xbb\xbd\x75\xf2\x47\x2c\xa8\x89\
2914    \x21\x75\x89\xb1\x12\xc4\xd2\xf7\x40\x06\x52\x57\x83\x8a\xaa\x7b\
2915    \x75\xc0\x0c\x00\x10\x00\x01\x00\x00\x0e\x10\x00\x34\x33\x76\x3d\
2916    \x73\x70\x66\x31\x20\x2b\x6d\x78\x20\x2b\x61\x3a\x6d\x61\x69\x6c\
2917    \x2e\x6e\x69\x78\x64\x2e\x6f\x72\x67\x20\x69\x70\x34\x3a\x32\x31\
2918    \x37\x2e\x32\x30\x2e\x31\x31\x32\x2e\x32\x30\x38\x20\x2d\x61\x6c\
2919    \x6c\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\x10\x0d\
2920    \x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\
2921    \x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xd1\x6c\xd1\xf4\x3b\xe0\
2922    \x44\xba\xfe\xe9\xdb\x82\xbd\x89\x5f\xa1\x07\x72\xdd\x47\xad\x4e\
2923    \x91\xd5\xc3\xfe\x3e\x39\x74\xdb\x50\x50\x19\x6c\x3f\x6c\xb7\xa8\
2924    \x01\x03\x6a\xf5\xa7\xf3\x9b\xf7\x76\xd4\xff\xa3\xd5\x43\xfc\xec\
2925    \xa9\x89\x24\xf8\xd2\xb6\x76\xd4\x20\xbc\xc0\x0c\x00\x30\x00\x01\
2926    \x00\x00\x0e\x10\x00\x44\x01\x01\x03\x0d\xf3\x87\xe2\x7c\x2b\x82\
2927    \x40\x72\x7c\xfd\xc9\x2b\xe8\x22\xd6\xa9\x40\xc0\xab\x03\x25\x7d\
2928    \x92\xae\xf3\x17\x71\x82\x67\xc6\xcd\xb6\x4b\x11\x62\xc6\xfa\x06\
2929    \xec\x4c\x9f\xd9\xe6\xaf\x5c\x3d\xe4\x32\xde\x11\x1b\x09\x13\xe3\
2930    \xd0\xba\x66\xd1\xbc\x32\xdb\x13\xd7\x1d\xc0\x0c\x00\x30\x00\x01\
2931    \x00\x00\x0e\x10\x00\x44\x01\x00\x03\x0d\xd4\x43\xde\x96\xe5\xea\
2932    \x0a\xf9\x5d\x4f\x72\x88\x9c\xd9\x9c\xf7\xa6\x3f\x12\xd7\xf3\xea\
2933    \x8a\x6b\x44\x4c\x79\x23\x81\x94\x43\xa3\xbd\x9e\xb8\xde\xfe\x8c\
2934    \xe6\x21\xe3\x8a\x71\xba\x05\xd2\x0f\x98\x5b\xfc\x7e\x72\x8c\xe9\
2935    \x9a\xc0\x49\x00\xca\xd5\x62\x93\x7f\x03\xc0\x0c\x00\x2e\x00\x01\
2936    \x00\x00\x0e\x10\x00\x5d\x00\x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\
2937    \xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\
2938    \x73\x6b\x00\xc0\x93\x23\x1d\xcb\x1e\x79\xfe\x7c\x40\x3e\xd4\x33\
2939    \x5f\xed\x69\x8e\x7d\x75\xff\x73\x6b\x24\x71\x8f\x50\xf8\xe0\x49\
2940    \xce\x5f\x62\x0c\x8c\xb3\x06\x8f\x26\xea\x20\xa0\xe3\x71\xe0\xa1\
2941    \x8b\xe0\x4a\x2f\x1d\x4b\x79\x2c\x52\x6b\xa4\x43\xb5\x70\x27\x01\
2942    \xb0\x63\x47\xc0\x0c\x00\x2e\x00\x01\x00\x00\x0e\x10\x00\x5d\x00\
2943    \x30\x0d\x02\x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x97\
2944    \x18\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x41\x87\x75\x1d\
2945    \x30\x44\xd1\x94\x40\xd4\xe6\x40\x98\x62\x94\x53\xad\x53\xe2\xed\
2946    \xc0\xc0\xb7\xa3\x20\x15\xae\x59\xbb\x97\x45\xfb\x0e\xbf\x70\xf3\
2947    \xb1\x24\x79\xe8\x85\x6c\x2a\x66\x10\xb6\x75\x99\x7b\x77\x78\x65\
2948    \xa6\x67\x8d\x59\xa6\x14\xf7\xe6\x77\xab\x53\x9c\xc0\x0c\x00\x33\
2949    \x00\x01\x00\x00\x02\x58\x00\x0d\x01\x00\x00\x0a\x08\x90\xc7\xf1\
2950    \x74\x0b\x0c\xfb\x34\xc0\x0c\x00\x2e\x00\x01\x00\x00\x02\x58\x00\
2951    \x5d\x00\x33\x0d\x02\x00\x00\x00\x00\x61\xf2\xaf\x39\x61\xcb\x22\
2952    \x39\x28\xeb\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\xc4\x4d\
2953    \x00\x48\x9c\x86\x49\xac\x8d\x03\x28\x23\xac\xec\xf5\x5b\xb6\xe5\
2954    \x2f\xf6\xae\xaa\x01\x5a\x66\x52\xf7\x43\xc3\xb1\xe5\xef\xe5\xbf\
2955    \x5f\x71\x5d\xa1\x57\x64\x66\x5e\xa1\x6f\x96\xa8\xcd\x48\x85\xe4\
2956    \x20\xe2\xfb\xb0\xc1\x00\x47\x72\xc8\x72\x98\xc7\x41\xd9";
2957        
2958        let dummy = 
2959            DnsRequestHeader
2960            {
2961                header: DnsHeader {id: 0xd079, ..Default::default()},
2962                payload: DnsRequestPayload
2963                    {
2964                        qname: b"\x06\x72\x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00".to_vec(),
2965                        qtype: QType::ALL,
2966                        qclass: QClass::IN, 
2967                    }
2968            };
2969    
2970        let now = Instant::now();
2971        let ans = DnsRequestAnswer::parse(pkt.as_slice());
2972        let elapsed = now.elapsed();
2973        println!("Elapsed: {:.2?}", elapsed);
2974    
2975        assert_eq!(ans.is_ok(), true, "{}", ans.err().unwrap());
2976        let ans = ans.unwrap();
2977    
2978        let verif = ans.verify(&dummy);
2979        assert_eq!(verif.is_ok(), true, "{}", verif.err().unwrap());
2980    
2981        assert_eq!(ans.req_header.header.id, 0xd079);
2982        assert_eq!(ans.req_header.header.ancount, 23);
2983        assert_eq!(ans.req_header.header.arcount, 0);
2984        assert_eq!(ans.req_header.header.nscount, 0);
2985        assert_eq!(ans.req_header.header.qdcount, 1);
2986    
2987        let ansord = &ans.response[0];
2988        assert_eq!(
2989            ansord.rdata, 
2990                RecordSOA::wrap(
2991                    RecordSOA
2992                    { 
2993                        pnm: "ns21.cloudns.net".to_string(), 
2994                        ram: "support.cloudns.net".to_string(), 
2995                        serial: 2021122801,  
2996                        interv_refr: 7200,
2997                        interv_retry: 1800,
2998                        expire_limit: 1209600,
2999                        min_ttl: 3600
3000                    }
3001            )
3002        );
3003        assert_eq!(ansord.name, "relkom.sk".to_string());
3004        assert_eq!(ansord.dtype, QType::SOA);
3005        assert_eq!(ansord.class, QClass::IN);
3006        assert_eq!(ansord.ttl, 3600);
3007        assert_eq!(ansord.rdlength, 48);
3008    
3009        let a1 = 
3010    b"\x00\x06\x0d\x02\
3011    \x00\x00\x0e\x10\x61\xf2\xaf\x39\x61\xcb\x22\x39\x28\xeb\x06\x72\
3012    \x65\x6c\x6b\x6f\x6d\x02\x73\x6b\x00\x2f\x79\xed\x73\xd0\x75\xc8\
3013    \xa9\xa2\x2a\x08\x3c\x78\xb9\xfb\x43\xc5\x8e\x62\x4c\xbc\x36\xeb\
3014    \x22\x96\x45\x59\x36\x1f\x69\x3a\x7a\x5e\x67\xd0\x54\x1e\xf0\xf2\
3015    \x11\x1a\x72\x00\x56\x89\x26\x79\xf4\x06\x1a\x0c\x59\x41\x32\x60\
3016    \x68\x75\x05\x3d\x90\xed\x1e\x0f\xfc";
3017        let mut a1curs = Cursor::new(a1.as_slice());
3018        let a1len = a1.len();
3019
3020        let ansord = &ans.response[1];
3021        assert_eq!(ansord.rdata, RecordRRSIG::wrap( RecordRRSIG::read(&mut a1curs, a1len as u16, QType::RRSIG).unwrap() ));
3022        assert_eq!(ansord.name, "relkom.sk".to_string());
3023        assert_eq!(ansord.dtype, QType::RRSIG);
3024        assert_eq!(ansord.class, QClass::IN);
3025        assert_eq!(ansord.ttl, 3600);
3026        assert_eq!(ansord.rdlength, a1len as u16);
3027    
3028        let ansord = &ans.response[2];
3029        assert_eq!(ansord.rdata, RecordNS::wrap( RecordNS{ fqdn: "ns21.cloudns.net".to_string() }));
3030        assert_eq!(ansord.name, "relkom.sk".to_string());
3031        assert_eq!(ansord.dtype, QType::NS);
3032        assert_eq!(ansord.class, QClass::IN);
3033        assert_eq!(ansord.ttl, 3600);
3034        assert_eq!(ansord.rdlength, 2);
3035    }
3036    
3037    
3038    #[test]
3039    fn test_request()
3040    {
3041        use std::time::Instant;
3042        use std::net::IpAddr;
3043    
3044        let ipp = IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8));
3045        let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3046    
3047        let now = Instant::now();
3048    
3049        let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3050    
3051        let elapsed = now.elapsed();
3052        println!("Elapsed: {:.2?}", elapsed);
3053    
3054        assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3055    
3056        let pkt = req.unwrap().to_bytes(false);
3057        assert_eq!(pkt.is_ok(), true);
3058        let pkt = pkt.unwrap();
3059    
3060        let ctrl = 
3061        b"\x15\xc8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x38\x01\x38\
3062        \x01\x38\x01\x38\x07\x69\x6e\x2d\x61\x64\x64\x72\x04\x61\x72\x70\
3063        \x61\x00\x00\x0c\x00\x01";
3064    
3065        assert_eq!(&pkt[2..], &ctrl[2..]);
3066    }
3067    
3068    #[test]
3069    fn test_request_1()
3070    {
3071        use std::time::Instant;
3072        use std::net::IpAddr;
3073    
3074        let ipp = IpAddr::V4("100.150.111.80".parse().unwrap());
3075        let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3076    
3077        let now = Instant::now();
3078    
3079        let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3080    
3081        let elapsed = now.elapsed();
3082        println!("Elapsed: {:.2?}", elapsed);
3083    
3084        assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3085    
3086        let pkt = req.unwrap().to_bytes(false);
3087        assert_eq!(pkt.is_ok(), true);
3088        let pkt = pkt.unwrap();
3089    
3090        let ctrl = 
3091        b"\x74\xa1\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x38\x30\x03\
3092        \x31\x31\x31\x03\x31\x35\x30\x03\x31\x30\x30\x07\x69\x6e\x2d\x61\
3093        \x64\x64\x72\x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
3094        
3095        assert_eq!(&pkt[2..], &ctrl[2..]);
3096    }
3097    
3098    #[test]
3099    fn test_request6()
3100    {
3101        use std::time::Instant;
3102        use std::net::IpAddr;
3103        
3104        let ipp =  IpAddr::V6("2a00:1450:4003:802::200e".parse().unwrap());
3105        let qdnsreq = QDnsReq::new_into(&ipp, QType::PTR);
3106    
3107        let now = Instant::now();
3108    
3109        let req = DnsRequestHeader::construct_lookup(&qdnsreq);
3110    
3111        let elapsed = now.elapsed();
3112        println!("Elapsed: {:.2?}", elapsed);
3113    
3114        assert_eq!(req.is_ok(), true, "{}", req.err().unwrap());
3115    
3116        let pkt = req.unwrap().to_bytes(false);
3117        assert_eq!(pkt.is_ok(), true);
3118        let pkt = pkt.unwrap();
3119    
3120        let ctrl = 
3121        b"\xee\xec\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x65\x01\x30\
3122        \x01\x30\x01\x32\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\
3123        \x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x30\x01\x32\x01\x30\
3124        \x01\x38\x01\x30\x01\x33\x01\x30\x01\x30\x01\x34\x01\x30\x01\x35\
3125        \x01\x34\x01\x31\x01\x30\x01\x30\x01\x61\x01\x32\x03\x69\x70\x36\
3126        \x04\x61\x72\x70\x61\x00\x00\x0c\x00\x01";
3127    
3128        assert_eq!(&pkt[2..], &ctrl[2..]);
3129    }
3130    
3131    
3132}