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 implements UDP/IPv6 sockets.
32  */
33 
34 #include "udp6.hpp"
35 
36 #include <stdio.h>
37 
38 #include <openthread/platform/udp.h>
39 
40 #include "common/code_utils.hpp"
41 #include "common/encoding.hpp"
42 #include "common/instance.hpp"
43 #include "common/locator_getters.hpp"
44 #include "net/checksum.hpp"
45 #include "net/ip6.hpp"
46 
47 namespace ot {
48 namespace Ip6 {
49 
Matches(const MessageInfo & aMessageInfo) const50 bool Udp::SocketHandle::Matches(const MessageInfo &aMessageInfo) const
51 {
52     bool matches = false;
53 
54     VerifyOrExit(GetSockName().mPort == aMessageInfo.GetSockPort());
55 
56     VerifyOrExit(aMessageInfo.GetSockAddr().IsMulticast() || GetSockName().GetAddress().IsUnspecified() ||
57                  GetSockName().GetAddress() == aMessageInfo.GetSockAddr());
58 
59     // Verify source if connected socket
60     if (GetPeerName().mPort != 0)
61     {
62         VerifyOrExit(GetPeerName().mPort == aMessageInfo.GetPeerPort());
63 
64         VerifyOrExit(GetPeerName().GetAddress().IsUnspecified() ||
65                      GetPeerName().GetAddress() == aMessageInfo.GetPeerAddr());
66     }
67 
68     matches = true;
69 
70 exit:
71     return matches;
72 }
73 
Socket(Instance & aInstance)74 Udp::Socket::Socket(Instance &aInstance)
75     : InstanceLocator(aInstance)
76 {
77     Clear();
78 }
79 
NewMessage(void)80 Message *Udp::Socket::NewMessage(void) { return NewMessage(0); }
81 
NewMessage(uint16_t aReserved)82 Message *Udp::Socket::NewMessage(uint16_t aReserved) { return NewMessage(aReserved, Message::Settings::GetDefault()); }
83 
NewMessage(uint16_t aReserved,const Message::Settings & aSettings)84 Message *Udp::Socket::NewMessage(uint16_t aReserved, const Message::Settings &aSettings)
85 {
86     return Get<Udp>().NewMessage(aReserved, aSettings);
87 }
88 
Open(otUdpReceive aHandler,void * aContext)89 Error Udp::Socket::Open(otUdpReceive aHandler, void *aContext) { return Get<Udp>().Open(*this, aHandler, aContext); }
90 
IsOpen(void) const91 bool Udp::Socket::IsOpen(void) const { return Get<Udp>().IsOpen(*this); }
92 
Bind(const SockAddr & aSockAddr,NetifIdentifier aNetifIdentifier)93 Error Udp::Socket::Bind(const SockAddr &aSockAddr, NetifIdentifier aNetifIdentifier)
94 {
95     return Get<Udp>().Bind(*this, aSockAddr, aNetifIdentifier);
96 }
97 
Bind(uint16_t aPort,NetifIdentifier aNetifIdentifier)98 Error Udp::Socket::Bind(uint16_t aPort, NetifIdentifier aNetifIdentifier)
99 {
100     return Bind(SockAddr(aPort), aNetifIdentifier);
101 }
102 
Connect(const SockAddr & aSockAddr)103 Error Udp::Socket::Connect(const SockAddr &aSockAddr) { return Get<Udp>().Connect(*this, aSockAddr); }
104 
Connect(uint16_t aPort)105 Error Udp::Socket::Connect(uint16_t aPort) { return Connect(SockAddr(aPort)); }
106 
Close(void)107 Error Udp::Socket::Close(void) { return Get<Udp>().Close(*this); }
108 
SendTo(Message & aMessage,const MessageInfo & aMessageInfo)109 Error Udp::Socket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
110 {
111     return Get<Udp>().SendTo(*this, aMessage, aMessageInfo);
112 }
113 
114 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
JoinNetifMulticastGroup(NetifIdentifier aNetifIdentifier,const Address & aAddress)115 Error Udp::Socket::JoinNetifMulticastGroup(NetifIdentifier aNetifIdentifier, const Address &aAddress)
116 {
117     OT_UNUSED_VARIABLE(aNetifIdentifier);
118     OT_UNUSED_VARIABLE(aAddress);
119 
120     Error error = kErrorNotImplemented;
121 
122     VerifyOrExit(aAddress.IsMulticast(), error = kErrorInvalidArgs);
123 
124 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
125     error = otPlatUdpJoinMulticastGroup(this, MapEnum(aNetifIdentifier), &aAddress);
126 #endif
127 
128 exit:
129     return error;
130 }
131 
LeaveNetifMulticastGroup(NetifIdentifier aNetifIdentifier,const Address & aAddress)132 Error Udp::Socket::LeaveNetifMulticastGroup(NetifIdentifier aNetifIdentifier, const Address &aAddress)
133 {
134     OT_UNUSED_VARIABLE(aNetifIdentifier);
135     OT_UNUSED_VARIABLE(aAddress);
136 
137     Error error = kErrorNotImplemented;
138 
139     VerifyOrExit(aAddress.IsMulticast(), error = kErrorInvalidArgs);
140 
141 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
142     error = otPlatUdpLeaveMulticastGroup(this, MapEnum(aNetifIdentifier), &aAddress);
143 #endif
144 
145 exit:
146     return error;
147 }
148 #endif
149 
Udp(Instance & aInstance)150 Udp::Udp(Instance &aInstance)
151     : InstanceLocator(aInstance)
152     , mEphemeralPort(kDynamicPortMin)
153 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
154     , mPrevBackboneSockets(nullptr)
155 #endif
156 {
157 }
158 
AddReceiver(Receiver & aReceiver)159 Error Udp::AddReceiver(Receiver &aReceiver) { return mReceivers.Add(aReceiver); }
160 
RemoveReceiver(Receiver & aReceiver)161 Error Udp::RemoveReceiver(Receiver &aReceiver)
162 {
163     Error error;
164 
165     SuccessOrExit(error = mReceivers.Remove(aReceiver));
166     aReceiver.SetNext(nullptr);
167 
168 exit:
169     return error;
170 }
171 
Open(SocketHandle & aSocket,otUdpReceive aHandler,void * aContext)172 Error Udp::Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext)
173 {
174     Error error = kErrorNone;
175 
176     OT_ASSERT(!IsOpen(aSocket));
177 
178     aSocket.GetSockName().Clear();
179     aSocket.GetPeerName().Clear();
180     aSocket.mHandler = aHandler;
181     aSocket.mContext = aContext;
182 
183 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
184     error = otPlatUdpSocket(&aSocket);
185 #endif
186     SuccessOrExit(error);
187 
188     AddSocket(aSocket);
189 
190 exit:
191     return error;
192 }
193 
Bind(SocketHandle & aSocket,const SockAddr & aSockAddr,NetifIdentifier aNetifIdentifier)194 Error Udp::Bind(SocketHandle &aSocket, const SockAddr &aSockAddr, NetifIdentifier aNetifIdentifier)
195 {
196     OT_UNUSED_VARIABLE(aNetifIdentifier);
197 
198     Error error = kErrorNone;
199 
200 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
201     SuccessOrExit(error = otPlatUdpBindToNetif(&aSocket, MapEnum(aNetifIdentifier)));
202 #endif
203 
204 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
205     if (aNetifIdentifier == kNetifBackbone)
206     {
207         SetBackboneSocket(aSocket);
208     }
209 #endif
210 
211     VerifyOrExit(aSockAddr.GetAddress().IsUnspecified() || Get<ThreadNetif>().HasUnicastAddress(aSockAddr.GetAddress()),
212                  error = kErrorInvalidArgs);
213 
214     aSocket.mSockName = aSockAddr;
215 
216     if (!aSocket.IsBound())
217     {
218         do
219         {
220             aSocket.mSockName.mPort = GetEphemeralPort();
221 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
222             error = otPlatUdpBind(&aSocket);
223 #endif
224         } while (error != kErrorNone);
225     }
226 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
227     else if (ShouldUsePlatformUdp(aSocket))
228     {
229         error = otPlatUdpBind(&aSocket);
230     }
231 #endif
232 
233 exit:
234     return error;
235 }
236 
237 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
SetBackboneSocket(SocketHandle & aSocket)238 void Udp::SetBackboneSocket(SocketHandle &aSocket)
239 {
240     RemoveSocket(aSocket);
241 
242     if (mPrevBackboneSockets != nullptr)
243     {
244         mSockets.PushAfter(aSocket, *mPrevBackboneSockets);
245     }
246     else
247     {
248         mSockets.Push(aSocket);
249     }
250 }
251 
GetBackboneSockets(void) const252 const Udp::SocketHandle *Udp::GetBackboneSockets(void) const
253 {
254     return mPrevBackboneSockets != nullptr ? mPrevBackboneSockets->GetNext() : mSockets.GetHead();
255 }
256 
IsBackboneSocket(const SocketHandle & aSocket) const257 bool Udp::IsBackboneSocket(const SocketHandle &aSocket) const
258 {
259     bool retval = false;
260 
261     for (const SocketHandle *sock = GetBackboneSockets(); sock != nullptr; sock = sock->GetNext())
262     {
263         if (sock == &aSocket)
264         {
265             ExitNow(retval = true);
266         }
267     }
268 
269 exit:
270     return retval;
271 }
272 #endif
273 
Connect(SocketHandle & aSocket,const SockAddr & aSockAddr)274 Error Udp::Connect(SocketHandle &aSocket, const SockAddr &aSockAddr)
275 {
276     Error error = kErrorNone;
277 
278     aSocket.mPeerName = aSockAddr;
279 
280     if (!aSocket.IsBound())
281     {
282         SuccessOrExit(error = Bind(aSocket, aSocket.GetSockName(), kNetifThread));
283     }
284 
285 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
286     if (ShouldUsePlatformUdp(aSocket))
287     {
288         error = otPlatUdpConnect(&aSocket);
289     }
290 #endif
291 
292 exit:
293     return error;
294 }
295 
Close(SocketHandle & aSocket)296 Error Udp::Close(SocketHandle &aSocket)
297 {
298     Error error = kErrorNone;
299 
300     VerifyOrExit(IsOpen(aSocket));
301 
302 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
303     error = otPlatUdpClose(&aSocket);
304 #endif
305     SuccessOrExit(error);
306 
307     RemoveSocket(aSocket);
308     aSocket.GetSockName().Clear();
309     aSocket.GetPeerName().Clear();
310 
311 exit:
312     return error;
313 }
314 
SendTo(SocketHandle & aSocket,Message & aMessage,const MessageInfo & aMessageInfo)315 Error Udp::SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo)
316 {
317     Error       error = kErrorNone;
318     MessageInfo messageInfoLocal;
319 
320     VerifyOrExit((aMessageInfo.GetSockPort() == 0) || (aSocket.GetSockName().mPort == aMessageInfo.GetSockPort()),
321                  error = kErrorInvalidArgs);
322 
323     messageInfoLocal = aMessageInfo;
324 
325     if (messageInfoLocal.GetPeerAddr().IsUnspecified())
326     {
327         VerifyOrExit(!aSocket.GetPeerName().GetAddress().IsUnspecified(), error = kErrorInvalidArgs);
328 
329         messageInfoLocal.SetPeerAddr(aSocket.GetPeerName().GetAddress());
330     }
331 
332     if (messageInfoLocal.mPeerPort == 0)
333     {
334         VerifyOrExit(aSocket.GetPeerName().mPort != 0, error = kErrorInvalidArgs);
335         messageInfoLocal.mPeerPort = aSocket.GetPeerName().mPort;
336     }
337 
338     if (messageInfoLocal.GetSockAddr().IsUnspecified())
339     {
340         messageInfoLocal.SetSockAddr(aSocket.GetSockName().GetAddress());
341     }
342 
343     if (!aSocket.IsBound())
344     {
345         SuccessOrExit(error = Bind(aSocket, aSocket.GetSockName(), kNetifThread));
346     }
347 
348     messageInfoLocal.SetSockPort(aSocket.GetSockName().mPort);
349 
350 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
351     if (ShouldUsePlatformUdp(aSocket))
352     {
353         SuccessOrExit(error = otPlatUdpSend(&aSocket, &aMessage, &messageInfoLocal));
354     }
355     else
356 #endif
357     {
358         SuccessOrExit(error = SendDatagram(aMessage, messageInfoLocal, kProtoUdp));
359     }
360 
361 exit:
362     return error;
363 }
364 
IsPortReserved(uint16_t aPort)365 bool Udp::IsPortReserved(uint16_t aPort)
366 {
367     return aPort == Tmf::kUdpPort || (kSrpServerPortMin <= aPort && aPort <= kSrpServerPortMax);
368 }
369 
AddSocket(SocketHandle & aSocket)370 void Udp::AddSocket(SocketHandle &aSocket)
371 {
372     SuccessOrExit(mSockets.Add(aSocket));
373 
374 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
375     if (mPrevBackboneSockets == nullptr)
376     {
377         mPrevBackboneSockets = &aSocket;
378     }
379 #endif
380 exit:
381     return;
382 }
383 
RemoveSocket(SocketHandle & aSocket)384 void Udp::RemoveSocket(SocketHandle &aSocket)
385 {
386     SocketHandle *prev;
387 
388     SuccessOrExit(mSockets.Find(aSocket, prev));
389 
390     mSockets.PopAfter(prev);
391     aSocket.SetNext(nullptr);
392 
393 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
394     if (&aSocket == mPrevBackboneSockets)
395     {
396         mPrevBackboneSockets = prev;
397     }
398 #endif
399 
400 exit:
401     return;
402 }
403 
GetEphemeralPort(void)404 uint16_t Udp::GetEphemeralPort(void)
405 {
406     do
407     {
408         if (mEphemeralPort < kDynamicPortMax)
409         {
410             mEphemeralPort++;
411         }
412         else
413         {
414             mEphemeralPort = kDynamicPortMin;
415         }
416     } while (IsPortReserved(mEphemeralPort));
417 
418     return mEphemeralPort;
419 }
420 
NewMessage(void)421 Message *Udp::NewMessage(void) { return NewMessage(0); }
422 
NewMessage(uint16_t aReserved)423 Message *Udp::NewMessage(uint16_t aReserved) { return NewMessage(aReserved, Message::Settings::GetDefault()); }
424 
NewMessage(uint16_t aReserved,const Message::Settings & aSettings)425 Message *Udp::NewMessage(uint16_t aReserved, const Message::Settings &aSettings)
426 {
427     return Get<Ip6>().NewMessage(sizeof(Header) + aReserved, aSettings);
428 }
429 
SendDatagram(Message & aMessage,MessageInfo & aMessageInfo,uint8_t aIpProto)430 Error Udp::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
431 {
432     Error error = kErrorNone;
433 
434 #if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
435     if (aMessageInfo.IsHostInterface())
436     {
437         VerifyOrExit(mUdpForwarder.IsSet(), error = kErrorNoRoute);
438         mUdpForwarder.Invoke(&aMessage, aMessageInfo.mPeerPort, &aMessageInfo.GetPeerAddr(), aMessageInfo.mSockPort);
439         // message is consumed by the callback
440     }
441     else
442 #endif
443     {
444         Header udpHeader;
445 
446         udpHeader.SetSourcePort(aMessageInfo.mSockPort);
447         udpHeader.SetDestinationPort(aMessageInfo.mPeerPort);
448         udpHeader.SetLength(sizeof(udpHeader) + aMessage.GetLength());
449         udpHeader.SetChecksum(0);
450 
451         SuccessOrExit(error = aMessage.Prepend(udpHeader));
452         aMessage.SetOffset(0);
453 
454         error = Get<Ip6>().SendDatagram(aMessage, aMessageInfo, aIpProto);
455     }
456 
457 exit:
458     return error;
459 }
460 
HandleMessage(Message & aMessage,MessageInfo & aMessageInfo)461 Error Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
462 {
463     Error  error = kErrorNone;
464     Header udpHeader;
465 
466     SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), udpHeader));
467 
468 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
469     SuccessOrExit(error = Checksum::VerifyMessageChecksum(aMessage, aMessageInfo, kProtoUdp));
470 #endif
471 
472     aMessage.MoveOffset(sizeof(udpHeader));
473     aMessageInfo.mPeerPort = udpHeader.GetSourcePort();
474     aMessageInfo.mSockPort = udpHeader.GetDestinationPort();
475 
476 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
477     VerifyOrExit(!ShouldUsePlatformUdp(aMessageInfo.mSockPort) || IsPortInUse(aMessageInfo.mSockPort));
478 #endif
479 
480     for (Receiver &receiver : mReceivers)
481     {
482         VerifyOrExit(!receiver.HandleMessage(aMessage, aMessageInfo));
483     }
484 
485     HandlePayload(aMessage, aMessageInfo);
486 
487 exit:
488     return error;
489 }
490 
HandlePayload(Message & aMessage,MessageInfo & aMessageInfo)491 void Udp::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo)
492 {
493     SocketHandle *socket;
494     SocketHandle *prev;
495 
496 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
497     {
498         const SocketHandle *socketsBegin, *socketsEnd;
499 
500         if (!aMessageInfo.IsHostInterface())
501         {
502             socketsBegin = mSockets.GetHead();
503             socketsEnd   = GetBackboneSockets();
504         }
505         else
506         {
507             socketsBegin = GetBackboneSockets();
508             socketsEnd   = nullptr;
509         }
510 
511         socket = mSockets.FindMatching(socketsBegin, socketsEnd, aMessageInfo, prev);
512     }
513 #else
514     socket = mSockets.FindMatching(aMessageInfo, prev);
515 #endif
516 
517     VerifyOrExit(socket != nullptr);
518 
519     aMessage.RemoveHeader(aMessage.GetOffset());
520     OT_ASSERT(aMessage.GetOffset() == 0);
521     socket->HandleUdpReceive(aMessage, aMessageInfo);
522 
523 exit:
524     return;
525 }
526 
IsPortInUse(uint16_t aPort) const527 bool Udp::IsPortInUse(uint16_t aPort) const
528 {
529     bool found = false;
530 
531     for (const SocketHandle &socket : mSockets)
532     {
533         if (socket.GetSockName().GetPort() == aPort)
534         {
535             found = true;
536             break;
537         }
538     }
539 
540     return found;
541 }
542 
ShouldUsePlatformUdp(uint16_t aPort) const543 bool Udp::ShouldUsePlatformUdp(uint16_t aPort) const
544 {
545     return (aPort != Mle::kUdpPort && aPort != Tmf::kUdpPort
546 #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE && !OPENTHREAD_CONFIG_DNSSD_SERVER_BIND_UNSPECIFIED_NETIF
547             && aPort != Dns::ServiceDiscovery::Server::kPort
548 #endif
549 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
550             && aPort != Get<MeshCoP::BorderAgent>().GetUdpProxyPort()
551 #endif
552 #if OPENTHREAD_FTD
553             && aPort != Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort()
554 #endif
555     );
556 }
557 
558 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
ShouldUsePlatformUdp(const Udp::SocketHandle & aSocket) const559 bool Udp::ShouldUsePlatformUdp(const Udp::SocketHandle &aSocket) const
560 {
561     return (ShouldUsePlatformUdp(aSocket.mSockName.mPort)
562 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
563             || IsBackboneSocket(aSocket)
564 #endif
565     );
566 }
567 #endif // OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
568 
569 } // namespace Ip6
570 } // namespace ot
571