pkt4.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. // Copyright (C) 2011 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 <iostream>
  17. #include <vector>
  18. #include <boost/shared_ptr.hpp>
  19. #include <boost/shared_array.hpp>
  20. #include "asiolink/io_address.h"
  21. #include "util/buffer.h"
  22. #include "dhcp/option.h"
  23. namespace isc {
  24. namespace dhcp {
  25. class Pkt4 {
  26. public:
  27. /// length of the CHADDR field in DHCPv4 message
  28. const static size_t MAX_CHADDR_LEN = 16;
  29. /// length of the SNAME field in DHCPv4 message
  30. const static size_t MAX_SNAME_LEN = 64;
  31. /// length of the FILE field in DHCPv4 message
  32. const static size_t MAX_FILE_LEN = 128;
  33. /// specifies DHCPv4 packet header length (fixed part)
  34. const static size_t DHCPV4_PKT_HDR_LEN = 236;
  35. /// Constructor, used in replying to a message.
  36. ///
  37. /// @param msg_type type of message (e.g. DHCPDISOVER=1)
  38. /// @param transid transaction-id
  39. Pkt4(uint8_t msg_type, uint32_t transid);
  40. /// @brief Constructor, used in message reception.
  41. ///
  42. /// Creates new message. Pkt4 will copy data to bufferIn_
  43. /// buffer on creation.
  44. ///
  45. /// @param data pointer to received data
  46. /// @param len size of buffer to be allocated for this packet.
  47. Pkt4(const uint8_t* data, size_t len);
  48. /// @brief Prepares on-wire format of DHCPv4 packet.
  49. ///
  50. /// Prepares on-wire format of message and all its options.
  51. /// Options must be stored in options_ field.
  52. /// Output buffer will be stored in bufferOut_.
  53. ///
  54. /// @return true if packing procedure was successful
  55. bool
  56. pack();
  57. /// @brief Parses on-wire form of DHCPv4 packet.
  58. ///
  59. /// Parses received packet, stored in on-wire format in bufferIn_.
  60. ///
  61. /// Will create a collection of option objects that will
  62. /// be stored in options_ container.
  63. ///
  64. /// @return true, if parsing was successful
  65. bool
  66. unpack();
  67. /// @brief Returns text representation of the packet.
  68. ///
  69. /// This function is useful mainly for debugging.
  70. ///
  71. /// @return string with text representation
  72. std::string
  73. toText();
  74. /// @brief Returns the size of the required buffer to build the packet.
  75. ///
  76. /// Returns the size of the required buffer to build the packet with
  77. /// the current set of packet options.
  78. ///
  79. /// @return number of bytes required to build this packet
  80. size_t
  81. len();
  82. /// Sets hops field
  83. ///
  84. /// @param hops value to be set
  85. void
  86. setHops(uint8_t hops) { hops_ = hops; };
  87. /// Returns hops field
  88. ///
  89. /// @return hops field
  90. uint8_t
  91. getHops() const { return (hops_); };
  92. // Note: There's no need to manipulate OP field directly,
  93. // thus no setOp() method. See op_ comment.
  94. /// Returns op field
  95. ///
  96. /// @return op field
  97. uint8_t
  98. getOp() const { return (op_); };
  99. /// Sets secs field
  100. ///
  101. /// @param secs value to be set
  102. void
  103. setSecs(uint16_t secs) { secs_ = secs; };
  104. /// Returns secs field
  105. ///
  106. /// @return secs field
  107. uint16_t
  108. getSecs() const { return (secs_); };
  109. /// Sets flags field
  110. ///
  111. /// @param flags value to be set
  112. void
  113. setFlags(uint16_t flags) { flags_ = flags; };
  114. /// Returns flags field
  115. ///
  116. /// @return flags field
  117. uint16_t
  118. getFlags() const { return (flags_); };
  119. /// Returns ciaddr field
  120. ///
  121. /// @return ciaddr field
  122. const isc::asiolink::IOAddress&
  123. getCiaddr() const { return (ciaddr_); };
  124. /// Sets ciaddr field
  125. ///
  126. /// @param ciaddr value to be set
  127. void
  128. setCiaddr(const isc::asiolink::IOAddress& ciaddr) { ciaddr_ = ciaddr; };
  129. /// Returns siaddr field
  130. ///
  131. /// @return siaddr field
  132. const isc::asiolink::IOAddress&
  133. getSiaddr() const { return (siaddr_); };
  134. /// Sets siaddr field
  135. ///
  136. /// @param siaddr value to be set
  137. void
  138. setSiaddr(const isc::asiolink::IOAddress& siaddr) { siaddr_ = siaddr; };
  139. /// Returns yiaddr field
  140. ///
  141. /// @return yiaddr field
  142. const isc::asiolink::IOAddress&
  143. getYiaddr() const { return (yiaddr_); };
  144. /// Sets yiaddr field
  145. ///
  146. /// @param yiaddr value to be set
  147. void
  148. setYiaddr(const isc::asiolink::IOAddress& yiaddr) { yiaddr_ = yiaddr; };
  149. /// Returns giaddr field
  150. ///
  151. /// @return giaddr field
  152. const isc::asiolink::IOAddress&
  153. getGiaddr() const { return (giaddr_); };
  154. /// Sets giaddr field
  155. ///
  156. /// @param giaddr value to be set
  157. void
  158. setGiaddr(const isc::asiolink::IOAddress& giaddr) { giaddr_ = giaddr; };
  159. /// Returns value of transaction-id field
  160. ///
  161. /// @return transaction-id
  162. uint32_t getTransid() const { return (transid_); };
  163. /// Returns message type (e.g. 1 = DHCPDISCOVER)
  164. ///
  165. /// @return message type
  166. uint8_t
  167. getType() const { return (msg_type_); }
  168. /// Sets message type (e.g. 1 = DHCPDISCOVER)
  169. ///
  170. /// @param type message type to be set
  171. void setType(uint8_t type) { msg_type_=type; };
  172. /// @brief Returns sname field
  173. ///
  174. /// Note: This is 64 bytes long field. It doesn't have to be
  175. /// null-terminated. Do not use strlen() or similar on it.
  176. ///
  177. /// @return sname field
  178. const std::vector<uint8_t>
  179. getSname() const { return (std::vector<uint8_t>(sname_, &sname_[MAX_SNAME_LEN])); };
  180. /// Sets sname field
  181. ///
  182. /// @param sname value to be set
  183. void
  184. setSname(const uint8_t* sname, size_t snameLen = MAX_SNAME_LEN);
  185. /// @brief Returns file field
  186. ///
  187. /// Note: This is 128 bytes long field. It doesn't have to be
  188. /// null-terminated. Do not use strlen() or similar on it.
  189. ///
  190. /// @return pointer to file field
  191. const std::vector<uint8_t>
  192. getFile() const { return (std::vector<uint8_t>(file_, &file_[MAX_FILE_LEN])); };
  193. /// Sets file field
  194. ///
  195. /// @param file value to be set
  196. void
  197. setFile(const uint8_t* file, size_t fileLen = MAX_FILE_LEN);
  198. /// @brief Sets hardware address.
  199. ///
  200. /// Sets parameters of hardware address. hlen specifies
  201. /// length of macAddr buffer. Content of macAddr buffer
  202. /// will be copied to appropriate field.
  203. ///
  204. /// Note: macAddr must be a buffer of at least hlen bytes.
  205. ///
  206. /// @param hwType hardware type (will be sent in htype field)
  207. /// @param hlen hardware length (will be sent in hlen field)
  208. /// @param macAddr pointer to hardware address
  209. void setHWAddr(uint8_t hType, uint8_t hlen,
  210. const std::vector<uint8_t>& macAddr);
  211. /// Returns htype field
  212. ///
  213. /// @return hardware type
  214. uint8_t
  215. getHtype() const { return (htype_); };
  216. /// Returns hlen field
  217. ///
  218. /// @return hardware address length
  219. uint8_t
  220. getHlen() const { return (hlen_); };
  221. /// @brief Returns chaddr field.
  222. ///
  223. /// Note: This is 16 bytes long field. It doesn't have to be
  224. /// null-terminated. Do no use strlen() or similar on it.
  225. ///
  226. /// @return pointer to hardware address
  227. const uint8_t*
  228. getChaddr() const { return (chaddr_); };
  229. /// @brief Returns reference to output buffer.
  230. ///
  231. /// Returned buffer will contain reasonable data only for
  232. /// output (TX) packet and after pack() was called. This buffer
  233. /// is only valid till Pkt4 object is valid.
  234. ///
  235. /// RX packet or TX packet before pack() will return buffer with
  236. /// zero length
  237. ///
  238. /// @return reference to output buffer
  239. const isc::util::OutputBuffer&
  240. getBuffer() const { return (bufferOut_); };
  241. /// @brief Add an option.
  242. ///
  243. /// Throws BadValue if option with that type is already present.
  244. ///
  245. /// @param opt option to be added
  246. void
  247. addOption(boost::shared_ptr<Option> opt);
  248. /// @brief Returns an option of specified type.
  249. ///
  250. /// @return returns option of requested type (or NULL)
  251. /// if no such option is present
  252. boost::shared_ptr<Option>
  253. getOption(uint8_t opt_type);
  254. /// @brief set interface over which packet should be sent
  255. ///
  256. /// @param interface defines outbound interface
  257. void setIface(const std::string& interface){ iface_ = interface; }
  258. /// @brief gets interface over which packet was received or
  259. /// will be transmitted
  260. ///
  261. /// @return name of the interface
  262. std::string getIface() const { return iface_; }
  263. protected:
  264. /// converts DHCP message type to BOOTP op type
  265. ///
  266. /// @param dhcpType DHCP message type (e.g. DHCPDISCOVER)
  267. ///
  268. /// @return BOOTP type (BOOTREQUEST or BOOTREPLY)
  269. uint8_t
  270. DHCPTypeToBootpType(uint8_t dhcpType);
  271. /// local address (dst if receiving packet, src if sending packet)
  272. isc::asiolink::IOAddress local_addr_;
  273. /// remote address (src if receiving packet, dst if sending packet)
  274. isc::asiolink::IOAddress remote_addr_;
  275. /// name of the network interface the packet was received/to be sent over
  276. std::string iface_;
  277. /// @brief interface index
  278. ///
  279. /// Each network interface has assigned unique ifindex. It is functional
  280. /// equvalent of name, but sometimes more useful, e.g. when using crazy
  281. /// systems that allow spaces in interface names e.g. MS Windows)
  282. int ifindex_;
  283. /// local UDP port
  284. int local_port_;
  285. /// remote UDP port
  286. int remote_port_;
  287. /// @brief message operation code
  288. ///
  289. /// Note: This is legacy BOOTP field. There's no need to manipulate it
  290. /// directly. Its value is set based on DHCP message type. Note that
  291. /// DHCPv4 protocol reuses BOOTP message format, so this field is
  292. /// kept due to BOOTP format. This is NOT DHCPv4 type (DHCPv4 message
  293. /// type is kept in message type option).
  294. uint8_t op_;
  295. /// link-layer address type
  296. uint8_t htype_;
  297. /// link-layer address length
  298. uint8_t hlen_;
  299. /// Number of relay agents traversed
  300. uint8_t hops_;
  301. /// DHCPv4 transaction-id (32 bits, not 24 bits as in DHCPv6)
  302. uint32_t transid_;
  303. /// elapsed (number of seconds since beginning of transmission)
  304. uint16_t secs_;
  305. /// flags
  306. uint16_t flags_;
  307. /// ciaddr field (32 bits): Client's IP address
  308. isc::asiolink::IOAddress ciaddr_;
  309. /// yiaddr field (32 bits): Client's IP address ("your"), set by server
  310. isc::asiolink::IOAddress yiaddr_;
  311. /// siaddr field (32 bits): next server IP address in boot process(e.g.TFTP)
  312. isc::asiolink::IOAddress siaddr_;
  313. /// giaddr field (32 bits): Gateway IP address
  314. isc::asiolink::IOAddress giaddr_;
  315. /// Hardware address field (16 bytes)
  316. uint8_t chaddr_[MAX_CHADDR_LEN];
  317. /// sname field (64 bytes)
  318. uint8_t sname_[MAX_SNAME_LEN];
  319. /// file field (128 bytes)
  320. uint8_t file_[MAX_FILE_LEN];
  321. // end of real DHCPv4 fields
  322. /// output buffer (used during message
  323. isc::util::OutputBuffer bufferOut_;
  324. // that's the data of input buffer used in RX packet. Note that
  325. // InputBuffer does not store the data itself, but just expects that
  326. // data will be valid for the whole life of InputBuffer. Therefore we
  327. // need to keep the data around.
  328. std::vector<uint8_t> data_;
  329. /// message type (e.g. 1=DHCPDISCOVER)
  330. /// TODO: this will eventually be replaced with DHCP Message Type
  331. /// option (option 53)
  332. uint8_t msg_type_;
  333. /// collection of options present in this message
  334. isc::dhcp::Option::OptionCollection options_;
  335. }; // Pkt4 class
  336. } // isc::dhcp namespace
  337. } // isc namespace
  338. #endif