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 <net/if.h>
81 #include <net/if_arp.h>
82 #include <stdio.h>
83 #include <string.h>
84 #include <sys/ioctl.h>
85 #include <sys/select.h>
86 #include <sys/socket.h>
87 #include <sys/stat.h>
88 #include <sys/types.h>
89 #include <unistd.h>
90 
91 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
92 #include <netinet/in.h>
93 #if defined(__APPLE__) || defined(__FreeBSD__)
94 #include <net/if_var.h>
95 #endif // defined(__APPLE__) || defined(__FreeBSD__)
96 #include <net/route.h>
97 #include <netinet6/in6_var.h>
98 #if defined(__APPLE__) || defined(__FreeBSD__)
99 // the prf_ra structure is defined inside another structure (in6_prflags), and C++
100 //   treats that as out of scope if another structure tries to use it -- this (slightly gross)
101 //   workaround makes us dependent on our definition remaining in sync (at least the size of it),
102 //   so we add a compile-time check that will fail if the SDK ever changes
103 //
104 // our definition of the struct:
105 struct prf_ra
106 {
107     u_char onlink : 1;
108     u_char autonomous : 1;
109     u_char reserved : 6;
110 } prf_ra;
111 // object that contains the SDK's version of the structure:
112 struct in6_prflags compile_time_check_prflags;
113 // compile time check to make sure they're the same size:
114 extern int
115     compile_time_check_struct_prf_ra[(sizeof(struct prf_ra) == sizeof(compile_time_check_prflags.prf_ra)) ? 1 : -1];
116 #endif
117 #include <net/if_dl.h>    // struct sockaddr_dl
118 #include <netinet6/nd6.h> // ND6_INFINITE_LIFETIME
119 
120 #ifdef __APPLE__
121 #if OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN
122 #include <net/if_utun.h>
123 #endif
124 
125 #if OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN
126 #include <sys/ioccom.h>
127 // FIX ME: include the tun_ioctl.h file (challenging, as it's location depends on where the developer puts it)
128 #define TUNSIFHEAD _IOW('t', 96, int)
129 #define TUNGIFHEAD _IOR('t', 97, int)
130 #endif
131 
132 #include <sys/kern_control.h>
133 #endif // defined(__APPLE__)
134 
135 #if defined(__NetBSD__) || defined(__FreeBSD__)
136 #include <net/if_tun.h>
137 #endif // defined(__NetBSD__) || defined(__FreeBSD__)
138 
139 #endif // defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
140 
141 #include <openthread/border_router.h>
142 #include <openthread/icmp6.h>
143 #include <openthread/instance.h>
144 #include <openthread/ip6.h>
145 #include <openthread/logging.h>
146 #include <openthread/message.h>
147 #include <openthread/nat64.h>
148 #include <openthread/netdata.h>
149 #include <openthread/platform/misc.h>
150 
151 #include "common/code_utils.hpp"
152 #include "common/debug.hpp"
153 #include "net/ip6_address.hpp"
154 
155 #include "resolver.hpp"
156 
157 unsigned int gNetifIndex = 0;
158 char         gNetifName[IFNAMSIZ];
159 otIp4Cidr    gNat64Cidr;
160 
otSysGetThreadNetifName(void)161 const char *otSysGetThreadNetifName(void) { return gNetifName; }
162 
otSysGetThreadNetifIndex(void)163 unsigned int otSysGetThreadNetifIndex(void) { return gNetifIndex; }
164 
165 #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
166 #if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
167 #include "firewall.hpp"
168 #endif
169 #include "posix/platform/ip6_utils.hpp"
170 
171 using namespace ot::Posix::Ip6Utils;
172 
173 #ifndef OPENTHREAD_POSIX_TUN_DEVICE
174 
175 #ifdef __linux__
176 #define OPENTHREAD_POSIX_TUN_DEVICE "/dev/net/tun"
177 #elif defined(__NetBSD__) || defined(__FreeBSD__)
178 #define OPENTHREAD_POSIX_TUN_DEVICE "/dev/tun0"
179 #elif defined(__APPLE__)
180 #if OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN
181 #define OPENTHREAD_POSIX_TUN_DEVICE // not used - calculated dynamically
182 #elif OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN
183 #define OPENTHREAD_POSIX_TUN_DEVICE "/dev/tun0"
184 #endif
185 #else
186 // good luck -- untested platform...
187 #define OPENTHREAD_POSIX_TUN_DEVICE "/dev/net/tun"
188 #endif
189 
190 #endif // OPENTHREAD_TUN_DEVICE
191 
192 #if defined(__linux__)
193 static uint32_t sNetlinkSequence = 0; ///< Netlink message sequence.
194 #endif
195 
196 #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && __linux__
197 static constexpr uint32_t kOmrRoutesPriority = OPENTHREAD_POSIX_CONFIG_OMR_ROUTES_PRIORITY;
198 static constexpr uint8_t  kMaxOmrRoutesNum   = OPENTHREAD_POSIX_CONFIG_MAX_OMR_ROUTES_NUM;
199 static uint8_t            sAddedOmrRoutesNum = 0;
200 static otIp6Prefix        sAddedOmrRoutes[kMaxOmrRoutesNum];
201 #endif
202 
203 #if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && __linux__
204 static constexpr uint32_t kExternalRoutePriority  = OPENTHREAD_POSIX_CONFIG_EXTERNAL_ROUTE_PRIORITY;
205 static constexpr uint8_t  kMaxExternalRoutesNum   = OPENTHREAD_POSIX_CONFIG_MAX_EXTERNAL_ROUTE_NUM;
206 static uint8_t            sAddedExternalRoutesNum = 0;
207 static otIp6Prefix        sAddedExternalRoutes[kMaxExternalRoutesNum];
208 #endif
209 
210 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
211 static constexpr uint32_t kNat64RoutePriority = 100; ///< Priority for route to NAT64 CIDR, 100 means a high priority.
212 #endif
213 
214 #if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
215 ot::Posix::Resolver gResolver;
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 mulicast 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 #if !defined(__linux__)
UnicastAddressIsSubscribed(otInstance * aInstance,const otNetifAddress * netAddr)291 static bool UnicastAddressIsSubscribed(otInstance *aInstance, const otNetifAddress *netAddr)
292 {
293     const otNetifAddress *address = otIp6GetUnicastAddresses(aInstance);
294 
295     while (address != nullptr)
296     {
297         if (memcmp(address->mAddress.mFields.m8, netAddr->mAddress.mFields.m8, sizeof(address->mAddress.mFields.m8)) ==
298             0)
299         {
300             return true;
301         }
302 
303         address = address->mNext;
304     }
305 
306     return false;
307 }
308 #endif
309 
310 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
311 static const uint8_t allOnes[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
312                                   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
313 
InitNetaskWithPrefixLength(struct in6_addr * address,uint8_t prefixLen)314 static void InitNetaskWithPrefixLength(struct in6_addr *address, uint8_t prefixLen)
315 {
316 #define MAX_PREFIX_LENGTH (OT_IP6_ADDRESS_SIZE * CHAR_BIT)
317     if (prefixLen > MAX_PREFIX_LENGTH)
318     {
319         prefixLen = MAX_PREFIX_LENGTH;
320     }
321 
322     ot::Ip6::Address addr;
323 
324     addr.Clear();
325     addr.SetPrefix(allOnes, prefixLen);
326     memcpy(address, addr.mFields.m8, sizeof(addr.mFields.m8));
327 }
328 
NetmaskToPrefixLength(const struct sockaddr_in6 * netmask)329 static uint8_t NetmaskToPrefixLength(const struct sockaddr_in6 *netmask)
330 {
331     return otIp6PrefixMatch(reinterpret_cast<const otIp6Address *>(netmask->sin6_addr.s6_addr),
332                             reinterpret_cast<const otIp6Address *>(allOnes));
333 }
334 #endif
335 
336 #if defined(__linux__)
337 #pragma GCC diagnostic push
338 #pragma GCC diagnostic ignored "-Wcast-align"
339 
AddRtAttr(struct nlmsghdr * aHeader,uint32_t aMaxLen,uint8_t aType,const void * aData,uint8_t aLen)340 static struct rtattr *AddRtAttr(struct nlmsghdr *aHeader,
341                                 uint32_t         aMaxLen,
342                                 uint8_t          aType,
343                                 const void      *aData,
344                                 uint8_t          aLen)
345 {
346     uint8_t        len = RTA_LENGTH(aLen);
347     struct rtattr *rta;
348 
349     assert(NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len) <= aMaxLen);
350     OT_UNUSED_VARIABLE(aMaxLen);
351 
352     rta           = (struct rtattr *)((char *)(aHeader) + NLMSG_ALIGN((aHeader)->nlmsg_len));
353     rta->rta_type = aType;
354     rta->rta_len  = len;
355     if (aLen)
356     {
357         memcpy(RTA_DATA(rta), aData, aLen);
358     }
359     aHeader->nlmsg_len = NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len);
360 
361     return rta;
362 }
363 
AddRtAttrUint32(struct nlmsghdr * aHeader,uint32_t aMaxLen,uint8_t aType,uint32_t aData)364 void AddRtAttrUint32(struct nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, uint32_t aData)
365 {
366     AddRtAttr(aHeader, aMaxLen, aType, &aData, sizeof(aData));
367 }
368 
369 #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
IsOmrAddress(otInstance * aInstance,const otIp6AddressInfo & aAddressInfo)370 static bool IsOmrAddress(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo)
371 {
372     otIp6Prefix addressPrefix{*aAddressInfo.mAddress, aAddressInfo.mPrefixLength};
373 
374     return otNetDataContainsOmrPrefix(aInstance, &addressPrefix);
375 }
376 #endif
377 
UpdateUnicastLinux(otInstance * aInstance,const otIp6AddressInfo & aAddressInfo,bool aIsAdded)378 static void UpdateUnicastLinux(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo, bool aIsAdded)
379 {
380     OT_UNUSED_VARIABLE(aInstance);
381 
382     struct
383     {
384         struct nlmsghdr  nh;
385         struct ifaddrmsg ifa;
386         char             buf[512];
387     } req;
388 
389     memset(&req, 0, sizeof(req));
390 
391     req.nh.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
392     req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
393     req.nh.nlmsg_type  = aIsAdded ? RTM_NEWADDR : RTM_DELADDR;
394     req.nh.nlmsg_pid   = 0;
395     req.nh.nlmsg_seq   = ++sNetlinkSequence;
396 
397     req.ifa.ifa_family    = AF_INET6;
398     req.ifa.ifa_prefixlen = aAddressInfo.mPrefixLength;
399     req.ifa.ifa_flags     = IFA_F_NODAD;
400     req.ifa.ifa_scope     = aAddressInfo.mScope;
401     req.ifa.ifa_index     = gNetifIndex;
402 
403     AddRtAttr(&req.nh, sizeof(req), IFA_LOCAL, aAddressInfo.mAddress, sizeof(*aAddressInfo.mAddress));
404 
405     if (!aAddressInfo.mPreferred)
406     {
407         struct ifa_cacheinfo cacheinfo;
408 
409         memset(&cacheinfo, 0, sizeof(cacheinfo));
410         cacheinfo.ifa_valid = UINT32_MAX;
411 
412         AddRtAttr(&req.nh, sizeof(req), IFA_CACHEINFO, &cacheinfo, sizeof(cacheinfo));
413     }
414 
415 #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
416     if (IsOmrAddress(aInstance, aAddressInfo))
417     {
418         // Remove prefix route for OMR address if `OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE` is enabled to
419         // avoid having two routes.
420         if (aIsAdded)
421         {
422             AddRtAttrUint32(&req.nh, sizeof(req), IFA_FLAGS, IFA_F_NOPREFIXROUTE);
423         }
424     }
425     else
426 #endif
427     {
428 #if OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC > 0
429         if (aAddressInfo.mScope > ot::Ip6::Address::kLinkLocalScope)
430         {
431             AddRtAttrUint32(&req.nh, sizeof(req), IFA_RT_PRIORITY, OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC);
432         }
433 #endif
434     }
435 
436     if (send(sNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
437     {
438         otLogInfoPlat("[netif] Sent request#%u to %s %s/%u", sNetlinkSequence, (aIsAdded ? "add" : "remove"),
439                       Ip6AddressString(aAddressInfo.mAddress).AsCString(), aAddressInfo.mPrefixLength);
440     }
441     else
442     {
443         otLogWarnPlat("[netif] Failed to send request#%u to %s %s/%u", sNetlinkSequence, (aIsAdded ? "add" : "remove"),
444                       Ip6AddressString(aAddressInfo.mAddress).AsCString(), aAddressInfo.mPrefixLength);
445     }
446 }
447 
448 #pragma GCC diagnostic pop
449 #endif // defined(__linux__)
450 
UpdateUnicast(otInstance * aInstance,const otIp6AddressInfo & aAddressInfo,bool aIsAdded)451 static void UpdateUnicast(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo, bool aIsAdded)
452 {
453     OT_UNUSED_VARIABLE(aInstance);
454 
455     assert(gInstance == aInstance);
456     assert(sIpFd >= 0);
457 
458 #if defined(__linux__)
459     UpdateUnicastLinux(aInstance, aAddressInfo, aIsAdded);
460 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
461     {
462         int                 rval;
463         struct in6_aliasreq ifr6;
464 
465         memset(&ifr6, 0, sizeof(ifr6));
466         strlcpy(ifr6.ifra_name, gNetifName, sizeof(ifr6.ifra_name));
467         ifr6.ifra_addr.sin6_family = AF_INET6;
468         ifr6.ifra_addr.sin6_len    = sizeof(ifr6.ifra_addr);
469         memcpy(&ifr6.ifra_addr.sin6_addr, aAddressInfo.mAddress, sizeof(struct in6_addr));
470         ifr6.ifra_prefixmask.sin6_family = AF_INET6;
471         ifr6.ifra_prefixmask.sin6_len    = sizeof(ifr6.ifra_prefixmask);
472         InitNetaskWithPrefixLength(&ifr6.ifra_prefixmask.sin6_addr, aAddressInfo.mPrefixLength);
473         ifr6.ifra_lifetime.ia6t_vltime    = ND6_INFINITE_LIFETIME;
474         ifr6.ifra_lifetime.ia6t_pltime    = ND6_INFINITE_LIFETIME;
475 
476 #if defined(__APPLE__)
477         ifr6.ifra_lifetime.ia6t_expire    = ND6_INFINITE_LIFETIME;
478         ifr6.ifra_lifetime.ia6t_preferred = (aAddressInfo.mPreferred ? ND6_INFINITE_LIFETIME : 0);
479 #endif
480 
481         rval = ioctl(sIpFd, aIsAdded ? SIOCAIFADDR_IN6 : SIOCDIFADDR_IN6, &ifr6);
482         if (rval == 0)
483         {
484             otLogInfoPlat("[netif] %s %s/%u", (aIsAdded ? "Added" : "Removed"),
485                           Ip6AddressString(aAddressInfo.mAddress).AsCString(), aAddressInfo.mPrefixLength);
486         }
487         else if (errno != EALREADY)
488         {
489             otLogWarnPlat("[netif] Failed to %s %s/%u: %s", (aIsAdded ? "add" : "remove"),
490                           Ip6AddressString(aAddressInfo.mAddress).AsCString(), aAddressInfo.mPrefixLength,
491                           strerror(errno));
492         }
493     }
494 #endif
495 }
496 
UpdateMulticast(otInstance * aInstance,const otIp6Address & aAddress,bool aIsAdded)497 static void UpdateMulticast(otInstance *aInstance, const otIp6Address &aAddress, bool aIsAdded)
498 {
499     OT_UNUSED_VARIABLE(aInstance);
500 
501     struct ipv6_mreq mreq;
502     otError          error = OT_ERROR_NONE;
503     int              err;
504 
505     assert(gInstance == aInstance);
506 
507     VerifyOrExit(sIpFd >= 0);
508     memcpy(&mreq.ipv6mr_multiaddr, &aAddress, sizeof(mreq.ipv6mr_multiaddr));
509     mreq.ipv6mr_interface = gNetifIndex;
510 
511     err = setsockopt(sIpFd, IPPROTO_IPV6, (aIsAdded ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP), &mreq, sizeof(mreq));
512 
513 #if defined(__APPLE__) || defined(__FreeBSD__)
514     if ((err != 0) && (errno == EINVAL) && (IN6_IS_ADDR_MC_LINKLOCAL(&mreq.ipv6mr_multiaddr)))
515     {
516         // FIX ME
517         // on mac OS (and FreeBSD), the first time we run (but not subsequently), we get a failure on this
518         // particular join. do we need to bring up the interface at least once prior to joining? we need to figure
519         // out why so we can get rid of this workaround
520         char addressString[INET6_ADDRSTRLEN + 1];
521 
522         inet_ntop(AF_INET6, mreq.ipv6mr_multiaddr.s6_addr, addressString, sizeof(addressString));
523         otLogWarnPlat("[netif] Ignoring %s failure (EINVAL) for MC LINKLOCAL address (%s)",
524                       aIsAdded ? "IPV6_JOIN_GROUP" : "IPV6_LEAVE_GROUP", addressString);
525         err = 0;
526     }
527 #endif
528 
529     if (err != 0)
530     {
531         otLogWarnPlat("[netif] %s failure (%d)", aIsAdded ? "IPV6_JOIN_GROUP" : "IPV6_LEAVE_GROUP", errno);
532         error = OT_ERROR_FAILED;
533         ExitNow();
534     }
535 
536     otLogInfoPlat("[netif] %s multicast address %s", aIsAdded ? "Added" : "Removed",
537                   Ip6AddressString(&aAddress).AsCString());
538 
539 exit:
540     SuccessOrDie(error);
541 }
542 
SetLinkState(otInstance * aInstance,bool aState)543 static void SetLinkState(otInstance *aInstance, bool aState)
544 {
545     OT_UNUSED_VARIABLE(aInstance);
546 
547     otError      error = OT_ERROR_NONE;
548     struct ifreq ifr;
549     bool         ifState = false;
550 
551     assert(gInstance == aInstance);
552 
553     VerifyOrExit(sIpFd >= 0);
554     memset(&ifr, 0, sizeof(ifr));
555     strncpy(ifr.ifr_name, gNetifName, sizeof(ifr.ifr_name));
556     VerifyOrExit(ioctl(sIpFd, SIOCGIFFLAGS, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED);
557 
558     ifState = ((ifr.ifr_flags & IFF_UP) == IFF_UP) ? true : false;
559 
560     otLogNotePlat("[netif] Changing interface state to %s%s.", aState ? "up" : "down",
561                   (ifState == aState) ? " (already done, ignoring)" : "");
562 
563     if (ifState != aState)
564     {
565         ifr.ifr_flags = aState ? (ifr.ifr_flags | IFF_UP) : (ifr.ifr_flags & ~IFF_UP);
566         VerifyOrExit(ioctl(sIpFd, SIOCSIFFLAGS, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED);
567 #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
568         // wait for RTM_NEWLINK event before processing notification from kernel to avoid infinite loop
569         sIsSyncingState = true;
570 #endif
571     }
572 
573 exit:
574     if (error != OT_ERROR_NONE)
575     {
576         otLogWarnPlat("[netif] Failed to update state %s", otThreadErrorToString(error));
577     }
578 }
579 
UpdateLink(otInstance * aInstance)580 static void UpdateLink(otInstance *aInstance)
581 {
582     assert(gInstance == aInstance);
583     SetLinkState(aInstance, otIp6IsEnabled(aInstance));
584 }
585 
586 #if defined(__linux__)
AddRoute(const uint8_t (& aAddress)[N],uint8_t aPrefixLen,uint32_t aPriority)587 template <size_t N> otError AddRoute(const uint8_t (&aAddress)[N], uint8_t aPrefixLen, uint32_t aPriority)
588 {
589     constexpr unsigned int kBufSize = 128;
590     struct
591     {
592         struct nlmsghdr header;
593         struct rtmsg    msg;
594         char            buf[kBufSize];
595     } req{};
596     unsigned int netifIdx = otSysGetThreadNetifIndex();
597     otError      error    = OT_ERROR_NONE;
598 
599     static_assert(N == sizeof(in6_addr) || N == sizeof(in_addr), "aAddress should be 4 octets or 16 octets");
600 
601     VerifyOrExit(netifIdx > 0, error = OT_ERROR_INVALID_STATE);
602     VerifyOrExit(sNetlinkFd >= 0, error = OT_ERROR_INVALID_STATE);
603 
604     req.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
605 
606     req.header.nlmsg_len  = NLMSG_LENGTH(sizeof(rtmsg));
607     req.header.nlmsg_type = RTM_NEWROUTE;
608     req.header.nlmsg_pid  = 0;
609     req.header.nlmsg_seq  = ++sNetlinkSequence;
610 
611     req.msg.rtm_family   = (N == sizeof(in6_addr) ? AF_INET6 : AF_INET);
612     req.msg.rtm_src_len  = 0;
613     req.msg.rtm_dst_len  = aPrefixLen;
614     req.msg.rtm_tos      = 0;
615     req.msg.rtm_scope    = RT_SCOPE_UNIVERSE;
616     req.msg.rtm_type     = RTN_UNICAST;
617     req.msg.rtm_table    = RT_TABLE_MAIN;
618     req.msg.rtm_protocol = RTPROT_BOOT;
619     req.msg.rtm_flags    = 0;
620 
621     AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), RTA_DST, aAddress, sizeof(aAddress));
622     AddRtAttrUint32(&req.header, sizeof(req), RTA_PRIORITY, aPriority);
623     AddRtAttrUint32(&req.header, sizeof(req), RTA_OIF, netifIdx);
624 
625     if (send(sNetlinkFd, &req, sizeof(req), 0) < 0)
626     {
627         VerifyOrExit(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK, error = OT_ERROR_BUSY);
628         DieNow(OT_EXIT_ERROR_ERRNO);
629     }
630 exit:
631     return error;
632 }
633 
DeleteRoute(const uint8_t (& aAddress)[N],uint8_t aPrefixLen)634 template <size_t N> otError DeleteRoute(const uint8_t (&aAddress)[N], uint8_t aPrefixLen)
635 {
636     constexpr unsigned int kBufSize = 512;
637     struct
638     {
639         struct nlmsghdr header;
640         struct rtmsg    msg;
641         char            buf[kBufSize];
642     } req{};
643     unsigned int netifIdx = otSysGetThreadNetifIndex();
644     otError      error    = OT_ERROR_NONE;
645 
646     static_assert(N == sizeof(in6_addr) || N == sizeof(in_addr), "aAddress should be 4 octets or 16 octets");
647 
648     VerifyOrExit(netifIdx > 0, error = OT_ERROR_INVALID_STATE);
649     VerifyOrExit(sNetlinkFd >= 0, error = OT_ERROR_INVALID_STATE);
650 
651     req.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_NONREC;
652 
653     req.header.nlmsg_len  = NLMSG_LENGTH(sizeof(rtmsg));
654     req.header.nlmsg_type = RTM_DELROUTE;
655     req.header.nlmsg_pid  = 0;
656     req.header.nlmsg_seq  = ++sNetlinkSequence;
657 
658     req.msg.rtm_family   = (N == sizeof(in6_addr) ? AF_INET6 : AF_INET);
659     req.msg.rtm_src_len  = 0;
660     req.msg.rtm_dst_len  = aPrefixLen;
661     req.msg.rtm_tos      = 0;
662     req.msg.rtm_scope    = RT_SCOPE_UNIVERSE;
663     req.msg.rtm_type     = RTN_UNICAST;
664     req.msg.rtm_table    = RT_TABLE_MAIN;
665     req.msg.rtm_protocol = RTPROT_BOOT;
666     req.msg.rtm_flags    = 0;
667 
668     AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), RTA_DST, &aAddress, sizeof(aAddress));
669     AddRtAttrUint32(&req.header, sizeof(req), RTA_OIF, netifIdx);
670 
671     if (send(sNetlinkFd, &req, sizeof(req), 0) < 0)
672     {
673         VerifyOrExit(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK, error = OT_ERROR_BUSY);
674         DieNow(OT_EXIT_ERROR_ERRNO);
675     }
676 
677 exit:
678     return error;
679 }
680 
681 #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
AddRoute(const otIp6Prefix & aPrefix,uint32_t aPriority)682 static otError AddRoute(const otIp6Prefix &aPrefix, uint32_t aPriority)
683 {
684     return AddRoute(aPrefix.mPrefix.mFields.m8, aPrefix.mLength, aPriority);
685 }
686 
DeleteRoute(const otIp6Prefix & aPrefix)687 static otError DeleteRoute(const otIp6Prefix &aPrefix)
688 {
689     return DeleteRoute(aPrefix.mPrefix.mFields.m8, aPrefix.mLength);
690 }
691 #endif // OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
692 
693 #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
HasAddedOmrRoute(const otIp6Prefix & aOmrPrefix)694 static bool HasAddedOmrRoute(const otIp6Prefix &aOmrPrefix)
695 {
696     bool found = false;
697 
698     for (uint8_t i = 0; i < sAddedOmrRoutesNum; ++i)
699     {
700         if (otIp6ArePrefixesEqual(&sAddedOmrRoutes[i], &aOmrPrefix))
701         {
702             found = true;
703             break;
704         }
705     }
706 
707     return found;
708 }
709 
AddOmrRoute(const otIp6Prefix & aPrefix)710 static otError AddOmrRoute(const otIp6Prefix &aPrefix)
711 {
712     otError error;
713 
714     VerifyOrExit(sAddedOmrRoutesNum < kMaxOmrRoutesNum, error = OT_ERROR_NO_BUFS);
715 
716     error = AddRoute(aPrefix, kOmrRoutesPriority);
717 exit:
718     return error;
719 }
720 
UpdateOmrRoutes(otInstance * aInstance)721 static void UpdateOmrRoutes(otInstance *aInstance)
722 {
723     otError               error;
724     otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
725     otBorderRouterConfig  config;
726     char                  prefixString[OT_IP6_PREFIX_STRING_SIZE];
727 
728     // Remove kernel routes if the OMR prefix is removed
729     for (int i = 0; i < static_cast<int>(sAddedOmrRoutesNum); ++i)
730     {
731         if (otNetDataContainsOmrPrefix(aInstance, &sAddedOmrRoutes[i]))
732         {
733             continue;
734         }
735 
736         otIp6PrefixToString(&sAddedOmrRoutes[i], prefixString, sizeof(prefixString));
737         if ((error = DeleteRoute(sAddedOmrRoutes[i])) != OT_ERROR_NONE)
738         {
739             otLogWarnPlat("[netif] Failed to delete an OMR route %s in kernel: %s", prefixString,
740                           otThreadErrorToString(error));
741         }
742         else
743         {
744             sAddedOmrRoutes[i] = sAddedOmrRoutes[sAddedOmrRoutesNum - 1];
745             --sAddedOmrRoutesNum;
746             --i;
747             otLogInfoPlat("[netif] Successfully deleted an OMR route %s in kernel", prefixString);
748         }
749     }
750 
751     // Add kernel routes for OMR prefixes in Network Data
752     while (otNetDataGetNextOnMeshPrefix(aInstance, &iterator, &config) == OT_ERROR_NONE)
753     {
754         if (HasAddedOmrRoute(config.mPrefix))
755         {
756             continue;
757         }
758 
759         otIp6PrefixToString(&config.mPrefix, prefixString, sizeof(prefixString));
760         if ((error = AddOmrRoute(config.mPrefix)) != OT_ERROR_NONE)
761         {
762             otLogWarnPlat("[netif] Failed to add an OMR route %s in kernel: %s", prefixString,
763                           otThreadErrorToString(error));
764         }
765         else
766         {
767             sAddedOmrRoutes[sAddedOmrRoutesNum++] = config.mPrefix;
768             otLogInfoPlat("[netif] Successfully added an OMR route %s in kernel", prefixString);
769         }
770     }
771 }
772 #endif // OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
773 
774 #if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
AddExternalRoute(const otIp6Prefix & aPrefix)775 static otError AddExternalRoute(const otIp6Prefix &aPrefix)
776 {
777     otError error;
778 
779     VerifyOrExit(sAddedExternalRoutesNum < kMaxExternalRoutesNum, error = OT_ERROR_NO_BUFS);
780 
781     error = AddRoute(aPrefix, kExternalRoutePriority);
782 exit:
783     return error;
784 }
785 
HasExternalRouteInNetData(otInstance * aInstance,const otIp6Prefix & aExternalRoute)786 bool HasExternalRouteInNetData(otInstance *aInstance, const otIp6Prefix &aExternalRoute)
787 {
788     otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
789     otExternalRouteConfig config;
790     bool                  found = false;
791 
792     while (otNetDataGetNextRoute(aInstance, &iterator, &config) == OT_ERROR_NONE)
793     {
794         if (otIp6ArePrefixesEqual(&config.mPrefix, &aExternalRoute))
795         {
796             found = true;
797             break;
798         }
799     }
800     return found;
801 }
802 
HasAddedExternalRoute(const otIp6Prefix & aExternalRoute)803 bool HasAddedExternalRoute(const otIp6Prefix &aExternalRoute)
804 {
805     bool found = false;
806 
807     for (uint8_t i = 0; i < sAddedExternalRoutesNum; ++i)
808     {
809         if (otIp6ArePrefixesEqual(&sAddedExternalRoutes[i], &aExternalRoute))
810         {
811             found = true;
812             break;
813         }
814     }
815     return found;
816 }
817 
UpdateExternalRoutes(otInstance * aInstance)818 static void UpdateExternalRoutes(otInstance *aInstance)
819 {
820     otError               error;
821     otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
822     otExternalRouteConfig config;
823     char                  prefixString[OT_IP6_PREFIX_STRING_SIZE];
824 
825     for (int i = 0; i < static_cast<int>(sAddedExternalRoutesNum); ++i)
826     {
827         if (HasExternalRouteInNetData(aInstance, sAddedExternalRoutes[i]))
828         {
829             continue;
830         }
831 
832         otIp6PrefixToString(&sAddedExternalRoutes[i], prefixString, sizeof(prefixString));
833         if ((error = DeleteRoute(sAddedExternalRoutes[i])) != OT_ERROR_NONE)
834         {
835             otLogWarnPlat("[netif] Failed to delete an external route %s in kernel: %s", prefixString,
836                           otThreadErrorToString(error));
837         }
838         else
839         {
840             sAddedExternalRoutes[i] = sAddedExternalRoutes[sAddedExternalRoutesNum - 1];
841             --sAddedExternalRoutesNum;
842             --i;
843             otLogWarnPlat("[netif] Successfully deleted an external route %s in kernel", prefixString);
844         }
845     }
846 
847     while (otNetDataGetNextRoute(aInstance, &iterator, &config) == OT_ERROR_NONE)
848     {
849         if (config.mRloc16 == otThreadGetRloc16(aInstance) || HasAddedExternalRoute(config.mPrefix))
850         {
851             continue;
852         }
853         VerifyOrExit(sAddedExternalRoutesNum < kMaxExternalRoutesNum,
854                      otLogWarnPlat("[netif] No buffer to add more external routes in kernel"));
855 
856         otIp6PrefixToString(&config.mPrefix, prefixString, sizeof(prefixString));
857         if ((error = AddExternalRoute(config.mPrefix)) != OT_ERROR_NONE)
858         {
859             otLogWarnPlat("[netif] Failed to add an external route %s in kernel: %s", prefixString,
860                           otThreadErrorToString(error));
861         }
862         else
863         {
864             sAddedExternalRoutes[sAddedExternalRoutesNum++] = config.mPrefix;
865             otLogWarnPlat("[netif] Successfully added an external route %s in kernel", prefixString);
866         }
867     }
868 exit:
869     return;
870 }
871 #endif // OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
872 
873 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
AddIp4Route(const otIp4Cidr & aIp4Cidr,uint32_t aPriority)874 static otError AddIp4Route(const otIp4Cidr &aIp4Cidr, uint32_t aPriority)
875 {
876     return AddRoute(aIp4Cidr.mAddress.mFields.m8, aIp4Cidr.mLength, aPriority);
877 }
878 
DeleteIp4Route(const otIp4Cidr & aIp4Cidr)879 static otError DeleteIp4Route(const otIp4Cidr &aIp4Cidr)
880 {
881     return DeleteRoute(aIp4Cidr.mAddress.mFields.m8, aIp4Cidr.mLength);
882 }
883 #endif
884 #endif // defined(__linux__)
885 
processAddressChange(const otIp6AddressInfo * aAddressInfo,bool aIsAdded,void * aContext)886 static void processAddressChange(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aContext)
887 {
888     if (aAddressInfo->mAddress->mFields.m8[0] == 0xff)
889     {
890         UpdateMulticast(static_cast<otInstance *>(aContext), *aAddressInfo->mAddress, aIsAdded);
891     }
892     else
893     {
894         UpdateUnicast(static_cast<otInstance *>(aContext), *aAddressInfo, aIsAdded);
895     }
896 }
897 
898 #if defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
processNat64StateChange(otNat64State aNewState)899 void processNat64StateChange(otNat64State aNewState)
900 {
901     // If the interface is not up and we are enabling NAT64, the route will be added when we bring up the route.
902     // Also, the route will be deleted by the kernel when we shutting down the interface.
903     // We should try to add route first, since otNat64SetEnabled never fails.
904     if (otIp6IsEnabled(gInstance))
905     {
906         if (aNewState == OT_NAT64_STATE_ACTIVE)
907         {
908             AddIp4Route(gNat64Cidr, kNat64RoutePriority);
909             otLogInfoPlat("[netif] Adding route for NAT64");
910         }
911         else
912         {
913             DeleteIp4Route(gNat64Cidr);
914             otLogInfoPlat("[netif] Deleting route for NAT64");
915         }
916     }
917 }
918 #endif // defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
919 
platformNetifStateChange(otInstance * aInstance,otChangedFlags aFlags)920 void platformNetifStateChange(otInstance *aInstance, otChangedFlags aFlags)
921 {
922     if (OT_CHANGED_THREAD_NETIF_STATE & aFlags)
923     {
924         UpdateLink(aInstance);
925     }
926     if (OT_CHANGED_THREAD_NETDATA & aFlags)
927     {
928 #if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && __linux__
929         UpdateOmrRoutes(aInstance);
930 #endif
931 #if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && __linux__
932         UpdateExternalRoutes(aInstance);
933 #endif
934 #if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
935         ot::Posix::UpdateIpSets(aInstance);
936 #endif
937     }
938 #if defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
939     if (OT_CHANGED_NAT64_TRANSLATOR_STATE & aFlags)
940     {
941         processNat64StateChange(otNat64GetTranslatorState(aInstance));
942     }
943 #endif
944 }
945 
processReceive(otMessage * aMessage,void * aContext)946 static void processReceive(otMessage *aMessage, void *aContext)
947 {
948     OT_UNUSED_VARIABLE(aContext);
949 
950     char     packet[kMaxIp6Size + 4];
951     otError  error     = OT_ERROR_NONE;
952     uint16_t length    = otMessageGetLength(aMessage);
953     size_t   offset    = 0;
954     uint16_t maxLength = sizeof(packet) - 4;
955 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
956     // BSD tunnel drivers use (for legacy reasons) a 4-byte header to determine the address family of the packet
957     offset += 4;
958 #endif
959 
960     assert(gInstance == aContext);
961     assert(length <= kMaxIp6Size);
962 
963     VerifyOrExit(sTunFd > 0);
964 
965     VerifyOrExit(otMessageRead(aMessage, 0, &packet[offset], maxLength) == length, error = OT_ERROR_NO_BUFS);
966 
967 #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
968     otLogInfoPlat("[netif] Packet from NCP (%u bytes)", static_cast<uint16_t>(length));
969     otDumpInfoPlat("", &packet[offset], length);
970 #endif
971 
972 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
973     packet[0] = 0;
974     packet[1] = 0;
975     packet[2] = (PF_INET6 << 8) & 0xFF;
976     packet[3] = (PF_INET6 << 0) & 0xFF;
977     length += 4;
978 #endif
979 
980     VerifyOrExit(write(sTunFd, packet, length) == length, perror("write"); error = OT_ERROR_FAILED);
981 
982 exit:
983     otMessageFree(aMessage);
984 
985     if (error != OT_ERROR_NONE)
986     {
987         otLogWarnPlat("[netif] Failed to receive, error:%s", otThreadErrorToString(error));
988     }
989 }
990 
processTransmit(otInstance * aInstance)991 static void processTransmit(otInstance *aInstance)
992 {
993     otMessage *message = nullptr;
994     ssize_t    rval;
995     char       packet[kMaxIp6Size];
996     otError    error  = OT_ERROR_NONE;
997     size_t     offset = 0;
998 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
999     bool isIp4 = false;
1000 #endif
1001 
1002     assert(gInstance == aInstance);
1003 
1004     rval = read(sTunFd, packet, sizeof(packet));
1005     VerifyOrExit(rval > 0, error = OT_ERROR_FAILED);
1006 
1007 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1008     // BSD tunnel drivers have (for legacy reasons), may have a 4-byte header on them
1009     if ((rval >= 4) && (packet[0] == 0) && (packet[1] == 0))
1010     {
1011         rval -= 4;
1012         offset = 4;
1013     }
1014 #endif
1015 
1016     {
1017         otMessageSettings settings;
1018 
1019         settings.mLinkSecurityEnabled = (otThreadGetDeviceRole(aInstance) != OT_DEVICE_ROLE_DISABLED);
1020         settings.mPriority            = OT_MESSAGE_PRIORITY_LOW;
1021 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1022         isIp4   = (packet[offset] & 0xf0) == 0x40;
1023         message = isIp4 ? otIp4NewMessage(aInstance, &settings) : otIp6NewMessage(aInstance, &settings);
1024 #else
1025         message = otIp6NewMessage(aInstance, &settings);
1026 #endif
1027         VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
1028     }
1029 
1030 #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
1031     otLogInfoPlat("[netif] Packet to NCP (%hu bytes)", static_cast<uint16_t>(rval));
1032     otDumpInfoPlat("", &packet[offset], static_cast<size_t>(rval));
1033 #endif
1034 
1035     SuccessOrExit(error = otMessageAppend(message, &packet[offset], static_cast<uint16_t>(rval)));
1036 
1037 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1038     error = isIp4 ? otNat64Send(aInstance, message) : otIp6Send(aInstance, message);
1039 #else
1040     error = otIp6Send(aInstance, message);
1041 #endif
1042     message = nullptr;
1043 
1044 exit:
1045     if (message != nullptr)
1046     {
1047         otMessageFree(message);
1048     }
1049 
1050     if (error != OT_ERROR_NONE)
1051     {
1052         if (error == OT_ERROR_DROP)
1053         {
1054             otLogInfoPlat("[netif] Message dropped by Thread");
1055         }
1056         else
1057         {
1058             otLogWarnPlat("[netif] Failed to transmit, error:%s", otThreadErrorToString(error));
1059         }
1060     }
1061 }
1062 
logAddrEvent(bool isAdd,const ot::Ip6::Address & aAddress,otError error)1063 static void logAddrEvent(bool isAdd, const ot::Ip6::Address &aAddress, otError error)
1064 {
1065     OT_UNUSED_VARIABLE(aAddress);
1066 
1067     if ((error == OT_ERROR_NONE) || ((isAdd) && (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)) ||
1068         ((!isAdd) && (error == OT_ERROR_NOT_FOUND || error == OT_ERROR_REJECTED)))
1069     {
1070         otLogInfoPlat("[netif] %s [%s] %s%s", isAdd ? "ADD" : "DEL", aAddress.IsMulticast() ? "M" : "U",
1071                       aAddress.ToString().AsCString(),
1072                       error == OT_ERROR_ALREADY     ? " (already subscribed, ignored)"
1073                       : error == OT_ERROR_REJECTED  ? " (rejected)"
1074                       : error == OT_ERROR_NOT_FOUND ? " (not found, ignored)"
1075                                                     : "");
1076     }
1077     else
1078     {
1079         otLogWarnPlat("[netif] %s [%s] %s failed (%s)", isAdd ? "ADD" : "DEL", aAddress.IsMulticast() ? "M" : "U",
1080                       aAddress.ToString().AsCString(), otThreadErrorToString(error));
1081     }
1082 }
1083 
1084 #if defined(__linux__)
1085 
processNetifAddrEvent(otInstance * aInstance,struct nlmsghdr * aNetlinkMessage)1086 static void processNetifAddrEvent(otInstance *aInstance, struct nlmsghdr *aNetlinkMessage)
1087 {
1088     struct ifaddrmsg   *ifaddr = reinterpret_cast<struct ifaddrmsg *>(NLMSG_DATA(aNetlinkMessage));
1089     size_t              rtaLength;
1090     otError             error = OT_ERROR_NONE;
1091     struct sockaddr_in6 addr6;
1092 
1093     VerifyOrExit(ifaddr->ifa_index == static_cast<unsigned int>(gNetifIndex) && ifaddr->ifa_family == AF_INET6);
1094 
1095     rtaLength = IFA_PAYLOAD(aNetlinkMessage);
1096 
1097     for (struct rtattr *rta = reinterpret_cast<struct rtattr *>(IFA_RTA(ifaddr)); RTA_OK(rta, rtaLength);
1098          rta                = RTA_NEXT(rta, rtaLength))
1099     {
1100         switch (rta->rta_type)
1101         {
1102         case IFA_ADDRESS:
1103         case IFA_LOCAL:
1104         case IFA_BROADCAST:
1105         case IFA_ANYCAST:
1106         case IFA_MULTICAST:
1107         {
1108             ot::Ip6::Address addr;
1109             memcpy(&addr, RTA_DATA(rta), sizeof(addr));
1110 
1111             memset(&addr6, 0, sizeof(addr6));
1112             addr6.sin6_family = AF_INET6;
1113             memcpy(&addr6.sin6_addr, RTA_DATA(rta), sizeof(addr6.sin6_addr));
1114 
1115             if (aNetlinkMessage->nlmsg_type == RTM_NEWADDR)
1116             {
1117                 if (!addr.IsMulticast())
1118                 {
1119                     otNetifAddress netAddr;
1120 
1121                     netAddr.mAddress      = addr;
1122                     netAddr.mPrefixLength = ifaddr->ifa_prefixlen;
1123 
1124                     error = otIp6AddUnicastAddress(aInstance, &netAddr);
1125                 }
1126                 else
1127                 {
1128                     otNetifMulticastAddress netAddr;
1129 
1130                     netAddr.mAddress = addr;
1131 
1132                     error = otIp6SubscribeMulticastAddress(aInstance, &addr);
1133                 }
1134 
1135                 logAddrEvent(/* isAdd */ true, addr, error);
1136                 if (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)
1137                 {
1138                     error = OT_ERROR_NONE;
1139                 }
1140 
1141                 SuccessOrExit(error);
1142             }
1143             else if (aNetlinkMessage->nlmsg_type == RTM_DELADDR)
1144             {
1145                 if (!addr.IsMulticast())
1146                 {
1147                     error = otIp6RemoveUnicastAddress(aInstance, &addr);
1148                 }
1149                 else
1150                 {
1151                     error = otIp6UnsubscribeMulticastAddress(aInstance, &addr);
1152                 }
1153 
1154                 logAddrEvent(/* isAdd */ false, addr, error);
1155                 if (error == OT_ERROR_NOT_FOUND || error == OT_ERROR_REJECTED)
1156                 {
1157                     error = OT_ERROR_NONE;
1158                 }
1159 
1160                 SuccessOrExit(error);
1161             }
1162             else
1163             {
1164                 continue;
1165             }
1166             break;
1167         }
1168 
1169         default:
1170             otLogDebgPlat("[netif] Unexpected address type (%d).", (int)rta->rta_type);
1171             break;
1172         }
1173     }
1174 
1175 exit:
1176     if (error != OT_ERROR_NONE)
1177     {
1178         otLogWarnPlat("[netif] Failed to process event, error:%s", otThreadErrorToString(error));
1179     }
1180 }
1181 
processNetifLinkEvent(otInstance * aInstance,struct nlmsghdr * aNetlinkMessage)1182 static void processNetifLinkEvent(otInstance *aInstance, struct nlmsghdr *aNetlinkMessage)
1183 {
1184     struct ifinfomsg *ifinfo = reinterpret_cast<struct ifinfomsg *>(NLMSG_DATA(aNetlinkMessage));
1185     otError           error  = OT_ERROR_NONE;
1186     bool              isUp;
1187 
1188     VerifyOrExit(ifinfo->ifi_index == static_cast<int>(gNetifIndex) && (ifinfo->ifi_change & IFF_UP));
1189 
1190     isUp = ((ifinfo->ifi_flags & IFF_UP) != 0);
1191 
1192     otLogInfoPlat("[netif] Host netif is %s", isUp ? "up" : "down");
1193 
1194 #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
1195     if (sIsSyncingState)
1196     {
1197         VerifyOrExit(isUp == otIp6IsEnabled(aInstance),
1198                      otLogWarnPlat("[netif] Host netif state notification is unexpected (ignore)"));
1199         sIsSyncingState = false;
1200     }
1201     else
1202 #endif
1203         if (isUp != otIp6IsEnabled(aInstance))
1204     {
1205         SuccessOrExit(error = otIp6SetEnabled(aInstance, isUp));
1206         otLogInfoPlat("[netif] Succeeded to sync netif state with host");
1207     }
1208 
1209 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1210     if (isUp && gNat64Cidr.mLength > 0)
1211     {
1212         SuccessOrExit(error = otNat64SetIp4Cidr(gInstance, &gNat64Cidr));
1213         otLogInfoPlat("[netif] Succeeded to enable NAT64");
1214     }
1215 #endif
1216 
1217 exit:
1218     if (error != OT_ERROR_NONE)
1219     {
1220         otLogWarnPlat("[netif] Failed to sync netif state with host: %s", otThreadErrorToString(error));
1221     }
1222 }
1223 #endif // defined(__linux__)
1224 
1225 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1226 
1227 #if defined(__FreeBSD__)
1228 #define ROUNDUP(a) ((a) > 0 ? (1 + (((a)-1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
1229 #endif
1230 
1231 #if defined(__APPLE__)
1232 #define ROUNDUP(a) ((a) > 0 ? (1 + (((a)-1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
1233 #define DARWIN_SA_SIZE(sa) ROUNDUP(sa->sa_len)
1234 #define SA_SIZE(sa) DARWIN_SA_SIZE(sa)
1235 #endif
1236 
1237 #if defined(__NetBSD__)
1238 #define RT_ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a)-1U) | ((n)-1))) : (n))
1239 #define RT_ROUNDUP(a) RT_ROUNDUP2((a), sizeof(uint64_t))
1240 #define SA_SIZE(sa) RT_ROUNDUP(sa->sa_len)
1241 #endif
1242 
processNetifAddrEvent(otInstance * aInstance,struct rt_msghdr * rtm)1243 static void processNetifAddrEvent(otInstance *aInstance, struct rt_msghdr *rtm)
1244 {
1245     otError            error;
1246     struct ifa_msghdr *ifam;
1247 #ifdef RTM_NEWMADDR
1248     struct ifma_msghdr *ifmam;
1249 #endif
1250     struct sockaddr_in6 addr6;
1251     struct sockaddr_in6 netmask;
1252     uint8_t            *addrbuf;
1253     unsigned int        addrmask = 0;
1254     unsigned int        i;
1255     struct sockaddr    *sa;
1256     bool                is_link_local;
1257 
1258     addr6.sin6_family   = 0;
1259     netmask.sin6_family = 0;
1260 
1261     if ((rtm->rtm_type == RTM_NEWADDR) || (rtm->rtm_type == RTM_DELADDR))
1262     {
1263         ifam = reinterpret_cast<struct ifa_msghdr *>(rtm);
1264 
1265         VerifyOrExit(ifam->ifam_index == static_cast<unsigned int>(gNetifIndex));
1266 
1267         addrbuf  = (uint8_t *)&ifam[1];
1268         addrmask = (unsigned int)ifam->ifam_addrs;
1269     }
1270 #ifdef RTM_NEWMADDR
1271     else if ((rtm->rtm_type == RTM_NEWMADDR) || (rtm->rtm_type == RTM_DELMADDR))
1272     {
1273         ifmam = reinterpret_cast<struct ifma_msghdr *>(rtm);
1274 
1275         VerifyOrExit(ifmam->ifmam_index == static_cast<unsigned int>(gNetifIndex));
1276 
1277         addrbuf  = (uint8_t *)&ifmam[1];
1278         addrmask = (unsigned int)ifmam->ifmam_addrs;
1279     }
1280 #endif
1281 
1282     if (addrmask != 0)
1283     {
1284         for (i = 0; i < RTAX_MAX; i++)
1285         {
1286             unsigned int mask = (addrmask & (1 << i));
1287             if (mask)
1288             {
1289                 sa = (struct sockaddr *)addrbuf;
1290 
1291                 if (sa->sa_family == AF_INET6)
1292                 {
1293                     if (i == RTAX_IFA)
1294                         memcpy(&addr6, sa, sizeof(sockaddr_in6));
1295                     if (i == RTAX_NETMASK)
1296                         memcpy(&netmask, sa, sizeof(sockaddr_in6));
1297                 }
1298                 addrbuf += SA_SIZE(sa);
1299             }
1300         }
1301     }
1302 
1303     if (addr6.sin6_family == AF_INET6)
1304     {
1305         is_link_local = false;
1306         if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr))
1307         {
1308             is_link_local = true;
1309             // clear the scope -- Mac OS X sends this to us (bozos!)
1310             addr6.sin6_addr.s6_addr[3] = 0;
1311         }
1312         else if (IN6_IS_ADDR_MC_LINKLOCAL(&addr6.sin6_addr))
1313         {
1314             addr6.sin6_addr.s6_addr[3] = 0;
1315         }
1316 
1317         ot::Ip6::Address addr;
1318         memcpy(&addr, &addr6.sin6_addr, sizeof(addr));
1319 
1320         if (rtm->rtm_type == RTM_NEWADDR
1321 #ifdef RTM_NEWMADDR
1322             || rtm->rtm_type == RTM_NEWMADDR
1323 #endif
1324         )
1325         {
1326             if (!addr.IsMulticast())
1327             {
1328                 otNetifAddress netAddr;
1329                 bool           subscribed;
1330 
1331                 netAddr.mAddress      = addr;
1332                 netAddr.mPrefixLength = NetmaskToPrefixLength(&netmask);
1333 
1334                 subscribed = UnicastAddressIsSubscribed(aInstance, &netAddr);
1335 
1336                 if (subscribed)
1337                 {
1338                     logAddrEvent(/* isAdd */ true, addr, OT_ERROR_ALREADY);
1339                     error = OT_ERROR_NONE;
1340                 }
1341                 else
1342                 {
1343                     if (is_link_local)
1344                     {
1345                         // remove the stack-added link-local address
1346 
1347                         int                 err;
1348                         struct in6_aliasreq ifr6;
1349                         char                addressString[INET6_ADDRSTRLEN + 1];
1350 
1351                         OT_UNUSED_VARIABLE(addressString); // if otLog*Plat is disabled, we'll get a warning
1352 
1353                         memset(&ifr6, 0, sizeof(ifr6));
1354                         strlcpy(ifr6.ifra_name, gNetifName, sizeof(ifr6.ifra_name));
1355                         ifr6.ifra_addr.sin6_family = AF_INET6;
1356                         ifr6.ifra_addr.sin6_len    = sizeof(ifr6.ifra_addr);
1357                         memcpy(&ifr6.ifra_addr.sin6_addr, &addr6.sin6_addr, sizeof(struct in6_addr));
1358                         ifr6.ifra_prefixmask.sin6_family = AF_INET6;
1359                         ifr6.ifra_prefixmask.sin6_len    = sizeof(ifr6.ifra_prefixmask);
1360                         InitNetaskWithPrefixLength(&ifr6.ifra_prefixmask.sin6_addr, netAddr.mPrefixLength);
1361                         ifr6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
1362                         ifr6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
1363 
1364 #if defined(__APPLE__)
1365                         ifr6.ifra_lifetime.ia6t_expire    = ND6_INFINITE_LIFETIME;
1366                         ifr6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME;
1367 #endif
1368 
1369                         err = ioctl(sIpFd, SIOCDIFADDR_IN6, &ifr6);
1370                         if (err != 0)
1371                         {
1372                             otLogWarnPlat(
1373                                 "[netif] Error (%d) removing stack-addded link-local address %s", errno,
1374                                 inet_ntop(AF_INET6, addr6.sin6_addr.s6_addr, addressString, sizeof(addressString)));
1375                             error = OT_ERROR_FAILED;
1376                         }
1377                         else
1378                         {
1379                             otLogNotePlat(
1380                                 "[netif]        %s (removed stack-added link-local)",
1381                                 inet_ntop(AF_INET6, addr6.sin6_addr.s6_addr, addressString, sizeof(addressString)));
1382                             error = OT_ERROR_NONE;
1383                         }
1384                     }
1385                     else
1386                     {
1387                         error = otIp6AddUnicastAddress(aInstance, &netAddr);
1388                         logAddrEvent(/* isAdd */ true, addr, error);
1389                         if (error == OT_ERROR_ALREADY)
1390                         {
1391                             error = OT_ERROR_NONE;
1392                         }
1393                     }
1394                 }
1395                 SuccessOrExit(error);
1396             }
1397             else
1398             {
1399                 otNetifMulticastAddress netAddr;
1400                 netAddr.mAddress = addr;
1401 
1402                 error = otIp6SubscribeMulticastAddress(aInstance, &addr);
1403                 logAddrEvent(/* isAdd */ true, addr, error);
1404                 if (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)
1405                 {
1406                     error = OT_ERROR_NONE;
1407                 }
1408                 SuccessOrExit(error);
1409             }
1410         }
1411         else if (rtm->rtm_type == RTM_DELADDR
1412 #ifdef RTM_DELMADDR
1413                  || rtm->rtm_type == RTM_DELMADDR
1414 #endif
1415         )
1416         {
1417             if (!addr.IsMulticast())
1418             {
1419                 error = otIp6RemoveUnicastAddress(aInstance, &addr);
1420                 logAddrEvent(/* isAdd */ false, addr, error);
1421                 if (error == OT_ERROR_NOT_FOUND)
1422                 {
1423                     error = OT_ERROR_NONE;
1424                 }
1425             }
1426             else
1427             {
1428                 error = otIp6UnsubscribeMulticastAddress(aInstance, &addr);
1429                 logAddrEvent(/* isAdd */ false, addr, error);
1430                 if (error == OT_ERROR_NOT_FOUND)
1431                 {
1432                     error = OT_ERROR_NONE;
1433                 }
1434             }
1435             SuccessOrExit(error);
1436         }
1437     }
1438 
1439 exit:;
1440 }
1441 
processNetifInfoEvent(otInstance * aInstance,struct rt_msghdr * rtm)1442 static void processNetifInfoEvent(otInstance *aInstance, struct rt_msghdr *rtm)
1443 {
1444     struct if_msghdr *ifm   = reinterpret_cast<struct if_msghdr *>(rtm);
1445     otError           error = OT_ERROR_NONE;
1446 
1447     VerifyOrExit(ifm->ifm_index == static_cast<int>(gNetifIndex));
1448 
1449     UpdateLink(aInstance);
1450 
1451 exit:
1452     if (error != OT_ERROR_NONE)
1453     {
1454         otLogWarnPlat("[netif] Failed to process info event: %s", otThreadErrorToString(error));
1455     }
1456 }
1457 
1458 #endif
1459 
processNetlinkEvent(otInstance * aInstance)1460 static void processNetlinkEvent(otInstance *aInstance)
1461 {
1462     const size_t kMaxNetifEvent = 8192;
1463     ssize_t      length;
1464 
1465     union
1466     {
1467 #if defined(__linux__)
1468         nlmsghdr nlMsg;
1469 #else
1470         rt_msghdr rtMsg;
1471 #endif
1472         char buffer[kMaxNetifEvent];
1473     } msgBuffer;
1474 
1475     length = recv(sNetlinkFd, msgBuffer.buffer, sizeof(msgBuffer.buffer), 0);
1476 
1477     VerifyOrExit(length > 0);
1478 
1479 #if defined(__linux__)
1480     for (struct nlmsghdr *msg = &msgBuffer.nlMsg; NLMSG_OK(msg, static_cast<size_t>(length));
1481          msg                  = NLMSG_NEXT(msg, length))
1482     {
1483 #else
1484     {
1485         // BSD sends one message per read to routing socket (see route.c, monitor command)
1486         struct rt_msghdr *msg;
1487 
1488         msg = &msgBuffer.rtMsg;
1489 
1490 #define nlmsg_type rtm_type
1491 
1492 #endif
1493         switch (msg->nlmsg_type)
1494         {
1495         case RTM_NEWADDR:
1496         case RTM_DELADDR:
1497             processNetifAddrEvent(aInstance, msg);
1498             break;
1499 
1500 #if defined(RTM_NEWLINK) && defined(RTM_DELLINK)
1501         case RTM_NEWLINK:
1502         case RTM_DELLINK:
1503             processNetifLinkEvent(aInstance, msg);
1504             break;
1505 #endif
1506 
1507 #if defined(RTM_NEWMADDR) && defined(RTM_DELMADDR)
1508         case RTM_NEWMADDR:
1509         case RTM_DELMADDR:
1510             processNetifAddrEvent(aInstance, msg);
1511             break;
1512 #endif
1513 
1514 #if !defined(__linux__)
1515         case RTM_IFINFO:
1516             processNetifInfoEvent(aInstance, msg);
1517             break;
1518 
1519 #else
1520         case NLMSG_ERROR:
1521         {
1522             const struct nlmsgerr *err = reinterpret_cast<const nlmsgerr *>(NLMSG_DATA(msg));
1523 
1524             if (err->error == 0)
1525             {
1526                 otLogInfoPlat("[netif] Succeeded to process request#%u", err->msg.nlmsg_seq);
1527             }
1528             else
1529             {
1530                 otLogWarnPlat("[netif] Failed to process request#%u: %s", err->msg.nlmsg_seq, strerror(err->error));
1531             }
1532 
1533             break;
1534         }
1535 #endif
1536 
1537 #if defined(ROUTE_FILTER) || defined(RO_MSGFILTER) || defined(__linux__)
1538         default:
1539             otLogWarnPlat("[netif] Unhandled/Unexpected netlink/route message (%d).", (int)msg->nlmsg_type);
1540             break;
1541 #else
1542         // this platform doesn't support filtering, so we expect messages of other types...we just ignore them
1543 #endif
1544         }
1545     }
1546 
1547 exit:
1548     return;
1549 }
1550 
1551 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
1552 static void mldListenerInit(void)
1553 {
1554     struct ipv6_mreq mreq6;
1555 
1556     sMLDMonitorFd          = SocketWithCloseExec(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, kSocketNonBlock);
1557     mreq6.ipv6mr_interface = gNetifIndex;
1558     memcpy(&mreq6.ipv6mr_multiaddr, kMLDv2MulticastAddress.mFields.m8, sizeof(kMLDv2MulticastAddress.mFields.m8));
1559 
1560     VerifyOrDie(setsockopt(sMLDMonitorFd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)) == 0, OT_EXIT_FAILURE);
1561 #if defined(__linux__)
1562     VerifyOrDie(setsockopt(sMLDMonitorFd, SOL_SOCKET, SO_BINDTODEVICE, gNetifName,
1563                            static_cast<socklen_t>(strnlen(gNetifName, IFNAMSIZ))) == 0,
1564                 OT_EXIT_FAILURE);
1565 #endif
1566 }
1567 
1568 static void processMLDEvent(otInstance *aInstance)
1569 {
1570     const size_t        kMaxMLDEvent = 8192;
1571     uint8_t             buffer[kMaxMLDEvent];
1572     ssize_t             bufferLen = -1;
1573     struct sockaddr_in6 srcAddr;
1574     socklen_t           addrLen  = sizeof(srcAddr);
1575     bool                fromSelf = false;
1576     MLDv2Header        *hdr      = reinterpret_cast<MLDv2Header *>(buffer);
1577     size_t              offset;
1578     uint8_t             type;
1579     struct ifaddrs     *ifAddrs = nullptr;
1580     char                addressString[INET6_ADDRSTRLEN + 1];
1581 
1582     bufferLen = recvfrom(sMLDMonitorFd, buffer, sizeof(buffer), 0, reinterpret_cast<sockaddr *>(&srcAddr), &addrLen);
1583     VerifyOrExit(bufferLen > 0);
1584 
1585     type = buffer[0];
1586     VerifyOrExit(type == kICMPv6MLDv2Type && bufferLen >= static_cast<ssize_t>(sizeof(MLDv2Header)));
1587 
1588     // Check whether it is sent by self
1589     VerifyOrExit(getifaddrs(&ifAddrs) == 0);
1590     for (struct ifaddrs *ifAddr = ifAddrs; ifAddr != nullptr; ifAddr = ifAddr->ifa_next)
1591     {
1592         if (ifAddr->ifa_addr != nullptr && ifAddr->ifa_addr->sa_family == AF_INET6 &&
1593             strncmp(gNetifName, ifAddr->ifa_name, IFNAMSIZ) == 0)
1594         {
1595 #pragma GCC diagnostic push
1596 #pragma GCC diagnostic ignored "-Wcast-align"
1597             struct sockaddr_in6 *addr6 = reinterpret_cast<struct sockaddr_in6 *>(ifAddr->ifa_addr);
1598 #pragma GCC diagnostic pop
1599 
1600             if (memcmp(&addr6->sin6_addr, &srcAddr.sin6_addr, sizeof(in6_addr)) == 0)
1601             {
1602                 fromSelf = true;
1603                 break;
1604             }
1605         }
1606     }
1607     VerifyOrExit(fromSelf);
1608 
1609     hdr    = reinterpret_cast<MLDv2Header *>(buffer);
1610     offset = sizeof(MLDv2Header);
1611 
1612     for (size_t i = 0; i < ntohs(hdr->mNumRecords) && offset < static_cast<size_t>(bufferLen); i++)
1613     {
1614         if (static_cast<size_t>(bufferLen) >= (sizeof(MLDv2Record) + offset))
1615         {
1616             MLDv2Record *record = reinterpret_cast<MLDv2Record *>(&buffer[offset]);
1617 
1618             otError          err;
1619             ot::Ip6::Address address;
1620 
1621             memcpy(&address.mFields.m8, &record->mMulticastAddress, sizeof(address.mFields.m8));
1622             inet_ntop(AF_INET6, &record->mMulticastAddress, addressString, sizeof(addressString));
1623             if (record->mRecordType == kICMPv6MLDv2RecordChangeToIncludeType)
1624             {
1625                 err = otIp6SubscribeMulticastAddress(aInstance, &address);
1626                 logAddrEvent(/* isAdd */ true, address, err);
1627             }
1628             else if (record->mRecordType == kICMPv6MLDv2RecordChangeToExcludeType)
1629             {
1630                 err = otIp6UnsubscribeMulticastAddress(aInstance, &address);
1631                 logAddrEvent(/* isAdd */ false, address, err);
1632             }
1633 
1634             offset += sizeof(MLDv2Record) + sizeof(in6_addr) * ntohs(record->mNumSources);
1635         }
1636     }
1637 
1638 exit:
1639     if (ifAddrs)
1640     {
1641         freeifaddrs(ifAddrs);
1642     }
1643 }
1644 #endif
1645 
1646 #if defined(__linux__)
1647 static void SetAddrGenModeToNone(void)
1648 {
1649     struct
1650     {
1651         struct nlmsghdr  nh;
1652         struct ifinfomsg ifi;
1653         char             buf[512];
1654     } req;
1655 
1656     const enum in6_addr_gen_mode mode = IN6_ADDR_GEN_MODE_NONE;
1657 
1658     memset(&req, 0, sizeof(req));
1659 
1660     req.nh.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1661     req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1662     req.nh.nlmsg_type  = RTM_NEWLINK;
1663     req.nh.nlmsg_pid   = 0;
1664     req.nh.nlmsg_seq   = ++sNetlinkSequence;
1665 
1666     req.ifi.ifi_index  = static_cast<int>(gNetifIndex);
1667     req.ifi.ifi_change = 0xffffffff;
1668     req.ifi.ifi_flags  = IFF_MULTICAST | IFF_NOARP;
1669 
1670     {
1671         struct rtattr *afSpec  = AddRtAttr(&req.nh, sizeof(req), IFLA_AF_SPEC, 0, 0);
1672         struct rtattr *afInet6 = AddRtAttr(&req.nh, sizeof(req), AF_INET6, 0, 0);
1673         struct rtattr *inet6AddrGenMode =
1674             AddRtAttr(&req.nh, sizeof(req), IFLA_INET6_ADDR_GEN_MODE, &mode, sizeof(mode));
1675 
1676         afInet6->rta_len += inet6AddrGenMode->rta_len;
1677         afSpec->rta_len += afInet6->rta_len;
1678     }
1679 
1680     if (send(sNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
1681     {
1682         otLogInfoPlat("[netif] Sent request#%u to set addr_gen_mode to %d", sNetlinkSequence, mode);
1683     }
1684     else
1685     {
1686         otLogWarnPlat("[netif] Failed to send request#%u to set addr_gen_mode to %d", sNetlinkSequence, mode);
1687     }
1688 }
1689 
1690 // set up the tun device
1691 static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
1692 {
1693     struct ifreq ifr;
1694     const char  *interfaceName;
1695 
1696     sTunFd = open(OPENTHREAD_POSIX_TUN_DEVICE, O_RDWR | O_CLOEXEC | O_NONBLOCK);
1697     VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
1698 
1699     memset(&ifr, 0, sizeof(ifr));
1700     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
1701     if (!aPlatformConfig->mPersistentInterface)
1702     {
1703         ifr.ifr_flags |= static_cast<short>(IFF_TUN_EXCL);
1704     }
1705 
1706     interfaceName = aPlatformConfig->mInterfaceName;
1707     if (interfaceName)
1708     {
1709         VerifyOrDie(strlen(interfaceName) < IFNAMSIZ, OT_EXIT_INVALID_ARGUMENTS);
1710 
1711         strncpy(ifr.ifr_name, interfaceName, IFNAMSIZ);
1712     }
1713     else
1714     {
1715         strncpy(ifr.ifr_name, "wpan%d", IFNAMSIZ);
1716     }
1717 
1718     VerifyOrDie(ioctl(sTunFd, TUNSETIFF, static_cast<void *>(&ifr)) == 0, OT_EXIT_ERROR_ERRNO);
1719 
1720     strncpy(gNetifName, ifr.ifr_name, sizeof(gNetifName));
1721 
1722     if (aPlatformConfig->mPersistentInterface)
1723     {
1724         VerifyOrDie(ioctl(sTunFd, TUNSETPERSIST, 1) == 0, OT_EXIT_ERROR_ERRNO);
1725         // Set link down to reset the tun configuration.
1726         // This will drop all existing IP addresses on the interface.
1727         SetLinkState(gInstance, false);
1728     }
1729 
1730     VerifyOrDie(ioctl(sTunFd, TUNSETLINK, ARPHRD_NONE) == 0, OT_EXIT_ERROR_ERRNO);
1731 
1732     ifr.ifr_mtu = static_cast<int>(kMaxIp6Size);
1733     VerifyOrDie(ioctl(sIpFd, SIOCSIFMTU, static_cast<void *>(&ifr)) == 0, OT_EXIT_ERROR_ERRNO);
1734 }
1735 #endif
1736 
1737 #if defined(__APPLE__) && (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_UTUN)
1738 static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
1739 {
1740     (void)aPlatformConfig;
1741     int                 err = 0;
1742     struct sockaddr_ctl addr;
1743     struct ctl_info     info;
1744 
1745     sTunFd = SocketWithCloseExec(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL, kSocketNonBlock);
1746     VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
1747 
1748     memset(&info, 0, sizeof(info));
1749     strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
1750     err = ioctl(sTunFd, CTLIOCGINFO, &info);
1751     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
1752 
1753     addr.sc_id      = info.ctl_id;
1754     addr.sc_len     = sizeof(addr);
1755     addr.sc_family  = AF_SYSTEM;
1756     addr.ss_sysaddr = AF_SYS_CONTROL;
1757 
1758     addr.sc_unit = 0;
1759     err          = connect(sTunFd, (struct sockaddr *)&addr, sizeof(addr));
1760     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
1761 
1762     socklen_t devNameLen;
1763     devNameLen = (socklen_t)sizeof(gNetifName);
1764     err        = getsockopt(sTunFd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, gNetifName, &devNameLen);
1765     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
1766 
1767     otLogInfoPlat("[netif] Tunnel device name = '%s'", gNetifName);
1768 }
1769 #endif
1770 
1771 #if defined(__NetBSD__) || defined(__FreeBSD__)
1772 static otError destroyTunnel(void)
1773 {
1774     otError      error;
1775     struct ifreq ifr;
1776 
1777     memset(&ifr, 0, sizeof(ifr));
1778     strncpy(ifr.ifr_name, gNetifName, sizeof(ifr.ifr_name));
1779     VerifyOrExit(ioctl(sIpFd, SIOCIFDESTROY, &ifr) == 0, perror("ioctl"); error = OT_ERROR_FAILED);
1780     error = OT_ERROR_NONE;
1781 
1782 exit:
1783     return error;
1784 }
1785 #endif
1786 
1787 #if defined(__NetBSD__) ||                                                                             \
1788     (defined(__APPLE__) && (OPENTHREAD_POSIX_CONFIG_MACOS_TUN_OPTION == OT_POSIX_CONFIG_MACOS_TUN)) || \
1789     defined(__FreeBSD__)
1790 static void platformConfigureTunDevice(otPlatformConfig *aPlatformConfig)
1791 {
1792     int         flags = IFF_BROADCAST | IFF_MULTICAST;
1793     int         err;
1794     const char *last_slash;
1795     const char *path;
1796 
1797     (void)aPlatformConfig;
1798 
1799     path = OPENTHREAD_POSIX_TUN_DEVICE;
1800 
1801     sTunFd = open(path, O_RDWR | O_NONBLOCK);
1802     VerifyOrDie(sTunFd >= 0, OT_EXIT_ERROR_ERRNO);
1803 
1804 #if defined(__NetBSD__) || defined(__FreeBSD__)
1805     err = ioctl(sTunFd, TUNSIFMODE, &flags);
1806     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
1807 #endif
1808 
1809     flags = 1;
1810     err   = ioctl(sTunFd, TUNSIFHEAD, &flags);
1811     VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
1812 
1813     last_slash = strrchr(OPENTHREAD_POSIX_TUN_DEVICE, '/');
1814     VerifyOrDie(last_slash != nullptr, OT_EXIT_ERROR_ERRNO);
1815     last_slash++;
1816 
1817     strncpy(gNetifName, last_slash, sizeof(gNetifName));
1818 }
1819 #endif
1820 
1821 static void platformConfigureNetLink(void)
1822 {
1823 #if defined(__linux__)
1824     sNetlinkFd = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketNonBlock);
1825 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1826     sNetlinkFd = SocketWithCloseExec(PF_ROUTE, SOCK_RAW, 0, kSocketNonBlock);
1827 #else
1828 #error "!! Unknown platform !!"
1829 #endif
1830     VerifyOrDie(sNetlinkFd >= 0, OT_EXIT_ERROR_ERRNO);
1831 
1832 #if defined(__linux__)
1833     {
1834         struct sockaddr_nl sa;
1835 
1836         memset(&sa, 0, sizeof(sa));
1837         sa.nl_family = AF_NETLINK;
1838         sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
1839         VerifyOrDie(bind(sNetlinkFd, reinterpret_cast<struct sockaddr *>(&sa), sizeof(sa)) == 0, OT_EXIT_ERROR_ERRNO);
1840     }
1841 #endif
1842 
1843 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1844     {
1845         int status;
1846 #ifdef ROUTE_FILTER
1847         unsigned int msgfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR) |
1848                                  ROUTE_FILTER(RTM_NEWMADDR) | ROUTE_FILTER(RTM_DELMADDR);
1849 #define FILTER_CMD ROUTE_MSGFILTER
1850 #define FILTER_ARG msgfilter
1851 #define FILTER_ARG_SZ sizeof(msgfilter)
1852 #endif
1853 #ifdef RO_MSGFILTER
1854         uint8_t msgfilter[] = {RTM_IFINFO, RTM_NEWADDR, RTM_DELADDR};
1855 #define FILTER_CMD RO_MSGFILTER
1856 #define FILTER_ARG msgfilter
1857 #define FILTER_ARG_SZ sizeof(msgfilter)
1858 #endif
1859 #if defined(ROUTE_FILTER) || defined(RO_MSGFILTER)
1860         status = setsockopt(sNetlinkFd, AF_ROUTE, FILTER_CMD, FILTER_ARG, FILTER_ARG_SZ);
1861         VerifyOrDie(status == 0, OT_EXIT_ERROR_ERRNO);
1862 #endif
1863         status = fcntl(sNetlinkFd, F_SETFL, O_NONBLOCK);
1864         VerifyOrDie(status == 0, OT_EXIT_ERROR_ERRNO);
1865     }
1866 #endif // defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
1867 }
1868 
1869 void platformNetifInit(otPlatformConfig *aPlatformConfig)
1870 {
1871     sIpFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
1872     VerifyOrDie(sIpFd >= 0, OT_EXIT_ERROR_ERRNO);
1873 
1874     platformConfigureNetLink();
1875     platformConfigureTunDevice(aPlatformConfig);
1876 
1877     gNetifIndex = if_nametoindex(gNetifName);
1878     VerifyOrDie(gNetifIndex > 0, OT_EXIT_FAILURE);
1879 
1880 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
1881     mldListenerInit();
1882 #endif
1883 
1884 #if __linux__
1885     SetAddrGenModeToNone();
1886 #endif
1887 }
1888 
1889 void platformNetifSetUp(void)
1890 {
1891     OT_ASSERT(gInstance != nullptr);
1892 
1893     otIp6SetReceiveFilterEnabled(gInstance, true);
1894 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
1895     otIcmp6SetEchoMode(gInstance, OT_ICMP6_ECHO_HANDLER_ALL);
1896 #else
1897     otIcmp6SetEchoMode(gInstance, OT_ICMP6_ECHO_HANDLER_DISABLED);
1898 #endif
1899     otIp6SetReceiveCallback(gInstance, processReceive, gInstance);
1900 #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
1901     // We can use the same function for IPv6 and translated IPv4 messages.
1902     otNat64SetReceiveIp4Callback(gInstance, processReceive, gInstance);
1903 #endif
1904     otIp6SetAddressCallback(gInstance, processAddressChange, gInstance);
1905 #if OPENTHREAD_POSIX_MULTICAST_PROMISCUOUS_REQUIRED
1906     otIp6SetMulticastPromiscuousEnabled(aInstance, true);
1907 #endif
1908 #if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
1909     gResolver.Init();
1910 #endif
1911 }
1912 
1913 void platformNetifTearDown(void) {}
1914 
1915 void platformNetifDeinit(void)
1916 {
1917     if (sTunFd != -1)
1918     {
1919         close(sTunFd);
1920         sTunFd = -1;
1921 
1922 #if defined(__NetBSD__) || defined(__FreeBSD__)
1923         destroyTunnel();
1924 #endif
1925     }
1926 
1927     if (sIpFd != -1)
1928     {
1929         close(sIpFd);
1930         sIpFd = -1;
1931     }
1932 
1933     if (sNetlinkFd != -1)
1934     {
1935         close(sNetlinkFd);
1936         sNetlinkFd = -1;
1937     }
1938 
1939 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
1940     if (sMLDMonitorFd != -1)
1941     {
1942         close(sMLDMonitorFd);
1943         sMLDMonitorFd = -1;
1944     }
1945 #endif
1946 
1947     gNetifIndex = 0;
1948 }
1949 
1950 void platformNetifUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd)
1951 {
1952     OT_UNUSED_VARIABLE(aWriteFdSet);
1953 
1954     VerifyOrExit(gNetifIndex > 0);
1955 
1956     assert(sTunFd >= 0);
1957     assert(sNetlinkFd >= 0);
1958     assert(sIpFd >= 0);
1959 
1960     FD_SET(sTunFd, aReadFdSet);
1961     FD_SET(sTunFd, aErrorFdSet);
1962     FD_SET(sNetlinkFd, aReadFdSet);
1963     FD_SET(sNetlinkFd, aErrorFdSet);
1964 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
1965     FD_SET(sMLDMonitorFd, aReadFdSet);
1966     FD_SET(sMLDMonitorFd, aErrorFdSet);
1967 #endif
1968 
1969 #if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
1970     gResolver.UpdateFdSet(aReadFdSet, aErrorFdSet, aMaxFd);
1971 #endif
1972 
1973     if (sTunFd > *aMaxFd)
1974     {
1975         *aMaxFd = sTunFd;
1976     }
1977 
1978     if (sNetlinkFd > *aMaxFd)
1979     {
1980         *aMaxFd = sNetlinkFd;
1981     }
1982 
1983 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
1984     if (sMLDMonitorFd > *aMaxFd)
1985     {
1986         *aMaxFd = sMLDMonitorFd;
1987     }
1988 #endif
1989 exit:
1990     return;
1991 }
1992 
1993 void platformNetifProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, const fd_set *aErrorFdSet)
1994 {
1995     OT_UNUSED_VARIABLE(aWriteFdSet);
1996     VerifyOrExit(gNetifIndex > 0);
1997 
1998     if (FD_ISSET(sTunFd, aErrorFdSet))
1999     {
2000         close(sTunFd);
2001         DieNow(OT_EXIT_FAILURE);
2002     }
2003 
2004     if (FD_ISSET(sNetlinkFd, aErrorFdSet))
2005     {
2006         close(sNetlinkFd);
2007         DieNow(OT_EXIT_FAILURE);
2008     }
2009 
2010 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2011     if (FD_ISSET(sMLDMonitorFd, aErrorFdSet))
2012     {
2013         close(sMLDMonitorFd);
2014         DieNow(OT_EXIT_FAILURE);
2015     }
2016 #endif
2017 
2018     if (FD_ISSET(sTunFd, aReadFdSet))
2019     {
2020         processTransmit(gInstance);
2021     }
2022 
2023     if (FD_ISSET(sNetlinkFd, aReadFdSet))
2024     {
2025         processNetlinkEvent(gInstance);
2026     }
2027 
2028 #if OPENTHREAD_POSIX_USE_MLD_MONITOR
2029     if (FD_ISSET(sMLDMonitorFd, aReadFdSet))
2030     {
2031         processMLDEvent(gInstance);
2032     }
2033 #endif
2034 
2035 #if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
2036     gResolver.Process(aReadFdSet, aErrorFdSet);
2037 #endif
2038 
2039 exit:
2040     return;
2041 }
2042 
2043 #endif // OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
2044