extended ICMP packet dumping to parts after packet creation
[pingcheck] / src / ip / ipv6header.cpp
1 // Copyright (c) 2003-2010 Christopher M. Kohlhoff
2 // Modifications (c) 2011 by Guilherme Maciel Ferreira / Intra2net AG
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 //    (See accompanying file LICENSE_1_0.txt or copy at
6 //          http://www.boost.org/LICENSE_1_0.txt)
7 #include "ip/ipv6header.h"
8
9 #include <boost/foreach.hpp>
10 #include <boost/scoped_array.hpp>
11
12 #include "boost_assert_handler.h"
13
14 using namespace std;
15 using boost::asio::ip::address_v6;
16 using boost::asio::ip::address;
17 using boost::scoped_array;
18
19 //-----------------------------------------------------------------------------
20 // Ipv6Header
21 //-----------------------------------------------------------------------------
22
23 static const size_t Ipv6HeaderSizeInBytes = 40;
24
25 /**
26  * @brief Default constructor.
27  */
28 Ipv6Header::Ipv6Header() :
29     IpHeader( Ipv6HeaderSizeInBytes )
30 {
31     // encode a 6 into the first 4 bits
32     Payload.encode1(0, 0, 0);
33     Payload.encode1(0, 1, 1);
34     Payload.encode1(0, 2, 1);
35     Payload.encode1(0, 3, 0);
36 }
37
38 /**
39  * @brief Get the IP version.
40  *
41  * The Version field keeps track of which version of the protocol the
42  * packet belongs to.
43  *
44  * @return The 4-bits representing the Version field.
45  */
46 uint8_t Ipv6Header::get_version() const
47 {
48     return ( Payload[ 0 ] >> 4 ) & 0x0F;
49 }
50
51 uint16_t Ipv6Header::get_header_length() const
52 {  return static_cast<uint16_t>(40);   }
53
54 uint16_t Ipv6Header::get_total_length() const
55 {
56     // the compiler converts anything smaller than int to int when adding
57     // which results in a warning when assigning the result to uint16
58     return static_cast<uint16_t>( get_payload_length() + 40 );
59 }
60
61 // in IPv6, this corresponds to the "HOP limit"
62 uint8_t Ipv6Header::get_time_to_live() const
63 {   return get_hop_limit();    }
64
65 /**
66  * @brief Get the Differentiated Services, originally called Traffic Class.
67  *
68  * The Differentiated Services field is used to provide QoS.
69  *
70  * @return The 8-bits representing the Differentiated Services.
71  */
72 uint8_t Ipv6Header::get_differentiated_services() const
73 {
74     uint16_t first_word = static_cast<uint16_t>( (Payload[ 0 ] << 8) | Payload[ 1 ] );
75     uint8_t differentiated_services = static_cast<uint8_t>( (first_word & 0x0FF0) >> 4 );
76
77     return differentiated_services;
78 }
79
80 /**
81  * @brief Get the Flow Label field.
82  *
83  * The Flow Label field provides a way for a source and destination to mark
84  * groups of packets that have the same requirements and should be treated in
85  * the same way by the network.
86  *
87  * @return The 32-bits representing the Flow Label.
88  */
89 uint32_t Ipv6Header::get_flow_label() const
90 {
91     uint32_t flow_label = Payload.decode32( 0, 3 );
92     return ( flow_label & 0xFFFFF );
93 }
94
95 /**
96  * @brief Get the Payload Length in bytes.
97  *
98  * This field tells how many bytes follow the 40-byte fixed length IPv6 header.
99  *
100  * @return The 16-bits representing the amount of bytes that follow the IPv6
101  * header, at most 65,535 bytes.
102  */
103 uint16_t Ipv6Header::get_payload_length() const
104 {
105     return Payload.decode16( 4, 5 );
106 }
107
108 /**
109  * @brief Get the Next Header field.
110  *
111  * The Next Header field tells which of the extension headers, if any, follow
112  * this one. If this header is the last IP header, this field tells which
113  * transport protocol handler (e.g. TCP, UDP) to pass the packet to.
114  *
115  * @return An 8-bits number identifying the next header that follows this one.
116  */
117 uint8_t Ipv6Header::get_next_header() const
118 {
119     return Payload[ 6 ];
120 }
121
122 /**
123  * @brief Get the Hop Limit field.
124  *
125  * The Hop Limit field is used to keep packets from living forever, it is
126  * decremented at each router the packet pass.
127  *
128  * @return An 8-bits number representing the amount of hops left before
129  * discarding this packet.
130  */
131 uint8_t Ipv6Header::get_hop_limit() const
132 {
133     return Payload[ 7 ];
134 }
135
136 /**
137  * @brief Get the source address.
138  *
139  * The Source Address field indicates the source network host address.
140  *
141  * @brief The source address.
142  */
143 address Ipv6Header::get_source_address() const
144 {
145     address_v6::bytes_type address; // 16 bytes
146     BOOST_ASSERT( 16 == address_v6::bytes_type::size() );
147
148     address.fill( 0 );
149     size_t header_byte_index = 8;
150     BOOST_FOREACH( unsigned char &byte, address )
151     {
152         byte = Payload[ header_byte_index ];
153         header_byte_index++;
154     }
155
156     BOOST_ASSERT( 24 == header_byte_index );
157
158     return address_v6( address );
159 }
160
161 /**
162  * @brief Get the destination address.
163  *
164  * The Destination Address field indicates the destination network host address.
165  *
166  * @return The destination address.
167  */
168 address Ipv6Header::get_destination_address() const
169 {
170     address_v6::bytes_type address; // 16 bytes
171     BOOST_ASSERT( 16 == address_v6::bytes_type::size() );
172
173     address.fill( 0 );
174     size_t header_byte_index = 24;
175     BOOST_FOREACH( unsigned char &byte, address )
176     {
177         byte = Payload[ header_byte_index ];
178         header_byte_index++;
179     }
180
181     BOOST_ASSERT( 40 == header_byte_index );
182
183     return address_v6( address );
184 }
185
186 istream &operator>>(
187         istream &is,
188         Ipv6Header &header
189 )
190 {
191     // read the first 40 bytes (mandatory for IPv6 header) from the input stream
192     // and stores in the buffer object
193     (void) header.Payload.read( is );
194
195     if ( header.get_version() != 6 )
196     {
197         is.setstate( ios::failbit );
198     }
199
200     return is;
201 }