DnsProxyListener.cpp revision 007e987fee7e815e0c4bc820f434a632b7a69a9d
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 && c->sendData(data, len) == 0; 64} 65 66void DnsProxyListener::GetAddrInfoHandler::run() { 67 if (DBG) { 68 LOGD("GetAddrInfoHandler, now for %s / %s", mHost, mService); 69 } 70 71 struct addrinfo* result = NULL; 72 int rv = getaddrinfo(mHost, mService, mHints, &result); 73 bool success = mClient->sendData(&rv, sizeof(rv)); 74 if (rv == 0) { 75 struct addrinfo* ai = result; 76 while (ai && success) { 77 success = sendLenAndData(mClient, sizeof(struct addrinfo), ai) 78 && sendLenAndData(mClient, ai->ai_addrlen, ai->ai_addr) 79 && sendLenAndData(mClient, 80 ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0, 81 ai->ai_canonname); 82 ai = ai->ai_next; 83 } 84 success = success && sendLenAndData(mClient, 0, ""); 85 } 86 if (result) { 87 freeaddrinfo(result); 88 } 89 if (!success) { 90 LOGW("Error writing DNS result to client"); 91 } 92} 93 94DnsProxyListener::GetAddrInfoCmd::GetAddrInfoCmd() : 95 NetdCommand("getaddrinfo") { 96} 97 98int DnsProxyListener::GetAddrInfoCmd::runCommand(SocketClient *cli, 99 int argc, char **argv) { 100 if (argc != 7) { 101 LOGW("Invalid number of arguments to getaddrinfo"); 102 return 0; 103 } 104 105 char* name = argv[1]; 106 if (strcmp("^", name) == 0) { 107 name = NULL; 108 } else { 109 name = strdup(name); 110 } 111 112 char* service = argv[2]; 113 if (strcmp("^", service) == 0) { 114 service = NULL; 115 } else { 116 service = strdup(service); 117 } 118 119 struct addrinfo* hints = NULL; 120 int ai_flags = atoi(argv[3]); 121 int ai_family = atoi(argv[4]); 122 int ai_socktype = atoi(argv[5]); 123 int ai_protocol = atoi(argv[6]); 124 if (ai_flags != -1 || ai_family != -1 || 125 ai_socktype != -1 || ai_protocol != -1) { 126 hints = (struct addrinfo*) calloc(1, sizeof(struct addrinfo)); 127 hints->ai_flags = ai_flags; 128 hints->ai_family = ai_family; 129 hints->ai_socktype = ai_socktype; 130 hints->ai_protocol = ai_protocol; 131 } 132 133 if (DBG) { 134 LOGD("GetAddrInfoHandler for %s / %s", 135 name ? name : "[nullhost]", 136 service ? service : "[nullservice]"); 137 } 138 139 DnsProxyListener::GetAddrInfoHandler* handler = 140 new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints); 141 handler->start(); 142 143 144 return 0; 145} 146