domain_core/bits/
header.rs

1//! The header of a DNS message.
2//!
3//! Each DNS message starts with a twelve octet long header section
4//! containing some general information related to the message as well as
5//! the number of records in each of the four sections that follow the header.
6//! Its content and format are defined in section 4.1.1 of [RFC 1035].
7//!
8//! In order to reflect the fact that changing the section counts may
9//! invalidate the rest of the message whereas the other elements of the
10//! header section can safely be modified, the whole header has been split
11//! into two separate types: [`Header`] contains the safely modifyable part
12//! at the beginning and [`HeaderCounts`] contains the section counts. In
13//! addition, the [`HeaderSection`] type wraps both of them into a single
14//! type.
15//!
16//! [`Header`]: struct.Header.html
17//! [`HeaderCounts`]: struct.HeaderCounts.html
18//! [`HeaderSection`]: struct.HeaderSection.html
19//! [RFC 1035]: https://tools.ietf.org/html/rfc1035
20
21use std::mem;
22use bytes::{BigEndian, BufMut, ByteOrder};
23use ::iana::{Opcode, Rcode};
24use super::compose::Compose;
25use super::parse::{Parse, Parser, ShortBuf};
26
27
28//------------ Header --------------------------------------------------
29
30/// The first part of the header of a DNS message.
31///
32/// This type represents the information contained in the first four bytes of
33/// the header: the message ID, opcode, rcode, and the various flags.
34///
35/// The type’s data contains such a header in its wire format which is layed
36/// out like this:
37///
38/// ```text
39///                                 1  1  1  1  1  1
40///   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
41/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
42/// |                      ID                       |
43/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44/// |QR|   Opcode  |AA|TC|RD|RA|Z |AD|CD|   RCODE   |
45/// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
46/// ```
47///
48/// Methods are available for accessing each of these fields.
49/// See [Field Access] below.
50///
51/// The basic structure and most of the fields re defined in [RFC 1035],
52/// except for the AD and CD flags, which are defined in [RFC 4035].
53///
54/// [Field Access]: #field-access 
55/// [RFC 1035]: https://tools.ietf.org/html/rfc1035
56/// [RFC 4035]: https://tools.ietf.org/html/rfc4035
57#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
58pub struct Header {
59    /// The actual header in its wire format representation.
60    ///
61    /// This means that the ID field is in big endian.
62    inner: [u8; 4]
63}
64
65/// # Creation and Conversion
66///
67impl Header {
68    /// Creates a new header.
69    ///
70    /// The new header has all fields as either zero or false. Thus, the
71    /// opcode will be `Opcode::Query` and the response code will be
72    /// `Rcode::NoError`.
73    pub fn new() -> Self {
74        Self::default()
75    }
76
77    /// Creates a header reference from a byte slice of a message.
78    ///
79    /// # Panics
80    ///
81    /// This function panics if the byte slice is too short.
82    pub fn for_message_slice(s: &[u8]) -> &Header {
83        assert!(s.len() >= mem::size_of::<Header>());
84        unsafe { &*(s.as_ptr() as *const Header) }
85    }
86
87    /// Creates a mutable header reference from a byte slice of a message.
88    ///
89    /// # Panics
90    ///
91    /// This function panics if the byte slice is too short.
92    pub fn for_message_slice_mut(s: &mut [u8]) -> &mut Header {
93        assert!(s.len() >= mem::size_of::<Header>());
94        unsafe { &mut *(s.as_ptr() as *mut Header) }
95    }
96
97    /// Returns a reference to the underlying bytes slice.
98    pub fn as_slice(&self) -> &[u8] {
99        &self.inner
100    }
101}
102
103
104/// # Field Access
105///
106impl Header {
107    /// Returns the value of the ID field.
108    ///
109    /// The ID field is an identifier chosen by whoever created a query
110    /// and is copied into a response by a server. It allows matching
111    /// incoming responses to their queries.
112    pub fn id(self) -> u16 {
113        BigEndian::read_u16(&self.inner)
114    }
115
116    /// Sets the value of the ID field.
117    pub fn set_id(&mut self, value: u16) {
118        BigEndian::write_u16(&mut self.inner, value)
119    }
120
121    /// Sets the value of the ID field to a randomly chosen number.
122    ///
123    /// This uses [`rand::random`] which may not be good enough.
124    pub fn set_random_id(&mut self) { self.set_id(::rand::random()) }
125
126    /// Returns whether the QR bit is set.
127    ///
128    /// The QR bit specifies whether this message is a query (`false`) or
129    /// a response (`true`). In other words, this bit is actually stating
130    /// whether the message is *not* a query. So, perhaps it might be good
131    /// to read ‘QR’ as ‘query response.’
132    pub fn qr(self) -> bool { self.get_bit(2, 7) }
133
134    /// Sets the value of the QR bit.
135    ///
136    pub fn set_qr(&mut self, set: bool) { self.set_bit(2, 7, set) }
137
138    /// Returns the value of the Opcode field.
139    ///
140    /// This field specifies the kind of query this message contains. See
141    /// the [`Opcode`] type for more information on the possible values and
142    /// their meaning. Normal queries have the variant [`Opcode::Query`]
143    /// which is also the value set when creating a new header.
144    ///
145    /// [`Opcode`]: ../../iana/opcode/enum.Opcode.html
146    /// [`Opcode::Query`]: ../../iana/opcode/enum.Opcode.html#variant.Query
147    pub fn opcode(self) -> Opcode {
148        Opcode::from_int((self.inner[2] >> 3) & 0x0F)
149    }
150
151    /// Sets the value of the opcode field.
152    pub fn set_opcode(&mut self, opcode: Opcode) {
153        self.inner[2] = self.inner[2] & 0x87 | (opcode.to_int() << 3);
154    }
155
156    /// Returns whether the AA bit is set.
157    ///
158    /// Using this bit, a name server generating a response states whether
159    /// it is authoritative for the requested domain name, ie., whether this
160    /// response is an *authoritative answer.* The field has no meaning in 
161    /// a query.
162    pub fn aa(self) -> bool { self.get_bit(2, 2) }
163
164    /// Sets the value of the AA bit.
165    pub fn set_aa(&mut self, set: bool) { self.set_bit(2, 2, set) }
166
167    /// Returns whether the TC bit is set.
168    ///
169    /// The *truncation* bit is set if there was more data available then
170    /// fit into the message. This is typically used when employing
171    /// datagram transports such as UDP to signal to try again using a
172    /// stream transport such as TCP.
173    pub fn tc(self) -> bool { self.get_bit(2, 1) }
174
175    /// Sets the value of the TC bit.
176    pub fn set_tc(&mut self, set: bool) { self.set_bit(2, 1, set) }
177
178    /// Returns whether the RD bit is set.
179    ///
180    /// The *recursion desired* bit may be set in a query to ask the name
181    /// server to try and recursively gather a response if it doesn’t have
182    /// the data available locally. The bit’s value is copied into the
183    /// response.
184    pub fn rd(self) -> bool { self.get_bit(2, 0) }
185
186    /// Sets the value of the RD bit.
187    pub fn set_rd(&mut self, set: bool) { self.set_bit(2, 0, set) }
188
189    /// Returns whether the RA bit is set.
190    ///
191    /// In a response, the *recursion available* bit denotes whether the
192    /// responding name server supports recursion. It has no meaning in
193    /// a query.
194    pub fn ra(self) -> bool { self.get_bit(3, 7) }
195
196    /// Sets the value of the RA bit.
197    pub fn set_ra(&mut self, set: bool) { self.set_bit(3, 7, set) }
198
199    /// Returns whether the reserved bit is set.
200    ///
201    /// This bit must be `false` in all queries and responses.
202    pub fn z(self) -> bool { self.get_bit(3, 6) }
203
204    /// Sets the value of the reserved bit.
205    pub fn set_z(&mut self, set: bool) { self.set_bit(3, 6, set) }
206
207    /// Returns whether the AD bit is set.
208    ///
209    /// The *authentic data* bit is used by security-aware recursive name
210    /// servers to indicate that it considers all RRsets in its response to
211    /// be authentic.
212    pub fn ad(self) -> bool { self.get_bit(3, 5) }
213
214    /// Sets the value of the AD bit.
215    pub fn set_ad(&mut self, set: bool) { self.set_bit(3, 5, set) }
216
217    /// Returns whether the CD bit is set.
218    ///
219    /// The *checking disabled* bit is used by a security-aware resolver
220    /// to indicate that it does not want upstream name servers to perform
221    /// verification but rather would like to verify everything itself.
222    pub fn cd(self) -> bool { self.get_bit(3, 4) }
223
224    /// Sets the value of the CD bit.
225    pub fn set_cd(&mut self, set: bool) { self.set_bit(3, 4, set) }
226
227    /// Returns the value of the RCODE field.
228    ///
229    /// The *response code* is used in a response to indicate what happened
230    /// when processing the query. See the [`Rcode`] type for information on
231    /// possible values and their meaning.
232    ///
233    /// [`Rcode`]: ../../iana/rcode/enum.Rcode.html
234    pub fn rcode(self) -> Rcode {
235        Rcode::from_int(self.inner[3] & 0x0F)
236    }
237
238    /// Sets the value of the RCODE field.
239    pub fn set_rcode(&mut self, rcode: Rcode) {
240        self.inner[3] = self.inner[3] & 0xF0 | (rcode.to_int() & 0x0F);
241    }
242
243
244    //--- Internal helpers
245
246    /// Returns the value of the bit at the given position.
247    ///
248    /// The argument `offset` gives the byte offset of the underlying bytes
249    /// slice and `bit` gives the number of the bit with the most significant
250    /// bit being 7.
251    fn get_bit(self, offset: usize, bit: usize) -> bool {
252        self.inner[offset] & (1 << bit) != 0
253    }
254
255    /// Sets or resets the given bit.
256    fn set_bit(&mut self, offset: usize, bit: usize, set: bool) {
257        if set { self.inner[offset] |= 1 << bit }
258        else { self.inner[offset] &= !(1 << bit) }
259    }
260} 
261
262
263//------------ HeaderCounts -------------------------------------------------
264
265/// The section count part of the header section of a DNS message.
266///
267/// This part consists of four 16 bit counters for the number of entries in
268/// the four sections of a DNS message.
269///
270/// The counters are arranged in the same order as the sections themselves:
271/// QDCOUNT for the question section, ANCOUNT for the answer section,
272/// NSCOUNT for the authority section, and ARCOUNT for the additional section.
273/// These are defined in [RFC 1035].
274///
275/// [RFC 2136] defines the UPDATE method and reuses the four section for
276/// different purposes. Here the counters are ZOCOUNT for the zone section,
277/// PRCOUNT for the prerequisite section, UPCOUNT for the update section,
278/// and ADCOUNT for the additional section. The type has convenience methods
279/// for these fields as well so you don’t have to remember which is which.
280///
281/// For each field there are three methods for getting, setting, and
282/// incrementing.
283///
284/// [RFC 1035]: https://tools.ietf.org/html/rfc1035
285/// [RFC 2136]: https://tools.ietf.org/html/rfc2136
286#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
287pub struct HeaderCounts {
288    /// The actual headers in their wire-format representation.
289    ///
290    /// Ie., all values are stored big endian.
291    inner: [u8; 8]
292}
293
294/// # Creation and Conversion
295///
296impl HeaderCounts {
297    /// Creates a new value with all counters set to zero.
298    pub fn new() -> Self {
299        Self::default()
300    }
301
302    /// Creates a header reference from a byte slice of a message.
303    ///
304    /// The slice `message` mut be the whole message, i.e., start with the
305    /// bytes of the [`Header`](struct.Header.html).
306    /// 
307    /// # Panics
308    ///
309    /// This function panics if the bytes slice is too short.
310    pub fn for_message_slice(message: &[u8]) -> &Self {
311        assert!(message.len() >= mem::size_of::<HeaderSection>());
312        unsafe {
313            &*((message[mem::size_of::<Header>()..].as_ptr())
314                                                      as *const HeaderCounts)
315        }
316    }
317
318    /// Creates a mutable header reference from a bytes slice of a message.
319    ///
320    /// The slice `message` mut be the whole message, i.e., start with the
321    /// bytes of the [`Header`](struct.Header.html).
322    ///
323    /// # Panics
324    ///
325    /// This function panics if the bytes slice is too short.
326    pub fn for_message_slice_mut(message: &mut [u8]) -> &mut Self {
327        assert!(message.len() >= mem::size_of::<HeaderSection>());
328        unsafe {
329            &mut *((message[mem::size_of::<Header>()..].as_ptr())
330                                                         as *mut HeaderCounts)
331        }
332    }
333
334    /// Returns a reference to the raw byte slice of the header counts.
335    pub fn as_slice(&self) -> &[u8] {
336        &self.inner
337    }
338
339    /// Returns a mutable reference to the raw byte slice of the header counts.
340    pub fn as_slice_mut(&mut self) -> &mut [u8] {
341        &mut self.inner
342    }
343
344    /// Sets the counts to those from `counts`.
345    pub fn set(&mut self, counts: HeaderCounts) {
346        self.as_slice_mut().copy_from_slice(counts.as_slice())
347    }
348}
349
350
351/// # Field Access
352///
353impl HeaderCounts {
354    //--- Count fields in regular messages
355
356    /// Returns the value of the QDCOUNT field.
357    ///
358    /// This field contains the number of questions in the first
359    /// section of the message, normally the question section.
360    pub fn qdcount(self) -> u16 {
361        self.get_u16(0)
362    }
363
364    /// Sets the value of the QDCOUNT field.
365    pub fn set_qdcount(&mut self, value: u16) {
366        self.set_u16(0, value)
367    }
368
369    /// Increases the value of the QDCOUNT field by one.
370    ///
371    /// # Panics
372    ///
373    /// This method panics if the count is already at its maximum.
374    pub fn inc_qdcount(&mut self) {
375        let count = self.qdcount();
376        assert!(count < ::std::u16::MAX);
377        self.set_qdcount(count + 1);
378    }
379
380    /// Returns the value of the ANCOUNT field.
381    ///
382    /// This field contains the number of resource records in the second
383    /// section of the message, normally the answer section.
384    pub fn ancount(self) -> u16 {
385        self.get_u16(2)
386    }
387
388    /// Sets the value of the ANCOUNT field.
389    pub fn set_ancount(&mut self, value: u16) {
390        self.set_u16(2, value)
391    }
392
393    /// Increases the value of the ANCOUNT field by one.
394    ///
395    /// # Panics
396    ///
397    /// This method panics if the count is already at its maximum.
398    pub fn inc_ancount(&mut self) {
399        let count = self.ancount();
400        assert!(count < ::std::u16::MAX);
401        self.set_ancount(count + 1);
402    }
403
404    /// Returns the value of the NSCOUNT field.
405    ///
406    /// This field contains the number of resource records in the third
407    /// section of the message, normally the authority section.
408    pub fn nscount(self) -> u16 {
409        self.get_u16(4)
410    }
411
412    /// Sets the value of the NSCOUNT field.
413    pub fn set_nscount(&mut self, value: u16) {
414        self.set_u16(4, value)
415    }
416
417    /// Increases the value of the NSCOUNT field by one.
418    ///
419    /// # Panics
420    ///
421    /// This method panics if the count is already at its maximum.
422    pub fn inc_nscount(&mut self) {
423        let count = self.nscount();
424        assert!(count < ::std::u16::MAX);
425        self.set_nscount(count + 1);
426    }
427
428    /// Returns the value of the ARCOUNT field.
429    ///
430    /// This field contains the number of resource records in the fourth
431    /// section of the message, normally the additional section.
432    pub fn arcount(self) -> u16 {
433        self.get_u16(6)
434    }
435
436    /// Sets the value of the ARCOUNT field.
437    pub fn set_arcount(&mut self, value: u16) {
438        self.set_u16(6, value)
439    }
440
441    /// Increases the value of the ARCOUNT field by one.
442    ///
443    /// # Panics
444    ///
445    /// This method panics if the count is already at its maximum.
446    pub fn inc_arcount(&mut self) {
447        let count = self.arcount();
448        assert!(count < ::std::u16::MAX);
449        self.set_arcount(count + 1);
450    }
451
452
453    //--- Count fields in UPDATE messages
454
455    /// Returns the value of the ZOCOUNT field.
456    ///
457    /// This is the same as the `qdcount()`. It is used in UPDATE queries
458    /// where the first section is the zone section.
459    pub fn zocount(self) -> u16 {
460        self.qdcount()
461    }
462
463    /// Sets the value of the ZOCOUNT field.
464    pub fn set_zocount(&mut self, value: u16) {
465        self.set_qdcount(value)
466    }
467
468    /// Returns the value of the PRCOUNT field.
469    ///
470    /// This is the same as the `ancount()`. It is used in UPDATE queries
471    /// where the first section is the prerequisite section.
472    pub fn prcount(self) -> u16 {
473        self.ancount()
474    }
475
476    /// Sete the value of the PRCOUNT field.
477    pub fn set_prcount(&mut self, value: u16) {
478        self.set_ancount(value)
479    }
480
481    /// Returns the value of the UPCOUNT field.
482    ///
483    /// This is the same as the `nscount()`. It is used in UPDATE queries
484    /// where the first section is the update section.
485    pub fn upcount(self) -> u16 {
486        self.nscount()
487    }
488
489    /// Sets the value of the UPCOUNT field.
490    pub fn set_upcount(&mut self, value: u16) {
491        self.set_nscount(value)
492    }
493
494    /// Returns the value of the ADCOUNT field.
495    ///
496    /// This is the same as the `arcount()`. It is used in UPDATE queries
497    /// where the first section is the additional section.
498    pub fn adcount(self) -> u16 {
499        self.arcount()
500    }
501
502    /// Sets the value of the ADCOUNT field.
503    pub fn set_adcount(&mut self, value: u16) {
504        self.set_arcount(value)
505    }
506   
507
508    //--- Internal helpers
509
510    /// Returns the value of the 16 bit integer starting at a given offset.
511    fn get_u16(self, offset: usize) -> u16 {
512        BigEndian::read_u16(&self.inner[offset..])
513    }
514
515    /// Sets the value of the 16 bit integer starting at a given offset.
516    fn set_u16(&mut self, offset: usize, value: u16) {
517        BigEndian::write_u16(&mut self.inner[offset..], value)
518    }
519}
520
521
522//------------ HeaderSection -------------------------------------------------
523
524/// The complete header section of a DNS message.
525///
526/// Consists of a `Header` and a `HeaderCounts`.
527#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
528pub struct HeaderSection {
529    inner: [u8; 12]
530}
531
532/// # Creation and Conversion
533///
534impl HeaderSection {
535    /// Creates a new empty header section.
536    pub fn new() -> Self {
537        Self::default()
538    }
539
540    /// Creates a reference from the bytes slice of a message.
541    ///
542    /// # Panics
543    ///
544    /// This function panics if the size of the bytes slice is smaller than
545    /// the header section.
546    pub fn for_message_slice(s: &[u8]) -> &HeaderSection {
547        assert!(s.len() >= mem::size_of::<HeaderSection>());
548        unsafe { &*(s.as_ptr() as *const HeaderSection) }
549    }
550
551    /// Creates a mutable reference from the bytes slice of a message.
552    ///
553    /// # Panics
554    ///
555    /// This function panics if the size of the bytes slice is smaller than
556    /// the header section.
557    pub fn for_message_slice_mut(s: &mut [u8]) -> &mut HeaderSection {
558        assert!(s.len() >= mem::size_of::<HeaderSection>());
559        unsafe { &mut *(s.as_ptr() as *mut HeaderSection) }
560    }
561
562    /// Returns a reference to the underlying bytes slice.
563    pub fn as_slice(&self) -> &[u8] {
564        &self.inner
565    }
566}
567
568
569/// # Access to Header and Counts
570///
571impl HeaderSection {
572    /// Returns a reference to the header.
573    pub fn header(&self) -> &Header {
574        Header::for_message_slice(&self.inner)
575    }
576
577    /// Returns a mutable reference to the header.
578    pub fn header_mut(&mut self) -> &mut Header {
579        Header::for_message_slice_mut(&mut self. inner)
580    }
581
582    /// Returns a reference to the header counts.
583    pub fn counts(&self) -> &HeaderCounts {
584        HeaderCounts::for_message_slice(&self.inner)
585    }
586
587    /// Returns a mutable reference to the header counts.
588    pub fn counts_mut(&mut self) -> &mut HeaderCounts {
589        HeaderCounts::for_message_slice_mut(&mut self.inner)
590    }
591}
592
593
594//--- Parse and Compose
595
596impl Parse for HeaderSection {
597    type Err = ShortBuf;
598
599    fn parse(parser: &mut Parser) -> Result<Self, Self::Err> {
600        let mut res = Self::default();
601        parser.parse_buf(&mut res.inner)?;
602        Ok(res)
603    }
604
605    fn skip(parser: &mut Parser) -> Result<(), Self::Err> {
606        parser.advance(12)
607    }
608}
609
610impl Compose for HeaderSection {
611    fn compose_len(&self) -> usize {
612        12
613    }
614
615    fn compose<B: BufMut>(&self, buf: &mut B) {
616        buf.put_slice(&self.inner)
617    }
618}
619
620
621//============ Testing ======================================================
622
623#[cfg(test)]
624mod test {
625    use super::*;
626    use iana::{Opcode, Rcode};
627
628    #[test]
629    fn for_slice() {
630        let header = b"\x01\x02\x00\x00\x12\x34\x56\x78\x9a\xbc\xde\xf0";
631        let mut vec = Vec::from(&header[..]);
632        assert_eq!(Header::for_message_slice(header).as_slice(),
633                   b"\x01\x02\x00\x00");
634        assert_eq!(Header::for_message_slice_mut(vec.as_mut()).as_slice(),
635                   b"\x01\x02\x00\x00");
636        assert_eq!(HeaderCounts::for_message_slice(header).as_slice(),
637                   b"\x12\x34\x56\x78\x9a\xbc\xde\xf0");
638        assert_eq!(HeaderCounts::for_message_slice_mut(vec.as_mut()).as_slice(),
639                   b"\x12\x34\x56\x78\x9a\xbc\xde\xf0");
640        assert_eq!(HeaderSection::for_message_slice(header).as_slice(),
641                   header);
642        assert_eq!(HeaderSection::for_message_slice_mut(vec.as_mut())
643                                 .as_slice(),
644                   header);
645    }
646
647    #[test]
648    #[should_panic]
649    fn short_header() {
650        Header::for_message_slice(b"134");
651    }
652
653    #[test]
654    #[should_panic]
655    fn short_header_counts() {
656        HeaderCounts::for_message_slice(b"12345678");
657    }
658
659    #[test]
660    #[should_panic]
661    fn short_header_section() {
662        HeaderSection::for_message_slice(b"1234");
663    }
664
665    macro_rules! test_field {
666        ($get:ident, $set:ident, $default:expr, $($value:expr),*) => {
667            $({
668                let mut h = Header::new();
669                assert_eq!(h.$get(), $default);
670                h.$set($value);
671                assert_eq!(h.$get(), $value);
672            })*
673        }
674    }
675
676    #[test]
677    fn header() {
678        test_field!(id, set_id, 0, 0x1234);
679        test_field!(qr, set_qr, false, true, false);
680        test_field!(opcode, set_opcode, Opcode::Query, Opcode::Notify);
681        test_field!(aa, set_aa, false, true, false);
682        test_field!(tc, set_tc, false, true, false);
683        test_field!(rd, set_rd, false, true, false);
684        test_field!(ra, set_ra, false, true, false);
685        test_field!(z, set_z, false, true, false);
686        test_field!(ad, set_ad, false, true, false);
687        test_field!(cd, set_cd, false, true, false);
688        test_field!(rcode, set_rcode, Rcode::NoError, Rcode::Refused);
689    }
690
691    #[test]
692    fn counts() {
693        let mut c = HeaderCounts { inner: [ 1, 2, 3, 4, 5, 6, 7, 8 ] };
694        assert_eq!(c.qdcount(), 0x0102);
695        assert_eq!(c.ancount(), 0x0304);
696        assert_eq!(c.nscount(), 0x0506);
697        assert_eq!(c.arcount(), 0x0708);
698        c.inc_qdcount();
699        c.inc_ancount();
700        c.inc_nscount();
701        c.inc_arcount();
702        assert_eq!(c.inner, [ 1, 3, 3, 5, 5, 7, 7, 9 ]);
703        c.set_qdcount(0x0807);
704        c.set_ancount(0x0605);
705        c.set_nscount(0x0403);
706        c.set_arcount(0x0201);
707        assert_eq!(c.inner, [ 8, 7, 6, 5, 4, 3, 2, 1 ]);
708    }
709
710    #[test]
711    fn update_counts() {
712        let mut c = HeaderCounts { inner: [ 1, 2, 3, 4, 5, 6, 7, 8 ] };
713        assert_eq!(c.zocount(), 0x0102);
714        assert_eq!(c.prcount(), 0x0304);
715        assert_eq!(c.upcount(), 0x0506);
716        assert_eq!(c.adcount(), 0x0708);
717        c.set_zocount(0x0807);
718        c.set_prcount(0x0605);
719        c.set_upcount(0x0403);
720        c.set_adcount(0x0201);
721        assert_eq!(c.inner, [ 8, 7, 6, 5, 4, 3, 2, 1 ]);
722    }
723
724    #[test]
725    #[should_panic]
726    fn bad_inc_qdcount() {
727        let mut c = HeaderCounts {
728            inner: [ 0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff ]
729        };
730        c.inc_qdcount()
731    }
732
733    #[test]
734    #[should_panic]
735    fn bad_inc_ancount() {
736        let mut c = HeaderCounts {
737            inner: [ 0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff ]
738        };
739        c.inc_ancount()
740    }
741
742    #[test]
743    #[should_panic]
744    fn bad_inc_nscount() {
745        let mut c = HeaderCounts {
746            inner: [ 0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff ]
747        };
748        c.inc_nscount()
749    }
750
751    #[test]
752    #[should_panic]
753    fn bad_inc_arcount() {
754        let mut c = HeaderCounts {
755            inner: [ 0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff ]
756        };
757        c.inc_arcount()
758    }
759}