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