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