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 UDP/IPv6 sockets. 32 */ 33 34 #ifndef UDP6_HPP_ 35 #define UDP6_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <openthread/udp.h> 40 #include <openthread/platform/udp.h> 41 42 #include "common/as_core_type.hpp" 43 #include "common/callback.hpp" 44 #include "common/clearable.hpp" 45 #include "common/linked_list.hpp" 46 #include "common/locator.hpp" 47 #include "common/non_copyable.hpp" 48 #include "net/ip6_headers.hpp" 49 50 namespace ot { 51 namespace Ip6 { 52 53 class Udp; 54 55 /** 56 * @addtogroup core-udp 57 * 58 * @brief 59 * This module includes definitions for UDP/IPv6 sockets. 60 * 61 * @{ 62 * 63 */ 64 65 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE && OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 66 #error "OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE and OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE must not both be set." 67 #endif 68 69 /** 70 * This enumeration defines the network interface identifiers. 71 * 72 */ 73 enum NetifIdentifier : uint8_t 74 { 75 kNetifUnspecified = OT_NETIF_UNSPECIFIED, ///< Unspecified network interface. 76 kNetifThread = OT_NETIF_THREAD, ///< The Thread interface. 77 kNetifBackbone = OT_NETIF_BACKBONE, ///< The Backbone interface. 78 }; 79 80 /** 81 * This class implements core UDP message handling. 82 * 83 */ 84 class Udp : public InstanceLocator, private NonCopyable 85 { 86 public: 87 /** 88 * This class implements a UDP/IPv6 socket. 89 * 90 */ 91 class SocketHandle : public otUdpSocket, public LinkedListEntry<SocketHandle>, public Clearable<SocketHandle> 92 { 93 friend class Udp; 94 friend class LinkedList<SocketHandle>; 95 96 public: 97 /** 98 * This method indicates whether or not the socket is bound. 99 * 100 * @retval TRUE if the socket is bound (i.e. source port is non-zero). 101 * @retval FALSE if the socket is not bound (source port is zero). 102 * 103 */ IsBound(void) const104 bool IsBound(void) const { return mSockName.mPort != 0; } 105 106 /** 107 * This method returns the local socket address. 108 * 109 * @returns A reference to the local socket address. 110 * 111 */ GetSockName(void)112 SockAddr &GetSockName(void) { return AsCoreType(&mSockName); } 113 114 /** 115 * This method returns the local socket address. 116 * 117 * @returns A reference to the local socket address. 118 * 119 */ GetSockName(void) const120 const SockAddr &GetSockName(void) const { return AsCoreType(&mSockName); } 121 122 /** 123 * This method returns the peer's socket address. 124 * 125 * @returns A reference to the peer's socket address. 126 * 127 */ GetPeerName(void)128 SockAddr &GetPeerName(void) { return AsCoreType(&mPeerName); } 129 130 /** 131 * This method returns the peer's socket address. 132 * 133 * @returns A reference to the peer's socket address. 134 * 135 */ GetPeerName(void) const136 const SockAddr &GetPeerName(void) const { return AsCoreType(&mPeerName); } 137 138 private: 139 bool Matches(const MessageInfo &aMessageInfo) const; 140 HandleUdpReceive(Message & aMessage,const MessageInfo & aMessageInfo)141 void HandleUdpReceive(Message &aMessage, const MessageInfo &aMessageInfo) 142 { 143 mHandler(mContext, &aMessage, &aMessageInfo); 144 } 145 }; 146 147 /** 148 * This class implements a UDP/IPv6 socket. 149 * 150 */ 151 class Socket : public InstanceLocator, public SocketHandle 152 { 153 friend class Udp; 154 155 public: 156 /** 157 * This constructor initializes the object. 158 * 159 * @param[in] aInstance A reference to OpenThread instance. 160 * 161 */ 162 explicit Socket(Instance &aInstance); 163 164 /** 165 * This method returns a new UDP message with default settings (link security enabled and `kPriorityNormal`) 166 * 167 * @returns A pointer to the message or `nullptr` if no buffers are available. 168 * 169 */ 170 Message *NewMessage(void); 171 172 /** 173 * This method returns a new UDP message with default settings (link security enabled and `kPriorityNormal`) 174 * 175 * @param[in] aReserved The number of header bytes to reserve after the UDP header. 176 * 177 * @returns A pointer to the message or `nullptr` if no buffers are available. 178 * 179 */ 180 Message *NewMessage(uint16_t aReserved); 181 182 /** 183 * This method returns a new UDP message with sufficient header space reserved. 184 * 185 * @param[in] aReserved The number of header bytes to reserve after the UDP header. 186 * @param[in] aSettings The message settings (default is used if not provided). 187 * 188 * @returns A pointer to the message or `nullptr` if no buffers are available. 189 * 190 */ 191 Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings); 192 193 /** 194 * This method opens the UDP socket. 195 * 196 * @param[in] aHandler A pointer to a function that is called when receiving UDP messages. 197 * @param[in] aContext A pointer to arbitrary context information. 198 * 199 * @retval kErrorNone Successfully opened the socket. 200 * @retval kErrorFailed Failed to open the socket. 201 * 202 */ 203 Error Open(otUdpReceive aHandler, void *aContext); 204 205 /** 206 * This method returns if the UDP socket is open. 207 * 208 * @returns If the UDP socket is open. 209 * 210 */ 211 bool IsOpen(void) const; 212 213 /** 214 * This method binds the UDP socket. 215 * 216 * @param[in] aSockAddr A reference to the socket address. 217 * @param[in] aNetifIdentifier The network interface identifier. 218 * 219 * @retval kErrorNone Successfully bound the socket. 220 * @retval kErrorInvalidArgs Unable to bind to Thread network interface with the given address. 221 * @retval kErrorFailed Failed to bind UDP Socket. 222 * 223 */ 224 Error Bind(const SockAddr &aSockAddr, NetifIdentifier aNetifIdentifier = kNetifThread); 225 226 /** 227 * This method binds the UDP socket. 228 * 229 * @param[in] aPort A port number. 230 * @param[in] aNetifIdentifier The network interface identifier. 231 * 232 * @retval kErrorNone Successfully bound the socket. 233 * @retval kErrorFailed Failed to bind UDP Socket. 234 * 235 */ 236 Error Bind(uint16_t aPort, NetifIdentifier aNetifIdentifier = kNetifThread); 237 238 /** 239 * This method binds the UDP socket. 240 * 241 * @retval kErrorNone Successfully bound the socket. 242 * @retval kErrorFailed Failed to bind UDP Socket. 243 * 244 */ Bind(void)245 Error Bind(void) { return Bind(0); } 246 247 /** 248 * This method connects the UDP socket. 249 * 250 * @param[in] aSockAddr A reference to the socket address. 251 * 252 * @retval kErrorNone Successfully connected the socket. 253 * @retval kErrorFailed Failed to connect UDP Socket. 254 * 255 */ 256 Error Connect(const SockAddr &aSockAddr); 257 258 /** 259 * This method connects the UDP socket. 260 * 261 * @param[in] aPort A port number. 262 * 263 * @retval kErrorNone Successfully connected the socket. 264 * @retval kErrorFailed Failed to connect UDP Socket. 265 * 266 */ 267 Error Connect(uint16_t aPort); 268 269 /** 270 * This method connects the UDP socket. 271 * 272 * @retval kErrorNone Successfully connected the socket. 273 * @retval kErrorFailed Failed to connect UDP Socket. 274 * 275 */ Connect(void)276 Error Connect(void) { return Connect(0); } 277 278 /** 279 * This method closes the UDP socket. 280 * 281 * @retval kErrorNone Successfully closed the UDP socket. 282 * @retval kErrorFailed Failed to close UDP Socket. 283 * 284 */ 285 Error Close(void); 286 287 /** 288 * This method sends a UDP message. 289 * 290 * @param[in] aMessage The message to send. 291 * @param[in] aMessageInfo The message info associated with @p aMessage. 292 * 293 * @retval kErrorNone Successfully sent the UDP message. 294 * @retval kErrorInvalidArgs If no peer is specified in @p aMessageInfo or by Connect(). 295 * @retval kErrorNoBufs Insufficient available buffer to add the UDP and IPv6 headers. 296 * 297 */ 298 Error SendTo(Message &aMessage, const MessageInfo &aMessageInfo); 299 300 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 301 /** 302 * This method configures the UDP socket to join a multicast group on a Host network interface. 303 * 304 * @param[in] aNetifIdentifier The network interface identifier. 305 * @param[in] aAddress The multicast group address. 306 * 307 * @retval kErrorNone Successfully joined the multicast group. 308 * @retval kErrorFailed Failed to join the multicast group. 309 * 310 */ 311 Error JoinNetifMulticastGroup(NetifIdentifier aNetifIdentifier, const Address &aAddress); 312 313 /** 314 * This method configures the UDP socket to leave a multicast group on a Host network interface. 315 * 316 * @param[in] aNetifIdentifier The network interface identifier. 317 * @param[in] aAddress The multicast group address. 318 * 319 * @retval kErrorNone Successfully left the multicast group. 320 * @retval kErrorFailed Failed to leave the multicast group. 321 * 322 */ 323 Error LeaveNetifMulticastGroup(NetifIdentifier aNetifIdentifier, const Address &aAddress); 324 #endif 325 }; 326 327 /** 328 * This class implements a UDP receiver. 329 * 330 */ 331 class Receiver : public otUdpReceiver, public LinkedListEntry<Receiver> 332 { 333 friend class Udp; 334 335 public: 336 /** 337 * This constructor initializes the UDP receiver. 338 * 339 * @param[in] aHandler A pointer to the function to handle UDP message. 340 * @param[in] aContext A pointer to arbitrary context information. 341 * 342 */ Receiver(otUdpHandler aHandler,void * aContext)343 Receiver(otUdpHandler aHandler, void *aContext) 344 { 345 mNext = nullptr; 346 mHandler = aHandler; 347 mContext = aContext; 348 } 349 350 private: HandleMessage(Message & aMessage,const MessageInfo & aMessageInfo)351 bool HandleMessage(Message &aMessage, const MessageInfo &aMessageInfo) 352 { 353 return mHandler(mContext, &aMessage, &aMessageInfo); 354 } 355 }; 356 357 /** 358 * This class implements UDP header generation and parsing. 359 * 360 */ 361 OT_TOOL_PACKED_BEGIN 362 class Header : public Clearable<Header> 363 { 364 public: 365 static constexpr uint16_t kSourcePortFieldOffset = 0; ///< Byte offset of Source Port field in UDP header. 366 static constexpr uint16_t kDestPortFieldOffset = 2; ///< Byte offset of Destination Port field in UDP header. 367 static constexpr uint16_t kLengthFieldOffset = 4; ///< Byte offset of Length field in UDP header. 368 static constexpr uint16_t kChecksumFieldOffset = 6; ///< Byte offset of Checksum field in UDP header. 369 370 /** 371 * This method returns the UDP Source Port. 372 * 373 * @returns The UDP Source Port. 374 * 375 */ GetSourcePort(void) const376 uint16_t GetSourcePort(void) const { return HostSwap16(mSourcePort); } 377 378 /** 379 * This method sets the UDP Source Port. 380 * 381 * @param[in] aPort The UDP Source Port. 382 * 383 */ SetSourcePort(uint16_t aPort)384 void SetSourcePort(uint16_t aPort) { mSourcePort = HostSwap16(aPort); } 385 386 /** 387 * This method returns the UDP Destination Port. 388 * 389 * @returns The UDP Destination Port. 390 * 391 */ GetDestinationPort(void) const392 uint16_t GetDestinationPort(void) const { return HostSwap16(mDestinationPort); } 393 394 /** 395 * This method sets the UDP Destination Port. 396 * 397 * @param[in] aPort The UDP Destination Port. 398 * 399 */ SetDestinationPort(uint16_t aPort)400 void SetDestinationPort(uint16_t aPort) { mDestinationPort = HostSwap16(aPort); } 401 402 /** 403 * This method returns the UDP Length. 404 * 405 * @returns The UDP Length. 406 * 407 */ GetLength(void) const408 uint16_t GetLength(void) const { return HostSwap16(mLength); } 409 410 /** 411 * This method sets the UDP Length. 412 * 413 * @param[in] aLength The UDP Length. 414 * 415 */ SetLength(uint16_t aLength)416 void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); } 417 418 /** 419 * This method returns the UDP Checksum. 420 * 421 * @returns The UDP Checksum. 422 * 423 */ GetChecksum(void) const424 uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); } 425 426 /** 427 * This method sets the UDP Checksum. 428 * 429 * @param[in] aChecksum The UDP Checksum. 430 * 431 */ SetChecksum(uint16_t aChecksum)432 void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); } 433 434 private: 435 uint16_t mSourcePort; 436 uint16_t mDestinationPort; 437 uint16_t mLength; 438 uint16_t mChecksum; 439 440 } OT_TOOL_PACKED_END; 441 442 /** 443 * This constructor initializes the object. 444 * 445 * @param[in] aInstance A reference to OpenThread instance. 446 * 447 */ 448 explicit Udp(Instance &aInstance); 449 450 /** 451 * This method adds a UDP receiver. 452 * 453 * @param[in] aReceiver A reference to the UDP receiver. 454 * 455 * @retval kErrorNone Successfully added the UDP receiver. 456 * @retval kErrorAlready The UDP receiver was already added. 457 * 458 */ 459 Error AddReceiver(Receiver &aReceiver); 460 461 /** 462 * This method removes a UDP receiver. 463 * 464 * @param[in] aReceiver A reference to the UDP receiver. 465 * 466 * @retval kErrorNone Successfully removed the UDP receiver. 467 * @retval kErrorNotFound The UDP receiver was not added. 468 * 469 */ 470 Error RemoveReceiver(Receiver &aReceiver); 471 472 /** 473 * This method opens a UDP socket. 474 * 475 * @param[in] aSocket A reference to the socket. 476 * @param[in] aHandler A pointer to a function that is called when receiving UDP messages. 477 * @param[in] aContext A pointer to arbitrary context information. 478 * 479 * @retval kErrorNone Successfully opened the socket. 480 * @retval kErrorFailed Failed to open the socket. 481 * 482 */ 483 Error Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext); 484 485 /** 486 * This method returns if a UDP socket is open. 487 * 488 * @param[in] aSocket A reference to the socket. 489 * 490 * @returns If the UDP socket is open. 491 * 492 */ IsOpen(const SocketHandle & aSocket) const493 bool IsOpen(const SocketHandle &aSocket) const { return mSockets.Contains(aSocket); } 494 495 /** 496 * This method binds a UDP socket. 497 * 498 * @param[in] aSocket A reference to the socket. 499 * @param[in] aSockAddr A reference to the socket address. 500 * @param[in] aNetifIdentifier The network interface identifier. 501 * 502 * @retval kErrorNone Successfully bound the socket. 503 * @retval kErrorInvalidArgs Unable to bind to Thread network interface with the given address. 504 * @retval kErrorFailed Failed to bind UDP Socket. 505 * 506 */ 507 Error Bind(SocketHandle &aSocket, const SockAddr &aSockAddr, NetifIdentifier aNetifIdentifier); 508 509 /** 510 * This method connects a UDP socket. 511 * 512 * @param[in] aSocket A reference to the socket. 513 * @param[in] aSockAddr A reference to the socket address. 514 * 515 * @retval kErrorNone Successfully connected the socket. 516 * @retval kErrorFailed Failed to connect UDP Socket. 517 * 518 */ 519 Error Connect(SocketHandle &aSocket, const SockAddr &aSockAddr); 520 521 /** 522 * This method closes the UDP socket. 523 * 524 * @param[in] aSocket A reference to the socket. 525 * 526 * @retval kErrorNone Successfully closed the UDP socket. 527 * @retval kErrorFailed Failed to close UDP Socket. 528 * 529 */ 530 Error Close(SocketHandle &aSocket); 531 532 /** 533 * This method sends a UDP message using a socket. 534 * 535 * @param[in] aSocket A reference to the socket. 536 * @param[in] aMessage The message to send. 537 * @param[in] aMessageInfo The message info associated with @p aMessage. 538 * 539 * @retval kErrorNone Successfully sent the UDP message. 540 * @retval kErrorInvalidArgs If no peer is specified in @p aMessageInfo or by Connect(). 541 * @retval kErrorNoBufs Insufficient available buffer to add the UDP and IPv6 headers. 542 * 543 */ 544 Error SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo); 545 546 /** 547 * This method returns a new ephemeral port. 548 * 549 * @returns A new ephemeral port. 550 * 551 */ 552 uint16_t GetEphemeralPort(void); 553 554 /** 555 * This method returns a new UDP message with default settings (link security enabled and `kPriorityNormal`) 556 * 557 * @returns A pointer to the message or `nullptr` if no buffers are available. 558 * 559 */ 560 Message *NewMessage(void); 561 562 /** 563 * This method returns a new UDP message with default settings (link security enabled and `kPriorityNormal`) 564 * 565 * @param[in] aReserved The number of header bytes to reserve after the UDP header. 566 * 567 * @returns A pointer to the message or `nullptr` if no buffers are available. 568 * 569 */ 570 Message *NewMessage(uint16_t aReserved); 571 572 /** 573 * This method returns a new UDP message with sufficient header space reserved. 574 * 575 * @param[in] aReserved The number of header bytes to reserve after the UDP header. 576 * @param[in] aSettings The message settings. 577 * 578 * @returns A pointer to the message or `nullptr` if no buffers are available. 579 * 580 */ 581 Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings); 582 583 /** 584 * This method sends an IPv6 datagram. 585 * 586 * @param[in] aMessage A reference to the message. 587 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 588 * @param[in] aIpProto The Internet Protocol value. 589 * 590 * @retval kErrorNone Successfully enqueued the message into an output interface. 591 * @retval kErrorNoBufs Insufficient available buffer to add the IPv6 headers. 592 * 593 */ 594 Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto); 595 596 /** 597 * This method handles a received UDP message. 598 * 599 * @param[in] aMessage A reference to the UDP message to process. 600 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 601 * 602 * @retval kErrorNone Successfully processed the UDP message. 603 * @retval kErrorDrop Could not fully process the UDP message. 604 * 605 */ 606 Error HandleMessage(Message &aMessage, MessageInfo &aMessageInfo); 607 608 /** 609 * This method handles a received UDP message with offset set to the payload. 610 * 611 * @param[in] aMessage A reference to the UDP message to process. 612 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 613 * 614 */ 615 void HandlePayload(Message &aMessage, MessageInfo &aMessageInfo); 616 617 /** 618 * This method returns the head of UDP Sockets list. 619 * 620 * @returns A pointer to the head of UDP Socket linked list. 621 * 622 */ GetUdpSockets(void)623 SocketHandle *GetUdpSockets(void) { return mSockets.GetHead(); } 624 625 #if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 626 /** 627 * This method sets the forward sender. 628 * 629 * @param[in] aForwarder A function pointer to forward UDP packets. 630 * @param[in] aContext A pointer to arbitrary context information. 631 * 632 */ SetUdpForwarder(otUdpForwarder aForwarder,void * aContext)633 void SetUdpForwarder(otUdpForwarder aForwarder, void *aContext) { mUdpForwarder.Set(aForwarder, aContext); } 634 #endif 635 636 /** 637 * This method returns whether a udp port is being used by OpenThread or any of it's optional 638 * features, e.g. CoAP API. 639 * 640 * @param[in] aPort The udp port 641 * 642 * @retval True when port is used by the OpenThread. 643 * @retval False when the port is not used by OpenThread. 644 * 645 */ 646 bool IsPortInUse(uint16_t aPort) const; 647 648 /** 649 * This method returns whether a udp port belongs to the platform or the stack. 650 * 651 * @param[in] aPort The udp port 652 * 653 * @retval True when the port belongs to the platform. 654 * @retval False when the port belongs to the stack. 655 * 656 */ 657 bool ShouldUsePlatformUdp(uint16_t aPort) const; 658 659 private: 660 static constexpr uint16_t kDynamicPortMin = 49152; // Service Name and Transport Protocol Port Number Registry 661 static constexpr uint16_t kDynamicPortMax = 65535; // Service Name and Transport Protocol Port Number Registry 662 663 // Reserved range for use by SRP server 664 static constexpr uint16_t kSrpServerPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN; 665 static constexpr uint16_t kSrpServerPortMax = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MAX; 666 667 static bool IsPortReserved(uint16_t aPort); 668 669 void AddSocket(SocketHandle &aSocket); 670 void RemoveSocket(SocketHandle &aSocket); 671 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE 672 bool ShouldUsePlatformUdp(const SocketHandle &aSocket) const; 673 #endif 674 675 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 676 void SetBackboneSocket(SocketHandle &aSocket); 677 const SocketHandle *GetBackboneSockets(void) const; 678 bool IsBackboneSocket(const SocketHandle &aSocket) const; 679 #endif 680 681 uint16_t mEphemeralPort; 682 LinkedList<Receiver> mReceivers; 683 LinkedList<SocketHandle> mSockets; 684 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 685 SocketHandle *mPrevBackboneSockets; 686 #endif 687 #if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 688 Callback<otUdpForwarder> mUdpForwarder; 689 #endif 690 }; 691 692 /** 693 * @} 694 * 695 */ 696 697 } // namespace Ip6 698 699 DefineCoreType(otUdpSocket, Ip6::Udp::SocketHandle); 700 DefineCoreType(otUdpReceiver, Ip6::Udp::Receiver); 701 DefineMapEnum(otNetifIdentifier, Ip6::NetifIdentifier); 702 703 } // namespace ot 704 705 #endif // UDP6_HPP_ 706