1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker * Copyright (c) 2020, 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 /**
30*4a64e381SAndroid Build Coastguard Worker * @file
31*4a64e381SAndroid Build Coastguard Worker * The file implements the ND Proxy management.
32*4a64e381SAndroid Build Coastguard Worker */
33*4a64e381SAndroid Build Coastguard Worker
34*4a64e381SAndroid Build Coastguard Worker #define OTBR_LOG_TAG "NDPROXY"
35*4a64e381SAndroid Build Coastguard Worker
36*4a64e381SAndroid Build Coastguard Worker #include "backbone_router/nd_proxy.hpp"
37*4a64e381SAndroid Build Coastguard Worker
38*4a64e381SAndroid Build Coastguard Worker #if OTBR_ENABLE_DUA_ROUTING
39*4a64e381SAndroid Build Coastguard Worker
40*4a64e381SAndroid Build Coastguard Worker #include <openthread/backbone_router_ftd.h>
41*4a64e381SAndroid Build Coastguard Worker
42*4a64e381SAndroid Build Coastguard Worker #include <assert.h>
43*4a64e381SAndroid Build Coastguard Worker #include <net/if.h>
44*4a64e381SAndroid Build Coastguard Worker #include <netinet/icmp6.h>
45*4a64e381SAndroid Build Coastguard Worker #include <netinet/ip6.h>
46*4a64e381SAndroid Build Coastguard Worker #include <sys/ioctl.h>
47*4a64e381SAndroid Build Coastguard Worker #include <unistd.h>
48*4a64e381SAndroid Build Coastguard Worker
49*4a64e381SAndroid Build Coastguard Worker #if __linux__
50*4a64e381SAndroid Build Coastguard Worker #include <linux/netfilter.h>
51*4a64e381SAndroid Build Coastguard Worker #else
52*4a64e381SAndroid Build Coastguard Worker #error "Platform not supported"
53*4a64e381SAndroid Build Coastguard Worker #endif
54*4a64e381SAndroid Build Coastguard Worker
55*4a64e381SAndroid Build Coastguard Worker #include "backbone_router/constants.hpp"
56*4a64e381SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
57*4a64e381SAndroid Build Coastguard Worker #include "common/logging.hpp"
58*4a64e381SAndroid Build Coastguard Worker #include "common/types.hpp"
59*4a64e381SAndroid Build Coastguard Worker #include "utils/system_utils.hpp"
60*4a64e381SAndroid Build Coastguard Worker
61*4a64e381SAndroid Build Coastguard Worker namespace otbr {
62*4a64e381SAndroid Build Coastguard Worker namespace BackboneRouter {
63*4a64e381SAndroid Build Coastguard Worker
Enable(const Ip6Prefix & aDomainPrefix)64*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::Enable(const Ip6Prefix &aDomainPrefix)
65*4a64e381SAndroid Build Coastguard Worker {
66*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
67*4a64e381SAndroid Build Coastguard Worker
68*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(!IsEnabled());
69*4a64e381SAndroid Build Coastguard Worker
70*4a64e381SAndroid Build Coastguard Worker assert(aDomainPrefix.IsValid());
71*4a64e381SAndroid Build Coastguard Worker mDomainPrefix = aDomainPrefix;
72*4a64e381SAndroid Build Coastguard Worker
73*4a64e381SAndroid Build Coastguard Worker SuccessOrExit(error = InitIcmp6RawSocket());
74*4a64e381SAndroid Build Coastguard Worker SuccessOrExit(error = UpdateMacAddress());
75*4a64e381SAndroid Build Coastguard Worker SuccessOrExit(error = InitNetfilterQueue());
76*4a64e381SAndroid Build Coastguard Worker
77*4a64e381SAndroid Build Coastguard Worker // Add ip6tables rule for unicast ICMPv6 messages
78*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(SystemUtils::ExecuteCommand(
79*4a64e381SAndroid Build Coastguard Worker "ip6tables -t raw -A PREROUTING -6 -d %s -p icmpv6 --icmpv6-type neighbor-solicitation -i %s -j "
80*4a64e381SAndroid Build Coastguard Worker "NFQUEUE --queue-num 88",
81*4a64e381SAndroid Build Coastguard Worker mDomainPrefix.ToString().c_str(), mBackboneInterfaceName.c_str()) == 0,
82*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
83*4a64e381SAndroid Build Coastguard Worker
84*4a64e381SAndroid Build Coastguard Worker exit:
85*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
86*4a64e381SAndroid Build Coastguard Worker {
87*4a64e381SAndroid Build Coastguard Worker FiniNetfilterQueue();
88*4a64e381SAndroid Build Coastguard Worker FiniIcmp6RawSocket();
89*4a64e381SAndroid Build Coastguard Worker }
90*4a64e381SAndroid Build Coastguard Worker
91*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: %s", __FUNCTION__);
92*4a64e381SAndroid Build Coastguard Worker }
93*4a64e381SAndroid Build Coastguard Worker
Disable(void)94*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::Disable(void)
95*4a64e381SAndroid Build Coastguard Worker {
96*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
97*4a64e381SAndroid Build Coastguard Worker
98*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(IsEnabled());
99*4a64e381SAndroid Build Coastguard Worker
100*4a64e381SAndroid Build Coastguard Worker FiniNetfilterQueue();
101*4a64e381SAndroid Build Coastguard Worker FiniIcmp6RawSocket();
102*4a64e381SAndroid Build Coastguard Worker
103*4a64e381SAndroid Build Coastguard Worker // Remove ip6tables rule for unicast ICMPv6 messages
104*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(SystemUtils::ExecuteCommand(
105*4a64e381SAndroid Build Coastguard Worker "ip6tables -t raw -D PREROUTING -6 -d %s -p icmpv6 --icmpv6-type neighbor-solicitation -i %s -j "
106*4a64e381SAndroid Build Coastguard Worker "NFQUEUE --queue-num 88",
107*4a64e381SAndroid Build Coastguard Worker mDomainPrefix.ToString().c_str(), mBackboneInterfaceName.c_str()) == 0,
108*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
109*4a64e381SAndroid Build Coastguard Worker
110*4a64e381SAndroid Build Coastguard Worker exit:
111*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: %s", __FUNCTION__);
112*4a64e381SAndroid Build Coastguard Worker }
113*4a64e381SAndroid Build Coastguard Worker
Init(void)114*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::Init(void)
115*4a64e381SAndroid Build Coastguard Worker {
116*4a64e381SAndroid Build Coastguard Worker mBackboneIfIndex = if_nametoindex(mBackboneInterfaceName.c_str());
117*4a64e381SAndroid Build Coastguard Worker VerifyOrDie(mBackboneIfIndex > 0, "if_nametoindex failed");
118*4a64e381SAndroid Build Coastguard Worker }
119*4a64e381SAndroid Build Coastguard Worker
Update(MainloopContext & aMainloop)120*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::Update(MainloopContext &aMainloop)
121*4a64e381SAndroid Build Coastguard Worker {
122*4a64e381SAndroid Build Coastguard Worker if (mIcmp6RawSock >= 0)
123*4a64e381SAndroid Build Coastguard Worker {
124*4a64e381SAndroid Build Coastguard Worker aMainloop.AddFdToReadSet(mIcmp6RawSock);
125*4a64e381SAndroid Build Coastguard Worker }
126*4a64e381SAndroid Build Coastguard Worker
127*4a64e381SAndroid Build Coastguard Worker if (mUnicastNsQueueSock >= 0)
128*4a64e381SAndroid Build Coastguard Worker {
129*4a64e381SAndroid Build Coastguard Worker aMainloop.AddFdToReadSet(mUnicastNsQueueSock);
130*4a64e381SAndroid Build Coastguard Worker }
131*4a64e381SAndroid Build Coastguard Worker }
132*4a64e381SAndroid Build Coastguard Worker
Process(const MainloopContext & aMainloop)133*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::Process(const MainloopContext &aMainloop)
134*4a64e381SAndroid Build Coastguard Worker {
135*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(IsEnabled());
136*4a64e381SAndroid Build Coastguard Worker
137*4a64e381SAndroid Build Coastguard Worker if (FD_ISSET(mIcmp6RawSock, &aMainloop.mReadFdSet))
138*4a64e381SAndroid Build Coastguard Worker {
139*4a64e381SAndroid Build Coastguard Worker ProcessMulticastNeighborSolicition();
140*4a64e381SAndroid Build Coastguard Worker }
141*4a64e381SAndroid Build Coastguard Worker
142*4a64e381SAndroid Build Coastguard Worker if (FD_ISSET(mUnicastNsQueueSock, &aMainloop.mReadFdSet))
143*4a64e381SAndroid Build Coastguard Worker {
144*4a64e381SAndroid Build Coastguard Worker ProcessUnicastNeighborSolicition();
145*4a64e381SAndroid Build Coastguard Worker }
146*4a64e381SAndroid Build Coastguard Worker exit:
147*4a64e381SAndroid Build Coastguard Worker return;
148*4a64e381SAndroid Build Coastguard Worker }
149*4a64e381SAndroid Build Coastguard Worker
ProcessMulticastNeighborSolicition()150*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::ProcessMulticastNeighborSolicition()
151*4a64e381SAndroid Build Coastguard Worker {
152*4a64e381SAndroid Build Coastguard Worker struct msghdr msghdr;
153*4a64e381SAndroid Build Coastguard Worker sockaddr_in6 sin6;
154*4a64e381SAndroid Build Coastguard Worker struct iovec iovec;
155*4a64e381SAndroid Build Coastguard Worker ssize_t len;
156*4a64e381SAndroid Build Coastguard Worker struct icmp6_hdr *icmp6header;
157*4a64e381SAndroid Build Coastguard Worker struct cmsghdr *cmsghdr;
158*4a64e381SAndroid Build Coastguard Worker unsigned char cbuf[2 * CMSG_SPACE(sizeof(struct in6_pktinfo))];
159*4a64e381SAndroid Build Coastguard Worker uint8_t packet[kMaxICMP6PacketSize];
160*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
161*4a64e381SAndroid Build Coastguard Worker bool found = false;
162*4a64e381SAndroid Build Coastguard Worker
163*4a64e381SAndroid Build Coastguard Worker iovec.iov_len = kMaxICMP6PacketSize;
164*4a64e381SAndroid Build Coastguard Worker iovec.iov_base = packet;
165*4a64e381SAndroid Build Coastguard Worker
166*4a64e381SAndroid Build Coastguard Worker msghdr.msg_name = &sin6;
167*4a64e381SAndroid Build Coastguard Worker msghdr.msg_namelen = sizeof(sin6);
168*4a64e381SAndroid Build Coastguard Worker msghdr.msg_iov = &iovec;
169*4a64e381SAndroid Build Coastguard Worker msghdr.msg_iovlen = 1;
170*4a64e381SAndroid Build Coastguard Worker msghdr.msg_control = cbuf;
171*4a64e381SAndroid Build Coastguard Worker msghdr.msg_controllen = sizeof(cbuf);
172*4a64e381SAndroid Build Coastguard Worker
173*4a64e381SAndroid Build Coastguard Worker len = recvmsg(mIcmp6RawSock, &msghdr, 0);
174*4a64e381SAndroid Build Coastguard Worker
175*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(len >= static_cast<ssize_t>(sizeof(struct icmp6_hdr)), error = OTBR_ERROR_ERRNO);
176*4a64e381SAndroid Build Coastguard Worker
177*4a64e381SAndroid Build Coastguard Worker {
178*4a64e381SAndroid Build Coastguard Worker Ip6Address &src = *reinterpret_cast<Ip6Address *>(&sin6.sin6_addr);
179*4a64e381SAndroid Build Coastguard Worker
180*4a64e381SAndroid Build Coastguard Worker icmp6header = reinterpret_cast<icmp6_hdr *>(packet);
181*4a64e381SAndroid Build Coastguard Worker
182*4a64e381SAndroid Build Coastguard Worker // only process neighbor solicit
183*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(icmp6header->icmp6_type == ND_NEIGHBOR_SOLICIT, error = OTBR_ERROR_PARSE);
184*4a64e381SAndroid Build Coastguard Worker
185*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("NdProxyManager: Received ND-NS from %s", src.ToString().c_str());
186*4a64e381SAndroid Build Coastguard Worker
187*4a64e381SAndroid Build Coastguard Worker for (cmsghdr = CMSG_FIRSTHDR(&msghdr); cmsghdr; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr))
188*4a64e381SAndroid Build Coastguard Worker {
189*4a64e381SAndroid Build Coastguard Worker if (cmsghdr->cmsg_level != IPPROTO_IPV6)
190*4a64e381SAndroid Build Coastguard Worker {
191*4a64e381SAndroid Build Coastguard Worker continue;
192*4a64e381SAndroid Build Coastguard Worker }
193*4a64e381SAndroid Build Coastguard Worker
194*4a64e381SAndroid Build Coastguard Worker switch (cmsghdr->cmsg_type)
195*4a64e381SAndroid Build Coastguard Worker {
196*4a64e381SAndroid Build Coastguard Worker case IPV6_PKTINFO:
197*4a64e381SAndroid Build Coastguard Worker if (cmsghdr->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))
198*4a64e381SAndroid Build Coastguard Worker {
199*4a64e381SAndroid Build Coastguard Worker struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsghdr);
200*4a64e381SAndroid Build Coastguard Worker Ip6Address &dst = *reinterpret_cast<Ip6Address *>(&pktinfo->ipi6_addr);
201*4a64e381SAndroid Build Coastguard Worker uint32_t ifindex = pktinfo->ipi6_ifindex;
202*4a64e381SAndroid Build Coastguard Worker
203*4a64e381SAndroid Build Coastguard Worker for (const Ip6Address &ipaddr : mNdProxySet)
204*4a64e381SAndroid Build Coastguard Worker {
205*4a64e381SAndroid Build Coastguard Worker if (ipaddr.ToSolicitedNodeMulticastAddress() == dst)
206*4a64e381SAndroid Build Coastguard Worker {
207*4a64e381SAndroid Build Coastguard Worker found = true;
208*4a64e381SAndroid Build Coastguard Worker break;
209*4a64e381SAndroid Build Coastguard Worker }
210*4a64e381SAndroid Build Coastguard Worker }
211*4a64e381SAndroid Build Coastguard Worker
212*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("NdProxyManager: dst=%s, ifindex=%d, proxying=%s", dst.ToString().c_str(), ifindex,
213*4a64e381SAndroid Build Coastguard Worker found ? "Y" : "N");
214*4a64e381SAndroid Build Coastguard Worker }
215*4a64e381SAndroid Build Coastguard Worker break;
216*4a64e381SAndroid Build Coastguard Worker
217*4a64e381SAndroid Build Coastguard Worker case IPV6_HOPLIMIT:
218*4a64e381SAndroid Build Coastguard Worker if (cmsghdr->cmsg_len == CMSG_LEN(sizeof(int)))
219*4a64e381SAndroid Build Coastguard Worker {
220*4a64e381SAndroid Build Coastguard Worker int hops = *(int *)CMSG_DATA(cmsghdr);
221*4a64e381SAndroid Build Coastguard Worker
222*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("NdProxyManager: hops=%d (%s)", hops, hops == 255 ? "Good" : "Bad");
223*4a64e381SAndroid Build Coastguard Worker
224*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(hops == 255);
225*4a64e381SAndroid Build Coastguard Worker }
226*4a64e381SAndroid Build Coastguard Worker break;
227*4a64e381SAndroid Build Coastguard Worker }
228*4a64e381SAndroid Build Coastguard Worker }
229*4a64e381SAndroid Build Coastguard Worker
230*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(found, error = OTBR_ERROR_NOT_FOUND);
231*4a64e381SAndroid Build Coastguard Worker
232*4a64e381SAndroid Build Coastguard Worker {
233*4a64e381SAndroid Build Coastguard Worker struct nd_neighbor_solicit *ns = reinterpret_cast<struct nd_neighbor_solicit *>(packet);
234*4a64e381SAndroid Build Coastguard Worker Ip6Address &target = *reinterpret_cast<Ip6Address *>(&ns->nd_ns_target);
235*4a64e381SAndroid Build Coastguard Worker
236*4a64e381SAndroid Build Coastguard Worker otbrLogInfo("NdProxyManager: send solicited NA for multicast NS: src=%s, target=%s", src.ToString().c_str(),
237*4a64e381SAndroid Build Coastguard Worker target.ToString().c_str());
238*4a64e381SAndroid Build Coastguard Worker
239*4a64e381SAndroid Build Coastguard Worker SendNeighborAdvertisement(target, src);
240*4a64e381SAndroid Build Coastguard Worker }
241*4a64e381SAndroid Build Coastguard Worker }
242*4a64e381SAndroid Build Coastguard Worker
243*4a64e381SAndroid Build Coastguard Worker exit:
244*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: %s", __FUNCTION__);
245*4a64e381SAndroid Build Coastguard Worker }
246*4a64e381SAndroid Build Coastguard Worker
ProcessUnicastNeighborSolicition(void)247*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::ProcessUnicastNeighborSolicition(void)
248*4a64e381SAndroid Build Coastguard Worker {
249*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
250*4a64e381SAndroid Build Coastguard Worker char packet[kMaxICMP6PacketSize];
251*4a64e381SAndroid Build Coastguard Worker ssize_t len;
252*4a64e381SAndroid Build Coastguard Worker
253*4a64e381SAndroid Build Coastguard Worker VerifyOrExit((len = recv(mUnicastNsQueueSock, packet, sizeof(packet), 0)) >= 0, error = OTBR_ERROR_ERRNO);
254*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(nfq_handle_packet(mNfqHandler, packet, len) == 0, error = OTBR_ERROR_ERRNO);
255*4a64e381SAndroid Build Coastguard Worker
256*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_NONE;
257*4a64e381SAndroid Build Coastguard Worker
258*4a64e381SAndroid Build Coastguard Worker exit:
259*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: %s", __FUNCTION__);
260*4a64e381SAndroid Build Coastguard Worker }
261*4a64e381SAndroid Build Coastguard Worker
HandleBackboneRouterNdProxyEvent(otBackboneRouterNdProxyEvent aEvent,const otIp6Address * aDua)262*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::HandleBackboneRouterNdProxyEvent(otBackboneRouterNdProxyEvent aEvent, const otIp6Address *aDua)
263*4a64e381SAndroid Build Coastguard Worker {
264*4a64e381SAndroid Build Coastguard Worker Ip6Address target;
265*4a64e381SAndroid Build Coastguard Worker
266*4a64e381SAndroid Build Coastguard Worker if (aEvent != OT_BACKBONE_ROUTER_NDPROXY_CLEARED)
267*4a64e381SAndroid Build Coastguard Worker {
268*4a64e381SAndroid Build Coastguard Worker assert(aDua != nullptr);
269*4a64e381SAndroid Build Coastguard Worker target = Ip6Address(aDua->mFields.m8);
270*4a64e381SAndroid Build Coastguard Worker }
271*4a64e381SAndroid Build Coastguard Worker
272*4a64e381SAndroid Build Coastguard Worker switch (aEvent)
273*4a64e381SAndroid Build Coastguard Worker {
274*4a64e381SAndroid Build Coastguard Worker case OT_BACKBONE_ROUTER_NDPROXY_ADDED:
275*4a64e381SAndroid Build Coastguard Worker case OT_BACKBONE_ROUTER_NDPROXY_RENEWED:
276*4a64e381SAndroid Build Coastguard Worker {
277*4a64e381SAndroid Build Coastguard Worker bool isNewInsert = mNdProxySet.insert(target).second;
278*4a64e381SAndroid Build Coastguard Worker
279*4a64e381SAndroid Build Coastguard Worker if (isNewInsert)
280*4a64e381SAndroid Build Coastguard Worker {
281*4a64e381SAndroid Build Coastguard Worker JoinSolicitedNodeMulticastGroup(target);
282*4a64e381SAndroid Build Coastguard Worker }
283*4a64e381SAndroid Build Coastguard Worker
284*4a64e381SAndroid Build Coastguard Worker SendNeighborAdvertisement(target, Ip6Address::GetLinkLocalAllNodesMulticastAddress());
285*4a64e381SAndroid Build Coastguard Worker break;
286*4a64e381SAndroid Build Coastguard Worker }
287*4a64e381SAndroid Build Coastguard Worker case OT_BACKBONE_ROUTER_NDPROXY_REMOVED:
288*4a64e381SAndroid Build Coastguard Worker mNdProxySet.erase(target);
289*4a64e381SAndroid Build Coastguard Worker LeaveSolicitedNodeMulticastGroup(target);
290*4a64e381SAndroid Build Coastguard Worker break;
291*4a64e381SAndroid Build Coastguard Worker case OT_BACKBONE_ROUTER_NDPROXY_CLEARED:
292*4a64e381SAndroid Build Coastguard Worker for (const Ip6Address &proxingTarget : mNdProxySet)
293*4a64e381SAndroid Build Coastguard Worker {
294*4a64e381SAndroid Build Coastguard Worker LeaveSolicitedNodeMulticastGroup(proxingTarget);
295*4a64e381SAndroid Build Coastguard Worker }
296*4a64e381SAndroid Build Coastguard Worker mNdProxySet.clear();
297*4a64e381SAndroid Build Coastguard Worker break;
298*4a64e381SAndroid Build Coastguard Worker }
299*4a64e381SAndroid Build Coastguard Worker }
300*4a64e381SAndroid Build Coastguard Worker
SendNeighborAdvertisement(const Ip6Address & aTarget,const Ip6Address & aDst)301*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::SendNeighborAdvertisement(const Ip6Address &aTarget, const Ip6Address &aDst)
302*4a64e381SAndroid Build Coastguard Worker {
303*4a64e381SAndroid Build Coastguard Worker uint8_t packet[kMaxICMP6PacketSize];
304*4a64e381SAndroid Build Coastguard Worker uint16_t len = 0;
305*4a64e381SAndroid Build Coastguard Worker struct nd_neighbor_advert &na = *reinterpret_cast<struct nd_neighbor_advert *>(packet);
306*4a64e381SAndroid Build Coastguard Worker struct nd_opt_hdr &opt = *reinterpret_cast<struct nd_opt_hdr *>(packet + sizeof(struct nd_neighbor_advert));
307*4a64e381SAndroid Build Coastguard Worker bool isSolicited = !aDst.IsMulticast();
308*4a64e381SAndroid Build Coastguard Worker sockaddr_in6 dst;
309*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
310*4a64e381SAndroid Build Coastguard Worker otBackboneRouterNdProxyInfo aNdProxyInfo;
311*4a64e381SAndroid Build Coastguard Worker
312*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(otBackboneRouterGetNdProxyInfo(mHost.GetInstance(), reinterpret_cast<const otIp6Address *>(&aTarget),
313*4a64e381SAndroid Build Coastguard Worker &aNdProxyInfo) == OT_ERROR_NONE,
314*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_OPENTHREAD);
315*4a64e381SAndroid Build Coastguard Worker
316*4a64e381SAndroid Build Coastguard Worker memset(packet, 0, sizeof(packet));
317*4a64e381SAndroid Build Coastguard Worker
318*4a64e381SAndroid Build Coastguard Worker na.nd_na_type = ND_NEIGHBOR_ADVERT;
319*4a64e381SAndroid Build Coastguard Worker na.nd_na_code = 0;
320*4a64e381SAndroid Build Coastguard Worker // set Solicited
321*4a64e381SAndroid Build Coastguard Worker na.nd_na_flags_reserved = isSolicited ? ND_NA_FLAG_SOLICITED : 0;
322*4a64e381SAndroid Build Coastguard Worker // set Router
323*4a64e381SAndroid Build Coastguard Worker na.nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
324*4a64e381SAndroid Build Coastguard Worker // set Override
325*4a64e381SAndroid Build Coastguard Worker na.nd_na_flags_reserved |= aNdProxyInfo.mTimeSinceLastTransaction <= kDuaRecentTime ? ND_NA_FLAG_OVERRIDE : 0;
326*4a64e381SAndroid Build Coastguard Worker
327*4a64e381SAndroid Build Coastguard Worker memcpy(&na.nd_na_target, aTarget.m8, sizeof(Ip6Address));
328*4a64e381SAndroid Build Coastguard Worker len += sizeof(struct nd_neighbor_advert);
329*4a64e381SAndroid Build Coastguard Worker
330*4a64e381SAndroid Build Coastguard Worker opt.nd_opt_type = ND_OPT_TARGET_LINKADDR;
331*4a64e381SAndroid Build Coastguard Worker opt.nd_opt_len = 1;
332*4a64e381SAndroid Build Coastguard Worker
333*4a64e381SAndroid Build Coastguard Worker memcpy(reinterpret_cast<uint8_t *>(&opt) + 2, mMacAddress.m8, sizeof(mMacAddress));
334*4a64e381SAndroid Build Coastguard Worker
335*4a64e381SAndroid Build Coastguard Worker len += (opt.nd_opt_len * 8);
336*4a64e381SAndroid Build Coastguard Worker
337*4a64e381SAndroid Build Coastguard Worker aDst.CopyTo(dst);
338*4a64e381SAndroid Build Coastguard Worker
339*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(sendto(mIcmp6RawSock, packet, len, 0, reinterpret_cast<const sockaddr *>(&dst), sizeof(dst)) == len,
340*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
341*4a64e381SAndroid Build Coastguard Worker
342*4a64e381SAndroid Build Coastguard Worker exit:
343*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: %s", __FUNCTION__);
344*4a64e381SAndroid Build Coastguard Worker }
345*4a64e381SAndroid Build Coastguard Worker
UpdateMacAddress(void)346*4a64e381SAndroid Build Coastguard Worker otbrError NdProxyManager::UpdateMacAddress(void)
347*4a64e381SAndroid Build Coastguard Worker {
348*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
349*4a64e381SAndroid Build Coastguard Worker
350*4a64e381SAndroid Build Coastguard Worker #if !__APPLE__
351*4a64e381SAndroid Build Coastguard Worker struct ifreq ifr;
352*4a64e381SAndroid Build Coastguard Worker
353*4a64e381SAndroid Build Coastguard Worker memset(&ifr, 0, sizeof(ifr));
354*4a64e381SAndroid Build Coastguard Worker strncpy(ifr.ifr_name, mBackboneInterfaceName.c_str(), sizeof(ifr.ifr_name) - 1);
355*4a64e381SAndroid Build Coastguard Worker
356*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(ioctl(mIcmp6RawSock, SIOCGIFHWADDR, &ifr) != -1, error = OTBR_ERROR_ERRNO);
357*4a64e381SAndroid Build Coastguard Worker memcpy(mMacAddress.m8, ifr.ifr_hwaddr.sa_data, sizeof(mMacAddress));
358*4a64e381SAndroid Build Coastguard Worker #else
359*4a64e381SAndroid Build Coastguard Worker ExitNow(error = OTBR_ERROR_NOT_IMPLEMENTED);
360*4a64e381SAndroid Build Coastguard Worker #endif
361*4a64e381SAndroid Build Coastguard Worker exit:
362*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: UpdateMacAddress to %s", mMacAddress.ToString().c_str());
363*4a64e381SAndroid Build Coastguard Worker return error;
364*4a64e381SAndroid Build Coastguard Worker }
365*4a64e381SAndroid Build Coastguard Worker
InitIcmp6RawSocket(void)366*4a64e381SAndroid Build Coastguard Worker otbrError NdProxyManager::InitIcmp6RawSocket(void)
367*4a64e381SAndroid Build Coastguard Worker {
368*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
369*4a64e381SAndroid Build Coastguard Worker int on = 1;
370*4a64e381SAndroid Build Coastguard Worker int hops = 255;
371*4a64e381SAndroid Build Coastguard Worker struct icmp6_filter filter;
372*4a64e381SAndroid Build Coastguard Worker
373*4a64e381SAndroid Build Coastguard Worker mIcmp6RawSock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
374*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mIcmp6RawSock >= 0, error = OTBR_ERROR_ERRNO);
375*4a64e381SAndroid Build Coastguard Worker
376*4a64e381SAndroid Build Coastguard Worker #if __linux__
377*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(setsockopt(mIcmp6RawSock, SOL_SOCKET, SO_BINDTODEVICE, mBackboneInterfaceName.c_str(),
378*4a64e381SAndroid Build Coastguard Worker mBackboneInterfaceName.length()) == 0,
379*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
380*4a64e381SAndroid Build Coastguard Worker #else // __NetBSD__ || __FreeBSD__ || __APPLE__
381*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(
382*4a64e381SAndroid Build Coastguard Worker setsockopt(mIcmp6RawSock, IPPROTO_IPV6, IPV6_BOUND_IF, mBackboneIfName.c_str(), mBackboneIfName.size()),
383*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
384*4a64e381SAndroid Build Coastguard Worker #endif // __linux__
385*4a64e381SAndroid Build Coastguard Worker
386*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(setsockopt(mIcmp6RawSock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) == 0,
387*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
388*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(setsockopt(mIcmp6RawSock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on)) == 0,
389*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
390*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(setsockopt(mIcmp6RawSock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) == 0,
391*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
392*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(setsockopt(mIcmp6RawSock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof(hops)) == 0,
393*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
394*4a64e381SAndroid Build Coastguard Worker
395*4a64e381SAndroid Build Coastguard Worker ICMP6_FILTER_SETBLOCKALL(&filter);
396*4a64e381SAndroid Build Coastguard Worker ICMP6_FILTER_SETPASS(ND_NEIGHBOR_SOLICIT, &filter);
397*4a64e381SAndroid Build Coastguard Worker
398*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(setsockopt(mIcmp6RawSock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) == 0,
399*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
400*4a64e381SAndroid Build Coastguard Worker exit:
401*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
402*4a64e381SAndroid Build Coastguard Worker {
403*4a64e381SAndroid Build Coastguard Worker FiniIcmp6RawSocket();
404*4a64e381SAndroid Build Coastguard Worker }
405*4a64e381SAndroid Build Coastguard Worker
406*4a64e381SAndroid Build Coastguard Worker return error;
407*4a64e381SAndroid Build Coastguard Worker }
408*4a64e381SAndroid Build Coastguard Worker
FiniIcmp6RawSocket(void)409*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::FiniIcmp6RawSocket(void)
410*4a64e381SAndroid Build Coastguard Worker {
411*4a64e381SAndroid Build Coastguard Worker if (mIcmp6RawSock != -1)
412*4a64e381SAndroid Build Coastguard Worker {
413*4a64e381SAndroid Build Coastguard Worker close(mIcmp6RawSock);
414*4a64e381SAndroid Build Coastguard Worker mIcmp6RawSock = -1;
415*4a64e381SAndroid Build Coastguard Worker }
416*4a64e381SAndroid Build Coastguard Worker }
417*4a64e381SAndroid Build Coastguard Worker
InitNetfilterQueue(void)418*4a64e381SAndroid Build Coastguard Worker otbrError NdProxyManager::InitNetfilterQueue(void)
419*4a64e381SAndroid Build Coastguard Worker {
420*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_ERRNO;
421*4a64e381SAndroid Build Coastguard Worker
422*4a64e381SAndroid Build Coastguard Worker VerifyOrExit((mNfqHandler = nfq_open()) != nullptr);
423*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(nfq_unbind_pf(mNfqHandler, AF_INET6) >= 0);
424*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(nfq_bind_pf(mNfqHandler, AF_INET6) >= 0);
425*4a64e381SAndroid Build Coastguard Worker
426*4a64e381SAndroid Build Coastguard Worker VerifyOrExit((mNfqQueueHandler = nfq_create_queue(mNfqHandler, 88, HandleNetfilterQueue, this)) != nullptr);
427*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(nfq_set_mode(mNfqQueueHandler, NFQNL_COPY_PACKET, 0xffff) >= 0);
428*4a64e381SAndroid Build Coastguard Worker VerifyOrExit((mUnicastNsQueueSock = nfq_fd(mNfqHandler)) >= 0);
429*4a64e381SAndroid Build Coastguard Worker
430*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_NONE;
431*4a64e381SAndroid Build Coastguard Worker
432*4a64e381SAndroid Build Coastguard Worker exit:
433*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: %s", __FUNCTION__);
434*4a64e381SAndroid Build Coastguard Worker
435*4a64e381SAndroid Build Coastguard Worker if (error != OTBR_ERROR_NONE)
436*4a64e381SAndroid Build Coastguard Worker {
437*4a64e381SAndroid Build Coastguard Worker FiniNetfilterQueue();
438*4a64e381SAndroid Build Coastguard Worker }
439*4a64e381SAndroid Build Coastguard Worker
440*4a64e381SAndroid Build Coastguard Worker return error;
441*4a64e381SAndroid Build Coastguard Worker }
442*4a64e381SAndroid Build Coastguard Worker
FiniNetfilterQueue(void)443*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::FiniNetfilterQueue(void)
444*4a64e381SAndroid Build Coastguard Worker {
445*4a64e381SAndroid Build Coastguard Worker if (mUnicastNsQueueSock != -1)
446*4a64e381SAndroid Build Coastguard Worker {
447*4a64e381SAndroid Build Coastguard Worker close(mUnicastNsQueueSock);
448*4a64e381SAndroid Build Coastguard Worker mUnicastNsQueueSock = -1;
449*4a64e381SAndroid Build Coastguard Worker }
450*4a64e381SAndroid Build Coastguard Worker
451*4a64e381SAndroid Build Coastguard Worker if (mNfqQueueHandler != nullptr)
452*4a64e381SAndroid Build Coastguard Worker {
453*4a64e381SAndroid Build Coastguard Worker nfq_destroy_queue(mNfqQueueHandler);
454*4a64e381SAndroid Build Coastguard Worker mNfqQueueHandler = nullptr;
455*4a64e381SAndroid Build Coastguard Worker }
456*4a64e381SAndroid Build Coastguard Worker
457*4a64e381SAndroid Build Coastguard Worker if (mNfqHandler != nullptr)
458*4a64e381SAndroid Build Coastguard Worker {
459*4a64e381SAndroid Build Coastguard Worker nfq_close(mNfqHandler);
460*4a64e381SAndroid Build Coastguard Worker mNfqHandler = nullptr;
461*4a64e381SAndroid Build Coastguard Worker }
462*4a64e381SAndroid Build Coastguard Worker }
463*4a64e381SAndroid Build Coastguard Worker
HandleNetfilterQueue(struct nfq_q_handle * aNfQueueHandler,struct nfgenmsg * aNfMsg,struct nfq_data * aNfData,void * aContext)464*4a64e381SAndroid Build Coastguard Worker int NdProxyManager::HandleNetfilterQueue(struct nfq_q_handle *aNfQueueHandler,
465*4a64e381SAndroid Build Coastguard Worker struct nfgenmsg *aNfMsg,
466*4a64e381SAndroid Build Coastguard Worker struct nfq_data *aNfData,
467*4a64e381SAndroid Build Coastguard Worker void *aContext)
468*4a64e381SAndroid Build Coastguard Worker {
469*4a64e381SAndroid Build Coastguard Worker return static_cast<NdProxyManager *>(aContext)->HandleNetfilterQueue(aNfQueueHandler, aNfMsg, aNfData);
470*4a64e381SAndroid Build Coastguard Worker }
471*4a64e381SAndroid Build Coastguard Worker
HandleNetfilterQueue(struct nfq_q_handle * aNfQueueHandler,struct nfgenmsg * aNfMsg,struct nfq_data * aNfData)472*4a64e381SAndroid Build Coastguard Worker int NdProxyManager::HandleNetfilterQueue(struct nfq_q_handle *aNfQueueHandler,
473*4a64e381SAndroid Build Coastguard Worker struct nfgenmsg *aNfMsg,
474*4a64e381SAndroid Build Coastguard Worker struct nfq_data *aNfData)
475*4a64e381SAndroid Build Coastguard Worker {
476*4a64e381SAndroid Build Coastguard Worker OTBR_UNUSED_VARIABLE(aNfMsg);
477*4a64e381SAndroid Build Coastguard Worker
478*4a64e381SAndroid Build Coastguard Worker struct nfqnl_msg_packet_hdr *ph;
479*4a64e381SAndroid Build Coastguard Worker unsigned char *data;
480*4a64e381SAndroid Build Coastguard Worker uint32_t id = 0;
481*4a64e381SAndroid Build Coastguard Worker int ret = 0;
482*4a64e381SAndroid Build Coastguard Worker int len = 0;
483*4a64e381SAndroid Build Coastguard Worker int verdict = NF_ACCEPT;
484*4a64e381SAndroid Build Coastguard Worker
485*4a64e381SAndroid Build Coastguard Worker Ip6Address dst;
486*4a64e381SAndroid Build Coastguard Worker Ip6Address src;
487*4a64e381SAndroid Build Coastguard Worker struct icmp6_hdr *icmp6header = nullptr;
488*4a64e381SAndroid Build Coastguard Worker struct ip6_hdr *ip6header = nullptr;
489*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
490*4a64e381SAndroid Build Coastguard Worker
491*4a64e381SAndroid Build Coastguard Worker if ((ph = nfq_get_msg_packet_hdr(aNfData)) != nullptr)
492*4a64e381SAndroid Build Coastguard Worker {
493*4a64e381SAndroid Build Coastguard Worker id = ntohl(ph->packet_id);
494*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("NdProxyManager: %s: id %d", __FUNCTION__, id);
495*4a64e381SAndroid Build Coastguard Worker }
496*4a64e381SAndroid Build Coastguard Worker
497*4a64e381SAndroid Build Coastguard Worker VerifyOrExit((len = nfq_get_payload(aNfData, &data)) > 0, error = OTBR_ERROR_PARSE);
498*4a64e381SAndroid Build Coastguard Worker
499*4a64e381SAndroid Build Coastguard Worker ip6header = reinterpret_cast<struct ip6_hdr *>(data);
500*4a64e381SAndroid Build Coastguard Worker src = *reinterpret_cast<Ip6Address *>(&ip6header->ip6_src);
501*4a64e381SAndroid Build Coastguard Worker dst = *reinterpret_cast<Ip6Address *>(&ip6header->ip6_dst);
502*4a64e381SAndroid Build Coastguard Worker
503*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(ip6header->ip6_nxt == IPPROTO_ICMPV6);
504*4a64e381SAndroid Build Coastguard Worker
505*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("NdProxyManager: Handle Neighbor Solicitation: from %s to %s", src.ToString().c_str(),
506*4a64e381SAndroid Build Coastguard Worker dst.ToString().c_str());
507*4a64e381SAndroid Build Coastguard Worker
508*4a64e381SAndroid Build Coastguard Worker icmp6header = reinterpret_cast<struct icmp6_hdr *>(data + sizeof(struct ip6_hdr));
509*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(icmp6header->icmp6_type == ND_NEIGHBOR_SOLICIT);
510*4a64e381SAndroid Build Coastguard Worker
511*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(mNdProxySet.find(dst) != mNdProxySet.end(), error = OTBR_ERROR_NOT_FOUND);
512*4a64e381SAndroid Build Coastguard Worker
513*4a64e381SAndroid Build Coastguard Worker {
514*4a64e381SAndroid Build Coastguard Worker struct nd_neighbor_solicit &ns = *reinterpret_cast<struct nd_neighbor_solicit *>(data + sizeof(struct ip6_hdr));
515*4a64e381SAndroid Build Coastguard Worker Ip6Address &target = *reinterpret_cast<Ip6Address *>(&ns.nd_ns_target);
516*4a64e381SAndroid Build Coastguard Worker
517*4a64e381SAndroid Build Coastguard Worker otbrLogDebug("NdProxyManager: %s: target: %s, hoplimit %d", __FUNCTION__, target.ToString().c_str(),
518*4a64e381SAndroid Build Coastguard Worker ip6header->ip6_hlim);
519*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(ip6header->ip6_hlim == 255, error = OTBR_ERROR_PARSE);
520*4a64e381SAndroid Build Coastguard Worker SendNeighborAdvertisement(target, src);
521*4a64e381SAndroid Build Coastguard Worker verdict = NF_DROP;
522*4a64e381SAndroid Build Coastguard Worker }
523*4a64e381SAndroid Build Coastguard Worker
524*4a64e381SAndroid Build Coastguard Worker exit:
525*4a64e381SAndroid Build Coastguard Worker ret = nfq_set_verdict(aNfQueueHandler, id, verdict, len, data);
526*4a64e381SAndroid Build Coastguard Worker
527*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: %s (nfq_set_verdict id %d, ret %d verdict %d)", __FUNCTION__, id, ret,
528*4a64e381SAndroid Build Coastguard Worker verdict);
529*4a64e381SAndroid Build Coastguard Worker
530*4a64e381SAndroid Build Coastguard Worker return ret;
531*4a64e381SAndroid Build Coastguard Worker }
532*4a64e381SAndroid Build Coastguard Worker
JoinSolicitedNodeMulticastGroup(const Ip6Address & aTarget) const533*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::JoinSolicitedNodeMulticastGroup(const Ip6Address &aTarget) const
534*4a64e381SAndroid Build Coastguard Worker {
535*4a64e381SAndroid Build Coastguard Worker ipv6_mreq mreq;
536*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
537*4a64e381SAndroid Build Coastguard Worker Ip6Address solicitedMulticastAddress = aTarget.ToSolicitedNodeMulticastAddress();
538*4a64e381SAndroid Build Coastguard Worker
539*4a64e381SAndroid Build Coastguard Worker mreq.ipv6mr_interface = mBackboneIfIndex;
540*4a64e381SAndroid Build Coastguard Worker solicitedMulticastAddress.CopyTo(mreq.ipv6mr_multiaddr);
541*4a64e381SAndroid Build Coastguard Worker
542*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(setsockopt(mIcmp6RawSock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == 0,
543*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
544*4a64e381SAndroid Build Coastguard Worker exit:
545*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: JoinSolicitedNodeMulticastGroup of %s: %s", aTarget.ToString().c_str(),
546*4a64e381SAndroid Build Coastguard Worker solicitedMulticastAddress.ToString().c_str());
547*4a64e381SAndroid Build Coastguard Worker }
548*4a64e381SAndroid Build Coastguard Worker
LeaveSolicitedNodeMulticastGroup(const Ip6Address & aTarget) const549*4a64e381SAndroid Build Coastguard Worker void NdProxyManager::LeaveSolicitedNodeMulticastGroup(const Ip6Address &aTarget) const
550*4a64e381SAndroid Build Coastguard Worker {
551*4a64e381SAndroid Build Coastguard Worker ipv6_mreq mreq;
552*4a64e381SAndroid Build Coastguard Worker otbrError error = OTBR_ERROR_NONE;
553*4a64e381SAndroid Build Coastguard Worker Ip6Address solicitedMulticastAddress = aTarget.ToSolicitedNodeMulticastAddress();
554*4a64e381SAndroid Build Coastguard Worker
555*4a64e381SAndroid Build Coastguard Worker mreq.ipv6mr_interface = mBackboneIfIndex;
556*4a64e381SAndroid Build Coastguard Worker solicitedMulticastAddress.CopyTo(mreq.ipv6mr_multiaddr);
557*4a64e381SAndroid Build Coastguard Worker
558*4a64e381SAndroid Build Coastguard Worker VerifyOrExit(setsockopt(mIcmp6RawSock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) == 0,
559*4a64e381SAndroid Build Coastguard Worker error = OTBR_ERROR_ERRNO);
560*4a64e381SAndroid Build Coastguard Worker exit:
561*4a64e381SAndroid Build Coastguard Worker otbrLogResult(error, "NdProxyManager: LeaveSolicitedNodeMulticastGroup of %s: %s", aTarget.ToString().c_str(),
562*4a64e381SAndroid Build Coastguard Worker solicitedMulticastAddress.ToString().c_str());
563*4a64e381SAndroid Build Coastguard Worker }
564*4a64e381SAndroid Build Coastguard Worker
565*4a64e381SAndroid Build Coastguard Worker } // namespace BackboneRouter
566*4a64e381SAndroid Build Coastguard Worker } // namespace otbr
567*4a64e381SAndroid Build Coastguard Worker
568*4a64e381SAndroid Build Coastguard Worker #endif // OTBR_ENABLE_DUA_ROUTING
569