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