Home | History | Annotate | Download | only in server
      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 <netdb.h>
     22 #include <netinet/in.h>
     23 #include <stdlib.h>
     24 #include <sys/socket.h>
     25 #include <sys/types.h>
     26 #include <string.h>
     27 #include <pthread.h>
     28 #include <resolv_netid.h>
     29 #include <net/if.h>
     30 
     31 #define LOG_TAG "DnsProxyListener"
     32 #define DBG 0
     33 #define VDBG 0
     34 
     35 #include <cutils/log.h>
     36 #include <sysutils/SocketClient.h>
     37 
     38 #include "Fwmark.h"
     39 #include "DnsProxyListener.h"
     40 #include "NetdConstants.h"
     41 #include "NetworkController.h"
     42 #include "ResponseCode.h"
     43 
     44 DnsProxyListener::DnsProxyListener(const NetworkController* netCtrl) :
     45         FrameworkListener("dnsproxyd"), mNetCtrl(netCtrl) {
     46     registerCmd(new GetAddrInfoCmd(this));
     47     registerCmd(new GetHostByAddrCmd(this));
     48     registerCmd(new GetHostByNameCmd(this));
     49 }
     50 
     51 DnsProxyListener::GetAddrInfoHandler::GetAddrInfoHandler(SocketClient *c,
     52                                                          char* host,
     53                                                          char* service,
     54                                                          struct addrinfo* hints,
     55                                                          unsigned netId,
     56                                                          uint32_t mark)
     57         : mClient(c),
     58           mHost(host),
     59           mService(service),
     60           mHints(hints),
     61           mNetId(netId),
     62           mMark(mark) {
     63 }
     64 
     65 DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
     66     free(mHost);
     67     free(mService);
     68     free(mHints);
     69 }
     70 
     71 void DnsProxyListener::GetAddrInfoHandler::start() {
     72     pthread_t thread;
     73     pthread_create(&thread, NULL,
     74                    DnsProxyListener::GetAddrInfoHandler::threadStart, this);
     75     pthread_detach(thread);
     76 }
     77 
     78 void* DnsProxyListener::GetAddrInfoHandler::threadStart(void* obj) {
     79     GetAddrInfoHandler* handler = reinterpret_cast<GetAddrInfoHandler*>(obj);
     80     handler->run();
     81     delete handler;
     82     pthread_exit(NULL);
     83     return NULL;
     84 }
     85 
     86 // Sends 4 bytes of big-endian length, followed by the data.
     87 // Returns true on success.
     88 static bool sendLenAndData(SocketClient *c, const int len, const void* data) {
     89     uint32_t len_be = htonl(len);
     90     return c->sendData(&len_be, 4) == 0 &&
     91         (len == 0 || c->sendData(data, len) == 0);
     92 }
     93 
     94 // Returns true on success
     95 static bool sendhostent(SocketClient *c, struct hostent *hp) {
     96     bool success = true;
     97     int i;
     98     if (hp->h_name != NULL) {
     99         success &= sendLenAndData(c, strlen(hp->h_name)+1, hp->h_name);
    100     } else {
    101         success &= sendLenAndData(c, 0, "") == 0;
    102     }
    103 
    104     for (i=0; hp->h_aliases[i] != NULL; i++) {
    105         success &= sendLenAndData(c, strlen(hp->h_aliases[i])+1, hp->h_aliases[i]);
    106     }
    107     success &= sendLenAndData(c, 0, ""); // null to indicate we're done
    108 
    109     uint32_t buf = htonl(hp->h_addrtype);
    110     success &= c->sendData(&buf, sizeof(buf)) == 0;
    111 
    112     buf = htonl(hp->h_length);
    113     success &= c->sendData(&buf, sizeof(buf)) == 0;
    114 
    115     for (i=0; hp->h_addr_list[i] != NULL; i++) {
    116         success &= sendLenAndData(c, 16, hp->h_addr_list[i]);
    117     }
    118     success &= sendLenAndData(c, 0, ""); // null to indicate we're done
    119     return success;
    120 }
    121 
    122 void DnsProxyListener::GetAddrInfoHandler::run() {
    123     if (DBG) {
    124         ALOGD("GetAddrInfoHandler, now for %s / %s / %u / %u", mHost, mService, mNetId, mMark);
    125     }
    126 
    127     struct addrinfo* result = NULL;
    128     uint32_t rv = android_getaddrinfofornet(mHost, mService, mHints, mNetId, mMark, &result);
    129     if (rv) {
    130         // getaddrinfo failed
    131         mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, &rv, sizeof(rv));
    132     } else {
    133         bool success = !mClient->sendCode(ResponseCode::DnsProxyQueryResult);
    134         struct addrinfo* ai = result;
    135         while (ai && success) {
    136             success = sendLenAndData(mClient, sizeof(struct addrinfo), ai)
    137                 && sendLenAndData(mClient, ai->ai_addrlen, ai->ai_addr)
    138                 && sendLenAndData(mClient,
    139                                   ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0,
    140                                   ai->ai_canonname);
    141             ai = ai->ai_next;
    142         }
    143         success = success && sendLenAndData(mClient, 0, "");
    144         if (!success) {
    145             ALOGW("Error writing DNS result to client");
    146         }
    147     }
    148     if (result) {
    149         freeaddrinfo(result);
    150     }
    151     mClient->decRef();
    152 }
    153 
    154 DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd(const DnsProxyListener* dnsProxyListener) :
    155     NetdCommand("getaddrinfo"),
    156     mDnsProxyListener(dnsProxyListener) {
    157 }
    158 
    159 int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli,
    160                                             int argc, char **argv) {
    161     if (DBG) {
    162         for (int i = 0; i < argc; i++) {
    163             ALOGD("argv[%i]=%s", i, argv[i]);
    164         }
    165     }
    166     if (argc != 8) {
    167         char* msg = NULL;
    168         asprintf( &msg, "Invalid number of arguments to getaddrinfo: %i", argc);
    169         ALOGW("%s", msg);
    170         cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
    171         free(msg);
    172         return -1;
    173     }
    174 
    175     char* name = argv[1];
    176     if (strcmp("^", name) == 0) {
    177         name = NULL;
    178     } else {
    179         name = strdup(name);
    180     }
    181 
    182     char* service = argv[2];
    183     if (strcmp("^", service) == 0) {
    184         service = NULL;
    185     } else {
    186         service = strdup(service);
    187     }
    188 
    189     struct addrinfo* hints = NULL;
    190     int ai_flags = atoi(argv[3]);
    191     int ai_family = atoi(argv[4]);
    192     int ai_socktype = atoi(argv[5]);
    193     int ai_protocol = atoi(argv[6]);
    194     unsigned netId = strtoul(argv[7], NULL, 10);
    195     uid_t uid = cli->getUid();
    196 
    197     uint32_t mark = mDnsProxyListener->mNetCtrl->getNetworkForDns(&netId, uid);
    198 
    199     if (ai_flags != -1 || ai_family != -1 ||
    200         ai_socktype != -1 || ai_protocol != -1) {
    201         hints = (struct addrinfo*) calloc(1, sizeof(struct addrinfo));
    202         hints->ai_flags = ai_flags;
    203         hints->ai_family = ai_family;
    204         hints->ai_socktype = ai_socktype;
    205         hints->ai_protocol = ai_protocol;
    206 
    207         // Only implement AI_ADDRCONFIG if application is using default network since our
    208         // implementation only works on the default network.
    209         if ((hints->ai_flags & AI_ADDRCONFIG) &&
    210                 netId != mDnsProxyListener->mNetCtrl->getDefaultNetwork()) {
    211             hints->ai_flags &= ~AI_ADDRCONFIG;
    212         }
    213     }
    214 
    215     if (DBG) {
    216         ALOGD("GetAddrInfoHandler for %s / %s / %u / %d / %u",
    217              name ? name : "[nullhost]",
    218              service ? service : "[nullservice]",
    219              netId, uid, mark);
    220     }
    221 
    222     cli->incRef();
    223     DnsProxyListener::GetAddrInfoHandler* handler =
    224             new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, netId, mark);
    225     handler->start();
    226 
    227     return 0;
    228 }
    229 
    230 /*******************************************************
    231  *                  GetHostByName                      *
    232  *******************************************************/
    233 DnsProxyListener::GetHostByNameCmd::GetHostByNameCmd(const DnsProxyListener* dnsProxyListener) :
    234       NetdCommand("gethostbyname"),
    235       mDnsProxyListener(dnsProxyListener) {
    236 }
    237 
    238 int DnsProxyListener::GetHostByNameCmd::runCommand(SocketClient *cli,
    239                                             int argc, char **argv) {
    240     if (DBG) {
    241         for (int i = 0; i < argc; i++) {
    242             ALOGD("argv[%i]=%s", i, argv[i]);
    243         }
    244     }
    245     if (argc != 4) {
    246         char* msg = NULL;
    247         asprintf(&msg, "Invalid number of arguments to gethostbyname: %i", argc);
    248         ALOGW("%s", msg);
    249         cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
    250         free(msg);
    251         return -1;
    252     }
    253 
    254     uid_t uid = cli->getUid();
    255     unsigned netId = strtoul(argv[1], NULL, 10);
    256     char* name = argv[2];
    257     int af = atoi(argv[3]);
    258 
    259     if (strcmp(name, "^") == 0) {
    260         name = NULL;
    261     } else {
    262         name = strdup(name);
    263     }
    264 
    265     uint32_t mark = mDnsProxyListener->mNetCtrl->getNetworkForDns(&netId, uid);
    266 
    267     cli->incRef();
    268     DnsProxyListener::GetHostByNameHandler* handler =
    269             new DnsProxyListener::GetHostByNameHandler(cli, name, af, netId, mark);
    270     handler->start();
    271 
    272     return 0;
    273 }
    274 
    275 DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c,
    276                                                              char* name,
    277                                                              int af,
    278                                                              unsigned netId,
    279                                                              uint32_t mark)
    280         : mClient(c),
    281           mName(name),
    282           mAf(af),
    283           mNetId(netId),
    284           mMark(mark) {
    285 }
    286 
    287 DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() {
    288     free(mName);
    289 }
    290 
    291 void DnsProxyListener::GetHostByNameHandler::start() {
    292     pthread_t thread;
    293     pthread_create(&thread, NULL,
    294             DnsProxyListener::GetHostByNameHandler::threadStart, this);
    295     pthread_detach(thread);
    296 }
    297 
    298 void* DnsProxyListener::GetHostByNameHandler::threadStart(void* obj) {
    299     GetHostByNameHandler* handler = reinterpret_cast<GetHostByNameHandler*>(obj);
    300     handler->run();
    301     delete handler;
    302     pthread_exit(NULL);
    303     return NULL;
    304 }
    305 
    306 void DnsProxyListener::GetHostByNameHandler::run() {
    307     if (DBG) {
    308         ALOGD("DnsProxyListener::GetHostByNameHandler::run\n");
    309     }
    310 
    311     struct hostent* hp;
    312 
    313     hp = android_gethostbynamefornet(mName, mAf, mNetId, mMark);
    314 
    315     if (DBG) {
    316         ALOGD("GetHostByNameHandler::run gethostbyname errno: %s hp->h_name = %s, name_len = %zu\n",
    317                 hp ? "success" : strerror(errno),
    318                 (hp && hp->h_name) ? hp->h_name : "null",
    319                 (hp && hp->h_name) ? strlen(hp->h_name) + 1 : 0);
    320     }
    321 
    322     bool success = true;
    323     if (hp) {
    324         success = mClient->sendCode(ResponseCode::DnsProxyQueryResult) == 0;
    325         success &= sendhostent(mClient, hp);
    326     } else {
    327         success = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, NULL, 0) == 0;
    328     }
    329 
    330     if (!success) {
    331         ALOGW("GetHostByNameHandler: Error writing DNS result to client\n");
    332     }
    333     mClient->decRef();
    334 }
    335 
    336 
    337 /*******************************************************
    338  *                  GetHostByAddr                      *
    339  *******************************************************/
    340 DnsProxyListener::GetHostByAddrCmd::GetHostByAddrCmd(const DnsProxyListener* dnsProxyListener) :
    341         NetdCommand("gethostbyaddr"),
    342         mDnsProxyListener(dnsProxyListener) {
    343 }
    344 
    345 int DnsProxyListener::GetHostByAddrCmd::runCommand(SocketClient *cli,
    346                                             int argc, char **argv) {
    347     if (DBG) {
    348         for (int i = 0; i < argc; i++) {
    349             ALOGD("argv[%i]=%s", i, argv[i]);
    350         }
    351     }
    352     if (argc != 5) {
    353         char* msg = NULL;
    354         asprintf(&msg, "Invalid number of arguments to gethostbyaddr: %i", argc);
    355         ALOGW("%s", msg);
    356         cli->sendMsg(ResponseCode::CommandParameterError, msg, false);
    357         free(msg);
    358         return -1;
    359     }
    360 
    361     char* addrStr = argv[1];
    362     int addrLen = atoi(argv[2]);
    363     int addrFamily = atoi(argv[3]);
    364     uid_t uid = cli->getUid();
    365     unsigned netId = strtoul(argv[4], NULL, 10);
    366 
    367     void* addr = malloc(sizeof(struct in6_addr));
    368     errno = 0;
    369     int result = inet_pton(addrFamily, addrStr, addr);
    370     if (result <= 0) {
    371         char* msg = NULL;
    372         asprintf(&msg, "inet_pton(\"%s\") failed %s", addrStr, strerror(errno));
    373         ALOGW("%s", msg);
    374         cli->sendMsg(ResponseCode::OperationFailed, msg, false);
    375         free(addr);
    376         free(msg);
    377         return -1;
    378     }
    379 
    380     uint32_t mark = mDnsProxyListener->mNetCtrl->getNetworkForDns(&netId, uid);
    381 
    382     cli->incRef();
    383     DnsProxyListener::GetHostByAddrHandler* handler =
    384             new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily, netId, mark);
    385     handler->start();
    386 
    387     return 0;
    388 }
    389 
    390 DnsProxyListener::GetHostByAddrHandler::GetHostByAddrHandler(SocketClient* c,
    391                                                              void* address,
    392                                                              int   addressLen,
    393                                                              int   addressFamily,
    394                                                              unsigned netId,
    395                                                              uint32_t mark)
    396         : mClient(c),
    397           mAddress(address),
    398           mAddressLen(addressLen),
    399           mAddressFamily(addressFamily),
    400           mNetId(netId),
    401           mMark(mark) {
    402 }
    403 
    404 DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
    405     free(mAddress);
    406 }
    407 
    408 void DnsProxyListener::GetHostByAddrHandler::start() {
    409     pthread_t thread;
    410     pthread_create(&thread, NULL,
    411                    DnsProxyListener::GetHostByAddrHandler::threadStart, this);
    412     pthread_detach(thread);
    413 }
    414 
    415 void* DnsProxyListener::GetHostByAddrHandler::threadStart(void* obj) {
    416     GetHostByAddrHandler* handler = reinterpret_cast<GetHostByAddrHandler*>(obj);
    417     handler->run();
    418     delete handler;
    419     pthread_exit(NULL);
    420     return NULL;
    421 }
    422 
    423 void DnsProxyListener::GetHostByAddrHandler::run() {
    424     if (DBG) {
    425         ALOGD("DnsProxyListener::GetHostByAddrHandler::run\n");
    426     }
    427     struct hostent* hp;
    428 
    429     // NOTE gethostbyaddr should take a void* but bionic thinks it should be char*
    430     hp = android_gethostbyaddrfornet((char*)mAddress, mAddressLen, mAddressFamily, mNetId, mMark);
    431 
    432     if (DBG) {
    433         ALOGD("GetHostByAddrHandler::run gethostbyaddr errno: %s hp->h_name = %s, name_len = %zu\n",
    434                 hp ? "success" : strerror(errno),
    435                 (hp && hp->h_name) ? hp->h_name : "null",
    436                 (hp && hp->h_name) ? strlen(hp->h_name) + 1 : 0);
    437     }
    438 
    439     bool success = true;
    440     if (hp) {
    441         success = mClient->sendCode(ResponseCode::DnsProxyQueryResult) == 0;
    442         success &= sendhostent(mClient, hp);
    443     } else {
    444         success = mClient->sendBinaryMsg(ResponseCode::DnsProxyOperationFailed, NULL, 0) == 0;
    445     }
    446 
    447     if (!success) {
    448         ALOGW("GetHostByAddrHandler: Error writing DNS result to client\n");
    449     }
    450     mClient->decRef();
    451 }
    452