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