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/nat64.h> 43 #include <openthread/udp.h> 44 45 #include "common/callback.hpp" 46 #include "common/encoding.hpp" 47 #include "common/frame_data.hpp" 48 #include "common/locator.hpp" 49 #include "common/log.hpp" 50 #include "common/message.hpp" 51 #include "common/non_copyable.hpp" 52 #include "common/owned_ptr.hpp" 53 #include "common/time_ticker.hpp" 54 #include "common/timer.hpp" 55 #include "net/icmp6.hpp" 56 #include "net/ip6_address.hpp" 57 #include "net/ip6_headers.hpp" 58 #include "net/ip6_mpl.hpp" 59 #include "net/ip6_types.hpp" 60 #include "net/netif.hpp" 61 #include "net/socket.hpp" 62 #include "net/tcp6.hpp" 63 #include "net/udp6.hpp" 64 65 namespace ot { 66 67 /** 68 * @namespace ot::Ip6 69 * 70 * @brief 71 * This namespace includes definitions for IPv6 networking. 72 * 73 */ 74 namespace Ip6 { 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 * 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 * Initializes the object. 116 * 117 * @param[in] aInstance A reference to the otInstance object. 118 * 119 */ 120 explicit Ip6(Instance &aInstance); 121 122 /** 123 * Allocates a new message buffer from the buffer pool with default settings (link security 124 * enabled and `kPriorityMedium`). 125 * 126 * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. 127 * 128 */ 129 Message *NewMessage(void); 130 131 /** 132 * Allocates a new message buffer from the buffer pool with default settings (link security 133 * enabled and `kPriorityMedium`). 134 * 135 * @param[in] aReserved The number of header bytes to reserve following the IPv6 header. 136 * 137 * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. 138 * 139 */ 140 Message *NewMessage(uint16_t aReserved); 141 142 /** 143 * Allocates a new message buffer from the buffer pool. 144 * 145 * @param[in] aReserved The number of header bytes to reserve following the IPv6 header. 146 * @param[in] aSettings The message settings. 147 * 148 * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. 149 * 150 */ 151 Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings); 152 153 /** 154 * Allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message. 155 * 156 * The message priority is always determined from IPv6 message itself (@p aData) and the priority included in 157 * @p aSetting is ignored. 158 * 159 * @param[in] aData A pointer to the IPv6 datagram buffer. 160 * @param[in] aDataLength The size of the IPV6 datagram buffer pointed by @p aData. 161 * @param[in] aSettings The message settings. 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 *NewMessageFromData(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings); 168 169 /** 170 * 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 * 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 * Sends a raw IPv6 datagram with a fully formed IPv6 header. 194 * 195 * @param[in] aMessage An owned pointer to a message (ownership is transferred to the method). 196 * 197 * @retval kErrorNone Successfully processed the message. 198 * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. 199 * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. 200 * @retval kErrorNoRoute No route to host. 201 * @retval kErrorParse Encountered a malformed header when processing the message. 202 * 203 */ 204 Error SendRaw(OwnedPtr<Message> aMessage); 205 206 /** 207 * Processes a received IPv6 datagram. 208 * 209 * @param[in] aMessage An owned pointer to a message. 210 * 211 * @retval kErrorNone Successfully processed the message. 212 * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. 213 * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. 214 * @retval kErrorNoRoute No route to host. 215 * @retval kErrorParse Encountered a malformed header when processing the message. 216 * 217 */ 218 Error HandleDatagram(OwnedPtr<Message> aMessagePtr, bool aIsReassembled = false); 219 220 /** 221 * Registers a callback to provide received raw IPv6 datagrams. 222 * 223 * By default, this callback does not pass Thread control traffic. See SetReceiveIp6FilterEnabled() to change 224 * the Thread control traffic filter setting. 225 * 226 * @param[in] aCallback A pointer to a function that is called when an IPv6 datagram is received 227 * or `nullptr` to disable the callback. 228 * @param[in] aCallbackContext A pointer to application-specific context. 229 * 230 * @sa IsReceiveIp6FilterEnabled 231 * @sa SetReceiveIp6FilterEnabled 232 * 233 */ SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback,void * aCallbackContext)234 void SetReceiveDatagramCallback(otIp6ReceiveCallback aCallback, void *aCallbackContext) 235 { 236 mReceiveIp6DatagramCallback.Set(aCallback, aCallbackContext); 237 } 238 239 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE 240 /** 241 * Registers a callback to provide received translated IPv4 datagrams. 242 * 243 * @param[in] aCallback A pointer to a function that is called when a translated IPv4 datagram is received 244 * or `nullptr` to disable the callback. 245 * @param[in] aCallbackContext A pointer to application-specific context. 246 * 247 * @sa SetReceiveDatagramCallback 248 * 249 */ SetNat64ReceiveIp4DatagramCallback(otNat64ReceiveIp4Callback aCallback,void * aCallbackContext)250 void SetNat64ReceiveIp4DatagramCallback(otNat64ReceiveIp4Callback aCallback, void *aCallbackContext) 251 { 252 mReceiveIp4DatagramCallback.Set(aCallback, aCallbackContext); 253 } 254 #endif 255 256 /** 257 * Indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams 258 * via the callback specified in SetReceiveIp6DatagramCallback(). 259 * 260 * @returns TRUE if Thread control traffic is filtered out, FALSE otherwise. 261 * 262 * @sa SetReceiveDatagramCallback 263 * @sa SetReceiveIp6FilterEnabled 264 * 265 */ IsReceiveIp6FilterEnabled(void) const266 bool IsReceiveIp6FilterEnabled(void) const { return mIsReceiveIp6FilterEnabled; } 267 268 /** 269 * Sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams 270 * via the callback specified in SetReceiveIp6DatagramCallback(). 271 * 272 * @param[in] aEnabled TRUE if Thread control traffic is filtered out, FALSE otherwise. 273 * 274 * @sa SetReceiveDatagramCallback 275 * @sa IsReceiveIp6FilterEnabled 276 * 277 */ SetReceiveIp6FilterEnabled(bool aEnabled)278 void SetReceiveIp6FilterEnabled(bool aEnabled) { mIsReceiveIp6FilterEnabled = aEnabled; } 279 280 /** 281 * Performs default source address selection. 282 * 283 * @param[in,out] aMessageInfo A reference to the message information. 284 * 285 * @retval kErrorNone Found a source address and updated SockAddr of @p aMessageInfo. 286 * @retval kErrorNotFound No source address was found and @p aMessageInfo is unchanged. 287 * 288 */ 289 Error SelectSourceAddress(MessageInfo &aMessageInfo) const; 290 291 /** 292 * Performs default source address selection. 293 * 294 * @param[in] aDestination The destination address. 295 * 296 * @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found. 297 * 298 */ 299 const Address *SelectSourceAddress(const Address &aDestination) const; 300 301 /** 302 * Returns a reference to the send queue. 303 * 304 * @returns A reference to the send queue. 305 * 306 */ GetSendQueue(void) const307 const PriorityQueue &GetSendQueue(void) const { return mSendQueue; } 308 309 /** 310 * Converts an IP protocol number to a string. 311 * 312 * @param[in] aIpProto An IP protocol number. 313 * 314 * @returns The string representation of @p aIpProto. 315 * 316 */ 317 static const char *IpProtoToString(uint8_t aIpProto); 318 319 /** 320 * Converts an IP header ECN value to a string. 321 * 322 * @param[in] aEcn The 2-bit ECN value. 323 * 324 * @returns The string representation of @p aEcn. 325 * 326 */ 327 static const char *EcnToString(Ecn aEcn); 328 329 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 330 /** 331 * Returns a reference to the Border Routing counters. 332 * 333 * @returns A reference to the Border Routing counters. 334 * 335 */ GetBorderRoutingCounters(void) const336 const otBorderRoutingCounters &GetBorderRoutingCounters(void) const { return mBorderRoutingCounters; } 337 338 /** 339 * Returns a reference to the Border Routing counters. 340 * 341 * @returns A reference to the Border Routing counters. 342 * 343 */ GetBorderRoutingCounters(void)344 otBorderRoutingCounters &GetBorderRoutingCounters(void) { return mBorderRoutingCounters; } 345 346 /** 347 * Resets the Border Routing counters. 348 * 349 */ ResetBorderRoutingCounters(void)350 void ResetBorderRoutingCounters(void) { ClearAllBytes(mBorderRoutingCounters); } 351 #endif 352 353 private: 354 static constexpr uint8_t kDefaultHopLimit = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT; 355 static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT; 356 357 static constexpr uint16_t kMinimalMtu = 1280; 358 359 static uint8_t PriorityToDscp(Message::Priority aPriority); 360 static Error TakeOrCopyMessagePtr(OwnedPtr<Message> &aTargetPtr, 361 OwnedPtr<Message> &aMessagePtr, 362 Message::Ownership aMessageOwnership); 363 364 void EnqueueDatagram(Message &aMessage); 365 void HandleSendQueue(void); 366 Error PassToHost(OwnedPtr<Message> &aMessagePtr, 367 const MessageInfo &aMessageInfo, 368 uint8_t aIpProto, 369 bool aApplyFilter, 370 bool aReceive, 371 Message::Ownership aMessageOwnership); 372 Error HandleExtensionHeaders(OwnedPtr<Message> &aMessagePtr, 373 MessageInfo &aMessageInfo, 374 Header &aHeader, 375 uint8_t &aNextHeader, 376 bool &aReceive); 377 Error FragmentDatagram(Message &aMessage, uint8_t aIpProto); 378 Error HandleFragment(Message &aMessage); 379 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE 380 void CleanupFragmentationBuffer(void); 381 void HandleTimeTick(void); 382 void UpdateReassemblyList(void); 383 void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode); 384 #endif 385 Error AddMplOption(Message &aMessage, Header &aHeader); 386 Error PrepareMulticastToLargerThanRealmLocal(Message &aMessage, const Header &aHeader); 387 Error InsertMplOption(Message &aMessage, Header &aHeader); 388 Error RemoveMplOption(Message &aMessage); 389 Error HandleOptions(Message &aMessage, Header &aHeader, bool &aReceive); 390 Error HandlePayload(Header &aIp6Header, 391 OwnedPtr<Message> &aMessagePtr, 392 MessageInfo &aMessageInfo, 393 uint8_t aIpProto, 394 Message::Ownership aMessageOwnership); 395 bool IsOnLink(const Address &aAddress) const; 396 Error RouteLookup(const Address &aSource, const Address &aDestination) const; 397 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 398 void UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound); 399 #endif 400 401 using SendQueueTask = TaskletIn<Ip6, &Ip6::HandleSendQueue>; 402 403 bool mIsReceiveIp6FilterEnabled; 404 405 Callback<otIp6ReceiveCallback> mReceiveIp6DatagramCallback; 406 407 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE 408 Callback<otNat64ReceiveIp4Callback> mReceiveIp4DatagramCallback; 409 #endif 410 411 PriorityQueue mSendQueue; 412 SendQueueTask mSendQueueTask; 413 414 Icmp mIcmp; 415 Udp mUdp; 416 Mpl mMpl; 417 418 #if OPENTHREAD_CONFIG_TCP_ENABLE 419 Tcp mTcp; 420 #endif 421 422 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE 423 MessageQueue mReassemblyList; 424 #endif 425 426 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 427 otBorderRoutingCounters mBorderRoutingCounters; 428 #endif 429 }; 430 431 /** 432 * Represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame. 433 * 434 */ 435 class Headers : private Clearable<Headers> 436 { 437 friend class Clearable<Headers>; 438 439 public: 440 /** 441 * Parses the IPv6 and UDP/TCP/ICMP6 headers from a given message. 442 * 443 * @param[in] aMessage The message to parse the headers from. 444 * 445 * @retval kErrorNone The headers are parsed successfully. 446 * @retval kErrorParse Failed to parse the headers. 447 * 448 */ 449 Error ParseFrom(const Message &aMessage); 450 451 /** 452 * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers. 453 * 454 * @param[in] aMessage The message from which to read the lowpan frame. 455 * @param[in] aOffset The offset in @p aMessage to start reading the frame. 456 * @param[in] aMacAddrs The MAC source and destination addresses. 457 * 458 * @retval kErrorNone Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers. 459 * @retval kErrorNotFound Lowpan frame is a next fragment and does not contain IPv6 headers. 460 * @retval kErrorParse Failed to parse the headers. 461 * 462 */ 463 Error DecompressFrom(const Message &aMessage, uint16_t aOffset, const Mac::Addresses &aMacAddrs); 464 465 /** 466 * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers. 467 * 468 * @param[in] aFrameData The lowpan frame data. 469 * @param[in] aMacAddrs The MAC source and destination addresses. 470 * @param[in] aInstance The OpenThread instance. 471 * 472 * @retval kErrorNone Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers. 473 * @retval kErrorNotFound Lowpan frame is a next fragment and does not contain IPv6 headers. 474 * @retval kErrorParse Failed to parse the headers. 475 * 476 */ 477 Error DecompressFrom(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, Instance &aInstance); 478 479 /** 480 * Returns the IPv6 header. 481 * 482 * @returns The IPv6 header. 483 * 484 */ GetIp6Header(void) const485 const Header &GetIp6Header(void) const { return mIp6Header; } 486 487 /** 488 * Returns the IP protocol number from IPv6 Next Header field. 489 * 490 * @returns The IP protocol number. 491 * 492 */ GetIpProto(void) const493 uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); } 494 495 /** 496 * Returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header. 497 * 498 * @returns The ECN value. 499 * 500 */ GetEcn(void) const501 Ecn GetEcn(void) const { return mIp6Header.GetEcn(); } 502 503 /** 504 * Indicates if the protocol number from IPv6 header is UDP. 505 * 506 * @retval TRUE If the protocol number in IPv6 header is UDP. 507 * @retval FALSE If the protocol number in IPv6 header is not UDP. 508 * 509 */ IsUdp(void) const510 bool IsUdp(void) const { return GetIpProto() == kProtoUdp; } 511 512 /** 513 * Indicates if the protocol number from IPv6 header is TCP. 514 * 515 * @retval TRUE If the protocol number in IPv6 header is TCP. 516 * @retval FALSE If the protocol number in IPv6 header is not TCP. 517 * 518 */ IsTcp(void) const519 bool IsTcp(void) const { return GetIpProto() == kProtoTcp; } 520 521 /** 522 * Indicates if the protocol number from IPv6 header is ICMPv6. 523 * 524 * @retval TRUE If the protocol number in IPv6 header is ICMPv6. 525 * @retval FALSE If the protocol number in IPv6 header is not ICMPv6. 526 * 527 */ IsIcmp6(void) const528 bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; } 529 530 /** 531 * Returns the source IPv6 address from IPv6 header. 532 * 533 * @returns The source IPv6 address. 534 * 535 */ GetSourceAddress(void) const536 const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); } 537 538 /** 539 * Returns the destination IPv6 address from IPv6 header. 540 * 541 * @returns The destination IPv6 address. 542 * 543 */ GetDestinationAddress(void) const544 const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); } 545 546 /** 547 * Returns the UDP header. 548 * 549 * MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined 550 * 551 * @returns The UDP header. 552 * 553 */ GetUdpHeader(void) const554 const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; } 555 556 /** 557 * Returns the TCP header. 558 * 559 * MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined 560 * 561 * @returns The TCP header. 562 * 563 */ GetTcpHeader(void) const564 const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; } 565 566 /** 567 * Returns the ICMPv6 header. 568 * 569 * MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined 570 * 571 * @returns The ICMPv6 header. 572 * 573 */ GetIcmpHeader(void) const574 const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; } 575 576 /** 577 * Returns the source port number if header is UDP or TCP, or zero otherwise 578 * 579 * @returns The source port number under UDP / TCP or zero. 580 * 581 */ 582 uint16_t GetSourcePort(void) const; 583 584 /** 585 * Returns the destination port number if header is UDP or TCP, or zero otherwise. 586 * 587 * @returns The destination port number under UDP / TCP or zero. 588 * 589 */ 590 uint16_t GetDestinationPort(void) const; 591 592 /** 593 * Returns the checksum values from corresponding UDP, TCP, or ICMPv6 header. 594 * 595 * @returns The checksum value. 596 * 597 */ 598 uint16_t GetChecksum(void) const; 599 600 private: 601 Header mIp6Header; 602 union 603 { 604 Udp::Header mUdp; 605 Tcp::Header mTcp; 606 Icmp::Header mIcmp; 607 } mHeader; 608 }; 609 610 /** 611 * @} 612 * 613 */ 614 615 } // namespace Ip6 616 } // namespace ot 617 618 #endif // IP6_HPP_ 619