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