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