1 //
2 // ipv4_header.hpp
3 // ~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2013 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