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