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