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