blob: 3892c361907825ed3958bf1e677306154b3b0218 [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for IPv6 packet processing.
*/
#ifndef IP6_HEADERS_HPP_
#define IP6_HEADERS_HPP_
#include <stddef.h>
#include <openthread/types.h>
#include "common/encoding.hpp"
#include "common/message.hpp"
#include "net/ip6_address.hpp"
#include "net/netif.hpp"
#include "net/socket.hpp"
using ot::Encoding::BigEndian::HostSwap16;
using ot::Encoding::BigEndian::HostSwap32;
namespace ot {
/**
* @namespace ot::Ip6
*
* @brief
* This namespace includes definitions for IPv6 networking.
*
*/
namespace Ip6 {
/**
* @addtogroup core-ipv6
*
* @brief
* This module includes definitions for the IPv6 network layer.
*
* @{
*
* @defgroup core-ip6-icmp6 ICMPv6
* @defgroup core-ip6-ip6 IPv6
* @defgroup core-ip6-mpl MPL
* @defgroup core-ip6-netif Network Interfaces
*
* @}
*
*/
/**
* @addtogroup core-ip6-ip6
*
* @brief
* This module includes definitions for core IPv6 networking.
*
* @{
*
*/
/**
* Internet Protocol Numbers
*/
enum IpProto
{
kProtoHopOpts = 0, ///< IPv6 Hop-by-Hop Option
kProtoTcp = 6, ///< Transmission Control Protocol
kProtoUdp = 17, ///< User Datagram
kProtoIp6 = 41, ///< IPv6 encapsulation
kProtoRouting = 43, ///< Routing Header for IPv6
kProtoFragment = 44, ///< Fragment Header for IPv6
kProtoIcmp6 = 58, ///< ICMP for IPv6
kProtoNone = 59, ///< No Next Header for IPv6
kProtoDstOpts = 60, ///< Destination Options for IPv6
};
enum
{
kVersionClassFlowSize = 4, ///< Combined size of Version, Class, Flow Label in bytes.
};
/**
* This structure represents an IPv6 header.
*
*/
OT_TOOL_PACKED_BEGIN
struct HeaderPoD
{
union
{
uint8_t m8[kVersionClassFlowSize / sizeof(uint8_t)];
uint16_t m16[kVersionClassFlowSize / sizeof(uint16_t)];
uint32_t m32[kVersionClassFlowSize / sizeof(uint32_t)];
} mVersionClassFlow; ///< Version, Class, Flow Label
uint16_t mPayloadLength; ///< Payload Length
uint8_t mNextHeader; ///< Next Header
uint8_t mHopLimit; ///< Hop Limit
otIp6Address mSource; ///< Source
otIp6Address mDestination; ///< Destination
} OT_TOOL_PACKED_END;
/**
* This class implements IPv6 header generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class Header: private HeaderPoD
{
public:
/**
* This method initializes the IPv6 header.
*
*/
void Init(void) { mVersionClassFlow.m32[0] = 0; mVersionClassFlow.m8[0] = kVersion6; }
/**
* This method initializes the IPv6 header and sets Version, Traffic Control and Flow Label fields.
*
*/
void Init(uint32_t aVersionClassFlow) { mVersionClassFlow.m32[0] = HostSwap32(aVersionClassFlow); }
/**
* This method indicates whether or not the IPv6 Version is set to 6.
*
* @retval TRUE If the IPv6 Version is set to 6.
* @retval FALSE If the IPv6 Version is not set to 6.
*
*/
bool IsVersion6(void) const { return (mVersionClassFlow.m8[0] & kVersionMask) == kVersion6; }
/**
* This method returns the IPv6 Payload Length value.
*
* @returns The IPv6 Payload Length value.
*
*/
uint16_t GetPayloadLength(void) { return HostSwap16(mPayloadLength); }
/**
* This method sets the IPv6 Payload Length value.
*
* @param[in] aLength The IPv6 Payload Length value.
*
*/
void SetPayloadLength(uint16_t aLength) { mPayloadLength = HostSwap16(aLength); }
/**
* This method returns the IPv6 Next Header value.
*
* @returns The IPv6 Next Header value.
*
*/
IpProto GetNextHeader(void) const { return static_cast<IpProto>(mNextHeader); }
/**
* This method sets the IPv6 Next Header value.
*
* @param[in] aNextHeader The IPv6 Next Header value.
*
*/
void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast<uint8_t>(aNextHeader); }
/**
* This method returns the IPv6 Hop Limit value.
*
* @returns The IPv6 Hop Limit value.
*
*/
uint8_t GetHopLimit(void) const { return mHopLimit; }
/**
* This method sets the IPv6 Hop Limit value.
*
* @param[in] aHopLimit The IPv6 Hop Limit value.
*
*/
void SetHopLimit(uint8_t aHopLimit) { mHopLimit = aHopLimit; }
/**
* This method returns the IPv6 Source address.
*
* @returns A reference to the IPv6 Source address.
*
*/
Address &GetSource(void) { return static_cast<Address &>(mSource); }
/**
* This method sets the IPv6 Source address.
*
* @param[in] aSource A reference to the IPv6 Source address.
*
*/
void SetSource(const Address &aSource) { mSource = aSource; }
/**
* This method returns the IPv6 Destination address.
*
* @returns A reference to the IPv6 Destination address.
*
*/
Address &GetDestination(void) { return static_cast<Address &>(mDestination); }
/**
* This method sets the IPv6 Destination address.
*
* @param[in] aDestination A reference to the IPv6 Destination address.
*
*/
void SetDestination(const Address &aDestination) { mDestination = aDestination; }
/**
* This static method returns the byte offset of the IPv6 Payload Length field.
*
* @returns The byte offset of the IPv6 Payload Length field.
*
*/
static uint8_t GetPayloadLengthOffset(void) { return offsetof(HeaderPoD, mPayloadLength); }
/**
* This static method returns the byte offset of the IPv6 Hop Limit field.
*
* @returns The byte offset of the IPv6 Hop Limit field.
*
*/
static uint8_t GetHopLimitOffset(void) { return offsetof(HeaderPoD, mHopLimit); }
/**
* This static method returns the size of the IPv6 Hop Limit field.
*
* @returns The size of the IPv6 Hop Limit field.
*
*/
static uint8_t GetHopLimitSize(void) { return sizeof(uint8_t); }
/**
* This static method returns the byte offset of the IPv6 Destination field.
*
* @returns The byte offset of the IPv6 Destination field.
*
*/
static uint8_t GetDestinationOffset(void) { return offsetof(HeaderPoD, mDestination); }
private:
enum
{
kVersion6 = 0x60,
kVersionMask = 0xf0,
};
} OT_TOOL_PACKED_END;
/**
* This class implements IPv6 Extension Header generation and processing.
*
*/
OT_TOOL_PACKED_BEGIN
class ExtensionHeader
{
public:
/**
* This method returns the IPv6 Next Header value.
*
* @returns The IPv6 Next Header value.
*
*/
IpProto GetNextHeader(void) const { return static_cast<IpProto>(mNextHeader); }
/**
* This method sets the IPv6 Next Header value.
*
* @param[in] aNextHeader The IPv6 Next Header value.
*
*/
void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast<uint8_t>(aNextHeader); }
/**
* This method returns the IPv6 Header Extension Length value.
*
* @returns The IPv6 Header Extension Length value.
*
*/
uint8_t GetLength(void) const { return mLength; }
/**
* This method sets the IPv6 Header Extension Length value.
*
* @param[in] aLength The IPv6 Header Extension Length value.
*
*/
void SetLength(uint8_t aLength) { mLength = aLength; }
private:
uint8_t mNextHeader;
uint8_t mLength;
} OT_TOOL_PACKED_END;
/**
* This class implements IPv6 Hop-by-Hop Options Header generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class HopByHopHeader: public ExtensionHeader
{
} OT_TOOL_PACKED_END;
/**
* This class implements IPv6 Options generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class OptionHeader
{
public:
/**
* Default constructor.
*
*/
OptionHeader(void):
mType(0),
mLength(0) {}
/**
* This method returns the IPv6 Option Type value.
*
* @returns The IPv6 Option Type value.
*
*/
uint8_t GetType(void) const { return mType; }
/**
* This method sets the IPv6 Option Type value.
*
* @param[in] aType The IPv6 Option Type value.
*
*/
void SetType(uint8_t aType) { mType = aType; }
/**
* IPv6 Option Type actions for unrecognized IPv6 Options.
*
*/
enum Action
{
kActionSkip = 0x00, ///< skip over this option and continue processing the header
kActionDiscard = 0x40, ///< discard the packet
kActionForceIcmp = 0x80, ///< discard the packet and forcibly send an ICMP Parameter Problem
kActionIcmp = 0xc0, ///< discard packet and conditionally send an ICMP Parameter Problem
kActionMask = 0xc0, ///< mask for action bits
};
/**
* This method returns the IPv6 Option action for unrecognized IPv6 Options.
*
* @returns The IPv6 Option action for unrecognized IPv6 Options.
*
*/
Action GetAction(void) const { return static_cast<Action>(mType & kActionMask); }
/**
* This method returns the IPv6 Option Length value.
*
* @returns The IPv6 Option Length value.
*
*/
uint8_t GetLength(void) const { return mLength; }
/**
* This method sets the IPv6 Option Length value.
*
* @param[in] aLength The IPv6 Option Length value.
*
*/
void SetLength(uint8_t aLength) { mLength = aLength; }
private:
uint8_t mType;
uint8_t mLength;
} OT_TOOL_PACKED_END;
/**
* This class implements IPv6 PadN Option generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class OptionPadN : public OptionHeader
{
public:
enum
{
kType = 0x01, ///< PadN type
kData = 0x00, ///< PadN specific data
kMaxLength = 0x05 ///< Maximum length of PadN option data
};
/**
* This method initializes the PadN header.
*
* @param[in] aPadLength The length of needed padding. Allowed value from
* range 2-7.
*
*/
void Init(uint8_t aPadLength) {
OptionHeader::SetType(kType);
OptionHeader::SetLength(aPadLength - sizeof(OptionHeader));
memset(mPad, kData, aPadLength - sizeof(OptionHeader));
}
/**
* This method returns the total IPv6 Option Length value including option
* header.
*
* @returns The total IPv6 Option Length.
*
*/
uint8_t GetTotalLength(void) const { return OptionHeader::GetLength() + sizeof(OptionHeader); }
private:
uint8_t mPad[kMaxLength];
} OT_TOOL_PACKED_END;
/**
* This class implements IPv6 Pad1 Option generation and parsing. Pad1 does not
* followdefault option header structure.
*
*/
OT_TOOL_PACKED_BEGIN
class OptionPad1
{
public:
enum
{
kType = 0x00
};
/**
* This method initializes the Pad1 header.
*
*/
void Init(void) { mType = kType; }
private:
uint8_t mType;
} OT_TOOL_PACKED_END;
/**
* This class implements IPv6 Fragment Header generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class FragmentHeader
{
public:
/**
* This method initializes the IPv6 Fragment header.
*
*/
void Init(void) { mReserved = 0; mIdentification = 0; }
/**
* This method returns the IPv6 Next Header value.
*
* @returns The IPv6 Next Header value.
*
*/
IpProto GetNextHeader(void) const { return static_cast<IpProto>(mNextHeader); }
/**
* This method sets the IPv6 Next Header value.
*
* @param[in] aNextHeader The IPv6 Next Header value.
*
*/
void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast<uint8_t>(aNextHeader); }
/**
* This method returns the Fragment Offset value.
*
* @returns The Fragment Offset value.
*
*/
uint16_t GetOffset(void) { return (HostSwap16(mOffsetMore) & kOffsetMask) >> kOffsetOffset; }
/**
* This method sets the Fragment Offset value.
*
* @param[in] aOffset The Fragment Offset value.
*/
void SetOffset(uint16_t aOffset) {
uint16_t tmp = HostSwap16(mOffsetMore);
tmp = (tmp & ~kOffsetMask) | ((aOffset << kOffsetOffset) & kOffsetMask);
mOffsetMore = HostSwap16(tmp);
}
/**
* This method returns the M flag value.
*
* @returns The M flag value.
*
*/
bool IsMoreFlagSet(void) { return HostSwap16(mOffsetMore) & kMoreFlag; }
/**
* This method clears the M flag value.
*
*/
void ClearMoreFlag(void) { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) & ~kMoreFlag); }
/**
* This method sets the M flag value.
*
*/
void SetMoreFlag(void) { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) | kMoreFlag); }
private:
uint8_t mNextHeader;
uint8_t mReserved;
enum
{
kOffsetOffset = 3,
kOffsetMask = 0xfff8,
kMoreFlag = 1,
};
uint16_t mOffsetMore;
uint32_t mIdentification;
} OT_TOOL_PACKED_END;
/**
* @}
*
*/
} // namespace Ip6
} // namespace ot
#endif // NET_IP6_HEADERS_HPP_