pkt4.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. // Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef PKT4_H
  15. #define PKT4_H
  16. #include <asiolink/io_address.h>
  17. #include <util/buffer.h>
  18. #include <dhcp/option.h>
  19. #include <dhcp/hwaddr.h>
  20. #include <boost/date_time/posix_time/posix_time.hpp>
  21. #include <boost/shared_ptr.hpp>
  22. #include <iostream>
  23. #include <vector>
  24. #include <time.h>
  25. namespace isc {
  26. namespace dhcp {
  27. class Pkt4 {
  28. public:
  29. /// length of the CHADDR field in DHCPv4 message
  30. const static size_t MAX_CHADDR_LEN = 16;
  31. /// length of the SNAME field in DHCPv4 message
  32. const static size_t MAX_SNAME_LEN = 64;
  33. /// length of the FILE field in DHCPv4 message
  34. const static size_t MAX_FILE_LEN = 128;
  35. /// specifies DHCPv4 packet header length (fixed part)
  36. const static size_t DHCPV4_PKT_HDR_LEN = 236;
  37. /// Mask for the value of flags field in the DHCPv4 message
  38. /// to check whether client requested broadcast response.
  39. const static uint16_t FLAG_BROADCAST_MASK = 0x8000;
  40. /// Constructor, used in replying to a message.
  41. ///
  42. /// @param msg_type type of message (e.g. DHCPDISOVER=1)
  43. /// @param transid transaction-id
  44. Pkt4(uint8_t msg_type, uint32_t transid);
  45. /// @brief Constructor, used in message reception.
  46. ///
  47. /// Creates new message. Pkt4 will copy data to bufferIn_
  48. /// buffer on creation.
  49. ///
  50. /// @param data pointer to received data
  51. /// @param len size of buffer to be allocated for this packet.
  52. Pkt4(const uint8_t* data, size_t len);
  53. /// @brief Prepares on-wire format of DHCPv4 packet.
  54. ///
  55. /// Prepares on-wire format of message and all its options.
  56. /// Options must be stored in options_ field.
  57. /// Output buffer will be stored in buffer_out_.
  58. ///
  59. /// @throw InvalidOperation if packing fails
  60. void
  61. pack();
  62. /// @brief Parses on-wire form of DHCPv4 packet.
  63. ///
  64. /// Parses received packet, stored in on-wire format in bufferIn_.
  65. ///
  66. /// Will create a collection of option objects that will
  67. /// be stored in options_ container.
  68. ///
  69. /// Method with throw exception if packet parsing fails.
  70. void unpack();
  71. /// @brief performs sanity check on a packet.
  72. ///
  73. /// This is usually performed after unpack(). It checks if packet is sane:
  74. /// required options are present, fields have sane content etc.
  75. /// For example verifies that DHCP_MESSAGE_TYPE is present and have
  76. /// reasonable value. This method is expected to grow significantly.
  77. /// It makes sense to separate unpack() and check() for testing purposes.
  78. ///
  79. /// @todo It is called from unpack() directly. It should be separated.
  80. ///
  81. /// Method will throw exception if anomaly is found.
  82. void check();
  83. /// @brief Copies content of input buffer to output buffer.
  84. ///
  85. /// This is mostly a diagnostic function. It is being used for sending
  86. /// received packet. Received packet is stored in bufferIn_, but
  87. /// transmitted data is stored in buffer_out_. If we want to send packet
  88. /// that we just received, a copy between those two buffers is necessary.
  89. void repack();
  90. /// @brief Returns text representation of the packet.
  91. ///
  92. /// This function is useful mainly for debugging.
  93. ///
  94. /// @return string with text representation
  95. std::string toText();
  96. /// @brief Returns the size of the required buffer to build the packet.
  97. ///
  98. /// Returns the size of the required buffer to build the packet with
  99. /// the current set of packet options.
  100. ///
  101. /// @return number of bytes required to build this packet
  102. size_t len();
  103. /// @brief Sets hops field.
  104. ///
  105. /// @param hops value to be set
  106. void setHops(uint8_t hops) { hops_ = hops; };
  107. /// @brief Returns hops field.
  108. ///
  109. /// @return hops field
  110. uint8_t getHops() const { return (hops_); };
  111. // Note: There's no need to manipulate OP field directly,
  112. // thus no setOp() method. See op_ comment.
  113. /// @brief Returns op field.
  114. ///
  115. /// @return op field
  116. uint8_t getOp() const { return (op_); };
  117. /// @brief Sets secs field.
  118. ///
  119. /// @param secs value to be set
  120. void setSecs(uint16_t secs) { secs_ = secs; };
  121. /// @brief Returns secs field.
  122. ///
  123. /// @return secs field
  124. uint16_t getSecs() const { return (secs_); };
  125. /// @brief Sets flags field.
  126. ///
  127. /// @param flags value to be set
  128. void setFlags(uint16_t flags) { flags_ = flags; };
  129. /// @brief Returns flags field.
  130. ///
  131. /// @return flags field
  132. uint16_t getFlags() const { return (flags_); };
  133. /// @brief Returns ciaddr field.
  134. ///
  135. /// @return ciaddr field
  136. const isc::asiolink::IOAddress&
  137. getCiaddr() const { return (ciaddr_); };
  138. /// @brief Sets ciaddr field.
  139. ///
  140. /// @param ciaddr value to be set
  141. void
  142. setCiaddr(const isc::asiolink::IOAddress& ciaddr) { ciaddr_ = ciaddr; };
  143. /// @brief Returns siaddr field.
  144. ///
  145. /// @return siaddr field
  146. const isc::asiolink::IOAddress&
  147. getSiaddr() const { return (siaddr_); };
  148. /// @brief Sets siaddr field.
  149. ///
  150. /// @param siaddr value to be set
  151. void
  152. setSiaddr(const isc::asiolink::IOAddress& siaddr) { siaddr_ = siaddr; };
  153. /// @brief Returns yiaddr field.
  154. ///
  155. /// @return yiaddr field
  156. const isc::asiolink::IOAddress&
  157. getYiaddr() const { return (yiaddr_); };
  158. /// @brief Sets yiaddr field.
  159. ///
  160. /// @param yiaddr value to be set
  161. void
  162. setYiaddr(const isc::asiolink::IOAddress& yiaddr) { yiaddr_ = yiaddr; };
  163. /// @brief Returns giaddr field.
  164. ///
  165. /// @return giaddr field
  166. const isc::asiolink::IOAddress&
  167. getGiaddr() const { return (giaddr_); };
  168. /// @brief Sets giaddr field.
  169. ///
  170. /// @param giaddr value to be set
  171. void
  172. setGiaddr(const isc::asiolink::IOAddress& giaddr) { giaddr_ = giaddr; };
  173. /// @brief Sets transaction-id value
  174. ///
  175. /// @param transid transaction-id to be set.
  176. void setTransid(uint32_t transid) { transid_ = transid; }
  177. /// @brief Returns value of transaction-id field.
  178. ///
  179. /// @return transaction-id
  180. uint32_t getTransid() const { return (transid_); };
  181. /// @brief Returns DHCP message type (e.g. 1 = DHCPDISCOVER).
  182. ///
  183. /// @return message type
  184. uint8_t getType() const;
  185. /// @brief Sets DHCP message type (e.g. 1 = DHCPDISCOVER).
  186. ///
  187. /// @param type message type to be set
  188. void setType(uint8_t type);
  189. /// @brief Returns sname field
  190. ///
  191. /// Note: This is 64 bytes long field. It doesn't have to be
  192. /// null-terminated. Do not use strlen() or similar on it.
  193. ///
  194. /// @return sname field
  195. const OptionBuffer
  196. getSname() const { return (std::vector<uint8_t>(sname_, &sname_[MAX_SNAME_LEN])); };
  197. /// @brief Sets sname field.
  198. ///
  199. /// @param sname value to be set
  200. /// @param sname_len length of the sname buffer (up to MAX_SNAME_LEN)
  201. void setSname(const uint8_t* sname, size_t sname_len = MAX_SNAME_LEN);
  202. /// @brief Returns file field
  203. ///
  204. /// Note: This is 128 bytes long field. It doesn't have to be
  205. /// null-terminated. Do not use strlen() or similar on it.
  206. ///
  207. /// @return pointer to file field
  208. const OptionBuffer
  209. getFile() const { return (std::vector<uint8_t>(file_, &file_[MAX_FILE_LEN])); };
  210. /// Sets file field
  211. ///
  212. /// @param file value to be set
  213. /// @param file_len length of the file buffer (up to MAX_FILE_LEN)
  214. void
  215. setFile(const uint8_t* file, size_t file_len = MAX_FILE_LEN);
  216. /// @brief Sets hardware address.
  217. ///
  218. /// Sets parameters of hardware address. hlen specifies
  219. /// length of mac_addr buffer. Content of mac_addr buffer
  220. /// will be copied to appropriate field.
  221. ///
  222. /// Note: mac_addr must be a buffer of at least hlen bytes.
  223. ///
  224. /// @param htype hardware type (will be sent in htype field)
  225. /// @param hlen hardware length (will be sent in hlen field)
  226. /// @param mac_addr pointer to hardware address
  227. void setHWAddr(uint8_t htype, uint8_t hlen,
  228. const std::vector<uint8_t>& mac_addr);
  229. /// @brief Sets hardware address
  230. ///
  231. /// Sets hardware address, based on existing HWAddr structure
  232. /// @param addr already filled in HWAddr structure
  233. /// @throw BadValue if addr is null
  234. void setHWAddr(const HWAddrPtr& addr);
  235. /// Returns htype field
  236. ///
  237. /// @return hardware type
  238. uint8_t
  239. getHtype() const;
  240. /// Returns hlen field
  241. ///
  242. /// @return hardware address length
  243. uint8_t
  244. getHlen() const;
  245. /// @brief returns hardware address information
  246. /// @return hardware address structure
  247. HWAddrPtr getHWAddr() const { return (hwaddr_); }
  248. /// @brief Returns reference to output buffer.
  249. ///
  250. /// Returned buffer will contain reasonable data only for
  251. /// output (TX) packet and after pack() was called. This buffer
  252. /// is only valid till Pkt4 object is valid.
  253. ///
  254. /// RX packet or TX packet before pack() will return buffer with
  255. /// zero length. This buffer is returned as non-const, so hooks
  256. /// framework (and user's callouts) can modify them if needed
  257. ///
  258. /// @return reference to output buffer
  259. isc::util::OutputBuffer&
  260. getBuffer() { return (buffer_out_); };
  261. /// @brief Add an option.
  262. ///
  263. /// Throws BadValue if option with that type is already present.
  264. ///
  265. /// @param opt option to be added
  266. void
  267. addOption(boost::shared_ptr<Option> opt);
  268. /// @brief Returns an option of specified type.
  269. ///
  270. /// @return returns option of requested type (or NULL)
  271. /// if no such option is present
  272. boost::shared_ptr<Option>
  273. getOption(uint8_t opt_type) const;
  274. /// @brief Deletes specified option
  275. /// @param type option type to be deleted
  276. /// @return true if anything was deleted, false otherwise
  277. bool delOption(uint8_t type);
  278. /// @brief Returns interface name.
  279. ///
  280. /// Returns interface name over which packet was received or is
  281. /// going to be transmitted.
  282. ///
  283. /// @return interface name
  284. std::string getIface() const { return iface_; };
  285. /// @brief Returns packet timestamp.
  286. ///
  287. /// Returns packet timestamp value updated when
  288. /// packet is received or send.
  289. ///
  290. /// @return packet timestamp.
  291. const boost::posix_time::ptime& getTimestamp() const { return timestamp_; }
  292. /// @brief Sets interface name.
  293. ///
  294. /// Sets interface name over which packet was received or is
  295. /// going to be transmitted.
  296. ///
  297. /// @return interface name
  298. void setIface(const std::string& iface ) { iface_ = iface; };
  299. /// @brief Sets interface index.
  300. ///
  301. /// @param ifindex specifies interface index.
  302. void setIndex(uint32_t ifindex) { ifindex_ = ifindex; };
  303. /// @brief Returns interface index.
  304. ///
  305. /// @return interface index
  306. uint32_t getIndex() const { return (ifindex_); };
  307. /// @brief Sets remote HW address.
  308. ///
  309. /// Sets the destination HW address for the outgoing packet
  310. /// or source HW address for the incoming packet. When this
  311. /// is an outgoing packet this address will be used to construct
  312. /// the link layer header.
  313. ///
  314. /// @note mac_addr must be a buffer of at least hlen bytes.
  315. ///
  316. /// @param htype hardware type (will be sent in htype field)
  317. /// @param hlen hardware length (will be sent in hlen field)
  318. /// @param mac_addr pointer to hardware address
  319. void setRemoteHWAddr(const uint8_t htype, const uint8_t hlen,
  320. const std::vector<uint8_t>& mac_addr);
  321. /// @brief Sets remote HW address.
  322. ///
  323. /// Sets hardware address from an existing HWAddr structure.
  324. /// The remote address is a destination address for outgoing
  325. /// packet and source address for incoming packet. When this
  326. /// is an outgoing packet, this address will be used to
  327. /// construct the link layer header.
  328. ///
  329. /// @param addr structure representing HW address.
  330. ///
  331. /// @throw BadValue if addr is null
  332. void setRemoteHWAddr(const HWAddrPtr& addr);
  333. /// @brief Returns the remote HW address.
  334. ///
  335. /// @return remote HW address.
  336. HWAddrPtr getRemoteHWAddr() const {
  337. return (remote_hwaddr_);
  338. }
  339. /// @brief Sets local HW address.
  340. ///
  341. /// Sets the source HW address for the outgoing packet or
  342. /// destination HW address for the incoming packet.
  343. ///
  344. /// @note mac_addr must be a buffer of at least hlen bytes.
  345. ///
  346. /// @param htype hardware type (will be sent in htype field)
  347. /// @param hlen hardware length (will be sent in hlen field)
  348. /// @param mac_addr pointer to hardware address
  349. void setLocalHWAddr(const uint8_t htype, const uint8_t hlen,
  350. const std::vector<uint8_t>& mac_addr);
  351. /// @brief Sets local HW address.
  352. ///
  353. /// Sets hardware address from an existing HWAddr structure.
  354. /// The local address is a source address for outgoing
  355. /// packet and destination address for incoming packet.
  356. ///
  357. /// @param addr structure representing HW address.
  358. ///
  359. /// @throw BadValue if addr is null
  360. void setLocalHWAddr(const HWAddrPtr& addr);
  361. /// @brief Returns local HW address.
  362. ///
  363. /// @return local HW addr.
  364. HWAddrPtr getLocalHWAddr() const {
  365. return (local_hwaddr_);
  366. }
  367. /// @brief Sets remote address.
  368. ///
  369. /// @param remote specifies remote address
  370. void setRemoteAddr(const isc::asiolink::IOAddress& remote) {
  371. remote_addr_ = remote;
  372. }
  373. /// @brief Returns remote address
  374. ///
  375. /// @return remote address
  376. const isc::asiolink::IOAddress& getRemoteAddr() const {
  377. return (remote_addr_);
  378. }
  379. /// @brief Sets local address.
  380. ///
  381. /// @param local specifies local address
  382. void setLocalAddr(const isc::asiolink::IOAddress& local) {
  383. local_addr_ = local;
  384. }
  385. /// @brief Returns local address.
  386. ///
  387. /// @return local address
  388. const isc::asiolink::IOAddress& getLocalAddr() const {
  389. return (local_addr_);
  390. }
  391. /// @brief Sets local port.
  392. ///
  393. /// @param local specifies local port
  394. void setLocalPort(uint16_t local) { local_port_ = local; }
  395. /// @brief Returns local port.
  396. ///
  397. /// @return local port
  398. uint16_t getLocalPort() const { return (local_port_); }
  399. /// @brief Sets remote port.
  400. ///
  401. /// @param remote specifies remote port
  402. void setRemotePort(uint16_t remote) { remote_port_ = remote; }
  403. /// @brief Returns remote port.
  404. ///
  405. /// @return remote port
  406. uint16_t getRemotePort() const { return (remote_port_); }
  407. /// @brief Update packet timestamp.
  408. ///
  409. /// Updates packet timestamp. This method is invoked
  410. /// by interface manager just before sending or
  411. /// just after receiving it.
  412. /// @throw isc::Unexpected if timestamp update failed
  413. void updateTimestamp();
  414. /// Output buffer (used during message transmission)
  415. ///
  416. /// @warning This public member is accessed by derived
  417. /// classes directly. One of such derived classes is
  418. /// @ref perfdhcp::PerfPkt4. The impact on derived clasess'
  419. /// behavior must be taken into consideration before making
  420. /// changes to this member such as access scope restriction or
  421. /// data format change etc. This field is also public, because
  422. /// it may be modified by callouts (which are written in C++ now,
  423. /// but we expect to also have them in Python, so any accesibility
  424. /// methods would overly complicate things here and degrade
  425. /// performance).
  426. isc::util::OutputBuffer buffer_out_;
  427. /// @brief That's the data of input buffer used in RX packet.
  428. ///
  429. /// @note Note that InputBuffer does not store the data itself, but just
  430. /// expects that data will be valid for the whole life of InputBuffer.
  431. /// Therefore we need to keep the data around.
  432. ///
  433. /// @warning This public member is accessed by derived
  434. /// classes directly. One of such derived classes is
  435. /// @ref perfdhcp::PerfPkt4. The impact on derived clasess'
  436. /// behavior must be taken into consideration before making
  437. /// changes to this member such as access scope restriction or
  438. /// data format change etc. This field is also public, because
  439. /// it may be modified by callouts (which are written in C++ now,
  440. /// but we expect to also have them in Python, so any accesibility
  441. /// methods would overly complicate things here and degrade
  442. /// performance).
  443. std::vector<uint8_t> data_;
  444. private:
  445. /// @brief Generic method that validates and sets HW address.
  446. ///
  447. /// This is a generic method used by all modifiers of this class
  448. /// which set class members representing HW address.
  449. ///
  450. /// @param htype hardware type.
  451. /// @param hlen hardware length.
  452. /// @param mac_addr pointer to actual hardware address.
  453. /// @param [out] hw_addr pointer to a class member to be modified.
  454. ///
  455. /// @trow isc::OutOfRange if invalid HW address specified.
  456. void setHWAddrMember(const uint8_t htype, const uint8_t hlen,
  457. const std::vector<uint8_t>& mac_addr,
  458. HWAddrPtr& hw_addr);
  459. protected:
  460. /// converts DHCP message type to BOOTP op type
  461. ///
  462. /// @param dhcpType DHCP message type (e.g. DHCPDISCOVER)
  463. ///
  464. /// @return BOOTP type (BOOTREQUEST or BOOTREPLY)
  465. uint8_t
  466. DHCPTypeToBootpType(uint8_t dhcpType);
  467. /// local HW address (dst if receiving packet, src if sending packet)
  468. HWAddrPtr local_hwaddr_;
  469. // remote HW address (src if receiving packet, dst if sending packet)
  470. HWAddrPtr remote_hwaddr_;
  471. /// local address (dst if receiving packet, src if sending packet)
  472. isc::asiolink::IOAddress local_addr_;
  473. /// remote address (src if receiving packet, dst if sending packet)
  474. isc::asiolink::IOAddress remote_addr_;
  475. /// name of the network interface the packet was received/to be sent over
  476. std::string iface_;
  477. /// @brief interface index
  478. ///
  479. /// Each network interface has assigned unique ifindex. It is functional
  480. /// equivalent of name, but sometimes more useful, e.g. when using crazy
  481. /// systems that allow spaces in interface names e.g. MS Windows)
  482. uint32_t ifindex_;
  483. /// local UDP port
  484. uint16_t local_port_;
  485. /// remote UDP port
  486. uint16_t remote_port_;
  487. /// @brief message operation code
  488. ///
  489. /// Note: This is legacy BOOTP field. There's no need to manipulate it
  490. /// directly. Its value is set based on DHCP message type. Note that
  491. /// DHCPv4 protocol reuses BOOTP message format, so this field is
  492. /// kept due to BOOTP format. This is NOT DHCPv4 type (DHCPv4 message
  493. /// type is kept in message type option).
  494. uint8_t op_;
  495. /// @brief link-layer address and hardware information
  496. /// represents 3 fields: htype (hardware type, 1 byte), hlen (length of the
  497. /// hardware address, up to 16) and chaddr (hardware address field,
  498. /// 16 bytes)
  499. HWAddrPtr hwaddr_;
  500. /// Number of relay agents traversed
  501. uint8_t hops_;
  502. /// DHCPv4 transaction-id (32 bits, not 24 bits as in DHCPv6)
  503. uint32_t transid_;
  504. /// elapsed (number of seconds since beginning of transmission)
  505. uint16_t secs_;
  506. /// flags
  507. uint16_t flags_;
  508. /// ciaddr field (32 bits): Client's IP address
  509. isc::asiolink::IOAddress ciaddr_;
  510. /// yiaddr field (32 bits): Client's IP address ("your"), set by server
  511. isc::asiolink::IOAddress yiaddr_;
  512. /// siaddr field (32 bits): next server IP address in boot process(e.g.TFTP)
  513. isc::asiolink::IOAddress siaddr_;
  514. /// giaddr field (32 bits): Gateway IP address
  515. isc::asiolink::IOAddress giaddr_;
  516. /// sname field (64 bytes)
  517. uint8_t sname_[MAX_SNAME_LEN];
  518. /// file field (128 bytes)
  519. uint8_t file_[MAX_FILE_LEN];
  520. // end of real DHCPv4 fields
  521. /// collection of options present in this message
  522. ///
  523. /// @warning This protected member is accessed by derived
  524. /// classes directly. One of such derived classes is
  525. /// @ref perfdhcp::PerfPkt4. The impact on derived classes'
  526. /// behavior must be taken into consideration before making
  527. /// changes to this member such as access scope restriction or
  528. /// data format change etc.
  529. isc::dhcp::Option::OptionCollection options_;
  530. /// packet timestamp
  531. boost::posix_time::ptime timestamp_;
  532. }; // Pkt4 class
  533. typedef boost::shared_ptr<Pkt4> Pkt4Ptr;
  534. } // isc::dhcp namespace
  535. } // isc namespace
  536. #endif