dnsproxy: Fallback to resolv.conf if dnsproxy fails
[platform/upstream/connman.git] / src / dnsproxy.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <stdint.h>
30 #include <arpa/inet.h>
31 #include <netinet/in.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netdb.h>
35
36 #include <glib.h>
37
38 #include "connman.h"
39
40 #if __BYTE_ORDER == __LITTLE_ENDIAN
41 struct domain_hdr {
42         uint16_t id;
43         uint8_t rd:1;
44         uint8_t tc:1;
45         uint8_t aa:1;
46         uint8_t opcode:4;
47         uint8_t qr:1;
48         uint8_t rcode:4;
49         uint8_t z:3;
50         uint8_t ra:1;
51         uint16_t qdcount;
52         uint16_t ancount;
53         uint16_t nscount;
54         uint16_t arcount;
55 } __attribute__ ((packed));
56 #elif __BYTE_ORDER == __BIG_ENDIAN
57 struct domain_hdr {
58         uint16_t id;
59         uint8_t qr:1;
60         uint8_t opcode:4;
61         uint8_t aa:1;
62         uint8_t tc:1;
63         uint8_t rd:1;
64         uint8_t ra:1;
65         uint8_t z:3;
66         uint8_t rcode:4;
67         uint16_t qdcount;
68         uint16_t ancount;
69         uint16_t nscount;
70         uint16_t arcount;
71 } __attribute__ ((packed));
72 #else
73 #error "Unknown byte order"
74 #endif
75
76 struct partial_reply {
77         uint16_t len;
78         uint16_t received;
79         unsigned char buf[];
80 };
81
82 struct server_data {
83         char *interface;
84         GList *domains;
85         char *server;
86         int protocol;
87         GIOChannel *channel;
88         guint watch;
89         guint timeout;
90         gboolean enabled;
91         gboolean connected;
92         struct partial_reply *incoming_reply;
93 };
94
95 struct request_data {
96         union {
97                 struct sockaddr_in6 __sin6; /* Only for the length */
98                 struct sockaddr sa;
99         };
100         socklen_t sa_len;
101         int client_sk;
102         int protocol;
103         guint16 srcid;
104         guint16 dstid;
105         guint16 altid;
106         guint timeout;
107         guint watch;
108         guint numserv;
109         guint numresp;
110         gpointer request;
111         gsize request_len;
112         gpointer name;
113         gpointer resp;
114         gsize resplen;
115 };
116
117 static GSList *server_list = NULL;
118 static GSList *request_list = NULL;
119 static GSList *request_pending_list = NULL;
120 static guint16 request_id = 0x0000;
121
122 static GIOChannel *udp_listener_channel = NULL;
123 static guint udp_listener_watch = 0;
124 static GIOChannel *tcp_listener_channel = NULL;
125 static guint tcp_listener_watch = 0;
126
127 static int protocol_offset(int protocol)
128 {
129         switch (protocol) {
130         case IPPROTO_UDP:
131                 return 0;
132
133         case IPPROTO_TCP:
134                 return 2;
135
136         default:
137                 return -EINVAL;
138         }
139
140 }
141
142 static struct request_data *find_request(guint16 id)
143 {
144         GSList *list;
145
146         for (list = request_list; list; list = list->next) {
147                 struct request_data *req = list->data;
148
149                 if (req->dstid == id || req->altid == id)
150                         return req;
151         }
152
153         return NULL;
154 }
155
156 static struct server_data *find_server(const char *interface,
157                                         const char *server,
158                                                 int protocol)
159 {
160         GSList *list;
161
162         DBG("interface %s server %s", interface, server);
163
164         for (list = server_list; list; list = list->next) {
165                 struct server_data *data = list->data;
166
167                 if (interface == NULL && data->interface == NULL &&
168                                 g_str_equal(data->server, server) == TRUE &&
169                                 data->protocol == protocol)
170                         return data;
171
172                 if (interface == NULL ||
173                                 data->interface == NULL || data->server == NULL)
174                         continue;
175
176                 if (g_str_equal(data->interface, interface) == TRUE &&
177                                 g_str_equal(data->server, server) == TRUE &&
178                                 data->protocol == protocol)
179                         return data;
180         }
181
182         return NULL;
183 }
184
185
186 static void send_response(int sk, unsigned char *buf, int len,
187                                 const struct sockaddr *to, socklen_t tolen,
188                                 int protocol)
189 {
190         struct domain_hdr *hdr;
191         int err, offset = protocol_offset(protocol);
192
193         DBG("");
194
195         if (offset < 0)
196                 return;
197
198         if (len < 12)
199                 return;
200
201         hdr = (void *) (buf + offset);
202
203         DBG("id 0x%04x qr %d opcode %d", hdr->id, hdr->qr, hdr->opcode);
204
205         hdr->qr = 1;
206         hdr->rcode = 2;
207
208         hdr->ancount = 0;
209         hdr->nscount = 0;
210         hdr->arcount = 0;
211
212         err = sendto(sk, buf, len, 0, to, tolen);
213 }
214
215 static gboolean request_timeout(gpointer user_data)
216 {
217         struct request_data *req = user_data;
218
219         DBG("id 0x%04x", req->srcid);
220
221         if (req == NULL)
222                 return FALSE;
223
224         request_list = g_slist_remove(request_list, req);
225         req->numserv--;
226
227         if (req->resplen > 0 && req->resp != NULL) {
228                 int sk, err;
229
230                 sk = g_io_channel_unix_get_fd(udp_listener_channel);
231
232                 err = sendto(sk, req->resp, req->resplen, 0,
233                              &req->sa, req->sa_len);
234         } else if (req->request && req->numserv == 0) {
235                 struct domain_hdr *hdr;
236
237                 if (req->protocol == IPPROTO_TCP) {
238                         hdr = (void *) (req->request + 2);
239                         hdr->id = req->srcid;
240                         send_response(req->client_sk, req->request,
241                                         req->request_len, NULL, 0, IPPROTO_TCP);
242
243                 } else if (req->protocol == IPPROTO_UDP) {
244                         int sk;
245
246                         hdr = (void *) (req->request);
247                         hdr->id = req->srcid;
248                         sk = g_io_channel_unix_get_fd(udp_listener_channel);
249                         send_response(sk, req->request, req->request_len,
250                                       &req->sa, req->sa_len, IPPROTO_UDP);
251                 }
252         }
253
254         g_free(req->resp);
255         g_free(req);
256
257         return FALSE;
258 }
259
260 static int append_query(unsigned char *buf, unsigned int size,
261                                 const char *query, const char *domain)
262 {
263         unsigned char *ptr = buf;
264         char *offset;
265
266         DBG("query %s domain %s", query, domain);
267
268         offset = (char *) query;
269         while (offset != NULL) {
270                 char *tmp;
271
272                 tmp = strchr(offset, '.');
273                 if (tmp == NULL) {
274                         if (strlen(offset) == 0)
275                                 break;
276                         *ptr = strlen(offset);
277                         memcpy(ptr + 1, offset, strlen(offset));
278                         ptr += strlen(offset) + 1;
279                         break;
280                 }
281
282                 *ptr = tmp - offset;
283                 memcpy(ptr + 1, offset, tmp - offset);
284                 ptr += tmp - offset + 1;
285
286                 offset = tmp + 1;
287         }
288
289         offset = (char *) domain;
290         while (offset != NULL) {
291                 char *tmp;
292
293                 tmp = strchr(offset, '.');
294                 if (tmp == NULL) {
295                         if (strlen(offset) == 0)
296                                 break;
297                         *ptr = strlen(offset);
298                         memcpy(ptr + 1, offset, strlen(offset));
299                         ptr += strlen(offset) + 1;
300                         break;
301                 }
302
303                 *ptr = tmp - offset;
304                 memcpy(ptr + 1, offset, tmp - offset);
305                 ptr += tmp - offset + 1;
306
307                 offset = tmp + 1;
308         }
309
310         *ptr++ = 0x00;
311
312         return ptr - buf;
313 }
314
315 static int ns_resolv(struct server_data *server, struct request_data *req,
316                                 gpointer request, gpointer name)
317 {
318         GList *list;
319         int sk, err;
320
321         sk = g_io_channel_unix_get_fd(server->channel);
322
323         err = send(sk, request, req->request_len, 0);
324
325         req->numserv++;
326
327         for (list = server->domains; list; list = list->next) {
328                 char *domain;
329                 unsigned char alt[1024];
330                 struct domain_hdr *hdr = (void *) &alt;
331                 int altlen, domlen, offset;
332
333                 domain = list->data;
334
335                 if (domain == NULL)
336                         continue;
337
338                 offset = protocol_offset(server->protocol);
339                 if (offset < 0)
340                         return offset;
341
342                 domlen = strlen(domain) + 1;
343                 if (domlen < 5)
344                         return -EINVAL;
345
346                 alt[offset] = req->altid & 0xff;
347                 alt[offset + 1] = req->altid >> 8;
348
349                 memcpy(alt + offset + 2, request + offset + 2, 10);
350                 hdr->qdcount = htons(1);
351
352                 altlen = append_query(alt + offset + 12, sizeof(alt) - 12,
353                                         name, domain);
354                 if (altlen < 0)
355                         return -EINVAL;
356
357                 altlen += 12;
358
359                 memcpy(alt + offset + altlen,
360                         request + offset + altlen - domlen,
361                                 req->request_len - altlen + domlen);
362
363                 if (server->protocol == IPPROTO_TCP) {
364                         int req_len = req->request_len + domlen - 1;
365
366                         alt[0] = (req_len >> 8) & 0xff;
367                         alt[1] = req_len & 0xff;
368                 }
369
370                 err = send(sk, alt, req->request_len + domlen + 1, 0);
371
372                 req->numserv++;
373         }
374
375         return 0;
376 }
377
378 static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol)
379 {
380         struct domain_hdr *hdr;
381         struct request_data *req;
382         int dns_id, sk, err, offset = protocol_offset(protocol);
383
384         if (offset < 0)
385                 return offset;
386
387         hdr = (void *)(reply + offset);
388         dns_id = reply[offset] | reply[offset + 1] << 8;
389
390         DBG("Received %d bytes (id 0x%04x)", reply_len, dns_id);
391
392         req = find_request(dns_id);
393         if (req == NULL)
394                 return -EINVAL;
395
396         DBG("id 0x%04x rcode %d", hdr->id, hdr->rcode);
397
398         reply[offset] = req->srcid & 0xff;
399         reply[offset + 1] = req->srcid >> 8;
400
401         req->numresp++;
402
403         if (hdr->rcode == 0 || req->resp == NULL) {
404                 g_free(req->resp);
405                 req->resplen = 0;
406
407                 req->resp = g_try_malloc(reply_len);
408                 if (req->resp == NULL)
409                         return -ENOMEM;
410
411                 memcpy(req->resp, reply, reply_len);
412                 req->resplen = reply_len;
413         }
414
415         if (hdr->rcode > 0 && req->numresp < req->numserv)
416                 return -EINVAL;
417
418         if (req->timeout > 0)
419                 g_source_remove(req->timeout);
420
421         request_list = g_slist_remove(request_list, req);
422
423         if (protocol == IPPROTO_UDP) {
424                 sk = g_io_channel_unix_get_fd(udp_listener_channel);
425                 err = sendto(sk, req->resp, req->resplen, 0,
426                              &req->sa, req->sa_len);
427         } else {
428                 sk = req->client_sk;
429                 err = send(sk, req->resp, req->resplen, 0);
430                 close(sk);
431         }
432
433         g_free(req->resp);
434         g_free(req);
435
436         return err;
437 }
438
439 static void destroy_server(struct server_data *server)
440 {
441         GList *list;
442
443         DBG("interface %s server %s", server->interface, server->server);
444
445         server_list = g_slist_remove(server_list, server);
446
447         if (server->watch > 0)
448                 g_source_remove(server->watch);
449
450         if (server->timeout > 0)
451                 g_source_remove(server->timeout);
452
453         g_io_channel_unref(server->channel);
454
455         if (server->protocol == IPPROTO_UDP)
456                 connman_info("Removing DNS server %s", server->server);
457
458         g_free(server->incoming_reply);
459         g_free(server->server);
460         for (list = server->domains; list; list = list->next) {
461                 char *domain = list->data;
462
463                 server->domains = g_list_remove(server->domains, domain);
464                 g_free(domain);
465         }
466         g_free(server->interface);
467         g_free(server);
468 }
469
470 static gboolean udp_server_event(GIOChannel *channel, GIOCondition condition,
471                                                         gpointer user_data)
472 {
473         unsigned char buf[4096];
474         int sk, err, len;
475
476         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
477                 struct server_data *data = user_data;
478
479                 connman_error("Error with UDP server %s", data->server);
480                 data->watch = 0;
481                 return FALSE;
482         }
483
484         sk = g_io_channel_unix_get_fd(channel);
485
486         len = recv(sk, buf, sizeof(buf), 0);
487         if (len < 12)
488                 return TRUE;
489
490         err = forward_dns_reply(buf, len, IPPROTO_UDP);
491
492         return TRUE;
493 }
494
495 static gboolean tcp_server_event(GIOChannel *channel, GIOCondition condition,
496                                                         gpointer user_data)
497 {
498         int sk;
499         struct server_data *server = user_data;
500
501         sk = g_io_channel_unix_get_fd(channel);
502         if (sk == 0)
503                 return FALSE;
504
505         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
506                 GSList *list;
507 hangup:
508                 DBG("TCP server channel closed");
509
510                 /*
511                  * Discard any partial response which is buffered; better
512                  * to get a proper response from a working server.
513                  */
514                 g_free(server->incoming_reply);
515                 server->incoming_reply = NULL;
516
517                 for (list = request_list; list; list = list->next) {
518                         struct request_data *req = list->data;
519                         struct domain_hdr *hdr;
520
521                         if (req->protocol == IPPROTO_UDP)
522                                 continue;
523
524                         if (req->request == NULL)
525                                 continue;
526
527                         /*
528                          * If we're not waiting for any further response
529                          * from another name server, then we send an error
530                          * response to the client.
531                          */
532                         if (req->numserv && --(req->numserv))
533                                 continue;
534
535                         hdr = (void *) (req->request + 2);
536                         hdr->id = req->srcid;
537                         send_response(req->client_sk, req->request,
538                                         req->request_len, NULL, 0, IPPROTO_TCP);
539
540                         request_list = g_slist_remove(request_list, req);
541                 }
542
543                 destroy_server(server);
544
545                 return FALSE;
546         }
547
548         if ((condition & G_IO_OUT) && !server->connected) {
549                 GSList *list;
550                 GList *domains;
551                 struct server_data *udp_server;
552
553                 udp_server = find_server(server->interface, server->server,
554                                                                 IPPROTO_UDP);
555                 if (udp_server != NULL) {
556                         for (domains = udp_server->domains; domains;
557                                                 domains = domains->next) {
558                                 char *dom = domains->data;
559
560                                 DBG("Adding domain %s to %s",
561                                                 dom, server->server);
562
563                                 server->domains = g_list_append(server->domains,
564                                                                 g_strdup(dom));
565                         }
566                 }
567
568                 server->connected = TRUE;
569                 server_list = g_slist_append(server_list, server);
570
571                 if (server->timeout > 0) {
572                         g_source_remove(server->timeout);
573                         server->timeout = 0;
574                 }
575
576                 for (list = request_list; list; list = list->next) {
577                         struct request_data *req = list->data;
578
579                         if (req->protocol == IPPROTO_UDP)
580                                 continue;
581
582                         DBG("Sending req %s over TCP", (char *)req->name);
583
584                         if (req->timeout > 0)
585                                 g_source_remove(req->timeout);
586
587                         req->timeout = g_timeout_add_seconds(30,
588                                                 request_timeout, req);
589                         ns_resolv(server, req, req->request, req->name);
590                 }
591
592         } else if (condition & G_IO_IN) {
593                 struct partial_reply *reply = server->incoming_reply;
594                 int bytes_recv;
595
596                 if (!reply) {
597                         unsigned char reply_len_buf[2];
598                         uint16_t reply_len;
599
600                         bytes_recv = recv(sk, reply_len_buf, 2, MSG_PEEK);
601                         if (!bytes_recv) {
602                                 goto hangup;
603                         } else if (bytes_recv < 0) {
604                                 if (errno == EAGAIN || errno == EWOULDBLOCK)
605                                         return TRUE;
606
607                                 connman_error("DNS proxy error %s",
608                                                 strerror(errno));
609                                 goto hangup;
610                         } else if (bytes_recv < 2)
611                                 return TRUE;
612
613                         reply_len = reply_len_buf[1] | reply_len_buf[0] << 8;
614                         reply_len += 2;
615
616                         DBG("TCP reply %d bytes", reply_len);
617
618                         reply = g_try_malloc(sizeof(*reply) + reply_len + 2);
619                         if (!reply)
620                                 return TRUE;
621
622                         reply->len = reply_len;
623                         reply->received = 0;
624
625                         server->incoming_reply = reply;
626                 }
627
628                 while (reply->received < reply->len) {
629                         bytes_recv = recv(sk, reply->buf + reply->received,
630                                         reply->len - reply->received, 0);
631                         if (!bytes_recv) {
632                                 connman_error("DNS proxy TCP disconnect");
633                                 break;
634                         } else if (bytes_recv < 0) {
635                                 if (errno == EAGAIN || errno == EWOULDBLOCK)
636                                         return TRUE;
637
638                                 connman_error("DNS proxy error %s",
639                                                 strerror(errno));
640                                 break;
641                         }
642                         reply->received += bytes_recv;
643                 }
644
645                 forward_dns_reply(reply->buf, reply->received, IPPROTO_TCP);
646
647                 g_free(reply);
648                 server->incoming_reply = NULL;
649
650                 destroy_server(server);
651
652                 return FALSE;
653         }
654
655         return TRUE;
656 }
657
658 static gboolean tcp_idle_timeout(gpointer user_data)
659 {
660         struct server_data *server = user_data;
661
662         DBG("");
663
664         if (server == NULL)
665                 return FALSE;
666
667         destroy_server(server);
668
669         return FALSE;
670 }
671
672 static struct server_data *create_server(const char *interface,
673                                         const char *domain, const char *server,
674                                         int protocol)
675 {
676         struct addrinfo hints, *rp;
677         struct server_data *data;
678         int sk, ret;
679
680         DBG("interface %s server %s", interface, server);
681
682         memset(&hints, 0, sizeof(hints));
683
684         switch (protocol) {
685         case IPPROTO_UDP:
686                 hints.ai_socktype = SOCK_DGRAM;
687                 break;
688
689         case IPPROTO_TCP:
690                 hints.ai_socktype = SOCK_STREAM;
691                 break;
692
693         default:
694                 return NULL;
695         }
696         hints.ai_family = AF_UNSPEC;
697         hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_NUMERICHOST;
698
699         ret = getaddrinfo(server, "53", &hints, &rp);
700         if (ret) {
701                 connman_error("Failed to parse server %s address: %s\n",
702                               server, gai_strerror(ret));
703                 return NULL;
704         }
705         /* Do not blindly copy this code elsewhere; it doesn't loop over the
706            results using ->ai_next as it should. That's OK in *this* case
707            because it was a numeric lookup; we *know* there's only one. */
708
709         sk = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
710         if (sk < 0) {
711                 connman_error("Failed to create server %s socket", server);
712                 freeaddrinfo(rp);
713                 return NULL;
714         }
715
716         if (interface != NULL) {
717                 if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
718                                 interface, strlen(interface) + 1) < 0) {
719                         connman_error("Failed to bind server %s "
720                                                 "to interface %s",
721                                                         server, interface);
722                         freeaddrinfo(rp);
723                         close(sk);
724                         return NULL;
725                 }
726         }
727
728         data = g_try_new0(struct server_data, 1);
729         if (data == NULL) {
730                 connman_error("Failed to allocate server %s data", server);
731                 freeaddrinfo(rp);
732                 close(sk);
733                 return NULL;
734         }
735
736         data->channel = g_io_channel_unix_new(sk);
737         if (data->channel == NULL) {
738                 connman_error("Failed to create server %s channel", server);
739                 freeaddrinfo(rp);
740                 close(sk);
741                 g_free(data);
742                 return NULL;
743         }
744
745         g_io_channel_set_close_on_unref(data->channel, TRUE);
746
747         if (protocol == IPPROTO_TCP) {
748                 g_io_channel_set_flags(data->channel, G_IO_FLAG_NONBLOCK, NULL);
749                 data->watch = g_io_add_watch(data->channel,
750                         G_IO_OUT | G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR,
751                                                 tcp_server_event, data);
752                 data->timeout = g_timeout_add_seconds(30, tcp_idle_timeout,
753                                                                 data);
754         } else
755                 data->watch = g_io_add_watch(data->channel,
756                         G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
757                                                 udp_server_event, data);
758
759         data->interface = g_strdup(interface);
760         if (domain)
761                 data->domains = g_list_append(data->domains, g_strdup(domain));
762         data->server = g_strdup(server);
763         data->protocol = protocol;
764
765         ret = connect(sk, rp->ai_addr, rp->ai_addrlen);
766         freeaddrinfo(rp);
767         if (ret < 0) {
768                 if ((protocol == IPPROTO_TCP && errno != EINPROGRESS) ||
769                                 protocol == IPPROTO_UDP) {
770                         GList *list;
771
772                         connman_error("Failed to connect to server %s", server);
773                         if (data->watch > 0)
774                                 g_source_remove(data->watch);
775                         if (data->timeout > 0)
776                                 g_source_remove(data->timeout);
777
778                         g_io_channel_unref(data->channel);
779                         close(sk);
780
781                         g_free(data->server);
782                         g_free(data->interface);
783                         for (list = data->domains; list; list = list->next) {
784                                 char *domain = list->data;
785
786                                 data->domains = g_list_remove(data->domains,
787                                                                         domain);
788                                 g_free(domain);
789                         }
790                         g_free(data);
791                         return NULL;
792                 }
793         }
794
795         if (protocol == IPPROTO_UDP) {
796                 /* Enable new servers by default */
797                 data->enabled = TRUE;
798                 connman_info("Adding DNS server %s", data->server);
799
800                 server_list = g_slist_append(server_list, data);
801
802                 return data;
803         }
804
805         return NULL;
806 }
807
808 static gboolean resolv(struct request_data *req,
809                                 gpointer request, gpointer name)
810 {
811         GSList *list;
812
813         for (list = server_list; list; list = list->next) {
814                 struct server_data *data = list->data;
815
816                 DBG("server %s enabled %d", data->server, data->enabled);
817
818                 if (data->enabled == FALSE)
819                         continue;
820
821                 if (data->watch == 0 && data->protocol == IPPROTO_UDP)
822                         data->watch = g_io_add_watch(data->channel,
823                                 G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
824                                                 udp_server_event, data);
825
826                 if (ns_resolv(data, req, request, name) < 0)
827                         continue;
828         }
829
830         return TRUE;
831 }
832
833 static void append_domain(const char *interface, const char *domain)
834 {
835         GSList *list;
836
837         DBG("interface %s domain %s", interface, domain);
838
839         for (list = server_list; list; list = list->next) {
840                 struct server_data *data = list->data;
841                 GList *dom_list;
842                 char *dom;
843                 gboolean dom_found = FALSE;
844
845                 if (data->interface == NULL)
846                         continue;
847
848                 if (g_str_equal(data->interface, interface) == FALSE)
849                         continue;
850
851                 for (dom_list = data->domains; dom_list;
852                                 dom_list = dom_list->next) {
853                         dom = dom_list->data;
854
855                         if (g_str_equal(dom, domain)) {
856                                 dom_found = TRUE;
857                                 break;
858                         }
859                 }
860
861                 if (dom_found == FALSE) {
862                         data->domains =
863                                 g_list_append(data->domains, g_strdup(domain));
864                 }
865         }
866 }
867
868 int __connman_dnsproxy_append(const char *interface, const char *domain,
869                                                         const char *server)
870 {
871         struct server_data *data;
872
873         DBG("interface %s server %s", interface, server);
874
875         if (server == NULL && domain == NULL)
876                 return -EINVAL;
877
878         if (server == NULL) {
879                 append_domain(interface, domain);
880
881                 return 0;
882         }
883
884         if (g_str_equal(server, "127.0.0.1") == TRUE)
885                 return -ENODEV;
886
887         data = find_server(interface, server, IPPROTO_UDP);
888         if (data != NULL) {
889                 append_domain(interface, domain);
890                 return 0;
891         }
892
893         data = create_server(interface, domain, server, IPPROTO_UDP);
894         if (data == NULL)
895                 return -EIO;
896
897         return 0;
898 }
899
900 static void remove_server(const char *interface, const char *domain,
901                         const char *server, int protocol)
902 {
903         struct server_data *data;
904
905         data = find_server(interface, server, protocol);
906         if (data == NULL)
907                 return;
908
909         destroy_server(data);
910 }
911
912 int __connman_dnsproxy_remove(const char *interface, const char *domain,
913                                                         const char *server)
914 {
915         DBG("interface %s server %s", interface, server);
916
917         if (server == NULL)
918                 return -EINVAL;
919
920         if (g_str_equal(server, "127.0.0.1") == TRUE)
921                 return -ENODEV;
922
923         remove_server(interface, domain, server, IPPROTO_UDP);
924         remove_server(interface, domain, server, IPPROTO_TCP);
925
926         return 0;
927 }
928
929 void __connman_dnsproxy_flush(void)
930 {
931         GSList *list;
932
933         list = request_pending_list;
934         while (list) {
935                 struct request_data *req = list->data;
936
937                 list = list->next;
938
939                 request_pending_list =
940                                 g_slist_remove(request_pending_list, req);
941                 resolv(req, req->request, req->name);
942                 g_free(req->request);
943                 g_free(req->name);
944         }
945 }
946
947 static void dnsproxy_offline_mode(connman_bool_t enabled)
948 {
949         GSList *list;
950
951         DBG("enabled %d", enabled);
952
953         for (list = server_list; list; list = list->next) {
954                 struct server_data *data = list->data;
955
956                 if (enabled == FALSE) {
957                         connman_info("Enabling DNS server %s", data->server);
958                         data->enabled = TRUE;
959                 } else {
960                         connman_info("Disabling DNS server %s", data->server);
961                         data->enabled = FALSE;
962                 }
963         }
964 }
965
966 static void dnsproxy_default_changed(struct connman_service *service)
967 {
968         GSList *list;
969         char *interface;
970
971         DBG("service %p", service);
972
973         if (service == NULL) {
974                 /* When no services are active, then disable DNS proxying */
975                 dnsproxy_offline_mode(TRUE);
976                 return;
977         }
978
979         interface = connman_service_get_interface(service);
980         if (interface == NULL)
981                 return;
982
983         for (list = server_list; list; list = list->next) {
984                 struct server_data *data = list->data;
985
986                 if (g_strcmp0(data->interface, interface) == 0) {
987                         connman_info("Enabling DNS server %s", data->server);
988                         data->enabled = TRUE;
989                 } else {
990                         connman_info("Disabling DNS server %s", data->server);
991                         data->enabled = FALSE;
992                 }
993         }
994
995         g_free(interface);
996 }
997
998 static struct connman_notifier dnsproxy_notifier = {
999         .name                   = "dnsproxy",
1000         .default_changed        = dnsproxy_default_changed,
1001         .offline_mode           = dnsproxy_offline_mode,
1002 };
1003
1004 static unsigned char opt_edns0_type[2] = { 0x00, 0x29 };
1005
1006 static int parse_request(unsigned char *buf, int len,
1007                                         char *name, unsigned int size)
1008 {
1009         struct domain_hdr *hdr = (void *) buf;
1010         uint16_t qdcount = ntohs(hdr->qdcount);
1011         uint16_t arcount = ntohs(hdr->arcount);
1012         unsigned char *ptr;
1013         char *last_label = NULL;
1014         unsigned int remain, used = 0;
1015
1016         if (len < 12)
1017                 return -EINVAL;
1018
1019         DBG("id 0x%04x qr %d opcode %d qdcount %d arcount %d",
1020                                         hdr->id, hdr->qr, hdr->opcode,
1021                                                         qdcount, arcount);
1022
1023         if (hdr->qr != 0 || qdcount != 1)
1024                 return -EINVAL;
1025
1026         memset(name, 0, size);
1027
1028         ptr = buf + sizeof(struct domain_hdr);
1029         remain = len - sizeof(struct domain_hdr);
1030
1031         while (remain > 0) {
1032                 uint8_t len = *ptr;
1033
1034                 if (len == 0x00) {
1035                         last_label = (char *) (ptr + 1);
1036                         break;
1037                 }
1038
1039                 if (used + len + 1 > size)
1040                         return -ENOBUFS;
1041
1042                 strncat(name, (char *) (ptr + 1), len);
1043                 strcat(name, ".");
1044
1045                 used += len + 1;
1046
1047                 ptr += len + 1;
1048                 remain -= len + 1;
1049         }
1050
1051         if (last_label && arcount && remain >= 9 && last_label[4] == 0 &&
1052                                 !memcmp(last_label + 5, opt_edns0_type, 2)) {
1053                 uint16_t edns0_bufsize;
1054
1055                 edns0_bufsize = last_label[7] << 8 | last_label[8];
1056
1057                 DBG("EDNS0 buffer size %u", edns0_bufsize);
1058
1059                 /* This is an evil hack until full TCP support has been
1060                  * implemented.
1061                  *
1062                  * Somtimes the EDNS0 request gets send with a too-small
1063                  * buffer size. Since glibc doesn't seem to crash when it
1064                  * gets a response biffer then it requested, just bump
1065                  * the buffer size up to 4KiB.
1066                  */
1067                 if (edns0_bufsize < 0x1000) {
1068                         last_label[7] = 0x10;
1069                         last_label[8] = 0x00;
1070                 }
1071         }
1072
1073         DBG("query %s", name);
1074
1075         return 0;
1076 }
1077
1078 static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition,
1079                                                         gpointer user_data)
1080 {
1081         unsigned char buf[768];
1082         char query[512];
1083         struct request_data *req;
1084         struct server_data *server;
1085         int sk, client_sk, len, err;
1086         struct sockaddr_in6 client_addr;
1087         socklen_t client_addr_len = sizeof(client_addr);
1088         GSList *list;
1089
1090         DBG("condition 0x%x", condition);
1091
1092         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
1093                 if (tcp_listener_watch > 0)
1094                         g_source_remove(tcp_listener_watch);
1095                 tcp_listener_watch = 0;
1096
1097                 connman_error("Error with TCP listener channel");
1098
1099                 return FALSE;
1100         }
1101
1102         sk = g_io_channel_unix_get_fd(channel);
1103
1104         client_sk = accept(sk, (void *)&client_addr, &client_addr_len);
1105         if (client_sk < 0) {
1106                 connman_error("Accept failure on TCP listener");
1107                 tcp_listener_watch = 0;
1108                 return FALSE;
1109         }
1110
1111         len = recv(client_sk, buf, sizeof(buf), 0);
1112         if (len < 2)
1113                 return TRUE;
1114
1115         DBG("Received %d bytes (id 0x%04x)", len, buf[2] | buf[3] << 8);
1116
1117         err = parse_request(buf + 2, len - 2, query, sizeof(query));
1118         if (err < 0 || (g_slist_length(server_list) == 0)) {
1119                 send_response(client_sk, buf, len, NULL, 0, IPPROTO_TCP);
1120                 return TRUE;
1121         }
1122
1123         req = g_try_new0(struct request_data, 1);
1124         if (req == NULL)
1125                 return TRUE;
1126
1127         memcpy(&req->sa, &client_addr, client_addr_len);
1128         req->sa_len = client_addr_len;
1129         req->client_sk = client_sk;
1130         req->protocol = IPPROTO_TCP;
1131
1132         request_id += 2;
1133         if (request_id == 0x0000 || request_id == 0xffff)
1134                 request_id += 2;
1135
1136         req->srcid = buf[2] | (buf[3] << 8);
1137         req->dstid = request_id;
1138         req->altid = request_id + 1;
1139         req->request_len = len;
1140
1141         buf[2] = req->dstid & 0xff;
1142         buf[3] = req->dstid >> 8;
1143
1144         req->numserv = 0;
1145         request_list = g_slist_append(request_list, req);
1146
1147         for (list = server_list; list; list = list->next) {
1148                 struct server_data *data = list->data;
1149                 GList *domains;
1150
1151                 if (data->protocol != IPPROTO_UDP || data->enabled == FALSE)
1152                         continue;
1153
1154                 server = create_server(data->interface, NULL,
1155                                         data->server, IPPROTO_TCP);
1156
1157                 /*
1158                  * If server is NULL, we're not connected yet.
1159                  * Copy the relevant buffers and continue with
1160                  * the next nameserver.
1161                  * The request will actually be sent once we're
1162                  * properly connected over TCP to this nameserver.
1163                  */
1164                 if (server == NULL) {
1165                         req->request = g_try_malloc0(req->request_len);
1166                         if (req->request == NULL)
1167                                 return TRUE;
1168
1169                         memcpy(req->request, buf, req->request_len);
1170
1171                         req->name = g_try_malloc0(sizeof(query));
1172                         if (req->name == NULL) {
1173                                 g_free(req->request);
1174                                 return TRUE;
1175                         }
1176                         memcpy(req->name, query, sizeof(query));
1177
1178                         continue;
1179                 }
1180
1181                 if (req->timeout > 0)
1182                         g_source_remove(req->timeout);
1183
1184                 for (domains = data->domains; domains;
1185                                 domains = domains->next) {
1186                         char *dom = domains->data;
1187
1188                         DBG("Adding domain %s to %s", dom, server->server);
1189
1190                         server->domains = g_list_append(server->domains,
1191                                                 g_strdup(dom));
1192                 }
1193
1194                 req->timeout = g_timeout_add_seconds(30, request_timeout, req);
1195                 ns_resolv(server, req, buf, query);
1196         }
1197
1198         return TRUE;
1199 }
1200
1201 static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition,
1202                                                         gpointer user_data)
1203 {
1204         unsigned char buf[768];
1205         char query[512];
1206         struct request_data *req;
1207         struct sockaddr_in6 client_addr;
1208         socklen_t client_addr_len = sizeof(client_addr);
1209         int sk, err, len;
1210
1211         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
1212                 connman_error("Error with UDP listener channel");
1213                 udp_listener_watch = 0;
1214                 return FALSE;
1215         }
1216
1217         sk = g_io_channel_unix_get_fd(channel);
1218
1219         memset(&client_addr, 0, client_addr_len);
1220         len = recvfrom(sk, buf, sizeof(buf), 0, (void *)&client_addr,
1221                        &client_addr_len);
1222         if (len < 2)
1223                 return TRUE;
1224
1225         DBG("Received %d bytes (id 0x%04x)", len, buf[0] | buf[1] << 8);
1226
1227         err = parse_request(buf, len, query, sizeof(query));
1228         if (err < 0 || (g_slist_length(server_list) == 0)) {
1229                 send_response(sk, buf, len, (void *)&client_addr,
1230                               client_addr_len, IPPROTO_UDP);
1231                 return TRUE;
1232         }
1233
1234         req = g_try_new0(struct request_data, 1);
1235         if (req == NULL)
1236                 return TRUE;
1237
1238         memcpy(&req->sa, &client_addr, client_addr_len);
1239         req->sa_len = client_addr_len;
1240         req->client_sk = 0;
1241         req->protocol = IPPROTO_UDP;
1242
1243         request_id += 2;
1244         if (request_id == 0x0000 || request_id == 0xffff)
1245                 request_id += 2;
1246
1247         req->srcid = buf[0] | (buf[1] << 8);
1248         req->dstid = request_id;
1249         req->altid = request_id + 1;
1250         req->request_len = len;
1251
1252         buf[0] = req->dstid & 0xff;
1253         buf[1] = req->dstid >> 8;
1254
1255         req->numserv = 0;
1256         req->timeout = g_timeout_add_seconds(5, request_timeout, req);
1257         request_list = g_slist_append(request_list, req);
1258
1259         return resolv(req, buf, query);
1260 }
1261
1262 static int create_dns_listener(int protocol)
1263 {
1264         GIOChannel *channel;
1265         const char *ifname = "lo", *proto;
1266         union {
1267                 struct sockaddr sa;
1268                 struct sockaddr_in6 sin6;
1269                 struct sockaddr_in sin;
1270         } s;
1271         socklen_t slen;
1272         int sk, type, v6only = 0;
1273         int family = AF_INET6;
1274
1275         DBG("");
1276
1277         switch (protocol) {
1278         case IPPROTO_UDP:
1279                 proto = "UDP";
1280                 type = SOCK_DGRAM;
1281                 break;
1282
1283         case IPPROTO_TCP:
1284                 proto = "TCP";
1285                 type = SOCK_STREAM;
1286                 break;
1287
1288         default:
1289                 return -EINVAL;
1290         }
1291
1292         sk = socket(family, type, protocol);
1293         if (sk < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
1294                 connman_error("No IPv6 support; DNS proxy listening only on Legacy IP");
1295                 family = AF_INET;
1296                 sk = socket(family, type, protocol);
1297         }
1298         if (sk < 0) {
1299                 connman_error("Failed to create %s listener socket", proto);
1300                 return -EIO;
1301         }
1302
1303         if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
1304                                         ifname, strlen(ifname) + 1) < 0) {
1305                 connman_error("Failed to bind %s listener interface", proto);
1306                 close(sk);
1307                 return -EIO;
1308         }
1309         /* Ensure it accepts Legacy IP connections too */
1310         if (family == AF_INET6 &&
1311                         setsockopt(sk, SOL_IPV6, IPV6_V6ONLY,
1312                                         &v6only, sizeof(v6only)) < 0) {
1313                 connman_error("Failed to clear V6ONLY on %s listener socket",
1314                               proto);
1315                 close(sk);
1316                 return -EIO;
1317         }
1318
1319         if (family == AF_INET) {
1320                 memset(&s.sin, 0, sizeof(s.sin));
1321                 s.sin.sin_family = AF_INET;
1322                 s.sin.sin_port = htons(53);
1323                 s.sin.sin_addr.s_addr = htonl(INADDR_ANY);
1324                 slen = sizeof(s.sin);
1325         } else {
1326                 memset(&s.sin6, 0, sizeof(s.sin6));
1327                 s.sin6.sin6_family = AF_INET6;
1328                 s.sin6.sin6_port = htons(53);
1329                 s.sin6.sin6_addr = in6addr_any;
1330                 slen = sizeof(s.sin6);
1331         }
1332
1333         if (bind(sk, &s.sa, slen) < 0) {
1334                 connman_error("Failed to bind %s listener socket", proto);
1335                 close(sk);
1336                 return -EIO;
1337         }
1338
1339         if (protocol == IPPROTO_TCP && listen(sk, 10) < 0) {
1340                 connman_error("Failed to listen on TCP socket");
1341                 close(sk);
1342                 return -EIO;
1343         }
1344
1345         channel = g_io_channel_unix_new(sk);
1346         if (channel == NULL) {
1347                 connman_error("Failed to create %s listener channel", proto);
1348                 close(sk);
1349                 return -EIO;
1350         }
1351
1352         g_io_channel_set_close_on_unref(channel, TRUE);
1353
1354         if (protocol == IPPROTO_TCP) {
1355                 tcp_listener_channel = channel;
1356                 tcp_listener_watch = g_io_add_watch(channel,
1357                                         G_IO_IN, tcp_listener_event, NULL);
1358         } else {
1359                 udp_listener_channel = channel;
1360                 udp_listener_watch = g_io_add_watch(channel,
1361                                         G_IO_IN, udp_listener_event, NULL);
1362         }
1363
1364         return 0;
1365 }
1366
1367 static void destroy_udp_listener(void)
1368 {
1369         DBG("");
1370
1371         if (udp_listener_watch > 0)
1372                 g_source_remove(udp_listener_watch);
1373
1374         g_io_channel_unref(udp_listener_channel);
1375 }
1376
1377 static void destroy_tcp_listener(void)
1378 {
1379         DBG("");
1380
1381         if (tcp_listener_watch > 0)
1382                 g_source_remove(tcp_listener_watch);
1383
1384         g_io_channel_unref(tcp_listener_channel);
1385 }
1386
1387 static int create_listener(void)
1388 {
1389         int err;
1390
1391         err = create_dns_listener(IPPROTO_UDP);
1392         if (err < 0)
1393                 return err;
1394
1395         err = create_dns_listener(IPPROTO_TCP);
1396         if (err < 0) {
1397                 destroy_udp_listener();
1398                 return err;
1399         }
1400
1401         __connman_resolvfile_append("lo", NULL, "127.0.0.1");
1402
1403         return 0;
1404 }
1405
1406 static void destroy_listener(void)
1407 {
1408         GSList *list;
1409
1410         __connman_resolvfile_remove("lo", NULL, "127.0.0.1");
1411
1412         for (list = request_pending_list; list; list = list->next) {
1413                 struct request_data *req = list->data;
1414
1415                 DBG("Dropping pending request (id 0x%04x -> 0x%04x)",
1416                                                 req->srcid, req->dstid);
1417
1418                 g_free(req->resp);
1419                 g_free(req->request);
1420                 g_free(req->name);
1421                 g_free(req);
1422                 list->data = NULL;
1423         }
1424
1425         g_slist_free(request_pending_list);
1426         request_pending_list = NULL;
1427
1428         for (list = request_list; list; list = list->next) {
1429                 struct request_data *req = list->data;
1430
1431                 DBG("Dropping request (id 0x%04x -> 0x%04x)",
1432                                                 req->srcid, req->dstid);
1433
1434                 g_free(req->resp);
1435                 g_free(req->request);
1436                 g_free(req->name);
1437                 g_free(req);
1438                 list->data = NULL;
1439         }
1440
1441         g_slist_free(request_list);
1442         request_list = NULL;
1443
1444         destroy_tcp_listener();
1445         destroy_udp_listener();
1446 }
1447
1448 int __connman_dnsproxy_init(void)
1449 {
1450         int err;
1451
1452         DBG("");
1453
1454         err = create_listener();
1455         if (err < 0)
1456                 return err;
1457
1458         err = connman_notifier_register(&dnsproxy_notifier);
1459         if (err < 0)
1460                 goto destroy;
1461
1462         return 0;
1463
1464 destroy:
1465         destroy_listener();
1466
1467         return err;
1468 }
1469
1470 void __connman_dnsproxy_cleanup(void)
1471 {
1472         DBG("");
1473
1474         connman_notifier_unregister(&dnsproxy_notifier);
1475
1476         destroy_listener();
1477 }