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