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