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