SockDiag.cpp revision f32fc598b01ba8d59873b0a1085716fd84678b54
18464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti/* 28464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * Copyright (C) 2016 The Android Open Source Project 38464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * 48464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License"); 58464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * you may not use this file except in compliance with the License. 68464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * You may obtain a copy of the License at 78464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * 88464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * http://www.apache.org/licenses/LICENSE-2.0 98464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * 108464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * Unless required by applicable law or agreed to in writing, software 118464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS, 128464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * See the License for the specific language governing permissions and 148464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti * limitations under the License. 158464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti */ 168464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 178464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <errno.h> 188464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <netdb.h> 198464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <string.h> 208464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <netinet/in.h> 218464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <netinet/tcp.h> 228464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <sys/socket.h> 238464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <sys/uio.h> 248464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 258464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <linux/netlink.h> 268464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <linux/sock_diag.h> 278464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <linux/inet_diag.h> 288464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 298464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#define LOG_TAG "Netd" 308464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 318464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <cutils/log.h> 328464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 338464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include "NetdConstants.h" 348464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include "SockDiag.h" 358464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 36f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti#include <chrono> 37f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 388464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#ifndef SOCK_DESTROY 398464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#define SOCK_DESTROY 21 408464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#endif 418464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 428464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittinamespace { 438464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 448464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittistruct AddrinfoDeleter { 458464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti void operator()(addrinfo *a) { if (a) freeaddrinfo(a); } 468464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti}; 478464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 488464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittitypedef std::unique_ptr<addrinfo, AddrinfoDeleter> ScopedAddrinfo; 498464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 508464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittiint checkError(int fd) { 518464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti struct { 528464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti nlmsghdr h; 538464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti nlmsgerr err; 548464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } __attribute__((__packed__)) ack; 558464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti ssize_t bytesread = recv(fd, &ack, sizeof(ack), MSG_DONTWAIT | MSG_PEEK); 568464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if (bytesread == -1) { 578464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti // Read failed (error), or nothing to read (good). 588464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return (errno == EAGAIN) ? 0 : -errno; 598464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } else if (bytesread == (ssize_t) sizeof(ack) && ack.h.nlmsg_type == NLMSG_ERROR) { 608464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti // We got an error. Consume it. 618464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti recv(fd, &ack, sizeof(ack), 0); 628464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return ack.err.error; 638464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } else { 648464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti // The kernel replied with something. Leave it to the caller. 658464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return 0; 668464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 678464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti} 688464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 698464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti} // namespace 708464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 718464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittibool SockDiag::open() { 728464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if (hasSocks()) { 738464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return false; 748464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 758464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 768464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti mSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG); 778464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti mWriteSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG); 788464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if (!hasSocks()) { 798464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti closeSocks(); 808464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return false; 818464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 828464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 838464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti sockaddr_nl nl = { .nl_family = AF_NETLINK }; 848464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if ((connect(mSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1) || 858464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti (connect(mWriteSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1)) { 868464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti closeSocks(); 878464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return false; 888464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 898464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 908464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return true; 918464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti} 928464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 938464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittiint SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, const char *addrstr) { 948464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti addrinfo hints = { .ai_flags = AI_NUMERICHOST }; 958464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti addrinfo *res; 968464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti in6_addr mapped = { .s6_addr32 = { 0, 0, htonl(0xffff), 0 } }; 978464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti int ret; 988464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 998464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti // TODO: refactor the netlink parsing code out of system/core, bring it into netd, and stop 1008464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti // doing string conversions when they're not necessary. 1018464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if ((ret = getaddrinfo(addrstr, nullptr, &hints, &res)) != 0) { 1028464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return -EINVAL; 1038464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 1048464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1058464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti // So we don't have to call freeaddrinfo on every failure path. 1068464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti ScopedAddrinfo resP(res); 1078464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1088464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti void *addr; 1098464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti uint8_t addrlen; 1108464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if (res->ai_family == AF_INET && family == AF_INET) { 1118464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr; 1128464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti addr = &ina; 1138464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti addrlen = sizeof(ina); 1148464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } else if (res->ai_family == AF_INET && family == AF_INET6) { 1158464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr; 1168464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti mapped.s6_addr32[3] = ina.s_addr; 1178464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti addr = &mapped; 1188464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti addrlen = sizeof(mapped); 1198464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } else if (res->ai_family == AF_INET6 && family == AF_INET6) { 1208464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti in6_addr& in6a = reinterpret_cast<sockaddr_in6*>(res->ai_addr)->sin6_addr; 1218464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti addr = &in6a; 1228464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti addrlen = sizeof(in6a); 1238464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } else { 1248464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return -EAFNOSUPPORT; 1258464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 1268464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1278464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti uint8_t prefixlen = addrlen * 8; 1288464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti uint8_t yesjump = sizeof(inet_diag_bc_op) + sizeof(inet_diag_hostcond) + addrlen; 1298464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti uint8_t nojump = yesjump + 4; 1308464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti uint32_t states = ~(1 << TCP_TIME_WAIT); 1318464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1328464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti struct { 1338464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti nlmsghdr nlh; 1348464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti inet_diag_req_v2 req; 1358464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti nlattr nla; 1368464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti inet_diag_bc_op op; 1378464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti inet_diag_hostcond cond; 1388464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } __attribute__((__packed__)) request = { 1398464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .nlh = { 1408464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .nlmsg_type = SOCK_DIAG_BY_FAMILY, 1418464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, 1428464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }, 1438464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .req = { 1448464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .sdiag_family = family, 1458464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .sdiag_protocol = proto, 1468464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .idiag_states = states, 1478464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }, 1488464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .nla = { 1498464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .nla_type = INET_DIAG_REQ_BYTECODE, 1508464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }, 1518464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .op = { 1528464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti INET_DIAG_BC_S_COND, 1538464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti yesjump, 1548464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti nojump, 1558464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }, 1568464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .cond = { 1578464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti family, 1588464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti prefixlen, 1598464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti -1, 1608464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti {} 1618464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }, 1628464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }; 1638464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1648464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti request.nlh.nlmsg_len = sizeof(request) + addrlen; 1658464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti request.nla.nla_len = sizeof(request.nla) + sizeof(request.op) + sizeof(request.cond) + addrlen; 1668464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1678464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti struct iovec iov[] = { 1688464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti { &request, sizeof(request) }, 1698464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti { addr, addrlen }, 1708464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }; 1718464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1728464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if (writev(mSock, iov, ARRAY_SIZE(iov)) != (int) request.nlh.nlmsg_len) { 1738464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return -errno; 1748464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 1758464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1768464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return checkError(mSock); 1778464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti} 1788464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1798464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittiint SockDiag::readDiagMsg(uint8_t proto, SockDiag::DumpCallback callback) { 1808464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti char buf[kBufferSize]; 1818464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1828464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti ssize_t bytesread; 1838464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti do { 1848464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti bytesread = read(mSock, buf, sizeof(buf)); 1858464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1868464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if (bytesread < 0) { 1878464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return -errno; 1888464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 1898464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 1908464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti uint32_t len = bytesread; 1918464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti for (nlmsghdr *nlh = reinterpret_cast<nlmsghdr *>(buf); 1928464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti NLMSG_OK(nlh, len); 1938464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti nlh = NLMSG_NEXT(nlh, len)) { 1948464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti switch (nlh->nlmsg_type) { 1958464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti case NLMSG_DONE: 1968464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti callback(proto, NULL); 1978464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return 0; 1988464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti case NLMSG_ERROR: { 1998464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti nlmsgerr *err = reinterpret_cast<nlmsgerr *>(NLMSG_DATA(nlh)); 2008464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return err->error; 2018464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 2028464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti default: 2038464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh)); 2048464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti callback(proto, msg); 2058464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 2068464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 2078464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } while (bytesread > 0); 2088464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 2098464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return 0; 2108464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti} 2118464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 2128464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittiint SockDiag::sockDestroy(uint8_t proto, const inet_diag_msg *msg) { 213f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti if (msg == nullptr) { 214f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return 0; 215f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti } 216f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 2178464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti DestroyRequest request = { 2188464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .nlh = { 2198464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .nlmsg_type = SOCK_DESTROY, 2208464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .nlmsg_flags = NLM_F_REQUEST, 2218464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }, 2228464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .req = { 2238464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .sdiag_family = msg->idiag_family, 2248464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .sdiag_protocol = proto, 2258464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .idiag_states = (uint32_t) (1 << msg->idiag_state), 2268464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti .id = msg->id, 2278464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }, 2288464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti }; 2298464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti request.nlh.nlmsg_len = sizeof(request); 2308464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 2318464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti if (write(mWriteSock, &request, sizeof(request)) < (ssize_t) sizeof(request)) { 2328464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti return -errno; 2338464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti } 2348464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti 235f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti int ret = checkError(mWriteSock); 236f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti if (!ret) mSocketsDestroyed++; 237f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return ret; 238f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti} 239f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 240f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colittiint SockDiag::destroySockets(uint8_t proto, int family, const char *addrstr) { 241f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti if (!hasSocks()) { 242f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return -EBADFD; 243f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti } 244f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 245f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti if (int ret = sendDumpRequest(proto, family, addrstr)) { 246f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return ret; 247f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti } 248f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 249f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti auto destroy = [this] (uint8_t proto, const inet_diag_msg *msg) { 250f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return this->sockDestroy(proto, msg); 251f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti }; 252f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 253f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return readDiagMsg(proto, destroy); 254f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti} 255f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 256f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colittiint SockDiag::destroySockets(const char *addrstr) { 257f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti using ms = std::chrono::duration<float, std::ratio<1, 1000>>; 258f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 259f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti mSocketsDestroyed = 0; 260f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti const auto start = std::chrono::steady_clock::now(); 261f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti if (!strchr(addrstr, ':')) { 262f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti if (int ret = destroySockets(IPPROTO_TCP, AF_INET, addrstr)) { 263f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti ALOGE("Failed to destroy IPv4 sockets on %s: %s", addrstr, strerror(-ret)); 264f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return ret; 265f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti } 266f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti } 267f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti if (int ret = destroySockets(IPPROTO_TCP, AF_INET6, addrstr)) { 268f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti ALOGE("Failed to destroy IPv6 sockets on %s: %s", addrstr, strerror(-ret)); 269f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return ret; 270f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti } 271f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti auto elapsed = std::chrono::duration_cast<ms>(std::chrono::steady_clock::now() - start); 272f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 273f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti if (mSocketsDestroyed > 0) { 274f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti ALOGI("Destroyed %d sockets on %s in %.1f ms", mSocketsDestroyed, addrstr, elapsed.count()); 275f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti } 276f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti 277f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti return mSocketsDestroyed; 2788464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti} 279