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 * This file implements the platform network on Linux.
32*cfb92d14SAndroid Build Coastguard Worker */
33*cfb92d14SAndroid Build Coastguard Worker
34*cfb92d14SAndroid Build Coastguard Worker #include "openthread-posix-config.h"
35*cfb92d14SAndroid Build Coastguard Worker #include "platform-posix.h"
36*cfb92d14SAndroid Build Coastguard Worker
37*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__)
38*cfb92d14SAndroid Build Coastguard Worker
39*cfb92d14SAndroid Build Coastguard Worker // NOTE: on mac OS, the utun driver is present on the system and "works" --
40*cfb92d14SAndroid Build Coastguard Worker // but in a limited way. In particular, the mac OS "utun" driver is marked IFF_POINTTOPOINT,
41*cfb92d14SAndroid Build Coastguard Worker // and you cannot clear that flag with SIOCSIFFLAGS (it's part of the IFF_CANTCHANGE definition
42*cfb92d14SAndroid Build Coastguard Worker // in xnu's net/if.h [but removed from the mac OS SDK net/if.h]). And unfortunately, mac OS's
43*cfb92d14SAndroid Build Coastguard Worker // build of mDNSResponder won't allow for mDNS over an interface marked IFF_POINTTOPOINT
44*cfb92d14SAndroid Build Coastguard Worker // (see comments near definition of MulticastInterface in mDNSMacOSX.c for the bogus reasoning).
45*cfb92d14SAndroid Build Coastguard Worker //
46*cfb92d14SAndroid Build Coastguard Worker // There is an alternative. An open-source tuntap kernel extension is available here:
47*cfb92d14SAndroid Build Coastguard Worker //
48*cfb92d14SAndroid Build Coastguard Worker // <http://tuntaposx.sourceforge.net>
49*cfb92d14SAndroid Build Coastguard Worker // <https://sourceforge.net/p/tuntaposx/code/ci/master/tree/>
50*cfb92d14SAndroid Build Coastguard Worker //
51*cfb92d14SAndroid Build Coastguard Worker // and can be installed via homebrew here:
52*cfb92d14SAndroid Build Coastguard Worker //
53*cfb92d14SAndroid Build Coastguard Worker // <https://formulae.brew.sh/cask/tuntap>
54*cfb92d14SAndroid Build Coastguard Worker //
55*cfb92d14SAndroid Build Coastguard Worker // Building from source and installing isn't trivial, and it's
56*cfb92d14SAndroid Build Coastguard Worker // not getting easier (https://forums.developer.apple.com/thread/79590).
57*cfb92d14SAndroid Build Coastguard Worker //
58*cfb92d14SAndroid Build Coastguard Worker // If you want mDNS support, then you can't use Apple utun. I use the non-Apple driver
59*cfb92d14SAndroid Build Coastguard Worker // pretty much exclusively, because mDNS is a requirement.
60*cfb92d14SAndroid Build Coastguard Worker
61*cfb92d14SAndroid Build Coastguard Worker #if !(defined(OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION) && \
62*cfb92d14SAndroid Build Coastguard Worker ((OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN) || \
63*cfb92d14SAndroid Build Coastguard Worker (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN)))
64*cfb92d14SAndroid Build Coastguard Worker #error "Unexpected tunnel driver selection"
65*cfb92d14SAndroid Build Coastguard Worker #endif
66*cfb92d14SAndroid Build Coastguard Worker
67*cfb92d14SAndroid Build Coastguard Worker #endif // defined(__APPLE__)
68*cfb92d14SAndroid Build Coastguard Worker
69*cfb92d14SAndroid Build Coastguard Worker #include <arpa/inet.h>
70*cfb92d14SAndroid Build Coastguard Worker #include <assert.h>
71*cfb92d14SAndroid Build Coastguard Worker #include <errno.h>
72*cfb92d14SAndroid Build Coastguard Worker #include <fcntl.h>
73*cfb92d14SAndroid Build Coastguard Worker #include <ifaddrs.h>
74*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
75*cfb92d14SAndroid Build Coastguard Worker #include <linux/if_link.h>
76*cfb92d14SAndroid Build Coastguard Worker #include <linux/if_tun.h>
77*cfb92d14SAndroid Build Coastguard Worker #include <linux/netlink.h>
78*cfb92d14SAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
79*cfb92d14SAndroid Build Coastguard Worker #endif // __linux__
80*cfb92d14SAndroid Build Coastguard Worker #include <math.h>
81*cfb92d14SAndroid Build Coastguard Worker #include <net/if.h>
82*cfb92d14SAndroid Build Coastguard Worker #include <net/if_arp.h>
83*cfb92d14SAndroid Build Coastguard Worker #include <stdio.h>
84*cfb92d14SAndroid Build Coastguard Worker #include <string.h>
85*cfb92d14SAndroid Build Coastguard Worker #include <sys/ioctl.h>
86*cfb92d14SAndroid Build Coastguard Worker #include <sys/select.h>
87*cfb92d14SAndroid Build Coastguard Worker #include <sys/socket.h>
88*cfb92d14SAndroid Build Coastguard Worker #include <sys/stat.h>
89*cfb92d14SAndroid Build Coastguard Worker #include <sys/types.h>
90*cfb92d14SAndroid Build Coastguard Worker #include <unistd.h>
91*cfb92d14SAndroid Build Coastguard Worker
92*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
93*cfb92d14SAndroid Build Coastguard Worker #include <netinet/in.h>
94*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__FreeBSD__)
95*cfb92d14SAndroid Build Coastguard Worker #include <net/if_var.h>
96*cfb92d14SAndroid Build Coastguard Worker #endif // defined(__APPLE__) || defined(__FreeBSD__)
97*cfb92d14SAndroid Build Coastguard Worker #include <net/route.h>
98*cfb92d14SAndroid Build Coastguard Worker #include <netinet6/in6_var.h>
99*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__FreeBSD__)
100*cfb92d14SAndroid Build Coastguard Worker // the prf_ra structure is defined inside another structure (in6_prflags), and C++
101*cfb92d14SAndroid Build Coastguard Worker // treats that as out of scope if another structure tries to use it -- this (slightly gross)
102*cfb92d14SAndroid Build Coastguard Worker // workaround makes us dependent on our definition remaining in sync (at least the size of it),
103*cfb92d14SAndroid Build Coastguard Worker // so we add a compile-time check that will fail if the SDK ever changes
104*cfb92d14SAndroid Build Coastguard Worker //
105*cfb92d14SAndroid Build Coastguard Worker // our definition of the struct:
106*cfb92d14SAndroid Build Coastguard Worker struct prf_ra
107*cfb92d14SAndroid Build Coastguard Worker {
108*cfb92d14SAndroid Build Coastguard Worker u_char onlink : 1;
109*cfb92d14SAndroid Build Coastguard Worker u_char autonomous : 1;
110*cfb92d14SAndroid Build Coastguard Worker u_char reserved : 6;
111*cfb92d14SAndroid Build Coastguard Worker } prf_ra;
112*cfb92d14SAndroid Build Coastguard Worker // object that contains the SDK's version of the structure:
113*cfb92d14SAndroid Build Coastguard Worker struct in6_prflags compile_time_check_prflags;
114*cfb92d14SAndroid Build Coastguard Worker // compile time check to make sure they're the same size:
115*cfb92d14SAndroid Build Coastguard Worker extern int
116*cfb92d14SAndroid Build Coastguard Worker compile_time_check_struct_prf_ra[(sizeof(struct prf_ra) == sizeof(compile_time_check_prflags.prf_ra)) ? 1 : -1];
117*cfb92d14SAndroid Build Coastguard Worker #endif
118*cfb92d14SAndroid Build Coastguard Worker #include <net/if_dl.h> // struct sockaddr_dl
119*cfb92d14SAndroid Build Coastguard Worker #include <netinet6/nd6.h> // ND6_INFINITE_LIFETIME
120*cfb92d14SAndroid Build Coastguard Worker
121*cfb92d14SAndroid Build Coastguard Worker #ifdef __APPLE__
122*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN
123*cfb92d14SAndroid Build Coastguard Worker #include <net/if_utun.h>
124*cfb92d14SAndroid Build Coastguard Worker #endif
125*cfb92d14SAndroid Build Coastguard Worker
126*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN
127*cfb92d14SAndroid Build Coastguard Worker #include <sys/ioccom.h>
128*cfb92d14SAndroid Build Coastguard Worker // FIX ME: include the tun_ioctl.h file (challenging, as it's location depends on where the developer puts it)
129*cfb92d14SAndroid Build Coastguard Worker #define TUNSIFHEAD _IOW('t', 96, int)
130*cfb92d14SAndroid Build Coastguard Worker #define TUNGIFHEAD _IOR('t', 97, int)
131*cfb92d14SAndroid Build Coastguard Worker #endif
132*cfb92d14SAndroid Build Coastguard Worker
133*cfb92d14SAndroid Build Coastguard Worker #include <sys/kern_control.h>
134*cfb92d14SAndroid Build Coastguard Worker #endif // defined(__APPLE__)
135*cfb92d14SAndroid Build Coastguard Worker
136*cfb92d14SAndroid Build Coastguard Worker #if defined(__NetBSD__) || defined(__FreeBSD__)
137*cfb92d14SAndroid Build Coastguard Worker #include <net/if_tun.h>
138*cfb92d14SAndroid Build Coastguard Worker #endif // defined(__NetBSD__) || defined(__FreeBSD__)
139*cfb92d14SAndroid Build Coastguard Worker
140*cfb92d14SAndroid Build Coastguard Worker #endif // defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
141*cfb92d14SAndroid Build Coastguard Worker
142*cfb92d14SAndroid Build Coastguard Worker #include <openthread/border_router.h>
143*cfb92d14SAndroid Build Coastguard Worker #include <openthread/icmp6.h>
144*cfb92d14SAndroid Build Coastguard Worker #include <openthread/instance.h>
145*cfb92d14SAndroid Build Coastguard Worker #include <openthread/ip6.h>
146*cfb92d14SAndroid Build Coastguard Worker #include <openthread/logging.h>
147*cfb92d14SAndroid Build Coastguard Worker #include <openthread/message.h>
148*cfb92d14SAndroid Build Coastguard Worker #include <openthread/nat64.h>
149*cfb92d14SAndroid Build Coastguard Worker #include <openthread/netdata.h>
150*cfb92d14SAndroid Build Coastguard Worker #include <openthread/thread.h>
151*cfb92d14SAndroid Build Coastguard Worker #include <openthread/platform/border_routing.h>
152*cfb92d14SAndroid Build Coastguard Worker #include <openthread/platform/misc.h>
153*cfb92d14SAndroid Build Coastguard Worker
154*cfb92d14SAndroid Build Coastguard Worker #include "ip6_utils.hpp"
155*cfb92d14SAndroid Build Coastguard Worker #include "logger.hpp"
156*cfb92d14SAndroid Build Coastguard Worker #include "resolver.hpp"
157*cfb92d14SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
158*cfb92d14SAndroid Build Coastguard Worker
159*cfb92d14SAndroid Build Coastguard Worker unsigned int gNetifIndex = 0;
160*cfb92d14SAndroid Build Coastguard Worker char gNetifName[IFNAMSIZ];
161*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
162*cfb92d14SAndroid Build Coastguard Worker static otIp4Cidr sActiveNat64Cidr;
163*cfb92d14SAndroid Build Coastguard Worker #endif
164*cfb92d14SAndroid Build Coastguard Worker
otSysGetThreadNetifName(void)165*cfb92d14SAndroid Build Coastguard Worker const char *otSysGetThreadNetifName(void) { return gNetifName; }
166*cfb92d14SAndroid Build Coastguard Worker
otSysGetThreadNetifIndex(void)167*cfb92d14SAndroid Build Coastguard Worker unsigned int otSysGetThreadNetifIndex(void) { return gNetifIndex; }
168*cfb92d14SAndroid Build Coastguard Worker
169*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
170*cfb92d14SAndroid Build Coastguard Worker
171*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
172*cfb92d14SAndroid Build Coastguard Worker #include "firewall.hpp"
173*cfb92d14SAndroid Build Coastguard Worker #endif
174*cfb92d14SAndroid Build Coastguard Worker
175*cfb92d14SAndroid Build Coastguard Worker using namespace ot::Posix::Ip6Utils;
176*cfb92d14SAndroid Build Coastguard Worker
177*cfb92d14SAndroid Build Coastguard Worker #ifndef OPENTHREAD_POSIX_TUN_DEVICE
178*cfb92d14SAndroid Build Coastguard Worker
179*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
180*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_TUN_DEVICE "/dev/net/tun"
181*cfb92d14SAndroid Build Coastguard Worker #elif defined(__NetBSD__) || defined(__FreeBSD__)
182*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_TUN_DEVICE "/dev/tun0"
183*cfb92d14SAndroid Build Coastguard Worker #elif defined(__APPLE__)
184*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN
185*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_TUN_DEVICE // not used - calculated dynamically
186*cfb92d14SAndroid Build Coastguard Worker #elif OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN
187*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_TUN_DEVICE "/dev/tun0"
188*cfb92d14SAndroid Build Coastguard Worker #endif
189*cfb92d14SAndroid Build Coastguard Worker #else
190*cfb92d14SAndroid Build Coastguard Worker // good luck -- untested platform...
191*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_TUN_DEVICE "/dev/net/tun"
192*cfb92d14SAndroid Build Coastguard Worker #endif
193*cfb92d14SAndroid Build Coastguard Worker
194*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_POSIX_TUN_DEVICE
195*cfb92d14SAndroid Build Coastguard Worker
196*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
197*cfb92d14SAndroid Build Coastguard Worker static uint32_t sNetlinkSequence = 0; ///< Netlink message sequence.
198*cfb92d14SAndroid Build Coastguard Worker #endif
199*cfb92d14SAndroid Build Coastguard Worker
200*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && defined(__linux__)
201*cfb92d14SAndroid Build Coastguard Worker static constexpr uint32_t kOmrRoutesPriority = OPENTHREAD_POSIX_CONFIG_OMR_ROUTES_PRIORITY;
202*cfb92d14SAndroid Build Coastguard Worker static constexpr uint8_t kMaxOmrRoutesNum = OPENTHREAD_POSIX_CONFIG_MAX_OMR_ROUTES_NUM;
203*cfb92d14SAndroid Build Coastguard Worker static uint8_t sAddedOmrRoutesNum = 0;
204*cfb92d14SAndroid Build Coastguard Worker static otIp6Prefix sAddedOmrRoutes[kMaxOmrRoutesNum];
205*cfb92d14SAndroid Build Coastguard Worker #endif
206*cfb92d14SAndroid Build Coastguard Worker
207*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && defined(__linux__)
208*cfb92d14SAndroid Build Coastguard Worker static constexpr uint32_t kExternalRoutePriority = OPENTHREAD_POSIX_CONFIG_EXTERNAL_ROUTE_PRIORITY;
209*cfb92d14SAndroid Build Coastguard Worker static constexpr uint8_t kMaxExternalRoutesNum = OPENTHREAD_POSIX_CONFIG_MAX_EXTERNAL_ROUTE_NUM;
210*cfb92d14SAndroid Build Coastguard Worker static uint8_t sAddedExternalRoutesNum = 0;
211*cfb92d14SAndroid Build Coastguard Worker static otIp6Prefix sAddedExternalRoutes[kMaxExternalRoutesNum];
212*cfb92d14SAndroid Build Coastguard Worker #endif
213*cfb92d14SAndroid Build Coastguard Worker
214*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
215*cfb92d14SAndroid Build Coastguard Worker static constexpr uint32_t kNat64RoutePriority = 100; ///< Priority for route to NAT64 CIDR, 100 means a high priority.
216*cfb92d14SAndroid Build Coastguard Worker #endif
217*cfb92d14SAndroid Build Coastguard Worker
218*cfb92d14SAndroid Build Coastguard Worker #if defined(RTM_NEWMADDR) || defined(__NetBSD__)
219*cfb92d14SAndroid Build Coastguard Worker // on some BSDs (mac OS, FreeBSD), we get RTM_NEWMADDR/RTM_DELMADDR messages, so we don't need to monitor using MLD
220*cfb92d14SAndroid Build Coastguard Worker // on NetBSD, MLD monitoring simply doesn't work
221*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_USE_MLD_MONITOR 0
222*cfb92d14SAndroid Build Coastguard Worker #else
223*cfb92d14SAndroid Build Coastguard Worker // on some platforms (Linux, but others might be made to work), we do not get information about multicast
224*cfb92d14SAndroid Build Coastguard Worker // group joining via AF_NETLINK or AF_ROUTE sockets. on those platform, we must listen for IPv6 ICMP
225*cfb92d14SAndroid Build Coastguard Worker // MLDv2 messages to know when multicast memberships change
226*cfb92d14SAndroid Build Coastguard Worker // https://stackoverflow.com/questions/37346289/using-netlink-is-it-possible-to-listen-whenever-multicast-group-membership-is-ch
227*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_USE_MLD_MONITOR 1
228*cfb92d14SAndroid Build Coastguard Worker #endif // defined(RTM_NEWMADDR) || defined(__NetBSD__)
229*cfb92d14SAndroid Build Coastguard Worker
230*cfb92d14SAndroid Build Coastguard Worker // some platforms (like NetBSD) do not have RTM_NEWMADDR/RTM_DELMADDR messages, and they ALSO lack
231*cfb92d14SAndroid Build Coastguard Worker // working MLDv2 support. for those platforms, we must tell the OpenThread interface to
232*cfb92d14SAndroid Build Coastguard Worker // pass ALL multicast packets up; the kernel's IPv6 will filter and drop those that have no listeners
233*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_MULTICAST_PROMISCUOUS_REQUIRED 0
234*cfb92d14SAndroid Build Coastguard Worker #if !OPENTHREAD_POSIX_USE_MLD_MONITOR
235*cfb92d14SAndroid Build Coastguard Worker #if defined(__NetBSD__)
236*cfb92d14SAndroid Build Coastguard Worker #undef OPENTHREAD_POSIX_MULTICAST_PROMISCUOUS_REQUIRED
237*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_MULTICAST_PROMISCUOUS_REQUIRED 1
238*cfb92d14SAndroid Build Coastguard Worker #endif
239*cfb92d14SAndroid Build Coastguard Worker #endif
240*cfb92d14SAndroid Build Coastguard Worker
241*cfb92d14SAndroid Build Coastguard Worker #if defined(__NetBSD__) || defined(__FreeBSD__)
242*cfb92d14SAndroid Build Coastguard Worker static otError destroyTunnel(void);
243*cfb92d14SAndroid Build Coastguard Worker #endif
244*cfb92d14SAndroid Build Coastguard Worker
245*cfb92d14SAndroid Build Coastguard Worker static int sTunFd = -1; ///< Used to exchange IPv6 packets.
246*cfb92d14SAndroid Build Coastguard Worker static int sIpFd = -1; ///< Used to manage IPv6 stack on Thread interface.
247*cfb92d14SAndroid Build Coastguard Worker static int sNetlinkFd = -1; ///< Used to receive netlink events.
248*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
249*cfb92d14SAndroid Build Coastguard Worker static int sMLDMonitorFd = -1; ///< Used to receive MLD events.
250*cfb92d14SAndroid Build Coastguard Worker #endif
251*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
252*cfb92d14SAndroid Build Coastguard Worker // ff02::16
253*cfb92d14SAndroid Build Coastguard Worker static const otIp6Address kMLDv2MulticastAddress = {
254*cfb92d14SAndroid Build Coastguard Worker {{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16}}};
255*cfb92d14SAndroid Build Coastguard Worker
256*cfb92d14SAndroid Build Coastguard Worker OT_TOOL_PACKED_BEGIN
257*cfb92d14SAndroid Build Coastguard Worker struct MLDv2Header
258*cfb92d14SAndroid Build Coastguard Worker {
259*cfb92d14SAndroid Build Coastguard Worker uint8_t mType;
260*cfb92d14SAndroid Build Coastguard Worker uint8_t _rsv0;
261*cfb92d14SAndroid Build Coastguard Worker uint16_t mChecksum;
262*cfb92d14SAndroid Build Coastguard Worker uint16_t _rsv1;
263*cfb92d14SAndroid Build Coastguard Worker uint16_t mNumRecords;
264*cfb92d14SAndroid Build Coastguard Worker } OT_TOOL_PACKED_END;
265*cfb92d14SAndroid Build Coastguard Worker
266*cfb92d14SAndroid Build Coastguard Worker OT_TOOL_PACKED_BEGIN
267*cfb92d14SAndroid Build Coastguard Worker struct MLDv2Record
268*cfb92d14SAndroid Build Coastguard Worker {
269*cfb92d14SAndroid Build Coastguard Worker uint8_t mRecordType;
270*cfb92d14SAndroid Build Coastguard Worker uint8_t mAuxDataLen;
271*cfb92d14SAndroid Build Coastguard Worker uint16_t mNumSources;
272*cfb92d14SAndroid Build Coastguard Worker struct in6_addr mMulticastAddress;
273*cfb92d14SAndroid Build Coastguard Worker } OT_TOOL_PACKED_END;
274*cfb92d14SAndroid Build Coastguard Worker
275*cfb92d14SAndroid Build Coastguard Worker enum
276*cfb92d14SAndroid Build Coastguard Worker {
277*cfb92d14SAndroid Build Coastguard Worker kICMPv6MLDv2Type = 143,
278*cfb92d14SAndroid Build Coastguard Worker kICMPv6MLDv2RecordChangeToExcludeType = 3,
279*cfb92d14SAndroid Build Coastguard Worker kICMPv6MLDv2RecordChangeToIncludeType = 4,
280*cfb92d14SAndroid Build Coastguard Worker };
281*cfb92d14SAndroid Build Coastguard Worker #endif
282*cfb92d14SAndroid Build Coastguard Worker
283*cfb92d14SAndroid Build Coastguard Worker static constexpr size_t kMaxIp6Size = OPENTHREAD_CONFIG_IP6_MAX_DATAGRAM_LENGTH;
284*cfb92d14SAndroid Build Coastguard Worker #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
285*cfb92d14SAndroid Build Coastguard Worker static bool sIsSyncingState = false;
286*cfb92d14SAndroid Build Coastguard Worker #endif
287*cfb92d14SAndroid Build Coastguard Worker
288*cfb92d14SAndroid Build Coastguard Worker #define OPENTHREAD_POSIX_LOG_TUN_PACKETS 0
289*cfb92d14SAndroid Build Coastguard Worker
290*cfb92d14SAndroid Build Coastguard Worker static const char kLogModuleName[] = "Netif";
291*cfb92d14SAndroid Build Coastguard Worker
LogCrit(const char * aFormat,...)292*cfb92d14SAndroid Build Coastguard Worker static void LogCrit(const char *aFormat, ...)
293*cfb92d14SAndroid Build Coastguard Worker {
294*cfb92d14SAndroid Build Coastguard Worker va_list args;
295*cfb92d14SAndroid Build Coastguard Worker
296*cfb92d14SAndroid Build Coastguard Worker va_start(args, aFormat);
297*cfb92d14SAndroid Build Coastguard Worker otLogPlatArgs(OT_LOG_LEVEL_CRIT, kLogModuleName, aFormat, args);
298*cfb92d14SAndroid Build Coastguard Worker va_end(args);
299*cfb92d14SAndroid Build Coastguard Worker }
300*cfb92d14SAndroid Build Coastguard Worker
LogWarn(const char * aFormat,...)301*cfb92d14SAndroid Build Coastguard Worker static void LogWarn(const char *aFormat, ...)
302*cfb92d14SAndroid Build Coastguard Worker {
303*cfb92d14SAndroid Build Coastguard Worker va_list args;
304*cfb92d14SAndroid Build Coastguard Worker
305*cfb92d14SAndroid Build Coastguard Worker va_start(args, aFormat);
306*cfb92d14SAndroid Build Coastguard Worker otLogPlatArgs(OT_LOG_LEVEL_WARN, kLogModuleName, aFormat, args);
307*cfb92d14SAndroid Build Coastguard Worker va_end(args);
308*cfb92d14SAndroid Build Coastguard Worker }
309*cfb92d14SAndroid Build Coastguard Worker
LogNote(const char * aFormat,...)310*cfb92d14SAndroid Build Coastguard Worker static void LogNote(const char *aFormat, ...)
311*cfb92d14SAndroid Build Coastguard Worker {
312*cfb92d14SAndroid Build Coastguard Worker va_list args;
313*cfb92d14SAndroid Build Coastguard Worker
314*cfb92d14SAndroid Build Coastguard Worker va_start(args, aFormat);
315*cfb92d14SAndroid Build Coastguard Worker otLogPlatArgs(OT_LOG_LEVEL_NOTE, kLogModuleName, aFormat, args);
316*cfb92d14SAndroid Build Coastguard Worker va_end(args);
317*cfb92d14SAndroid Build Coastguard Worker }
318*cfb92d14SAndroid Build Coastguard Worker
LogInfo(const char * aFormat,...)319*cfb92d14SAndroid Build Coastguard Worker static void LogInfo(const char *aFormat, ...)
320*cfb92d14SAndroid Build Coastguard Worker {
321*cfb92d14SAndroid Build Coastguard Worker va_list args;
322*cfb92d14SAndroid Build Coastguard Worker
323*cfb92d14SAndroid Build Coastguard Worker va_start(args, aFormat);
324*cfb92d14SAndroid Build Coastguard Worker otLogPlatArgs(OT_LOG_LEVEL_INFO, kLogModuleName, aFormat, args);
325*cfb92d14SAndroid Build Coastguard Worker va_end(args);
326*cfb92d14SAndroid Build Coastguard Worker }
327*cfb92d14SAndroid Build Coastguard Worker
LogDebg(const char * aFormat,...)328*cfb92d14SAndroid Build Coastguard Worker static void LogDebg(const char *aFormat, ...)
329*cfb92d14SAndroid Build Coastguard Worker {
330*cfb92d14SAndroid Build Coastguard Worker va_list args;
331*cfb92d14SAndroid Build Coastguard Worker
332*cfb92d14SAndroid Build Coastguard Worker va_start(args, aFormat);
333*cfb92d14SAndroid Build Coastguard Worker otLogPlatArgs(OT_LOG_LEVEL_DEBG, kLogModuleName, aFormat, args);
334*cfb92d14SAndroid Build Coastguard Worker va_end(args);
335*cfb92d14SAndroid Build Coastguard Worker }
336*cfb92d14SAndroid Build Coastguard Worker
337*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
338*cfb92d14SAndroid Build Coastguard Worker
339*cfb92d14SAndroid Build Coastguard Worker static const uint8_t kAllOnes[] = {
340*cfb92d14SAndroid Build Coastguard Worker 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
341*cfb92d14SAndroid Build Coastguard Worker };
342*cfb92d14SAndroid Build Coastguard Worker
343*cfb92d14SAndroid Build Coastguard Worker #define BITS_PER_BYTE 8
344*cfb92d14SAndroid Build Coastguard Worker #define MAX_PREFIX_LENGTH (OT_IP6_ADDRESS_SIZE * BITS_PER_BYTE)
345*cfb92d14SAndroid Build Coastguard Worker
CopyBits(uint8_t * aDst,const uint8_t * aSrc,uint8_t aNumBits)346*cfb92d14SAndroid Build Coastguard Worker static void CopyBits(uint8_t *aDst, const uint8_t *aSrc, uint8_t aNumBits)
347*cfb92d14SAndroid Build Coastguard Worker {
348*cfb92d14SAndroid Build Coastguard Worker // Copies `aNumBits` from `aSrc` into `aDst` handling
349*cfb92d14SAndroid Build Coastguard Worker // the case where `aNumBits` may not be a multiple of 8.
350*cfb92d14SAndroid Build Coastguard Worker // Leaves the remaining bits beyond `aNumBits` in `aDst`
351*cfb92d14SAndroid Build Coastguard Worker // unchanged.
352*cfb92d14SAndroid Build Coastguard Worker
353*cfb92d14SAndroid Build Coastguard Worker uint8_t numBytes = aNumBits / BITS_PER_BYTE;
354*cfb92d14SAndroid Build Coastguard Worker uint8_t extraBits = aNumBits % BITS_PER_BYTE;
355*cfb92d14SAndroid Build Coastguard Worker
356*cfb92d14SAndroid Build Coastguard Worker memcpy(aDst, aSrc, numBytes);
357*cfb92d14SAndroid Build Coastguard Worker
358*cfb92d14SAndroid Build Coastguard Worker if (extraBits > 0)
359*cfb92d14SAndroid Build Coastguard Worker {
360*cfb92d14SAndroid Build Coastguard Worker uint8_t mask = ((0x80 >> (extraBits - 1)) - 1);
361*cfb92d14SAndroid Build Coastguard Worker
362*cfb92d14SAndroid Build Coastguard Worker aDst[numBytes] &= mask;
363*cfb92d14SAndroid Build Coastguard Worker aDst[numBytes] |= (aSrc[numBytes] & ~mask);
364*cfb92d14SAndroid Build Coastguard Worker }
365*cfb92d14SAndroid Build Coastguard Worker }
366*cfb92d14SAndroid Build Coastguard Worker
InitNetaskWithPrefixLength(struct in6_addr * address,uint8_t prefixLen)367*cfb92d14SAndroid Build Coastguard Worker static void InitNetaskWithPrefixLength(struct in6_addr *address, uint8_t prefixLen)
368*cfb92d14SAndroid Build Coastguard Worker {
369*cfb92d14SAndroid Build Coastguard Worker otIp6Address addr;
370*cfb92d14SAndroid Build Coastguard Worker
371*cfb92d14SAndroid Build Coastguard Worker if (prefixLen > MAX_PREFIX_LENGTH)
372*cfb92d14SAndroid Build Coastguard Worker {
373*cfb92d14SAndroid Build Coastguard Worker prefixLen = MAX_PREFIX_LENGTH;
374*cfb92d14SAndroid Build Coastguard Worker }
375*cfb92d14SAndroid Build Coastguard Worker
376*cfb92d14SAndroid Build Coastguard Worker memset(&addr, 0, sizeof(otIp6Address));
377*cfb92d14SAndroid Build Coastguard Worker CopyBits(addr.mFields.m8, kAllOnes, prefixLen);
378*cfb92d14SAndroid Build Coastguard Worker CopyIp6AddressTo(addr, address);
379*cfb92d14SAndroid Build Coastguard Worker }
380*cfb92d14SAndroid Build Coastguard Worker
NetmaskToPrefixLength(const struct sockaddr_in6 * netmask)381*cfb92d14SAndroid Build Coastguard Worker static uint8_t NetmaskToPrefixLength(const struct sockaddr_in6 *netmask)
382*cfb92d14SAndroid Build Coastguard Worker {
383*cfb92d14SAndroid Build Coastguard Worker return otIp6PrefixMatch(reinterpret_cast<const otIp6Address *>(netmask->sin6_addr.s6_addr),
384*cfb92d14SAndroid Build Coastguard Worker reinterpret_cast<const otIp6Address *>(kAllOnes));
385*cfb92d14SAndroid Build Coastguard Worker }
386*cfb92d14SAndroid Build Coastguard Worker
387*cfb92d14SAndroid Build Coastguard Worker #endif // defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
388*cfb92d14SAndroid Build Coastguard Worker
389*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
390*cfb92d14SAndroid Build Coastguard Worker #pragma GCC diagnostic push
391*cfb92d14SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wcast-align"
392*cfb92d14SAndroid Build Coastguard Worker
AddRtAttr(struct nlmsghdr * aHeader,uint32_t aMaxLen,uint8_t aType,const void * aData,uint8_t aLen)393*cfb92d14SAndroid Build Coastguard Worker static struct rtattr *AddRtAttr(struct nlmsghdr *aHeader,
394*cfb92d14SAndroid Build Coastguard Worker uint32_t aMaxLen,
395*cfb92d14SAndroid Build Coastguard Worker uint8_t aType,
396*cfb92d14SAndroid Build Coastguard Worker const void *aData,
397*cfb92d14SAndroid Build Coastguard Worker uint8_t aLen)
398*cfb92d14SAndroid Build Coastguard Worker {
399*cfb92d14SAndroid Build Coastguard Worker uint8_t len = RTA_LENGTH(aLen);
400*cfb92d14SAndroid Build Coastguard Worker struct rtattr *rta;
401*cfb92d14SAndroid Build Coastguard Worker
402*cfb92d14SAndroid Build Coastguard Worker assert(NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len) <= aMaxLen);
403*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aMaxLen);
404*cfb92d14SAndroid Build Coastguard Worker
405*cfb92d14SAndroid Build Coastguard Worker rta = (struct rtattr *)((char *)(aHeader) + NLMSG_ALIGN((aHeader)->nlmsg_len));
406*cfb92d14SAndroid Build Coastguard Worker rta->rta_type = aType;
407*cfb92d14SAndroid Build Coastguard Worker rta->rta_len = len;
408*cfb92d14SAndroid Build Coastguard Worker if (aLen)
409*cfb92d14SAndroid Build Coastguard Worker {
410*cfb92d14SAndroid Build Coastguard Worker memcpy(RTA_DATA(rta), aData, aLen);
411*cfb92d14SAndroid Build Coastguard Worker }
412*cfb92d14SAndroid Build Coastguard Worker aHeader->nlmsg_len = NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len);
413*cfb92d14SAndroid Build Coastguard Worker
414*cfb92d14SAndroid Build Coastguard Worker return rta;
415*cfb92d14SAndroid Build Coastguard Worker }
416*cfb92d14SAndroid Build Coastguard Worker
AddRtAttrUint32(struct nlmsghdr * aHeader,uint32_t aMaxLen,uint8_t aType,uint32_t aData)417*cfb92d14SAndroid Build Coastguard Worker void AddRtAttrUint32(struct nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, uint32_t aData)
418*cfb92d14SAndroid Build Coastguard Worker {
419*cfb92d14SAndroid Build Coastguard Worker AddRtAttr(aHeader, aMaxLen, aType, &aData, sizeof(aData));
420*cfb92d14SAndroid Build Coastguard Worker }
421*cfb92d14SAndroid Build Coastguard Worker
422*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
IsOmrAddress(otInstance * aInstance,const otIp6AddressInfo & aAddressInfo)423*cfb92d14SAndroid Build Coastguard Worker static bool IsOmrAddress(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo)
424*cfb92d14SAndroid Build Coastguard Worker {
425*cfb92d14SAndroid Build Coastguard Worker otIp6Prefix addressPrefix{*aAddressInfo.mAddress, aAddressInfo.mPrefixLength};
426*cfb92d14SAndroid Build Coastguard Worker
427*cfb92d14SAndroid Build Coastguard Worker return otNetDataContainsOmrPrefix(aInstance, &addressPrefix);
428*cfb92d14SAndroid Build Coastguard Worker }
429*cfb92d14SAndroid Build Coastguard Worker #endif
430*cfb92d14SAndroid Build Coastguard Worker
UpdateUnicastLinux(otInstance * aInstance,const otIp6AddressInfo & aAddressInfo,bool aIsAdded)431*cfb92d14SAndroid Build Coastguard Worker static void UpdateUnicastLinux(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo, bool aIsAdded)
432*cfb92d14SAndroid Build Coastguard Worker {
433*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aInstance);
434*cfb92d14SAndroid Build Coastguard Worker
435*cfb92d14SAndroid Build Coastguard Worker struct
436*cfb92d14SAndroid Build Coastguard Worker {
437*cfb92d14SAndroid Build Coastguard Worker struct nlmsghdr nh;
438*cfb92d14SAndroid Build Coastguard Worker struct ifaddrmsg ifa;
439*cfb92d14SAndroid Build Coastguard Worker char buf[512];
440*cfb92d14SAndroid Build Coastguard Worker } req;
441*cfb92d14SAndroid Build Coastguard Worker
442*cfb92d14SAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
443*cfb92d14SAndroid Build Coastguard Worker
444*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
445*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (aIsAdded ? (NLM_F_CREATE | NLM_F_EXCL) : 0);
446*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_type = aIsAdded ? RTM_NEWADDR : RTM_DELADDR;
447*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_pid = 0;
448*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_seq = ++sNetlinkSequence;
449*cfb92d14SAndroid Build Coastguard Worker
450*cfb92d14SAndroid Build Coastguard Worker req.ifa.ifa_family = AF_INET6;
451*cfb92d14SAndroid Build Coastguard Worker req.ifa.ifa_prefixlen = aAddressInfo.mPrefixLength;
452*cfb92d14SAndroid Build Coastguard Worker req.ifa.ifa_flags = IFA_F_NODAD;
453*cfb92d14SAndroid Build Coastguard Worker req.ifa.ifa_scope = aAddressInfo.mScope;
454*cfb92d14SAndroid Build Coastguard Worker req.ifa.ifa_index = gNetifIndex;
455*cfb92d14SAndroid Build Coastguard Worker
456*cfb92d14SAndroid Build Coastguard Worker AddRtAttr(&req.nh, sizeof(req), IFA_LOCAL, aAddressInfo.mAddress, sizeof(*aAddressInfo.mAddress));
457*cfb92d14SAndroid Build Coastguard Worker
458*cfb92d14SAndroid Build Coastguard Worker if (!aAddressInfo.mPreferred || aAddressInfo.mMeshLocal)
459*cfb92d14SAndroid Build Coastguard Worker {
460*cfb92d14SAndroid Build Coastguard Worker struct ifa_cacheinfo cacheinfo;
461*cfb92d14SAndroid Build Coastguard Worker
462*cfb92d14SAndroid Build Coastguard Worker memset(&cacheinfo, 0, sizeof(cacheinfo));
463*cfb92d14SAndroid Build Coastguard Worker cacheinfo.ifa_valid = UINT32_MAX;
464*cfb92d14SAndroid Build Coastguard Worker
465*cfb92d14SAndroid Build Coastguard Worker AddRtAttr(&req.nh, sizeof(req), IFA_CACHEINFO, &cacheinfo, sizeof(cacheinfo));
466*cfb92d14SAndroid Build Coastguard Worker }
467*cfb92d14SAndroid Build Coastguard Worker
468*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
469*cfb92d14SAndroid Build Coastguard Worker if (IsOmrAddress(aInstance, aAddressInfo))
470*cfb92d14SAndroid Build Coastguard Worker {
471*cfb92d14SAndroid Build Coastguard Worker // Remove prefix route for OMR address if `OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE` is enabled to
472*cfb92d14SAndroid Build Coastguard Worker // avoid having two routes.
473*cfb92d14SAndroid Build Coastguard Worker if (aIsAdded)
474*cfb92d14SAndroid Build Coastguard Worker {
475*cfb92d14SAndroid Build Coastguard Worker AddRtAttrUint32(&req.nh, sizeof(req), IFA_FLAGS, IFA_F_NOPREFIXROUTE);
476*cfb92d14SAndroid Build Coastguard Worker }
477*cfb92d14SAndroid Build Coastguard Worker }
478*cfb92d14SAndroid Build Coastguard Worker else
479*cfb92d14SAndroid Build Coastguard Worker #endif
480*cfb92d14SAndroid Build Coastguard Worker {
481*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC > 0
482*cfb92d14SAndroid Build Coastguard Worker static constexpr uint8_t kLinkLocalScope = 2;
483*cfb92d14SAndroid Build Coastguard Worker
484*cfb92d14SAndroid Build Coastguard Worker if (aAddressInfo.mScope > kLinkLocalScope)
485*cfb92d14SAndroid Build Coastguard Worker {
486*cfb92d14SAndroid Build Coastguard Worker AddRtAttrUint32(&req.nh, sizeof(req), IFA_RT_PRIORITY, OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC);
487*cfb92d14SAndroid Build Coastguard Worker }
488*cfb92d14SAndroid Build Coastguard Worker #endif
489*cfb92d14SAndroid Build Coastguard Worker }
490*cfb92d14SAndroid Build Coastguard Worker
491*cfb92d14SAndroid Build Coastguard Worker if (send(sNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
492*cfb92d14SAndroid Build Coastguard Worker {
493*cfb92d14SAndroid Build Coastguard Worker LogInfo("Sent request#%u to %s %s/%u", sNetlinkSequence, (aIsAdded ? "add" : "remove"),
494*cfb92d14SAndroid Build Coastguard Worker Ip6AddressString(aAddressInfo.mAddress).AsCString(), aAddressInfo.mPrefixLength);
495*cfb92d14SAndroid Build Coastguard Worker }
496*cfb92d14SAndroid Build Coastguard Worker else
497*cfb92d14SAndroid Build Coastguard Worker {
498*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to send request#%u to %s %s/%u", sNetlinkSequence, (aIsAdded ? "add" : "remove"),
499*cfb92d14SAndroid Build Coastguard Worker Ip6AddressString(aAddressInfo.mAddress).AsCString(), aAddressInfo.mPrefixLength);
500*cfb92d14SAndroid Build Coastguard Worker }
501*cfb92d14SAndroid Build Coastguard Worker }
502*cfb92d14SAndroid Build Coastguard Worker
503*cfb92d14SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
504*cfb92d14SAndroid Build Coastguard Worker #endif // __linux__
505*cfb92d14SAndroid Build Coastguard Worker
UpdateUnicast(otInstance * aInstance,const otIp6AddressInfo & aAddressInfo,bool aIsAdded)506*cfb92d14SAndroid Build Coastguard Worker static void UpdateUnicast(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo, bool aIsAdded)
507*cfb92d14SAndroid Build Coastguard Worker {
508*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aInstance);
509*cfb92d14SAndroid Build Coastguard Worker
510*cfb92d14SAndroid Build Coastguard Worker assert(gInstance == aInstance);
511*cfb92d14SAndroid Build Coastguard Worker assert(sIpFd >= 0);
512*cfb92d14SAndroid Build Coastguard Worker
513*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
514*cfb92d14SAndroid Build Coastguard Worker UpdateUnicastLinux(aInstance, aAddressInfo, aIsAdded);
515*cfb92d14SAndroid Build Coastguard Worker #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
516*cfb92d14SAndroid Build Coastguard Worker {
517*cfb92d14SAndroid Build Coastguard Worker int rval;
518*cfb92d14SAndroid Build Coastguard Worker struct in6_aliasreq ifr6;
519*cfb92d14SAndroid Build Coastguard Worker
520*cfb92d14SAndroid Build Coastguard Worker memset(&ifr6, 0, sizeof(ifr6));
521*cfb92d14SAndroid Build Coastguard Worker strlcpy(ifr6.ifra_name, gNetifName, sizeof(ifr6.ifra_name));
522*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_addr.sin6_family = AF_INET6;
523*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_addr.sin6_len = sizeof(ifr6.ifra_addr);
524*cfb92d14SAndroid Build Coastguard Worker memcpy(&ifr6.ifra_addr.sin6_addr, aAddressInfo.mAddress, sizeof(struct in6_addr));
525*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_prefixmask.sin6_family = AF_INET6;
526*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_prefixmask.sin6_len = sizeof(ifr6.ifra_prefixmask);
527*cfb92d14SAndroid Build Coastguard Worker InitNetaskWithPrefixLength(&ifr6.ifra_prefixmask.sin6_addr, aAddressInfo.mPrefixLength);
528*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
529*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
530*cfb92d14SAndroid Build Coastguard Worker
531*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__)
532*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_lifetime.ia6t_expire = ND6_INFINITE_LIFETIME;
533*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_lifetime.ia6t_preferred =
534*cfb92d14SAndroid Build Coastguard Worker (aAddressInfo.mPreferred && !aAddressInfo.mMeshLocal ? ND6_INFINITE_LIFETIME : 0);
535*cfb92d14SAndroid Build Coastguard Worker #endif
536*cfb92d14SAndroid Build Coastguard Worker
537*cfb92d14SAndroid Build Coastguard Worker rval = ioctl(sIpFd, aIsAdded ? SIOCAIFADDR_IN6 : SIOCDIFADDR_IN6, &ifr6);
538*cfb92d14SAndroid Build Coastguard Worker if (rval == 0)
539*cfb92d14SAndroid Build Coastguard Worker {
540*cfb92d14SAndroid Build Coastguard Worker LogInfo("%s %s/%u", (aIsAdded ? "Added" : "Removed"), Ip6AddressString(aAddressInfo.mAddress).AsCString(),
541*cfb92d14SAndroid Build Coastguard Worker aAddressInfo.mPrefixLength);
542*cfb92d14SAndroid Build Coastguard Worker }
543*cfb92d14SAndroid Build Coastguard Worker else if (errno != EALREADY)
544*cfb92d14SAndroid Build Coastguard Worker {
545*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to %s %s/%u: %s", (aIsAdded ? "add" : "remove"),
546*cfb92d14SAndroid Build Coastguard Worker Ip6AddressString(aAddressInfo.mAddress).AsCString(), aAddressInfo.mPrefixLength, strerror(errno));
547*cfb92d14SAndroid Build Coastguard Worker }
548*cfb92d14SAndroid Build Coastguard Worker }
549*cfb92d14SAndroid Build Coastguard Worker #endif
550*cfb92d14SAndroid Build Coastguard Worker }
551*cfb92d14SAndroid Build Coastguard Worker
UpdateMulticast(otInstance * aInstance,const otIp6Address & aAddress,bool aIsAdded)552*cfb92d14SAndroid Build Coastguard Worker static void UpdateMulticast(otInstance *aInstance, const otIp6Address &aAddress, bool aIsAdded)
553*cfb92d14SAndroid Build Coastguard Worker {
554*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aInstance);
555*cfb92d14SAndroid Build Coastguard Worker
556*cfb92d14SAndroid Build Coastguard Worker struct ipv6_mreq mreq;
557*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
558*cfb92d14SAndroid Build Coastguard Worker int err;
559*cfb92d14SAndroid Build Coastguard Worker
560*cfb92d14SAndroid Build Coastguard Worker assert(gInstance == aInstance);
561*cfb92d14SAndroid Build Coastguard Worker
562*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(sIpFd >= 0);
563*cfb92d14SAndroid Build Coastguard Worker memcpy(&mreq.ipv6mr_multiaddr, &aAddress, sizeof(mreq.ipv6mr_multiaddr));
564*cfb92d14SAndroid Build Coastguard Worker mreq.ipv6mr_interface = gNetifIndex;
565*cfb92d14SAndroid Build Coastguard Worker
566*cfb92d14SAndroid Build Coastguard Worker err = setsockopt(sIpFd, IPPROTO_IPV6, (aIsAdded ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP), &mreq, sizeof(mreq));
567*cfb92d14SAndroid Build Coastguard Worker
568*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__FreeBSD__)
569*cfb92d14SAndroid Build Coastguard Worker if ((err != 0) && (errno == EINVAL) && (IN6_IS_ADDR_MC_LINKLOCAL(&mreq.ipv6mr_multiaddr)))
570*cfb92d14SAndroid Build Coastguard Worker {
571*cfb92d14SAndroid Build Coastguard Worker // FIX ME
572*cfb92d14SAndroid Build Coastguard Worker // on mac OS (and FreeBSD), the first time we run (but not subsequently), we get a failure on this
573*cfb92d14SAndroid Build Coastguard Worker // particular join. do we need to bring up the interface at least once prior to joining? we need to figure
574*cfb92d14SAndroid Build Coastguard Worker // out why so we can get rid of this workaround
575*cfb92d14SAndroid Build Coastguard Worker char addressString[INET6_ADDRSTRLEN + 1];
576*cfb92d14SAndroid Build Coastguard Worker
577*cfb92d14SAndroid Build Coastguard Worker inet_ntop(AF_INET6, mreq.ipv6mr_multiaddr.s6_addr, addressString, sizeof(addressString));
578*cfb92d14SAndroid Build Coastguard Worker LogWarn("Ignoring %s failure (EINVAL) for MC LINKLOCAL address (%s)",
579*cfb92d14SAndroid Build Coastguard Worker aIsAdded ? "IPV6_JOIN_GROUP" : "IPV6_LEAVE_GROUP", addressString);
580*cfb92d14SAndroid Build Coastguard Worker err = 0;
581*cfb92d14SAndroid Build Coastguard Worker }
582*cfb92d14SAndroid Build Coastguard Worker #endif
583*cfb92d14SAndroid Build Coastguard Worker
584*cfb92d14SAndroid Build Coastguard Worker if (err != 0)
585*cfb92d14SAndroid Build Coastguard Worker {
586*cfb92d14SAndroid Build Coastguard Worker LogWarn("%s failure (%d)", aIsAdded ? "IPV6_JOIN_GROUP" : "IPV6_LEAVE_GROUP", errno);
587*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_FAILED;
588*cfb92d14SAndroid Build Coastguard Worker ExitNow();
589*cfb92d14SAndroid Build Coastguard Worker }
590*cfb92d14SAndroid Build Coastguard Worker
591*cfb92d14SAndroid Build Coastguard Worker LogInfo("%s multicast address %s", aIsAdded ? "Added" : "Removed", Ip6AddressString(&aAddress).AsCString());
592*cfb92d14SAndroid Build Coastguard Worker
593*cfb92d14SAndroid Build Coastguard Worker exit:
594*cfb92d14SAndroid Build Coastguard Worker SuccessOrDie(error);
595*cfb92d14SAndroid Build Coastguard Worker }
596*cfb92d14SAndroid Build Coastguard Worker
SetLinkState(otInstance * aInstance,bool aState)597*cfb92d14SAndroid Build Coastguard Worker static void SetLinkState(otInstance *aInstance, bool aState)
598*cfb92d14SAndroid Build Coastguard Worker {
599*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aInstance);
600*cfb92d14SAndroid Build Coastguard Worker
601*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
602*cfb92d14SAndroid Build Coastguard Worker struct ifreq ifr;
603*cfb92d14SAndroid Build Coastguard Worker bool ifState = false;
604*cfb92d14SAndroid Build Coastguard Worker
605*cfb92d14SAndroid Build Coastguard Worker assert(gInstance == aInstance);
606*cfb92d14SAndroid Build Coastguard Worker
607*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(sIpFd >= 0);
608*cfb92d14SAndroid Build Coastguard Worker memset(&ifr, 0, sizeof(ifr));
609*cfb92d14SAndroid Build Coastguard Worker strncpy(ifr.ifr_name, gNetifName, sizeof(ifr.ifr_name));
610*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ioctl(sIpFd, SIOCGIFFLAGS, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED);
611*cfb92d14SAndroid Build Coastguard Worker
612*cfb92d14SAndroid Build Coastguard Worker ifState = ((ifr.ifr_flags & IFF_UP) == IFF_UP) ? true : false;
613*cfb92d14SAndroid Build Coastguard Worker
614*cfb92d14SAndroid Build Coastguard Worker LogNote("Changing interface state to %s%s.", aState ? "up" : "down",
615*cfb92d14SAndroid Build Coastguard Worker (ifState == aState) ? " (already done, ignoring)" : "");
616*cfb92d14SAndroid Build Coastguard Worker
617*cfb92d14SAndroid Build Coastguard Worker if (ifState != aState)
618*cfb92d14SAndroid Build Coastguard Worker {
619*cfb92d14SAndroid Build Coastguard Worker ifr.ifr_flags = aState ? (ifr.ifr_flags | IFF_UP) : (ifr.ifr_flags & ~IFF_UP);
620*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ioctl(sIpFd, SIOCSIFFLAGS, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED);
621*cfb92d14SAndroid Build Coastguard Worker #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
622*cfb92d14SAndroid Build Coastguard Worker // wait for RTM_NEWLINK event before processing notification from kernel to avoid infinite loop
623*cfb92d14SAndroid Build Coastguard Worker sIsSyncingState = true;
624*cfb92d14SAndroid Build Coastguard Worker #endif
625*cfb92d14SAndroid Build Coastguard Worker }
626*cfb92d14SAndroid Build Coastguard Worker
627*cfb92d14SAndroid Build Coastguard Worker exit:
628*cfb92d14SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
629*cfb92d14SAndroid Build Coastguard Worker {
630*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to update state %s", otThreadErrorToString(error));
631*cfb92d14SAndroid Build Coastguard Worker }
632*cfb92d14SAndroid Build Coastguard Worker }
633*cfb92d14SAndroid Build Coastguard Worker
UpdateLink(otInstance * aInstance)634*cfb92d14SAndroid Build Coastguard Worker static void UpdateLink(otInstance *aInstance)
635*cfb92d14SAndroid Build Coastguard Worker {
636*cfb92d14SAndroid Build Coastguard Worker assert(gInstance == aInstance);
637*cfb92d14SAndroid Build Coastguard Worker SetLinkState(aInstance, otIp6IsEnabled(aInstance));
638*cfb92d14SAndroid Build Coastguard Worker }
639*cfb92d14SAndroid Build Coastguard Worker
640*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
AddRoute(const uint8_t (& aAddress)[N],uint8_t aPrefixLen,uint32_t aPriority)641*cfb92d14SAndroid Build Coastguard Worker template <size_t N> otError AddRoute(const uint8_t (&aAddress)[N], uint8_t aPrefixLen, uint32_t aPriority)
642*cfb92d14SAndroid Build Coastguard Worker {
643*cfb92d14SAndroid Build Coastguard Worker constexpr unsigned int kBufSize = 128;
644*cfb92d14SAndroid Build Coastguard Worker struct
645*cfb92d14SAndroid Build Coastguard Worker {
646*cfb92d14SAndroid Build Coastguard Worker struct nlmsghdr header;
647*cfb92d14SAndroid Build Coastguard Worker struct rtmsg msg;
648*cfb92d14SAndroid Build Coastguard Worker char buf[kBufSize];
649*cfb92d14SAndroid Build Coastguard Worker } req{};
650*cfb92d14SAndroid Build Coastguard Worker unsigned int netifIdx = otSysGetThreadNetifIndex();
651*cfb92d14SAndroid Build Coastguard Worker char addrStrBuf[INET6_ADDRSTRLEN];
652*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
653*cfb92d14SAndroid Build Coastguard Worker
654*cfb92d14SAndroid Build Coastguard Worker static_assert(N == sizeof(in6_addr) || N == sizeof(in_addr), "aAddress should be 4 octets or 16 octets");
655*cfb92d14SAndroid Build Coastguard Worker
656*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(netifIdx > 0, error = OT_ERROR_INVALID_STATE);
657*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(sNetlinkFd >= 0, error = OT_ERROR_INVALID_STATE);
658*cfb92d14SAndroid Build Coastguard Worker
659*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
660*cfb92d14SAndroid Build Coastguard Worker
661*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
662*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_type = RTM_NEWROUTE;
663*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_pid = 0;
664*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_seq = ++sNetlinkSequence;
665*cfb92d14SAndroid Build Coastguard Worker
666*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_family = (N == sizeof(in6_addr) ? AF_INET6 : AF_INET);
667*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_src_len = 0;
668*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_dst_len = aPrefixLen;
669*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_tos = 0;
670*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_scope = RT_SCOPE_UNIVERSE;
671*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_type = RTN_UNICAST;
672*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_table = RT_TABLE_MAIN;
673*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_protocol = RTPROT_BOOT;
674*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_flags = 0;
675*cfb92d14SAndroid Build Coastguard Worker
676*cfb92d14SAndroid Build Coastguard Worker AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), RTA_DST, aAddress, sizeof(aAddress));
677*cfb92d14SAndroid Build Coastguard Worker AddRtAttrUint32(&req.header, sizeof(req), RTA_PRIORITY, aPriority);
678*cfb92d14SAndroid Build Coastguard Worker AddRtAttrUint32(&req.header, sizeof(req), RTA_OIF, netifIdx);
679*cfb92d14SAndroid Build Coastguard Worker
680*cfb92d14SAndroid Build Coastguard Worker inet_ntop(req.msg.rtm_family, aAddress, addrStrBuf, sizeof(addrStrBuf));
681*cfb92d14SAndroid Build Coastguard Worker
682*cfb92d14SAndroid Build Coastguard Worker if (send(sNetlinkFd, &req, sizeof(req), 0) < 0)
683*cfb92d14SAndroid Build Coastguard Worker {
684*cfb92d14SAndroid Build Coastguard Worker LogInfo("Failed to send request#%u to add route %s/%u", sNetlinkSequence, addrStrBuf, aPrefixLen);
685*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK, error = OT_ERROR_BUSY);
686*cfb92d14SAndroid Build Coastguard Worker DieNow(OT_EXIT_ERROR_ERRNO);
687*cfb92d14SAndroid Build Coastguard Worker }
688*cfb92d14SAndroid Build Coastguard Worker else
689*cfb92d14SAndroid Build Coastguard Worker {
690*cfb92d14SAndroid Build Coastguard Worker LogInfo("Sent request#%u to add route %s/%u", sNetlinkSequence, addrStrBuf, aPrefixLen);
691*cfb92d14SAndroid Build Coastguard Worker }
692*cfb92d14SAndroid Build Coastguard Worker exit:
693*cfb92d14SAndroid Build Coastguard Worker return error;
694*cfb92d14SAndroid Build Coastguard Worker }
695*cfb92d14SAndroid Build Coastguard Worker
DeleteRoute(const uint8_t (& aAddress)[N],uint8_t aPrefixLen)696*cfb92d14SAndroid Build Coastguard Worker template <size_t N> otError DeleteRoute(const uint8_t (&aAddress)[N], uint8_t aPrefixLen)
697*cfb92d14SAndroid Build Coastguard Worker {
698*cfb92d14SAndroid Build Coastguard Worker constexpr unsigned int kBufSize = 512;
699*cfb92d14SAndroid Build Coastguard Worker struct
700*cfb92d14SAndroid Build Coastguard Worker {
701*cfb92d14SAndroid Build Coastguard Worker struct nlmsghdr header;
702*cfb92d14SAndroid Build Coastguard Worker struct rtmsg msg;
703*cfb92d14SAndroid Build Coastguard Worker char buf[kBufSize];
704*cfb92d14SAndroid Build Coastguard Worker } req{};
705*cfb92d14SAndroid Build Coastguard Worker unsigned int netifIdx = otSysGetThreadNetifIndex();
706*cfb92d14SAndroid Build Coastguard Worker char addrStrBuf[INET6_ADDRSTRLEN];
707*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
708*cfb92d14SAndroid Build Coastguard Worker
709*cfb92d14SAndroid Build Coastguard Worker static_assert(N == sizeof(in6_addr) || N == sizeof(in_addr), "aAddress should be 4 octets or 16 octets");
710*cfb92d14SAndroid Build Coastguard Worker
711*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(netifIdx > 0, error = OT_ERROR_INVALID_STATE);
712*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(sNetlinkFd >= 0, error = OT_ERROR_INVALID_STATE);
713*cfb92d14SAndroid Build Coastguard Worker
714*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_NONREC;
715*cfb92d14SAndroid Build Coastguard Worker
716*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
717*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_type = RTM_DELROUTE;
718*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_pid = 0;
719*cfb92d14SAndroid Build Coastguard Worker req.header.nlmsg_seq = ++sNetlinkSequence;
720*cfb92d14SAndroid Build Coastguard Worker
721*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_family = (N == sizeof(in6_addr) ? AF_INET6 : AF_INET);
722*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_src_len = 0;
723*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_dst_len = aPrefixLen;
724*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_tos = 0;
725*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_scope = RT_SCOPE_UNIVERSE;
726*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_type = RTN_UNICAST;
727*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_table = RT_TABLE_MAIN;
728*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_protocol = RTPROT_BOOT;
729*cfb92d14SAndroid Build Coastguard Worker req.msg.rtm_flags = 0;
730*cfb92d14SAndroid Build Coastguard Worker
731*cfb92d14SAndroid Build Coastguard Worker AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), RTA_DST, &aAddress, sizeof(aAddress));
732*cfb92d14SAndroid Build Coastguard Worker AddRtAttrUint32(&req.header, sizeof(req), RTA_OIF, netifIdx);
733*cfb92d14SAndroid Build Coastguard Worker
734*cfb92d14SAndroid Build Coastguard Worker inet_ntop(req.msg.rtm_family, aAddress, addrStrBuf, sizeof(addrStrBuf));
735*cfb92d14SAndroid Build Coastguard Worker
736*cfb92d14SAndroid Build Coastguard Worker if (send(sNetlinkFd, &req, sizeof(req), 0) < 0)
737*cfb92d14SAndroid Build Coastguard Worker {
738*cfb92d14SAndroid Build Coastguard Worker LogInfo("Failed to send request#%u to delete route %s/%u", sNetlinkSequence, addrStrBuf, aPrefixLen);
739*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK, error = OT_ERROR_BUSY);
740*cfb92d14SAndroid Build Coastguard Worker DieNow(OT_EXIT_ERROR_ERRNO);
741*cfb92d14SAndroid Build Coastguard Worker }
742*cfb92d14SAndroid Build Coastguard Worker else
743*cfb92d14SAndroid Build Coastguard Worker {
744*cfb92d14SAndroid Build Coastguard Worker LogInfo("Sent request#%u to delete route %s/%u", sNetlinkSequence, addrStrBuf, aPrefixLen);
745*cfb92d14SAndroid Build Coastguard Worker }
746*cfb92d14SAndroid Build Coastguard Worker
747*cfb92d14SAndroid Build Coastguard Worker exit:
748*cfb92d14SAndroid Build Coastguard Worker return error;
749*cfb92d14SAndroid Build Coastguard Worker }
750*cfb92d14SAndroid Build Coastguard Worker
751*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
AddRoute(const otIp6Prefix & aPrefix,uint32_t aPriority)752*cfb92d14SAndroid Build Coastguard Worker static otError AddRoute(const otIp6Prefix &aPrefix, uint32_t aPriority)
753*cfb92d14SAndroid Build Coastguard Worker {
754*cfb92d14SAndroid Build Coastguard Worker return AddRoute(aPrefix.mPrefix.mFields.m8, aPrefix.mLength, aPriority);
755*cfb92d14SAndroid Build Coastguard Worker }
756*cfb92d14SAndroid Build Coastguard Worker
DeleteRoute(const otIp6Prefix & aPrefix)757*cfb92d14SAndroid Build Coastguard Worker static otError DeleteRoute(const otIp6Prefix &aPrefix)
758*cfb92d14SAndroid Build Coastguard Worker {
759*cfb92d14SAndroid Build Coastguard Worker return DeleteRoute(aPrefix.mPrefix.mFields.m8, aPrefix.mLength);
760*cfb92d14SAndroid Build Coastguard Worker }
761*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
762*cfb92d14SAndroid Build Coastguard Worker
763*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
HasAddedOmrRoute(const otIp6Prefix & aOmrPrefix)764*cfb92d14SAndroid Build Coastguard Worker static bool HasAddedOmrRoute(const otIp6Prefix &aOmrPrefix)
765*cfb92d14SAndroid Build Coastguard Worker {
766*cfb92d14SAndroid Build Coastguard Worker bool found = false;
767*cfb92d14SAndroid Build Coastguard Worker
768*cfb92d14SAndroid Build Coastguard Worker for (uint8_t i = 0; i < sAddedOmrRoutesNum; ++i)
769*cfb92d14SAndroid Build Coastguard Worker {
770*cfb92d14SAndroid Build Coastguard Worker if (otIp6ArePrefixesEqual(&sAddedOmrRoutes[i], &aOmrPrefix))
771*cfb92d14SAndroid Build Coastguard Worker {
772*cfb92d14SAndroid Build Coastguard Worker found = true;
773*cfb92d14SAndroid Build Coastguard Worker break;
774*cfb92d14SAndroid Build Coastguard Worker }
775*cfb92d14SAndroid Build Coastguard Worker }
776*cfb92d14SAndroid Build Coastguard Worker
777*cfb92d14SAndroid Build Coastguard Worker return found;
778*cfb92d14SAndroid Build Coastguard Worker }
779*cfb92d14SAndroid Build Coastguard Worker
AddOmrRoute(const otIp6Prefix & aPrefix)780*cfb92d14SAndroid Build Coastguard Worker static otError AddOmrRoute(const otIp6Prefix &aPrefix)
781*cfb92d14SAndroid Build Coastguard Worker {
782*cfb92d14SAndroid Build Coastguard Worker otError error;
783*cfb92d14SAndroid Build Coastguard Worker
784*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(sAddedOmrRoutesNum < kMaxOmrRoutesNum, error = OT_ERROR_NO_BUFS);
785*cfb92d14SAndroid Build Coastguard Worker
786*cfb92d14SAndroid Build Coastguard Worker error = AddRoute(aPrefix, kOmrRoutesPriority);
787*cfb92d14SAndroid Build Coastguard Worker exit:
788*cfb92d14SAndroid Build Coastguard Worker return error;
789*cfb92d14SAndroid Build Coastguard Worker }
790*cfb92d14SAndroid Build Coastguard Worker
UpdateOmrRoutes(otInstance * aInstance)791*cfb92d14SAndroid Build Coastguard Worker static void UpdateOmrRoutes(otInstance *aInstance)
792*cfb92d14SAndroid Build Coastguard Worker {
793*cfb92d14SAndroid Build Coastguard Worker otError error;
794*cfb92d14SAndroid Build Coastguard Worker otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
795*cfb92d14SAndroid Build Coastguard Worker otBorderRouterConfig config;
796*cfb92d14SAndroid Build Coastguard Worker char prefixString[OT_IP6_PREFIX_STRING_SIZE];
797*cfb92d14SAndroid Build Coastguard Worker
798*cfb92d14SAndroid Build Coastguard Worker // Remove kernel routes if the OMR prefix is removed
799*cfb92d14SAndroid Build Coastguard Worker for (int i = 0; i < static_cast<int>(sAddedOmrRoutesNum); ++i)
800*cfb92d14SAndroid Build Coastguard Worker {
801*cfb92d14SAndroid Build Coastguard Worker if (otNetDataContainsOmrPrefix(aInstance, &sAddedOmrRoutes[i]))
802*cfb92d14SAndroid Build Coastguard Worker {
803*cfb92d14SAndroid Build Coastguard Worker continue;
804*cfb92d14SAndroid Build Coastguard Worker }
805*cfb92d14SAndroid Build Coastguard Worker
806*cfb92d14SAndroid Build Coastguard Worker otIp6PrefixToString(&sAddedOmrRoutes[i], prefixString, sizeof(prefixString));
807*cfb92d14SAndroid Build Coastguard Worker if ((error = DeleteRoute(sAddedOmrRoutes[i])) != OT_ERROR_NONE)
808*cfb92d14SAndroid Build Coastguard Worker {
809*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to delete an OMR route %s in kernel: %s", prefixString, otThreadErrorToString(error));
810*cfb92d14SAndroid Build Coastguard Worker }
811*cfb92d14SAndroid Build Coastguard Worker else
812*cfb92d14SAndroid Build Coastguard Worker {
813*cfb92d14SAndroid Build Coastguard Worker sAddedOmrRoutes[i] = sAddedOmrRoutes[sAddedOmrRoutesNum - 1];
814*cfb92d14SAndroid Build Coastguard Worker --sAddedOmrRoutesNum;
815*cfb92d14SAndroid Build Coastguard Worker --i;
816*cfb92d14SAndroid Build Coastguard Worker LogInfo("Successfully deleted an OMR route %s in kernel", prefixString);
817*cfb92d14SAndroid Build Coastguard Worker }
818*cfb92d14SAndroid Build Coastguard Worker }
819*cfb92d14SAndroid Build Coastguard Worker
820*cfb92d14SAndroid Build Coastguard Worker // Add kernel routes for OMR prefixes in Network Data
821*cfb92d14SAndroid Build Coastguard Worker while (otNetDataGetNextOnMeshPrefix(aInstance, &iterator, &config) == OT_ERROR_NONE)
822*cfb92d14SAndroid Build Coastguard Worker {
823*cfb92d14SAndroid Build Coastguard Worker if (HasAddedOmrRoute(config.mPrefix))
824*cfb92d14SAndroid Build Coastguard Worker {
825*cfb92d14SAndroid Build Coastguard Worker continue;
826*cfb92d14SAndroid Build Coastguard Worker }
827*cfb92d14SAndroid Build Coastguard Worker
828*cfb92d14SAndroid Build Coastguard Worker otIp6PrefixToString(&config.mPrefix, prefixString, sizeof(prefixString));
829*cfb92d14SAndroid Build Coastguard Worker if ((error = AddOmrRoute(config.mPrefix)) != OT_ERROR_NONE)
830*cfb92d14SAndroid Build Coastguard Worker {
831*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to add an OMR route %s in kernel: %s", prefixString, otThreadErrorToString(error));
832*cfb92d14SAndroid Build Coastguard Worker }
833*cfb92d14SAndroid Build Coastguard Worker else
834*cfb92d14SAndroid Build Coastguard Worker {
835*cfb92d14SAndroid Build Coastguard Worker sAddedOmrRoutes[sAddedOmrRoutesNum++] = config.mPrefix;
836*cfb92d14SAndroid Build Coastguard Worker LogInfo("Successfully added an OMR route %s in kernel", prefixString);
837*cfb92d14SAndroid Build Coastguard Worker }
838*cfb92d14SAndroid Build Coastguard Worker }
839*cfb92d14SAndroid Build Coastguard Worker }
840*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
841*cfb92d14SAndroid Build Coastguard Worker
842*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
AddExternalRoute(const otIp6Prefix & aPrefix)843*cfb92d14SAndroid Build Coastguard Worker static otError AddExternalRoute(const otIp6Prefix &aPrefix)
844*cfb92d14SAndroid Build Coastguard Worker {
845*cfb92d14SAndroid Build Coastguard Worker otError error;
846*cfb92d14SAndroid Build Coastguard Worker
847*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(sAddedExternalRoutesNum < kMaxExternalRoutesNum, error = OT_ERROR_NO_BUFS);
848*cfb92d14SAndroid Build Coastguard Worker
849*cfb92d14SAndroid Build Coastguard Worker error = AddRoute(aPrefix, kExternalRoutePriority);
850*cfb92d14SAndroid Build Coastguard Worker exit:
851*cfb92d14SAndroid Build Coastguard Worker return error;
852*cfb92d14SAndroid Build Coastguard Worker }
853*cfb92d14SAndroid Build Coastguard Worker
HasExternalRouteInNetData(otInstance * aInstance,const otIp6Prefix & aExternalRoute)854*cfb92d14SAndroid Build Coastguard Worker bool HasExternalRouteInNetData(otInstance *aInstance, const otIp6Prefix &aExternalRoute)
855*cfb92d14SAndroid Build Coastguard Worker {
856*cfb92d14SAndroid Build Coastguard Worker otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
857*cfb92d14SAndroid Build Coastguard Worker otExternalRouteConfig config;
858*cfb92d14SAndroid Build Coastguard Worker bool found = false;
859*cfb92d14SAndroid Build Coastguard Worker
860*cfb92d14SAndroid Build Coastguard Worker while (otNetDataGetNextRoute(aInstance, &iterator, &config) == OT_ERROR_NONE)
861*cfb92d14SAndroid Build Coastguard Worker {
862*cfb92d14SAndroid Build Coastguard Worker if (otIp6ArePrefixesEqual(&config.mPrefix, &aExternalRoute))
863*cfb92d14SAndroid Build Coastguard Worker {
864*cfb92d14SAndroid Build Coastguard Worker found = true;
865*cfb92d14SAndroid Build Coastguard Worker break;
866*cfb92d14SAndroid Build Coastguard Worker }
867*cfb92d14SAndroid Build Coastguard Worker }
868*cfb92d14SAndroid Build Coastguard Worker return found;
869*cfb92d14SAndroid Build Coastguard Worker }
870*cfb92d14SAndroid Build Coastguard Worker
HasAddedExternalRoute(const otIp6Prefix & aExternalRoute)871*cfb92d14SAndroid Build Coastguard Worker bool HasAddedExternalRoute(const otIp6Prefix &aExternalRoute)
872*cfb92d14SAndroid Build Coastguard Worker {
873*cfb92d14SAndroid Build Coastguard Worker bool found = false;
874*cfb92d14SAndroid Build Coastguard Worker
875*cfb92d14SAndroid Build Coastguard Worker for (uint8_t i = 0; i < sAddedExternalRoutesNum; ++i)
876*cfb92d14SAndroid Build Coastguard Worker {
877*cfb92d14SAndroid Build Coastguard Worker if (otIp6ArePrefixesEqual(&sAddedExternalRoutes[i], &aExternalRoute))
878*cfb92d14SAndroid Build Coastguard Worker {
879*cfb92d14SAndroid Build Coastguard Worker found = true;
880*cfb92d14SAndroid Build Coastguard Worker break;
881*cfb92d14SAndroid Build Coastguard Worker }
882*cfb92d14SAndroid Build Coastguard Worker }
883*cfb92d14SAndroid Build Coastguard Worker return found;
884*cfb92d14SAndroid Build Coastguard Worker }
885*cfb92d14SAndroid Build Coastguard Worker
UpdateExternalRoutes(otInstance * aInstance)886*cfb92d14SAndroid Build Coastguard Worker static void UpdateExternalRoutes(otInstance *aInstance)
887*cfb92d14SAndroid Build Coastguard Worker {
888*cfb92d14SAndroid Build Coastguard Worker otError error;
889*cfb92d14SAndroid Build Coastguard Worker otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
890*cfb92d14SAndroid Build Coastguard Worker otExternalRouteConfig config;
891*cfb92d14SAndroid Build Coastguard Worker char prefixString[OT_IP6_PREFIX_STRING_SIZE];
892*cfb92d14SAndroid Build Coastguard Worker
893*cfb92d14SAndroid Build Coastguard Worker for (int i = 0; i < static_cast<int>(sAddedExternalRoutesNum); ++i)
894*cfb92d14SAndroid Build Coastguard Worker {
895*cfb92d14SAndroid Build Coastguard Worker if (HasExternalRouteInNetData(aInstance, sAddedExternalRoutes[i]))
896*cfb92d14SAndroid Build Coastguard Worker {
897*cfb92d14SAndroid Build Coastguard Worker continue;
898*cfb92d14SAndroid Build Coastguard Worker }
899*cfb92d14SAndroid Build Coastguard Worker
900*cfb92d14SAndroid Build Coastguard Worker otIp6PrefixToString(&sAddedExternalRoutes[i], prefixString, sizeof(prefixString));
901*cfb92d14SAndroid Build Coastguard Worker if ((error = DeleteRoute(sAddedExternalRoutes[i])) != OT_ERROR_NONE)
902*cfb92d14SAndroid Build Coastguard Worker {
903*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to delete an external route %s in kernel: %s", prefixString, otThreadErrorToString(error));
904*cfb92d14SAndroid Build Coastguard Worker }
905*cfb92d14SAndroid Build Coastguard Worker else
906*cfb92d14SAndroid Build Coastguard Worker {
907*cfb92d14SAndroid Build Coastguard Worker sAddedExternalRoutes[i] = sAddedExternalRoutes[sAddedExternalRoutesNum - 1];
908*cfb92d14SAndroid Build Coastguard Worker --sAddedExternalRoutesNum;
909*cfb92d14SAndroid Build Coastguard Worker --i;
910*cfb92d14SAndroid Build Coastguard Worker LogWarn("Successfully deleted an external route %s in kernel", prefixString);
911*cfb92d14SAndroid Build Coastguard Worker }
912*cfb92d14SAndroid Build Coastguard Worker }
913*cfb92d14SAndroid Build Coastguard Worker
914*cfb92d14SAndroid Build Coastguard Worker while (otNetDataGetNextRoute(aInstance, &iterator, &config) == OT_ERROR_NONE)
915*cfb92d14SAndroid Build Coastguard Worker {
916*cfb92d14SAndroid Build Coastguard Worker if (config.mRloc16 == otThreadGetRloc16(aInstance) || HasAddedExternalRoute(config.mPrefix))
917*cfb92d14SAndroid Build Coastguard Worker {
918*cfb92d14SAndroid Build Coastguard Worker continue;
919*cfb92d14SAndroid Build Coastguard Worker }
920*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(sAddedExternalRoutesNum < kMaxExternalRoutesNum,
921*cfb92d14SAndroid Build Coastguard Worker LogWarn("No buffer to add more external routes in kernel"));
922*cfb92d14SAndroid Build Coastguard Worker
923*cfb92d14SAndroid Build Coastguard Worker otIp6PrefixToString(&config.mPrefix, prefixString, sizeof(prefixString));
924*cfb92d14SAndroid Build Coastguard Worker if ((error = AddExternalRoute(config.mPrefix)) != OT_ERROR_NONE)
925*cfb92d14SAndroid Build Coastguard Worker {
926*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to add an external route %s in kernel: %s", prefixString, otThreadErrorToString(error));
927*cfb92d14SAndroid Build Coastguard Worker }
928*cfb92d14SAndroid Build Coastguard Worker else
929*cfb92d14SAndroid Build Coastguard Worker {
930*cfb92d14SAndroid Build Coastguard Worker sAddedExternalRoutes[sAddedExternalRoutesNum++] = config.mPrefix;
931*cfb92d14SAndroid Build Coastguard Worker LogWarn("Successfully added an external route %s in kernel", prefixString);
932*cfb92d14SAndroid Build Coastguard Worker }
933*cfb92d14SAndroid Build Coastguard Worker }
934*cfb92d14SAndroid Build Coastguard Worker exit:
935*cfb92d14SAndroid Build Coastguard Worker return;
936*cfb92d14SAndroid Build Coastguard Worker }
937*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
938*cfb92d14SAndroid Build Coastguard Worker
939*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
AddIp4Route(const otIp4Cidr & aIp4Cidr,uint32_t aPriority)940*cfb92d14SAndroid Build Coastguard Worker static otError AddIp4Route(const otIp4Cidr &aIp4Cidr, uint32_t aPriority)
941*cfb92d14SAndroid Build Coastguard Worker {
942*cfb92d14SAndroid Build Coastguard Worker return AddRoute(aIp4Cidr.mAddress.mFields.m8, aIp4Cidr.mLength, aPriority);
943*cfb92d14SAndroid Build Coastguard Worker }
944*cfb92d14SAndroid Build Coastguard Worker
DeleteIp4Route(const otIp4Cidr & aIp4Cidr)945*cfb92d14SAndroid Build Coastguard Worker static otError DeleteIp4Route(const otIp4Cidr &aIp4Cidr)
946*cfb92d14SAndroid Build Coastguard Worker {
947*cfb92d14SAndroid Build Coastguard Worker return DeleteRoute(aIp4Cidr.mAddress.mFields.m8, aIp4Cidr.mLength);
948*cfb92d14SAndroid Build Coastguard Worker }
949*cfb92d14SAndroid Build Coastguard Worker #endif
950*cfb92d14SAndroid Build Coastguard Worker #endif // __linux__
951*cfb92d14SAndroid Build Coastguard Worker
processAddressChange(const otIp6AddressInfo * aAddressInfo,bool aIsAdded,void * aContext)952*cfb92d14SAndroid Build Coastguard Worker static void processAddressChange(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aContext)
953*cfb92d14SAndroid Build Coastguard Worker {
954*cfb92d14SAndroid Build Coastguard Worker if (aAddressInfo->mAddress->mFields.m8[0] == 0xff)
955*cfb92d14SAndroid Build Coastguard Worker {
956*cfb92d14SAndroid Build Coastguard Worker UpdateMulticast(static_cast<otInstance *>(aContext), *aAddressInfo->mAddress, aIsAdded);
957*cfb92d14SAndroid Build Coastguard Worker }
958*cfb92d14SAndroid Build Coastguard Worker else
959*cfb92d14SAndroid Build Coastguard Worker {
960*cfb92d14SAndroid Build Coastguard Worker UpdateUnicast(static_cast<otInstance *>(aContext), *aAddressInfo, aIsAdded);
961*cfb92d14SAndroid Build Coastguard Worker }
962*cfb92d14SAndroid Build Coastguard Worker }
963*cfb92d14SAndroid Build Coastguard Worker
964*cfb92d14SAndroid Build Coastguard Worker #if defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
isSameIp4Cidr(const otIp4Cidr & aCidr1,const otIp4Cidr & aCidr2)965*cfb92d14SAndroid Build Coastguard Worker static bool isSameIp4Cidr(const otIp4Cidr &aCidr1, const otIp4Cidr &aCidr2)
966*cfb92d14SAndroid Build Coastguard Worker {
967*cfb92d14SAndroid Build Coastguard Worker bool res = true;
968*cfb92d14SAndroid Build Coastguard Worker
969*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(aCidr1.mLength == aCidr2.mLength, res = false);
970*cfb92d14SAndroid Build Coastguard Worker
971*cfb92d14SAndroid Build Coastguard Worker // The higher (32 - length) bits must be the same, host bits are ignored.
972*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(((ntohl(aCidr1.mAddress.mFields.m32) ^ ntohl(aCidr2.mAddress.mFields.m32)) >> (32 - aCidr1.mLength)) ==
973*cfb92d14SAndroid Build Coastguard Worker 0,
974*cfb92d14SAndroid Build Coastguard Worker res = false);
975*cfb92d14SAndroid Build Coastguard Worker
976*cfb92d14SAndroid Build Coastguard Worker exit:
977*cfb92d14SAndroid Build Coastguard Worker return res;
978*cfb92d14SAndroid Build Coastguard Worker }
979*cfb92d14SAndroid Build Coastguard Worker
processNat64StateChange(void)980*cfb92d14SAndroid Build Coastguard Worker static void processNat64StateChange(void)
981*cfb92d14SAndroid Build Coastguard Worker {
982*cfb92d14SAndroid Build Coastguard Worker otIp4Cidr translatorCidr;
983*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
984*cfb92d14SAndroid Build Coastguard Worker
985*cfb92d14SAndroid Build Coastguard Worker // Skip if NAT64 translator has not been configured with a CIDR.
986*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(otNat64GetCidr(gInstance, &translatorCidr));
987*cfb92d14SAndroid Build Coastguard Worker
988*cfb92d14SAndroid Build Coastguard Worker if (!isSameIp4Cidr(translatorCidr, sActiveNat64Cidr)) // Someone sets a new CIDR for NAT64.
989*cfb92d14SAndroid Build Coastguard Worker {
990*cfb92d14SAndroid Build Coastguard Worker char cidrString[OT_IP4_CIDR_STRING_SIZE];
991*cfb92d14SAndroid Build Coastguard Worker
992*cfb92d14SAndroid Build Coastguard Worker if (sActiveNat64Cidr.mLength != 0)
993*cfb92d14SAndroid Build Coastguard Worker {
994*cfb92d14SAndroid Build Coastguard Worker if ((error = DeleteIp4Route(sActiveNat64Cidr)) != OT_ERROR_NONE)
995*cfb92d14SAndroid Build Coastguard Worker {
996*cfb92d14SAndroid Build Coastguard Worker LogWarn("failed to delete route for NAT64: %s", otThreadErrorToString(error));
997*cfb92d14SAndroid Build Coastguard Worker }
998*cfb92d14SAndroid Build Coastguard Worker }
999*cfb92d14SAndroid Build Coastguard Worker sActiveNat64Cidr = translatorCidr;
1000*cfb92d14SAndroid Build Coastguard Worker
1001*cfb92d14SAndroid Build Coastguard Worker otIp4CidrToString(&translatorCidr, cidrString, sizeof(cidrString));
1002*cfb92d14SAndroid Build Coastguard Worker LogInfo("NAT64 CIDR updated to %s.", cidrString);
1003*cfb92d14SAndroid Build Coastguard Worker }
1004*cfb92d14SAndroid Build Coastguard Worker
1005*cfb92d14SAndroid Build Coastguard Worker if (otNat64GetTranslatorState(gInstance) == OT_NAT64_STATE_ACTIVE)
1006*cfb92d14SAndroid Build Coastguard Worker {
1007*cfb92d14SAndroid Build Coastguard Worker if ((error = AddIp4Route(sActiveNat64Cidr, kNat64RoutePriority)) != OT_ERROR_NONE)
1008*cfb92d14SAndroid Build Coastguard Worker {
1009*cfb92d14SAndroid Build Coastguard Worker LogWarn("failed to add route for NAT64: %s", otThreadErrorToString(error));
1010*cfb92d14SAndroid Build Coastguard Worker }
1011*cfb92d14SAndroid Build Coastguard Worker LogInfo("Adding route for NAT64");
1012*cfb92d14SAndroid Build Coastguard Worker }
1013*cfb92d14SAndroid Build Coastguard Worker else if (sActiveNat64Cidr.mLength > 0) // Translator is not active.
1014*cfb92d14SAndroid Build Coastguard Worker {
1015*cfb92d14SAndroid Build Coastguard Worker if ((error = DeleteIp4Route(sActiveNat64Cidr)) != OT_ERROR_NONE)
1016*cfb92d14SAndroid Build Coastguard Worker {
1017*cfb92d14SAndroid Build Coastguard Worker LogWarn("failed to delete route for NAT64: %s", otThreadErrorToString(error));
1018*cfb92d14SAndroid Build Coastguard Worker }
1019*cfb92d14SAndroid Build Coastguard Worker LogInfo("Deleting route for NAT64");
1020*cfb92d14SAndroid Build Coastguard Worker }
1021*cfb92d14SAndroid Build Coastguard Worker
1022*cfb92d14SAndroid Build Coastguard Worker exit:
1023*cfb92d14SAndroid Build Coastguard Worker return;
1024*cfb92d14SAndroid Build Coastguard Worker }
1025*cfb92d14SAndroid Build Coastguard Worker #endif // defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1026*cfb92d14SAndroid Build Coastguard Worker
platformNetifStateChange(otInstance * aInstance,otChangedFlags aFlags)1027*cfb92d14SAndroid Build Coastguard Worker void platformNetifStateChange(otInstance *aInstance, otChangedFlags aFlags)
1028*cfb92d14SAndroid Build Coastguard Worker {
1029*cfb92d14SAndroid Build Coastguard Worker if (OT_CHANGED_THREAD_NETIF_STATE & aFlags)
1030*cfb92d14SAndroid Build Coastguard Worker {
1031*cfb92d14SAndroid Build Coastguard Worker UpdateLink(aInstance);
1032*cfb92d14SAndroid Build Coastguard Worker }
1033*cfb92d14SAndroid Build Coastguard Worker if (OT_CHANGED_THREAD_NETDATA & aFlags)
1034*cfb92d14SAndroid Build Coastguard Worker {
1035*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && defined(__linux__)
1036*cfb92d14SAndroid Build Coastguard Worker UpdateOmrRoutes(aInstance);
1037*cfb92d14SAndroid Build Coastguard Worker #endif
1038*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && defined(__linux__)
1039*cfb92d14SAndroid Build Coastguard Worker UpdateExternalRoutes(aInstance);
1040*cfb92d14SAndroid Build Coastguard Worker #endif
1041*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
1042*cfb92d14SAndroid Build Coastguard Worker ot::Posix::UpdateIpSets(aInstance);
1043*cfb92d14SAndroid Build Coastguard Worker #endif
1044*cfb92d14SAndroid Build Coastguard Worker }
1045*cfb92d14SAndroid Build Coastguard Worker #if defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1046*cfb92d14SAndroid Build Coastguard Worker if ((OT_CHANGED_NAT64_TRANSLATOR_STATE | OT_CHANGED_THREAD_NETIF_STATE) & aFlags)
1047*cfb92d14SAndroid Build Coastguard Worker {
1048*cfb92d14SAndroid Build Coastguard Worker processNat64StateChange();
1049*cfb92d14SAndroid Build Coastguard Worker }
1050*cfb92d14SAndroid Build Coastguard Worker #endif
1051*cfb92d14SAndroid Build Coastguard Worker }
1052*cfb92d14SAndroid Build Coastguard Worker
processReceive(otMessage * aMessage,void * aContext)1053*cfb92d14SAndroid Build Coastguard Worker static void processReceive(otMessage *aMessage, void *aContext)
1054*cfb92d14SAndroid Build Coastguard Worker {
1055*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aContext);
1056*cfb92d14SAndroid Build Coastguard Worker
1057*cfb92d14SAndroid Build Coastguard Worker char packet[kMaxIp6Size + 4];
1058*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
1059*cfb92d14SAndroid Build Coastguard Worker uint16_t length = otMessageGetLength(aMessage);
1060*cfb92d14SAndroid Build Coastguard Worker size_t offset = 0;
1061*cfb92d14SAndroid Build Coastguard Worker uint16_t maxLength = sizeof(packet) - 4;
1062*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1063*cfb92d14SAndroid Build Coastguard Worker // BSD tunnel drivers use (for legacy reasons) a 4-byte header to determine the address family of the packet
1064*cfb92d14SAndroid Build Coastguard Worker offset += 4;
1065*cfb92d14SAndroid Build Coastguard Worker #endif
1066*cfb92d14SAndroid Build Coastguard Worker
1067*cfb92d14SAndroid Build Coastguard Worker assert(gInstance == aContext);
1068*cfb92d14SAndroid Build Coastguard Worker assert(length <= kMaxIp6Size);
1069*cfb92d14SAndroid Build Coastguard Worker
1070*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(sTunFd > 0);
1071*cfb92d14SAndroid Build Coastguard Worker
1072*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(otMessageRead(aMessage, 0, &packet[offset], maxLength) == length, error = OT_ERROR_NO_BUFS);
1073*cfb92d14SAndroid Build Coastguard Worker
1074*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
1075*cfb92d14SAndroid Build Coastguard Worker LogInfo("Packet from NCP (%u bytes)", static_cast<uint16_t>(length));
1076*cfb92d14SAndroid Build Coastguard Worker otDumpInfoPlat("", &packet[offset], length);
1077*cfb92d14SAndroid Build Coastguard Worker #endif
1078*cfb92d14SAndroid Build Coastguard Worker
1079*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1080*cfb92d14SAndroid Build Coastguard Worker packet[0] = 0;
1081*cfb92d14SAndroid Build Coastguard Worker packet[1] = 0;
1082*cfb92d14SAndroid Build Coastguard Worker packet[2] = (PF_INET6 << 8) & 0xFF;
1083*cfb92d14SAndroid Build Coastguard Worker packet[3] = (PF_INET6 << 0) & 0xFF;
1084*cfb92d14SAndroid Build Coastguard Worker length += 4;
1085*cfb92d14SAndroid Build Coastguard Worker #endif
1086*cfb92d14SAndroid Build Coastguard Worker
1087*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(write(sTunFd, packet, length) == length, perror("write"); error = OT_ERROR_FAILED);
1088*cfb92d14SAndroid Build Coastguard Worker
1089*cfb92d14SAndroid Build Coastguard Worker exit:
1090*cfb92d14SAndroid Build Coastguard Worker otMessageFree(aMessage);
1091*cfb92d14SAndroid Build Coastguard Worker
1092*cfb92d14SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
1093*cfb92d14SAndroid Build Coastguard Worker {
1094*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to receive, error:%s", otThreadErrorToString(error));
1095*cfb92d14SAndroid Build Coastguard Worker }
1096*cfb92d14SAndroid Build Coastguard Worker }
1097*cfb92d14SAndroid Build Coastguard Worker
1098*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE || OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1099*cfb92d14SAndroid Build Coastguard Worker static constexpr uint8_t kIpVersion4 = 4;
1100*cfb92d14SAndroid Build Coastguard Worker static constexpr uint8_t kIpVersion6 = 6;
1101*cfb92d14SAndroid Build Coastguard Worker
getIpVersion(const uint8_t * data)1102*cfb92d14SAndroid Build Coastguard Worker static uint8_t getIpVersion(const uint8_t *data)
1103*cfb92d14SAndroid Build Coastguard Worker {
1104*cfb92d14SAndroid Build Coastguard Worker assert(data != nullptr);
1105*cfb92d14SAndroid Build Coastguard Worker
1106*cfb92d14SAndroid Build Coastguard Worker // Mute compiler warnings.
1107*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(kIpVersion4);
1108*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(kIpVersion6);
1109*cfb92d14SAndroid Build Coastguard Worker
1110*cfb92d14SAndroid Build Coastguard Worker return (static_cast<uint8_t>(data[0]) >> 4) & 0x0F;
1111*cfb92d14SAndroid Build Coastguard Worker }
1112*cfb92d14SAndroid Build Coastguard Worker #endif
1113*cfb92d14SAndroid Build Coastguard Worker
1114*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1115*cfb92d14SAndroid Build Coastguard Worker
1116*cfb92d14SAndroid Build Coastguard Worker /**
1117*cfb92d14SAndroid Build Coastguard Worker * Returns nullptr if data does not point to a valid ICMPv6 RA message.
1118*cfb92d14SAndroid Build Coastguard Worker *
1119*cfb92d14SAndroid Build Coastguard Worker */
getIcmp6RaMessage(const uint8_t * data,ssize_t length)1120*cfb92d14SAndroid Build Coastguard Worker static const uint8_t *getIcmp6RaMessage(const uint8_t *data, ssize_t length)
1121*cfb92d14SAndroid Build Coastguard Worker {
1122*cfb92d14SAndroid Build Coastguard Worker const uint8_t *ret = nullptr;
1123*cfb92d14SAndroid Build Coastguard Worker otIcmp6Header icmpHeader;
1124*cfb92d14SAndroid Build Coastguard Worker
1125*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(length >= OT_IP6_HEADER_SIZE + OT_ICMP6_ROUTER_ADVERT_MIN_SIZE);
1126*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(getIpVersion(data) == kIpVersion6);
1127*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(data[OT_IP6_HEADER_PROTO_OFFSET] == OT_IP6_PROTO_ICMP6);
1128*cfb92d14SAndroid Build Coastguard Worker
1129*cfb92d14SAndroid Build Coastguard Worker ret = data + OT_IP6_HEADER_SIZE;
1130*cfb92d14SAndroid Build Coastguard Worker memcpy(&icmpHeader, ret, sizeof(icmpHeader));
1131*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(icmpHeader.mType == OT_ICMP6_TYPE_ROUTER_ADVERT, ret = nullptr);
1132*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(icmpHeader.mCode == 0, ret = nullptr);
1133*cfb92d14SAndroid Build Coastguard Worker
1134*cfb92d14SAndroid Build Coastguard Worker exit:
1135*cfb92d14SAndroid Build Coastguard Worker return ret;
1136*cfb92d14SAndroid Build Coastguard Worker }
1137*cfb92d14SAndroid Build Coastguard Worker
1138*cfb92d14SAndroid Build Coastguard Worker /**
1139*cfb92d14SAndroid Build Coastguard Worker * Returns false if the message is not an ICMPv6 RA message.
1140*cfb92d14SAndroid Build Coastguard Worker *
1141*cfb92d14SAndroid Build Coastguard Worker */
tryProcessIcmp6RaMessage(otInstance * aInstance,const uint8_t * data,ssize_t length)1142*cfb92d14SAndroid Build Coastguard Worker static otError tryProcessIcmp6RaMessage(otInstance *aInstance, const uint8_t *data, ssize_t length)
1143*cfb92d14SAndroid Build Coastguard Worker {
1144*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
1145*cfb92d14SAndroid Build Coastguard Worker const uint8_t *ra = getIcmp6RaMessage(data, length);
1146*cfb92d14SAndroid Build Coastguard Worker ssize_t raLength;
1147*cfb92d14SAndroid Build Coastguard Worker
1148*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ra != nullptr, error = OT_ERROR_INVALID_ARGS);
1149*cfb92d14SAndroid Build Coastguard Worker
1150*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
1151*cfb92d14SAndroid Build Coastguard Worker LogInfo("RA to BorderRouting (%hu bytes)", static_cast<uint16_t>(length));
1152*cfb92d14SAndroid Build Coastguard Worker otDumpInfoPlat("", data, static_cast<size_t>(length));
1153*cfb92d14SAndroid Build Coastguard Worker #endif
1154*cfb92d14SAndroid Build Coastguard Worker
1155*cfb92d14SAndroid Build Coastguard Worker raLength = length + (ra - data);
1156*cfb92d14SAndroid Build Coastguard Worker otPlatBorderRoutingProcessIcmp6Ra(aInstance, ra, raLength);
1157*cfb92d14SAndroid Build Coastguard Worker
1158*cfb92d14SAndroid Build Coastguard Worker exit:
1159*cfb92d14SAndroid Build Coastguard Worker return error;
1160*cfb92d14SAndroid Build Coastguard Worker }
1161*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1162*cfb92d14SAndroid Build Coastguard Worker
1163*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1164*cfb92d14SAndroid Build Coastguard Worker /**
1165*cfb92d14SAndroid Build Coastguard Worker * Returns whether the address is a required anycast address (RFC2373, 2.6.1).
1166*cfb92d14SAndroid Build Coastguard Worker *
1167*cfb92d14SAndroid Build Coastguard Worker */
isRequiredAnycast(const uint8_t * aAddress,uint8_t aPrefixLength)1168*cfb92d14SAndroid Build Coastguard Worker static bool isRequiredAnycast(const uint8_t *aAddress, uint8_t aPrefixLength)
1169*cfb92d14SAndroid Build Coastguard Worker {
1170*cfb92d14SAndroid Build Coastguard Worker bool isRequiredAnycast = false;
1171*cfb92d14SAndroid Build Coastguard Worker uint8_t firstBytePos = aPrefixLength / 8;
1172*cfb92d14SAndroid Build Coastguard Worker uint8_t remainingBits = aPrefixLength % 8;
1173*cfb92d14SAndroid Build Coastguard Worker
1174*cfb92d14SAndroid Build Coastguard Worker if (aPrefixLength == OT_IP6_ADDRESS_BITSIZE)
1175*cfb92d14SAndroid Build Coastguard Worker {
1176*cfb92d14SAndroid Build Coastguard Worker ExitNow();
1177*cfb92d14SAndroid Build Coastguard Worker }
1178*cfb92d14SAndroid Build Coastguard Worker
1179*cfb92d14SAndroid Build Coastguard Worker if (remainingBits != 0)
1180*cfb92d14SAndroid Build Coastguard Worker {
1181*cfb92d14SAndroid Build Coastguard Worker if ((aAddress[firstBytePos] & ((1 << remainingBits) - 1)) != 0)
1182*cfb92d14SAndroid Build Coastguard Worker {
1183*cfb92d14SAndroid Build Coastguard Worker ExitNow();
1184*cfb92d14SAndroid Build Coastguard Worker }
1185*cfb92d14SAndroid Build Coastguard Worker firstBytePos++;
1186*cfb92d14SAndroid Build Coastguard Worker }
1187*cfb92d14SAndroid Build Coastguard Worker
1188*cfb92d14SAndroid Build Coastguard Worker for (int i = firstBytePos; i < OT_IP6_ADDRESS_SIZE; ++i)
1189*cfb92d14SAndroid Build Coastguard Worker {
1190*cfb92d14SAndroid Build Coastguard Worker if (aAddress[i] != 0)
1191*cfb92d14SAndroid Build Coastguard Worker {
1192*cfb92d14SAndroid Build Coastguard Worker ExitNow();
1193*cfb92d14SAndroid Build Coastguard Worker }
1194*cfb92d14SAndroid Build Coastguard Worker }
1195*cfb92d14SAndroid Build Coastguard Worker
1196*cfb92d14SAndroid Build Coastguard Worker isRequiredAnycast = true;
1197*cfb92d14SAndroid Build Coastguard Worker
1198*cfb92d14SAndroid Build Coastguard Worker exit:
1199*cfb92d14SAndroid Build Coastguard Worker return isRequiredAnycast;
1200*cfb92d14SAndroid Build Coastguard Worker }
1201*cfb92d14SAndroid Build Coastguard Worker #endif // __linux__
1202*cfb92d14SAndroid Build Coastguard Worker
processTransmit(otInstance * aInstance)1203*cfb92d14SAndroid Build Coastguard Worker static void processTransmit(otInstance *aInstance)
1204*cfb92d14SAndroid Build Coastguard Worker {
1205*cfb92d14SAndroid Build Coastguard Worker otMessage *message = nullptr;
1206*cfb92d14SAndroid Build Coastguard Worker ssize_t rval;
1207*cfb92d14SAndroid Build Coastguard Worker char packet[kMaxIp6Size];
1208*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
1209*cfb92d14SAndroid Build Coastguard Worker size_t offset = 0;
1210*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1211*cfb92d14SAndroid Build Coastguard Worker bool isIp4 = false;
1212*cfb92d14SAndroid Build Coastguard Worker #endif
1213*cfb92d14SAndroid Build Coastguard Worker
1214*cfb92d14SAndroid Build Coastguard Worker assert(gInstance == aInstance);
1215*cfb92d14SAndroid Build Coastguard Worker
1216*cfb92d14SAndroid Build Coastguard Worker rval = read(sTunFd, packet, sizeof(packet));
1217*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(rval > 0, error = OT_ERROR_FAILED);
1218*cfb92d14SAndroid Build Coastguard Worker
1219*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1220*cfb92d14SAndroid Build Coastguard Worker // BSD tunnel drivers have (for legacy reasons), may have a 4-byte header on them
1221*cfb92d14SAndroid Build Coastguard Worker if ((rval >= 4) && (packet[0] == 0) && (packet[1] == 0))
1222*cfb92d14SAndroid Build Coastguard Worker {
1223*cfb92d14SAndroid Build Coastguard Worker rval -= 4;
1224*cfb92d14SAndroid Build Coastguard Worker offset = 4;
1225*cfb92d14SAndroid Build Coastguard Worker }
1226*cfb92d14SAndroid Build Coastguard Worker #endif
1227*cfb92d14SAndroid Build Coastguard Worker
1228*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1229*cfb92d14SAndroid Build Coastguard Worker if (tryProcessIcmp6RaMessage(aInstance, reinterpret_cast<uint8_t *>(&packet[offset]), rval) == OT_ERROR_NONE)
1230*cfb92d14SAndroid Build Coastguard Worker {
1231*cfb92d14SAndroid Build Coastguard Worker ExitNow();
1232*cfb92d14SAndroid Build Coastguard Worker }
1233*cfb92d14SAndroid Build Coastguard Worker #endif
1234*cfb92d14SAndroid Build Coastguard Worker
1235*cfb92d14SAndroid Build Coastguard Worker {
1236*cfb92d14SAndroid Build Coastguard Worker otMessageSettings settings;
1237*cfb92d14SAndroid Build Coastguard Worker
1238*cfb92d14SAndroid Build Coastguard Worker settings.mLinkSecurityEnabled = (otThreadGetDeviceRole(aInstance) != OT_DEVICE_ROLE_DISABLED);
1239*cfb92d14SAndroid Build Coastguard Worker settings.mPriority = OT_MESSAGE_PRIORITY_LOW;
1240*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1241*cfb92d14SAndroid Build Coastguard Worker isIp4 = (getIpVersion(reinterpret_cast<uint8_t *>(&packet[offset])) == kIpVersion4);
1242*cfb92d14SAndroid Build Coastguard Worker message = isIp4 ? otIp4NewMessage(aInstance, &settings) : otIp6NewMessage(aInstance, &settings);
1243*cfb92d14SAndroid Build Coastguard Worker #else
1244*cfb92d14SAndroid Build Coastguard Worker message = otIp6NewMessage(aInstance, &settings);
1245*cfb92d14SAndroid Build Coastguard Worker #endif
1246*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
1247*cfb92d14SAndroid Build Coastguard Worker otMessageSetOrigin(message, OT_MESSAGE_ORIGIN_HOST_UNTRUSTED);
1248*cfb92d14SAndroid Build Coastguard Worker }
1249*cfb92d14SAndroid Build Coastguard Worker
1250*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
1251*cfb92d14SAndroid Build Coastguard Worker LogInfo("Packet to NCP (%hu bytes)", static_cast<uint16_t>(rval));
1252*cfb92d14SAndroid Build Coastguard Worker otDumpInfoPlat("", &packet[offset], static_cast<size_t>(rval));
1253*cfb92d14SAndroid Build Coastguard Worker #endif
1254*cfb92d14SAndroid Build Coastguard Worker
1255*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(error = otMessageAppend(message, &packet[offset], static_cast<uint16_t>(rval)));
1256*cfb92d14SAndroid Build Coastguard Worker
1257*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1258*cfb92d14SAndroid Build Coastguard Worker error = isIp4 ? otNat64Send(aInstance, message) : otIp6Send(aInstance, message);
1259*cfb92d14SAndroid Build Coastguard Worker #else
1260*cfb92d14SAndroid Build Coastguard Worker error = otIp6Send(aInstance, message);
1261*cfb92d14SAndroid Build Coastguard Worker #endif
1262*cfb92d14SAndroid Build Coastguard Worker message = nullptr;
1263*cfb92d14SAndroid Build Coastguard Worker
1264*cfb92d14SAndroid Build Coastguard Worker exit:
1265*cfb92d14SAndroid Build Coastguard Worker if (message != nullptr)
1266*cfb92d14SAndroid Build Coastguard Worker {
1267*cfb92d14SAndroid Build Coastguard Worker otMessageFree(message);
1268*cfb92d14SAndroid Build Coastguard Worker }
1269*cfb92d14SAndroid Build Coastguard Worker
1270*cfb92d14SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
1271*cfb92d14SAndroid Build Coastguard Worker {
1272*cfb92d14SAndroid Build Coastguard Worker if (error == OT_ERROR_DROP)
1273*cfb92d14SAndroid Build Coastguard Worker {
1274*cfb92d14SAndroid Build Coastguard Worker LogInfo("Message dropped by Thread");
1275*cfb92d14SAndroid Build Coastguard Worker }
1276*cfb92d14SAndroid Build Coastguard Worker else
1277*cfb92d14SAndroid Build Coastguard Worker {
1278*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to transmit, error:%s", otThreadErrorToString(error));
1279*cfb92d14SAndroid Build Coastguard Worker }
1280*cfb92d14SAndroid Build Coastguard Worker }
1281*cfb92d14SAndroid Build Coastguard Worker }
1282*cfb92d14SAndroid Build Coastguard Worker
logAddrEvent(bool isAdd,const otIp6Address & aAddress,otError error)1283*cfb92d14SAndroid Build Coastguard Worker static void logAddrEvent(bool isAdd, const otIp6Address &aAddress, otError error)
1284*cfb92d14SAndroid Build Coastguard Worker {
1285*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(aAddress);
1286*cfb92d14SAndroid Build Coastguard Worker
1287*cfb92d14SAndroid Build Coastguard Worker if ((error == OT_ERROR_NONE) || ((isAdd) && (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)) ||
1288*cfb92d14SAndroid Build Coastguard Worker ((!isAdd) && (error == OT_ERROR_NOT_FOUND || error == OT_ERROR_REJECTED)))
1289*cfb92d14SAndroid Build Coastguard Worker {
1290*cfb92d14SAndroid Build Coastguard Worker LogInfo("%s [%s] %s%s", isAdd ? "ADD" : "DEL", IsIp6AddressMulticast(aAddress) ? "M" : "U",
1291*cfb92d14SAndroid Build Coastguard Worker Ip6AddressString(&aAddress).AsCString(),
1292*cfb92d14SAndroid Build Coastguard Worker error == OT_ERROR_ALREADY ? " (already subscribed, ignored)"
1293*cfb92d14SAndroid Build Coastguard Worker : error == OT_ERROR_REJECTED ? " (rejected)"
1294*cfb92d14SAndroid Build Coastguard Worker : error == OT_ERROR_NOT_FOUND ? " (not found, ignored)"
1295*cfb92d14SAndroid Build Coastguard Worker : "");
1296*cfb92d14SAndroid Build Coastguard Worker }
1297*cfb92d14SAndroid Build Coastguard Worker else
1298*cfb92d14SAndroid Build Coastguard Worker {
1299*cfb92d14SAndroid Build Coastguard Worker LogWarn("%s [%s] %s failed (%s)", isAdd ? "ADD" : "DEL", IsIp6AddressMulticast(aAddress) ? "M" : "U",
1300*cfb92d14SAndroid Build Coastguard Worker Ip6AddressString(&aAddress).AsCString(), otThreadErrorToString(error));
1301*cfb92d14SAndroid Build Coastguard Worker }
1302*cfb92d14SAndroid Build Coastguard Worker }
1303*cfb92d14SAndroid Build Coastguard Worker
1304*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1305*cfb92d14SAndroid Build Coastguard Worker
processNetifAddrEvent(otInstance * aInstance,struct nlmsghdr * aNetlinkMessage)1306*cfb92d14SAndroid Build Coastguard Worker static void processNetifAddrEvent(otInstance *aInstance, struct nlmsghdr *aNetlinkMessage)
1307*cfb92d14SAndroid Build Coastguard Worker {
1308*cfb92d14SAndroid Build Coastguard Worker struct ifaddrmsg *ifaddr = reinterpret_cast<struct ifaddrmsg *>(NLMSG_DATA(aNetlinkMessage));
1309*cfb92d14SAndroid Build Coastguard Worker size_t rtaLength;
1310*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
1311*cfb92d14SAndroid Build Coastguard Worker struct sockaddr_in6 addr6;
1312*cfb92d14SAndroid Build Coastguard Worker
1313*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ifaddr->ifa_index == static_cast<unsigned int>(gNetifIndex) && ifaddr->ifa_family == AF_INET6);
1314*cfb92d14SAndroid Build Coastguard Worker
1315*cfb92d14SAndroid Build Coastguard Worker rtaLength = IFA_PAYLOAD(aNetlinkMessage);
1316*cfb92d14SAndroid Build Coastguard Worker
1317*cfb92d14SAndroid Build Coastguard Worker for (struct rtattr *rta = reinterpret_cast<struct rtattr *>(IFA_RTA(ifaddr)); RTA_OK(rta, rtaLength);
1318*cfb92d14SAndroid Build Coastguard Worker rta = RTA_NEXT(rta, rtaLength))
1319*cfb92d14SAndroid Build Coastguard Worker {
1320*cfb92d14SAndroid Build Coastguard Worker switch (rta->rta_type)
1321*cfb92d14SAndroid Build Coastguard Worker {
1322*cfb92d14SAndroid Build Coastguard Worker case IFA_ADDRESS:
1323*cfb92d14SAndroid Build Coastguard Worker case IFA_LOCAL:
1324*cfb92d14SAndroid Build Coastguard Worker case IFA_BROADCAST:
1325*cfb92d14SAndroid Build Coastguard Worker case IFA_ANYCAST:
1326*cfb92d14SAndroid Build Coastguard Worker case IFA_MULTICAST:
1327*cfb92d14SAndroid Build Coastguard Worker {
1328*cfb92d14SAndroid Build Coastguard Worker otIp6Address addr;
1329*cfb92d14SAndroid Build Coastguard Worker
1330*cfb92d14SAndroid Build Coastguard Worker ReadIp6AddressFrom(RTA_DATA(rta), addr);
1331*cfb92d14SAndroid Build Coastguard Worker
1332*cfb92d14SAndroid Build Coastguard Worker memset(&addr6, 0, sizeof(addr6));
1333*cfb92d14SAndroid Build Coastguard Worker addr6.sin6_family = AF_INET6;
1334*cfb92d14SAndroid Build Coastguard Worker memcpy(&addr6.sin6_addr, RTA_DATA(rta), sizeof(addr6.sin6_addr));
1335*cfb92d14SAndroid Build Coastguard Worker
1336*cfb92d14SAndroid Build Coastguard Worker // Linux allows adding an IPv6 required anycast address to an interface,
1337*cfb92d14SAndroid Build Coastguard Worker // which blocks openthread deriving an address by SLAAC and will cause routing issues.
1338*cfb92d14SAndroid Build Coastguard Worker // Ignore the required anycast addresses here to allow OpenThread stack generate one when necessary,
1339*cfb92d14SAndroid Build Coastguard Worker // and Linux will prefer the non-required anycast address on the interface.
1340*cfb92d14SAndroid Build Coastguard Worker if (isRequiredAnycast(addr.mFields.m8, ifaddr->ifa_prefixlen))
1341*cfb92d14SAndroid Build Coastguard Worker {
1342*cfb92d14SAndroid Build Coastguard Worker continue;
1343*cfb92d14SAndroid Build Coastguard Worker }
1344*cfb92d14SAndroid Build Coastguard Worker
1345*cfb92d14SAndroid Build Coastguard Worker if (aNetlinkMessage->nlmsg_type == RTM_NEWADDR)
1346*cfb92d14SAndroid Build Coastguard Worker {
1347*cfb92d14SAndroid Build Coastguard Worker if (!IsIp6AddressMulticast(addr))
1348*cfb92d14SAndroid Build Coastguard Worker {
1349*cfb92d14SAndroid Build Coastguard Worker otNetifAddress netAddr;
1350*cfb92d14SAndroid Build Coastguard Worker
1351*cfb92d14SAndroid Build Coastguard Worker netAddr.mAddress = addr;
1352*cfb92d14SAndroid Build Coastguard Worker netAddr.mPrefixLength = ifaddr->ifa_prefixlen;
1353*cfb92d14SAndroid Build Coastguard Worker
1354*cfb92d14SAndroid Build Coastguard Worker error = otIp6AddUnicastAddress(aInstance, &netAddr);
1355*cfb92d14SAndroid Build Coastguard Worker error = (error == OT_ERROR_INVALID_ARGS) ? OT_ERROR_NONE : error;
1356*cfb92d14SAndroid Build Coastguard Worker }
1357*cfb92d14SAndroid Build Coastguard Worker else
1358*cfb92d14SAndroid Build Coastguard Worker {
1359*cfb92d14SAndroid Build Coastguard Worker otNetifMulticastAddress netAddr;
1360*cfb92d14SAndroid Build Coastguard Worker
1361*cfb92d14SAndroid Build Coastguard Worker netAddr.mAddress = addr;
1362*cfb92d14SAndroid Build Coastguard Worker
1363*cfb92d14SAndroid Build Coastguard Worker error = otIp6SubscribeMulticastAddress(aInstance, &addr);
1364*cfb92d14SAndroid Build Coastguard Worker }
1365*cfb92d14SAndroid Build Coastguard Worker
1366*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ true, addr, error);
1367*cfb92d14SAndroid Build Coastguard Worker
1368*cfb92d14SAndroid Build Coastguard Worker if (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)
1369*cfb92d14SAndroid Build Coastguard Worker {
1370*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
1371*cfb92d14SAndroid Build Coastguard Worker }
1372*cfb92d14SAndroid Build Coastguard Worker
1373*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(error);
1374*cfb92d14SAndroid Build Coastguard Worker }
1375*cfb92d14SAndroid Build Coastguard Worker else if (aNetlinkMessage->nlmsg_type == RTM_DELADDR)
1376*cfb92d14SAndroid Build Coastguard Worker {
1377*cfb92d14SAndroid Build Coastguard Worker if (!IsIp6AddressMulticast(addr))
1378*cfb92d14SAndroid Build Coastguard Worker {
1379*cfb92d14SAndroid Build Coastguard Worker error = otIp6RemoveUnicastAddress(aInstance, &addr);
1380*cfb92d14SAndroid Build Coastguard Worker }
1381*cfb92d14SAndroid Build Coastguard Worker else
1382*cfb92d14SAndroid Build Coastguard Worker {
1383*cfb92d14SAndroid Build Coastguard Worker error = otIp6UnsubscribeMulticastAddress(aInstance, &addr);
1384*cfb92d14SAndroid Build Coastguard Worker }
1385*cfb92d14SAndroid Build Coastguard Worker
1386*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ false, addr, error);
1387*cfb92d14SAndroid Build Coastguard Worker
1388*cfb92d14SAndroid Build Coastguard Worker if (error == OT_ERROR_NOT_FOUND || error == OT_ERROR_REJECTED)
1389*cfb92d14SAndroid Build Coastguard Worker {
1390*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
1391*cfb92d14SAndroid Build Coastguard Worker }
1392*cfb92d14SAndroid Build Coastguard Worker
1393*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(error);
1394*cfb92d14SAndroid Build Coastguard Worker }
1395*cfb92d14SAndroid Build Coastguard Worker else
1396*cfb92d14SAndroid Build Coastguard Worker {
1397*cfb92d14SAndroid Build Coastguard Worker continue;
1398*cfb92d14SAndroid Build Coastguard Worker }
1399*cfb92d14SAndroid Build Coastguard Worker break;
1400*cfb92d14SAndroid Build Coastguard Worker }
1401*cfb92d14SAndroid Build Coastguard Worker
1402*cfb92d14SAndroid Build Coastguard Worker default:
1403*cfb92d14SAndroid Build Coastguard Worker LogDebg("Unexpected address type (%d).", (int)rta->rta_type);
1404*cfb92d14SAndroid Build Coastguard Worker break;
1405*cfb92d14SAndroid Build Coastguard Worker }
1406*cfb92d14SAndroid Build Coastguard Worker }
1407*cfb92d14SAndroid Build Coastguard Worker
1408*cfb92d14SAndroid Build Coastguard Worker exit:
1409*cfb92d14SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
1410*cfb92d14SAndroid Build Coastguard Worker {
1411*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to process event, error:%s", otThreadErrorToString(error));
1412*cfb92d14SAndroid Build Coastguard Worker }
1413*cfb92d14SAndroid Build Coastguard Worker }
1414*cfb92d14SAndroid Build Coastguard Worker
processNetifLinkEvent(otInstance * aInstance,struct nlmsghdr * aNetlinkMessage)1415*cfb92d14SAndroid Build Coastguard Worker static void processNetifLinkEvent(otInstance *aInstance, struct nlmsghdr *aNetlinkMessage)
1416*cfb92d14SAndroid Build Coastguard Worker {
1417*cfb92d14SAndroid Build Coastguard Worker struct ifinfomsg *ifinfo = reinterpret_cast<struct ifinfomsg *>(NLMSG_DATA(aNetlinkMessage));
1418*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
1419*cfb92d14SAndroid Build Coastguard Worker bool isUp;
1420*cfb92d14SAndroid Build Coastguard Worker
1421*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ifinfo->ifi_index == static_cast<int>(gNetifIndex) && (ifinfo->ifi_change & IFF_UP));
1422*cfb92d14SAndroid Build Coastguard Worker
1423*cfb92d14SAndroid Build Coastguard Worker isUp = ((ifinfo->ifi_flags & IFF_UP) != 0);
1424*cfb92d14SAndroid Build Coastguard Worker
1425*cfb92d14SAndroid Build Coastguard Worker LogInfo("Host netif is %s", isUp ? "up" : "down");
1426*cfb92d14SAndroid Build Coastguard Worker
1427*cfb92d14SAndroid Build Coastguard Worker #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
1428*cfb92d14SAndroid Build Coastguard Worker if (sIsSyncingState)
1429*cfb92d14SAndroid Build Coastguard Worker {
1430*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(isUp == otIp6IsEnabled(aInstance),
1431*cfb92d14SAndroid Build Coastguard Worker LogWarn("Host netif state notification is unexpected (ignore)"));
1432*cfb92d14SAndroid Build Coastguard Worker sIsSyncingState = false;
1433*cfb92d14SAndroid Build Coastguard Worker }
1434*cfb92d14SAndroid Build Coastguard Worker else
1435*cfb92d14SAndroid Build Coastguard Worker #endif
1436*cfb92d14SAndroid Build Coastguard Worker if (isUp != otIp6IsEnabled(aInstance))
1437*cfb92d14SAndroid Build Coastguard Worker {
1438*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(error = otIp6SetEnabled(aInstance, isUp));
1439*cfb92d14SAndroid Build Coastguard Worker LogInfo("Succeeded to sync netif state with host");
1440*cfb92d14SAndroid Build Coastguard Worker }
1441*cfb92d14SAndroid Build Coastguard Worker
1442*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1443*cfb92d14SAndroid Build Coastguard Worker if (isUp && otNat64GetTranslatorState(gInstance) == OT_NAT64_STATE_ACTIVE)
1444*cfb92d14SAndroid Build Coastguard Worker {
1445*cfb92d14SAndroid Build Coastguard Worker // Recover NAT64 route.
1446*cfb92d14SAndroid Build Coastguard Worker if ((error = AddIp4Route(sActiveNat64Cidr, kNat64RoutePriority)) != OT_ERROR_NONE)
1447*cfb92d14SAndroid Build Coastguard Worker {
1448*cfb92d14SAndroid Build Coastguard Worker LogWarn("failed to add route for NAT64: %s", otThreadErrorToString(error));
1449*cfb92d14SAndroid Build Coastguard Worker }
1450*cfb92d14SAndroid Build Coastguard Worker }
1451*cfb92d14SAndroid Build Coastguard Worker #endif
1452*cfb92d14SAndroid Build Coastguard Worker
1453*cfb92d14SAndroid Build Coastguard Worker exit:
1454*cfb92d14SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
1455*cfb92d14SAndroid Build Coastguard Worker {
1456*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to sync netif state with host: %s", otThreadErrorToString(error));
1457*cfb92d14SAndroid Build Coastguard Worker }
1458*cfb92d14SAndroid Build Coastguard Worker }
1459*cfb92d14SAndroid Build Coastguard Worker #endif // __linux__
1460*cfb92d14SAndroid Build Coastguard Worker
1461*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1462*cfb92d14SAndroid Build Coastguard Worker
1463*cfb92d14SAndroid Build Coastguard Worker #if defined(__FreeBSD__)
1464*cfb92d14SAndroid Build Coastguard Worker #define ROUNDUP(a) ((a) > 0 ? (1 + (((a)-1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
1465*cfb92d14SAndroid Build Coastguard Worker #endif
1466*cfb92d14SAndroid Build Coastguard Worker
1467*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__)
1468*cfb92d14SAndroid Build Coastguard Worker #define ROUNDUP(a) ((a) > 0 ? (1 + (((a)-1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
1469*cfb92d14SAndroid Build Coastguard Worker #define DARWIN_SA_SIZE(sa) ROUNDUP(sa->sa_len)
1470*cfb92d14SAndroid Build Coastguard Worker #define SA_SIZE(sa) DARWIN_SA_SIZE(sa)
1471*cfb92d14SAndroid Build Coastguard Worker #endif
1472*cfb92d14SAndroid Build Coastguard Worker
1473*cfb92d14SAndroid Build Coastguard Worker #if defined(__NetBSD__)
1474*cfb92d14SAndroid Build Coastguard Worker #define RT_ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a)-1U) | ((n)-1))) : (n))
1475*cfb92d14SAndroid Build Coastguard Worker #define RT_ROUNDUP(a) RT_ROUNDUP2((a), sizeof(uint64_t))
1476*cfb92d14SAndroid Build Coastguard Worker #define SA_SIZE(sa) RT_ROUNDUP(sa->sa_len)
1477*cfb92d14SAndroid Build Coastguard Worker #endif
1478*cfb92d14SAndroid Build Coastguard Worker
processNetifAddrEvent(otInstance * aInstance,struct rt_msghdr * rtm)1479*cfb92d14SAndroid Build Coastguard Worker static void processNetifAddrEvent(otInstance *aInstance, struct rt_msghdr *rtm)
1480*cfb92d14SAndroid Build Coastguard Worker {
1481*cfb92d14SAndroid Build Coastguard Worker otError error;
1482*cfb92d14SAndroid Build Coastguard Worker struct ifa_msghdr *ifam;
1483*cfb92d14SAndroid Build Coastguard Worker #ifdef RTM_NEWMADDR
1484*cfb92d14SAndroid Build Coastguard Worker struct ifma_msghdr *ifmam;
1485*cfb92d14SAndroid Build Coastguard Worker #endif
1486*cfb92d14SAndroid Build Coastguard Worker struct sockaddr_in6 addr6;
1487*cfb92d14SAndroid Build Coastguard Worker struct sockaddr_in6 netmask;
1488*cfb92d14SAndroid Build Coastguard Worker uint8_t *addrbuf;
1489*cfb92d14SAndroid Build Coastguard Worker unsigned int addrmask = 0;
1490*cfb92d14SAndroid Build Coastguard Worker unsigned int i;
1491*cfb92d14SAndroid Build Coastguard Worker struct sockaddr *sa;
1492*cfb92d14SAndroid Build Coastguard Worker bool is_link_local;
1493*cfb92d14SAndroid Build Coastguard Worker
1494*cfb92d14SAndroid Build Coastguard Worker addr6.sin6_family = 0;
1495*cfb92d14SAndroid Build Coastguard Worker netmask.sin6_family = 0;
1496*cfb92d14SAndroid Build Coastguard Worker
1497*cfb92d14SAndroid Build Coastguard Worker if ((rtm->rtm_type == RTM_NEWADDR) || (rtm->rtm_type == RTM_DELADDR))
1498*cfb92d14SAndroid Build Coastguard Worker {
1499*cfb92d14SAndroid Build Coastguard Worker ifam = reinterpret_cast<struct ifa_msghdr *>(rtm);
1500*cfb92d14SAndroid Build Coastguard Worker
1501*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ifam->ifam_index == static_cast<unsigned int>(gNetifIndex));
1502*cfb92d14SAndroid Build Coastguard Worker
1503*cfb92d14SAndroid Build Coastguard Worker addrbuf = (uint8_t *)&ifam[1];
1504*cfb92d14SAndroid Build Coastguard Worker addrmask = (unsigned int)ifam->ifam_addrs;
1505*cfb92d14SAndroid Build Coastguard Worker }
1506*cfb92d14SAndroid Build Coastguard Worker #ifdef RTM_NEWMADDR
1507*cfb92d14SAndroid Build Coastguard Worker else if ((rtm->rtm_type == RTM_NEWMADDR) || (rtm->rtm_type == RTM_DELMADDR))
1508*cfb92d14SAndroid Build Coastguard Worker {
1509*cfb92d14SAndroid Build Coastguard Worker ifmam = reinterpret_cast<struct ifma_msghdr *>(rtm);
1510*cfb92d14SAndroid Build Coastguard Worker
1511*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ifmam->ifmam_index == static_cast<unsigned int>(gNetifIndex));
1512*cfb92d14SAndroid Build Coastguard Worker
1513*cfb92d14SAndroid Build Coastguard Worker addrbuf = (uint8_t *)&ifmam[1];
1514*cfb92d14SAndroid Build Coastguard Worker addrmask = (unsigned int)ifmam->ifmam_addrs;
1515*cfb92d14SAndroid Build Coastguard Worker }
1516*cfb92d14SAndroid Build Coastguard Worker #endif
1517*cfb92d14SAndroid Build Coastguard Worker
1518*cfb92d14SAndroid Build Coastguard Worker if (addrmask != 0)
1519*cfb92d14SAndroid Build Coastguard Worker {
1520*cfb92d14SAndroid Build Coastguard Worker for (i = 0; i < RTAX_MAX; i++)
1521*cfb92d14SAndroid Build Coastguard Worker {
1522*cfb92d14SAndroid Build Coastguard Worker unsigned int mask = (addrmask & (1 << i));
1523*cfb92d14SAndroid Build Coastguard Worker if (mask)
1524*cfb92d14SAndroid Build Coastguard Worker {
1525*cfb92d14SAndroid Build Coastguard Worker sa = (struct sockaddr *)addrbuf;
1526*cfb92d14SAndroid Build Coastguard Worker
1527*cfb92d14SAndroid Build Coastguard Worker if (sa->sa_family == AF_INET6)
1528*cfb92d14SAndroid Build Coastguard Worker {
1529*cfb92d14SAndroid Build Coastguard Worker if (i == RTAX_IFA)
1530*cfb92d14SAndroid Build Coastguard Worker memcpy(&addr6, sa, sizeof(sockaddr_in6));
1531*cfb92d14SAndroid Build Coastguard Worker if (i == RTAX_NETMASK)
1532*cfb92d14SAndroid Build Coastguard Worker memcpy(&netmask, sa, sizeof(sockaddr_in6));
1533*cfb92d14SAndroid Build Coastguard Worker }
1534*cfb92d14SAndroid Build Coastguard Worker addrbuf += SA_SIZE(sa);
1535*cfb92d14SAndroid Build Coastguard Worker }
1536*cfb92d14SAndroid Build Coastguard Worker }
1537*cfb92d14SAndroid Build Coastguard Worker }
1538*cfb92d14SAndroid Build Coastguard Worker
1539*cfb92d14SAndroid Build Coastguard Worker if (addr6.sin6_family == AF_INET6)
1540*cfb92d14SAndroid Build Coastguard Worker {
1541*cfb92d14SAndroid Build Coastguard Worker otIp6Address addr;
1542*cfb92d14SAndroid Build Coastguard Worker
1543*cfb92d14SAndroid Build Coastguard Worker is_link_local = false;
1544*cfb92d14SAndroid Build Coastguard Worker
1545*cfb92d14SAndroid Build Coastguard Worker if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr))
1546*cfb92d14SAndroid Build Coastguard Worker {
1547*cfb92d14SAndroid Build Coastguard Worker is_link_local = true;
1548*cfb92d14SAndroid Build Coastguard Worker // clear the scope -- Mac OS X sends this to us (bozos!)
1549*cfb92d14SAndroid Build Coastguard Worker addr6.sin6_addr.s6_addr[3] = 0;
1550*cfb92d14SAndroid Build Coastguard Worker }
1551*cfb92d14SAndroid Build Coastguard Worker else if (IN6_IS_ADDR_MC_LINKLOCAL(&addr6.sin6_addr))
1552*cfb92d14SAndroid Build Coastguard Worker {
1553*cfb92d14SAndroid Build Coastguard Worker addr6.sin6_addr.s6_addr[3] = 0;
1554*cfb92d14SAndroid Build Coastguard Worker }
1555*cfb92d14SAndroid Build Coastguard Worker
1556*cfb92d14SAndroid Build Coastguard Worker ReadIp6AddressFrom(&addr6.sin6_addr, addr);
1557*cfb92d14SAndroid Build Coastguard Worker
1558*cfb92d14SAndroid Build Coastguard Worker if (rtm->rtm_type == RTM_NEWADDR
1559*cfb92d14SAndroid Build Coastguard Worker #ifdef RTM_NEWMADDR
1560*cfb92d14SAndroid Build Coastguard Worker || rtm->rtm_type == RTM_NEWMADDR
1561*cfb92d14SAndroid Build Coastguard Worker #endif
1562*cfb92d14SAndroid Build Coastguard Worker )
1563*cfb92d14SAndroid Build Coastguard Worker {
1564*cfb92d14SAndroid Build Coastguard Worker if (!IsIp6AddressMulticast(addr))
1565*cfb92d14SAndroid Build Coastguard Worker {
1566*cfb92d14SAndroid Build Coastguard Worker otNetifAddress netAddr;
1567*cfb92d14SAndroid Build Coastguard Worker
1568*cfb92d14SAndroid Build Coastguard Worker netAddr.mAddress = addr;
1569*cfb92d14SAndroid Build Coastguard Worker netAddr.mPrefixLength = NetmaskToPrefixLength(&netmask);
1570*cfb92d14SAndroid Build Coastguard Worker
1571*cfb92d14SAndroid Build Coastguard Worker if (otIp6HasUnicastAddress(aInstance, &addr))
1572*cfb92d14SAndroid Build Coastguard Worker {
1573*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ true, addr, OT_ERROR_ALREADY);
1574*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
1575*cfb92d14SAndroid Build Coastguard Worker }
1576*cfb92d14SAndroid Build Coastguard Worker else
1577*cfb92d14SAndroid Build Coastguard Worker {
1578*cfb92d14SAndroid Build Coastguard Worker if (is_link_local)
1579*cfb92d14SAndroid Build Coastguard Worker {
1580*cfb92d14SAndroid Build Coastguard Worker // remove the stack-added link-local address
1581*cfb92d14SAndroid Build Coastguard Worker
1582*cfb92d14SAndroid Build Coastguard Worker int err;
1583*cfb92d14SAndroid Build Coastguard Worker struct in6_aliasreq ifr6;
1584*cfb92d14SAndroid Build Coastguard Worker char addressString[INET6_ADDRSTRLEN + 1];
1585*cfb92d14SAndroid Build Coastguard Worker
1586*cfb92d14SAndroid Build Coastguard Worker OT_UNUSED_VARIABLE(addressString); // if otLog*Plat is disabled, we'll get a warning
1587*cfb92d14SAndroid Build Coastguard Worker
1588*cfb92d14SAndroid Build Coastguard Worker memset(&ifr6, 0, sizeof(ifr6));
1589*cfb92d14SAndroid Build Coastguard Worker strlcpy(ifr6.ifra_name, gNetifName, sizeof(ifr6.ifra_name));
1590*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_addr.sin6_family = AF_INET6;
1591*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_addr.sin6_len = sizeof(ifr6.ifra_addr);
1592*cfb92d14SAndroid Build Coastguard Worker memcpy(&ifr6.ifra_addr.sin6_addr, &addr6.sin6_addr, sizeof(struct in6_addr));
1593*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_prefixmask.sin6_family = AF_INET6;
1594*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_prefixmask.sin6_len = sizeof(ifr6.ifra_prefixmask);
1595*cfb92d14SAndroid Build Coastguard Worker InitNetaskWithPrefixLength(&ifr6.ifra_prefixmask.sin6_addr, netAddr.mPrefixLength);
1596*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
1597*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
1598*cfb92d14SAndroid Build Coastguard Worker
1599*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__)
1600*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_lifetime.ia6t_expire = ND6_INFINITE_LIFETIME;
1601*cfb92d14SAndroid Build Coastguard Worker ifr6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME;
1602*cfb92d14SAndroid Build Coastguard Worker #endif
1603*cfb92d14SAndroid Build Coastguard Worker
1604*cfb92d14SAndroid Build Coastguard Worker err = ioctl(sIpFd, SIOCDIFADDR_IN6, &ifr6);
1605*cfb92d14SAndroid Build Coastguard Worker if (err != 0)
1606*cfb92d14SAndroid Build Coastguard Worker {
1607*cfb92d14SAndroid Build Coastguard Worker LogWarn("Error (%d) removing stack-addded link-local address %s", errno,
1608*cfb92d14SAndroid Build Coastguard Worker inet_ntop(AF_INET6, addr6.sin6_addr.s6_addr, addressString, sizeof(addressString)));
1609*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_FAILED;
1610*cfb92d14SAndroid Build Coastguard Worker }
1611*cfb92d14SAndroid Build Coastguard Worker else
1612*cfb92d14SAndroid Build Coastguard Worker {
1613*cfb92d14SAndroid Build Coastguard Worker LogNote(" %s (removed stack-added link-local)",
1614*cfb92d14SAndroid Build Coastguard Worker inet_ntop(AF_INET6, addr6.sin6_addr.s6_addr, addressString, sizeof(addressString)));
1615*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
1616*cfb92d14SAndroid Build Coastguard Worker }
1617*cfb92d14SAndroid Build Coastguard Worker }
1618*cfb92d14SAndroid Build Coastguard Worker else
1619*cfb92d14SAndroid Build Coastguard Worker {
1620*cfb92d14SAndroid Build Coastguard Worker error = otIp6AddUnicastAddress(aInstance, &netAddr);
1621*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ true, addr, error);
1622*cfb92d14SAndroid Build Coastguard Worker
1623*cfb92d14SAndroid Build Coastguard Worker if (error == OT_ERROR_ALREADY)
1624*cfb92d14SAndroid Build Coastguard Worker {
1625*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
1626*cfb92d14SAndroid Build Coastguard Worker }
1627*cfb92d14SAndroid Build Coastguard Worker }
1628*cfb92d14SAndroid Build Coastguard Worker }
1629*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(error);
1630*cfb92d14SAndroid Build Coastguard Worker }
1631*cfb92d14SAndroid Build Coastguard Worker else
1632*cfb92d14SAndroid Build Coastguard Worker {
1633*cfb92d14SAndroid Build Coastguard Worker otNetifMulticastAddress netAddr;
1634*cfb92d14SAndroid Build Coastguard Worker netAddr.mAddress = addr;
1635*cfb92d14SAndroid Build Coastguard Worker
1636*cfb92d14SAndroid Build Coastguard Worker error = otIp6SubscribeMulticastAddress(aInstance, &addr);
1637*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ true, addr, error);
1638*cfb92d14SAndroid Build Coastguard Worker
1639*cfb92d14SAndroid Build Coastguard Worker if (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)
1640*cfb92d14SAndroid Build Coastguard Worker {
1641*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
1642*cfb92d14SAndroid Build Coastguard Worker }
1643*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(error);
1644*cfb92d14SAndroid Build Coastguard Worker }
1645*cfb92d14SAndroid Build Coastguard Worker }
1646*cfb92d14SAndroid Build Coastguard Worker else if (rtm->rtm_type == RTM_DELADDR
1647*cfb92d14SAndroid Build Coastguard Worker #ifdef RTM_DELMADDR
1648*cfb92d14SAndroid Build Coastguard Worker || rtm->rtm_type == RTM_DELMADDR
1649*cfb92d14SAndroid Build Coastguard Worker #endif
1650*cfb92d14SAndroid Build Coastguard Worker )
1651*cfb92d14SAndroid Build Coastguard Worker {
1652*cfb92d14SAndroid Build Coastguard Worker if (!IsIp6AddressMulticast(addr))
1653*cfb92d14SAndroid Build Coastguard Worker {
1654*cfb92d14SAndroid Build Coastguard Worker error = otIp6RemoveUnicastAddress(aInstance, &addr);
1655*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ false, addr, error);
1656*cfb92d14SAndroid Build Coastguard Worker
1657*cfb92d14SAndroid Build Coastguard Worker if (error == OT_ERROR_NOT_FOUND)
1658*cfb92d14SAndroid Build Coastguard Worker {
1659*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
1660*cfb92d14SAndroid Build Coastguard Worker }
1661*cfb92d14SAndroid Build Coastguard Worker }
1662*cfb92d14SAndroid Build Coastguard Worker else
1663*cfb92d14SAndroid Build Coastguard Worker {
1664*cfb92d14SAndroid Build Coastguard Worker error = otIp6UnsubscribeMulticastAddress(aInstance, &addr);
1665*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ false, addr, error);
1666*cfb92d14SAndroid Build Coastguard Worker
1667*cfb92d14SAndroid Build Coastguard Worker if (error == OT_ERROR_NOT_FOUND)
1668*cfb92d14SAndroid Build Coastguard Worker {
1669*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
1670*cfb92d14SAndroid Build Coastguard Worker }
1671*cfb92d14SAndroid Build Coastguard Worker }
1672*cfb92d14SAndroid Build Coastguard Worker
1673*cfb92d14SAndroid Build Coastguard Worker SuccessOrExit(error);
1674*cfb92d14SAndroid Build Coastguard Worker }
1675*cfb92d14SAndroid Build Coastguard Worker }
1676*cfb92d14SAndroid Build Coastguard Worker
1677*cfb92d14SAndroid Build Coastguard Worker exit:;
1678*cfb92d14SAndroid Build Coastguard Worker }
1679*cfb92d14SAndroid Build Coastguard Worker
processNetifInfoEvent(otInstance * aInstance,struct rt_msghdr * rtm)1680*cfb92d14SAndroid Build Coastguard Worker static void processNetifInfoEvent(otInstance *aInstance, struct rt_msghdr *rtm)
1681*cfb92d14SAndroid Build Coastguard Worker {
1682*cfb92d14SAndroid Build Coastguard Worker struct if_msghdr *ifm = reinterpret_cast<struct if_msghdr *>(rtm);
1683*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
1684*cfb92d14SAndroid Build Coastguard Worker
1685*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ifm->ifm_index == static_cast<int>(gNetifIndex));
1686*cfb92d14SAndroid Build Coastguard Worker
1687*cfb92d14SAndroid Build Coastguard Worker UpdateLink(aInstance);
1688*cfb92d14SAndroid Build Coastguard Worker
1689*cfb92d14SAndroid Build Coastguard Worker exit:
1690*cfb92d14SAndroid Build Coastguard Worker if (error != OT_ERROR_NONE)
1691*cfb92d14SAndroid Build Coastguard Worker {
1692*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to process info event: %s", otThreadErrorToString(error));
1693*cfb92d14SAndroid Build Coastguard Worker }
1694*cfb92d14SAndroid Build Coastguard Worker }
1695*cfb92d14SAndroid Build Coastguard Worker
1696*cfb92d14SAndroid Build Coastguard Worker #endif
1697*cfb92d14SAndroid Build Coastguard Worker
1698*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1699*cfb92d14SAndroid Build Coastguard Worker
1700*cfb92d14SAndroid Build Coastguard Worker #define ERR_RTA(errmsg, requestPayloadLength) \
1701*cfb92d14SAndroid Build Coastguard Worker ((struct rtattr *)((char *)(errmsg)) + NLMSG_ALIGN(sizeof(struct nlmsgerr)) + NLMSG_ALIGN(requestPayloadLength))
1702*cfb92d14SAndroid Build Coastguard Worker
1703*cfb92d14SAndroid Build Coastguard Worker // The format of NLMSG_ERROR is described below:
1704*cfb92d14SAndroid Build Coastguard Worker //
1705*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------
1706*cfb92d14SAndroid Build Coastguard Worker // | struct nlmsghdr - response header |
1707*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------
1708*cfb92d14SAndroid Build Coastguard Worker // | int error | |
1709*cfb92d14SAndroid Build Coastguard Worker // ---------------------------------------------| struct nlmsgerr |
1710*cfb92d14SAndroid Build Coastguard Worker // | struct nlmsghdr - original request header | |
1711*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------------------------
1712*cfb92d14SAndroid Build Coastguard Worker // | ** optionally (1) payload of the request |
1713*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------
1714*cfb92d14SAndroid Build Coastguard Worker // | ** optionally (2) extended ACK attrs |
1715*cfb92d14SAndroid Build Coastguard Worker // ----------------------------------------------
1716*cfb92d14SAndroid Build Coastguard Worker //
HandleNetlinkResponse(struct nlmsghdr * msg)1717*cfb92d14SAndroid Build Coastguard Worker static void HandleNetlinkResponse(struct nlmsghdr *msg)
1718*cfb92d14SAndroid Build Coastguard Worker {
1719*cfb92d14SAndroid Build Coastguard Worker const struct nlmsgerr *err;
1720*cfb92d14SAndroid Build Coastguard Worker const char *errorMsg;
1721*cfb92d14SAndroid Build Coastguard Worker size_t rtaLength;
1722*cfb92d14SAndroid Build Coastguard Worker size_t requestPayloadLength = 0;
1723*cfb92d14SAndroid Build Coastguard Worker uint32_t requestSeq = 0;
1724*cfb92d14SAndroid Build Coastguard Worker
1725*cfb92d14SAndroid Build Coastguard Worker if (msg->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1726*cfb92d14SAndroid Build Coastguard Worker {
1727*cfb92d14SAndroid Build Coastguard Worker LogWarn("Truncated netlink reply of request#%u", requestSeq);
1728*cfb92d14SAndroid Build Coastguard Worker ExitNow();
1729*cfb92d14SAndroid Build Coastguard Worker }
1730*cfb92d14SAndroid Build Coastguard Worker
1731*cfb92d14SAndroid Build Coastguard Worker err = reinterpret_cast<const nlmsgerr *>(NLMSG_DATA(msg));
1732*cfb92d14SAndroid Build Coastguard Worker requestSeq = err->msg.nlmsg_seq;
1733*cfb92d14SAndroid Build Coastguard Worker
1734*cfb92d14SAndroid Build Coastguard Worker if (err->error == 0)
1735*cfb92d14SAndroid Build Coastguard Worker {
1736*cfb92d14SAndroid Build Coastguard Worker LogInfo("Succeeded to process request#%u", requestSeq);
1737*cfb92d14SAndroid Build Coastguard Worker ExitNow();
1738*cfb92d14SAndroid Build Coastguard Worker }
1739*cfb92d14SAndroid Build Coastguard Worker
1740*cfb92d14SAndroid Build Coastguard Worker // For rtnetlink, `abs(err->error)` maps to values of `errno`.
1741*cfb92d14SAndroid Build Coastguard Worker // But this is not a requirement in RFC 3549.
1742*cfb92d14SAndroid Build Coastguard Worker errorMsg = strerror(abs(err->error));
1743*cfb92d14SAndroid Build Coastguard Worker
1744*cfb92d14SAndroid Build Coastguard Worker // The payload of the request is omitted if NLM_F_CAPPED is set
1745*cfb92d14SAndroid Build Coastguard Worker if (!(msg->nlmsg_flags & NLM_F_CAPPED))
1746*cfb92d14SAndroid Build Coastguard Worker {
1747*cfb92d14SAndroid Build Coastguard Worker requestPayloadLength = NLMSG_PAYLOAD(&err->msg, 0);
1748*cfb92d14SAndroid Build Coastguard Worker }
1749*cfb92d14SAndroid Build Coastguard Worker
1750*cfb92d14SAndroid Build Coastguard Worker // Only extract inner TLV error if flag is set
1751*cfb92d14SAndroid Build Coastguard Worker if (msg->nlmsg_flags & NLM_F_ACK_TLVS)
1752*cfb92d14SAndroid Build Coastguard Worker {
1753*cfb92d14SAndroid Build Coastguard Worker rtaLength = NLMSG_PAYLOAD(msg, sizeof(struct nlmsgerr)) - requestPayloadLength;
1754*cfb92d14SAndroid Build Coastguard Worker
1755*cfb92d14SAndroid Build Coastguard Worker for (struct rtattr *rta = ERR_RTA(err, requestPayloadLength); RTA_OK(rta, rtaLength);
1756*cfb92d14SAndroid Build Coastguard Worker rta = RTA_NEXT(rta, rtaLength))
1757*cfb92d14SAndroid Build Coastguard Worker {
1758*cfb92d14SAndroid Build Coastguard Worker if (rta->rta_type == NLMSGERR_ATTR_MSG)
1759*cfb92d14SAndroid Build Coastguard Worker {
1760*cfb92d14SAndroid Build Coastguard Worker errorMsg = reinterpret_cast<const char *>(RTA_DATA(rta));
1761*cfb92d14SAndroid Build Coastguard Worker break;
1762*cfb92d14SAndroid Build Coastguard Worker }
1763*cfb92d14SAndroid Build Coastguard Worker else
1764*cfb92d14SAndroid Build Coastguard Worker {
1765*cfb92d14SAndroid Build Coastguard Worker LogDebg("Ignoring netlink response attribute %d (request#%u)", rta->rta_type, requestSeq);
1766*cfb92d14SAndroid Build Coastguard Worker }
1767*cfb92d14SAndroid Build Coastguard Worker }
1768*cfb92d14SAndroid Build Coastguard Worker }
1769*cfb92d14SAndroid Build Coastguard Worker
1770*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to process request#%u: %s", requestSeq, errorMsg);
1771*cfb92d14SAndroid Build Coastguard Worker
1772*cfb92d14SAndroid Build Coastguard Worker exit:
1773*cfb92d14SAndroid Build Coastguard Worker return;
1774*cfb92d14SAndroid Build Coastguard Worker }
1775*cfb92d14SAndroid Build Coastguard Worker
1776*cfb92d14SAndroid Build Coastguard Worker #endif // __linux__
1777*cfb92d14SAndroid Build Coastguard Worker
processNetlinkEvent(otInstance * aInstance)1778*cfb92d14SAndroid Build Coastguard Worker static void processNetlinkEvent(otInstance *aInstance)
1779*cfb92d14SAndroid Build Coastguard Worker {
1780*cfb92d14SAndroid Build Coastguard Worker const size_t kMaxNetifEvent = 8192;
1781*cfb92d14SAndroid Build Coastguard Worker ssize_t length;
1782*cfb92d14SAndroid Build Coastguard Worker
1783*cfb92d14SAndroid Build Coastguard Worker union
1784*cfb92d14SAndroid Build Coastguard Worker {
1785*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1786*cfb92d14SAndroid Build Coastguard Worker nlmsghdr nlMsg;
1787*cfb92d14SAndroid Build Coastguard Worker #else
1788*cfb92d14SAndroid Build Coastguard Worker rt_msghdr rtMsg;
1789*cfb92d14SAndroid Build Coastguard Worker #endif
1790*cfb92d14SAndroid Build Coastguard Worker char buffer[kMaxNetifEvent];
1791*cfb92d14SAndroid Build Coastguard Worker } msgBuffer;
1792*cfb92d14SAndroid Build Coastguard Worker
1793*cfb92d14SAndroid Build Coastguard Worker length = recv(sNetlinkFd, msgBuffer.buffer, sizeof(msgBuffer.buffer), 0);
1794*cfb92d14SAndroid Build Coastguard Worker
1795*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1796*cfb92d14SAndroid Build Coastguard Worker #define HEADER_SIZE sizeof(nlmsghdr)
1797*cfb92d14SAndroid Build Coastguard Worker #else
1798*cfb92d14SAndroid Build Coastguard Worker #define HEADER_SIZE sizeof(rt_msghdr)
1799*cfb92d14SAndroid Build Coastguard Worker #endif
1800*cfb92d14SAndroid Build Coastguard Worker
1801*cfb92d14SAndroid Build Coastguard Worker // Ensures full netlink header is received
1802*cfb92d14SAndroid Build Coastguard Worker if (length < static_cast<ssize_t>(HEADER_SIZE))
1803*cfb92d14SAndroid Build Coastguard Worker {
1804*cfb92d14SAndroid Build Coastguard Worker LogWarn("Unexpected netlink recv() result: %ld", static_cast<long>(length));
1805*cfb92d14SAndroid Build Coastguard Worker ExitNow();
1806*cfb92d14SAndroid Build Coastguard Worker }
1807*cfb92d14SAndroid Build Coastguard Worker
1808*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1809*cfb92d14SAndroid Build Coastguard Worker for (struct nlmsghdr *msg = &msgBuffer.nlMsg; NLMSG_OK(msg, static_cast<size_t>(length));
1810*cfb92d14SAndroid Build Coastguard Worker msg = NLMSG_NEXT(msg, length))
1811*cfb92d14SAndroid Build Coastguard Worker {
1812*cfb92d14SAndroid Build Coastguard Worker #else
1813*cfb92d14SAndroid Build Coastguard Worker {
1814*cfb92d14SAndroid Build Coastguard Worker // BSD sends one message per read to routing socket (see route.c, monitor command)
1815*cfb92d14SAndroid Build Coastguard Worker struct rt_msghdr *msg;
1816*cfb92d14SAndroid Build Coastguard Worker
1817*cfb92d14SAndroid Build Coastguard Worker msg = &msgBuffer.rtMsg;
1818*cfb92d14SAndroid Build Coastguard Worker
1819*cfb92d14SAndroid Build Coastguard Worker #define nlmsg_type rtm_type
1820*cfb92d14SAndroid Build Coastguard Worker
1821*cfb92d14SAndroid Build Coastguard Worker #endif
1822*cfb92d14SAndroid Build Coastguard Worker switch (msg->nlmsg_type)
1823*cfb92d14SAndroid Build Coastguard Worker {
1824*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1825*cfb92d14SAndroid Build Coastguard Worker case NLMSG_DONE:
1826*cfb92d14SAndroid Build Coastguard Worker // NLMSG_DONE indicates the end of the netlink message, exits now
1827*cfb92d14SAndroid Build Coastguard Worker ExitNow();
1828*cfb92d14SAndroid Build Coastguard Worker #endif
1829*cfb92d14SAndroid Build Coastguard Worker
1830*cfb92d14SAndroid Build Coastguard Worker case RTM_NEWADDR:
1831*cfb92d14SAndroid Build Coastguard Worker case RTM_DELADDR:
1832*cfb92d14SAndroid Build Coastguard Worker processNetifAddrEvent(aInstance, msg);
1833*cfb92d14SAndroid Build Coastguard Worker break;
1834*cfb92d14SAndroid Build Coastguard Worker
1835*cfb92d14SAndroid Build Coastguard Worker #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
1836*cfb92d14SAndroid Build Coastguard Worker case RTM_NEWLINK:
1837*cfb92d14SAndroid Build Coastguard Worker case RTM_DELLINK:
1838*cfb92d14SAndroid Build Coastguard Worker processNetifLinkEvent(aInstance, msg);
1839*cfb92d14SAndroid Build Coastguard Worker break;
1840*cfb92d14SAndroid Build Coastguard Worker #endif
1841*cfb92d14SAndroid Build Coastguard Worker
1842*cfb92d14SAndroid Build Coastguard Worker #if defined(RTM_NEWMADDR) && defined(RTM_DELMADDR)
1843*cfb92d14SAndroid Build Coastguard Worker case RTM_NEWMADDR:
1844*cfb92d14SAndroid Build Coastguard Worker case RTM_DELMADDR:
1845*cfb92d14SAndroid Build Coastguard Worker processNetifAddrEvent(aInstance, msg);
1846*cfb92d14SAndroid Build Coastguard Worker break;
1847*cfb92d14SAndroid Build Coastguard Worker #endif
1848*cfb92d14SAndroid Build Coastguard Worker
1849*cfb92d14SAndroid Build Coastguard Worker #ifndef __linux__
1850*cfb92d14SAndroid Build Coastguard Worker case RTM_IFINFO:
1851*cfb92d14SAndroid Build Coastguard Worker processNetifInfoEvent(aInstance, msg);
1852*cfb92d14SAndroid Build Coastguard Worker break;
1853*cfb92d14SAndroid Build Coastguard Worker
1854*cfb92d14SAndroid Build Coastguard Worker #else
1855*cfb92d14SAndroid Build Coastguard Worker case NLMSG_ERROR:
1856*cfb92d14SAndroid Build Coastguard Worker HandleNetlinkResponse(msg);
1857*cfb92d14SAndroid Build Coastguard Worker break;
1858*cfb92d14SAndroid Build Coastguard Worker #endif
1859*cfb92d14SAndroid Build Coastguard Worker
1860*cfb92d14SAndroid Build Coastguard Worker #if defined(ROUTE_FILTER) || defined(RO_MSGFILTER) || defined(__linux__)
1861*cfb92d14SAndroid Build Coastguard Worker default:
1862*cfb92d14SAndroid Build Coastguard Worker LogWarn("Unhandled/Unexpected netlink/route message (%d).", (int)msg->nlmsg_type);
1863*cfb92d14SAndroid Build Coastguard Worker break;
1864*cfb92d14SAndroid Build Coastguard Worker #else
1865*cfb92d14SAndroid Build Coastguard Worker // this platform doesn't support filtering, so we expect messages of other types...we just ignore them
1866*cfb92d14SAndroid Build Coastguard Worker #endif
1867*cfb92d14SAndroid Build Coastguard Worker }
1868*cfb92d14SAndroid Build Coastguard Worker }
1869*cfb92d14SAndroid Build Coastguard Worker
1870*cfb92d14SAndroid Build Coastguard Worker exit:
1871*cfb92d14SAndroid Build Coastguard Worker return;
1872*cfb92d14SAndroid Build Coastguard Worker }
1873*cfb92d14SAndroid Build Coastguard Worker
1874*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
1875*cfb92d14SAndroid Build Coastguard Worker static void mldListenerInit(void)
1876*cfb92d14SAndroid Build Coastguard Worker {
1877*cfb92d14SAndroid Build Coastguard Worker struct ipv6_mreq mreq6;
1878*cfb92d14SAndroid Build Coastguard Worker
1879*cfb92d14SAndroid Build Coastguard Worker sMLDMonitorFd = SocketWithCloseExec(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, kSocketNonBlock);
1880*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(sMLDMonitorFd != -1, OT_EXIT_FAILURE);
1881*cfb92d14SAndroid Build Coastguard Worker
1882*cfb92d14SAndroid Build Coastguard Worker mreq6.ipv6mr_interface = gNetifIndex;
1883*cfb92d14SAndroid Build Coastguard Worker memcpy(&mreq6.ipv6mr_multiaddr, kMLDv2MulticastAddress.mFields.m8, sizeof(kMLDv2MulticastAddress.mFields.m8));
1884*cfb92d14SAndroid Build Coastguard Worker
1885*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(setsockopt(sMLDMonitorFd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)) == 0, OT_EXIT_FAILURE);
1886*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1887*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(setsockopt(sMLDMonitorFd, SOL_SOCKET, SO_BINDTODEVICE, gNetifName,
1888*cfb92d14SAndroid Build Coastguard Worker static_cast<socklen_t>(strnlen(gNetifName, IFNAMSIZ))) == 0,
1889*cfb92d14SAndroid Build Coastguard Worker OT_EXIT_FAILURE);
1890*cfb92d14SAndroid Build Coastguard Worker #endif
1891*cfb92d14SAndroid Build Coastguard Worker }
1892*cfb92d14SAndroid Build Coastguard Worker
1893*cfb92d14SAndroid Build Coastguard Worker static void processMLDEvent(otInstance *aInstance)
1894*cfb92d14SAndroid Build Coastguard Worker {
1895*cfb92d14SAndroid Build Coastguard Worker const size_t kMaxMLDEvent = 8192;
1896*cfb92d14SAndroid Build Coastguard Worker uint8_t buffer[kMaxMLDEvent];
1897*cfb92d14SAndroid Build Coastguard Worker ssize_t bufferLen = -1;
1898*cfb92d14SAndroid Build Coastguard Worker struct sockaddr_in6 srcAddr;
1899*cfb92d14SAndroid Build Coastguard Worker socklen_t addrLen = sizeof(srcAddr);
1900*cfb92d14SAndroid Build Coastguard Worker bool fromSelf = false;
1901*cfb92d14SAndroid Build Coastguard Worker MLDv2Header *hdr = reinterpret_cast<MLDv2Header *>(buffer);
1902*cfb92d14SAndroid Build Coastguard Worker size_t offset;
1903*cfb92d14SAndroid Build Coastguard Worker uint8_t type;
1904*cfb92d14SAndroid Build Coastguard Worker struct ifaddrs *ifAddrs = nullptr;
1905*cfb92d14SAndroid Build Coastguard Worker char addressString[INET6_ADDRSTRLEN + 1];
1906*cfb92d14SAndroid Build Coastguard Worker
1907*cfb92d14SAndroid Build Coastguard Worker bufferLen = recvfrom(sMLDMonitorFd, buffer, sizeof(buffer), 0, reinterpret_cast<sockaddr *>(&srcAddr), &addrLen);
1908*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(bufferLen > 0);
1909*cfb92d14SAndroid Build Coastguard Worker
1910*cfb92d14SAndroid Build Coastguard Worker type = buffer[0];
1911*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(type == kICMPv6MLDv2Type && bufferLen >= static_cast<ssize_t>(sizeof(MLDv2Header)));
1912*cfb92d14SAndroid Build Coastguard Worker
1913*cfb92d14SAndroid Build Coastguard Worker // Check whether it is sent by self
1914*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(getifaddrs(&ifAddrs) == 0);
1915*cfb92d14SAndroid Build Coastguard Worker for (struct ifaddrs *ifAddr = ifAddrs; ifAddr != nullptr; ifAddr = ifAddr->ifa_next)
1916*cfb92d14SAndroid Build Coastguard Worker {
1917*cfb92d14SAndroid Build Coastguard Worker if (ifAddr->ifa_addr != nullptr && ifAddr->ifa_addr->sa_family == AF_INET6 &&
1918*cfb92d14SAndroid Build Coastguard Worker strncmp(gNetifName, ifAddr->ifa_name, IFNAMSIZ) == 0)
1919*cfb92d14SAndroid Build Coastguard Worker {
1920*cfb92d14SAndroid Build Coastguard Worker #pragma GCC diagnostic push
1921*cfb92d14SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wcast-align"
1922*cfb92d14SAndroid Build Coastguard Worker struct sockaddr_in6 *addr6 = reinterpret_cast<struct sockaddr_in6 *>(ifAddr->ifa_addr);
1923*cfb92d14SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
1924*cfb92d14SAndroid Build Coastguard Worker
1925*cfb92d14SAndroid Build Coastguard Worker if (memcmp(&addr6->sin6_addr, &srcAddr.sin6_addr, sizeof(in6_addr)) == 0)
1926*cfb92d14SAndroid Build Coastguard Worker {
1927*cfb92d14SAndroid Build Coastguard Worker fromSelf = true;
1928*cfb92d14SAndroid Build Coastguard Worker break;
1929*cfb92d14SAndroid Build Coastguard Worker }
1930*cfb92d14SAndroid Build Coastguard Worker }
1931*cfb92d14SAndroid Build Coastguard Worker }
1932*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(fromSelf);
1933*cfb92d14SAndroid Build Coastguard Worker
1934*cfb92d14SAndroid Build Coastguard Worker hdr = reinterpret_cast<MLDv2Header *>(buffer);
1935*cfb92d14SAndroid Build Coastguard Worker offset = sizeof(MLDv2Header);
1936*cfb92d14SAndroid Build Coastguard Worker
1937*cfb92d14SAndroid Build Coastguard Worker for (size_t i = 0; i < ntohs(hdr->mNumRecords) && offset < static_cast<size_t>(bufferLen); i++)
1938*cfb92d14SAndroid Build Coastguard Worker {
1939*cfb92d14SAndroid Build Coastguard Worker if (static_cast<size_t>(bufferLen) >= (sizeof(MLDv2Record) + offset))
1940*cfb92d14SAndroid Build Coastguard Worker {
1941*cfb92d14SAndroid Build Coastguard Worker MLDv2Record *record = reinterpret_cast<MLDv2Record *>(&buffer[offset]);
1942*cfb92d14SAndroid Build Coastguard Worker
1943*cfb92d14SAndroid Build Coastguard Worker otError err;
1944*cfb92d14SAndroid Build Coastguard Worker otIp6Address address;
1945*cfb92d14SAndroid Build Coastguard Worker
1946*cfb92d14SAndroid Build Coastguard Worker ReadIp6AddressFrom(&record->mMulticastAddress, address);
1947*cfb92d14SAndroid Build Coastguard Worker
1948*cfb92d14SAndroid Build Coastguard Worker inet_ntop(AF_INET6, &record->mMulticastAddress, addressString, sizeof(addressString));
1949*cfb92d14SAndroid Build Coastguard Worker
1950*cfb92d14SAndroid Build Coastguard Worker if (record->mRecordType == kICMPv6MLDv2RecordChangeToIncludeType)
1951*cfb92d14SAndroid Build Coastguard Worker {
1952*cfb92d14SAndroid Build Coastguard Worker err = otIp6SubscribeMulticastAddress(aInstance, &address);
1953*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ true, address, err);
1954*cfb92d14SAndroid Build Coastguard Worker }
1955*cfb92d14SAndroid Build Coastguard Worker else if (record->mRecordType == kICMPv6MLDv2RecordChangeToExcludeType)
1956*cfb92d14SAndroid Build Coastguard Worker {
1957*cfb92d14SAndroid Build Coastguard Worker err = otIp6UnsubscribeMulticastAddress(aInstance, &address);
1958*cfb92d14SAndroid Build Coastguard Worker logAddrEvent(/* isAdd */ false, address, err);
1959*cfb92d14SAndroid Build Coastguard Worker }
1960*cfb92d14SAndroid Build Coastguard Worker
1961*cfb92d14SAndroid Build Coastguard Worker offset += sizeof(MLDv2Record) + sizeof(in6_addr) * ntohs(record->mNumSources);
1962*cfb92d14SAndroid Build Coastguard Worker }
1963*cfb92d14SAndroid Build Coastguard Worker }
1964*cfb92d14SAndroid Build Coastguard Worker
1965*cfb92d14SAndroid Build Coastguard Worker exit:
1966*cfb92d14SAndroid Build Coastguard Worker if (ifAddrs)
1967*cfb92d14SAndroid Build Coastguard Worker {
1968*cfb92d14SAndroid Build Coastguard Worker freeifaddrs(ifAddrs);
1969*cfb92d14SAndroid Build Coastguard Worker }
1970*cfb92d14SAndroid Build Coastguard Worker }
1971*cfb92d14SAndroid Build Coastguard Worker #endif
1972*cfb92d14SAndroid Build Coastguard Worker
1973*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
1974*cfb92d14SAndroid Build Coastguard Worker static void SetAddrGenModeToNone(void)
1975*cfb92d14SAndroid Build Coastguard Worker {
1976*cfb92d14SAndroid Build Coastguard Worker struct
1977*cfb92d14SAndroid Build Coastguard Worker {
1978*cfb92d14SAndroid Build Coastguard Worker struct nlmsghdr nh;
1979*cfb92d14SAndroid Build Coastguard Worker struct ifinfomsg ifi;
1980*cfb92d14SAndroid Build Coastguard Worker char buf[512];
1981*cfb92d14SAndroid Build Coastguard Worker } req;
1982*cfb92d14SAndroid Build Coastguard Worker
1983*cfb92d14SAndroid Build Coastguard Worker const uint8_t mode = IN6_ADDR_GEN_MODE_NONE;
1984*cfb92d14SAndroid Build Coastguard Worker
1985*cfb92d14SAndroid Build Coastguard Worker memset(&req, 0, sizeof(req));
1986*cfb92d14SAndroid Build Coastguard Worker
1987*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1988*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1989*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_type = RTM_NEWLINK;
1990*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_pid = 0;
1991*cfb92d14SAndroid Build Coastguard Worker req.nh.nlmsg_seq = ++sNetlinkSequence;
1992*cfb92d14SAndroid Build Coastguard Worker
1993*cfb92d14SAndroid Build Coastguard Worker req.ifi.ifi_index = static_cast<int>(gNetifIndex);
1994*cfb92d14SAndroid Build Coastguard Worker req.ifi.ifi_change = 0xffffffff;
1995*cfb92d14SAndroid Build Coastguard Worker req.ifi.ifi_flags = IFF_MULTICAST | IFF_NOARP;
1996*cfb92d14SAndroid Build Coastguard Worker
1997*cfb92d14SAndroid Build Coastguard Worker {
1998*cfb92d14SAndroid Build Coastguard Worker struct rtattr *afSpec = AddRtAttr(&req.nh, sizeof(req), IFLA_AF_SPEC, 0, 0);
1999*cfb92d14SAndroid Build Coastguard Worker struct rtattr *afInet6 = AddRtAttr(&req.nh, sizeof(req), AF_INET6, 0, 0);
2000*cfb92d14SAndroid Build Coastguard Worker struct rtattr *inet6AddrGenMode =
2001*cfb92d14SAndroid Build Coastguard Worker AddRtAttr(&req.nh, sizeof(req), IFLA_INET6_ADDR_GEN_MODE, &mode, sizeof(mode));
2002*cfb92d14SAndroid Build Coastguard Worker
2003*cfb92d14SAndroid Build Coastguard Worker afInet6->rta_len += inet6AddrGenMode->rta_len;
2004*cfb92d14SAndroid Build Coastguard Worker afSpec->rta_len += afInet6->rta_len;
2005*cfb92d14SAndroid Build Coastguard Worker }
2006*cfb92d14SAndroid Build Coastguard Worker
2007*cfb92d14SAndroid Build Coastguard Worker if (send(sNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
2008*cfb92d14SAndroid Build Coastguard Worker {
2009*cfb92d14SAndroid Build Coastguard Worker LogInfo("Sent request#%u to set addr_gen_mode to %d", sNetlinkSequence, mode);
2010*cfb92d14SAndroid Build Coastguard Worker }
2011*cfb92d14SAndroid Build Coastguard Worker else
2012*cfb92d14SAndroid Build Coastguard Worker {
2013*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to send request#%u to set addr_gen_mode to %d", sNetlinkSequence, mode);
2014*cfb92d14SAndroid Build Coastguard Worker }
2015*cfb92d14SAndroid Build Coastguard Worker }
2016*cfb92d14SAndroid Build Coastguard Worker
2017*cfb92d14SAndroid Build Coastguard Worker // set up the tun device
2018*cfb92d14SAndroid Build Coastguard Worker static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
2019*cfb92d14SAndroid Build Coastguard Worker {
2020*cfb92d14SAndroid Build Coastguard Worker struct ifreq ifr;
2021*cfb92d14SAndroid Build Coastguard Worker const char *interfaceName;
2022*cfb92d14SAndroid Build Coastguard Worker
2023*cfb92d14SAndroid Build Coastguard Worker sTunFd = open(OPENTHREAD_POSIX_TUN_DEVICE, O_RDWR | O_CLOEXEC | O_NONBLOCK);
2024*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
2025*cfb92d14SAndroid Build Coastguard Worker
2026*cfb92d14SAndroid Build Coastguard Worker memset(&ifr, 0, sizeof(ifr));
2027*cfb92d14SAndroid Build Coastguard Worker ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
2028*cfb92d14SAndroid Build Coastguard Worker if (!aPlatformConfig->mPersistentInterface)
2029*cfb92d14SAndroid Build Coastguard Worker {
2030*cfb92d14SAndroid Build Coastguard Worker ifr.ifr_flags |= static_cast<short>(IFF_TUN_EXCL);
2031*cfb92d14SAndroid Build Coastguard Worker }
2032*cfb92d14SAndroid Build Coastguard Worker
2033*cfb92d14SAndroid Build Coastguard Worker interfaceName = aPlatformConfig->mInterfaceName;
2034*cfb92d14SAndroid Build Coastguard Worker if (interfaceName)
2035*cfb92d14SAndroid Build Coastguard Worker {
2036*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(strlen(interfaceName) < IFNAMSIZ, OT_EXIT_INVALID_ARGUMENTS);
2037*cfb92d14SAndroid Build Coastguard Worker
2038*cfb92d14SAndroid Build Coastguard Worker strncpy(ifr.ifr_name, interfaceName, IFNAMSIZ);
2039*cfb92d14SAndroid Build Coastguard Worker }
2040*cfb92d14SAndroid Build Coastguard Worker else
2041*cfb92d14SAndroid Build Coastguard Worker {
2042*cfb92d14SAndroid Build Coastguard Worker strncpy(ifr.ifr_name, "wpan%d", IFNAMSIZ);
2043*cfb92d14SAndroid Build Coastguard Worker }
2044*cfb92d14SAndroid Build Coastguard Worker
2045*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(ioctl(sTunFd, TUNSETIFF, static_cast<void *>(&ifr)) == 0, OT_EXIT_ERROR_ERRNO);
2046*cfb92d14SAndroid Build Coastguard Worker
2047*cfb92d14SAndroid Build Coastguard Worker strncpy(gNetifName, ifr.ifr_name, sizeof(gNetifName));
2048*cfb92d14SAndroid Build Coastguard Worker
2049*cfb92d14SAndroid Build Coastguard Worker if (aPlatformConfig->mPersistentInterface)
2050*cfb92d14SAndroid Build Coastguard Worker {
2051*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(ioctl(sTunFd, TUNSETPERSIST, 1) == 0, OT_EXIT_ERROR_ERRNO);
2052*cfb92d14SAndroid Build Coastguard Worker // Set link down to reset the tun configuration.
2053*cfb92d14SAndroid Build Coastguard Worker // This will drop all existing IP addresses on the interface.
2054*cfb92d14SAndroid Build Coastguard Worker SetLinkState(gInstance, false);
2055*cfb92d14SAndroid Build Coastguard Worker }
2056*cfb92d14SAndroid Build Coastguard Worker
2057*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(ioctl(sTunFd, TUNSETLINK, ARPHRD_NONE) == 0, OT_EXIT_ERROR_ERRNO);
2058*cfb92d14SAndroid Build Coastguard Worker
2059*cfb92d14SAndroid Build Coastguard Worker ifr.ifr_mtu = static_cast<int>(kMaxIp6Size);
2060*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(ioctl(sIpFd, SIOCSIFMTU, static_cast<void *>(&ifr)) == 0, OT_EXIT_ERROR_ERRNO);
2061*cfb92d14SAndroid Build Coastguard Worker }
2062*cfb92d14SAndroid Build Coastguard Worker #endif
2063*cfb92d14SAndroid Build Coastguard Worker
2064*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) && (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN)
2065*cfb92d14SAndroid Build Coastguard Worker static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
2066*cfb92d14SAndroid Build Coastguard Worker {
2067*cfb92d14SAndroid Build Coastguard Worker (void)aPlatformConfig;
2068*cfb92d14SAndroid Build Coastguard Worker int err = 0;
2069*cfb92d14SAndroid Build Coastguard Worker struct sockaddr_ctl addr;
2070*cfb92d14SAndroid Build Coastguard Worker struct ctl_info info;
2071*cfb92d14SAndroid Build Coastguard Worker
2072*cfb92d14SAndroid Build Coastguard Worker sTunFd = SocketWithCloseExec(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL, kSocketNonBlock);
2073*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
2074*cfb92d14SAndroid Build Coastguard Worker
2075*cfb92d14SAndroid Build Coastguard Worker memset(&info, 0, sizeof(info));
2076*cfb92d14SAndroid Build Coastguard Worker strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
2077*cfb92d14SAndroid Build Coastguard Worker err = ioctl(sTunFd, CTLIOCGINFO, &info);
2078*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2079*cfb92d14SAndroid Build Coastguard Worker
2080*cfb92d14SAndroid Build Coastguard Worker addr.sc_id = info.ctl_id;
2081*cfb92d14SAndroid Build Coastguard Worker addr.sc_len = sizeof(addr);
2082*cfb92d14SAndroid Build Coastguard Worker addr.sc_family = AF_SYSTEM;
2083*cfb92d14SAndroid Build Coastguard Worker addr.ss_sysaddr = AF_SYS_CONTROL;
2084*cfb92d14SAndroid Build Coastguard Worker
2085*cfb92d14SAndroid Build Coastguard Worker addr.sc_unit = 0;
2086*cfb92d14SAndroid Build Coastguard Worker err = connect(sTunFd, (struct sockaddr *)&addr, sizeof(addr));
2087*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2088*cfb92d14SAndroid Build Coastguard Worker
2089*cfb92d14SAndroid Build Coastguard Worker socklen_t devNameLen;
2090*cfb92d14SAndroid Build Coastguard Worker devNameLen = (socklen_t)sizeof(gNetifName);
2091*cfb92d14SAndroid Build Coastguard Worker err = getsockopt(sTunFd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, gNetifName, &devNameLen);
2092*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2093*cfb92d14SAndroid Build Coastguard Worker
2094*cfb92d14SAndroid Build Coastguard Worker LogInfo("Tunnel device name = '%s'", gNetifName);
2095*cfb92d14SAndroid Build Coastguard Worker }
2096*cfb92d14SAndroid Build Coastguard Worker #endif
2097*cfb92d14SAndroid Build Coastguard Worker
2098*cfb92d14SAndroid Build Coastguard Worker #if defined(__NetBSD__) || defined(__FreeBSD__)
2099*cfb92d14SAndroid Build Coastguard Worker static otError destroyTunnel(void)
2100*cfb92d14SAndroid Build Coastguard Worker {
2101*cfb92d14SAndroid Build Coastguard Worker otError error;
2102*cfb92d14SAndroid Build Coastguard Worker struct ifreq ifr;
2103*cfb92d14SAndroid Build Coastguard Worker
2104*cfb92d14SAndroid Build Coastguard Worker memset(&ifr, 0, sizeof(ifr));
2105*cfb92d14SAndroid Build Coastguard Worker strncpy(ifr.ifr_name, gNetifName, sizeof(ifr.ifr_name));
2106*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(ioctl(sIpFd, SIOCIFDESTROY, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED);
2107*cfb92d14SAndroid Build Coastguard Worker error = OT_ERROR_NONE;
2108*cfb92d14SAndroid Build Coastguard Worker
2109*cfb92d14SAndroid Build Coastguard Worker exit:
2110*cfb92d14SAndroid Build Coastguard Worker return error;
2111*cfb92d14SAndroid Build Coastguard Worker }
2112*cfb92d14SAndroid Build Coastguard Worker #endif
2113*cfb92d14SAndroid Build Coastguard Worker
2114*cfb92d14SAndroid Build Coastguard Worker #if defined(__NetBSD__) || \
2115*cfb92d14SAndroid Build Coastguard Worker (defined(__APPLE__) && (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN)) || \
2116*cfb92d14SAndroid Build Coastguard Worker defined(__FreeBSD__)
2117*cfb92d14SAndroid Build Coastguard Worker static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
2118*cfb92d14SAndroid Build Coastguard Worker {
2119*cfb92d14SAndroid Build Coastguard Worker int flags = IFF_BROADCAST | IFF_MULTICAST;
2120*cfb92d14SAndroid Build Coastguard Worker int err;
2121*cfb92d14SAndroid Build Coastguard Worker const char *last_slash;
2122*cfb92d14SAndroid Build Coastguard Worker const char *path;
2123*cfb92d14SAndroid Build Coastguard Worker
2124*cfb92d14SAndroid Build Coastguard Worker (void)aPlatformConfig;
2125*cfb92d14SAndroid Build Coastguard Worker
2126*cfb92d14SAndroid Build Coastguard Worker path = OPENTHREAD_POSIX_TUN_DEVICE;
2127*cfb92d14SAndroid Build Coastguard Worker
2128*cfb92d14SAndroid Build Coastguard Worker sTunFd = open(path, O_RDWR | O_NONBLOCK);
2129*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
2130*cfb92d14SAndroid Build Coastguard Worker
2131*cfb92d14SAndroid Build Coastguard Worker #if defined(__NetBSD__) || defined(__FreeBSD__)
2132*cfb92d14SAndroid Build Coastguard Worker err = ioctl(sTunFd, TUNSIFMODE, &flags);
2133*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2134*cfb92d14SAndroid Build Coastguard Worker #endif
2135*cfb92d14SAndroid Build Coastguard Worker
2136*cfb92d14SAndroid Build Coastguard Worker flags = 1;
2137*cfb92d14SAndroid Build Coastguard Worker err = ioctl(sTunFd, TUNSIFHEAD, &flags);
2138*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2139*cfb92d14SAndroid Build Coastguard Worker
2140*cfb92d14SAndroid Build Coastguard Worker last_slash = strrchr(OPENTHREAD_POSIX_TUN_DEVICE, '/');
2141*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(last_slash != nullptr, OT_EXIT_ERROR_ERRNO);
2142*cfb92d14SAndroid Build Coastguard Worker last_slash++;
2143*cfb92d14SAndroid Build Coastguard Worker
2144*cfb92d14SAndroid Build Coastguard Worker strncpy(gNetifName, last_slash, sizeof(gNetifName));
2145*cfb92d14SAndroid Build Coastguard Worker }
2146*cfb92d14SAndroid Build Coastguard Worker #endif
2147*cfb92d14SAndroid Build Coastguard Worker
2148*cfb92d14SAndroid Build Coastguard Worker static void platformConfigureNetLink(void)
2149*cfb92d14SAndroid Build Coastguard Worker {
2150*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
2151*cfb92d14SAndroid Build Coastguard Worker sNetlinkFd = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketNonBlock);
2152*cfb92d14SAndroid Build Coastguard Worker #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
2153*cfb92d14SAndroid Build Coastguard Worker sNetlinkFd = SocketWithCloseExec(PF_ROUTE, SOCK_RAW, 0, kSocketNonBlock);
2154*cfb92d14SAndroid Build Coastguard Worker #else
2155*cfb92d14SAndroid Build Coastguard Worker #error "!! Unknown platform !!"
2156*cfb92d14SAndroid Build Coastguard Worker #endif
2157*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(sNetlinkFd >= 0, OT_EXIT_ERROR_ERRNO);
2158*cfb92d14SAndroid Build Coastguard Worker
2159*cfb92d14SAndroid Build Coastguard Worker #if defined(SOL_NETLINK)
2160*cfb92d14SAndroid Build Coastguard Worker {
2161*cfb92d14SAndroid Build Coastguard Worker int enable = 1;
2162*cfb92d14SAndroid Build Coastguard Worker
2163*cfb92d14SAndroid Build Coastguard Worker #if defined(NETLINK_EXT_ACK)
2164*cfb92d14SAndroid Build Coastguard Worker if (setsockopt(sNetlinkFd, SOL_NETLINK, NETLINK_EXT_ACK, &enable, sizeof(enable)) != 0)
2165*cfb92d14SAndroid Build Coastguard Worker {
2166*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to enable NETLINK_EXT_ACK: %s", strerror(errno));
2167*cfb92d14SAndroid Build Coastguard Worker }
2168*cfb92d14SAndroid Build Coastguard Worker #endif
2169*cfb92d14SAndroid Build Coastguard Worker #if defined(NETLINK_CAP_ACK)
2170*cfb92d14SAndroid Build Coastguard Worker if (setsockopt(sNetlinkFd, SOL_NETLINK, NETLINK_CAP_ACK, &enable, sizeof(enable)) != 0)
2171*cfb92d14SAndroid Build Coastguard Worker {
2172*cfb92d14SAndroid Build Coastguard Worker LogWarn("Failed to enable NETLINK_CAP_ACK: %s", strerror(errno));
2173*cfb92d14SAndroid Build Coastguard Worker }
2174*cfb92d14SAndroid Build Coastguard Worker #endif
2175*cfb92d14SAndroid Build Coastguard Worker }
2176*cfb92d14SAndroid Build Coastguard Worker #endif
2177*cfb92d14SAndroid Build Coastguard Worker
2178*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
2179*cfb92d14SAndroid Build Coastguard Worker {
2180*cfb92d14SAndroid Build Coastguard Worker struct sockaddr_nl sa;
2181*cfb92d14SAndroid Build Coastguard Worker
2182*cfb92d14SAndroid Build Coastguard Worker memset(&sa, 0, sizeof(sa));
2183*cfb92d14SAndroid Build Coastguard Worker sa.nl_family = AF_NETLINK;
2184*cfb92d14SAndroid Build Coastguard Worker sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
2185*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(bind(sNetlinkFd, reinterpret_cast<struct sockaddr *>(&sa), sizeof(sa)) == 0, OT_EXIT_ERROR_ERRNO);
2186*cfb92d14SAndroid Build Coastguard Worker }
2187*cfb92d14SAndroid Build Coastguard Worker #endif
2188*cfb92d14SAndroid Build Coastguard Worker
2189*cfb92d14SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
2190*cfb92d14SAndroid Build Coastguard Worker {
2191*cfb92d14SAndroid Build Coastguard Worker int status;
2192*cfb92d14SAndroid Build Coastguard Worker #ifdef ROUTE_FILTER
2193*cfb92d14SAndroid Build Coastguard Worker unsigned int msgfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR) |
2194*cfb92d14SAndroid Build Coastguard Worker ROUTE_FILTER(RTM_NEWMADDR) | ROUTE_FILTER(RTM_DELMADDR);
2195*cfb92d14SAndroid Build Coastguard Worker #define FILTER_CMD ROUTE_MSGFILTER
2196*cfb92d14SAndroid Build Coastguard Worker #define FILTER_ARG msgfilter
2197*cfb92d14SAndroid Build Coastguard Worker #define FILTER_ARG_SZ sizeof(msgfilter)
2198*cfb92d14SAndroid Build Coastguard Worker #endif
2199*cfb92d14SAndroid Build Coastguard Worker #ifdef RO_MSGFILTER
2200*cfb92d14SAndroid Build Coastguard Worker uint8_t msgfilter[] = {RTM_IFINFO, RTM_NEWADDR, RTM_DELADDR};
2201*cfb92d14SAndroid Build Coastguard Worker #define FILTER_CMD RO_MSGFILTER
2202*cfb92d14SAndroid Build Coastguard Worker #define FILTER_ARG msgfilter
2203*cfb92d14SAndroid Build Coastguard Worker #define FILTER_ARG_SZ sizeof(msgfilter)
2204*cfb92d14SAndroid Build Coastguard Worker #endif
2205*cfb92d14SAndroid Build Coastguard Worker #if defined(ROUTE_FILTER) || defined(RO_MSGFILTER)
2206*cfb92d14SAndroid Build Coastguard Worker status = setsockopt(sNetlinkFd, AF_ROUTE, FILTER_CMD, FILTER_ARG, FILTER_ARG_SZ);
2207*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(status == 0, OT_EXIT_ERROR_ERRNO);
2208*cfb92d14SAndroid Build Coastguard Worker #endif
2209*cfb92d14SAndroid Build Coastguard Worker status = fcntl(sNetlinkFd, F_SETFL, O_NONBLOCK);
2210*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(status == 0, OT_EXIT_ERROR_ERRNO);
2211*cfb92d14SAndroid Build Coastguard Worker }
2212*cfb92d14SAndroid Build Coastguard Worker #endif // defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
2213*cfb92d14SAndroid Build Coastguard Worker }
2214*cfb92d14SAndroid Build Coastguard Worker
2215*cfb92d14SAndroid Build Coastguard Worker void platformNetifInit(otPlatformConfig *aPlatformConfig)
2216*cfb92d14SAndroid Build Coastguard Worker {
2217*cfb92d14SAndroid Build Coastguard Worker // To silence "unused function" warning.
2218*cfb92d14SAndroid Build Coastguard Worker (void)LogCrit;
2219*cfb92d14SAndroid Build Coastguard Worker (void)LogWarn;
2220*cfb92d14SAndroid Build Coastguard Worker (void)LogInfo;
2221*cfb92d14SAndroid Build Coastguard Worker (void)LogNote;
2222*cfb92d14SAndroid Build Coastguard Worker (void)LogDebg;
2223*cfb92d14SAndroid Build Coastguard Worker
2224*cfb92d14SAndroid Build Coastguard Worker sIpFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
2225*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(sIpFd >= 0, OT_EXIT_ERROR_ERRNO);
2226*cfb92d14SAndroid Build Coastguard Worker
2227*cfb92d14SAndroid Build Coastguard Worker platformConfigureNetLink();
2228*cfb92d14SAndroid Build Coastguard Worker platformConfigureTunDevice(aPlatformConfig);
2229*cfb92d14SAndroid Build Coastguard Worker
2230*cfb92d14SAndroid Build Coastguard Worker gNetifIndex = if_nametoindex(gNetifName);
2231*cfb92d14SAndroid Build Coastguard Worker VerifyOrDie(gNetifIndex > 0, OT_EXIT_FAILURE);
2232*cfb92d14SAndroid Build Coastguard Worker
2233*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2234*cfb92d14SAndroid Build Coastguard Worker mldListenerInit();
2235*cfb92d14SAndroid Build Coastguard Worker #endif
2236*cfb92d14SAndroid Build Coastguard Worker
2237*cfb92d14SAndroid Build Coastguard Worker #ifdef __linux__
2238*cfb92d14SAndroid Build Coastguard Worker SetAddrGenModeToNone();
2239*cfb92d14SAndroid Build Coastguard Worker #endif
2240*cfb92d14SAndroid Build Coastguard Worker }
2241*cfb92d14SAndroid Build Coastguard Worker
2242*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
2243*cfb92d14SAndroid Build Coastguard Worker void nat64Init(void)
2244*cfb92d14SAndroid Build Coastguard Worker {
2245*cfb92d14SAndroid Build Coastguard Worker otIp4Cidr cidr;
2246*cfb92d14SAndroid Build Coastguard Worker otError error = OT_ERROR_NONE;
2247*cfb92d14SAndroid Build Coastguard Worker
2248*cfb92d14SAndroid Build Coastguard Worker if (otIp4CidrFromString(OPENTHREAD_POSIX_CONFIG_NAT64_CIDR, &cidr) == OT_ERROR_NONE && cidr.mLength != 0)
2249*cfb92d14SAndroid Build Coastguard Worker {
2250*cfb92d14SAndroid Build Coastguard Worker if ((error = otNat64SetIp4Cidr(gInstance, &cidr)) != OT_ERROR_NONE)
2251*cfb92d14SAndroid Build Coastguard Worker {
2252*cfb92d14SAndroid Build Coastguard Worker LogWarn("failed to set CIDR for NAT64: %s", otThreadErrorToString(error));
2253*cfb92d14SAndroid Build Coastguard Worker }
2254*cfb92d14SAndroid Build Coastguard Worker }
2255*cfb92d14SAndroid Build Coastguard Worker else
2256*cfb92d14SAndroid Build Coastguard Worker {
2257*cfb92d14SAndroid Build Coastguard Worker LogInfo("No default NAT64 CIDR provided.");
2258*cfb92d14SAndroid Build Coastguard Worker }
2259*cfb92d14SAndroid Build Coastguard Worker }
2260*cfb92d14SAndroid Build Coastguard Worker #endif
2261*cfb92d14SAndroid Build Coastguard Worker
2262*cfb92d14SAndroid Build Coastguard Worker void platformNetifSetUp(void)
2263*cfb92d14SAndroid Build Coastguard Worker {
2264*cfb92d14SAndroid Build Coastguard Worker assert(gInstance != nullptr);
2265*cfb92d14SAndroid Build Coastguard Worker
2266*cfb92d14SAndroid Build Coastguard Worker otIp6SetReceiveFilterEnabled(gInstance, true);
2267*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2268*cfb92d14SAndroid Build Coastguard Worker otIcmp6SetEchoMode(gInstance, OT_ICMP6_ECHO_HANDLER_ALL);
2269*cfb92d14SAndroid Build Coastguard Worker #else
2270*cfb92d14SAndroid Build Coastguard Worker otIcmp6SetEchoMode(gInstance, OT_ICMP6_ECHO_HANDLER_DISABLED);
2271*cfb92d14SAndroid Build Coastguard Worker #endif
2272*cfb92d14SAndroid Build Coastguard Worker otIp6SetReceiveCallback(gInstance, processReceive, gInstance);
2273*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
2274*cfb92d14SAndroid Build Coastguard Worker // We can use the same function for IPv6 and translated IPv4 messages.
2275*cfb92d14SAndroid Build Coastguard Worker otNat64SetReceiveIp4Callback(gInstance, processReceive, gInstance);
2276*cfb92d14SAndroid Build Coastguard Worker #endif
2277*cfb92d14SAndroid Build Coastguard Worker otIp6SetAddressCallback(gInstance, processAddressChange, gInstance);
2278*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_MULTICAST_PROMISCUOUS_REQUIRED
2279*cfb92d14SAndroid Build Coastguard Worker otIp6SetMulticastPromiscuousEnabled(aInstance, true);
2280*cfb92d14SAndroid Build Coastguard Worker #endif
2281*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
2282*cfb92d14SAndroid Build Coastguard Worker nat64Init();
2283*cfb92d14SAndroid Build Coastguard Worker #endif
2284*cfb92d14SAndroid Build Coastguard Worker }
2285*cfb92d14SAndroid Build Coastguard Worker
2286*cfb92d14SAndroid Build Coastguard Worker void platformNetifTearDown(void) {}
2287*cfb92d14SAndroid Build Coastguard Worker
2288*cfb92d14SAndroid Build Coastguard Worker void platformNetifDeinit(void)
2289*cfb92d14SAndroid Build Coastguard Worker {
2290*cfb92d14SAndroid Build Coastguard Worker if (sTunFd != -1)
2291*cfb92d14SAndroid Build Coastguard Worker {
2292*cfb92d14SAndroid Build Coastguard Worker close(sTunFd);
2293*cfb92d14SAndroid Build Coastguard Worker sTunFd = -1;
2294*cfb92d14SAndroid Build Coastguard Worker
2295*cfb92d14SAndroid Build Coastguard Worker #if defined(__NetBSD__) || defined(__FreeBSD__)
2296*cfb92d14SAndroid Build Coastguard Worker destroyTunnel();
2297*cfb92d14SAndroid Build Coastguard Worker #endif
2298*cfb92d14SAndroid Build Coastguard Worker }
2299*cfb92d14SAndroid Build Coastguard Worker
2300*cfb92d14SAndroid Build Coastguard Worker if (sIpFd != -1)
2301*cfb92d14SAndroid Build Coastguard Worker {
2302*cfb92d14SAndroid Build Coastguard Worker close(sIpFd);
2303*cfb92d14SAndroid Build Coastguard Worker sIpFd = -1;
2304*cfb92d14SAndroid Build Coastguard Worker }
2305*cfb92d14SAndroid Build Coastguard Worker
2306*cfb92d14SAndroid Build Coastguard Worker if (sNetlinkFd != -1)
2307*cfb92d14SAndroid Build Coastguard Worker {
2308*cfb92d14SAndroid Build Coastguard Worker close(sNetlinkFd);
2309*cfb92d14SAndroid Build Coastguard Worker sNetlinkFd = -1;
2310*cfb92d14SAndroid Build Coastguard Worker }
2311*cfb92d14SAndroid Build Coastguard Worker
2312*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2313*cfb92d14SAndroid Build Coastguard Worker if (sMLDMonitorFd != -1)
2314*cfb92d14SAndroid Build Coastguard Worker {
2315*cfb92d14SAndroid Build Coastguard Worker close(sMLDMonitorFd);
2316*cfb92d14SAndroid Build Coastguard Worker sMLDMonitorFd = -1;
2317*cfb92d14SAndroid Build Coastguard Worker }
2318*cfb92d14SAndroid Build Coastguard Worker #endif
2319*cfb92d14SAndroid Build Coastguard Worker
2320*cfb92d14SAndroid Build Coastguard Worker gNetifIndex = 0;
2321*cfb92d14SAndroid Build Coastguard Worker }
2322*cfb92d14SAndroid Build Coastguard Worker
2323*cfb92d14SAndroid Build Coastguard Worker void platformNetifUpdateFdSet(otSysMainloopContext *aContext)
2324*cfb92d14SAndroid Build Coastguard Worker {
2325*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(gNetifIndex > 0);
2326*cfb92d14SAndroid Build Coastguard Worker
2327*cfb92d14SAndroid Build Coastguard Worker assert(aContext != nullptr);
2328*cfb92d14SAndroid Build Coastguard Worker assert(sTunFd >= 0);
2329*cfb92d14SAndroid Build Coastguard Worker assert(sNetlinkFd >= 0);
2330*cfb92d14SAndroid Build Coastguard Worker assert(sIpFd >= 0);
2331*cfb92d14SAndroid Build Coastguard Worker
2332*cfb92d14SAndroid Build Coastguard Worker FD_SET(sTunFd, &aContext->mReadFdSet);
2333*cfb92d14SAndroid Build Coastguard Worker FD_SET(sTunFd, &aContext->mErrorFdSet);
2334*cfb92d14SAndroid Build Coastguard Worker FD_SET(sNetlinkFd, &aContext->mReadFdSet);
2335*cfb92d14SAndroid Build Coastguard Worker FD_SET(sNetlinkFd, &aContext->mErrorFdSet);
2336*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2337*cfb92d14SAndroid Build Coastguard Worker FD_SET(sMLDMonitorFd, &aContext->mReadFdSet);
2338*cfb92d14SAndroid Build Coastguard Worker FD_SET(sMLDMonitorFd, &aContext->mErrorFdSet);
2339*cfb92d14SAndroid Build Coastguard Worker #endif
2340*cfb92d14SAndroid Build Coastguard Worker
2341*cfb92d14SAndroid Build Coastguard Worker if (sTunFd > aContext->mMaxFd)
2342*cfb92d14SAndroid Build Coastguard Worker {
2343*cfb92d14SAndroid Build Coastguard Worker aContext->mMaxFd = sTunFd;
2344*cfb92d14SAndroid Build Coastguard Worker }
2345*cfb92d14SAndroid Build Coastguard Worker
2346*cfb92d14SAndroid Build Coastguard Worker if (sNetlinkFd > aContext->mMaxFd)
2347*cfb92d14SAndroid Build Coastguard Worker {
2348*cfb92d14SAndroid Build Coastguard Worker aContext->mMaxFd = sNetlinkFd;
2349*cfb92d14SAndroid Build Coastguard Worker }
2350*cfb92d14SAndroid Build Coastguard Worker
2351*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2352*cfb92d14SAndroid Build Coastguard Worker if (sMLDMonitorFd > aContext->mMaxFd)
2353*cfb92d14SAndroid Build Coastguard Worker {
2354*cfb92d14SAndroid Build Coastguard Worker aContext->mMaxFd = sMLDMonitorFd;
2355*cfb92d14SAndroid Build Coastguard Worker }
2356*cfb92d14SAndroid Build Coastguard Worker #endif
2357*cfb92d14SAndroid Build Coastguard Worker exit:
2358*cfb92d14SAndroid Build Coastguard Worker return;
2359*cfb92d14SAndroid Build Coastguard Worker }
2360*cfb92d14SAndroid Build Coastguard Worker
2361*cfb92d14SAndroid Build Coastguard Worker void platformNetifProcess(const otSysMainloopContext *aContext)
2362*cfb92d14SAndroid Build Coastguard Worker {
2363*cfb92d14SAndroid Build Coastguard Worker assert(aContext != nullptr);
2364*cfb92d14SAndroid Build Coastguard Worker VerifyOrExit(gNetifIndex > 0);
2365*cfb92d14SAndroid Build Coastguard Worker
2366*cfb92d14SAndroid Build Coastguard Worker if (FD_ISSET(sTunFd, &aContext->mErrorFdSet))
2367*cfb92d14SAndroid Build Coastguard Worker {
2368*cfb92d14SAndroid Build Coastguard Worker close(sTunFd);
2369*cfb92d14SAndroid Build Coastguard Worker DieNow(OT_EXIT_FAILURE);
2370*cfb92d14SAndroid Build Coastguard Worker }
2371*cfb92d14SAndroid Build Coastguard Worker
2372*cfb92d14SAndroid Build Coastguard Worker if (FD_ISSET(sNetlinkFd, &aContext->mErrorFdSet))
2373*cfb92d14SAndroid Build Coastguard Worker {
2374*cfb92d14SAndroid Build Coastguard Worker close(sNetlinkFd);
2375*cfb92d14SAndroid Build Coastguard Worker DieNow(OT_EXIT_FAILURE);
2376*cfb92d14SAndroid Build Coastguard Worker }
2377*cfb92d14SAndroid Build Coastguard Worker
2378*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2379*cfb92d14SAndroid Build Coastguard Worker if (FD_ISSET(sMLDMonitorFd, &aContext->mErrorFdSet))
2380*cfb92d14SAndroid Build Coastguard Worker {
2381*cfb92d14SAndroid Build Coastguard Worker close(sMLDMonitorFd);
2382*cfb92d14SAndroid Build Coastguard Worker DieNow(OT_EXIT_FAILURE);
2383*cfb92d14SAndroid Build Coastguard Worker }
2384*cfb92d14SAndroid Build Coastguard Worker #endif
2385*cfb92d14SAndroid Build Coastguard Worker
2386*cfb92d14SAndroid Build Coastguard Worker if (FD_ISSET(sTunFd, &aContext->mReadFdSet))
2387*cfb92d14SAndroid Build Coastguard Worker {
2388*cfb92d14SAndroid Build Coastguard Worker processTransmit(gInstance);
2389*cfb92d14SAndroid Build Coastguard Worker }
2390*cfb92d14SAndroid Build Coastguard Worker
2391*cfb92d14SAndroid Build Coastguard Worker if (FD_ISSET(sNetlinkFd, &aContext->mReadFdSet))
2392*cfb92d14SAndroid Build Coastguard Worker {
2393*cfb92d14SAndroid Build Coastguard Worker processNetlinkEvent(gInstance);
2394*cfb92d14SAndroid Build Coastguard Worker }
2395*cfb92d14SAndroid Build Coastguard Worker
2396*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2397*cfb92d14SAndroid Build Coastguard Worker if (FD_ISSET(sMLDMonitorFd, &aContext->mReadFdSet))
2398*cfb92d14SAndroid Build Coastguard Worker {
2399*cfb92d14SAndroid Build Coastguard Worker processMLDEvent(gInstance);
2400*cfb92d14SAndroid Build Coastguard Worker }
2401*cfb92d14SAndroid Build Coastguard Worker #endif
2402*cfb92d14SAndroid Build Coastguard Worker
2403*cfb92d14SAndroid Build Coastguard Worker exit:
2404*cfb92d14SAndroid Build Coastguard Worker return;
2405*cfb92d14SAndroid Build Coastguard Worker }
2406*cfb92d14SAndroid Build Coastguard Worker
2407*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
2408