1 // 2 // ipv4_header.hpp 3 // ~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2020 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 11 #ifndef IPV4_HEADER_HPP 12 #define IPV4_HEADER_HPP 13 14 #include <algorithm> 15 #include <boost/asio/ip/address_v4.hpp> 16 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 51 class ipv4_header 52 { 53 public: ipv4_header()54 ipv4_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); } 55 version() const56 unsigned char version() const { return (rep_[0] >> 4) & 0xF; } header_length() const57 unsigned short header_length() const { return (rep_[0] & 0xF) * 4; } type_of_service() const58 unsigned char type_of_service() const { return rep_[1]; } total_length() const59 unsigned short total_length() const { return decode(2, 3); } identification() const60 unsigned short identification() const { return decode(4, 5); } dont_fragment() const61 bool dont_fragment() const { return (rep_[6] & 0x40) != 0; } more_fragments() const62 bool more_fragments() const { return (rep_[6] & 0x20) != 0; } fragment_offset() const63 unsigned short fragment_offset() const { return decode(6, 7) & 0x1FFF; } time_to_live() const64 unsigned int time_to_live() const { return rep_[8]; } protocol() const65 unsigned char protocol() const { return rep_[9]; } header_checksum() const66 unsigned short header_checksum() const { return decode(10, 11); } 67 source_address() const68 boost::asio::ip::address_v4 source_address() const 69 { 70 boost::asio::ip::address_v4::bytes_type bytes 71 = { { rep_[12], rep_[13], rep_[14], rep_[15] } }; 72 return boost::asio::ip::address_v4(bytes); 73 } 74 destination_address() const75 boost::asio::ip::address_v4 destination_address() const 76 { 77 boost::asio::ip::address_v4::bytes_type bytes 78 = { { rep_[16], rep_[17], rep_[18], rep_[19] } }; 79 return boost::asio::ip::address_v4(bytes); 80 } 81 operator >>(std::istream & is,ipv4_header & header)82 friend std::istream& operator>>(std::istream& is, ipv4_header& header) 83 { 84 is.read(reinterpret_cast<char*>(header.rep_), 20); 85 if (header.version() != 4) 86 is.setstate(std::ios::failbit); 87 std::streamsize options_length = header.header_length() - 20; 88 if (options_length < 0 || options_length > 40) 89 is.setstate(std::ios::failbit); 90 else 91 is.read(reinterpret_cast<char*>(header.rep_) + 20, options_length); 92 return is; 93 } 94 95 private: decode(int a,int b) const96 unsigned short decode(int a, int b) const 97 { return (rep_[a] << 8) + rep_[b]; } 98 99 unsigned char rep_[60]; 100 }; 101 102 #endif // IPV4_HEADER_HPP 103