domain_core/rdata/
rfc5155.rs

1//! Record data from [RFC 5155].
2//!
3//! This RFC defines the NSEC3 and NSEC3PARAM resource records.
4//!
5//! [RFC 5155]: https://tools.ietf.org/html/rfc5155
6
7use std::fmt;
8use bytes::BufMut;
9use ::bits::charstr::CharStr;
10use ::bits::compose::{Compose, Compress, Compressor};
11use ::bits::parse::{Parse, ParseAll, ParseAllError, Parser, ShortBuf};
12use ::bits::rdata::RtypeRecordData;
13use ::iana::{Nsec3HashAlg, Rtype};
14use ::master::scan::{CharSource, Scan, Scanner, ScanError, SyntaxError};
15use ::utils::base32;
16use super::rfc4034::{RtypeBitmap, RtypeBitmapError};
17
18
19//------------ Nsec3 ---------------------------------------------------------
20
21#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
22pub struct Nsec3 {
23    hash_algorithm: Nsec3HashAlg,
24    flags: u8,
25    iterations: u16,
26    salt: CharStr,
27    next_owner: CharStr,
28    types: RtypeBitmap,
29}
30
31impl Nsec3 {
32    pub fn new(
33        hash_algorithm: Nsec3HashAlg,
34        flags: u8,
35        iterations: u16,
36        salt: CharStr,
37        next_owner: CharStr,
38        types: RtypeBitmap
39    ) -> Self {
40        Nsec3 { hash_algorithm, flags, iterations, salt, next_owner, types }
41    }
42
43    pub fn hash_algorithm(&self) -> Nsec3HashAlg {
44        self.hash_algorithm
45    }
46
47    pub fn flags(&self) -> u8 { 
48        self.flags
49    }
50
51    pub fn opt_out(&self) -> bool {
52        self.flags & 0x01 != 0
53    }
54
55    pub fn iterations(&self) -> u16 {
56        self.iterations
57    }
58
59    pub fn salt(&self) -> &CharStr {
60        &self.salt
61    }
62
63    pub fn next_owner(&self) -> &CharStr {
64        &self.next_owner
65    }
66
67    pub fn types(&self) -> &RtypeBitmap {
68        &self.types
69    }
70}
71
72
73//--- ParseAll, Compose, Compress
74
75impl ParseAll for Nsec3 {
76    type Err = ParseNsec3Error;
77
78    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
79        if len < 6 {
80            return Err(ShortBuf.into())
81        }
82        let start = parser.pos();
83        let hash_algorithm = Nsec3HashAlg::parse(parser)?;
84        let flags = u8::parse(parser)?;
85        let iterations = u16:: parse(parser)?;
86        let salt = CharStr::parse(parser)?;
87        let next_owner = CharStr::parse(parser)?;
88        let len = if parser.pos() > start + len {
89            return Err(ShortBuf.into())
90        }
91        else {
92            len - (parser.pos() - start)
93        };
94        let types = RtypeBitmap::parse_all(parser, len)?;
95        Ok(Self::new(
96            hash_algorithm, flags, iterations, salt, next_owner, types
97        ))
98    }
99}
100
101impl Compose for Nsec3 {
102    fn compose_len(&self) -> usize {
103        4 + self.salt.compose_len() + self.next_owner.compose_len() +
104            self.types.compose_len()
105    }
106
107    fn compose<B: BufMut>(&self, buf: &mut B) {
108        self.hash_algorithm.compose(buf);
109        self.flags.compose(buf);
110        self.iterations.compose(buf);
111        self.salt.compose(buf);
112        self.next_owner.compose(buf);
113        self.types.compose(buf);
114    }
115}
116
117impl Compress for Nsec3 {
118    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
119        buf.compose(self)
120    }
121}
122
123
124//------------ Scan and Display ----------------------------------------------
125
126impl Scan for Nsec3 {
127    fn scan<C: CharSource>(
128        scanner: &mut Scanner<C>
129    ) -> Result<Self, ScanError> {
130        Ok(Self::new(
131            Nsec3HashAlg::scan(scanner)?,
132            u8::scan(scanner)?,
133            u16::scan(scanner)?,
134            scan_salt(scanner)?,
135            scan_hash(scanner)?,
136            RtypeBitmap::scan(scanner)?
137        ))
138    }
139}
140
141fn scan_salt<C: CharSource>(
142    scanner: &mut Scanner<C>
143) -> Result<CharStr, ScanError> {
144    if let Ok(()) = scanner.skip_literal("-") {    
145        Ok(CharStr::empty())
146    }
147    else {
148        CharStr::scan_hex(scanner)
149    }
150}
151
152fn scan_hash<C: CharSource>(
153    scanner: &mut Scanner<C>
154) -> Result<CharStr, ScanError> {
155    scanner.scan_base32hex_phrase(|bytes| {
156        CharStr::from_bytes(bytes).map_err(SyntaxError::content)
157    })
158}
159
160impl fmt::Display for Nsec3 {
161    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
162        write!(f, "{} {} {} ", self.hash_algorithm, self.flags,
163               self.iterations)?;
164        self.salt.display_hex(f)?;
165        base32::display_hex(&self.next_owner, f)?;
166        write!(f, " {}", self.types)
167    }
168}
169
170
171//--- RtypeRecordData
172
173impl RtypeRecordData for Nsec3 {
174    const RTYPE: Rtype = Rtype::Nsec3;
175}
176
177
178//------------ Nsec3param ----------------------------------------------------
179
180
181#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
182pub struct Nsec3param {
183    hash_algorithm: Nsec3HashAlg,
184    flags: u8,
185    iterations: u16,
186    salt: CharStr,
187}
188
189impl Nsec3param {
190    pub fn new(
191        hash_algorithm: Nsec3HashAlg,
192        flags: u8,
193        iterations: u16,
194        salt: CharStr
195    ) -> Self {
196        Nsec3param { hash_algorithm, flags, iterations, salt } 
197    }
198
199    pub fn hash_algorithm(&self) -> Nsec3HashAlg {
200        self.hash_algorithm
201    }
202
203    pub fn flags(&self) -> u8 {
204        self.flags
205    }
206
207    pub fn iterations(&self) -> u16 {
208        self.iterations
209    }
210
211    pub fn salt(&self) -> &CharStr {
212        &self.salt
213    }
214}
215
216
217//--- Parse, ParseAll, Compose, Compres
218
219impl Parse for Nsec3param {
220    type Err = ShortBuf;
221
222    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
223        Ok(Self::new(
224            Nsec3HashAlg::parse(parser)?,
225            u8::parse(parser)?,
226            u16::parse(parser)?,
227            CharStr::parse(parser)?,
228        ))
229    }
230
231    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
232        parser.advance(4)?;
233        CharStr::skip(parser)
234    }
235}
236
237impl ParseAll for Nsec3param {
238    type Err = ParseAllError;
239
240    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
241        if len < 5 {
242            return Err(ParseAllError::ShortField)
243        }
244        Ok(Self::new(
245            Nsec3HashAlg::parse(parser)?,
246            u8::parse(parser)?,
247            u16::parse(parser)?,
248            CharStr::parse_all(parser, len - 4)?,
249        ))
250    }
251}
252
253impl Compose for Nsec3param {
254    fn compose_len(&self) -> usize {
255        4 + self.salt.compose_len()
256    }
257
258    fn compose<B: BufMut>(&self, buf: &mut B) {
259        self.hash_algorithm.compose(buf);
260        self.flags.compose(buf);
261        self.iterations.compose(buf);
262        self.salt.compose(buf);
263    }
264}
265
266impl Compress for Nsec3param {
267    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
268        buf.compose(self)
269    }
270}
271
272
273//--- Scan and Display
274
275impl Scan for Nsec3param {
276    fn scan<C: CharSource>(
277        scanner: &mut Scanner<C>
278    ) -> Result<Self, ScanError> {
279        Ok(Self::new(
280            Nsec3HashAlg::scan(scanner)?,
281            u8::scan(scanner)?,
282            u16::scan(scanner)?,
283            scan_salt(scanner)?
284        ))
285    }
286}
287
288impl fmt::Display for Nsec3param {
289    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
290        write!(f, "{} {} {} ", self.hash_algorithm, self.flags,
291               self.iterations)?;
292        self.salt.display_hex(f)
293    }
294}
295
296
297//--- RtypeRecordData
298
299impl RtypeRecordData for Nsec3param {
300    const RTYPE: Rtype = Rtype::Nsec3param;
301}
302
303
304//------------ ParseNsec3Error -----------------------------------------------
305
306#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
307pub enum ParseNsec3Error {
308    #[fail(display="short field")]
309    ShortField,
310
311    #[fail(display="invalid record type bitmap")]
312    BadRtypeBitmap,
313}
314
315impl From<ShortBuf> for ParseNsec3Error {
316    fn from(_: ShortBuf) -> Self {
317        ParseNsec3Error::ShortField
318    }
319}
320
321impl From<RtypeBitmapError> for ParseNsec3Error {
322    fn from(err: RtypeBitmapError) -> Self {
323        match err {
324            RtypeBitmapError::ShortBuf => ParseNsec3Error::ShortField,
325            RtypeBitmapError::BadRtypeBitmap => ParseNsec3Error::BadRtypeBitmap
326        }
327    }
328}
329
330
331//------------ parsed --------------------------------------------------------
332
333pub mod parsed {
334    pub use super::{Nsec3, Nsec3param};
335}
336