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