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