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