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