// Copyright (c) 2003-2010 Christopher M. Kohlhoff // Modifications (c) 2011 by Guilherme Maciel Ferreira / Intra2net AG // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "ip/ipv6header.h" #include #include #include "boost_assert_handler.h" using namespace std; using boost::asio::ip::address_v6; using boost::asio::ip::address; using boost::scoped_array; //----------------------------------------------------------------------------- // Ipv6Header //----------------------------------------------------------------------------- static const size_t Ipv6HeaderSizeInBytes = 40; /** * @brief Default constructor. */ Ipv6Header::Ipv6Header() : IpHeader( Ipv6HeaderSizeInBytes ) { // encode a 6 into the first 4 bits Payload.encode1(0, 0, 0); Payload.encode1(0, 1, 1); Payload.encode1(0, 2, 1); Payload.encode1(0, 3, 0); } /** * @brief Get the IP version. * * The Version field keeps track of which version of the protocol the * packet belongs to. * * @return The 4-bits representing the Version field. */ uint8_t Ipv6Header::get_version() const { return ( Payload[ 0 ] >> 4 ) & 0x0F; } uint16_t Ipv6Header::get_header_length() const { return static_cast(40); } uint16_t Ipv6Header::get_total_length() const { // the compiler converts anything smaller than int to int when adding // which results in a warning when assigning the result to uint16 return static_cast( get_payload_length() + 40 ); } // in IPv6, this corresponds to the "HOP limit" uint8_t Ipv6Header::get_time_to_live() const { return get_hop_limit(); } /** * @brief Get the Differentiated Services, originally called Traffic Class. * * The Differentiated Services field is used to provide QoS. * * @return The 8-bits representing the Differentiated Services. */ uint8_t Ipv6Header::get_differentiated_services() const { uint16_t first_word = static_cast( (Payload[ 0 ] << 8) | Payload[ 1 ] ); uint8_t differentiated_services = static_cast( (first_word & 0x0FF0) >> 4 ); return differentiated_services; } /** * @brief Get the Flow Label field. * * The Flow Label field provides a way for a source and destination to mark * groups of packets that have the same requirements and should be treated in * the same way by the network. * * @return The 32-bits representing the Flow Label. */ uint32_t Ipv6Header::get_flow_label() const { uint32_t flow_label = Payload.decode32( 0, 3 ); return ( flow_label & 0xFFFFF ); } /** * @brief Get the Payload Length in bytes. * * This field tells how many bytes follow the 40-byte fixed length IPv6 header. * * @return The 16-bits representing the amount of bytes that follow the IPv6 * header, at most 65,535 bytes. */ uint16_t Ipv6Header::get_payload_length() const { return Payload.decode16( 4, 5 ); } /** * @brief Get the Next Header field. * * The Next Header field tells which of the extension headers, if any, follow * this one. If this header is the last IP header, this field tells which * transport protocol handler (e.g. TCP, UDP) to pass the packet to. * * @return An 8-bits number identifying the next header that follows this one. */ uint8_t Ipv6Header::get_next_header() const { return Payload[ 6 ]; } /** * @brief Get the Hop Limit field. * * The Hop Limit field is used to keep packets from living forever, it is * decremented at each router the packet pass. * * @return An 8-bits number representing the amount of hops left before * discarding this packet. */ uint8_t Ipv6Header::get_hop_limit() const { return Payload[ 7 ]; } /** * @brief Get the source address. * * The Source Address field indicates the source network host address. * * @brief The source address. */ address Ipv6Header::get_source_address() const { address_v6::bytes_type address; // 16 bytes BOOST_ASSERT( 16 == address_v6::bytes_type::size() ); address.fill( 0 ); size_t header_byte_index = 8; BOOST_FOREACH( unsigned char &byte, address ) { byte = Payload[ header_byte_index ]; header_byte_index++; } BOOST_ASSERT( 24 == header_byte_index ); return address_v6( address ); } /** * @brief Get the destination address. * * The Destination Address field indicates the destination network host address. * * @return The destination address. */ address Ipv6Header::get_destination_address() const { address_v6::bytes_type address; // 16 bytes BOOST_ASSERT( 16 == address_v6::bytes_type::size() ); address.fill( 0 ); size_t header_byte_index = 24; BOOST_FOREACH( unsigned char &byte, address ) { byte = Payload[ header_byte_index ]; header_byte_index++; } BOOST_ASSERT( 40 == header_byte_index ); return address_v6( address ); } istream &operator>>( istream &is, Ipv6Header &header ) { // read the first 40 bytes (mandatory for IPv6 header) from the input stream // and stores in the buffer object (void) header.Payload.read( is ); if ( header.get_version() != 6 ) { is.setstate( ios::failbit ); } return is; }