DnsProxyListener.cpp revision 4e248e5a7a542067fd3f0467680eef2f92b1e195
14e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick/*
24e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * Copyright (C) 2010 The Android Open Source Project
34e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick *
44e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * Licensed under the Apache License, Version 2.0 (the "License");
54e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * you may not use this file except in compliance with the License.
64e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * You may obtain a copy of the License at
74e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick *
84e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick *      http://www.apache.org/licenses/LICENSE-2.0
94e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick *
104e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * Unless required by applicable law or agreed to in writing, software
114e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * distributed under the License is distributed on an "AS IS" BASIS,
124e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * See the License for the specific language governing permissions and
144e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick * limitations under the License.
154e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick */
164e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
174e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <arpa/inet.h>
184e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <dirent.h>
194e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <errno.h>
204e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <linux/if.h>
214e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <netdb.h>
224e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <netinet/in.h>
234e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <stdlib.h>
244e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <sys/socket.h>
254e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <sys/types.h>
264e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
274e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#define LOG_TAG "DnsProxyListener"
284e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#define DBG 0
294e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
304e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <cutils/log.h>
314e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include <sysutils/SocketClient.h>
324e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
334e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick#include "DnsProxyListener.h"
344e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
354e248e5a7a542067fd3f0467680eef2f92b1e195Brad FitzpatrickDnsProxyListener::DnsProxyListener() :
364e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick                 FrameworkListener("dnsproxyd") {
374e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    registerCmd(new GetAddrInfoCmd());
384e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick}
394e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
404e248e5a7a542067fd3f0467680eef2f92b1e195Brad FitzpatrickDnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
414e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    free(mHost);
424e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    free(mService);
434e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    free(mHints);
444e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick}
454e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
464e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrickvoid DnsProxyListener::GetAddrInfoHandler::start() {
474e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    pthread_create(&mThread, NULL,
484e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick                   DnsProxyListener::GetAddrInfoHandler::threadStart, this);
494e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick}
504e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
514e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrickvoid* DnsProxyListener::GetAddrInfoHandler::threadStart(void* obj) {
524e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    GetAddrInfoHandler* handler = reinterpret_cast<GetAddrInfoHandler*>(obj);
534e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    handler->run();
544e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    delete handler;
554e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    pthread_exit(NULL);
564e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    return NULL;
574e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick}
584e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
594e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick// Sends 4 bytes of big-endian length, followed by the data.
604e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick// Returns true on success.
614e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrickstatic bool sendLenAndData(SocketClient *c, const int len, const void* data) {
624e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    uint32_t len_be = htonl(len);
634e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    return c->sendData(&len_be, 4) == 0 && c->sendData(data, len) == 0;
644e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick}
654e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
664e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrickvoid DnsProxyListener::GetAddrInfoHandler::run() {
674e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (DBG) {
684e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        LOGD("GetAddrInfoHandler, now for %s / %s", mHost, mService);
694e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
704e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
714e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    struct addrinfo* result = NULL;
724e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    int rv = getaddrinfo(mHost, mService, mHints, &result);
734e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    bool success = mClient->sendData(&rv, sizeof(rv));
744e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (rv == 0) {
754e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        struct addrinfo* ai = result;
764e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        while (ai && success) {
774e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick            success = sendLenAndData(mClient, sizeof(struct addrinfo), ai)
784e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick                && sendLenAndData(mClient, ai->ai_addrlen, ai->ai_addr)
794e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick                && sendLenAndData(mClient,
804e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick                                  ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0,
814e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick                                  ai->ai_canonname);
824e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick            ai = ai->ai_next;
834e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        }
844e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        success = success && sendLenAndData(mClient, 0, "");
854e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
864e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (result) {
874e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        freeaddrinfo(result);
884e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
894e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (!success) {
904e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        LOGW("Error writing DNS result to client");
914e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
924e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick}
934e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
944e248e5a7a542067fd3f0467680eef2f92b1e195Brad FitzpatrickDnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd() :
954e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    NetdCommand("getaddrinfo") {
964e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick}
974e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
984e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrickint DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli,
994e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick                                            int argc, char **argv) {
1004e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (argc != 7) {
1014e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        LOGW("Invalid number of arguments to getaddrinfo");
1024e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        return 0;
1034e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
1044e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
1054e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    char* name = argv[1];
1064e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (strcmp("^", name) == 0) {
1074e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        name = NULL;
1084e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    } else {
1094e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        name = strdup(name);
1104e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
1114e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
1124e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    char* service = argv[2];
1134e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (strcmp("^", service) == 0) {
1144e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        service = NULL;
1154e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    } else {
1164e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        service = strdup(service);
1174e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
1184e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
1194e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    struct addrinfo* hints = NULL;
1204e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    int ai_flags = atoi(argv[3]);
1214e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    int ai_family = atoi(argv[4]);
1224e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    int ai_socktype = atoi(argv[5]);
1234e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    int ai_protocol = atoi(argv[6]);
1244e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (ai_flags != -1 || ai_family != -1 ||
1254e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        ai_socktype != -1 || ai_protocol != -1) {
1264e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        hints = (struct addrinfo*) calloc(1, sizeof(struct addrinfo));
1274e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        hints->ai_flags = ai_flags;
1284e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        hints->ai_family = ai_family;
1294e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        hints->ai_socktype = ai_socktype;
1304e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        hints->ai_protocol = ai_protocol;
1314e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
1324e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
1334e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    if (DBG) {
1344e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        LOGD("GetAddrInfoHandler for %s / %s",
1354e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick             name ? name : "[nullhost]",
1364e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick             service ? service : "[nullservice]");
1374e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    }
1384e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
1394e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    DnsProxyListener::GetAddrInfoHandler* handler =
1404e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick        new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints);
1414e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    handler->start();
1424e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
1434e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick
1444e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick    return 0;
1454e248e5a7a542067fd3f0467680eef2f92b1e195Brad Fitzpatrick}
146