domain_core/rdata/
rfc1035.rs

1//! Record data from [RFC 1035].
2//!
3//! This RFC defines the initial set of record types.
4//!
5//! [RFC 1035]: https://tools.ietf.org/html/rfc1035
6
7use std::{fmt, ops};
8use std::net::Ipv4Addr;
9use std::str::FromStr;
10use bytes::{BufMut, Bytes, BytesMut};
11use ::iana::Rtype;
12use ::bits::charstr::CharStr;
13use ::bits::compose::{Compose, Compress, Compressor};
14use ::bits::name::ParsedDname;
15use ::bits::parse::{ParseAll, ParseAllError, ParseOpenError, Parse,
16                    Parser, ShortBuf};
17use ::bits::rdata::RtypeRecordData;
18use ::bits::serial::Serial;
19use ::master::scan::{CharSource, ScanError, Scan, Scanner};
20
21
22//------------ dname_type! --------------------------------------------------
23
24/// A macro for implementing a record data type with a single domain name.
25///
26/// Implements some basic methods plus the `RecordData`, `FlatRecordData`,
27/// and `Display` traits.
28macro_rules! dname_type {
29    ($target:ident, $rtype:ident, $field:ident) => {
30        #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
31        pub struct $target<N> {
32            $field: N
33        }
34
35        impl<N> $target<N> {
36            pub fn new($field: N) -> Self {
37                $target { $field: $field }
38            }
39
40            pub fn $field(&self) -> &N {
41                &self.$field
42            }
43        }
44
45        //--- From and FromStr
46
47        impl<N> From<N> for $target<N> {
48            fn from(name: N) -> Self {
49                Self::new(name)
50            }
51        }
52
53        impl<N: FromStr> FromStr for $target<N> {
54            type Err = N::Err;
55
56            fn from_str(s: &str) -> Result<Self, Self::Err> {
57                N::from_str(s).map(Self::new)
58            }
59        }
60
61        
62        //--- Parse, ParseAll, Compose, and Compress
63
64        impl Parse for $target<ParsedDname> {
65            type Err = <ParsedDname as Parse>::Err;
66
67            fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
68                ParsedDname::parse(parser).map(Self::new)
69            }
70
71            fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
72                ParsedDname::skip(parser).map_err(Into::into)
73            }
74        }
75
76        impl ParseAll for $target<ParsedDname> {
77            type Err = <ParsedDname as ParseAll>::Err;
78
79            fn parse_all(parser: &mut Parser, len: usize)
80                         -> Result<Self, Self::Err> {
81                ParsedDname::parse_all(parser, len).map(Self::new)
82            }
83        }
84
85        impl<N: Compose> Compose for $target<N> {
86            fn compose_len(&self) -> usize {
87                self.$field.compose_len()
88            }
89        
90            fn compose<B: BufMut>(&self, buf: &mut B) {
91                self.$field.compose(buf)
92            }
93        }
94
95        impl<N: Compress> Compress for $target<N> {
96            fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
97                self.$field.compress(buf)
98            }
99        }
100
101
102        //--- Scan and Display
103
104        impl<N: Scan> Scan for $target<N> {
105            fn scan<C: CharSource>(scanner: &mut Scanner<C>)
106                                   -> Result<Self, ScanError> {
107                N::scan(scanner).map(Self::new)
108            }
109        }
110
111        impl<N: fmt::Display> fmt::Display for $target<N> {
112            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113                write!(f, "{}.", self.$field)
114            }
115        }
116
117
118        //--- RtypeRecordData
119
120        impl<N> RtypeRecordData for $target<N> {
121            const RTYPE: Rtype = Rtype::$rtype;
122        }
123
124
125        //--- Deref
126
127        impl<N> ops::Deref for $target<N> {
128            type Target = N;
129
130            fn deref(&self) -> &Self::Target {
131                &self.$field
132            }
133        }
134    }
135}
136
137
138//------------ A ------------------------------------------------------------
139
140/// A record data.
141///
142/// A records convey the IPv4 address of a host. The wire format is the 32
143/// bit IPv4 address in network byte order. The master file format is the
144/// usual dotted notation.
145///
146/// The A record type is defined in RFC 1035, section 3.4.1.
147#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
148pub struct A {
149    addr: Ipv4Addr,
150}
151
152impl A {
153    /// Creates a new A record data from an IPv4 address.
154    pub fn new(addr: Ipv4Addr) -> A {
155        A { addr }
156    }
157
158    /// Creates a new A record from the IPv4 address components.
159    pub fn from_octets(a: u8, b: u8, c: u8, d: u8) -> A {
160        A::new(Ipv4Addr::new(a, b, c, d))
161    }
162
163    pub fn addr(&self) -> Ipv4Addr { self.addr }
164    pub fn set_addr(&mut self, addr: Ipv4Addr) { self.addr = addr }
165}
166
167
168//--- From and FromStr
169
170impl From<Ipv4Addr> for A {
171    fn from(addr: Ipv4Addr) -> Self {
172        Self::new(addr)
173    }
174}
175
176impl From<A> for Ipv4Addr {
177    fn from(a: A) -> Self {
178        a.addr
179    }
180}
181
182impl FromStr for A {
183    type Err = <Ipv4Addr as FromStr>::Err;
184
185    fn from_str(s: &str) -> Result<Self, Self::Err> {
186        Ipv4Addr::from_str(s).map(A::new)
187    }
188}
189
190
191//--- Parse, ParseAll, Compose, and Compress
192
193impl Parse for A {
194    type Err = <Ipv4Addr as Parse>::Err;
195
196    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
197        Ipv4Addr::parse(parser).map(Self::new)
198    }
199
200    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
201        Ipv4Addr::skip(parser)?;
202        Ok(())
203    }
204}
205
206impl ParseAll for A {
207    type Err = <Ipv4Addr as ParseAll>::Err;
208
209    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
210        Ipv4Addr::parse_all(parser, len).map(Self::new)
211    }
212}
213
214impl Compose for A {
215    fn compose_len(&self) -> usize {
216        4
217    }
218
219    fn compose<B: BufMut>(&self, buf: &mut B) {
220        self.addr.compose(buf)
221    }
222}
223
224impl Compress for A {
225    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
226        buf.compose(self)
227    }
228}
229
230
231//--- Scan and Display
232
233impl Scan for A {
234    fn scan<C: CharSource>(scanner: &mut Scanner<C>)
235                           -> Result<Self, ScanError> {
236        scanner.scan_string_phrase(|res| A::from_str(&res).map_err(Into::into))
237    }
238}
239
240impl fmt::Display for A {
241    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
242        self.addr.fmt(f)
243    }
244}
245
246
247//--- RtypeRecordData
248
249impl RtypeRecordData for A {
250    const RTYPE: Rtype = Rtype::A;
251}
252
253
254//--- Deref and DerefMut
255
256impl ops::Deref for A {
257    type Target = Ipv4Addr;
258
259    fn deref(&self) -> &Self::Target {
260        &self.addr
261    }
262}
263
264impl ops::DerefMut for A {
265    fn deref_mut(&mut self) -> &mut Self::Target {
266        &mut self.addr
267    }
268}
269
270
271//--- AsRef and AsMut
272
273impl AsRef<Ipv4Addr> for A {
274    fn as_ref(&self) -> &Ipv4Addr {
275        &self.addr
276    }
277}
278
279impl AsMut<Ipv4Addr> for A {
280    fn as_mut(&mut self) -> &mut Ipv4Addr {
281        &mut self.addr
282    }
283}
284
285
286//------------ Cname --------------------------------------------------------
287
288/// CNAME record data.
289///
290/// The CNAME record specifies the canonical or primary name for domain
291/// name alias.
292///
293/// The CNAME type is defined in RFC 1035, section 3.3.1.
294dname_type!(Cname, Cname, cname);
295
296
297//------------ Hinfo --------------------------------------------------------
298
299/// Hinfo record data.
300///
301/// Hinfo records are used to acquire general information about a host,
302/// specifically the CPU type and operating system type.
303///
304/// The Hinfo type is defined in RFC 1035, section 3.3.2.
305#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
306pub struct Hinfo {
307    cpu: CharStr,
308    os: CharStr,
309}
310
311impl Hinfo {
312    /// Creates a new Hinfo record data from the components.
313    pub fn new(cpu: CharStr, os: CharStr) -> Self {
314        Hinfo { cpu, os }
315    }
316
317    /// The CPU type of the host.
318    pub fn cpu(&self) -> &CharStr {
319        &self.cpu
320    }
321
322    /// The operating system type of the host.
323    pub fn os(&self) -> &CharStr {
324        &self.os
325    }
326}
327
328//--- Parse, Compose, and Compress
329
330impl Parse for Hinfo {
331    type Err = ShortBuf;
332
333    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
334        Ok(Self::new(CharStr::parse(parser)?, CharStr::parse(parser)?))
335    }
336
337    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
338        CharStr::skip(parser)?;
339        CharStr::skip(parser)?;
340        Ok(())
341    }
342}
343
344impl ParseAll for Hinfo {
345    type Err = ParseAllError;
346
347    fn parse_all(parser: &mut Parser, len: usize)
348                    -> Result<Self, Self::Err> {
349        let cpu = CharStr::parse(parser)?;
350        let len = match len.checked_sub(cpu.len() + 1) {
351            Some(len) => len,
352            None => return Err(ParseAllError::ShortField)
353        };
354        let os = CharStr::parse_all(parser, len)?;
355        Ok(Hinfo::new(cpu, os))
356    }
357}
358
359impl Compose for Hinfo {
360    fn compose_len(&self) -> usize {
361        self.cpu.compose_len() + self.os.compose_len()
362    }
363
364    fn compose<B: BufMut>(&self, buf: &mut B) {
365        self.cpu.compose(buf);
366        self.os.compose(buf);
367    }
368}
369
370impl Compress for Hinfo {
371    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
372        buf.compose(self)
373    }
374}
375
376
377//--- Scan and Display
378
379impl Scan for Hinfo {
380    fn scan<C: CharSource>(scanner: &mut Scanner<C>)
381                           -> Result<Self, ScanError> {
382        Ok(Self::new(CharStr::scan(scanner)?, CharStr::scan(scanner)?))
383    }
384}
385
386impl fmt::Display for Hinfo {
387    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
388        write!(f, "{} {}", self.cpu, self.os)
389    }
390}
391
392
393//--- RtypeRecordData
394
395impl RtypeRecordData for Hinfo {
396    const RTYPE: Rtype = Rtype::Hinfo;
397}
398
399
400//------------ Mb -----------------------------------------------------------
401
402/// MB record data.
403///
404/// The experimental MB record specifies a host that serves a mailbox.
405///
406/// The MB record type is defined in RFC 1035, section 3.3.3.
407dname_type!(Mb, Mb, madname);
408
409
410//------------ Md -----------------------------------------------------------
411
412/// MD record data.
413///
414/// The MD record specifices a host which has a mail agent for
415/// the domain which should be able to deliver mail for the domain.
416/// 
417/// The MD record is obsolete. It is recommended to either reject the record
418/// or convert them into an Mx record at preference 0.
419///
420/// The MD record type is defined in RFC 1035, section 3.3.4.
421dname_type!(Md, Md, madname);
422
423
424//------------ Mf -----------------------------------------------------------
425
426/// MF record data.
427///
428/// The MF record specifices a host which has a mail agent for
429/// the domain which will be accept mail for forwarding to the domain.
430/// 
431/// The MF record is obsolete. It is recommended to either reject the record
432/// or convert them into an Mx record at preference 10.
433///
434/// The MF record type is defined in RFC 1035, section 3.3.5.
435dname_type!(Mf, Mf, madname);
436
437
438//------------ Mg -----------------------------------------------------------
439
440/// MG record data.
441///
442/// The MG record specifices a mailbox which is a member of the mail group
443/// specified by the domain name.
444/// 
445/// The MG record is experimental.
446///
447/// The MG record type is defined in RFC 1035, section 3.3.6.
448dname_type!(Mg, Mg, madname);
449
450
451//------------ Minfo --------------------------------------------------------
452
453/// Minfo record data.
454///
455/// The Minfo record specifies a mailbox which is responsible for the mailing
456/// list or mailbox and a mailbox that receives error messages related to the
457/// list or box.
458///
459/// The Minfo record is experimental.
460///
461/// The Minfo record type is defined in RFC 1035, section 3.3.7.
462#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
463pub struct Minfo<N=ParsedDname> {
464    rmailbx: N,
465    emailbx: N,
466}
467
468impl<N> Minfo<N> {
469    /// Creates a new Minfo record data from the components.
470    pub fn new(rmailbx: N, emailbx: N) -> Self {
471        Minfo { rmailbx, emailbx }
472    }
473
474    /// The responsible mail box.
475    ///
476    /// The domain name specifies the mailbox which is responsible for the
477    /// mailing list or mailbox. If this domain name is the root, the owner
478    /// of the Minfo record is responsible for itself.
479    pub fn rmailbx(&self) -> &N {
480        &self.rmailbx
481    }
482
483    /// The error mail box.
484    ///
485    /// The domain name specifies a mailbox which is to receive error
486    /// messages related to the mailing list or mailbox specified by the
487    /// owner of the record. If this is the root domain name, errors should
488    /// be returned to the sender of the message.
489    pub fn emailbx(&self) -> &N {
490        &self.emailbx
491    }
492}
493
494
495//--- Parse, ParseAll, Compose, and Compress
496
497impl<N: Parse> Parse for Minfo<N> {
498    type Err = N::Err;
499
500    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
501        Ok(Self::new(N::parse(parser)?, N::parse(parser)?))
502    }
503
504    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
505        N::skip(parser)?;
506        N::skip(parser)?;
507        Ok(())
508    }
509}
510
511impl<N: Parse + ParseAll> ParseAll for Minfo<N>
512     where <N as ParseAll>::Err: From<<N as Parse>::Err> + From<ShortBuf> {
513    type Err = <N as ParseAll>::Err;
514
515    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
516        let pos = parser.pos();
517        let rmailbx = N::parse(parser)?;
518        let rlen = parser.pos() - pos;
519        let len = if len <= rlen {
520            // Because a domain name can never be empty, we seek back to the
521            // beginning and reset the length to zero.
522            parser.seek(pos)?;
523            0
524        }
525        else {
526            len - rlen
527        };
528        let emailbx = N::parse_all(parser, len)?;
529        Ok(Self::new(rmailbx, emailbx))
530    }
531}
532
533impl<N: Compose> Compose for Minfo<N> {
534    fn compose_len(&self) -> usize {
535        self.rmailbx.compose_len() + self.emailbx.compose_len()
536    }
537
538    fn compose<B: BufMut>(&self, buf: &mut B) {
539        self.rmailbx.compose(buf);
540        self.emailbx.compose(buf);
541    }
542}
543
544impl<N: Compress> Compress for Minfo<N> {
545    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
546        self.rmailbx.compress(buf)?;
547        self.emailbx.compress(buf)
548    }
549}
550
551
552//--- Scan and Display
553
554impl<N: Scan> Scan for Minfo<N> {
555    fn scan<C: CharSource>(scanner: &mut  Scanner<C>)
556                           -> Result<Self, ScanError> {
557        Ok(Self::new(N::scan(scanner)?, N::scan(scanner)?))
558    }
559}
560
561impl<N: fmt::Display> fmt::Display for Minfo<N> {
562    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
563        write!(f, "{}. {}.", self.rmailbx, self.emailbx)
564    }
565}
566
567
568//--- RecordData
569
570impl<N> RtypeRecordData for Minfo<N> {
571    const RTYPE: Rtype = Rtype::Minfo;
572}
573
574
575//------------ Mr -----------------------------------------------------------
576
577/// MR record data.
578///
579/// The MR record specifices a mailbox which is the proper rename of the
580/// specified mailbox.
581/// 
582/// The MR record is experimental.
583///
584/// The MR record type is defined in RFC 1035, section 3.3.8.
585dname_type!(Mr, Mr, newname);
586
587
588//------------ Mx -----------------------------------------------------------
589
590/// Mx record data.
591///
592/// The Mx record specifies a host willing to serve as a mail exchange for
593/// the owner name.
594///
595/// The Mx record type is defined in RFC 1035, section 3.3.9.
596#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
597pub struct Mx<N=ParsedDname> {
598    preference: u16,
599    exchange: N,
600}
601
602impl<N> Mx<N> {
603    /// Creates a new Mx record data from the components.
604    pub fn new(preference: u16, exchange: N) -> Self {
605        Mx { preference, exchange }
606    }
607
608    /// The preference for this record.
609    ///
610    /// Defines an order if there are several Mx records for the same owner.
611    /// Lower values are preferred.
612    pub fn preference(&self) -> u16 {
613        self.preference
614    }
615
616    /// The name of the host that is the exchange.
617    pub fn exchange(&self) -> &N {
618        &self.exchange
619    }
620}
621
622
623//--- Parse, ParseAll, Compose, Compress
624
625impl<N: Parse> Parse for Mx<N>
626     where N::Err: From<ShortBuf> {
627    type Err = N::Err;
628
629    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
630        Ok(Self::new(u16::parse(parser)?, N::parse(parser)?))
631    }
632
633    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
634        u16::skip(parser)?;
635        N::skip(parser)
636    }
637}
638
639impl<N: ParseAll> ParseAll for Mx<N>
640     where N::Err: From<ParseOpenError> + From<ShortBuf> {
641    type Err = N::Err;
642
643    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
644        if len < 3 {
645            return Err(ParseOpenError::ShortField.into())
646        }
647        Ok(Self::new(u16::parse(parser)?, N::parse_all(parser, len - 2)?))
648    }
649}
650
651impl<N: Compose> Compose for Mx<N> {
652    fn compose_len(&self) -> usize {
653        self.exchange.compose_len() + 2
654    }
655
656    fn compose<B: BufMut>(&self, buf: &mut B) {
657        self.preference.compose(buf);
658        self.exchange.compose(buf);
659    }
660}
661
662impl<N: Compress> Compress for Mx<N> {
663    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
664        buf.compose(&self.preference)?;
665        self.exchange.compress(buf)
666    }
667}
668
669
670//--- Scan and Display
671
672impl<N: Scan> Scan for Mx<N> {
673    fn scan<C: CharSource>(scanner: &mut Scanner<C>)
674                           -> Result<Self, ScanError> {
675        Ok(Self::new(u16::scan(scanner)?, N::scan(scanner)?))
676    }
677}
678
679impl<N: fmt::Display> fmt::Display for Mx<N> {
680    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
681        write!(f, "{} {}.", self.preference, self.exchange)
682    }
683}
684
685
686//--- RtypeRecordData
687
688impl<N> RtypeRecordData for Mx<N> {
689    const RTYPE: Rtype = Rtype::Mx;
690}
691
692
693//------------ Ns -----------------------------------------------------------
694
695/// NS record data.
696///
697/// NS records specify hosts that are authoritative for a class and domain.
698///
699/// The NS record type is defined in RFC 1035, section 3.3.11.
700dname_type!(Ns, Ns, nsdname);
701
702
703//------------ Null ---------------------------------------------------------
704
705/// Null record data.
706///
707/// Null records can contain whatever data. They are experimental and not
708/// allowed in master files.
709///
710/// The Null record type is defined in RFC 1035, section 3.3.10.
711#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
712pub struct Null {
713    data: Bytes,
714}
715
716impl Null {
717    /// Creates new, empty owned Null record data.
718    pub fn new(data: Bytes) -> Self {
719        Null { data }
720    }
721
722    /// The raw content of the record.
723    pub fn data(&self) -> &Bytes {
724        &self.data
725    }
726}
727
728
729//--- From
730
731impl From<Bytes> for Null {
732    fn from(data: Bytes) -> Self {
733        Self::new(data)
734    }
735}
736
737
738//--- ParseAll, Compose, and Compress
739
740impl ParseAll for Null {
741    type Err = ShortBuf;
742
743    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
744        parser.parse_bytes(len).map(Self::new)
745    }
746}
747
748impl Compose for Null {
749    fn compose_len(&self) -> usize {
750        self.data.len()
751    }
752
753    fn compose<B: BufMut>(&self, buf: &mut B) {
754        buf.put_slice(self.data.as_ref())
755    }
756}
757
758impl Compress for Null {
759    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
760        buf.compose(self)
761    }
762}
763
764
765//--- RtypeRecordData
766
767impl RtypeRecordData for Null {
768    const RTYPE: Rtype = Rtype::Null;
769}
770
771
772//--- Deref
773
774impl ops::Deref for Null {
775    type Target = Bytes;
776
777    fn deref(&self) -> &Self::Target {
778        &self.data
779    }
780}
781
782
783//--- AsRef
784
785impl AsRef<Bytes> for Null {
786    fn as_ref(&self) -> &Bytes {
787        &self.data
788    }
789}
790
791impl AsRef<[u8]> for Null {
792    fn as_ref(&self) -> &[u8] {
793        self.data.as_ref()
794    }
795}
796
797
798//--- Display
799
800impl fmt::Display for Null {
801    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
802        write!(f, "\\# {}", self.data().len())?;
803        for ch in self.data().iter() {
804            write!(f, " {:02x}", ch)?;
805        }
806        Ok(())
807    }
808}
809
810
811//------------ Ptr ----------------------------------------------------------
812
813/// PTR record data.
814///
815/// PRT records are used in special domains to point to some other location
816/// in the domain space.
817///
818/// The PTR record type is defined in RFC 1035, section 3.3.12.
819dname_type!(Ptr, Ptr, ptrdname);
820
821impl<N> Ptr<N> {
822    pub fn into_ptrdname(self) -> N {
823        self.ptrdname
824    }
825}
826
827
828//------------ Soa ----------------------------------------------------------
829
830/// Soa record data.
831///
832/// Soa records mark the top of a zone and contain information pertinent to
833/// name server maintenance operations.
834///
835/// The Soa record type is defined in RFC 1035, section 3.3.13.
836#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd)]
837pub struct Soa<N=ParsedDname> {
838    mname: N,
839    rname: N,
840    serial: Serial,
841    refresh: u32,
842    retry: u32,
843    expire: u32,
844    minimum:u32 
845}
846
847impl<N> Soa<N> {
848    /// Creates new Soa record data from content.
849    pub fn new(mname: N, rname: N, serial: Serial,
850               refresh: u32, retry: u32, expire: u32, minimum: u32) -> Self {
851        Soa { mname, rname, serial, refresh, retry, expire, minimum }
852    }
853
854    /// The primary name server for the zone.
855    pub fn mname(&self) -> &N {
856        &self.mname
857    }
858
859    /// The mailbox for the person responsible for this zone.
860    pub fn rname(&self) -> &N {
861        &self.rname
862    }
863
864    /// The serial number of the original copy of the zone.
865    pub fn serial(&self) -> Serial {
866        self.serial
867    }
868
869    /// The time interval in seconds before the zone should be refreshed.
870    pub fn refresh(&self) -> u32 {
871        self.refresh
872    }
873
874    /// The time in seconds before a failed refresh is retried.
875    pub fn retry(&self) -> u32 {
876        self.retry
877    }
878
879    /// The upper limit of time in seconds the zone is authoritative.
880    pub fn expire(&self) -> u32 {
881        self.expire
882    }
883
884    /// The minimum TTL to be exported with any RR from this zone.
885    pub fn minimum(&self) -> u32 {
886        self.minimum
887    }
888}
889
890
891//--- Parse, ParseAll, Compose, and Compress
892
893impl<N: Parse> Parse for Soa<N> where N::Err: From<ShortBuf> {
894    type Err = N::Err;
895
896    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
897        Ok(Self::new(N::parse(parser)?, N::parse(parser)?,
898                     Serial::parse(parser)?, u32::parse(parser)?,
899                     u32::parse(parser)?, u32::parse(parser)?,
900                     u32::parse(parser)?))
901    }
902
903    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
904        N::skip(parser)?;
905        N::skip(parser)?;
906        Serial::skip(parser)?;
907        u32::skip(parser)?;
908        u32::skip(parser)?;
909        u32::skip(parser)?;
910        u32::skip(parser)?;
911        Ok(())
912    }
913}
914
915impl<N: ParseAll + Parse> ParseAll for Soa<N>
916        where <N as ParseAll>::Err: From<<N as Parse>::Err>,
917              <N as ParseAll>::Err: From<ParseAllError>,
918              <N as Parse>::Err: From<ShortBuf> {
919    type Err = <N as ParseAll>::Err;
920
921    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
922        let mut tmp = parser.clone();
923        let res = <Self as Parse>::parse(&mut tmp)?;
924        if tmp.pos() - parser.pos() < len {
925            Err(ParseAllError::TrailingData.into())
926        }
927        else if tmp.pos() - parser.pos() > len {
928            Err(ParseAllError::ShortField.into())
929        }
930        else {
931            parser.advance(len)?;
932            Ok(res)
933        }
934    }
935}
936
937impl<N: Compose> Compose for Soa<N> {
938    fn compose_len(&self) -> usize {
939        self.mname.compose_len() + self.rname.compose_len() + (5 * 4)
940    }
941
942    fn compose<B: BufMut>(&self, buf: &mut B) {
943        self.mname.compose(buf);
944        self.rname.compose(buf);
945        self.serial.compose(buf);
946        self.refresh.compose(buf);
947        self.retry.compose(buf);
948        self.expire.compose(buf);
949        self.minimum.compose(buf);
950    }
951}
952
953impl<N: Compress> Compress for Soa<N> {
954    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
955        self.mname.compress(buf)?;
956        self.rname.compress(buf)?;
957        buf.compose(&self.serial)?;
958        buf.compose(&self.refresh)?;
959        buf.compose(&self.retry)?;
960        buf.compose(&self.expire)?;
961        buf.compose(&self.minimum)
962    }
963}
964
965
966//--- Scan and Display
967
968impl<N: Scan> Scan for Soa<N> {
969    fn scan<C: CharSource>(scanner: &mut Scanner<C>)
970                           -> Result<Self, ScanError> {
971        Ok(Self::new(N::scan(scanner)?, N::scan(scanner)?,
972                     Serial::scan(scanner)?, u32::scan(scanner)?,
973                     u32::scan(scanner)?, u32::scan(scanner)?,
974                     u32::scan(scanner)?))
975    }
976}
977
978impl<N: fmt::Display> fmt::Display for Soa<N> {
979    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
980        write!(f, "{}. {}. {} {} {} {} {}",
981               self.mname, self.rname, self.serial, self.refresh, self.retry,
982               self.expire, self.minimum)
983    }
984}
985
986
987//--- RecordData
988
989impl<N> RtypeRecordData for Soa<N> {
990    const RTYPE: Rtype = Rtype::Soa;
991}
992
993
994//------------ Txt ----------------------------------------------------------
995
996/// Txt record data.
997///
998/// Txt records hold descriptive text.
999///
1000/// The Txt record type is defined in RFC 1035, section 3.3.14.
1001#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1002pub struct Txt {
1003    text: Bytes,
1004}
1005
1006impl Txt {
1007    /// Creates a new Txt record from a single character string.
1008    pub fn new(text: CharStr) -> Self {
1009        Txt { text: text.into_bytes() }
1010    }
1011
1012    /// Returns an iterator over the text items.
1013    ///
1014    /// The Txt format contains one or more length-delimited byte strings.
1015    /// This method returns an iterator over each of them.
1016    pub fn iter(&self) -> TxtIter {
1017        TxtIter::new(self.text.clone())
1018    }
1019
1020    /// Returns the text content.
1021    ///
1022    /// If the data is only one single character string, returns a simple
1023    /// clone of the slice with the data. If there are several character
1024    /// strings, their content will be copied together into one single,
1025    /// newly allocated bytes value.
1026    ///
1027    /// Access to the individual character strings is possible via iteration.
1028    pub fn text(&self) -> Bytes {
1029        if self.text[0] as usize == self.text.len() + 1 {
1030            self.text.slice_from(1)
1031        }
1032        else {
1033            // Capacity will be a few bytes too much. Probably better than
1034            // re-allocating.
1035            let mut res = BytesMut::with_capacity(self.text.len());
1036            for item in self.iter() {
1037                res.put_slice(item.as_ref());
1038            }
1039            res.freeze()
1040        }
1041    }
1042}
1043
1044
1045//--- IntoIterator
1046
1047impl IntoIterator for Txt {
1048    type Item = CharStr;
1049    type IntoIter = TxtIter;
1050
1051    fn into_iter(self) -> Self::IntoIter {
1052        self.iter()
1053    }
1054}
1055
1056impl<'a> IntoIterator for &'a Txt {
1057    type Item = CharStr;
1058    type IntoIter = TxtIter;
1059
1060    fn into_iter(self) -> Self::IntoIter {
1061        self.iter()
1062    }
1063}
1064
1065
1066//--- ParseAll, Compose, and Compress
1067
1068impl ParseAll for Txt {
1069    type Err = ParseOpenError;
1070
1071    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
1072        let text = parser.parse_bytes(len)?;
1073        let mut tmp = Parser::from_bytes(text.clone());
1074        while tmp.remaining() > 0 {
1075            CharStr::skip(&mut tmp).map_err(|_| ParseOpenError::ShortField)?
1076        }
1077        Ok(Txt { text })
1078    }
1079}
1080
1081impl Compose for Txt {
1082    fn compose_len(&self) -> usize {
1083        self.text.len()
1084    }
1085
1086    fn compose<B: BufMut>(&self, buf: &mut B) {
1087        buf.put_slice(self.text.as_ref())
1088    }
1089}
1090
1091impl Compress for Txt {
1092    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
1093        buf.compose(self)
1094    }
1095}
1096
1097
1098//--- Scan and Display
1099
1100impl Scan for Txt {
1101    fn scan<C: CharSource>(scanner: &mut Scanner<C>)
1102                           -> Result<Self, ScanError> {
1103        let first = CharStr::scan(scanner)?;
1104        let second = match CharStr::scan(scanner) {
1105            Err(_) => return Ok(Txt::new(first)),
1106            Ok(second) => second,
1107        };
1108        let mut text = first.into_bytes();
1109        text.extend_from_slice(second.as_ref());
1110        while let Ok(some) = CharStr::scan(scanner) {
1111            text.extend_from_slice(some.as_ref());
1112        }
1113        Ok(Txt { text })
1114    }
1115}
1116
1117impl fmt::Display for Txt {
1118    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1119        let mut items = self.iter();
1120        match items.next() {
1121            Some(item) => item.fmt(f)?,
1122            None => return Ok(())
1123        }
1124        for item in items {
1125            write!(f, " {}", item)?;
1126        }
1127        Ok(())
1128    }
1129}
1130
1131
1132//--- RecordData
1133
1134impl RtypeRecordData for Txt {
1135    const RTYPE: Rtype = Rtype::Txt;
1136}
1137
1138
1139//------------ TxtIter -------------------------------------------------------
1140
1141/// An iterator over the character strings of a Txt record.
1142#[derive(Clone, Debug)]
1143pub struct TxtIter {
1144    parser: Parser,
1145}
1146
1147impl TxtIter {
1148    fn new(text: Bytes)-> Self {
1149        TxtIter { parser: Parser::from_bytes(text) }
1150    }
1151}
1152
1153impl Iterator for TxtIter {
1154    type Item = CharStr;
1155
1156    fn next(&mut self) -> Option<Self::Item> {
1157        if self.parser.remaining() == 0 {
1158            None
1159        }
1160        else {
1161            Some(CharStr::parse(&mut self.parser).unwrap())
1162        }
1163    }
1164}
1165
1166
1167//------------ Wks ----------------------------------------------------------
1168
1169/// Wks record data.
1170///
1171/// Wks records describe the well-known services supported by a particular
1172/// protocol on a particular internet address.
1173///
1174/// The Wks record type is defined in RFC 1035, section 3.4.2.
1175#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1176pub struct Wks {
1177    address: Ipv4Addr,
1178    protocol: u8,
1179    bitmap: Bytes,
1180}
1181
1182
1183impl Wks {
1184    /// Creates a new record data from components.
1185    pub fn new(address: Ipv4Addr, protocol: u8, bitmap: Bytes) -> Self {
1186        Wks { address, protocol, bitmap }
1187    }
1188
1189    /// The IPv4 address of the host this record refers to.
1190    pub fn address(&self) -> Ipv4Addr {
1191        self.address
1192    }
1193
1194    /// The protocol number of the protocol this record refers to.
1195    ///
1196    /// This will typically be `6` for TCP or `17` for UDP.
1197    pub fn protocol(&self) -> u8 {
1198        self.protocol
1199    }
1200
1201    /// A bitmap indicating the ports where service is being provided.
1202    pub fn bitmap(&self) -> &Bytes {
1203        &self.bitmap
1204    }
1205
1206    /// Returns whether a certain service is being provided.
1207    pub fn serves(&self, port: u16) -> bool {
1208        let octet = (port / 8) as usize;
1209        let bit = (port % 8) as usize;
1210        match self.bitmap.get(octet) {
1211            Some(x) => (x >> bit) > 0,
1212            None => false
1213        }
1214    }
1215
1216    /// Returns an iterator over the served ports.
1217    pub fn iter(&self) -> WksIter {
1218        WksIter::new(self.bitmap.clone())
1219    }
1220}
1221
1222
1223//--- ParseAll, Compose, Compress
1224
1225impl ParseAll for Wks {
1226    type Err = ParseOpenError;
1227
1228    fn parse_all(parser: &mut Parser, len: usize) -> Result<Self, Self::Err> {
1229        if len < 5 {
1230            return Err(ParseOpenError::ShortField)
1231        }
1232        Ok(Self::new(Ipv4Addr::parse(parser)?, u8::parse(parser)?,
1233                     parser.parse_bytes(len - 5)?))
1234    }
1235}
1236
1237impl Compose for Wks {
1238    fn compose_len(&self) -> usize {
1239        self.bitmap.len() + 5
1240    }
1241
1242    fn compose<B: BufMut>(&self, buf: &mut B) {
1243        self.address.compose(buf);
1244        self.protocol.compose(buf);
1245        self.bitmap.compose(buf);
1246    }
1247}
1248
1249impl Compress for Wks {
1250    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
1251        buf.compose(self)
1252    }
1253}
1254
1255
1256//--- Scan and Display
1257
1258impl Scan for Wks {
1259    fn scan<C: CharSource>(scanner: &mut Scanner<C>)
1260                           -> Result<Self, ScanError> {
1261        let address = scanner.scan_string_phrase(|res| {
1262            Ipv4Addr::from_str(&res).map_err(Into::into)
1263        })?;
1264        let protocol = u8::scan(scanner)?;
1265        let mut builder = WksBuilder::new(address, protocol);
1266        while let Ok(service) = u16::scan(scanner) {
1267            builder.add_service(service)
1268        }
1269        Ok(builder.finish())
1270    }
1271}
1272
1273impl fmt::Display for Wks {
1274    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1275        write!(f, "{} {}", self.address, self.protocol)?;
1276        for service in self.iter() {
1277            write!(f, " {}", service)?;
1278        }
1279        Ok(())
1280    }
1281}
1282
1283
1284//--- RecordData
1285
1286impl RtypeRecordData for Wks {
1287    const RTYPE: Rtype = Rtype::Wks;
1288}
1289
1290
1291//------------ WksIter -------------------------------------------------------
1292
1293/// An iterator over the services active in a Wks record.
1294///
1295/// This iterates over the port numbers in growing order.
1296#[derive(Clone, Debug)]
1297pub struct WksIter {
1298    bitmap: Bytes,
1299    octet: usize,
1300    bit: usize
1301}
1302
1303impl WksIter {
1304    fn new(bitmap: Bytes) -> Self {
1305        WksIter { bitmap, octet: 0, bit: 0 }
1306    }
1307
1308    fn serves(&self) -> bool {
1309        (self.bitmap[self.octet] >> self.bit) > 0
1310    }
1311}
1312
1313impl Iterator for WksIter {
1314    type Item = u16;
1315
1316    fn next(&mut self) -> Option<Self::Item> {
1317        loop {
1318            if self.octet >= self.bitmap.len() { return None }
1319            else {
1320                if self.serves() {
1321                    return Some((self.octet * 8 + self.bit) as u16)
1322                }
1323                if self.bit == 7 { self.octet += 1; self.bit = 0 }
1324                else { self.bit += 1 }
1325            }
1326        }
1327    }
1328}
1329
1330
1331//------------ WksBuilder ----------------------------------------------------
1332
1333#[derive(Clone, Debug)]
1334pub struct WksBuilder {
1335    address: Ipv4Addr,
1336    protocol: u8,
1337    bitmap: BytesMut,
1338}
1339
1340impl WksBuilder {
1341    pub fn new(address: Ipv4Addr, protocol: u8) -> Self {
1342        WksBuilder { address, protocol, bitmap: BytesMut::new() }
1343    }
1344
1345    pub fn add_service(&mut self, service: u16) {
1346        let octet = (service >> 2) as usize;
1347        let bit = 1 << (service & 0x3);
1348        while self.bitmap.len() < octet + 1 {
1349            self.bitmap.extend_from_slice(b"0")
1350        }
1351        self.bitmap[octet] |= bit;
1352    }
1353
1354    pub fn finish(self) -> Wks {
1355        Wks::new(self.address, self.protocol, self.bitmap.freeze())
1356    }
1357}
1358
1359
1360//------------ parsed sub-module ---------------------------------------------
1361
1362pub mod parsed {
1363    use ::bits::name::ParsedDname;
1364
1365    pub use super::A;
1366    pub type Cname = super::Cname<ParsedDname>;
1367    pub use super::Hinfo;
1368    pub type Mb = super::Mb<ParsedDname>;
1369    pub type Md = super::Md<ParsedDname>;
1370    pub type Mf = super::Mf<ParsedDname>;
1371    pub type Mg = super::Mg<ParsedDname>;
1372    pub type Minfo = super::Minfo<ParsedDname>;
1373    pub type Mr = super::Mr<ParsedDname>;
1374    pub type Mx = super::Mx<ParsedDname>;
1375    pub type Ns = super::Ns<ParsedDname>;
1376    pub use super::Null;
1377    pub type Ptr = super::Ptr<ParsedDname>;
1378    pub type Soa = super::Soa<ParsedDname>;
1379    pub use super::Txt;
1380    pub use super::Wks;
1381}
1382