• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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