Android-x86
Fork
Spenden

  • R/O
  • HTTP
  • SSH
  • HTTPS

system-netd: Commit

system/netd


Commit MetaInfo

Revision17c1f5c5e4cecce8a2647b4b021943cbc5104adf (tree)
Zeit2017-04-05 23:19:24
AutorDan Pasanen <dan.pasanen@gmai...>
CommiterDan Pasanen

Log Message

Android 7.1.2 Release 2 (N2G47E)
-----BEGIN PGP SIGNATURE-----

iEYEABECAAYFAljh7rAACgkQ6K0/gZqxDnjkHACfXjF6dPLMIi5OXGd64VRetNGz
b30AoIzDfB+eXclYhQuJwIX3ASPIVZZs
=fBbp
-----END PGP SIGNATURE-----

Merge tag 'android-7.1.2_r2' into cm-14.1

Android 7.1.2 Release 2 (N2G47E)

Change-Id: Ibe6b430b8fe7afbe371e492ee3c881f341a62e8f

Ändern Zusammenfassung

Diff

--- a/client/FwmarkClient.cpp
+++ b/client/FwmarkClient.cpp
@@ -25,6 +25,8 @@
2525 #include <sys/un.h>
2626 #include <unistd.h>
2727
28+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
29+
2830 namespace {
2931
3032 const sockaddr_un FWMARK_SERVER_PATH = {AF_UNIX, "/dev/socket/fwmarkd"};
@@ -32,7 +34,13 @@ const sockaddr_un FWMARK_SERVER_PATH = {AF_UNIX, "/dev/socket/fwmarkd"};
3234 } // namespace
3335
3436 bool FwmarkClient::shouldSetFwmark(int family) {
35- return (family == AF_INET || family == AF_INET6) && !getenv("ANDROID_NO_USE_FWMARK_CLIENT");
37+ return (family == AF_INET || family == AF_INET6) && !getenv(ANDROID_NO_USE_FWMARK_CLIENT);
38+}
39+
40+bool FwmarkClient::shouldReportConnectComplete(int family) {
41+ // TODO: put getenv(ANDROID_FWMARK_METRICS_ONLY) behind the ro.debuggable system property
42+ // or else an app can evade connect logging just by setting the env variable
43+ return shouldSetFwmark(family) && !getenv(ANDROID_FWMARK_METRICS_ONLY);
3644 }
3745
3846 FwmarkClient::FwmarkClient() : mChannel(-1) {
@@ -44,7 +52,7 @@ FwmarkClient::~FwmarkClient() {
4452 }
4553 }
4654
47-int FwmarkClient::send(FwmarkCommand* data, int fd) {
55+int FwmarkClient::send(FwmarkCommand* data, int fd, FwmarkConnectInfo* connectInfo) {
4856 mChannel = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
4957 if (mChannel == -1) {
5058 return -errno;
@@ -57,14 +65,14 @@ int FwmarkClient::send(FwmarkCommand* data, int fd) {
5765 return 0;
5866 }
5967
60- iovec iov;
61- iov.iov_base = data;
62- iov.iov_len = sizeof(*data);
63-
68+ iovec iov[2] = {
69+ { data, sizeof(*data) },
70+ { connectInfo, (connectInfo ? sizeof(*connectInfo) : 0) },
71+ };
6472 msghdr message;
6573 memset(&message, 0, sizeof(message));
66- message.msg_iov = &iov;
67- message.msg_iovlen = 1;
74+ message.msg_iov = iov;
75+ message.msg_iovlen = ARRAY_SIZE(iov);
6876
6977 union {
7078 cmsghdr cmh;
--- a/client/FwmarkClient.h
+++ b/client/FwmarkClient.h
@@ -20,6 +20,7 @@
2020 #include <sys/socket.h>
2121
2222 struct FwmarkCommand;
23+struct FwmarkConnectInfo;
2324
2425 class FwmarkClient {
2526 public:
@@ -27,12 +28,26 @@ public:
2728 // its SO_MARK set.
2829 static bool shouldSetFwmark(int family);
2930
31+ // Returns true if an additional call should be made after ON_CONNECT calls, to log extra
32+ // information like latency and source IP.
33+ static bool shouldReportConnectComplete(int family);
34+
3035 FwmarkClient();
3136 ~FwmarkClient();
3237
3338 // Sends |data| to the fwmark server, along with |fd| as ancillary data using cmsg(3).
39+ // For ON_CONNECT_COMPLETE |data| command, |connectInfo| should be provided.
3440 // Returns 0 on success or a negative errno value on failure.
35- int send(FwmarkCommand* data, int fd);
41+ int send(FwmarkCommand* data, int fd, FwmarkConnectInfo* connectInfo);
42+
43+ // Env flag to control whether FwmarkClient sends any information at all about network events
44+ // back to the system server through FwmarkServer.
45+ static constexpr const char* ANDROID_NO_USE_FWMARK_CLIENT = "ANDROID_NO_USE_FWMARK_CLIENT";
46+
47+ // Env flag to control whether FwmarkClient should exclude detailed information like IP
48+ // addresses and only send basic information necessary for marking sockets.
49+ // Has no effect if ANDROID_NO_USE_FWMARK_CLIENT is set.
50+ static constexpr const char* ANDROID_FWMARK_METRICS_ONLY = "ANDROID_FWMARK_METRICS_ONLY";
3651
3752 private:
3853 int mChannel;
--- a/client/NetdClient.cpp
+++ b/client/NetdClient.cpp
@@ -16,7 +16,9 @@
1616
1717 #include "NetdClient.h"
1818
19+#include <arpa/inet.h>
1920 #include <errno.h>
21+#include <math.h>
2022 #include <sys/socket.h>
2123 #include <unistd.h>
2224
@@ -26,6 +28,7 @@
2628 #include "FwmarkClient.h"
2729 #include "FwmarkCommand.h"
2830 #include "resolv_netid.h"
31+#include "Stopwatch.h"
2932
3033 namespace {
3134
@@ -65,7 +68,7 @@ int netdClientAccept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags)
6568 }
6669 if (FwmarkClient::shouldSetFwmark(family)) {
6770 FwmarkCommand command = {FwmarkCommand::ON_ACCEPT, 0, 0};
68- if (int error = FwmarkClient().send(&command, acceptedSocket)) {
71+ if (int error = FwmarkClient().send(&command, acceptedSocket, nullptr)) {
6972 return closeFdAndSetErrno(acceptedSocket, error);
7073 }
7174 }
@@ -73,14 +76,32 @@ int netdClientAccept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags)
7376 }
7477
7578 int netdClientConnect(int sockfd, const sockaddr* addr, socklen_t addrlen) {
76- if (sockfd >= 0 && addr && FwmarkClient::shouldSetFwmark(addr->sa_family)) {
79+ const bool shouldSetFwmark = (sockfd >= 0) && addr
80+ && FwmarkClient::shouldSetFwmark(addr->sa_family);
81+ if (shouldSetFwmark) {
7782 FwmarkCommand command = {FwmarkCommand::ON_CONNECT, 0, 0};
78- if (int error = FwmarkClient().send(&command, sockfd)) {
83+ if (int error = FwmarkClient().send(&command, sockfd, nullptr)) {
7984 errno = -error;
8085 return -1;
8186 }
8287 }
83- return libcConnect(sockfd, addr, addrlen);
88+ // Latency measurement does not include time of sending commands to Fwmark
89+ Stopwatch s;
90+ const int ret = libcConnect(sockfd, addr, addrlen);
91+ // Save errno so it isn't clobbered by sending ON_CONNECT_COMPLETE
92+ const int connectErrno = errno;
93+ const unsigned latencyMs = lround(s.timeTaken());
94+ // Send an ON_CONNECT_COMPLETE command that includes sockaddr and connect latency for reporting
95+ if (shouldSetFwmark && FwmarkClient::shouldReportConnectComplete(addr->sa_family)) {
96+ FwmarkConnectInfo connectInfo(ret == 0 ? 0 : connectErrno, latencyMs, addr);
97+ // TODO: get the netId from the socket mark once we have continuous benchmark runs
98+ FwmarkCommand command = {FwmarkCommand::ON_CONNECT_COMPLETE, /* netId (ignored) */ 0,
99+ /* uid (filled in by the server) */ 0};
100+ // Ignore return value since it's only used for logging
101+ FwmarkClient().send(&command, sockfd, &connectInfo);
102+ }
103+ errno = connectErrno;
104+ return ret;
84105 }
85106
86107 int netdClientSocket(int domain, int type, int protocol) {
@@ -185,7 +206,7 @@ extern "C" int setNetworkForSocket(unsigned netId, int socketFd) {
185206 return -EBADF;
186207 }
187208 FwmarkCommand command = {FwmarkCommand::SELECT_NETWORK, netId, 0};
188- return FwmarkClient().send(&command, socketFd);
209+ return FwmarkClient().send(&command, socketFd, nullptr);
189210 }
190211
191212 extern "C" int setNetworkForProcess(unsigned netId) {
@@ -201,7 +222,7 @@ extern "C" int protectFromVpn(int socketFd) {
201222 return -EBADF;
202223 }
203224 FwmarkCommand command = {FwmarkCommand::PROTECT_FROM_VPN, 0, 0};
204- return FwmarkClient().send(&command, socketFd);
225+ return FwmarkClient().send(&command, socketFd, nullptr);
205226 }
206227
207228 extern "C" int setNetworkForUser(uid_t uid, int socketFd) {
@@ -209,10 +230,10 @@ extern "C" int setNetworkForUser(uid_t uid, int socketFd) {
209230 return -EBADF;
210231 }
211232 FwmarkCommand command = {FwmarkCommand::SELECT_FOR_USER, 0, uid};
212- return FwmarkClient().send(&command, socketFd);
233+ return FwmarkClient().send(&command, socketFd, nullptr);
213234 }
214235
215236 extern "C" int queryUserAccess(uid_t uid, unsigned netId) {
216237 FwmarkCommand command = {FwmarkCommand::QUERY_USER_ACCESS, netId, uid};
217- return FwmarkClient().send(&command, -1);
238+ return FwmarkClient().send(&command, -1, nullptr);
218239 }
--- a/include/FwmarkCommand.h
+++ b/include/FwmarkCommand.h
@@ -17,9 +17,40 @@
1717 #ifndef NETD_INCLUDE_FWMARK_COMMAND_H
1818 #define NETD_INCLUDE_FWMARK_COMMAND_H
1919
20+#include <arpa/inet.h>
21+#include <sys/socket.h>
2022 #include <sys/types.h>
2123
24+// Additional information sent with ON_CONNECT_COMPLETE command
25+struct FwmarkConnectInfo {
26+ int error;
27+ unsigned latencyMs;
28+ union {
29+ sockaddr s;
30+ sockaddr_in sin;
31+ sockaddr_in6 sin6;
32+ } addr;
33+
34+ FwmarkConnectInfo() {}
35+
36+ FwmarkConnectInfo(const int connectErrno, const unsigned latency, const sockaddr* saddr) {
37+ error = connectErrno;
38+ latencyMs = latency;
39+ if (saddr->sa_family == AF_INET) {
40+ addr.sin = *((struct sockaddr_in*) saddr);
41+ } else if (saddr->sa_family == AF_INET6) {
42+ addr.sin6 = *((struct sockaddr_in6*) saddr);
43+ } else {
44+ // Cannot happen because we only call this if shouldSetFwmark returns true, and thus
45+ // the address family is one we understand.
46+ addr.s.sa_family = AF_UNSPEC;
47+ }
48+ }
49+};
50+
2251 // Commands sent from clients to the fwmark server to mark sockets (i.e., set their SO_MARK).
52+// ON_CONNECT_COMPLETE command should be accompanied by FwmarkConnectInfo which should contain
53+// info about that connect attempt
2354 struct FwmarkCommand {
2455 enum {
2556 ON_ACCEPT,
@@ -28,6 +59,7 @@ struct FwmarkCommand {
2859 PROTECT_FROM_VPN,
2960 SELECT_FOR_USER,
3061 QUERY_USER_ACCESS,
62+ ON_CONNECT_COMPLETE,
3163 } cmdId;
3264 unsigned netId; // used only in the SELECT_NETWORK command; ignored otherwise.
3365 uid_t uid; // used only in the SELECT_FOR_USER and QUERY_USER_ACCESS commands;
--- /dev/null
+++ b/include/Stopwatch.h
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright (C) 2016 The Android Open Source Project
3+ *
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
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
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.
15+ */
16+
17+#ifndef NETD_INCLUDE_STOPWATCH_H
18+#define NETD_INCLUDE_STOPWATCH_H
19+
20+#include <chrono>
21+
22+class Stopwatch {
23+public:
24+ Stopwatch() : mStart(std::chrono::steady_clock::now()) {}
25+ virtual ~Stopwatch() {};
26+
27+ float timeTaken() const {
28+ using ms = std::chrono::duration<float, std::ratio<1, 1000>>;
29+ return (std::chrono::duration_cast<ms>(
30+ std::chrono::steady_clock::now() - mStart)).count();
31+ }
32+
33+private:
34+ std::chrono::time_point<std::chrono::steady_clock> mStart;
35+};
36+
37+#endif // NETD_INCLUDE_STOPWATCH_H
--- a/server/Android.mk
+++ b/server/Android.mk
@@ -78,6 +78,7 @@ LOCAL_SRC_FILES := \
7878 DnsProxyListener.cpp \
7979 DummyNetwork.cpp \
8080 DumpWriter.cpp \
81+ EventReporter.cpp \
8182 FirewallController.cpp \
8283 FwmarkServer.cpp \
8384 IdletimerController.cpp \
@@ -105,7 +106,7 @@ LOCAL_SRC_FILES := \
105106 VirtualNetwork.cpp \
106107 main.cpp \
107108 oem_iptables_hook.cpp \
108- binder/android/net/metrics/IDnsEventListener.aidl \
109+ binder/android/net/metrics/INetdEventListener.aidl \
109110 QtiDataController.cpp \
110111
111112 LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/binder
--- a/server/Controllers.h
+++ b/server/Controllers.h
@@ -31,6 +31,7 @@
3131 #include "FirewallController.h"
3232 #include "ClatdController.h"
3333 #include "StrictController.h"
34+#include "EventReporter.h"
3435
3536 namespace android {
3637 namespace net {
@@ -49,6 +50,7 @@ struct Controllers {
4950 FirewallController firewallCtrl;
5051 ClatdController clatdCtrl;
5152 StrictController strictCtrl;
53+ EventReporter eventReporter;
5254 };
5355
5456 extern Controllers* gCtls;
--- a/server/DnsProxyListener.cpp
+++ b/server/DnsProxyListener.cpp
@@ -34,9 +34,9 @@
3434 #define VDBG 0
3535
3636 #include <chrono>
37+#include <vector>
3738
3839 #include <cutils/log.h>
39-#include <binder/IServiceManager.h>
4040 #include <utils/String16.h>
4141 #include <sysutils/SocketClient.h>
4242
@@ -45,15 +45,15 @@
4545 #include "NetdConstants.h"
4646 #include "NetworkController.h"
4747 #include "ResponseCode.h"
48-#include "android/net/metrics/IDnsEventListener.h"
48+#include "Stopwatch.h"
49+#include "android/net/metrics/INetdEventListener.h"
4950 #include "QtiDataController.h"
5051
5152 using android::String16;
52-using android::interface_cast;
53-using android::net::metrics::IDnsEventListener;
53+using android::net::metrics::INetdEventListener;
5454
55-DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl) :
56- FrameworkListener("dnsproxyd"), mNetCtrl(netCtrl) {
55+DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl, EventReporter* eventReporter) :
56+ FrameworkListener("dnsproxyd"), mNetCtrl(netCtrl), mEventReporter(eventReporter) {
5757 registerCmd(new GetAddrInfoCmd(this));
5858 registerCmd(new GetHostByAddrCmd(this));
5959 registerCmd(new GetHostByNameCmd(this));
@@ -61,14 +61,15 @@ DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl) :
6161
6262 DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(
6363 SocketClient *c, char* host, char* service, struct addrinfo* hints,
64- const struct android_net_context& netcontext,
65- const android::sp<android::net::metrics::IDnsEventListener>& dnsEventListener)
64+ const struct android_net_context& netcontext, const int reportingLevel,
65+ const android::sp<android::net::metrics::INetdEventListener>& netdEventListener)
6666 : mClient(c),
6767 mHost(host),
6868 mService(service),
6969 mHints(hints),
7070 mNetContext(netcontext),
71- mDnsEventListener(dnsEventListener) {
71+ mReportingLevel(reportingLevel),
72+ mNetdEventListener(netdEventListener) {
7273 }
7374
7475 DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
@@ -92,25 +93,6 @@ void* DnsProxyListener::GetAddrInfoHandler::threadStart(void* obj) {
9293 return NULL;
9394 }
9495
95-android::sp<IDnsEventListener> DnsProxyListener::getDnsEventListener() {
96- if (mDnsEventListener == nullptr) {
97- // Use checkService instead of getService because getService waits for 5 seconds for the
98- // service to become available. The DNS resolver inside netd is started much earlier in the
99- // boot sequence than the framework DNS listener, and we don't want to delay all DNS lookups
100- // for 5 seconds until the DNS listener starts up.
101- android::sp<android::IBinder> b = android::defaultServiceManager()->checkService(
102- android::String16("dns_listener"));
103- if (b != nullptr) {
104- mDnsEventListener = interface_cast<IDnsEventListener>(b);
105- }
106- }
107- // If the DNS listener service is dead, the binder call will just return an error, which should
108- // be fine because the only impact is that we can't log DNS events. In any case, this should
109- // only happen if the system server is going down, which means it will shortly be taking us down
110- // with it.
111- return mDnsEventListener;
112-}
113-
11496 static bool sendBE32(SocketClient* c, uint32_t data) {
11597 uint32_t be_data = htonl(data);
11698 return c->sendData(&be_data, sizeof(be_data)) == 0;
@@ -214,13 +196,56 @@ void DnsProxyListener::GetAddrInfoHandler::run() {
214196 ALOGW("Error writing DNS result to client");
215197 }
216198 }
199+ std::vector<String16> ip_addrs;
200+ int total_ip_addr_count = 0;
217201 if (result) {
202+ if (mNetdEventListener != nullptr
203+ && mReportingLevel == INetdEventListener::REPORTING_LEVEL_FULL) {
204+ for (addrinfo* ai = result; ai; ai = ai->ai_next) {
205+ sockaddr* ai_addr = ai->ai_addr;
206+ if (ai_addr) {
207+ addIpAddrWithinLimit(ip_addrs, ai_addr, ai->ai_addrlen);
208+ total_ip_addr_count++;
209+ }
210+ }
211+ }
218212 freeaddrinfo(result);
219213 }
220214 mClient->decRef();
221- if (mDnsEventListener != nullptr) {
222- mDnsEventListener->onDnsEvent(mNetContext.dns_netid, IDnsEventListener::EVENT_GETADDRINFO,
223- (int32_t) rv, latencyMs);
215+ if (mNetdEventListener != nullptr) {
216+ switch (mReportingLevel) {
217+ case INetdEventListener::REPORTING_LEVEL_NONE:
218+ // Skip reporting.
219+ break;
220+ case INetdEventListener::REPORTING_LEVEL_METRICS:
221+ // Metrics reporting is on. Send metrics.
222+ mNetdEventListener->onDnsEvent(mNetContext.dns_netid,
223+ INetdEventListener::EVENT_GETADDRINFO, (int32_t) rv,
224+ latencyMs, String16(""), {}, -1, -1);
225+ break;
226+ case INetdEventListener::REPORTING_LEVEL_FULL:
227+ // Full event info reporting is on. Send full info.
228+ mNetdEventListener->onDnsEvent(mNetContext.dns_netid,
229+ INetdEventListener::EVENT_GETADDRINFO, (int32_t) rv,
230+ latencyMs, String16(mHost), ip_addrs,
231+ total_ip_addr_count, mNetContext.uid);
232+ break;
233+ }
234+ } else {
235+ ALOGW("Netd event listener is not available; skipping.");
236+ }
237+}
238+
239+void DnsProxyListener::addIpAddrWithinLimit(std::vector<android::String16>& ip_addrs,
240+ const sockaddr* addr, socklen_t addrlen) {
241+ // ipAddresses array is limited to first INetdEventListener::DNS_REPORTED_IP_ADDRESSES_LIMIT
242+ // addresses for A and AAAA. Total count of addresses is provided, to be able to tell whether
243+ // some addresses didn't get logged.
244+ if (ip_addrs.size() < INetdEventListener::DNS_REPORTED_IP_ADDRESSES_LIMIT) {
245+ char ip_addr[INET6_ADDRSTRLEN];
246+ if (getnameinfo(addr, addrlen, ip_addr, sizeof(ip_addr), nullptr, 0, NI_NUMERICHOST) == 0) {
247+ ip_addrs.push_back(String16(ip_addr));
248+ }
224249 }
225250 }
226251
@@ -297,10 +322,12 @@ int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli,
297322 netcontext.uid);
298323 }
299324
325+ const int metricsLevel = mDnsProxyListener->mEventReporter->getMetricsReportingLevel();
326+
300327 cli->incRef();
301328 DnsProxyListener::GetAddrInfoHandler* handler =
302329 new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, netcontext,
303- mDnsProxyListener->getDnsEventListener());
330+ metricsLevel, mDnsProxyListener->mEventReporter->getNetdEventListener());
304331 handler->start();
305332
306333 return 0;
@@ -352,25 +379,27 @@ int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli,
352379 }
353380
354381 uint32_t mark = mDnsProxyListener->mNetCtrl->getNetworkForDns(&netId, uid);
382+ const int metricsLevel = mDnsProxyListener->mEventReporter->getMetricsReportingLevel();
355383
356384 cli->incRef();
357385 DnsProxyListener::GetHostByNameHandler* handler =
358- new DnsProxyListener::GetHostByNameHandler(cli, name, af, netId, mark,
359- mDnsProxyListener->getDnsEventListener());
386+ new DnsProxyListener::GetHostByNameHandler(cli, name, af, netId, mark, metricsLevel,
387+ mDnsProxyListener->mEventReporter->getNetdEventListener());
360388 handler->start();
361389
362390 return 0;
363391 }
364392
365393 DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(
366- SocketClient* c, char* name, int af, unsigned netId, uint32_t mark,
367- const android::sp<android::net::metrics::IDnsEventListener>& dnsEventListener)
394+ SocketClient* c, char* name, int af, unsigned netId, uint32_t mark, const int metricsLevel,
395+ const android::sp<android::net::metrics::INetdEventListener>& netdEventListener)
368396 : mClient(c),
369397 mName(name),
370398 mAf(af),
371399 mNetId(netId),
372400 mMark(mark),
373- mDnsEventListener(dnsEventListener) {
401+ mReportingLevel(metricsLevel),
402+ mNetdEventListener(netdEventListener) {
374403 }
375404
376405 DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() {
@@ -419,12 +448,46 @@ void DnsProxyListener::GetHostByNameHandler::run() {
419448 if (!success) {
420449 ALOGW("GetHostByNameHandler: Error writing DNS result to client\n");
421450 }
422- mClient->decRef();
423451
424- if (mDnsEventListener != nullptr) {
425- mDnsEventListener->onDnsEvent(mNetId, IDnsEventListener::EVENT_GETHOSTBYNAME,
426- h_errno, latencyMs);
452+ if (mNetdEventListener != nullptr) {
453+ std::vector<String16> ip_addrs;
454+ int total_ip_addr_count = 0;
455+ if (mReportingLevel == INetdEventListener::REPORTING_LEVEL_FULL) {
456+ if (hp != nullptr && hp->h_addrtype == AF_INET) {
457+ in_addr** list = (in_addr**) hp->h_addr_list;
458+ for (int i = 0; list[i] != NULL; i++) {
459+ sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = *list[i] };
460+ addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin, sizeof(sin));
461+ total_ip_addr_count++;
462+ }
463+ } else if (hp != nullptr && hp->h_addrtype == AF_INET6) {
464+ in6_addr** list = (in6_addr**) hp->h_addr_list;
465+ for (int i = 0; list[i] != NULL; i++) {
466+ sockaddr_in6 sin6 = { .sin6_family = AF_INET6, .sin6_addr = *list[i] };
467+ addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin6, sizeof(sin6));
468+ total_ip_addr_count++;
469+ }
470+ }
471+ }
472+ switch (mReportingLevel) {
473+ case INetdEventListener::REPORTING_LEVEL_NONE:
474+ // Reporting is off.
475+ break;
476+ case INetdEventListener::REPORTING_LEVEL_METRICS:
477+ // Metrics reporting is on. Send metrics.
478+ mNetdEventListener->onDnsEvent(mNetId, INetdEventListener::EVENT_GETHOSTBYNAME,
479+ h_errno, latencyMs, String16(""), {}, -1, -1);
480+ break;
481+ case INetdEventListener::REPORTING_LEVEL_FULL:
482+ // Full event info reporting is on. Send full info.
483+ mNetdEventListener->onDnsEvent(mNetId, INetdEventListener::EVENT_GETHOSTBYNAME,
484+ h_errno, latencyMs, String16(mName), ip_addrs,
485+ total_ip_addr_count, mClient->getUid());
486+ break;
487+ }
427488 }
489+
490+ mClient->decRef();
428491 }
429492
430493
--- a/server/DnsProxyListener.h
+++ b/server/DnsProxyListener.h
@@ -21,26 +21,22 @@
2121 #include <binder/IServiceManager.h>
2222 #include <sysutils/FrameworkListener.h>
2323
24-#include "android/net/metrics/IDnsEventListener.h"
24+#include "android/net/metrics/INetdEventListener.h"
25+#include "EventReporter.h"
2526 #include "NetdCommand.h"
2627
2728 class NetworkController;
2829
2930 class DnsProxyListener : public FrameworkListener {
3031 public:
31- explicit DnsProxyListener(const NetworkController* netCtrl);
32+ explicit DnsProxyListener(const NetworkController* netCtrl, EventReporter* eventReporter);
3233 virtual ~DnsProxyListener() {}
3334
34- // Returns the binder reference to the DNS listener service, attempting to fetch it if we do not
35- // have it already. This method mutates internal state without taking a lock and must only be
36- // called on one thread. This is safe because we only call this in the runCommand methods of our
37- // commands, which are only called by FrameworkListener::onDataAvailable, which is only called
38- // from SocketListener::runListener, which is a single-threaded select loop.
39- android::sp<android::net::metrics::IDnsEventListener> getDnsEventListener();
40-
4135 private:
4236 const NetworkController *mNetCtrl;
43- android::sp<android::net::metrics::IDnsEventListener> mDnsEventListener;
37+ EventReporter *mEventReporter;
38+ static void addIpAddrWithinLimit(std::vector<android::String16>& ip_addrs, const sockaddr* addr,
39+ socklen_t addrlen);
4440
4541 class GetAddrInfoCmd : public NetdCommand {
4642 public:
@@ -59,7 +55,8 @@ private:
5955 char* service,
6056 struct addrinfo* hints,
6157 const struct android_net_context& netcontext,
62- const android::sp<android::net::metrics::IDnsEventListener>& listener);
58+ const int reportingLevel,
59+ const android::sp<android::net::metrics::INetdEventListener>& listener);
6360 ~GetAddrInfoHandler();
6461
6562 static void* threadStart(void* handler);
@@ -72,7 +69,8 @@ private:
7269 char* mService; // owned
7370 struct addrinfo* mHints; // owned
7471 struct android_net_context mNetContext;
75- android::sp<android::net::metrics::IDnsEventListener> mDnsEventListener;
72+ const int mReportingLevel;
73+ android::sp<android::net::metrics::INetdEventListener> mNetdEventListener;
7674 };
7775
7876 /* ------ gethostbyname ------*/
@@ -92,7 +90,8 @@ private:
9290 int af,
9391 unsigned netId,
9492 uint32_t mark,
95- const android::sp<android::net::metrics::IDnsEventListener>& listener);
93+ int reportingLevel,
94+ const android::sp<android::net::metrics::INetdEventListener>& listener);
9695 ~GetHostByNameHandler();
9796 static void* threadStart(void* handler);
9897 void start();
@@ -103,7 +102,8 @@ private:
103102 int mAf;
104103 unsigned mNetId;
105104 uint32_t mMark;
106- android::sp<android::net::metrics::IDnsEventListener> mDnsEventListener;
105+ const int mReportingLevel;
106+ android::sp<android::net::metrics::INetdEventListener> mNetdEventListener;
107107 };
108108
109109 /* ------ gethostbyaddr ------*/
--- /dev/null
+++ b/server/EventReporter.cpp
@@ -0,0 +1,57 @@
1+/*
2+ * Copyright (C) 2016 The Android Open Source Project
3+ *
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
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
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.
15+ */
16+
17+#define LOG_TAG "Netd"
18+
19+#include "EventReporter.h"
20+#include "log/log.h"
21+
22+using android::interface_cast;
23+using android::net::metrics::INetdEventListener;
24+
25+int EventReporter::setMetricsReportingLevel(const int level) {
26+ if (level < INetdEventListener::REPORTING_LEVEL_NONE
27+ || level > INetdEventListener::REPORTING_LEVEL_FULL) {
28+ ALOGE("Invalid metrics reporting level %d", level);
29+ return -EINVAL;
30+ }
31+ mReportingLevel = level;
32+ return 0;
33+}
34+
35+int EventReporter::getMetricsReportingLevel() const {
36+ return mReportingLevel;
37+}
38+
39+android::sp<INetdEventListener> EventReporter::getNetdEventListener() {
40+ std::lock_guard<std::mutex> lock(mutex);
41+ if (mNetdEventListener == nullptr) {
42+ // Use checkService instead of getService because getService waits for 5 seconds for the
43+ // service to become available. The DNS resolver inside netd is started much earlier in the
44+ // boot sequence than the framework DNS listener, and we don't want to delay all DNS lookups
45+ // for 5 seconds until the DNS listener starts up.
46+ android::sp<android::IBinder> b = android::defaultServiceManager()->checkService(
47+ android::String16("netd_listener"));
48+ if (b != nullptr) {
49+ mNetdEventListener = interface_cast<INetdEventListener>(b);
50+ }
51+ }
52+ // If the netd listener service is dead, the binder call will just return an error, which should
53+ // be fine because the only impact is that we can't log netd events. In any case, this should
54+ // only happen if the system server is going down, which means it will shortly be taking us down
55+ // with it.
56+ return mNetdEventListener;
57+}
--- /dev/null
+++ b/server/EventReporter.h
@@ -0,0 +1,52 @@
1+/*
2+ * Copyright (C) 2016 The Android Open Source Project
3+ *
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
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
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.
15+ */
16+
17+#ifndef NETD_SERVER_EVENT_REPORTER_H
18+#define NETD_SERVER_EVENT_REPORTER_H
19+
20+#include <atomic>
21+#include <binder/IServiceManager.h>
22+#include <mutex>
23+
24+#include "android/net/metrics/INetdEventListener.h"
25+
26+/*
27+ * This class stores the reporting level and can be used to get the event listener service.
28+ */
29+class EventReporter {
30+public:
31+ int setMetricsReportingLevel(const int level);
32+ int getMetricsReportingLevel() const;
33+
34+ // Returns the binder reference to the netd events listener service, attempting to fetch it if
35+ // we do not have it already. This method is threadsafe.
36+ android::sp<android::net::metrics::INetdEventListener> getNetdEventListener();
37+
38+private:
39+ std::atomic_int mReportingLevel{
40+ android::net::metrics::INetdEventListener::REPORTING_LEVEL_FULL};
41+ // TODO: consider changing this into an atomic type such as
42+ // std::atomic<android::net::metrics::INetdEventListener> and deleting the mutex.
43+ //
44+ // Alternatively, if this locking causes a performance penalty, have each single-threaded
45+ // caller (DnsProxyListener, FwmarkServer) keep their own per-thread copy of NetdEventListener
46+ // and remove mNetdEventListener entirely.
47+ android::sp<android::net::metrics::INetdEventListener> mNetdEventListener;
48+ std::mutex mutex;
49+
50+};
51+
52+#endif // NETD_SERVER_EVENT_REPORTER_H
--- a/server/FwmarkServer.cpp
+++ b/server/FwmarkServer.cpp
@@ -18,14 +18,21 @@
1818
1919 #include "Fwmark.h"
2020 #include "FwmarkCommand.h"
21+#include "NetdConstants.h"
2122 #include "NetworkController.h"
2223 #include "resolv_netid.h"
2324
25+#include <netinet/in.h>
2426 #include <sys/socket.h>
2527 #include <unistd.h>
28+#include <utils/String16.h>
2629
27-FwmarkServer::FwmarkServer(NetworkController* networkController) :
28- SocketListener("fwmarkd", true), mNetworkController(networkController) {
30+using android::String16;
31+using android::net::metrics::INetdEventListener;
32+
33+FwmarkServer::FwmarkServer(NetworkController* networkController, EventReporter* eventReporter) :
34+ SocketListener("fwmarkd", true), mNetworkController(networkController),
35+ mEventReporter(eventReporter) {
2936 }
3037
3138 bool FwmarkServer::onDataAvailable(SocketClient* client) {
@@ -47,15 +54,16 @@ bool FwmarkServer::onDataAvailable(SocketClient* client) {
4754
4855 int FwmarkServer::processClient(SocketClient* client, int* socketFd) {
4956 FwmarkCommand command;
57+ FwmarkConnectInfo connectInfo;
5058
51- iovec iov;
52- iov.iov_base = &command;
53- iov.iov_len = sizeof(command);
54-
59+ iovec iov[2] = {
60+ { &command, sizeof(command) },
61+ { &connectInfo, sizeof(connectInfo) },
62+ };
5563 msghdr message;
5664 memset(&message, 0, sizeof(message));
57- message.msg_iov = &iov;
58- message.msg_iovlen = 1;
65+ message.msg_iov = iov;
66+ message.msg_iovlen = ARRAY_SIZE(iov);
5967
6068 union {
6169 cmsghdr cmh;
@@ -71,7 +79,9 @@ int FwmarkServer::processClient(SocketClient* client, int* socketFd) {
7179 return -errno;
7280 }
7381
74- if (messageLength != sizeof(command)) {
82+ if (!((command.cmdId != FwmarkCommand::ON_CONNECT_COMPLETE && messageLength == sizeof(command))
83+ || (command.cmdId == FwmarkCommand::ON_CONNECT_COMPLETE
84+ && messageLength == sizeof(command) + sizeof(connectInfo)))) {
7585 return -EBADMSG;
7686 }
7787
@@ -152,6 +162,37 @@ int FwmarkServer::processClient(SocketClient* client, int* socketFd) {
152162 break;
153163 }
154164
165+ case FwmarkCommand::ON_CONNECT_COMPLETE: {
166+ // Called after a socket connect() completes.
167+ // This reports connect event including netId, destination IP address, destination port,
168+ // uid, connect latency, and connect errno if any.
169+
170+ // Skip reporting if connect() happened on a UDP socket.
171+ int socketProto;
172+ socklen_t intSize = sizeof(socketProto);
173+ const int ret = getsockopt(*socketFd, SOL_SOCKET, SO_PROTOCOL, &socketProto, &intSize);
174+ if ((ret != 0) || (socketProto == IPPROTO_UDP)) {
175+ break;
176+ }
177+
178+ android::sp<android::net::metrics::INetdEventListener> netdEventListener =
179+ mEventReporter->getNetdEventListener();
180+
181+ if (netdEventListener != nullptr) {
182+ char addrstr[INET6_ADDRSTRLEN];
183+ char portstr[sizeof("65536")];
184+ const int ret = getnameinfo((sockaddr*) &connectInfo.addr, sizeof(connectInfo.addr),
185+ addrstr, sizeof(addrstr), portstr, sizeof(portstr),
186+ NI_NUMERICHOST | NI_NUMERICSERV);
187+
188+ netdEventListener->onConnectEvent(fwmark.netId, connectInfo.error,
189+ connectInfo.latencyMs,
190+ (ret == 0) ? String16(addrstr) : String16(""),
191+ (ret == 0) ? strtoul(portstr, NULL, 10) : 0, client->getUid());
192+ }
193+ break;
194+ }
195+
155196 case FwmarkCommand::SELECT_NETWORK: {
156197 fwmark.netId = command.netId;
157198 if (command.netId == NETID_UNSET) {
--- a/server/FwmarkServer.h
+++ b/server/FwmarkServer.h
@@ -17,13 +17,15 @@
1717 #ifndef NETD_SERVER_FWMARK_SERVER_H
1818 #define NETD_SERVER_FWMARK_SERVER_H
1919
20+#include "android/net/metrics/INetdEventListener.h"
21+#include "EventReporter.h"
2022 #include "sysutils/SocketListener.h"
2123
2224 class NetworkController;
2325
2426 class FwmarkServer : public SocketListener {
2527 public:
26- explicit FwmarkServer(NetworkController* networkController);
28+ explicit FwmarkServer(NetworkController* networkController, EventReporter* eventReporter);
2729
2830 private:
2931 // Overridden from SocketListener:
@@ -33,6 +35,7 @@ private:
3335 int processClient(SocketClient* client, int* socketFd);
3436
3537 NetworkController* const mNetworkController;
38+ EventReporter* mEventReporter;
3639 };
3740
3841 #endif // NETD_SERVER_FWMARK_SERVER_H
--- a/server/NetdConstants.h
+++ b/server/NetdConstants.h
@@ -60,21 +60,6 @@ int parsePrefix(const char *prefix, uint8_t *family, void *address, int size, ui
6060
6161 const uid_t INVALID_UID = static_cast<uid_t>(-1);
6262
63-class Stopwatch {
64-public:
65- Stopwatch() : mStart(std::chrono::steady_clock::now()) {}
66- virtual ~Stopwatch() {};
67-
68- float timeTaken() const {
69- using ms = std::chrono::duration<float, std::ratio<1, 1000>>;
70- return (std::chrono::duration_cast<ms>(
71- std::chrono::steady_clock::now() - mStart)).count();
72- }
73-
74-private:
75- std::chrono::time_point<std::chrono::steady_clock> mStart;
76-};
77-
7863
7964 struct AddrinfoDeleter {
8065 void operator()(struct addrinfo* p) const {
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -20,6 +20,7 @@
2020
2121 #include <android-base/stringprintf.h>
2222 #include <cutils/log.h>
23+#include <cutils/properties.h>
2324 #include <utils/Errors.h>
2425 #include <utils/String16.h>
2526
@@ -29,6 +30,7 @@
2930
3031 #include "Controllers.h"
3132 #include "DumpWriter.h"
33+#include "EventReporter.h"
3234 #include "InterfaceController.h"
3335 #include "NetdConstants.h"
3436 #include "NetdNativeService.h"
@@ -58,6 +60,17 @@ binder::Status checkPermission(const char *permission) {
5860 }
5961 }
6062
63+#define ENFORCE_DEBUGGABLE() { \
64+ char value[PROPERTY_VALUE_MAX + 1]; \
65+ if (property_get("ro.debuggable", value, NULL) != 1 \
66+ || value[0] != '1') { \
67+ return binder::Status::fromExceptionCode( \
68+ binder::Status::EX_SECURITY, \
69+ String8("Not available in production builds.") \
70+ ); \
71+ } \
72+}
73+
6174 #define ENFORCE_PERMISSION(permission) { \
6275 binder::Status status = checkPermission((permission)); \
6376 if (!status.isOk()) { \
@@ -275,5 +288,26 @@ binder::Status NetdNativeService::setProcSysNet(
275288 return binder::Status::ok();
276289 }
277290
291+binder::Status NetdNativeService::getMetricsReportingLevel(int *reportingLevel) {
292+ // This function intentionally does not lock, since the only thing it does is one read from an
293+ // atomic_int.
294+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
295+ ENFORCE_DEBUGGABLE();
296+
297+ *reportingLevel = gCtls->eventReporter.getMetricsReportingLevel();
298+ return binder::Status::ok();
299+}
300+
301+binder::Status NetdNativeService::setMetricsReportingLevel(const int reportingLevel) {
302+ // This function intentionally does not lock, since the only thing it does is one write to an
303+ // atomic_int.
304+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
305+ ENFORCE_DEBUGGABLE();
306+
307+ return (gCtls->eventReporter.setMetricsReportingLevel(reportingLevel) == 0)
308+ ? binder::Status::ok()
309+ : binder::Status::fromExceptionCode(binder::Status::EX_ILLEGAL_ARGUMENT);
310+}
311+
278312 } // namespace net
279313 } // namespace android
--- a/server/NetdNativeService.h
+++ b/server/NetdNativeService.h
@@ -59,6 +59,10 @@ class NetdNativeService : public BinderService<NetdNativeService>, public BnNetd
5959 binder::Status setProcSysNet(
6060 int32_t family, int32_t which, const std::string &ifname, const std::string &parameter,
6161 const std::string &value) override;
62+
63+ // Metrics reporting level set / get (internal use only).
64+ binder::Status getMetricsReportingLevel(int *reportingLevel) override;
65+ binder::Status setMetricsReportingLevel(const int reportingLevel) override;
6266 };
6367
6468 } // namespace net
--- a/server/NetworkController.h
+++ b/server/NetworkController.h
@@ -113,6 +113,7 @@ private:
113113 std::map<unsigned, Network*> mNetworks; // Map keys are NetIds.
114114 std::map<uid_t, Permission> mUsers;
115115 std::set<uid_t> mProtectableUsers;
116+
116117 };
117118
118119 #endif // NETD_SERVER_NETWORK_CONTROLLER_H
--- a/server/SockDiag.cpp
+++ b/server/SockDiag.cpp
@@ -35,6 +35,7 @@
3535 #include "NetdConstants.h"
3636 #include "Permission.h"
3737 #include "SockDiag.h"
38+#include "Stopwatch.h"
3839
3940 #include <chrono>
4041
--- a/server/SockDiag.h
+++ b/server/SockDiag.h
@@ -14,6 +14,9 @@
1414 * limitations under the License.
1515 */
1616
17+#ifndef _SOCK_DIAG_H
18+#define _SOCK_DIAG_H
19+
1720 #include <unistd.h>
1821 #include <sys/socket.h>
1922
@@ -76,3 +79,5 @@ class SockDiag {
7679 void closeSocks() { close(mSock); close(mWriteSock); mSock = mWriteSock = -1; }
7780 static bool isLoopbackSocket(const inet_diag_msg *msg);
7881 };
82+
83+#endif // _SOCK_DIAG_H
--- a/server/binder/android/net/INetd.aidl
+++ b/server/binder/android/net/INetd.aidl
@@ -171,7 +171,7 @@ interface INetd {
171171 void interfaceDelAddress(in @utf8InCpp String ifName, in @utf8InCpp String addrString,
172172 int prefixLength);
173173
174- /*
174+ /**
175175 * Set and get /proc/sys/net interface configuration parameters.
176176 *
177177 * @param family One of IPV4/IPV6 integers, indicating the desired address family directory.
@@ -188,4 +188,15 @@ interface INetd {
188188 void setProcSysNet(int family, int which, in @utf8InCpp String ifname,
189189 in @utf8InCpp String parameter, in @utf8InCpp String value);
190190 // TODO: add corresponding getProcSysNet().
191+
192+ /**
193+ * Get/Set metrics reporting level.
194+ *
195+ * Reporting level is one of:
196+ * 0 (NONE)
197+ * 1 (METRICS)
198+ * 2 (FULL)
199+ */
200+ int getMetricsReportingLevel();
201+ void setMetricsReportingLevel(int level);
191202 }
--- a/server/binder/android/net/UidRange.cpp
+++ b/server/binder/android/net/UidRange.cpp
@@ -76,7 +76,7 @@ void UidRange::setStart(int32_t uid) {
7676
7777 void UidRange::setStop(int32_t uid) {
7878 if (mStart != -1) {
79- ALOG_ASSERT(uid <= mStop, "stop UID must be greater than or equal to start UID");
79+ ALOG_ASSERT(mStart <= uid, "stop UID must be greater than or equal to start UID");
8080 }
8181 mStop = uid;
8282 }
--- /dev/null
+++ b/server/binder/android/net/metrics/INetdEventListener.aidl
@@ -0,0 +1,63 @@
1+/**
2+ * Copyright (c) 2016, The Android Open Source Project
3+ *
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
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
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.
15+ */
16+
17+package android.net.metrics;
18+
19+/**
20+ * Logs netd events.
21+ *
22+ * {@hide}
23+ */
24+oneway interface INetdEventListener {
25+ const int EVENT_GETADDRINFO = 1;
26+ const int EVENT_GETHOSTBYNAME = 2;
27+
28+ const int REPORTING_LEVEL_NONE = 0;
29+ const int REPORTING_LEVEL_METRICS = 1;
30+ const int REPORTING_LEVEL_FULL = 2;
31+
32+ // Maximum number of IP addresses logged for DNS lookups before we truncate the full list.
33+ const int DNS_REPORTED_IP_ADDRESSES_LIMIT = 10;
34+
35+ /**
36+ * Logs a DNS lookup function call (getaddrinfo and gethostbyname).
37+ *
38+ * @param netId the ID of the network the lookup was performed on.
39+ * @param eventType one of the EVENT_* constants in this interface.
40+ * @param returnCode the return value of the function call.
41+ * @param latencyMs the latency of the function call.
42+ * @param hostname the name that was looked up.
43+ * @param ipAddresses (possibly a subset of) the IP addresses returned.
44+ * At most {@link #DNS_REPORTED_IP_ADDRESSES_LIMIT} addresses are logged.
45+ * @param ipAddressesCount the number of IP addresses returned. May be different from the length
46+ * of ipAddresses if there were too many addresses to log.
47+ * @param uid the UID of the application that performed the query.
48+ */
49+ void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs, String hostname,
50+ in String[] ipAddresses, int ipAddressesCount, int uid);
51+
52+ /**
53+ * Logs a single connect library call.
54+ *
55+ * @param netId the ID of the network the connect was performed on.
56+ * @param error 0 if the connect call succeeded, otherwise errno if it failed.
57+ * @param latencyMs the latency of the connect call.
58+ * @param ipAddr destination IP address.
59+ * @param port destination port number.
60+ * @param uid the UID of the application that performed the connection.
61+ */
62+ void onConnectEvent(int netId, int error, int latencyMs, String ipAddr, int port, int uid);
63+}
--- a/server/main.cpp
+++ b/server/main.cpp
@@ -87,7 +87,7 @@ int main() {
8787 // Set local DNS mode, to prevent bionic from proxying
8888 // back to this service, recursively.
8989 setenv("ANDROID_DNS_MODE", "local", 1);
90- DnsProxyListener dpl(&gCtls->netCtrl);
90+ DnsProxyListener dpl(&gCtls->netCtrl, &gCtls->eventReporter);
9191 if (dpl.startListener()) {
9292 ALOGE("Unable to start DnsProxyListener (%s)", strerror(errno));
9393 exit(1);
@@ -99,7 +99,7 @@ int main() {
9999 exit(1);
100100 }
101101
102- FwmarkServer fwmarkServer(&gCtls->netCtrl);
102+ FwmarkServer fwmarkServer(&gCtls->netCtrl, &gCtls->eventReporter);
103103 if (fwmarkServer.startListener()) {
104104 ALOGE("Unable to start FwmarkServer (%s)", strerror(errno));
105105 exit(1);
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -22,18 +22,22 @@ LOCAL_CFLAGS := -Wall -Werror -Wunused-parameter
2222 EXTRA_LDLIBS := -lpthread
2323 LOCAL_SHARED_LIBRARIES += libbase libbinder libcutils liblog liblogwrap libnetdaidl libnetd_client \
2424 libnetutils libutils
25-LOCAL_STATIC_LIBRARIES += libtestUtil
25+LOCAL_STATIC_LIBRARIES += libtestUtil libnetd_test_dnsresponder
2626 LOCAL_AIDL_INCLUDES := system/netd/server/binder
2727 LOCAL_C_INCLUDES += system/netd/include system/extras/tests/include system/netd/binder/include \
2828 system/netd/server system/core/logwrapper/include \
29+ system/netd/tests/dns_responder \
2930 system/core/libnetutils/include \
3031 system/extras/tests/include bionic/libc/dns/include
3132 # netd_integration_test.cpp is currently empty and exists only so that we can do:
3233 # runtest -x system/netd/tests/netd_integration_test.cpp
3334 LOCAL_SRC_FILES := binder_test.cpp \
34- dns_responder.cpp \
35+ dns_responder/dns_responder.cpp \
3536 netd_integration_test.cpp \
3637 netd_test.cpp \
37- ../server/NetdConstants.cpp
38+ ../server/NetdConstants.cpp \
39+ ../server/binder/android/net/metrics/INetdEventListener.aidl
3840 LOCAL_MODULE_TAGS := eng tests
3941 include $(BUILD_NATIVE_TEST)
42+
43+include $(call all-makefiles-under, $(LOCAL_PATH))
--- /dev/null
+++ b/tests/benchmarks/Android.mk
@@ -0,0 +1,54 @@
1+#
2+# Copyright (C) 2016 The Android Open Source Project
3+#
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
7+#
8+# http://www.apache.org/licenses/LICENSE-2.0
9+#
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.
15+#
16+#
17+# Note: netd benchmark can't build on nyc-mr2-dev, because google-benchmark project is out of date
18+# and won't be backported, and thus the content of this file is commented out to disable it.
19+# In order to run netd benchmark locally you can uncomment the content of this file and follow
20+# instructions in ag/1673408 (checkout that commit and build external/google-benchmark and
21+# system/netd locally and then run the benchmark locally)
22+#
23+#
24+#LOCAL_PATH := $(call my-dir)
25+#
26+## APCT build target for metrics tests
27+#include $(CLEAR_VARS)
28+#LOCAL_MODULE := netd_benchmark
29+#LOCAL_CFLAGS := -Wall -Werror -Wunused-parameter
30+## Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
31+#LOCAL_CFLAGS += -Wno-varargs
32+
33+#EXTRA_LDLIBS := -lpthread
34+#LOCAL_SHARED_LIBRARIES += libbase libbinder liblog libnetd_client
35+#LOCAL_STATIC_LIBRARIES += libnetd_test_dnsresponder libtestUtil libutils
36+
37+#LOCAL_AIDL_INCLUDES := system/netd/server/binder
38+#LOCAL_C_INCLUDES += system/netd/include \
39+# system/extras/tests/include \
40+# system/netd/client \
41+# system/netd/server \
42+# system/netd/server/binder \
43+# system/netd/tests/dns_responder \
44+# system/extras/tests/include \
45+# bionic/libc/dns/include
46+
47+#LOCAL_SRC_FILES := main.cpp \
48+# connect_benchmark.cpp \
49+# dns_benchmark.cpp \
50+# ../../server/binder/android/net/metrics/INetdEventListener.aidl
51+
52+#LOCAL_MODULE_TAGS := eng tests
53+
54+#include $(BUILD_NATIVE_BENCHMARK)
--- /dev/null
+++ b/tests/benchmarks/connect_benchmark.cpp
@@ -0,0 +1,287 @@
1+/*
2+ * Copyright (C) 2016 The Android Open Source Project
3+ *
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
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
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.
15+ */
16+
17+#define LOG_TAG "connect_benchmark"
18+
19+#include <arpa/inet.h>
20+#include <cutils/sockets.h>
21+#include <errno.h>
22+#include <netinet/in.h>
23+#include <time.h>
24+
25+#include <map>
26+#include <functional>
27+#include <thread>
28+
29+#include <android-base/stringprintf.h>
30+#include <benchmark/benchmark.h>
31+#include <log/log.h>
32+#include <utils/StrongPointer.h>
33+
34+#include "FwmarkClient.h"
35+#include "SockDiag.h"
36+#include "Stopwatch.h"
37+#include "android/net/metrics/INetdEventListener.h"
38+
39+using android::base::StringPrintf;
40+using android::net::metrics::INetdEventListener;
41+
42+static int bindAndListen(int s) {
43+ sockaddr_in6 sin6 = { .sin6_family = AF_INET6 };
44+ if (bind(s, (sockaddr*) &sin6, sizeof(sin6)) == 0) {
45+ if (listen(s, 1)) {
46+ return -1;
47+ }
48+ sockaddr_in sin = {};
49+ socklen_t len = sizeof(sin);
50+ if (getsockname(s, (sockaddr*) &sin, &len)) {
51+ return -1;
52+ }
53+ return ntohs(sin.sin_port);
54+ } else {
55+ return -1;
56+ }
57+}
58+
59+static void ipv4_loopback(benchmark::State& state, const bool waitBetweenRuns) {
60+ const int listensocket = socket(AF_INET6, SOCK_STREAM, 0);
61+ const int port = bindAndListen(listensocket);
62+ if (port == -1) {
63+ state.SkipWithError("Unable to bind server socket");
64+ return;
65+ }
66+
67+ // ALOGW("Listening on port = %d", port);
68+ std::vector<uint64_t> latencies(state.max_iterations);
69+ uint64_t iterations = 0;
70+
71+ while (state.KeepRunning()) {
72+ int sock = socket(AF_INET, SOCK_STREAM, 0);
73+ if (sock < 0) {
74+ state.SkipWithError(StringPrintf("socket() failed with errno=%d", errno).c_str());
75+ break;
76+ }
77+
78+ const Stopwatch stopwatch;
79+
80+ sockaddr_in server = { .sin_family = AF_INET, .sin_port = htons(port) };
81+ if (connect(sock, (sockaddr*) &server, sizeof(server))) {
82+ state.SkipWithError(StringPrintf("connect() failed with errno=%d", errno).c_str());
83+ close(sock);
84+ break;
85+ }
86+
87+ if (waitBetweenRuns) {
88+ latencies[iterations] = stopwatch.timeTaken() * 1e6L;
89+ state.SetIterationTime(latencies[iterations] / 1e9L);
90+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
91+ ++iterations;
92+ }
93+
94+ sockaddr_in6 client;
95+ socklen_t clientlen = sizeof(client);
96+ int accepted = accept(listensocket, (sockaddr *) &client, &clientlen);
97+ if (accepted < 0) {
98+ state.SkipWithError(StringPrintf("accept() failed with errno=%d", errno).c_str());
99+ close(sock);
100+ break;
101+ }
102+
103+ close(accepted);
104+ close(sock);
105+ }
106+ close(listensocket);
107+ // ALOGI("Finished test on port = %d", port);
108+
109+ if (iterations > 0) {
110+ latencies.resize(iterations);
111+ sort(latencies.begin(), latencies.end());
112+ state.SetLabel(StringPrintf("%lld", (long long) latencies[iterations * 9 / 10]));
113+ }
114+}
115+
116+static void ipv6_loopback(benchmark::State& state, const bool waitBetweenRuns) {
117+ const int listensocket = socket(AF_INET6, SOCK_STREAM, 0);
118+ const int port = bindAndListen(listensocket);
119+ if (port == -1) {
120+ state.SkipWithError("Unable to bind server socket");
121+ return;
122+ }
123+
124+ // ALOGW("Listening on port = %d", port);
125+ std::vector<uint64_t> latencies(state.max_iterations);
126+ uint64_t iterations = 0;
127+
128+ while (state.KeepRunning()) {
129+ int sock = socket(AF_INET6, SOCK_STREAM, 0);
130+ if (sock < 0) {
131+ state.SkipWithError(StringPrintf("socket() failed with errno=%d", errno).c_str());
132+ break;
133+ }
134+
135+ const Stopwatch stopwatch;
136+
137+ sockaddr_in6 server = { .sin6_family = AF_INET6, .sin6_port = htons(port) };
138+ if (connect(sock, (sockaddr*) &server, sizeof(server))) {
139+ state.SkipWithError(StringPrintf("connect() failed with errno=%d", errno).c_str());
140+ close(sock);
141+ break;
142+ }
143+
144+ if (waitBetweenRuns) {
145+ latencies[iterations] = stopwatch.timeTaken() * 1e6L;
146+ state.SetIterationTime(latencies[iterations] / 1e9L);
147+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
148+ ++iterations;
149+ }
150+
151+ sockaddr_in6 client;
152+ socklen_t clientlen = sizeof(client);
153+ int accepted = accept(listensocket, (sockaddr *) &client, &clientlen);
154+ if (accepted < 0) {
155+ state.SkipWithError(StringPrintf("accept() failed with errno=%d", errno).c_str());
156+ close(sock);
157+ break;
158+ }
159+
160+ close(accepted);
161+ close(sock);
162+ }
163+ close(listensocket);
164+ // ALOGI("Finished test on port = %d", port);
165+
166+ if (iterations > 0) {
167+ latencies.resize(iterations);
168+ sort(latencies.begin(), latencies.end());
169+ state.SetLabel(StringPrintf("%lld", (long long) latencies[iterations * 9 / 10]));
170+ }
171+}
172+
173+static void run_at_reporting_level(decltype(ipv4_loopback) benchmarkFunction,
174+ ::benchmark::State& state, const int reportingLevel,
175+ const bool waitBetweenRuns) {
176+ // Our master thread (thread_index == 0) will control setup and teardown for other threads.
177+ const bool isMaster = (state.thread_index == 0);
178+
179+ // Previous values of env variables used by fwmarkclient (only read/written by master thread)
180+ const std::string savedSettings[] = {
181+ FwmarkClient::ANDROID_NO_USE_FWMARK_CLIENT,
182+ FwmarkClient::ANDROID_FWMARK_METRICS_ONLY
183+ };
184+ std::map<std::string, std::string> prevSettings;
185+
186+ // SETUP
187+ if (isMaster) {
188+ for (const auto setting : savedSettings) {
189+ const char* prevEnvStr = getenv(setting.c_str());
190+ if (prevEnvStr != nullptr) {
191+ prevSettings[setting.c_str()] = prevEnvStr;
192+ }
193+ }
194+ switch (reportingLevel) {
195+ case INetdEventListener::REPORTING_LEVEL_NONE:
196+ setenv(FwmarkClient::ANDROID_NO_USE_FWMARK_CLIENT, "", 1);
197+ break;
198+ case INetdEventListener::REPORTING_LEVEL_METRICS:
199+ unsetenv(FwmarkClient::ANDROID_NO_USE_FWMARK_CLIENT);
200+ setenv(FwmarkClient::ANDROID_FWMARK_METRICS_ONLY, "", 1);
201+ break;
202+ case INetdEventListener::REPORTING_LEVEL_FULL:
203+ unsetenv(FwmarkClient::ANDROID_NO_USE_FWMARK_CLIENT);
204+ unsetenv(FwmarkClient::ANDROID_FWMARK_METRICS_ONLY);
205+ break;
206+ }
207+ }
208+
209+ // TEST
210+ benchmarkFunction(state, waitBetweenRuns);
211+
212+ // TEARDOWN
213+ if (isMaster) {
214+ for (const auto setting : savedSettings) {
215+ if (prevSettings.count(setting)) {
216+ setenv(setting.c_str(), prevSettings[setting].c_str(), 1);
217+ } else {
218+ unsetenv(setting.c_str());
219+ }
220+ }
221+ }
222+}
223+
224+constexpr int MIN_THREADS = 1;
225+constexpr int MAX_THREADS = 1;
226+constexpr double MIN_TIME = 0.5 /* seconds */;
227+
228+static void ipv4_metrics_reporting_no_fwmark(::benchmark::State& state) {
229+ run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_NONE, true);
230+}
231+BENCHMARK(ipv4_metrics_reporting_no_fwmark)->MinTime(MIN_TIME)->UseManualTime();
232+
233+// IPv4 metrics under low load
234+static void ipv4_metrics_reporting_no_load(::benchmark::State& state) {
235+ run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_METRICS, true);
236+}
237+BENCHMARK(ipv4_metrics_reporting_no_load)->MinTime(MIN_TIME)->UseManualTime();
238+
239+static void ipv4_full_reporting_no_load(::benchmark::State& state) {
240+ run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_FULL, true);
241+}
242+BENCHMARK(ipv4_full_reporting_no_load)->MinTime(MIN_TIME)->UseManualTime();
243+
244+// IPv4 benchmarks under high load
245+static void ipv4_metrics_reporting_high_load(::benchmark::State& state) {
246+ run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_METRICS,
247+ false);
248+}
249+BENCHMARK(ipv4_metrics_reporting_high_load)
250+ ->ThreadRange(MIN_THREADS, MAX_THREADS)->MinTime(MIN_TIME)->UseRealTime();
251+
252+static void ipv4_full_reporting_high_load(::benchmark::State& state) {
253+ run_at_reporting_level(ipv4_loopback, state, INetdEventListener::REPORTING_LEVEL_FULL, false);
254+}
255+BENCHMARK(ipv4_full_reporting_high_load)
256+ ->ThreadRange(MIN_THREADS, MAX_THREADS)->MinTime(MIN_TIME)->UseRealTime();
257+
258+// IPv6 raw connect() without using fwmark
259+static void ipv6_metrics_reporting_no_fwmark(::benchmark::State& state) {
260+ run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_NONE, true);
261+}
262+BENCHMARK(ipv6_metrics_reporting_no_fwmark)->MinTime(MIN_TIME)->UseManualTime();
263+
264+// IPv6 metrics under low load
265+static void ipv6_metrics_reporting_no_load(::benchmark::State& state) {
266+ run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_METRICS, true);
267+}
268+BENCHMARK(ipv6_metrics_reporting_no_load)->MinTime(MIN_TIME)->UseManualTime();
269+
270+static void ipv6_full_reporting_no_load(::benchmark::State& state) {
271+ run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_FULL, true);
272+}
273+BENCHMARK(ipv6_full_reporting_no_load)->MinTime(MIN_TIME)->UseManualTime();
274+
275+// IPv6 benchmarks under high load
276+static void ipv6_metrics_reporting_high_load(::benchmark::State& state) {
277+ run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_METRICS,
278+ false);
279+}
280+BENCHMARK(ipv6_metrics_reporting_high_load)
281+ ->ThreadRange(MIN_THREADS, MAX_THREADS)->MinTime(MIN_TIME)->UseRealTime();
282+
283+static void ipv6_full_reporting_high_load(::benchmark::State& state) {
284+ run_at_reporting_level(ipv6_loopback, state, INetdEventListener::REPORTING_LEVEL_FULL, false);
285+}
286+BENCHMARK(ipv6_full_reporting_high_load)
287+ ->ThreadRange(MIN_THREADS, MAX_THREADS)->MinTime(MIN_TIME)->UseRealTime();
--- /dev/null
+++ b/tests/benchmarks/dns_benchmark.cpp
@@ -0,0 +1,151 @@
1+/*
2+ * Copyright (C) 2016 The Android Open Source Project
3+ *
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
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
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.
15+ */
16+
17+#define LOG_TAG "dns_benchmark"
18+
19+#include <netdb.h>
20+#include <netinet/in.h>
21+#include <sys/types.h>
22+#include <sys/socket.h>
23+
24+#include <android-base/stringprintf.h>
25+#include <benchmark/benchmark.h>
26+#include <utils/String16.h>
27+#include <utils/StrongPointer.h>
28+
29+#include "dns_responder_client.h"
30+#include "NetdClient.h"
31+#include "android/net/metrics/INetdEventListener.h"
32+
33+using android::base::StringPrintf;
34+using android::net::metrics::INetdEventListener;
35+
36+constexpr int MIN_THREADS = 1;
37+constexpr int MAX_THREADS = 32;
38+
39+class DnsFixture : public ::benchmark::Fixture {
40+protected:
41+ static constexpr unsigned num_hosts = 1000;
42+ DnsResponderClient dns;
43+ std::vector<DnsResponderClient::Mapping> mappings;
44+ std::vector<std::unique_ptr<test::DNSResponder>> mDns;
45+
46+public:
47+ void SetUp(const ::benchmark::State& state) override {
48+ if (state.thread_index == 0) {
49+ dns.SetUp();
50+
51+ std::vector<std::string> domains = { "example.com" };
52+ std::vector<std::string> servers;
53+ dns.SetupMappings(num_hosts, domains, &mappings);
54+
55+ dns.SetupDNSServers(MAXNS, mappings, &mDns, &servers);
56+
57+ const std::vector<int> mDefaultParams_Binder = { 300, 25, 8, 8 };
58+ dns.SetResolversForNetwork(servers, domains, mDefaultParams_Binder);
59+ }
60+ }
61+
62+ void TearDown(const ::benchmark::State& state) override {
63+ if (state.thread_index == 0) {
64+ dns.ShutdownDNSServers(&mDns);
65+ dns.TearDown();
66+ }
67+ }
68+
69+ std::vector<DnsResponderClient::Mapping> const& getMappings() const {
70+ return mappings;
71+ }
72+
73+ android::sp<android::net::INetd> getNetd() const {
74+ return dns.mNetdSrv;
75+ }
76+
77+ void getaddrinfo_until_done(benchmark::State &state) {
78+ while (state.KeepRunning()) {
79+ const uint32_t ofs = arc4random_uniform(getMappings().size());
80+ const auto& mapping = getMappings()[ofs];
81+ addrinfo* result = nullptr;
82+ if (getaddrinfo(mapping.host.c_str(), nullptr, nullptr, &result)) {
83+ state.SkipWithError(StringPrintf("getaddrinfo failed with errno=%d",
84+ errno).c_str());
85+ break;
86+ }
87+ if (result) {
88+ freeaddrinfo(result);
89+ result = nullptr;
90+ }
91+ }
92+ }
93+
94+ void benchmark_at_reporting_level(benchmark::State &state, int metricsLevel) {
95+ const bool isMaster = (state.thread_index == 0);
96+ int oldMetricsLevel;
97+
98+ // SETUP
99+ if (isMaster) {
100+ auto rv = getNetd()->getMetricsReportingLevel(&oldMetricsLevel);
101+ if (!rv.isOk()) {
102+ state.SkipWithError(StringPrintf("Failed saving metrics reporting level: %s",
103+ rv.toString8().string()).c_str());
104+ return;
105+ }
106+ rv = getNetd()->setMetricsReportingLevel(metricsLevel);
107+ if (!rv.isOk()) {
108+ state.SkipWithError(StringPrintf("Failed changing metrics reporting: %s",
109+ rv.toString8().string()).c_str());
110+ return;
111+ }
112+ }
113+
114+ // TEST
115+ getaddrinfo_until_done(state);
116+
117+ // TEARDOWN
118+ if (isMaster) {
119+ auto rv = getNetd()->setMetricsReportingLevel(oldMetricsLevel);
120+ if (!rv.isOk()) {
121+ state.SkipWithError(StringPrintf("Failed restoring metrics reporting level: %s",
122+ rv.toString8().string()).c_str());
123+ return;
124+ }
125+ }
126+ }
127+};
128+
129+// DNS calls without any metrics logged or sent.
130+BENCHMARK_DEFINE_F(DnsFixture, getaddrinfo_log_nothing)(benchmark::State& state) {
131+ benchmark_at_reporting_level(state, INetdEventListener::REPORTING_LEVEL_NONE);
132+}
133+BENCHMARK_REGISTER_F(DnsFixture, getaddrinfo_log_nothing)
134+ ->ThreadRange(MIN_THREADS, MAX_THREADS)
135+ ->UseRealTime();
136+
137+// DNS calls with metrics only (netId, latency, return code) sent to the system server.
138+BENCHMARK_DEFINE_F(DnsFixture, getaddrinfo_log_metrics)(benchmark::State& state) {
139+ benchmark_at_reporting_level(state, INetdEventListener::REPORTING_LEVEL_METRICS);
140+}
141+BENCHMARK_REGISTER_F(DnsFixture, getaddrinfo_log_metrics)
142+ ->ThreadRange(MIN_THREADS, MAX_THREADS)
143+ ->UseRealTime();
144+
145+// DNS calls with all information logged and sent to the system server.
146+BENCHMARK_DEFINE_F(DnsFixture, getaddrinfo_log_everything)(benchmark::State& state) {
147+ benchmark_at_reporting_level(state, INetdEventListener::REPORTING_LEVEL_FULL);
148+}
149+BENCHMARK_REGISTER_F(DnsFixture, getaddrinfo_log_everything)
150+ ->ThreadRange(MIN_THREADS, MAX_THREADS)
151+ ->UseRealTime();
--- a/server/binder/android/net/metrics/IDnsEventListener.aidl
+++ b/tests/benchmarks/main.cpp
@@ -1,11 +1,11 @@
1-/**
2- * Copyright (c) 2016, The Android Open Source Project
1+/*
2+ * Copyright (C) 2016 The Android Open Source Project
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
66 * You may obtain a copy of the License at
77 *
8- * http://www.apache.org/licenses/LICENSE-2.0
8+ * http://www.apache.org/licenses/LICENSE-2.0
99 *
1010 * Unless required by applicable law or agreed to in writing, software
1111 * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,17 +14,6 @@
1414 * limitations under the License.
1515 */
1616
17-package android.net.metrics;
17+#include <benchmark/benchmark.h>
1818
19-/**
20- * Logs DNS lookups.
21- *
22- * {@hide}
23- */
24-oneway interface IDnsEventListener {
25- const int EVENT_GETADDRINFO = 1;
26- const int EVENT_GETHOSTBYNAME = 2;
27-
28- // Logs a single DNS lookup.
29- void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs);
30-}
19+BENCHMARK_MAIN();
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -42,6 +42,7 @@
4242 #include <netutils/ifc.h>
4343
4444 #include "NetdConstants.h"
45+#include "Stopwatch.h"
4546 #include "android/net/INetd.h"
4647 #include "android/net/UidRange.h"
4748 #include "binder/IServiceManager.h"
--- /dev/null
+++ b/tests/dns_responder/Android.mk
@@ -0,0 +1,46 @@
1+#
2+# Copyright (C) 2016 The Android Open Source Project
3+#
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
7+#
8+# http://www.apache.org/licenses/LICENSE-2.0
9+#
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.
15+#
16+LOCAL_PATH := $(call my-dir)
17+
18+# TODO describe library here
19+include $(CLEAR_VARS)
20+LOCAL_MODULE := libnetd_test_dnsresponder
21+LOCAL_CFLAGS := -Wall -Werror -Wunused-parameter
22+# Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
23+LOCAL_CFLAGS += -Wno-varargs
24+
25+EXTRA_LDLIBS := -lpthread
26+LOCAL_SHARED_LIBRARIES += libbase libbinder liblog libnetd_client
27+LOCAL_STATIC_LIBRARIES += libutils
28+
29+LOCAL_AIDL_INCLUDES += system/netd/server/binder
30+
31+LOCAL_C_INCLUDES += system/netd/include \
32+ system/extras/tests/include \
33+ system/netd/server \
34+ system/netd/server/binder \
35+ system/netd/tests/dns_responder \
36+ system/extras/tests/include \
37+ bionic/libc/dns/include
38+
39+LOCAL_SRC_FILES := dns_responder.cpp \
40+ dns_responder_client.cpp \
41+ ../../server/binder/android/net/INetd.aidl \
42+ ../../server/binder/android/net/UidRange.cpp
43+
44+LOCAL_MODULE_TAGS := eng tests
45+
46+include $(BUILD_STATIC_LIBRARY)
--- /dev/null
+++ b/tests/dns_responder/dns_responder_client.cpp
@@ -0,0 +1,188 @@
1+/*
2+ * Copyright (C) 2016 The Android Open Source Project
3+ *
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
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
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.
15+ */
16+
17+#include "dns_responder_client.h"
18+
19+#include <android-base/stringprintf.h>
20+
21+// TODO: make this dynamic and stop depending on implementation details.
22+#define TEST_OEM_NETWORK "oem29"
23+#define TEST_NETID 30
24+
25+// TODO: move this somewhere shared.
26+static const char* ANDROID_DNS_MODE = "ANDROID_DNS_MODE";
27+
28+// The only response code used in this class. See
29+// frameworks/base/services/java/com/android/server/NetworkManagementService.java
30+// for others.
31+static constexpr int ResponseCodeOK = 200;
32+
33+using android::base::StringPrintf;
34+
35+static int netdCommand(const char* sockname, const char* command) {
36+ int sock = socket_local_client(sockname,
37+ ANDROID_SOCKET_NAMESPACE_RESERVED,
38+ SOCK_STREAM);
39+ if (sock < 0) {
40+ perror("Error connecting");
41+ return -1;
42+ }
43+
44+ // FrameworkListener expects the whole command in one read.
45+ char buffer[256];
46+ int nwritten = snprintf(buffer, sizeof(buffer), "0 %s", command);
47+ if (write(sock, buffer, nwritten + 1) < 0) {
48+ perror("Error sending netd command");
49+ close(sock);
50+ return -1;
51+ }
52+
53+ int nread = read(sock, buffer, sizeof(buffer));
54+ if (nread < 0) {
55+ perror("Error reading response");
56+ close(sock);
57+ return -1;
58+ }
59+ close(sock);
60+ return atoi(buffer);
61+}
62+
63+static bool expectNetdResult(int expected, const char* sockname, const char* format, ...) {
64+ char command[256];
65+ va_list args;
66+ va_start(args, format);
67+ vsnprintf(command, sizeof(command), format, args);
68+ va_end(args);
69+ int result = netdCommand(sockname, command);
70+ if (expected != result) {
71+ return false;
72+ }
73+ return (200 <= expected && expected < 300);
74+}
75+
76+void DnsResponderClient::SetupMappings(unsigned num_hosts, const std::vector<std::string>& domains,
77+ std::vector<Mapping>* mappings) {
78+ mappings->resize(num_hosts * domains.size());
79+ auto mappings_it = mappings->begin();
80+ for (unsigned i = 0 ; i < num_hosts ; ++i) {
81+ for (const auto& domain : domains) {
82+ mappings_it->host = StringPrintf("host%u", i);
83+ mappings_it->entry = StringPrintf("%s.%s.", mappings_it->host.c_str(),
84+ domain.c_str());
85+ mappings_it->ip4 = StringPrintf("192.0.2.%u", i%253 + 1);
86+ mappings_it->ip6 = StringPrintf("2001:db8::%x", i%65534 + 1);
87+ ++mappings_it;
88+ }
89+ }
90+}
91+
92+bool DnsResponderClient::SetResolversForNetwork(const std::vector<std::string>& servers,
93+ const std::vector<std::string>& domains, const std::vector<int>& params) {
94+ auto rv = mNetdSrv->setResolverConfiguration(TEST_NETID, servers, domains, params);
95+ return rv.isOk();
96+}
97+
98+bool DnsResponderClient::SetResolversForNetwork(const std::vector<std::string>& searchDomains,
99+ const std::vector<std::string>& servers, const std::string& params) {
100+ std::string cmd = StringPrintf("resolver setnetdns %d \"", mOemNetId);
101+ if (!searchDomains.empty()) {
102+ cmd += searchDomains[0].c_str();
103+ for (size_t i = 1 ; i < searchDomains.size() ; ++i) {
104+ cmd += " ";
105+ cmd += searchDomains[i];
106+ }
107+ }
108+ cmd += "\"";
109+
110+ for (const auto& str : servers) {
111+ cmd += " ";
112+ cmd += str;
113+ }
114+
115+ if (!params.empty()) {
116+ cmd += " --params \"";
117+ cmd += params;
118+ cmd += "\"";
119+ }
120+
121+ int rv = netdCommand("netd", cmd.c_str());
122+ if (rv != ResponseCodeOK) {
123+ return false;
124+ }
125+ return true;
126+}
127+
128+void DnsResponderClient::SetupDNSServers(unsigned num_servers, const std::vector<Mapping>& mappings,
129+ std::vector<std::unique_ptr<test::DNSResponder>>* dns,
130+ std::vector<std::string>* servers) {
131+ const char* listen_srv = "53";
132+ dns->resize(num_servers);
133+ servers->resize(num_servers);
134+ for (unsigned i = 0 ; i < num_servers ; ++i) {
135+ auto& server = (*servers)[i];
136+ auto& d = (*dns)[i];
137+ server = StringPrintf("127.0.0.%u", i + 100);
138+ d = std::make_unique<test::DNSResponder>(server, listen_srv, 250,
139+ ns_rcode::ns_r_servfail, 1.0);
140+ for (const auto& mapping : mappings) {
141+ d->addMapping(mapping.entry.c_str(), ns_type::ns_t_a, mapping.ip4.c_str());
142+ d->addMapping(mapping.entry.c_str(), ns_type::ns_t_aaaa, mapping.ip6.c_str());
143+ }
144+ d->startServer();
145+ }
146+}
147+
148+void DnsResponderClient::ShutdownDNSServers(std::vector<std::unique_ptr<test::DNSResponder>>* dns) {
149+ for (const auto& d : *dns) {
150+ d->stopServer();
151+ }
152+ dns->clear();
153+}
154+
155+int DnsResponderClient::SetupOemNetwork() {
156+ netdCommand("netd", "network destroy " TEST_OEM_NETWORK);
157+ if (!expectNetdResult(ResponseCodeOK, "netd",
158+ "network create %s", TEST_OEM_NETWORK)) {
159+ return -1;
160+ }
161+ int oemNetId = TEST_NETID;
162+ setNetworkForProcess(oemNetId);
163+ if ((unsigned) oemNetId != getNetworkForProcess()) {
164+ return -1;
165+ }
166+ return oemNetId;
167+}
168+
169+void DnsResponderClient::TearDownOemNetwork(int oemNetId) {
170+ if (oemNetId != -1) {
171+ expectNetdResult(ResponseCodeOK, "netd",
172+ "network destroy %s", TEST_OEM_NETWORK);
173+ }
174+}
175+
176+void DnsResponderClient::SetUp() {
177+ // Ensure resolutions go via proxy.
178+ setenv(ANDROID_DNS_MODE, "", 1);
179+ mOemNetId = SetupOemNetwork();
180+
181+ // binder setup
182+ auto binder = android::defaultServiceManager()->getService(android::String16("netd"));
183+ mNetdSrv = android::interface_cast<android::net::INetd>(binder);
184+}
185+
186+void DnsResponderClient::TearDown() {
187+ TearDownOemNetwork(mOemNetId);
188+}
--- /dev/null
+++ b/tests/dns_responder/dns_responder_client.h
@@ -0,0 +1,56 @@
1+#ifndef DNS_RESPONDER_CLIENT_H
2+#define DNS_RESPONDER_CLIENT_H
3+
4+#include "SockDiag.h"
5+
6+#include <cutils/sockets.h>
7+
8+#include <private/android_filesystem_config.h>
9+#include <utils/StrongPointer.h>
10+
11+#include "android/net/INetd.h"
12+#include "binder/IServiceManager.h"
13+#include "NetdClient.h"
14+#include "dns_responder.h"
15+#include "resolv_params.h"
16+
17+class DnsResponderClient {
18+public:
19+ struct Mapping {
20+ std::string host;
21+ std::string entry;
22+ std::string ip4;
23+ std::string ip6;
24+ };
25+
26+ virtual ~DnsResponderClient() = default;
27+
28+ void SetupMappings(unsigned num_hosts, const std::vector<std::string>& domains,
29+ std::vector<Mapping>* mappings);
30+
31+ bool SetResolversForNetwork(const std::vector<std::string>& servers,
32+ const std::vector<std::string>& domains, const std::vector<int>& params);
33+
34+ bool SetResolversForNetwork(const std::vector<std::string>& searchDomains,
35+ const std::vector<std::string>& servers, const std::string& params);
36+
37+ static void SetupDNSServers(unsigned num_servers, const std::vector<Mapping>& mappings,
38+ std::vector<std::unique_ptr<test::DNSResponder>>* dns,
39+ std::vector<std::string>* servers);
40+
41+ static void ShutdownDNSServers(std::vector<std::unique_ptr<test::DNSResponder>>* dns);
42+
43+ static int SetupOemNetwork();
44+
45+ static void TearDownOemNetwork(int oemNetId);
46+
47+ virtual void SetUp();
48+
49+ virtual void TearDown();
50+
51+public:
52+ android::sp<android::net::INetd> mNetdSrv = nullptr;
53+ int mOemNetId = -1;
54+};
55+
56+#endif // DNS_RESPONDER_CLIENT_H
--- a/tests/netd_test.cpp
+++ b/tests/netd_test.cpp
@@ -47,15 +47,18 @@
4747 #include <testUtil.h>
4848
4949 #include "dns_responder.h"
50+#include "dns_responder_client.h"
5051 #include "resolv_params.h"
5152 #include "ResolverStats.h"
5253
5354 #include "android/net/INetd.h"
55+#include "android/net/metrics/INetdEventListener.h"
5456 #include "binder/IServiceManager.h"
5557
5658 using android::base::StringPrintf;
5759 using android::base::StringAppendF;
5860 using android::net::ResolverStats;
61+using android::net::metrics::INetdEventListener;
5962
6063 // Emulates the behavior of UnorderedElementsAreArray, which currently cannot be used.
6164 // TODO: Use UnorderedElementsAreArray, which depends on being able to compile libgmock_host,
@@ -79,51 +82,6 @@ bool UnorderedCompareArray(const A& a, const B& b) {
7982 return true;
8083 }
8184
82-// The only response code used in this test, see
83-// frameworks/base/services/java/com/android/server/NetworkManagementService.java
84-// for others.
85-static constexpr int ResponseCodeOK = 200;
86-
87-// Returns ResponseCode.
88-int netdCommand(const char* sockname, const char* command) {
89- int sock = socket_local_client(sockname,
90- ANDROID_SOCKET_NAMESPACE_RESERVED,
91- SOCK_STREAM);
92- if (sock < 0) {
93- perror("Error connecting");
94- return -1;
95- }
96-
97- // FrameworkListener expects the whole command in one read.
98- char buffer[256];
99- int nwritten = snprintf(buffer, sizeof(buffer), "0 %s", command);
100- if (write(sock, buffer, nwritten + 1) < 0) {
101- perror("Error sending netd command");
102- close(sock);
103- return -1;
104- }
105-
106- int nread = read(sock, buffer, sizeof(buffer));
107- if (nread < 0) {
108- perror("Error reading response");
109- close(sock);
110- return -1;
111- }
112- close(sock);
113- return atoi(buffer);
114-}
115-
116-bool expectNetdResult(int expected, const char* sockname, const char* format, ...) {
117- char command[256];
118- va_list args;
119- va_start(args, format);
120- vsnprintf(command, sizeof(command), format, args);
121- va_end(args);
122- int result = netdCommand(sockname, command);
123- EXPECT_EQ(expected, result) << command;
124- return (200 <= expected && expected < 300);
125-}
126-
12785 class AddrInfo {
12886 public:
12987 AddrInfo() : ai_(nullptr), error_(0) {}
@@ -168,131 +126,31 @@ class AddrInfo {
168126 int error_;
169127 };
170128
171-class ResolverTest : public ::testing::Test {
172-protected:
173- struct Mapping {
174- std::string host;
175- std::string entry;
176- std::string ip4;
177- std::string ip6;
178- };
129+class ResolverTest : public ::testing::Test, public DnsResponderClient {
130+private:
131+ int mOriginalMetricsLevel;
179132
133+protected:
180134 virtual void SetUp() {
181135 // Ensure resolutions go via proxy.
182- setenv("ANDROID_DNS_MODE", "", 1);
183- uid = getuid();
184- pid = getpid();
185- SetupOemNetwork();
186-
187- // binder setup
188- auto binder = android::defaultServiceManager()->getService(android::String16("netd"));
189- ASSERT_TRUE(binder != nullptr);
190- mNetdSrv = android::interface_cast<android::net::INetd>(binder);
191- }
192-
193- virtual void TearDown() {
194- TearDownOemNetwork();
195- netdCommand("netd", "network destroy " TEST_OEM_NETWORK);
196- }
197-
198- void SetupOemNetwork() {
199- netdCommand("netd", "network destroy " TEST_OEM_NETWORK);
200- if (expectNetdResult(ResponseCodeOK, "netd",
201- "network create %s", TEST_OEM_NETWORK)) {
202- oemNetId = TEST_NETID;
136+ DnsResponderClient::SetUp();
137+
138+ // If DNS reporting is off: turn it on so we run through everything.
139+ auto rv = mNetdSrv->getMetricsReportingLevel(&mOriginalMetricsLevel);
140+ ASSERT_TRUE(rv.isOk());
141+ if (mOriginalMetricsLevel != INetdEventListener::REPORTING_LEVEL_FULL) {
142+ rv = mNetdSrv->setMetricsReportingLevel(INetdEventListener::REPORTING_LEVEL_FULL);
143+ ASSERT_TRUE(rv.isOk());
203144 }
204- setNetworkForProcess(oemNetId);
205- ASSERT_EQ((unsigned) oemNetId, getNetworkForProcess());
206145 }
207146
208- void SetupMappings(unsigned num_hosts, const std::vector<std::string>& domains,
209- std::vector<Mapping>* mappings) const {
210- mappings->resize(num_hosts * domains.size());
211- auto mappings_it = mappings->begin();
212- for (unsigned i = 0 ; i < num_hosts ; ++i) {
213- for (const auto& domain : domains) {
214- ASSERT_TRUE(mappings_it != mappings->end());
215- mappings_it->host = StringPrintf("host%u", i);
216- mappings_it->entry = StringPrintf("%s.%s.", mappings_it->host.c_str(),
217- domain.c_str());
218- mappings_it->ip4 = StringPrintf("192.0.2.%u", i%253 + 1);
219- mappings_it->ip6 = StringPrintf("2001:db8::%x", i%65534 + 1);
220- ++mappings_it;
221- }
222- }
223- }
224-
225- void SetupDNSServers(unsigned num_servers, const std::vector<Mapping>& mappings,
226- std::vector<std::unique_ptr<test::DNSResponder>>* dns,
227- std::vector<std::string>* servers) const {
228- ASSERT_TRUE(num_servers != 0 && num_servers < 100);
229- const char* listen_srv = "53";
230- dns->resize(num_servers);
231- servers->resize(num_servers);
232- for (unsigned i = 0 ; i < num_servers ; ++i) {
233- auto& server = (*servers)[i];
234- auto& d = (*dns)[i];
235- server = StringPrintf("127.0.0.%u", i + 100);
236- d = std::make_unique<test::DNSResponder>(server, listen_srv, 250,
237- ns_rcode::ns_r_servfail, 1.0);
238- ASSERT_TRUE(d.get() != nullptr);
239- for (const auto& mapping : mappings) {
240- d->addMapping(mapping.entry.c_str(), ns_type::ns_t_a, mapping.ip4.c_str());
241- d->addMapping(mapping.entry.c_str(), ns_type::ns_t_aaaa, mapping.ip6.c_str());
242- }
243- ASSERT_TRUE(d->startServer());
244- }
245- }
246-
247- void ShutdownDNSServers(std::vector<std::unique_ptr<test::DNSResponder>>* dns) const {
248- for (const auto& d : *dns) {
249- ASSERT_TRUE(d.get() != nullptr);
250- d->stopServer();
251- }
252- dns->clear();
253- }
254-
255- void TearDownOemNetwork() {
256- if (oemNetId != -1) {
257- expectNetdResult(ResponseCodeOK, "netd",
258- "network destroy %s", TEST_OEM_NETWORK);
259- }
260- }
261-
262- bool SetResolversForNetwork(const std::vector<std::string>& servers,
263- const std::vector<std::string>& domains, const std::vector<int>& params) {
264- auto rv = mNetdSrv->setResolverConfiguration(TEST_NETID, servers, domains, params);
265- return rv.isOk();
266- }
267-
268- bool SetResolversForNetwork(const std::vector<std::string>& searchDomains,
269- const std::vector<std::string>& servers, const std::string& params) {
270- std::string cmd = StringPrintf("resolver setnetdns %d \"", oemNetId);
271- if (!searchDomains.empty()) {
272- cmd += searchDomains[0].c_str();
273- for (size_t i = 1 ; i < searchDomains.size() ; ++i) {
274- cmd += " ";
275- cmd += searchDomains[i];
276- }
277- }
278- cmd += "\"";
279-
280- for (const auto& str : servers) {
281- cmd += " ";
282- cmd += str;
283- }
284-
285- if (!params.empty()) {
286- cmd += " --params \"";
287- cmd += params;
288- cmd += "\"";
147+ virtual void TearDown() {
148+ if (mOriginalMetricsLevel != INetdEventListener::REPORTING_LEVEL_FULL) {
149+ auto rv = mNetdSrv->setMetricsReportingLevel(mOriginalMetricsLevel);
150+ ASSERT_TRUE(rv.isOk());
289151 }
290152
291- int rv = netdCommand("netd", cmd.c_str());
292- if (rv != ResponseCodeOK) {
293- return false;
294- }
295- return true;
153+ DnsResponderClient::TearDown();
296154 }
297155
298156 bool GetResolverInfo(std::vector<std::string>* servers, std::vector<std::string>* domains,
@@ -368,7 +226,7 @@ protected:
368226 std::vector<std::string> domains = { "example.com" };
369227 std::vector<std::unique_ptr<test::DNSResponder>> dns;
370228 std::vector<std::string> servers;
371- std::vector<Mapping> mappings;
229+ std::vector<DnsResponderClient::Mapping> mappings;
372230 ASSERT_NO_FATAL_FAILURE(SetupMappings(num_hosts, domains, &mappings));
373231 ASSERT_NO_FATAL_FAILURE(SetupDNSServers(MAXNS, mappings, &dns, &servers));
374232
@@ -380,8 +238,7 @@ protected:
380238 thread = std::thread([this, &servers, &dns, &mappings, num_queries]() {
381239 for (unsigned i = 0 ; i < num_queries ; ++i) {
382240 uint32_t ofs = arc4random_uniform(mappings.size());
383- ASSERT_TRUE(ofs < mappings.size());
384- auto& mapping = mappings[i];
241+ auto& mapping = mappings[ofs];
385242 addrinfo* result = nullptr;
386243 int rv = getaddrinfo(mapping.host.c_str(), nullptr, nullptr, &result);
387244 EXPECT_EQ(0, rv) << "error [" << rv << "] " << gai_strerror(rv);
@@ -408,10 +265,6 @@ protected:
408265 ASSERT_NO_FATAL_FAILURE(ShutdownDNSServers(&dns));
409266 }
410267
411- int pid;
412- int uid;
413- int oemNetId = -1;
414- android::sp<android::net::INetd> mNetdSrv = nullptr;
415268 const std::vector<std::string> mDefaultSearchDomains = { "example.com" };
416269 // <sample validity in s> <success threshold in percent> <min samples> <max samples>
417270 const std::string mDefaultParams = "300 25 8 8";
@@ -422,20 +275,30 @@ TEST_F(ResolverTest, GetHostByName) {
422275 const char* listen_addr = "127.0.0.3";
423276 const char* listen_srv = "53";
424277 const char* host_name = "hello.example.com.";
278+ const char *nonexistent_host_name = "nonexistent.example.com.";
425279 test::DNSResponder dns(listen_addr, listen_srv, 250, ns_rcode::ns_r_servfail, 1.0);
426280 dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.3");
427281 ASSERT_TRUE(dns.startServer());
428282 std::vector<std::string> servers = { listen_addr };
429283 ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams));
430284
285+ const hostent* result;
286+
431287 dns.clearQueries();
432- const hostent* result = gethostbyname("hello");
288+ result = gethostbyname("nonexistent");
289+ EXPECT_EQ(1U, GetNumQueriesForType(dns, ns_type::ns_t_a, nonexistent_host_name));
290+ ASSERT_TRUE(result == nullptr);
291+ ASSERT_EQ(HOST_NOT_FOUND, h_errno);
292+
293+ dns.clearQueries();
294+ result = gethostbyname("hello");
433295 EXPECT_EQ(1U, GetNumQueriesForType(dns, ns_type::ns_t_a, host_name));
434296 ASSERT_FALSE(result == nullptr);
435297 ASSERT_EQ(4, result->h_length);
436298 ASSERT_FALSE(result->h_addr_list[0] == nullptr);
437299 EXPECT_EQ("1.2.3.3", ToString(result));
438300 EXPECT_TRUE(result->h_addr_list[1] == nullptr);
301+
439302 dns.stopServer();
440303 }
441304
Show on old repository browser