domain/rdata/
dnssec.rs

1//! Record data from [RFC 4034]: DS, DNSKEY, RRSIG, and NSEC records.
2//!
3//! This RFC defines the record types for DNSSEC.
4//!
5//! [RFC 4034]: https://tools.ietf.org/html/rfc4034
6
7use crate::base::cmp::CanonicalOrd;
8use crate::base::iana::{DigestAlg, Rtype, SecAlg};
9use crate::base::name::{FlattenInto, ParsedDname, ToDname};
10use crate::base::rdata::{
11    ComposeRecordData, LongRecordData, ParseRecordData, RecordData,
12};
13use crate::base::Ttl;
14use crate::base::scan::{Scan, Scanner, ScannerError};
15use crate::base::serial::Serial;
16use crate::base::wire::{Compose, Composer, FormError, Parse, ParseError};
17use crate::utils::{base16, base64};
18use core::cmp::Ordering;
19use core::convert::TryInto;
20use core::{fmt, hash, ptr};
21use octseq::builder::{
22    EmptyBuilder, FreezeBuilder, FromBuilder, OctetsBuilder, Truncate,
23};
24use octseq::octets::{Octets, OctetsFrom, OctetsInto};
25use octseq::parse::Parser;
26#[cfg(feature = "serde")]
27use octseq::serde::{DeserializeOctets, SerializeOctets};
28#[cfg(feature = "std")]
29use std::vec::Vec;
30
31//------------ Dnskey --------------------------------------------------------
32
33#[derive(Clone)]
34#[cfg_attr(
35    feature = "serde",
36    derive(serde::Serialize, serde::Deserialize),
37    serde(bound(
38        serialize = "
39            Octs: octseq::serde::SerializeOctets + AsRef<[u8]>
40        ",
41        deserialize = "
42            Octs: FromBuilder + octseq::serde::DeserializeOctets<'de>,
43            <Octs as FromBuilder>::Builder:
44                OctetsBuilder + EmptyBuilder,
45        ",
46    ))
47)]
48pub struct Dnskey<Octs> {
49    flags: u16,
50    protocol: u8,
51    algorithm: SecAlg,
52    #[cfg_attr(
53        feature = "serde",
54        serde(with = "crate::utils::base64::serde")
55    )]
56    public_key: Octs,
57}
58
59impl<Octs> Dnskey<Octs> {
60    pub fn new(
61        flags: u16,
62        protocol: u8,
63        algorithm: SecAlg,
64        public_key: Octs,
65    ) -> Result<Self, LongRecordData>
66    where
67        Octs: AsRef<[u8]>,
68    {
69        LongRecordData::check_len(
70            usize::from(
71                u16::COMPOSE_LEN + u8::COMPOSE_LEN + SecAlg::COMPOSE_LEN,
72            )
73            .checked_add(public_key.as_ref().len())
74            .expect("long key"),
75        )?;
76        Ok(Dnskey {
77            flags,
78            protocol,
79            algorithm,
80            public_key,
81        })
82    }
83
84    /// Creates new DNSKEY record data without checking.
85    ///
86    /// # Safety
87    ///
88    /// The caller needs to ensure that wire format representation of the
89    /// record data is at most 65,535 octets long.
90    pub unsafe fn new_unchecked(
91        flags: u16,
92        protocol: u8,
93        algorithm: SecAlg,
94        public_key: Octs,
95    ) -> Self {
96        Dnskey {
97            flags,
98            protocol,
99            algorithm,
100            public_key,
101        }
102    }
103
104    pub fn flags(&self) -> u16 {
105        self.flags
106    }
107
108    pub fn protocol(&self) -> u8 {
109        self.protocol
110    }
111
112    pub fn algorithm(&self) -> SecAlg {
113        self.algorithm
114    }
115
116    pub fn public_key(&self) -> &Octs {
117        &self.public_key
118    }
119
120    pub fn into_public_key(self) -> Octs {
121        self.public_key
122    }
123
124    pub fn convert<Other: From<Octs>>(self) -> Dnskey<Other> {
125        Dnskey {
126            flags: self.flags,
127            protocol: self.protocol,
128            algorithm: self.algorithm,
129            public_key: self.public_key.into(),
130        }
131    }
132
133    /// Returns whether the Revoke flag is set.
134    ///
135    /// See [RFC 5011, Section 3].
136    ///
137    /// [RFC 5011, Section 3]: https://tools.ietf.org/html/rfc5011#section-3
138    pub fn is_revoked(&self) -> bool {
139        self.flags() & 0b0000_0000_1000_0000 != 0
140    }
141
142    /// Returns whether the the Secure Entry Point (SEP) flag is set.
143    ///
144    /// See [RFC 4034, Section 2.1.1]:
145    ///
146    /// > This flag is only intended to be a hint to zone signing or
147    /// > debugging software as to the intended use of this DNSKEY record;
148    /// > validators MUST NOT alter their behavior during the signature
149    /// > validation process in any way based on the setting of this bit.
150    ///
151    /// [RFC 4034, Section 2.1.1]: https://tools.ietf.org/html/rfc4034#section-2.1.1
152    pub fn is_secure_entry_point(&self) -> bool {
153        self.flags() & 0b0000_0000_0000_0001 != 0
154    }
155
156    /// Returns whether the Zone Key flag is set.
157    ///
158    /// If the flag is not set, the key MUST NOT be used to verify RRSIGs that
159    /// cover RRSETs. See [RFC 4034, Section 2.1.1].
160    ///
161    /// [RFC 4034, Section 2.1.1]: https://tools.ietf.org/html/rfc4034#section-2.1.1
162    pub fn is_zsk(&self) -> bool {
163        self.flags() & 0b0000_0001_0000_0000 != 0
164    }
165
166    /// Returns the key tag for this DNSKEY data.
167    #[allow(clippy::while_let_loop)] // I find this clearer with a loop.
168    pub fn key_tag(&self) -> u16
169    where
170        Octs: AsRef<[u8]>,
171    {
172        if self.algorithm == SecAlg::RsaMd5 {
173            // The key tag is third-to-last and second-to-last octets of the
174            // key as a big-endian u16. If we don’t have enough octets in the
175            // key, we return 0.
176            let len = self.public_key.as_ref().len();
177            if len > 2 {
178                u16::from_be_bytes(
179                    self.public_key.as_ref()[len - 3..len - 1]
180                        .try_into()
181                        .unwrap(),
182                )
183            } else {
184                0
185            }
186        } else {
187            // Treat record data as a octet sequence. Add octets at odd
188            // indexes as they are, add octets at even indexes shifted left
189            // by 8 bits.
190            let mut res = u32::from(self.flags);
191            res += u32::from(self.protocol) << 8;
192            res += u32::from(self.algorithm.to_int());
193            let mut iter = self.public_key().as_ref().iter();
194            loop {
195                match iter.next() {
196                    Some(&x) => res += u32::from(x) << 8,
197                    None => break,
198                }
199                match iter.next() {
200                    Some(&x) => res += u32::from(x),
201                    None => break,
202                }
203            }
204            res += (res >> 16) & 0xFFFF;
205            (res & 0xFFFF) as u16
206        }
207    }
208
209    pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
210        self,
211    ) -> Result<Dnskey<Target>, Target::Error> {
212        Ok(unsafe {
213            Dnskey::new_unchecked(
214                self.flags,
215                self.protocol,
216                self.algorithm,
217                self.public_key.try_octets_into()?,
218            )
219        })
220    }
221
222    pub(super) fn flatten<Target: OctetsFrom<Octs>>(
223        self,
224    ) -> Result<Dnskey<Target>, Target::Error> {
225        self.convert_octets()
226    }
227
228    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
229        parser: &mut Parser<'a, Src>,
230    ) -> Result<Self, ParseError> {
231        let len = match parser.remaining().checked_sub(4) {
232            Some(len) => len,
233            None => return Err(ParseError::ShortInput),
234        };
235        Ok(unsafe {
236            Self::new_unchecked(
237                u16::parse(parser)?,
238                u8::parse(parser)?,
239                SecAlg::parse(parser)?,
240                parser.parse_octets(len)?,
241            )
242        })
243    }
244
245    pub fn scan<S: Scanner<Octets = Octs>>(
246        scanner: &mut S,
247    ) -> Result<Self, S::Error>
248    where
249        Octs: AsRef<[u8]>,
250    {
251        Self::new(
252            u16::scan(scanner)?,
253            u8::scan(scanner)?,
254            SecAlg::scan(scanner)?,
255            scanner.convert_entry(base64::SymbolConverter::new())?,
256        )
257        .map_err(|err| S::Error::custom(err.as_str()))
258    }
259}
260
261//--- OctetsFrom
262
263impl<Octs, SrcOcts> OctetsFrom<Dnskey<SrcOcts>> for Dnskey<Octs>
264where
265    Octs: OctetsFrom<SrcOcts>,
266{
267    type Error = Octs::Error;
268
269    fn try_octets_from(source: Dnskey<SrcOcts>) -> Result<Self, Self::Error> {
270        Ok(unsafe {
271            Dnskey::new_unchecked(
272                source.flags,
273                source.protocol,
274                source.algorithm,
275                Octs::try_octets_from(source.public_key)?,
276            )
277        })
278    }
279}
280
281//--- PartialEq and Eq
282
283impl<Octs, Other> PartialEq<Dnskey<Other>> for Dnskey<Octs>
284where
285    Octs: AsRef<[u8]>,
286    Other: AsRef<[u8]>,
287{
288    fn eq(&self, other: &Dnskey<Other>) -> bool {
289        self.flags == other.flags
290            && self.protocol == other.protocol
291            && self.algorithm == other.algorithm
292            && self.public_key.as_ref() == other.public_key.as_ref()
293    }
294}
295
296impl<Octs: AsRef<[u8]>> Eq for Dnskey<Octs> {}
297
298//--- PartialOrd, CanonicalOrd, and Ord
299
300impl<Octs, Other> PartialOrd<Dnskey<Other>> for Dnskey<Octs>
301where
302    Octs: AsRef<[u8]>,
303    Other: AsRef<[u8]>,
304{
305    fn partial_cmp(&self, other: &Dnskey<Other>) -> Option<Ordering> {
306        Some(self.canonical_cmp(other))
307    }
308}
309
310impl<Octs, Other> CanonicalOrd<Dnskey<Other>> for Dnskey<Octs>
311where
312    Octs: AsRef<[u8]>,
313    Other: AsRef<[u8]>,
314{
315    fn canonical_cmp(&self, other: &Dnskey<Other>) -> Ordering {
316        match self.flags.cmp(&other.flags) {
317            Ordering::Equal => {}
318            other => return other,
319        }
320        match self.protocol.cmp(&other.protocol) {
321            Ordering::Equal => {}
322            other => return other,
323        }
324        match self.algorithm.cmp(&other.algorithm) {
325            Ordering::Equal => {}
326            other => return other,
327        }
328        self.public_key.as_ref().cmp(other.public_key.as_ref())
329    }
330}
331
332impl<Octs: AsRef<[u8]>> Ord for Dnskey<Octs> {
333    fn cmp(&self, other: &Self) -> Ordering {
334        self.canonical_cmp(other)
335    }
336}
337
338//--- Hash
339
340impl<Octs: AsRef<[u8]>> hash::Hash for Dnskey<Octs> {
341    fn hash<H: hash::Hasher>(&self, state: &mut H) {
342        self.flags.hash(state);
343        self.protocol.hash(state);
344        self.algorithm.hash(state);
345        self.public_key.as_ref().hash(state);
346    }
347}
348
349//--- RecordData, ParseRecordData, ComposeRecordData
350
351impl<Octs> RecordData for Dnskey<Octs> {
352    fn rtype(&self) -> Rtype {
353        Rtype::Dnskey
354    }
355}
356
357impl<'a, Octs> ParseRecordData<'a, Octs> for Dnskey<Octs::Range<'a>>
358where
359    Octs: Octets + ?Sized,
360{
361    fn parse_rdata(
362        rtype: Rtype,
363        parser: &mut Parser<'a, Octs>,
364    ) -> Result<Option<Self>, ParseError> {
365        if rtype == Rtype::Dnskey {
366            Self::parse(parser).map(Some)
367        } else {
368            Ok(None)
369        }
370    }
371}
372
373impl<Octs: AsRef<[u8]>> ComposeRecordData for Dnskey<Octs> {
374    fn rdlen(&self, _compress: bool) -> Option<u16> {
375        Some(
376            u16::try_from(self.public_key.as_ref().len())
377                .expect("long key")
378                .checked_add(
379                    u16::COMPOSE_LEN + u8::COMPOSE_LEN + SecAlg::COMPOSE_LEN,
380                )
381                .expect("long key"),
382        )
383    }
384
385    fn compose_rdata<Target: Composer + ?Sized>(
386        &self,
387        target: &mut Target,
388    ) -> Result<(), Target::AppendError> {
389        self.flags.compose(target)?;
390        self.protocol.compose(target)?;
391        self.algorithm.compose(target)?;
392        target.append_slice(self.public_key.as_ref())
393    }
394
395    fn compose_canonical_rdata<Target: Composer + ?Sized>(
396        &self,
397        target: &mut Target,
398    ) -> Result<(), Target::AppendError> {
399        self.compose_rdata(target)
400    }
401}
402
403//--- Display
404
405impl<Octs: AsRef<[u8]>> fmt::Display for Dnskey<Octs> {
406    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
407        write!(f, "{} {} {} ", self.flags, self.protocol, self.algorithm)?;
408        base64::display(&self.public_key, f)
409    }
410}
411
412//--- Debug
413
414impl<Octs: AsRef<[u8]>> fmt::Debug for Dnskey<Octs> {
415    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416        f.debug_struct("Dnskey")
417            .field("flags", &self.flags)
418            .field("protocol", &self.protocol)
419            .field("algorithm", &self.algorithm)
420            .field("public_key", &self.public_key.as_ref())
421            .finish()
422    }
423}
424
425//------------ ProtoRrsig ----------------------------------------------------
426
427/// The RRSIG RDATA to be included when creating the signature.
428#[derive(Clone)]
429pub struct ProtoRrsig<Name> {
430    type_covered: Rtype,
431    algorithm: SecAlg,
432    labels: u8,
433    original_ttl: Ttl,
434    expiration: Serial,
435    inception: Serial,
436    key_tag: u16,
437    signer_name: Name,
438}
439
440impl<Name> ProtoRrsig<Name> {
441    #[allow(clippy::too_many_arguments)] // XXX Consider changing.
442    pub fn new(
443        type_covered: Rtype,
444        algorithm: SecAlg,
445        labels: u8,
446        original_ttl: Ttl,
447        expiration: Serial,
448        inception: Serial,
449        key_tag: u16,
450        signer_name: Name,
451    ) -> Self {
452        ProtoRrsig {
453            type_covered,
454            algorithm,
455            labels,
456            original_ttl,
457            expiration,
458            inception,
459            key_tag,
460            signer_name,
461        }
462    }
463
464    pub fn into_rrsig<Octs: AsRef<[u8]>>(
465        self,
466        signature: Octs,
467    ) -> Result<Rrsig<Octs, Name>, LongRecordData>
468    where
469        Name: ToDname,
470    {
471        Rrsig::new(
472            self.type_covered,
473            self.algorithm,
474            self.labels,
475            self.original_ttl,
476            self.expiration,
477            self.inception,
478            self.key_tag,
479            self.signer_name,
480            signature,
481        )
482    }
483}
484
485impl<Name: ToDname> ProtoRrsig<Name> {
486    pub fn compose<Target: Composer + ?Sized>(
487        &self,
488        target: &mut Target,
489    ) -> Result<(), Target::AppendError> {
490        self.compose_head(target)?;
491        self.signer_name.compose(target)
492    }
493
494    pub fn compose_canonical<Target: Composer + ?Sized>(
495        &self,
496        target: &mut Target,
497    ) -> Result<(), Target::AppendError> {
498        self.compose_head(target)?;
499        self.signer_name.compose_canonical(target)
500    }
501
502    fn compose_len(&self) -> u16 {
503        Rtype::COMPOSE_LEN
504            + SecAlg::COMPOSE_LEN
505            + u8::COMPOSE_LEN
506            + u32::COMPOSE_LEN
507            + Serial::COMPOSE_LEN
508            + Serial::COMPOSE_LEN
509            + u16::COMPOSE_LEN
510            + self.signer_name.compose_len()
511    }
512
513    fn compose_head<Target: Composer + ?Sized>(
514        &self,
515        target: &mut Target,
516    ) -> Result<(), Target::AppendError> {
517        self.compose_len().compose(target)?;
518        self.type_covered.compose(target)?;
519        self.algorithm.compose(target)?;
520        self.labels.compose(target)?;
521        self.original_ttl.compose(target)?;
522        self.expiration.compose(target)?;
523        self.inception.compose(target)?;
524        self.key_tag.compose(target)
525    }
526}
527
528//--- OctetsFrom and FlattenInto
529
530impl<Name, SrcName> OctetsFrom<ProtoRrsig<SrcName>> for ProtoRrsig<Name>
531where
532    Name: OctetsFrom<SrcName>,
533{
534    type Error = Name::Error;
535
536    fn try_octets_from(
537        source: ProtoRrsig<SrcName>,
538    ) -> Result<Self, Self::Error> {
539        Ok(ProtoRrsig::new(
540            source.type_covered,
541            source.algorithm,
542            source.labels,
543            source.original_ttl,
544            source.expiration,
545            source.inception,
546            source.key_tag,
547            Name::try_octets_from(source.signer_name)?,
548        ))
549    }
550}
551
552impl<Name, TName> FlattenInto<ProtoRrsig<TName>> for ProtoRrsig<Name>
553where
554    Name: FlattenInto<TName>,
555{
556    type AppendError = Name::AppendError;
557
558    fn try_flatten_into(
559        self
560    ) -> Result<ProtoRrsig<TName>, Name::AppendError> {
561        Ok(ProtoRrsig::new(
562            self.type_covered,
563            self.algorithm,
564            self.labels,
565            self.original_ttl,
566            self.expiration,
567            self.inception,
568            self.key_tag,
569            self.signer_name.try_flatten_into()?,
570        ))
571    }
572}
573
574//------------ Rrsig ---------------------------------------------------------
575
576#[derive(Clone)]
577#[cfg_attr(
578    feature = "serde",
579    derive(serde::Serialize, serde::Deserialize),
580    serde(bound(
581        serialize = "
582            Octs: octseq::serde::SerializeOctets + AsRef<[u8]>,
583            Name: serde::Serialize,
584        ",
585        deserialize = "
586            Octs: FromBuilder + octseq::serde::DeserializeOctets<'de>,
587            <Octs as FromBuilder>::Builder:
588                OctetsBuilder + EmptyBuilder,
589            Name: serde::Deserialize<'de>,
590        ",
591    ))
592)]
593pub struct Rrsig<Octs, Name> {
594    type_covered: Rtype,
595    algorithm: SecAlg,
596    labels: u8,
597    original_ttl: Ttl,
598    expiration: Serial,
599    inception: Serial,
600    key_tag: u16,
601    signer_name: Name,
602    #[cfg_attr(
603        feature = "serde",
604        serde(with = "crate::utils::base64::serde")
605    )]
606    signature: Octs,
607}
608
609impl<Octs, Name> Rrsig<Octs, Name> {
610    #[allow(clippy::too_many_arguments)] // XXX Consider changing.
611    pub fn new(
612        type_covered: Rtype,
613        algorithm: SecAlg,
614        labels: u8,
615        original_ttl: Ttl,
616        expiration: Serial,
617        inception: Serial,
618        key_tag: u16,
619        signer_name: Name,
620        signature: Octs,
621    ) -> Result<Self, LongRecordData>
622    where
623        Octs: AsRef<[u8]>,
624        Name: ToDname,
625    {
626        LongRecordData::check_len(
627            usize::from(
628                Rtype::COMPOSE_LEN
629                    + SecAlg::COMPOSE_LEN
630                    + u8::COMPOSE_LEN
631                    + u32::COMPOSE_LEN
632                    + Serial::COMPOSE_LEN
633                    + Serial::COMPOSE_LEN
634                    + u16::COMPOSE_LEN
635                    + signer_name.compose_len(),
636            )
637            .checked_add(signature.as_ref().len())
638            .expect("long signature"),
639        )?;
640        Ok(unsafe {
641            Rrsig::new_unchecked(
642                type_covered,
643                algorithm,
644                labels,
645                original_ttl,
646                expiration,
647                inception,
648                key_tag,
649                signer_name,
650                signature,
651            )
652        })
653    }
654
655    /// Creates new RRSIG record data without checking.
656    ///
657    /// # Safety
658    ///
659    /// The caller needs to ensure that wire format representation of the
660    /// record data is at most 65,535 octets long.
661    #[allow(clippy::too_many_arguments)] // XXX Consider changing.
662    pub unsafe fn new_unchecked(
663        type_covered: Rtype,
664        algorithm: SecAlg,
665        labels: u8,
666        original_ttl: Ttl,
667        expiration: Serial,
668        inception: Serial,
669        key_tag: u16,
670        signer_name: Name,
671        signature: Octs,
672    ) -> Self {
673        Rrsig {
674            type_covered,
675            algorithm,
676            labels,
677            original_ttl,
678            expiration,
679            inception,
680            key_tag,
681            signer_name,
682            signature,
683        }
684    }
685
686    pub fn type_covered(&self) -> Rtype {
687        self.type_covered
688    }
689
690    pub fn algorithm(&self) -> SecAlg {
691        self.algorithm
692    }
693
694    pub fn labels(&self) -> u8 {
695        self.labels
696    }
697
698    pub fn original_ttl(&self) -> Ttl {
699        self.original_ttl
700    }
701
702    pub fn expiration(&self) -> Serial {
703        self.expiration
704    }
705
706    pub fn inception(&self) -> Serial {
707        self.inception
708    }
709
710    pub fn key_tag(&self) -> u16 {
711        self.key_tag
712    }
713
714    pub fn signer_name(&self) -> &Name {
715        &self.signer_name
716    }
717
718    pub fn signature(&self) -> &Octs {
719        &self.signature
720    }
721
722    pub fn set_signature(&mut self, signature: Octs) {
723        self.signature = signature
724    }
725
726    pub(super) fn convert_octets<TOcts, TName>(
727        self,
728    ) -> Result<Rrsig<TOcts, TName>, TOcts::Error>
729    where
730        TOcts: OctetsFrom<Octs>,
731        TName: OctetsFrom<Name, Error = TOcts::Error>,
732    {
733        Ok(unsafe {
734            Rrsig::new_unchecked(
735                self.type_covered,
736                self.algorithm,
737                self.labels,
738                self.original_ttl,
739                self.expiration,
740                self.inception,
741                self.key_tag,
742                TName::try_octets_from(self.signer_name)?,
743                TOcts::try_octets_from(self.signature)?,
744            )
745        })
746    }
747
748    pub(super) fn flatten<TOcts, TName>(
749        self,
750    ) -> Result<Rrsig<TOcts, TName>, TOcts::Error>
751    where
752        TOcts: OctetsFrom<Octs>,
753        Name: FlattenInto<TName, AppendError = TOcts::Error>,
754    {
755        Ok(unsafe {
756            Rrsig::new_unchecked(
757                self.type_covered,
758                self.algorithm,
759                self.labels,
760                self.original_ttl,
761                self.expiration,
762                self.inception,
763                self.key_tag,
764                self.signer_name.try_flatten_into()?,
765                TOcts::try_octets_from(self.signature)?,
766            )
767        })
768    }
769
770    pub fn scan<S: Scanner<Octets = Octs, Dname = Name>>(
771        scanner: &mut S,
772    ) -> Result<Self, S::Error>
773    where
774        Octs: AsRef<[u8]>,
775        Name: ToDname,
776    {
777        Self::new(
778            Rtype::scan(scanner)?,
779            SecAlg::scan(scanner)?,
780            u8::scan(scanner)?,
781            Ttl::scan(scanner)?,
782            Serial::scan_rrsig(scanner)?,
783            Serial::scan_rrsig(scanner)?,
784            u16::scan(scanner)?,
785            scanner.scan_dname()?,
786            scanner.convert_entry(base64::SymbolConverter::new())?,
787        )
788        .map_err(|err| S::Error::custom(err.as_str()))
789    }
790}
791
792impl<Octs> Rrsig<Octs, ParsedDname<Octs>> {
793    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized + 'a>(
794        parser: &mut Parser<'a, Src>,
795    ) -> Result<Self, ParseError> {
796        let type_covered = Rtype::parse(parser)?;
797        let algorithm = SecAlg::parse(parser)?;
798        let labels = u8::parse(parser)?;
799        let original_ttl = Ttl::parse(parser)?;
800        let expiration = Serial::parse(parser)?;
801        let inception = Serial::parse(parser)?;
802        let key_tag = u16::parse(parser)?;
803        let signer_name = ParsedDname::parse(parser)?;
804        let len = parser.remaining();
805        let signature = parser.parse_octets(len)?;
806        Ok(unsafe {
807            Self::new_unchecked(
808                type_covered,
809                algorithm,
810                labels,
811                original_ttl,
812                expiration,
813                inception,
814                key_tag,
815                signer_name,
816                signature,
817            )
818        })
819    }
820}
821
822//--- OctetsFrom and FlattenInto
823
824impl<Octs, SrcOcts, Name, SrcName> OctetsFrom<Rrsig<SrcOcts, SrcName>>
825    for Rrsig<Octs, Name>
826where
827    Octs: OctetsFrom<SrcOcts>,
828    Name: OctetsFrom<SrcName>,
829    Octs::Error: From<Name::Error>,
830{
831    type Error = Octs::Error;
832
833    fn try_octets_from(
834        source: Rrsig<SrcOcts, SrcName>,
835    ) -> Result<Self, Self::Error> {
836        Ok(unsafe {
837            Rrsig::new_unchecked(
838                source.type_covered,
839                source.algorithm,
840                source.labels,
841                source.original_ttl,
842                source.expiration,
843                source.inception,
844                source.key_tag,
845                Name::try_octets_from(source.signer_name)?,
846                Octs::try_octets_from(source.signature)?,
847            )
848        })
849    }
850}
851
852impl<Octs, TOcts, Name, TName> FlattenInto<Rrsig<TOcts, TName>>
853    for Rrsig<Octs, Name>
854where
855    TOcts: OctetsFrom<Octs>,
856    Name: FlattenInto<TName, AppendError = TOcts::Error>,
857{
858    type AppendError = TOcts::Error;
859
860    fn try_flatten_into(self) -> Result<Rrsig<TOcts, TName>, TOcts::Error> {
861        self.flatten()
862    }
863}
864
865//--- PartialEq and Eq
866
867impl<N, NN, O, OO> PartialEq<Rrsig<OO, NN>> for Rrsig<O, N>
868where
869    N: ToDname,
870    NN: ToDname,
871    O: AsRef<[u8]>,
872    OO: AsRef<[u8]>,
873{
874    fn eq(&self, other: &Rrsig<OO, NN>) -> bool {
875        self.type_covered == other.type_covered
876            && self.algorithm == other.algorithm
877            && self.labels == other.labels
878            && self.original_ttl == other.original_ttl
879            && self.expiration.into_int() == other.expiration.into_int()
880            && self.inception.into_int() == other.inception.into_int()
881            && self.key_tag == other.key_tag
882            && self.signer_name.name_eq(&other.signer_name)
883            && self.signature.as_ref() == other.signature.as_ref()
884    }
885}
886
887impl<Octs, Name> Eq for Rrsig<Octs, Name>
888where
889    Octs: AsRef<[u8]>,
890    Name: ToDname,
891{
892}
893
894//--- PartialOrd, CanonicalOrd, and Ord
895
896impl<N, NN, O, OO> PartialOrd<Rrsig<OO, NN>> for Rrsig<O, N>
897where
898    N: ToDname,
899    NN: ToDname,
900    O: AsRef<[u8]>,
901    OO: AsRef<[u8]>,
902{
903    fn partial_cmp(&self, other: &Rrsig<OO, NN>) -> Option<Ordering> {
904        match self.type_covered.partial_cmp(&other.type_covered) {
905            Some(Ordering::Equal) => {}
906            other => return other,
907        }
908        match self.algorithm.partial_cmp(&other.algorithm) {
909            Some(Ordering::Equal) => {}
910            other => return other,
911        }
912        match self.labels.partial_cmp(&other.labels) {
913            Some(Ordering::Equal) => {}
914            other => return other,
915        }
916        match self.original_ttl.partial_cmp(&other.original_ttl) {
917            Some(Ordering::Equal) => {}
918            other => return other,
919        }
920        match self.expiration.partial_cmp(&other.expiration) {
921            Some(Ordering::Equal) => {}
922            other => return other,
923        }
924        match self.inception.partial_cmp(&other.inception) {
925            Some(Ordering::Equal) => {}
926            other => return other,
927        }
928        match self.key_tag.partial_cmp(&other.key_tag) {
929            Some(Ordering::Equal) => {}
930            other => return other,
931        }
932        match self.signer_name.name_cmp(&other.signer_name) {
933            Ordering::Equal => {}
934            other => return Some(other),
935        }
936        self.signature
937            .as_ref()
938            .partial_cmp(other.signature.as_ref())
939    }
940}
941
942impl<N, NN, O, OO> CanonicalOrd<Rrsig<OO, NN>> for Rrsig<O, N>
943where
944    N: ToDname,
945    NN: ToDname,
946    O: AsRef<[u8]>,
947    OO: AsRef<[u8]>,
948{
949    fn canonical_cmp(&self, other: &Rrsig<OO, NN>) -> Ordering {
950        match self.type_covered.cmp(&other.type_covered) {
951            Ordering::Equal => {}
952            other => return other,
953        }
954        match self.algorithm.cmp(&other.algorithm) {
955            Ordering::Equal => {}
956            other => return other,
957        }
958        match self.labels.cmp(&other.labels) {
959            Ordering::Equal => {}
960            other => return other,
961        }
962        match self.original_ttl.cmp(&other.original_ttl) {
963            Ordering::Equal => {}
964            other => return other,
965        }
966        match self.expiration.canonical_cmp(&other.expiration) {
967            Ordering::Equal => {}
968            other => return other,
969        }
970        match self.inception.canonical_cmp(&other.inception) {
971            Ordering::Equal => {}
972            other => return other,
973        }
974        match self.key_tag.cmp(&other.key_tag) {
975            Ordering::Equal => {}
976            other => return other,
977        }
978        match self.signer_name.lowercase_composed_cmp(&other.signer_name) {
979            Ordering::Equal => {}
980            other => return other,
981        }
982        self.signature.as_ref().cmp(other.signature.as_ref())
983    }
984}
985
986impl<O: AsRef<[u8]>, N: ToDname> Ord for Rrsig<O, N> {
987    fn cmp(&self, other: &Self) -> Ordering {
988        self.canonical_cmp(other)
989    }
990}
991
992//--- Hash
993
994impl<O: AsRef<[u8]>, N: hash::Hash> hash::Hash for Rrsig<O, N> {
995    fn hash<H: hash::Hasher>(&self, state: &mut H) {
996        self.type_covered.hash(state);
997        self.algorithm.hash(state);
998        self.labels.hash(state);
999        self.original_ttl.hash(state);
1000        self.expiration.into_int().hash(state);
1001        self.inception.into_int().hash(state);
1002        self.key_tag.hash(state);
1003        self.signer_name.hash(state);
1004        self.signature.as_ref().hash(state);
1005    }
1006}
1007
1008//--- RecordData, ParseRecordData, ComposeRecordData
1009
1010impl<Octs, Name> RecordData for Rrsig<Octs, Name> {
1011    fn rtype(&self) -> Rtype {
1012        Rtype::Rrsig
1013    }
1014}
1015
1016impl<'a, Octs: Octets + ?Sized> ParseRecordData<'a, Octs>
1017    for Rrsig<Octs::Range<'a>, ParsedDname<Octs::Range<'a>>>
1018{
1019    fn parse_rdata(
1020        rtype: Rtype,
1021        parser: &mut Parser<'a, Octs>,
1022    ) -> Result<Option<Self>, ParseError> {
1023        if rtype == Rtype::Rrsig {
1024            Self::parse(parser).map(Some)
1025        } else {
1026            Ok(None)
1027        }
1028    }
1029}
1030
1031impl<Octs, Name> ComposeRecordData for Rrsig<Octs, Name>
1032where
1033    Octs: AsRef<[u8]>,
1034    Name: ToDname,
1035{
1036    fn rdlen(&self, _compress: bool) -> Option<u16> {
1037        Some(
1038            (Rtype::COMPOSE_LEN
1039                + SecAlg::COMPOSE_LEN
1040                + u8::COMPOSE_LEN
1041                + u32::COMPOSE_LEN
1042                + Serial::COMPOSE_LEN
1043                + Serial::COMPOSE_LEN
1044                + u16::COMPOSE_LEN
1045                + self.signer_name.compose_len())
1046            .checked_add(
1047                u16::try_from(self.signature.as_ref().len())
1048                    .expect("long signature"),
1049            )
1050            .expect("long signature"),
1051        )
1052    }
1053
1054    fn compose_rdata<Target: Composer + ?Sized>(
1055        &self,
1056        target: &mut Target,
1057    ) -> Result<(), Target::AppendError> {
1058        self.compose_head(target)?;
1059        self.signer_name.compose(target)?;
1060        target.append_slice(self.signature.as_ref())
1061    }
1062
1063    fn compose_canonical_rdata<Target: Composer + ?Sized>(
1064        &self,
1065        target: &mut Target,
1066    ) -> Result<(), Target::AppendError> {
1067        self.compose_head(target)?;
1068        self.signer_name.compose_canonical(target)?;
1069        target.append_slice(self.signature.as_ref())
1070    }
1071}
1072
1073impl<Octs: AsRef<[u8]>, Name: ToDname> Rrsig<Octs, Name> {
1074    fn compose_head<Target: Composer + ?Sized>(
1075        &self,
1076        target: &mut Target,
1077    ) -> Result<(), Target::AppendError> {
1078        self.type_covered.compose(target)?;
1079        self.algorithm.compose(target)?;
1080        self.labels.compose(target)?;
1081        self.original_ttl.compose(target)?;
1082        self.expiration.compose(target)?;
1083        self.inception.compose(target)?;
1084        self.key_tag.compose(target)
1085    }
1086}
1087
1088//--- Display
1089
1090impl<Octs, Name> fmt::Display for Rrsig<Octs, Name>
1091where
1092    Octs: AsRef<[u8]>,
1093    Name: fmt::Display,
1094{
1095    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1096        write!(
1097            f,
1098            "{} {} {} {} {} {} {} {}. ",
1099            self.type_covered,
1100            self.algorithm,
1101            self.labels,
1102            self.original_ttl.as_secs(),
1103            self.expiration,
1104            self.inception,
1105            self.key_tag,
1106            self.signer_name
1107        )?;
1108        base64::display(&self.signature, f)
1109    }
1110}
1111
1112//--- Debug
1113
1114impl<Octs, Name> fmt::Debug for Rrsig<Octs, Name>
1115where
1116    Octs: AsRef<[u8]>,
1117    Name: fmt::Debug,
1118{
1119    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1120        f.debug_struct("Rrsig")
1121            .field("type_covered", &self.type_covered)
1122            .field("algorithm", &self.algorithm)
1123            .field("labels", &self.labels)
1124            .field("original_ttl", &self.original_ttl)
1125            .field("expiration", &self.expiration)
1126            .field("inception", &self.inception)
1127            .field("key_tag", &self.key_tag)
1128            .field("signer_name", &self.signer_name)
1129            .field("signature", &self.signature.as_ref())
1130            .finish()
1131    }
1132}
1133
1134//------------ Nsec ----------------------------------------------------------
1135
1136#[derive(Clone)]
1137#[cfg_attr(
1138    feature = "serde",
1139    derive(serde::Serialize, serde::Deserialize),
1140    serde(bound(
1141        serialize = "
1142            Octs: octseq::serde::SerializeOctets + AsRef<[u8]>,
1143            Name: serde::Serialize,
1144        ",
1145        deserialize = "
1146            Octs: FromBuilder + octseq::serde::DeserializeOctets<'de>,
1147            <Octs as FromBuilder>::Builder:
1148                OctetsBuilder + EmptyBuilder + Truncate 
1149                + AsRef<[u8]> + AsMut<[u8]>,
1150            Name: serde::Deserialize<'de>,
1151        ",
1152    ))
1153)]
1154pub struct Nsec<Octs, Name> {
1155    next_name: Name,
1156    types: RtypeBitmap<Octs>,
1157}
1158
1159impl<Octs, Name> Nsec<Octs, Name> {
1160    pub fn new(next_name: Name, types: RtypeBitmap<Octs>) -> Self {
1161        Nsec { next_name, types }
1162    }
1163
1164    pub fn next_name(&self) -> &Name {
1165        &self.next_name
1166    }
1167
1168    pub fn set_next_name(&mut self, next_name: Name) {
1169        self.next_name = next_name
1170    }
1171
1172    pub fn types(&self) -> &RtypeBitmap<Octs> {
1173        &self.types
1174    }
1175
1176    pub(super) fn convert_octets<TOcts, TName>(
1177        self,
1178    ) -> Result<Nsec<TOcts, TName>, TOcts::Error>
1179    where
1180        TOcts: OctetsFrom<Octs>,
1181        TName: OctetsFrom<Name, Error = TOcts::Error>,
1182    {
1183        Ok(Nsec::new(
1184            self.next_name.try_octets_into()?,
1185            self.types.convert_octets()?,
1186        ))
1187    }
1188
1189    pub(super) fn flatten<TOcts, TName>(
1190        self,
1191    ) -> Result<Nsec<TOcts, TName>, TOcts::Error>
1192    where
1193        TOcts: OctetsFrom<Octs>,
1194        Name: FlattenInto<TName, AppendError = TOcts::Error>,
1195    {
1196        Ok(Nsec::new(
1197            self.next_name.try_flatten_into()?,
1198            self.types.convert_octets()?,
1199        ))
1200    }
1201
1202    pub fn scan<S: Scanner<Octets = Octs, Dname = Name>>(
1203        scanner: &mut S,
1204    ) -> Result<Self, S::Error> {
1205        Ok(Self::new(
1206            scanner.scan_dname()?,
1207            RtypeBitmap::scan(scanner)?,
1208        ))
1209    }
1210}
1211
1212impl<Octs: AsRef<[u8]>> Nsec<Octs, ParsedDname<Octs>> {
1213    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized + 'a>(
1214        parser: &mut Parser<'a, Src>,
1215    ) -> Result<Self, ParseError> {
1216        Ok(Nsec::new(
1217            ParsedDname::parse(parser)?,
1218            RtypeBitmap::parse(parser)?,
1219        ))
1220    }
1221}
1222
1223//--- OctetsFrom and FlattenInto
1224
1225impl<Octs, SrcOcts, Name, SrcName> OctetsFrom<Nsec<SrcOcts, SrcName>>
1226    for Nsec<Octs, Name>
1227where
1228    Octs: OctetsFrom<SrcOcts>,
1229    Name: OctetsFrom<SrcName, Error = Octs::Error>,
1230{
1231    type Error = Octs::Error;
1232
1233    fn try_octets_from(
1234        source: Nsec<SrcOcts, SrcName>,
1235    ) -> Result<Self, Self::Error> {
1236        Ok(Nsec::new(
1237            Name::try_octets_from(source.next_name)?,
1238            RtypeBitmap::try_octets_from(source.types)?,
1239        ))
1240    }
1241}
1242
1243impl<Octs, TOcts, Name, TName> FlattenInto<Nsec<TOcts, TName>>
1244    for Nsec<Octs, Name>
1245where
1246    TOcts: OctetsFrom<Octs>,
1247    Name: FlattenInto<TName, AppendError = TOcts::Error>,
1248{
1249    type AppendError = TOcts::Error;
1250
1251    fn try_flatten_into(self) -> Result<Nsec<TOcts, TName>, TOcts::Error> {
1252        self.flatten()
1253    }
1254}
1255
1256//--- PartialEq and Eq
1257
1258impl<O, OO, N, NN> PartialEq<Nsec<OO, NN>> for Nsec<O, N>
1259where
1260    O: AsRef<[u8]>,
1261    OO: AsRef<[u8]>,
1262    N: ToDname,
1263    NN: ToDname,
1264{
1265    fn eq(&self, other: &Nsec<OO, NN>) -> bool {
1266        self.next_name.name_eq(&other.next_name) && self.types == other.types
1267    }
1268}
1269
1270impl<O: AsRef<[u8]>, N: ToDname> Eq for Nsec<O, N> {}
1271
1272//--- PartialOrd, Ord, and CanonicalOrd
1273
1274impl<O, OO, N, NN> PartialOrd<Nsec<OO, NN>> for Nsec<O, N>
1275where
1276    O: AsRef<[u8]>,
1277    OO: AsRef<[u8]>,
1278    N: ToDname,
1279    NN: ToDname,
1280{
1281    fn partial_cmp(&self, other: &Nsec<OO, NN>) -> Option<Ordering> {
1282        match self.next_name.name_cmp(&other.next_name) {
1283            Ordering::Equal => {}
1284            other => return Some(other),
1285        }
1286        self.types.partial_cmp(&self.types)
1287    }
1288}
1289
1290impl<O, OO, N, NN> CanonicalOrd<Nsec<OO, NN>> for Nsec<O, N>
1291where
1292    O: AsRef<[u8]>,
1293    OO: AsRef<[u8]>,
1294    N: ToDname,
1295    NN: ToDname,
1296{
1297    fn canonical_cmp(&self, other: &Nsec<OO, NN>) -> Ordering {
1298        // RFC 6840 says that Nsec::next_name is not converted to lower case.
1299        match self.next_name.composed_cmp(&other.next_name) {
1300            Ordering::Equal => {}
1301            other => return other,
1302        }
1303        self.types.cmp(&self.types)
1304    }
1305}
1306
1307impl<O, N> Ord for Nsec<O, N>
1308where
1309    O: AsRef<[u8]>,
1310    N: ToDname,
1311{
1312    fn cmp(&self, other: &Self) -> Ordering {
1313        match self.next_name.name_cmp(&other.next_name) {
1314            Ordering::Equal => {}
1315            other => return other,
1316        }
1317        self.types.cmp(&self.types)
1318    }
1319}
1320
1321//--- Hash
1322
1323impl<Octs: AsRef<[u8]>, Name: hash::Hash> hash::Hash for Nsec<Octs, Name> {
1324    fn hash<H: hash::Hasher>(&self, state: &mut H) {
1325        self.next_name.hash(state);
1326        self.types.hash(state);
1327    }
1328}
1329
1330//--- RecordData, ParseRecordData, ComposeRecordData
1331
1332impl<Octs, Name> RecordData for Nsec<Octs, Name> {
1333    fn rtype(&self) -> Rtype {
1334        Rtype::Nsec
1335    }
1336}
1337
1338impl<'a, Octs: Octets + ?Sized> ParseRecordData<'a, Octs>
1339    for Nsec<Octs::Range<'a>, ParsedDname<Octs::Range<'a>>>
1340{
1341    fn parse_rdata(
1342        rtype: Rtype,
1343        parser: &mut Parser<'a, Octs>,
1344    ) -> Result<Option<Self>, ParseError> {
1345        if rtype == Rtype::Nsec {
1346            Self::parse(parser).map(Some)
1347        } else {
1348            Ok(None)
1349        }
1350    }
1351}
1352
1353impl<Octs, Name> ComposeRecordData for Nsec<Octs, Name>
1354where
1355    Octs: AsRef<[u8]>,
1356    Name: ToDname,
1357{
1358    fn rdlen(&self, _compress: bool) -> Option<u16> {
1359        Some(
1360            self.next_name
1361                .compose_len()
1362                .checked_add(self.types.compose_len())
1363                .expect("long type bitmap"),
1364        )
1365    }
1366
1367    fn compose_rdata<Target: Composer + ?Sized>(
1368        &self,
1369        target: &mut Target,
1370    ) -> Result<(), Target::AppendError> {
1371        self.next_name.compose(target)?;
1372        self.types.compose(target)
1373    }
1374
1375    fn compose_canonical_rdata<Target: Composer + ?Sized>(
1376        &self,
1377        target: &mut Target,
1378    ) -> Result<(), Target::AppendError> {
1379        // Deferring to compose_rdata is correct as we keep the case of the
1380        // next name.
1381        self.compose_rdata(target)
1382    }
1383}
1384
1385//--- Display
1386
1387impl<Octs, Name> fmt::Display for Nsec<Octs, Name>
1388where
1389    Octs: AsRef<[u8]>,
1390    Name: fmt::Display,
1391{
1392    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1393        write!(f, "{}. {}", self.next_name, self.types)
1394    }
1395}
1396
1397//--- Debug
1398
1399impl<Octs, Name> fmt::Debug for Nsec<Octs, Name>
1400where
1401    Octs: AsRef<[u8]>,
1402    Name: fmt::Debug,
1403{
1404    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1405        f.debug_struct("Nsec")
1406            .field("next_name", &self.next_name)
1407            .field("types", &self.types)
1408            .finish()
1409    }
1410}
1411
1412//------------ Ds -----------------------------------------------------------
1413
1414#[derive(Clone)]
1415#[cfg_attr(
1416    feature = "serde",
1417    derive(serde::Serialize, serde::Deserialize),
1418    serde(bound(
1419        serialize = "
1420            Octs: octseq::serde::SerializeOctets + AsRef<[u8]>
1421        ",
1422        deserialize = "
1423            Octs: FromBuilder + octseq::serde::DeserializeOctets<'de>,
1424            <Octs as FromBuilder>::Builder:
1425                OctetsBuilder + EmptyBuilder,
1426        ",
1427    ))
1428)]
1429pub struct Ds<Octs> {
1430    key_tag: u16,
1431    algorithm: SecAlg,
1432    digest_type: DigestAlg,
1433    #[cfg_attr(
1434        feature = "serde",
1435        serde(with = "crate::utils::base64::serde")
1436    )]
1437    digest: Octs,
1438}
1439
1440impl<Octs> Ds<Octs> {
1441    pub fn new(
1442        key_tag: u16,
1443        algorithm: SecAlg,
1444        digest_type: DigestAlg,
1445        digest: Octs,
1446    ) -> Result<Self, LongRecordData>
1447    where
1448        Octs: AsRef<[u8]>,
1449    {
1450        LongRecordData::check_len(
1451            usize::from(
1452                u16::COMPOSE_LEN
1453                    + SecAlg::COMPOSE_LEN
1454                    + DigestAlg::COMPOSE_LEN,
1455            )
1456            .checked_add(digest.as_ref().len())
1457            .expect("long digest"),
1458        )?;
1459        Ok(unsafe {
1460            Ds::new_unchecked(key_tag, algorithm, digest_type, digest)
1461        })
1462    }
1463
1464    /// Creates new DS record data without checking.
1465    ///
1466    /// # Safety
1467    ///
1468    /// The caller needs to ensure that wire format representation of the
1469    /// record data is at most 65,535 octets long.
1470    pub unsafe fn new_unchecked(
1471        key_tag: u16,
1472        algorithm: SecAlg,
1473        digest_type: DigestAlg,
1474        digest: Octs,
1475    ) -> Self {
1476        Ds {
1477            key_tag,
1478            algorithm,
1479            digest_type,
1480            digest,
1481        }
1482    }
1483
1484    pub fn key_tag(&self) -> u16 {
1485        self.key_tag
1486    }
1487
1488    pub fn algorithm(&self) -> SecAlg {
1489        self.algorithm
1490    }
1491
1492    pub fn digest_type(&self) -> DigestAlg {
1493        self.digest_type
1494    }
1495
1496    pub fn digest(&self) -> &Octs {
1497        &self.digest
1498    }
1499
1500    pub fn into_digest(self) -> Octs {
1501        self.digest
1502    }
1503
1504    pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
1505        self,
1506    ) -> Result<Ds<Target>, Target::Error> {
1507        Ok(unsafe {
1508            Ds::new_unchecked(
1509                self.key_tag,
1510                self.algorithm,
1511                self.digest_type,
1512                self.digest.try_octets_into()?,
1513            )
1514        })
1515    }
1516
1517    pub(super) fn flatten<Target: OctetsFrom<Octs>>(
1518        self,
1519    ) -> Result<Ds<Target>, Target::Error> {
1520        self.convert_octets()
1521    }
1522
1523    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
1524        parser: &mut Parser<'a, Src>,
1525    ) -> Result<Self, ParseError> {
1526        let len = match parser.remaining().checked_sub(4) {
1527            Some(len) => len,
1528            None => return Err(ParseError::ShortInput),
1529        };
1530        Ok(unsafe {
1531            Self::new_unchecked(
1532                u16::parse(parser)?,
1533                SecAlg::parse(parser)?,
1534                DigestAlg::parse(parser)?,
1535                parser.parse_octets(len)?,
1536            )
1537        })
1538    }
1539
1540    pub fn scan<S: Scanner<Octets = Octs>>(
1541        scanner: &mut S,
1542    ) -> Result<Self, S::Error>
1543    where
1544        Octs: AsRef<[u8]>,
1545    {
1546        Self::new(
1547            u16::scan(scanner)?,
1548            SecAlg::scan(scanner)?,
1549            DigestAlg::scan(scanner)?,
1550            scanner.convert_entry(base16::SymbolConverter::new())?,
1551        )
1552        .map_err(|err| S::Error::custom(err.as_str()))
1553    }
1554}
1555
1556//--- OctetsFrom
1557
1558impl<Octs, SrcOcts> OctetsFrom<Ds<SrcOcts>> for Ds<Octs>
1559where
1560    Octs: OctetsFrom<SrcOcts>,
1561{
1562    type Error = Octs::Error;
1563
1564    fn try_octets_from(source: Ds<SrcOcts>) -> Result<Self, Self::Error> {
1565        Ok(unsafe {
1566            Ds::new_unchecked(
1567                source.key_tag,
1568                source.algorithm,
1569                source.digest_type,
1570                Octs::try_octets_from(source.digest)?,
1571            )
1572        })
1573    }
1574}
1575
1576//--- PartialEq and Eq
1577
1578impl<Octs, Other> PartialEq<Ds<Other>> for Ds<Octs>
1579where
1580    Octs: AsRef<[u8]>,
1581    Other: AsRef<[u8]>,
1582{
1583    fn eq(&self, other: &Ds<Other>) -> bool {
1584        self.key_tag == other.key_tag
1585            && self.algorithm == other.algorithm
1586            && self.digest_type == other.digest_type
1587            && self.digest.as_ref().eq(other.digest.as_ref())
1588    }
1589}
1590
1591impl<Octs: AsRef<[u8]>> Eq for Ds<Octs> {}
1592
1593//--- PartialOrd, CanonicalOrd, and Ord
1594
1595impl<Octs, Other> PartialOrd<Ds<Other>> for Ds<Octs>
1596where
1597    Octs: AsRef<[u8]>,
1598    Other: AsRef<[u8]>,
1599{
1600    fn partial_cmp(&self, other: &Ds<Other>) -> Option<Ordering> {
1601        match self.key_tag.partial_cmp(&other.key_tag) {
1602            Some(Ordering::Equal) => {}
1603            other => return other,
1604        }
1605        match self.algorithm.partial_cmp(&other.algorithm) {
1606            Some(Ordering::Equal) => {}
1607            other => return other,
1608        }
1609        match self.digest_type.partial_cmp(&other.digest_type) {
1610            Some(Ordering::Equal) => {}
1611            other => return other,
1612        }
1613        self.digest.as_ref().partial_cmp(other.digest.as_ref())
1614    }
1615}
1616
1617impl<Octs, Other> CanonicalOrd<Ds<Other>> for Ds<Octs>
1618where
1619    Octs: AsRef<[u8]>,
1620    Other: AsRef<[u8]>,
1621{
1622    fn canonical_cmp(&self, other: &Ds<Other>) -> Ordering {
1623        match self.key_tag.cmp(&other.key_tag) {
1624            Ordering::Equal => {}
1625            other => return other,
1626        }
1627        match self.algorithm.cmp(&other.algorithm) {
1628            Ordering::Equal => {}
1629            other => return other,
1630        }
1631        match self.digest_type.cmp(&other.digest_type) {
1632            Ordering::Equal => {}
1633            other => return other,
1634        }
1635        self.digest.as_ref().cmp(other.digest.as_ref())
1636    }
1637}
1638
1639impl<Octs: AsRef<[u8]>> Ord for Ds<Octs> {
1640    fn cmp(&self, other: &Self) -> Ordering {
1641        self.canonical_cmp(other)
1642    }
1643}
1644
1645//--- Hash
1646
1647impl<Octs: AsRef<[u8]>> hash::Hash for Ds<Octs> {
1648    fn hash<H: hash::Hasher>(&self, state: &mut H) {
1649        self.key_tag.hash(state);
1650        self.algorithm.hash(state);
1651        self.digest_type.hash(state);
1652        self.digest.as_ref().hash(state);
1653    }
1654}
1655
1656//--- RecordData, ParseRecordData, ComposeRecordData
1657
1658impl<Octs> RecordData for Ds<Octs> {
1659    fn rtype(&self) -> Rtype {
1660        Rtype::Ds
1661    }
1662}
1663
1664impl<'a, Octs> ParseRecordData<'a, Octs> for Ds<Octs::Range<'a>>
1665where
1666    Octs: Octets + ?Sized,
1667{
1668    fn parse_rdata(
1669        rtype: Rtype,
1670        parser: &mut Parser<'a, Octs>,
1671    ) -> Result<Option<Self>, ParseError> {
1672        if rtype == Rtype::Ds {
1673            Self::parse(parser).map(Some)
1674        } else {
1675            Ok(None)
1676        }
1677    }
1678}
1679
1680impl<Octs: AsRef<[u8]>> ComposeRecordData for Ds<Octs> {
1681    fn rdlen(&self, _compress: bool) -> Option<u16> {
1682        Some(
1683            u16::checked_add(
1684                u16::COMPOSE_LEN
1685                    + SecAlg::COMPOSE_LEN
1686                    + DigestAlg::COMPOSE_LEN,
1687                self.digest.as_ref().len().try_into().expect("long digest"),
1688            )
1689            .expect("long digest"),
1690        )
1691    }
1692
1693    fn compose_rdata<Target: Composer + ?Sized>(
1694        &self,
1695        target: &mut Target,
1696    ) -> Result<(), Target::AppendError> {
1697        self.key_tag.compose(target)?;
1698        self.algorithm.compose(target)?;
1699        self.digest_type.compose(target)?;
1700        target.append_slice(self.digest.as_ref())
1701    }
1702
1703    fn compose_canonical_rdata<Target: Composer + ?Sized>(
1704        &self,
1705        target: &mut Target,
1706    ) -> Result<(), Target::AppendError> {
1707        self.compose_rdata(target)
1708    }
1709}
1710
1711//--- Display
1712
1713impl<Octs: AsRef<[u8]>> fmt::Display for Ds<Octs> {
1714    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1715        write!(
1716            f,
1717            "{} {} {} ",
1718            self.key_tag, self.algorithm, self.digest_type
1719        )?;
1720        for ch in self.digest.as_ref() {
1721            write!(f, "{:02x}", ch)?
1722        }
1723        Ok(())
1724    }
1725}
1726
1727//--- Debug
1728
1729impl<Octs: AsRef<[u8]>> fmt::Debug for Ds<Octs> {
1730    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1731        f.debug_struct("Ds")
1732            .field("key_tag", &self.key_tag)
1733            .field("algorithm", &self.algorithm)
1734            .field("digest_type", &self.digest_type)
1735            .field("digest", &self.digest.as_ref())
1736            .finish()
1737    }
1738}
1739
1740//------------ RtypeBitmap ---------------------------------------------------
1741
1742#[derive(Clone)]
1743pub struct RtypeBitmap<Octs>(Octs);
1744
1745impl<Octs> RtypeBitmap<Octs> {
1746    pub fn from_octets(octets: Octs) -> Result<Self, RtypeBitmapError>
1747    where
1748        Octs: AsRef<[u8]>,
1749    {
1750        {
1751            let mut data = octets.as_ref();
1752            while !data.is_empty() {
1753                // At least bitmap number and length must be present.
1754                if data.len() < 2 {
1755                    return Err(RtypeBitmapError::ShortInput);
1756                }
1757
1758                let len = (data[1] as usize) + 2;
1759                // https://tools.ietf.org/html/rfc4034#section-4.1.2:
1760                //  Blocks with no types present MUST NOT be included.
1761                if len == 2 {
1762                    return Err(RtypeBitmapError::BadRtypeBitmap);
1763                }
1764                if len > 34 {
1765                    return Err(RtypeBitmapError::BadRtypeBitmap);
1766                }
1767                if data.len() < len {
1768                    return Err(RtypeBitmapError::ShortInput);
1769                }
1770                data = &data[len..];
1771            }
1772        }
1773        Ok(RtypeBitmap(octets))
1774    }
1775
1776    #[must_use]
1777    pub fn builder() -> RtypeBitmapBuilder<Octs::Builder>
1778    where
1779        Octs: FromBuilder,
1780        <Octs as FromBuilder>::Builder: EmptyBuilder,
1781    {
1782        RtypeBitmapBuilder::new()
1783    }
1784
1785    pub fn scan<S: Scanner<Octets = Octs>>(
1786        scanner: &mut S,
1787    ) -> Result<Self, S::Error> {
1788        let first = Rtype::scan(scanner)?;
1789        let mut builder =
1790            RtypeBitmapBuilder::with_builder(scanner.octets_builder()?);
1791        builder.add(first).map_err(|_| S::Error::short_buf())?;
1792        while scanner.continues() {
1793            builder
1794                .add(Rtype::scan(scanner)?)
1795                .map_err(|_| S::Error::short_buf())?;
1796        }
1797        Ok(builder.finalize())
1798    }
1799
1800    pub fn as_octets(&self) -> &Octs {
1801        &self.0
1802    }
1803
1804    pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
1805        self,
1806    ) -> Result<RtypeBitmap<Target>, Target::Error> {
1807        Ok(RtypeBitmap(self.0.try_octets_into()?))
1808    }
1809}
1810
1811impl<Octs: AsRef<[u8]>> RtypeBitmap<Octs> {
1812    pub fn as_slice(&self) -> &[u8] {
1813        self.0.as_ref()
1814    }
1815
1816    pub fn iter(&self) -> RtypeBitmapIter {
1817        RtypeBitmapIter::new(self.0.as_ref())
1818    }
1819
1820    pub fn contains(&self, rtype: Rtype) -> bool {
1821        let (block, octet, mask) = split_rtype(rtype);
1822        let mut data = self.0.as_ref();
1823        while !data.is_empty() {
1824            let ((window_num, window), next_data) =
1825                read_window(data).unwrap();
1826            if window_num == block {
1827                return !(window.len() <= octet || window[octet] & mask == 0);
1828            }
1829            data = next_data;
1830        }
1831        false
1832    }
1833
1834    pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
1835        parser: &mut Parser<'a, Src>,
1836    ) -> Result<Self, ParseError> {
1837        let len = parser.remaining();
1838        RtypeBitmap::from_octets(parser.parse_octets(len)?)
1839            .map_err(Into::into)
1840    }
1841
1842    pub fn compose_len(&self) -> u16 {
1843        u16::try_from(self.0.as_ref().len()).expect("long rtype bitmap")
1844    }
1845
1846    pub fn compose<Target: OctetsBuilder + ?Sized>(
1847        &self,
1848        target: &mut Target,
1849    ) -> Result<(), Target::AppendError> {
1850        target.append_slice(self.0.as_ref())
1851    }
1852}
1853
1854//--- AsRef
1855
1856impl<T, Octs: AsRef<T>> AsRef<T> for RtypeBitmap<Octs> {
1857    fn as_ref(&self) -> &T {
1858        self.0.as_ref()
1859    }
1860}
1861
1862//--- OctetsFrom
1863
1864impl<Octs, SrcOcts> OctetsFrom<RtypeBitmap<SrcOcts>> for RtypeBitmap<Octs>
1865where
1866    Octs: OctetsFrom<SrcOcts>,
1867{
1868    type Error = Octs::Error;
1869
1870    fn try_octets_from(
1871        source: RtypeBitmap<SrcOcts>,
1872    ) -> Result<Self, Self::Error> {
1873        Octs::try_octets_from(source.0).map(RtypeBitmap)
1874    }
1875}
1876
1877//--- PartialEq and Eq
1878
1879impl<O, OO> PartialEq<RtypeBitmap<OO>> for RtypeBitmap<O>
1880where
1881    O: AsRef<[u8]>,
1882    OO: AsRef<[u8]>,
1883{
1884    fn eq(&self, other: &RtypeBitmap<OO>) -> bool {
1885        self.0.as_ref().eq(other.0.as_ref())
1886    }
1887}
1888
1889impl<O: AsRef<[u8]>> Eq for RtypeBitmap<O> {}
1890
1891//--- PartialOrd, CanonicalOrd, and Ord
1892
1893impl<O, OO> PartialOrd<RtypeBitmap<OO>> for RtypeBitmap<O>
1894where
1895    O: AsRef<[u8]>,
1896    OO: AsRef<[u8]>,
1897{
1898    fn partial_cmp(&self, other: &RtypeBitmap<OO>) -> Option<Ordering> {
1899        self.0.as_ref().partial_cmp(other.0.as_ref())
1900    }
1901}
1902
1903impl<O, OO> CanonicalOrd<RtypeBitmap<OO>> for RtypeBitmap<O>
1904where
1905    O: AsRef<[u8]>,
1906    OO: AsRef<[u8]>,
1907{
1908    fn canonical_cmp(&self, other: &RtypeBitmap<OO>) -> Ordering {
1909        self.0.as_ref().cmp(other.0.as_ref())
1910    }
1911}
1912
1913impl<O: AsRef<[u8]>> Ord for RtypeBitmap<O> {
1914    fn cmp(&self, other: &Self) -> Ordering {
1915        self.0.as_ref().cmp(other.0.as_ref())
1916    }
1917}
1918
1919//--- Hash
1920
1921impl<O: AsRef<[u8]>> hash::Hash for RtypeBitmap<O> {
1922    fn hash<H: hash::Hasher>(&self, state: &mut H) {
1923        self.0.as_ref().hash(state)
1924    }
1925}
1926
1927//--- IntoIterator
1928
1929impl<'a, Octs: AsRef<[u8]>> IntoIterator for &'a RtypeBitmap<Octs> {
1930    type Item = Rtype;
1931    type IntoIter = RtypeBitmapIter<'a>;
1932
1933    fn into_iter(self) -> Self::IntoIter {
1934        self.iter()
1935    }
1936}
1937
1938//--- Display
1939
1940impl<Octs: AsRef<[u8]>> fmt::Display for RtypeBitmap<Octs> {
1941    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1942        let mut iter = self.iter();
1943        if let Some(rtype) = iter.next() {
1944            rtype.fmt(f)?;
1945        }
1946        for rtype in iter {
1947            write!(f, " {}", rtype)?
1948        }
1949        Ok(())
1950    }
1951}
1952
1953//--- Debug
1954
1955impl<Octs: AsRef<[u8]>> fmt::Debug for RtypeBitmap<Octs> {
1956    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1957        f.write_str("RtypeBitmap(")?;
1958        fmt::Display::fmt(self, f)?;
1959        f.write_str(")")
1960    }
1961}
1962
1963//--- Serialize and Deserialize
1964
1965#[cfg(feature = "serde")]
1966impl<Octs> serde::Serialize for RtypeBitmap<Octs>
1967where
1968    Octs: AsRef<[u8]> + SerializeOctets,
1969{
1970    fn serialize<S: serde::Serializer>(
1971        &self,
1972        serializer: S,
1973    ) -> Result<S::Ok, S::Error> {
1974        if serializer.is_human_readable() {
1975            struct Inner<'a>(&'a [u8]);
1976
1977            impl<'a> serde::Serialize for Inner<'a> {
1978                fn serialize<S: serde::Serializer>(
1979                    &self,
1980                    serializer: S,
1981                ) -> Result<S::Ok, S::Error> {
1982                    use serde::ser::SerializeSeq;
1983
1984                    let mut serializer = serializer.serialize_seq(None)?;
1985                    for item in RtypeBitmapIter::new(self.0) {
1986                        serializer.serialize_element(&item)?;
1987                    }
1988                    serializer.end()
1989                }
1990            }
1991
1992            serializer.serialize_newtype_struct(
1993                "RtypeBitmap",
1994                &Inner(self.0.as_ref()),
1995            )
1996        } else {
1997            serializer.serialize_newtype_struct(
1998                "RtypeBitmap",
1999                &self.0.as_serialized_octets(),
2000            )
2001        }
2002    }
2003}
2004
2005#[cfg(feature = "serde")]
2006impl<'de, Octs> serde::Deserialize<'de> for RtypeBitmap<Octs>
2007where
2008    Octs: FromBuilder + DeserializeOctets<'de>,
2009    <Octs as FromBuilder>::Builder:
2010        EmptyBuilder + Truncate + AsRef<[u8]> + AsMut<[u8]>,
2011{
2012    fn deserialize<D: serde::Deserializer<'de>>(
2013        deserializer: D,
2014    ) -> Result<Self, D::Error> {
2015        use core::marker::PhantomData;
2016
2017        struct InnerVisitor<'de, T: DeserializeOctets<'de>>(T::Visitor);
2018
2019        impl<'de, Octs> serde::de::Visitor<'de> for InnerVisitor<'de, Octs>
2020        where
2021            Octs: FromBuilder + DeserializeOctets<'de>,
2022            <Octs as FromBuilder>::Builder: OctetsBuilder
2023                + EmptyBuilder
2024                + Truncate
2025                + AsRef<[u8]>
2026                + AsMut<[u8]>,
2027        {
2028            type Value = RtypeBitmap<Octs>;
2029
2030            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
2031                f.write_str("a record type bitmap")
2032            }
2033
2034            fn visit_seq<A: serde::de::SeqAccess<'de>>(
2035                self,
2036                mut seq: A,
2037            ) -> Result<Self::Value, A::Error> {
2038                use serde::de::Error;
2039
2040                let mut builder = RtypeBitmap::<Octs>::builder();
2041                while let Some(element) = seq.next_element()? {
2042                    builder.add(element).map_err(|_| {
2043                        A::Error::custom(octseq::builder::ShortBuf)
2044                    })?;
2045                }
2046
2047                Ok(builder.finalize())
2048            }
2049
2050            fn visit_borrowed_bytes<E: serde::de::Error>(
2051                self,
2052                value: &'de [u8],
2053            ) -> Result<Self::Value, E> {
2054                self.0.visit_borrowed_bytes(value).and_then(|octets| {
2055                    RtypeBitmap::from_octets(octets).map_err(E::custom)
2056                })
2057            }
2058
2059            #[cfg(feature = "std")]
2060            fn visit_byte_buf<E: serde::de::Error>(
2061                self,
2062                value: std::vec::Vec<u8>,
2063            ) -> Result<Self::Value, E> {
2064                self.0.visit_byte_buf(value).and_then(|octets| {
2065                    RtypeBitmap::from_octets(octets).map_err(E::custom)
2066                })
2067            }
2068        }
2069
2070        struct NewtypeVisitor<T>(PhantomData<T>);
2071
2072        impl<'de, Octs> serde::de::Visitor<'de> for NewtypeVisitor<Octs>
2073        where
2074            Octs: FromBuilder + DeserializeOctets<'de>,
2075            <Octs as FromBuilder>::Builder: OctetsBuilder
2076                + EmptyBuilder
2077                + Truncate
2078                + AsRef<[u8]>
2079                + AsMut<[u8]>,
2080        {
2081            type Value = RtypeBitmap<Octs>;
2082
2083            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
2084                f.write_str("a record type bitmap")
2085            }
2086
2087            fn visit_newtype_struct<D: serde::Deserializer<'de>>(
2088                self,
2089                deserializer: D,
2090            ) -> Result<Self::Value, D::Error> {
2091                if deserializer.is_human_readable() {
2092                    deserializer
2093                        .deserialize_seq(InnerVisitor(Octs::visitor()))
2094                } else {
2095                    Octs::deserialize_with_visitor(
2096                        deserializer,
2097                        InnerVisitor(Octs::visitor()),
2098                    )
2099                }
2100            }
2101        }
2102
2103        deserializer.deserialize_newtype_struct(
2104            "RtypeBitmap",
2105            NewtypeVisitor(PhantomData),
2106        )
2107    }
2108}
2109
2110//------------ RtypeBitmapBuilder --------------------------------------------
2111
2112/// A builder for a record type bitmap.
2113//
2114//  Here is how this is going to work: We keep one long Builder into which
2115//  we place all added types. The buffer contains a sequence of blocks
2116//  encoded similarly to the final format but with all 32 octets of the
2117//  bitmap present. Blocks are in order and are only added when needed (which
2118//  means we may have to insert a block in the middle). When finalizing, we
2119//  compress the block buffer by dropping the unncessary octets of each
2120//  block.
2121#[derive(Clone, Debug)]
2122pub struct RtypeBitmapBuilder<Builder> {
2123    buf: Builder,
2124}
2125
2126impl<Builder: OctetsBuilder> RtypeBitmapBuilder<Builder> {
2127    #[must_use]
2128    pub fn new() -> Self
2129    where
2130        Builder: EmptyBuilder,
2131    {
2132        RtypeBitmapBuilder {
2133            // Start out with the capacity for one block.
2134            buf: Builder::with_capacity(34),
2135        }
2136    }
2137
2138    pub fn with_builder(builder: Builder) -> Self {
2139        RtypeBitmapBuilder { buf: builder }
2140    }
2141}
2142
2143#[cfg(feature = "std")]
2144impl RtypeBitmapBuilder<Vec<u8>> {
2145    #[must_use]
2146    pub fn new_vec() -> Self {
2147        Self::new()
2148    }
2149}
2150
2151impl<Builder> RtypeBitmapBuilder<Builder>
2152where
2153    Builder: OctetsBuilder + AsRef<[u8]> + AsMut<[u8]>,
2154{
2155    pub fn add(&mut self, rtype: Rtype) -> Result<(), Builder::AppendError> {
2156        let (block, octet, bit) = split_rtype(rtype);
2157        let block = self.get_block(block)?;
2158        if (block[1] as usize) < (octet + 1) {
2159            block[1] = (octet + 1) as u8
2160        }
2161        block[octet + 2] |= bit;
2162        Ok(())
2163    }
2164
2165    fn get_block(
2166        &mut self,
2167        block: u8,
2168    ) -> Result<&mut [u8], Builder::AppendError> {
2169        let mut pos = 0;
2170        while pos < self.buf.as_ref().len() {
2171            match self.buf.as_ref()[pos].cmp(&block) {
2172                Ordering::Equal => {
2173                    return Ok(&mut self.buf.as_mut()[pos..pos + 34])
2174                }
2175                Ordering::Greater => {
2176                    let len = self.buf.as_ref().len() - pos;
2177                    self.buf.append_slice(&[0; 34])?;
2178                    let buf = self.buf.as_mut();
2179                    unsafe {
2180                        ptr::copy(
2181                            buf.as_ptr().add(pos),
2182                            buf.as_mut_ptr().add(pos + 34),
2183                            len,
2184                        );
2185                        ptr::write_bytes(buf.as_mut_ptr().add(pos), 0, 34);
2186                    }
2187                    buf[pos] = block;
2188                    return Ok(&mut buf[pos..pos + 34]);
2189                }
2190                Ordering::Less => pos += 34,
2191            }
2192        }
2193
2194        self.buf.append_slice(&[0; 34])?;
2195        self.buf.as_mut()[pos] = block;
2196        Ok(&mut self.buf.as_mut()[pos..pos + 34])
2197    }
2198
2199    pub fn finalize(mut self) -> RtypeBitmap<Builder::Octets>
2200    where
2201        Builder: FreezeBuilder + Truncate,
2202    {
2203        let mut src_pos = 0;
2204        let mut dst_pos = 0;
2205        while src_pos < self.buf.as_ref().len() {
2206            let len = (self.buf.as_ref()[src_pos + 1] as usize) + 2;
2207            if src_pos != dst_pos {
2208                let buf = self.buf.as_mut();
2209                unsafe {
2210                    ptr::copy(
2211                        buf.as_ptr().add(src_pos),
2212                        buf.as_mut_ptr().add(dst_pos),
2213                        len,
2214                    )
2215                }
2216            }
2217            dst_pos += len;
2218            src_pos += 34;
2219        }
2220        self.buf.truncate(dst_pos);
2221        RtypeBitmap(self.buf.freeze())
2222    }
2223}
2224
2225//--- Default
2226
2227impl<Builder> Default for RtypeBitmapBuilder<Builder>
2228where
2229    Builder: OctetsBuilder + EmptyBuilder,
2230{
2231    fn default() -> Self {
2232        Self::new()
2233    }
2234}
2235
2236//------------ RtypeBitmapIter -----------------------------------------------
2237
2238pub struct RtypeBitmapIter<'a> {
2239    /// The data to iterate over.
2240    ///
2241    /// This starts with the octets of the current block without the block
2242    /// number and length.
2243    data: &'a [u8],
2244
2245    /// The base value of the current block, i.e., its upper 8 bits.
2246    block: u16,
2247
2248    /// The length of the current block’s data.
2249    len: usize,
2250
2251    /// Index of the current octet in the current block.
2252    octet: usize,
2253
2254    /// Index of the next set bit in the current octet in the current block.
2255    bit: u16,
2256}
2257
2258impl<'a> RtypeBitmapIter<'a> {
2259    fn new(data: &'a [u8]) -> Self {
2260        if data.is_empty() {
2261            RtypeBitmapIter {
2262                data,
2263                block: 0,
2264                len: 0,
2265                octet: 0,
2266                bit: 0,
2267            }
2268        } else {
2269            let mut res = RtypeBitmapIter {
2270                data: &data[2..],
2271                block: u16::from(data[0]) << 8,
2272                len: usize::from(data[1]),
2273                octet: 0,
2274                bit: 0,
2275            };
2276            if res.data[0] & 0x80 == 0 {
2277                res.advance()
2278            }
2279            res
2280        }
2281    }
2282
2283    fn advance(&mut self) {
2284        loop {
2285            self.bit += 1;
2286            if self.bit == 8 {
2287                self.bit = 0;
2288                self.octet += 1;
2289                if self.octet == self.len {
2290                    self.data = &self.data[self.len..];
2291                    if self.data.is_empty() {
2292                        return;
2293                    }
2294                    self.block = u16::from(self.data[0]) << 8;
2295                    self.len = usize::from(self.data[1]);
2296                    self.data = &self.data[2..];
2297                    self.octet = 0;
2298                }
2299            }
2300            if self.data[self.octet] & (0x80 >> self.bit) != 0 {
2301                return;
2302            }
2303        }
2304    }
2305}
2306
2307impl<'a> Iterator for RtypeBitmapIter<'a> {
2308    type Item = Rtype;
2309
2310    fn next(&mut self) -> Option<Self::Item> {
2311        if self.data.is_empty() {
2312            return None;
2313        }
2314        let res =
2315            Rtype::from_int(self.block | (self.octet as u16) << 3 | self.bit);
2316        self.advance();
2317        Some(res)
2318    }
2319}
2320
2321//------------ RtypeBitmapError ----------------------------------------------
2322
2323#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2324pub enum RtypeBitmapError {
2325    ShortInput,
2326    BadRtypeBitmap,
2327}
2328
2329//--- From
2330
2331impl From<RtypeBitmapError> for ParseError {
2332    fn from(err: RtypeBitmapError) -> ParseError {
2333        match err {
2334            RtypeBitmapError::ShortInput => ParseError::ShortInput,
2335            RtypeBitmapError::BadRtypeBitmap => {
2336                FormError::new("invalid NSEC bitmap").into()
2337            }
2338        }
2339    }
2340}
2341
2342//--- Display and Error
2343
2344impl fmt::Display for RtypeBitmapError {
2345    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2346        match *self {
2347            RtypeBitmapError::ShortInput => ParseError::ShortInput.fmt(f),
2348            RtypeBitmapError::BadRtypeBitmap => {
2349                f.write_str("invalid record type bitmap")
2350            }
2351        }
2352    }
2353}
2354
2355#[cfg(feature = "std")]
2356impl std::error::Error for RtypeBitmapError {}
2357
2358//------------ Friendly Helper Functions -------------------------------------
2359
2360/// Splits an Rtype value into window number, octet number, and octet mask.
2361fn split_rtype(rtype: Rtype) -> (u8, usize, u8) {
2362    let rtype = rtype.to_int();
2363    (
2364        (rtype >> 8) as u8,
2365        ((rtype & 0xFF) >> 3) as usize,
2366        0b1000_0000 >> (rtype & 0x07),
2367    )
2368}
2369
2370/// Splits the next bitmap window from the bitmap and returns None when there's no next window.
2371#[allow(clippy::type_complexity)]
2372fn read_window(data: &[u8]) -> Option<((u8, &[u8]), &[u8])> {
2373    data.split_first().and_then(|(n, data)| {
2374        data.split_first().and_then(|(l, data)| {
2375            if data.len() >= usize::from(*l) {
2376                let (window, data) = data.split_at(usize::from(*l));
2377                Some(((*n, window), data))
2378            } else {
2379                None
2380            }
2381        })
2382    })
2383}
2384
2385//============ Test ==========================================================
2386
2387#[cfg(test)]
2388#[cfg(all(feature = "std", feature = "bytes"))]
2389mod test {
2390    use super::*;
2391    use crate::base::iana::Rtype;
2392    use crate::base::name::Dname;
2393    use crate::base::rdata::test::{
2394        test_compose_parse, test_rdlen, test_scan,
2395    };
2396    use core::str::FromStr;
2397    use std::vec::Vec;
2398
2399    //--- Dnskey
2400
2401    #[test]
2402    #[allow(clippy::redundant_closure)] // lifetimes ...
2403    fn dnskey_compose_parse_scan() {
2404        let rdata = Dnskey::new(10, 11, SecAlg::RsaSha1, b"key0").unwrap();
2405        test_rdlen(&rdata);
2406        test_compose_parse(&rdata, |parser| Dnskey::parse(parser));
2407        test_scan(&["10", "11", "RSASHA1", "a2V5MA=="], Dnskey::scan, &rdata);
2408    }
2409
2410    //--- Rrsig
2411
2412    #[test]
2413    #[allow(clippy::redundant_closure)] // lifetimes ...
2414    fn rrsig_compose_parse_scan() {
2415        let rdata = Rrsig::new(
2416            Rtype::A,
2417            SecAlg::RsaSha1,
2418            3,
2419            Ttl::from_secs(12),
2420            Serial::from(13),
2421            Serial::from(14),
2422            15,
2423            Dname::<Vec<u8>>::from_str("example.com.").unwrap(),
2424            b"key",
2425        )
2426        .unwrap();
2427        test_rdlen(&rdata);
2428        test_compose_parse(&rdata, |parser| Rrsig::parse(parser));
2429        test_scan(
2430            &[
2431                "A",
2432                "RSASHA1",
2433                "3",
2434                "12",
2435                "13",
2436                "14",
2437                "15",
2438                "example.com.",
2439                "a2V5",
2440            ],
2441            Rrsig::scan,
2442            &rdata,
2443        );
2444    }
2445
2446    //--- Nsec
2447
2448    #[test]
2449    #[allow(clippy::redundant_closure)] // lifetimes ...
2450    fn nsec_compose_parse_scan() {
2451        let mut rtype = RtypeBitmapBuilder::new_vec();
2452        rtype.add(Rtype::A).unwrap();
2453        rtype.add(Rtype::Srv).unwrap();
2454        let rdata = Nsec::new(
2455            Dname::<Vec<u8>>::from_str("example.com.").unwrap(),
2456            rtype.finalize(),
2457        );
2458        test_rdlen(&rdata);
2459        test_compose_parse(&rdata, |parser| Nsec::parse(parser));
2460        test_scan(&["example.com.", "A", "SRV"], Nsec::scan, &rdata);
2461    }
2462
2463    //--- Ds
2464
2465    #[test]
2466    #[allow(clippy::redundant_closure)] // lifetimes ...
2467    fn ds_compose_parse_scan() {
2468        let rdata =
2469            Ds::new(10, SecAlg::RsaSha1, DigestAlg::Sha256, b"key").unwrap();
2470        test_rdlen(&rdata);
2471        test_compose_parse(&rdata, |parser| Ds::parse(parser));
2472        test_scan(&["10", "RSASHA1", "2", "6b6579"], Ds::scan, &rdata);
2473    }
2474
2475    //--- RtypeBitmape
2476
2477    #[test]
2478    fn rtype_split() {
2479        assert_eq!(split_rtype(Rtype::A), (0, 0, 0b01000000));
2480        assert_eq!(split_rtype(Rtype::Ns), (0, 0, 0b00100000));
2481        assert_eq!(split_rtype(Rtype::Caa), (1, 0, 0b01000000));
2482    }
2483
2484    #[test]
2485    fn rtype_bitmap_read_window() {
2486        let mut builder = RtypeBitmapBuilder::new_vec();
2487        builder.add(Rtype::A).unwrap();
2488        builder.add(Rtype::Caa).unwrap();
2489        let bitmap = builder.finalize();
2490
2491        let ((n, window), data) = read_window(bitmap.as_slice()).unwrap();
2492        assert_eq!((n, window), (0u8, b"\x40".as_ref()));
2493        let ((n, window), data) = read_window(data).unwrap();
2494        assert_eq!((n, window), (1u8, b"\x40".as_ref()));
2495        assert!(data.is_empty());
2496        assert!(read_window(data).is_none());
2497    }
2498
2499    #[test]
2500    fn rtype_bitmap_builder() {
2501        let mut builder = RtypeBitmapBuilder::new_vec();
2502        builder.add(Rtype::Int(1234)).unwrap(); // 0x04D2
2503        builder.add(Rtype::A).unwrap(); // 0x0001
2504        builder.add(Rtype::Mx).unwrap(); // 0x000F
2505        builder.add(Rtype::Rrsig).unwrap(); // 0x002E
2506        builder.add(Rtype::Nsec).unwrap(); // 0x002F
2507        let bitmap = builder.finalize();
2508        assert_eq!(
2509            bitmap.as_slice(),
2510            &b"\x00\x06\x40\x01\x00\x00\x00\x03\
2511                     \x04\x1b\x00\x00\x00\x00\x00\x00\
2512                     \x00\x00\x00\x00\x00\x00\x00\x00\
2513                     \x00\x00\x00\x00\x00\x00\x00\x00\
2514                     \x00\x00\x00\x00\x20"[..]
2515        );
2516
2517        assert!(bitmap.contains(Rtype::A));
2518        assert!(bitmap.contains(Rtype::Mx));
2519        assert!(bitmap.contains(Rtype::Rrsig));
2520        assert!(bitmap.contains(Rtype::Nsec));
2521        assert!(bitmap.contains(Rtype::Int(1234)));
2522        assert!(!bitmap.contains(Rtype::Int(1235)));
2523        assert!(!bitmap.contains(Rtype::Ns));
2524    }
2525
2526    #[test]
2527    fn rtype_bitmap_iter() {
2528        use std::vec::Vec;
2529
2530        let mut builder = RtypeBitmapBuilder::new_vec();
2531        let types = vec![
2532            Rtype::Ns,
2533            Rtype::Soa,
2534            Rtype::Mx,
2535            Rtype::Txt,
2536            Rtype::Rrsig,
2537            Rtype::Dnskey,
2538            Rtype::Nsec3param,
2539            Rtype::Spf,
2540            Rtype::Caa,
2541        ];
2542        for t in types.iter() {
2543            builder.add(*t).unwrap();
2544        }
2545
2546        let bitmap = builder.finalize();
2547        let bitmap_types: Vec<_> = bitmap.iter().collect();
2548        assert_eq!(types, bitmap_types);
2549    }
2550
2551    #[test]
2552    fn dnskey_key_tag() {
2553        assert_eq!(
2554            Dnskey::new(
2555                256,
2556                3,
2557                SecAlg::RsaSha256,
2558                base64::decode::<Vec<u8>>(
2559                    "AwEAAcTQyaIe6nt3xSPOG2L/YfwBkOVTJN6mlnZ249O5Rtt3ZSRQHxQS\
2560                     W61AODYw6bvgxrrGq8eeOuenFjcSYgNAMcBYoEYYmKDW6e9EryW4ZaT/\
2561                     MCq+8Am06oR40xAA3fClOM6QjRcT85tP41Go946AicBGP8XOP/Aj1aI/\
2562                     oPRGzRnboUPUok/AzTNnW5npBU69+BuiIwYE7mQOiNBFePyvjQBdoiuY\
2563                     bmuD3Py0IyjlBxzZUXbqLsRL9gYFkCqeTY29Ik7usuzMTa+JRSLz6KGS\
2564                     5RSJ7CTSMjZg8aNaUbN2dvGhakJPh92HnLvMA3TefFgbKJphFNPA3BWS\
2565                     KLZ02cRWXqM="
2566                )
2567                .unwrap()
2568            ).unwrap()
2569            .key_tag(),
2570            59944
2571        );
2572        assert_eq!(
2573            Dnskey::new(
2574                257,
2575                3,
2576                SecAlg::RsaSha256,
2577                base64::decode::<Vec<u8>>(
2578                    "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTO\
2579                    iW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN\
2580                    7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5\
2581                    LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8\
2582                    efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7\
2583                    pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLY\
2584                    A4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws\
2585                    9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU="
2586                )
2587                .unwrap()
2588            )
2589            .unwrap()
2590            .key_tag(),
2591            20326
2592        );
2593        assert_eq!(
2594            Dnskey::new(
2595                257,
2596                3,
2597                SecAlg::RsaMd5,
2598                base64::decode::<Vec<u8>>(
2599                    "AwEAAcVaA4jSBIGRrSzpecoJELvKE9+OMuFnL8mmUBsY\
2600                    lB6epN1CqX7NzwjDpi6VySiEXr0C4uTYkU/L1uMv2mHE\
2601                    AljThFDJ1GuozJ6gA7jf3lnaGppRg2IoVQ9IVmLORmjw\
2602                    C+7Eoi12SqybMTicD3Ezwa9XbG1iPjmjhbMrLh7MSQpX"
2603                )
2604                .unwrap()
2605            )
2606            .unwrap()
2607            .key_tag(),
2608            18698
2609        );
2610    }
2611
2612    #[test]
2613    fn dnskey_flags() {
2614        let dnskey =
2615            Dnskey::new(257, 3, SecAlg::RsaSha256, bytes::Bytes::new())
2616                .unwrap();
2617        assert!(dnskey.is_zsk());
2618        assert!(dnskey.is_secure_entry_point());
2619        assert!(!dnskey.is_revoked());
2620    }
2621}