1 /*
2 * Copyright 2019, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "ipv6_monitor.h"
18
19 #include <errno.h>
20 #include <linux/filter.h>
21 #include <net/if.h>
22 #include <netinet/ether.h>
23 #include <netinet/icmp6.h>
24 #include <netinet/ip6.h>
25 #include <poll.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include <array>
30 #include <mutex>
31 #include <string>
32 #include <thread>
33 #include <unordered_set>
34 #include <vector>
35
36 #define LOG_TAG "RIL-IPV6MON"
37 #include <utils/Log.h>
38
39 static constexpr size_t kReadBufferSize = 32768;
40
41 static constexpr size_t kRecursiveDnsOptHeaderSize = 8;
42
43 static constexpr size_t kControlClient = 0;
44 static constexpr size_t kControlServer = 1;
45
46 static constexpr char kMonitorAckCommand = '\1';
47 static constexpr char kMonitorStopCommand = '\2';
48
49 // The amount of time to wait before trying to initialize interface again if
50 // it's not ready when rild starts.
51 static constexpr int kDeferredTimeoutMilliseconds = 1000;
52
operator ==(const in6_addr & left,const in6_addr & right)53 bool operator==(const in6_addr& left, const in6_addr& right) {
54 return ::memcmp(left.s6_addr, right.s6_addr, sizeof(left.s6_addr)) == 0;
55 }
56
operator !=(const in6_addr & left,const in6_addr & right)57 bool operator!=(const in6_addr& left, const in6_addr& right) {
58 return ::memcmp(left.s6_addr, right.s6_addr, sizeof(left.s6_addr)) != 0;
59 }
60
61 template<class T>
hash_combine(size_t & seed,const T & value)62 static inline void hash_combine(size_t& seed, const T& value) {
63 std::hash<T> hasher;
64 seed ^= hasher(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
65 }
66
67 namespace std {
68 template<> struct hash<in6_addr> {
operator ()std::hash69 size_t operator()(const in6_addr& ad) const {
70 size_t seed = 0;
71 hash_combine(seed, *reinterpret_cast<const uint32_t*>(&ad.s6_addr[0]));
72 hash_combine(seed, *reinterpret_cast<const uint32_t*>(&ad.s6_addr[4]));
73 hash_combine(seed, *reinterpret_cast<const uint32_t*>(&ad.s6_addr[8]));
74 hash_combine(seed, *reinterpret_cast<const uint32_t*>(&ad.s6_addr[12]));
75 return seed;
76 }
77 };
78 } // namespace std
79
80 static constexpr uint32_t kIpTypeOffset = offsetof(ip6_hdr, ip6_nxt);
81 static constexpr uint32_t kIcmpTypeOffset = sizeof(ip6_hdr) +
82 offsetof(icmp6_hdr, icmp6_type);
83
84 // This is BPF program that will filter out anything that is not an NDP router
85 // advertisement. It's a very basic assembler syntax. The jumps indicate how
86 // many instructions to jump in addition to the automatic increment of the
87 // program counter. So a jump statement with a zero means to go to the next
88 // instruction, a value of 3 means that the next instruction will be the 4th
89 // after the current one.
90 static const struct sock_filter kNdpFilter[] = {
91 // Load byte at absolute address kIpTypeOffset
92 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kIpTypeOffset),
93 // Jump, if byte is IPPROTO_ICMPV6 jump 0 instructions, if not jump 3.
94 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
95 // Load byte at absolute address kIcmpTypeOffset
96 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, kIcmpTypeOffset),
97 // Jump, if byte is ND_ROUTER_ADVERT jump 0 instructions, if not jump 1
98 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_ROUTER_ADVERT, 0, 1),
99 // Return the number of bytes to accept, accept all of them
100 BPF_STMT(BPF_RET | BPF_K, std::numeric_limits<uint32_t>::max()),
101 // Accept zero bytes, this is where the failed jumps go
102 BPF_STMT(BPF_RET | BPF_K, 0)
103 };
104 static constexpr size_t kNdpFilterSize =
105 sizeof(kNdpFilter) / sizeof(kNdpFilter[0]);
106
107 class Ipv6Monitor {
108 public:
109 Ipv6Monitor(const char* interfaceName);
110 ~Ipv6Monitor();
111
112 enum class InitResult {
113 Error,
114 Deferred,
115 Success,
116 };
117 InitResult init();
118 void setCallback(ipv6MonitorCallback callback);
119 void runAsync();
120 void stop();
121
122 private:
123 InitResult initInterfaces();
124 void run();
125 void onReadAvailable();
126
127 ipv6MonitorCallback mMonitorCallback;
128
129 in6_addr mGateway;
130 std::unordered_set<in6_addr> mDnsServers;
131
132 std::unique_ptr<std::thread> mThread;
133 std::mutex mThreadMutex;
134
135 std::string mInterfaceName;
136 int mSocketFd;
137 int mControlSocket[2];
138 int mPollTimeout = -1;
139 bool mFullyInitialized = false;
140 };
141
Ipv6Monitor(const char * interfaceName)142 Ipv6Monitor::Ipv6Monitor(const char* interfaceName) :
143 mMonitorCallback(nullptr),
144 mInterfaceName(interfaceName),
145 mSocketFd(-1) {
146 memset(&mGateway, 0, sizeof(mGateway));
147 mControlSocket[0] = -1;
148 mControlSocket[1] = -1;
149 }
150
~Ipv6Monitor()151 Ipv6Monitor::~Ipv6Monitor() {
152 for (int& fd : mControlSocket) {
153 if (fd != -1) {
154 ::close(fd);
155 fd = -1;
156 }
157 }
158 if (mSocketFd != -1) {
159 ::close(mSocketFd);
160 mSocketFd = -1;
161 }
162 }
163
init()164 Ipv6Monitor::InitResult Ipv6Monitor::init() {
165 if (mSocketFd != -1) {
166 RLOGE("Ipv6Monitor already initialized");
167 return InitResult::Error;
168 }
169
170 if (::socketpair(AF_UNIX, SOCK_DGRAM, 0, mControlSocket) != 0) {
171 RLOGE("Ipv6Monitor failed to create control socket pair: %s",
172 strerror(errno));
173 return InitResult::Error;
174 }
175
176 mSocketFd = ::socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC, ETH_P_IPV6);
177 if (mSocketFd == -1) {
178 RLOGE("Ipv6Monitor failed to open socket: %s", strerror(errno));
179 return InitResult::Error;
180 }
181 // If interface initialization fails we'll retry later
182 return initInterfaces();
183 }
184
setCallback(ipv6MonitorCallback callback)185 void Ipv6Monitor::setCallback(ipv6MonitorCallback callback) {
186 mMonitorCallback = callback;
187 }
188
initInterfaces()189 Ipv6Monitor::InitResult Ipv6Monitor::initInterfaces() {
190 if (mFullyInitialized) {
191 RLOGE("Ipv6Monitor already initialized");
192 return InitResult::Error;
193 }
194 struct ifreq request;
195 memset(&request, 0, sizeof(request));
196 strlcpy(request.ifr_name, mInterfaceName.c_str(), sizeof(request.ifr_name));
197
198 // Set the ALLMULTI flag so we can capture multicast traffic
199 int status = ::ioctl(mSocketFd, SIOCGIFFLAGS, &request);
200 if (status != 0) {
201 if (errno == ENODEV) {
202 // It is not guaranteed that the network is entirely set up by the
203 // time rild has started. If that's the case the radio interface
204 // might not be up yet, try again later.
205 RLOGE("Ipv6Monitor could not initialize %s yet, retrying later",
206 mInterfaceName.c_str());
207 mPollTimeout = kDeferredTimeoutMilliseconds;
208 return InitResult::Deferred;
209 }
210 RLOGE("Ipv6Monitor failed to get interface flags for %s: %s",
211 mInterfaceName.c_str(), strerror(errno));
212 return InitResult::Error;
213 }
214
215 if ((request.ifr_flags & IFF_ALLMULTI) == 0) {
216 // The flag is not set, we have to make another call
217 request.ifr_flags |= IFF_ALLMULTI;
218
219 status = ::ioctl(mSocketFd, SIOCSIFFLAGS, &request);
220 if (status != 0) {
221 RLOGE("Ipv6Monitor failed to set interface flags for %s: %s",
222 mInterfaceName.c_str(), strerror(errno));
223 return InitResult::Error;
224 }
225 }
226
227 // Add a BPF filter to the socket so that we only receive the specific
228 // type of packet we're interested in. Otherwise we will receive ALL
229 // traffic on this interface.
230 struct sock_fprog filter;
231 filter.len = kNdpFilterSize;
232 // The API doesn't have const but it's not going to modify it so this is OK
233 filter.filter = const_cast<struct sock_filter*>(kNdpFilter);
234 status = ::setsockopt(mSocketFd,
235 SOL_SOCKET,
236 SO_ATTACH_FILTER,
237 &filter,
238 sizeof(filter));
239 if (status != 0) {
240 RLOGE("Ipv6Monitor failed to set socket filter: %s", strerror(errno));
241 return InitResult::Error;
242 }
243
244 // Get the hardware address of the interface into a sockaddr struct for bind
245 struct sockaddr_ll ethAddr;
246 memset(ðAddr, 0, sizeof(ethAddr));
247 ethAddr.sll_family = AF_PACKET;
248 ethAddr.sll_protocol = htons(ETH_P_IPV6);
249 ethAddr.sll_ifindex = if_nametoindex(mInterfaceName.c_str());
250 if (ethAddr.sll_ifindex == 0) {
251 RLOGE("Ipv6Monitor failed to find index for %s: %s",
252 mInterfaceName.c_str(), strerror(errno));
253 return InitResult::Error;
254 }
255
256 status = ::ioctl(mSocketFd, SIOCGIFHWADDR, &request);
257 if (status != 0) {
258 RLOGE("Ipv6Monitor failed to get hardware address for %s: %s",
259 mInterfaceName.c_str(), strerror(errno));
260 return InitResult::Error;
261 }
262 memcpy(ethAddr.sll_addr, request.ifr_addr.sa_data, ETH_ALEN);
263
264 // Now bind to the hardware address
265 status = ::bind(mSocketFd,
266 reinterpret_cast<const struct sockaddr*>(ðAddr),
267 sizeof(ethAddr));
268 if (status != 0) {
269 RLOGE("Ipv6Monitor failed to bind to %s hardware address: %s",
270 mInterfaceName.c_str(), strerror(errno));
271 return InitResult::Error;
272 }
273 mFullyInitialized = true;
274 return InitResult::Success;
275 }
276
runAsync()277 void Ipv6Monitor::runAsync() {
278 std::unique_lock<std::mutex> lock(mThreadMutex);
279 mThread = std::make_unique<std::thread>([this]() { run(); });
280 }
281
stop()282 void Ipv6Monitor::stop() {
283 std::unique_lock<std::mutex> lock(mThreadMutex);
284 if (!mThread) {
285 return;
286 }
287 ::write(mControlSocket[kControlClient], &kMonitorStopCommand, 1);
288 char ack = -1;
289 while (ack != kMonitorAckCommand) {
290 ::read(mControlSocket[kControlClient], &ack, sizeof(ack));
291 }
292 mThread->join();
293 mThread.reset();
294 }
295
run()296 void Ipv6Monitor::run() {
297 std::array<struct pollfd, 2> fds;
298 fds[0].events = POLLIN;
299 fds[0].fd = mControlSocket[kControlServer];
300 fds[1].events = POLLIN;
301 fds[1].fd = mSocketFd;
302
303 bool running = true;
304 while (running) {
305 int status = ::poll(fds.data(), fds.size(), mPollTimeout);
306 if (status < 0) {
307 if (errno == EINTR) {
308 // Interrupted, keep going
309 continue;
310 }
311 // An error occurred
312 RLOGE("Ipv6Monitor fatal failure polling failed; %s",
313 strerror(errno));
314 break;
315 } else if (status == 0) {
316 // Timeout, nothing to read
317 if (!mFullyInitialized) {
318 InitResult result = initInterfaces();
319 switch (result) {
320 case InitResult::Error:
321 // Something went wrong this time and we can't recover
322 running = false;
323 break;
324 case InitResult::Deferred:
325 // We need to keep waiting and then try again
326 mPollTimeout = kDeferredTimeoutMilliseconds;
327 break;
328 case InitResult::Success:
329 // Interfaces are initialized, no need to timeout again
330 mPollTimeout = -1;
331 break;
332 }
333 }
334 continue;
335 }
336
337 if (fds[0].revents & POLLIN) {
338 // Control message received
339 char command = -1;
340 if (::read(mControlSocket[kControlServer],
341 &command,
342 sizeof(command)) == 1) {
343 if (command == kMonitorStopCommand) {
344 break;
345 }
346 }
347 } else if (fds[1].revents & POLLIN) {
348 onReadAvailable();
349 }
350 }
351 ::write(mControlSocket[kControlServer], &kMonitorAckCommand, 1);
352 }
353
onReadAvailable()354 void Ipv6Monitor::onReadAvailable() {
355 char buffer[kReadBufferSize];
356
357 ssize_t bytesRead = 0;
358 while (true) {
359 bytesRead = ::recv(mSocketFd, buffer, sizeof(buffer), 0);
360 if (bytesRead < 0) {
361 if (errno == EINTR) {
362 // Interrupted, try again right away
363 continue;
364 }
365 if (errno != EAGAIN && errno != EWOULDBLOCK) {
366 // Do not report an error for the above error codes, they are
367 // part of the normal turn of events. We just need to try again
368 // later when we run into those errors.
369 RLOGE("Ipv6Monitor failed to receive data: %s",
370 strerror(errno));
371 }
372 return;
373 }
374 break;
375 }
376
377 if (mMonitorCallback == nullptr) {
378 // No point in doing anything, we have read the data so the socket
379 // buffer doesn't fill up and that's all we can do.
380 return;
381 }
382
383 if (static_cast<size_t>(bytesRead) < sizeof(ip6_hdr) + sizeof(icmp6_hdr)) {
384 // This message cannot be an ICMPv6 packet, ignore it
385 return;
386 }
387
388 auto ipv6 = reinterpret_cast<const ip6_hdr*>(buffer);
389 uint8_t version = (ipv6->ip6_vfc & 0xF0) >> 4;
390 if (version != 6 || ipv6->ip6_nxt != IPPROTO_ICMPV6) {
391 // This message is not an IPv6 packet or not an ICMPv6 packet, ignore it
392 return;
393 }
394
395 // The ICMP header starts right after the IPv6 header
396 auto icmp = reinterpret_cast<const icmp6_hdr*>(buffer + sizeof(ip6_hdr));
397 if (icmp->icmp6_code != 0) {
398 // All packets we care about have an icmp code of zero.
399 return;
400 }
401
402 if (icmp->icmp6_type != ND_ROUTER_ADVERT) {
403 // We only care about router advertisements
404 return;
405 }
406
407 // At this point we know it's a valid packet, let's look inside
408
409 // The gateway is the same as the source in the IP header
410 in6_addr gateway = ipv6->ip6_src;
411
412 // Search through the options for DNS servers
413 const char* options = buffer + sizeof(ip6_hdr) + sizeof(nd_router_advert);
414 const nd_opt_hdr* option = reinterpret_cast<const nd_opt_hdr*>(options);
415
416 std::vector<in6_addr> dnsServers;
417 const nd_opt_hdr* nextOpt = nullptr;
418 for (const nd_opt_hdr* opt = option; opt; opt = nextOpt) {
419 auto nextOptLoc =
420 reinterpret_cast<const char*>(opt) + opt->nd_opt_len * 8u;
421 if (nextOptLoc > buffer + bytesRead) {
422 // Not enough room for this option, abort
423 break;
424 }
425 if (nextOptLoc < buffer + bytesRead) {
426 nextOpt = reinterpret_cast<const nd_opt_hdr*>(nextOptLoc);
427 } else {
428 nextOpt = nullptr;
429 }
430 if (opt->nd_opt_type != 25 || opt->nd_opt_len < 1) {
431 // Not an RNDSS option, skip it
432 continue;
433 }
434
435 size_t numEntries = (opt->nd_opt_len - 1) / 2;
436 const char* addrLoc = reinterpret_cast<const char*>(opt);
437 addrLoc += kRecursiveDnsOptHeaderSize;
438 auto addrs = reinterpret_cast<const in6_addr*>(addrLoc);
439
440 for (size_t i = 0; i < numEntries; ++i) {
441 dnsServers.push_back(addrs[i]);
442 }
443 }
444
445 bool changed = false;
446 if (gateway != mGateway) {
447 changed = true;
448 mGateway = gateway;
449 }
450
451 for (const auto& dns : dnsServers) {
452 if (mDnsServers.find(dns) == mDnsServers.end()) {
453 mDnsServers.insert(dns);
454 changed = true;
455 }
456 }
457
458 if (changed) {
459 mMonitorCallback(&gateway, dnsServers.data(), dnsServers.size());
460 }
461 }
462
463 extern "C"
ipv6MonitorCreate(const char * interfaceName)464 struct ipv6Monitor* ipv6MonitorCreate(const char* interfaceName) {
465 auto monitor = std::make_unique<Ipv6Monitor>(interfaceName);
466 if (!monitor || monitor->init() == Ipv6Monitor::InitResult::Error) {
467 return nullptr;
468 }
469 return reinterpret_cast<struct ipv6Monitor*>(monitor.release());
470 }
471
472 extern "C"
ipv6MonitorFree(struct ipv6Monitor * ipv6Monitor)473 void ipv6MonitorFree(struct ipv6Monitor* ipv6Monitor) {
474 auto monitor = reinterpret_cast<Ipv6Monitor*>(ipv6Monitor);
475 delete monitor;
476 }
477
478 extern "C"
ipv6MonitorSetCallback(struct ipv6Monitor * ipv6Monitor,ipv6MonitorCallback callback)479 void ipv6MonitorSetCallback(struct ipv6Monitor* ipv6Monitor,
480 ipv6MonitorCallback callback) {
481 auto monitor = reinterpret_cast<Ipv6Monitor*>(ipv6Monitor);
482 monitor->setCallback(callback);
483 }
484
485 extern "C"
ipv6MonitorRunAsync(struct ipv6Monitor * ipv6Monitor)486 void ipv6MonitorRunAsync(struct ipv6Monitor* ipv6Monitor) {
487 auto monitor = reinterpret_cast<Ipv6Monitor*>(ipv6Monitor);
488 monitor->runAsync();
489 }
490
491 extern "C"
ipv6MonitorStop(struct ipv6Monitor * ipv6Monitor)492 void ipv6MonitorStop(struct ipv6Monitor* ipv6Monitor) {
493 auto monitor = reinterpret_cast<Ipv6Monitor*>(ipv6Monitor);
494 monitor->stop();
495 }
496
497