dnsproxy: Do not add NULL domains to the domain list
[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         if (domain == NULL)
840                 return;
841
842         for (list = server_list; list; list = list->next) {
843                 struct server_data *data = list->data;
844                 GList *dom_list;
845                 char *dom;
846                 gboolean dom_found = FALSE;
847
848                 if (data->interface == NULL)
849                         continue;
850
851                 if (g_str_equal(data->interface, interface) == FALSE)
852                         continue;
853
854                 for (dom_list = data->domains; dom_list;
855                                 dom_list = dom_list->next) {
856                         dom = dom_list->data;
857
858                         if (g_str_equal(dom, domain)) {
859                                 dom_found = TRUE;
860                                 break;
861                         }
862                 }
863
864                 if (dom_found == FALSE) {
865                         data->domains =
866                                 g_list_append(data->domains, g_strdup(domain));
867                 }
868         }
869 }
870
871 int __connman_dnsproxy_append(const char *interface, const char *domain,
872                                                         const char *server)
873 {
874         struct server_data *data;
875
876         DBG("interface %s server %s", interface, server);
877
878         if (server == NULL && domain == NULL)
879                 return -EINVAL;
880
881         if (server == NULL) {
882                 append_domain(interface, domain);
883
884                 return 0;
885         }
886
887         if (g_str_equal(server, "127.0.0.1") == TRUE)
888                 return -ENODEV;
889
890         data = find_server(interface, server, IPPROTO_UDP);
891         if (data != NULL) {
892                 append_domain(interface, domain);
893                 return 0;
894         }
895
896         data = create_server(interface, domain, server, IPPROTO_UDP);
897         if (data == NULL)
898                 return -EIO;
899
900         return 0;
901 }
902
903 static void remove_server(const char *interface, const char *domain,
904                         const char *server, int protocol)
905 {
906         struct server_data *data;
907
908         data = find_server(interface, server, protocol);
909         if (data == NULL)
910                 return;
911
912         destroy_server(data);
913 }
914
915 int __connman_dnsproxy_remove(const char *interface, const char *domain,
916                                                         const char *server)
917 {
918         DBG("interface %s server %s", interface, server);
919
920         if (server == NULL)
921                 return -EINVAL;
922
923         if (g_str_equal(server, "127.0.0.1") == TRUE)
924                 return -ENODEV;
925
926         remove_server(interface, domain, server, IPPROTO_UDP);
927         remove_server(interface, domain, server, IPPROTO_TCP);
928
929         return 0;
930 }
931
932 void __connman_dnsproxy_flush(void)
933 {
934         GSList *list;
935
936         list = request_pending_list;
937         while (list) {
938                 struct request_data *req = list->data;
939
940                 list = list->next;
941
942                 request_pending_list =
943                                 g_slist_remove(request_pending_list, req);
944                 resolv(req, req->request, req->name);
945                 g_free(req->request);
946                 g_free(req->name);
947         }
948 }
949
950 static void dnsproxy_offline_mode(connman_bool_t enabled)
951 {
952         GSList *list;
953
954         DBG("enabled %d", enabled);
955
956         for (list = server_list; list; list = list->next) {
957                 struct server_data *data = list->data;
958
959                 if (enabled == FALSE) {
960                         connman_info("Enabling DNS server %s", data->server);
961                         data->enabled = TRUE;
962                 } else {
963                         connman_info("Disabling DNS server %s", data->server);
964                         data->enabled = FALSE;
965                 }
966         }
967 }
968
969 static void dnsproxy_default_changed(struct connman_service *service)
970 {
971         GSList *list;
972         char *interface;
973
974         DBG("service %p", service);
975
976         if (service == NULL) {
977                 /* When no services are active, then disable DNS proxying */
978                 dnsproxy_offline_mode(TRUE);
979                 return;
980         }
981
982         interface = connman_service_get_interface(service);
983         if (interface == NULL)
984                 return;
985
986         for (list = server_list; list; list = list->next) {
987                 struct server_data *data = list->data;
988
989                 if (g_strcmp0(data->interface, interface) == 0) {
990                         connman_info("Enabling DNS server %s", data->server);
991                         data->enabled = TRUE;
992                 } else {
993                         connman_info("Disabling DNS server %s", data->server);
994                         data->enabled = FALSE;
995                 }
996         }
997
998         g_free(interface);
999 }
1000
1001 static struct connman_notifier dnsproxy_notifier = {
1002         .name                   = "dnsproxy",
1003         .default_changed        = dnsproxy_default_changed,
1004         .offline_mode           = dnsproxy_offline_mode,
1005 };
1006
1007 static unsigned char opt_edns0_type[2] = { 0x00, 0x29 };
1008
1009 static int parse_request(unsigned char *buf, int len,
1010                                         char *name, unsigned int size)
1011 {
1012         struct domain_hdr *hdr = (void *) buf;
1013         uint16_t qdcount = ntohs(hdr->qdcount);
1014         uint16_t arcount = ntohs(hdr->arcount);
1015         unsigned char *ptr;
1016         char *last_label = NULL;
1017         unsigned int remain, used = 0;
1018
1019         if (len < 12)
1020                 return -EINVAL;
1021
1022         DBG("id 0x%04x qr %d opcode %d qdcount %d arcount %d",
1023                                         hdr->id, hdr->qr, hdr->opcode,
1024                                                         qdcount, arcount);
1025
1026         if (hdr->qr != 0 || qdcount != 1)
1027                 return -EINVAL;
1028
1029         memset(name, 0, size);
1030
1031         ptr = buf + sizeof(struct domain_hdr);
1032         remain = len - sizeof(struct domain_hdr);
1033
1034         while (remain > 0) {
1035                 uint8_t len = *ptr;
1036
1037                 if (len == 0x00) {
1038                         last_label = (char *) (ptr + 1);
1039                         break;
1040                 }
1041
1042                 if (used + len + 1 > size)
1043                         return -ENOBUFS;
1044
1045                 strncat(name, (char *) (ptr + 1), len);
1046                 strcat(name, ".");
1047
1048                 used += len + 1;
1049
1050                 ptr += len + 1;
1051                 remain -= len + 1;
1052         }
1053
1054         if (last_label && arcount && remain >= 9 && last_label[4] == 0 &&
1055                                 !memcmp(last_label + 5, opt_edns0_type, 2)) {
1056                 uint16_t edns0_bufsize;
1057
1058                 edns0_bufsize = last_label[7] << 8 | last_label[8];
1059
1060                 DBG("EDNS0 buffer size %u", edns0_bufsize);
1061
1062                 /* This is an evil hack until full TCP support has been
1063                  * implemented.
1064                  *
1065                  * Somtimes the EDNS0 request gets send with a too-small
1066                  * buffer size. Since glibc doesn't seem to crash when it
1067                  * gets a response biffer then it requested, just bump
1068                  * the buffer size up to 4KiB.
1069                  */
1070                 if (edns0_bufsize < 0x1000) {
1071                         last_label[7] = 0x10;
1072                         last_label[8] = 0x00;
1073                 }
1074         }
1075
1076         DBG("query %s", name);
1077
1078         return 0;
1079 }
1080
1081 static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition,
1082                                                         gpointer user_data)
1083 {
1084         unsigned char buf[768];
1085         char query[512];
1086         struct request_data *req;
1087         struct server_data *server;
1088         int sk, client_sk, len, err;
1089         struct sockaddr_in6 client_addr;
1090         socklen_t client_addr_len = sizeof(client_addr);
1091         GSList *list;
1092
1093         DBG("condition 0x%x", condition);
1094
1095         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
1096                 if (tcp_listener_watch > 0)
1097                         g_source_remove(tcp_listener_watch);
1098                 tcp_listener_watch = 0;
1099
1100                 connman_error("Error with TCP listener channel");
1101
1102                 return FALSE;
1103         }
1104
1105         sk = g_io_channel_unix_get_fd(channel);
1106
1107         client_sk = accept(sk, (void *)&client_addr, &client_addr_len);
1108         if (client_sk < 0) {
1109                 connman_error("Accept failure on TCP listener");
1110                 tcp_listener_watch = 0;
1111                 return FALSE;
1112         }
1113
1114         len = recv(client_sk, buf, sizeof(buf), 0);
1115         if (len < 2)
1116                 return TRUE;
1117
1118         DBG("Received %d bytes (id 0x%04x)", len, buf[2] | buf[3] << 8);
1119
1120         err = parse_request(buf + 2, len - 2, query, sizeof(query));
1121         if (err < 0 || (g_slist_length(server_list) == 0)) {
1122                 send_response(client_sk, buf, len, NULL, 0, IPPROTO_TCP);
1123                 return TRUE;
1124         }
1125
1126         req = g_try_new0(struct request_data, 1);
1127         if (req == NULL)
1128                 return TRUE;
1129
1130         memcpy(&req->sa, &client_addr, client_addr_len);
1131         req->sa_len = client_addr_len;
1132         req->client_sk = client_sk;
1133         req->protocol = IPPROTO_TCP;
1134
1135         request_id += 2;
1136         if (request_id == 0x0000 || request_id == 0xffff)
1137                 request_id += 2;
1138
1139         req->srcid = buf[2] | (buf[3] << 8);
1140         req->dstid = request_id;
1141         req->altid = request_id + 1;
1142         req->request_len = len;
1143
1144         buf[2] = req->dstid & 0xff;
1145         buf[3] = req->dstid >> 8;
1146
1147         req->numserv = 0;
1148         request_list = g_slist_append(request_list, req);
1149
1150         for (list = server_list; list; list = list->next) {
1151                 struct server_data *data = list->data;
1152                 GList *domains;
1153
1154                 if (data->protocol != IPPROTO_UDP || data->enabled == FALSE)
1155                         continue;
1156
1157                 server = create_server(data->interface, NULL,
1158                                         data->server, IPPROTO_TCP);
1159
1160                 /*
1161                  * If server is NULL, we're not connected yet.
1162                  * Copy the relevant buffers and continue with
1163                  * the next nameserver.
1164                  * The request will actually be sent once we're
1165                  * properly connected over TCP to this nameserver.
1166                  */
1167                 if (server == NULL) {
1168                         req->request = g_try_malloc0(req->request_len);
1169                         if (req->request == NULL)
1170                                 return TRUE;
1171
1172                         memcpy(req->request, buf, req->request_len);
1173
1174                         req->name = g_try_malloc0(sizeof(query));
1175                         if (req->name == NULL) {
1176                                 g_free(req->request);
1177                                 return TRUE;
1178                         }
1179                         memcpy(req->name, query, sizeof(query));
1180
1181                         continue;
1182                 }
1183
1184                 if (req->timeout > 0)
1185                         g_source_remove(req->timeout);
1186
1187                 for (domains = data->domains; domains;
1188                                 domains = domains->next) {
1189                         char *dom = domains->data;
1190
1191                         DBG("Adding domain %s to %s", dom, server->server);
1192
1193                         server->domains = g_list_append(server->domains,
1194                                                 g_strdup(dom));
1195                 }
1196
1197                 req->timeout = g_timeout_add_seconds(30, request_timeout, req);
1198                 ns_resolv(server, req, buf, query);
1199         }
1200
1201         return TRUE;
1202 }
1203
1204 static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition,
1205                                                         gpointer user_data)
1206 {
1207         unsigned char buf[768];
1208         char query[512];
1209         struct request_data *req;
1210         struct sockaddr_in6 client_addr;
1211         socklen_t client_addr_len = sizeof(client_addr);
1212         int sk, err, len;
1213
1214         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
1215                 connman_error("Error with UDP listener channel");
1216                 udp_listener_watch = 0;
1217                 return FALSE;
1218         }
1219
1220         sk = g_io_channel_unix_get_fd(channel);
1221
1222         memset(&client_addr, 0, client_addr_len);
1223         len = recvfrom(sk, buf, sizeof(buf), 0, (void *)&client_addr,
1224                        &client_addr_len);
1225         if (len < 2)
1226                 return TRUE;
1227
1228         DBG("Received %d bytes (id 0x%04x)", len, buf[0] | buf[1] << 8);
1229
1230         err = parse_request(buf, len, query, sizeof(query));
1231         if (err < 0 || (g_slist_length(server_list) == 0)) {
1232                 send_response(sk, buf, len, (void *)&client_addr,
1233                               client_addr_len, IPPROTO_UDP);
1234                 return TRUE;
1235         }
1236
1237         req = g_try_new0(struct request_data, 1);
1238         if (req == NULL)
1239                 return TRUE;
1240
1241         memcpy(&req->sa, &client_addr, client_addr_len);
1242         req->sa_len = client_addr_len;
1243         req->client_sk = 0;
1244         req->protocol = IPPROTO_UDP;
1245
1246         request_id += 2;
1247         if (request_id == 0x0000 || request_id == 0xffff)
1248                 request_id += 2;
1249
1250         req->srcid = buf[0] | (buf[1] << 8);
1251         req->dstid = request_id;
1252         req->altid = request_id + 1;
1253         req->request_len = len;
1254
1255         buf[0] = req->dstid & 0xff;
1256         buf[1] = req->dstid >> 8;
1257
1258         req->numserv = 0;
1259         req->timeout = g_timeout_add_seconds(5, request_timeout, req);
1260         request_list = g_slist_append(request_list, req);
1261
1262         return resolv(req, buf, query);
1263 }
1264
1265 static int create_dns_listener(int protocol)
1266 {
1267         GIOChannel *channel;
1268         const char *ifname = "lo", *proto;
1269         union {
1270                 struct sockaddr sa;
1271                 struct sockaddr_in6 sin6;
1272                 struct sockaddr_in sin;
1273         } s;
1274         socklen_t slen;
1275         int sk, type, v6only = 0;
1276         int family = AF_INET6;
1277
1278         DBG("");
1279
1280         switch (protocol) {
1281         case IPPROTO_UDP:
1282                 proto = "UDP";
1283                 type = SOCK_DGRAM;
1284                 break;
1285
1286         case IPPROTO_TCP:
1287                 proto = "TCP";
1288                 type = SOCK_STREAM;
1289                 break;
1290
1291         default:
1292                 return -EINVAL;
1293         }
1294
1295         sk = socket(family, type, protocol);
1296         if (sk < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
1297                 connman_error("No IPv6 support; DNS proxy listening only on Legacy IP");
1298                 family = AF_INET;
1299                 sk = socket(family, type, protocol);
1300         }
1301         if (sk < 0) {
1302                 connman_error("Failed to create %s listener socket", proto);
1303                 return -EIO;
1304         }
1305
1306         if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
1307                                         ifname, strlen(ifname) + 1) < 0) {
1308                 connman_error("Failed to bind %s listener interface", proto);
1309                 close(sk);
1310                 return -EIO;
1311         }
1312         /* Ensure it accepts Legacy IP connections too */
1313         if (family == AF_INET6 &&
1314                         setsockopt(sk, SOL_IPV6, IPV6_V6ONLY,
1315                                         &v6only, sizeof(v6only)) < 0) {
1316                 connman_error("Failed to clear V6ONLY on %s listener socket",
1317                               proto);
1318                 close(sk);
1319                 return -EIO;
1320         }
1321
1322         if (family == AF_INET) {
1323                 memset(&s.sin, 0, sizeof(s.sin));
1324                 s.sin.sin_family = AF_INET;
1325                 s.sin.sin_port = htons(53);
1326                 s.sin.sin_addr.s_addr = htonl(INADDR_ANY);
1327                 slen = sizeof(s.sin);
1328         } else {
1329                 memset(&s.sin6, 0, sizeof(s.sin6));
1330                 s.sin6.sin6_family = AF_INET6;
1331                 s.sin6.sin6_port = htons(53);
1332                 s.sin6.sin6_addr = in6addr_any;
1333                 slen = sizeof(s.sin6);
1334         }
1335
1336         if (bind(sk, &s.sa, slen) < 0) {
1337                 connman_error("Failed to bind %s listener socket", proto);
1338                 close(sk);
1339                 return -EIO;
1340         }
1341
1342         if (protocol == IPPROTO_TCP && listen(sk, 10) < 0) {
1343                 connman_error("Failed to listen on TCP socket");
1344                 close(sk);
1345                 return -EIO;
1346         }
1347
1348         channel = g_io_channel_unix_new(sk);
1349         if (channel == NULL) {
1350                 connman_error("Failed to create %s listener channel", proto);
1351                 close(sk);
1352                 return -EIO;
1353         }
1354
1355         g_io_channel_set_close_on_unref(channel, TRUE);
1356
1357         if (protocol == IPPROTO_TCP) {
1358                 tcp_listener_channel = channel;
1359                 tcp_listener_watch = g_io_add_watch(channel,
1360                                         G_IO_IN, tcp_listener_event, NULL);
1361         } else {
1362                 udp_listener_channel = channel;
1363                 udp_listener_watch = g_io_add_watch(channel,
1364                                         G_IO_IN, udp_listener_event, NULL);
1365         }
1366
1367         return 0;
1368 }
1369
1370 static void destroy_udp_listener(void)
1371 {
1372         DBG("");
1373
1374         if (udp_listener_watch > 0)
1375                 g_source_remove(udp_listener_watch);
1376
1377         g_io_channel_unref(udp_listener_channel);
1378 }
1379
1380 static void destroy_tcp_listener(void)
1381 {
1382         DBG("");
1383
1384         if (tcp_listener_watch > 0)
1385                 g_source_remove(tcp_listener_watch);
1386
1387         g_io_channel_unref(tcp_listener_channel);
1388 }
1389
1390 static int create_listener(void)
1391 {
1392         int err;
1393
1394         err = create_dns_listener(IPPROTO_UDP);
1395         if (err < 0)
1396                 return err;
1397
1398         err = create_dns_listener(IPPROTO_TCP);
1399         if (err < 0) {
1400                 destroy_udp_listener();
1401                 return err;
1402         }
1403
1404         __connman_resolvfile_append("lo", NULL, "127.0.0.1");
1405
1406         return 0;
1407 }
1408
1409 static void destroy_listener(void)
1410 {
1411         GSList *list;
1412
1413         __connman_resolvfile_remove("lo", NULL, "127.0.0.1");
1414
1415         for (list = request_pending_list; list; list = list->next) {
1416                 struct request_data *req = list->data;
1417
1418                 DBG("Dropping pending request (id 0x%04x -> 0x%04x)",
1419                                                 req->srcid, req->dstid);
1420
1421                 g_free(req->resp);
1422                 g_free(req->request);
1423                 g_free(req->name);
1424                 g_free(req);
1425                 list->data = NULL;
1426         }
1427
1428         g_slist_free(request_pending_list);
1429         request_pending_list = NULL;
1430
1431         for (list = request_list; list; list = list->next) {
1432                 struct request_data *req = list->data;
1433
1434                 DBG("Dropping request (id 0x%04x -> 0x%04x)",
1435                                                 req->srcid, req->dstid);
1436
1437                 g_free(req->resp);
1438                 g_free(req->request);
1439                 g_free(req->name);
1440                 g_free(req);
1441                 list->data = NULL;
1442         }
1443
1444         g_slist_free(request_list);
1445         request_list = NULL;
1446
1447         destroy_tcp_listener();
1448         destroy_udp_listener();
1449 }
1450
1451 int __connman_dnsproxy_init(void)
1452 {
1453         int err;
1454
1455         DBG("");
1456
1457         err = create_listener();
1458         if (err < 0)
1459                 return err;
1460
1461         err = connman_notifier_register(&dnsproxy_notifier);
1462         if (err < 0)
1463                 goto destroy;
1464
1465         return 0;
1466
1467 destroy:
1468         destroy_listener();
1469
1470         return err;
1471 }
1472
1473 void __connman_dnsproxy_cleanup(void)
1474 {
1475         DBG("");
1476
1477         connman_notifier_unregister(&dnsproxy_notifier);
1478
1479         destroy_listener();
1480 }