c97ad263ceec8bba12d6d05f8fcff9b422d00090
[resolv_wrapper.git] / src / resolv_wrapper.c
1 /*
2  * Copyright (c) 2014-2018 Andreas Schneider <asn@samba.org>
3  * Copyright (c) 2014-2016 Jakub Hrozek <jakub.hrozek@posteo.se>
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the author nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include "config.h"
36
37 #include <errno.h>
38 #include <arpa/inet.h>
39 #ifdef HAVE_ARPA_NAMESER_H
40 #include <arpa/nameser.h>
41 #endif /* HAVE_ARPA_NAMESER_H */
42 #include <netinet/in.h>
43 #include <sys/socket.h>
44 #include <sys/types.h>
45 #include <stdarg.h>
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <stdbool.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <ctype.h>
52
53 #include <resolv.h>
54
55 #ifdef HAVE_RES_STATE_U_EXT_NSADDRS
56 #define HAVE_RESOLV_IPV6_NSADDRS 1
57 #endif
58
59 /* GCC has printf type attribute check. */
60 #ifdef HAVE_ATTRIBUTE_PRINTF_FORMAT
61 #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
62 #else
63 #define PRINTF_ATTRIBUTE(a,b)
64 #endif /* HAVE_ATTRIBUTE_PRINTF_FORMAT */
65
66 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
67 #define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
68 #else
69 #define DESTRUCTOR_ATTRIBUTE
70 #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
71
72 #ifndef RWRAP_DEFAULT_FAKE_TTL
73 #define RWRAP_DEFAULT_FAKE_TTL 600
74 #endif  /* RWRAP_DEFAULT_FAKE_TTL */
75
76 #ifndef HAVE_NS_NAME_COMPRESS
77 #define ns_name_compress dn_comp
78 #endif
79
80 #define ns_t_uri 256
81
82 enum rwrap_dbglvl_e {
83         RWRAP_LOG_ERROR = 0,
84         RWRAP_LOG_WARN,
85         RWRAP_LOG_NOTICE,
86         RWRAP_LOG_DEBUG,
87         RWRAP_LOG_TRACE
88 };
89
90 #ifndef HAVE_GETPROGNAME
91 static const char *getprogname(void)
92 {
93 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
94         return program_invocation_short_name;
95 #elif defined(HAVE_GETEXECNAME)
96         return getexecname();
97 #else
98         return NULL;
99 #endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
100 }
101 #endif /* HAVE_GETPROGNAME */
102
103 static void rwrap_log(enum rwrap_dbglvl_e dbglvl, const char *func, const char *format, ...) PRINTF_ATTRIBUTE(3, 4);
104 # define RWRAP_LOG(dbglvl, ...) rwrap_log((dbglvl), __func__, __VA_ARGS__)
105
106 static void rwrap_log(enum rwrap_dbglvl_e dbglvl,
107                       const char *func,
108                       const char *format, ...)
109 {
110         char buffer[1024];
111         va_list va;
112         const char *d;
113         unsigned int lvl = 0;
114         const char *prefix = NULL;
115         const char *progname = NULL;
116
117         d = getenv("RESOLV_WRAPPER_DEBUGLEVEL");
118         if (d != NULL) {
119                 lvl = atoi(d);
120         }
121
122         if (lvl < dbglvl) {
123                 return;
124         }
125
126         va_start(va, format);
127         vsnprintf(buffer, sizeof(buffer), format, va);
128         va_end(va);
129
130         switch (dbglvl) {
131                 case RWRAP_LOG_ERROR:
132                         prefix = "RWRAP_ERROR";
133                         break;
134                 case RWRAP_LOG_WARN:
135                         prefix = "RWRAP_WARN";
136                         break;
137                 case RWRAP_LOG_NOTICE:
138                         prefix = "RWRAP_NOTICE";
139                         break;
140                 case RWRAP_LOG_DEBUG:
141                         prefix = "RWRAP_DEBUG";
142                         break;
143                 case RWRAP_LOG_TRACE:
144                         prefix = "RWRAP_TRACE";
145                         break;
146         }
147
148         progname = getprogname();
149         if (progname == NULL) {
150                 progname = "<unknown>";
151         }
152
153         fprintf(stderr,
154                 "%s[%s (%u)] - %s: %s\n",
155                 prefix,
156                 progname,
157                 (unsigned int)getpid(),
158                 func,
159                 buffer);
160 }
161
162 #ifndef SAFE_FREE
163 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
164 #endif
165
166 #define NEXT_KEY(buf, key) do {                                 \
167         (key) = (buf) ? strpbrk((buf), " \t") : NULL;           \
168         if ((key) != NULL) {                                    \
169                 (key)[0] = '\0';                                \
170                 (key)++;                                        \
171         }                                                       \
172         while ((key) != NULL                                    \
173                && (isblank((int)(key)[0]))) {                   \
174                 (key)++;                                        \
175         }                                                       \
176 } while(0);
177
178 #define RWRAP_MAX_RECURSION 64
179
180 union rwrap_sockaddr {
181         struct sockaddr sa;
182         struct sockaddr_in in;
183         struct sockaddr_in6 in6;
184 };
185
186 /* Priority and weight can be omitted from the hosts file, but need to be part
187  * of the output
188  */
189 #define DFL_SRV_PRIO    1
190 #define DFL_SRV_WEIGHT  100
191 #define DFL_URI_PRIO    1
192 #define DFL_URI_WEIGHT  100
193
194 struct rwrap_srv_rrdata {
195         uint16_t port;
196         uint16_t prio;
197         uint16_t weight;
198         char hostname[MAXDNAME];
199 };
200
201 struct rwrap_uri_rrdata {
202         uint16_t prio;
203         uint16_t weight;
204         char uri[MAXDNAME];
205 };
206
207 struct rwrap_soa_rrdata {
208         uint32_t serial;
209         uint32_t refresh;
210         uint32_t retry;
211         uint32_t expire;
212         uint32_t minimum;
213         char nameserver[MAXDNAME];
214         char mailbox[MAXDNAME];
215 };
216
217 struct rwrap_fake_rr {
218         union fake_rrdata {
219                 struct in_addr a_rec;
220                 struct in6_addr aaaa_rec;
221                 struct rwrap_srv_rrdata srv_rec;
222                 struct rwrap_uri_rrdata uri_rec;
223                 struct rwrap_soa_rrdata soa_rec;
224                 char cname_rec[MAXDNAME];
225                 char ptr_rec[MAXDNAME];
226                 char txt_rec[MAXDNAME];
227         } rrdata;
228
229         char key[MAXDNAME];
230         int type; /* ns_t_* */
231 };
232
233 static void rwrap_fake_rr_init(struct rwrap_fake_rr *rr, size_t len)
234 {
235         size_t i;
236
237         for (i = 0; i < len; i++) {
238                 rr[i].type = ns_t_invalid;
239         }
240 }
241
242 static int rwrap_create_fake_a_rr(const char *key,
243                                   const char *value,
244                                   struct rwrap_fake_rr *rr)
245 {
246         int ok;
247
248         ok = inet_pton(AF_INET, value, &rr->rrdata.a_rec);
249         if (!ok) {
250                 RWRAP_LOG(RWRAP_LOG_ERROR,
251                           "Failed to convert [%s] to binary\n", value);
252                 return -1;
253         }
254
255         memcpy(rr->key, key, strlen(key) + 1);
256         rr->type = ns_t_a;
257         return 0;
258 }
259
260 static int rwrap_create_fake_aaaa_rr(const char *key,
261                                      const char *value,
262                                      struct rwrap_fake_rr *rr)
263 {
264         int ok;
265
266         ok = inet_pton(AF_INET6, value, &rr->rrdata.aaaa_rec);
267         if (!ok) {
268                 RWRAP_LOG(RWRAP_LOG_ERROR,
269                           "Failed to convert [%s] to binary\n", value);
270                 return -1;
271         }
272
273         memcpy(rr->key, key, strlen(key) + 1);
274         rr->type = ns_t_aaaa;
275         return 0;
276 }
277 static int rwrap_create_fake_ns_rr(const char *key,
278                                    const char *value,
279                                    struct rwrap_fake_rr *rr)
280 {
281         memcpy(rr->rrdata.srv_rec.hostname, value, strlen(value) + 1);
282         memcpy(rr->key, key, strlen(key) + 1);
283         rr->type = ns_t_ns;
284         return 0;
285 }
286
287 static int rwrap_create_fake_srv_rr(const char *key,
288                                     const char *value,
289                                     struct rwrap_fake_rr *rr)
290 {
291         char *str_prio;
292         char *str_weight;
293         char *str_port;
294         const char *hostname;
295
296         /* parse the value into priority, weight, port and hostname
297          * and check the validity */
298         hostname = value;
299         NEXT_KEY(hostname, str_port);
300         NEXT_KEY(str_port, str_prio);
301         NEXT_KEY(str_prio, str_weight);
302         if (str_port == NULL || hostname == NULL) {
303                 RWRAP_LOG(RWRAP_LOG_ERROR,
304                           "Malformed SRV entry [%s]\n", value);
305                 return -1;
306         }
307
308         if (str_prio) {
309                 rr->rrdata.srv_rec.prio = atoi(str_prio);
310         } else {
311                 rr->rrdata.srv_rec.prio = DFL_SRV_PRIO;
312         }
313         if (str_weight) {
314                 rr->rrdata.srv_rec.weight = atoi(str_weight);
315         } else {
316                 rr->rrdata.srv_rec.weight = DFL_SRV_WEIGHT;
317         }
318         rr->rrdata.srv_rec.port = atoi(str_port);
319         memcpy(rr->rrdata.srv_rec.hostname , hostname, strlen(hostname) + 1);
320
321         memcpy(rr->key, key, strlen(key) + 1);
322         rr->type = ns_t_srv;
323         return 0;
324 }
325
326 static int rwrap_create_fake_uri_rr(const char *key,
327                                     const char *value,
328                                     struct rwrap_fake_rr *rr)
329 {
330         char *str_prio;
331         char *str_weight;
332         const char *uri;
333
334         /* parse the value into priority, weight, and uri
335          * and check the validity */
336         uri = value;
337         NEXT_KEY(uri, str_prio);
338         NEXT_KEY(str_prio, str_weight);
339         if (uri == NULL) {
340                 RWRAP_LOG(RWRAP_LOG_ERROR,
341                           "Malformed URI entry [<null>]\n");
342                 return -1;
343         }
344
345         if (str_prio) {
346                 rr->rrdata.uri_rec.prio = atoi(str_prio);
347         } else {
348                 rr->rrdata.uri_rec.prio = DFL_URI_PRIO;
349         }
350         if (str_weight) {
351                 rr->rrdata.uri_rec.weight = atoi(str_weight);
352         } else {
353                 rr->rrdata.uri_rec.weight = DFL_URI_WEIGHT;
354         }
355         memcpy(rr->rrdata.uri_rec.uri, uri, strlen(uri) + 1);
356
357         memcpy(rr->key, key, strlen(key) + 1);
358         rr->type = ns_t_uri;
359         return 0;
360 }
361
362 static int rwrap_create_fake_txt_rr(const char *key,
363                                     const char *value,
364                                     struct rwrap_fake_rr *rr)
365 {
366         memcpy(rr->rrdata.txt_rec, value, strlen(value) + 1);
367
368         memcpy(rr->key, key, strlen(key) + 1);
369         rr->type = ns_t_txt;
370         return 0;
371 }
372
373 static int rwrap_create_fake_soa_rr(const char *key,
374                                     const char *value,
375                                     struct rwrap_fake_rr *rr)
376 {
377         const char *nameserver;
378         char *mailbox;
379         char *str_serial;
380         char *str_refresh;
381         char *str_retry;
382         char *str_expire;
383         char *str_minimum;
384
385         /* parse the value into nameserver, mailbox, serial, refresh,
386          * retry, expire, minimum and check the validity
387          */
388         nameserver = value;
389         NEXT_KEY(nameserver, mailbox);
390         NEXT_KEY(mailbox, str_serial);
391         NEXT_KEY(str_serial, str_refresh);
392         NEXT_KEY(str_refresh, str_retry);
393         NEXT_KEY(str_retry, str_expire);
394         NEXT_KEY(str_expire, str_minimum);
395         if (nameserver == NULL || mailbox == NULL || str_serial == NULL ||
396             str_refresh == NULL || str_retry == NULL || str_expire == NULL ||
397             str_minimum == NULL) {
398                 RWRAP_LOG(RWRAP_LOG_ERROR,
399                           "Malformed SOA entry [%s]\n", value);
400                 return -1;
401         }
402
403         memcpy(rr->rrdata.soa_rec.nameserver, nameserver, strlen(nameserver)+1);
404         memcpy(rr->rrdata.soa_rec.mailbox, mailbox, strlen(mailbox)+1);
405
406         rr->rrdata.soa_rec.serial = atoi(str_serial);
407         rr->rrdata.soa_rec.refresh = atoi(str_refresh);
408         rr->rrdata.soa_rec.retry = atoi(str_retry);
409         rr->rrdata.soa_rec.expire = atoi(str_expire);
410         rr->rrdata.soa_rec.minimum = atoi(str_minimum);
411
412         memcpy(rr->key, key, strlen(key) + 1);
413         rr->type = ns_t_soa;
414         return 0;
415 }
416
417 static int rwrap_create_fake_cname_rr(const char *key,
418                                       const char *value,
419                                       struct rwrap_fake_rr *rr)
420 {
421         memcpy(rr->rrdata.cname_rec , value, strlen(value) + 1);
422         memcpy(rr->key, key, strlen(key) + 1);
423         rr->type = ns_t_cname;
424         return 0;
425 }
426
427 static int rwrap_create_fake_ptr_rr(const char *key,
428                                     const char *value,
429                                     struct rwrap_fake_rr *rr)
430 {
431         memcpy(rr->rrdata.ptr_rec , value, strlen(value) + 1);
432         memcpy(rr->key, key, strlen(key) + 1);
433         rr->type = ns_t_ptr;
434         return 0;
435 }
436
437 /* Prepares a fake header with a single response. Advances header_blob */
438 static ssize_t rwrap_fake_header(uint8_t **header_blob, size_t remaining,
439                                  size_t ancount, size_t arcount)
440 {
441         union {
442                 uint8_t *blob;
443                 HEADER *header;
444         } h;
445
446         if (remaining < NS_HFIXEDSZ) {
447                 RWRAP_LOG(RWRAP_LOG_ERROR, "Buffer too small!\n");
448                 return -1;
449         }
450
451         h.blob = *header_blob;
452         memset(h.blob, 0, NS_HFIXEDSZ);
453
454         h.header->id = res_randomid();          /* random query ID */
455         h.header->qr = 1;                       /* response flag */
456         h.header->rd = 1;                       /* recursion desired */
457         h.header->ra = 1;                       /* recursion available */
458
459         h.header->qdcount = htons(1);           /* no. of questions */
460         h.header->ancount = htons(ancount);     /* no. of answers */
461         h.header->arcount = htons(arcount);     /* no. of add'tl records */
462
463         /* move past the header */
464         *header_blob = h.blob += NS_HFIXEDSZ;
465
466         return NS_HFIXEDSZ;
467 }
468
469 static ssize_t rwrap_fake_question(const char *question,
470                                    uint16_t type,
471                                    uint8_t **question_ptr,
472                                    size_t remaining)
473 {
474         uint8_t *qb = *question_ptr;
475         int n;
476
477         n = ns_name_compress(question, qb, remaining, NULL, NULL);
478         if (n < 0) {
479                 RWRAP_LOG(RWRAP_LOG_ERROR,
480                           "Failed to compress [%s]\n", question);
481                 return -1;
482         }
483
484         qb += n;
485         remaining -= n;
486
487         if (remaining < 2 * sizeof(uint16_t)) {
488                 RWRAP_LOG(RWRAP_LOG_ERROR, "Buffer too small!\n");
489                 return -1;
490         }
491
492         NS_PUT16(type, qb);
493         NS_PUT16(ns_c_in, qb);
494
495         *question_ptr = qb;
496         return n + 2 * sizeof(uint16_t);
497 }
498
499 static ssize_t rwrap_fake_rdata_common(uint16_t type,
500                                        size_t rdata_size,
501                                        const char *key,
502                                        size_t remaining,
503                                        uint8_t **rdata_ptr)
504 {
505         uint8_t *rd = *rdata_ptr;
506         ssize_t written = 0;
507
508         written = ns_name_compress(key, rd, remaining, NULL, NULL);
509         if (written < 0) {
510                 RWRAP_LOG(RWRAP_LOG_ERROR,
511                           "Failed to compress [%s]\n", key);
512                 return -1;
513         }
514         rd += written;
515         remaining -= written;
516
517         if (remaining < 3 * sizeof(uint16_t) + sizeof(uint32_t)) {
518                 RWRAP_LOG(RWRAP_LOG_ERROR, "Buffer too small\n");
519                 return -1;
520         }
521
522         NS_PUT16(type, rd);
523         NS_PUT16(ns_c_in, rd);
524         NS_PUT32(RWRAP_DEFAULT_FAKE_TTL, rd);
525         NS_PUT16(rdata_size, rd);
526
527         if (remaining < rdata_size) {
528                 RWRAP_LOG(RWRAP_LOG_ERROR, "Buffer too small\n");
529                 return -1;
530         }
531
532         *rdata_ptr = rd;
533         return written + 3 * sizeof(uint16_t) + sizeof(uint32_t) + rdata_size;
534 }
535
536 static ssize_t rwrap_fake_a(struct rwrap_fake_rr *rr,
537                             uint8_t *answer_ptr,
538                             size_t anslen)
539 {
540         uint8_t *a = answer_ptr;
541         ssize_t resp_size;
542
543         if (rr->type != ns_t_a) {
544                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
545                 return -1;
546         }
547         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding A RR");
548
549         resp_size = rwrap_fake_rdata_common(ns_t_a, sizeof(struct in_addr), rr->key,
550                                             anslen, &a);
551         if (resp_size < 0) {
552                 return -1;
553         }
554
555         memcpy(a, &rr->rrdata.a_rec, sizeof(struct in_addr));
556
557         return resp_size;
558 }
559
560 static ssize_t rwrap_fake_aaaa(struct rwrap_fake_rr *rr,
561                                uint8_t *answer,
562                                size_t anslen)
563 {
564         uint8_t *a = answer;
565         ssize_t resp_size;
566
567         if (rr->type != ns_t_aaaa) {
568                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
569                 return -1;
570         }
571         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding AAAA RR");
572
573         resp_size = rwrap_fake_rdata_common(ns_t_aaaa, sizeof(struct in6_addr),
574                                             rr->key, anslen, &a);
575         if (resp_size < 0) {
576                 return -1;
577         }
578
579         memcpy(a, &rr->rrdata.aaaa_rec, sizeof(struct in6_addr));
580
581         return resp_size;
582 }
583
584 static ssize_t rwrap_fake_ns(struct rwrap_fake_rr *rr,
585                              uint8_t *answer,
586                             size_t anslen)
587 {
588         uint8_t *a = answer;
589         ssize_t resp_size = 0;
590         size_t rdata_size;
591         unsigned char hostname_compressed[MAXDNAME];
592         ssize_t compressed_len;
593
594         if (rr->type != ns_t_ns) {
595                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
596                 return -1;
597         }
598         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding NS RR");
599
600         /* Prepare the data to write */
601         compressed_len = ns_name_compress(rr->rrdata.srv_rec.hostname,
602                                           hostname_compressed,
603                                           MAXDNAME,
604                                           NULL,
605                                           NULL);
606         if (compressed_len < 0) {
607                 return -1;
608         }
609
610         /* Is this enough? */
611         rdata_size = compressed_len;
612
613         resp_size = rwrap_fake_rdata_common(ns_t_ns, rdata_size,
614                                             rr->key, anslen, &a);
615         if (resp_size < 0) {
616                 return -1;
617         }
618
619         memcpy(a, hostname_compressed, compressed_len);
620
621         return resp_size;
622 }
623
624 static ssize_t rwrap_fake_srv(struct rwrap_fake_rr *rr,
625                               uint8_t *answer,
626                               size_t anslen)
627 {
628         uint8_t *a = answer;
629         ssize_t resp_size;
630         size_t rdata_size;
631         unsigned char hostname_compressed[MAXDNAME];
632         ssize_t compressed_len;
633
634         if (rr->type != ns_t_srv) {
635                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
636                 return -1;
637         }
638         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding SRV RR");
639         rdata_size = 3 * sizeof(uint16_t);
640
641         /* Prepare the data to write */
642         compressed_len = ns_name_compress(rr->rrdata.srv_rec.hostname,
643                                           hostname_compressed, MAXDNAME,
644                                           NULL, NULL);
645         if (compressed_len < 0) {
646                 return -1;
647         }
648         rdata_size += compressed_len;
649
650         resp_size = rwrap_fake_rdata_common(ns_t_srv, rdata_size,
651                                             rr->key, anslen, &a);
652         if (resp_size < 0) {
653                 return -1;
654         }
655
656         NS_PUT16(rr->rrdata.srv_rec.prio, a);
657         NS_PUT16(rr->rrdata.srv_rec.weight, a);
658         NS_PUT16(rr->rrdata.srv_rec.port, a);
659         memcpy(a, hostname_compressed, compressed_len);
660
661         return resp_size;
662 }
663
664 static ssize_t rwrap_fake_uri(struct rwrap_fake_rr *rr,
665                               uint8_t *answer,
666                               size_t anslen)
667 {
668         uint8_t *a = answer;
669         ssize_t resp_size;
670         size_t rdata_size;
671         size_t uri_len;
672
673         if (rr->type != ns_t_uri) {
674                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
675                 return -1;
676         }
677         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding URI RR");
678         rdata_size = 3 * sizeof(uint16_t);
679         uri_len = strlen(rr->rrdata.uri_rec.uri) + 1;
680         rdata_size += uri_len;
681
682         resp_size = rwrap_fake_rdata_common(ns_t_uri, rdata_size,
683                                             rr->key, anslen, &a);
684         if (resp_size < 0) {
685                 return -1;
686         }
687
688         NS_PUT16(rr->rrdata.uri_rec.prio, a);
689         NS_PUT16(rr->rrdata.uri_rec.weight, a);
690         memcpy(a, rr->rrdata.uri_rec.uri, uri_len);
691
692         return resp_size;
693 }
694
695 static ssize_t rwrap_fake_txt(struct rwrap_fake_rr *rr,
696                               uint8_t *answer,
697                               size_t anslen)
698 {
699         uint8_t *a = answer;
700         ssize_t resp_size;
701         size_t rdata_size;
702         size_t txt_len;
703
704         if (rr->type != ns_t_txt) {
705                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
706                 return -1;
707         }
708         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding TXT RR");
709         txt_len = strlen(rr->rrdata.txt_rec) + 1;
710         rdata_size = txt_len;
711
712         resp_size = rwrap_fake_rdata_common(ns_t_txt, rdata_size,
713                                             rr->key, anslen, &a);
714         if (resp_size < 0) {
715                 return -1;
716         }
717
718         memcpy(a, rr->rrdata.txt_rec, txt_len);
719
720         return resp_size;
721 }
722
723 static ssize_t rwrap_fake_soa(struct rwrap_fake_rr *rr,
724                               uint8_t *answer,
725                               size_t anslen)
726 {
727         uint8_t *a = answer;
728         ssize_t resp_size;
729         size_t rdata_size;
730         unsigned char nameser_compressed[MAXDNAME];
731         ssize_t compressed_ns_len;
732         unsigned char mailbox_compressed[MAXDNAME];
733         ssize_t compressed_mb_len;
734
735         if (rr->type != ns_t_soa) {
736                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
737                 return -1;
738         }
739         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding SOA RR");
740         rdata_size = 5 * sizeof(uint16_t);
741
742         compressed_ns_len = ns_name_compress(rr->rrdata.soa_rec.nameserver,
743                                              nameser_compressed,
744                                              MAXDNAME, NULL, NULL);
745         if (compressed_ns_len < 0) {
746                 return -1;
747         }
748         rdata_size += compressed_ns_len;
749
750         compressed_mb_len = ns_name_compress(rr->rrdata.soa_rec.mailbox,
751                                              mailbox_compressed,
752                                              MAXDNAME, NULL, NULL);
753         if (compressed_mb_len < 0) {
754                 return -1;
755         }
756         rdata_size += compressed_mb_len;
757
758         resp_size = rwrap_fake_rdata_common(ns_t_soa, rdata_size,
759                                             rr->key, anslen, &a);
760         if (resp_size < 0) {
761                 return -1;
762         }
763
764         memcpy(a, nameser_compressed, compressed_ns_len);
765         a += compressed_ns_len;
766         memcpy(a, mailbox_compressed, compressed_mb_len);
767         a += compressed_mb_len;
768         NS_PUT32(rr->rrdata.soa_rec.serial, a);
769         NS_PUT32(rr->rrdata.soa_rec.refresh, a);
770         NS_PUT32(rr->rrdata.soa_rec.retry, a);
771         NS_PUT32(rr->rrdata.soa_rec.expire, a);
772         NS_PUT32(rr->rrdata.soa_rec.minimum, a);
773
774         return resp_size;
775 }
776
777 static ssize_t rwrap_fake_cname(struct rwrap_fake_rr *rr,
778                                 uint8_t *answer,
779                                 size_t anslen)
780 {
781         uint8_t *a = answer;
782         ssize_t resp_size;
783         unsigned char hostname_compressed[MAXDNAME];
784         ssize_t rdata_size;
785
786         if (rr->type != ns_t_cname) {
787                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
788                 return -1;
789         }
790         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding CNAME RR");
791
792         /* Prepare the data to write */
793         rdata_size = ns_name_compress(rr->rrdata.cname_rec,
794                                       hostname_compressed, MAXDNAME,
795                                       NULL, NULL);
796         if (rdata_size < 0) {
797                 return -1;
798         }
799
800         resp_size = rwrap_fake_rdata_common(ns_t_cname, rdata_size,
801                                             rr->key, anslen, &a);
802         if (resp_size < 0) {
803                 return -1;
804         }
805
806         memcpy(a, hostname_compressed, rdata_size);
807
808         return resp_size;
809 }
810
811 static ssize_t rwrap_fake_ptr(struct rwrap_fake_rr *rr,
812                               uint8_t *answer,
813                               size_t anslen)
814 {
815         uint8_t *a = answer;
816         ssize_t rdata_size;
817         ssize_t resp_size;
818         unsigned char hostname_compressed[MAXDNAME];
819
820         if (rr->type != ns_t_ptr) {
821                 RWRAP_LOG(RWRAP_LOG_ERROR, "Wrong type!\n");
822                 return -1;
823         }
824         RWRAP_LOG(RWRAP_LOG_TRACE, "Adding PTR RR");
825
826         /* Prepare the data to write */
827         rdata_size = ns_name_compress(rr->rrdata.ptr_rec,
828                                       hostname_compressed, MAXDNAME,
829                                       NULL, NULL);
830         if (rdata_size < 0) {
831                 return -1;
832         }
833
834         resp_size = rwrap_fake_rdata_common(ns_t_ptr, rdata_size,
835                                             rr->key, anslen, &a);
836         if (resp_size < 0) {
837                 return -1;
838         }
839
840         memcpy(a, hostname_compressed, rdata_size);
841
842         return resp_size;
843 }
844
845 #define RESOLV_MATCH(line, name) \
846         (strncmp(line, name, sizeof(name) - 1) == 0 && \
847         (line[sizeof(name) - 1] == ' ' || \
848          line[sizeof(name) - 1] == '\t'))
849
850 #define TYPE_MATCH(type, ns_type, rec_type, str_type, key, query) \
851         ((type) == (ns_type) && \
852          (strncmp((rec_type), (str_type), sizeof(str_type)) == 0) && \
853          (strcasecmp(key, query)) == 0)
854
855
856 static int rwrap_get_record(const char *hostfile, unsigned recursion,
857                             const char *query, int type,
858                             struct rwrap_fake_rr *rr);
859
860 static int rwrap_uri_recurse(const char *hostfile, unsigned recursion,
861                              const char *query, struct rwrap_fake_rr *rr)
862 {
863         int rc;
864
865         rc = rwrap_get_record(hostfile, recursion, query, ns_t_uri, rr);
866         if (rc == ENOENT) {
867                 rc = 0;
868         }
869
870         return rc;
871 }
872
873 static int rwrap_srv_recurse(const char *hostfile, unsigned recursion,
874                              const char *query, struct rwrap_fake_rr *rr)
875 {
876         int rc;
877
878         rc = rwrap_get_record(hostfile, recursion, query, ns_t_a, rr);
879         if (rc == 0) return 0;
880
881         rc = rwrap_get_record(hostfile, recursion, query, ns_t_aaaa, rr);
882         if (rc == ENOENT) rc = 0;
883
884         return rc;
885 }
886
887 static int rwrap_cname_recurse(const char *hostfile, unsigned recursion,
888                                const char *query, struct rwrap_fake_rr *rr)
889 {
890         int rc;
891
892         rc = rwrap_get_record(hostfile, recursion, query, ns_t_a, rr);
893         if (rc == 0) return 0;
894
895         rc = rwrap_get_record(hostfile, recursion, query, ns_t_aaaa, rr);
896         if (rc == 0) return 0;
897
898         rc = rwrap_get_record(hostfile, recursion, query, ns_t_cname, rr);
899         if (rc == ENOENT) rc = 0;
900
901         return rc;
902 }
903
904 static int rwrap_get_record(const char *hostfile, unsigned recursion,
905                             const char *query, int type,
906                             struct rwrap_fake_rr *rr)
907 {
908         FILE *fp = NULL;
909         char buf[BUFSIZ];
910         char *key = NULL;
911         char *value = NULL;
912         int rc = ENOENT;
913         unsigned num_uris = 0;
914
915         if (recursion >= RWRAP_MAX_RECURSION) {
916                 RWRAP_LOG(RWRAP_LOG_ERROR, "Recursed too deep!\n");
917                 return -1;
918         }
919
920         RWRAP_LOG(RWRAP_LOG_TRACE,
921                   "Searching in fake hosts file %s for %s:%d\n", hostfile,
922                   query, type);
923
924         fp = fopen(hostfile, "r");
925         if (fp == NULL) {
926                 RWRAP_LOG(RWRAP_LOG_WARN,
927                           "Opening %s failed: %s",
928                           hostfile, strerror(errno));
929                 return -1;
930         }
931
932         while (fgets(buf, sizeof(buf), fp) != NULL) {
933                 char *rec_type;
934                 char *q;
935
936                 rec_type = buf;
937                 key = value = NULL;
938
939                 NEXT_KEY(rec_type, key);
940                 NEXT_KEY(key, value);
941
942                 if (key == NULL || value == NULL) {
943                         RWRAP_LOG(RWRAP_LOG_WARN,
944                                 "Malformed line: not enough parts, use \"rec_type key data\n"
945                                 "For example \"A cwrap.org 10.10.10.10\"");
946                         continue;
947                 }
948
949                 q = value;
950                 while(q[0] != '\n' && q[0] != '\0') {
951                         q++;
952                 }
953                 q[0] = '\0';
954
955                 if (type == ns_t_uri && recursion > 0) {
956                         /* Skip non-URI records. */
957                         if (!TYPE_MATCH(type, ns_t_uri, rec_type, "URI", key, query)) {
958                                 continue;
959                         }
960                         /* Skip previous records based on the recurse depth. */
961                         num_uris++;
962                         if (num_uris <= recursion) {
963                                 continue;
964                         }
965                 }
966
967                 if (TYPE_MATCH(type, ns_t_a, rec_type, "A", key, query)) {
968                         rc = rwrap_create_fake_a_rr(key, value, rr);
969                         break;
970                 } else if (TYPE_MATCH(type, ns_t_aaaa,
971                                       rec_type, "AAAA", key, query)) {
972                         rc = rwrap_create_fake_aaaa_rr(key, value, rr);
973                         break;
974                 } else if (TYPE_MATCH(type, ns_t_ns,
975                                       rec_type, "NS", key, query)) {
976                         rc = rwrap_create_fake_ns_rr(key, value, rr);
977                         break;
978                 } else if (TYPE_MATCH(type, ns_t_srv,
979                                       rec_type, "SRV", key, query)) {
980                         rc = rwrap_create_fake_srv_rr(key, value, rr);
981                         if (rc == 0) {
982                                 rc = rwrap_srv_recurse(hostfile, recursion+1,
983                                                 rr->rrdata.srv_rec.hostname,
984                                                 rr + 1);
985                         }
986                         break;
987                 } else if (TYPE_MATCH(type, ns_t_uri,
988                                       rec_type, "URI", key, query)) {
989                         rc = rwrap_create_fake_uri_rr(key, value, rr);
990                         if (rc == 0) {
991                                 /* Recurse to collect multiple URI answers under a single key. */
992                                 rc = rwrap_uri_recurse(hostfile, recursion + 1, key, rr + 1);
993                         }
994                         break;
995                 } else if (TYPE_MATCH(type, ns_t_soa,
996                                       rec_type, "SOA", key, query)) {
997                         rc = rwrap_create_fake_soa_rr(key, value, rr);
998                         break;
999                 } else if (TYPE_MATCH(type, ns_t_cname,
1000                                       rec_type, "CNAME", key, query)) {
1001                         rc = rwrap_create_fake_cname_rr(key, value, rr);
1002                         if (rc == 0) {
1003                                 rc = rwrap_cname_recurse(hostfile, recursion+1,
1004                                                          value, rr + 1);
1005                         }
1006                         break;
1007                 } else if (TYPE_MATCH(type, ns_t_a, rec_type, "CNAME", key, query)) {
1008                         rc = rwrap_create_fake_cname_rr(key, value, rr);
1009                         if (rc == 0) {
1010                                 rc = rwrap_cname_recurse(hostfile, recursion+1,
1011                                                          value, rr + 1);
1012                         }
1013                         break;
1014                 } else if (TYPE_MATCH(type, ns_t_ptr,
1015                                       rec_type, "PTR", key, query)) {
1016                         rc = rwrap_create_fake_ptr_rr(key, value, rr);
1017                         break;
1018                 }
1019                 else if (TYPE_MATCH(type, ns_t_txt,
1020                                       rec_type, "TXT", key, query)) {
1021                         rc = rwrap_create_fake_txt_rr(key, value, rr);
1022                         break;
1023                 }
1024         }
1025
1026         if (rc == ENOENT && recursion == 0 && key != NULL) {
1027                 RWRAP_LOG(RWRAP_LOG_TRACE, "Record for [%s] not found\n", query);
1028                 memcpy(rr->key, key, strlen(key) + 1);
1029         }
1030
1031         fclose(fp);
1032         return rc;
1033 }
1034
1035 static ssize_t rwrap_fake_empty(int type,
1036                                 const char *question,
1037                                 uint8_t *answer,
1038                                 size_t anslen)
1039 {
1040         ssize_t resp_data;
1041         size_t remaining = anslen;
1042
1043         resp_data = rwrap_fake_header(&answer, remaining, 0, 0);
1044         if (resp_data < 0) {
1045                 return -1;
1046         }
1047         remaining -= resp_data;
1048
1049         resp_data += rwrap_fake_question(question, type, &answer, remaining);
1050         if (resp_data < 0) {
1051                 return -1;
1052         }
1053         remaining -= resp_data;
1054
1055         resp_data += rwrap_fake_rdata_common(type, 0, question,
1056                                             remaining, &answer);
1057         if (resp_data < 0) {
1058                 return -1;
1059         }
1060
1061         return resp_data;
1062 }
1063
1064 static inline bool rwrap_known_type(int type)
1065 {
1066         switch (type) {
1067         case ns_t_a:
1068         case ns_t_aaaa:
1069         case ns_t_ns:
1070         case ns_t_srv:
1071         case ns_t_uri:
1072         case ns_t_soa:
1073         case ns_t_cname:
1074         case ns_t_ptr:
1075         case ns_t_txt:
1076                 return true;
1077         }
1078
1079         return false;
1080 }
1081
1082 static int rwrap_ancount(struct rwrap_fake_rr *rrs, int qtype)
1083 {
1084         int i;
1085         int ancount = 0;
1086
1087         /* For URI return the number of URIs. */
1088         if (qtype == ns_t_uri) {
1089                 for (i = 0; i < RWRAP_MAX_RECURSION; i++) {
1090                         if (rwrap_known_type(rrs[i].type) &&
1091                             rrs[i].type == qtype) {
1092                                 ancount++;
1093                         }
1094                 }
1095                 return ancount;
1096         }
1097
1098         /* Include all RRs in the stack until the sought type
1099          * in the answer section. This is the case i.e. when looking
1100          * up an A record but the name points to a CNAME
1101          */
1102         for (i = 0; i < RWRAP_MAX_RECURSION; i++) {
1103                 ancount++;
1104
1105                 if (rwrap_known_type(rrs[i].type) &&
1106                     rrs[i].type == qtype) {
1107                         break;
1108                 }
1109         }
1110
1111         /* Return 0 records if the sought type wasn't in the stack */
1112         return i < RWRAP_MAX_RECURSION ? ancount : 0;
1113 }
1114
1115 static int rwrap_arcount(struct rwrap_fake_rr *rrs, int ancount)
1116 {
1117         int i;
1118         int arcount = 0;
1119
1120         /* start from index ancount */
1121         for (i = ancount; i < RWRAP_MAX_RECURSION; i++) {
1122                 if (rwrap_known_type(rrs[i].type)) {
1123                         arcount++;
1124                 }
1125         }
1126
1127         return arcount;
1128 }
1129
1130 static ssize_t rwrap_add_rr(struct rwrap_fake_rr *rr,
1131                             uint8_t *answer,
1132                             size_t anslen)
1133 {
1134         ssize_t resp_data;
1135
1136         if (rr == NULL) {
1137                 RWRAP_LOG(RWRAP_LOG_ERROR, "Internal error!\n");
1138                 return -1;
1139         }
1140
1141         switch (rr->type) {
1142         case ns_t_a:
1143                 resp_data = rwrap_fake_a(rr, answer, anslen);
1144                 break;
1145         case ns_t_aaaa:
1146                 resp_data = rwrap_fake_aaaa(rr, answer, anslen);
1147                 break;
1148         case ns_t_ns:
1149                 resp_data = rwrap_fake_ns(rr, answer, anslen);
1150                 break;
1151         case ns_t_srv:
1152                 resp_data = rwrap_fake_srv(rr, answer, anslen);
1153                 break;
1154         case ns_t_uri:
1155                 resp_data = rwrap_fake_uri(rr, answer, anslen);
1156                 break;
1157         case ns_t_soa:
1158                 resp_data = rwrap_fake_soa(rr, answer, anslen);
1159                 break;
1160         case ns_t_cname:
1161                 resp_data = rwrap_fake_cname(rr, answer, anslen);
1162                 break;
1163         case ns_t_ptr:
1164                 resp_data = rwrap_fake_ptr(rr, answer, anslen);
1165                 break;
1166         case ns_t_txt:
1167                 resp_data = rwrap_fake_txt(rr, answer, anslen);
1168                 break;
1169         default:
1170                 return -1;
1171         }
1172
1173         return resp_data;
1174 }
1175
1176 static ssize_t rwrap_fake_answer(struct rwrap_fake_rr *rrs,
1177                                  int type,
1178                                  uint8_t *answer,
1179                                  size_t anslen)
1180
1181 {
1182         ssize_t resp_data;
1183         ssize_t rrlen;
1184         size_t remaining = anslen;
1185         int ancount;
1186         int arcount;
1187         int i;
1188
1189         ancount = rwrap_ancount(rrs, type);
1190         arcount = rwrap_arcount(rrs, ancount);
1191         RWRAP_LOG(RWRAP_LOG_TRACE,
1192                   "Got %d answers and %d additional records\n", ancount, arcount);
1193
1194         resp_data = rwrap_fake_header(&answer, remaining, ancount, arcount);
1195         if (resp_data < 0) {
1196                 return -1;
1197         }
1198         remaining -= resp_data;
1199
1200         resp_data += rwrap_fake_question(rrs->key, rrs->type, &answer, remaining);
1201         if (resp_data < 0) {
1202                 return -1;
1203         }
1204         remaining -= resp_data;
1205
1206         /* answer */
1207         for (i = 0; i < ancount; i++) {
1208                 rrlen = rwrap_add_rr(&rrs[i], answer, remaining);
1209                 if (rrlen < 0) {
1210                         return -1;
1211                 }
1212                 remaining -= rrlen;
1213                 answer += rrlen;
1214                 resp_data += rrlen;
1215         }
1216
1217         /* add authoritative NS here? */
1218
1219         /* additional records */
1220         for (i = ancount; i < ancount + arcount; i++) {
1221                 rrlen = rwrap_add_rr(&rrs[i], answer, remaining);
1222                 if (rrlen < 0) {
1223                         return -1;
1224                 }
1225                 remaining -= rrlen;
1226                 answer += rrlen;
1227                 resp_data += rrlen;
1228         }
1229
1230         return resp_data;
1231 }
1232
1233 /* Reads in a file in the following format:
1234  * TYPE RDATA
1235  *
1236  * Malformed entries are silently skipped.
1237  * Allocates answer buffer of size anslen that has to be freed after use.
1238  */
1239 static int rwrap_res_fake_hosts(const char *hostfile,
1240                                 const char *query,
1241                                 int type,
1242                                 unsigned char *answer,
1243                                 size_t anslen)
1244 {
1245         int rc = ENOENT;
1246         char *query_name = NULL;
1247         size_t qlen = strlen(query);
1248         struct rwrap_fake_rr rrs[RWRAP_MAX_RECURSION];
1249         ssize_t resp_size;
1250
1251         RWRAP_LOG(RWRAP_LOG_TRACE,
1252                   "Searching in fake hosts file %s\n", hostfile);
1253
1254         if (qlen > 0 && query[qlen-1] == '.') {
1255                 qlen--;
1256         }
1257
1258         query_name = strndup(query, qlen);
1259         if (query_name == NULL) {
1260                 return -1;
1261         }
1262
1263         rwrap_fake_rr_init(rrs, RWRAP_MAX_RECURSION);
1264
1265         rc = rwrap_get_record(hostfile, 0, query_name, type, rrs);
1266         switch (rc) {
1267         case 0:
1268                 RWRAP_LOG(RWRAP_LOG_TRACE,
1269                                 "Found record for [%s]\n", query_name);
1270                 resp_size = rwrap_fake_answer(rrs, type, answer, anslen);
1271                 break;
1272         case ENOENT:
1273                 RWRAP_LOG(RWRAP_LOG_TRACE,
1274                                 "No record for [%s]\n", query_name);
1275                 resp_size = rwrap_fake_empty(type, rrs->key, answer, anslen);
1276                 break;
1277         default:
1278                 RWRAP_LOG(RWRAP_LOG_NOTICE,
1279                           "Searching for [%s] did not return any results\n",
1280                           query_name);
1281                 free(query_name);
1282                 return -1;
1283         }
1284
1285         switch (resp_size) {
1286         case -1:
1287                 RWRAP_LOG(RWRAP_LOG_ERROR,
1288                                 "Error faking answer for [%s]\n", query_name);
1289                 break;
1290         default:
1291                 RWRAP_LOG(RWRAP_LOG_TRACE,
1292                                 "Successfully faked answer for [%s]\n",
1293                                 query_name);
1294                 break;
1295         }
1296
1297         free(query_name);
1298         return resp_size;
1299 }
1300
1301 /*********************************************************
1302  * RWRAP LOADING LIBC FUNCTIONS
1303  *********************************************************/
1304
1305 #include <dlfcn.h>
1306
1307 typedef int (*__libc_res_ninit)(struct __res_state *state);
1308 typedef int (*__libc___res_ninit)(struct __res_state *state);
1309 typedef void (*__libc_res_nclose)(struct __res_state *state);
1310 typedef void (*__libc___res_nclose)(struct __res_state *state);
1311 typedef int (*__libc_res_nquery)(struct __res_state *state,
1312                                  const char *dname,
1313                                  int class,
1314                                  int type,
1315                                  unsigned char *answer,
1316                                  int anslen);
1317 typedef int (*__libc___res_nquery)(struct __res_state *state,
1318                                    const char *dname,
1319                                    int class,
1320                                    int type,
1321                                    unsigned char *answer,
1322                                    int anslen);
1323 typedef int (*__libc_res_nsearch)(struct __res_state *state,
1324                                   const char *dname,
1325                                   int class,
1326                                   int type,
1327                                   unsigned char *answer,
1328                                   int anslen);
1329 typedef int (*__libc___res_nsearch)(struct __res_state *state,
1330                                     const char *dname,
1331                                     int class,
1332                                     int type,
1333                                     unsigned char *answer,
1334                                     int anslen);
1335
1336 #define RWRAP_SYMBOL_ENTRY(i) \
1337         union { \
1338                 __libc_##i f; \
1339                 void *obj; \
1340         } _libc_##i
1341
1342 struct rwrap_libc_symbols {
1343         RWRAP_SYMBOL_ENTRY(res_ninit);
1344         RWRAP_SYMBOL_ENTRY(__res_ninit);
1345         RWRAP_SYMBOL_ENTRY(res_nclose);
1346         RWRAP_SYMBOL_ENTRY(__res_nclose);
1347         RWRAP_SYMBOL_ENTRY(res_nquery);
1348         RWRAP_SYMBOL_ENTRY(__res_nquery);
1349         RWRAP_SYMBOL_ENTRY(res_nsearch);
1350         RWRAP_SYMBOL_ENTRY(__res_nsearch);
1351 };
1352 #undef RWRAP_SYMBOL_ENTRY
1353
1354 struct rwrap {
1355         struct {
1356                 void *handle;
1357                 struct rwrap_libc_symbols symbols;
1358         } libc;
1359
1360         struct {
1361                 void *handle;
1362                 struct rwrap_libc_symbols symbols;
1363         } libresolv;
1364
1365         bool initialised;
1366         bool enabled;
1367
1368         char *socket_dir;
1369 };
1370
1371 static struct rwrap rwrap;
1372
1373 enum rwrap_lib {
1374     RWRAP_LIBC,
1375     RWRAP_LIBRESOLV
1376 };
1377
1378 static const char *rwrap_str_lib(enum rwrap_lib lib)
1379 {
1380         switch (lib) {
1381         case RWRAP_LIBC:
1382                 return "libc";
1383         case RWRAP_LIBRESOLV:
1384                 return "libresolv";
1385         }
1386
1387         /* Compiler would warn us about unhandled enum value if we get here */
1388         return "unknown";
1389 }
1390
1391 static void *rwrap_load_lib_handle(enum rwrap_lib lib)
1392 {
1393         int flags = RTLD_LAZY;
1394         void *handle = NULL;
1395         int i;
1396
1397 #ifdef RTLD_DEEPBIND
1398         const char *env_preload = getenv("LD_PRELOAD");
1399         const char *env_deepbind = getenv("RESOLV_WRAPPER_DISABLE_DEEPBIND");
1400         bool enable_deepbind = true;
1401
1402         /* Don't do a deepbind if we run with libasan */
1403         if (env_preload != NULL && strlen(env_preload) < 1024) {
1404                 const char *p = strstr(env_preload, "libasan.so");
1405                 if (p != NULL) {
1406                         enable_deepbind = false;
1407                 }
1408         }
1409
1410         if (env_deepbind != NULL && strlen(env_deepbind) >= 1) {
1411                 enable_deepbind = false;
1412         }
1413
1414         if (enable_deepbind) {
1415                 flags |= RTLD_DEEPBIND;
1416         }
1417 #endif
1418
1419         switch (lib) {
1420         case RWRAP_LIBRESOLV:
1421 #ifdef HAVE_LIBRESOLV
1422                 handle = rwrap.libresolv.handle;
1423                 if (handle == NULL) {
1424                         for (i = 10; i >= 0; i--) {
1425                                 char soname[256] = {0};
1426
1427                                 snprintf(soname, sizeof(soname), "libresolv.so.%d", i);
1428                                 handle = dlopen(soname, flags);
1429                                 if (handle != NULL) {
1430                                         break;
1431                                 }
1432                         }
1433
1434                         rwrap.libresolv.handle = handle;
1435                 }
1436                 break;
1437 #endif
1438                 /* FALL TROUGH */
1439         case RWRAP_LIBC:
1440                 handle = rwrap.libc.handle;
1441 #ifdef LIBC_SO
1442                 if (handle == NULL) {
1443                         handle = dlopen(LIBC_SO, flags);
1444
1445                         rwrap.libc.handle = handle;
1446                 }
1447 #endif
1448                 if (handle == NULL) {
1449                         for (i = 10; i >= 0; i--) {
1450                                 char soname[256] = {0};
1451
1452                                 snprintf(soname, sizeof(soname), "libc.so.%d", i);
1453                                 handle = dlopen(soname, flags);
1454                                 if (handle != NULL) {
1455                                         break;
1456                                 }
1457                         }
1458
1459                         rwrap.libc.handle = handle;
1460                 }
1461                 break;
1462         }
1463
1464         if (handle == NULL) {
1465 #ifdef RTLD_NEXT
1466                 handle = rwrap.libc.handle = rwrap.libresolv.handle = RTLD_NEXT;
1467 #else
1468                 RWRAP_LOG(RWRAP_LOG_ERROR,
1469                           "Failed to dlopen library: %s\n",
1470                           dlerror());
1471                 exit(-1);
1472 #endif
1473         }
1474
1475         return handle;
1476 }
1477
1478 static void *_rwrap_bind_symbol(enum rwrap_lib lib, const char *fn_name)
1479 {
1480         void *handle;
1481         void *func;
1482
1483         handle = rwrap_load_lib_handle(lib);
1484
1485         func = dlsym(handle, fn_name);
1486         if (func == NULL) {
1487                 RWRAP_LOG(RWRAP_LOG_ERROR,
1488                                 "Failed to find %s: %s\n",
1489                                 fn_name, dlerror());
1490                 exit(-1);
1491         }
1492
1493         RWRAP_LOG(RWRAP_LOG_TRACE,
1494                         "Loaded %s from %s",
1495                         fn_name, rwrap_str_lib(lib));
1496         return func;
1497 }
1498
1499 #define rwrap_bind_symbol_libc(sym_name) \
1500         if (rwrap.libc.symbols._libc_##sym_name.obj == NULL) { \
1501                 rwrap.libc.symbols._libc_##sym_name.obj = \
1502                         _rwrap_bind_symbol(RWRAP_LIBC, #sym_name); \
1503         }
1504
1505 #define rwrap_bind_symbol_libresolv(sym_name) \
1506         if (rwrap.libresolv.symbols._libc_##sym_name.obj == NULL) { \
1507                 rwrap.libresolv.symbols._libc_##sym_name.obj = \
1508                         _rwrap_bind_symbol(RWRAP_LIBRESOLV, #sym_name); \
1509         }
1510
1511 /*
1512  * IMPORTANT
1513  *
1514  * Functions especially from libc need to be loaded individually, you can't load
1515  * all at once or gdb will segfault at startup. The same applies to valgrind and
1516  * has probably something todo with with the linker.
1517  * So we need load each function at the point it is called the first time.
1518  */
1519
1520 static int libc_res_ninit(struct __res_state *state)
1521 {
1522 #if !defined(res_ninit) && defined(HAVE_RES_NINIT)
1523         rwrap_bind_symbol_libresolv(res_ninit);
1524
1525         return rwrap.libresolv.symbols._libc_res_ninit.f(state);
1526 #elif defined(HAVE___RES_NINIT)
1527         rwrap_bind_symbol_libresolv(__res_ninit);
1528
1529         return rwrap.libresolv.symbols._libc___res_ninit.f(state);
1530 #else
1531 #error "No res_ninit function"
1532 #endif
1533 }
1534
1535 static void libc_res_nclose(struct __res_state *state)
1536 {
1537 #if !defined(res_close) && defined(HAVE_RES_NCLOSE)
1538         rwrap_bind_symbol_libresolv(res_nclose);
1539
1540         rwrap.libresolv.symbols._libc_res_nclose.f(state);
1541         return;
1542 #elif defined(HAVE___RES_NCLOSE)
1543         rwrap_bind_symbol_libresolv(__res_nclose);
1544
1545         rwrap.libresolv.symbols._libc___res_nclose.f(state);
1546 #else
1547 #error "No res_nclose function"
1548 #endif
1549 }
1550
1551 static int libc_res_nquery(struct __res_state *state,
1552                            const char *dname,
1553                            int class,
1554                            int type,
1555                            unsigned char *answer,
1556                            int anslen)
1557 {
1558 #if !defined(res_nquery) && defined(HAVE_RES_NQUERY)
1559         rwrap_bind_symbol_libresolv(res_nquery);
1560
1561         return rwrap.libresolv.symbols._libc_res_nquery.f(state,
1562                                                           dname,
1563                                                           class,
1564                                                           type,
1565                                                           answer,
1566                                                           anslen);
1567 #elif defined(HAVE___RES_NQUERY)
1568         rwrap_bind_symbol_libresolv(__res_nquery);
1569
1570         return rwrap.libresolv.symbols._libc___res_nquery.f(state,
1571                                                             dname,
1572                                                             class,
1573                                                             type,
1574                                                             answer,
1575                                                             anslen);
1576 #else
1577 #error "No res_nquery function"
1578 #endif
1579 }
1580
1581 static int libc_res_nsearch(struct __res_state *state,
1582                             const char *dname,
1583                             int class,
1584                             int type,
1585                             unsigned char *answer,
1586                             int anslen)
1587 {
1588 #if !defined(res_nsearch) && defined(HAVE_RES_NSEARCH)
1589         rwrap_bind_symbol_libresolv(res_nsearch);
1590
1591         return rwrap.libresolv.symbols._libc_res_nsearch.f(state,
1592                                                            dname,
1593                                                            class,
1594                                                            type,
1595                                                            answer,
1596                                                            anslen);
1597 #elif defined(HAVE___RES_NSEARCH)
1598         rwrap_bind_symbol_libresolv(__res_nsearch);
1599
1600         return rwrap.libresolv.symbols._libc___res_nsearch.f(state,
1601                                                              dname,
1602                                                              class,
1603                                                              type,
1604                                                              answer,
1605                                                              anslen);
1606 #else
1607 #error "No res_nsearch function"
1608 #endif
1609 }
1610
1611 /****************************************************************************
1612  *   RES_HELPER
1613  ***************************************************************************/
1614
1615 static size_t rwrap_get_nameservers(struct __res_state *state,
1616                                     size_t nserv,
1617                                     union rwrap_sockaddr *nsaddrs)
1618 {
1619         size_t i;
1620
1621         memset(nsaddrs, 0, sizeof(*nsaddrs) * nserv);
1622
1623         if (nserv > (size_t)state->nscount) {
1624                 nserv = (size_t)state->nscount;
1625         }
1626
1627         for (i = 0; i < nserv; i++) {
1628 #ifdef HAVE_RES_STATE_U_EXT_NSADDRS
1629                 if (state->_u._ext.nsaddrs[i] != NULL) {
1630                         nsaddrs[i] = (union rwrap_sockaddr) {
1631                                 .in6 = *state->_u._ext.nsaddrs[i],
1632                         };
1633                 } else
1634 #endif /* HAVE_RES_STATE_U_EXT_NSADDRS */
1635                 {
1636                         nsaddrs[i] = (union rwrap_sockaddr) {
1637                                 .in = state->nsaddr_list[i],
1638                         };
1639                 }
1640         }
1641
1642         return nserv;
1643 }
1644
1645 static void rwrap_log_nameservers(enum rwrap_dbglvl_e dbglvl,
1646                                   const char *func,
1647                                   struct __res_state *state)
1648 {
1649         union rwrap_sockaddr nsaddrs[MAXNS];
1650         size_t nserv = MAXNS;
1651         size_t i;
1652
1653         memset(nsaddrs, 0, sizeof(nsaddrs));
1654         nserv = rwrap_get_nameservers(state, nserv, nsaddrs);
1655         for (i = 0; i < nserv; i++) {
1656                 char ip[INET6_ADDRSTRLEN];
1657
1658                 switch (nsaddrs[i].sa.sa_family) {
1659                 case AF_INET:
1660                         inet_ntop(AF_INET, &(nsaddrs[i].in.sin_addr),
1661                                   ip, sizeof(ip));
1662                         break;
1663                 case AF_INET6:
1664                         inet_ntop(AF_INET6, &(nsaddrs[i].in6.sin6_addr),
1665                                   ip, sizeof(ip));
1666                         break;
1667                 default:
1668                         snprintf(ip, sizeof(ip), "<unknown sa_family=%d",
1669                                  nsaddrs[i].sa.sa_family);
1670                         break;
1671                 }
1672
1673                 rwrap_log(dbglvl, func,
1674                           "        nameserver: %s",
1675                           ip);
1676         }
1677 }
1678
1679 static void rwrap_reset_nameservers(struct __res_state *state)
1680 {
1681 #ifdef HAVE_RES_STATE_U_EXT_NSADDRS
1682         size_t i;
1683
1684         for (i = 0; i < (size_t)state->nscount; i++) {
1685                 if (state->_u._ext.nssocks[i] != -1) {
1686                         close(state->_u._ext.nssocks[i]);
1687                         state->_u._ext.nssocks[i] = -1;
1688                 }
1689                 SAFE_FREE(state->_u._ext.nsaddrs[i]);
1690         }
1691         memset(&state->_u._ext, 0, sizeof(state->_u._ext));
1692         for (i = 0; i < MAXNS; i++) {
1693                 state->_u._ext.nssocks[i] = -1;
1694                 state->_u._ext.nsmap[i] = MAXNS + 1;
1695         }
1696         state->ipv6_unavail = false;
1697 #endif
1698         memset(state->nsaddr_list, 0, sizeof(state->nsaddr_list));
1699         state->nscount = 0;
1700 }
1701
1702 static int rwrap_parse_resolv_conf(struct __res_state *state,
1703                                    const char *resolv_conf)
1704 {
1705         FILE *fp;
1706         char buf[BUFSIZ];
1707         int nserv = 0;
1708
1709         rwrap_reset_nameservers(state);
1710
1711         fp = fopen(resolv_conf, "r");
1712         if (fp == NULL) {
1713                 RWRAP_LOG(RWRAP_LOG_ERROR,
1714                           "Opening %s failed: %s",
1715                           resolv_conf, strerror(errno));
1716                 return -1;
1717         }
1718
1719         while(fgets(buf, sizeof(buf), fp) != NULL) {
1720                 char *p;
1721
1722                 /* Ignore comments */
1723                 if (buf[0] == '#' || buf[0] == ';') {
1724                         continue;
1725                 }
1726
1727                 if (RESOLV_MATCH(buf, "nameserver") && nserv < MAXNS) {
1728                         struct in_addr a;
1729                         char *q;
1730                         int ok;
1731
1732                         p = buf + strlen("nameserver");
1733
1734                         /* Skip spaces and tabs */
1735                         while(isblank((int)p[0])) {
1736                                 p++;
1737                         }
1738
1739                         q = p;
1740                         while(q[0] != '\n' && q[0] != '\0') {
1741                                 q++;
1742                         }
1743                         q[0] = '\0';
1744
1745                         ok = inet_pton(AF_INET, p, &a);
1746                         if (ok) {
1747                                 state->nsaddr_list[nserv] = (struct sockaddr_in) {
1748                                         .sin_family = AF_INET,
1749                                         .sin_addr = a,
1750                                         .sin_port = htons(53),
1751                                         .sin_zero = { 0 },
1752                                 };
1753
1754                                 nserv++;
1755                         } else {
1756 #ifdef HAVE_RESOLV_IPV6_NSADDRS
1757                                 /* IPv6 */
1758                                 struct in6_addr a6;
1759                                 ok = inet_pton(AF_INET6, p, &a6);
1760                                 if (ok) {
1761                                         struct sockaddr_in6 *sa6;
1762
1763                                         sa6 = malloc(sizeof(*sa6));
1764                                         if (sa6 == NULL) {
1765                                                 fclose(fp);
1766                                                 return -1;
1767                                         }
1768
1769                                         sa6->sin6_family = AF_INET6;
1770                                         sa6->sin6_port = htons(53);
1771                                         sa6->sin6_flowinfo = 0;
1772                                         sa6->sin6_addr = a6;
1773
1774                                         state->_u._ext.nsaddrs[nserv] = sa6;
1775                                         state->_u._ext.nssocks[nserv] = -1;
1776                                         state->_u._ext.nsmap[nserv] = MAXNS + 1;
1777
1778                                         state->_u._ext.nscount6++;
1779                                         nserv++;
1780                                 } else {
1781                                         RWRAP_LOG(RWRAP_LOG_ERROR,
1782                                                 "Malformed DNS server");
1783                                         continue;
1784                                 }
1785 #else /* !HAVE_RESOLV_IPV6_NSADDRS */
1786                                 /*
1787                                  * BSD uses an opaque structure to store the
1788                                  * IPv6 addresses. So we can not simply store
1789                                  * these addresses the same way as above.
1790                                  */
1791                                 RWRAP_LOG(RWRAP_LOG_WARN,
1792                                           "resolve_wrapper does not support "
1793                                           "IPv6 on this platform");
1794                                         continue;
1795 #endif
1796                         }
1797                         continue;
1798                 } /* TODO: match other keywords */
1799         }
1800
1801         /*
1802          * note that state->_u._ext.nscount is left as 0,
1803          * this matches glibc and allows resolv wrapper
1804          * to work with most (maybe all) glibc versions.
1805          */
1806         state->nscount = nserv;
1807
1808         if (ferror(fp)) {
1809                 RWRAP_LOG(RWRAP_LOG_ERROR,
1810                           "Reading from %s failed",
1811                           resolv_conf);
1812                 fclose(fp);
1813                 return -1;
1814         }
1815
1816         fclose(fp);
1817         return 0;
1818 }
1819
1820 /****************************************************************************
1821  *   RES_NINIT
1822  ***************************************************************************/
1823
1824 static int rwrap_res_ninit(struct __res_state *state)
1825 {
1826         int rc;
1827
1828         rc = libc_res_ninit(state);
1829         if (rc == 0) {
1830                 const char *resolv_conf = getenv("RESOLV_WRAPPER_CONF");
1831
1832                 if (resolv_conf != NULL) {
1833                         rc = rwrap_parse_resolv_conf(state, resolv_conf);
1834                 }
1835         }
1836
1837         return rc;
1838 }
1839
1840 #if !defined(res_ninit) && defined(HAVE_RES_NINIT)
1841 int res_ninit(struct __res_state *state)
1842 #elif defined(HAVE___RES_NINIT)
1843 int __res_ninit(struct __res_state *state)
1844 #endif
1845 {
1846         return rwrap_res_ninit(state);
1847 }
1848
1849 /****************************************************************************
1850  *   RES_INIT
1851  ***************************************************************************/
1852
1853 static struct __res_state rwrap_res_state;
1854
1855 static int rwrap_res_init(void)
1856 {
1857         int rc;
1858
1859         rc = rwrap_res_ninit(&rwrap_res_state);
1860
1861         return rc;
1862 }
1863
1864 #if !defined(res_ninit) && defined(HAVE_RES_INIT)
1865 int res_init(void)
1866 #elif defined(HAVE___RES_INIT)
1867 int __res_init(void)
1868 #endif
1869 {
1870         return rwrap_res_init();
1871 }
1872
1873 /****************************************************************************
1874  *   RES_NCLOSE
1875  ***************************************************************************/
1876
1877 static void rwrap_res_nclose(struct __res_state *state)
1878 {
1879         rwrap_reset_nameservers(state);
1880         libc_res_nclose(state);
1881 }
1882
1883 #if !defined(res_nclose) && defined(HAVE_RES_NCLOSE)
1884 void res_nclose(struct __res_state *state)
1885 #elif defined(HAVE___RES_NCLOSE)
1886 void __res_nclose(struct __res_state *state)
1887 #endif
1888 {
1889         rwrap_res_nclose(state);
1890 }
1891
1892 /****************************************************************************
1893  *   RES_CLOSE
1894  ***************************************************************************/
1895
1896 static void rwrap_res_close(void)
1897 {
1898         rwrap_res_nclose(&rwrap_res_state);
1899 }
1900
1901 #if defined(HAVE_RES_CLOSE)
1902 void res_close(void)
1903 #elif defined(HAVE___RES_CLOSE)
1904 void __res_close(void)
1905 #endif
1906 {
1907         rwrap_res_close();
1908 }
1909
1910 /****************************************************************************
1911  *   RES_NQUERY
1912  ***************************************************************************/
1913
1914 static int rwrap_res_nquery(struct __res_state *state,
1915                             const char *dname,
1916                             int class,
1917                             int type,
1918                             unsigned char *answer,
1919                             int anslen)
1920 {
1921         int rc;
1922         const char *fake_hosts;
1923
1924         RWRAP_LOG(RWRAP_LOG_TRACE,
1925                   "Resolve the domain name [%s] - class=%d, type=%d",
1926                   dname, class, type);
1927         rwrap_log_nameservers(RWRAP_LOG_TRACE, __func__, state);
1928
1929         fake_hosts = getenv("RESOLV_WRAPPER_HOSTS");
1930         if (fake_hosts != NULL) {
1931                 rc = rwrap_res_fake_hosts(fake_hosts, dname, type, answer, anslen);
1932         } else {
1933                 rc = libc_res_nquery(state, dname, class, type, answer, anslen);
1934         }
1935
1936
1937         RWRAP_LOG(RWRAP_LOG_TRACE,
1938                   "The returned response length is: %d",
1939                   rc);
1940
1941         return rc;
1942 }
1943
1944 #if !defined(res_nquery) && defined(HAVE_RES_NQUERY)
1945 int res_nquery(struct __res_state *state,
1946                const char *dname,
1947                int class,
1948                int type,
1949                unsigned char *answer,
1950                int anslen)
1951 #elif defined(HAVE___RES_NQUERY)
1952 int __res_nquery(struct __res_state *state,
1953                  const char *dname,
1954                  int class,
1955                  int type,
1956                  unsigned char *answer,
1957                  int anslen)
1958 #endif
1959 {
1960         return rwrap_res_nquery(state, dname, class, type, answer, anslen);
1961 }
1962
1963 /****************************************************************************
1964  *   RES_QUERY
1965  ***************************************************************************/
1966
1967 static int rwrap_res_query(const char *dname,
1968                            int class,
1969                            int type,
1970                            unsigned char *answer,
1971                            int anslen)
1972 {
1973         int rc;
1974
1975         rc = rwrap_res_ninit(&rwrap_res_state);
1976         if (rc != 0) {
1977                 return rc;
1978         }
1979
1980         rc = rwrap_res_nquery(&rwrap_res_state,
1981                               dname,
1982                               class,
1983                               type,
1984                               answer,
1985                               anslen);
1986
1987         return rc;
1988 }
1989
1990 #if !defined(res_query) && defined(HAVE_RES_QUERY)
1991 int res_query(const char *dname,
1992               int class,
1993               int type,
1994               unsigned char *answer,
1995               int anslen)
1996 #elif defined(HAVE___RES_QUERY)
1997 int __res_query(const char *dname,
1998                 int class,
1999                 int type,
2000                 unsigned char *answer,
2001                 int anslen)
2002 #endif
2003 {
2004         return rwrap_res_query(dname, class, type, answer, anslen);
2005 }
2006
2007 /****************************************************************************
2008  *   RES_NSEARCH
2009  ***************************************************************************/
2010
2011 static int rwrap_res_nsearch(struct __res_state *state,
2012                              const char *dname,
2013                              int class,
2014                              int type,
2015                              unsigned char *answer,
2016                              int anslen)
2017 {
2018         int rc;
2019         const char *fake_hosts;
2020
2021         RWRAP_LOG(RWRAP_LOG_TRACE,
2022                   "Resolve the domain name [%s] - class=%d, type=%d",
2023                   dname, class, type);
2024         rwrap_log_nameservers(RWRAP_LOG_TRACE, __func__, state);
2025
2026         fake_hosts = getenv("RESOLV_WRAPPER_HOSTS");
2027         if (fake_hosts != NULL) {
2028                 rc = rwrap_res_fake_hosts(fake_hosts, dname, type, answer, anslen);
2029         } else {
2030                 rc = libc_res_nsearch(state, dname, class, type, answer, anslen);
2031         }
2032
2033         RWRAP_LOG(RWRAP_LOG_TRACE,
2034                   "The returned response length is: %d",
2035                   rc);
2036
2037         return rc;
2038 }
2039
2040 #if !defined(res_nsearch) && defined(HAVE_RES_NSEARCH)
2041 int res_nsearch(struct __res_state *state,
2042                 const char *dname,
2043                 int class,
2044                 int type,
2045                 unsigned char *answer,
2046                 int anslen)
2047 #elif defined(HAVE___RES_NSEARCH)
2048 int __res_nsearch(struct __res_state *state,
2049                   const char *dname,
2050                   int class,
2051                   int type,
2052                   unsigned char *answer,
2053                   int anslen)
2054 #endif
2055 {
2056         return rwrap_res_nsearch(state, dname, class, type, answer, anslen);
2057 }
2058
2059 /****************************************************************************
2060  *   RES_SEARCH
2061  ***************************************************************************/
2062
2063 static int rwrap_res_search(const char *dname,
2064                             int class,
2065                             int type,
2066                             unsigned char *answer,
2067                             int anslen)
2068 {
2069         int rc;
2070
2071         rc = rwrap_res_ninit(&rwrap_res_state);
2072         if (rc != 0) {
2073                 return rc;
2074         }
2075
2076         rc = rwrap_res_nsearch(&rwrap_res_state,
2077                                dname,
2078                                class,
2079                                type,
2080                                answer,
2081                                anslen);
2082
2083         return rc;
2084 }
2085
2086 #if !defined(res_search) && defined(HAVE_RES_SEARCH)
2087 int res_search(const char *dname,
2088                int class,
2089                int type,
2090                unsigned char *answer,
2091                int anslen)
2092 #elif defined(HAVE___RES_SEARCH)
2093 int __res_search(const char *dname,
2094                  int class,
2095                  int type,
2096                  unsigned char *answer,
2097                  int anslen)
2098 #endif
2099 {
2100         return rwrap_res_search(dname, class, type, answer, anslen);
2101 }