DnsProxyListener.cpp revision 89b99f2375271f2020dbb41ae96afd8c17b8e11a
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 27#define LOG_TAG "DnsProxyListener" 28#define DBG 0 29 30#include <cutils/log.h> 31#include <sysutils/SocketClient.h> 32 33#include "DnsProxyListener.h" 34 35DnsProxyListener::DnsProxyListener() : 36 FrameworkListener("dnsproxyd") { 37 registerCmd(new GetAddrInfoCmd()); 38} 39 40DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() { 41 free(mHost); 42 free(mService); 43 free(mHints); 44} 45 46void DnsProxyListener::GetAddrInfoHandler::start() { 47 pthread_create(&mThread, NULL, 48 DnsProxyListener::GetAddrInfoHandler::threadStart, this); 49} 50 51void* DnsProxyListener::GetAddrInfoHandler::threadStart(void* obj) { 52 GetAddrInfoHandler* handler = reinterpret_cast<GetAddrInfoHandler*>(obj); 53 handler->run(); 54 delete handler; 55 pthread_exit(NULL); 56 return NULL; 57} 58 59// Sends 4 bytes of big-endian length, followed by the data. 60// Returns true on success. 61static bool sendLenAndData(SocketClient *c, const int len, const void* data) { 62 uint32_t len_be = htonl(len); 63 return c->sendData(&len_be, 4) == 0 && 64 (len == 0 || c->sendData(data, len) == 0); 65} 66 67void DnsProxyListener::GetAddrInfoHandler::run() { 68 if (DBG) { 69 LOGD("GetAddrInfoHandler, now for %s / %s", mHost, mService); 70 } 71 72 struct addrinfo* result = NULL; 73 int rv = getaddrinfo(mHost, mService, mHints, &result); 74 bool success = mClient->sendData(&rv, sizeof(rv)); 75 if (rv == 0) { 76 struct addrinfo* ai = result; 77 while (ai && success) { 78 success = sendLenAndData(mClient, sizeof(struct addrinfo), ai) 79 && sendLenAndData(mClient, ai->ai_addrlen, ai->ai_addr) 80 && sendLenAndData(mClient, 81 ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0, 82 ai->ai_canonname); 83 ai = ai->ai_next; 84 } 85 success = success && sendLenAndData(mClient, 0, ""); 86 } 87 if (result) { 88 freeaddrinfo(result); 89 } 90 if (!success) { 91 LOGW("Error writing DNS result to client"); 92 } 93} 94 95DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd() : 96 NetdCommand("getaddrinfo") { 97} 98 99int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, 100 int argc, char **argv) { 101 if (argc != 7) { 102 LOGW("Invalid number of arguments to getaddrinfo"); 103 return 0; 104 } 105 106 char* name = argv[1]; 107 if (strcmp("^", name) == 0) { 108 name = NULL; 109 } else { 110 name = strdup(name); 111 } 112 113 char* service = argv[2]; 114 if (strcmp("^", service) == 0) { 115 service = NULL; 116 } else { 117 service = strdup(service); 118 } 119 120 struct addrinfo* hints = NULL; 121 int ai_flags = atoi(argv[3]); 122 int ai_family = atoi(argv[4]); 123 int ai_socktype = atoi(argv[5]); 124 int ai_protocol = atoi(argv[6]); 125 if (ai_flags != -1 || ai_family != -1 || 126 ai_socktype != -1 || ai_protocol != -1) { 127 hints = (struct addrinfo*) calloc(1, sizeof(struct addrinfo)); 128 hints->ai_flags = ai_flags; 129 hints->ai_family = ai_family; 130 hints->ai_socktype = ai_socktype; 131 hints->ai_protocol = ai_protocol; 132 } 133 134 if (DBG) { 135 LOGD("GetAddrInfoHandler for %s / %s", 136 name ? name : "[nullhost]", 137 service ? service : "[nullservice]"); 138 } 139 140 DnsProxyListener::GetAddrInfoHandler* handler = 141 new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints); 142 handler->start(); 143 144 145 return 0; 146} 147