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
31fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti#include <android-base/strings.h>
328464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include <cutils/log.h>
338464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
348464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include "NetdConstants.h"
358464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#include "SockDiag.h"
368464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
37f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti#include <chrono>
38f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
398464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#ifndef SOCK_DESTROY
408464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#define SOCK_DESTROY 21
418464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti#endif
428464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
438464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittinamespace {
448464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
458464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittistruct AddrinfoDeleter {
468464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti  void operator()(addrinfo *a) { if (a) freeaddrinfo(a); }
478464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti};
488464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
498464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittitypedef std::unique_ptr<addrinfo, AddrinfoDeleter> ScopedAddrinfo;
508464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
518464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittiint checkError(int fd) {
528464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    struct {
538464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        nlmsghdr h;
548464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        nlmsgerr err;
558464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    } __attribute__((__packed__)) ack;
568464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    ssize_t bytesread = recv(fd, &ack, sizeof(ack), MSG_DONTWAIT | MSG_PEEK);
578464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    if (bytesread == -1) {
588464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti       // Read failed (error), or nothing to read (good).
598464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti       return (errno == EAGAIN) ? 0 : -errno;
608464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    } else if (bytesread == (ssize_t) sizeof(ack) && ack.h.nlmsg_type == NLMSG_ERROR) {
618464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        // We got an error. Consume it.
628464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        recv(fd, &ack, sizeof(ack), 0);
638464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        return ack.err.error;
648464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    } else {
658464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        // The kernel replied with something. Leave it to the caller.
668464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        return 0;
678464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    }
688464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti}
698464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
708464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti}  // namespace
718464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
728464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittibool SockDiag::open() {
738464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    if (hasSocks()) {
748464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        return false;
758464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    }
768464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
778464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    mSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG);
788464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    mWriteSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG);
798464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    if (!hasSocks()) {
808464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        closeSocks();
818464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        return false;
828464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    }
838464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
848464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    sockaddr_nl nl = { .nl_family = AF_NETLINK };
858464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    if ((connect(mSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1) ||
868464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        (connect(mWriteSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1)) {
878464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        closeSocks();
888464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        return false;
898464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    }
908464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
918464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    return true;
928464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti}
938464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
9494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colittiint SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states,
9594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti                              iovec *iov, int iovcnt) {
9694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    struct {
9794a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        nlmsghdr nlh;
9894a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        inet_diag_req_v2 req;
9994a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    } __attribute__((__packed__)) request = {
10094a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        .nlh = {
10194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            .nlmsg_type = SOCK_DIAG_BY_FAMILY,
10294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
10394a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        },
10494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        .req = {
10594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            .sdiag_family = family,
10694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            .sdiag_protocol = proto,
10794a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            .idiag_states = states,
10894a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        },
10994a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    };
11094a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
11194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    size_t len = 0;
11294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    iov[0].iov_base = &request;
11394a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    iov[0].iov_len = sizeof(request);
11494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    for (int i = 0; i < iovcnt; i++) {
11594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        len += iov[i].iov_len;
11694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    }
11794a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    request.nlh.nlmsg_len = len;
11894a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
11994a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    if (writev(mSock, iov, iovcnt) != (ssize_t) len) {
12094a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        return -errno;
12194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    }
12294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
12394a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    return checkError(mSock);
12494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti}
12594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
12694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colittiint SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states) {
12794a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    iovec iov[] = {
12894a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        { nullptr, 0 },
12994a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    };
13094a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    return sendDumpRequest(proto, family, states, iov, ARRAY_SIZE(iov));
13194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti}
13294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
1338464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittiint SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, const char *addrstr) {
1348464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    addrinfo hints = { .ai_flags = AI_NUMERICHOST };
1358464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    addrinfo *res;
1368464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    in6_addr mapped = { .s6_addr32 = { 0, 0, htonl(0xffff), 0 } };
1378464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    int ret;
1388464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
1398464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    // TODO: refactor the netlink parsing code out of system/core, bring it into netd, and stop
1408464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    // doing string conversions when they're not necessary.
1418464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    if ((ret = getaddrinfo(addrstr, nullptr, &hints, &res)) != 0) {
1428464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        return -EINVAL;
1438464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    }
1448464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
1458464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    // So we don't have to call freeaddrinfo on every failure path.
1468464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    ScopedAddrinfo resP(res);
1478464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
1488464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    void *addr;
1498464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    uint8_t addrlen;
1508464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    if (res->ai_family == AF_INET && family == AF_INET) {
1518464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
1528464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        addr = &ina;
1538464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        addrlen = sizeof(ina);
1548464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    } else if (res->ai_family == AF_INET && family == AF_INET6) {
1558464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
1568464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        mapped.s6_addr32[3] = ina.s_addr;
1578464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        addr = &mapped;
1588464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        addrlen = sizeof(mapped);
1598464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    } else if (res->ai_family == AF_INET6 && family == AF_INET6) {
1608464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        in6_addr& in6a = reinterpret_cast<sockaddr_in6*>(res->ai_addr)->sin6_addr;
1618464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        addr = &in6a;
1628464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        addrlen = sizeof(in6a);
1638464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    } else {
1648464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        return -EAFNOSUPPORT;
1658464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    }
1668464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
1678464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    uint8_t prefixlen = addrlen * 8;
1688464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    uint8_t yesjump = sizeof(inet_diag_bc_op) + sizeof(inet_diag_hostcond) + addrlen;
1698464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    uint8_t nojump = yesjump + 4;
1708464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
1718464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    struct {
1728464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        nlattr nla;
1738464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        inet_diag_bc_op op;
1748464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        inet_diag_hostcond cond;
17594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    } __attribute__((__packed__)) attrs = {
1768464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        .nla = {
1778464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            .nla_type = INET_DIAG_REQ_BYTECODE,
1788464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        },
1798464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        .op = {
1808464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            INET_DIAG_BC_S_COND,
1818464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            yesjump,
1828464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            nojump,
1838464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        },
1848464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        .cond = {
1858464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            family,
1868464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            prefixlen,
1878464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            -1,
1888464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            {}
1898464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        },
1908464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    };
1918464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
19294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    attrs.nla.nla_len = sizeof(attrs) + addrlen;
1938464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
19494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    iovec iov[] = {
19594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        { nullptr, 0 },
19694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        { &attrs, sizeof(attrs) },
1978464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        { addr, addrlen },
1988464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    };
1998464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
20094a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    uint32_t states = ~(1 << TCP_TIME_WAIT);
20194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    return sendDumpRequest(proto, family, states, iov, ARRAY_SIZE(iov));
2028464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti}
2038464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
2048464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittiint SockDiag::readDiagMsg(uint8_t proto, SockDiag::DumpCallback callback) {
2058464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    char buf[kBufferSize];
2068464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
2078464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    ssize_t bytesread;
2088464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    do {
2098464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        bytesread = read(mSock, buf, sizeof(buf));
2108464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
2118464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        if (bytesread < 0) {
2128464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            return -errno;
2138464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        }
2148464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
2158464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        uint32_t len = bytesread;
2168464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        for (nlmsghdr *nlh = reinterpret_cast<nlmsghdr *>(buf);
2178464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti             NLMSG_OK(nlh, len);
2188464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti             nlh = NLMSG_NEXT(nlh, len)) {
2198464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            switch (nlh->nlmsg_type) {
2208464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti              case NLMSG_DONE:
2218464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti                callback(proto, NULL);
2228464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti                return 0;
2238464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti              case NLMSG_ERROR: {
2248464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti                nlmsgerr *err = reinterpret_cast<nlmsgerr *>(NLMSG_DATA(nlh));
2258464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti                return err->error;
2268464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti              }
2278464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti              default:
2288464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti                inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
229fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti                if (callback(proto, msg)) {
230fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti                    sockDestroy(proto, msg);
231fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti                }
2328464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            }
2338464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        }
2348464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    } while (bytesread > 0);
2358464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
2368464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    return 0;
2378464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti}
2388464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
2398464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colittiint SockDiag::sockDestroy(uint8_t proto, const inet_diag_msg *msg) {
240f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    if (msg == nullptr) {
241f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti       return 0;
242f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    }
243f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
2448464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    DestroyRequest request = {
2458464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        .nlh = {
2468464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            .nlmsg_type = SOCK_DESTROY,
2478464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            .nlmsg_flags = NLM_F_REQUEST,
2488464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        },
2498464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        .req = {
2508464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            .sdiag_family = msg->idiag_family,
2518464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            .sdiag_protocol = proto,
2528464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            .idiag_states = (uint32_t) (1 << msg->idiag_state),
2538464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti            .id = msg->id,
2548464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        },
2558464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    };
2568464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    request.nlh.nlmsg_len = sizeof(request);
2578464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
2588464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    if (write(mWriteSock, &request, sizeof(request)) < (ssize_t) sizeof(request)) {
2598464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti        return -errno;
2608464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti    }
2618464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti
262f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    int ret = checkError(mWriteSock);
263f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    if (!ret) mSocketsDestroyed++;
264f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    return ret;
265f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti}
266f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
267f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colittiint SockDiag::destroySockets(uint8_t proto, int family, const char *addrstr) {
268f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    if (!hasSocks()) {
269f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti        return -EBADFD;
270f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    }
271f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
272f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    if (int ret = sendDumpRequest(proto, family, addrstr)) {
273f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti        return ret;
274f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    }
275f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
276fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    auto destroyAll = [] (uint8_t, const inet_diag_msg*) { return true; };
277f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
278fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    return readDiagMsg(proto, destroyAll);
279f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti}
280f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
281f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colittiint SockDiag::destroySockets(const char *addrstr) {
28294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    Stopwatch s;
283f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    mSocketsDestroyed = 0;
28494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
285f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    if (!strchr(addrstr, ':')) {
286f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti        if (int ret = destroySockets(IPPROTO_TCP, AF_INET, addrstr)) {
287f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti            ALOGE("Failed to destroy IPv4 sockets on %s: %s", addrstr, strerror(-ret));
288f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti            return ret;
289f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti        }
290f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    }
291f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    if (int ret = destroySockets(IPPROTO_TCP, AF_INET6, addrstr)) {
292f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti        ALOGE("Failed to destroy IPv6 sockets on %s: %s", addrstr, strerror(-ret));
293f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti        return ret;
294f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    }
295f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
296f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    if (mSocketsDestroyed > 0) {
29794a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        ALOGI("Destroyed %d sockets on %s in %.1f ms", mSocketsDestroyed, addrstr, s.timeTaken());
298f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    }
299f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti
300f32fc598b01ba8d59873b0a1085716fd84678b54Lorenzo Colitti    return mSocketsDestroyed;
3018464e1ed13a30ca91ae44dd2e334f63de7ade0f3Lorenzo Colitti}
30294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
303fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colittiint SockDiag::destroyLiveSockets(DumpCallback destroyFilter) {
304fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    int proto = IPPROTO_TCP;
305fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
306fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    for (const int family : {AF_INET, AF_INET6}) {
307fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        const char *familyName = (family == AF_INET) ? "IPv4" : "IPv6";
308fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
309fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        if (int ret = sendDumpRequest(proto, family, states)) {
310fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti            ALOGE("Failed to dump %s sockets for UID: %s", familyName, strerror(-ret));
311fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti            return ret;
312fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        }
313fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        if (int ret = readDiagMsg(proto, destroyFilter)) {
314fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti            ALOGE("Failed to destroy %s sockets for UID: %s", familyName, strerror(-ret));
315fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti            return ret;
316fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        }
317fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    }
318fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
319fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    return 0;
320fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti}
321fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
32294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colittiint SockDiag::destroySockets(uint8_t proto, const uid_t uid) {
32394a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    mSocketsDestroyed = 0;
32494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    Stopwatch s;
32594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
326fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    auto shouldDestroy = [uid] (uint8_t, const inet_diag_msg *msg) {
327fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        return (msg != nullptr && msg->idiag_uid == uid);
32894a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    };
32994a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
33094a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    for (const int family : {AF_INET, AF_INET6}) {
33194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        const char *familyName = family == AF_INET ? "IPv4" : "IPv6";
33294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
33394a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        if (int ret = sendDumpRequest(proto, family, states)) {
33494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            ALOGE("Failed to dump %s sockets for UID: %s", familyName, strerror(-ret));
33594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            return ret;
33694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        }
337fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        if (int ret = readDiagMsg(proto, shouldDestroy)) {
33894a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            ALOGE("Failed to destroy %s sockets for UID: %s", familyName, strerror(-ret));
33994a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti            return ret;
34094a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        }
34194a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    }
34294a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
34394a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    if (mSocketsDestroyed > 0) {
34494a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti        ALOGI("Destroyed %d sockets for UID in %.1f ms", mSocketsDestroyed, s.timeTaken());
34594a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    }
34694a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti
34794a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti    return 0;
34894a7b43ecb13094313d5f1bdc2515be760a0b6beLorenzo Colitti}
349fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
350fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colittiint SockDiag::destroySockets(const UidRanges& uidRanges, const std::set<uid_t>& skipUids) {
351fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    mSocketsDestroyed = 0;
352fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    Stopwatch s;
353fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
354fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    auto shouldDestroy = [&] (uint8_t, const inet_diag_msg *msg) {
355fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        return msg != nullptr &&
356fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti               uidRanges.hasUid(msg->idiag_uid) &&
357fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti               skipUids.find(msg->idiag_uid) == skipUids.end();
358fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    };
359fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
360fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    if (int ret = destroyLiveSockets(shouldDestroy)) {
361fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        return ret;
362fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    }
363fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
364fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    std::vector<uid_t> skipUidStrings;
365fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    for (uid_t uid : skipUids) {
366fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        skipUidStrings.push_back(uid);
367fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    }
368fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    std::sort(skipUidStrings.begin(), skipUidStrings.end());
369fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
370fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    if (mSocketsDestroyed > 0) {
371fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti        ALOGI("Destroyed %d sockets for %s skip={%s} in %.1f ms",
372fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti              mSocketsDestroyed, uidRanges.toString().c_str(),
373fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti              android::base::Join(skipUidStrings, " ").c_str(), s.timeTaken());
374fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    }
375fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti
376fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti    return 0;
377fff4bd31ff2bad0acfd8f2439eccf7df70e9695fLorenzo Colitti}
378