1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker *
4*8542734aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker *
8*8542734aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker *
10*8542734aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker */
16*8542734aSAndroid Build Coastguard Worker
17*8542734aSAndroid Build Coastguard Worker #define LOG_TAG "Netd"
18*8542734aSAndroid Build Coastguard Worker
19*8542734aSAndroid Build Coastguard Worker #include "SockDiag.h"
20*8542734aSAndroid Build Coastguard Worker
21*8542734aSAndroid Build Coastguard Worker #include <errno.h>
22*8542734aSAndroid Build Coastguard Worker #include <linux/inet_diag.h>
23*8542734aSAndroid Build Coastguard Worker #include <linux/netlink.h>
24*8542734aSAndroid Build Coastguard Worker #include <linux/sock_diag.h>
25*8542734aSAndroid Build Coastguard Worker #include <netdb.h>
26*8542734aSAndroid Build Coastguard Worker #include <netinet/in.h>
27*8542734aSAndroid Build Coastguard Worker #include <netinet/tcp.h>
28*8542734aSAndroid Build Coastguard Worker #include <string.h>
29*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
30*8542734aSAndroid Build Coastguard Worker #include <sys/uio.h>
31*8542734aSAndroid Build Coastguard Worker
32*8542734aSAndroid Build Coastguard Worker #include <cinttypes>
33*8542734aSAndroid Build Coastguard Worker
34*8542734aSAndroid Build Coastguard Worker #include <android-base/properties.h>
35*8542734aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
36*8542734aSAndroid Build Coastguard Worker #include <android-base/strings.h>
37*8542734aSAndroid Build Coastguard Worker #include <log/log.h>
38*8542734aSAndroid Build Coastguard Worker #include <netdutils/InternetAddresses.h>
39*8542734aSAndroid Build Coastguard Worker #include <netdutils/Stopwatch.h>
40*8542734aSAndroid Build Coastguard Worker
41*8542734aSAndroid Build Coastguard Worker #include "Permission.h"
42*8542734aSAndroid Build Coastguard Worker
43*8542734aSAndroid Build Coastguard Worker #ifndef SOCK_DESTROY
44*8542734aSAndroid Build Coastguard Worker #define SOCK_DESTROY 21
45*8542734aSAndroid Build Coastguard Worker #endif
46*8542734aSAndroid Build Coastguard Worker
47*8542734aSAndroid Build Coastguard Worker #define INET_DIAG_BC_MARK_COND 10
48*8542734aSAndroid Build Coastguard Worker
49*8542734aSAndroid Build Coastguard Worker namespace android {
50*8542734aSAndroid Build Coastguard Worker
51*8542734aSAndroid Build Coastguard Worker using android::base::StringPrintf;
52*8542734aSAndroid Build Coastguard Worker using netdutils::ScopedAddrinfo;
53*8542734aSAndroid Build Coastguard Worker using netdutils::Stopwatch;
54*8542734aSAndroid Build Coastguard Worker
55*8542734aSAndroid Build Coastguard Worker namespace net {
56*8542734aSAndroid Build Coastguard Worker namespace {
57*8542734aSAndroid Build Coastguard Worker
58*8542734aSAndroid Build Coastguard Worker static const bool isUser = (android::base::GetProperty("ro.build.type", "") == "user");
59*8542734aSAndroid Build Coastguard Worker
getAdbPort()60*8542734aSAndroid Build Coastguard Worker int getAdbPort() {
61*8542734aSAndroid Build Coastguard Worker return android::base::GetIntProperty("service.adb.tcp.port", 0);
62*8542734aSAndroid Build Coastguard Worker }
63*8542734aSAndroid Build Coastguard Worker
isAdbSocket(const inet_diag_msg * msg,int adbPort)64*8542734aSAndroid Build Coastguard Worker bool isAdbSocket(const inet_diag_msg *msg, int adbPort) {
65*8542734aSAndroid Build Coastguard Worker return adbPort > 0 && msg->id.idiag_sport == htons(adbPort) &&
66*8542734aSAndroid Build Coastguard Worker (msg->idiag_uid == AID_ROOT || msg->idiag_uid == AID_SHELL);
67*8542734aSAndroid Build Coastguard Worker }
68*8542734aSAndroid Build Coastguard Worker
checkError(int fd)69*8542734aSAndroid Build Coastguard Worker int checkError(int fd) {
70*8542734aSAndroid Build Coastguard Worker struct {
71*8542734aSAndroid Build Coastguard Worker nlmsghdr h;
72*8542734aSAndroid Build Coastguard Worker nlmsgerr err;
73*8542734aSAndroid Build Coastguard Worker } __attribute__((__packed__)) ack;
74*8542734aSAndroid Build Coastguard Worker ssize_t bytesread = recv(fd, &ack, sizeof(ack), MSG_DONTWAIT | MSG_PEEK);
75*8542734aSAndroid Build Coastguard Worker if (bytesread == -1) {
76*8542734aSAndroid Build Coastguard Worker // Read failed (error), or nothing to read (good).
77*8542734aSAndroid Build Coastguard Worker return (errno == EAGAIN) ? 0 : -errno;
78*8542734aSAndroid Build Coastguard Worker } else if (bytesread == (ssize_t) sizeof(ack) && ack.h.nlmsg_type == NLMSG_ERROR) {
79*8542734aSAndroid Build Coastguard Worker // We got an error. Consume it.
80*8542734aSAndroid Build Coastguard Worker recv(fd, &ack, sizeof(ack), 0);
81*8542734aSAndroid Build Coastguard Worker return ack.err.error;
82*8542734aSAndroid Build Coastguard Worker } else {
83*8542734aSAndroid Build Coastguard Worker // The kernel replied with something. Leave it to the caller.
84*8542734aSAndroid Build Coastguard Worker return 0;
85*8542734aSAndroid Build Coastguard Worker }
86*8542734aSAndroid Build Coastguard Worker }
87*8542734aSAndroid Build Coastguard Worker
88*8542734aSAndroid Build Coastguard Worker } // namespace
89*8542734aSAndroid Build Coastguard Worker
open()90*8542734aSAndroid Build Coastguard Worker bool SockDiag::open() {
91*8542734aSAndroid Build Coastguard Worker if (hasSocks()) {
92*8542734aSAndroid Build Coastguard Worker return false;
93*8542734aSAndroid Build Coastguard Worker }
94*8542734aSAndroid Build Coastguard Worker
95*8542734aSAndroid Build Coastguard Worker mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_INET_DIAG);
96*8542734aSAndroid Build Coastguard Worker mWriteSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_INET_DIAG);
97*8542734aSAndroid Build Coastguard Worker if (!hasSocks()) {
98*8542734aSAndroid Build Coastguard Worker closeSocks();
99*8542734aSAndroid Build Coastguard Worker return false;
100*8542734aSAndroid Build Coastguard Worker }
101*8542734aSAndroid Build Coastguard Worker
102*8542734aSAndroid Build Coastguard Worker sockaddr_nl nl = { .nl_family = AF_NETLINK };
103*8542734aSAndroid Build Coastguard Worker if ((connect(mSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1) ||
104*8542734aSAndroid Build Coastguard Worker (connect(mWriteSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1)) {
105*8542734aSAndroid Build Coastguard Worker closeSocks();
106*8542734aSAndroid Build Coastguard Worker return false;
107*8542734aSAndroid Build Coastguard Worker }
108*8542734aSAndroid Build Coastguard Worker
109*8542734aSAndroid Build Coastguard Worker return true;
110*8542734aSAndroid Build Coastguard Worker }
111*8542734aSAndroid Build Coastguard Worker
sendDumpRequest(uint8_t proto,uint8_t family,uint8_t extensions,uint32_t states,iovec * iov,int iovcnt)112*8542734aSAndroid Build Coastguard Worker int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint8_t extensions, uint32_t states,
113*8542734aSAndroid Build Coastguard Worker iovec *iov, int iovcnt) {
114*8542734aSAndroid Build Coastguard Worker struct {
115*8542734aSAndroid Build Coastguard Worker nlmsghdr nlh;
116*8542734aSAndroid Build Coastguard Worker inet_diag_req_v2 req;
117*8542734aSAndroid Build Coastguard Worker } __attribute__((__packed__)) request = {
118*8542734aSAndroid Build Coastguard Worker .nlh = {
119*8542734aSAndroid Build Coastguard Worker .nlmsg_type = SOCK_DIAG_BY_FAMILY,
120*8542734aSAndroid Build Coastguard Worker .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
121*8542734aSAndroid Build Coastguard Worker },
122*8542734aSAndroid Build Coastguard Worker .req = {
123*8542734aSAndroid Build Coastguard Worker .sdiag_family = family,
124*8542734aSAndroid Build Coastguard Worker .sdiag_protocol = proto,
125*8542734aSAndroid Build Coastguard Worker .idiag_ext = extensions,
126*8542734aSAndroid Build Coastguard Worker .idiag_states = states,
127*8542734aSAndroid Build Coastguard Worker },
128*8542734aSAndroid Build Coastguard Worker };
129*8542734aSAndroid Build Coastguard Worker
130*8542734aSAndroid Build Coastguard Worker size_t len = 0;
131*8542734aSAndroid Build Coastguard Worker iov[0].iov_base = &request;
132*8542734aSAndroid Build Coastguard Worker iov[0].iov_len = sizeof(request);
133*8542734aSAndroid Build Coastguard Worker for (int i = 0; i < iovcnt; i++) {
134*8542734aSAndroid Build Coastguard Worker len += iov[i].iov_len;
135*8542734aSAndroid Build Coastguard Worker }
136*8542734aSAndroid Build Coastguard Worker request.nlh.nlmsg_len = len;
137*8542734aSAndroid Build Coastguard Worker
138*8542734aSAndroid Build Coastguard Worker ssize_t writevRet = writev(mSock, iov, iovcnt);
139*8542734aSAndroid Build Coastguard Worker // Don't let pointers to the stack escape.
140*8542734aSAndroid Build Coastguard Worker iov[0] = {nullptr, 0};
141*8542734aSAndroid Build Coastguard Worker if (writevRet != (ssize_t)len) {
142*8542734aSAndroid Build Coastguard Worker return -errno;
143*8542734aSAndroid Build Coastguard Worker }
144*8542734aSAndroid Build Coastguard Worker
145*8542734aSAndroid Build Coastguard Worker return checkError(mSock);
146*8542734aSAndroid Build Coastguard Worker }
147*8542734aSAndroid Build Coastguard Worker
sendDumpRequest(uint8_t proto,uint8_t family,uint32_t states)148*8542734aSAndroid Build Coastguard Worker int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states) {
149*8542734aSAndroid Build Coastguard Worker iovec iov[] = {
150*8542734aSAndroid Build Coastguard Worker { nullptr, 0 },
151*8542734aSAndroid Build Coastguard Worker };
152*8542734aSAndroid Build Coastguard Worker return sendDumpRequest(proto, family, 0, states, iov, ARRAY_SIZE(iov));
153*8542734aSAndroid Build Coastguard Worker }
154*8542734aSAndroid Build Coastguard Worker
sendDumpRequest(uint8_t proto,uint8_t family,const char * addrstr)155*8542734aSAndroid Build Coastguard Worker int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, const char *addrstr) {
156*8542734aSAndroid Build Coastguard Worker addrinfo hints = { .ai_flags = AI_NUMERICHOST };
157*8542734aSAndroid Build Coastguard Worker addrinfo *res;
158*8542734aSAndroid Build Coastguard Worker in6_addr mapped = { .s6_addr32 = { 0, 0, htonl(0xffff), 0 } };
159*8542734aSAndroid Build Coastguard Worker
160*8542734aSAndroid Build Coastguard Worker // TODO: refactor the netlink parsing code out of system/core, bring it into netd, and stop
161*8542734aSAndroid Build Coastguard Worker // doing string conversions when they're not necessary.
162*8542734aSAndroid Build Coastguard Worker int ret = getaddrinfo(addrstr, nullptr, &hints, &res);
163*8542734aSAndroid Build Coastguard Worker if (ret != 0) return -EINVAL;
164*8542734aSAndroid Build Coastguard Worker
165*8542734aSAndroid Build Coastguard Worker // So we don't have to call freeaddrinfo on every failure path.
166*8542734aSAndroid Build Coastguard Worker ScopedAddrinfo resP(res);
167*8542734aSAndroid Build Coastguard Worker
168*8542734aSAndroid Build Coastguard Worker void *addr;
169*8542734aSAndroid Build Coastguard Worker uint8_t addrlen;
170*8542734aSAndroid Build Coastguard Worker if (res->ai_family == AF_INET && family == AF_INET) {
171*8542734aSAndroid Build Coastguard Worker in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
172*8542734aSAndroid Build Coastguard Worker addr = &ina;
173*8542734aSAndroid Build Coastguard Worker addrlen = sizeof(ina);
174*8542734aSAndroid Build Coastguard Worker } else if (res->ai_family == AF_INET && family == AF_INET6) {
175*8542734aSAndroid Build Coastguard Worker in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
176*8542734aSAndroid Build Coastguard Worker mapped.s6_addr32[3] = ina.s_addr;
177*8542734aSAndroid Build Coastguard Worker addr = &mapped;
178*8542734aSAndroid Build Coastguard Worker addrlen = sizeof(mapped);
179*8542734aSAndroid Build Coastguard Worker } else if (res->ai_family == AF_INET6 && family == AF_INET6) {
180*8542734aSAndroid Build Coastguard Worker in6_addr& in6a = reinterpret_cast<sockaddr_in6*>(res->ai_addr)->sin6_addr;
181*8542734aSAndroid Build Coastguard Worker addr = &in6a;
182*8542734aSAndroid Build Coastguard Worker addrlen = sizeof(in6a);
183*8542734aSAndroid Build Coastguard Worker } else {
184*8542734aSAndroid Build Coastguard Worker return -EAFNOSUPPORT;
185*8542734aSAndroid Build Coastguard Worker }
186*8542734aSAndroid Build Coastguard Worker
187*8542734aSAndroid Build Coastguard Worker uint8_t prefixlen = addrlen * 8;
188*8542734aSAndroid Build Coastguard Worker uint8_t yesjump = sizeof(inet_diag_bc_op) + sizeof(inet_diag_hostcond) + addrlen;
189*8542734aSAndroid Build Coastguard Worker uint8_t nojump = yesjump + 4;
190*8542734aSAndroid Build Coastguard Worker
191*8542734aSAndroid Build Coastguard Worker struct {
192*8542734aSAndroid Build Coastguard Worker nlattr nla;
193*8542734aSAndroid Build Coastguard Worker inet_diag_bc_op op;
194*8542734aSAndroid Build Coastguard Worker inet_diag_hostcond cond;
195*8542734aSAndroid Build Coastguard Worker } __attribute__((__packed__)) attrs = {
196*8542734aSAndroid Build Coastguard Worker .nla = {
197*8542734aSAndroid Build Coastguard Worker .nla_type = INET_DIAG_REQ_BYTECODE,
198*8542734aSAndroid Build Coastguard Worker },
199*8542734aSAndroid Build Coastguard Worker .op = {
200*8542734aSAndroid Build Coastguard Worker INET_DIAG_BC_S_COND,
201*8542734aSAndroid Build Coastguard Worker yesjump,
202*8542734aSAndroid Build Coastguard Worker nojump,
203*8542734aSAndroid Build Coastguard Worker },
204*8542734aSAndroid Build Coastguard Worker .cond = {
205*8542734aSAndroid Build Coastguard Worker family,
206*8542734aSAndroid Build Coastguard Worker prefixlen,
207*8542734aSAndroid Build Coastguard Worker -1,
208*8542734aSAndroid Build Coastguard Worker {}
209*8542734aSAndroid Build Coastguard Worker },
210*8542734aSAndroid Build Coastguard Worker };
211*8542734aSAndroid Build Coastguard Worker
212*8542734aSAndroid Build Coastguard Worker attrs.nla.nla_len = sizeof(attrs) + addrlen;
213*8542734aSAndroid Build Coastguard Worker
214*8542734aSAndroid Build Coastguard Worker iovec iov[] = {
215*8542734aSAndroid Build Coastguard Worker { nullptr, 0 },
216*8542734aSAndroid Build Coastguard Worker { &attrs, sizeof(attrs) },
217*8542734aSAndroid Build Coastguard Worker { addr, addrlen },
218*8542734aSAndroid Build Coastguard Worker };
219*8542734aSAndroid Build Coastguard Worker
220*8542734aSAndroid Build Coastguard Worker uint32_t states = ~(1 << TCP_TIME_WAIT);
221*8542734aSAndroid Build Coastguard Worker return sendDumpRequest(proto, family, 0, states, iov, ARRAY_SIZE(iov));
222*8542734aSAndroid Build Coastguard Worker }
223*8542734aSAndroid Build Coastguard Worker
readDiagMsg(uint8_t proto,const SockDiag::DestroyFilter & shouldDestroy)224*8542734aSAndroid Build Coastguard Worker int SockDiag::readDiagMsg(uint8_t proto, const SockDiag::DestroyFilter& shouldDestroy) {
225*8542734aSAndroid Build Coastguard Worker NetlinkDumpCallback callback = [this, proto, shouldDestroy] (nlmsghdr *nlh) {
226*8542734aSAndroid Build Coastguard Worker const inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
227*8542734aSAndroid Build Coastguard Worker if (shouldDestroy(proto, msg)) {
228*8542734aSAndroid Build Coastguard Worker sockDestroy(proto, msg);
229*8542734aSAndroid Build Coastguard Worker }
230*8542734aSAndroid Build Coastguard Worker };
231*8542734aSAndroid Build Coastguard Worker
232*8542734aSAndroid Build Coastguard Worker return processNetlinkDump(mSock, callback);
233*8542734aSAndroid Build Coastguard Worker }
234*8542734aSAndroid Build Coastguard Worker
readDiagMsgWithTcpInfo(const TcpInfoReader & tcpInfoReader)235*8542734aSAndroid Build Coastguard Worker int SockDiag::readDiagMsgWithTcpInfo(const TcpInfoReader& tcpInfoReader) {
236*8542734aSAndroid Build Coastguard Worker NetlinkDumpCallback callback = [tcpInfoReader] (nlmsghdr *nlh) {
237*8542734aSAndroid Build Coastguard Worker if (nlh->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
238*8542734aSAndroid Build Coastguard Worker ALOGE("expected nlmsg_type=SOCK_DIAG_BY_FAMILY, got nlmsg_type=%d", nlh->nlmsg_type);
239*8542734aSAndroid Build Coastguard Worker return;
240*8542734aSAndroid Build Coastguard Worker }
241*8542734aSAndroid Build Coastguard Worker Fwmark mark;
242*8542734aSAndroid Build Coastguard Worker struct tcp_info *tcpinfo = nullptr;
243*8542734aSAndroid Build Coastguard Worker uint32_t tcpinfoLength = 0;
244*8542734aSAndroid Build Coastguard Worker inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
245*8542734aSAndroid Build Coastguard Worker uint32_t attr_len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg));
246*8542734aSAndroid Build Coastguard Worker struct rtattr *attr = reinterpret_cast<struct rtattr*>(msg+1);
247*8542734aSAndroid Build Coastguard Worker while (RTA_OK(attr, attr_len)) {
248*8542734aSAndroid Build Coastguard Worker if (attr->rta_type == INET_DIAG_INFO) {
249*8542734aSAndroid Build Coastguard Worker tcpinfo = reinterpret_cast<struct tcp_info*>(RTA_DATA(attr));
250*8542734aSAndroid Build Coastguard Worker tcpinfoLength = RTA_PAYLOAD(attr);
251*8542734aSAndroid Build Coastguard Worker }
252*8542734aSAndroid Build Coastguard Worker if (attr->rta_type == INET_DIAG_MARK) {
253*8542734aSAndroid Build Coastguard Worker mark.intValue = *reinterpret_cast<uint32_t*>(RTA_DATA(attr));
254*8542734aSAndroid Build Coastguard Worker }
255*8542734aSAndroid Build Coastguard Worker attr = RTA_NEXT(attr, attr_len);
256*8542734aSAndroid Build Coastguard Worker }
257*8542734aSAndroid Build Coastguard Worker
258*8542734aSAndroid Build Coastguard Worker tcpInfoReader(mark, msg, tcpinfo, tcpinfoLength);
259*8542734aSAndroid Build Coastguard Worker };
260*8542734aSAndroid Build Coastguard Worker
261*8542734aSAndroid Build Coastguard Worker return processNetlinkDump(mSock, callback);
262*8542734aSAndroid Build Coastguard Worker }
263*8542734aSAndroid Build Coastguard Worker
264*8542734aSAndroid Build Coastguard Worker // Determines whether a socket is a loopback socket. Does not check socket state.
isLoopbackSocket(const inet_diag_msg * msg)265*8542734aSAndroid Build Coastguard Worker bool SockDiag::isLoopbackSocket(const inet_diag_msg *msg) {
266*8542734aSAndroid Build Coastguard Worker switch (msg->idiag_family) {
267*8542734aSAndroid Build Coastguard Worker case AF_INET:
268*8542734aSAndroid Build Coastguard Worker // Old kernels only copy the IPv4 address and leave the other 12 bytes uninitialized.
269*8542734aSAndroid Build Coastguard Worker return IN_LOOPBACK(htonl(msg->id.idiag_src[0])) ||
270*8542734aSAndroid Build Coastguard Worker IN_LOOPBACK(htonl(msg->id.idiag_dst[0])) ||
271*8542734aSAndroid Build Coastguard Worker msg->id.idiag_src[0] == msg->id.idiag_dst[0];
272*8542734aSAndroid Build Coastguard Worker
273*8542734aSAndroid Build Coastguard Worker case AF_INET6: {
274*8542734aSAndroid Build Coastguard Worker const struct in6_addr *src = (const struct in6_addr *) &msg->id.idiag_src;
275*8542734aSAndroid Build Coastguard Worker const struct in6_addr *dst = (const struct in6_addr *) &msg->id.idiag_dst;
276*8542734aSAndroid Build Coastguard Worker return (IN6_IS_ADDR_V4MAPPED(src) && IN_LOOPBACK(src->s6_addr32[3])) ||
277*8542734aSAndroid Build Coastguard Worker (IN6_IS_ADDR_V4MAPPED(dst) && IN_LOOPBACK(dst->s6_addr32[3])) ||
278*8542734aSAndroid Build Coastguard Worker IN6_IS_ADDR_LOOPBACK(src) || IN6_IS_ADDR_LOOPBACK(dst) ||
279*8542734aSAndroid Build Coastguard Worker !memcmp(src, dst, sizeof(*src));
280*8542734aSAndroid Build Coastguard Worker }
281*8542734aSAndroid Build Coastguard Worker default:
282*8542734aSAndroid Build Coastguard Worker return false;
283*8542734aSAndroid Build Coastguard Worker }
284*8542734aSAndroid Build Coastguard Worker }
285*8542734aSAndroid Build Coastguard Worker
sockDestroy(uint8_t proto,const inet_diag_msg * msg)286*8542734aSAndroid Build Coastguard Worker int SockDiag::sockDestroy(uint8_t proto, const inet_diag_msg *msg) {
287*8542734aSAndroid Build Coastguard Worker if (msg == nullptr) {
288*8542734aSAndroid Build Coastguard Worker return 0;
289*8542734aSAndroid Build Coastguard Worker }
290*8542734aSAndroid Build Coastguard Worker
291*8542734aSAndroid Build Coastguard Worker DestroyRequest request = {
292*8542734aSAndroid Build Coastguard Worker .nlh = {
293*8542734aSAndroid Build Coastguard Worker .nlmsg_type = SOCK_DESTROY,
294*8542734aSAndroid Build Coastguard Worker .nlmsg_flags = NLM_F_REQUEST,
295*8542734aSAndroid Build Coastguard Worker },
296*8542734aSAndroid Build Coastguard Worker .req = {
297*8542734aSAndroid Build Coastguard Worker .sdiag_family = msg->idiag_family,
298*8542734aSAndroid Build Coastguard Worker .sdiag_protocol = proto,
299*8542734aSAndroid Build Coastguard Worker .idiag_states = (uint32_t) (1 << msg->idiag_state),
300*8542734aSAndroid Build Coastguard Worker .id = msg->id,
301*8542734aSAndroid Build Coastguard Worker },
302*8542734aSAndroid Build Coastguard Worker };
303*8542734aSAndroid Build Coastguard Worker request.nlh.nlmsg_len = sizeof(request);
304*8542734aSAndroid Build Coastguard Worker
305*8542734aSAndroid Build Coastguard Worker if (write(mWriteSock, &request, sizeof(request)) < (ssize_t) sizeof(request)) {
306*8542734aSAndroid Build Coastguard Worker return -errno;
307*8542734aSAndroid Build Coastguard Worker }
308*8542734aSAndroid Build Coastguard Worker
309*8542734aSAndroid Build Coastguard Worker int ret = checkError(mWriteSock);
310*8542734aSAndroid Build Coastguard Worker if (!ret) mSocketsDestroyed++;
311*8542734aSAndroid Build Coastguard Worker return ret;
312*8542734aSAndroid Build Coastguard Worker }
313*8542734aSAndroid Build Coastguard Worker
destroySockets(uint8_t proto,int family,const char * addrstr,int ifindex)314*8542734aSAndroid Build Coastguard Worker int SockDiag::destroySockets(uint8_t proto, int family, const char* addrstr, int ifindex) {
315*8542734aSAndroid Build Coastguard Worker if (!hasSocks()) {
316*8542734aSAndroid Build Coastguard Worker return -EBADFD;
317*8542734aSAndroid Build Coastguard Worker }
318*8542734aSAndroid Build Coastguard Worker
319*8542734aSAndroid Build Coastguard Worker if (int ret = sendDumpRequest(proto, family, addrstr)) {
320*8542734aSAndroid Build Coastguard Worker return ret;
321*8542734aSAndroid Build Coastguard Worker }
322*8542734aSAndroid Build Coastguard Worker
323*8542734aSAndroid Build Coastguard Worker // Destroy all sockets on the address, except link-local sockets where ifindex doesn't match.
324*8542734aSAndroid Build Coastguard Worker auto shouldDestroy = [ifindex](uint8_t, const inet_diag_msg* msg) {
325*8542734aSAndroid Build Coastguard Worker return ifindex == 0 || ifindex == (int)msg->id.idiag_if;
326*8542734aSAndroid Build Coastguard Worker };
327*8542734aSAndroid Build Coastguard Worker
328*8542734aSAndroid Build Coastguard Worker return readDiagMsg(proto, shouldDestroy);
329*8542734aSAndroid Build Coastguard Worker }
330*8542734aSAndroid Build Coastguard Worker
destroySockets(const char * addrstr,int ifindex)331*8542734aSAndroid Build Coastguard Worker int SockDiag::destroySockets(const char* addrstr, int ifindex) {
332*8542734aSAndroid Build Coastguard Worker Stopwatch s;
333*8542734aSAndroid Build Coastguard Worker mSocketsDestroyed = 0;
334*8542734aSAndroid Build Coastguard Worker
335*8542734aSAndroid Build Coastguard Worker std::string where = addrstr;
336*8542734aSAndroid Build Coastguard Worker if (ifindex) where += StringPrintf(" ifindex %d", ifindex);
337*8542734aSAndroid Build Coastguard Worker
338*8542734aSAndroid Build Coastguard Worker if (!strchr(addrstr, ':')) { // inet_ntop never returns something like ::ffff:192.0.2.1
339*8542734aSAndroid Build Coastguard Worker if (int ret = destroySockets(IPPROTO_TCP, AF_INET, addrstr, ifindex)) {
340*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to destroy IPv4 sockets on %s: %s",
341*8542734aSAndroid Build Coastguard Worker (isUser ? "[hidden: user build]" : where.c_str()), strerror(-ret));
342*8542734aSAndroid Build Coastguard Worker return ret;
343*8542734aSAndroid Build Coastguard Worker }
344*8542734aSAndroid Build Coastguard Worker }
345*8542734aSAndroid Build Coastguard Worker if (int ret = destroySockets(IPPROTO_TCP, AF_INET6, addrstr, ifindex)) {
346*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to destroy IPv6 sockets on %s: %s",
347*8542734aSAndroid Build Coastguard Worker (isUser ? "[hidden: user build]" : where.c_str()), strerror(-ret));
348*8542734aSAndroid Build Coastguard Worker return ret;
349*8542734aSAndroid Build Coastguard Worker }
350*8542734aSAndroid Build Coastguard Worker
351*8542734aSAndroid Build Coastguard Worker if (mSocketsDestroyed > 0) {
352*8542734aSAndroid Build Coastguard Worker ALOGI("Destroyed %d sockets on %s in %" PRId64 "us", mSocketsDestroyed,
353*8542734aSAndroid Build Coastguard Worker (isUser ? "[hidden: user build]" : where.c_str()), s.timeTakenUs());
354*8542734aSAndroid Build Coastguard Worker }
355*8542734aSAndroid Build Coastguard Worker
356*8542734aSAndroid Build Coastguard Worker return mSocketsDestroyed;
357*8542734aSAndroid Build Coastguard Worker }
358*8542734aSAndroid Build Coastguard Worker
destroyLiveSockets(const DestroyFilter & destroyFilter,const char * what,iovec * iov,int iovcnt)359*8542734aSAndroid Build Coastguard Worker int SockDiag::destroyLiveSockets(const DestroyFilter& destroyFilter, const char *what,
360*8542734aSAndroid Build Coastguard Worker iovec *iov, int iovcnt) {
361*8542734aSAndroid Build Coastguard Worker const int proto = IPPROTO_TCP;
362*8542734aSAndroid Build Coastguard Worker const uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
363*8542734aSAndroid Build Coastguard Worker
364*8542734aSAndroid Build Coastguard Worker for (const int family : {AF_INET, AF_INET6}) {
365*8542734aSAndroid Build Coastguard Worker const char *familyName = (family == AF_INET) ? "IPv4" : "IPv6";
366*8542734aSAndroid Build Coastguard Worker if (int ret = sendDumpRequest(proto, family, 0, states, iov, iovcnt)) {
367*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to dump %s sockets for %s: %s", familyName, what, strerror(-ret));
368*8542734aSAndroid Build Coastguard Worker return ret;
369*8542734aSAndroid Build Coastguard Worker }
370*8542734aSAndroid Build Coastguard Worker if (int ret = readDiagMsg(proto, destroyFilter)) {
371*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to destroy %s sockets for %s: %s", familyName, what, strerror(-ret));
372*8542734aSAndroid Build Coastguard Worker return ret;
373*8542734aSAndroid Build Coastguard Worker }
374*8542734aSAndroid Build Coastguard Worker }
375*8542734aSAndroid Build Coastguard Worker
376*8542734aSAndroid Build Coastguard Worker return 0;
377*8542734aSAndroid Build Coastguard Worker }
378*8542734aSAndroid Build Coastguard Worker
getLiveTcpInfos(const TcpInfoReader & tcpInfoReader)379*8542734aSAndroid Build Coastguard Worker int SockDiag::getLiveTcpInfos(const TcpInfoReader& tcpInfoReader) {
380*8542734aSAndroid Build Coastguard Worker const int proto = IPPROTO_TCP;
381*8542734aSAndroid Build Coastguard Worker const uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
382*8542734aSAndroid Build Coastguard Worker const uint8_t extensions = (1 << INET_DIAG_MEMINFO); // flag for dumping struct tcp_info.
383*8542734aSAndroid Build Coastguard Worker
384*8542734aSAndroid Build Coastguard Worker iovec iov[] = {
385*8542734aSAndroid Build Coastguard Worker { nullptr, 0 },
386*8542734aSAndroid Build Coastguard Worker };
387*8542734aSAndroid Build Coastguard Worker
388*8542734aSAndroid Build Coastguard Worker for (const int family : {AF_INET, AF_INET6}) {
389*8542734aSAndroid Build Coastguard Worker const char *familyName = (family == AF_INET) ? "IPv4" : "IPv6";
390*8542734aSAndroid Build Coastguard Worker if (int ret = sendDumpRequest(proto, family, extensions, states, iov, ARRAY_SIZE(iov))) {
391*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to dump %s sockets struct tcp_info: %s", familyName, strerror(-ret));
392*8542734aSAndroid Build Coastguard Worker return ret;
393*8542734aSAndroid Build Coastguard Worker }
394*8542734aSAndroid Build Coastguard Worker if (int ret = readDiagMsgWithTcpInfo(tcpInfoReader)) {
395*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to read %s sockets struct tcp_info: %s", familyName, strerror(-ret));
396*8542734aSAndroid Build Coastguard Worker return ret;
397*8542734aSAndroid Build Coastguard Worker }
398*8542734aSAndroid Build Coastguard Worker }
399*8542734aSAndroid Build Coastguard Worker
400*8542734aSAndroid Build Coastguard Worker return 0;
401*8542734aSAndroid Build Coastguard Worker }
402*8542734aSAndroid Build Coastguard Worker
destroySockets(uint8_t proto,const uid_t uid,bool excludeLoopback)403*8542734aSAndroid Build Coastguard Worker int SockDiag::destroySockets(uint8_t proto, const uid_t uid, bool excludeLoopback) {
404*8542734aSAndroid Build Coastguard Worker mSocketsDestroyed = 0;
405*8542734aSAndroid Build Coastguard Worker Stopwatch s;
406*8542734aSAndroid Build Coastguard Worker
407*8542734aSAndroid Build Coastguard Worker auto shouldDestroy = [uid, excludeLoopback] (uint8_t, const inet_diag_msg *msg) {
408*8542734aSAndroid Build Coastguard Worker return msg != nullptr &&
409*8542734aSAndroid Build Coastguard Worker msg->idiag_uid == uid &&
410*8542734aSAndroid Build Coastguard Worker !(excludeLoopback && isLoopbackSocket(msg));
411*8542734aSAndroid Build Coastguard Worker };
412*8542734aSAndroid Build Coastguard Worker
413*8542734aSAndroid Build Coastguard Worker for (const int family : {AF_INET, AF_INET6}) {
414*8542734aSAndroid Build Coastguard Worker const char *familyName = family == AF_INET ? "IPv4" : "IPv6";
415*8542734aSAndroid Build Coastguard Worker uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
416*8542734aSAndroid Build Coastguard Worker if (int ret = sendDumpRequest(proto, family, states)) {
417*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to dump %s sockets for UID: %s", familyName, strerror(-ret));
418*8542734aSAndroid Build Coastguard Worker return ret;
419*8542734aSAndroid Build Coastguard Worker }
420*8542734aSAndroid Build Coastguard Worker if (int ret = readDiagMsg(proto, shouldDestroy)) {
421*8542734aSAndroid Build Coastguard Worker ALOGE("Failed to destroy %s sockets for UID: %s", familyName, strerror(-ret));
422*8542734aSAndroid Build Coastguard Worker return ret;
423*8542734aSAndroid Build Coastguard Worker }
424*8542734aSAndroid Build Coastguard Worker }
425*8542734aSAndroid Build Coastguard Worker
426*8542734aSAndroid Build Coastguard Worker if (mSocketsDestroyed > 0) {
427*8542734aSAndroid Build Coastguard Worker ALOGI("Destroyed %d sockets for UID in %" PRId64 "us", mSocketsDestroyed, s.timeTakenUs());
428*8542734aSAndroid Build Coastguard Worker }
429*8542734aSAndroid Build Coastguard Worker
430*8542734aSAndroid Build Coastguard Worker return 0;
431*8542734aSAndroid Build Coastguard Worker }
432*8542734aSAndroid Build Coastguard Worker
destroySockets(const UidRanges & uidRanges,const std::set<uid_t> & skipUids,bool excludeLoopback)433*8542734aSAndroid Build Coastguard Worker int SockDiag::destroySockets(const UidRanges& uidRanges, const std::set<uid_t>& skipUids,
434*8542734aSAndroid Build Coastguard Worker bool excludeLoopback) {
435*8542734aSAndroid Build Coastguard Worker mSocketsDestroyed = 0;
436*8542734aSAndroid Build Coastguard Worker Stopwatch s;
437*8542734aSAndroid Build Coastguard Worker
438*8542734aSAndroid Build Coastguard Worker auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
439*8542734aSAndroid Build Coastguard Worker return msg != nullptr &&
440*8542734aSAndroid Build Coastguard Worker uidRanges.hasUid(msg->idiag_uid) &&
441*8542734aSAndroid Build Coastguard Worker skipUids.find(msg->idiag_uid) == skipUids.end() &&
442*8542734aSAndroid Build Coastguard Worker !(excludeLoopback && isLoopbackSocket(msg)) &&
443*8542734aSAndroid Build Coastguard Worker !isAdbSocket(msg, getAdbPort());
444*8542734aSAndroid Build Coastguard Worker };
445*8542734aSAndroid Build Coastguard Worker
446*8542734aSAndroid Build Coastguard Worker iovec iov[] = {
447*8542734aSAndroid Build Coastguard Worker { nullptr, 0 },
448*8542734aSAndroid Build Coastguard Worker };
449*8542734aSAndroid Build Coastguard Worker
450*8542734aSAndroid Build Coastguard Worker if (int ret = destroyLiveSockets(shouldDestroy, "UID", iov, ARRAY_SIZE(iov))) {
451*8542734aSAndroid Build Coastguard Worker return ret;
452*8542734aSAndroid Build Coastguard Worker }
453*8542734aSAndroid Build Coastguard Worker
454*8542734aSAndroid Build Coastguard Worker if (mSocketsDestroyed > 0) {
455*8542734aSAndroid Build Coastguard Worker ALOGI("Destroyed %d sockets for %s skip={%s} in %" PRId64 "us", mSocketsDestroyed,
456*8542734aSAndroid Build Coastguard Worker uidRanges.toString().c_str(), android::base::Join(skipUids, " ").c_str(),
457*8542734aSAndroid Build Coastguard Worker s.timeTakenUs());
458*8542734aSAndroid Build Coastguard Worker }
459*8542734aSAndroid Build Coastguard Worker
460*8542734aSAndroid Build Coastguard Worker return 0;
461*8542734aSAndroid Build Coastguard Worker }
462*8542734aSAndroid Build Coastguard Worker
463*8542734aSAndroid Build Coastguard Worker // Destroys all "live" (CONNECTED, SYN_SENT, SYN_RECV) TCP sockets on the specified netId where:
464*8542734aSAndroid Build Coastguard Worker // 1. The opening app no longer has permission to use this network, or:
465*8542734aSAndroid Build Coastguard Worker // 2. The opening app does have permission, but did not explicitly select this network.
466*8542734aSAndroid Build Coastguard Worker //
467*8542734aSAndroid Build Coastguard Worker // We destroy sockets without the explicit bit because we want to avoid the situation where a
468*8542734aSAndroid Build Coastguard Worker // privileged app uses its privileges without knowing it is doing so. For example, a privileged app
469*8542734aSAndroid Build Coastguard Worker // might have opened a socket on this network just because it was the default network at the
470*8542734aSAndroid Build Coastguard Worker // time. If we don't kill these sockets, those apps could continue to use them without realizing
471*8542734aSAndroid Build Coastguard Worker // that they are now sending and receiving traffic on a network that is now restricted.
destroySocketsLackingPermission(unsigned netId,Permission permission,bool excludeLoopback)472*8542734aSAndroid Build Coastguard Worker int SockDiag::destroySocketsLackingPermission(unsigned netId, Permission permission,
473*8542734aSAndroid Build Coastguard Worker bool excludeLoopback) {
474*8542734aSAndroid Build Coastguard Worker struct markmatch {
475*8542734aSAndroid Build Coastguard Worker inet_diag_bc_op op;
476*8542734aSAndroid Build Coastguard Worker // TODO: switch to inet_diag_markcond
477*8542734aSAndroid Build Coastguard Worker __u32 mark;
478*8542734aSAndroid Build Coastguard Worker __u32 mask;
479*8542734aSAndroid Build Coastguard Worker } __attribute__((packed));
480*8542734aSAndroid Build Coastguard Worker constexpr uint8_t matchlen = sizeof(markmatch);
481*8542734aSAndroid Build Coastguard Worker
482*8542734aSAndroid Build Coastguard Worker Fwmark netIdMark, netIdMask;
483*8542734aSAndroid Build Coastguard Worker netIdMark.netId = netId;
484*8542734aSAndroid Build Coastguard Worker netIdMask.netId = 0xffff;
485*8542734aSAndroid Build Coastguard Worker
486*8542734aSAndroid Build Coastguard Worker Fwmark controlMark;
487*8542734aSAndroid Build Coastguard Worker controlMark.explicitlySelected = true;
488*8542734aSAndroid Build Coastguard Worker controlMark.permission = permission;
489*8542734aSAndroid Build Coastguard Worker
490*8542734aSAndroid Build Coastguard Worker // A SOCK_DIAG bytecode program that accepts the sockets we intend to destroy.
491*8542734aSAndroid Build Coastguard Worker struct bytecode {
492*8542734aSAndroid Build Coastguard Worker markmatch netIdMatch;
493*8542734aSAndroid Build Coastguard Worker markmatch controlMatch;
494*8542734aSAndroid Build Coastguard Worker inet_diag_bc_op controlJump;
495*8542734aSAndroid Build Coastguard Worker } __attribute__((packed)) bytecode;
496*8542734aSAndroid Build Coastguard Worker
497*8542734aSAndroid Build Coastguard Worker // The length of the INET_DIAG_BC_JMP instruction.
498*8542734aSAndroid Build Coastguard Worker constexpr uint8_t jmplen = sizeof(inet_diag_bc_op);
499*8542734aSAndroid Build Coastguard Worker // Jump exactly this far past the end of the program to reject.
500*8542734aSAndroid Build Coastguard Worker constexpr uint8_t rejectoffset = sizeof(inet_diag_bc_op);
501*8542734aSAndroid Build Coastguard Worker // Total length of the program.
502*8542734aSAndroid Build Coastguard Worker constexpr uint8_t bytecodelen = sizeof(bytecode);
503*8542734aSAndroid Build Coastguard Worker
504*8542734aSAndroid Build Coastguard Worker bytecode = (struct bytecode) {
505*8542734aSAndroid Build Coastguard Worker // If netId matches, continue, otherwise, reject (i.e., leave socket alone).
506*8542734aSAndroid Build Coastguard Worker { { INET_DIAG_BC_MARK_COND, matchlen, bytecodelen + rejectoffset },
507*8542734aSAndroid Build Coastguard Worker netIdMark.intValue, netIdMask.intValue },
508*8542734aSAndroid Build Coastguard Worker
509*8542734aSAndroid Build Coastguard Worker // If explicit and permission bits match, go to the JMP below which rejects the socket
510*8542734aSAndroid Build Coastguard Worker // (i.e., we leave it alone). Otherwise, jump to the end of the program, which accepts the
511*8542734aSAndroid Build Coastguard Worker // socket (so we destroy it).
512*8542734aSAndroid Build Coastguard Worker { { INET_DIAG_BC_MARK_COND, matchlen, matchlen + jmplen },
513*8542734aSAndroid Build Coastguard Worker controlMark.intValue, controlMark.intValue },
514*8542734aSAndroid Build Coastguard Worker
515*8542734aSAndroid Build Coastguard Worker // This JMP unconditionally rejects the packet by jumping to the reject target. It is
516*8542734aSAndroid Build Coastguard Worker // necessary to keep the kernel bytecode verifier happy. If we don't have a JMP the bytecode
517*8542734aSAndroid Build Coastguard Worker // is invalid because the target of every no jump must always be reachable by yes jumps.
518*8542734aSAndroid Build Coastguard Worker // Without this JMP, the accept target is not reachable by yes jumps and the program will
519*8542734aSAndroid Build Coastguard Worker // be rejected by the validator.
520*8542734aSAndroid Build Coastguard Worker { INET_DIAG_BC_JMP, jmplen, jmplen + rejectoffset },
521*8542734aSAndroid Build Coastguard Worker
522*8542734aSAndroid Build Coastguard Worker // We have reached the end of the program. Accept the socket, and destroy it below.
523*8542734aSAndroid Build Coastguard Worker };
524*8542734aSAndroid Build Coastguard Worker
525*8542734aSAndroid Build Coastguard Worker struct nlattr nla = {
526*8542734aSAndroid Build Coastguard Worker .nla_len = sizeof(struct nlattr) + bytecodelen,
527*8542734aSAndroid Build Coastguard Worker .nla_type = INET_DIAG_REQ_BYTECODE,
528*8542734aSAndroid Build Coastguard Worker };
529*8542734aSAndroid Build Coastguard Worker
530*8542734aSAndroid Build Coastguard Worker iovec iov[] = {
531*8542734aSAndroid Build Coastguard Worker { nullptr, 0 },
532*8542734aSAndroid Build Coastguard Worker { &nla, sizeof(nla) },
533*8542734aSAndroid Build Coastguard Worker { &bytecode, bytecodelen },
534*8542734aSAndroid Build Coastguard Worker };
535*8542734aSAndroid Build Coastguard Worker
536*8542734aSAndroid Build Coastguard Worker mSocketsDestroyed = 0;
537*8542734aSAndroid Build Coastguard Worker Stopwatch s;
538*8542734aSAndroid Build Coastguard Worker
539*8542734aSAndroid Build Coastguard Worker auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
540*8542734aSAndroid Build Coastguard Worker return msg != nullptr && !(excludeLoopback && isLoopbackSocket(msg));
541*8542734aSAndroid Build Coastguard Worker };
542*8542734aSAndroid Build Coastguard Worker
543*8542734aSAndroid Build Coastguard Worker if (int ret = destroyLiveSockets(shouldDestroy, "permission change", iov, ARRAY_SIZE(iov))) {
544*8542734aSAndroid Build Coastguard Worker return ret;
545*8542734aSAndroid Build Coastguard Worker }
546*8542734aSAndroid Build Coastguard Worker
547*8542734aSAndroid Build Coastguard Worker if (mSocketsDestroyed > 0) {
548*8542734aSAndroid Build Coastguard Worker ALOGI("Destroyed %d sockets for netId %d permission=%d in %" PRId64 "us", mSocketsDestroyed,
549*8542734aSAndroid Build Coastguard Worker netId, permission, s.timeTakenUs());
550*8542734aSAndroid Build Coastguard Worker }
551*8542734aSAndroid Build Coastguard Worker
552*8542734aSAndroid Build Coastguard Worker return 0;
553*8542734aSAndroid Build Coastguard Worker }
554*8542734aSAndroid Build Coastguard Worker
555*8542734aSAndroid Build Coastguard Worker } // namespace net
556*8542734aSAndroid Build Coastguard Worker } // namespace android
557