ipv4_header.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // ipv4_header.hpp
  3. // ~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef __ASIO2_IPV4_HEADER_HPP__
  11. #define __ASIO2_IPV4_HEADER_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <algorithm>
  16. #include <asio2/external/asio.hpp>
  17. // Packet header for IPv4.
  18. //
  19. // The wire format of an IPv4 header is:
  20. //
  21. // 0 8 16 31
  22. // +-------+-------+---------------+------------------------------+ ---
  23. // | | | | | ^
  24. // |version|header | type of | total length in bytes | |
  25. // | (4) | length| service | | |
  26. // +-------+-------+---------------+-+-+-+------------------------+ |
  27. // | | | | | | |
  28. // | identification |0|D|M| fragment offset | |
  29. // | | |F|F| | |
  30. // +---------------+---------------+-+-+-+------------------------+ |
  31. // | | | | |
  32. // | time to live | protocol | header checksum | 20 bytes
  33. // | | | | |
  34. // +---------------+---------------+------------------------------+ |
  35. // | | |
  36. // | source IPv4 address | |
  37. // | | |
  38. // +--------------------------------------------------------------+ |
  39. // | | |
  40. // | destination IPv4 address | |
  41. // | | v
  42. // +--------------------------------------------------------------+ ---
  43. // | | ^
  44. // | | |
  45. // / options (if any) / 0 - 40
  46. // / / bytes
  47. // | | |
  48. // | | v
  49. // +--------------------------------------------------------------+ ---
  50. namespace asio2::detail
  51. {
  52. class ipv4_header
  53. {
  54. public:
  55. ipv4_header()
  56. {
  57. std::fill(rep_, rep_ + sizeof(rep_), static_cast<unsigned char>(0));
  58. }
  59. inline unsigned char version() const { return (rep_[0] >> 4) & 0xF; }
  60. inline unsigned short header_length() const { return (unsigned short)((rep_[0] & 0xF) * 4); }
  61. inline unsigned char type_of_service() const { return rep_[1]; }
  62. inline unsigned short total_length() const { return decode(2, 3); }
  63. inline unsigned short identification() const { return decode(4, 5); }
  64. inline bool dont_fragment() const { return (rep_[6] & 0x40) != 0; }
  65. inline bool more_fragments() const { return (rep_[6] & 0x20) != 0; }
  66. inline unsigned short fragment_offset() const { return decode(6, 7) & 0x1FFF; }
  67. inline unsigned int time_to_live() const { return rep_[8]; }
  68. inline unsigned char protocol() const { return rep_[9]; }
  69. inline unsigned short header_checksum() const { return decode(10, 11); }
  70. inline asio::ip::address_v4 source_address() const
  71. {
  72. asio::ip::address_v4::bytes_type bytes = { { rep_[12], rep_[13], rep_[14], rep_[15] } };
  73. return asio::ip::address_v4(bytes);
  74. }
  75. inline asio::ip::address_v4 destination_address() const
  76. {
  77. asio::ip::address_v4::bytes_type bytes = { { rep_[16], rep_[17], rep_[18], rep_[19] } };
  78. return asio::ip::address_v4(bytes);
  79. }
  80. friend std::istream& operator>>(std::istream& is, ipv4_header& header)
  81. {
  82. is.read(reinterpret_cast<char*>(header.rep_), 20);
  83. if (header.version() != 4)
  84. is.setstate(std::ios::failbit);
  85. std::streamsize options_length = header.header_length() - 20;
  86. if (options_length < 0 || options_length > 40)
  87. is.setstate(std::ios::failbit);
  88. else
  89. is.read(reinterpret_cast<char*>(header.rep_) + 20, options_length);
  90. return is;
  91. }
  92. private:
  93. inline unsigned short decode(int a, int b) const
  94. {
  95. return (unsigned short)((rep_[a] << 8) + rep_[b]);
  96. }
  97. unsigned char rep_[60];
  98. };
  99. }
  100. #endif // __ASIO2_IPV4_HEADER_HPP__