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