1 /*
2 * Copyright (C) 2010 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 <arpa/inet.h>
18 #include <dirent.h>
19 #include <errno.h>
20 #include <linux/if.h>
21 #include <math.h>
22 #include <netdb.h>
23 #include <netinet/in.h>
24 #include <stdlib.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <string.h>
28 #include <pthread.h>
29 #include <resolv_netid.h>
30 #include <net/if.h>
31
32 #define LOG_TAG "DnsProxyListener"
33 #define DBG 0
34 #define VDBG 0
35
36 #include <chrono>
37 #include <vector>
38
39 #include <cutils/log.h>
40 #include <utils/String16.h>
41 #include <sysutils/SocketClient.h>
42
43 #include "Fwmark.h"
44 #include "DnsProxyListener.h"
45 #include "NetdConstants.h"
46 #include "NetworkController.h"
47 #include "ResponseCode.h"
48 #include "Stopwatch.h"
49 #include "android/net/metrics/INetdEventListener.h"
50
51 using android::String16;
52 using android::net::metrics::INetdEventListener;
53
54 namespace android {
55 namespace net {
56
57 namespace {
58
59 template<typename T>
threadMain(void * obj)60 void* threadMain(void* obj) {
61 std::unique_ptr<T> handler(reinterpret_cast<T*>(obj));
62 handler->run();
63 return nullptr;
64 }
65
66 struct scoped_pthread_attr {
scoped_pthread_attrandroid::net::__anon12339bd10111::scoped_pthread_attr67 scoped_pthread_attr() { pthread_attr_init(&attr); }
~scoped_pthread_attrandroid::net::__anon12339bd10111::scoped_pthread_attr68 ~scoped_pthread_attr() { pthread_attr_destroy(&attr); }
69
detachandroid::net::__anon12339bd10111::scoped_pthread_attr70 int detach() {
71 return pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
72 }
73
74 pthread_attr_t attr;
75 };
76
77 template<typename T>
threadLaunch(T * self)78 int threadLaunch(T* self) {
79 if (self == nullptr) { return -EINVAL;}
80
81 scoped_pthread_attr scoped_attr;
82
83 int rval = scoped_attr.detach();
84 if (rval != 0) { return -errno; }
85
86 pthread_t thread;
87 rval = pthread_create(&thread, &scoped_attr.attr, &threadMain<T>, self);
88 if (rval != 0) {
89 ALOGW("pthread_create failed: %d", errno);
90 return -errno;
91 }
92
93 return rval;
94 }
95
96 template<typename T>
tryThreadOrError(SocketClient * cli,T * handler)97 void tryThreadOrError(SocketClient* cli, T* handler) {
98 cli->incRef();
99
100 const int rval = threadLaunch(handler);
101 if (rval == 0) {
102 // SocketClient decRef() happens in the handler's run() method.
103 return;
104 }
105
106 char* msg = NULL;
107 asprintf(&msg, "%s (%d)", strerror(-rval), -rval);
108 cli->sendMsg(ResponseCode::OperationFailed, msg, false);
109 free(msg);
110
111 delete handler;
112 cli->decRef();
113 }
114
115 } // namespace
116
DnsProxyListener(const NetworkController * netCtrl,EventReporter * eventReporter)117 DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl, EventReporter* eventReporter) :
118 FrameworkListener("dnsproxyd"), mNetCtrl(netCtrl), mEventReporter(eventReporter) {
119 registerCmd(new GetAddrInfoCmd(this));
120 registerCmd(new GetHostByAddrCmd(this));
121 registerCmd(new GetHostByNameCmd(this));
122 }
123
GetAddrInfoHandler(SocketClient * c,char * host,char * service,struct addrinfo * hints,const struct android_net_context & netcontext,const int reportingLevel,const android::sp<android::net::metrics::INetdEventListener> & netdEventListener)124 DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(
125 SocketClient *c, char* host, char* service, struct addrinfo* hints,
126 const struct android_net_context& netcontext, const int reportingLevel,
127 const android::sp<android::net::metrics::INetdEventListener>& netdEventListener)
128 : mClient(c),
129 mHost(host),
130 mService(service),
131 mHints(hints),
132 mNetContext(netcontext),
133 mReportingLevel(reportingLevel),
134 mNetdEventListener(netdEventListener) {
135 }
136
~GetAddrInfoHandler()137 DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
138 free(mHost);
139 free(mService);
140 free(mHints);
141 }
142
sendBE32(SocketClient * c,uint32_t data)143 static bool sendBE32(SocketClient* c, uint32_t data) {
144 uint32_t be_data = htonl(data);
145 return c->sendData(&be_data, sizeof(be_data)) == 0;
146 }
147
148 // Sends 4 bytes of big-endian length, followed by the data.
149 // Returns true on success.
sendLenAndData(SocketClient * c,const int len,const void * data)150 static bool sendLenAndData(SocketClient* c, const int len, const void* data) {
151 return sendBE32(c, len) && (len == 0 || c->sendData(data, len) == 0);
152 }
153
154 // Returns true on success
sendhostent(SocketClient * c,struct hostent * hp)155 static bool sendhostent(SocketClient *c, struct hostent *hp) {
156 bool success = true;
157 int i;
158 if (hp->h_name != NULL) {
159 success &= sendLenAndData(c, strlen(hp->h_name)+1, hp->h_name);
160 } else {
161 success &= sendLenAndData(c, 0, "") == 0;
162 }
163
164 for (i=0; hp->h_aliases[i] != NULL; i++) {
165 success &= sendLenAndData(c, strlen(hp->h_aliases[i])+1, hp->h_aliases[i]);
166 }
167 success &= sendLenAndData(c, 0, ""); // null to indicate we're done
168
169 uint32_t buf = htonl(hp->h_addrtype);
170 success &= c->sendData(&buf, sizeof(buf)) == 0;
171
172 buf = htonl(hp->h_length);
173 success &= c->sendData(&buf, sizeof(buf)) == 0;
174
175 for (i=0; hp->h_addr_list[i] != NULL; i++) {
176 success &= sendLenAndData(c, 16, hp->h_addr_list[i]);
177 }
178 success &= sendLenAndData(c, 0, ""); // null to indicate we're done
179 return success;
180 }
181
sendaddrinfo(SocketClient * c,struct addrinfo * ai)182 static bool sendaddrinfo(SocketClient* c, struct addrinfo* ai) {
183 // struct addrinfo {
184 // int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
185 // int ai_family; /* PF_xxx */
186 // int ai_socktype; /* SOCK_xxx */
187 // int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
188 // socklen_t ai_addrlen; /* length of ai_addr */
189 // char *ai_canonname; /* canonical name for hostname */
190 // struct sockaddr *ai_addr; /* binary address */
191 // struct addrinfo *ai_next; /* next structure in linked list */
192 // };
193
194 // Write the struct piece by piece because we might be a 64-bit netd
195 // talking to a 32-bit process.
196 bool success =
197 sendBE32(c, ai->ai_flags) &&
198 sendBE32(c, ai->ai_family) &&
199 sendBE32(c, ai->ai_socktype) &&
200 sendBE32(c, ai->ai_protocol);
201 if (!success) {
202 return false;
203 }
204
205 // ai_addrlen and ai_addr.
206 if (!sendLenAndData(c, ai->ai_addrlen, ai->ai_addr)) {
207 return false;
208 }
209
210 // strlen(ai_canonname) and ai_canonname.
211 if (!sendLenAndData(c, ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0, ai->ai_canonname)) {
212 return false;
213 }
214
215 return true;
216 }
217
run()218 void DnsProxyListener::GetAddrInfoHandler::run() {
219 if (DBG) {
220 ALOGD("GetAddrInfoHandler, now for %s / %s / {%u,%u,%u,%u,%u}", mHost, mService,
221 mNetContext.app_netid, mNetContext.app_mark,
222 mNetContext.dns_netid, mNetContext.dns_mark,
223 mNetContext.uid);
224 }
225
226 struct addrinfo* result = NULL;
227 Stopwatch s;
228 uint32_t rv = android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext, &result);
229 const int latencyMs = lround(s.timeTaken());
230
231 if (rv) {
232 // getaddrinfo failed
233 mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, &rv, sizeof(rv));
234 } else {
235 bool success = !mClient->sendCode(ResponseCode::DnsProxyQueryResult);
236 struct addrinfo* ai = result;
237 while (ai && success) {
238 success = sendBE32(mClient, 1) && sendaddrinfo(mClient, ai);
239 ai = ai->ai_next;
240 }
241 success = success && sendBE32(mClient, 0);
242 if (!success) {
243 ALOGW("Error writing DNS result to client");
244 }
245 }
246 std::vector<String16> ip_addrs;
247 int total_ip_addr_count = 0;
248 if (result) {
249 if (mNetdEventListener != nullptr
250 && mReportingLevel == INetdEventListener::REPORTING_LEVEL_FULL) {
251 for (addrinfo* ai = result; ai; ai = ai->ai_next) {
252 sockaddr* ai_addr = ai->ai_addr;
253 if (ai_addr) {
254 addIpAddrWithinLimit(ip_addrs, ai_addr, ai->ai_addrlen);
255 total_ip_addr_count++;
256 }
257 }
258 }
259 freeaddrinfo(result);
260 }
261 mClient->decRef();
262 if (mNetdEventListener != nullptr) {
263 switch (mReportingLevel) {
264 case INetdEventListener::REPORTING_LEVEL_NONE:
265 // Skip reporting.
266 break;
267 case INetdEventListener::REPORTING_LEVEL_METRICS:
268 // Metrics reporting is on. Send metrics.
269 mNetdEventListener->onDnsEvent(mNetContext.dns_netid,
270 INetdEventListener::EVENT_GETADDRINFO, (int32_t) rv,
271 latencyMs, String16(""), {}, -1, -1);
272 break;
273 case INetdEventListener::REPORTING_LEVEL_FULL:
274 // Full event info reporting is on. Send full info.
275 mNetdEventListener->onDnsEvent(mNetContext.dns_netid,
276 INetdEventListener::EVENT_GETADDRINFO, (int32_t) rv,
277 latencyMs, String16(mHost), ip_addrs,
278 total_ip_addr_count, mNetContext.uid);
279 break;
280 }
281 } else {
282 ALOGW("Netd event listener is not available; skipping.");
283 }
284 }
285
addIpAddrWithinLimit(std::vector<android::String16> & ip_addrs,const sockaddr * addr,socklen_t addrlen)286 void DnsProxyListener::addIpAddrWithinLimit(std::vector<android::String16>& ip_addrs,
287 const sockaddr* addr, socklen_t addrlen) {
288 // ipAddresses array is limited to first INetdEventListener::DNS_REPORTED_IP_ADDRESSES_LIMIT
289 // addresses for A and AAAA. Total count of addresses is provided, to be able to tell whether
290 // some addresses didn't get logged.
291 if (ip_addrs.size() < INetdEventListener::DNS_REPORTED_IP_ADDRESSES_LIMIT) {
292 char ip_addr[INET6_ADDRSTRLEN];
293 if (getnameinfo(addr, addrlen, ip_addr, sizeof(ip_addr), nullptr, 0, NI_NUMERICHOST) == 0) {
294 ip_addrs.push_back(String16(ip_addr));
295 }
296 }
297 }
298
GetAddrInfoCmd(DnsProxyListener * dnsProxyListener)299 DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd(DnsProxyListener* dnsProxyListener) :
300 NetdCommand("getaddrinfo"),
301 mDnsProxyListener(dnsProxyListener) {
302 }
303
runCommand(SocketClient * cli,int argc,char ** argv)304 int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli,
305 int argc, char **argv) {
306 if (DBG) {
307 for (int i = 0; i < argc; i++) {
308 ALOGD("argv[%i]=%s", i, argv[i]);
309 }
310 }
311 if (argc != 8) {
312 char* msg = NULL;
313 asprintf( &msg, "Invalid number of arguments to getaddrinfo: %i", argc);
314 ALOGW("%s", msg);
315 cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
316 free(msg);
317 return -1;
318 }
319
320 char* name = argv[1];
321 if (strcmp("^", name) == 0) {
322 name = NULL;
323 } else {
324 name = strdup(name);
325 }
326
327 char* service = argv[2];
328 if (strcmp("^", service) == 0) {
329 service = NULL;
330 } else {
331 service = strdup(service);
332 }
333
334 struct addrinfo* hints = NULL;
335 int ai_flags = atoi(argv[3]);
336 int ai_family = atoi(argv[4]);
337 int ai_socktype = atoi(argv[5]);
338 int ai_protocol = atoi(argv[6]);
339 unsigned netId = strtoul(argv[7], NULL, 10);
340 uid_t uid = cli->getUid();
341
342 struct android_net_context netcontext;
343 mDnsProxyListener->mNetCtrl->getNetworkContext(netId, uid, &netcontext);
344
345 if (ai_flags != -1 || ai_family != -1 ||
346 ai_socktype != -1 || ai_protocol != -1) {
347 hints = (struct addrinfo*) calloc(1, sizeof(struct addrinfo));
348 hints->ai_flags = ai_flags;
349 hints->ai_family = ai_family;
350 hints->ai_socktype = ai_socktype;
351 hints->ai_protocol = ai_protocol;
352 }
353
354 if (DBG) {
355 ALOGD("GetAddrInfoHandler for %s / %s / {%u,%u,%u,%u,%u}",
356 name ? name : "[nullhost]",
357 service ? service : "[nullservice]",
358 netcontext.app_netid, netcontext.app_mark,
359 netcontext.dns_netid, netcontext.dns_mark,
360 netcontext.uid);
361 }
362
363 const int metricsLevel = mDnsProxyListener->mEventReporter->getMetricsReportingLevel();
364
365 DnsProxyListener::GetAddrInfoHandler* handler =
366 new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, netcontext,
367 metricsLevel, mDnsProxyListener->mEventReporter->getNetdEventListener());
368 tryThreadOrError(cli, handler);
369 return 0;
370 }
371
372 /*******************************************************
373 * GetHostByName *
374 *******************************************************/
GetHostByNameCmd(DnsProxyListener * dnsProxyListener)375 DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd(DnsProxyListener* dnsProxyListener) :
376 NetdCommand("gethostbyname"),
377 mDnsProxyListener(dnsProxyListener) {
378 }
379
runCommand(SocketClient * cli,int argc,char ** argv)380 int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli,
381 int argc, char **argv) {
382 if (DBG) {
383 for (int i = 0; i < argc; i++) {
384 ALOGD("argv[%i]=%s", i, argv[i]);
385 }
386 }
387 if (argc != 4) {
388 char* msg = NULL;
389 asprintf(&msg, "Invalid number of arguments to gethostbyname: %i", argc);
390 ALOGW("%s", msg);
391 cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
392 free(msg);
393 return -1;
394 }
395
396 uid_t uid = cli->getUid();
397 unsigned netId = strtoul(argv[1], NULL, 10);
398 char* name = argv[2];
399 int af = atoi(argv[3]);
400
401 if (strcmp(name, "^") == 0) {
402 name = NULL;
403 } else {
404 name = strdup(name);
405 }
406
407 uint32_t mark = mDnsProxyListener->mNetCtrl->getNetworkForDns(&netId, uid);
408 const int metricsLevel = mDnsProxyListener->mEventReporter->getMetricsReportingLevel();
409
410 DnsProxyListener::GetHostByNameHandler* handler =
411 new DnsProxyListener::GetHostByNameHandler(cli, name, af, netId, mark, metricsLevel,
412 mDnsProxyListener->mEventReporter->getNetdEventListener());
413 tryThreadOrError(cli, handler);
414 return 0;
415 }
416
GetHostByNameHandler(SocketClient * c,char * name,int af,unsigned netId,uint32_t mark,const int metricsLevel,const android::sp<android::net::metrics::INetdEventListener> & netdEventListener)417 DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(
418 SocketClient* c, char* name, int af, unsigned netId, uint32_t mark, const int metricsLevel,
419 const android::sp<android::net::metrics::INetdEventListener>& netdEventListener)
420 : mClient(c),
421 mName(name),
422 mAf(af),
423 mNetId(netId),
424 mMark(mark),
425 mReportingLevel(metricsLevel),
426 mNetdEventListener(netdEventListener) {
427 }
428
~GetHostByNameHandler()429 DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() {
430 free(mName);
431 }
432
run()433 void DnsProxyListener::GetHostByNameHandler::run() {
434 if (DBG) {
435 ALOGD("DnsProxyListener::GetHostByNameHandler::run\n");
436 }
437
438 Stopwatch s;
439 struct hostent* hp = android_gethostbynamefornet(mName, mAf, mNetId, mMark);
440 const int latencyMs = lround(s.timeTaken());
441
442 if (DBG) {
443 ALOGD("GetHostByNameHandler::run gethostbyname errno: %s hp->h_name = %s, name_len = %zu\n",
444 hp ? "success" : strerror(errno),
445 (hp && hp->h_name) ? hp->h_name : "null",
446 (hp && hp->h_name) ? strlen(hp->h_name) + 1 : 0);
447 }
448
449 bool success = true;
450 if (hp) {
451 success = mClient->sendCode(ResponseCode::DnsProxyQueryResult) == 0;
452 success &= sendhostent(mClient, hp);
453 } else {
454 success = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, NULL, 0) == 0;
455 }
456
457 if (!success) {
458 ALOGW("GetHostByNameHandler: Error writing DNS result to client\n");
459 }
460
461 if (mNetdEventListener != nullptr) {
462 std::vector<String16> ip_addrs;
463 int total_ip_addr_count = 0;
464 if (mReportingLevel == INetdEventListener::REPORTING_LEVEL_FULL) {
465 if (hp != nullptr && hp->h_addrtype == AF_INET) {
466 in_addr** list = (in_addr**) hp->h_addr_list;
467 for (int i = 0; list[i] != NULL; i++) {
468 sockaddr_in sin = { .sin_family = AF_INET, .sin_addr = *list[i] };
469 addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin, sizeof(sin));
470 total_ip_addr_count++;
471 }
472 } else if (hp != nullptr && hp->h_addrtype == AF_INET6) {
473 in6_addr** list = (in6_addr**) hp->h_addr_list;
474 for (int i = 0; list[i] != NULL; i++) {
475 sockaddr_in6 sin6 = { .sin6_family = AF_INET6, .sin6_addr = *list[i] };
476 addIpAddrWithinLimit(ip_addrs, (sockaddr*) &sin6, sizeof(sin6));
477 total_ip_addr_count++;
478 }
479 }
480 }
481 switch (mReportingLevel) {
482 case INetdEventListener::REPORTING_LEVEL_NONE:
483 // Reporting is off.
484 break;
485 case INetdEventListener::REPORTING_LEVEL_METRICS:
486 // Metrics reporting is on. Send metrics.
487 mNetdEventListener->onDnsEvent(mNetId, INetdEventListener::EVENT_GETHOSTBYNAME,
488 h_errno, latencyMs, String16(""), {}, -1, -1);
489 break;
490 case INetdEventListener::REPORTING_LEVEL_FULL:
491 // Full event info reporting is on. Send full info.
492 mNetdEventListener->onDnsEvent(mNetId, INetdEventListener::EVENT_GETHOSTBYNAME,
493 h_errno, latencyMs, String16(mName), ip_addrs,
494 total_ip_addr_count, mClient->getUid());
495 break;
496 }
497 }
498
499 mClient->decRef();
500 }
501
502
503 /*******************************************************
504 * GetHostByAddr *
505 *******************************************************/
GetHostByAddrCmd(const DnsProxyListener * dnsProxyListener)506 DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd(const DnsProxyListener* dnsProxyListener) :
507 NetdCommand("gethostbyaddr"),
508 mDnsProxyListener(dnsProxyListener) {
509 }
510
runCommand(SocketClient * cli,int argc,char ** argv)511 int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli,
512 int argc, char **argv) {
513 if (DBG) {
514 for (int i = 0; i < argc; i++) {
515 ALOGD("argv[%i]=%s", i, argv[i]);
516 }
517 }
518 if (argc != 5) {
519 char* msg = NULL;
520 asprintf(&msg, "Invalid number of arguments to gethostbyaddr: %i", argc);
521 ALOGW("%s", msg);
522 cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
523 free(msg);
524 return -1;
525 }
526
527 char* addrStr = argv[1];
528 int addrLen = atoi(argv[2]);
529 int addrFamily = atoi(argv[3]);
530 uid_t uid = cli->getUid();
531 unsigned netId = strtoul(argv[4], NULL, 10);
532
533 void* addr = malloc(sizeof(struct in6_addr));
534 errno = 0;
535 int result = inet_pton(addrFamily, addrStr, addr);
536 if (result <= 0) {
537 char* msg = NULL;
538 asprintf(&msg, "inet_pton(\"%s\") failed %s", addrStr, strerror(errno));
539 ALOGW("%s", msg);
540 cli->sendMsg(ResponseCode::OperationFailed, msg, false);
541 free(addr);
542 free(msg);
543 return -1;
544 }
545
546 uint32_t mark = mDnsProxyListener->mNetCtrl->getNetworkForDns(&netId, uid);
547
548 DnsProxyListener::GetHostByAddrHandler* handler =
549 new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily, netId, mark);
550 tryThreadOrError(cli, handler);
551 return 0;
552 }
553
GetHostByAddrHandler(SocketClient * c,void * address,int addressLen,int addressFamily,unsigned netId,uint32_t mark)554 DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c,
555 void* address,
556 int addressLen,
557 int addressFamily,
558 unsigned netId,
559 uint32_t mark)
560 : mClient(c),
561 mAddress(address),
562 mAddressLen(addressLen),
563 mAddressFamily(addressFamily),
564 mNetId(netId),
565 mMark(mark) {
566 }
567
~GetHostByAddrHandler()568 DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
569 free(mAddress);
570 }
571
run()572 void DnsProxyListener::GetHostByAddrHandler::run() {
573 if (DBG) {
574 ALOGD("DnsProxyListener::GetHostByAddrHandler::run\n");
575 }
576 struct hostent* hp;
577
578 // NOTE gethostbyaddr should take a void* but bionic thinks it should be char*
579 hp = android_gethostbyaddrfornet((char*)mAddress, mAddressLen, mAddressFamily, mNetId, mMark);
580
581 if (DBG) {
582 ALOGD("GetHostByAddrHandler::run gethostbyaddr errno: %s hp->h_name = %s, name_len = %zu\n",
583 hp ? "success" : strerror(errno),
584 (hp && hp->h_name) ? hp->h_name : "null",
585 (hp && hp->h_name) ? strlen(hp->h_name) + 1 : 0);
586 }
587
588 bool success = true;
589 if (hp) {
590 success = mClient->sendCode(ResponseCode::DnsProxyQueryResult) == 0;
591 success &= sendhostent(mClient, hp);
592 } else {
593 success = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, NULL, 0) == 0;
594 }
595
596 if (!success) {
597 ALOGW("GetHostByAddrHandler: Error writing DNS result to client\n");
598 }
599 mClient->decRef();
600 }
601
602 } // namespace net
603 } // namespace android
604