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/checksum.hpp" 56 #include "net/icmp6.hpp" 57 #include "net/ip6_address.hpp" 58 #include "net/ip6_headers.hpp" 59 #include "net/ip6_mpl.hpp" 60 #include "net/ip6_types.hpp" 61 #include "net/netif.hpp" 62 #include "net/socket.hpp" 63 #include "net/tcp6.hpp" 64 #include "net/udp6.hpp" 65 66 namespace ot { 67 68 /** 69 * @namespace ot::Ip6 70 * 71 * @brief 72 * This namespace includes definitions for IPv6 networking. 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 * @addtogroup core-ip6-ip6 94 * 95 * @brief 96 * This module includes definitions for core IPv6 networking. 97 * 98 * @{ 99 */ 100 101 /** 102 * Implements the core IPv6 message processing. 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 typedef otIp6ReceiveCallback ReceiveCallback; ///< IPv6 receive callback function pointer. 112 113 /** 114 * Initializes the object. 115 * 116 * @param[in] aInstance A reference to the otInstance object. 117 */ 118 explicit Ip6(Instance &aInstance); 119 120 /** 121 * Allocates a new message buffer from the buffer pool with default settings (link security 122 * enabled and `kPriorityMedium`). 123 * 124 * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. 125 */ 126 Message *NewMessage(void); 127 128 /** 129 * Allocates a new message buffer from the buffer pool with default settings (link security 130 * enabled and `kPriorityMedium`). 131 * 132 * @param[in] aReserved The number of header bytes to reserve following the IPv6 header. 133 * 134 * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. 135 */ 136 Message *NewMessage(uint16_t aReserved); 137 138 /** 139 * Allocates a new message buffer from the buffer pool. 140 * 141 * @param[in] aReserved The number of header bytes to reserve following the IPv6 header. 142 * @param[in] aSettings The message settings. 143 * 144 * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. 145 */ 146 Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings); 147 148 /** 149 * Allocates a new message buffer from the buffer pool and writes the IPv6 datagram to the message. 150 * 151 * The message priority is always determined from IPv6 message itself (@p aData) and the priority included in 152 * @p aSetting is ignored. 153 * 154 * @param[in] aData A pointer to the IPv6 datagram buffer. 155 * @param[in] aDataLength The size of the IPV6 datagram buffer pointed by @p aData. 156 * @param[in] aSettings The message settings. 157 * 158 * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are 159 * available. 160 */ 161 Message *NewMessageFromData(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings); 162 163 /** 164 * Converts the IPv6 DSCP value to message priority level. 165 * 166 * @param[in] aDscp The IPv6 DSCP value. 167 * 168 * @returns The message priority level. 169 */ 170 static Message::Priority DscpToPriority(uint8_t aDscp); 171 172 /** 173 * Sends an IPv6 datagram. 174 * 175 * @param[in] aMessage A reference to the message. 176 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 177 * @param[in] aIpProto The Internet Protocol value. 178 * 179 * @retval kErrorNone Successfully enqueued the message into an output interface. 180 * @retval kErrorNoBufs Insufficient available buffer to add the IPv6 headers. 181 */ 182 Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto); 183 184 /** 185 * Sends a raw IPv6 datagram with a fully formed IPv6 header. 186 * 187 * @param[in] aMessage An owned pointer to a message (ownership is transferred to the method). 188 * 189 * @retval kErrorNone Successfully processed the message. 190 * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. 191 * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. 192 * @retval kErrorNoRoute No route to host. 193 * @retval kErrorParse Encountered a malformed header when processing the message. 194 */ 195 Error SendRaw(OwnedPtr<Message> aMessage); 196 197 /** 198 * Processes a received IPv6 datagram. 199 * 200 * @param[in] aMessage An owned pointer to a message. 201 * 202 * @retval kErrorNone Successfully processed the message. 203 * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. 204 * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. 205 * @retval kErrorNoRoute No route to host. 206 * @retval kErrorParse Encountered a malformed header when processing the message. 207 */ 208 Error HandleDatagram(OwnedPtr<Message> aMessagePtr, bool aIsReassembled = false); 209 210 /** 211 * Sets the callback to provide received raw IPv6 datagrams. 212 * 213 * By default, this callback does not pass Thread control traffic. See `SetReceiveIp6FilterEnabled()` to change 214 * the Thread control traffic filter setting. 215 * 216 * @param[in] aCallback The receive callback function. Can be `nullptr` to disable the callback. 217 * @param[in] aContext A pointer to application-specific context. 218 */ SetReceiveCallback(ReceiveCallback aCallback,void * aContext)219 void SetReceiveCallback(ReceiveCallback aCallback, void *aContext) { mReceiveCallback.Set(aCallback, aContext); } 220 221 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE 222 typedef otNat64ReceiveIp4Callback Ip4ReceiveCallback; ///< NAT64 IPv4 receive callback function pointer. 223 224 /** 225 * Sets the callback to provide received translated IPv4 datagrams. 226 * 227 * @param[in] aCallback The NAT64 IPv4 callbac, used when translated IPv4 datagram is received. 228 * @param[in] aContext A pointer to application-specific context. 229 */ SetNat64ReceiveIp4Callback(Ip4ReceiveCallback aCallback,void * aContext)230 void SetNat64ReceiveIp4Callback(Ip4ReceiveCallback aCallback, void *aContext) 231 { 232 mIp4ReceiveCallback.Set(aCallback, aContext); 233 } 234 #endif 235 236 /** 237 * Indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams 238 * via the callback specified in `SetReceiveIp6Callback()`. 239 * 240 * @returns TRUE if Thread control traffic is filtered out, FALSE otherwise. 241 */ IsReceiveIp6FilterEnabled(void) const242 bool IsReceiveIp6FilterEnabled(void) const { return mReceiveFilterEnabled; } 243 244 /** 245 * Sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams 246 * via the callback specified in `SetReceiveIp6Callback()`. 247 * 248 * @param[in] aEnabled TRUE if Thread control traffic is filtered out, FALSE otherwise. 249 */ SetReceiveIp6FilterEnabled(bool aEnabled)250 void SetReceiveIp6FilterEnabled(bool aEnabled) { mReceiveFilterEnabled = aEnabled; } 251 252 /** 253 * Performs default source address selection. 254 * 255 * @param[in,out] aMessageInfo A reference to the message information. 256 * 257 * @retval kErrorNone Found a source address and updated SockAddr of @p aMessageInfo. 258 * @retval kErrorNotFound No source address was found and @p aMessageInfo is unchanged. 259 */ 260 Error SelectSourceAddress(MessageInfo &aMessageInfo) const; 261 262 /** 263 * Performs default source address selection. 264 * 265 * @param[in] aDestination The destination address. 266 * 267 * @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found. 268 */ 269 const Address *SelectSourceAddress(const Address &aDestination) const; 270 271 /** 272 * Returns a reference to the send queue. 273 * 274 * @returns A reference to the send queue. 275 */ GetSendQueue(void) const276 const PriorityQueue &GetSendQueue(void) const { return mSendQueue; } 277 278 /** 279 * Converts an IP protocol number to a string. 280 * 281 * @param[in] aIpProto An IP protocol number. 282 * 283 * @returns The string representation of @p aIpProto. 284 */ 285 static const char *IpProtoToString(uint8_t aIpProto); 286 287 /** 288 * Converts an IP header ECN value to a string. 289 * 290 * @param[in] aEcn The 2-bit ECN value. 291 * 292 * @returns The string representation of @p aEcn. 293 */ 294 static const char *EcnToString(Ecn aEcn); 295 296 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 297 298 typedef otBorderRoutingCounters BrCounters; ///< Border Routing counters. 299 300 /** 301 * Returns a reference to the Border Routing counters. 302 * 303 * @returns A reference to the Border Routing counters. 304 */ GetBorderRoutingCounters(void) const305 const BrCounters &GetBorderRoutingCounters(void) const { return mBrCounters; } 306 307 /** 308 * Returns a reference to the Border Routing counters. 309 * 310 * @returns A reference to the Border Routing counters. 311 */ GetBorderRoutingCounters(void)312 BrCounters &GetBorderRoutingCounters(void) { return mBrCounters; } 313 314 /** 315 * Resets the Border Routing counters. 316 */ ResetBorderRoutingCounters(void)317 void ResetBorderRoutingCounters(void) { ClearAllBytes(mBrCounters); } 318 319 #endif // OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 320 321 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 322 323 /** 324 * Enables or disables the filter that drops TMF UDP messages from untrusted origin. 325 * 326 * @param[in] aEnabled TRUE to enable filter, FALSE otherwise. 327 */ SetTmfOriginFilterEnabled(bool aEnabled)328 void SetTmfOriginFilterEnabled(bool aEnabled) { mTmfOriginFilterEnabled = aEnabled; } 329 330 /** 331 * Indicates whether the filter that drops TMF UDP messages from untrusted origin is enabled or not. 332 * 333 * @returns TRUE if the filter is enabled, FALSE otherwise. 334 */ IsTmfOriginFilterEnabled(void)335 bool IsTmfOriginFilterEnabled(void) { return mTmfOriginFilterEnabled; } 336 337 #endif 338 339 private: 340 static constexpr uint8_t kDefaultHopLimit = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT; 341 static constexpr uint8_t kReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT; 342 343 static constexpr uint16_t kMinimalMtu = 1280; 344 345 static uint8_t PriorityToDscp(Message::Priority aPriority); 346 static Error TakeOrCopyMessagePtr(OwnedPtr<Message> &aTargetPtr, 347 OwnedPtr<Message> &aMessagePtr, 348 Message::Ownership aMessageOwnership); 349 350 void EnqueueDatagram(Message &aMessage); 351 void HandleSendQueue(void); 352 Error PassToHost(OwnedPtr<Message> &aMessagePtr, 353 const Header &aHeader, 354 uint8_t aIpProto, 355 bool aReceive, 356 Message::Ownership aMessageOwnership); 357 Error HandleExtensionHeaders(OwnedPtr<Message> &aMessagePtr, 358 const Header &aHeader, 359 uint8_t &aNextHeader, 360 bool &aReceive); 361 Error FragmentDatagram(Message &aMessage, uint8_t aIpProto); 362 Error HandleFragment(Message &aMessage); 363 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE 364 void CleanupFragmentationBuffer(void); 365 void HandleTimeTick(void); 366 void UpdateReassemblyList(void); 367 void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode); 368 #endif 369 Error ReadHopByHopHeader(const Message &aMessage, OffsetRange &aOffsetRange, HopByHopHeader &aHbhHeader) const; 370 Error AddMplOption(Message &aMessage, Header &aHeader); 371 Error PrepareMulticastToLargerThanRealmLocal(Message &aMessage, const Header &aHeader); 372 Error InsertMplOption(Message &aMessage, Header &aHeader); 373 Error RemoveMplOption(Message &aMessage); 374 Error HandleOptions(Message &aMessage, const Header &aHeader, bool &aReceive); 375 Error Receive(Header &aIp6Header, 376 OwnedPtr<Message> &aMessagePtr, 377 uint8_t aIpProto, 378 Message::Ownership aMessageOwnership); 379 bool IsOnLink(const Address &aAddress) const; 380 Error RouteLookup(const Address &aSource, const Address &aDestination) const; 381 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 382 void UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound); 383 #endif 384 385 using SendQueueTask = TaskletIn<Ip6, &Ip6::HandleSendQueue>; 386 387 bool mReceiveFilterEnabled; 388 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 389 bool mTmfOriginFilterEnabled; 390 #endif 391 Callback<ReceiveCallback> mReceiveCallback; 392 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE 393 Callback<Ip4ReceiveCallback> mIp4ReceiveCallback; 394 #endif 395 PriorityQueue mSendQueue; 396 SendQueueTask mSendQueueTask; 397 Icmp mIcmp; 398 Udp mUdp; 399 Mpl mMpl; 400 #if OPENTHREAD_CONFIG_TCP_ENABLE 401 Tcp mTcp; 402 #endif 403 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE 404 MessageQueue mReassemblyList; 405 #endif 406 #if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE 407 BrCounters mBrCounters; 408 #endif 409 }; 410 411 /** 412 * Represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame. 413 */ 414 class Headers : private Clearable<Headers> 415 { 416 friend class Clearable<Headers>; 417 418 public: 419 /** 420 * Parses the IPv6 and UDP/TCP/ICMP6 headers from a given message. 421 * 422 * @param[in] aMessage The message to parse the headers from. 423 * 424 * @retval kErrorNone The headers are parsed successfully. 425 * @retval kErrorParse Failed to parse the headers. 426 */ 427 Error ParseFrom(const Message &aMessage); 428 429 /** 430 * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers. 431 * 432 * @param[in] aMessage The message from which to read the lowpan frame. 433 * @param[in] aOffset The offset in @p aMessage to start reading the frame. 434 * @param[in] aMacAddrs The MAC source and destination addresses. 435 * 436 * @retval kErrorNone Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers. 437 * @retval kErrorNotFound Lowpan frame is a next fragment and does not contain IPv6 headers. 438 * @retval kErrorParse Failed to parse the headers. 439 */ 440 Error DecompressFrom(const Message &aMessage, uint16_t aOffset, const Mac::Addresses &aMacAddrs); 441 442 /** 443 * Decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers. 444 * 445 * @param[in] aFrameData The lowpan frame data. 446 * @param[in] aMacAddrs The MAC source and destination addresses. 447 * @param[in] aInstance The OpenThread instance. 448 * 449 * @retval kErrorNone Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers. 450 * @retval kErrorNotFound Lowpan frame is a next fragment and does not contain IPv6 headers. 451 * @retval kErrorParse Failed to parse the headers. 452 */ 453 Error DecompressFrom(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, Instance &aInstance); 454 455 /** 456 * Returns the IPv6 header. 457 * 458 * @returns The IPv6 header. 459 */ GetIp6Header(void) const460 const Header &GetIp6Header(void) const { return mIp6Header; } 461 462 /** 463 * Returns the IP protocol number from IPv6 Next Header field. 464 * 465 * @returns The IP protocol number. 466 */ GetIpProto(void) const467 uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); } 468 469 /** 470 * Returns the IPv6 Payload Length value. 471 * 472 * @returns The IPv6 Payload Length value. 473 */ GetIpLength(void) const474 uint8_t GetIpLength(void) const { return mIp6Header.GetPayloadLength(); } 475 476 /** 477 * Returns the IPv6 Hop Limit value. 478 * 479 * @returns The IPv6 Hop Limit value. 480 */ GetIpHopLimit(void) const481 uint8_t GetIpHopLimit(void) const { return mIp6Header.GetHopLimit(); } 482 483 /** 484 * Returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header. 485 * 486 * @returns The ECN value. 487 */ GetEcn(void) const488 Ecn GetEcn(void) const { return mIp6Header.GetEcn(); } 489 490 /** 491 * Indicates if the protocol number from IPv6 header is UDP. 492 * 493 * @retval TRUE If the protocol number in IPv6 header is UDP. 494 * @retval FALSE If the protocol number in IPv6 header is not UDP. 495 */ IsUdp(void) const496 bool IsUdp(void) const { return GetIpProto() == kProtoUdp; } 497 498 /** 499 * Indicates if the protocol number from IPv6 header is TCP. 500 * 501 * @retval TRUE If the protocol number in IPv6 header is TCP. 502 * @retval FALSE If the protocol number in IPv6 header is not TCP. 503 */ IsTcp(void) const504 bool IsTcp(void) const { return GetIpProto() == kProtoTcp; } 505 506 /** 507 * Indicates if the protocol number from IPv6 header is ICMPv6. 508 * 509 * @retval TRUE If the protocol number in IPv6 header is ICMPv6. 510 * @retval FALSE If the protocol number in IPv6 header is not ICMPv6. 511 */ IsIcmp6(void) const512 bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; } 513 514 /** 515 * Returns the source IPv6 address from IPv6 header. 516 * 517 * @returns The source IPv6 address. 518 */ GetSourceAddress(void) const519 const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); } 520 521 /** 522 * Returns the destination IPv6 address from IPv6 header. 523 * 524 * @returns The destination IPv6 address. 525 */ GetDestinationAddress(void) const526 const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); } 527 528 /** 529 * Returns the UDP header. 530 * 531 * MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined 532 * 533 * @returns The UDP header. 534 */ GetUdpHeader(void) const535 const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; } 536 537 /** 538 * Returns the TCP header. 539 * 540 * MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined 541 * 542 * @returns The TCP header. 543 */ GetTcpHeader(void) const544 const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; } 545 546 /** 547 * Returns the ICMPv6 header. 548 * 549 * MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined 550 * 551 * @returns The ICMPv6 header. 552 */ GetIcmpHeader(void) const553 const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; } 554 555 /** 556 * Returns the source port number if header is UDP or TCP, or zero otherwise 557 * 558 * @returns The source port number under UDP / TCP or zero. 559 */ 560 uint16_t GetSourcePort(void) const; 561 562 /** 563 * Sets the source port number if the header is UDP or TCP, does nothing otherwise 564 * 565 * @param[in] aSrcPort The UDP / TCP source Port. 566 */ 567 void SetSourcePort(uint16_t aSrcPort); 568 569 /** 570 * Returns the destination port number if header is UDP or TCP, or zero otherwise. 571 * 572 * @returns The destination port number under UDP / TCP or zero. 573 */ 574 uint16_t GetDestinationPort(void) const; 575 576 /** 577 * Returns the checksum values from corresponding UDP, TCP, or ICMPv6 header. 578 * 579 * @returns The checksum value. 580 */ 581 uint16_t GetChecksum(void) const; 582 583 private: 584 Header mIp6Header; 585 union 586 { 587 Udp::Header mUdp; 588 Tcp::Header mTcp; 589 Icmp::Header mIcmp; 590 } mHeader; 591 }; 592 593 /** 594 * @} 595 */ 596 597 } // namespace Ip6 598 } // namespace ot 599 600 #endif // IP6_HPP_ 601