xref: /aosp_15_r20/external/ot-br-posix/src/ncp/posix/netif_linux.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker  *  Copyright (c) 2024, The OpenThread Authors.
3*4a64e381SAndroid Build Coastguard Worker  *  All rights reserved.
4*4a64e381SAndroid Build Coastguard Worker  *
5*4a64e381SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*4a64e381SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*4a64e381SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*4a64e381SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*4a64e381SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*4a64e381SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*4a64e381SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*4a64e381SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*4a64e381SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*4a64e381SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*4a64e381SAndroid Build Coastguard Worker  *
16*4a64e381SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*4a64e381SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*4a64e381SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*4a64e381SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*4a64e381SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*4a64e381SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*4a64e381SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*4a64e381SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*4a64e381SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*4a64e381SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*4a64e381SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*4a64e381SAndroid Build Coastguard Worker  */
28*4a64e381SAndroid Build Coastguard Worker 
29*4a64e381SAndroid Build Coastguard Worker #ifdef __linux__
30*4a64e381SAndroid Build Coastguard Worker 
31*4a64e381SAndroid Build Coastguard Worker #define OTBR_LOG_TAG "NETIF"
32*4a64e381SAndroid Build Coastguard Worker 
33*4a64e381SAndroid Build Coastguard Worker #include "netif.hpp"
34*4a64e381SAndroid Build Coastguard Worker 
35*4a64e381SAndroid Build Coastguard Worker #include <assert.h>
36*4a64e381SAndroid Build Coastguard Worker #include <fcntl.h>
37*4a64e381SAndroid Build Coastguard Worker #include <linux/if.h>
38*4a64e381SAndroid Build Coastguard Worker #include <linux/if_tun.h>
39*4a64e381SAndroid Build Coastguard Worker #include <linux/netlink.h>
40*4a64e381SAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
41*4a64e381SAndroid Build Coastguard Worker #include <net/if.h>
42*4a64e381SAndroid Build Coastguard Worker #include <net/if_arp.h>
43*4a64e381SAndroid Build Coastguard Worker #include <sys/ioctl.h>
44*4a64e381SAndroid Build Coastguard Worker #include <unistd.h>
45*4a64e381SAndroid Build Coastguard Worker 
46*4a64e381SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
47*4a64e381SAndroid Build Coastguard Worker #include "common/logging.hpp"
48*4a64e381SAndroid Build Coastguard Worker #include "common/types.hpp"
49*4a64e381SAndroid Build Coastguard Worker #include "utils/socket_utils.hpp"
50*4a64e381SAndroid Build Coastguard Worker 
51*4a64e381SAndroid Build Coastguard Worker #ifndef OTBR_POSIX_TUN_DEVICE
52*4a64e381SAndroid Build Coastguard Worker #define OTBR_POSIX_TUN_DEVICE "/dev/net/tun"
53*4a64e381SAndroid Build Coastguard Worker #endif
54*4a64e381SAndroid Build Coastguard Worker 
55*4a64e381SAndroid Build Coastguard Worker namespace otbr {
56*4a64e381SAndroid Build Coastguard Worker 
AddRtAttr(nlmsghdr * aHeader,uint32_t aMaxLen,uint8_t aType,const void * aData,uint8_t aLen)57*4a64e381SAndroid Build Coastguard Worker static struct rtattr *AddRtAttr(nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, const void *aData, uint8_t aLen)
58*4a64e381SAndroid Build Coastguard Worker {
59*4a64e381SAndroid Build Coastguard Worker     uint8_t len = RTA_LENGTH(aLen);
60*4a64e381SAndroid Build Coastguard Worker     rtattr *rta;
61*4a64e381SAndroid Build Coastguard Worker 
62*4a64e381SAndroid Build Coastguard Worker     assert(NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len) <= aMaxLen);
63*4a64e381SAndroid Build Coastguard Worker     OTBR_UNUSED_VARIABLE(aMaxLen);
64*4a64e381SAndroid Build Coastguard Worker 
65*4a64e381SAndroid Build Coastguard Worker     rta           = reinterpret_cast<rtattr *>(reinterpret_cast<char *>(aHeader) + NLMSG_ALIGN((aHeader)->nlmsg_len));
66*4a64e381SAndroid Build Coastguard Worker     rta->rta_type = aType;
67*4a64e381SAndroid Build Coastguard Worker     rta->rta_len  = len;
68*4a64e381SAndroid Build Coastguard Worker     if (aLen)
69*4a64e381SAndroid Build Coastguard Worker     {
70*4a64e381SAndroid Build Coastguard Worker         memcpy(RTA_DATA(rta), aData, aLen);
71*4a64e381SAndroid Build Coastguard Worker     }
72*4a64e381SAndroid Build Coastguard Worker     aHeader->nlmsg_len = NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len);
73*4a64e381SAndroid Build Coastguard Worker 
74*4a64e381SAndroid Build Coastguard Worker     return rta;
75*4a64e381SAndroid Build Coastguard Worker }
76*4a64e381SAndroid Build Coastguard Worker 
CreateTunDevice(const std::string & aInterfaceName)77*4a64e381SAndroid Build Coastguard Worker otbrError Netif::CreateTunDevice(const std::string &aInterfaceName)
78*4a64e381SAndroid Build Coastguard Worker {
79*4a64e381SAndroid Build Coastguard Worker     ifreq     ifr;
80*4a64e381SAndroid Build Coastguard Worker     otbrError error = OTBR_ERROR_NONE;
81*4a64e381SAndroid Build Coastguard Worker 
82*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(aInterfaceName.size() < IFNAMSIZ, error = OTBR_ERROR_INVALID_ARGS);
83*4a64e381SAndroid Build Coastguard Worker 
84*4a64e381SAndroid Build Coastguard Worker     memset(&ifr, 0, sizeof(ifr));
85*4a64e381SAndroid Build Coastguard Worker     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
86*4a64e381SAndroid Build Coastguard Worker     if (aInterfaceName.size() > 0)
87*4a64e381SAndroid Build Coastguard Worker     {
88*4a64e381SAndroid Build Coastguard Worker         strncpy(ifr.ifr_name, aInterfaceName.c_str(), aInterfaceName.size());
89*4a64e381SAndroid Build Coastguard Worker     }
90*4a64e381SAndroid Build Coastguard Worker     else
91*4a64e381SAndroid Build Coastguard Worker     {
92*4a64e381SAndroid Build Coastguard Worker         strncpy(ifr.ifr_name, "wpan%d", IFNAMSIZ);
93*4a64e381SAndroid Build Coastguard Worker     }
94*4a64e381SAndroid Build Coastguard Worker 
95*4a64e381SAndroid Build Coastguard Worker     mTunFd = open(OTBR_POSIX_TUN_DEVICE, O_RDWR | O_CLOEXEC | O_NONBLOCK);
96*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(mTunFd >= 0, error = OTBR_ERROR_ERRNO);
97*4a64e381SAndroid Build Coastguard Worker 
98*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(ioctl(mTunFd, TUNSETIFF, &ifr) == 0, error = OTBR_ERROR_ERRNO);
99*4a64e381SAndroid Build Coastguard Worker 
100*4a64e381SAndroid Build Coastguard Worker     mNetifName.assign(ifr.ifr_name, strlen(ifr.ifr_name));
101*4a64e381SAndroid Build Coastguard Worker     otbrLogInfo("Netif name: %s", mNetifName.c_str());
102*4a64e381SAndroid Build Coastguard Worker 
103*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(ioctl(mTunFd, TUNSETLINK, ARPHRD_NONE) == 0, error = OTBR_ERROR_ERRNO);
104*4a64e381SAndroid Build Coastguard Worker 
105*4a64e381SAndroid Build Coastguard Worker     ifr.ifr_mtu = static_cast<int>(kIp6Mtu);
106*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(ioctl(mIpFd, SIOCSIFMTU, &ifr) == 0, error = OTBR_ERROR_ERRNO);
107*4a64e381SAndroid Build Coastguard Worker 
108*4a64e381SAndroid Build Coastguard Worker exit:
109*4a64e381SAndroid Build Coastguard Worker     return error;
110*4a64e381SAndroid Build Coastguard Worker }
111*4a64e381SAndroid Build Coastguard Worker 
InitNetlink(void)112*4a64e381SAndroid Build Coastguard Worker otbrError Netif::InitNetlink(void)
113*4a64e381SAndroid Build Coastguard Worker {
114*4a64e381SAndroid Build Coastguard Worker     otbrError error = OTBR_ERROR_NONE;
115*4a64e381SAndroid Build Coastguard Worker 
116*4a64e381SAndroid Build Coastguard Worker     mNetlinkFd = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketNonBlock);
117*4a64e381SAndroid Build Coastguard Worker     VerifyOrExit(mNetlinkFd >= 0, error = OTBR_ERROR_ERRNO);
118*4a64e381SAndroid Build Coastguard Worker 
119*4a64e381SAndroid Build Coastguard Worker #if defined(SOL_NETLINK)
120*4a64e381SAndroid Build Coastguard Worker     {
121*4a64e381SAndroid Build Coastguard Worker         int enable = 1;
122*4a64e381SAndroid Build Coastguard Worker 
123*4a64e381SAndroid Build Coastguard Worker #if defined(NETLINK_EXT_ACK)
124*4a64e381SAndroid Build Coastguard Worker         if (setsockopt(mNetlinkFd, SOL_NETLINK, NETLINK_EXT_ACK, &enable, sizeof(enable)) != 0)
125*4a64e381SAndroid Build Coastguard Worker         {
126*4a64e381SAndroid Build Coastguard Worker             otbrLogWarning("Failed to enable NETLINK_EXT_ACK: %s", strerror(errno));
127*4a64e381SAndroid Build Coastguard Worker         }
128*4a64e381SAndroid Build Coastguard Worker #endif
129*4a64e381SAndroid Build Coastguard Worker #if defined(NETLINK_CAP_ACK)
130*4a64e381SAndroid Build Coastguard Worker         if (setsockopt(mNetlinkFd, SOL_NETLINK, NETLINK_CAP_ACK, &enable, sizeof(enable)) != 0)
131*4a64e381SAndroid Build Coastguard Worker         {
132*4a64e381SAndroid Build Coastguard Worker             otbrLogWarning("Failed to enable NETLINK_CAP_ACK: %s", strerror(errno));
133*4a64e381SAndroid Build Coastguard Worker         }
134*4a64e381SAndroid Build Coastguard Worker #endif
135*4a64e381SAndroid Build Coastguard Worker     }
136*4a64e381SAndroid Build Coastguard Worker #endif
137*4a64e381SAndroid Build Coastguard Worker 
138*4a64e381SAndroid Build Coastguard Worker     {
139*4a64e381SAndroid Build Coastguard Worker         sockaddr_nl sa;
140*4a64e381SAndroid Build Coastguard Worker 
141*4a64e381SAndroid Build Coastguard Worker         memset(&sa, 0, sizeof(sa));
142*4a64e381SAndroid Build Coastguard Worker         sa.nl_family = AF_NETLINK;
143*4a64e381SAndroid Build Coastguard Worker         sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
144*4a64e381SAndroid Build Coastguard Worker         VerifyOrExit(bind(mNetlinkFd, reinterpret_cast<sockaddr *>(&sa), sizeof(sa)) == 0, error = OTBR_ERROR_ERRNO);
145*4a64e381SAndroid Build Coastguard Worker     }
146*4a64e381SAndroid Build Coastguard Worker 
147*4a64e381SAndroid Build Coastguard Worker exit:
148*4a64e381SAndroid Build Coastguard Worker     return error;
149*4a64e381SAndroid Build Coastguard Worker }
150*4a64e381SAndroid Build Coastguard Worker 
PlatformSpecificInit(void)151*4a64e381SAndroid Build Coastguard Worker void Netif::PlatformSpecificInit(void)
152*4a64e381SAndroid Build Coastguard Worker {
153*4a64e381SAndroid Build Coastguard Worker     SetAddrGenModeToNone();
154*4a64e381SAndroid Build Coastguard Worker }
155*4a64e381SAndroid Build Coastguard Worker 
SetAddrGenModeToNone(void)156*4a64e381SAndroid Build Coastguard Worker void Netif::SetAddrGenModeToNone(void)
157*4a64e381SAndroid Build Coastguard Worker {
158*4a64e381SAndroid Build Coastguard Worker     struct
159*4a64e381SAndroid Build Coastguard Worker     {
160*4a64e381SAndroid Build Coastguard Worker         nlmsghdr  nh;
161*4a64e381SAndroid Build Coastguard Worker         ifinfomsg ifi;
162*4a64e381SAndroid Build Coastguard Worker         char      buf[512];
163*4a64e381SAndroid Build Coastguard Worker     } req;
164*4a64e381SAndroid Build Coastguard Worker 
165*4a64e381SAndroid Build Coastguard Worker     const uint8_t mode = IN6_ADDR_GEN_MODE_NONE;
166*4a64e381SAndroid Build Coastguard Worker 
167*4a64e381SAndroid Build Coastguard Worker     memset(&req, 0, sizeof(req));
168*4a64e381SAndroid Build Coastguard Worker 
169*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_len   = NLMSG_LENGTH(sizeof(ifinfomsg));
170*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
171*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_type  = RTM_NEWLINK;
172*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_pid   = 0;
173*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_seq   = ++mNetlinkSequence;
174*4a64e381SAndroid Build Coastguard Worker 
175*4a64e381SAndroid Build Coastguard Worker     req.ifi.ifi_index  = static_cast<int>(mNetifIndex);
176*4a64e381SAndroid Build Coastguard Worker     req.ifi.ifi_change = 0xffffffff;
177*4a64e381SAndroid Build Coastguard Worker     req.ifi.ifi_flags  = IFF_MULTICAST | IFF_NOARP;
178*4a64e381SAndroid Build Coastguard Worker 
179*4a64e381SAndroid Build Coastguard Worker     {
180*4a64e381SAndroid Build Coastguard Worker         rtattr *afSpec           = AddRtAttr(&req.nh, sizeof(req), IFLA_AF_SPEC, 0, 0);
181*4a64e381SAndroid Build Coastguard Worker         rtattr *afInet6          = AddRtAttr(&req.nh, sizeof(req), AF_INET6, 0, 0);
182*4a64e381SAndroid Build Coastguard Worker         rtattr *inet6AddrGenMode = AddRtAttr(&req.nh, sizeof(req), IFLA_INET6_ADDR_GEN_MODE, &mode, sizeof(mode));
183*4a64e381SAndroid Build Coastguard Worker 
184*4a64e381SAndroid Build Coastguard Worker         afInet6->rta_len += inet6AddrGenMode->rta_len;
185*4a64e381SAndroid Build Coastguard Worker         afSpec->rta_len += afInet6->rta_len;
186*4a64e381SAndroid Build Coastguard Worker     }
187*4a64e381SAndroid Build Coastguard Worker 
188*4a64e381SAndroid Build Coastguard Worker     if (send(mNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
189*4a64e381SAndroid Build Coastguard Worker     {
190*4a64e381SAndroid Build Coastguard Worker         otbrLogInfo("Sent request#%u to set addr_gen_mode to %d", mNetlinkSequence, mode);
191*4a64e381SAndroid Build Coastguard Worker     }
192*4a64e381SAndroid Build Coastguard Worker     else
193*4a64e381SAndroid Build Coastguard Worker     {
194*4a64e381SAndroid Build Coastguard Worker         otbrLogWarning("Failed to send request#%u to set addr_gen_mode to %d", mNetlinkSequence, mode);
195*4a64e381SAndroid Build Coastguard Worker     }
196*4a64e381SAndroid Build Coastguard Worker }
197*4a64e381SAndroid Build Coastguard Worker 
ProcessUnicastAddressChange(const Ip6AddressInfo & aAddressInfo,bool aIsAdded)198*4a64e381SAndroid Build Coastguard Worker void Netif::ProcessUnicastAddressChange(const Ip6AddressInfo &aAddressInfo, bool aIsAdded)
199*4a64e381SAndroid Build Coastguard Worker {
200*4a64e381SAndroid Build Coastguard Worker     struct
201*4a64e381SAndroid Build Coastguard Worker     {
202*4a64e381SAndroid Build Coastguard Worker         nlmsghdr  nh;
203*4a64e381SAndroid Build Coastguard Worker         ifaddrmsg ifa;
204*4a64e381SAndroid Build Coastguard Worker         char      buf[512];
205*4a64e381SAndroid Build Coastguard Worker     } req;
206*4a64e381SAndroid Build Coastguard Worker 
207*4a64e381SAndroid Build Coastguard Worker     assert(mIpFd >= 0);
208*4a64e381SAndroid Build Coastguard Worker     memset(&req, 0, sizeof(req));
209*4a64e381SAndroid Build Coastguard Worker 
210*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_len   = NLMSG_LENGTH(sizeof(ifaddrmsg));
211*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (aIsAdded ? (NLM_F_CREATE | NLM_F_EXCL) : 0);
212*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_type  = aIsAdded ? RTM_NEWADDR : RTM_DELADDR;
213*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_pid   = 0;
214*4a64e381SAndroid Build Coastguard Worker     req.nh.nlmsg_seq   = ++mNetlinkSequence;
215*4a64e381SAndroid Build Coastguard Worker 
216*4a64e381SAndroid Build Coastguard Worker     req.ifa.ifa_family    = AF_INET6;
217*4a64e381SAndroid Build Coastguard Worker     req.ifa.ifa_prefixlen = aAddressInfo.mPrefixLength;
218*4a64e381SAndroid Build Coastguard Worker     req.ifa.ifa_flags     = IFA_F_NODAD;
219*4a64e381SAndroid Build Coastguard Worker     req.ifa.ifa_scope     = aAddressInfo.mScope;
220*4a64e381SAndroid Build Coastguard Worker     req.ifa.ifa_index     = mNetifIndex;
221*4a64e381SAndroid Build Coastguard Worker 
222*4a64e381SAndroid Build Coastguard Worker     AddRtAttr(&req.nh, sizeof(req), IFA_LOCAL, &aAddressInfo.mAddress, sizeof(aAddressInfo.mAddress));
223*4a64e381SAndroid Build Coastguard Worker 
224*4a64e381SAndroid Build Coastguard Worker     if (!aAddressInfo.mPreferred || aAddressInfo.mMeshLocal)
225*4a64e381SAndroid Build Coastguard Worker     {
226*4a64e381SAndroid Build Coastguard Worker         ifa_cacheinfo cacheinfo;
227*4a64e381SAndroid Build Coastguard Worker 
228*4a64e381SAndroid Build Coastguard Worker         memset(&cacheinfo, 0, sizeof(cacheinfo));
229*4a64e381SAndroid Build Coastguard Worker         cacheinfo.ifa_valid = UINT32_MAX;
230*4a64e381SAndroid Build Coastguard Worker 
231*4a64e381SAndroid Build Coastguard Worker         AddRtAttr(&req.nh, sizeof(req), IFA_CACHEINFO, &cacheinfo, sizeof(cacheinfo));
232*4a64e381SAndroid Build Coastguard Worker     }
233*4a64e381SAndroid Build Coastguard Worker 
234*4a64e381SAndroid Build Coastguard Worker     if (send(mNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
235*4a64e381SAndroid Build Coastguard Worker     {
236*4a64e381SAndroid Build Coastguard Worker         otbrLogInfo("Sent request#%u to %s %s/%u", mNetlinkSequence, (aIsAdded ? "add" : "remove"),
237*4a64e381SAndroid Build Coastguard Worker                     Ip6Address(aAddressInfo.mAddress).ToString().c_str(), aAddressInfo.mPrefixLength);
238*4a64e381SAndroid Build Coastguard Worker     }
239*4a64e381SAndroid Build Coastguard Worker     else
240*4a64e381SAndroid Build Coastguard Worker     {
241*4a64e381SAndroid Build Coastguard Worker         otbrLogWarning("Failed to send request#%u to %s %s/%u", mNetlinkSequence, (aIsAdded ? "add" : "remove"),
242*4a64e381SAndroid Build Coastguard Worker                        Ip6Address(aAddressInfo.mAddress).ToString().c_str(), aAddressInfo.mPrefixLength);
243*4a64e381SAndroid Build Coastguard Worker     }
244*4a64e381SAndroid Build Coastguard Worker }
245*4a64e381SAndroid Build Coastguard Worker 
246*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
247*4a64e381SAndroid Build Coastguard Worker 
248*4a64e381SAndroid Build Coastguard Worker #endif // __linux__
249