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/frame_data.hpp" 46 #include "common/locator.hpp" 47 #include "common/log.hpp" 48 #include "common/message.hpp" 49 #include "common/non_copyable.hpp" 50 #include "common/time_ticker.hpp" 51 #include "common/timer.hpp" 52 #include "net/icmp6.hpp" 53 #include "net/ip6_address.hpp" 54 #include "net/ip6_headers.hpp" 55 #include "net/ip6_mpl.hpp" 56 #include "net/ip6_types.hpp" 57 #include "net/netif.hpp" 58 #include "net/socket.hpp" 59 #include "net/tcp6.hpp" 60 #include "net/udp6.hpp" 61 62 namespace ot { 63 64 /** 65 * @namespace ot::Ip6 66 * 67 * @brief 68 * This namespace includes definitions for IPv6 networking. 69 * 70 */ 71 namespace Ip6 { 72 73 using ot::Encoding::BigEndian::HostSwap16; 74 using ot::Encoding::BigEndian::HostSwap32; 75 76 /** 77 * @addtogroup core-ipv6 78 * 79 * @brief 80 * This module includes definitions for the IPv6 network layer. 81 * 82 * @{ 83 * 84 * @defgroup core-ip6-icmp6 ICMPv6 85 * @defgroup core-ip6-ip6 IPv6 86 * @defgroup core-ip6-mpl MPL 87 * @defgroup core-ip6-netif Network Interfaces 88 * 89 * @} 90 * 91 */ 92 93 /** 94 * @addtogroup core-ip6-ip6 95 * 96 * @brief 97 * This module includes definitions for core IPv6 networking. 98 * 99 * @{ 100 * 101 */ 102 103 /** 104 * This class implements the core IPv6 message processing. 105 * 106 */ 107 class Ip6 : public InstanceLocator, private NonCopyable 108 { 109 friend class ot::Instance; 110 friend class ot::TimeTicker; 111 friend class Mpl; 112 113 public: 114 /** 115 * This constructor initializes the object. 116 * 117 * @param[in] aInstance A reference to the otInstance object. 118 * 119 */ 120 explicit Ip6(Instance &aInstance); 121 122 /** 123 * This method allocates a new message buffer from the buffer pool. 124 * 125 * @param[in] aReserved The number of header bytes to reserve following the IPv6 header. 126 * @param[in] aSettings The message settings. 127 * 128 * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. 129 * 130 */ 131 Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault()); 132 133 /** 134 * This method allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message. 135 * 136 * @param[in] aData A pointer to the IPv6 datagram buffer. 137 * @param[in] aDataLength The size of the IPV6 datagram buffer pointed by @p aData. 138 * @param[in] aSettings The message settings. 139 * 140 * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are 141 * available. 142 * 143 */ 144 Message *NewMessage(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings); 145 146 /** 147 * This method allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message. 148 * 149 * @note The link layer security is enabled and the message priority is obtained from IPv6 message itself. 150 * 151 * @param[in] aData A pointer to the IPv6 datagram buffer. 152 * @param[in] aDataLength The size of the IPV6 datagram buffer pointed by @p aData. 153 * 154 * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are 155 * available. 156 * 157 */ 158 Message *NewMessage(const uint8_t *aData, uint16_t aDataLength); 159 160 /** 161 * This method converts the IPv6 DSCP value to message priority level. 162 * 163 * @param[in] aDscp The IPv6 DSCP value. 164 * 165 * @returns The message priority level. 166 * 167 */ 168 static Message::Priority DscpToPriority(uint8_t aDscp); 169 170 /** 171 * This method sends an IPv6 datagram. 172 * 173 * @param[in] aMessage A reference to the message. 174 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 175 * @param[in] aIpProto The Internet Protocol value. 176 * 177 * @retval kErrorNone Successfully enqueued the message into an output interface. 178 * @retval kErrorNoBufs Insufficient available buffer to add the IPv6 headers. 179 * 180 */ 181 Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto); 182 183 /** 184 * This method sends a raw IPv6 datagram with a fully formed IPv6 header. 185 * 186 * The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when 187 * processing is complete, including when a value other than `kErrorNone` is returned. 188 * 189 * @param[in] aMessage A reference to the message. 190 * @param[in] aFromHost TRUE if the message is originated from the host, FALSE otherwise. 191 * 192 * @retval kErrorNone Successfully processed the message. 193 * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. 194 * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. 195 * @retval kErrorNoRoute No route to host. 196 * @retval kErrorParse Encountered a malformed header when processing the message. 197 * 198 */ 199 Error SendRaw(Message &aMessage, bool aFromHost); 200 201 /** 202 * This method processes a received IPv6 datagram. 203 * 204 * @param[in] aMessage A reference to the message. 205 * @param[in] aNetif A pointer to the network interface that received the message. 206 * @param[in] aLinkMessageInfo A pointer to link-specific message information. 207 * @param[in] aFromHost TRUE if the message is originated from the host, FALSE otherwise. 208 * 209 * @retval kErrorNone Successfully processed the message. 210 * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. 211 * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. 212 * @retval kErrorNoRoute No route to host. 213 * @retval kErrorParse Encountered a malformed header when processing the message. 214 * 215 */ 216 Error HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromHost); 217 218 /** 219 * This method registers a callback to provide received raw IPv6 datagrams. 220 * 221 * By default, this callback does not pass Thread control traffic. See SetReceiveIp6FilterEnabled() to change 222 * the Thread control traffic filter setting. 223 * 224 * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received 225 * or `nullptr` to disable the callback. 226 * @param[in] aCallbackContext A pointer to application-specific context. 227 * 228 * @sa IsReceiveIp6FilterEnabled 229 * @sa SetReceiveIp6FilterEnabled 230 * 231 */ 232 void SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext); 233 234 /** 235 * This method indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams 236 * via the callback specified in SetReceiveIp6DatagramCallback(). 237 * 238 * @returns TRUE if Thread control traffic is filtered out, FALSE otherwise. 239 * 240 * @sa SetReceiveDatagramCallback 241 * @sa SetReceiveIp6FilterEnabled 242 * 243 */ IsReceiveIp6FilterEnabled(void) const244 bool IsReceiveIp6FilterEnabled(void) const { return mIsReceiveIp6FilterEnabled; } 245 246 /** 247 * This method sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams 248 * via the callback specified in SetReceiveIp6DatagramCallback(). 249 * 250 * @param[in] aEnabled TRUE if Thread control traffic is filtered out, FALSE otherwise. 251 * 252 * @sa SetReceiveDatagramCallback 253 * @sa IsReceiveIp6FilterEnabled 254 * 255 */ SetReceiveIp6FilterEnabled(bool aEnabled)256 void SetReceiveIp6FilterEnabled(bool aEnabled) { mIsReceiveIp6FilterEnabled = aEnabled; } 257 258 /** 259 * This method indicates whether or not IPv6 forwarding is enabled. 260 * 261 * @returns TRUE if IPv6 forwarding is enabled, FALSE otherwise. 262 * 263 */ IsForwardingEnabled(void) const264 bool IsForwardingEnabled(void) const { return mForwardingEnabled; } 265 266 /** 267 * This method enables/disables IPv6 forwarding. 268 * 269 * @param[in] aEnable TRUE to enable IPv6 forwarding, FALSE otherwise. 270 * 271 */ SetForwardingEnabled(bool aEnable)272 void SetForwardingEnabled(bool aEnable) { mForwardingEnabled = aEnable; } 273 274 /** 275 * This method perform default source address selection. 276 * 277 * @param[in] aMessageInfo A reference to the message information. 278 * 279 * @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found. 280 * 281 */ 282 const Netif::UnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo); 283 284 /** 285 * This method returns a reference to the send queue. 286 * 287 * @returns A reference to the send queue. 288 * 289 */ GetSendQueue(void) const290 const PriorityQueue &GetSendQueue(void) const { return mSendQueue; } 291 292 /** 293 * This static method converts an IP protocol number to a string. 294 * 295 * @param[in] aIpProto An IP protocol number. 296 * 297 * @returns The string representation of @p aIpProto. 298 * 299 */ 300 static const char *IpProtoToString(uint8_t aIpProto); 301 302 /** 303 * This static method converts an IP header ECN value to a string. 304 * 305 * @param[in] aEcn The 2-bit ECN value. 306 * 307 * @returns The string representation of @p aEcn. 308 * 309 */ 310 static const char *EcnToString(Ecn aEcn); 311 312 private: 313 static constexpr uint8_t kDefaultHopLimit = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT; 314 static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT; 315 316 static constexpr uint16_t kMinimalMtu = 1280; 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 aFromHost, 329 bool aAllowReceiveFilter, 330 Message::Ownership aMessageOwnership); 331 Error HandleExtensionHeaders(Message & aMessage, 332 Netif * aNetif, 333 MessageInfo &aMessageInfo, 334 Header & aHeader, 335 uint8_t & aNextHeader, 336 bool aIsOutbound, 337 bool aFromHost, 338 bool & aReceive); 339 Error FragmentDatagram(Message &aMessage, uint8_t aIpProto); 340 Error HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromHost); 341 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE 342 void CleanupFragmentationBuffer(void); 343 void HandleTimeTick(void); 344 void UpdateReassemblyList(void); 345 void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode); 346 #endif 347 Error AddMplOption(Message &aMessage, Header &aHeader); 348 Error AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo); 349 Error InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo); 350 Error RemoveMplOption(Message &aMessage); 351 Error HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive); 352 Error HandlePayload(Header & aIp6Header, 353 Message & aMessage, 354 MessageInfo & aMessageInfo, 355 uint8_t aIpProto, 356 Message::Ownership aMessageOwnership); 357 bool ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromHost) const; 358 bool IsOnLink(const Address &aAddress) const; 359 360 bool mForwardingEnabled; 361 bool mIsReceiveIp6FilterEnabled; 362 otIp6ReceiveCallback mReceiveIp6DatagramCallback; 363 void * mReceiveIp6DatagramCallbackContext; 364 365 PriorityQueue mSendQueue; 366 Tasklet mSendQueueTask; 367 368 Icmp mIcmp; 369 Udp mUdp; 370 Mpl mMpl; 371 372 #if OPENTHREAD_CONFIG_TCP_ENABLE 373 Tcp mTcp; 374 #endif 375 376 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE 377 MessageQueue mReassemblyList; 378 #endif 379 }; 380 381 /** 382 * This class represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame. 383 * 384 */ 385 class Headers : private Clearable<Headers> 386 { 387 public: 388 /** 389 * This method parses the IPv6 and UDP/TCP/ICMP6 headers from a given message. 390 * 391 * @param[in] aMessage The message to parse the headers from. 392 * 393 * @retval kErrorNone The headers are parsed successfully. 394 * @retval kErrorParse Failed to parse the headers. 395 * 396 */ 397 Error ParseFrom(const Message &aMessage); 398 399 /** 400 * This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers. 401 * 402 * @param[in] aMessage The message from which to read the lowpan frame. 403 * @param[in] aOffset The offset in @p aMessage to start reading the frame. 404 * @param[in] aMacSource The MAC source address. 405 * @param[in] aMacDest The MAC destination address. 406 * 407 * @retval kErrorNone Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers. 408 * @retval kErrorNotFound Lowpan frame is a next fragment and does not contain IPv6 headers. 409 * @retval kErrorParse Failed to parse the headers. 410 * 411 */ 412 Error DecompressFrom(const Message & aMessage, 413 uint16_t aOffset, 414 const Mac::Address &aMacSource, 415 const Mac::Address &aMacDest); 416 417 /** 418 * This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers. 419 * 420 * @param[in] aFrameData The lowpan frame data. 421 * @param[in] aMacSource The MAC source address. 422 * @param[in] aMacDest The MAC destination address. 423 * @param[in] aInstance The OpenThread instance. 424 * 425 * @retval kErrorNone Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers. 426 * @retval kErrorNotFound Lowpan frame is a next fragment and does not contain IPv6 headers. 427 * @retval kErrorParse Failed to parse the headers. 428 * 429 */ 430 Error DecompressFrom(const FrameData & aFrameData, 431 const Mac::Address &aMacSource, 432 const Mac::Address &aMacDest, 433 Instance & aInstance); 434 435 /** 436 * This method returns the IPv6 header. 437 * 438 * @returns The IPv6 header. 439 * 440 */ GetIp6Header(void) const441 const Header &GetIp6Header(void) const { return mIp6Header; } 442 443 /** 444 * This method returns the IP protocol number from IPv6 Next Header field. 445 * 446 * @returns The IP protocol number. 447 * 448 */ GetIpProto(void) const449 uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); } 450 451 /** 452 * This method returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header. 453 * 454 * @returns The ECN value. 455 * 456 */ GetEcn(void) const457 Ecn GetEcn(void) const { return mIp6Header.GetEcn(); } 458 459 /** 460 * This method indicates if the protocol number from IPv6 header is UDP. 461 * 462 * @retval TRUE If the protocol number in IPv6 header is UDP. 463 * @retval FALSE If the protocol number in IPv6 header is not UDP. 464 * 465 */ IsUdp(void) const466 bool IsUdp(void) const { return GetIpProto() == kProtoUdp; } 467 468 /** 469 * This method indicates if the protocol number from IPv6 header is TCP. 470 * 471 * @retval TRUE If the protocol number in IPv6 header is TCP. 472 * @retval FALSE If the protocol number in IPv6 header is not TCP. 473 * 474 */ IsTcp(void) const475 bool IsTcp(void) const { return GetIpProto() == kProtoTcp; } 476 477 /** 478 * This method indicates if the protocol number from IPv6 header is ICMPv6. 479 * 480 * @retval TRUE If the protocol number in IPv6 header is ICMPv6. 481 * @retval FALSE If the protocol number in IPv6 header is not ICMPv6. 482 * 483 */ IsIcmp6(void) const484 bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; } 485 486 /** 487 * This method returns the source IPv6 address from IPv6 header. 488 * 489 * @returns The source IPv6 address. 490 * 491 */ GetSourceAddress(void) const492 const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); } 493 494 /** 495 * This method returns the destination IPv6 address from IPv6 header. 496 * 497 * @returns The destination IPv6 address. 498 * 499 */ GetDestinationAddress(void) const500 const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); } 501 502 /** 503 * This method returns the UDP header. 504 * 505 * This method MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined 506 * 507 * @returns The UDP header. 508 * 509 */ GetUdpHeader(void) const510 const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; } 511 512 /** 513 * This method returns the TCP header. 514 * 515 * This method MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined 516 * 517 * @returns The TCP header. 518 * 519 */ GetTcpHeader(void) const520 const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; } 521 522 /** 523 * This method returns the ICMPv6 header. 524 * 525 * This method MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined 526 * 527 * @returns The ICMPv6 header. 528 * 529 */ GetIcmpHeader(void) const530 const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; } 531 532 /** 533 * This method returns the source port number if header is UDP or TCP, or zero otherwise 534 * 535 * @returns The source port number under UDP / TCP or zero. 536 * 537 */ 538 uint16_t GetSourcePort(void) const; 539 540 /** 541 * This method returns the destination port number if header is UDP or TCP, or zero otherwise. 542 * 543 * @returns The destination port number under UDP / TCP or zero. 544 * 545 */ 546 uint16_t GetDestinationPort(void) const; 547 548 /** 549 * This method returns the checksum values from corresponding UDP, TCP, or ICMPv6 header. 550 * 551 * @returns The checksum value. 552 * 553 */ 554 uint16_t GetChecksum(void) const; 555 556 private: 557 Header mIp6Header; 558 union 559 { 560 Udp::Header mUdp; 561 Tcp::Header mTcp; 562 Icmp::Header mIcmp; 563 } mHeader; 564 }; 565 566 /** 567 * @} 568 * 569 */ 570 571 } // namespace Ip6 572 } // namespace ot 573 574 #endif // IP6_HPP_ 575