extended ICMP packet dumping to parts after packet creation
[pingcheck] / src / ip / ipv6header.cpp
CommitLineData
fd40cca9
GMF
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
fd40cca9
GMF
9#include <boost/foreach.hpp>
10#include <boost/scoped_array.hpp>
11
780b0bca
CH
12#include "boost_assert_handler.h"
13
fd40cca9
GMF
14using namespace std;
15using boost::asio::ip::address_v6;
5d9d2808 16using boost::asio::ip::address;
fd40cca9
GMF
17using boost::scoped_array;
18
19//-----------------------------------------------------------------------------
20// Ipv6Header
21//-----------------------------------------------------------------------------
22
23static const size_t Ipv6HeaderSizeInBytes = 40;
24
01e517ff
GMF
25/**
26 * @brief Default constructor.
27 */
fd40cca9 28Ipv6Header::Ipv6Header() :
6d80c0be 29 IpHeader( Ipv6HeaderSizeInBytes )
fd40cca9 30{
747c13ca
CH
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);
fd40cca9
GMF
36}
37
01e517ff
GMF
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 */
fd40cca9
GMF
46uint8_t Ipv6Header::get_version() const
47{
48 return ( Payload[ 0 ] >> 4 ) & 0x0F;
49}
50
fc921308
CH
51uint16_t Ipv6Header::get_header_length() const
52{ return static_cast<uint16_t>(40); }
53
54uint16_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"
62uint8_t Ipv6Header::get_time_to_live() const
63{ return get_hop_limit(); }
64
01e517ff
GMF
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 */
72uint8_t Ipv6Header::get_differentiated_services() const
fd40cca9
GMF
73{
74 uint16_t first_word = static_cast<uint16_t>( (Payload[ 0 ] << 8) | Payload[ 1 ] );
01e517ff 75 uint8_t differentiated_services = static_cast<uint8_t>( (first_word & 0x0FF0) >> 4 );
fd40cca9 76
01e517ff 77 return differentiated_services;
fd40cca9
GMF
78}
79
01e517ff
GMF
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 */
fd40cca9
GMF
89uint32_t Ipv6Header::get_flow_label() const
90{
91 uint32_t flow_label = Payload.decode32( 0, 3 );
92 return ( flow_label & 0xFFFFF );
93}
94
01e517ff 95/**
2c8e193f 96 * @brief Get the Payload Length in bytes.
01e517ff
GMF
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 */
fd40cca9
GMF
103uint16_t Ipv6Header::get_payload_length() const
104{
105 return Payload.decode16( 4, 5 );
106}
107
01e517ff
GMF
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 */
fd40cca9
GMF
117uint8_t Ipv6Header::get_next_header() const
118{
119 return Payload[ 6 ];
120}
121
01e517ff
GMF
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 */
fd40cca9
GMF
131uint8_t Ipv6Header::get_hop_limit() const
132{
133 return Payload[ 7 ];
134}
135
01e517ff
GMF
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 */
5d9d2808 143address Ipv6Header::get_source_address() const
fd40cca9
GMF
144{
145 address_v6::bytes_type address; // 16 bytes
b091ea2c 146 BOOST_ASSERT( 16 == address_v6::bytes_type::size() );
fd40cca9 147
aabef446 148 address.fill( 0 );
b091ea2c 149 size_t header_byte_index = 8;
fd40cca9
GMF
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
01e517ff
GMF
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 */
5d9d2808 168address Ipv6Header::get_destination_address() const
fd40cca9
GMF
169{
170 address_v6::bytes_type address; // 16 bytes
b091ea2c 171 BOOST_ASSERT( 16 == address_v6::bytes_type::size() );
fd40cca9 172
aabef446 173 address.fill( 0 );
b091ea2c 174 size_t header_byte_index = 24;
fd40cca9
GMF
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
186istream &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
b091ea2c 193 (void) header.Payload.read( is );
fd40cca9
GMF
194
195 if ( header.get_version() != 6 )
196 {
197 is.setstate( ios::failbit );
198 }
199
200 return is;
201}