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