1use 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#[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
73impl 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
124impl 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
171impl RtypeRecordData for Nsec3 {
174 const RTYPE: Rtype = Rtype::Nsec3;
175}
176
177
178#[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
217impl 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
273impl 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
297impl RtypeRecordData for Nsec3param {
300 const RTYPE: Rtype = Rtype::Nsec3param;
301}
302
303
304#[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
331pub mod parsed {
334 pub use super::{Nsec3, Nsec3param};
335}
336