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