pkt4.h 15 KB

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