xref: /aosp_15_r20/external/openthread/src/posix/platform/netif.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2018, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker /**
30*cfb92d14SAndroid Build Coastguard Worker  * @file
31*cfb92d14SAndroid Build Coastguard Worker  *   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