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