5368ceb6e93406f92ba49365323cfeead407cf32
[platform/upstream/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/log.h>
38
39 #include <glib.h>
40
41 #if __BYTE_ORDER == __LITTLE_ENDIAN
42 struct domain_hdr {
43         uint16_t id;
44         uint8_t rd:1;
45         uint8_t tc:1;
46         uint8_t aa:1;
47         uint8_t opcode:4;
48         uint8_t qr:1;
49         uint8_t rcode:4;
50         uint8_t z:3;
51         uint8_t ra:1;
52         uint16_t qdcount;
53         uint16_t ancount;
54         uint16_t nscount;
55         uint16_t arcount;
56 } __attribute__ ((packed));
57 #elif __BYTE_ORDER == __BIG_ENDIAN
58 struct domain_hdr {
59         uint16_t id;
60         uint8_t qr:1;
61         uint8_t opcode:4;
62         uint8_t aa:1;
63         uint8_t tc:1;
64         uint8_t rd:1;
65         uint8_t ra:1;
66         uint8_t z:3;
67         uint8_t rcode:4;
68         uint16_t qdcount;
69         uint16_t ancount;
70         uint16_t nscount;
71         uint16_t arcount;
72 } __attribute__ ((packed));
73 #else
74 #error "Unknown byte order"
75 #endif
76
77 struct server_data {
78         char *interface;
79         char *domain;
80         char *server;
81         GIOChannel *channel;
82         guint watch;
83         gboolean enabled;
84 };
85
86 struct request_data {
87         struct sockaddr_in sin;
88         socklen_t len;
89         guint16 srcid;
90         guint16 dstid;
91         guint16 altid;
92         guint timeout;
93         guint numserv;
94         guint numresp;
95         gpointer request;
96         gsize request_len;
97         gpointer name;
98         gpointer resp;
99         gsize resplen;
100 };
101
102 static GSList *server_list = NULL;
103 static GSList *request_list = NULL;
104 static GSList *request_pending_list = NULL;
105 static guint16 request_id = 0x0000;
106
107 static GIOChannel *listener_channel = NULL;
108 static guint listener_watch = 0;
109
110 static struct request_data *find_request(guint16 id)
111 {
112         GSList *list;
113
114         for (list = request_list; list; list = list->next) {
115                 struct request_data *req = list->data;
116
117                 if (req->dstid == id || req->altid == id)
118                         return req;
119         }
120
121         return NULL;
122 }
123
124 static struct server_data *find_server(const char *interface,
125                                         const char *domain, const char *server)
126 {
127         GSList *list;
128
129         DBG("interface %s server %s", interface, server);
130
131         for (list = server_list; list; list = list->next) {
132                 struct server_data *data = list->data;
133
134                 if (data->interface == NULL || data->server == NULL)
135                         continue;
136
137                 if (g_str_equal(data->interface, interface) == TRUE &&
138                                 g_str_equal(data->server, server) == TRUE) {
139                         if (domain == NULL) {
140                                 if (data->domain == NULL)
141                                         return data;
142                                 continue;
143                         }
144
145                         if (g_str_equal(data->domain, domain) == TRUE)
146                                 return data;
147                 }
148         }
149
150         return NULL;
151 }
152
153 static gboolean server_event(GIOChannel *channel, GIOCondition condition,
154                                                         gpointer user_data)
155 {
156         struct server_data *data = user_data;
157         struct request_data *req;
158         unsigned char buf[4096];
159         struct domain_hdr *hdr = (void *) &buf;
160         int sk, err, len;
161
162         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
163                 connman_error("Error with server channel");
164                 data->watch = 0;
165                 return FALSE;
166         }
167
168         sk = g_io_channel_unix_get_fd(channel);
169
170         len = recv(sk, buf, sizeof(buf), 0);
171         if (len < 12)
172                 return TRUE;
173
174         DBG("Received %d bytes (id 0x%04x)", len, buf[0] | buf[1] << 8);
175
176         req = find_request(buf[0] | buf[1] << 8);
177         if (req == NULL)
178                 return TRUE;
179
180         DBG("id 0x%04x rcode %d", hdr->id, hdr->rcode);
181
182         buf[0] = req->srcid & 0xff;
183         buf[1] = req->srcid >> 8;
184
185         req->numresp++;
186
187         if (hdr->rcode == 0 || req->resp == NULL) {
188                 g_free(req->resp);
189                 req->resplen = 0;
190
191                 req->resp = g_try_malloc(len);
192                 if (req->resp == NULL)
193                         return TRUE;
194
195                 memcpy(req->resp, buf, len);
196                 req->resplen = len;
197         }
198
199         if (hdr->rcode > 0 && req->numresp < req->numserv)
200                 return TRUE;
201
202         if (req->timeout > 0)
203                 g_source_remove(req->timeout);
204
205         request_list = g_slist_remove(request_list, req);
206
207         sk = g_io_channel_unix_get_fd(listener_channel);
208
209         err = sendto(sk, req->resp, req->resplen, 0,
210                                 (struct sockaddr *) &req->sin, req->len);
211
212         g_free(req->resp);
213         g_free(req);
214
215         return TRUE;
216 }
217
218 static struct server_data *create_server(const char *interface,
219                                         const char *domain, const char *server)
220 {
221         struct server_data *data;
222         struct sockaddr_in sin;
223         int sk;
224
225         DBG("interface %s server %s", interface, server);
226
227         sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
228         if (sk < 0) {
229                 connman_error("Failed to create server %s socket", server);
230                 return NULL;
231         }
232
233         if (interface != NULL) {
234                 if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
235                                 interface, strlen(interface) + 1) < 0) {
236                         connman_error("Failed to bind server %s "
237                                                 "to interface %s",
238                                                         server, interface);
239                         close(sk);
240                         return NULL;
241                 }
242         }
243
244         memset(&sin, 0, sizeof(sin));
245         sin.sin_family = AF_INET;
246         sin.sin_port = htons(53);
247         sin.sin_addr.s_addr = inet_addr(server);
248
249         if (connect(sk, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
250                 connman_error("Failed to connect server %s", server);
251                 close(sk);
252                 return NULL;
253         }
254
255         data = g_try_new0(struct server_data, 1);
256         if (data == NULL) {
257                 connman_error("Failed to allocate server %s data", server);
258                 close(sk);
259                 return NULL;
260         }
261
262         data->channel = g_io_channel_unix_new(sk);
263         if (data->channel == NULL) {
264                 connman_error("Failed to create server %s channel", server);
265                 close(sk);
266                 g_free(data);
267                 return NULL;
268         }
269
270         g_io_channel_set_close_on_unref(data->channel, TRUE);
271
272         data->watch = g_io_add_watch(data->channel, G_IO_IN,
273                                                 server_event, data);
274
275         data->interface = g_strdup(interface);
276         data->domain = g_strdup(domain);
277         data->server = g_strdup(server);
278
279         /* Enable new servers by default */
280         data->enabled = TRUE;
281
282         connman_info("Adding DNS server %s", data->server);
283
284         return data;
285 }
286
287 static void destroy_server(struct server_data *data)
288 {
289         DBG("interface %s server %s", data->interface, data->server);
290
291         if (data->watch > 0)
292                 g_source_remove(data->watch);
293
294         g_io_channel_unref(data->channel);
295
296         connman_info("Removing DNS server %s", data->server);
297
298         g_free(data->server);
299         g_free(data->domain);
300         g_free(data->interface);
301         g_free(data);
302 }
303
304 static int append_query(unsigned char *buf, unsigned int size,
305                                 const char *query, const char *domain)
306 {
307         unsigned char *ptr = buf;
308         char *offset;
309
310         DBG("query %s domain %s", query, domain);
311
312         offset = (char *) query;
313         while (offset != NULL) {
314                 char *tmp;
315
316                 tmp = strchr(offset, '.');
317                 if (tmp == NULL) {
318                         if (strlen(offset) == 0)
319                                 break;
320                         *ptr = strlen(offset);
321                         memcpy(ptr + 1, offset, strlen(offset));
322                         ptr += strlen(offset) + 1;
323                         break;
324                 }
325
326                 *ptr = tmp - offset;
327                 memcpy(ptr + 1, offset, tmp - offset);
328                 ptr += tmp - offset + 1;
329
330                 offset = tmp + 1;
331         }
332
333         offset = (char *) domain;
334         while (offset != NULL) {
335                 char *tmp;
336
337                 tmp = strchr(offset, '.');
338                 if (tmp == NULL) {
339                         if (strlen(offset) == 0)
340                                 break;
341                         *ptr = strlen(offset);
342                         memcpy(ptr + 1, offset, strlen(offset));
343                         ptr += strlen(offset) + 1;
344                         break;
345                 }
346
347                 *ptr = tmp - offset;
348                 memcpy(ptr + 1, offset, tmp - offset);
349                 ptr += tmp - offset + 1;
350
351                 offset = tmp + 1;
352         }
353
354         *ptr++ = 0x00;
355
356         return ptr - buf;
357 }
358
359 static gboolean request_timeout(gpointer user_data)
360 {
361         struct request_data *req = user_data;
362
363         DBG("id 0x%04x", req->srcid);
364
365         request_list = g_slist_remove(request_list, req);
366
367         if (req->resplen > 0 && req->resp != NULL) {
368                 int sk, err;
369
370                 sk = g_io_channel_unix_get_fd(listener_channel);
371
372                 err = sendto(sk, req->resp, req->resplen, 0,
373                                 (struct sockaddr *) &req->sin, req->len);
374         }
375
376         g_free(req->resp);
377         g_free(req);
378
379         return FALSE;
380 }
381
382 static gboolean resolv(struct request_data *req,
383                                 gpointer request, gpointer name)
384 {
385         int sk, err;
386         GSList *list;
387
388         request_list = g_slist_append(request_list, req);
389
390         req->numserv = 0;
391         req->timeout = g_timeout_add_seconds(5, request_timeout, req);
392
393         for (list = server_list; list; list = list->next) {
394                 struct server_data *data = list->data;
395
396                 DBG("server %s domain %s enabled %d",
397                                 data->server, data->domain, data->enabled);
398
399                 if (data->enabled == FALSE)
400                         continue;
401
402                 sk = g_io_channel_unix_get_fd(data->channel);
403
404                 err = send(sk, request, req->request_len, 0);
405
406                 req->numserv++;
407
408                 if (data->domain != NULL) {
409                         unsigned char alt[1024];
410                         struct domain_hdr *hdr = (void *) &alt;
411                         int altlen, domlen;
412
413                         domlen = strlen(data->domain) + 1;
414                         if (domlen < 5)
415                                 continue;
416
417                         alt[0] = req->altid & 0xff;
418                         alt[1] = req->altid >> 8;
419
420                         memcpy(alt + 2, request + 2, 10);
421                         hdr->qdcount = htons(1);
422
423                         altlen = append_query(alt + 12, sizeof(alt) - 12,
424                                                 name, data->domain);
425                         if (altlen < 0)
426                                 continue;
427
428                         altlen += 12;
429
430                         memcpy(alt + altlen, request + altlen - domlen,
431                                         req->request_len - altlen + domlen);
432
433                         err = send(sk, alt, req->request_len + domlen + 1, 0);
434
435                         req->numserv++;
436                 }
437         }
438
439         return TRUE;
440 }
441
442 static int dnsproxy_append(const char *interface, const char *domain,
443                                                         const char *server)
444 {
445         struct server_data *data;
446
447         DBG("interface %s server %s", interface, server);
448
449         if (g_str_equal(server, "127.0.0.1") == TRUE)
450                 return -ENODEV;
451
452         data = create_server(interface, domain, server);
453         if (data == NULL)
454                 return -EIO;
455
456         server_list = g_slist_append(server_list, data);
457
458         return 0;
459 }
460
461 static int dnsproxy_remove(const char *interface, const char *domain,
462                                                         const char *server)
463 {
464         struct server_data *data;
465
466         DBG("interface %s server %s", interface, server);
467
468         if (g_str_equal(server, "127.0.0.1") == TRUE)
469                 return -ENODEV;
470
471         data = find_server(interface, domain, server);
472         if (data == NULL)
473                 return 0;
474
475         server_list = g_slist_remove(server_list, data);
476
477         destroy_server(data);
478
479         return 0;
480 }
481
482 static void dnsproxy_flush(void)
483 {
484         GSList *list;
485
486         list = request_pending_list;
487         while (list) {
488                 struct request_data *req = list->data;
489
490                 list = list->next;
491
492                 request_pending_list =
493                                 g_slist_remove(request_pending_list, req);
494                 resolv(req, req->request, req->name);
495                 g_free(req->request);
496                 g_free(req->name);
497         }
498 }
499
500 static struct connman_resolver dnsproxy_resolver = {
501         .name           = "dnsproxy",
502         .priority       = CONNMAN_RESOLVER_PRIORITY_HIGH,
503         .append         = dnsproxy_append,
504         .remove         = dnsproxy_remove,
505         .flush          = dnsproxy_flush,
506 };
507
508 static void dnsproxy_offline_mode(connman_bool_t enabled)
509 {
510         GSList *list;
511
512         DBG("enabled %d", enabled);
513
514         for (list = server_list; list; list = list->next) {
515                 struct server_data *data = list->data;
516
517                 if (enabled == FALSE) {
518                         connman_info("Enabling DNS server %s", data->server);
519                         data->enabled = TRUE;
520                 } else {
521                         connman_info("Disabling DNS server %s", data->server);
522                         data->enabled = FALSE;
523                 }
524         }
525 }
526
527 static void dnsproxy_default_changed(struct connman_service *service)
528 {
529         GSList *list;
530         char *interface;
531
532         DBG("service %p", service);
533
534         if (service == NULL) {
535                 /* When no services are active, then disable DNS proxying */
536                 dnsproxy_offline_mode(TRUE);
537                 return;
538         }
539
540         interface = connman_service_get_interface(service);
541         if (interface == NULL)
542                 return;
543
544         for (list = server_list; list; list = list->next) {
545                 struct server_data *data = list->data;
546
547                 if (g_strcmp0(data->interface, interface) == 0) {
548                         connman_info("Enabling DNS server %s", data->server);
549                         data->enabled = TRUE;
550                 } else {
551                         connman_info("Disabling DNS server %s", data->server);
552                         data->enabled = FALSE;
553                 }
554         }
555
556         g_free(interface);
557 }
558
559 static struct connman_notifier dnsproxy_notifier = {
560         .name                   = "dnsproxy",
561         .default_changed        = dnsproxy_default_changed,
562         .offline_mode           = dnsproxy_offline_mode,
563 };
564
565 static unsigned char opt_edns0_type[2] = { 0x00, 0x29 };
566
567 static int parse_request(unsigned char *buf, int len,
568                                         char *name, unsigned int size)
569 {
570         struct domain_hdr *hdr = (void *) buf;
571         uint16_t qdcount = ntohs(hdr->qdcount);
572         uint16_t arcount = ntohs(hdr->arcount);
573         unsigned char *ptr;
574         char *last_label = NULL;
575         unsigned int remain, used = 0;
576
577         if (len < 12)
578                 return -EINVAL;
579
580         DBG("id 0x%04x qr %d opcode %d qdcount %d arcount %d",
581                                         hdr->id, hdr->qr, hdr->opcode,
582                                                         qdcount, arcount);
583
584         if (hdr->qr != 0 || qdcount != 1)
585                 return -EINVAL;
586
587         memset(name, 0, size);
588
589         ptr = buf + sizeof(struct domain_hdr);
590         remain = len - sizeof(struct domain_hdr);
591
592         while (remain > 0) {
593                 uint8_t len = *ptr;
594
595                 if (len == 0x00) {
596                         last_label = (char *) (ptr + 1);
597                         break;
598                 }
599
600                 if (used + len + 1 > size)
601                         return -ENOBUFS;
602
603                 strncat(name, (char *) (ptr + 1), len);
604                 strcat(name, ".");
605
606                 used += len + 1;
607
608                 ptr += len + 1;
609                 remain -= len + 1;
610         }
611
612         if (last_label && arcount && remain >= 9 && last_label[4] == 0 &&
613                                 !memcmp(last_label + 5, opt_edns0_type, 2)) {
614                 uint16_t edns0_bufsize;
615
616                 edns0_bufsize = last_label[7] << 8 | last_label[8];
617
618                 DBG("EDNS0 buffer size %u", edns0_bufsize);
619
620                 /* This is an evil hack until full TCP support has been
621                  * implemented.
622                  *
623                  * Somtimes the EDNS0 request gets send with a too-small
624                  * buffer size. Since glibc doesn't seem to crash when it
625                  * gets a response biffer then it requested, just bump
626                  * the buffer size up to 4KiB.
627                  */
628                 if (edns0_bufsize < 0x1000) {
629                         last_label[7] = 0x10;
630                         last_label[8] = 0x00;
631                 }
632         }
633
634         DBG("query %s", name);
635
636         return 0;
637 }
638
639 static void send_response(int sk, unsigned char *buf, int len,
640                                 const struct sockaddr *to, socklen_t tolen)
641 {
642         struct domain_hdr *hdr = (void *) buf;
643         int err;
644
645         if (len < 12)
646                 return;
647
648         DBG("id 0x%04x qr %d opcode %d", hdr->id, hdr->qr, hdr->opcode);
649
650         hdr->qr = 1;
651         hdr->rcode = 2;
652
653         hdr->ancount = 0;
654         hdr->nscount = 0;
655         hdr->arcount = 0;
656
657         err = sendto(sk, buf, len, 0, to, tolen);
658 }
659
660 static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
661                                                         gpointer user_data)
662 {
663         unsigned char buf[768];
664         char query[512];
665         struct request_data *req;
666         struct sockaddr_in sin;
667         socklen_t size = sizeof(sin);
668         int sk, err, len;
669
670         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
671                 connman_error("Error with listener channel");
672                 listener_watch = 0;
673                 return FALSE;
674         }
675
676         sk = g_io_channel_unix_get_fd(channel);
677
678         memset(&sin, 0, sizeof(sin));
679         len = recvfrom(sk, buf, sizeof(buf), 0,
680                                         (struct sockaddr *) &sin, &size);
681         if (len < 2)
682                 return TRUE;
683
684         DBG("Received %d bytes (id 0x%04x)", len, buf[0] | buf[1] << 8);
685
686         err = parse_request(buf, len, query, sizeof(query));
687         if (err < 0 || g_slist_length(server_list) == 0) {
688                 send_response(sk, buf, len, (struct sockaddr *) &sin, size);
689                 return TRUE;
690         }
691
692         req = g_try_new0(struct request_data, 1);
693         if (req == NULL)
694                 return TRUE;
695
696         memcpy(&req->sin, &sin, sizeof(sin));
697         req->len = size;
698
699         request_id += 2;
700         if (request_id == 0x0000 || request_id == 0xffff)
701                 request_id += 2;
702
703         req->srcid = buf[0] | (buf[1] << 8);
704         req->dstid = request_id;
705         req->altid = request_id + 1;
706         req->request_len = len;
707
708         buf[0] = req->dstid & 0xff;
709         buf[1] = req->dstid >> 8;
710
711         return resolv(req, buf, query);
712 }
713
714 static int create_listener(void)
715 {
716         const char *ifname = "lo";
717         struct sockaddr_in sin;
718         int sk;
719
720         DBG("");
721
722         sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
723         if (sk < 0) {
724                 connman_error("Failed to create listener socket");
725                 return -EIO;
726         }
727
728         //setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
729         //setsockopt(sk, SOL_IP, IP_PKTINFO, &opt, sizeof(opt));
730
731         if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
732                                         ifname, strlen(ifname) + 1) < 0) {
733                 connman_error("Failed to bind listener interface");
734                 close(sk);
735                 return -EIO;
736         }
737
738         memset(&sin, 0, sizeof(sin));
739         sin.sin_family = AF_INET;
740         sin.sin_port = htons(53);
741         sin.sin_addr.s_addr = inet_addr("127.0.0.1");
742         //sin.sin_addr.s_addr = INADDR_ANY;
743
744         if (bind(sk, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
745                 connman_error("Failed to bind listener socket");
746                 close(sk);
747                 return -EIO;
748         }
749
750         listener_channel = g_io_channel_unix_new(sk);
751         if (listener_channel == NULL) {
752                 connman_error("Failed to create listener channel");
753                 close(sk);
754                 return -EIO;
755         }
756
757         g_io_channel_set_close_on_unref(listener_channel, TRUE);
758
759         listener_watch = g_io_add_watch(listener_channel, G_IO_IN,
760                                                         listener_event, NULL);
761
762         connman_resolver_append("lo", NULL, "127.0.0.1");
763
764         return 0;
765 }
766
767 static void destroy_listener(void)
768 {
769         GSList *list;
770
771         DBG("");
772
773         connman_resolver_remove_all("lo");
774
775         if (listener_watch > 0)
776                 g_source_remove(listener_watch);
777
778         for (list = request_pending_list; list; list = list->next) {
779                 struct request_data *req = list->data;
780
781                 DBG("Dropping pending request (id 0x%04x -> 0x%04x)",
782                                                 req->srcid, req->dstid);
783
784                 g_free(req->resp);
785                 g_free(req->request);
786                 g_free(req->name);
787                 g_free(req);
788                 list->data = NULL;
789         }
790
791         g_slist_free(request_pending_list);
792         request_pending_list = NULL;
793
794         for (list = request_list; list; list = list->next) {
795                 struct request_data *req = list->data;
796
797                 DBG("Dropping request (id 0x%04x -> 0x%04x)",
798                                                 req->srcid, req->dstid);
799
800                 g_free(req->resp);
801                 g_free(req->request);
802                 g_free(req->name);
803                 g_free(req);
804                 list->data = NULL;
805         }
806
807         g_slist_free(request_list);
808         request_list = NULL;
809
810         g_io_channel_unref(listener_channel);
811 }
812
813 static int dnsproxy_init(void)
814 {
815         int err;
816
817         err = create_listener();
818         if (err < 0)
819                 return err;
820
821         err = connman_resolver_register(&dnsproxy_resolver);
822         if (err < 0)
823                 goto destroy;
824
825         err = connman_notifier_register(&dnsproxy_notifier);
826         if (err < 0)
827                 goto unregister;
828
829         return 0;
830
831 unregister:
832         connman_resolver_unregister(&dnsproxy_resolver);
833
834 destroy:
835         destroy_listener();
836
837         return err;
838 }
839
840 static void dnsproxy_exit(void)
841 {
842         connman_notifier_unregister(&dnsproxy_notifier);
843
844         connman_resolver_unregister(&dnsproxy_resolver);
845
846         destroy_listener();
847 }
848
849 CONNMAN_PLUGIN_DEFINE(dnsproxy, "DNS proxy resolver plugin", VERSION,
850                  CONNMAN_PLUGIN_PRIORITY_DEFAULT, dnsproxy_init, dnsproxy_exit)