xref: /aosp_15_r20/external/ot-br-posix/src/ncp/posix/netif.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *  Copyright (c) 2024, 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 #define OTBR_LOG_TAG "NETIF"
30 
31 #include "netif.hpp"
32 
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <net/if.h>
36 #include <net/if_arp.h>
37 #include <netinet/in.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
42 #include <unistd.h>
43 
44 #include <algorithm>
45 
46 #include "common/code_utils.hpp"
47 #include "common/logging.hpp"
48 #include "common/types.hpp"
49 #include "utils/socket_utils.hpp"
50 
51 namespace otbr {
52 
Netif(void)53 Netif::Netif(void)
54     : mTunFd(-1)
55     , mIpFd(-1)
56     , mNetlinkFd(-1)
57     , mNetlinkSequence(0)
58     , mNetifIndex(0)
59 {
60 }
61 
Init(const std::string & aInterfaceName,const Ip6SendFunc & aIp6SendFunc)62 otbrError Netif::Init(const std::string &aInterfaceName, const Ip6SendFunc &aIp6SendFunc)
63 {
64     otbrError error = OTBR_ERROR_NONE;
65 
66     VerifyOrExit(aIp6SendFunc, error = OTBR_ERROR_INVALID_ARGS);
67     mIp6SendFunc = aIp6SendFunc;
68 
69     mIpFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
70     VerifyOrExit(mIpFd >= 0, error = OTBR_ERROR_ERRNO);
71 
72     SuccessOrExit(error = CreateTunDevice(aInterfaceName));
73     SuccessOrExit(error = InitNetlink());
74 
75     mNetifIndex = if_nametoindex(mNetifName.c_str());
76     VerifyOrExit(mNetifIndex > 0, error = OTBR_ERROR_INVALID_STATE);
77 
78     PlatformSpecificInit();
79 
80 exit:
81     if (error != OTBR_ERROR_NONE)
82     {
83         Clear();
84     }
85     return error;
86 }
87 
Deinit(void)88 void Netif::Deinit(void)
89 {
90     Clear();
91 }
92 
Process(const MainloopContext * aContext)93 void Netif::Process(const MainloopContext *aContext)
94 {
95     if (FD_ISSET(mTunFd, &aContext->mErrorFdSet))
96     {
97         close(mTunFd);
98         DieNow("Error on Tun Fd!");
99     }
100 
101     if (FD_ISSET(mTunFd, &aContext->mReadFdSet))
102     {
103         ProcessIp6Send();
104     }
105 }
106 
UpdateFdSet(MainloopContext * aContext)107 void Netif::UpdateFdSet(MainloopContext *aContext)
108 {
109     assert(aContext != nullptr);
110     assert(mTunFd >= 0);
111     assert(mIpFd >= 0);
112 
113     aContext->AddFdToSet(mTunFd, MainloopContext::kErrorFdSet | MainloopContext::kReadFdSet);
114 }
115 
UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> & aAddrInfos)116 void Netif::UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> &aAddrInfos)
117 {
118     // Remove stale addresses
119     for (const Ip6AddressInfo &addrInfo : mIp6UnicastAddresses)
120     {
121         if (std::find(aAddrInfos.begin(), aAddrInfos.end(), addrInfo) == aAddrInfos.end())
122         {
123             otbrLogInfo("Remove address: %s", Ip6Address(addrInfo.mAddress).ToString().c_str());
124             // TODO: Verify success of the addition or deletion in Netlink response.
125             ProcessUnicastAddressChange(addrInfo, false);
126         }
127     }
128 
129     // Add new addresses
130     for (const Ip6AddressInfo &addrInfo : aAddrInfos)
131     {
132         if (std::find(mIp6UnicastAddresses.begin(), mIp6UnicastAddresses.end(), addrInfo) == mIp6UnicastAddresses.end())
133         {
134             otbrLogInfo("Add address: %s", Ip6Address(addrInfo.mAddress).ToString().c_str());
135             // TODO: Verify success of the addition or deletion in Netlink response.
136             ProcessUnicastAddressChange(addrInfo, true);
137         }
138     }
139 
140     mIp6UnicastAddresses.assign(aAddrInfos.begin(), aAddrInfos.end());
141 }
142 
UpdateIp6MulticastAddresses(const std::vector<Ip6Address> & aAddrs)143 otbrError Netif::UpdateIp6MulticastAddresses(const std::vector<Ip6Address> &aAddrs)
144 {
145     otbrError error = OTBR_ERROR_NONE;
146 
147     // Remove stale addresses
148     for (const Ip6Address &address : mIp6MulticastAddresses)
149     {
150         if (std::find(aAddrs.begin(), aAddrs.end(), address) == aAddrs.end())
151         {
152             otbrLogInfo("Remove address: %s", Ip6Address(address).ToString().c_str());
153             SuccessOrExit(error = ProcessMulticastAddressChange(address, /* aIsAdded */ false));
154         }
155     }
156 
157     // Add new addresses
158     for (const Ip6Address &address : aAddrs)
159     {
160         if (std::find(mIp6MulticastAddresses.begin(), mIp6MulticastAddresses.end(), address) ==
161             mIp6MulticastAddresses.end())
162         {
163             otbrLogInfo("Add address: %s", Ip6Address(address).ToString().c_str());
164             SuccessOrExit(error = ProcessMulticastAddressChange(address, /* aIsAdded */ true));
165         }
166     }
167 
168     mIp6MulticastAddresses.assign(aAddrs.begin(), aAddrs.end());
169 
170 exit:
171     if (error != OTBR_ERROR_NONE)
172     {
173         mIp6MulticastAddresses.clear();
174     }
175     return error;
176 }
177 
ProcessMulticastAddressChange(const Ip6Address & aAddress,bool aIsAdded)178 otbrError Netif::ProcessMulticastAddressChange(const Ip6Address &aAddress, bool aIsAdded)
179 {
180     struct ipv6_mreq mreq;
181     otbrError        error = OTBR_ERROR_NONE;
182     int              err;
183 
184     VerifyOrExit(mIpFd >= 0, error = OTBR_ERROR_INVALID_STATE);
185     memcpy(&mreq.ipv6mr_multiaddr, &aAddress, sizeof(mreq.ipv6mr_multiaddr));
186     mreq.ipv6mr_interface = mNetifIndex;
187 
188     err = setsockopt(mIpFd, IPPROTO_IPV6, (aIsAdded ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP), &mreq, sizeof(mreq));
189 
190     if (err != 0)
191     {
192         otbrLogWarning("%s failure (%d)", aIsAdded ? "IPV6_JOIN_GROUP" : "IPV6_LEAVE_GROUP", errno);
193         ExitNow(error = OTBR_ERROR_ERRNO);
194     }
195 
196     otbrLogInfo("%s multicast address %s", aIsAdded ? "Added" : "Removed", Ip6Address(aAddress).ToString().c_str());
197 
198 exit:
199     return error;
200 }
201 
SetNetifState(bool aState)202 void Netif::SetNetifState(bool aState)
203 {
204     otbrError    error = OTBR_ERROR_NONE;
205     struct ifreq ifr;
206     bool         ifState = false;
207 
208     VerifyOrExit(mIpFd >= 0);
209     memset(&ifr, 0, sizeof(ifr));
210     strncpy(ifr.ifr_name, mNetifName.c_str(), IFNAMSIZ - 1);
211     VerifyOrExit(ioctl(mIpFd, SIOCGIFFLAGS, &ifr) == 0, error = OTBR_ERROR_ERRNO);
212 
213     ifState = ((ifr.ifr_flags & IFF_UP) == IFF_UP) ? true : false;
214 
215     otbrLogInfo("Changing interface state to %s%s.", aState ? "up" : "down",
216                 (ifState == aState) ? " (already done, ignoring)" : "");
217 
218     if (ifState != aState)
219     {
220         ifr.ifr_flags = aState ? (ifr.ifr_flags | IFF_UP) : (ifr.ifr_flags & ~IFF_UP);
221         VerifyOrExit(ioctl(mIpFd, SIOCSIFFLAGS, &ifr) == 0, error = OTBR_ERROR_ERRNO);
222     }
223 
224 exit:
225     if (error != OTBR_ERROR_NONE)
226     {
227         otbrLogWarning("Failed to update state %s", otbrErrorString(error));
228     }
229 }
230 
Ip6Receive(const uint8_t * aBuf,uint16_t aLen)231 void Netif::Ip6Receive(const uint8_t *aBuf, uint16_t aLen)
232 {
233     otbrError error = OTBR_ERROR_NONE;
234 
235     VerifyOrExit(aLen <= kIp6Mtu, error = OTBR_ERROR_DROPPED);
236     VerifyOrExit(mTunFd > 0, error = OTBR_ERROR_INVALID_STATE);
237 
238     otbrLogInfo("Packet from NCP (%u bytes)", aLen);
239     VerifyOrExit(write(mTunFd, aBuf, aLen) == aLen, error = OTBR_ERROR_ERRNO);
240 
241 exit:
242     if (error != OTBR_ERROR_NONE)
243     {
244         otbrLogWarning("Failed to receive, error:%s", otbrErrorString(error));
245     }
246 }
247 
ProcessIp6Send(void)248 void Netif::ProcessIp6Send(void)
249 {
250     ssize_t   rval;
251     uint8_t   packet[kIp6Mtu];
252     otbrError error = OTBR_ERROR_NONE;
253 
254     rval = read(mTunFd, packet, sizeof(packet));
255     VerifyOrExit(rval > 0, error = OTBR_ERROR_ERRNO);
256 
257     otbrLogInfo("Send packet (%hu bytes)", static_cast<uint16_t>(rval));
258 
259     if (mIp6SendFunc != nullptr)
260     {
261         error = mIp6SendFunc(packet, rval);
262     }
263 exit:
264     if (error == OTBR_ERROR_ERRNO)
265     {
266         otbrLogInfo("Error reading from Tun Fd: %s", strerror(errno));
267     }
268 }
269 
Clear(void)270 void Netif::Clear(void)
271 {
272     if (mTunFd != -1)
273     {
274         close(mTunFd);
275         mTunFd = -1;
276     }
277 
278     if (mIpFd != -1)
279     {
280         close(mIpFd);
281         mIpFd = -1;
282     }
283 
284     if (mNetlinkFd != -1)
285     {
286         close(mNetlinkFd);
287         mNetlinkFd = -1;
288     }
289 
290     mNetifIndex = 0;
291     mIp6UnicastAddresses.clear();
292     mIp6MulticastAddresses.clear();
293     mIp6SendFunc = nullptr;
294 }
295 
296 } // namespace otbr
297