2 * Copyright (C) 2016 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <netinet/in.h>
21 #include <netinet/tcp.h>
22 #include <sys/socket.h>
25 #include <linux/netlink.h>
26 #include <linux/sock_diag.h>
27 #include <linux/inet_diag.h>
29 #define LOG_TAG "Netd"
31 #include <cutils/log.h>
33 #include "NetdConstants.h"
39 #define SOCK_DESTROY 21
44 struct AddrinfoDeleter {
45 void operator()(addrinfo *a) { if (a) freeaddrinfo(a); }
48 typedef std::unique_ptr<addrinfo, AddrinfoDeleter> ScopedAddrinfo;
52 Stopwatch(): mStart(std::chrono::steady_clock::now()) {}
54 using ms = std::chrono::duration<float, std::ratio<1, 1000>>;
55 return (std::chrono::duration_cast<ms>(
56 std::chrono::steady_clock::now() - mStart)).count();
60 std::chrono::time_point<std::chrono::steady_clock> mStart;
64 int checkError(int fd) {
68 } __attribute__((__packed__)) ack;
69 ssize_t bytesread = recv(fd, &ack, sizeof(ack), MSG_DONTWAIT | MSG_PEEK);
70 if (bytesread == -1) {
71 // Read failed (error), or nothing to read (good).
72 return (errno == EAGAIN) ? 0 : -errno;
73 } else if (bytesread == (ssize_t) sizeof(ack) && ack.h.nlmsg_type == NLMSG_ERROR) {
74 // We got an error. Consume it.
75 recv(fd, &ack, sizeof(ack), 0);
78 // The kernel replied with something. Leave it to the caller.
85 bool SockDiag::open() {
90 mSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG);
91 mWriteSock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_INET_DIAG);
97 sockaddr_nl nl = { .nl_family = AF_NETLINK };
98 if ((connect(mSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1) ||
99 (connect(mWriteSock, reinterpret_cast<sockaddr *>(&nl), sizeof(nl)) == -1)) {
107 int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states,
108 iovec *iov, int iovcnt) {
111 inet_diag_req_v2 req;
112 } __attribute__((__packed__)) request = {
114 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
115 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
118 .sdiag_family = family,
119 .sdiag_protocol = proto,
120 .idiag_states = states,
125 iov[0].iov_base = &request;
126 iov[0].iov_len = sizeof(request);
127 for (int i = 0; i < iovcnt; i++) {
128 len += iov[i].iov_len;
130 request.nlh.nlmsg_len = len;
132 if (writev(mSock, iov, iovcnt) != (ssize_t) len) {
136 return checkError(mSock);
139 int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, uint32_t states) {
143 return sendDumpRequest(proto, family, states, iov, ARRAY_SIZE(iov));
146 int SockDiag::sendDumpRequest(uint8_t proto, uint8_t family, const char *addrstr) {
147 addrinfo hints = { .ai_flags = AI_NUMERICHOST };
149 in6_addr mapped = { .s6_addr32 = { 0, 0, htonl(0xffff), 0 } };
152 // TODO: refactor the netlink parsing code out of system/core, bring it into netd, and stop
153 // doing string conversions when they're not necessary.
154 if ((ret = getaddrinfo(addrstr, nullptr, &hints, &res)) != 0) {
158 // So we don't have to call freeaddrinfo on every failure path.
159 ScopedAddrinfo resP(res);
163 if (res->ai_family == AF_INET && family == AF_INET) {
164 in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
166 addrlen = sizeof(ina);
167 } else if (res->ai_family == AF_INET && family == AF_INET6) {
168 in_addr& ina = reinterpret_cast<sockaddr_in*>(res->ai_addr)->sin_addr;
169 mapped.s6_addr32[3] = ina.s_addr;
171 addrlen = sizeof(mapped);
172 } else if (res->ai_family == AF_INET6 && family == AF_INET6) {
173 in6_addr& in6a = reinterpret_cast<sockaddr_in6*>(res->ai_addr)->sin6_addr;
175 addrlen = sizeof(in6a);
177 return -EAFNOSUPPORT;
180 uint8_t prefixlen = addrlen * 8;
181 uint8_t yesjump = sizeof(inet_diag_bc_op) + sizeof(inet_diag_hostcond) + addrlen;
182 uint8_t nojump = yesjump + 4;
187 inet_diag_hostcond cond;
188 } __attribute__((__packed__)) attrs = {
190 .nla_type = INET_DIAG_REQ_BYTECODE,
205 attrs.nla.nla_len = sizeof(attrs) + addrlen;
209 { &attrs, sizeof(attrs) },
213 uint32_t states = ~(1 << TCP_TIME_WAIT);
214 return sendDumpRequest(proto, family, states, iov, ARRAY_SIZE(iov));
217 int SockDiag::readDiagMsg(uint8_t proto, SockDiag::DumpCallback callback) {
218 char buf[kBufferSize];
222 bytesread = read(mSock, buf, sizeof(buf));
228 uint32_t len = bytesread;
229 for (nlmsghdr *nlh = reinterpret_cast<nlmsghdr *>(buf);
231 nlh = NLMSG_NEXT(nlh, len)) {
232 switch (nlh->nlmsg_type) {
234 callback(proto, NULL);
237 nlmsgerr *err = reinterpret_cast<nlmsgerr *>(NLMSG_DATA(nlh));
241 inet_diag_msg *msg = reinterpret_cast<inet_diag_msg *>(NLMSG_DATA(nlh));
242 callback(proto, msg);
245 } while (bytesread > 0);
250 int SockDiag::sockDestroy(uint8_t proto, const inet_diag_msg *msg) {
251 if (msg == nullptr) {
255 DestroyRequest request = {
257 .nlmsg_type = SOCK_DESTROY,
258 .nlmsg_flags = NLM_F_REQUEST,
261 .sdiag_family = msg->idiag_family,
262 .sdiag_protocol = proto,
263 .idiag_states = (uint32_t) (1 << msg->idiag_state),
267 request.nlh.nlmsg_len = sizeof(request);
269 if (write(mWriteSock, &request, sizeof(request)) < (ssize_t) sizeof(request)) {
273 int ret = checkError(mWriteSock);
274 if (!ret) mSocketsDestroyed++;
278 int SockDiag::destroySockets(uint8_t proto, int family, const char *addrstr) {
283 if (int ret = sendDumpRequest(proto, family, addrstr)) {
287 auto destroy = [this] (uint8_t proto, const inet_diag_msg *msg) {
288 return this->sockDestroy(proto, msg);
291 return readDiagMsg(proto, destroy);
294 int SockDiag::destroySockets(const char *addrstr) {
296 mSocketsDestroyed = 0;
298 if (!strchr(addrstr, ':')) {
299 if (int ret = destroySockets(IPPROTO_TCP, AF_INET, addrstr)) {
300 ALOGE("Failed to destroy IPv4 sockets on %s: %s", addrstr, strerror(-ret));
304 if (int ret = destroySockets(IPPROTO_TCP, AF_INET6, addrstr)) {
305 ALOGE("Failed to destroy IPv6 sockets on %s: %s", addrstr, strerror(-ret));
309 if (mSocketsDestroyed > 0) {
310 ALOGI("Destroyed %d sockets on %s in %.1f ms", mSocketsDestroyed, addrstr, s.timeTaken());
313 return mSocketsDestroyed;
316 int SockDiag::destroySockets(uint8_t proto, const uid_t uid) {
317 mSocketsDestroyed = 0;
320 auto destroy = [this, uid] (uint8_t proto, const inet_diag_msg *msg) {
321 if (msg != nullptr && msg->idiag_uid == uid) {
322 return this->sockDestroy(proto, msg);
328 for (const int family : {AF_INET, AF_INET6}) {
329 const char *familyName = family == AF_INET ? "IPv4" : "IPv6";
330 uint32_t states = (1 << TCP_ESTABLISHED) | (1 << TCP_SYN_SENT) | (1 << TCP_SYN_RECV);
331 if (int ret = sendDumpRequest(proto, family, states)) {
332 ALOGE("Failed to dump %s sockets for UID: %s", familyName, strerror(-ret));
335 if (int ret = readDiagMsg(proto, destroy)) {
336 ALOGE("Failed to destroy %s sockets for UID: %s", familyName, strerror(-ret));
341 if (mSocketsDestroyed > 0) {
342 ALOGI("Destroyed %d sockets for UID in %.1f ms", mSocketsDestroyed, s.timeTaken());