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(&ethAddr, 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*>(&ethAddr),
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