pkt6.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. // Copyright (C) 2011-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. #ifndef PKT6_H
  7. #define PKT6_H
  8. #include <asiolink/io_address.h>
  9. #include <dhcp/duid.h>
  10. #include <dhcp/option.h>
  11. #include <dhcp/pkt.h>
  12. #include <boost/date_time/posix_time/posix_time.hpp>
  13. #include <boost/shared_array.hpp>
  14. #include <boost/shared_ptr.hpp>
  15. #include <iostream>
  16. #include <set>
  17. #include <time.h>
  18. namespace isc {
  19. namespace dhcp {
  20. class Pkt6;
  21. /// @brief A pointer to Pkt6 packet
  22. typedef boost::shared_ptr<Pkt6> Pkt6Ptr;
  23. /// @brief Represents a DHCPv6 packet
  24. ///
  25. /// This class represents a single DHCPv6 packet. It handles both incoming
  26. /// and transmitted packets, parsing incoming options, options handling
  27. /// (add, get, remove), on-wire assembly, sanity checks and other operations.
  28. /// This specific class has several DHCPv6-specific methods, but it uses a lot
  29. /// of common operations from its base @c Pkt class that is shared with Pkt4.
  30. ///
  31. /// This class also handles relayed packets. For example, a RELAY-FORW message
  32. /// with a SOLICIT inside will be represented as SOLICIT and the RELAY-FORW
  33. /// layers will be stored in relay_info_ vector.
  34. class Pkt6 : public Pkt {
  35. public:
  36. /// specifies non-relayed DHCPv6 packet header length (over UDP)
  37. const static size_t DHCPV6_PKT_HDR_LEN = 4;
  38. /// specifies relay DHCPv6 packet header length (over UDP)
  39. const static size_t DHCPV6_RELAY_HDR_LEN = 34;
  40. /// DHCPv6 transport protocol
  41. enum DHCPv6Proto {
  42. UDP = 0, // most packets are UDP
  43. TCP = 1 // there are TCP DHCPv6 packets (bulk leasequery, failover)
  44. };
  45. /// @brief defines relay search pattern
  46. ///
  47. /// Defines order in which options are searched in a message that
  48. /// passed through multiple relays. RELAY_SEACH_FROM_CLIENT will
  49. /// start search from the relay that was the closest to the client
  50. /// (i.e. innermost in the encapsulated message, which also means
  51. /// this was the first relay that forwarded packet received by the
  52. /// server and this will be the last relay that will handle the
  53. /// response that server sent towards the client.).
  54. /// RELAY_SEARCH_FROM_SERVER is the opposite. This will be the
  55. /// relay closest to the server (i.e. outermost in the encapsulated
  56. /// message, which also means it was the last relay that relayed
  57. /// the received message and will be the first one to process
  58. /// server's response). RELAY_GET_FIRST will try to get option from
  59. /// the first relay only (closest to the client), RELAY_GET_LAST will
  60. /// try to get option form the the last relay (closest to the server).
  61. enum RelaySearchOrder {
  62. RELAY_SEARCH_FROM_CLIENT = 1,
  63. RELAY_SEARCH_FROM_SERVER = 2,
  64. RELAY_GET_FIRST = 3,
  65. RELAY_GET_LAST = 4
  66. };
  67. /// @brief structure that describes a single relay information
  68. ///
  69. /// Client sends messages. Each relay along its way will encapsulate the message.
  70. /// This structure represents all information added by a single relay.
  71. struct RelayInfo {
  72. /// @brief default constructor
  73. RelayInfo();
  74. /// @brief Returns prinable representation of the relay information.
  75. /// @return text representation of the structure (used in debug logging)
  76. std::string toText() const;
  77. uint8_t msg_type_; ///< message type (RELAY-FORW oro RELAY-REPL)
  78. uint8_t hop_count_; ///< number of traversed relays (up to 32)
  79. isc::asiolink::IOAddress linkaddr_;///< fixed field in relay-forw/relay-reply
  80. isc::asiolink::IOAddress peeraddr_;///< fixed field in relay-forw/relay-reply
  81. /// @brief length of the relay_msg_len
  82. /// Used when calculating length during pack/unpack
  83. uint16_t relay_msg_len_;
  84. /// options received from a specified relay, except relay-msg option
  85. isc::dhcp::OptionCollection options_;
  86. };
  87. /// Constructor, used in replying to a message
  88. ///
  89. /// @param msg_type type of message (SOLICIT=1, ADVERTISE=2, ...)
  90. /// @param transid transaction-id
  91. /// @param proto protocol (TCP or UDP)
  92. Pkt6(uint8_t msg_type,
  93. uint32_t transid,
  94. DHCPv6Proto proto = UDP);
  95. /// Constructor, used in message transmission
  96. ///
  97. /// Creates new message. Transaction-id will randomized.
  98. ///
  99. /// @param buf pointer to a buffer of received packet content
  100. /// @param len size of buffer of received packet content
  101. /// @param proto protocol (usually UDP, but TCP will be supported eventually)
  102. Pkt6(const uint8_t* buf, uint32_t len, DHCPv6Proto proto = UDP);
  103. /// @brief Prepares on-wire format.
  104. ///
  105. /// Prepares on-wire format of message and all its options.
  106. /// Options must be stored in options_ field.
  107. /// Output buffer will be stored in data_. Length
  108. /// will be set in data_len_.
  109. /// The output buffer is cleared before new data is written to it.
  110. ///
  111. /// @throw BadValue if packet protocol is invalid, InvalidOperation
  112. /// if packing fails, or NotImplemented if protocol is TCP (IPv6 over TCP is
  113. /// not yet supported).
  114. virtual void pack();
  115. /// @brief Dispatch method that handles binary packet parsing.
  116. ///
  117. /// This method calls appropriate dispatch function (unpackUDP or
  118. /// unpackTCP).
  119. ///
  120. /// @throw tbd
  121. virtual void unpack();
  122. /// @brief Returns protocol of this packet (UDP or TCP).
  123. ///
  124. /// @return protocol type
  125. DHCPv6Proto getProto();
  126. /// @brief Sets protocol of this packet.
  127. ///
  128. /// @param proto protocol (UDP or TCP)
  129. void setProto(DHCPv6Proto proto = UDP) {
  130. proto_ = proto;
  131. }
  132. /// @brief Returns text representation of the given packet identifiers.
  133. ///
  134. /// @note The parameters are ordered from the one that should be available
  135. /// almost at all times, to the one that is optional. This allows for
  136. /// providing default values for the parameters that may not be available
  137. /// in some places in the code where @c Pkt6::makeLabel is called.
  138. ///
  139. /// @param duid Pointer to the client identifier or NULL.
  140. /// @param transid Numeric transaction id to include in the string.
  141. /// @param hwaddr Hardware address to include in the string or NULL.
  142. ///
  143. /// @return String with text representation of the packet identifiers.
  144. static std::string makeLabel(const DuidPtr duid, const uint32_t transid,
  145. const HWAddrPtr& hwaddr);
  146. /// @brief Returns text representation of the given packet identifiers.
  147. ///
  148. /// This variant of the method does not include transaction id.
  149. ///
  150. /// @param duid Pointer to the client identifier or NULL.
  151. /// @param hwaddr Hardware address to include in the string or NULL.
  152. ///
  153. /// @return String with text representation of the packet identifiers.
  154. static std::string makeLabel(const DuidPtr duid, const HWAddrPtr& hwaddr);
  155. /// @brief Returns text representation of the primary packet identifiers
  156. ///
  157. /// This method is intended to be used to provide a consistent way to
  158. /// identify packets within log statements. It is an instance-level
  159. /// wrapper around static makeLabel(). See this method for string
  160. /// content.
  161. ///
  162. /// @note Currently this method doesn't include the HW address in the
  163. /// returned text.
  164. ///
  165. /// @return string with text representation
  166. virtual std::string getLabel() const;
  167. /// @brief Returns text representation of the packet.
  168. ///
  169. /// This function is useful mainly for debugging.
  170. ///
  171. /// @return string with text representation
  172. virtual std::string toText() const;
  173. /// @brief Returns length of the packet.
  174. ///
  175. /// This function returns size required to hold this packet.
  176. /// It includes DHCPv6 header and all options stored in
  177. /// options_ field.
  178. ///
  179. /// Note: It does not return proper length of incoming packets
  180. /// before they are unpacked.
  181. ///
  182. /// @return number of bytes required to assemble this packet
  183. virtual size_t len();
  184. /// @brief Returns message type (e.g. 1 = SOLICIT).
  185. ///
  186. /// @return message type
  187. virtual uint8_t getType() const { return (msg_type_); }
  188. /// @brief Sets message type (e.g. 1 = SOLICIT).
  189. ///
  190. /// @param type message type to be set
  191. virtual void setType(uint8_t type) { msg_type_=type; };
  192. /// @brief Retrieves the DUID from the Client Identifier option.
  193. ///
  194. /// This method is exception safe.
  195. ///
  196. /// @return Pointer to the DUID or NULL if the option doesn't exist.
  197. DuidPtr getClientId() const;
  198. protected:
  199. /// @brief Returns pointer to an option inserted by relay agent.
  200. ///
  201. /// This is a variant of the @ref Pkt6::getRelayOption function which
  202. /// never copies an option returned. This method should be only used by
  203. /// the @ref Pkt6 class and derived classes. Any external callers should
  204. /// use @ref getRelayOption which copies the option before returning it
  205. /// when the @ref Pkt::copy_retrieved_options_ flag is set to true.
  206. ///
  207. /// @param opt_type Code of the requested option.
  208. /// @param relay_level Nesting level as described for
  209. /// @ref Pkt6::getRelayOption.
  210. ///
  211. /// @return Pointer to the option or NULL if such option doesn't exist.
  212. OptionPtr getNonCopiedRelayOption(const uint16_t opt_type,
  213. const uint8_t relay_level) const;
  214. public:
  215. /// @brief Returns option inserted by relay
  216. ///
  217. /// Returns an option from specified relay scope (inserted by a given relay
  218. /// if this is received packet or to be decapsulated by a given relay if
  219. /// this is a transmitted packet). nesting_level specifies which relay
  220. /// scope is to be used. 0 is the outermost encapsulation (relay closest to
  221. /// the server). pkt->relay_info_.size() - 1 is the innermost encapsulation
  222. /// (relay closest to the client).
  223. ///
  224. /// @throw isc::OutOfRange if nesting level has invalid value.
  225. ///
  226. /// @param option_code code of the requested option
  227. /// @param nesting_level see description above
  228. ///
  229. /// @return pointer to the option (or NULL if there is no such option)
  230. OptionPtr getRelayOption(uint16_t option_code, uint8_t nesting_level);
  231. private:
  232. /// @brief Prepares parameters for loop used in @ref getAnyRelayOption
  233. /// and @ref getNonCopiedAnyRelayOption.
  234. ///
  235. /// The methods retrieving "any" relay option iterate over the relay
  236. /// info structures to find the matching option. This method returns
  237. /// the index of the first and last relay info structure to be used
  238. /// for this iteration. It also returns the direction in which the
  239. /// iteration should be performed.
  240. ///
  241. /// @param order Option search order (see @ref RelaySearchOrder).
  242. /// @param [out] start Index of the relay information structure from
  243. /// which the search should be started.
  244. /// @param [out] end Index of the relay information structure on which
  245. /// the option searches should stop.
  246. /// @param [out] direction Equals to -1 for backwards searches, and
  247. /// equals to 1 for forward searches.
  248. void prepareGetAnyRelayOption(const RelaySearchOrder& order,
  249. int& start, int& end, int& direction) const;
  250. protected:
  251. /// @brief Returns pointer to an instance of specified option.
  252. ///
  253. /// This is a variant of @ref getAnyRelayOption but it never copies
  254. /// an option returned. This method should be only used by
  255. /// the @ref Pkt6 class and derived classes. Any external callers should
  256. /// use @ref getAnyRelayOption which copies the option before returning it
  257. /// when the @ref Pkt::copy_retrieved_options_ flag is set to true.
  258. ///
  259. /// @param option_code Searched option.
  260. /// @param order Option search order (see @ref RelaySearchOrder).
  261. ///
  262. /// @return Option pointer or NULL, if no option matches specified criteria.
  263. OptionPtr getNonCopiedAnyRelayOption(const uint16_t option_code,
  264. const RelaySearchOrder& order) const;
  265. public:
  266. /// @brief Return first instance of a specified option
  267. ///
  268. /// When a client's packet traverses multiple relays, each passing relay may
  269. /// insert extra options. This method allows the specific instance of a given
  270. /// option to be obtained (e.g. closest to the client, closest to the server,
  271. /// etc.) See @ref RelaySearchOrder for a detailed description.
  272. ///
  273. /// @param option_code searched option
  274. /// @param order option search order (see @ref RelaySearchOrder)
  275. /// @return option pointer (or NULL if no option matches specified criteria)
  276. OptionPtr getAnyRelayOption(const uint16_t option_code,
  277. const RelaySearchOrder& order);
  278. /// @brief return the link address field from a relay option
  279. ///
  280. /// As with @c Pkt6::getRelayOption this returns information from the
  281. /// specified relay scope. The relay_level specifies which relay
  282. /// scope is to be used. 0 is the outermost encapsulation (relay closest
  283. /// to the server). pkt->relay_info_.size() -1 is the innermost encapsulation
  284. /// (relay closest to the client).
  285. ///
  286. /// @throw isc::OutOfRange if relay level has an invalid value.
  287. ///
  288. /// @param relay_level see description above
  289. ///
  290. /// @return pointer to the link address field
  291. const isc::asiolink::IOAddress&
  292. getRelay6LinkAddress(uint8_t relay_level) const;
  293. /// @brief return the peer address field from a relay option
  294. ///
  295. /// As with @c Pkt6::getRelayOption this returns information from the
  296. /// specified relay scope. The relay_level specifies which relay
  297. /// scope is to be used. 0 is the outermost encapsulation (relay closest
  298. /// to the server). pkt->relay_info_.size() -1 is the innermost encapsulation
  299. /// (relay closest to the client).
  300. ///
  301. /// @throw isc::OutOfRange if relay level has an invalid value.
  302. ///
  303. /// @param relay_level see description above
  304. ///
  305. /// @return pointer to the peer address field
  306. const isc::asiolink::IOAddress&
  307. getRelay6PeerAddress(uint8_t relay_level) const;
  308. protected:
  309. /// @brief Returns all option instances of specified type without
  310. /// copying.
  311. ///
  312. /// This is a variant of @ref getOptions method, which returns a collection
  313. /// of options without copying them. This method should be only used by
  314. /// the @ref Pkt6 class and derived classes. Any external callers should
  315. /// use @ref getOptions which copies option instances before returning them
  316. /// when the @ref Pkt::copy_retrieved_options_ flag is set to true.
  317. ///
  318. /// @param opt_type Option code.
  319. ///
  320. /// @return Collection of options found.
  321. OptionCollection getNonCopiedOptions(const uint16_t opt_type) const;
  322. public:
  323. /// @brief Returns all instances of specified type.
  324. ///
  325. /// Returns all instances of options of the specified type. DHCPv6 protocol
  326. /// allows (and uses frequently) multiple instances.
  327. ///
  328. /// @param type option type we are looking for
  329. /// @return instance of option collection with requested options
  330. isc::dhcp::OptionCollection getOptions(const uint16_t type);
  331. /// @brief add information about one traversed relay
  332. ///
  333. /// This adds information about one traversed relay, i.e.
  334. /// one relay-forw or relay-repl level of encapsulation.
  335. ///
  336. /// @param relay structure with necessary relay information
  337. void addRelayInfo(const RelayInfo& relay);
  338. /// @brief Returns name of the DHCPv6 message for a given type number.
  339. ///
  340. /// As the operation of the method does not depend on any server state, it
  341. /// is declared static. There is also non-static getName() method that
  342. /// works on Pkt6 objects.
  343. ///
  344. /// @param type DHCPv6 message type which name should be returned.
  345. ///
  346. /// @return Pointer to "const" string containing the message name. If
  347. /// the message type is unknown the "UNKNOWN" is returned. The caller
  348. /// must not release the returned pointer.
  349. static const char* getName(const uint8_t type);
  350. /// @brief Returns name of the DHCPv6 message.
  351. ///
  352. /// This method requires an object. There is also a static version, which
  353. /// requires one parameter (type).
  354. ///
  355. /// @return Pointer to "const" string containing the message name. If
  356. /// the message type is unknown the "UNKNOWN" is returned. The caller
  357. /// must not release the returned pointer.
  358. const char* getName() const;
  359. /// @brief copies relay information from client's packet to server's response
  360. ///
  361. /// This information is not simply copied over. Some parameter are
  362. /// removed, msg_type_is updated (RELAY-FORW => RELAY-REPL), etc.
  363. ///
  364. /// @param question client's packet
  365. void copyRelayInfo(const Pkt6Ptr& question);
  366. /// @brief Relay information.
  367. ///
  368. /// This is a public field. Otherwise we hit one of the two problems:
  369. /// we return reference to an internal field (and that reference could
  370. /// be potentially used past Pkt6 object lifetime causing badness) or
  371. /// we return a copy (which is inefficient and also causes any updates
  372. /// to be impossible). Therefore public field is considered the best
  373. /// (or least bad) solution.
  374. ///
  375. /// This vector is arranged in the order packet is encapsulated, i.e.
  376. /// relay[0] was the outermost encapsulation (relay closest to the server),
  377. /// relay[last] was the innermost encapsulation (relay closest to the
  378. /// client).
  379. std::vector<RelayInfo> relay_info_;
  380. protected:
  381. /// @brief Attempts to generate MAC/Hardware address from IPv6 link-local
  382. /// address.
  383. ///
  384. /// This method uses source IPv6 address for direct messages and the
  385. /// peeraddr or the first relay that saw that packet. It may fail if the
  386. /// address is not link-local or does not use EUI-64 identifier.
  387. ///
  388. /// @return Hardware address (or NULL)
  389. virtual HWAddrPtr getMACFromSrcLinkLocalAddr();
  390. /// @brief Extract MAC/Hardware address from client link-layer address
  391. // option inserted by a relay agent (RFC6939).
  392. ///
  393. /// This method extracts the client's hardware address from the
  394. // client-linklayer-addr option inserted by the relay agent closest to
  395. // the client.
  396. ///
  397. /// @return Hardware address (or NULL)
  398. virtual HWAddrPtr getMACFromIPv6RelayOpt();
  399. /// @brief Extract MAC/Hardware address from client-id.
  400. ///
  401. /// This method attempts to extract MAC/Hardware address from DUID sent
  402. /// as client-id. This method may fail, as only DUID-LLT and DUID-LL are
  403. /// based on link-layer addresses. Client may use other valid DUID types
  404. /// and this method will fail.
  405. ///
  406. /// @return Hardware address (or NULL)
  407. virtual HWAddrPtr getMACFromDUID();
  408. /// @brief Attempts to extract MAC/Hardware address from DOCSIS options
  409. /// inserted by the modem itself.
  410. ///
  411. /// The mechanism extracts that information from DOCSIS option
  412. /// (vendor-specific info, vendor-id=4491, suboption 36). Note that
  413. /// in a DOCSIS capable network, the MAC address information is provided
  414. /// several times. The first is specified by the modem itself. The second
  415. /// is added by the CMTS, which acts as a relay agent. This method
  416. /// attempts to extract the former. See @ref getMACFromDocsisCMTS
  417. /// for a similar method that extracts from the CMTS (relay) options.
  418. ///
  419. /// @return hardware address (if DOCSIS suboption 36 is present)
  420. virtual HWAddrPtr getMACFromDocsisModem();
  421. /// @brief Attempts to extract MAC/Hardware address from DOCSIS options.
  422. ///
  423. /// The DHCPv6 mechanism extracts that information from DOCSIS option
  424. /// (vendor-specific info, vendor-id=4491, suboption 1026). Note that
  425. /// in a DOCSIS capable network, the MAC address information is provided
  426. /// several times. The first is specified by the modem itself. The second
  427. /// is added by the CMTS, which acts as a relay agent. This method
  428. /// attempts to extract the latter. See @ref getMACFromDocsisModem
  429. /// for a similar method that extracts from the modem (client) options.
  430. ///
  431. /// @return hardware address (if DOCSIS suboption 1026 is present)
  432. virtual HWAddrPtr getMACFromDocsisCMTS();
  433. /// @brief Attempts to obtain MAC address from remote-id relay option.
  434. ///
  435. /// This method is called from getMAC(HWADDR_SOURCE_REMOTE_ID) and should not be
  436. /// called directly. It will attempt to extract MAC address information
  437. /// from remote-id option inserted by a relay agent closest to the client.
  438. /// If this method fails, it will return NULL.
  439. ///
  440. /// @return hardware address (or NULL)
  441. virtual HWAddrPtr getMACFromRemoteIdRelayOption();
  442. /// @brief Builds on wire packet for TCP transmission.
  443. ///
  444. /// @todo This function is not implemented yet.
  445. ///
  446. /// @throw NotImplemented, IPv6 over TCP is not yet supported.
  447. void packTCP();
  448. /// @brief Builds on wire packet for UDP transmission.
  449. ///
  450. /// @throw InvalidOperation if packing fails
  451. void packUDP();
  452. /// @brief Parses on-wire form of TCP DHCPv6 packet.
  453. ///
  454. /// Parses received packet, stored in on-wire format in data_.
  455. /// data_len_ must be set to indicate data length.
  456. /// Will create a collection of option objects that will
  457. /// be stored in options_ container.
  458. ///
  459. /// @todo This function is not implemented yet.
  460. ///
  461. /// @throw tbd
  462. void unpackTCP();
  463. /// @brief Parses on-wire form of UDP DHCPv6 packet.
  464. ///
  465. /// Parses received packet, stored in on-wire format in data_.
  466. /// data_len_ must be set to indicate data length.
  467. /// Will create a collection of option objects that will
  468. /// be stored in options_ container.
  469. ///
  470. /// @throw tbd
  471. void unpackUDP();
  472. /// @brief Unpacks direct (non-relayed) message.
  473. ///
  474. /// This method unpacks specified buffer range as a direct
  475. /// (e.g. solicit or request) message. This method is called from
  476. /// unpackUDP() when received message is detected to be direct.
  477. ///
  478. /// @param begin start of the buffer
  479. /// @param end end of the buffer
  480. /// @throw tbd
  481. void unpackMsg(OptionBuffer::const_iterator begin,
  482. OptionBuffer::const_iterator end);
  483. /// @brief Unpacks relayed message (RELAY-FORW or RELAY-REPL).
  484. ///
  485. /// This method is called from unpackUDP() when received message
  486. /// is detected to be relay-message. It goes iteratively over
  487. /// all relays (if there are multiple encapsulation levels).
  488. ///
  489. /// @throw tbd
  490. void unpackRelayMsg();
  491. /// @brief Calculates overhead introduced in specified relay.
  492. ///
  493. /// It is used when calculating message size and packing message
  494. /// @param relay RelayInfo structure that holds information about relay
  495. /// @return number of bytes needed to store relay information
  496. uint16_t getRelayOverhead(const RelayInfo& relay) const;
  497. /// @brief Calculates overhead for all relays defined for this message.
  498. /// @return number of bytes needed to store all relay information
  499. uint16_t calculateRelaySizes();
  500. /// @brief Calculates size of the message as if it was not relayed at all.
  501. ///
  502. /// This is equal to len() if the message was not relayed.
  503. /// @return number of bytes required to store the message
  504. uint16_t directLen() const;
  505. /// UDP (usually) or TCP (bulk leasequery or failover)
  506. DHCPv6Proto proto_;
  507. /// DHCPv6 message type
  508. uint8_t msg_type_;
  509. }; // Pkt6 class
  510. } // isc::dhcp namespace
  511. } // isc namespace
  512. #endif