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