diff --git a/darling-resolver/resolver.c b/darling-resolver/resolver.c index f3ae33d..6fb6e9e 100644 --- a/darling-resolver/resolver.c +++ b/darling-resolver/resolver.c @@ -22,6 +22,33 @@ #include #include #include +#include +#include +#include + +/* res_query shares the global resolver's sockets. Concurrent lookups must + * own their resolver state so they cannot consume each other's replies. */ +static int +dr_query(const char *name, int dns_class, int type, unsigned char *answer, int length) +{ + struct __res_state state = {0}; + int result; + /* Riot's bundled downloader cannot use IPv6 CONNECT_TO addresses. + * Restrict this opt-in workaround to its CDN; keep other DNS unchanged. */ + const char *ipv4_only = getenv("RCLOL_CDN_IPV4_ONLY"); + size_t name_len = strlen(name); + const char suffix[] = ".riotcdn.net"; + if (type == ns_t_aaaa && ipv4_only && strcmp(ipv4_only, "1") == 0 && + name_len >= sizeof(suffix) - 1 && + strcasecmp(name + name_len - (sizeof(suffix) - 1), suffix) == 0) + return -1; + + if (res_ninit(&state) < 0) + return -1; + result = res_nquery(&state, name, dns_class, type, answer, length); + res_ndestroy(&state); + return result; +} static int dr_is_valid(si_mod_t *si, si_item_t *item) @@ -58,7 +85,7 @@ dr_hostbyname(si_mod_t *si, const char *name, int af, const char *interface, uin else return NULL; - l = res_query(name, ns_c_in, type, buf, sizeof(buf)); + l = dr_query(name, ns_c_in, type, buf, sizeof(buf)); if (l < 0) return NULL; @@ -144,7 +171,7 @@ dr_hostbyaddr(si_mod_t *si, const void *addr, int af, const char *interface, uin else return NULL; - l = res_query(ptr, ns_c_in, ns_t_ptr, buf, sizeof(buf)); + l = dr_query(ptr, ns_c_in, ns_t_ptr, buf, sizeof(buf)); if (l < 0) return NULL; @@ -240,7 +267,7 @@ dr_addrinfo(si_mod_t *si, const void *node, const void *serv, uint32_t family, u if (resolveV6) { - l = res_query((const char*) node, ns_c_in, ns_t_aaaa, buf, sizeof(buf)); + l = dr_query((const char*) node, ns_c_in, ns_t_aaaa, buf, sizeof(buf)); if (l < 0) goto after_v6; @@ -279,7 +306,7 @@ dr_addrinfo(si_mod_t *si, const void *node, const void *serv, uint32_t family, u after_v6: if (resolveV4) { - l = res_query((const char*) node, ns_c_in, ns_t_a, buf, sizeof(buf)); + l = dr_query((const char*) node, ns_c_in, ns_t_a, buf, sizeof(buf)); if (l < 0) goto after_v4; @@ -375,4 +402,3 @@ si_mod_t *si_module_static_darling(void) return (si_mod_t*)&si; } -