1#[macro_use] mod macros;
27opt_types!{
28 rfc5001::{Nsid};
29 rfc6975::{Dau, Dhu, N3u};
30 rfc7314::{Expire};
31 rfc7828::{TcpKeepalive};
32 rfc7830::{Padding};
33 rfc7871::{ClientSubnet};
34 rfc7873::{Cookie};
35 rfc7901::{Chain};
36 rfc8145::{KeyTag};
37}
38
39
40use std::{fmt, mem, ops};
43use std::marker::PhantomData;
44use bytes::{BigEndian, BufMut, ByteOrder, Bytes};
45use ::iana::{OptionCode, OptRcode, Rtype};
46use super::compose::{Compose, Compress, Compressor};
47use super::header::Header;
48use super::name::ToDname;
49use super::parse::{Parse, ParseAll, Parser, ShortBuf};
50use super::rdata::RtypeRecordData;
51use super::record::Record;
52
53
54#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
63pub struct Opt {
64 bytes: Bytes,
65}
66
67impl Opt {
68 pub fn from_bytes(bytes: Bytes) -> Result<Self, ShortBuf> {
73 let mut parser = Parser::from_bytes(bytes);
74 while parser.remaining() > 0 {
75 parser.advance(2)?;
76 let len = parser.parse_u16()?;
77 parser.advance(len as usize)?;
78 }
79 Ok(Opt { bytes: parser.unwrap() })
80 }
81
82 pub fn iter<D: OptData>(&self) -> OptIter<D> {
87 OptIter::new(self.bytes.clone())
88 }
89}
90
91
92impl ParseAll for Opt {
95 type Err = ShortBuf;
96
97 fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
98 Self::from_bytes(parser.parse_bytes(len)?)
99 }
100}
101
102impl Compose for Opt {
103 fn compose_len(&self) -> usize {
104 self.bytes.len()
105 }
106
107 fn compose<B: BufMut>(&self, buf: &mut B) {
108 buf.put_slice(self.bytes.as_ref())
109 }
110}
111
112impl Compress for Opt {
113 fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
114 buf.compose(self)
115 }
116}
117
118impl RtypeRecordData for Opt {
119 const RTYPE: Rtype = Rtype::Opt;
120}
121
122
123impl fmt::Display for Opt {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 f.write_str("OPT ...")
129 }
130}
131
132
133#[derive(Copy, Clone, Debug, Eq, PartialEq)]
154pub struct OptHeader {
155 inner: [u8; 9],
157}
158
159impl OptHeader {
160 pub fn for_record_slice(slice: &[u8]) -> &OptHeader {
161 assert!(slice.len() >= mem::size_of::<Self>());
162 unsafe { &*(slice.as_ptr() as *const OptHeader) }
163 }
164
165 pub fn for_record_slice_mut(slice: &mut [u8]) -> &mut OptHeader {
166 assert!(slice.len() >= mem::size_of::<Self>());
167 unsafe { &mut *(slice.as_ptr() as *mut OptHeader) }
168 }
169
170 pub fn udp_payload_size(&self) -> u16 {
171 BigEndian::read_u16(&self.inner[3..])
172 }
173
174 pub fn set_udp_payload_size(&mut self, value: u16) {
175 BigEndian::write_u16(&mut self.inner[3..], value)
176 }
177
178 pub fn rcode(&self, header: Header) -> OptRcode {
179 OptRcode::from_parts(header.rcode(), self.inner[5])
180 }
181
182 pub fn set_rcode(&mut self, rcode: OptRcode) {
183 self.inner[5] = rcode.ext()
184 }
185
186 pub fn version(&self) -> u8 {
187 self.inner[6]
188 }
189
190 pub fn set_version(&mut self, version: u8) {
191 self.inner[6] = version
192 }
193
194 pub fn dnssec_ok(&self) -> bool {
195 self.inner[7] & 0x80 != 0
196 }
197
198 pub fn set_dnssec_ok(&mut self, value: bool) {
199 if value {
200 self.inner[7] |= 0x80
201 }
202 else {
203 self.inner[7] &= 0x7F
204 }
205 }
206}
207
208impl Default for OptHeader {
209 fn default() -> Self {
210 OptHeader { inner: [0, 0, 41, 0, 0, 0, 0, 0, 0] }
211 }
212}
213
214impl Compose for OptHeader {
215 fn compose_len(&self) -> usize {
216 9
217 }
218
219 fn compose<B: BufMut>(&self, buf: &mut B) {
220 buf.put_slice(&self.inner)
221 }
222}
223
224
225#[derive(Clone, Debug)]
229pub struct OptRecord {
230 udp_payload_size: u16,
231 ext_rcode: u8,
232 version: u8,
233 flags: u16,
234 data: Opt,
235}
236
237impl OptRecord {
238 pub fn from_record<N: ToDname>(record: Record<N, Opt>) -> Self {
239 OptRecord {
240 udp_payload_size: record.class().to_int(),
241 ext_rcode: (record.ttl() >> 24) as u8,
242 version: (record.ttl() >> 16) as u8,
243 flags: record.ttl() as u16,
244 data: record.into_data()
245 }
246 }
247
248 pub fn udp_payload_size(&self) -> u16 {
249 self.udp_payload_size
250 }
251
252 pub fn rcode(&self, header: Header) -> OptRcode {
253 OptRcode::from_parts(header.rcode(), self.ext_rcode)
254 }
255
256 pub fn version(&self) -> u8 {
257 self.version
258 }
259
260 pub fn dnssec_ok(&self) -> bool {
261 self.flags & 0x8000 != 0
262 }
263
264 pub fn as_opt(&self) -> &Opt {
265 &self.data
266 }
267}
268
269
270impl<N: ToDname> From<Record<N, Opt>> for OptRecord {
273 fn from(record: Record<N, Opt>) -> Self {
274 Self::from_record(record)
275 }
276}
277
278
279impl ops::Deref for OptRecord {
282 type Target = Opt;
283
284 fn deref(&self) -> &Opt {
285 &self.data
286 }
287}
288
289impl AsRef<Opt> for OptRecord {
290 fn as_ref(&self) -> &Opt {
291 &self.data
292 }
293}
294
295
296#[derive(Clone, Debug)]
299pub struct OptionHeader {
300 code: u16,
301 len: u16,
302}
303
304#[allow(len_without_is_empty)]
305impl OptionHeader {
306 pub fn new(code: u16, len: u16) -> Self {
307 OptionHeader { code, len }
308 }
309
310 pub fn code(&self) -> u16 {
311 self.code
312 }
313
314 pub fn len(&self) -> u16 {
315 self.len
316 }
317}
318
319impl Parse for OptionHeader {
320 type Err = ShortBuf;
321
322 fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
323 Ok(OptionHeader::new(parser.parse_u16()?, parser.parse_u16()?))
324 }
325
326 fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
327 parser.advance(4)
328 }
329}
330
331impl Compose for OptionHeader {
332 fn compose_len(&self) -> usize {
333 4
334 }
335
336 fn compose<B: BufMut>(&self, buf: &mut B) {
337 self.code.compose(buf);
338 self.len.compose(buf);
339 }
340}
341
342
343#[derive(Clone, Debug)]
346pub struct OptIter<D: OptData> {
347 parser: Parser,
348 marker: PhantomData<D>
349}
350
351impl<D: OptData> OptIter<D> {
352 fn new(bytes: Bytes) -> Self {
353 OptIter { parser: Parser::from_bytes(bytes), marker: PhantomData }
354 }
355}
356
357impl<D: OptData> Iterator for OptIter<D> {
358 type Item = Result<D, D::ParseErr>;
359
360 fn next(&mut self) -> Option<Self::Item> {
361 while self.parser.remaining() > 0 {
362 match self.next_step() {
363 Ok(Some(res)) => return Some(Ok(res)),
364 Ok(None) => { }
365 Err(err) => return Some(Err(err)),
366 }
367 }
368 None
369 }
370}
371
372impl<D: OptData> OptIter<D> {
373 fn next_step(&mut self) -> Result<Option<D>, D::ParseErr> {
374 let code = self.parser.parse_u16().unwrap().into();
375 let len = self.parser.parse_u16().unwrap() as usize;
376 D::parse_option(code, &mut self.parser, len)
377 }
378}
379
380
381pub trait OptData: Compose + Sized {
384 type ParseErr;
385
386 fn code(&self) -> OptionCode;
387
388 fn parse_option(code: OptionCode, parser: &mut Parser, len: usize)
389 -> Result<Option<Self>, Self::ParseErr>;
390}
391
392
393pub trait CodeOptData {
396 const CODE: OptionCode;
397}
398
399impl<T: CodeOptData + ParseAll + Compose + Sized> OptData for T {
400 type ParseErr = <Self as ParseAll>::Err;
401
402 fn code(&self) -> OptionCode { Self::CODE }
403
404 fn parse_option(code: OptionCode, parser: &mut Parser, len: usize)
405 -> Result<Option<Self>, Self::ParseErr> {
406 if code == Self::CODE {
407 Self::parse_all(parser, len).map(Some)
408 }
409 else {
410 Ok(None)
411 }
412 }
413}
414
415
416#[derive(Clone, Debug)]
419pub struct UnknownOptData {
420 code: OptionCode,
421 data: Bytes,
422}
423
424impl UnknownOptData {
425 pub fn from_bytes(code: OptionCode, data: Bytes) -> Self {
426 UnknownOptData { code, data }
427 }
428
429 pub fn code(&self) -> OptionCode {
430 self.code
431 }
432
433 pub fn data(&self) -> &Bytes {
434 &self.data
435 }
436}
437
438
439impl Compose for UnknownOptData {
442 fn compose_len(&self) -> usize {
443 self.data.len()
444 }
445
446 fn compose<B: BufMut>(&self, buf: &mut B) {
447 buf.put_slice(self.data.as_ref())
448 }
449}
450
451
452impl OptData for UnknownOptData {
455 type ParseErr = ShortBuf;
456
457 fn code(&self) -> OptionCode {
458 self.code
459 }
460
461 fn parse_option(
462 code: OptionCode,
463 parser: &mut Parser,
464 len: usize
465 ) -> Result<Option<Self>, Self::ParseErr> {
466 parser.parse_bytes(len)
467 .map(|data| Some(Self::from_bytes(code, data)))
468 }
469}
470
471
472#[cfg(test)]
475mod test {
476 use super::*;
477 use super::super::record::ParsedRecord;
478
479 #[test]
480 fn opt_record_header() {
481 let mut header = OptHeader::default();
482 header.set_udp_payload_size(0x1234);
483 header.set_rcode(OptRcode::BadVers);
484 header.set_version(0xbd);
485 header.set_dnssec_ok(true);
486 let mut buf = Vec::with_capacity(11);
487 header.compose(&mut buf);
488 0u16.compose(&mut buf);
489 let mut buf = Parser::from_bytes(buf.into());
490 let record = ParsedRecord::parse(&mut buf).unwrap()
491 .into_record::<Opt>().unwrap().unwrap();
492 let record = OptRecord::from_record(record);
493 assert_eq!(record.udp_payload_size(), 0x1234);
494 assert_eq!(record.ext_rcode, OptRcode::BadVers.ext());
495 assert_eq!(record.version(), 0xbd);
496 assert!(record.dnssec_ok());
497 }
498}
499