Created
December 30, 2016 20:03
-
-
Save jarcode-foss/2168add42e72589ae6e09a72e709b0a0 to your computer and use it in GitHub Desktop.
Fix for name resolution in belle-sip
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 7b92f57a4eec5fe2d01ee620f1213c238d128b86 Mon Sep 17 00:00:00 2001 | |
From: BuildTools <[email protected]> | |
Date: Fri, 30 Dec 2016 11:43:57 -0800 | |
Subject: [PATCH] Update dns.c and usage | |
--- | |
src/belle_sip_resolver.c | 2 +- | |
src/dns.c | 690 ++++++++++++++++++++--------------------------- | |
src/dns.h | 37 +-- | |
3 files changed, 296 insertions(+), 433 deletions(-) | |
diff --git a/src/belle_sip_resolver.c b/src/belle_sip_resolver.c | |
index a1969d5..4206723 100644 | |
--- a/src/belle_sip_resolver.c | |
+++ b/src/belle_sip_resolver.c | |
@@ -488,7 +488,7 @@ static int resolver_process_data(belle_sip_simple_resolver_context_t *ctx, unsig | |
belle_sip_resolver_context_notify(BELLE_SIP_RESOLVER_CONTEXT(ctx)); | |
return BELLE_SIP_STOP; | |
} | |
- dns_res_enable_search(ctx->R, search_enabled); | |
+ /*dns_res_enable_search(ctx->R, search_enabled);*/ | |
/*belle_sip_message("resolver_process_data(): revents=%i",revents);*/ | |
error = dns_res_check(ctx->R); | |
if (!error) { | |
diff --git a/src/dns.c b/src/dns.c | |
index 8d22f88..15ff335 100644 | |
--- a/src/dns.c | |
+++ b/src/dns.c | |
@@ -28,9 +28,6 @@ | |
#define _XOPEN_SOURCE 600 | |
#endif | |
-#undef _DEFAULT_SOURCE | |
-#define _DEFAULT_SOURCE | |
- | |
#undef _BSD_SOURCE | |
#define _BSD_SOURCE | |
@@ -41,26 +38,17 @@ | |
#define _NETBSD_SOURCE | |
#endif | |
-#ifdef _MSC_VER | |
-#define DNS_INLINE __inline | |
-#else | |
-#define DNS_INLINE inline | |
-#endif | |
- | |
#include <limits.h> /* INT_MAX */ | |
#include <stddef.h> /* offsetof() */ | |
-/*#ifdef _WIN32 | |
-#define uint16_t unsigned short | |
+#ifdef _WIN32 | |
#define uint32_t unsigned int | |
-#else*/ | |
+#else | |
#include <stdint.h> /* uint32_t */ | |
-//#endif | |
+#endif | |
#include <stdlib.h> /* malloc(3) realloc(3) free(3) rand(3) random(3) arc4random(3) */ | |
#include <stdio.h> /* FILE fopen(3) fclose(3) getc(3) rewind(3) */ | |
#include <string.h> /* memcpy(3) strlen(3) memmove(3) memchr(3) memcmp(3) strchr(3) strsep(3) strcspn(3) */ | |
-#ifndef _WIN32 | |
#include <strings.h> /* strcasecmp(3) strncasecmp(3) */ | |
-#endif | |
#include <ctype.h> /* isspace(3) isdigit(3) */ | |
#include <time.h> /* time_t time(2) difftime(3) */ | |
#include <signal.h> /* SIGPIPE sigemptyset(3) sigaddset(3) sigpending(2) sigprocmask(2) pthread_sigmask(3) sigtimedwait(2) */ | |
@@ -70,27 +58,10 @@ | |
#if _WIN32 | |
#ifndef FD_SETSIZE | |
-#define FD_SETSIZE 2048 | |
+#define FD_SETSIZE 256 | |
#endif | |
#include <winsock2.h> | |
#include <ws2tcpip.h> | |
-#ifndef USE_FIXED_NAMESERVERS | |
-#include <IPHlpApi.h> | |
-#pragma comment(lib, "IPHLPAPI.lib") | |
-#endif | |
- | |
-#if defined(__MINGW32__) || !defined(WINAPI_FAMILY_PARTITION) || !defined(WINAPI_PARTITION_DESKTOP) | |
-#define BELLE_SIP_WINDOWS_DESKTOP 1 | |
-#elif defined(WINAPI_FAMILY_PARTITION) | |
-#if defined(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) | |
-#define BELLE_SIP_WINDOWS_DESKTOP 1 | |
-#elif defined(WINAPI_PARTITION_PHONE_APP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) | |
-#define BELLE_SIP_WINDOWS_PHONE 1 | |
-#elif defined(WINAPI_PARTITION_APP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) | |
-#define BELLE_SIP_WINDOWS_UNIVERSAL 1 | |
-#endif | |
-#endif | |
- | |
#else | |
#include <sys/types.h> /* FD_SETSIZE socklen_t */ | |
#include <sys/select.h> /* FD_ZERO FD_SET fd_set select(2) */ | |
@@ -108,15 +79,6 @@ | |
#include "dns.h" | |
-#if defined(HAVE_RESINIT) || defined(USE_STRUCT_RES_STATE_NAMESERVERS) | |
-#include <resolv.h> | |
-#endif | |
- | |
-#ifdef ANDROID | |
-#include <sys/system_properties.h> | |
-#endif | |
- | |
-#include <bctoolbox/port.h> | |
/* | |
* C O M P I L E R V E R S I O N & F E A T U R E D E T E C T I O N | |
@@ -190,12 +152,13 @@ | |
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
#if HAVE___BUILTIN_TYPES_COMPATIBLE_P | |
-#define dns_same_type(a, b, def) __builtin_types_compatible_p(typeof (a), typeof (b)) | |
+#define dns_same_type(a, b, def) __builtin_types_compatible_p(__typeof__ (a), __typeof__ (b)) | |
#else | |
#define dns_same_type(a, b, def) (def) | |
#endif | |
#define dns_isarray(a) (!dns_same_type((a), (&(a)[0]), 0)) | |
-#define dns_inline_assert(cond) ((void)(sizeof (struct { int:-!(cond); }))) | |
+/* NB: "_" field silences Sun Studio "zero-sized struct/union" error diagnostic */ | |
+#define dns_inline_assert(cond) ((void)(sizeof (struct { int:-!(cond); int _; }))) | |
#if HAVE___ASSUME | |
#define dns_assume(cond) __assume(cond) | |
@@ -269,13 +232,16 @@ int *dns_debug_p(void) { | |
#if DNS_DEBUG | |
+#undef DNS_DEBUG | |
+#define DNS_DEBUG dns_debug | |
+ | |
#define DNS_SAY_(fmt, ...) \ | |
do { if (DNS_DEBUG > 0) fprintf(stderr, fmt "%.1s", __func__, __LINE__, __VA_ARGS__); } while (0) | |
#define DNS_SAY(...) DNS_SAY_("@@ (%s:%d) " __VA_ARGS__, "\n") | |
#define DNS_HAI DNS_SAY("HAI") | |
#define DNS_SHOW_(P, fmt, ...) do { \ | |
- if (DNS_DEBUG >= 1) { \ | |
+ if (DNS_DEBUG > 1) { \ | |
fprintf(stderr, "@@ BEGIN * * * * * * * * * * * *\n"); \ | |
fprintf(stderr, "@@ " fmt "%.0s\n", __VA_ARGS__); \ | |
dns_p_dump((P), stderr); \ | |
@@ -338,9 +304,6 @@ int dns_v_api(void) { | |
#define DNS_EALREADY WSAEALREADY | |
#define DNS_EAGAIN EAGAIN | |
#define DNS_ETIMEDOUT WSAETIMEDOUT | |
-#define DNS_ECONNREFUSED WSAECONNREFUSED | |
-#define DNS_ENETUNREACH WSAENETUNREACH | |
-#define DNS_EHOSTUNREACH WSAEHOSTUNREACH | |
#define dns_syerr() ((int)GetLastError()) | |
#define dns_soerr() ((int)WSAGetLastError()) | |
@@ -354,9 +317,6 @@ int dns_v_api(void) { | |
#define DNS_EALREADY EALREADY | |
#define DNS_EAGAIN EAGAIN | |
#define DNS_ETIMEDOUT ETIMEDOUT | |
-#define DNS_ECONNREFUSED ECONNREFUSED | |
-#define DNS_ENETUNREACH ENETUNREACH | |
-#define DNS_EHOSTUNREACH EHOSTUNREACH | |
#define dns_syerr() errno | |
#define dns_soerr() errno | |
@@ -437,12 +397,12 @@ const char *dns_strerror(int error) { | |
#endif | |
#endif | |
-static DNS_INLINE unsigned dns_atomic_fetch_add(dns_atomic_t *i) { | |
+static inline unsigned dns_atomic_fetch_add(dns_atomic_t *i) { | |
return DNS_ATOMIC_FETCH_ADD(i); | |
} /* dns_atomic_fetch_add() */ | |
-static DNS_INLINE unsigned dns_atomic_fetch_sub(dns_atomic_t *i) { | |
+static inline unsigned dns_atomic_fetch_sub(dns_atomic_t *i) { | |
return DNS_ATOMIC_FETCH_SUB(i); | |
} /* dns_atomic_fetch_sub() */ | |
@@ -571,7 +531,7 @@ struct dns_k_permutor { | |
}; /* struct dns_k_permutor */ | |
-static DNS_INLINE unsigned dns_k_permutor_powof(unsigned n) { | |
+static inline unsigned dns_k_permutor_powof(unsigned n) { | |
unsigned m, i = 0; | |
for (m = 1; m < n; m <<= 1, i++) | |
@@ -730,6 +690,40 @@ static unsigned short dns_k_shuffle16(unsigned short n, unsigned s) { | |
return ((0xff00 & (a << 8)) | (0x00ff & (b << 0))); | |
} /* dns_k_shuffle16() */ | |
+/* | |
+ * S T A T E M A C H I N E R O U T I N E S | |
+ * | |
+ * Application code should define DNS_SM_RESTORE and DNS_SM_SAVE, and the | |
+ * local variable pc. | |
+ * | |
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
+ | |
+#define DNS_SM_ENTER \ | |
+ do { \ | |
+ static const int pc0 = __LINE__; \ | |
+ DNS_SM_RESTORE; \ | |
+ switch (pc0 + pc) { \ | |
+ case __LINE__: (void)0 | |
+ | |
+#define DNS_SM_SAVE_AND_DO(do_statement) \ | |
+ do { \ | |
+ pc = __LINE__ - pc0; \ | |
+ DNS_SM_SAVE; \ | |
+ do_statement; \ | |
+ case __LINE__: (void)0; \ | |
+ } while (0) | |
+ | |
+#define DNS_SM_YIELD(rv) \ | |
+ DNS_SM_SAVE_AND_DO(return (rv)) | |
+ | |
+#define DNS_SM_EXIT \ | |
+ do { goto leave; } while (0) | |
+ | |
+#define DNS_SM_LEAVE \ | |
+ leave: (void)0; \ | |
+ DNS_SM_SAVE_AND_DO(break); \ | |
+ } \ | |
+ } while (0) | |
/* | |
* U T I L I T Y R O U T I N E S | |
@@ -799,7 +793,7 @@ static size_t dns_af_len(int af) { | |
return table[af]; | |
} /* dns_af_len() */ | |
-#define dns_sa_family(sa) (((struct sockaddr_storage *)(sa))->ss_family) | |
+#define dns_sa_family(sa) (((struct sockaddr *)(sa))->sa_family) | |
#define dns_sa_len(sa) dns_af_len(dns_sa_family(sa)) | |
@@ -1069,37 +1063,29 @@ static char *dns_strsep(char **sp, const char *delim) { | |
#if _WIN32 | |
-#ifndef strcasecmp | |
#define strcasecmp(...) _stricmp(__VA_ARGS__) | |
-#endif | |
-#ifndef strncasecmp | |
#define strncasecmp(...) _strnicmp(__VA_ARGS__) | |
#endif | |
-#endif | |
-static DNS_INLINE _Bool dns_isalpha(unsigned char c) { | |
+static inline _Bool dns_isalpha(unsigned char c) { | |
return isalpha(c); | |
} /* dns_isalpha() */ | |
-static DNS_INLINE _Bool dns_isdigit(unsigned char c) { | |
+static inline _Bool dns_isdigit(unsigned char c) { | |
return isdigit(c); | |
} /* dns_isdigit() */ | |
-static DNS_INLINE _Bool dns_isalnum(unsigned char c) { | |
+static inline _Bool dns_isalnum(unsigned char c) { | |
return isalnum(c); | |
} /* dns_isalnum() */ | |
-static DNS_INLINE _Bool dns_isspace(unsigned char c) { | |
+static inline _Bool dns_isspace(unsigned char c) { | |
return isspace(c); | |
} /* dns_isspace() */ | |
static int dns_poll(int fd, short events, int timeout) { | |
-/* For our usage in belle sip, we are called by the main loop when something is to read on the dns socket. | |
- * As a result there is no need to perform a blocking select. | |
-**/ | |
-#if 0 | |
fd_set rset, wset; | |
if (!events) | |
@@ -1118,7 +1104,6 @@ static int dns_poll(int fd, short events, int timeout) { | |
select(fd + 1, &rset, &wset, 0, (timeout >= 0)? &(struct timeval){ timeout, 0 } : NULL); | |
-#endif | |
return 0; | |
} /* dns_poll() */ | |
@@ -1273,13 +1258,13 @@ struct dns_buf { | |
size_t overflow; | |
}; /* struct dns_buf */ | |
-static DNS_INLINE size_t | |
+static inline size_t | |
dns_b_tell(struct dns_buf *b) | |
{ | |
return b->p - b->base; | |
} | |
-static DNS_INLINE dns_error_t | |
+static inline dns_error_t | |
dns_b_setoverflow(struct dns_buf *b, size_t n, dns_error_t error) | |
{ | |
b->overflow += n; | |
@@ -1317,13 +1302,13 @@ dns_b_pputc(struct dns_buf *b, unsigned char uc, size_t p) | |
return 0; | |
} | |
-static DNS_INLINE dns_error_t | |
+static inline dns_error_t | |
dns_b_put16(struct dns_buf *b, uint16_t u) | |
{ | |
return dns_b_putc(b, u >> 8), dns_b_putc(b, u >> 0); | |
} | |
-static DNS_INLINE dns_error_t | |
+static inline dns_error_t | |
dns_b_pput16(struct dns_buf *b, uint16_t u, size_t p) | |
{ | |
if (dns_b_pputc(b, u >> 8, p) || dns_b_pputc(b, u >> 0, p + 1)) | |
@@ -1332,7 +1317,7 @@ dns_b_pput16(struct dns_buf *b, uint16_t u, size_t p) | |
return 0; | |
} | |
-DNS_NOTUSED static DNS_INLINE dns_error_t | |
+DNS_NOTUSED static inline dns_error_t | |
dns_b_put32(struct dns_buf *b, uint32_t u) | |
{ | |
return dns_b_putc(b, u >> 24), dns_b_putc(b, u >> 16), | |
@@ -1359,7 +1344,7 @@ dns_b_puts(struct dns_buf *b, const void *src) | |
return dns_b_put(b, src, strlen(src)); | |
} | |
-DNS_NOTUSED static DNS_INLINE dns_error_t | |
+DNS_NOTUSED static inline dns_error_t | |
dns_b_fmtju(struct dns_buf *b, const uintmax_t u, const unsigned width) | |
{ | |
size_t digits, padding, overflow; | |
@@ -1408,7 +1393,7 @@ dns_b_popc(struct dns_buf *b) | |
b->p--; | |
} | |
-static DNS_INLINE const char * | |
+static inline const char * | |
dns_b_tolstring(struct dns_buf *b, size_t *n) | |
{ | |
if (b->p < b->pe) { | |
@@ -1431,14 +1416,14 @@ dns_b_tolstring(struct dns_buf *b, size_t *n) | |
} | |
} | |
-static DNS_INLINE const char * | |
+static inline const char * | |
dns_b_tostring(struct dns_buf *b) | |
{ | |
size_t n; | |
return dns_b_tolstring(b, &n); | |
} | |
-static DNS_INLINE size_t | |
+static inline size_t | |
dns_b_strlen(struct dns_buf *b) | |
{ | |
size_t n; | |
@@ -1446,7 +1431,7 @@ dns_b_strlen(struct dns_buf *b) | |
return n; | |
} | |
-static DNS_INLINE size_t | |
+static inline size_t | |
dns_b_strllen(struct dns_buf *b) | |
{ | |
size_t n = dns_b_strlen(b); | |
@@ -1461,7 +1446,7 @@ dns_b_from(const struct dns_buf *b, const void *src, size_t n) | |
return b; | |
} | |
-static DNS_INLINE int | |
+static inline int | |
dns_b_getc(const struct dns_buf *_b, const int eof) | |
{ | |
struct dns_buf *b = (struct dns_buf *)_b; | |
@@ -1472,7 +1457,7 @@ dns_b_getc(const struct dns_buf *_b, const int eof) | |
return *b->p++; | |
} | |
-static DNS_INLINE intmax_t | |
+static inline intmax_t | |
dns_b_get16(const struct dns_buf *b, const intmax_t eof) | |
{ | |
intmax_t n; | |
@@ -1483,7 +1468,7 @@ dns_b_get16(const struct dns_buf *b, const intmax_t eof) | |
return (!b->overflow)? n : eof; | |
} | |
-DNS_NOTUSED static DNS_INLINE intmax_t | |
+DNS_NOTUSED static inline intmax_t | |
dns_b_get32(const struct dns_buf *b, const intmax_t eof) | |
{ | |
intmax_t n; | |
@@ -1494,7 +1479,7 @@ dns_b_get32(const struct dns_buf *b, const intmax_t eof) | |
return (!b->overflow)? n : eof; | |
} | |
-static DNS_INLINE dns_error_t | |
+static inline dns_error_t | |
dns_b_move(struct dns_buf *dst, const struct dns_buf *_src, size_t n) | |
{ | |
struct dns_buf *src = (struct dns_buf *)_src; | |
@@ -2132,6 +2117,25 @@ invalid: | |
} /* dns_l_skip() */ | |
+static _Bool dns_d_isanchored(const void *_src, size_t len) { | |
+ const unsigned char *src = _src; | |
+ return len > 0 && src[len - 1] == '.'; | |
+} /* dns_d_isanchored() */ | |
+ | |
+ | |
+static size_t dns_d_ndots(const void *_src, size_t len) { | |
+ const unsigned char *p = _src, *pe = p + len; | |
+ size_t ndots = 0; | |
+ | |
+ while ((p = memchr(p, '.', pe - p))) { | |
+ ndots++; | |
+ p++; | |
+ } | |
+ | |
+ return ndots; | |
+} /* dns_d_ndots() */ | |
+ | |
+ | |
static size_t dns_d_trim(void *dst_, size_t lim, const void *src_, size_t len, int flags) { | |
unsigned char *dst = dst_; | |
const unsigned char *src = src_; | |
@@ -3691,8 +3695,11 @@ size_t dns_ptr_qname(void *dst, size_t lim, int af, void *addr) { | |
return dns_aaaa_arpa(dst, lim, addr); | |
case AF_INET: | |
return dns_a_arpa(dst, lim, addr); | |
- default: | |
- return dns_a_arpa(dst, lim, &(struct dns_a){ { INADDR_NONE } }); | |
+ default: { | |
+ struct dns_a a; | |
+ a.addr.s_addr = INADDR_NONE; | |
+ return dns_a_arpa(dst, lim, &a); | |
+ } | |
} | |
} /* dns_ptr_qname() */ | |
@@ -4161,22 +4168,6 @@ struct dns_hosts *dns_hosts_mortal(struct dns_hosts *hosts) { | |
return hosts; | |
} /* dns_hosts_mortal() */ | |
-#if defined(BELLE_SIP_WINDOWS_PHONE) || defined(BELLE_SIP_WINDOWS_UNIVERSAL) | |
-static int dns_hosts_add_localhost(struct dns_hosts *hosts) { | |
- struct dns_hosts_entry ent; | |
- memset(&ent, '\0', sizeof(ent)); | |
- ent.af = AF_INET; | |
- dns_inet_pton(ent.af, "127.0.0.1", &ent.addr); | |
- dns_d_anchor(ent.host, sizeof(ent.host), "localhost", 9); | |
- dns_hosts_insert(hosts, ent.af, &ent.addr, ent.host, 0); | |
- memset(&ent, '\0', sizeof(ent)); | |
- ent.af = AF_INET6; | |
- dns_inet_pton(ent.af, "::1", &ent.addr); | |
- dns_d_anchor(ent.host, sizeof(ent.host), "localhost", 9); | |
- dns_hosts_insert(hosts, ent.af, &ent.addr, ent.host, 1); | |
- return 0; | |
-} | |
-#endif | |
struct dns_hosts *dns_hosts_local(int *error_) { | |
struct dns_hosts *hosts; | |
@@ -4185,15 +4176,7 @@ struct dns_hosts *dns_hosts_local(int *error_) { | |
if (!(hosts = dns_hosts_open(&error))) | |
goto error; | |
-#ifdef _WIN32 | |
-#if defined(BELLE_SIP_WINDOWS_PHONE) || defined(BELLE_SIP_WINDOWS_UNIVERSAL) | |
- if ((error = dns_hosts_add_localhost(hosts))) | |
-#else | |
- if ((error = dns_hosts_loadpath(hosts, "C:/Windows/System32/drivers/etc/hosts"))) | |
-#endif | |
-#else | |
if ((error = dns_hosts_loadpath(hosts, "/etc/hosts"))) | |
-#endif | |
goto error; | |
return hosts; | |
@@ -4250,21 +4233,6 @@ int dns_hosts_loadfile(struct dns_hosts *hosts, FILE *fp) { | |
break; | |
case 1: | |
ent.af = (strchr(word, ':'))? AF_INET6 : AF_INET; | |
- // Normalize some strange IPv4 addresses, eg. 127.1 --> 127.0.0.1 | |
- if (ent.af == AF_INET) { | |
- int nbdots = 0; | |
- char *p = word; | |
- while ((p = strchr(p, '.')) != NULL) { | |
- nbdots++; | |
- p++; | |
- } | |
- if (nbdots == 1) { | |
- p = strchr(word, '.'); | |
- p++; | |
- memmove(p + 4, p, strlen(p)); | |
- memcpy(p, "0.0.", 4); | |
- } | |
- } | |
skip = (1 != dns_inet_pton(ent.af, word, &ent.addr)); | |
break; | |
@@ -4444,7 +4412,7 @@ error: | |
struct dns_resolv_conf *dns_resconf_open(int *error) { | |
static const struct dns_resolv_conf resconf_initializer = { | |
- .lookup = "fb", | |
+ .lookup = "bf", | |
.family = { AF_INET, AF_INET6 }, | |
.options = { .ndots = 1, .timeout = 5, .attempts = 2, .tcp = DNS_RESCONF_TCP_ENABLE, }, | |
.iface = { .ss_family = AF_INET }, | |
@@ -4644,8 +4612,7 @@ static enum dns_resconf_keyword dns_resconf_keyword(const char *word) { | |
int dns_resconf_pton(struct sockaddr_storage *ss, const char *src) { | |
struct { char buf[128], *p; } addr = { "", addr.buf }; | |
unsigned short port = 0; | |
- struct addrinfo *ai; | |
- int ch, af = AF_INET; | |
+ int ch, af = AF_INET, error; | |
while ((ch = *src++)) { | |
switch (ch) { | |
@@ -4677,11 +4644,13 @@ int dns_resconf_pton(struct sockaddr_storage *ss, const char *src) { | |
} /* while() */ | |
inet: | |
+ if ((error = dns_pton(af, addr.buf, dns_sa_addr(af, ss, NULL)))) | |
+ return error; | |
+ | |
port = (!port)? 53 : port; | |
- ai = bctbx_ip_address_to_addrinfo(af, SOCK_DGRAM, addr.buf, port); | |
- if (ai == NULL) return dns_soerr(); | |
- memcpy(ss, ai->ai_addr, ai->ai_addrlen); | |
- bctbx_freeaddrinfo(ai); | |
+ *dns_sa_port(af, ss) = htons(port); | |
+ dns_sa_family(ss) = af; | |
+ | |
return 0; | |
} /* dns_resconf_pton() */ | |
@@ -4896,120 +4865,6 @@ int dns_resconf_loadpath(struct dns_resolv_conf *resconf, const char *path) { | |
return error; | |
} /* dns_resconf_loadpath() */ | |
-#ifdef USE_FIXED_NAMESERVERS | |
-int dns_resconf_load_fixed_nameservers(struct dns_resolv_conf *resconf) { | |
- const char * const nameservers[] = { | |
- "8.8.8.8", | |
- "8.8.4.4" | |
- }; | |
- int i; | |
- int error = 0; | |
- | |
- for (i = 0; !error && (i < lengthof(nameservers)); i++) { | |
- error = dns_resconf_pton(&resconf->nameserver[i], nameservers[i]); | |
- } | |
- | |
- return error; | |
-} | |
-#endif /* USE_FIXED_NAMESERVERS */ | |
- | |
-#ifdef USE_STRUCT_RES_STATE_NAMESERVERS | |
-int dns_resconf_load_struct_res_state_nameservers(struct dns_resolv_conf *resconf) { | |
- int i; | |
- struct __res_state *rs = __res_get_state(); | |
- | |
- for (i = 0; i < rs->nscount; i++) { | |
- memcpy(&resconf->nameserver[i], (struct sockaddr_storage *)&rs->nsaddr_list[i], sizeof(struct sockaddr_in)); | |
- } | |
- | |
- return 0; | |
-} | |
-#endif /* USE_STRUCT_RES_STATE_NAMESERVERS */ | |
- | |
-#if defined(_WIN32) && !defined(USE_FIXED_NAMESERVERS) | |
-int dns_resconf_loadwin(struct dns_resolv_conf *resconf) { | |
- FIXED_INFO *pFixedInfo; | |
- ULONG ulOutBufLen; | |
- DWORD dwRetVal; | |
- IP_ADDR_STRING *pIPAddr; | |
- unsigned sa_count = 0; | |
- int error; | |
- | |
- pFixedInfo = (FIXED_INFO *) malloc(sizeof(FIXED_INFO)); | |
- if (pFixedInfo == NULL) { | |
- return -1; | |
- } | |
- ulOutBufLen = sizeof(FIXED_INFO); | |
- if (GetNetworkParams(pFixedInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { | |
- free(pFixedInfo); | |
- pFixedInfo = (FIXED_INFO *) malloc(ulOutBufLen); | |
- if (pFixedInfo == NULL) { | |
- return -1; | |
- } | |
- } | |
- | |
- if ((dwRetVal = GetNetworkParams(pFixedInfo, &ulOutBufLen)) == NO_ERROR) { | |
- memset(resconf->search, '\0', sizeof resconf->search); | |
- memcpy(resconf->search[0], pFixedInfo->DomainName, sizeof pFixedInfo->DomainName); | |
- pIPAddr = &pFixedInfo->DnsServerList; | |
- do { | |
- error = dns_resconf_pton(&resconf->nameserver[sa_count], pIPAddr->IpAddress.String); | |
- pIPAddr = pIPAddr->Next; | |
- sa_count++; | |
- } while (!error && pIPAddr && (sa_count < lengthof(resconf->nameserver))); | |
- } | |
- free(pFixedInfo); | |
- return 0; | |
-} | |
-#endif /* dns_resconf_loadwin() */ | |
- | |
-#ifdef ANDROID | |
-int dns_resconf_loadandroid(struct dns_resolv_conf *resconf) { | |
- char dns[PROP_VALUE_MAX]; | |
- char prop_name[PROP_NAME_MAX]; | |
- unsigned int sa_count = 0; | |
- int error = 0; | |
- int i; | |
- | |
- for (i = 1; !error && (i <= lengthof(resconf->nameserver)); i++) { | |
- snprintf(prop_name, sizeof(prop_name), "net.dns%d", i); | |
- if (__system_property_get(prop_name, dns) > 0) { | |
- if (dns_resconf_pton(&resconf->nameserver[sa_count], dns) == 0){ | |
- sa_count++; | |
- } | |
- } | |
- } | |
- | |
- if (sa_count == 0) { | |
- /* No net.dnsX property found, return an error. */ | |
- error = -1; | |
- } | |
- | |
- return error; | |
-} /* dns_resconf_loadandroid */ | |
-#endif | |
- | |
-#ifdef HAVE_RESINIT | |
-int dns_resconf_loadfromresolv(struct dns_resolv_conf *resconf) { | |
- struct __res_state res; | |
- union res_sockaddr_union addresses[3]; | |
- int i,error; | |
- | |
- if ((error = res_ninit(&res))) { | |
- return error; | |
- } | |
- | |
- error=res_getservers(&res,addresses,3); | |
- if (error>0){ | |
- for (i = 0; i<error ; i++ ) { | |
- memcpy(&resconf->nameserver[i],&addresses[i],sizeof(union res_sockaddr_union)); | |
- } | |
- error=0; | |
- }else error=-1; | |
- res_ndestroy(&res); | |
- return error; | |
-} | |
-#endif /*HAVE_RESINIT*/ | |
struct dns_anyconf { | |
char *token[16]; | |
@@ -5306,7 +5161,7 @@ int dns_nssconf_loadfile(struct dns_resolv_conf *resconf, FILE *fp) { | |
dns_anyconf_skip(" \t", fp); | |
if ('[' == dns_anyconf_peek(fp)) { | |
- dns_anyconf_skip("[ \t", fp); | |
+ dns_anyconf_skip("[! \t", fp); | |
while (dns_anyconf_scan(&cf, "%w_", fp, &error)) { | |
dns_anyconf_skip("= \t", fp); | |
@@ -5400,7 +5255,7 @@ struct dns_nssconf_source { | |
typedef unsigned dns_nssconf_i; | |
-static DNS_INLINE int dns_nssconf_peek(const struct dns_resolv_conf *resconf, dns_nssconf_i state) { | |
+static inline int dns_nssconf_peek(const struct dns_resolv_conf *resconf, dns_nssconf_i state) { | |
return (state < lengthof(resconf->lookup) && resconf->lookup[state])? resconf->lookup[state] : 0; | |
} /* dns_nssconf_peek() */ | |
@@ -5531,66 +5386,65 @@ int dns_resconf_setiface(struct dns_resolv_conf *resconf, const char *addr, unsi | |
} /* dns_resconf_setiface() */ | |
-size_t dns_resconf_search(void *dst, size_t lim, const void *qname, size_t qlen, struct dns_resolv_conf *resconf, dns_resconf_i_t *state) { | |
- unsigned srchi = 0xff & (*state >> 8); | |
- unsigned ndots = 0xff & (*state >> 16); | |
- unsigned len = 0; | |
- const char *qp, *qe; | |
- | |
- switch (0xff & *state) { | |
- case 0: | |
- qp = qname; | |
- qe = qp + qlen; | |
+#define DNS_SM_RESTORE \ | |
+ do { \ | |
+ pc = 0xff & (*state >> 0); \ | |
+ srchi = 0xff & (*state >> 8); \ | |
+ ndots = 0xff & (*state >> 16); \ | |
+ } while (0) | |
- while ((qp = memchr(qp, '.', qe - qp))) | |
- { ndots++; qp++; } | |
+#define DNS_SM_SAVE \ | |
+ do { \ | |
+ *state = ((0xff & pc) << 0) \ | |
+ | ((0xff & srchi) << 8) \ | |
+ | ((0xff & ndots) << 16); \ | |
+ } while (0) | |
- ++*state; | |
- | |
- if (ndots >= resconf->options.ndots) { | |
- len = dns_d_anchor(dst, lim, qname, qlen); | |
- | |
- break; | |
- } | |
- | |
- /* FALL THROUGH */ | |
- case 1: | |
- if (srchi < lengthof(resconf->search) && resconf->search[srchi][0] && strcmp(resconf->search[srchi], ".")) { | |
- len = dns_d_anchor(dst, lim, qname, qlen); | |
- len += dns_strlcpy((char *)dst + DNS_PP_MIN(len, lim), resconf->search[srchi], lim - DNS_PP_MIN(len, lim)); | |
- | |
- srchi++; | |
+size_t dns_resconf_search(void *dst, size_t lim, const void *qname, size_t qlen, struct dns_resolv_conf *resconf, dns_resconf_i_t *state) { | |
+ unsigned pc, srchi, ndots, len; | |
- break; | |
- } | |
+ DNS_SM_ENTER; | |
- ++*state; | |
+ /* if FQDN then return as-is and finish */ | |
+ if (dns_d_isanchored(qname, qlen)) { | |
+ len = dns_d_anchor(dst, lim, qname, qlen); | |
+ DNS_SM_YIELD(len); | |
+ DNS_SM_EXIT; | |
+ } | |
- /* FALL THROUGH */ | |
- case 2: | |
- ++*state; | |
+ ndots = dns_d_ndots(qname, qlen); | |
- if (ndots < resconf->options.ndots) { | |
- len = dns_d_anchor(dst, lim, qname, qlen); | |
+ if (ndots >= resconf->options.ndots) { | |
+ len = dns_d_anchor(dst, lim, qname, qlen); | |
+ DNS_SM_YIELD(len); | |
+ } | |
- break; | |
- } | |
+ while (srchi < lengthof(resconf->search) && resconf->search[srchi][0]) { | |
+ struct dns_buf buf = DNS_B_INTO(dst, lim); | |
+ const char *dn = resconf->search[srchi++]; | |
- /* FALL THROUGH */ | |
- default: | |
- break; | |
- } /* switch() */ | |
+ dns_b_put(&buf, qname, qlen); | |
+ dns_b_putc(&buf, '.'); | |
+ dns_b_puts(&buf, dn); | |
+ if (!dns_d_isanchored(dn, strlen(dn))) | |
+ dns_b_putc(&buf, '.'); | |
+ len = dns_b_strllen(&buf); | |
+ DNS_SM_YIELD(len); | |
+ } | |
- *state = ((0xff & *state) << 0) | |
- | ((0xff & srchi) << 8) | |
- | ((0xff & ndots) << 16); | |
+ if (ndots < resconf->options.ndots) { | |
+ len = dns_d_anchor(dst, lim, qname, qlen); | |
+ DNS_SM_YIELD(len); | |
+ } | |
- if (lim > 0) | |
- ((char *)dst)[DNS_PP_MIN(lim - 1, len)] = '\0'; | |
+ DNS_SM_LEAVE; | |
- return len; | |
+ return dns_strlcpy(dst, "", lim); | |
} /* dns_resconf_search() */ | |
+#undef DNS_SM_SAVE | |
+#undef DNS_SM_RESTORE | |
+ | |
int dns_resconf_dump(struct dns_resolv_conf *resconf, FILE *fp) { | |
unsigned i; | |
@@ -6090,11 +5944,12 @@ error: | |
} /* dns_hints_query() */ | |
-/** | |
- * Fill a whole sockaddr from the the nameservers' sockaddr contained in the hints. This is needed for scope link IPv6 nameservers. | |
-**/ | |
-static void dns_fill_sockaddr_from_hints(struct dns_hints *hints, int af, struct sockaddr *addr) { | |
+/** ugly hack to support specifying ports other than 53 in resolv.conf. */ | |
+static unsigned short dns_hints_port(struct dns_hints *hints, int af, void *addr) { | |
struct dns_hints_soa *soa; | |
+ void *addrsoa; | |
+ socklen_t addrlen; | |
+ unsigned short port; | |
unsigned i; | |
for (soa = hints->head; soa; soa = soa->next) { | |
@@ -6102,19 +5957,20 @@ static void dns_fill_sockaddr_from_hints(struct dns_hints *hints, int af, struct | |
if (af != soa->addrs[i].ss.ss_family) | |
continue; | |
- if ((af == AF_INET) | |
- && (memcmp(&((struct sockaddr_in *)&soa->addrs[i].ss)->sin_addr, &((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr)))) | |
+ if (!(addrsoa = dns_sa_addr(af, &soa->addrs[i].ss, &addrlen))) | |
continue; | |
- if ((af == AF_INET6) | |
- && (memcmp(&((struct sockaddr_in6 *)&soa->addrs[i].ss)->sin6_addr, &((struct sockaddr_in6 *)addr)->sin6_addr, sizeof(struct in6_addr)))) | |
+ if (memcmp(addr, addrsoa, addrlen)) | |
continue; | |
- memcpy(addr, &soa->addrs[i].ss, dns_af_len(af)); | |
- return; | |
+ port = *dns_sa_port(af, &soa->addrs[i].ss); | |
+ | |
+ return (port)? port : htons(53); | |
} | |
} | |
-} | |
+ | |
+ return htons(53); | |
+} /* dns_hints_port() */ | |
int dns_hints_dump(struct dns_hints *hints, FILE *fp) { | |
@@ -6283,11 +6139,6 @@ static int dns_socket(struct sockaddr *local, int type, int *error_) { | |
#endif | |
if (-1 == (fd = socket(local->sa_family, type|flags, 0))) | |
goto soerr; | |
- | |
- if (local->sa_family == AF_INET6){ | |
- int value=0; | |
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&value, sizeof(value)); | |
- } | |
#if defined F_SETFD && !HAVE_SOCK_CLOEXEC | |
if (-1 == fcntl(fd, F_SETFD, 1)) | |
@@ -6327,8 +6178,20 @@ static int dns_socket(struct sockaddr *local, int type, int *error_) { | |
* TODO: Optionally rely on the kernel to select a random port. | |
*/ | |
if (*dns_sa_port(local->sa_family, local) == 0) { | |
- /*bellesip: let the system find a random port*/ | |
- return fd; | |
+ struct sockaddr_storage tmp; | |
+ unsigned i, port; | |
+ | |
+ memcpy(&tmp, local, dns_sa_len(local)); | |
+ | |
+ for (i = 0; i < DNS_SO_MAXTRY; i++) { | |
+ port = 1025 + (dns_random() % 64510); | |
+ | |
+ *dns_sa_port(tmp.ss_family, &tmp) = htons(port); | |
+ | |
+ if (0 == bind(fd, (struct sockaddr *)&tmp, dns_sa_len(&tmp))) | |
+ return fd; | |
+ } | |
+ | |
/* NB: continue to next bind statement */ | |
} | |
@@ -6578,17 +6441,7 @@ int dns_so_submit(struct dns_socket *so, struct dns_packet *Q, struct sockaddr * | |
if ((error = dns_so_newanswer(so, (Q->memo.opt.maxudp)? Q->memo.opt.maxudp : DNS_SO_MINBUF))) | |
goto syerr; | |
- if (so->local.ss_family==AF_INET6 && host->sa_family==AF_INET){ | |
- socklen_t addrlen = sizeof(so->remote); | |
- uint32_t *addr=(uint32_t*)dns_sa_addr(AF_INET6,&so->remote, &addrlen); | |
- /* add v4mapping*/ | |
- so->remote.ss_family=AF_INET6; | |
- addr[0]=0; | |
- addr[1]=0; | |
- addr[2]=ntohl(0xffff); | |
- addr[3]=((struct sockaddr_in*)host)->sin_addr.s_addr; | |
- *dns_sa_port(AF_INET6,&so->remote)=((struct sockaddr_in*)host)->sin_port; | |
- }else memcpy(&so->remote, host, dns_sa_len(host)); | |
+ memcpy(&so->remote, host, dns_sa_len(host)); | |
so->query = Q; | |
so->qout = 0; | |
@@ -6735,7 +6588,6 @@ static int dns_so_tcp_recv(struct dns_socket *so) { | |
int dns_so_check(struct dns_socket *so) { | |
- struct sockaddr_storage reset_ss; | |
int error; | |
long n; | |
@@ -6744,8 +6596,6 @@ retry: | |
case DNS_SO_UDP_INIT: | |
so->state++; | |
case DNS_SO_UDP_CONN: | |
- memset(&reset_ss, 0, sizeof(reset_ss)); | |
- connect(so->udp, (struct sockaddr *)&reset_ss, sizeof(reset_ss)); // Reset the previous connection | |
if (0 != connect(so->udp, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote))) | |
goto soerr; | |
@@ -7055,8 +6905,6 @@ struct dns_resolver { | |
struct dns_rr_i hints_i, hints_j; | |
struct dns_rr hints_ns, ans_cname; | |
} stack[DNS_R_MAXDEPTH]; | |
- | |
- unsigned char search_enabled; | |
}; /* struct dns_resolver */ | |
@@ -7096,8 +6944,11 @@ struct dns_resolver *dns_res_open(struct dns_resolv_conf *resconf, struct dns_ho | |
* error from, say, dns_resconf_root(), and loading | |
* dns_resconf_local() by default would create undesirable surpises. | |
*/ | |
- if (!resconf || !hosts || !hints) | |
+ if (!resconf || !hosts || !hints) { | |
+ if (!*_error) | |
+ *_error = EINVAL; | |
goto _error; | |
+ } | |
if (!(R = malloc(sizeof *R))) | |
goto syerr; | |
@@ -7169,10 +7020,16 @@ static void dns_res_frame_destroy(struct dns_resolver *R, struct dns_res_frame * | |
static void dns_res_frame_init(struct dns_resolver *R, struct dns_res_frame *frame) { | |
memset(frame, '\0', sizeof *frame); | |
- if (!R->resconf->options.recurse) | |
- frame->qflags |= DNS_Q_RD; | |
- if (R->resconf->options.edns0) | |
- frame->qflags |= DNS_Q_EDNS0; | |
+ /* | |
+ * NB: Can be invoked from dns_res_open, before R->resconf has been | |
+ * initialized. | |
+ */ | |
+ if (R->resconf) { | |
+ if (!R->resconf->options.recurse) | |
+ frame->qflags |= DNS_Q_RD; | |
+ if (R->resconf->options.edns0) | |
+ frame->qflags |= DNS_Q_EDNS0; | |
+ } | |
} /* dns_res_frame_init() */ | |
@@ -7632,8 +7489,8 @@ exec: | |
dgoto(R->sp, DNS_R_FOREACH_NS); | |
case DNS_R_FOREACH_A: { | |
- struct sockaddr_storage saddr={0}; | |
- socklen_t saddr_len = sizeof(saddr); | |
+ struct dns_a a; | |
+ struct sockaddr_in sin; | |
/* | |
* NOTE: Iterator initialized in DNS_R_FOREACH_NS because | |
@@ -7644,7 +7501,7 @@ exec: | |
goto error; | |
F->hints_j.name = u.ns.host; | |
- F->hints_j.type = DNS_T_ALL; | |
+ F->hints_j.type = DNS_T_A; | |
F->hints_j.section = DNS_S_ALL & ~DNS_S_QD; | |
if (!dns_rr_grep(&rr, 1, &F->hints_j, F->hints, &error)) { | |
@@ -7654,28 +7511,24 @@ exec: | |
dgoto(R->sp, DNS_R_FOREACH_NS); | |
} | |
- saddr.ss_family = rr.type==DNS_T_AAAA ? AF_INET6 : AF_INET; | |
- if (saddr.ss_family==AF_INET){ | |
- if ((error = dns_a_parse((struct dns_a *)dns_sa_addr(saddr.ss_family, &saddr, &saddr_len), &rr, F->hints))) | |
- goto error; | |
- }else{ | |
- if ((error = dns_aaaa_parse((struct dns_aaaa *)dns_sa_addr(saddr.ss_family, &saddr, &saddr_len), &rr, F->hints))) | |
- goto error; | |
- } | |
+ if ((error = dns_a_parse(&a, &rr, F->hints))) | |
+ goto error; | |
- if (R->sp == 0) dns_fill_sockaddr_from_hints(R->hints, saddr.ss_family, (struct sockaddr *)&saddr); | |
- else *dns_sa_port(saddr.ss_family, &saddr) = htons(53); | |
+ sin.sin_family = AF_INET; | |
+ sin.sin_addr = a.addr; | |
+ if (R->sp == 0) | |
+ sin.sin_port = dns_hints_port(R->hints, AF_INET, &sin.sin_addr); | |
+ else | |
+ sin.sin_port = htons(53); | |
if (DNS_DEBUG) { | |
char addr[INET_ADDRSTRLEN + 1]; | |
- if (saddr.ss_family==AF_INET) | |
- dns_a_print(addr, sizeof addr, (struct dns_a *)dns_sa_addr(saddr.ss_family, &saddr, &saddr_len)); | |
- else dns_aaaa_print(addr, sizeof addr, (struct dns_aaaa *)dns_sa_addr(saddr.ss_family, &saddr, &saddr_len)); | |
+ dns_a_print(addr, sizeof addr, &a); | |
dns_header(F->query)->qid = dns_so_mkqid(&R->so); | |
DNS_SHOW(F->query, "ASKING: %s/%s @ DEPTH: %u)", u.ns.host, addr, R->sp); | |
} | |
- if ((error = dns_so_submit(&R->so, F->query, (struct sockaddr *)&saddr))) | |
+ if ((error = dns_so_submit(&R->so, F->query, (struct sockaddr *)&sin))) | |
goto error; | |
F->state++; | |
@@ -7684,14 +7537,9 @@ exec: | |
if (dns_so_elapsed(&R->so) >= dns_resconf_timeout(R->resconf)) | |
dgoto(R->sp, DNS_R_FOREACH_A); | |
- if ((error = dns_so_check(&R->so)) != 0){ | |
- if (error == DNS_ENETUNREACH | |
- || error == DNS_ECONNREFUSED | |
- || error == EINVAL | |
- || error == DNS_EHOSTUNREACH) { /* maybe even more case*/ | |
- dgoto(R->sp, DNS_R_FOREACH_A); | |
- }else goto error; | |
- } | |
+ if ((error = dns_so_check(&R->so))) | |
+ goto error; | |
+ | |
if (!dns_p_setptr(&F->answer, dns_so_fetch(&R->so, &error))) | |
goto error; | |
@@ -7740,10 +7588,7 @@ exec: | |
if (!R->nodata) | |
dns_p_movptr(&R->nodata, &F->answer); | |
- if (R->search_enabled) | |
- dgoto(R->sp, DNS_R_SEARCH); | |
- else | |
- dgoto(R->sp, DNS_R_FINISH); | |
+ dgoto(R->sp, DNS_R_SEARCH); | |
} | |
dns_rr_foreach(&rr, F->answer, .section = DNS_S_NS, .type = DNS_T_NS) { | |
@@ -8044,15 +7889,11 @@ int dns_res_check(struct dns_resolver *R) { | |
struct dns_packet *dns_res_fetch(struct dns_resolver *R, int *error) { | |
struct dns_packet *P = NULL; | |
- if (R->stack[0].state != DNS_R_DONE) { | |
- *error = DNS_EUNKNOWN; | |
- return NULL; | |
- } | |
+ if (R->stack[0].state != DNS_R_DONE) | |
+ return *error = DNS_EUNKNOWN, (void *)0; | |
- if (!dns_p_movptr(&P, &R->stack[0].answer)) { | |
- *error = DNS_EFETCHED; | |
- return NULL; | |
- } | |
+ if (!dns_p_movptr(&P, &R->stack[0].answer)) | |
+ return *error = DNS_EFETCHED, (void *)0; | |
return P; | |
} /* dns_res_fetch() */ | |
@@ -8113,10 +7954,6 @@ void dns_res_sethints(struct dns_resolver *res, struct dns_hints *hints) { | |
res->hints = hints; | |
} /* dns_res_sethints() */ | |
-void dns_res_enable_search(struct dns_resolver *res, unsigned char enable) { | |
- res->search_enabled = enable; | |
-} | |
- | |
/* | |
* A D D R I N F O R O U T I N E S | |
@@ -8133,6 +7970,7 @@ struct dns_addrinfo { | |
struct { | |
unsigned long todo; | |
+ int state; | |
int atype; | |
enum dns_type qtype; | |
} af; | |
@@ -8146,6 +7984,8 @@ struct dns_addrinfo { | |
char cname[DNS_D_MAXNAME + 1]; | |
char i_cname[DNS_D_MAXNAME + 1], g_cname[DNS_D_MAXNAME + 1]; | |
+ int g_depth; | |
+ | |
int state; | |
int found; | |
@@ -8156,46 +7996,78 @@ struct dns_addrinfo { | |
#define DNS_AI_AFMAX 32 | |
#define DNS_AI_AF2INDEX(af) (1UL << ((af) - 1)) | |
+static inline unsigned long dns_ai_af2index(int af) { | |
+ dns_static_assert(dns_same_type(unsigned long, DNS_AI_AF2INDEX(1), 1), "internal type mismatch"); | |
+ dns_static_assert(dns_same_type(unsigned long, ((struct dns_addrinfo *)0)->af.todo, 1), "internal type mismatch"); | |
+ | |
+ return (af > 0 && af <= DNS_AI_AFMAX)? DNS_AI_AF2INDEX(af) : 0; | |
+} | |
+ | |
+static int dns_ai_setaf(struct dns_addrinfo *ai, int af, int qtype) { | |
+ ai->af.atype = af; | |
+ ai->af.qtype = qtype; | |
+ | |
+ ai->af.todo &= ~dns_ai_af2index(af); | |
+ | |
+ return af; | |
+} /* dns_ai_setaf() */ | |
+ | |
+#define DNS_SM_RESTORE \ | |
+ do { pc = 0xff & (ai->af.state >> 0); i = 0xff & (ai->af.state >> 8); } while (0) | |
+#define DNS_SM_SAVE \ | |
+ do { ai->af.state = ((0xff & pc) << 0) | ((0xff & i) << 8); } while (0) | |
+ | |
static int dns_ai_nextaf(struct dns_addrinfo *ai) { | |
- int qtype = 0, atype = 0; | |
- unsigned i; | |
+ int i, pc; | |
dns_static_assert(AF_UNSPEC == 0, "AF_UNSPEC constant not 0"); | |
dns_static_assert(AF_INET <= DNS_AI_AFMAX, "AF_INET constant too large"); | |
dns_static_assert(AF_INET6 <= DNS_AI_AFMAX, "AF_INET6 constant too large"); | |
- for (i = 0; i < lengthof(ai->res->resconf->family); i++) { | |
- int af = ai->res->resconf->family[i]; | |
+ DNS_SM_ENTER; | |
- if (af == AF_UNSPEC) | |
- break; | |
- if (af < 0 || af > DNS_AI_AFMAX) | |
- continue; | |
- if (!(DNS_AI_AF2INDEX(af) & ai->af.todo)) | |
- continue; | |
+ if (ai->res) { | |
+ /* | |
+ * NB: On OpenBSD, at least, the types of entries resolved | |
+ * is the intersection of the /etc/resolv.conf families and | |
+ * the families permitted by the .ai_type hint. So if | |
+ * /etc/resolv.conf has "family inet4" and .ai_type | |
+ * is AF_INET6, then the address ::1 will return 0 entries | |
+ * even if AI_NUMERICHOST is specified in .ai_flags. | |
+ */ | |
+ while (i < (int)lengthof(ai->res->resconf->family)) { | |
+ int af = ai->res->resconf->family[i++]; | |
- switch (af) { | |
- case AF_INET: | |
- atype = AF_INET; | |
- qtype = DNS_T_A; | |
- goto update; | |
- case AF_INET6: | |
- atype = AF_INET6; | |
- qtype = DNS_T_AAAA; | |
- goto update; | |
+ if (af == AF_UNSPEC) { | |
+ DNS_SM_EXIT; | |
+ } else if (af < 0 || af > DNS_AI_AFMAX) { | |
+ continue; | |
+ } else if (!(DNS_AI_AF2INDEX(af) & ai->af.todo)) { | |
+ continue; | |
+ } else if (af == AF_INET) { | |
+ DNS_SM_YIELD(dns_ai_setaf(ai, AF_INET, DNS_T_A)); | |
+ } else if (af == AF_INET6) { | |
+ DNS_SM_YIELD(dns_ai_setaf(ai, AF_INET6, DNS_T_AAAA)); | |
+ } | |
} | |
+ } else { | |
+ /* | |
+ * NB: If we get here than AI_NUMERICFLAGS should be set and | |
+ * order shouldn't matter. | |
+ */ | |
+ if (DNS_AI_AF2INDEX(AF_INET) & ai->af.todo) | |
+ DNS_SM_YIELD(dns_ai_setaf(ai, AF_INET, DNS_T_A)); | |
+ if (DNS_AI_AF2INDEX(AF_INET6) & ai->af.todo) | |
+ DNS_SM_YIELD(dns_ai_setaf(ai, AF_INET6, DNS_T_AAAA)); | |
} | |
-update: | |
- ai->af.atype = atype; | |
- ai->af.qtype = qtype; | |
- | |
- if (atype) | |
- ai->af.todo &= ~DNS_AI_AF2INDEX(atype); | |
+ DNS_SM_LEAVE; | |
- return atype; | |
+ return dns_ai_setaf(ai, AF_UNSPEC, 0); | |
} /* dns_ai_nextaf() */ | |
+#undef DNS_SM_RESTORE | |
+#undef DNS_SM_SAVE | |
static enum dns_type dns_ai_qtype(struct dns_addrinfo *ai) { | |
return (ai->qtype)? ai->qtype : ai->af.qtype; | |
@@ -8229,7 +8101,7 @@ static dns_error_t dns_ai_parseport(unsigned short *port, const char *serv, cons | |
} /* dns_ai_parseport() */ | |
-struct dns_addrinfo *dns_ai_open(const char *host, const char *serv, enum dns_type qtype, const struct addrinfo *hints, struct dns_resolver *res, int *error_) { | |
+struct dns_addrinfo *dns_ai_open(const char *host, const char *serv, enum dns_type qtype, const struct addrinfo *hints, struct dns_resolver *res, int *_error) { | |
static const struct dns_addrinfo ai_initializer; | |
struct dns_addrinfo *ai; | |
int error; | |
@@ -8242,6 +8114,8 @@ struct dns_addrinfo *dns_ai_open(const char *host, const char *serv, enum dns_ty | |
* API function call, such as dns_res_stub(). Should change | |
* this semantic, but it's applied elsewhere, too. | |
*/ | |
+ if (!*_error) | |
+ *_error = EINVAL; | |
return NULL; | |
} | |
@@ -8264,6 +8138,12 @@ struct dns_addrinfo *dns_ai_open(const char *host, const char *serv, enum dns_ty | |
goto error; | |
ai->port = ai->qport; | |
+ /* | |
+ * FIXME: If an explicit A or AAAA record type conflicts with | |
+ * .ai_family or with resconf.family (i.e. AAAA specified but | |
+ * AF_INET6 not in interection of .ai_family and resconf.family), | |
+ * then what? | |
+ */ | |
switch (ai->qtype) { | |
case DNS_T_A: | |
ai->af.todo = DNS_AI_AF2INDEX(AF_INET); | |
@@ -8291,7 +8171,7 @@ struct dns_addrinfo *dns_ai_open(const char *host, const char *serv, enum dns_ty | |
syerr: | |
error = dns_syerr(); | |
error: | |
- *error_ = error; | |
+ *_error = error; | |
dns_ai_close(ai); | |
dns_res_close(res); | |
@@ -8381,6 +8261,7 @@ enum dns_ai_state { | |
DNS_AI_S_CHECK, | |
DNS_AI_S_FETCH, | |
DNS_AI_S_FOREACH_I, | |
+ DNS_AI_S_INIT_G, | |
DNS_AI_S_ITERATE_G, | |
DNS_AI_S_FOREACH_G, | |
DNS_AI_S_SUBMIT_G, | |
@@ -8503,6 +8384,10 @@ exec: | |
} /* switch() */ | |
ai->state++; | |
+ case DNS_AI_S_INIT_G: | |
+ ai->g_depth = 0; | |
+ | |
+ ai->state++; | |
case DNS_AI_S_ITERATE_G: | |
dns_strlcpy(ai->g_cname, ai->cname, sizeof ai->g_cname); | |
dns_rr_i_init(&ai->g, ai->glue); | |
@@ -8527,6 +8412,9 @@ exec: | |
/* skip if already queried */ | |
if (dns_rr_grep(&rr, 1, dns_rr_i_new(ai->glue, .section = DNS_S_QD, .name = ai->g.name, .type = ai->g.type), ai->glue, &error)) | |
dns_ai_goto(DNS_AI_S_FOREACH_I); | |
+ /* skip if we recursed (CNAME chains should have been handled in the resolver) */ | |
+ if (++ai->g_depth > 1) | |
+ dns_ai_goto(DNS_AI_S_FOREACH_I); | |
if ((error = dns_res_submit(ai->res, ai->g.name, ai->g.type, DNS_C_IN))) | |
return error; | |
diff --git a/src/dns.h b/src/dns.h | |
index d4b1dca..78d6402 100644 | |
--- a/src/dns.h | |
+++ b/src/dns.h | |
@@ -25,9 +25,7 @@ | |
*/ | |
#ifndef DNS_H | |
#define DNS_H | |
-#ifdef HAVE_CONFIG_H | |
-#include "config.h" | |
-#endif | |
+ | |
#include <stddef.h> /* size_t offsetof() */ | |
#include <stdio.h> /* FILE */ | |
@@ -77,7 +75,7 @@ | |
#define DNS_VENDOR "[email protected]" | |
-#define DNS_V_REL 0x20160608 | |
+#define DNS_V_REL 0x20161214 | |
#define DNS_V_ABI 0x20160608 | |
#define DNS_V_API 0x20160608 | |
@@ -537,7 +535,7 @@ struct dns_rr_i { | |
int follow; | |
- int (*sort)(struct dns_rr *, struct dns_rr *, struct dns_rr_i *, struct dns_packet *); | |
+ int (*sort)(); | |
unsigned args[2]; | |
struct { | |
@@ -563,9 +561,11 @@ DNS_PUBLIC struct dns_rr_i *dns_rr_i_init(struct dns_rr_i *, struct dns_packet * | |
DNS_PUBLIC unsigned dns_rr_grep(struct dns_rr *, unsigned, struct dns_rr_i *, struct dns_packet *, int *); | |
-#define dns_rr_foreach(rr, P, ...) \ | |
+#define dns_rr_foreach_(rr, P, ...) \ | |
for (struct dns_rr_i DNS_PP_XPASTE(i, __LINE__) = *dns_rr_i_new((P), __VA_ARGS__); dns_rr_grep((rr), 1, &DNS_PP_XPASTE(i, __LINE__), (P), &(int){ 0 }); ) | |
+#define dns_rr_foreach(...) dns_rr_foreach_(__VA_ARGS__) | |
+ | |
/* | |
* A R E S O U R C E R E C O R D | |
@@ -948,39 +948,16 @@ DNS_PUBLIC int dns_resconf_loadfile(struct dns_resolv_conf *, FILE *); | |
DNS_PUBLIC int dns_resconf_loadpath(struct dns_resolv_conf *, const char *); | |
-#ifdef USE_FIXED_NAMESERVERS | |
-int dns_resconf_load_fixed_nameservers(struct dns_resolv_conf *resconf); | |
-#endif /* USE_FIXED_NAMESERVERS */ | |
- | |
-#ifdef USE_STRUCT_RES_STATE_NAMESERVERS | |
-int dns_resconf_load_struct_res_state_nameservers(struct dns_resolv_conf *resconf); | |
-#endif /* USE_STRUCT_RES_STATE_NAMESERVERS */ | |
- | |
-#ifdef _WIN32 | |
-DNS_PUBLIC int dns_resconf_loadwin(struct dns_resolv_conf *); | |
-#endif | |
- | |
-#ifdef ANDROID | |
-DNS_PUBLIC int dns_resconf_loadandroid(struct dns_resolv_conf *resconf); | |
-#endif | |
- | |
-#ifdef HAVE_RESINIT | |
-DNS_PUBLIC int dns_resconf_loadfromresolv(struct dns_resolv_conf *resconf); | |
-#endif /*HAVE_RESINIT*/ | |
- | |
DNS_PUBLIC int dns_nssconf_loadfile(struct dns_resolv_conf *, FILE *); | |
DNS_PUBLIC int dns_nssconf_loadpath(struct dns_resolv_conf *, const char *); | |
-DNS_PUBLIC int dns_resconf_pton(struct sockaddr_storage *ss, const char *src); | |
- | |
DNS_PUBLIC int dns_resconf_dump(struct dns_resolv_conf *, FILE *); | |
DNS_PUBLIC int dns_nssconf_dump(struct dns_resolv_conf *, FILE *); | |
DNS_PUBLIC int dns_resconf_setiface(struct dns_resolv_conf *, const char *, unsigned short); | |
- | |
typedef unsigned long dns_resconf_i_t; | |
DNS_PUBLIC size_t dns_resconf_search(void *, size_t, const void *, size_t, struct dns_resolv_conf *, dns_resconf_i_t *); | |
@@ -1200,8 +1177,6 @@ DNS_PUBLIC const struct dns_stat *dns_res_stat(struct dns_resolver *); | |
DNS_PUBLIC void dns_res_sethints(struct dns_resolver *, struct dns_hints *); | |
-DNS_PUBLIC void dns_res_enable_search(struct dns_resolver *, unsigned char enable); | |
- | |
/* | |
* A D D R I N F O I N T E R F A C E | |
-- | |
2.11.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment