summaryrefslogtreecommitdiff
path: root/src/lib/ecore_con/dns.c
diff options
context:
space:
mode:
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>2013-01-22 08:01:13 +0000
committerMike Blumenkrantz <michael.blumenkrantz@gmail.com>2013-01-22 08:01:13 +0000
commit10a10310e8de28d7cc0b4b707e11fb7a8f06fd71 (patch)
tree110ee91ab0cf8cd349b08f2c5ad9f32f06b15d4d /src/lib/ecore_con/dns.c
parentd606adf10ded687e9da75c97133aeb15d7cda2c3 (diff)
rebase dns.c against upstream
SVN revision: 83058
Diffstat (limited to 'src/lib/ecore_con/dns.c')
-rw-r--r--src/lib/ecore_con/dns.c1109
1 files changed, 959 insertions, 150 deletions
diff --git a/src/lib/ecore_con/dns.c b/src/lib/ecore_con/dns.c
index fad42e9..15d9bb0 100644
--- a/src/lib/ecore_con/dns.c
+++ b/src/lib/ecore_con/dns.c
@@ -23,11 +23,7 @@
23 * USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * ========================================================================== 24 * ==========================================================================
25 */ 25 */
26#ifdef HAVE_CONFIG_H 26#if !defined(__FreeBSD__) && !defined(__sun)
27# include "config.h"
28#endif
29
30#if !defined(__FreeBSD__)
31#ifndef _XOPEN_SOURCE 27#ifndef _XOPEN_SOURCE
32#define _XOPEN_SOURCE 600 28#define _XOPEN_SOURCE 600
33#endif 29#endif
@@ -43,7 +39,11 @@
43#endif 39#endif
44 40
45#include <stddef.h> /* offsetof() */ 41#include <stddef.h> /* offsetof() */
42#ifdef _WIN32
43#define uint32_t unsigned int
44#else
46#include <stdint.h> /* uint32_t */ 45#include <stdint.h> /* uint32_t */
46#endif
47#include <stdlib.h> /* malloc(3) realloc(3) free(3) rand(3) random(3) arc4random(3) */ 47#include <stdlib.h> /* malloc(3) realloc(3) free(3) rand(3) random(3) arc4random(3) */
48#include <stdio.h> /* FILE fopen(3) fclose(3) getc(3) rewind(3) */ 48#include <stdio.h> /* FILE fopen(3) fclose(3) getc(3) rewind(3) */
49 49
@@ -52,9 +52,9 @@
52 52
53#include <ctype.h> /* isspace(3) isdigit(3) */ 53#include <ctype.h> /* isspace(3) isdigit(3) */
54 54
55#include <time.h> /* time_t time(2) */ 55#include <time.h> /* time_t time(2) difftime(3) */
56 56
57#include <signal.h> /* sig_atomic_t */ 57#include <signal.h> /* SIGPIPE sigemptyset(3) sigaddset(3) sigpending(2) sigprocmask(2) pthread_sigmask(3) sigtimedwait(2) */
58 58
59#include <errno.h> /* errno EINVAL ENOENT */ 59#include <errno.h> /* errno EINVAL ENOENT */
60 60
@@ -62,6 +62,9 @@
62#include <assert.h> /* assert(3) */ 62#include <assert.h> /* assert(3) */
63 63
64#if _WIN32 64#if _WIN32
65#ifndef FD_SETSIZE
66#define FD_SETSIZE 256
67#endif
65#include <winsock2.h> 68#include <winsock2.h>
66#include <ws2tcpip.h> 69#include <ws2tcpip.h>
67#else 70#else
@@ -75,7 +78,7 @@
75 78
76#include <fcntl.h> /* F_SETFD F_GETFL F_SETFL O_NONBLOCK fcntl(2) */ 79#include <fcntl.h> /* F_SETFD F_GETFL F_SETFL O_NONBLOCK fcntl(2) */
77 80
78#include <unistd.h> /* gethostname(3) close(2) */ 81#include <unistd.h> /* _POSIX_THREADS gethostname(3) close(2) */
79 82
80#include <poll.h> /* POLLIN POLLOUT */ 83#include <poll.h> /* POLLIN POLLOUT */
81 84
@@ -90,6 +93,26 @@
90 93
91 94
92/* 95/*
96 * C O M P I L E R A N N O T A T I O N S
97 *
98 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
99
100#if __GNUC__
101#define DNS_NOTUSED __attribute__((unused))
102#else
103#define DNS_NOTUSED
104#endif
105
106#if __clang__
107#pragma clang diagnostic push
108#pragma clang diagnostic ignored "-Wunused-parameter"
109#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4
110#pragma GCC diagnostic push
111#pragma GCC diagnostic ignored "-Wunused-parameter"
112#endif
113
114
115/*
93 * S T A N D A R D M A C R O S 116 * S T A N D A R D M A C R O S
94 * 117 *
95 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 118 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -114,6 +137,26 @@
114 137
115 138
116/* 139/*
140 * M I S C E L L A N E O U S C O M P A T
141 *
142 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
143
144#if _WIN32 || _WIN64
145#define PRIuZ "Iu"
146#else
147#define PRIuZ "zu"
148#endif
149
150#ifndef DNS_THREAD_SAFE
151#if (defined _REENTRANT || defined _THREAD_SAFE) && _POSIX_THREADS > 0
152#define DNS_THREAD_SAFE 1
153#else
154#define DNS_THREAD_SAFE 0
155#endif
156#endif
157
158
159/*
117 * D E B U G M A C R O S 160 * D E B U G M A C R O S
118 * 161 *
119 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 162 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -224,6 +267,8 @@ const char *dns_strerror(int error) {
224 return "Invalid section specified"; 267 return "Invalid section specified";
225 case DNS_EUNKNOWN: 268 case DNS_EUNKNOWN:
226 return "Unknown DNS error"; 269 return "Unknown DNS error";
270 case DNS_EADDRESS:
271 return "Invalid textual address form";
227 default: 272 default:
228 return strerror(error); 273 return strerror(error);
229 } /* switch() */ 274 } /* switch() */
@@ -235,6 +280,11 @@ const char *dns_strerror(int error) {
235 * 280 *
236 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 281 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
237 282
283DNS_NOTUSED static void dns_atomic_fence(void) {
284 return;
285} /* dns_atomic_fence() */
286
287
238static unsigned dns_atomic_inc(dns_atomic_t *i) { 288static unsigned dns_atomic_inc(dns_atomic_t *i) {
239 return (*i)++; 289 return (*i)++;
240} /* dns_atomic_inc() */ 290} /* dns_atomic_inc() */
@@ -245,6 +295,20 @@ static unsigned dns_atomic_dec(dns_atomic_t *i) {
245} /* dns_atomic_dec() */ 295} /* dns_atomic_dec() */
246 296
247 297
298static unsigned dns_atomic_load(dns_atomic_t *i) {
299 return *i;
300} /* dns_atomic_load() */
301
302
303DNS_NOTUSED static unsigned dns_atomic_store(dns_atomic_t *i, unsigned n) {
304 unsigned o;
305
306 o = dns_atomic_load(i);
307 *i = n;
308 return o;
309} /* dns_atomic_store() */
310
311
248/* 312/*
249 * C R Y P T O R O U T I N E S 313 * C R Y P T O R O U T I N E S
250 * 314 *
@@ -429,6 +493,26 @@ static unsigned dns_k_permutor_E(struct dns_k_permutor *p, unsigned n) {
429 return ((l[i % 2] & p->mask) << p->shift) | ((r[i % 2] & p->mask) << 0); 493 return ((l[i % 2] & p->mask) << p->shift) | ((r[i % 2] & p->mask) << 0);
430} /* dns_k_permutor_E() */ 494} /* dns_k_permutor_E() */
431 495
496
497DNS_NOTUSED static unsigned dns_k_permutor_D(struct dns_k_permutor *p, unsigned n) {
498 unsigned l[2], r[2];
499 unsigned i;
500
501 i = p->rounds - 1;
502 l[i % 2] = p->mask & (n >> p->shift);
503 r[i % 2] = p->mask & (n >> 0);
504
505 do {
506 i--;
507
508 r[i % 2] = l[(i + 1) % 2];
509 l[i % 2] = r[(i + 1) % 2] ^ dns_k_permutor_F(p, i, l[(i + 1) % 2]);
510 } while (i > 0);
511
512 return ((l[i % 2] & p->mask) << p->shift) | ((r[i % 2] & p->mask) << 0);
513} /* dns_k_permutor_D() */
514
515
432static unsigned dns_k_permutor_step(struct dns_k_permutor *p) { 516static unsigned dns_k_permutor_step(struct dns_k_permutor *p) {
433 unsigned n; 517 unsigned n;
434 518
@@ -508,36 +592,30 @@ static unsigned short dns_k_shuffle16(unsigned short n, unsigned s) {
508 * 592 *
509 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 593 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
510 594
511/* 595#define DNS_MAXINTERVAL 300
512 * Monotonic Time
513 *
514 */
515static time_t dns_now(void) {
516 /* XXX: Assumes sizeof (time_t) <= sizeof (sig_atomic_t) */
517 static volatile sig_atomic_t last, tick;
518 volatile sig_atomic_t tmp_last, tmp_tick;
519 time_t now;
520 596
521 time(&now); 597struct dns_clock {
598 time_t sample, elapsed;
599}; /* struct dns_clock */
522 600
523 tmp_last = last; 601static void dns_begin(struct dns_clock *clk) {
602 clk->sample = time(0);
603 clk->elapsed = 0;
604} /* dns_begin() */
524 605
525 if (now > tmp_last) { 606static time_t dns_elapsed(struct dns_clock *clk) {
526 tmp_tick = tick; 607 time_t curtime;
527 tmp_tick += now - tmp_last;
528 tick = tmp_tick;
529 }
530 608
531 last = now; 609 if ((time_t)-1 == time(&curtime))
610 return clk->elapsed;
532 611
533 return tick; 612 if (curtime > clk->sample)
534} /* dns_now() */ 613 clk->elapsed += (time_t)MIN(difftime(curtime, clk->sample), DNS_MAXINTERVAL);
535 614
536static time_t dns_elapsed(time_t from) { 615 clk->sample = curtime;
537 time_t now = dns_now();
538 616
539 return (now > from)? now - from : 0; 617 return clk->elapsed;
540} /* dns_elpased() */ 618} /* dns_elapsed() */
541 619
542 620
543static size_t dns_af_len(int af) { 621static size_t dns_af_len(int af) {
@@ -552,6 +630,8 @@ static size_t dns_af_len(int af) {
552 return table[af]; 630 return table[af];
553} /* dns_af_len() */ 631} /* dns_af_len() */
554 632
633#define dns_sa_family(sa) (((struct sockaddr *)(sa))->sa_family)
634
555#define dns_sa_len(sa) dns_af_len(dns_sa_family(sa)) 635#define dns_sa_len(sa) dns_af_len(dns_sa_family(sa))
556 636
557 637
@@ -605,7 +685,7 @@ static int dns_inet_pton(int af, const void *src, void *dst) {
605 } 685 }
606} /* dns_inet_pton() */ 686} /* dns_inet_pton() */
607 687
608const char *dns_inet_ntop(int af, const void *src, void *dst, unsigned long lim) { 688static const char *dns_inet_ntop(int af, const void *src, void *dst, unsigned long lim) {
609 union { struct sockaddr_in sin; struct sockaddr_in6 sin6; } u; 689 union { struct sockaddr_in sin; struct sockaddr_in6 sin6; } u;
610 690
611 /* NOTE: WSAAddressToString will print .sin_port unless zeroed. */ 691 /* NOTE: WSAAddressToString will print .sin_port unless zeroed. */
@@ -630,9 +710,29 @@ const char *dns_inet_ntop(int af, const void *src, void *dst, unsigned long lim)
630 710
631 return dst; 711 return dst;
632} /* dns_inet_ntop() */ 712} /* dns_inet_ntop() */
713#else
714#define dns_inet_pton(...) inet_pton(__VA_ARGS__)
715#define dns_inet_ntop(...) inet_ntop(__VA_ARGS__)
633#endif 716#endif
634 717
635 718
719static dns_error_t dns_pton(int af, const void *src, void *dst) {
720 switch (dns_inet_pton(af, src, dst)) {
721 case 1:
722 return 0;
723 case -1:
724 return dns_soerr();
725 default:
726 return DNS_EADDRESS;
727 }
728} /* dns_pton() */
729
730
731static dns_error_t dns_ntop(int af, const void *src, void *dst, unsigned long lim) {
732 return (dns_inet_ntop(af, src, dst, lim))? 0 : dns_soerr();
733} /* dns_ntop() */
734
735
636size_t dns_strlcpy(char *dst, const char *src, size_t lim) { 736size_t dns_strlcpy(char *dst, const char *src, size_t lim) {
637 char *d = dst; 737 char *d = dst;
638 char *e = &dst[lim]; 738 char *e = &dst[lim];
@@ -678,7 +778,7 @@ size_t dns_strlcat(char *dst, const char *src, size_t lim) {
678} /* dns_strlcat() */ 778} /* dns_strlcat() */
679 779
680 780
681#if defined(_WIN32) || defined(__SUNPRO_C) 781#if _WIN32
682 782
683static char *dns_strsep(char **sp, const char *delim) { 783static char *dns_strsep(char **sp, const char *delim) {
684 char *p; 784 char *p;
@@ -714,7 +814,7 @@ static int dns_poll(int fd, short events, int timeout) {
714 if (!events) 814 if (!events)
715 return 0; 815 return 0;
716 816
717 assert(fd >= 0 && fd < FD_SETSIZE); 817 assert(fd >= 0 && (unsigned)fd < FD_SETSIZE);
718 818
719 FD_ZERO(&rset); 819 FD_ZERO(&rset);
720 FD_ZERO(&wset); 820 FD_ZERO(&wset);
@@ -731,6 +831,71 @@ static int dns_poll(int fd, short events, int timeout) {
731} /* dns_poll() */ 831} /* dns_poll() */
732 832
733 833
834#if !_WIN32
835DNS_NOTUSED static int dns_sigmask(int how, const sigset_t *set, sigset_t *oset) {
836#if DNS_THREAD_SAFE
837 return pthread_sigmask(how, set, oset);
838#else
839 return (0 == sigprocmask(how, set, oset))? 0 : errno;
840#endif
841} /* dns_sigmask() */
842#endif
843
844
845static long dns_send(int fd, const void *src, size_t lim, int flags) {
846#if _WIN32 || !defined SIGPIPE || defined SO_NOSIGPIPE
847 return send(fd, src, lim, flags);
848#elif defined MSG_NOSIGNAL
849 return send(fd, src, lim, flags|MSG_NOSIGNAL);
850#elif _POSIX_REALTIME_SIGNALS > 0 /* require sigtimedwait */
851 /*
852 * SIGPIPE handling similar to the approach described in
853 * http://krokisplace.blogspot.com/2010/02/suppressing-sigpipe-in-library.html
854 */
855 sigset_t pending, blocked, piped;
856 long count;
857 int saved, error;
858
859 sigemptyset(&pending);
860 sigpending(&pending);
861
862 if (!sigismember(&pending, SIGPIPE)) {
863 sigemptyset(&piped);
864 sigaddset(&piped, SIGPIPE);
865 sigemptyset(&blocked);
866
867 if ((error = dns_sigmask(SIG_BLOCK, &piped, &blocked)))
868 goto error;
869 }
870
871 count = send(fd, src, lim, flags);
872
873 if (!sigismember(&pending, SIGPIPE)) {
874 saved = errno;
875
876 if (count == -1 && errno == EPIPE) {
877 while (-1 == sigtimedwait(&piped, NULL, &(struct timespec){ 0, 0 }) && errno == EINTR)
878 ;;
879 }
880
881 if ((error = dns_sigmask(SIG_SETMASK, &blocked, NULL)))
882 goto error;
883
884 errno = saved;
885 }
886
887 return count;
888error:
889 errno = error;
890
891 return -1;
892#else
893#error "unable to suppress SIGPIPE"
894 return send(fd, src, lim, flags);
895#endif
896} /* dns_send() */
897
898
734/* 899/*
735 * P A C K E T R O U T I N E S 900 * P A C K E T R O U T I N E S
736 * 901 *
@@ -949,7 +1114,6 @@ void dns_p_dictadd(struct dns_packet *P, unsigned short dn) {
949int dns_p_push(struct dns_packet *P, enum dns_section section, const void *dn, size_t dnlen, enum dns_type type, enum dns_class class, unsigned ttl, const void *any) { 1114int dns_p_push(struct dns_packet *P, enum dns_section section, const void *dn, size_t dnlen, enum dns_type type, enum dns_class class, unsigned ttl, const void *any) {
950 size_t end = P->end; 1115 size_t end = P->end;
951 int error; 1116 int error;
952 unsigned short count;
953 1117
954 if ((error = dns_d_push(P, dn, dnlen))) 1118 if ((error = dns_d_push(P, dn, dnlen)))
955 goto error; 1119 goto error;
@@ -986,8 +1150,7 @@ update:
986 if (!P->qd.base && (error = dns_p_study(P))) 1150 if (!P->qd.base && (error = dns_p_study(P)))
987 goto error; 1151 goto error;
988 1152
989 count = ntohs(dns_header(P)->qdcount) + 1; 1153 dns_header(P)->qdcount = htons(ntohs(dns_header(P)->qdcount) + 1);
990 dns_header(P)->qdcount = htons(count);
991 1154
992 P->qd.end = P->end; 1155 P->qd.end = P->end;
993 P->an.base = P->end; 1156 P->an.base = P->end;
@@ -1005,8 +1168,7 @@ update:
1005 if (!P->an.base && (error = dns_p_study(P))) 1168 if (!P->an.base && (error = dns_p_study(P)))
1006 goto error; 1169 goto error;
1007 1170
1008 count = ntohs(dns_header(P)->ancount) + 1; 1171 dns_header(P)->ancount = htons(ntohs(dns_header(P)->ancount) + 1);
1009 dns_header(P)->ancount = htons(count);
1010 1172
1011 P->an.end = P->end; 1173 P->an.end = P->end;
1012 P->ns.base = P->end; 1174 P->ns.base = P->end;
@@ -1022,8 +1184,7 @@ update:
1022 if (!P->ns.base && (error = dns_p_study(P))) 1184 if (!P->ns.base && (error = dns_p_study(P)))
1023 goto error; 1185 goto error;
1024 1186
1025 count = ntohs(dns_header(P)->nscount) + 1; 1187 dns_header(P)->nscount = htons(ntohs(dns_header(P)->nscount) + 1);
1026 dns_header(P)->nscount = htons(count);
1027 1188
1028 P->ns.end = P->end; 1189 P->ns.end = P->end;
1029 P->ar.base = P->end; 1190 P->ar.base = P->end;
@@ -1034,8 +1195,7 @@ update:
1034 if (!P->ar.base && (error = dns_p_study(P))) 1195 if (!P->ar.base && (error = dns_p_study(P)))
1035 goto error; 1196 goto error;
1036 1197
1037 count = ntohs(dns_header(P)->arcount) + 1; 1198 dns_header(P)->arcount = htons(ntohs(dns_header(P)->arcount) + 1);
1038 dns_header(P)->arcount = htons(count);
1039 1199
1040 P->ar.end = P->end; 1200 P->ar.end = P->end;
1041 1201
@@ -1327,7 +1487,7 @@ size_t dns_d_cleave(void *dst, size_t lim, const void *src, size_t len) {
1327} /* dns_d_cleave() */ 1487} /* dns_d_cleave() */
1328 1488
1329 1489
1330size_t dns_d_comp(void *dst_, size_t lim, const void *src_, size_t len, struct dns_packet *P, int *error EINA_UNUSED) { 1490size_t dns_d_comp(void *dst_, size_t lim, const void *src_, size_t len, struct dns_packet *P, int *error) {
1331 struct { unsigned char *b; size_t p, x; } dst, src; 1491 struct { unsigned char *b; size_t p, x; } dst, src;
1332 unsigned char ch = '.'; 1492 unsigned char ch = '.';
1333 1493
@@ -1702,7 +1862,7 @@ unsigned short dns_rr_skip(unsigned short src, struct dns_packet *P) {
1702 1862
1703static enum dns_section dns_rr_section(unsigned short src, struct dns_packet *P) { 1863static enum dns_section dns_rr_section(unsigned short src, struct dns_packet *P) {
1704 enum dns_section section; 1864 enum dns_section section;
1705 unsigned count, ind; 1865 unsigned count, index;
1706 unsigned short rp; 1866 unsigned short rp;
1707 1867
1708 if (src >= P->qd.base && src < P->qd.end) 1868 if (src >= P->qd.base && src < P->qd.end)
@@ -1716,13 +1876,13 @@ static enum dns_section dns_rr_section(unsigned short src, struct dns_packet *P)
1716 1876
1717 /* NOTE: Possibly bad memoization. Try it the hard-way. */ 1877 /* NOTE: Possibly bad memoization. Try it the hard-way. */
1718 1878
1719 for (rp = 12, ind = 0; rp < src && rp < P->end; ind++) 1879 for (rp = 12, index = 0; rp < src && rp < P->end; index++)
1720 rp = dns_rr_skip(rp, P); 1880 rp = dns_rr_skip(rp, P);
1721 1881
1722 section = DNS_S_QD; 1882 section = DNS_S_QD;
1723 count = dns_p_count(P, section); 1883 count = dns_p_count(P, section);
1724 1884
1725 while (ind >= count && section <= DNS_S_AR) { 1885 while (index >= count && section <= DNS_S_AR) {
1726 section <<= 1; 1886 section <<= 1;
1727 count += dns_p_count(P, section); 1887 count += dns_p_count(P, section);
1728 } 1888 }
@@ -1857,7 +2017,7 @@ static unsigned short dns_rr_i_start(struct dns_rr_i *i, struct dns_packet *P) {
1857 else 2017 else
1858 rp = 12; 2018 rp = 12;
1859 2019
1860 for (rp = 12; rp < P->end; rp = dns_rr_skip(rp, P)) { 2020 for (; rp < P->end; rp = dns_rr_skip(rp, P)) {
1861 if ((error = dns_rr_parse(&rr, rp, P))) 2021 if ((error = dns_rr_parse(&rr, rp, P)))
1862 continue; 2022 continue;
1863 2023
@@ -1948,12 +2108,12 @@ lower:
1948} /* dns_rr_i_skip() */ 2108} /* dns_rr_i_skip() */
1949 2109
1950 2110
1951int dns_rr_i_packet(struct dns_rr *a, struct dns_rr *b, struct dns_rr_i *i EINA_UNUSED, struct dns_packet *P EINA_UNUSED) { 2111int dns_rr_i_packet(struct dns_rr *a, struct dns_rr *b, struct dns_rr_i *i, struct dns_packet *P) {
1952 return (int)a->dn.p - (int)b->dn.p; 2112 return (int)a->dn.p - (int)b->dn.p;
1953} /* dns_rr_i_packet() */ 2113} /* dns_rr_i_packet() */
1954 2114
1955 2115
1956int dns_rr_i_order(struct dns_rr *a, struct dns_rr *b, struct dns_rr_i *i EINA_UNUSED, struct dns_packet *P) { 2116int dns_rr_i_order(struct dns_rr *a, struct dns_rr *b, struct dns_rr_i *i, struct dns_packet *P) {
1957 int cmp; 2117 int cmp;
1958 2118
1959 if ((cmp = a->section - b->section)) 2119 if ((cmp = a->section - b->section))
@@ -1966,7 +2126,7 @@ int dns_rr_i_order(struct dns_rr *a, struct dns_rr *b, struct dns_rr_i *i EINA_U
1966} /* dns_rr_i_order() */ 2126} /* dns_rr_i_order() */
1967 2127
1968 2128
1969int dns_rr_i_shuffle(struct dns_rr *a, struct dns_rr *b, struct dns_rr_i *i, struct dns_packet *P EINA_UNUSED) { 2129int dns_rr_i_shuffle(struct dns_rr *a, struct dns_rr *b, struct dns_rr_i *i, struct dns_packet *P) {
1970 int cmp; 2130 int cmp;
1971 2131
1972 while (!i->state.regs[0]) 2132 while (!i->state.regs[0])
@@ -1979,7 +2139,7 @@ int dns_rr_i_shuffle(struct dns_rr *a, struct dns_rr *b, struct dns_rr_i *i, str
1979} /* dns_rr_i_shuffle() */ 2139} /* dns_rr_i_shuffle() */
1980 2140
1981 2141
1982struct dns_rr_i *dns_rr_i_init(struct dns_rr_i *i, struct dns_packet *P EINA_UNUSED) { 2142struct dns_rr_i *dns_rr_i_init(struct dns_rr_i *i, struct dns_packet *P) {
1983 static const struct dns_rr_i i_initializer; 2143 static const struct dns_rr_i i_initializer;
1984 2144
1985 i->state = i_initializer.state; 2145 i->state = i_initializer.state;
@@ -2731,6 +2891,70 @@ size_t dns_srv_cname(void *dst, size_t lim, struct dns_srv *srv) {
2731} /* dns_srv_cname() */ 2891} /* dns_srv_cname() */
2732 2892
2733 2893
2894unsigned int dns_opt_ttl(const struct dns_opt *opt) {
2895 unsigned int ttl = 0;
2896
2897 ttl |= (0xffU & opt->rcode) << 24U;
2898 ttl |= (0xffU & opt->version) << 16U;
2899
2900 return ttl;
2901} /* dns_opt_ttl() */
2902
2903
2904unsigned short dns_opt_class(const struct dns_opt *opt) {
2905 return opt->maxsize;
2906} /* dns_opt_class() */
2907
2908
2909struct dns_opt *dns_opt_init(struct dns_opt *opt, size_t size) {
2910 assert(size >= offsetof(struct dns_opt, data));
2911
2912 opt->size = size - offsetof(struct dns_opt, data);
2913 opt->len = 0;
2914
2915 opt->rcode = 0;
2916 opt->version = 0;
2917 opt->maxsize = 512;
2918
2919 return opt;
2920} /* dns_opt_init() */
2921
2922
2923int dns_opt_parse(struct dns_opt *opt, struct dns_rr *rr, struct dns_packet *P) {
2924 opt->len = 0;
2925
2926 return 0;
2927} /* dns_opt_parse() */
2928
2929
2930int dns_opt_push(struct dns_packet *P, struct dns_opt *opt) {
2931 return 0;
2932} /* dns_opt_push() */
2933
2934
2935int dns_opt_cmp(const struct dns_opt *a, const struct dns_opt *b) {
2936 return 0;
2937} /* dns_opt_cmp() */
2938
2939
2940size_t dns_opt_print(void *dst, size_t lim, struct dns_opt *opt) {
2941 size_t p = 0, src;
2942
2943 p += dns__printchar(dst, lim, p, '"');
2944
2945 for (src = 0; src < opt->len; src++) {
2946 p += dns__printchar(dst, lim, p, '\\');
2947 p += dns__print10(dst, lim, p, opt->data[src], 3);
2948 }
2949
2950 p += dns__printchar(dst, lim, p, '"');
2951
2952 dns__printnul(dst, lim, p);
2953
2954 return p;
2955} /* dns_opt_print() */
2956
2957
2734int dns_ptr_parse(struct dns_ptr *ptr, struct dns_rr *rr, struct dns_packet *P) { 2958int dns_ptr_parse(struct dns_ptr *ptr, struct dns_rr *rr, struct dns_packet *P) {
2735 return dns_ns_parse((struct dns_ns *)ptr, rr, P); 2959 return dns_ns_parse((struct dns_ns *)ptr, rr, P);
2736} /* dns_ptr_parse() */ 2960} /* dns_ptr_parse() */
@@ -2827,7 +3051,7 @@ int dns_sshfp_push(struct dns_packet *P, struct dns_sshfp *fp) {
2827int dns_sshfp_cmp(const struct dns_sshfp *a, const struct dns_sshfp *b) { 3051int dns_sshfp_cmp(const struct dns_sshfp *a, const struct dns_sshfp *b) {
2828 int cmp; 3052 int cmp;
2829 3053
2830 if ((cmp = a->algo - b->algo) || (cmp - a->type - b->type)) 3054 if ((cmp = a->algo - b->algo) || (cmp = a->type - b->type))
2831 return cmp; 3055 return cmp;
2832 3056
2833 switch (a->type) { 3057 switch (a->type) {
@@ -2953,7 +3177,7 @@ int dns_txt_push(struct dns_packet *P, struct dns_txt *txt) {
2953} /* dns_txt_push() */ 3177} /* dns_txt_push() */
2954 3178
2955 3179
2956int dns_txt_cmp(const struct dns_txt *a EINA_UNUSED, const struct dns_txt *b EINA_UNUSED) { 3180int dns_txt_cmp(const struct dns_txt *a, const struct dns_txt *b) {
2957 return -1; 3181 return -1;
2958} /* dns_txt_cmp() */ 3182} /* dns_txt_cmp() */
2959 3183
@@ -3013,6 +3237,7 @@ static const struct {
3013 { DNS_T_CNAME, "CNAME", &dns_cname_parse, &dns_cname_push, &dns_cname_cmp, &dns_cname_print, &dns_cname_cname }, 3237 { DNS_T_CNAME, "CNAME", &dns_cname_parse, &dns_cname_push, &dns_cname_cmp, &dns_cname_print, &dns_cname_cname },
3014 { DNS_T_SOA, "SOA", &dns_soa_parse, &dns_soa_push, &dns_soa_cmp, &dns_soa_print, 0 }, 3238 { DNS_T_SOA, "SOA", &dns_soa_parse, &dns_soa_push, &dns_soa_cmp, &dns_soa_print, 0 },
3015 { DNS_T_SRV, "SRV", &dns_srv_parse, &dns_srv_push, &dns_srv_cmp, &dns_srv_print, &dns_srv_cname }, 3239 { DNS_T_SRV, "SRV", &dns_srv_parse, &dns_srv_push, &dns_srv_cmp, &dns_srv_print, &dns_srv_cname },
3240 { DNS_T_OPT, "OPT", &dns_opt_parse, &dns_opt_push, &dns_opt_cmp, &dns_opt_print, 0 },
3016 { DNS_T_PTR, "PTR", &dns_ptr_parse, &dns_ptr_push, &dns_ptr_cmp, &dns_ptr_print, &dns_ptr_cname }, 3241 { DNS_T_PTR, "PTR", &dns_ptr_parse, &dns_ptr_push, &dns_ptr_cmp, &dns_ptr_print, &dns_ptr_cname },
3017 { DNS_T_TXT, "TXT", &dns_txt_parse, &dns_txt_push, &dns_txt_cmp, &dns_txt_print, 0 }, 3242 { DNS_T_TXT, "TXT", &dns_txt_parse, &dns_txt_push, &dns_txt_cmp, &dns_txt_print, 0 },
3018 { DNS_T_SPF, "SPF", &dns_txt_parse, &dns_txt_push, &dns_txt_cmp, &dns_txt_print, 0 }, 3243 { DNS_T_SPF, "SPF", &dns_txt_parse, &dns_txt_push, &dns_txt_cmp, &dns_txt_print, 0 },
@@ -3529,6 +3754,11 @@ struct dns_resolv_conf *dns_resconf_local(int *error_) {
3529 if ((error = dns_resconf_loadpath(resconf, "/etc/resolv.conf"))) 3754 if ((error = dns_resconf_loadpath(resconf, "/etc/resolv.conf")))
3530 goto error; 3755 goto error;
3531 3756
3757 if ((error = dns_nssconf_loadpath(resconf, "/etc/nsswitch.conf"))) {
3758 if (error != ENOENT)
3759 goto error;
3760 }
3761
3532 return resconf; 3762 return resconf;
3533error: 3763error:
3534 *error_ = error; 3764 *error_ = error;
@@ -3539,25 +3769,13 @@ error:
3539} /* dns_resconf_local() */ 3769} /* dns_resconf_local() */
3540 3770
3541 3771
3542struct dns_resolv_conf *dns_resconf_root(int *error_) { 3772struct dns_resolv_conf *dns_resconf_root(int *error) {
3543 struct dns_resolv_conf *resconf; 3773 struct dns_resolv_conf *resconf;
3544 int error;
3545
3546 if (!(resconf = dns_resconf_open(&error)))
3547 goto error;
3548
3549 if ((error = dns_resconf_loadpath(resconf, "/etc/resolv.conf")))
3550 goto error;
3551 3774
3552 resconf->options.recurse = 1; 3775 if ((resconf = dns_resconf_local(error)))
3776 resconf->options.recurse = 1;
3553 3777
3554 return resconf; 3778 return resconf;
3555error:
3556 *error_ = error;
3557
3558 dns_resconf_close(resconf);
3559
3560 return 0;
3561} /* dns_resconf_root() */ 3779} /* dns_resconf_root() */
3562 3780
3563 3781
@@ -3636,7 +3854,7 @@ static enum dns_resconf_keyword dns_resconf_keyword(const char *word) {
3636static int dns_resconf_pton(struct sockaddr_storage *ss, const char *src) { 3854static int dns_resconf_pton(struct sockaddr_storage *ss, const char *src) {
3637 struct { char buf[128], *p; } addr = { "", addr.buf }; 3855 struct { char buf[128], *p; } addr = { "", addr.buf };
3638 unsigned short port = 0; 3856 unsigned short port = 0;
3639 int ch, af = AF_INET; 3857 int ch, af = AF_INET, error;
3640 3858
3641 while ((ch = *src++)) { 3859 while ((ch = *src++)) {
3642 switch (ch) { 3860 switch (ch) {
@@ -3668,12 +3886,8 @@ static int dns_resconf_pton(struct sockaddr_storage *ss, const char *src) {
3668 } /* while() */ 3886 } /* while() */
3669inet: 3887inet:
3670 3888
3671 switch (dns_inet_pton(af, addr.buf, dns_sa_addr(af, ss))) { 3889 if ((error = dns_pton(af, addr.buf, dns_sa_addr(af, ss))))
3672 case -1: 3890 return error;
3673 return errno;
3674 case 0:
3675 return EINVAL;
3676 } /* switch() */
3677 3891
3678 port = (!port)? 53 : port; 3892 port = (!port)? 53 : port;
3679 *dns_sa_port(af, ss) = htons(port); 3893 *dns_sa_port(af, ss) = htons(port);
@@ -3875,11 +4089,518 @@ int dns_resconf_loadpath(struct dns_resolv_conf *resconf, const char *path) {
3875} /* dns_resconf_loadpath() */ 4089} /* dns_resconf_loadpath() */
3876 4090
3877 4091
4092struct dns_anyconf {
4093 char *token[16];
4094 unsigned count;
4095 char buffer[1024], *tp, *cp;
4096}; /* struct dns_anyconf */
4097
4098
4099static void dns_anyconf_reset(struct dns_anyconf *cf) {
4100 cf->count = 0;
4101 cf->tp = cf->cp = cf->buffer;
4102} /* dns_anyconf_reset() */
4103
4104
4105static int dns_anyconf_push(struct dns_anyconf *cf) {
4106 if (!(cf->cp < endof(cf->buffer) && cf->count < lengthof(cf->token)))
4107 return ENOMEM;
4108
4109 *cf->cp++ = '\0';
4110 cf->token[cf->count++] = cf->tp;
4111 cf->tp = cf->cp;
4112
4113 return 0;
4114} /* dns_anyconf_push() */
4115
4116
4117static void dns_anyconf_pop(struct dns_anyconf *cf) {
4118 if (cf->count > 0) {
4119 --cf->count;
4120 cf->tp = cf->cp = cf->token[cf->count];
4121 cf->token[cf->count] = 0;
4122 }
4123} /* dns_anyconf_pop() */
4124
4125
4126static int dns_anyconf_addc(struct dns_anyconf *cf, int ch) {
4127 if (!(cf->cp < endof(cf->buffer)))
4128 return ENOMEM;
4129
4130 *cf->cp++ = ch;
4131
4132 return 0;
4133} /* dns_anyconf_addc() */
4134
4135
4136static _Bool dns_anyconf_match(const char *pat, int mc) {
4137 _Bool match;
4138 int pc;
4139
4140 if (*pat == '^') {
4141 match = 0;
4142 ++pat;
4143 } else {
4144 match = 1;
4145 }
4146
4147 while ((pc = *(const unsigned char *)pat++)) {
4148 switch (pc) {
4149 case '%':
4150 if (!(pc = *(const unsigned char *)pat++))
4151 return !match;
4152
4153 switch (pc) {
4154 case 'a':
4155 if (isalpha(mc))
4156 return match;
4157 break;
4158 case 'd':
4159 if (isdigit(mc))
4160 return match;
4161 break;
4162 case 'w':
4163 if (isalnum(mc))
4164 return match;
4165 break;
4166 case 's':
4167 if (isspace(mc))
4168 return match;
4169 break;
4170 default:
4171 if (mc == pc)
4172 return match;
4173 break;
4174 } /* switch() */
4175
4176 break;
4177 default:
4178 if (mc == pc)
4179 return match;
4180 break;
4181 } /* switch() */
4182 } /* while() */
4183
4184 return !match;
4185} /* dns_anyconf_match() */
4186
4187
4188static int dns_anyconf_peek(FILE *fp) {
4189 int ch;
4190 ch = getc(fp);
4191 ungetc(ch, fp);
4192 return ch;
4193} /* dns_anyconf_peek() */
4194
4195
4196static size_t dns_anyconf_skip(const char *pat, FILE *fp) {
4197 size_t count = 0;
4198 int ch;
4199
4200 while (EOF != (ch = getc(fp))) {
4201 if (dns_anyconf_match(pat, ch)) {
4202 count++;
4203 continue;
4204 }
4205
4206 ungetc(ch, fp);
4207
4208 break;
4209 }
4210
4211 return count;
4212} /* dns_anyconf_skip() */
4213
4214
4215static size_t dns_anyconf_scan(struct dns_anyconf *cf, const char *pat, FILE *fp, int *error) {
4216 size_t len;
4217 int ch;
4218
4219 while (EOF != (ch = getc(fp))) {
4220 if (dns_anyconf_match(pat, ch)) {
4221 if ((*error = dns_anyconf_addc(cf, ch)))
4222 return 0;
4223
4224 continue;
4225 } else {
4226 ungetc(ch, fp);
4227
4228 break;
4229 }
4230 }
4231
4232 if ((len = cf->cp - cf->tp)) {
4233 if ((*error = dns_anyconf_push(cf)))
4234 return 0;
4235
4236 return len;
4237 } else {
4238 *error = 0;
4239
4240 return 0;
4241 }
4242} /* dns_anyconf_scan() */
4243
4244
4245DNS_NOTUSED static void dns_anyconf_dump(struct dns_anyconf *cf, FILE *fp) {
4246 unsigned i;
4247
4248 fprintf(fp, "tokens:");
4249
4250 for (i = 0; i < cf->count; i++) {
4251 fprintf(fp, " %s", cf->token[i]);
4252 }
4253
4254 fputc('\n', fp);
4255} /* dns_anyconf_dump() */
4256
4257
4258enum dns_nssconf_keyword {
4259 DNS_NSSCONF_INVALID = 0,
4260 DNS_NSSCONF_HOSTS = 1,
4261 DNS_NSSCONF_SUCCESS,
4262 DNS_NSSCONF_NOTFOUND,
4263 DNS_NSSCONF_UNAVAIL,
4264 DNS_NSSCONF_TRYAGAIN,
4265 DNS_NSSCONF_CONTINUE,
4266 DNS_NSSCONF_RETURN,
4267 DNS_NSSCONF_FILES,
4268 DNS_NSSCONF_DNS,
4269 DNS_NSSCONF_MDNS,
4270
4271 DNS_NSSCONF_LAST,
4272}; /* enum dns_nssconf_keyword */
4273
4274static enum dns_nssconf_keyword dns_nssconf_keyword(const char *word) {
4275 static const char *list[] = {
4276 [DNS_NSSCONF_HOSTS] = "hosts",
4277 [DNS_NSSCONF_SUCCESS] = "success",
4278 [DNS_NSSCONF_NOTFOUND] = "notfound",
4279 [DNS_NSSCONF_UNAVAIL] = "unavail",
4280 [DNS_NSSCONF_TRYAGAIN] = "tryagain",
4281 [DNS_NSSCONF_CONTINUE] = "continue",
4282 [DNS_NSSCONF_RETURN] = "return",
4283 [DNS_NSSCONF_FILES] = "files",
4284 [DNS_NSSCONF_DNS] = "dns",
4285 [DNS_NSSCONF_MDNS] = "mdns",
4286 };
4287 unsigned i;
4288
4289 for (i = 1; i < lengthof(list); i++) {
4290 if (list[i] && 0 == strcasecmp(list[i], word))
4291 return i;
4292 }
4293
4294 return DNS_NSSCONF_INVALID;
4295} /* dns_nssconf_keyword() */
4296
4297
4298static enum dns_nssconf_keyword dns_nssconf_c2k(int ch) {
4299 static const char map[] = {
4300 ['S'] = DNS_NSSCONF_SUCCESS,
4301 ['N'] = DNS_NSSCONF_NOTFOUND,
4302 ['U'] = DNS_NSSCONF_UNAVAIL,
4303 ['T'] = DNS_NSSCONF_TRYAGAIN,
4304 ['C'] = DNS_NSSCONF_CONTINUE,
4305 ['R'] = DNS_NSSCONF_RETURN,
4306 ['f'] = DNS_NSSCONF_FILES,
4307 ['F'] = DNS_NSSCONF_FILES,
4308 ['d'] = DNS_NSSCONF_DNS,
4309 ['D'] = DNS_NSSCONF_DNS,
4310 ['b'] = DNS_NSSCONF_DNS,
4311 ['B'] = DNS_NSSCONF_DNS,
4312 ['m'] = DNS_NSSCONF_MDNS,
4313 ['M'] = DNS_NSSCONF_MDNS,
4314 };
4315
4316 return (ch >= 0 && ch < (int)lengthof(map))? map[ch] : DNS_NSSCONF_INVALID;
4317} /* dns_nssconf_c2k() */
4318
4319
4320DNS_PRAGMA_PUSH
4321DNS_PRAGMA_QUIET
4322
4323static int dns_nssconf_k2c(int k) {
4324 static const char map[DNS_NSSCONF_LAST] = {
4325 [DNS_NSSCONF_SUCCESS] = 'S',
4326 [DNS_NSSCONF_NOTFOUND] = 'N',
4327 [DNS_NSSCONF_UNAVAIL] = 'U',
4328 [DNS_NSSCONF_TRYAGAIN] = 'T',
4329 [DNS_NSSCONF_CONTINUE] = 'C',
4330 [DNS_NSSCONF_RETURN] = 'R',
4331 [DNS_NSSCONF_FILES] = 'f',
4332 [DNS_NSSCONF_DNS] = 'b',
4333 [DNS_NSSCONF_MDNS] = 'm',
4334 };
4335
4336 return (k >= 0 && k < (int)lengthof(map))? (map[k]? map[k] : '?') : '?';
4337} /* dns_nssconf_k2c() */
4338
4339static const char *dns_nssconf_k2s(int k) {
4340 static const char *const map[DNS_NSSCONF_LAST] = {
4341 [DNS_NSSCONF_SUCCESS] = "SUCCESS",
4342 [DNS_NSSCONF_NOTFOUND] = "NOTFOUND",
4343 [DNS_NSSCONF_UNAVAIL] = "UNAVAIL",
4344 [DNS_NSSCONF_TRYAGAIN] = "TRYAGAIN",
4345 [DNS_NSSCONF_CONTINUE] = "continue",
4346 [DNS_NSSCONF_RETURN] = "return",
4347 [DNS_NSSCONF_FILES] = "files",
4348 [DNS_NSSCONF_DNS] = "dns",
4349 [DNS_NSSCONF_MDNS] = "mdns",
4350 };
4351
4352 return (k >= 0 && k < (int)lengthof(map))? (map[k]? map[k] : "") : "";
4353} /* dns_nssconf_k2s() */
4354
4355DNS_PRAGMA_POP
4356
4357
4358int dns_nssconf_loadfile(struct dns_resolv_conf *resconf, FILE *fp) {
4359 enum dns_nssconf_keyword source, status, action;
4360 char lookup[sizeof resconf->lookup] = "", *lp;
4361 struct dns_anyconf cf;
4362 size_t i;
4363 int error;
4364
4365 while (!feof(fp) && !ferror(fp)) {
4366 dns_anyconf_reset(&cf);
4367
4368 dns_anyconf_skip("%s", fp);
4369
4370 if (!dns_anyconf_scan(&cf, "%w_", fp, &error))
4371 goto nextent;
4372
4373 if (DNS_NSSCONF_HOSTS != dns_nssconf_keyword(cf.token[0]))
4374 goto nextent;
4375
4376 dns_anyconf_pop(&cf);
4377
4378 if (!dns_anyconf_skip(": \t", fp))
4379 goto nextent;
4380
4381 *(lp = lookup) = '\0';
4382
4383 while (dns_anyconf_scan(&cf, "%w_", fp, &error)) {
4384 dns_anyconf_skip(" \t", fp);
4385
4386 if ('[' == dns_anyconf_peek(fp)) {
4387 dns_anyconf_skip("[ \t", fp);
4388
4389 while (dns_anyconf_scan(&cf, "%w_", fp, &error)) {
4390 dns_anyconf_skip("= \t", fp);
4391 if (!dns_anyconf_scan(&cf, "%w_", fp, &error)) {
4392 dns_anyconf_pop(&cf); /* discard status */
4393 dns_anyconf_skip("^#;]\n", fp); /* skip to end of criteria */
4394 break;
4395 }
4396 dns_anyconf_skip(" \t", fp);
4397 }
4398
4399 dns_anyconf_skip("] \t", fp);
4400 }
4401
4402 if (endof(lookup) - lp < cf.count + 1) /* +1 for '\0' */
4403 goto nextsrc;
4404
4405 source = dns_nssconf_keyword(cf.token[0]);
4406
4407 switch (source) {
4408 case DNS_NSSCONF_DNS:
4409 case DNS_NSSCONF_MDNS:
4410 case DNS_NSSCONF_FILES:
4411 *lp++ = dns_nssconf_k2c(source);
4412 break;
4413 default:
4414 goto nextsrc;
4415 }
4416
4417 for (i = 1; i + 1 < cf.count; i += 2) {
4418 status = dns_nssconf_keyword(cf.token[i]);
4419 action = dns_nssconf_keyword(cf.token[i + 1]);
4420
4421 switch (status) {
4422 case DNS_NSSCONF_SUCCESS:
4423 case DNS_NSSCONF_NOTFOUND:
4424 case DNS_NSSCONF_UNAVAIL:
4425 case DNS_NSSCONF_TRYAGAIN:
4426 *lp++ = dns_nssconf_k2c(status);
4427 break;
4428 default:
4429 continue;
4430 }
4431
4432 switch (action) {
4433 case DNS_NSSCONF_CONTINUE:
4434 case DNS_NSSCONF_RETURN:
4435 break;
4436 default:
4437 action = (status == DNS_NSSCONF_SUCCESS)
4438 ? DNS_NSSCONF_RETURN
4439 : DNS_NSSCONF_CONTINUE;
4440 break;
4441 }
4442
4443 *lp++ = dns_nssconf_k2c(action);
4444 }
4445nextsrc:
4446 *lp = '\0';
4447 dns_anyconf_reset(&cf);
4448 }
4449nextent:
4450 dns_anyconf_skip("^\n", fp);
4451 }
4452
4453 if (*lookup)
4454 strncpy(resconf->lookup, lookup, sizeof resconf->lookup);
4455
4456 return 0;
4457} /* dns_nssconf_loadfile() */
4458
4459
4460int dns_nssconf_loadpath(struct dns_resolv_conf *resconf, const char *path) {
4461 FILE *fp;
4462 int error;
4463
4464 if (!(fp = fopen(path, "r")))
4465 return dns_syerr();
4466
4467 error = dns_nssconf_loadfile(resconf, fp);
4468
4469 fclose(fp);
4470
4471 return error;
4472} /* dns_nssconf_loadpath() */
4473
4474
4475struct dns_nssconf_source {
4476 enum dns_nssconf_keyword source, success, notfound, unavail, tryagain;
4477}; /* struct dns_nssconf_source */
4478
4479typedef unsigned dns_nssconf_i;
4480
4481static inline int dns_nssconf_peek(const struct dns_resolv_conf *resconf, dns_nssconf_i state) {
4482 return (state < lengthof(resconf->lookup) && resconf->lookup[state])? resconf->lookup[state] : 0;
4483} /* dns_nssconf_peek() */
4484
4485static _Bool dns_nssconf_next(struct dns_nssconf_source *src, const struct dns_resolv_conf *resconf, dns_nssconf_i *state) {
4486 int source, status, action;
4487
4488 src->source = DNS_NSSCONF_INVALID;
4489 src->success = DNS_NSSCONF_RETURN;
4490 src->notfound = DNS_NSSCONF_CONTINUE;
4491 src->unavail = DNS_NSSCONF_CONTINUE;
4492 src->tryagain = DNS_NSSCONF_CONTINUE;
4493
4494 while ((source = dns_nssconf_peek(resconf, *state))) {
4495 source = dns_nssconf_c2k(source);
4496 ++*state;
4497
4498 switch (source) {
4499 case DNS_NSSCONF_FILES:
4500 case DNS_NSSCONF_DNS:
4501 case DNS_NSSCONF_MDNS:
4502 src->source = source;
4503 break;
4504 default:
4505 continue;
4506 }
4507
4508 while ((status = dns_nssconf_peek(resconf, *state)) && (action = dns_nssconf_peek(resconf, *state + 1))) {
4509 status = dns_nssconf_c2k(status);
4510 action = dns_nssconf_c2k(action);
4511
4512 switch (action) {
4513 case DNS_NSSCONF_RETURN:
4514 case DNS_NSSCONF_CONTINUE:
4515 break;
4516 default:
4517 goto done;
4518 }
4519
4520 switch (status) {
4521 case DNS_NSSCONF_SUCCESS:
4522 src->success = action;
4523 break;
4524 case DNS_NSSCONF_NOTFOUND:
4525 src->notfound = action;
4526 break;
4527 case DNS_NSSCONF_UNAVAIL:
4528 src->unavail = action;
4529 break;
4530 case DNS_NSSCONF_TRYAGAIN:
4531 src->tryagain = action;
4532 break;
4533 default:
4534 goto done;
4535 }
4536
4537 *state += 2;
4538 }
4539
4540 break;
4541 }
4542done:
4543 return src->source != DNS_NSSCONF_INVALID;
4544} /* dns_nssconf_next() */
4545
4546
4547static int dns_nssconf_dump_status(int status, int action, unsigned *count, FILE *fp) {
4548 switch (status) {
4549 case DNS_NSSCONF_SUCCESS:
4550 if (action == DNS_NSSCONF_RETURN)
4551 return 0;
4552 break;
4553 default:
4554 if (action == DNS_NSSCONF_CONTINUE)
4555 return 0;
4556 break;
4557 }
4558
4559 fputc(' ', fp);
4560
4561 if (!*count)
4562 fputc('[', fp);
4563
4564 fprintf(fp, "%s=%s", dns_nssconf_k2s(status), dns_nssconf_k2s(action));
4565
4566 ++*count;
4567
4568 return 0;
4569} /* dns_nssconf_dump_status() */
4570
4571
4572int dns_nssconf_dump(struct dns_resolv_conf *resconf, FILE *fp) {
4573 struct dns_nssconf_source src;
4574 dns_nssconf_i i = 0;
4575
4576 fputs("hosts:", fp);
4577
4578 while (dns_nssconf_next(&src, resconf, &i)) {
4579 unsigned n = 0;
4580
4581 fprintf(fp, " %s", dns_nssconf_k2s(src.source));
4582
4583 dns_nssconf_dump_status(DNS_NSSCONF_SUCCESS, src.success, &n, fp);
4584 dns_nssconf_dump_status(DNS_NSSCONF_NOTFOUND, src.notfound, &n, fp);
4585 dns_nssconf_dump_status(DNS_NSSCONF_UNAVAIL, src.unavail, &n, fp);
4586 dns_nssconf_dump_status(DNS_NSSCONF_TRYAGAIN, src.tryagain, &n, fp);
4587
4588 if (n)
4589 fputc(']', fp);
4590 }
4591
4592 fputc('\n', fp);
4593
4594 return 0;
4595} /* dns_nssconf_dump() */
4596
4597
3878int dns_resconf_setiface(struct dns_resolv_conf *resconf, const char *addr, unsigned short port) { 4598int dns_resconf_setiface(struct dns_resolv_conf *resconf, const char *addr, unsigned short port) {
3879 int af = (strchr(addr, ':'))? AF_INET6 : AF_INET; 4599 int af = (strchr(addr, ':'))? AF_INET6 : AF_INET;
4600 int error;
3880 4601
3881 if (1 != dns_inet_pton(af, addr, dns_sa_addr(af, &resconf->iface))) 4602 if ((error = dns_pton(af, addr, dns_sa_addr(af, &resconf->iface))))
3882 return dns_soerr(); 4603 return error;
3883 4604
3884 *dns_sa_port(af, &resconf->iface) = htons(port); 4605 *dns_sa_port(af, &resconf->iface) = htons(port);
3885 resconf->iface.ss_family = af; 4606 resconf->iface.ss_family = af;
@@ -3977,6 +4698,9 @@ int dns_resconf_dump(struct dns_resolv_conf *resconf, FILE *fp) {
3977 fputc('\n', fp); 4698 fputc('\n', fp);
3978 4699
3979 4700
4701 fputs("; ", fp);
4702 dns_nssconf_dump(resconf, fp);
4703
3980 fprintf(fp, "lookup"); 4704 fprintf(fp, "lookup");
3981 4705
3982 for (i = 0; i < lengthof(resconf->lookup) && resconf->lookup[i]; i++) { 4706 for (i = 0; i < lengthof(resconf->lookup) && resconf->lookup[i]; i++) {
@@ -4004,6 +4728,17 @@ int dns_resconf_dump(struct dns_resolv_conf *resconf, FILE *fp) {
4004 if (resconf->options.smart) 4728 if (resconf->options.smart)
4005 fprintf(fp, " smart"); 4729 fprintf(fp, " smart");
4006 4730
4731 switch (resconf->options.tcp) {
4732 case DNS_RESCONF_TCP_ENABLE:
4733 break;
4734 case DNS_RESCONF_TCP_ONLY:
4735 fprintf(fp, " tcp");
4736 break;
4737 case DNS_RESCONF_TCP_DISABLE:
4738 fprintf(fp, " tcp:disable");
4739 break;
4740 }
4741
4007 fputc('\n', fp); 4742 fputc('\n', fp);
4008 4743
4009 4744
@@ -4045,7 +4780,7 @@ struct dns_hints {
4045}; /* struct dns_hints */ 4780}; /* struct dns_hints */
4046 4781
4047 4782
4048struct dns_hints *dns_hints_open(struct dns_resolv_conf *resconf EINA_UNUSED, int *error) { 4783struct dns_hints *dns_hints_open(struct dns_resolv_conf *resconf, int *error) {
4049 static const struct dns_hints H_initializer; 4784 static const struct dns_hints H_initializer;
4050 struct dns_hints *H; 4785 struct dns_hints *H;
4051 4786
@@ -4163,8 +4898,8 @@ struct dns_hints *dns_hints_root(struct dns_resolv_conf *resconf, int *error_) {
4163 for (i = 0; i < lengthof(root_hints); i++) { 4898 for (i = 0; i < lengthof(root_hints); i++) {
4164 af = root_hints[i].af; 4899 af = root_hints[i].af;
4165 4900
4166 if (1 != dns_inet_pton(af, root_hints[i].addr, dns_sa_addr(af, &ss))) 4901 if ((error = dns_pton(af, root_hints[i].addr, dns_sa_addr(af, &ss))))
4167 goto soerr; 4902 goto error;
4168 4903
4169 *dns_sa_port(af, &ss) = htons(53); 4904 *dns_sa_port(af, &ss) = htons(53);
4170 ss.ss_family = af; 4905 ss.ss_family = af;
@@ -4174,10 +4909,6 @@ struct dns_hints *dns_hints_root(struct dns_resolv_conf *resconf, int *error_) {
4174 } 4909 }
4175 4910
4176 return hints; 4911 return hints;
4177soerr:
4178 error = dns_soerr();
4179
4180 goto error;
4181error: 4912error:
4182 *error_ = error; 4913 *error_ = error;
4183 4914
@@ -4421,15 +5152,16 @@ int dns_hints_dump(struct dns_hints *hints, FILE *fp) {
4421 struct dns_hints_soa *soa; 5152 struct dns_hints_soa *soa;
4422 char addr[INET6_ADDRSTRLEN]; 5153 char addr[INET6_ADDRSTRLEN];
4423 unsigned i; 5154 unsigned i;
4424 int af; 5155 int af, error;
4425 5156
4426 for (soa = hints->head; soa; soa = soa->next) { 5157 for (soa = hints->head; soa; soa = soa->next) {
4427 fprintf(fp, "ZONE \"%s\"\n", soa->zone); 5158 fprintf(fp, "ZONE \"%s\"\n", soa->zone);
4428 5159
4429 for (i = 0; i < soa->count; i++) { 5160 for (i = 0; i < soa->count; i++) {
4430 af = soa->addrs[i].ss.ss_family; 5161 af = soa->addrs[i].ss.ss_family;
4431 if (!dns_inet_ntop(af, dns_sa_addr(af, &soa->addrs[i].ss), addr, sizeof addr)) 5162
4432 return dns_soerr(); 5163 if ((error = dns_ntop(af, dns_sa_addr(af, &soa->addrs[i].ss), addr, sizeof addr)))
5164 return error;
4433 5165
4434 fprintf(fp, "\t(%d) [%s]:%hu\n", (int)soa->addrs[i].priority, addr, ntohs(*dns_sa_port(af, &soa->addrs[i].ss))); 5166 fprintf(fp, "\t(%d) [%s]:%hu\n", (int)soa->addrs[i].priority, addr, ntohs(*dns_sa_port(af, &soa->addrs[i].ss)));
4435 } 5167 }
@@ -4444,47 +5176,47 @@ int dns_hints_dump(struct dns_hints *hints, FILE *fp) {
4444 * 5176 *
4445 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 5177 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4446 5178
4447static dns_atomic_t dns_cache_acquire(struct dns_cache *cache EINA_UNUSED) { 5179static dns_atomic_t dns_cache_acquire(struct dns_cache *cache) {
4448 return 0; 5180 return 0;
4449} /* dns_cache_acquire() */ 5181} /* dns_cache_acquire() */
4450 5182
4451 5183
4452static dns_atomic_t dns_cache_release(struct dns_cache *cache EINA_UNUSED) { 5184static dns_atomic_t dns_cache_release(struct dns_cache *cache) {
4453 return 0; 5185 return 0;
4454} /* dns_cache_release() */ 5186} /* dns_cache_release() */
4455 5187
4456 5188
4457static struct dns_packet *dns_cache_query(struct dns_packet *query EINA_UNUSED, struct dns_cache *cache EINA_UNUSED, int *error EINA_UNUSED) { 5189static struct dns_packet *dns_cache_query(struct dns_packet *query, struct dns_cache *cache, int *error) {
4458 return 0; 5190 return 0;
4459} /* dns_cache_submit() */ 5191} /* dns_cache_submit() */
4460 5192
4461 5193
4462static int dns_cache_submit(struct dns_packet *query EINA_UNUSED, struct dns_cache *cache EINA_UNUSED) { 5194static int dns_cache_submit(struct dns_packet *query, struct dns_cache *cache) {
4463 return 0; 5195 return 0;
4464} /* dns_cache_submit() */ 5196} /* dns_cache_submit() */
4465 5197
4466 5198
4467static int dns_cache_check(struct dns_cache *cache EINA_UNUSED) { 5199static int dns_cache_check(struct dns_cache *cache) {
4468 return 0; 5200 return 0;
4469} /* dns_cache_check() */ 5201} /* dns_cache_check() */
4470 5202
4471 5203
4472static struct dns_packet *dns_cache_fetch(struct dns_cache *cache EINA_UNUSED, int *error EINA_UNUSED) { 5204static struct dns_packet *dns_cache_fetch(struct dns_cache *cache, int *error) {
4473 return 0; 5205 return 0;
4474} /* dns_cache_fetch() */ 5206} /* dns_cache_fetch() */
4475 5207
4476 5208
4477static int dns_cache_pollfd(struct dns_cache *cache EINA_UNUSED) { 5209static int dns_cache_pollfd(struct dns_cache *cache) {
4478 return -1; 5210 return -1;
4479} /* dns_cache_pollfd() */ 5211} /* dns_cache_pollfd() */
4480 5212
4481 5213
4482static short dns_cache_events(struct dns_cache *cache EINA_UNUSED) { 5214static short dns_cache_events(struct dns_cache *cache) {
4483 return 0; 5215 return 0;
4484} /* dns_cache_events() */ 5216} /* dns_cache_events() */
4485 5217
4486 5218
4487static void dns_cache_clear(struct dns_cache *cache EINA_UNUSED) { 5219static void dns_cache_clear(struct dns_cache *cache) {
4488 return; 5220 return;
4489} /* dns_cache_clear() */ 5221} /* dns_cache_clear() */
4490 5222
@@ -4562,6 +5294,13 @@ static int dns_socket(struct sockaddr *local, int type, int *error_) {
4562 goto soerr; 5294 goto soerr;
4563#endif 5295#endif
4564 5296
5297#if defined(SO_NOSIGPIPE)
5298 if (type == SOCK_DGRAM) {
5299 if (0 != setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){ 1 }, sizeof (int)))
5300 goto soerr;
5301 }
5302#endif
5303
4565 if (local->sa_family != AF_INET && local->sa_family != AF_INET6) 5304 if (local->sa_family != AF_INET && local->sa_family != AF_INET6)
4566 return fd; 5305 return fd;
4567 5306
@@ -4592,10 +5331,12 @@ soerr:
4592 error = dns_soerr(); 5331 error = dns_soerr();
4593 5332
4594 goto error; 5333 goto error;
5334#if defined(F_SETFD) || defined(O_NONBLOCK)
4595syerr: 5335syerr:
4596 error = dns_syerr(); 5336 error = dns_syerr();
4597 5337
4598 goto error; 5338 goto error;
5339#endif
4599error: 5340error:
4600 *error_ = error; 5341 *error_ = error;
4601 5342
@@ -4650,7 +5391,7 @@ struct dns_socket {
4650 struct dns_packet *query; 5391 struct dns_packet *query;
4651 size_t qout; 5392 size_t qout;
4652 5393
4653 time_t began; 5394 struct dns_clock elapsed;
4654 5395
4655 struct dns_packet *answer; 5396 struct dns_packet *answer;
4656 size_t alen, apos; 5397 size_t alen, apos;
@@ -4832,7 +5573,8 @@ int dns_so_submit(struct dns_socket *so, struct dns_packet *Q, struct sockaddr *
4832 5573
4833 so->query = Q; 5574 so->query = Q;
4834 so->qout = 0; 5575 so->qout = 0;
4835 so->began = dns_now(); 5576
5577 dns_begin(&so->elapsed);
4836 5578
4837 if (dns_header(so->query)->qid == 0) 5579 if (dns_header(so->query)->qid == 0)
4838 dns_header(so->query)->qid = dns_so_mkqid(so); 5580 dns_header(so->query)->qid = dns_so_mkqid(so);
@@ -4882,6 +5624,11 @@ static int dns_so_verify(struct dns_socket *so, struct dns_packet *P) {
4882} /* dns_so_verify() */ 5624} /* dns_so_verify() */
4883 5625
4884 5626
5627#if defined __clang__
5628#pragma clang diagnostic push
5629#pragma clang diagnostic ignored "-Warray-bounds"
5630#endif
5631
4885static int dns_so_tcp_send(struct dns_socket *so) { 5632static int dns_so_tcp_send(struct dns_socket *so) {
4886 unsigned char *qsrc; 5633 unsigned char *qsrc;
4887 size_t qend; 5634 size_t qend;
@@ -4894,7 +5641,7 @@ static int dns_so_tcp_send(struct dns_socket *so) {
4894 qend = so->query->end + 2; 5641 qend = so->query->end + 2;
4895 5642
4896 while (so->qout < qend) { 5643 while (so->qout < qend) {
4897 if (0 > (n = send(so->tcp, (void *)&qsrc[so->qout], qend - so->qout, 0))) 5644 if (0 > (n = dns_send(so->tcp, (void *)&qsrc[so->qout], qend - so->qout, 0)))
4898 return dns_soerr(); 5645 return dns_soerr();
4899 5646
4900 so->qout += n; 5647 so->qout += n;
@@ -4944,6 +5691,10 @@ static int dns_so_tcp_recv(struct dns_socket *so) {
4944 return 0; 5691 return 0;
4945} /* dns_so_tcp_recv() */ 5692} /* dns_so_tcp_recv() */
4946 5693
5694#if __clang__
5695#pragma clang diagnostic pop
5696#endif
5697
4947 5698
4948int dns_so_check(struct dns_socket *so) { 5699int dns_so_check(struct dns_socket *so) {
4949 int error; 5700 int error;
@@ -5098,7 +5849,7 @@ error:
5098 5849
5099 5850
5100time_t dns_so_elapsed(struct dns_socket *so) { 5851time_t dns_so_elapsed(struct dns_socket *so) {
5101 return dns_elapsed(so->began); 5852 return dns_elapsed(&so->elapsed);
5102} /* dns_so_elapsed() */ 5853} /* dns_so_elapsed() */
5103 5854
5104 5855
@@ -5229,7 +5980,7 @@ struct dns_resolver {
5229 enum dns_type qtype; 5980 enum dns_type qtype;
5230 enum dns_class qclass; 5981 enum dns_class qclass;
5231 5982
5232 time_t began; 5983 struct dns_clock elapsed;
5233 5984
5234 dns_resconf_i_t search; 5985 dns_resconf_i_t search;
5235 5986
@@ -5264,7 +6015,7 @@ static int dns_res_tcp2type(int tcp) {
5264 } 6015 }
5265} /* dns_res_tcp2type() */ 6016} /* dns_res_tcp2type() */
5266 6017
5267struct dns_resolver *dns_res_open(struct dns_resolv_conf *resconf, struct dns_hosts *hosts, struct dns_hints *hints, struct dns_cache *cache, const struct dns_options *opts, int *error_) { 6018struct dns_resolver *dns_res_open(struct dns_resolv_conf *resconf, struct dns_hosts *hosts, struct dns_hints *hints, struct dns_cache *cache, const struct dns_options *opts, int *_error) {
5268 static const struct dns_resolver R_initializer 6019 static const struct dns_resolver R_initializer
5269 = { .refcount = 1, }; 6020 = { .refcount = 1, };
5270 struct dns_resolver *R = 0; 6021 struct dns_resolver *R = 0;
@@ -5290,7 +6041,7 @@ struct dns_resolver *dns_res_open(struct dns_resolv_conf *resconf, struct dns_ho
5290 * dns_resconf_local() by default would create undesirable surpises. 6041 * dns_resconf_local() by default would create undesirable surpises.
5291 */ 6042 */
5292 if (!resconf || !hosts || !hints) 6043 if (!resconf || !hosts || !hints)
5293 goto error; 6044 goto _error;
5294 6045
5295 if (!(R = malloc(sizeof *R))) 6046 if (!(R = malloc(sizeof *R)))
5296 goto syerr; 6047 goto syerr;
@@ -5310,8 +6061,8 @@ struct dns_resolver *dns_res_open(struct dns_resolv_conf *resconf, struct dns_ho
5310syerr: 6061syerr:
5311 error = dns_syerr(); 6062 error = dns_syerr();
5312error: 6063error:
5313 *error_ = error; 6064 *_error = error;
5314 6065_error:
5315 dns_res_close(R); 6066 dns_res_close(R);
5316 6067
5317 dns_resconf_close(resconf); 6068 dns_resconf_close(resconf);
@@ -5350,7 +6101,7 @@ epilog:
5350} /* dns_res_stub() */ 6101} /* dns_res_stub() */
5351 6102
5352 6103
5353static void dns_res_reset_frame(struct dns_resolver *R EINA_UNUSED, struct dns_res_frame *frame) { 6104static void dns_res_reset_frame(struct dns_resolver *R, struct dns_res_frame *frame) {
5354 free(frame->query); 6105 free(frame->query);
5355 free(frame->answer); 6106 free(frame->answer);
5356 free(frame->hints); 6107 free(frame->hints);
@@ -5618,7 +6369,7 @@ exec:
5618 6369
5619 F->state++; 6370 F->state++;
5620 case DNS_R_SWITCH: 6371 case DNS_R_SWITCH:
5621 while (F->which < (int)sizeof R->resconf->lookup) { 6372 while (F->which < (int)sizeof R->resconf->lookup && R->resconf->lookup[F->which]) {
5622 switch (R->resconf->lookup[F->which++]) { 6373 switch (R->resconf->lookup[F->which++]) {
5623 case 'b': case 'B': 6374 case 'b': case 'B':
5624 goto(R->sp, DNS_R_BIND); 6375 goto(R->sp, DNS_R_BIND);
@@ -5755,6 +6506,8 @@ exec:
5755 6506
5756 F->state++; 6507 F->state++;
5757 case DNS_R_HINTS: 6508 case DNS_R_HINTS:
6509 free(F->hints);
6510
5758 if (!(F->hints = dns_hints_query(R->hints, F->query, &error))) 6511 if (!(F->hints = dns_hints_query(R->hints, F->query, &error)))
5759 goto error; 6512 goto error;
5760 6513
@@ -5893,7 +6646,7 @@ exec:
5893 } 6646 }
5894 6647
5895 if (!R->resconf->options.recurse) 6648 if (!R->resconf->options.recurse)
5896 goto(R->sp, DNS_R_SWITCH); 6649 goto(R->sp, DNS_R_SEARCH);
5897 6650
5898 dns_rr_foreach(&rr, F->answer, .section = DNS_S_NS, .type = DNS_T_NS) { 6651 dns_rr_foreach(&rr, F->answer, .section = DNS_S_NS, .type = DNS_T_NS) {
5899 free(F->hints); 6652 free(F->hints);
@@ -6083,9 +6836,11 @@ error:
6083void dns_res_clear(struct dns_resolver *R) { 6836void dns_res_clear(struct dns_resolver *R) {
6084 switch (R->stack[R->sp].state) { 6837 switch (R->stack[R->sp].state) {
6085 case DNS_R_CHECK: 6838 case DNS_R_CHECK:
6086 return R->cache->clear(R->cache); 6839 R->cache->clear(R->cache);
6840 break;
6087 default: 6841 default:
6088 return dns_so_clear(&R->so); 6842 dns_so_clear(&R->so);
6843 break;
6089 } 6844 }
6090} /* dns_res_clear() */ 6845} /* dns_res_clear() */
6091 6846
@@ -6120,7 +6875,7 @@ int dns_res_pollfd(struct dns_resolver *R) {
6120 6875
6121 6876
6122time_t dns_res_elapsed(struct dns_resolver *R) { 6877time_t dns_res_elapsed(struct dns_resolver *R) {
6123 return dns_elapsed(R->began); 6878 return dns_elapsed(&R->elapsed);
6124} /* dns_res_elapsed() */ 6879} /* dns_res_elapsed() */
6125 6880
6126 6881
@@ -6138,7 +6893,7 @@ int dns_res_submit(struct dns_resolver *R, const char *qname, enum dns_type qtyp
6138 R->qtype = qtype; 6893 R->qtype = qtype;
6139 R->qclass = qclass; 6894 R->qclass = qclass;
6140 6895
6141 R->began = dns_now(); 6896 dns_begin(&R->elapsed);
6142 6897
6143 return 0; 6898 return 0;
6144} /* dns_res_submit() */ 6899} /* dns_res_submit() */
@@ -6534,7 +7289,7 @@ time_t dns_ai_elapsed(struct dns_addrinfo *ai) {
6534 7289
6535 7290
6536void dns_ai_clear(struct dns_addrinfo *ai) { 7291void dns_ai_clear(struct dns_addrinfo *ai) {
6537 return dns_res_clear(ai->res); 7292 dns_res_clear(ai->res);
6538} /* dns_ai_clear() */ 7293} /* dns_ai_clear() */
6539 7294
6540 7295
@@ -6815,6 +7570,7 @@ enum dns_rcode dns_ircode(const char *name) {
6815} /* dns_ircode() */ 7570} /* dns_ircode() */
6816 7571
6817 7572
7573
6818/* 7574/*
6819 * C O M M A N D - L I N E / R E G R E S S I O N R O U T I N E S 7575 * C O M M A N D - L I N E / R E G R E S S I O N R O U T I N E S
6820 * 7576 *
@@ -6840,17 +7596,7 @@ struct {
6840 struct { 7596 struct {
6841 const char *path[8]; 7597 const char *path[8];
6842 unsigned count; 7598 unsigned count;
6843 } resconf; 7599 } resconf, nssconf, hosts, cache;
6844
6845 struct {
6846 const char *path[8];
6847 unsigned count;
6848 } hosts;
6849
6850 struct {
6851 const char *path[8];
6852 unsigned count;
6853 } cache;
6854 7600
6855 const char *qname; 7601 const char *qname;
6856 enum dns_type qtype; 7602 enum dns_type qtype;
@@ -6923,7 +7669,7 @@ static void *grow(unsigned char *p, size_t size) {
6923 void *tmp; 7669 void *tmp;
6924 7670
6925 if (!(tmp = realloc(p, size))) 7671 if (!(tmp = realloc(p, size)))
6926 panic("realloc(%zu): %s", size, dns_strerror(errno)); 7672 panic("realloc(%"PRIuZ"): %s", size, dns_strerror(errno));
6927 7673
6928 return tmp; 7674 return tmp;
6929} /* grow() */ 7675} /* grow() */
@@ -6931,7 +7677,7 @@ static void *grow(unsigned char *p, size_t size) {
6931 7677
6932static size_t add(size_t a, size_t b) { 7678static size_t add(size_t a, size_t b) {
6933 if (~a < b) 7679 if (~a < b)
6934 panic("%zu + %zu: integer overflow", a, b); 7680 panic("%"PRIuZ" + %"PRIuZ": integer overflow", a, b);
6935 7681
6936 return a + b; 7682 return a + b;
6937} /* add() */ 7683} /* add() */
@@ -6989,6 +7735,27 @@ static struct dns_resolv_conf *resconf(void) {
6989 panic("%s: %s", path, dns_strerror(error)); 7735 panic("%s: %s", path, dns_strerror(error));
6990 } 7736 }
6991 7737
7738 for (i = 0; i < MAIN.nssconf.count; i++) {
7739 path = MAIN.nssconf.path[i];
7740
7741 if (0 == strcmp(path, "-"))
7742 error = dns_nssconf_loadfile(resconf, stdin);
7743 else
7744 error = dns_nssconf_loadpath(resconf, path);
7745
7746 if (error)
7747 panic("%s: %s", path, dns_strerror(error));
7748 }
7749
7750 if (!MAIN.nssconf.count) {
7751 path = "/etc/nsswitch.conf";
7752
7753 if (!(error = dns_nssconf_loadpath(resconf, path)))
7754 MAIN.nssconf.path[MAIN.nssconf.count++] = path;
7755 else if (error != ENOENT)
7756 panic("%s: %s", path, dns_strerror(error));
7757 }
7758
6992 return resconf; 7759 return resconf;
6993} /* resconf() */ 7760} /* resconf() */
6994 7761
@@ -7086,7 +7853,7 @@ static int parse_packet(int argc, char *argv[]) {
7086 P->end = fread(P->data, 1, P->size, stdin); 7853 P->end = fread(P->data, 1, P->size, stdin);
7087 7854
7088 fputs(";; [HEADER]\n", stdout); 7855 fputs(";; [HEADER]\n", stdout);
7089 fprintf(stdout, ";; qr : %s(%d)\n", (dns_header(P)->qr)? "QUERY" : "RESPONSE", dns_header(P)->qr); 7856 fprintf(stdout, ";; qr : %s(%d)\n", (dns_header(P)->qr)? "RESPONSE" : "QUERY", dns_header(P)->qr);
7090 fprintf(stdout, ";; opcode : %s(%d)\n", dns_stropcode(dns_header(P)->opcode), dns_header(P)->opcode); 7857 fprintf(stdout, ";; opcode : %s(%d)\n", dns_stropcode(dns_header(P)->opcode), dns_header(P)->opcode);
7091 fprintf(stdout, ";; aa : %s(%d)\n", (dns_header(P)->aa)? "AUTHORITATIVE" : "NON-AUTHORITATIVE", dns_header(P)->aa); 7858 fprintf(stdout, ";; aa : %s(%d)\n", (dns_header(P)->aa)? "AUTHORITATIVE" : "NON-AUTHORITATIVE", dns_header(P)->aa);
7092 fprintf(stdout, ";; tc : %s(%d)\n", (dns_header(P)->tc)? "TRUNCATED" : "NOT-TRUNCATED", dns_header(P)->tc); 7859 fprintf(stdout, ";; tc : %s(%d)\n", (dns_header(P)->tc)? "TRUNCATED" : "NOT-TRUNCATED", dns_header(P)->tc);
@@ -7118,9 +7885,8 @@ static int parse_packet(int argc, char *argv[]) {
7118 struct dns_rr rrset[32]; 7885 struct dns_rr rrset[32];
7119 struct dns_rr_i *rri = dns_rr_i_new(Q, .name = dns_d_new("ns8.yahoo.com", DNS_D_ANCHOR), .sort = MAIN.sort); 7886 struct dns_rr_i *rri = dns_rr_i_new(Q, .name = dns_d_new("ns8.yahoo.com", DNS_D_ANCHOR), .sort = MAIN.sort);
7120 unsigned rrcount = dns_rr_grep(rrset, lengthof(rrset), rri, Q, &error); 7887 unsigned rrcount = dns_rr_grep(rrset, lengthof(rrset), rri, Q, &error);
7121 unsigned i;
7122 7888
7123 for (i = 0; i < rrcount; i++) { 7889 for (unsigned i = 0; i < rrcount; i++) {
7124 rr = rrset[i]; 7890 rr = rrset[i];
7125#endif 7891#endif
7126 if (section != rr.section) 7892 if (section != rr.section)
@@ -7133,10 +7899,10 @@ static int parse_packet(int argc, char *argv[]) {
7133 } 7899 }
7134 7900
7135 if (MAIN.verbose > 1) { 7901 if (MAIN.verbose > 1) {
7136 fprintf(stderr, "orig:%zu\n", P->end); 7902 fprintf(stderr, "orig:%"PRIuZ"\n", P->end);
7137 hexdump(P->data, P->end, stdout); 7903 hexdump(P->data, P->end, stdout);
7138 7904
7139 fprintf(stderr, "copy:%zu\n", Q->end); 7905 fprintf(stderr, "copy:%"PRIuZ"\n", Q->end);
7140 hexdump(Q->data, Q->end, stdout); 7906 hexdump(Q->data, Q->end, stdout);
7141 } 7907 }
7142 7908
@@ -7175,7 +7941,7 @@ static int expand_domain(int argc, char *argv[]) {
7175 len = slurp(&src, 0, stdin, "-"); 7941 len = slurp(&src, 0, stdin, "-");
7176 7942
7177 if (!(pkt = dns_p_make(len, &error))) 7943 if (!(pkt = dns_p_make(len, &error)))
7178 panic("malloc(%zu): %s", len, dns_strerror(error)); 7944 panic("malloc(%"PRIuZ"): %s", len, dns_strerror(error));
7179 7945
7180 memcpy(pkt->data, src, len); 7946 memcpy(pkt->data, src, len);
7181 pkt->end = len; 7947 pkt->end = len;
@@ -7205,13 +7971,16 @@ static int expand_domain(int argc, char *argv[]) {
7205static int show_resconf(int argc, char *argv[]) { 7971static int show_resconf(int argc, char *argv[]) {
7206 unsigned i; 7972 unsigned i;
7207 7973
7208 resconf(); /* load it */ 7974 resconf(); /* load it */
7209 7975
7210 fputs("; SOURCES\n", stdout); 7976 fputs("; SOURCES\n", stdout);
7211 7977
7212 for (i = 0; i < MAIN.resconf.count; i++) 7978 for (i = 0; i < MAIN.resconf.count; i++)
7213 fprintf(stdout, "; %s\n", MAIN.resconf.path[i]); 7979 fprintf(stdout, "; %s\n", MAIN.resconf.path[i]);
7214 7980
7981 for (i = 0; i < MAIN.nssconf.count; i++)
7982 fprintf(stdout, "; %s\n", MAIN.nssconf.path[i]);
7983
7215 fputs(";\n", stdout); 7984 fputs(";\n", stdout);
7216 7985
7217 dns_resconf_dump(resconf(), stdout); 7986 dns_resconf_dump(resconf(), stdout);
@@ -7220,6 +7989,27 @@ static int show_resconf(int argc, char *argv[]) {
7220} /* show_resconf() */ 7989} /* show_resconf() */
7221 7990
7222 7991
7992static int show_nssconf(int argc, char *argv[]) {
7993 unsigned i;
7994
7995 resconf();
7996
7997 fputs("# SOURCES\n", stdout);
7998
7999 for (i = 0; i < MAIN.resconf.count; i++)
8000 fprintf(stdout, "# %s\n", MAIN.resconf.path[i]);
8001
8002 for (i = 0; i < MAIN.nssconf.count; i++)
8003 fprintf(stdout, "# %s\n", MAIN.nssconf.path[i]);
8004
8005 fputs("#\n", stdout);
8006
8007 dns_nssconf_dump(resconf(), stdout);
8008
8009 return 0;
8010} /* show_nssconf() */
8011
8012
7223static int show_hosts(int argc, char *argv[]) { 8013static int show_hosts(int argc, char *argv[]) {
7224 unsigned i; 8014 unsigned i;
7225 8015
@@ -7256,7 +8046,7 @@ static int query_hosts(int argc, char *argv[]) {
7256 union { struct in_addr a; struct in6_addr a6; } addr; 8046 union { struct in_addr a; struct in6_addr a6; } addr;
7257 int af = (strchr(MAIN.qname, ':'))? AF_INET6 : AF_INET; 8047 int af = (strchr(MAIN.qname, ':'))? AF_INET6 : AF_INET;
7258 8048
7259 if (1 != dns_inet_pton(af, MAIN.qname, &addr)) 8049 if ((error = dns_pton(af, MAIN.qname, &addr)))
7260 panic("%s: %s", MAIN.qname, dns_strerror(error)); 8050 panic("%s: %s", MAIN.qname, dns_strerror(error));
7261 8051
7262 qlen = dns_ptr_qname(qname, sizeof qname, af, &addr); 8052 qlen = dns_ptr_qname(qname, sizeof qname, af, &addr);
@@ -7366,8 +8156,8 @@ static int send_query(int argc, char *argv[]) {
7366 if (argc > 1) { 8156 if (argc > 1) {
7367 ss.ss_family = (strchr(argv[1], ':'))? AF_INET6 : AF_INET; 8157 ss.ss_family = (strchr(argv[1], ':'))? AF_INET6 : AF_INET;
7368 8158
7369 if (1 != dns_inet_pton(ss.ss_family, argv[1], dns_sa_addr(ss.ss_family, &ss))) 8159 if ((error = dns_pton(ss.ss_family, argv[1], dns_sa_addr(ss.ss_family, &ss))))
7370 panic("%s: invalid host address", argv[1]); 8160 panic("%s: %s", argv[1], dns_strerror(error));
7371 8161
7372 *dns_sa_port(ss.ss_family, &ss) = htons(53); 8162 *dns_sa_port(ss.ss_family, &ss) = htons(53);
7373 } else 8163 } else
@@ -7399,7 +8189,7 @@ static int send_query(int argc, char *argv[]) {
7399 panic("dns_so_open: %s", dns_strerror(error)); 8189 panic("dns_so_open: %s", dns_strerror(error));
7400 8190
7401 while (!(A = dns_so_query(so, Q, (struct sockaddr *)&ss, &error))) { 8191 while (!(A = dns_so_query(so, Q, (struct sockaddr *)&ss, &error))) {
7402 if (error != EAGAIN) 8192 if (error != DNS_EAGAIN)
7403 panic("dns_so_query: %s (%d)", dns_strerror(error), error); 8193 panic("dns_so_query: %s (%d)", dns_strerror(error), error);
7404 if (dns_so_elapsed(so) > 10) 8194 if (dns_so_elapsed(so) > 10)
7405 panic("query timed-out"); 8195 panic("query timed-out");
@@ -7492,7 +8282,7 @@ static int resolve_query(int argc, char *argv[]) {
7492 panic("%s: %s", MAIN.qname, dns_strerror(error)); 8282 panic("%s: %s", MAIN.qname, dns_strerror(error));
7493 8283
7494 while ((error = dns_res_check(R))) { 8284 while ((error = dns_res_check(R))) {
7495 if (error != EAGAIN) 8285 if (error != DNS_EAGAIN)
7496 panic("dns_res_check: %s (%d)", dns_strerror(error), error); 8286 panic("dns_res_check: %s (%d)", dns_strerror(error), error);
7497 if (dns_res_elapsed(R) > 30) 8287 if (dns_res_elapsed(R) > 30)
7498 panic("query timed-out"); 8288 panic("query timed-out");
@@ -7506,11 +8296,11 @@ static int resolve_query(int argc, char *argv[]) {
7506 8296
7507 st = dns_res_stat(R); 8297 st = dns_res_stat(R);
7508 putchar('\n'); 8298 putchar('\n');
7509 printf(";; queries: %zu\n", st->queries); 8299 printf(";; queries: %"PRIuZ"\n", st->queries);
7510 printf(";; udp sent: %zu in %zu bytes\n", st->udp.sent.count, st->udp.sent.bytes); 8300 printf(";; udp sent: %"PRIuZ" in %"PRIuZ" bytes\n", st->udp.sent.count, st->udp.sent.bytes);
7511 printf(";; udp rcvd: %zu in %zu bytes\n", st->udp.rcvd.count, st->udp.rcvd.bytes); 8301 printf(";; udp rcvd: %"PRIuZ" in %"PRIuZ" bytes\n", st->udp.rcvd.count, st->udp.rcvd.bytes);
7512 printf(";; tcp sent: %zu in %zu bytes\n", st->tcp.sent.count, st->tcp.sent.bytes); 8302 printf(";; tcp sent: %"PRIuZ" in %"PRIuZ" bytes\n", st->tcp.sent.count, st->tcp.sent.bytes);
7513 printf(";; tcp rcvd: %zu in %zu bytes\n", st->tcp.rcvd.count, st->tcp.rcvd.bytes); 8303 printf(";; tcp rcvd: %"PRIuZ" in %"PRIuZ" bytes\n", st->tcp.rcvd.count, st->tcp.rcvd.bytes);
7514 8304
7515 dns_res_close(R); 8305 dns_res_close(R);
7516 8306
@@ -7552,7 +8342,7 @@ static int resolve_addrinfo(int argc, char *argv[]) {
7552 break; 8342 break;
7553 case ENOENT: 8343 case ENOENT:
7554 break; 8344 break;
7555 case EAGAIN: 8345 case DNS_EAGAIN:
7556 if (dns_ai_elapsed(ai) > 30) 8346 if (dns_ai_elapsed(ai) > 30)
7557 panic("query timed-out"); 8347 panic("query timed-out");
7558 8348
@@ -7696,7 +8486,7 @@ static int sizes(int argc, char *argv[]) {
7696 SIZE(struct dns_sshfp, struct dns_txt, union dns_any), 8486 SIZE(struct dns_sshfp, struct dns_txt, union dns_any),
7697 SIZE(struct dns_resolv_conf, struct dns_hosts, struct dns_hints, struct dns_hints_i), 8487 SIZE(struct dns_resolv_conf, struct dns_hosts, struct dns_hints, struct dns_hints_i),
7698 SIZE(struct dns_options, struct dns_socket, struct dns_resolver, struct dns_addrinfo), 8488 SIZE(struct dns_options, struct dns_socket, struct dns_resolver, struct dns_addrinfo),
7699 SIZE(struct dns_cache), 8489 SIZE(struct dns_cache), SIZE(size_t), SIZE(void *), SIZE(long)
7700 }; 8490 };
7701 unsigned i, max; 8491 unsigned i, max;
7702 8492
@@ -7704,7 +8494,7 @@ static int sizes(int argc, char *argv[]) {
7704 max = MAX(max, strlen(type[i].name)); 8494 max = MAX(max, strlen(type[i].name));
7705 8495
7706 for (i = 0; i < lengthof(type); i++) 8496 for (i = 0; i < lengthof(type); i++)
7707 printf("%*s : %zu\n", max, type[i].name, type[i].size); 8497 printf("%*s : %"PRIuZ"\n", max, type[i].name, type[i].size);
7708 8498
7709 return 0; 8499 return 0;
7710} /* sizes() */ 8500} /* sizes() */
@@ -7716,6 +8506,7 @@ static const struct { const char *cmd; int (*run)(); const char *help; } cmds[]
7716 { "expand-domain", &expand_domain, "expand domain at offset NN in packet from stdin" }, 8506 { "expand-domain", &expand_domain, "expand domain at offset NN in packet from stdin" },
7717 { "show-resconf", &show_resconf, "show resolv.conf data" }, 8507 { "show-resconf", &show_resconf, "show resolv.conf data" },
7718 { "show-hosts", &show_hosts, "show hosts data" }, 8508 { "show-hosts", &show_hosts, "show hosts data" },
8509 { "show-nssconf", &show_nssconf, "show nsswitch.conf data" },
7719 { "query-hosts", &query_hosts, "query A, AAAA or PTR in hosts data" }, 8510 { "query-hosts", &query_hosts, "query A, AAAA or PTR in hosts data" },
7720 { "search-list", &search_list, "generate query search list from domain" }, 8511 { "search-list", &search_list, "generate query search list from domain" },
7721 { "permute-set", &permute_set, "generate random permutation -> (0 .. N or N .. M)" }, 8512 { "permute-set", &permute_set, "generate random permutation -> (0 .. N or N .. M)" },
@@ -7745,6 +8536,7 @@ static void print_usage(const char *progname, FILE *fp) {
7745 static const char *usage = 8536 static const char *usage =
7746 " [OPTIONS] COMMAND [ARGS]\n" 8537 " [OPTIONS] COMMAND [ARGS]\n"
7747 " -c PATH Path to resolv.conf\n" 8538 " -c PATH Path to resolv.conf\n"
8539 " -n PATH Path to nsswitch.conf\n"
7748 " -l PATH Path to local hosts\n" 8540 " -l PATH Path to local hosts\n"
7749 " -z PATH Path to zone cache\n" 8541 " -z PATH Path to zone cache\n"
7750 " -q QNAME Query name\n" 8542 " -q QNAME Query name\n"
@@ -7794,7 +8586,7 @@ int main(int argc, char **argv) {
7794 unsigned i; 8586 unsigned i;
7795 int ch; 8587 int ch;
7796 8588
7797 while (-1 != (ch = getopt(argc, argv, "q:t:c:l:z:s:vVh"))) { 8589 while (-1 != (ch = getopt(argc, argv, "q:t:c:n:l:z:s:vVh"))) {
7798 switch (ch) { 8590 switch (ch) {
7799 case 'c': 8591 case 'c':
7800 assert(MAIN.resconf.count < lengthof(MAIN.resconf.path)); 8592 assert(MAIN.resconf.count < lengthof(MAIN.resconf.path));
@@ -7802,6 +8594,12 @@ int main(int argc, char **argv) {
7802 MAIN.resconf.path[MAIN.resconf.count++] = optarg; 8594 MAIN.resconf.path[MAIN.resconf.count++] = optarg;
7803 8595
7804 break; 8596 break;
8597 case 'n':
8598 assert(MAIN.nssconf.count < lengthof(MAIN.nssconf.path));
8599
8600 MAIN.nssconf.path[MAIN.nssconf.count++] = optarg;
8601
8602 break;
7805 case 'l': 8603 case 'l':
7806 assert(MAIN.hosts.count < lengthof(MAIN.hosts.path)); 8604 assert(MAIN.hosts.count < lengthof(MAIN.hosts.path));
7807 8605
@@ -7881,3 +8679,14 @@ int main(int argc, char **argv) {
7881 8679
7882 8680
7883#endif /* DNS_MAIN */ 8681#endif /* DNS_MAIN */
8682
8683
8684/*
8685 * pop file-scoped compiler annotations
8686 */
8687#if __clang__
8688#pragma clang diagnostic pop
8689#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4
8690#pragma GCC diagnostic pop
8691#endif
8692