Commit | Line | Data |
---|---|---|
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 |
14 | using namespace std; |
15 | using boost::asio::ip::address_v6; | |
5d9d2808 | 16 | using boost::asio::ip::address; |
fd40cca9 GMF |
17 | using boost::scoped_array; |
18 | ||
19 | //----------------------------------------------------------------------------- | |
20 | // Ipv6Header | |
21 | //----------------------------------------------------------------------------- | |
22 | ||
23 | static const size_t Ipv6HeaderSizeInBytes = 40; | |
24 | ||
01e517ff GMF |
25 | /** |
26 | * @brief Default constructor. | |
27 | */ | |
fd40cca9 | 28 | Ipv6Header::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 |
46 | uint8_t Ipv6Header::get_version() const |
47 | { | |
48 | return ( Payload[ 0 ] >> 4 ) & 0x0F; | |
49 | } | |
50 | ||
fc921308 CH |
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 | ||
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 | */ | |
72 | uint8_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 |
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 | ||
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 |
103 | uint16_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 |
117 | uint8_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 |
131 | uint8_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 | 143 | address 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 | 168 | address 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 | ||
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 | |
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 | } |