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 || \
1099     (OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE)
1100 static constexpr uint8_t kIpVersion4 = 4;
1101 static constexpr uint8_t kIpVersion6 = 6;
1102 
getIpVersion(const uint8_t * data)1103 static uint8_t getIpVersion(const uint8_t *data)
1104 {
1105     assert(data != nullptr);
1106 
1107     // Mute compiler warnings.
1108     OT_UNUSED_VARIABLE(kIpVersion4);
1109     OT_UNUSED_VARIABLE(kIpVersion6);
1110 
1111     return (static_cast<uint8_t>(data[0]) >> 4) & 0x0F;
1112 }
1113 #endif
1114 
1115 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1116 
1117 /**
1118  * Returns nullptr if data does not point to a valid ICMPv6 RA message.
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  */
tryProcessIcmp6RaMessage(otInstance * aInstance,const uint8_t * data,ssize_t length)1141 static otError tryProcessIcmp6RaMessage(otInstance *aInstance, const uint8_t *data, ssize_t length)
1142 {
1143     otError        error = OT_ERROR_NONE;
1144     const uint8_t *ra    = getIcmp6RaMessage(data, length);
1145     ssize_t        raLength;
1146 
1147     VerifyOrExit(ra != nullptr, error = OT_ERROR_INVALID_ARGS);
1148 
1149 #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
1150     LogInfo("RA to BorderRouting (%hu bytes)", static_cast<uint16_t>(length));
1151     otDumpInfoPlat("", data, static_cast<size_t>(length));
1152 #endif
1153 
1154     raLength = length + (ra - data);
1155     otPlatBorderRoutingProcessIcmp6Ra(aInstance, ra, raLength);
1156 
1157 exit:
1158     return error;
1159 }
1160 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1161 
1162 #ifdef __linux__
1163 /**
1164  * Returns whether the address is a required anycast address (RFC2373, 2.6.1).
1165  */
isRequiredAnycast(const uint8_t * aAddress,uint8_t aPrefixLength)1166 static bool isRequiredAnycast(const uint8_t *aAddress, uint8_t aPrefixLength)
1167 {
1168     bool    isRequiredAnycast = false;
1169     uint8_t firstBytePos      = aPrefixLength / 8;
1170     uint8_t remainingBits     = aPrefixLength % 8;
1171 
1172     if (aPrefixLength == OT_IP6_ADDRESS_BITSIZE)
1173     {
1174         ExitNow();
1175     }
1176 
1177     if (remainingBits != 0)
1178     {
1179         if ((aAddress[firstBytePos] & ((1 << remainingBits) - 1)) != 0)
1180         {
1181             ExitNow();
1182         }
1183         firstBytePos++;
1184     }
1185 
1186     for (int i = firstBytePos; i < OT_IP6_ADDRESS_SIZE; ++i)
1187     {
1188         if (aAddress[i] != 0)
1189         {
1190             ExitNow();
1191         }
1192     }
1193 
1194     isRequiredAnycast = true;
1195 
1196 exit:
1197     return isRequiredAnycast;
1198 }
1199 #endif // __linux__
1200 
processTransmit(otInstance * aInstance)1201 static void processTransmit(otInstance *aInstance)
1202 {
1203     otMessage *message = nullptr;
1204     ssize_t    rval;
1205     char       packet[kMaxIp6Size];
1206     otError    error  = OT_ERROR_NONE;
1207     size_t     offset = 0;
1208 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1209     bool isIp4 = false;
1210 #endif
1211 
1212     assert(gInstance == aInstance);
1213 
1214     rval = read(sTunFd, packet, sizeof(packet));
1215     VerifyOrExit(rval > 0, error = OT_ERROR_FAILED);
1216 
1217 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1218     // BSD tunnel drivers have (for legacy reasons), may have a 4-byte header on them
1219     if ((rval >= 4) && (packet[0] == 0) && (packet[1] == 0))
1220     {
1221         rval -= 4;
1222         offset = 4;
1223     }
1224 #endif
1225 
1226 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
1227     if (tryProcessIcmp6RaMessage(aInstance, reinterpret_cast<uint8_t *>(&packet[offset]), rval) == OT_ERROR_NONE)
1228     {
1229         ExitNow();
1230     }
1231 #endif
1232 
1233     {
1234         otMessageSettings settings;
1235 
1236         settings.mLinkSecurityEnabled = (otThreadGetDeviceRole(aInstance) != OT_DEVICE_ROLE_DISABLED);
1237         settings.mPriority            = OT_MESSAGE_PRIORITY_LOW;
1238 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1239         isIp4   = (getIpVersion(reinterpret_cast<uint8_t *>(&packet[offset])) == kIpVersion4);
1240         message = isIp4 ? otIp4NewMessage(aInstance, &settings) : otIp6NewMessage(aInstance, &settings);
1241 #else
1242         message = otIp6NewMessage(aInstance, &settings);
1243 #endif
1244         VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
1245         otMessageSetOrigin(message, OT_MESSAGE_ORIGIN_HOST_UNTRUSTED);
1246     }
1247 
1248 #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
1249     LogInfo("Packet to NCP (%hu bytes)", static_cast<uint16_t>(rval));
1250     otDumpInfoPlat("", &packet[offset], static_cast<size_t>(rval));
1251 #endif
1252 
1253     SuccessOrExit(error = otMessageAppend(message, &packet[offset], static_cast<uint16_t>(rval)));
1254 
1255 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1256     error = isIp4 ? otNat64Send(aInstance, message) : otIp6Send(aInstance, message);
1257 #else
1258     error = otIp6Send(aInstance, message);
1259 #endif
1260     message = nullptr;
1261 
1262 exit:
1263     if (message != nullptr)
1264     {
1265         otMessageFree(message);
1266     }
1267 
1268     if (error != OT_ERROR_NONE)
1269     {
1270         if (error == OT_ERROR_DROP)
1271         {
1272             LogInfo("Message dropped by Thread");
1273         }
1274         else
1275         {
1276             LogWarn("Failed to transmit, error:%s", otThreadErrorToString(error));
1277         }
1278     }
1279 }
1280 
logAddrEvent(bool isAdd,const otIp6Address & aAddress,otError error)1281 static void logAddrEvent(bool isAdd, const otIp6Address &aAddress, otError error)
1282 {
1283     OT_UNUSED_VARIABLE(aAddress);
1284 
1285     if ((error == OT_ERROR_NONE) || ((isAdd) && (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)) ||
1286         ((!isAdd) && (error == OT_ERROR_NOT_FOUND || error == OT_ERROR_REJECTED)))
1287     {
1288         LogInfo("%s [%s] %s%s", isAdd ? "ADD" : "DEL", IsIp6AddressMulticast(aAddress) ? "M" : "U",
1289                 Ip6AddressString(&aAddress).AsCString(),
1290                 error == OT_ERROR_ALREADY     ? " (already subscribed, ignored)"
1291                 : error == OT_ERROR_REJECTED  ? " (rejected)"
1292                 : error == OT_ERROR_NOT_FOUND ? " (not found, ignored)"
1293                                               : "");
1294     }
1295     else
1296     {
1297         LogWarn("%s [%s] %s failed (%s)", isAdd ? "ADD" : "DEL", IsIp6AddressMulticast(aAddress) ? "M" : "U",
1298                 Ip6AddressString(&aAddress).AsCString(), otThreadErrorToString(error));
1299     }
1300 }
1301 
1302 #ifdef __linux__
1303 
processNetifAddrEvent(otInstance * aInstance,struct nlmsghdr * aNetlinkMessage)1304 static void processNetifAddrEvent(otInstance *aInstance, struct nlmsghdr *aNetlinkMessage)
1305 {
1306     struct ifaddrmsg   *ifaddr = reinterpret_cast<struct ifaddrmsg *>(NLMSG_DATA(aNetlinkMessage));
1307     size_t              rtaLength;
1308     otError             error = OT_ERROR_NONE;
1309     struct sockaddr_in6 addr6;
1310 
1311     VerifyOrExit(ifaddr->ifa_index == static_cast<unsigned int>(gNetifIndex) && ifaddr->ifa_family == AF_INET6);
1312 
1313     rtaLength = IFA_PAYLOAD(aNetlinkMessage);
1314 
1315     for (struct rtattr *rta = reinterpret_cast<struct rtattr *>(IFA_RTA(ifaddr)); RTA_OK(rta, rtaLength);
1316          rta                = RTA_NEXT(rta, rtaLength))
1317     {
1318         switch (rta->rta_type)
1319         {
1320         case IFA_ADDRESS:
1321         case IFA_LOCAL:
1322         case IFA_BROADCAST:
1323         case IFA_ANYCAST:
1324         case IFA_MULTICAST:
1325         {
1326             otIp6Address addr;
1327 
1328             ReadIp6AddressFrom(RTA_DATA(rta), addr);
1329 
1330             memset(&addr6, 0, sizeof(addr6));
1331             addr6.sin6_family = AF_INET6;
1332             memcpy(&addr6.sin6_addr, RTA_DATA(rta), sizeof(addr6.sin6_addr));
1333 
1334             // Linux allows adding an IPv6 required anycast address to an interface,
1335             // which blocks openthread deriving an address by SLAAC and will cause routing issues.
1336             // Ignore the required anycast addresses here to allow OpenThread stack generate one when necessary,
1337             // and Linux will prefer the non-required anycast address on the interface.
1338             if (isRequiredAnycast(addr.mFields.m8, ifaddr->ifa_prefixlen))
1339             {
1340                 continue;
1341             }
1342 
1343             if (aNetlinkMessage->nlmsg_type == RTM_NEWADDR)
1344             {
1345                 if (!IsIp6AddressMulticast(addr))
1346                 {
1347                     otNetifAddress netAddr;
1348 
1349                     netAddr.mAddress      = addr;
1350                     netAddr.mPrefixLength = ifaddr->ifa_prefixlen;
1351 
1352                     error = otIp6AddUnicastAddress(aInstance, &netAddr);
1353                     error = (error == OT_ERROR_INVALID_ARGS) ? OT_ERROR_NONE : error;
1354                 }
1355                 else
1356                 {
1357                     otNetifMulticastAddress netAddr;
1358 
1359                     netAddr.mAddress = addr;
1360 
1361                     error = otIp6SubscribeMulticastAddress(aInstance, &addr);
1362                 }
1363 
1364                 logAddrEvent(/* isAdd */ true, addr, error);
1365 
1366                 if (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)
1367                 {
1368                     error = OT_ERROR_NONE;
1369                 }
1370 
1371                 SuccessOrExit(error);
1372             }
1373             else if (aNetlinkMessage->nlmsg_type == RTM_DELADDR)
1374             {
1375                 if (!IsIp6AddressMulticast(addr))
1376                 {
1377                     error = otIp6RemoveUnicastAddress(aInstance, &addr);
1378                 }
1379                 else
1380                 {
1381                     error = otIp6UnsubscribeMulticastAddress(aInstance, &addr);
1382                 }
1383 
1384                 logAddrEvent(/* isAdd */ false, addr, error);
1385 
1386                 if (error == OT_ERROR_NOT_FOUND || error == OT_ERROR_REJECTED)
1387                 {
1388                     error = OT_ERROR_NONE;
1389                 }
1390 
1391                 SuccessOrExit(error);
1392             }
1393             else
1394             {
1395                 continue;
1396             }
1397             break;
1398         }
1399 
1400         default:
1401             LogDebg("Unexpected address type (%d).", (int)rta->rta_type);
1402             break;
1403         }
1404     }
1405 
1406 exit:
1407     if (error != OT_ERROR_NONE)
1408     {
1409         LogWarn("Failed to process event, error:%s", otThreadErrorToString(error));
1410     }
1411 }
1412 
processNetifLinkEvent(otInstance * aInstance,struct nlmsghdr * aNetlinkMessage)1413 static void processNetifLinkEvent(otInstance *aInstance, struct nlmsghdr *aNetlinkMessage)
1414 {
1415     struct ifinfomsg *ifinfo = reinterpret_cast<struct ifinfomsg *>(NLMSG_DATA(aNetlinkMessage));
1416     otError           error  = OT_ERROR_NONE;
1417     bool              isUp;
1418 
1419     VerifyOrExit(ifinfo->ifi_index == static_cast<int>(gNetifIndex) && (ifinfo->ifi_change & IFF_UP));
1420 
1421     isUp = ((ifinfo->ifi_flags & IFF_UP) != 0);
1422 
1423     LogInfo("Host netif is %s", isUp ? "up" : "down");
1424 
1425 #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
1426     if (sIsSyncingState)
1427     {
1428         VerifyOrExit(isUp == otIp6IsEnabled(aInstance),
1429                      LogWarn("Host netif state notification is unexpected (ignore)"));
1430         sIsSyncingState = false;
1431     }
1432     else
1433 #endif
1434         if (isUp != otIp6IsEnabled(aInstance))
1435     {
1436         SuccessOrExit(error = otIp6SetEnabled(aInstance, isUp));
1437         LogInfo("Succeeded to sync netif state with host");
1438     }
1439 
1440 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1441     if (isUp && otNat64GetTranslatorState(gInstance) == OT_NAT64_STATE_ACTIVE)
1442     {
1443         // Recover NAT64 route.
1444         if ((error = AddIp4Route(sActiveNat64Cidr, kNat64RoutePriority)) != OT_ERROR_NONE)
1445         {
1446             LogWarn("failed to add route for NAT64: %s", otThreadErrorToString(error));
1447         }
1448     }
1449 #endif
1450 
1451 exit:
1452     if (error != OT_ERROR_NONE)
1453     {
1454         LogWarn("Failed to sync netif state with host: %s", otThreadErrorToString(error));
1455     }
1456 }
1457 #endif // __linux__
1458 
1459 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1460 
1461 #if defined(__FreeBSD__)
1462 #define ROUNDUP(a) ((a) > 0 ? (1 + (((a)-1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
1463 #endif
1464 
1465 #if defined(__APPLE__)
1466 #define ROUNDUP(a) ((a) > 0 ? (1 + (((a)-1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
1467 #define DARWIN_SA_SIZE(sa) ROUNDUP(sa->sa_len)
1468 #define SA_SIZE(sa) DARWIN_SA_SIZE(sa)
1469 #endif
1470 
1471 #if defined(__NetBSD__)
1472 #define RT_ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a)-1U) | ((n)-1))) : (n))
1473 #define RT_ROUNDUP(a) RT_ROUNDUP2((a), sizeof(uint64_t))
1474 #define SA_SIZE(sa) RT_ROUNDUP(sa->sa_len)
1475 #endif
1476 
processNetifAddrEvent(otInstance * aInstance,struct rt_msghdr * rtm)1477 static void processNetifAddrEvent(otInstance *aInstance, struct rt_msghdr *rtm)
1478 {
1479     otError            error;
1480     struct ifa_msghdr *ifam;
1481 #ifdef RTM_NEWMADDR
1482     struct ifma_msghdr *ifmam;
1483 #endif
1484     struct sockaddr_in6 addr6;
1485     struct sockaddr_in6 netmask;
1486     uint8_t            *addrbuf;
1487     unsigned int        addrmask = 0;
1488     unsigned int        i;
1489     struct sockaddr    *sa;
1490     bool                is_link_local;
1491 
1492     addr6.sin6_family   = 0;
1493     netmask.sin6_family = 0;
1494 
1495     if ((rtm->rtm_type == RTM_NEWADDR) || (rtm->rtm_type == RTM_DELADDR))
1496     {
1497         ifam = reinterpret_cast<struct ifa_msghdr *>(rtm);
1498 
1499         VerifyOrExit(ifam->ifam_index == static_cast<unsigned int>(gNetifIndex));
1500 
1501         addrbuf  = (uint8_t *)&ifam[1];
1502         addrmask = (unsigned int)ifam->ifam_addrs;
1503     }
1504 #ifdef RTM_NEWMADDR
1505     else if ((rtm->rtm_type == RTM_NEWMADDR) || (rtm->rtm_type == RTM_DELMADDR))
1506     {
1507         ifmam = reinterpret_cast<struct ifma_msghdr *>(rtm);
1508 
1509         VerifyOrExit(ifmam->ifmam_index == static_cast<unsigned int>(gNetifIndex));
1510 
1511         addrbuf  = (uint8_t *)&ifmam[1];
1512         addrmask = (unsigned int)ifmam->ifmam_addrs;
1513     }
1514 #endif
1515 
1516     if (addrmask != 0)
1517     {
1518         for (i = 0; i < RTAX_MAX; i++)
1519         {
1520             unsigned int mask = (addrmask & (1 << i));
1521             if (mask)
1522             {
1523                 sa = (struct sockaddr *)addrbuf;
1524 
1525                 if (sa->sa_family == AF_INET6)
1526                 {
1527                     if (i == RTAX_IFA)
1528                         memcpy(&addr6, sa, sizeof(sockaddr_in6));
1529                     if (i == RTAX_NETMASK)
1530                         memcpy(&netmask, sa, sizeof(sockaddr_in6));
1531                 }
1532                 addrbuf += SA_SIZE(sa);
1533             }
1534         }
1535     }
1536 
1537     if (addr6.sin6_family == AF_INET6)
1538     {
1539         otIp6Address addr;
1540 
1541         is_link_local = false;
1542 
1543         if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr))
1544         {
1545             is_link_local = true;
1546             // clear the scope -- Mac OS X sends this to us (bozos!)
1547             addr6.sin6_addr.s6_addr[3] = 0;
1548         }
1549         else if (IN6_IS_ADDR_MC_LINKLOCAL(&addr6.sin6_addr))
1550         {
1551             addr6.sin6_addr.s6_addr[3] = 0;
1552         }
1553 
1554         ReadIp6AddressFrom(&addr6.sin6_addr, addr);
1555 
1556         if (rtm->rtm_type == RTM_NEWADDR
1557 #ifdef RTM_NEWMADDR
1558             || rtm->rtm_type == RTM_NEWMADDR
1559 #endif
1560         )
1561         {
1562             if (!IsIp6AddressMulticast(addr))
1563             {
1564                 otNetifAddress netAddr;
1565 
1566                 netAddr.mAddress      = addr;
1567                 netAddr.mPrefixLength = NetmaskToPrefixLength(&netmask);
1568 
1569                 if (otIp6HasUnicastAddress(aInstance, &addr))
1570                 {
1571                     logAddrEvent(/* isAdd */ true, addr, OT_ERROR_ALREADY);
1572                     error = OT_ERROR_NONE;
1573                 }
1574                 else
1575                 {
1576                     if (is_link_local)
1577                     {
1578                         // remove the stack-added link-local address
1579 
1580                         int                 err;
1581                         struct in6_aliasreq ifr6;
1582                         char                addressString[INET6_ADDRSTRLEN + 1];
1583 
1584                         OT_UNUSED_VARIABLE(addressString); // if otLog*Plat is disabled, we'll get a warning
1585 
1586                         memset(&ifr6, 0, sizeof(ifr6));
1587                         strlcpy(ifr6.ifra_name, gNetifName, sizeof(ifr6.ifra_name));
1588                         ifr6.ifra_addr.sin6_family = AF_INET6;
1589                         ifr6.ifra_addr.sin6_len    = sizeof(ifr6.ifra_addr);
1590                         memcpy(&ifr6.ifra_addr.sin6_addr, &addr6.sin6_addr, sizeof(struct in6_addr));
1591                         ifr6.ifra_prefixmask.sin6_family = AF_INET6;
1592                         ifr6.ifra_prefixmask.sin6_len    = sizeof(ifr6.ifra_prefixmask);
1593                         InitNetaskWithPrefixLength(&ifr6.ifra_prefixmask.sin6_addr, netAddr.mPrefixLength);
1594                         ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
1595                         ifr6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
1596 
1597 #if defined(__APPLE__)
1598                         ifr6.ifra_lifetime.ia6t_expire    = ND6_INFINITE_LIFETIME;
1599                         ifr6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME;
1600 #endif
1601 
1602                         err = ioctl(sIpFd, SIOCDIFADDR_IN6, &ifr6);
1603                         if (err != 0)
1604                         {
1605                             LogWarn("Error (%d) removing stack-addded link-local address %s", errno,
1606                                     inet_ntop(AF_INET6, addr6.sin6_addr.s6_addr, addressString, sizeof(addressString)));
1607                             error = OT_ERROR_FAILED;
1608                         }
1609                         else
1610                         {
1611                             LogNote("       %s (removed stack-added link-local)",
1612                                     inet_ntop(AF_INET6, addr6.sin6_addr.s6_addr, addressString, sizeof(addressString)));
1613                             error = OT_ERROR_NONE;
1614                         }
1615                     }
1616                     else
1617                     {
1618                         error = otIp6AddUnicastAddress(aInstance, &netAddr);
1619                         logAddrEvent(/* isAdd */ true, addr, error);
1620 
1621                         if (error == OT_ERROR_ALREADY)
1622                         {
1623                             error = OT_ERROR_NONE;
1624                         }
1625                     }
1626                 }
1627                 SuccessOrExit(error);
1628             }
1629             else
1630             {
1631                 otNetifMulticastAddress netAddr;
1632                 netAddr.mAddress = addr;
1633 
1634                 error = otIp6SubscribeMulticastAddress(aInstance, &addr);
1635                 logAddrEvent(/* isAdd */ true, addr, error);
1636 
1637                 if (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)
1638                 {
1639                     error = OT_ERROR_NONE;
1640                 }
1641                 SuccessOrExit(error);
1642             }
1643         }
1644         else if (rtm->rtm_type == RTM_DELADDR
1645 #ifdef RTM_DELMADDR
1646                  || rtm->rtm_type == RTM_DELMADDR
1647 #endif
1648         )
1649         {
1650             if (!IsIp6AddressMulticast(addr))
1651             {
1652                 error = otIp6RemoveUnicastAddress(aInstance, &addr);
1653                 logAddrEvent(/* isAdd */ false, addr, error);
1654 
1655                 if (error == OT_ERROR_NOT_FOUND)
1656                 {
1657                     error = OT_ERROR_NONE;
1658                 }
1659             }
1660             else
1661             {
1662                 error = otIp6UnsubscribeMulticastAddress(aInstance, &addr);
1663                 logAddrEvent(/* isAdd */ false, addr, error);
1664 
1665                 if (error == OT_ERROR_NOT_FOUND)
1666                 {
1667                     error = OT_ERROR_NONE;
1668                 }
1669             }
1670 
1671             SuccessOrExit(error);
1672         }
1673     }
1674 
1675 exit:;
1676 }
1677 
processNetifInfoEvent(otInstance * aInstance,struct rt_msghdr * rtm)1678 static void processNetifInfoEvent(otInstance *aInstance, struct rt_msghdr *rtm)
1679 {
1680     struct if_msghdr *ifm   = reinterpret_cast<struct if_msghdr *>(rtm);
1681     otError           error = OT_ERROR_NONE;
1682 
1683     VerifyOrExit(ifm->ifm_index == static_cast<int>(gNetifIndex));
1684 
1685     UpdateLink(aInstance);
1686 
1687 exit:
1688     if (error != OT_ERROR_NONE)
1689     {
1690         LogWarn("Failed to process info event: %s", otThreadErrorToString(error));
1691     }
1692 }
1693 
1694 #endif
1695 
1696 #ifdef __linux__
1697 
1698 #define ERR_RTA(errmsg, requestPayloadLength) \
1699     ((struct rtattr *)((char *)(errmsg)) + NLMSG_ALIGN(sizeof(struct nlmsgerr)) + NLMSG_ALIGN(requestPayloadLength))
1700 
1701 // The format of NLMSG_ERROR is described below:
1702 //
1703 // ----------------------------------------------
1704 // | struct nlmsghdr - response header          |
1705 // ----------------------------------------------------------------
1706 // |    int error                               |                 |
1707 // ---------------------------------------------| struct nlmsgerr |
1708 // | struct nlmsghdr - original request header  |                 |
1709 // ----------------------------------------------------------------
1710 // | ** optionally (1) payload of the request   |
1711 // ----------------------------------------------
1712 // | ** optionally (2) extended ACK attrs       |
1713 // ----------------------------------------------
1714 //
HandleNetlinkResponse(struct nlmsghdr * msg)1715 static void HandleNetlinkResponse(struct nlmsghdr *msg)
1716 {
1717     const struct nlmsgerr *err;
1718     const char            *errorMsg;
1719     size_t                 rtaLength;
1720     size_t                 requestPayloadLength = 0;
1721     uint32_t               requestSeq           = 0;
1722 
1723     if (msg->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1724     {
1725         LogWarn("Truncated netlink reply of request#%u", requestSeq);
1726         ExitNow();
1727     }
1728 
1729     err        = reinterpret_cast<const nlmsgerr *>(NLMSG_DATA(msg));
1730     requestSeq = err->msg.nlmsg_seq;
1731 
1732     if (err->error == 0)
1733     {
1734         LogInfo("Succeeded to process request#%u", requestSeq);
1735         ExitNow();
1736     }
1737 
1738     // For rtnetlink, `abs(err->error)` maps to values of `errno`.
1739     // But this is not a requirement in RFC 3549.
1740     errorMsg = strerror(abs(err->error));
1741 
1742     // The payload of the request is omitted if NLM_F_CAPPED is set
1743     if (!(msg->nlmsg_flags & NLM_F_CAPPED))
1744     {
1745         requestPayloadLength = NLMSG_PAYLOAD(&err->msg, 0);
1746     }
1747 
1748     // Only extract inner TLV error if flag is set
1749     if (msg->nlmsg_flags & NLM_F_ACK_TLVS)
1750     {
1751         rtaLength = NLMSG_PAYLOAD(msg, sizeof(struct nlmsgerr)) - requestPayloadLength;
1752 
1753         for (struct rtattr *rta = ERR_RTA(err, requestPayloadLength); RTA_OK(rta, rtaLength);
1754              rta                = RTA_NEXT(rta, rtaLength))
1755         {
1756             if (rta->rta_type == NLMSGERR_ATTR_MSG)
1757             {
1758                 errorMsg = reinterpret_cast<const char *>(RTA_DATA(rta));
1759                 break;
1760             }
1761             else
1762             {
1763                 LogDebg("Ignoring netlink response attribute %d (request#%u)", rta->rta_type, requestSeq);
1764             }
1765         }
1766     }
1767 
1768     LogWarn("Failed to process request#%u: %s", requestSeq, errorMsg);
1769 
1770 exit:
1771     return;
1772 }
1773 
1774 #endif // __linux__
1775 
processNetlinkEvent(otInstance * aInstance)1776 static void processNetlinkEvent(otInstance *aInstance)
1777 {
1778     const size_t kMaxNetifEvent = 8192;
1779     ssize_t      length;
1780 
1781     union
1782     {
1783 #ifdef __linux__
1784         nlmsghdr nlMsg;
1785 #else
1786         rt_msghdr rtMsg;
1787 #endif
1788         char buffer[kMaxNetifEvent];
1789     } msgBuffer;
1790 
1791     length = recv(sNetlinkFd, msgBuffer.buffer, sizeof(msgBuffer.buffer), 0);
1792 
1793 #ifdef __linux__
1794 #define HEADER_SIZE sizeof(nlmsghdr)
1795 #else
1796 #define HEADER_SIZE sizeof(rt_msghdr)
1797 #endif
1798 
1799     // Ensures full netlink header is received
1800     if (length < static_cast<ssize_t>(HEADER_SIZE))
1801     {
1802         LogWarn("Unexpected netlink recv() result: %ld", static_cast<long>(length));
1803         ExitNow();
1804     }
1805 
1806 #ifdef __linux__
1807     for (struct nlmsghdr *msg = &msgBuffer.nlMsg; NLMSG_OK(msg, static_cast<size_t>(length));
1808          msg                  = NLMSG_NEXT(msg, length))
1809     {
1810 #else
1811     {
1812         // BSD sends one message per read to routing socket (see route.c, monitor command)
1813         struct rt_msghdr *msg;
1814 
1815         msg = &msgBuffer.rtMsg;
1816 
1817 #define nlmsg_type rtm_type
1818 
1819 #endif
1820         switch (msg->nlmsg_type)
1821         {
1822 #ifdef __linux__
1823         case NLMSG_DONE:
1824             // NLMSG_DONE indicates the end of the netlink message, exits now
1825             ExitNow();
1826 #endif
1827 
1828         case RTM_NEWADDR:
1829         case RTM_DELADDR:
1830             processNetifAddrEvent(aInstance, msg);
1831             break;
1832 
1833 #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
1834         case RTM_NEWLINK:
1835         case RTM_DELLINK:
1836             processNetifLinkEvent(aInstance, msg);
1837             break;
1838 #endif
1839 
1840 #if defined(RTM_NEWMADDR) && defined(RTM_DELMADDR)
1841         case RTM_NEWMADDR:
1842         case RTM_DELMADDR:
1843             processNetifAddrEvent(aInstance, msg);
1844             break;
1845 #endif
1846 
1847 #ifndef __linux__
1848         case RTM_IFINFO:
1849             processNetifInfoEvent(aInstance, msg);
1850             break;
1851 
1852 #else
1853         case NLMSG_ERROR:
1854             HandleNetlinkResponse(msg);
1855             break;
1856 #endif
1857 
1858 #if defined(ROUTE_FILTER) || defined(RO_MSGFILTER) || defined(__linux__)
1859         default:
1860             LogWarn("Unhandled/Unexpected netlink/route message (%d).", (int)msg->nlmsg_type);
1861             break;
1862 #else
1863             // this platform doesn't support filtering, so we expect messages of other types...we just ignore them
1864 #endif
1865         }
1866     }
1867 
1868 exit:
1869     return;
1870 }
1871 
1872 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
1873 static void mldListenerInit(void)
1874 {
1875     struct ipv6_mreq mreq6;
1876 
1877     sMLDMonitorFd = SocketWithCloseExec(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, kSocketNonBlock);
1878     VerifyOrDie(sMLDMonitorFd != -1, OT_EXIT_FAILURE);
1879 
1880     mreq6.ipv6mr_interface = gNetifIndex;
1881     memcpy(&mreq6.ipv6mr_multiaddr, kMLDv2MulticastAddress.mFields.m8, sizeof(kMLDv2MulticastAddress.mFields.m8));
1882 
1883     VerifyOrDie(setsockopt(sMLDMonitorFd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)) == 0, OT_EXIT_FAILURE);
1884 #ifdef __linux__
1885     VerifyOrDie(setsockopt(sMLDMonitorFd, SOL_SOCKET, SO_BINDTODEVICE, gNetifName,
1886                            static_cast<socklen_t>(strnlen(gNetifName, IFNAMSIZ))) == 0,
1887                 OT_EXIT_FAILURE);
1888 #endif
1889 }
1890 
1891 static void processMLDEvent(otInstance *aInstance)
1892 {
1893     const size_t        kMaxMLDEvent = 8192;
1894     uint8_t             buffer[kMaxMLDEvent];
1895     ssize_t             bufferLen = -1;
1896     struct sockaddr_in6 srcAddr;
1897     socklen_t           addrLen  = sizeof(srcAddr);
1898     bool                fromSelf = false;
1899     MLDv2Header        *hdr      = reinterpret_cast<MLDv2Header *>(buffer);
1900     size_t              offset;
1901     uint8_t             type;
1902     struct ifaddrs     *ifAddrs = nullptr;
1903     char                addressString[INET6_ADDRSTRLEN + 1];
1904 
1905     bufferLen = recvfrom(sMLDMonitorFd, buffer, sizeof(buffer), 0, reinterpret_cast<sockaddr *>(&srcAddr), &addrLen);
1906     VerifyOrExit(bufferLen > 0);
1907 
1908     type = buffer[0];
1909     VerifyOrExit(type == kICMPv6MLDv2Type && bufferLen >= static_cast<ssize_t>(sizeof(MLDv2Header)));
1910 
1911     // Check whether it is sent by self
1912     VerifyOrExit(getifaddrs(&ifAddrs) == 0);
1913     for (struct ifaddrs *ifAddr = ifAddrs; ifAddr != nullptr; ifAddr = ifAddr->ifa_next)
1914     {
1915         if (ifAddr->ifa_addr != nullptr && ifAddr->ifa_addr->sa_family == AF_INET6 &&
1916             strncmp(gNetifName, ifAddr->ifa_name, IFNAMSIZ) == 0)
1917         {
1918 #pragma GCC diagnostic push
1919 #pragma GCC diagnostic ignored "-Wcast-align"
1920             struct sockaddr_in6 *addr6 = reinterpret_cast<struct sockaddr_in6 *>(ifAddr->ifa_addr);
1921 #pragma GCC diagnostic pop
1922 
1923             if (memcmp(&addr6->sin6_addr, &srcAddr.sin6_addr, sizeof(in6_addr)) == 0)
1924             {
1925                 fromSelf = true;
1926                 break;
1927             }
1928         }
1929     }
1930     VerifyOrExit(fromSelf);
1931 
1932     hdr    = reinterpret_cast<MLDv2Header *>(buffer);
1933     offset = sizeof(MLDv2Header);
1934 
1935     for (size_t i = 0; i < ntohs(hdr->mNumRecords) && offset < static_cast<size_t>(bufferLen); i++)
1936     {
1937         if (static_cast<size_t>(bufferLen) >= (sizeof(MLDv2Record) + offset))
1938         {
1939             MLDv2Record *record = reinterpret_cast<MLDv2Record *>(&buffer[offset]);
1940 
1941             otError      err;
1942             otIp6Address address;
1943 
1944             ReadIp6AddressFrom(&record->mMulticastAddress, address);
1945 
1946             inet_ntop(AF_INET6, &record->mMulticastAddress, addressString, sizeof(addressString));
1947 
1948             if (record->mRecordType == kICMPv6MLDv2RecordChangeToIncludeType)
1949             {
1950                 err = otIp6SubscribeMulticastAddress(aInstance, &address);
1951                 logAddrEvent(/* isAdd */ true, address, err);
1952             }
1953             else if (record->mRecordType == kICMPv6MLDv2RecordChangeToExcludeType)
1954             {
1955                 err = otIp6UnsubscribeMulticastAddress(aInstance, &address);
1956                 logAddrEvent(/* isAdd */ false, address, err);
1957             }
1958 
1959             offset += sizeof(MLDv2Record) + sizeof(in6_addr) * ntohs(record->mNumSources);
1960         }
1961     }
1962 
1963 exit:
1964     if (ifAddrs)
1965     {
1966         freeifaddrs(ifAddrs);
1967     }
1968 }
1969 #endif
1970 
1971 #ifdef __linux__
1972 static void SetAddrGenModeToNone(void)
1973 {
1974     struct
1975     {
1976         struct nlmsghdr  nh;
1977         struct ifinfomsg ifi;
1978         char             buf[512];
1979     } req;
1980 
1981     const uint8_t mode = IN6_ADDR_GEN_MODE_NONE;
1982 
1983     memset(&req, 0, sizeof(req));
1984 
1985     req.nh.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1986     req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1987     req.nh.nlmsg_type  = RTM_NEWLINK;
1988     req.nh.nlmsg_pid   = 0;
1989     req.nh.nlmsg_seq   = ++sNetlinkSequence;
1990 
1991     req.ifi.ifi_index  = static_cast<int>(gNetifIndex);
1992     req.ifi.ifi_change = 0xffffffff;
1993     req.ifi.ifi_flags  = IFF_MULTICAST | IFF_NOARP;
1994 
1995     {
1996         struct rtattr *afSpec  = AddRtAttr(&req.nh, sizeof(req), IFLA_AF_SPEC, 0, 0);
1997         struct rtattr *afInet6 = AddRtAttr(&req.nh, sizeof(req), AF_INET6, 0, 0);
1998         struct rtattr *inet6AddrGenMode =
1999             AddRtAttr(&req.nh, sizeof(req), IFLA_INET6_ADDR_GEN_MODE, &mode, sizeof(mode));
2000 
2001         afInet6->rta_len += inet6AddrGenMode->rta_len;
2002         afSpec->rta_len += afInet6->rta_len;
2003     }
2004 
2005     if (send(sNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
2006     {
2007         LogInfo("Sent request#%u to set addr_gen_mode to %d", sNetlinkSequence, mode);
2008     }
2009     else
2010     {
2011         LogWarn("Failed to send request#%u to set addr_gen_mode to %d", sNetlinkSequence, mode);
2012     }
2013 }
2014 
2015 // set up the tun device
2016 static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
2017 {
2018     struct ifreq ifr;
2019     const char  *interfaceName;
2020 
2021     sTunFd = open(OPENTHREAD_POSIX_TUN_DEVICE, O_RDWR | O_CLOEXEC | O_NONBLOCK);
2022     VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
2023 
2024     memset(&ifr, 0, sizeof(ifr));
2025     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
2026     if (!aPlatformConfig->mPersistentInterface)
2027     {
2028         ifr.ifr_flags |= static_cast<short>(IFF_TUN_EXCL);
2029     }
2030 
2031     interfaceName = aPlatformConfig->mInterfaceName;
2032     if (interfaceName)
2033     {
2034         VerifyOrDie(strlen(interfaceName) < IFNAMSIZ, OT_EXIT_INVALID_ARGUMENTS);
2035 
2036         strncpy(ifr.ifr_name, interfaceName, IFNAMSIZ);
2037     }
2038     else
2039     {
2040         strncpy(ifr.ifr_name, "wpan%d", IFNAMSIZ);
2041     }
2042 
2043     VerifyOrDie(ioctl(sTunFd, TUNSETIFF, static_cast<void *>(&ifr)) == 0, OT_EXIT_ERROR_ERRNO);
2044 
2045     strncpy(gNetifName, ifr.ifr_name, sizeof(gNetifName));
2046 
2047     if (aPlatformConfig->mPersistentInterface)
2048     {
2049         VerifyOrDie(ioctl(sTunFd, TUNSETPERSIST, 1) == 0, OT_EXIT_ERROR_ERRNO);
2050         // Set link down to reset the tun configuration.
2051         // This will drop all existing IP addresses on the interface.
2052         SetLinkState(gInstance, false);
2053     }
2054 
2055     VerifyOrDie(ioctl(sTunFd, TUNSETLINK, ARPHRD_NONE) == 0, OT_EXIT_ERROR_ERRNO);
2056 
2057     ifr.ifr_mtu = static_cast<int>(kMaxIp6Size);
2058     VerifyOrDie(ioctl(sIpFd, SIOCSIFMTU, static_cast<void *>(&ifr)) == 0, OT_EXIT_ERROR_ERRNO);
2059 }
2060 #endif
2061 
2062 #if defined(__APPLE__) && (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN)
2063 static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
2064 {
2065     (void)aPlatformConfig;
2066     int                 err = 0;
2067     struct sockaddr_ctl addr;
2068     struct ctl_info     info;
2069 
2070     sTunFd = SocketWithCloseExec(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL, kSocketNonBlock);
2071     VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
2072 
2073     memset(&info, 0, sizeof(info));
2074     strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
2075     err = ioctl(sTunFd, CTLIOCGINFO, &info);
2076     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2077 
2078     addr.sc_id      = info.ctl_id;
2079     addr.sc_len     = sizeof(addr);
2080     addr.sc_family  = AF_SYSTEM;
2081     addr.ss_sysaddr = AF_SYS_CONTROL;
2082 
2083     addr.sc_unit = 0;
2084     err          = connect(sTunFd, (struct sockaddr *)&addr, sizeof(addr));
2085     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2086 
2087     socklen_t devNameLen;
2088     devNameLen = (socklen_t)sizeof(gNetifName);
2089     err        = getsockopt(sTunFd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, gNetifName, &devNameLen);
2090     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2091 
2092     LogInfo("Tunnel device name = '%s'", gNetifName);
2093 }
2094 #endif
2095 
2096 #if defined(__NetBSD__) || defined(__FreeBSD__)
2097 static otError destroyTunnel(void)
2098 {
2099     otError      error;
2100     struct ifreq ifr;
2101 
2102     memset(&ifr, 0, sizeof(ifr));
2103     strncpy(ifr.ifr_name, gNetifName, sizeof(ifr.ifr_name));
2104     VerifyOrExit(ioctl(sIpFd, SIOCIFDESTROY, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED);
2105     error = OT_ERROR_NONE;
2106 
2107 exit:
2108     return error;
2109 }
2110 #endif
2111 
2112 #if defined(__NetBSD__) ||                                                                             \
2113     (defined(__APPLE__) && (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN)) || \
2114     defined(__FreeBSD__)
2115 static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
2116 {
2117     int         flags = IFF_BROADCAST | IFF_MULTICAST;
2118     int         err;
2119     const char *last_slash;
2120     const char *path;
2121 
2122     (void)aPlatformConfig;
2123 
2124     path = OPENTHREAD_POSIX_TUN_DEVICE;
2125 
2126     sTunFd = open(path, O_RDWR | O_NONBLOCK);
2127     VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
2128 
2129 #if defined(__NetBSD__) || defined(__FreeBSD__)
2130     err = ioctl(sTunFd, TUNSIFMODE, &flags);
2131     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2132 #endif
2133 
2134     flags = 1;
2135     err   = ioctl(sTunFd, TUNSIFHEAD, &flags);
2136     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
2137 
2138     last_slash = strrchr(OPENTHREAD_POSIX_TUN_DEVICE, '/');
2139     VerifyOrDie(last_slash != nullptr, OT_EXIT_ERROR_ERRNO);
2140     last_slash++;
2141 
2142     strncpy(gNetifName, last_slash, sizeof(gNetifName));
2143 }
2144 #endif
2145 
2146 static void platformConfigureNetLink(void)
2147 {
2148 #ifdef __linux__
2149     sNetlinkFd = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketNonBlock);
2150 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
2151     sNetlinkFd = SocketWithCloseExec(PF_ROUTE, SOCK_RAW, 0, kSocketNonBlock);
2152 #else
2153 #error "!! Unknown platform !!"
2154 #endif
2155     VerifyOrDie(sNetlinkFd >= 0, OT_EXIT_ERROR_ERRNO);
2156 
2157 #if defined(SOL_NETLINK)
2158     {
2159         int enable = 1;
2160 
2161 #if defined(NETLINK_EXT_ACK)
2162         if (setsockopt(sNetlinkFd, SOL_NETLINK, NETLINK_EXT_ACK, &enable, sizeof(enable)) != 0)
2163         {
2164             LogWarn("Failed to enable NETLINK_EXT_ACK: %s", strerror(errno));
2165         }
2166 #endif
2167 #if defined(NETLINK_CAP_ACK)
2168         if (setsockopt(sNetlinkFd, SOL_NETLINK, NETLINK_CAP_ACK, &enable, sizeof(enable)) != 0)
2169         {
2170             LogWarn("Failed to enable NETLINK_CAP_ACK: %s", strerror(errno));
2171         }
2172 #endif
2173     }
2174 #endif
2175 
2176 #ifdef __linux__
2177     {
2178         struct sockaddr_nl sa;
2179 
2180         memset(&sa, 0, sizeof(sa));
2181         sa.nl_family = AF_NETLINK;
2182         sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
2183         VerifyOrDie(bind(sNetlinkFd, reinterpret_cast<struct sockaddr *>(&sa), sizeof(sa)) == 0, OT_EXIT_ERROR_ERRNO);
2184     }
2185 #endif
2186 
2187 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
2188     {
2189         int status;
2190 #ifdef ROUTE_FILTER
2191         unsigned int msgfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR) |
2192                                  ROUTE_FILTER(RTM_NEWMADDR) | ROUTE_FILTER(RTM_DELMADDR);
2193 #define FILTER_CMD ROUTE_MSGFILTER
2194 #define FILTER_ARG msgfilter
2195 #define FILTER_ARG_SZ sizeof(msgfilter)
2196 #endif
2197 #ifdef RO_MSGFILTER
2198         uint8_t msgfilter[] = {RTM_IFINFO, RTM_NEWADDR, RTM_DELADDR};
2199 #define FILTER_CMD RO_MSGFILTER
2200 #define FILTER_ARG msgfilter
2201 #define FILTER_ARG_SZ sizeof(msgfilter)
2202 #endif
2203 #if defined(ROUTE_FILTER) || defined(RO_MSGFILTER)
2204         status = setsockopt(sNetlinkFd, AF_ROUTE, FILTER_CMD, FILTER_ARG, FILTER_ARG_SZ);
2205         VerifyOrDie(status == 0, OT_EXIT_ERROR_ERRNO);
2206 #endif
2207         status = fcntl(sNetlinkFd, F_SETFL, O_NONBLOCK);
2208         VerifyOrDie(status == 0, OT_EXIT_ERROR_ERRNO);
2209     }
2210 #endif // defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
2211 }
2212 
2213 void platformNetifInit(otPlatformConfig *aPlatformConfig)
2214 {
2215     // To silence "unused function" warning.
2216     (void)LogCrit;
2217     (void)LogWarn;
2218     (void)LogInfo;
2219     (void)LogNote;
2220     (void)LogDebg;
2221 
2222     sIpFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
2223     VerifyOrDie(sIpFd >= 0, OT_EXIT_ERROR_ERRNO);
2224 
2225     platformConfigureNetLink();
2226     platformConfigureTunDevice(aPlatformConfig);
2227 
2228     gNetifIndex = if_nametoindex(gNetifName);
2229     VerifyOrDie(gNetifIndex > 0, OT_EXIT_FAILURE);
2230 
2231 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2232     mldListenerInit();
2233 #endif
2234 
2235 #ifdef __linux__
2236     SetAddrGenModeToNone();
2237 #endif
2238 }
2239 
2240 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
2241 void nat64Init(void)
2242 {
2243     otIp4Cidr cidr;
2244     otError   error = OT_ERROR_NONE;
2245 
2246     if (otIp4CidrFromString(OPENTHREAD_POSIX_CONFIG_NAT64_CIDR, &cidr) == OT_ERROR_NONE && cidr.mLength != 0)
2247     {
2248         if ((error = otNat64SetIp4Cidr(gInstance, &cidr)) != OT_ERROR_NONE)
2249         {
2250             LogWarn("failed to set CIDR for NAT64: %s", otThreadErrorToString(error));
2251         }
2252     }
2253     else
2254     {
2255         LogInfo("No default NAT64 CIDR provided.");
2256     }
2257 }
2258 #endif
2259 
2260 void platformNetifSetUp(void)
2261 {
2262     assert(gInstance != nullptr);
2263 
2264     otIp6SetReceiveFilterEnabled(gInstance, true);
2265 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2266     otIcmp6SetEchoMode(gInstance, OT_ICMP6_ECHO_HANDLER_ALL);
2267 #else
2268     otIcmp6SetEchoMode(gInstance, OT_ICMP6_ECHO_HANDLER_DISABLED);
2269 #endif
2270     otIp6SetReceiveCallback(gInstance, processReceive, gInstance);
2271 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
2272     // We can use the same function for IPv6 and translated IPv4 messages.
2273     otNat64SetReceiveIp4Callback(gInstance, processReceive, gInstance);
2274 #endif
2275     otIp6SetAddressCallback(gInstance, processAddressChange, gInstance);
2276 #if OPENTHREAD_POSIX_MULTICAST_PROMISCUOUS_REQUIRED
2277     otIp6SetMulticastPromiscuousEnabled(aInstance, true);
2278 #endif
2279 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
2280     nat64Init();
2281 #endif
2282 }
2283 
2284 void platformNetifTearDown(void) {}
2285 
2286 void platformNetifDeinit(void)
2287 {
2288     if (sTunFd != -1)
2289     {
2290         close(sTunFd);
2291         sTunFd = -1;
2292 
2293 #if defined(__NetBSD__) || defined(__FreeBSD__)
2294         destroyTunnel();
2295 #endif
2296     }
2297 
2298     if (sIpFd != -1)
2299     {
2300         close(sIpFd);
2301         sIpFd = -1;
2302     }
2303 
2304     if (sNetlinkFd != -1)
2305     {
2306         close(sNetlinkFd);
2307         sNetlinkFd = -1;
2308     }
2309 
2310 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2311     if (sMLDMonitorFd != -1)
2312     {
2313         close(sMLDMonitorFd);
2314         sMLDMonitorFd = -1;
2315     }
2316 #endif
2317 
2318     gNetifIndex = 0;
2319 }
2320 
2321 void platformNetifUpdateFdSet(otSysMainloopContext *aContext)
2322 {
2323     VerifyOrExit(gNetifIndex > 0);
2324 
2325     assert(aContext != nullptr);
2326     assert(sTunFd >= 0);
2327     assert(sNetlinkFd >= 0);
2328     assert(sIpFd >= 0);
2329 
2330     FD_SET(sTunFd, &aContext->mReadFdSet);
2331     FD_SET(sTunFd, &aContext->mErrorFdSet);
2332     FD_SET(sNetlinkFd, &aContext->mReadFdSet);
2333     FD_SET(sNetlinkFd, &aContext->mErrorFdSet);
2334 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2335     FD_SET(sMLDMonitorFd, &aContext->mReadFdSet);
2336     FD_SET(sMLDMonitorFd, &aContext->mErrorFdSet);
2337 #endif
2338 
2339     if (sTunFd > aContext->mMaxFd)
2340     {
2341         aContext->mMaxFd = sTunFd;
2342     }
2343 
2344     if (sNetlinkFd > aContext->mMaxFd)
2345     {
2346         aContext->mMaxFd = sNetlinkFd;
2347     }
2348 
2349 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2350     if (sMLDMonitorFd > aContext->mMaxFd)
2351     {
2352         aContext->mMaxFd = sMLDMonitorFd;
2353     }
2354 #endif
2355 exit:
2356     return;
2357 }
2358 
2359 void platformNetifProcess(const otSysMainloopContext *aContext)
2360 {
2361     assert(aContext != nullptr);
2362     VerifyOrExit(gNetifIndex > 0);
2363 
2364     if (FD_ISSET(sTunFd, &aContext->mErrorFdSet))
2365     {
2366         close(sTunFd);
2367         DieNow(OT_EXIT_FAILURE);
2368     }
2369 
2370     if (FD_ISSET(sNetlinkFd, &aContext->mErrorFdSet))
2371     {
2372         close(sNetlinkFd);
2373         DieNow(OT_EXIT_FAILURE);
2374     }
2375 
2376 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2377     if (FD_ISSET(sMLDMonitorFd, &aContext->mErrorFdSet))
2378     {
2379         close(sMLDMonitorFd);
2380         DieNow(OT_EXIT_FAILURE);
2381     }
2382 #endif
2383 
2384     if (FD_ISSET(sTunFd, &aContext->mReadFdSet))
2385     {
2386         processTransmit(gInstance);
2387     }
2388 
2389     if (FD_ISSET(sNetlinkFd, &aContext->mReadFdSet))
2390     {
2391         processNetlinkEvent(gInstance);
2392     }
2393 
2394 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2395     if (FD_ISSET(sMLDMonitorFd, &aContext->mReadFdSet))
2396     {
2397         processMLDEvent(gInstance);
2398     }
2399 #endif
2400 
2401 exit:
2402     return;
2403 }
2404 
2405 #endif // OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
2406