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
51using android::String16;
52using android::net::metrics::INetdEventListener;
53
54namespace android {
55namespace net {
56
57namespace {
58
59template<typename T>
60void* threadMain(void* obj) {
61    std::unique_ptr<T> handler(reinterpret_cast<T*>(obj));
62    handler->run();
63    return nullptr;
64}
65
66struct scoped_pthread_attr {
67    scoped_pthread_attr() { pthread_attr_init(&attr); }
68    ~scoped_pthread_attr() { pthread_attr_destroy(&attr); }
69
70    int detach() {
71        return pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
72    }
73
74    pthread_attr_t attr;
75};
76
77template<typename T>
78int 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
96template<typename T>
97void 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
117DnsProxyListener::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
124DnsProxyListener::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
137DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
138    free(mHost);
139    free(mService);
140    free(mHints);
141}
142
143static 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.
150static 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
155static 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
182static 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
218void 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
286void 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
299DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd(DnsProxyListener* dnsProxyListener) :
300    NetdCommand("getaddrinfo"),
301    mDnsProxyListener(dnsProxyListener) {
302}
303
304int 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 *******************************************************/
375DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd(DnsProxyListener* dnsProxyListener) :
376      NetdCommand("gethostbyname"),
377      mDnsProxyListener(dnsProxyListener) {
378}
379
380int 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
417DnsProxyListener::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
429DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() {
430    free(mName);
431}
432
433void 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 *******************************************************/
506DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd(const DnsProxyListener* dnsProxyListener) :
507        NetdCommand("gethostbyaddr"),
508        mDnsProxyListener(dnsProxyListener) {
509}
510
511int 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
554DnsProxyListener::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
568DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
569    free(mAddress);
570}
571
572void 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