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