1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for IPv6 packet processing. 32 */ 33 34 #ifndef IP6_HPP_ 35 #define IP6_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <stddef.h> 40 41 #include <openthread/ip6.h> 42 #include <openthread/udp.h> 43 44 #include "common/encoding.hpp" 45 #include "common/locator.hpp" 46 #include "common/message.hpp" 47 #include "common/non_copyable.hpp" 48 #include "common/time_ticker.hpp" 49 #include "common/timer.hpp" 50 #include "net/icmp6.hpp" 51 #include "net/ip6_address.hpp" 52 #include "net/ip6_headers.hpp" 53 #include "net/ip6_mpl.hpp" 54 #include "net/netif.hpp" 55 #include "net/socket.hpp" 56 #include "net/tcp6.hpp" 57 #include "net/udp6.hpp" 58 59 namespace ot { 60 61 /** 62 * @namespace ot::Ip6 63 * 64 * @brief 65 * This namespace includes definitions for IPv6 networking. 66 * 67 */ 68 namespace Ip6 { 69 70 using ot::Encoding::BigEndian::HostSwap16; 71 using ot::Encoding::BigEndian::HostSwap32; 72 73 /** 74 * @addtogroup core-ipv6 75 * 76 * @brief 77 * This module includes definitions for the IPv6 network layer. 78 * 79 * @{ 80 * 81 * @defgroup core-ip6-icmp6 ICMPv6 82 * @defgroup core-ip6-ip6 IPv6 83 * @defgroup core-ip6-mpl MPL 84 * @defgroup core-ip6-netif Network Interfaces 85 * 86 * @} 87 * 88 */ 89 90 /** 91 * @addtogroup core-ip6-ip6 92 * 93 * @brief 94 * This module includes definitions for core IPv6 networking. 95 * 96 * @{ 97 * 98 */ 99 100 /** 101 * This class implements the core IPv6 message processing. 102 * 103 */ 104 class Ip6 : public InstanceLocator, private NonCopyable 105 { 106 friend class ot::Instance; 107 friend class ot::TimeTicker; 108 friend class Mpl; 109 110 public: 111 /** 112 * The max datagram length (in bytes) of an IPv6 message. 113 * 114 */ 115 static constexpr uint16_t kMaxDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_DATAGRAM_LENGTH; 116 117 /** 118 * The max datagram length (in bytes) of an unfragmented IPv6 message. 119 * 120 */ 121 static constexpr uint16_t kMaxAssembledDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_ASSEMBLED_DATAGRAM; 122 123 /** 124 * This constructor initializes the object. 125 * 126 * @param[in] aInstance A reference to the otInstance object. 127 * 128 */ 129 explicit Ip6(Instance &aInstance); 130 131 /** 132 * This method allocates a new message buffer from the buffer pool. 133 * 134 * @param[in] aReserved The number of header bytes to reserve following the IPv6 header. 135 * @param[in] aSettings The message settings. 136 * 137 * @returns A pointer to the message or nullptr if insufficient message buffers are available. 138 * 139 */ 140 Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault()); 141 142 /** 143 * This method allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message. 144 * 145 * @param[in] aData A pointer to the IPv6 datagram buffer. 146 * @param[in] aDataLength The size of the IPV6 datagram buffer pointed by @p aData. 147 * @param[in] aSettings The message settings. 148 * 149 * @returns A pointer to the message or nullptr if malformed IPv6 header or insufficient message buffers are 150 * available. 151 * 152 */ 153 Message *NewMessage(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings); 154 155 /** 156 * This method allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message. 157 * 158 * @note The link layer security is enabled and the message priority is obtained from IPv6 message itself. 159 * 160 * @param[in] aData A pointer to the IPv6 datagram buffer. 161 * @param[in] aDataLength The size of the IPV6 datagram buffer pointed by @p aData. 162 * 163 * @returns A pointer to the message or nullptr if malformed IPv6 header or insufficient message buffers are 164 * available. 165 * 166 */ 167 Message *NewMessage(const uint8_t *aData, uint16_t aDataLength); 168 169 /** 170 * This method converts the IPv6 DSCP value to message priority level. 171 * 172 * @param[in] aDscp The IPv6 DSCP value. 173 * 174 * @returns The message priority level. 175 * 176 */ 177 static Message::Priority DscpToPriority(uint8_t aDscp); 178 179 /** 180 * This method sends an IPv6 datagram. 181 * 182 * @param[in] aMessage A reference to the message. 183 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 184 * @param[in] aIpProto The Internet Protocol value. 185 * 186 * @retval kErrorNone Successfully enqueued the message into an output interface. 187 * @retval kErrorNoBufs Insufficient available buffer to add the IPv6 headers. 188 * 189 */ 190 Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto); 191 192 /** 193 * This method sends a raw IPv6 datagram with a fully formed IPv6 header. 194 * 195 * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when 196 * processing is complete, including when a value other than `kErrorNone` is returned. 197 * 198 * @param[in] aMessage A reference to the message. 199 * 200 * @retval kErrorNone Successfully processed the message. 201 * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. 202 * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. 203 * @retval kErrorNoRoute No route to host. 204 * @retval kErrorParse Encountered a malformed header when processing the message. 205 * 206 */ 207 Error SendRaw(Message &aMessage); 208 209 /** 210 * This method processes a received IPv6 datagram. 211 * 212 * @param[in] aMessage A reference to the message. 213 * @param[in] aNetif A pointer to the network interface that received the message. 214 * @param[in] aLinkMessageInfo A pointer to link-specific message information. 215 * @param[in] aFromNcpHost TRUE if the message was submitted by the NCP host, FALSE otherwise. 216 * 217 * @retval kErrorNone Successfully processed the message. 218 * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. 219 * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. 220 * @retval kErrorNoRoute No route to host. 221 * @retval kErrorParse Encountered a malformed header when processing the message. 222 * 223 */ 224 Error HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost); 225 226 /** 227 * This method registers a callback to provide received raw IPv6 datagrams. 228 * 229 * By default, this callback does not pass Thread control traffic. See SetReceiveIp6FilterEnabled() to change 230 * the Thread control traffic filter setting. 231 * 232 * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received 233 * or nullptr to disable the callback. 234 * @param[in] aCallbackContext A pointer to application-specific context. 235 * 236 * @sa IsReceiveIp6FilterEnabled 237 * @sa SetReceiveIp6FilterEnabled 238 * 239 */ 240 void SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext); 241 242 /** 243 * This method indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams 244 * via the callback specified in SetReceiveIp6DatagramCallback(). 245 * 246 * @returns TRUE if Thread control traffic is filtered out, FALSE otherwise. 247 * 248 * @sa SetReceiveDatagramCallback 249 * @sa SetReceiveIp6FilterEnabled 250 * 251 */ IsReceiveIp6FilterEnabled(void) const252 bool IsReceiveIp6FilterEnabled(void) const { return mIsReceiveIp6FilterEnabled; } 253 254 /** 255 * This method sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams 256 * via the callback specified in SetReceiveIp6DatagramCallback(). 257 * 258 * @param[in] aEnabled TRUE if Thread control traffic is filtered out, FALSE otherwise. 259 * 260 * @sa SetReceiveDatagramCallback 261 * @sa IsReceiveIp6FilterEnabled 262 * 263 */ SetReceiveIp6FilterEnabled(bool aEnabled)264 void SetReceiveIp6FilterEnabled(bool aEnabled) { mIsReceiveIp6FilterEnabled = aEnabled; } 265 266 /** 267 * This method indicates whether or not IPv6 forwarding is enabled. 268 * 269 * @returns TRUE if IPv6 forwarding is enabled, FALSE otherwise. 270 * 271 */ IsForwardingEnabled(void) const272 bool IsForwardingEnabled(void) const { return mForwardingEnabled; } 273 274 /** 275 * This method enables/disables IPv6 forwarding. 276 * 277 * @param[in] aEnable TRUE to enable IPv6 forwarding, FALSE otherwise. 278 * 279 */ SetForwardingEnabled(bool aEnable)280 void SetForwardingEnabled(bool aEnable) { mForwardingEnabled = aEnable; } 281 282 /** 283 * This method perform default source address selection. 284 * 285 * @param[in] aMessageInfo A reference to the message information. 286 * 287 * @returns A pointer to the selected IPv6 source address or nullptr if no source address was found. 288 * 289 */ 290 const Netif::UnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo); 291 292 /** 293 * This method returns a reference to the send queue. 294 * 295 * @returns A reference to the send queue. 296 * 297 */ GetSendQueue(void) const298 const PriorityQueue &GetSendQueue(void) const { return mSendQueue; } 299 300 /** 301 * This static method converts an IP protocol number to a string. 302 * 303 * @param[in] aIpPorto An IP protocol number. 304 * 305 * @returns The string representation of @p aIpProto. 306 * 307 */ 308 static const char *IpProtoToString(uint8_t aIpProto); 309 310 private: 311 static constexpr uint8_t kDefaultHopLimit = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT; 312 static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT; 313 314 static constexpr uint16_t kMinimalMtu = 1280; 315 316 static constexpr uint32_t kStateUpdatePeriod = 1000; 317 318 static void HandleSendQueue(Tasklet &aTasklet); 319 void HandleSendQueue(void); 320 321 static uint8_t PriorityToDscp(Message::Priority aPriority); 322 static Error GetDatagramPriority(const uint8_t *aData, uint16_t aDataLen, Message::Priority &aPriority); 323 324 void EnqueueDatagram(Message &aMessage); 325 Error ProcessReceiveCallback(Message & aMessage, 326 const MessageInfo &aMessageInfo, 327 uint8_t aIpProto, 328 bool aFromNcpHost, 329 Message::Ownership aMessageOwnership); 330 Error HandleExtensionHeaders(Message & aMessage, 331 Netif * aNetif, 332 MessageInfo &aMessageInfo, 333 Header & aHeader, 334 uint8_t & aNextHeader, 335 bool aIsOutbound, 336 bool aFromNcpHost, 337 bool & aReceive); 338 Error FragmentDatagram(Message &aMessage, uint8_t aIpProto); 339 Error HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost); 340 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE 341 void CleanupFragmentationBuffer(void); 342 void HandleTimeTick(void); 343 void UpdateReassemblyList(void); 344 void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode); 345 #endif 346 Error AddMplOption(Message &aMessage, Header &aHeader); 347 Error AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo); 348 Error InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo); 349 Error RemoveMplOption(Message &aMessage); 350 Error HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive); 351 Error HandlePayload(Header & aIp6Header, 352 Message & aMessage, 353 MessageInfo & aMessageInfo, 354 uint8_t aIpProto, 355 Message::Ownership aMessageOwnership); 356 bool ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromNcpHost) const; 357 bool IsOnLink(const Address &aAddress) const; 358 359 bool mForwardingEnabled; 360 bool mIsReceiveIp6FilterEnabled; 361 otIp6ReceiveCallback mReceiveIp6DatagramCallback; 362 void * mReceiveIp6DatagramCallbackContext; 363 364 PriorityQueue mSendQueue; 365 Tasklet mSendQueueTask; 366 367 Icmp mIcmp; 368 Udp mUdp; 369 Mpl mMpl; 370 371 #if OPENTHREAD_CONFIG_TCP_ENABLE 372 Tcp mTcp; 373 #endif 374 375 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE 376 MessageQueue mReassemblyList; 377 #endif 378 }; 379 380 /** 381 * @} 382 * 383 */ 384 385 } // namespace Ip6 386 } // namespace ot 387 388 #endif // IP6_HPP_ 389