1 // Copyright (C) 2009-2017 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef MESSAGE_H
8 #define MESSAGE_H 1
9 
10 #include <stdint.h>
11 
12 #include <iterator>
13 #include <string>
14 #include <ostream>
15 
16 #include <dns/exceptions.h>
17 
18 #include <dns/edns.h>
19 #include <dns/question.h>
20 #include <dns/rrset.h>
21 
22 namespace isc {
23 namespace util {
24 class InputBuffer;
25 }
26 
27 namespace dns {
28 class TSIGContext;
29 class TSIGRecord;
30 
31 ///
32 /// \brief A standard DNS module exception that is thrown if a wire format
33 /// message parser encounters a short length of data that don't even contain
34 /// the full header section.
35 ///
36 class MessageTooShort : public isc::dns::Exception {
37 public:
MessageTooShort(const char * file,size_t line,const char * what)38     MessageTooShort(const char* file, size_t line, const char* what) :
39         isc::dns::Exception(file, line, what) {}
40 };
41 
42 ///
43 /// \brief A standard DNS module exception that is thrown if a section iterator
44 /// is being constructed for an incompatible section.  Specifically, this
45 /// happens RRset iterator is being constructed for a Question section.
46 ///
47 class InvalidMessageSection : public isc::dns::Exception {
48 public:
InvalidMessageSection(const char * file,size_t line,const char * what)49     InvalidMessageSection(const char* file, size_t line, const char* what) :
50         isc::dns::Exception(file, line, what) {}
51 };
52 
53 ///
54 /// \brief A standard DNS module exception that is thrown if a \c Message
55 /// class method is called that is prohibited for the current mode of
56 /// the message.
57 ///
58 class InvalidMessageOperation : public isc::dns::Exception {
59 public:
InvalidMessageOperation(const char * file,size_t line,const char * what)60     InvalidMessageOperation(const char* file, size_t line, const char* what) :
61         isc::dns::Exception(file, line, what) {}
62 };
63 
64 ///
65 /// \brief A standard DNS module exception that is thrown if a UDP buffer size
66 /// smaller than the standard default maximum (DEFAULT_MAX_UDPSIZE) is
67 /// being specified for the message.
68 ///
69 class InvalidMessageUDPSize : public isc::dns::Exception {
70 public:
InvalidMessageUDPSize(const char * file,size_t line,const char * what)71     InvalidMessageUDPSize(const char* file, size_t line, const char* what) :
72         isc::dns::Exception(file, line, what) {}
73 };
74 
75 typedef uint16_t qid_t;
76 
77 class AbstractMessageRenderer;
78 class Message;
79 class MessageImpl;
80 class Opcode;
81 class Rcode;
82 
83 template <typename T>
84 struct SectionIteratorImpl;
85 
86 /// \c SectionIterator is a templated class to provide standard-compatible
87 /// iterators for Questions and RRsets for a given DNS message section.
88 /// The template parameter is either \c QuestionPtr (for the question section)
89 /// or \c RRsetPtr (for the answer, authority, or additional section).
90 template <typename T>
91 class SectionIterator : public std::iterator<std::input_iterator_tag, T> {
92 public:
SectionIterator()93     SectionIterator() : impl_(NULL) {}
94     SectionIterator(const SectionIteratorImpl<T>& impl);
95     ~SectionIterator();
96     SectionIterator(const SectionIterator<T>& source);
97     void operator=(const SectionIterator<T>& source);
98     SectionIterator<T>& operator++();
99     SectionIterator<T> operator++(int);
100     const T& operator*() const;
101     const T* operator->() const;
102     bool operator==(const SectionIterator<T>& other) const;
103     bool operator!=(const SectionIterator<T>& other) const;
104 private:
105     SectionIteratorImpl<T>* impl_;
106 };
107 
108 typedef SectionIterator<QuestionPtr> QuestionIterator;
109 typedef SectionIterator<RRsetPtr> RRsetIterator;
110 
111 /// \brief The \c Message class encapsulates a standard DNS message.
112 ///
113 /// Details of the design and interfaces of this class are still in flux.
114 /// Here are some notes about the current design.
115 ///
116 /// Since many realistic DNS applications deal with messages, message objects
117 /// will be frequently used, and can be performance sensitive.  To minimize
118 /// the performance overhead of constructing and destructing the objects,
119 /// this class is designed to be reusable.  The \c clear() method is provided
120 /// for this purpose.
121 ///
122 /// A \c Message class object is in either the \c PARSE or the \c RENDER mode.
123 /// A \c PARSE mode object is intended to be used to convert wire-format
124 /// message data into a complete \c Message object.
125 /// A \c RENDER mode object is intended to be used to convert a \c Message
126 /// object into wire-format data.
127 /// Some of the method functions of this class are limited to a specific mode.
128 /// In general, "set" type operations are only allowed for \c RENDER mode
129 /// objects.
130 /// The initial mode must be specified on construction, and can be changed
131 /// through some method functions.
132 ///
133 /// This class uses the "pimpl" idiom, and hides detailed implementation
134 /// through the \c impl_ pointer.  Since a \c Message object is expected to
135 /// be reused, the construction overhead of this approach should be acceptable.
136 ///
137 /// Open issues (among other things):
138 /// - We may want to provide an "iterator" for all RRsets/RRs for convenience.
139 ///   This will be for applications that do not care about performance much,
140 ///   so the implementation can only be moderately efficient.
141 /// - We may want to provide a "find" method for a specified type
142 ///   of RR in the message.
143 class Message {
144 public:
145     /// Constants to specify the operation mode of the \c Message.
146     enum Mode {
147         PARSE = 0,              ///< Parse mode (handling an incoming message)
148         RENDER = 1              ///< Render mode (building an outgoing message)
149     };
150 
151     /// \brief Constants for flag bit fields of a DNS message header.
152     ///
153     /// Only the defined constants are valid where a header flag is required
154     /// in this library (e.g., in \c Message::setHeaderFlag()).
155     /// Since these are enum constants, however, an invalid value could be
156     /// passed via casting without an error at compilation time.
157     /// It is generally the callee's responsibility to check and reject invalid
158     /// values.
159     /// Of course, applications shouldn't pass invalid values even if the
160     /// callee does not perform proper validation; the result in such usage
161     /// is undefined.
162     ///
163     /// In the current implementation, the defined values happen to be
164     /// a 16-bit integer with one bit being set corresponding to the
165     /// specified flag in the second 16 bits of the DNS Header section
166     /// in order to make the internal implementation simpler.
167     /// For example, \c HEADERFLAG_QR is defined to be 0x8000 as the QR
168     /// bit is the most significant bit of the second 16 bits of the header.
169     /// However, applications should not assume this coincidence and
170     /// must solely use the enum representations.
171     /// Any usage based on the assumption of the underlying values is invalid
172     /// and the result is undefined.
173     ///
174     /// Likewise, bit wise operations such as AND or OR on the flag values
175     /// are invalid and are not guaranteed to work, even if it could compile
176     /// with casting.
177     /// For example, the following code will compile:
178     /// \code const uint16_t combined_flags =
179     ///           static_cast<uint16_t>(Message::HEADERFLAG_AA) |
180     ///           static_cast<uint16_t>(Message::HEADERFLAG_CD);
181     /// message->setHeaderFlag(static_cast<Message::HeaderFlag>(combined_flags));
182     /// \endcode
183     /// and (with the current definition) happens to work as if it were
184     /// validly written as follows:
185     /// \code message->setHeaderFlag(Message::HEADERFLAG_AA);
186     /// message->setHeaderFlag(Message::HEADERFLAG_CD);
187     /// \endcode
188     /// But the former notation is invalid and may not work in future versions.
189     /// We did not try to prohibit such usage at compilation time, e.g., by
190     /// introducing a separately defined class considering the balance
191     /// between the complexity and advantage, but hopefully the cast notation
192     /// is sufficiently ugly to prevent proliferation of the usage.
193     enum HeaderFlag {
194         HEADERFLAG_QR = 0x8000, ///< Query (if cleared) or response (if set)
195         HEADERFLAG_AA = 0x0400, ///< Authoritative answer
196         HEADERFLAG_TC = 0x0200, ///< Truncation
197         HEADERFLAG_RD = 0x0100, ///< Recursion desired
198         HEADERFLAG_RA = 0x0080, ///< Recursion available
199         HEADERFLAG_AD = 0x0020, ///< Authentic %data (RFC4035)
200         HEADERFLAG_CD = 0x0010  ///< DNSSEC checking disabled (RFC4035)
201     };
202 
203     /// \brief Constants to specify sections of a DNS message.
204     ///
205     /// The sections are those defined in RFC 1035 excluding the Header
206     /// section; the fields of the Header section are accessed via specific
207     /// methods of the \c Message class (e.g., \c getQid()).
208     ///
209     /// <b>Open Design Issue:</b>
210     /// In the current implementation the values for the constants are
211     /// sorted in the order of appearance in DNS messages, i.e.,
212     /// from %Question to Additional.
213     /// So, for example,
214     /// code <code>section >= Message::SECTION_AUTHORITY</code> can be
215     /// used to do something in or after the Authority section.
216     /// This would be convenient, but it is not clear if it's really a good
217     /// idea to rely on relationship between the underlying values of enum
218     /// constants.  At the moment, applications are discouraged to rely on
219     /// this implementation detail.  We will see if such usage is sufficiently
220     /// common to officially support it.
221     ///
222     /// Note also that since we don't define \c operator++ for this enum,
223     /// the following code intending to iterate over all sections will
224     /// \b not compile:
225     /// \code for (Section s; s <= SECTION_ADDITIONAL; ++s) { // ++s undefined
226     ///     // do something
227     /// } \endcode
228     /// This is intentional at this moment, and we'll see if we need to allow
229     /// that as we have more experiences with this library.
230     ///
231     /// <b>Future Extension:</b> We'll probably also define constants for
232     /// the section names used in dynamic updates in future versions.
233     enum Section {
234         SECTION_QUESTION = 0,   ///< %Question section
235         SECTION_ANSWER = 1,     ///< Answer section
236         SECTION_AUTHORITY = 2,  ///< Authority section
237         SECTION_ADDITIONAL = 3  ///< Additional section
238     };
239 
240     ///
241     /// \name Constructors and Destructor
242     ///
243     /// Note: The copy constructor and the assignment operator are
244     /// intentionally defined as private.
245     /// The intended use case wouldn't require copies of a \c Message object;
246     /// once created, it would normally be expected to be reused, changing the
247     /// mode from \c PARSE to \c RENDER, and vice versa.
248     //@{
249 public:
250     /// \brief The constructor.
251     /// The mode of the message is specified by the \c mode parameter.
252     Message(Mode mode);
253     /// \brief The destructor.
254     ~Message();
255 private:
256     Message(const Message& source);
257     Message& operator=(const Message& source);
258     //@}
259 public:
260     /// \brief Return whether the specified header flag bit is set in the
261     /// header section.
262     ///
263     /// This method is basically exception free, but if
264     /// \c flag is not a valid constant of the \c HeaderFlag type,
265     /// an exception of class \c InvalidParameter will be thrown.
266     ///
267     /// \param flag The header flag constant to test.
268     /// \return \c true if the specified flag is set; otherwise \c false.
269     bool getHeaderFlag(const HeaderFlag flag) const;
270 
271     /// \brief Set or clear the specified header flag bit in the header
272     /// section.
273     ///
274     /// The optional parameter \c on indicates the operation mode,
275     /// set or clear; if it's \c true the corresponding flag will be set;
276     /// otherwise the flag will be cleared.
277     /// In either case the original state of the flag does not affect the
278     /// operation; for example, if a flag is already set and the "set"
279     /// operation is attempted, it effectively results in no operation.
280     ///
281     /// The parameter \c on can be omitted, in which case a value of \c true
282     /// (i.e., set operation) will be assumed.
283     /// This is based on the observation that the flag would have to be set
284     /// in the vast majority of the cases where an application needs to
285     /// use this method.
286     ///
287     /// This method is only allowed in the \c RENDER mode;
288     /// if the \c Message is in other mode, an exception of class
289     /// InvalidMessageOperation will be thrown.
290     ///
291     /// If \c flag is not a valid constant of the \c HeaderFlag type,
292     /// an exception of class \c InvalidParameter will be thrown.
293     ///
294     /// \param flag The header flag constant to set or clear.
295     /// \param on If \c true the flag will be set; otherwise the flag will be
296     /// cleared.
297     void setHeaderFlag(const HeaderFlag flag, const bool on = true);
298 
299     /// \brief Return the query ID given in the header section of the message.
300     qid_t getQid() const;
301 
302     /// \brief Set the query ID of the header section of the message.
303     ///
304     /// This method is only allowed in the \c RENDER mode;
305     /// if the \c Message is in other mode, an exception of class
306     /// InvalidMessageOperation will be thrown.
307     void setQid(qid_t qid);
308 
309     /// \brief Return the Response Code of the message.
310     ///
311     /// This includes extended codes specified by an EDNS OPT RR (when
312     /// included).  In the \c PARSE mode, if the received message contains
313     /// an EDNS OPT RR, the corresponding extended code is identified and
314     /// returned.
315     ///
316     /// The message must have been properly parsed (in the case of the
317     /// \c PARSE mode) or an \c Rcode has been set (in the case of the
318     /// \c RENDER mode) beforehand.  Otherwise, an exception of class
319     /// \c InvalidMessageOperation will be thrown.
320     const Rcode& getRcode() const;
321 
322     /// \brief Set the Response Code of the message.
323     ///
324     /// This method is only allowed in the \c RENDER mode;
325     /// if the \c Message is in other mode, an exception of class
326     /// InvalidMessageOperation will be thrown.
327     ///
328     /// If the specified code is an EDNS extended RCODE, an EDNS OPT RR will be
329     /// included in the message.
330     void setRcode(const Rcode& rcode);
331 
332     /// \brief Return the OPCODE given in the header section of the message.
333     ///
334     /// The message must have been properly parsed (in the case of the
335     /// \c PARSE mode) or an \c Opcode has been set (in the case of the
336     /// \c RENDER mode) beforehand.  Otherwise, an exception of class
337     /// \c InvalidMessageOperation will be thrown.
338     const Opcode& getOpcode() const;
339 
340     /// \brief Set the OPCODE of the header section of the message.
341     ///
342     /// This method is only allowed in the \c RENDER mode;
343     /// if the \c Message is in other mode, an exception of class
344     /// InvalidMessageOperation will be thrown.
345     void setOpcode(const Opcode& opcode);
346 
347     /// \brief Return, if any, the EDNS associated with the message.
348     ///
349     /// This method never throws an exception.
350     ///
351     /// \return A shared pointer to the EDNS.  This will be a null shared
352     /// pointer if the message is not associated with EDNS.
353     ConstEDNSPtr getEDNS() const;
354 
355     /// \brief Set EDNS for the message.
356     ///
357     /// This method is only allowed in the \c RENDER mode;
358     /// if the \c Message is in other mode, an exception of class
359     /// InvalidMessageOperation will be thrown.
360     ///
361     /// \param edns A shared pointer to an \c EDNS object to be set in
362     /// \c Message.
363     void setEDNS(ConstEDNSPtr edns);
364 
365     /// \brief Return, if any, the TSIG record contained in the received
366     /// message.
367     ///
368     /// Currently, this method is only intended to return a TSIG record
369     /// for an incoming message built via the \c fromWire() method in the
370     /// PARSE mode.  A call to this method in the RENDER mode is invalid and
371     /// result in an exception.  Also, calling this method is meaningless
372     /// unless \c fromWire() is performed.
373     ///
374     /// The returned pointer is valid only during the lifetime of the
375     /// \c Message object and until \c clear() is called.  The \c Message
376     /// object retains the ownership of \c TSIGRecord; the caller must not
377     /// try to delete it.
378     ///
379     /// \exception InvalidMessageOperation Message is not in the PARSE mode.
380     ///
381     /// \return A pointer to the stored \c TSIGRecord or \c NULL.
382     const TSIGRecord* getTSIGRecord() const;
383 
384     /// \brief Returns the number of RRs contained in the given section.
385     ///
386     /// In the \c PARSE mode, the returned value may not be identical to
387     /// the actual number of RRs of the incoming message that is parsed.
388     /// The \c Message class handles some "meta" RRs such as EDNS OPT RR
389     /// separately.  This method doesn't include such RRs.
390     /// Also, a future version of the parser will detect and unify duplicate
391     /// RRs (which should be rare in practice though), in which case
392     /// the stored RRs in the \c Message object will be fewer than the RRs
393     /// originally contained in the incoming message.
394     ///
395     /// Likewise, in the \c RENDER mode, even if \c EDNS is set in the
396     /// \c Message, this method doesn't count the corresponding OPT RR
397     /// in the Additional section.
398     ///
399     /// This method is basically exception free, but if
400     /// \c section is not a valid constant of the \c Section type,
401     /// an exception of class \c OutOfRange will be thrown.
402     ///
403     /// \param section The section in the message where RRs should be
404     /// counted.
405     /// \return The number of RRs stored in the specified section of the
406     /// message.
407     unsigned int getRRCount(const Section section) const;
408 
409     /// \brief Return an iterator corresponding to the beginning of the
410     /// Question section of the message.
411     const QuestionIterator beginQuestion() const;
412 
413     /// \brief Return an iterator corresponding to the end of the
414     /// Question section of the message.
415     const QuestionIterator endQuestion() const;
416 
417     /// \brief Return an iterator corresponding to the beginning of the
418     /// given section (other than Question) of the message.
419     ///
420     /// \c section must be a valid constant of the \c Section type;
421     /// otherwise, an exception of class \c OutOfRange will be thrown.
422     const RRsetIterator beginSection(const Section section) const;
423 
424     /// \brief Return an iterator corresponding to the end of the
425     /// given section (other than Question) of the message.
426     ///
427     /// \c section must be a valid constant of the \c Section type;
428     /// otherwise, an exception of class \c OutOfRange will be thrown.
429     const RRsetIterator endSection(const Section section) const;
430 
431     /// \brief Add a (pointer like object of) Question to the message.
432     ///
433     /// This method is only allowed in the \c RENDER mode;
434     /// if the \c Message is in other mode, an exception of class
435     /// InvalidMessageOperation will be thrown.
436     void addQuestion(QuestionPtr question);
437 
438     /// \brief Add a (pointer like object of) Question to the message.
439     ///
440     /// This version internally creates a \c QuestionPtr object from the
441     /// given \c question and calls the other version of this method.
442     /// So this is inherently less efficient, but is provided because this
443     /// form may be more intuitive and may make more sense for performance
444     /// insensitive applications.
445     ///
446     /// This method is only allowed in the \c RENDER mode;
447     /// if the \c Message is in other mode, an exception of class
448     /// InvalidMessageOperation will be thrown.
449     void addQuestion(const Question& question);
450 
451     /// \brief Add a (pointer like object of) RRset to the given section
452     /// of the message.
453     ///
454     /// Note that \c addRRset() does not currently check for duplicate
455     /// data before inserting RRsets.  The caller is responsible for
456     /// checking for these (see \c hasRRset() below).
457     ///
458     /// \throw InvalidParameter rrset is NULL
459     /// \throw InvalidMessageOperation The message is not in the \c RENDER
460     /// mode.
461     /// \throw OutOfRange \c section doesn't specify a valid \c Section value.
462     ///
463     /// \param section The message section to which the rrset is to be added
464     /// \param rrset The rrset to be added.  Must not be NULL.
465     void addRRset(const Section section, RRsetPtr rrset);
466 
467     /// \brief Determine whether the given section already has an RRset
468     /// matching the given name, RR class and RR type.
469     ///
470     /// \c section must be a valid constant of the \c Section type;
471     /// otherwise, an exception of class \c OutOfRange will be thrown.
472     ///
473     /// This should probably be extended to be a "find" method that returns
474     /// a matching RRset if found.
475     bool hasRRset(const Section section, const Name& name,
476                   const RRClass& rrclass, const RRType& rrtype) const;
477 
478     /// \brief Determine whether the given section already has an RRset
479     /// matching the one pointed to by the argument
480     ///
481     /// \c section must be a valid constant of the \c Section type;
482     /// otherwise, an exception of class \c OutOfRange will be thrown.
483     bool hasRRset(const Section section, const RRsetPtr& rrset) const;
484 
485     /// \brief Remove RRSet from Message
486     ///
487     /// Removes the RRset identified by the section iterator from the message.
488     /// Note: if,.for some reason, the RRset is duplicated in the section, only
489     /// one occurrence is removed.
490     ///
491     /// If the operation is successful, all iterators into the section are
492     /// invalidated.
493     ///
494     /// \param section Section to which the iterator belongs
495     /// \param iterator Iterator pointing to the element to be removed
496     ///
497     /// \return true if the element was removed, false if the iterator was not
498     /// found in the specified section.
499     bool removeRRset(const Section section, RRsetIterator& iterator);
500 
501     /// \brief Remove all RRSets from the given Section
502     ///
503     /// This method is only allowed in the \c RENDER mode, and the given
504     /// section must be valid.
505     ///
506     /// \throw InvalidMessageOperation Message is not in the \c RENDER mode
507     /// \throw OutOfRange The specified section is not valid
508     ///
509     /// \param section Section to remove all rrsets from
510     void clearSection(const Section section);
511 
512     // The following methods are not currently implemented.
513     //void removeQuestion(QuestionPtr question);
514     // notyet:
515     //void addRR(const Section section, const RR& rr);
516     //void removeRR(const Section section, const RR& rr);
517 
518     /// \brief Clear the message content (if any) and reinitialize it in the
519     /// specified mode.
520     void clear(Mode mode);
521 
522     /// \brief Adds all rrsets from the source the given section in the
523     /// source message to the same section of this message
524     ///
525     /// \param section the section to append
526     /// \param source The source Message
527     void appendSection(const Section section, const Message& source);
528 
529     /// \brief Prepare for making a response from a request.
530     ///
531     /// This will clear the DNS header except those fields that should be kept
532     /// for the response, and clear answer and the following sections.
533     /// See also dns_message_reply() of BIND9.
534     void makeResponse();
535 
536     /// \brief Convert the Message to a string.
537     ///
538     /// At least \c Opcode and \c Rcode must be validly set in the \c Message
539     /// (as a result of parse in the \c PARSE mode or by explicitly setting
540     /// in the \c RENDER mode);  otherwise, an exception of
541     /// class \c InvalidMessageOperation will be thrown.
542     std::string toText() const;
543 
544     /// \brief Render the message in wire formant into a message renderer
545     /// object with (or without) TSIG.
546     ///
547     /// This \c Message must be in the \c RENDER mode and both \c Opcode and
548     /// \c Rcode must have been set beforehand; otherwise, an exception of
549     /// class \c InvalidMessageOperation will be thrown.
550     ///
551     /// If a non-NULL \c tsig_ctx is passed, it will also add a TSIG RR
552     /// with (in many cases) the TSIG MAC for the message along with the
553     /// given TSIG context (\c tsig_ctx).  The TSIG RR will be placed at
554     /// the end of \c renderer. The \c TSIGContext at \c tsig_ctx will
555     /// be updated based on the fact it was used for signing and with
556     /// the latest MAC.
557     ///
558     /// \exception InvalidMessageOperation The message is not in the Render
559     /// mode, or either Rcode or Opcode is not set.
560     /// \exception InvalidParameter The allowable limit of \c renderer is too
561     /// small for a TSIG or the Header section.  Note that this shouldn't
562     /// happen with parameters as defined in the standard protocols,
563     /// so it's more likely a program bug.
564     /// \exception Unexpected Rendering the TSIG RR fails.  The implementation
565     /// internally makes sure this doesn't happen, so if that ever occurs
566     /// it should mean a bug either in the TSIG context or in the renderer
567     /// implementation.
568     ///
569     /// \note The renderer's internal buffers and data are automatically
570     /// cleared, keeping the length limit and the compression mode intact.
571     /// In case truncation is triggered, the renderer is cleared completely.
572     ///
573     /// \param renderer DNS message rendering context that encapsulates the
574     /// output buffer and name compression information.
575     /// \param tsig_ctx A TSIG context that is to be used for signing the
576     /// message
577     void toWire(AbstractMessageRenderer& renderer,
578                 TSIGContext* tsig_ctx = NULL);
579 
580     /// Parse options.
581     ///
582     /// describe PRESERVE_ORDER: note doesn't affect EDNS or TSIG.
583     ///
584     /// The option values are used as a parameter for \c fromWire().
585     /// These are values of a bitmask type.  Bitwise operations can be
586     /// performed on these values to express compound options.
587     enum ParseOptions {
588         PARSE_DEFAULT = 0,       ///< The default options
589         PRESERVE_ORDER = 1       ///< Preserve RR order and don't combine them
590     };
591 
592     /// \brief Parse the header section of the \c Message.
593     ///
594     /// NOTE: If the header has already been parsed by a previous call
595     /// to this method, this method simply returns (i.e., it does not
596     /// read from the \c buffer).
597     void parseHeader(isc::util::InputBuffer& buffer);
598 
599     /// \brief (Re)build a \c Message object from wire-format data.
600     ///
601     /// This method parses the given wire format data to build a
602     /// complete Message object.  On success, the values of the header section
603     /// fields can be accessible via corresponding get methods, and the
604     /// question and following sections can be accessible via the
605     /// corresponding iterators.  If the message contains an EDNS or TSIG,
606     /// they can be accessible via \c getEDNS() and \c getTSIGRecord(),
607     /// respectively.
608     ///
609     /// This \c Message must be in the \c PARSE mode.
610     ///
611     /// This method performs strict validation on the given message based
612     /// on the DNS protocol specifications.  If the given message data is
613     /// invalid, this method throws an exception (see the exception list).
614     ///
615     /// By default, this method combines RRs of the same name, RR type and
616     /// RR class in a section into a single RRset, even if they are interleaved
617     /// with a different type of RR (though it would be a rare case in
618     /// practice).  If the \c PRESERVE_ORDER option is specified, it handles
619     /// each RR separately, in the appearing order, and converts it to a
620     /// separate RRset (so this RRset should contain exactly one Rdata).
621     /// This mode will be necessary when the higher level protocol is
622     /// ordering conscious.  For example, in AXFR and IXFR, the position of
623     /// the SOA RRs are crucial.
624     ///
625     /// \exception InvalidMessageOperation \c Message is in the RENDER mode
626     /// \exception DNSMessageFORMERR The given message data is syntactically
627     /// \exception MessageTooShort The given data is shorter than a valid
628     /// header section
629     /// \exception std::bad_alloc Memory allocation failure
630     /// \exception Others \c Name, \c Rdata, and \c EDNS classes can also throw
631     ///
632     /// \param buffer A input buffer object that stores the wire
633     /// data. This method reads from position 0 in the passed buffer.
634     /// \param options Parse options
635     void fromWire(isc::util::InputBuffer& buffer, ParseOptions options
636         = PARSE_DEFAULT);
637 
638     ///
639     /// \name Protocol constants
640     ///
641     //@{
642     /// \brief The default maximum size of UDP DNS messages that don't cause
643     /// truncation.
644     ///
645     /// With EDNS the maximum size can be increased per message.
646     static const uint16_t DEFAULT_MAX_UDPSIZE = 512;
647 
648     /// \brief The default maximum size of UDP DNS messages we can handle
649     static const uint16_t DEFAULT_MAX_EDNS0_UDPSIZE = 4096;
650     //@}
651 
652 private:
653     MessageImpl* impl_;
654 };
655 
656 /// \brief Pointer-like type pointing to a \c Message
657 ///
658 /// This type is expected to be used as an argument in asynchronous
659 /// callback functions.  The internal reference-counting will ensure that
660 /// that ongoing state information will not be lost if the object
661 /// that originated the asynchronous call falls out of scope.
662 typedef boost::shared_ptr<Message> MessagePtr;
663 typedef boost::shared_ptr<const Message> ConstMessagePtr;
664 
665 /// Insert the \c Message as a string into stream.
666 ///
667 /// This method convert \c message into a string and inserts it into the
668 /// output stream \c os.
669 ///
670 /// \param os A \c std::ostream object on which the insertion operation is
671 /// performed.
672 /// \param message A \c Message object output by the operation.
673 /// \return A reference to the same \c std::ostream object referenced by
674 /// parameter \c os after the insertion operation.
675 std::ostream& operator<<(std::ostream& os, const Message& message);
676 }
677 }
678 #endif  // MESSAGE_H
679 
680 // Local Variables:
681 // mode: c++
682 // End:
683