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