1 /*
2 * Copyright (c) 2018, 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 * @brief
32 * This file includes the platform UDP driver.
33 */
34
35 #ifdef __APPLE__
36 #define __APPLE_USE_RFC_3542
37 #endif
38
39 #include "openthread-posix-config.h"
40 #include "platform-posix.h"
41
42 #include <arpa/inet.h>
43 #include <assert.h>
44 #include <net/if.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <sys/select.h>
49 #include <unistd.h>
50
51 #include <openthread/udp.h>
52 #include <openthread/platform/udp.h>
53
54 #include "common/code_utils.hpp"
55
56 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
57
58 #include "posix/platform/ip6_utils.hpp"
59 #include "posix/platform/mainloop.hpp"
60 #include "posix/platform/udp.hpp"
61
62 using namespace ot::Posix::Ip6Utils;
63
64 namespace {
65
66 constexpr size_t kMaxUdpSize = 1280;
67
FdToHandle(int aFd)68 void *FdToHandle(int aFd) { return reinterpret_cast<void *>(aFd); }
69
FdFromHandle(void * aHandle)70 int FdFromHandle(void *aHandle) { return static_cast<int>(reinterpret_cast<long>(aHandle)); }
71
transmitPacket(int aFd,uint8_t * aPayload,uint16_t aLength,const otMessageInfo & aMessageInfo)72 otError transmitPacket(int aFd, uint8_t *aPayload, uint16_t aLength, const otMessageInfo &aMessageInfo)
73 {
74 #ifdef __APPLE__
75 // use fixed value for CMSG_SPACE is not a constant expression on macOS
76 constexpr size_t kBufferSize = 128;
77 #else
78 constexpr size_t kBufferSize = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
79 #endif
80 struct sockaddr_in6 peerAddr;
81 uint8_t control[kBufferSize];
82 size_t controlLength = 0;
83 struct iovec iov;
84 struct msghdr msg;
85 struct cmsghdr *cmsg;
86 ssize_t rval;
87 otError error = OT_ERROR_NONE;
88
89 memset(&peerAddr, 0, sizeof(peerAddr));
90 peerAddr.sin6_port = htons(aMessageInfo.mPeerPort);
91 peerAddr.sin6_family = AF_INET6;
92 CopyIp6AddressTo(aMessageInfo.mPeerAddr, &peerAddr.sin6_addr);
93
94 if (IsIp6AddressLinkLocal(aMessageInfo.mPeerAddr) && !aMessageInfo.mIsHostInterface)
95 {
96 // sin6_scope_id only works for link local destinations
97 peerAddr.sin6_scope_id = gNetifIndex;
98 }
99
100 memset(control, 0, sizeof(control));
101
102 iov.iov_base = aPayload;
103 iov.iov_len = aLength;
104
105 msg.msg_name = &peerAddr;
106 msg.msg_namelen = sizeof(peerAddr);
107 msg.msg_control = control;
108 msg.msg_controllen = static_cast<decltype(msg.msg_controllen)>(sizeof(control));
109 msg.msg_iov = &iov;
110 msg.msg_iovlen = 1;
111 msg.msg_flags = 0;
112
113 {
114 int hopLimit = (aMessageInfo.mHopLimit ? aMessageInfo.mHopLimit : OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT);
115
116 cmsg = CMSG_FIRSTHDR(&msg);
117 cmsg->cmsg_level = IPPROTO_IPV6;
118 cmsg->cmsg_type = IPV6_HOPLIMIT;
119 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
120
121 memcpy(CMSG_DATA(cmsg), &hopLimit, sizeof(int));
122
123 controlLength += CMSG_SPACE(sizeof(int));
124 }
125
126 if (!IsIp6AddressMulticast(aMessageInfo.mSockAddr) && !IsIp6AddressUnspecified(aMessageInfo.mSockAddr))
127 {
128 struct in6_pktinfo pktinfo;
129
130 cmsg = CMSG_NXTHDR(&msg, cmsg);
131 cmsg->cmsg_level = IPPROTO_IPV6;
132 cmsg->cmsg_type = IPV6_PKTINFO;
133 cmsg->cmsg_len = CMSG_LEN(sizeof(pktinfo));
134
135 pktinfo.ipi6_ifindex = aMessageInfo.mIsHostInterface ? 0 : gNetifIndex;
136
137 CopyIp6AddressTo(aMessageInfo.mSockAddr, &pktinfo.ipi6_addr);
138 memcpy(CMSG_DATA(cmsg), &pktinfo, sizeof(pktinfo));
139
140 controlLength += CMSG_SPACE(sizeof(pktinfo));
141 }
142
143 #ifdef __APPLE__
144 msg.msg_controllen = static_cast<socklen_t>(controlLength);
145 #else
146 msg.msg_controllen = controlLength;
147 #endif
148
149 rval = sendmsg(aFd, &msg, 0);
150 VerifyOrExit(rval > 0, perror("sendmsg"));
151
152 exit:
153 // EINVAL happens when we shift from child to router and the
154 // interface address changes. Ask callers to try again later.
155 if (rval == -1)
156 {
157 error = (errno == EINVAL) ? OT_ERROR_INVALID_STATE : OT_ERROR_FAILED;
158 }
159
160 return error;
161 }
162
receivePacket(int aFd,uint8_t * aPayload,uint16_t & aLength,otMessageInfo & aMessageInfo)163 otError receivePacket(int aFd, uint8_t *aPayload, uint16_t &aLength, otMessageInfo &aMessageInfo)
164 {
165 struct sockaddr_in6 peerAddr;
166 uint8_t control[kMaxUdpSize];
167 struct iovec iov;
168 struct msghdr msg;
169 ssize_t rval;
170
171 iov.iov_base = aPayload;
172 iov.iov_len = aLength;
173
174 msg.msg_name = &peerAddr;
175 msg.msg_namelen = sizeof(peerAddr);
176 msg.msg_control = control;
177 msg.msg_controllen = sizeof(control);
178 msg.msg_iov = &iov;
179 msg.msg_iovlen = 1;
180 msg.msg_flags = 0;
181
182 rval = recvmsg(aFd, &msg, 0);
183 VerifyOrExit(rval > 0, perror("recvmsg"));
184 aLength = static_cast<uint16_t>(rval);
185
186 for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg))
187 {
188 if (cmsg->cmsg_level == IPPROTO_IPV6)
189 {
190 if (cmsg->cmsg_type == IPV6_HOPLIMIT)
191 {
192 int hoplimit;
193
194 memcpy(&hoplimit, CMSG_DATA(cmsg), sizeof(hoplimit));
195 aMessageInfo.mHopLimit = static_cast<uint8_t>(hoplimit);
196 }
197 else if (cmsg->cmsg_type == IPV6_PKTINFO)
198 {
199 struct in6_pktinfo pktinfo;
200
201 memcpy(&pktinfo, CMSG_DATA(cmsg), sizeof(pktinfo));
202
203 aMessageInfo.mIsHostInterface = (pktinfo.ipi6_ifindex != gNetifIndex);
204 ReadIp6AddressFrom(&pktinfo.ipi6_addr, aMessageInfo.mSockAddr);
205 }
206 }
207 }
208
209 aMessageInfo.mPeerPort = ntohs(peerAddr.sin6_port);
210 ReadIp6AddressFrom(&peerAddr.sin6_addr, aMessageInfo.mPeerAddr);
211
212 exit:
213 return rval > 0 ? OT_ERROR_NONE : OT_ERROR_FAILED;
214 }
215
216 } // namespace
217
otPlatUdpSocket(otUdpSocket * aUdpSocket)218 otError otPlatUdpSocket(otUdpSocket *aUdpSocket)
219 {
220 otError error = OT_ERROR_NONE;
221 int fd;
222
223 assert(aUdpSocket->mHandle == nullptr);
224
225 fd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, kSocketNonBlock);
226 VerifyOrExit(fd >= 0, error = OT_ERROR_FAILED);
227
228 aUdpSocket->mHandle = FdToHandle(fd);
229
230 exit:
231 return error;
232 }
233
otPlatUdpClose(otUdpSocket * aUdpSocket)234 otError otPlatUdpClose(otUdpSocket *aUdpSocket)
235 {
236 otError error = OT_ERROR_NONE;
237 int fd;
238
239 // Only call `close()` on platform UDP sockets.
240 // Platform UDP sockets always have valid `mHandle` upon creation.
241 VerifyOrExit(aUdpSocket->mHandle != nullptr);
242
243 fd = FdFromHandle(aUdpSocket->mHandle);
244 VerifyOrExit(0 == close(fd), error = OT_ERROR_FAILED);
245
246 aUdpSocket->mHandle = nullptr;
247
248 exit:
249 return error;
250 }
251
otPlatUdpBind(otUdpSocket * aUdpSocket)252 otError otPlatUdpBind(otUdpSocket *aUdpSocket)
253 {
254 otError error = OT_ERROR_NONE;
255 int fd;
256
257 assert(gNetifIndex != 0);
258 assert(aUdpSocket->mHandle != nullptr);
259 VerifyOrExit(aUdpSocket->mSockName.mPort != 0, error = OT_ERROR_INVALID_ARGS);
260 fd = FdFromHandle(aUdpSocket->mHandle);
261
262 {
263 struct sockaddr_in6 sin6;
264
265 memset(&sin6, 0, sizeof(struct sockaddr_in6));
266 sin6.sin6_port = htons(aUdpSocket->mSockName.mPort);
267 sin6.sin6_family = AF_INET6;
268 CopyIp6AddressTo(aUdpSocket->mSockName.mAddress, &sin6.sin6_addr);
269
270 VerifyOrExit(0 == bind(fd, reinterpret_cast<struct sockaddr *>(&sin6), sizeof(sin6)), error = OT_ERROR_FAILED);
271 }
272
273 {
274 int on = 1;
275 VerifyOrExit(0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on)), error = OT_ERROR_FAILED);
276 VerifyOrExit(0 == setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)), error = OT_ERROR_FAILED);
277 }
278
279 exit:
280 if (error == OT_ERROR_FAILED)
281 {
282 ot::Posix::Udp::LogCrit("Failed to bind UDP socket: %s", strerror(errno));
283 }
284
285 return error;
286 }
287
otPlatUdpBindToNetif(otUdpSocket * aUdpSocket,otNetifIdentifier aNetifIdentifier)288 otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifIdentifier)
289 {
290 otError error = OT_ERROR_NONE;
291 int fd = FdFromHandle(aUdpSocket->mHandle);
292 int one = 1;
293 int zero = 0;
294
295 switch (aNetifIdentifier)
296 {
297 case OT_NETIF_UNSPECIFIED:
298 {
299 #ifdef __linux__
300 VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, nullptr, 0) == 0, error = OT_ERROR_FAILED);
301 #else // __NetBSD__ || __FreeBSD__ || __APPLE__
302 unsigned int netifIndex = 0;
303 VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &netifIndex, sizeof(netifIndex)) == 0,
304 error = OT_ERROR_FAILED);
305 #endif // __linux__
306 break;
307 }
308 case OT_NETIF_THREAD_HOST:
309 {
310 #ifdef __linux__
311 VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &gNetifName, strlen(gNetifName)) == 0,
312 error = OT_ERROR_FAILED);
313 #else // __NetBSD__ || __FreeBSD__ || __APPLE__
314 VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &gNetifIndex, sizeof(gNetifIndex)) == 0,
315 error = OT_ERROR_FAILED);
316 #endif // __linux__
317 break;
318 }
319 case OT_NETIF_BACKBONE:
320 {
321 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
322 if (otSysGetInfraNetifName() == nullptr || otSysGetInfraNetifName()[0] == '\0')
323 {
324 ot::Posix::Udp::LogWarn("No backbone interface given, %s fails.", __func__);
325 ExitNow(error = OT_ERROR_INVALID_ARGS);
326 }
327 #ifdef __linux__
328 VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, otSysGetInfraNetifName(),
329 strlen(otSysGetInfraNetifName())) == 0,
330 error = OT_ERROR_FAILED);
331 #else // __NetBSD__ || __FreeBSD__ || __APPLE__
332 uint32_t backboneNetifIndex = otSysGetInfraNetifIndex();
333 VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &backboneNetifIndex, sizeof(backboneNetifIndex)) == 0,
334 error = OT_ERROR_FAILED);
335 #endif // __linux__
336 #else
337 ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
338 #endif
339 VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&one, sizeof(one)) == 0,
340 error = OT_ERROR_FAILED);
341
342 break;
343 }
344
345 case OT_NETIF_THREAD_INTERNAL:
346 assert(false);
347 }
348
349 VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) == 0, error = OT_ERROR_FAILED);
350
351 exit:
352 return error;
353 }
354
otPlatUdpConnect(otUdpSocket * aUdpSocket)355 otError otPlatUdpConnect(otUdpSocket *aUdpSocket)
356 {
357 otError error = OT_ERROR_NONE;
358 struct sockaddr_in6 sin6;
359 int fd;
360 bool isDisconnect = IsIp6AddressUnspecified(aUdpSocket->mPeerName.mAddress) && (aUdpSocket->mPeerName.mPort == 0);
361
362 VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS);
363
364 fd = FdFromHandle(aUdpSocket->mHandle);
365
366 memset(&sin6, 0, sizeof(struct sockaddr_in6));
367 sin6.sin6_port = htons(aUdpSocket->mPeerName.mPort);
368
369 if (!isDisconnect)
370 {
371 sin6.sin6_family = AF_INET6;
372 CopyIp6AddressTo(aUdpSocket->mPeerName.mAddress, &sin6.sin6_addr);
373 }
374 else
375 {
376 #ifdef __APPLE__
377 sin6.sin6_family = AF_UNSPEC;
378 #else
379 char netifName[IFNAMSIZ];
380 socklen_t len = sizeof(netifName);
381
382 if (getsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &netifName, &len) != 0)
383 {
384 ot::Posix::Udp::LogWarn("Failed to read socket bound device: %s", strerror(errno));
385 len = 0;
386 }
387
388 // There is a bug in linux that connecting to AF_UNSPEC does not disconnect.
389 // We create new socket to disconnect.
390 SuccessOrExit(error = otPlatUdpClose(aUdpSocket));
391 SuccessOrExit(error = otPlatUdpSocket(aUdpSocket));
392 SuccessOrExit(error = otPlatUdpBind(aUdpSocket));
393
394 if (len > 0 && netifName[0] != '\0')
395 {
396 fd = FdFromHandle(aUdpSocket->mHandle);
397 VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &netifName, len) == 0, {
398 ot::Posix::Udp::LogWarn("Failed to bind to device: %s", strerror(errno));
399 error = OT_ERROR_FAILED;
400 });
401 }
402
403 ExitNow();
404 #endif
405 }
406
407 if (connect(fd, reinterpret_cast<struct sockaddr *>(&sin6), sizeof(sin6)) != 0)
408 {
409 #ifdef __APPLE__
410 VerifyOrExit(errno == EAFNOSUPPORT && isDisconnect);
411 #endif
412 ot::Posix::Udp::LogWarn("Failed to connect to [%s]:%u: %s",
413 Ip6AddressString(&aUdpSocket->mPeerName.mAddress).AsCString(),
414 aUdpSocket->mPeerName.mPort, strerror(errno));
415 error = OT_ERROR_FAILED;
416 }
417
418 exit:
419 return error;
420 }
421
otPlatUdpSend(otUdpSocket * aUdpSocket,otMessage * aMessage,const otMessageInfo * aMessageInfo)422 otError otPlatUdpSend(otUdpSocket *aUdpSocket, otMessage *aMessage, const otMessageInfo *aMessageInfo)
423 {
424 otError error = OT_ERROR_NONE;
425 int fd;
426 uint16_t len;
427 uint8_t payload[kMaxUdpSize];
428
429 VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS);
430 fd = FdFromHandle(aUdpSocket->mHandle);
431
432 len = otMessageGetLength(aMessage);
433 VerifyOrExit(len == otMessageRead(aMessage, 0, payload, len), error = OT_ERROR_INVALID_ARGS);
434
435 if (aMessageInfo->mMulticastLoop)
436 {
437 int value = 1;
438
439 VerifyOrDie(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &value, sizeof(value)) == 0, OT_EXIT_ERROR_ERRNO);
440 }
441
442 error = transmitPacket(fd, payload, len, *aMessageInfo);
443
444 if (aMessageInfo->mMulticastLoop)
445 {
446 int value = 0;
447
448 VerifyOrDie(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &value, sizeof(value)) == 0, OT_EXIT_ERROR_ERRNO);
449 }
450
451 exit:
452 if (error == OT_ERROR_NONE)
453 {
454 otMessageFree(aMessage);
455 }
456
457 return error;
458 }
459
otPlatUdpJoinMulticastGroup(otUdpSocket * aUdpSocket,otNetifIdentifier aNetifIdentifier,const otIp6Address * aAddress)460 otError otPlatUdpJoinMulticastGroup(otUdpSocket *aUdpSocket,
461 otNetifIdentifier aNetifIdentifier,
462 const otIp6Address *aAddress)
463 {
464 otError error = OT_ERROR_NONE;
465 struct ipv6_mreq mreq;
466 int fd;
467
468 VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS);
469 fd = FdFromHandle(aUdpSocket->mHandle);
470
471 CopyIp6AddressTo(*aAddress, &mreq.ipv6mr_multiaddr);
472
473 switch (aNetifIdentifier)
474 {
475 case OT_NETIF_UNSPECIFIED:
476 break;
477 case OT_NETIF_THREAD_HOST:
478 mreq.ipv6mr_interface = gNetifIndex;
479 break;
480 case OT_NETIF_BACKBONE:
481 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
482 mreq.ipv6mr_interface = otSysGetInfraNetifIndex();
483 #else
484 ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
485 #endif
486 break;
487 case OT_NETIF_THREAD_INTERNAL:
488 assert(false);
489 }
490
491 VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == 0 || errno == EADDRINUSE,
492 error = OT_ERROR_FAILED);
493
494 exit:
495 if (error != OT_ERROR_NONE)
496 {
497 ot::Posix::Udp::LogCrit("IPV6_JOIN_GROUP failed: %s", strerror(errno));
498 }
499
500 return error;
501 }
502
otPlatUdpLeaveMulticastGroup(otUdpSocket * aUdpSocket,otNetifIdentifier aNetifIdentifier,const otIp6Address * aAddress)503 otError otPlatUdpLeaveMulticastGroup(otUdpSocket *aUdpSocket,
504 otNetifIdentifier aNetifIdentifier,
505 const otIp6Address *aAddress)
506 {
507 otError error = OT_ERROR_NONE;
508 struct ipv6_mreq mreq;
509 int fd;
510
511 VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS);
512 fd = FdFromHandle(aUdpSocket->mHandle);
513
514 CopyIp6AddressTo(*aAddress, &mreq.ipv6mr_multiaddr);
515
516 switch (aNetifIdentifier)
517 {
518 case OT_NETIF_UNSPECIFIED:
519 break;
520 case OT_NETIF_THREAD_HOST:
521 mreq.ipv6mr_interface = gNetifIndex;
522 break;
523 case OT_NETIF_BACKBONE:
524 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
525 mreq.ipv6mr_interface = otSysGetInfraNetifIndex();
526 #else
527 ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
528 #endif
529 break;
530
531 case OT_NETIF_THREAD_INTERNAL:
532 assert(false);
533 }
534
535 VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) == 0 || errno == EADDRINUSE,
536 error = OT_ERROR_FAILED);
537
538 exit:
539 if (error != OT_ERROR_NONE)
540 {
541 ot::Posix::Udp::LogCrit("IPV6_LEAVE_GROUP failed: %s", strerror(errno));
542 }
543
544 return error;
545 }
546
547 namespace ot {
548 namespace Posix {
549
550 const char Udp::kLogModuleName[] = "Udp";
551
Update(otSysMainloopContext & aContext)552 void Udp::Update(otSysMainloopContext &aContext)
553 {
554 VerifyOrExit(gNetifIndex != 0);
555
556 for (otUdpSocket *socket = otUdpGetSockets(gInstance); socket != nullptr; socket = socket->mNext)
557 {
558 int fd;
559
560 if (socket->mHandle == nullptr)
561 {
562 continue;
563 }
564
565 fd = FdFromHandle(socket->mHandle);
566 FD_SET(fd, &aContext.mReadFdSet);
567
568 if (aContext.mMaxFd < fd)
569 {
570 aContext.mMaxFd = fd;
571 }
572 }
573
574 exit:
575 return;
576 }
577
Init(const char * aIfName)578 void Udp::Init(const char *aIfName)
579 {
580 if (aIfName == nullptr)
581 {
582 DieNow(OT_EXIT_INVALID_ARGUMENTS);
583 }
584
585 if (aIfName != gNetifName)
586 {
587 VerifyOrDie(strlen(aIfName) < sizeof(gNetifName) - 1, OT_EXIT_INVALID_ARGUMENTS);
588 assert(gNetifIndex == 0);
589 strcpy(gNetifName, aIfName);
590 gNetifIndex = if_nametoindex(gNetifName);
591 VerifyOrDie(gNetifIndex != 0, OT_EXIT_ERROR_ERRNO);
592 }
593
594 assert(gNetifIndex != 0);
595 }
596
SetUp(void)597 void Udp::SetUp(void) { Mainloop::Manager::Get().Add(*this); }
598
TearDown(void)599 void Udp::TearDown(void) { Mainloop::Manager::Get().Remove(*this); }
600
Deinit(void)601 void Udp::Deinit(void)
602 {
603 // TODO All platform sockets should be closed
604 }
605
Get(void)606 Udp &Udp::Get(void)
607 {
608 static Udp sInstance;
609
610 return sInstance;
611 }
612
Process(const otSysMainloopContext & aContext)613 void Udp::Process(const otSysMainloopContext &aContext)
614 {
615 otMessageSettings msgSettings = {false, OT_MESSAGE_PRIORITY_NORMAL};
616
617 for (otUdpSocket *socket = otUdpGetSockets(gInstance); socket != nullptr; socket = socket->mNext)
618 {
619 int fd = FdFromHandle(socket->mHandle);
620
621 if (fd > 0 && FD_ISSET(fd, &aContext.mReadFdSet))
622 {
623 otMessageInfo messageInfo;
624 otMessage *message = nullptr;
625 uint8_t payload[kMaxUdpSize];
626 uint16_t length = sizeof(payload);
627
628 memset(&messageInfo, 0, sizeof(messageInfo));
629 messageInfo.mSockPort = socket->mSockName.mPort;
630
631 if (OT_ERROR_NONE != receivePacket(fd, payload, length, messageInfo))
632 {
633 continue;
634 }
635
636 message = otUdpNewMessage(gInstance, &msgSettings);
637
638 if (message == nullptr)
639 {
640 continue;
641 }
642
643 if (otMessageAppend(message, payload, length) != OT_ERROR_NONE)
644 {
645 otMessageFree(message);
646 continue;
647 }
648
649 socket->mHandler(socket->mContext, message, &messageInfo);
650 otMessageFree(message);
651 // only process one socket a time
652 break;
653 }
654 }
655
656 return;
657 }
658
659 } // namespace Posix
660 } // namespace ot
661 #endif // #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
662