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