• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <arpa/inet.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <ifaddrs.h>
37 #include <net/if.h>
38 #include <net/if_arp.h>
39 #include <netinet/in.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <sys/ioctl.h>
43 #include <sys/socket.h>
44 #include <unistd.h>
45 
46 #include <algorithm>
47 
48 #include "common/code_utils.hpp"
49 #include "common/logging.hpp"
50 #include "common/types.hpp"
51 #include "utils/socket_utils.hpp"
52 
53 namespace otbr {
54 
Ip6Send(const uint8_t * aData,uint16_t aLength)55 otbrError Netif::Dependencies::Ip6Send(const uint8_t *aData, uint16_t aLength)
56 {
57     OTBR_UNUSED_VARIABLE(aData);
58     OTBR_UNUSED_VARIABLE(aLength);
59 
60     return OTBR_ERROR_NONE;
61 }
62 
Ip6MulAddrUpdateSubscription(const otIp6Address & aAddress,bool aIsAdd)63 otbrError Netif::Dependencies::Ip6MulAddrUpdateSubscription(const otIp6Address &aAddress, bool aIsAdd)
64 {
65     OTBR_UNUSED_VARIABLE(aAddress);
66     OTBR_UNUSED_VARIABLE(aIsAdd);
67 
68     return OTBR_ERROR_NONE;
69 }
70 
71 OT_TOOL_PACKED_BEGIN
72 struct Mldv2Header
73 {
74     uint8_t  mType;
75     uint8_t  _rsv0;
76     uint16_t mChecksum;
77     uint16_t _rsv1;
78     uint16_t mNumRecords;
79 } OT_TOOL_PACKED_END;
80 
81 OT_TOOL_PACKED_BEGIN
82 struct Mldv2Record
83 {
84     uint8_t         mRecordType;
85     uint8_t         mAuxDataLen;
86     uint16_t        mNumSources;
87     struct in6_addr mMulticastAddress;
88 } OT_TOOL_PACKED_END;
89 
90 enum
91 {
92     kIcmpv6Mldv2Type                      = 143,
93     kIcmpv6Mldv2ModeIsIncludeType         = 1,
94     kIcmpv6Mldv2ModeIsExcludeType         = 2,
95     kIcmpv6Mldv2RecordChangeToIncludeType = 3,
96     kIcmpv6Mldv2RecordChangeToExcludeType = 4,
97 };
98 
Netif(Dependencies & aDependencies)99 Netif::Netif(Dependencies &aDependencies)
100     : mTunFd(-1)
101     , mIpFd(-1)
102     , mNetlinkFd(-1)
103     , mMldFd(-1)
104     , mNetlinkSequence(0)
105     , mNetifIndex(0)
106     , mDeps(aDependencies)
107 {
108 }
109 
Init(const std::string & aInterfaceName)110 otbrError Netif::Init(const std::string &aInterfaceName)
111 {
112     otbrError error = OTBR_ERROR_NONE;
113 
114     mIpFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
115     VerifyOrExit(mIpFd >= 0, error = OTBR_ERROR_ERRNO);
116 
117     SuccessOrExit(error = CreateTunDevice(aInterfaceName));
118     SuccessOrExit(error = InitNetlink());
119 
120     mNetifIndex = if_nametoindex(mNetifName.c_str());
121     VerifyOrExit(mNetifIndex > 0, error = OTBR_ERROR_INVALID_STATE);
122 
123     SuccessOrExit(error = InitMldListener());
124 
125     PlatformSpecificInit();
126 
127 exit:
128     if (error != OTBR_ERROR_NONE)
129     {
130         Clear();
131     }
132     return error;
133 }
134 
Deinit(void)135 void Netif::Deinit(void)
136 {
137     Clear();
138 }
139 
Process(const MainloopContext * aContext)140 void Netif::Process(const MainloopContext *aContext)
141 {
142     if (FD_ISSET(mTunFd, &aContext->mErrorFdSet))
143     {
144         close(mTunFd);
145         DieNow("Error on Tun Fd!");
146     }
147 
148     if (FD_ISSET(mMldFd, &aContext->mErrorFdSet))
149     {
150         close(mMldFd);
151         DieNow("Error on MLD Fd!");
152     }
153 
154     if (FD_ISSET(mTunFd, &aContext->mReadFdSet))
155     {
156         ProcessIp6Send();
157     }
158 
159     if (FD_ISSET(mMldFd, &aContext->mReadFdSet))
160     {
161         ProcessMldEvent();
162     }
163 }
164 
UpdateFdSet(MainloopContext * aContext)165 void Netif::UpdateFdSet(MainloopContext *aContext)
166 {
167     assert(aContext != nullptr);
168     assert(mTunFd >= 0);
169     assert(mIpFd >= 0);
170     assert(mMldFd >= 0);
171 
172     aContext->AddFdToSet(mTunFd, MainloopContext::kErrorFdSet | MainloopContext::kReadFdSet);
173     aContext->AddFdToSet(mMldFd, MainloopContext::kErrorFdSet | MainloopContext::kReadFdSet);
174 }
175 
UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> & aAddrInfos)176 void Netif::UpdateIp6UnicastAddresses(const std::vector<Ip6AddressInfo> &aAddrInfos)
177 {
178     // Remove stale addresses
179     for (const Ip6AddressInfo &addrInfo : mIp6UnicastAddresses)
180     {
181         if (std::find(aAddrInfos.begin(), aAddrInfos.end(), addrInfo) == aAddrInfos.end())
182         {
183             otbrLogInfo("Remove address: %s", Ip6Address(addrInfo.mAddress).ToString().c_str());
184             // TODO: Verify success of the addition or deletion in Netlink response.
185             ProcessUnicastAddressChange(addrInfo, false);
186         }
187     }
188 
189     // Add new addresses
190     for (const Ip6AddressInfo &addrInfo : aAddrInfos)
191     {
192         if (std::find(mIp6UnicastAddresses.begin(), mIp6UnicastAddresses.end(), addrInfo) == mIp6UnicastAddresses.end())
193         {
194             otbrLogInfo("Add address: %s", Ip6Address(addrInfo.mAddress).ToString().c_str());
195             // TODO: Verify success of the addition or deletion in Netlink response.
196             ProcessUnicastAddressChange(addrInfo, true);
197         }
198     }
199 
200     mIp6UnicastAddresses.assign(aAddrInfos.begin(), aAddrInfos.end());
201 }
202 
UpdateIp6MulticastAddresses(const std::vector<Ip6Address> & aAddrs)203 otbrError Netif::UpdateIp6MulticastAddresses(const std::vector<Ip6Address> &aAddrs)
204 {
205     otbrError error = OTBR_ERROR_NONE;
206 
207     // Remove stale addresses
208     for (const Ip6Address &address : mIp6MulticastAddresses)
209     {
210         if (std::find(aAddrs.begin(), aAddrs.end(), address) == aAddrs.end())
211         {
212             otbrLogInfo("Remove address: %s", Ip6Address(address).ToString().c_str());
213             SuccessOrExit(error = ProcessMulticastAddressChange(address, /* aIsAdded */ false));
214         }
215     }
216 
217     // Add new addresses
218     for (const Ip6Address &address : aAddrs)
219     {
220         if (std::find(mIp6MulticastAddresses.begin(), mIp6MulticastAddresses.end(), address) ==
221             mIp6MulticastAddresses.end())
222         {
223             otbrLogInfo("Add address: %s", Ip6Address(address).ToString().c_str());
224             SuccessOrExit(error = ProcessMulticastAddressChange(address, /* aIsAdded */ true));
225         }
226     }
227 
228     mIp6MulticastAddresses.assign(aAddrs.begin(), aAddrs.end());
229 
230 exit:
231     if (error != OTBR_ERROR_NONE)
232     {
233         mIp6MulticastAddresses.clear();
234     }
235     return error;
236 }
237 
ProcessMulticastAddressChange(const Ip6Address & aAddress,bool aIsAdded)238 otbrError Netif::ProcessMulticastAddressChange(const Ip6Address &aAddress, bool aIsAdded)
239 {
240     struct ipv6_mreq mreq;
241     otbrError        error = OTBR_ERROR_NONE;
242     int              err;
243 
244     VerifyOrExit(mIpFd >= 0, error = OTBR_ERROR_INVALID_STATE);
245     memcpy(&mreq.ipv6mr_multiaddr, &aAddress, sizeof(mreq.ipv6mr_multiaddr));
246     mreq.ipv6mr_interface = mNetifIndex;
247 
248     err = setsockopt(mIpFd, IPPROTO_IPV6, (aIsAdded ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP), &mreq, sizeof(mreq));
249 
250     if (err != 0)
251     {
252         otbrLogWarning("%s failure (%d)", aIsAdded ? "IPV6_JOIN_GROUP" : "IPV6_LEAVE_GROUP", errno);
253         ExitNow(error = OTBR_ERROR_ERRNO);
254     }
255 
256     otbrLogInfo("%s multicast address %s", aIsAdded ? "Added" : "Removed", Ip6Address(aAddress).ToString().c_str());
257 
258 exit:
259     return error;
260 }
261 
SetNetifState(bool aState)262 void Netif::SetNetifState(bool aState)
263 {
264     otbrError    error = OTBR_ERROR_NONE;
265     struct ifreq ifr;
266     bool         ifState = false;
267 
268     VerifyOrExit(mIpFd >= 0);
269     memset(&ifr, 0, sizeof(ifr));
270     strncpy(ifr.ifr_name, mNetifName.c_str(), IFNAMSIZ - 1);
271     VerifyOrExit(ioctl(mIpFd, SIOCGIFFLAGS, &ifr) == 0, error = OTBR_ERROR_ERRNO);
272 
273     ifState = ((ifr.ifr_flags & IFF_UP) == IFF_UP) ? true : false;
274 
275     otbrLogInfo("Changing interface state to %s%s.", aState ? "up" : "down",
276                 (ifState == aState) ? " (already done, ignoring)" : "");
277 
278     if (ifState != aState)
279     {
280         ifr.ifr_flags = aState ? (ifr.ifr_flags | IFF_UP) : (ifr.ifr_flags & ~IFF_UP);
281         VerifyOrExit(ioctl(mIpFd, SIOCSIFFLAGS, &ifr) == 0, error = OTBR_ERROR_ERRNO);
282     }
283 
284 exit:
285     if (error != OTBR_ERROR_NONE)
286     {
287         otbrLogWarning("Failed to update state %s", otbrErrorString(error));
288     }
289 }
290 
Ip6Receive(const uint8_t * aBuf,uint16_t aLen)291 void Netif::Ip6Receive(const uint8_t *aBuf, uint16_t aLen)
292 {
293     otbrError error = OTBR_ERROR_NONE;
294 
295     VerifyOrExit(aLen <= kIp6Mtu, error = OTBR_ERROR_DROPPED);
296     VerifyOrExit(mTunFd > 0, error = OTBR_ERROR_INVALID_STATE);
297 
298     otbrLogInfo("Packet from NCP (%u bytes)", aLen);
299     VerifyOrExit(write(mTunFd, aBuf, aLen) == aLen, error = OTBR_ERROR_ERRNO);
300 
301 exit:
302     if (error != OTBR_ERROR_NONE)
303     {
304         otbrLogWarning("Failed to receive, error:%s", otbrErrorString(error));
305     }
306 }
307 
ProcessIp6Send(void)308 void Netif::ProcessIp6Send(void)
309 {
310     ssize_t   rval;
311     uint8_t   packet[kIp6Mtu];
312     otbrError error = OTBR_ERROR_NONE;
313 
314     rval = read(mTunFd, packet, sizeof(packet));
315     VerifyOrExit(rval > 0, error = OTBR_ERROR_ERRNO);
316 
317     otbrLogInfo("Send packet (%hu bytes)", static_cast<uint16_t>(rval));
318 
319     error = mDeps.Ip6Send(packet, rval);
320 exit:
321     if (error == OTBR_ERROR_ERRNO)
322     {
323         otbrLogInfo("Error reading from Tun Fd: %s", strerror(errno));
324     }
325 }
326 
Clear(void)327 void Netif::Clear(void)
328 {
329     if (mTunFd != -1)
330     {
331         close(mTunFd);
332         mTunFd = -1;
333     }
334 
335     if (mIpFd != -1)
336     {
337         close(mIpFd);
338         mIpFd = -1;
339     }
340 
341     if (mNetlinkFd != -1)
342     {
343         close(mNetlinkFd);
344         mNetlinkFd = -1;
345     }
346 
347     if (mMldFd != -1)
348     {
349         close(mMldFd);
350         mMldFd = -1;
351     }
352 
353     mNetifIndex = 0;
354     mIp6UnicastAddresses.clear();
355     mIp6MulticastAddresses.clear();
356 }
357 
358 static const otIp6Address kMldv2MulticastAddress = {
359     {{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16}}};
360 static const otIp6Address kAllRouterLocalMulticastAddress = {
361     {{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}};
362 
IsMulAddrFiltered(const otIp6Address & aAddr)363 static bool IsMulAddrFiltered(const otIp6Address &aAddr)
364 {
365     return Ip6Address(aAddr) == Ip6Address(kMldv2MulticastAddress) ||
366            Ip6Address(aAddr) == Ip6Address(kAllRouterLocalMulticastAddress);
367 }
368 
InitMldListener(void)369 otbrError Netif::InitMldListener(void)
370 {
371     otbrError        error = OTBR_ERROR_NONE;
372     struct ipv6_mreq mreq6;
373 
374     mMldFd = SocketWithCloseExec(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, kSocketNonBlock);
375     VerifyOrExit(mMldFd != -1, error = OTBR_ERROR_ERRNO);
376 
377     mreq6.ipv6mr_interface = mNetifIndex;
378     memcpy(&mreq6.ipv6mr_multiaddr, kMldv2MulticastAddress.mFields.m8, sizeof(kMldv2MulticastAddress.mFields.m8));
379 
380     VerifyOrExit(setsockopt(mMldFd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)) == 0,
381                  error = OTBR_ERROR_ERRNO);
382 #ifdef __linux__
383     VerifyOrExit(setsockopt(mMldFd, SOL_SOCKET, SO_BINDTODEVICE, mNetifName.c_str(),
384                             static_cast<socklen_t>(mNetifName.length())) == 0,
385                  error = OTBR_ERROR_ERRNO);
386 #endif
387 
388 exit:
389     return error;
390 }
391 
ProcessMldEvent(void)392 void Netif::ProcessMldEvent(void)
393 {
394     const size_t        kMaxMldEvent = 8192;
395     uint8_t             buffer[kMaxMldEvent];
396     ssize_t             bufferLen = -1;
397     struct sockaddr_in6 srcAddr;
398     socklen_t           addrLen  = sizeof(srcAddr);
399     bool                fromSelf = false;
400     Mldv2Header        *hdr      = reinterpret_cast<Mldv2Header *>(buffer);
401     size_t              offset;
402     uint8_t             type;
403     struct ifaddrs     *ifAddrs = nullptr;
404     char                addressString[INET6_ADDRSTRLEN + 1];
405 
406     bufferLen = recvfrom(mMldFd, buffer, sizeof(buffer), 0, reinterpret_cast<sockaddr *>(&srcAddr), &addrLen);
407     VerifyOrExit(bufferLen > 0);
408 
409     type = buffer[0];
410     VerifyOrExit(type == kIcmpv6Mldv2Type && bufferLen >= static_cast<ssize_t>(sizeof(Mldv2Header)));
411 
412     // Check whether it is sent by self
413     VerifyOrExit(getifaddrs(&ifAddrs) == 0);
414     for (struct ifaddrs *ifAddr = ifAddrs; ifAddr != nullptr; ifAddr = ifAddr->ifa_next)
415     {
416         if (ifAddr->ifa_addr != nullptr && ifAddr->ifa_addr->sa_family == AF_INET6 &&
417             strncmp(mNetifName.c_str(), ifAddr->ifa_name, IFNAMSIZ) == 0)
418         {
419             struct sockaddr_in6 *addr6 = reinterpret_cast<struct sockaddr_in6 *>(ifAddr->ifa_addr);
420 
421             if (memcmp(&addr6->sin6_addr, &srcAddr.sin6_addr, sizeof(in6_addr)) == 0)
422             {
423                 fromSelf = true;
424                 break;
425             }
426         }
427     }
428     VerifyOrExit(fromSelf);
429 
430     hdr    = reinterpret_cast<Mldv2Header *>(buffer);
431     offset = sizeof(Mldv2Header);
432 
433     for (size_t i = 0; i < ntohs(hdr->mNumRecords) && offset < static_cast<size_t>(bufferLen); i++)
434     {
435         if (static_cast<size_t>(bufferLen) >= (sizeof(Mldv2Record) + offset))
436         {
437             Mldv2Record *record = reinterpret_cast<Mldv2Record *>(&buffer[offset]);
438 
439             otbrError    error = OTBR_ERROR_DROPPED;
440             otIp6Address address;
441 
442             memcpy(&address, &record->mMulticastAddress, sizeof(address));
443             if (IsMulAddrFiltered(address))
444             {
445                 continue;
446             }
447 
448             inet_ntop(AF_INET6, &record->mMulticastAddress, addressString, sizeof(addressString));
449 
450             switch (record->mRecordType)
451             {
452             case kIcmpv6Mldv2ModeIsIncludeType:
453             case kIcmpv6Mldv2ModeIsExcludeType:
454                 error = OTBR_ERROR_NONE;
455                 break;
456             ///< Only update subscription on NCP when the target multicast address is not in `mIp6MulticastAddresses`.
457             ///< This indicates that this is the first time the multicast address subscription needs to be updated.
458             case kIcmpv6Mldv2RecordChangeToIncludeType:
459                 if (record->mNumSources == 0)
460                 {
461                     if (std::find(mIp6MulticastAddresses.begin(), mIp6MulticastAddresses.end(), Ip6Address(address)) !=
462                         mIp6MulticastAddresses.end())
463                     {
464                         error = mDeps.Ip6MulAddrUpdateSubscription(address, /* isAdd */ false);
465                     }
466                     else
467                     {
468                         error = OTBR_ERROR_NONE;
469                     }
470                 }
471                 break;
472             case kIcmpv6Mldv2RecordChangeToExcludeType:
473                 if (std::find(mIp6MulticastAddresses.begin(), mIp6MulticastAddresses.end(), Ip6Address(address)) ==
474                     mIp6MulticastAddresses.end())
475                 {
476                     error = mDeps.Ip6MulAddrUpdateSubscription(address, /* isAdd */ true);
477                 }
478                 else
479                 {
480                     error = OTBR_ERROR_NONE;
481                 }
482                 break;
483             }
484 
485             offset += sizeof(Mldv2Record) + sizeof(in6_addr) * ntohs(record->mNumSources);
486 
487             if (error != OTBR_ERROR_NONE)
488             {
489                 otbrLogWarning("Failed to Update multicast subscription: %s", otbrErrorString(error));
490             }
491         }
492     }
493 
494 exit:
495     if (ifAddrs)
496     {
497         freeifaddrs(ifAddrs);
498     }
499 }
500 
501 } // namespace otbr
502