From 7bd3eb3b1ad4209ac4cf4b46f849213d46bc33aa Mon Sep 17 00:00:00 2001 From: David Timber Date: Mon, 17 Aug 2020 18:16:49 +0930 Subject: Employ pthsem ... * Use uint8_t array for hardcoded binary data * Add proone-ipaddr-arr to hardcode DoT servers * Convert X509 data * Brought back M68k and ARC archs just in case * Add CLOCK_REALTIME in prne_mbedtls_entropy_proc_src_f for more entropy * Remove installation of signal handlers. Use sigwait() instead * Bugfix: prne_rnd_anum_str() returned null characters * Add prne_dbgpf() and prne_dbgperr() * prne_assert(): put errno into a register so it's visible in the core dump --- src/resolv_worker.c | 1542 --------------------------------------------------- 1 file changed, 1542 deletions(-) delete mode 100644 src/resolv_worker.c (limited to 'src/resolv_worker.c') diff --git a/src/resolv_worker.c b/src/resolv_worker.c deleted file mode 100644 index 72c3cb0..0000000 --- a/src/resolv_worker.c +++ /dev/null @@ -1,1542 +0,0 @@ -#include "resolv_worker.h" -#include "util_rt.h" -#include "util_ct.h" -#include "llist.h" -#include "imap.h" -#include "iset.h" -#include "protocol.h" -#include "mbedtls.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -_Static_assert(sizeof(uint_fast16_t) <= sizeof(prne_imap_key_type_t), "prne_imap cannot contain uint_fast16_t"); - -#define OK_OR_ERR(v) if (v < 0) { goto ERR; } - -typedef enum { - RESOLV_WKR_STATE_OK, - RESOLV_WKR_STATE_FIN_CALLED, - RESOLV_WKR_STATE_FINALISED, -} resolv_wkr_state_t; - -typedef enum { - RESOLV_CTX_STATE_NONE, - RESOLV_CTX_STATE_CONN, - RESOLV_CTX_STATE_HNDSHK, - RESOLV_CTX_STATE_READY, - RESOLV_CTX_STATE_CLOSING, -} resolv_ctx_state_t; - -typedef struct { - prne_net_endpoint_t *arr; - size_t cnt; - size_t ptr; -} resolv_dnssrv_pool_t; - -typedef struct { - prne_resolv_wkr_ctx_t wkr; - prne_llist_entry_t *qlist_ent; - char *qname; - size_t qname_size; - int evtfd[2]; - prne_wkr_timeout_slot_pt to_slot; - uint_fast16_t qid; // 0 reserved - prne_resolv_fut_t fut; - prne_ipv_t ipv; - prne_resolv_query_type_t type; -} query_entry_t; - -struct prne_resolv_wkr_ctx { - int dnss_fd[2]; - int evtfd[2]; - size_t read_cnt_len; - size_t write_cnt_len; - prne_wkr_sched_req_t *wsr; - prne_wkr_timeout_slot_pt sckop_to_slot; - prne_wkr_timeout_slot_pt err_to_slot; - prne_wkr_pollfd_slot_pt evt_pfd_slot; - prne_wkr_pollfd_slot_pt sck_pfd_slot[2]; - int act_dns_fd; - resolv_dnssrv_pool_t dnssrv_4, dnssrv_6; - resolv_ctx_state_t ctx_state; - resolv_wkr_state_t wkr_state; - uint8_t write_buf[514]; - uint8_t read_buf[514]; - prne_llist_t qlist; - prne_imap_t qid_map; // uint16_t:q_ent(could be null) - struct { - mbedtls_ssl_config conf; - mbedtls_ssl_context ctx; - mbedtls_ctr_drbg_context *ctr_drbg; - } ssl; -}; - -#define DECL_CTX_PTR(p) prne_resolv_wkr_ctx_t ctx = (prne_resolv_wkr_ctx_t)p - -static const struct timespec RESOLV_RSRC_ERR_PAUSE = { 1, 0 }; // 1s -static const struct timespec RESOLV_CONN_ERR_PAUSE = { 0, 100000000 }; // 100ms -static const struct timespec RESOLV_QUERY_TIMEOUT = { 15, 0 }; // 15s -static const struct timespec RESOLV_SCK_OP_TIMEOUT = { 10, 0 }; // 10s -static const struct timespec RESOLV_SCK_IDLE_TIMEOUT = { 15, 0 }; // 15s -static const struct timespec RESOLV_SCK_CLOSE_TIMEOUT = { 1, 0 }; // 1s -static const size_t RESOLV_PIPELINE_SIZE = 4; - -static bool resolv_wkr_has_finalised (void *p) { - DECL_CTX_PTR(p); - return ctx->wkr_state == RESOLV_WKR_STATE_FINALISED; -} - -static int resolv_set_cmn_fd_opt (const int fd) { - return fcntl(fd, F_SETFL, O_NONBLOCK) == 0 ? fcntl(fd, F_SETFD, FD_CLOEXEC) : -1; -} - -static void resolv_free_q_ent (query_entry_t *q_ent) { - if (q_ent == NULL) { - return; - } - - prne_free(q_ent->qname); - prne_free_resolv_fut(&q_ent->fut); - prne_close(q_ent->evtfd[0]); - prne_close(q_ent->evtfd[1]); - prne_free_wkr_timeout_slot(q_ent->to_slot); - - prne_free(q_ent); -} - -static bool resolv_gen_qname (const char *name, char **out, size_t *out_size) { - size_t len = prne_nstrlen(name); - char *ptr = (char*)name, *delim; - char *end = ptr + len; - size_t label_size; - char *ret_ptr; - size_t ret_size; - - if (len == 0) { - errno = EINVAL; - return false; - } - if (name[len - 1] != '.') { - len += 1; - } - if (len > 255) { - errno = EINVAL; - return false; - } - for (; *name != 0; name += 1) { - if (((uint_fast8_t)*name & 0xC0) == 0xC0) { - errno = EINVAL; - return false; - } - } - - ret_ptr = prne_alloc_str(len); - if (ret_ptr == NULL) { - return false; - } - - ret_size = 0; - while (ptr < end) { - delim = strchr(ptr, '.'); - if (delim == NULL) { - delim = strchr(ptr, 0); - } - - label_size = delim - ptr; - if (label_size == 0 || label_size > 63) { - errno = EINVAL; - goto ERR; - } - - ret_ptr[ret_size] = (uint8_t)label_size; - memcpy(ret_ptr + ret_size + 1, ptr, label_size); - ret_size += 1 + label_size; - ptr = delim + 1; - } - ret_ptr[ret_size] = 0; - ret_size += 1; - - *out = prne_realloc(ret_ptr, 1, ret_size); - if (*out == NULL) { - *out = ret_ptr; - } - *out_size = ret_size; - - return true; -ERR: - prne_free(ret_ptr); - return false; -} - -char *resolv_qname_tostr (const char *qname) { - char *ret, *p, *end; - const size_t qname_size = strlen(qname) + 1; - size_t label_len; - - ret = p = (char*)prne_malloc(1, qname_size); - if (p == NULL) { - return NULL; - } - memcpy(p, qname, qname_size); - end = p + qname_size; - - while (p < end) { - label_len = *p; - if (label_len == 0) { - break; - } - else if (p + label_len > end) { - goto ERR; - } - - memmove(p, p + 1, label_len); - p[label_len] = '.'; - p += label_len + 1; - } - - return ret; -ERR: - prne_free(ret); - return NULL; -} - -static bool resolv_qq (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_prm_t *out, const struct timespec *timeout, query_entry_t **ny_q_ent) { - query_entry_t *q_ent = NULL; - - if (resolv_wkr_has_finalised(wkr)) { - errno = ECANCELED; - return false; - } - - q_ent = (query_entry_t*)prne_malloc(sizeof(query_entry_t), 1); - if (q_ent == NULL) { - goto ERR; - } - q_ent->wkr = wkr; - q_ent->qlist_ent = NULL; - q_ent->qname = NULL; - q_ent->qname_size = 0; - q_ent->evtfd[0] = q_ent->evtfd[1] = -1; - q_ent->to_slot = NULL; - q_ent->qid = 0; - q_ent->ipv = PRNE_IPV_NONE; - prne_init_resolv_fut(&q_ent->fut); - - if (!resolv_gen_qname(name, &q_ent->qname, &q_ent->qname_size)) { - goto ERR; - } - - q_ent->qlist_ent = prne_llist_append(&wkr->qlist, q_ent); - if (q_ent->qlist_ent == NULL) { - goto ERR; - } - - OK_OR_ERR(pipe(q_ent->evtfd)); - prne_set_pipe_size(q_ent->evtfd[0], 1); - OK_OR_ERR(resolv_set_cmn_fd_opt(q_ent->evtfd[0])); - OK_OR_ERR(resolv_set_cmn_fd_opt(q_ent->evtfd[1])); - - if (write(wkr->evtfd[1], &q_ent, 1) < 0) { - prne_die_not_nonblock_err(); - } - - q_ent->to_slot = prne_alloc_wkr_timeout_slot(wkr->wsr); - if (q_ent == NULL) { - goto ERR; - } - q_ent->to_slot->active = true; - q_ent->to_slot->dur = RESOLV_QUERY_TIMEOUT; - - out->ctx = q_ent; - out->fut = &q_ent->fut; - out->evtfd = q_ent->evtfd[0]; - *ny_q_ent = q_ent; - - return true; -ERR: - if (q_ent != NULL) { - prne_llist_erase(&wkr->qlist, q_ent->qlist_ent); - prne_free(q_ent->qname); - prne_close(q_ent->evtfd[0]); - prne_close(q_ent->evtfd[1]); - - prne_free(q_ent); - } - - return false; -} - -static void resolv_disown_qent (query_entry_t *qent) { - uint8_t rubbish = 0; - - prne_free_wkr_timeout_slot(qent->to_slot); - qent->to_slot = NULL; - qent->wkr = NULL; - qent->qlist_ent = NULL; - qent->qid = 0; - - if (write(qent->evtfd[1], &rubbish, 1) < 0) { - prne_die_not_nonblock_err(); - } -} - -#if 0 -static void resolv_disown_all_qent (prne_resolv_wkr_ctx_t ctx) { - query_entry_t *qent; - prne_llist_entry_t *cur; - size_t i; - - cur = ctx->qlist.head; - while (cur != NULL) { - qent = (query_entry_t*)cur->element; - qent->fut.qr = PRNE_RESOLV_QR_FIN; - resolv_disown_qent(qent); - cur = cur->next; - } - - for (i = 0; i < ctx->qid_map.size; i += 1) { - qent = (query_entry_t*)ctx->qid_map.tbl[i].val; - qent->fut.qr = PRNE_RESOLV_QR_FIN; - resolv_disown_qent(qent); - } - - prne_llist_clear(&ctx->qlist); - prne_imap_clear(&ctx->qid_map); -} -#endif - -static size_t resolv_next_pool_ptr (prne_resolv_wkr_ctx_t ctx, const size_t cnt) { - size_t ret = 0; - - if (mbedtls_ctr_drbg_random(ctx->ssl.ctr_drbg, (unsigned char*)&ret, sizeof(size_t)) != 0) { - abort(); - } - return ret % cnt; -} - -static uint16_t resolv_next_qid (prne_resolv_wkr_ctx_t ctx) { - uint16_t i, ret; - - for (i = 0; i < UINT16_MAX; i += 1) { - if (mbedtls_ctr_drbg_random(ctx->ssl.ctr_drbg, (unsigned char*)&ret, sizeof(uint16_t)) != 0) { - abort(); - } - ret = (ret % UINT16_MAX) + 1; - if (prne_imap_lookup(&ctx->qid_map, ret) == NULL) { - return ret; - } - } - - return 0; -} - -static void resolv_close_sck (prne_resolv_wkr_ctx_t ctx, const struct timespec *pause, bool change_srvr) { - size_t i; - query_entry_t *qent; - prne_llist_entry_t *lent; - - // ctx->qid_map -> ctx->qlist - for (i = 0; i < ctx->qid_map.size; i += 1) { - qent = (query_entry_t*)ctx->qid_map.tbl[i].val; - if (qent == NULL) { - continue; - } - - lent = prne_llist_append(&ctx->qlist, qent); - if (lent == NULL) { - qent->fut.qr = PRNE_RESOLV_QR_ERR; - qent->fut.err = errno; - resolv_disown_qent(qent); - } - else { - qent->qid = 0; - qent->qlist_ent = lent; - } - } - prne_imap_clear(&ctx->qid_map); - - prne_shutdown(ctx->dnss_fd[0], SHUT_RDWR); - prne_shutdown(ctx->dnss_fd[1], SHUT_RDWR); - prne_shutdown(ctx->act_dns_fd, SHUT_RDWR); - prne_close(ctx->dnss_fd[0]); - prne_close(ctx->dnss_fd[1]); - prne_close(ctx->act_dns_fd); - ctx->dnss_fd[0] = ctx->dnss_fd[1] = ctx->act_dns_fd = -1; - ctx->read_cnt_len = 0; - ctx->write_cnt_len = 0; - ctx->sckop_to_slot->active = false; - ctx->sck_pfd_slot[0]->pfd.fd = ctx->sck_pfd_slot[1]->pfd.fd = -1; - ctx->ctx_state = RESOLV_CTX_STATE_NONE; - mbedtls_ssl_free(&ctx->ssl.ctx); - mbedtls_ssl_init(&ctx->ssl.ctx); - - if (pause != NULL) { - ctx->err_to_slot->active = true; - ctx->err_to_slot->dur = *pause; - } - if (change_srvr) { - ctx->dnssrv_4.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_4.cnt); - ctx->dnssrv_6.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_6.cnt); - } -} - -static bool resolv_ensure_conn (prne_resolv_wkr_ctx_t ctx) { - size_t i; - - switch (ctx->ctx_state) { - case RESOLV_CTX_STATE_NONE: { - int optval = 1; - - ctx->dnss_fd[0] = socket(AF_INET6, SOCK_STREAM, 0); - ctx->dnss_fd[1] = socket(AF_INET, SOCK_STREAM, 0); - if (ctx->dnss_fd[0] >= 0) { - setsockopt(ctx->dnss_fd[0], SOL_TCP, TCP_NODELAY, &optval, sizeof(int)); - if (resolv_set_cmn_fd_opt(ctx->dnss_fd[0]) < 0) { - prne_close(ctx->dnss_fd[0]); - ctx->dnss_fd[0] = -1; - } - else { - struct sockaddr_in6 addr; - - memzero(&addr, sizeof(addr)); - prne_net_ep_tosin6(ctx->dnssrv_6.arr + ctx->dnssrv_6.ptr, &addr); - connect(ctx->dnss_fd[0], (const struct sockaddr*)&addr, sizeof(addr)); - } - } - if (ctx->dnss_fd[1] >= 0) { - setsockopt(ctx->dnss_fd[1], SOL_TCP, TCP_NODELAY, &optval, sizeof(int)); - if (resolv_set_cmn_fd_opt(ctx->dnss_fd[1]) < 0) { - prne_close(ctx->dnss_fd[1]); - ctx->dnss_fd[1] = -1; - } - else { - struct sockaddr_in addr; - - memzero(&addr, sizeof(addr)); - prne_net_ep_tosin4(ctx->dnssrv_4.arr + ctx->dnssrv_4.ptr, &addr); - connect(ctx->dnss_fd[1], (const struct sockaddr*)&addr, sizeof(addr)); - } - } - - if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) { - ctx->err_to_slot->active = true; - ctx->err_to_slot->dur = RESOLV_RSRC_ERR_PAUSE; - ctx->sckop_to_slot->active = false; - } - else { - ctx->sckop_to_slot->active = true; - ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT; - for (i = 0; i < 2; i += 1) { - ctx->sck_pfd_slot[i]->pfd.fd = ctx->dnss_fd[i]; - ctx->sck_pfd_slot[i]->pfd.events = POLLIN | POLLOUT; - } - - ctx->ctx_state = RESOLV_CTX_STATE_CONN; - } - - return false; - } - case RESOLV_CTX_STATE_CONN: { - int optval; - socklen_t optval_len; - - for (i = 0; i < 2; i += 1) { - assert(ctx->sck_pfd_slot[i]->pfd.fd == ctx->dnss_fd[i]); - if (ctx->sck_pfd_slot[i]->pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) { - prne_close(ctx->dnss_fd[i]); - ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1; - } - } - if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) { - ctx->err_to_slot->active = true; - ctx->err_to_slot->dur = RESOLV_CONN_ERR_PAUSE; - ctx->sckop_to_slot->active = false; - ctx->ctx_state = RESOLV_CTX_STATE_NONE; - - return false; - } - - for (i = 0; i < 2; i += 1) { - if (ctx->sck_pfd_slot[i]->pfd.fd < 0) { - continue; - } - - if (ctx->sck_pfd_slot[i]->pfd.revents & (POLLIN | POLLOUT)) { - optval_len = sizeof(optval); - if (getsockopt(ctx->sck_pfd_slot[i]->pfd.fd, SOL_SOCKET, SO_ERROR, &optval, &optval_len) < 0 || optval != 0) { - prne_close(ctx->dnss_fd[i]); - ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1; - } - else { - ctx->act_dns_fd = ctx->dnss_fd[i]; - ctx->dnss_fd[i] = -1; - break; - } - } - } - - if (ctx->act_dns_fd >= 0) { - for (i = 0; i < 2; i += 1) { - prne_close(ctx->dnss_fd[i]); - ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1; - } - - if (mbedtls_ssl_setup(&ctx->ssl.ctx, &ctx->ssl.conf) != 0 || mbedtls_ssl_set_hostname(&ctx->ssl.ctx, NULL) != 0) { - resolv_close_sck(ctx, &RESOLV_RSRC_ERR_PAUSE, false); - return false; - } - mbedtls_ssl_set_bio(&ctx->ssl.ctx, &ctx->act_dns_fd, prne_mbedtls_ssl_send_cb, prne_mbedtls_ssl_recv_cb, NULL); - - ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd; - ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT; - ctx->sckop_to_slot->active = true; - ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT; - ctx->ctx_state = RESOLV_CTX_STATE_HNDSHK; - } - else if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - } - - return false; - } - case RESOLV_CTX_STATE_HNDSHK: { - assert(ctx->sck_pfd_slot[0]->pfd.fd == ctx->act_dns_fd && ctx->act_dns_fd >= 0); - - if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLNVAL | POLLHUP)) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - - return false; - } - if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLIN | POLLOUT)) { - switch (mbedtls_ssl_handshake(&ctx->ssl.ctx)) { - case MBEDTLS_ERR_SSL_WANT_READ: - ctx->sck_pfd_slot[0]->pfd.events = POLLIN; - break; - case MBEDTLS_ERR_SSL_WANT_WRITE: - ctx->sck_pfd_slot[0]->pfd.events = POLLOUT; - break; - case 0: - ctx->sck_pfd_slot[0]->pfd.events = POLLIN; - ctx->sckop_to_slot->active = true; - ctx->sckop_to_slot->dur = RESOLV_SCK_IDLE_TIMEOUT; - ctx->ctx_state = RESOLV_CTX_STATE_READY; - - return true; - default: - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - - return false; - } - } - - return false; - } - case RESOLV_CTX_STATE_READY: - return true; - } - -#ifdef PRNE_DEBUG - abort(); -#endif - return false; -} - -static const uint8_t* resolv_index_labels (prne_imap_t *map, const uint8_t *start, const uint8_t *end, const uint8_t *p, prne_resolv_qr_t *qr, int *err) { - uint16_t ptr; - const prne_imap_tuple_t *tpl; - - assert(qr != NULL); - assert(err != NULL); - if (p >= end) { - *qr = PRNE_RESOLV_QR_PRO_ERR; - return NULL; - } - - while (*p != 0 && p < end) { - if ((p[0] & 0xC0) == 0xC0) { - // met pointer. don't go further. - ptr = ((uint16_t)p[0] << 8) | (uint16_t)p[1]; - tpl = prne_imap_lookup(map, ptr); - if (tpl == NULL) { - *qr = PRNE_RESOLV_QR_ERR; - *err = errno; - return NULL; - } - return p + 2; - } - else if (*p > 63) { - *qr = PRNE_RESOLV_QR_PRO_ERR; - return NULL; - } - else { - // index the label - ptr = (uint16_t)(p - start) | 0xC000; - if (prne_imap_insert(map, ptr, (void*)p) == NULL) { - *qr = PRNE_RESOLV_QR_ERR; - *err = errno; - return NULL; - } - p += *p + 1; - } - } - - return p + 1; -} - -static int resolv_mapped_qname_cmp (prne_imap_t *map, const uint8_t *a, const uint8_t *b, prne_resolv_qr_t *qr) { - const uint8_t *p[2] = { a, b }; - size_t i; - uint16_t ptr; - const prne_imap_tuple_t *tpl; - int ret; - - - assert(qr != NULL); - - do { - // deref the pointers - for (i = 0; i < 2; i += 1) { - if ((p[i][0] & 0xC0) == 0xC0) { - ptr = ((uint16_t)p[i][0] << 8) | (uint16_t)p[i][1]; - tpl = prne_imap_lookup(map, ptr); - if (tpl == NULL) { - ret = -1; - *qr = PRNE_RESOLV_QR_PRO_ERR; - break; - } - p[i] = (const uint8_t*)tpl->val; - } - } - - if (*p[0] != *p[1]) { - ret = 0; - break; - } - if (*p[0] == 0 || *p[1] == 0) { - ret = 1; - break; - } - - p[0] += 1; - p[1] += 1; - } while (true); - - return ret; -} - -static bool resolv_proc_dns_msg (prne_resolv_wkr_ctx_t ctx, const uint8_t *data, const size_t len, bool *err_flag) { - typedef struct { - const uint8_t *name; - const uint8_t *data; - uint32_t ttl; - uint16_t rtype; - uint16_t rclass; - uint16_t data_len; - } rr_tuple_t; - rr_tuple_t *tpl; - prne_resolv_qr_t qr; - int err = 0, cmp_ret; - uint_fast16_t qid, status, ancount, ttype; - prne_imap_t ptr_map; // val in msg(uint8_t):(uint8_t*)real addr - prne_llist_t rr_list, ret_list; - prne_iset_t alias_set; - prne_llist_entry_t *cur; - query_entry_t *qent; - const uint8_t *qname, *alias, *end = data + len, *p, *rname; - size_t i, j, loop_cnt; - bool ret; - - if (len < 12) { - *err_flag = true; - return false; - } - *err_flag = false; - - qr = PRNE_RESOLV_QR_NONE; - status = 0; - ttype = 0; - prne_init_imap(&ptr_map); - prne_init_llist(&rr_list); - prne_init_llist(&ret_list); - prne_init_iset(&alias_set); - - // ID - { - const prne_imap_tuple_t *tpl; - - qid = ((uint16_t)data[0] << 8) | (uint16_t)data[1]; - tpl = prne_imap_lookup(&ctx->qid_map, qid); - ret = tpl != NULL; - if (ret) { - qent = (query_entry_t*)tpl->val; - if (qent != NULL) { - switch (qent->type) { - case PRNE_RESOLV_QT_A: ttype = 1; break; - case PRNE_RESOLV_QT_AAAA: ttype = 28; break; - case PRNE_RESOLV_QT_TXT: ttype = 16; break; - default: abort(); - } - } - } - else { - qent = NULL; - } - prne_imap_erase(&ctx->qid_map, qid); - } - // QR - if ((data[2] & 0x80) == 0) { - qr = PRNE_RESOLV_QR_PRO_ERR; - *err_flag = true; - goto END; - } - // Opcode - if ((data[2] & 0x78) != 0) { - qr = PRNE_RESOLV_QR_PRO_ERR; - *err_flag = true; - goto END; - } - // AA - don't care - // RCODE - status = data[3] & 0x0F; - if (status != 0) { - qr = PRNE_RESOLV_QR_STATUS; - goto END; - } - // TC - if ((data[2] & 0x02) != 0) { - qr = PRNE_RESOLV_QR_IMPL; - goto END; - } - // QDCOUNT - if ((((uint_fast16_t)data[4] << 8) | (uint_fast16_t)data[5]) != 1) { - qr = PRNE_RESOLV_QR_PRO_ERR; - *err_flag = true; - goto END; - } - // ANCOUNT - ancount = ((uint_fast16_t)data[6] << 8) | (uint_fast16_t)data[7]; - - // decode question - if (len < 12 + 1 + 4) { // min msg with 1 QDCOUNT length - qr = PRNE_RESOLV_QR_PRO_ERR; - *err_flag = true; - goto END; - } - qname = data + 12; - p = resolv_index_labels(&ptr_map, data, end, (const uint8_t*)qname, &qr, &err); - if (p == NULL) { - goto END; - } - if ((size_t)(p - data + 4) > len) { - qr = PRNE_RESOLV_QR_PRO_ERR; - *err_flag = true; - goto END; - } - if (qent != NULL && strcmp((const char*)qname, qent->qname) != 0) { - qr = PRNE_RESOLV_QR_PRO_ERR; - *err_flag = true; - goto END; - } - if ((ttype != 0 && ttype != (((uint_fast16_t)p[0] << 8) | (uint_fast16_t)p[1])) || - (((uint_fast16_t)p[2] << 8) | (uint_fast16_t)p[3]) != 1) { - qr = PRNE_RESOLV_QR_PRO_ERR; - *err_flag = true; - goto END; - } - - p += 4; - // decode answer RRs - for (i = 0; i < ancount; i += 1) { - tpl = prne_malloc(sizeof(rr_tuple_t), 1); - if (tpl == NULL) { - err = errno; - qr = PRNE_RESOLV_QR_ERR; - goto END; - } - if (prne_llist_append(&rr_list, tpl) == NULL) { - prne_free(tpl); - err = errno; - qr = PRNE_RESOLV_QR_ERR; - goto END; - } - - tpl->name = p; - p = resolv_index_labels(&ptr_map, data, end, p, &qr, &err); - if (p == NULL) { - goto END; - } - if (p >= end || end - p < 10) { - qr = PRNE_RESOLV_QR_PRO_ERR; - *err_flag = true; - goto END; - } - tpl->rtype = ((uint_fast16_t)p[0] << 8) | (uint_fast16_t)p[1]; - tpl->rclass = ((uint_fast16_t)p[2] << 8) | (uint_fast16_t)p[3]; - tpl->ttl = ((uint_fast32_t)p[4]) | ((uint_fast32_t)p[5]) | ((uint_fast32_t)p[6]) | ((uint_fast32_t)p[7]); - tpl->data_len = ((uint_fast16_t)p[8] << 8) | (uint_fast16_t)p[9]; - rname = tpl->data = p + 10; - - switch (tpl->rtype) { - case PRNE_RESOLV_RTYPE_SOA: - loop_cnt = 2; - break; - case PRNE_RESOLV_RTYPE_CNAME: - case PRNE_RESOLV_RTYPE_MX: - case PRNE_RESOLV_RTYPE_NS: - case PRNE_RESOLV_RTYPE_PTR: - loop_cnt = 1; - break; - default: - loop_cnt = 0; - } - for (j = 0; j < loop_cnt; j += 1) { - rname = resolv_index_labels(&ptr_map, data, tpl->data + tpl->data_len, rname, &qr, &err); - if (rname == NULL) { - goto END; - } - } - - p += 10 + tpl->data_len; - } - - // resolve cname - alias = qname; - if (!prne_iset_insert(&alias_set, (prne_iset_val_t)alias)) { - qr = PRNE_RESOLV_QR_ERR; - err = errno; - goto END; - } -QNAME_START: - cur = rr_list.head; - while (cur != NULL) { - tpl = (rr_tuple_t*)cur->element; - - if (tpl->rtype == PRNE_RESOLV_RTYPE_CNAME) { - cmp_ret = resolv_mapped_qname_cmp(&ptr_map, tpl->name, alias, &qr); - if (cmp_ret < 0) { - goto END; - } - if (cmp_ret) { - if (prne_iset_lookup(&alias_set, (prne_iset_val_t)tpl->data)) { - qr = PRNE_RESOLV_QR_PRO_ERR; - goto END; - } - if (!prne_iset_insert(&alias_set, (prne_iset_val_t)tpl->data)) { - qr = PRNE_RESOLV_QR_ERR; - err = errno; - goto END; - } - alias = tpl->data; - goto QNAME_START; - } - } - - cur = cur->next; - } - - // index the selected(alias) resources - cur = rr_list.head; - while (cur != NULL) { - tpl = (rr_tuple_t*)cur->element; - - cmp_ret = resolv_mapped_qname_cmp(&ptr_map, tpl->name, alias, &qr); - if (cmp_ret < 0) { - goto END; - } - if (cmp_ret && ttype == tpl->rtype) { - if (prne_llist_append(&ret_list, tpl) == NULL) { - qr = PRNE_RESOLV_QR_ERR; - err = errno; - goto END; - } - } - - cur = cur->next; - } - - // return data - if (ret_list.size > 0 && qent != NULL) { - prne_llist_entry_t *cur; - rr_tuple_t *tpl; - - qent->fut.rr = (prne_resolv_rr_t*)prne_malloc(sizeof(prne_resolv_rr_t), ret_list.size); - if (qent->fut.rr == NULL) { - qr = PRNE_RESOLV_QR_ERR; - err = errno; - goto END; - } - qent->fut.rr_cnt = ret_list.size; - for (i = 0; i < qent->fut.rr_cnt; i += 1) { - prne_init_resolv_rr(qent->fut.rr + i); - } - - i = 0; - cur = ret_list.head; - while (cur != NULL) { - tpl = (rr_tuple_t*)cur->element; - - qent->fut.rr[i].rr_class = tpl->rclass; - qent->fut.rr[i].rr_type = tpl->rtype; - qent->fut.rr[i].rr_ttl = tpl->ttl; - if (tpl->data_len > 0) { - if ((qent->fut.rr[i].name = resolv_qname_tostr(qent->qname)) == NULL || - (qent->fut.rr[i].rd_data = (uint8_t*)prne_malloc(1, tpl->data_len)) == NULL) { - qr = PRNE_RESOLV_QR_ERR; - err = errno; - goto END; - } - qent->fut.rr[i].rd_len = tpl->data_len; - memcpy(qent->fut.rr[i].rd_data, tpl->data, tpl->data_len); - } - else { - qent->fut.rr[i].rd_data = NULL; - qent->fut.rr[i].rd_len = 0; - } - - i += 1; - cur = cur->next; - } - } - - qr = PRNE_RESOLV_QR_OK; - -END: - cur = rr_list.head; - while (cur != NULL) { - prne_free(cur->element); - cur = cur->next; - } - prne_free_llist(&rr_list); - prne_free_llist(&ret_list); - prne_free_imap(&ptr_map); - prne_free_iset(&alias_set); - if (qent != NULL) { - if (qr != PRNE_RESOLV_QR_OK) { - for (i = 0; i < qent->fut.rr_cnt; i += 1) { - prne_free_resolv_rr(qent->fut.rr + i); - } - prne_free(qent->fut.rr); - qent->fut.rr = NULL; - qent->fut.rr_cnt = 0; - } - qent->fut.qr = qr; - qent->fut.err = err; - qent->fut.status = status; - resolv_disown_qent(qent); - } - - return ret; -} - -static size_t resolv_calc_dot_msg_len (query_entry_t *qent) { - return 2/*DoT head*/ + 12/*msg head*/ + qent->qname_size + 4/*QCLASS, QTYPE*/; -} - -static void resolv_write_dns_msg (query_entry_t *qent, uint8_t *mem) { - // ID - mem[0] = (uint8_t)((qent->qid & 0xFF00) >> 8); - mem[1] = (uint8_t)(qent->qid & 0x00FF); - // QR: 0, Opcode: 0, AA:0, TC: 0, RD: 1, RA: 0, Z: 0, RCODE: 0 - mem[2] = 0x01; - mem[3] = 0x00; - // QDCOUNT: 1 - mem[4] = 0x00; - mem[5] = 0x01; - // ANCOUNT, NSCOUNT, ARCOUNT: 0 - mem[6] = mem[7] = mem[8] = mem[9] = mem[10] = mem[11] = 0x00; - - // QNAME - memcpy(mem + 12, qent->qname, qent->qname_size); - // QTYPE - switch (qent->type) { - case PRNE_RESOLV_QT_A: - mem[qent->qname_size + 12] = 0x00; - mem[qent->qname_size + 13] = 0x01; - break; - case PRNE_RESOLV_QT_AAAA: - mem[qent->qname_size + 12] = 0x00; - mem[qent->qname_size + 13] = 0x1C; - break; - case PRNE_RESOLV_QT_TXT: - mem[qent->qname_size + 12] = 0x00; - mem[qent->qname_size + 13] = 0x10; - break; - default: abort(); - } - // QCLASS: IN - mem[qent->qname_size + 14] = 0x00; - mem[qent->qname_size + 15] = 0x01; -} - -static bool resolv_send_dns_msgs (prne_resolv_wkr_ctx_t ctx) { - prne_llist_entry_t *cur; - query_entry_t *qent; - size_t dot_msg_len, dns_msg_len; - uint16_t qid; - bool ret = false; - - cur = ctx->qlist.head; - while (cur != NULL && ctx->qid_map.size < RESOLV_PIPELINE_SIZE) { - qent = (query_entry_t*)cur->element; - - dot_msg_len = resolv_calc_dot_msg_len(qent); - dns_msg_len = dot_msg_len - 2; - if (dot_msg_len + ctx->write_cnt_len <= sizeof(ctx->write_buf)) { - qid = resolv_next_qid(ctx); - if (qid == 0) { - qent->fut.qr = PRNE_RESOLV_QR_ERR; - qent->fut.err = 0; - prne_llist_erase(&ctx->qlist, qent->qlist_ent); - resolv_disown_qent(qent); - - return ret; - } - - if (prne_imap_insert(&ctx->qid_map, qid, qent) == NULL) { - qent->fut.err = errno; - qent->fut.qr = PRNE_RESOLV_QR_ERR; - prne_llist_erase(&ctx->qlist, cur); - resolv_disown_qent(qent); - - return ret; - } - else { - cur = prne_llist_erase(&ctx->qlist, cur); - - ctx->write_buf[ctx->write_cnt_len + 0] = (uint8_t)((dns_msg_len & 0xFF00) >> 8); - ctx->write_buf[ctx->write_cnt_len + 1] = (uint8_t)(dns_msg_len & 0x00FF); - qent->qid = qid; - resolv_write_dns_msg(qent, ctx->write_buf + ctx->write_cnt_len + 2); - - ctx->write_cnt_len += dot_msg_len; - ret |= true; - } - } - else { - break; - } - } - - return ret; -} - -static void resolv_proc_q (prne_resolv_wkr_ctx_t ctx) { - bool proc = false; // true if any meaningful message has been processed. - int ret; - - if (ctx->ctx_state == RESOLV_CTX_STATE_READY) { - assert(ctx->act_dns_fd >= 0); - assert(ctx->act_dns_fd == ctx->sck_pfd_slot[0]->pfd.fd); - - if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; - } - if (ctx->sck_pfd_slot[0]->pfd.revents & POLLIN) { - size_t pos, msg_len; - bool err_flag = false; - - ret = mbedtls_ssl_read(&ctx->ssl.ctx, ctx->read_buf + ctx->read_cnt_len, sizeof(ctx->read_buf) - ctx->read_cnt_len); - if (ret <= 0) { - // we don't renegotiate with terrorists. - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; - } - ctx->read_cnt_len += (size_t)ret; - - pos = 0; - while (true) { - if (pos + 1 >= ctx->read_cnt_len) { - break; - } - msg_len = ((size_t)ctx->read_buf[pos] << 8) | (size_t)ctx->read_buf[pos + 1]; - if (msg_len > 512) { // unimplemented. -#ifdef PRNE_DEBUG - fprintf(stderr, "* [resolv_wkr] Protocol error: received %zu bytes long msg. Dropping connection!\n", msg_len); -#endif - // try to get qid - if (ctx->read_cnt_len > pos + 4) { - const uint16_t qid = ((uint_fast16_t)ctx->read_buf[pos + 2] << 8) | (uint_fast16_t)ctx->read_buf[pos + 3]; - const prne_imap_tuple_t *tpl = prne_imap_lookup(&ctx->qid_map, qid); - - if (tpl->val != NULL) { - query_entry_t *qent = (query_entry_t*)tpl->val; - qent->fut.qr = PRNE_RESOLV_QR_IMPL; - resolv_disown_qent(qent); - } - prne_imap_erase(&ctx->qid_map, qid); - } - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; - } - if (pos + 1 + msg_len >= ctx->read_cnt_len) { - break; - } - - proc |= resolv_proc_dns_msg(ctx, ctx->read_buf + pos + 2, msg_len, &err_flag); - if (err_flag) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; - } - pos += 2 + msg_len; - } - if (pos > 0) { - memmove(ctx->read_buf, ctx->read_buf + pos, ctx->read_cnt_len - pos); - ctx->read_cnt_len -= pos; - } - } - } - - if (ctx->qlist.size > 0 || ctx->write_cnt_len > 0) { - if (!resolv_ensure_conn(ctx)) { - return; - } - - if ((ctx->sck_pfd_slot[0]->pfd.revents & POLLOUT) && ctx->write_cnt_len > 0) { - ret = mbedtls_ssl_write(&ctx->ssl.ctx, ctx->write_buf, ctx->write_cnt_len); - if (ret <= 0) { - // we don't renegotiate with terrorists. - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; - } - - memmove(ctx->write_buf, ctx->write_buf + (size_t)ret, ctx->write_cnt_len - (size_t)ret); - ctx->write_cnt_len -= (size_t)ret; - } - if (ctx->write_cnt_len == 0) { - proc |= resolv_send_dns_msgs(ctx); - } - - if (ctx->write_cnt_len > 0 || (0 < ctx->qlist.size && ctx->qid_map.size < RESOLV_PIPELINE_SIZE)) { - ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT; - } - else { - ctx->sck_pfd_slot[0]->pfd.events = POLLIN; - } - } - - if (proc) { - if (ctx->qlist.size == 0 && ctx->qid_map.size == 0 && - ctx->read_cnt_len == 0 && ctx->write_cnt_len == 0) { - ctx->sckop_to_slot->dur = RESOLV_SCK_IDLE_TIMEOUT; - } - else { - ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT; - } - } -} - -static bool resolv_proc_close (prne_resolv_wkr_ctx_t ctx) { - assert(ctx->ctx_state == RESOLV_CTX_STATE_CLOSING); - - if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return false; - } - if (ctx->sck_pfd_slot[0]->pfd.revents) { - switch (mbedtls_ssl_close_notify(&ctx->ssl.ctx)) { - case MBEDTLS_ERR_SSL_WANT_READ: - ctx->sck_pfd_slot[0]->pfd.events = POLLIN; - return false; - case MBEDTLS_ERR_SSL_WANT_WRITE: - ctx->sck_pfd_slot[0]->pfd.events = POLLOUT; - return false; - case 0: - resolv_close_sck(ctx, NULL, false); - return true; - default: - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return false; - } - } - - return false; -} - -static void resolv_proc_expired (prne_resolv_wkr_ctx_t ctx) { - prne_llist_entry_t *cur; - query_entry_t *qent; - - cur = ctx->qlist.head; - while (cur != NULL) { - qent = (query_entry_t*)cur->element; - - if (qent->to_slot != NULL && qent->to_slot->reached) { - qent->fut.qr = PRNE_RESOLV_QR_TIMEOUT; - cur = prne_llist_erase(&ctx->qlist, cur); - resolv_disown_qent(qent); - } - else { - cur = cur->next; - } - } -} - -static void resolv_wkr_free (void *p) { - DECL_CTX_PTR(p); - - if (p == NULL) { - return; - } - - prne_free_wkr_timeout_slot(ctx->sckop_to_slot); - prne_free_wkr_timeout_slot(ctx->err_to_slot); - prne_free_wkr_pollfd_slot(ctx->evt_pfd_slot); - prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[0]); - prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[1]); - prne_free(ctx->dnssrv_4.arr); - prne_free(ctx->dnssrv_6.arr); - prne_free_llist(&ctx->qlist); - prne_free_imap(&ctx->qid_map); - mbedtls_ssl_config_free(&ctx->ssl.conf); - mbedtls_ssl_free(&ctx->ssl.ctx); - - prne_close(ctx->act_dns_fd); - prne_close(ctx->dnss_fd[0]); - prne_close(ctx->dnss_fd[1]); - prne_close(ctx->evtfd[0]); - prne_close(ctx->evtfd[1]); - - prne_free(ctx); -} - -static void resolv_wkr_fin (void *p) { - DECL_CTX_PTR(p); - - assert(ctx->wkr_state == RESOLV_WKR_STATE_OK); - ctx->wkr_state = RESOLV_WKR_STATE_FIN_CALLED; -} - -static void resolv_wkr_work (void *p, const prne_wkr_tick_info_t *tick_info) { - DECL_CTX_PTR(p); - - assert(ctx->wkr_state != RESOLV_WKR_STATE_FINALISED); - assert((ctx->evt_pfd_slot->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) == 0); - - if (ctx->evt_pfd_slot->pfd.revents & POLLIN) { - uint8_t rubbish; - - if (read(ctx->evtfd[0], &rubbish, 1) < 0) { - prne_die_not_nonblock_err(); - } - } - - resolv_proc_expired(ctx); - - if (ctx->err_to_slot->active) { - if (ctx->err_to_slot->reached) { - ctx->err_to_slot->active = false; - } - else { - return; - } - } - - if (ctx->sckop_to_slot->active && ctx->sckop_to_slot->reached) { - if (ctx->ctx_state == RESOLV_CTX_STATE_READY) { - ctx->ctx_state = RESOLV_CTX_STATE_CLOSING; - ctx->sckop_to_slot->dur = RESOLV_SCK_CLOSE_TIMEOUT; - ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd; - ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT; - return; - } - else { - resolv_close_sck(ctx, NULL, true); - } - } - if (ctx->ctx_state == RESOLV_CTX_STATE_CLOSING && !resolv_proc_close(ctx)) { - return; - } - - resolv_proc_q(ctx); - if (ctx->wkr_state == RESOLV_WKR_STATE_FIN_CALLED && ctx->qid_map.size == 0 && ctx->qlist.size == 0) { - if (ctx->ctx_state == RESOLV_CTX_STATE_READY) { - ctx->ctx_state = RESOLV_CTX_STATE_CLOSING; - ctx->sckop_to_slot->dur = RESOLV_SCK_CLOSE_TIMEOUT; - ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd; - ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT; - } - else { - ctx->wkr_state = RESOLV_WKR_STATE_FINALISED; - resolv_close_sck(ctx, NULL, false); - ctx->evt_pfd_slot->pfd.fd = -1; - ctx->err_to_slot->active = false; - } - } -} - -prne_resolv_wkr_ctx_t prne_alloc_resolv_worker (prne_worker_t *w, prne_wkr_sched_req_t *wsr, mbedtls_ctr_drbg_context *ctr_drbg) { - prne_resolv_wkr_ctx_t ctx = NULL; - - if (wsr == NULL || ctr_drbg == NULL) { - errno = EINVAL; - return NULL; - } - - ctx = (prne_resolv_wkr_ctx_t)prne_malloc(sizeof(struct prne_resolv_wkr_ctx), 1); - if (ctx == NULL) { - return NULL; - } - ctx->dnss_fd[0] = ctx->dnss_fd[1] = -1; - ctx->evtfd[0] = ctx->evtfd[1] = -1; - ctx->read_cnt_len = 0; - ctx->write_cnt_len = 0; - ctx->wsr = wsr; - ctx->sckop_to_slot = prne_alloc_wkr_timeout_slot(wsr); - ctx->err_to_slot = prne_alloc_wkr_timeout_slot(wsr); - ctx->evt_pfd_slot = prne_alloc_wkr_pollfd_slot(wsr); - ctx->sck_pfd_slot[0] = prne_alloc_wkr_pollfd_slot(wsr); - ctx->sck_pfd_slot[1] = prne_alloc_wkr_pollfd_slot(wsr); - ctx->act_dns_fd = -1; - ctx->ctx_state = RESOLV_CTX_STATE_NONE; - ctx->wkr_state = RESOLV_WKR_STATE_OK; - ctx->ssl.ctr_drbg = ctr_drbg; - prne_init_llist(&ctx->qlist); - prne_init_imap(&ctx->qid_map); - mbedtls_ssl_config_init(&ctx->ssl.conf); - mbedtls_ssl_init(&ctx->ssl.ctx); - if (ctx->sckop_to_slot == NULL || - ctx->err_to_slot == NULL || - ctx->evt_pfd_slot == NULL || - ctx->sck_pfd_slot[0] == NULL || - ctx->sck_pfd_slot[1] == NULL) { - goto ERR; - } - - ctx->dnssrv_4.arr = NULL; - ctx->dnssrv_6.arr = NULL; - ctx->dnssrv_4.cnt = 8; - ctx->dnssrv_6.cnt = 8; - ctx->dnssrv_4.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_4.cnt); - ctx->dnssrv_6.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_6.cnt); - ctx->dnssrv_4.arr = prne_malloc(sizeof(prne_net_endpoint_t), ctx->dnssrv_4.cnt); - ctx->dnssrv_6.arr = prne_malloc(sizeof(prne_net_endpoint_t), ctx->dnssrv_6.cnt); - if (ctx->dnssrv_4.arr == NULL || ctx->dnssrv_6.arr == NULL) { - goto ERR; - } - // IPv4 servers - // Google - prne_true_or_die(prne_net_ep_set_ipv4("8.8.8.8", 853, ctx->dnssrv_4.arr + 0)); - prne_true_or_die(prne_net_ep_set_ipv4("8.8.4.4", 853, ctx->dnssrv_4.arr + 1)); - // Cloudflare - prne_true_or_die(prne_net_ep_set_ipv4("1.1.1.1", 853, ctx->dnssrv_4.arr + 2)); - prne_true_or_die(prne_net_ep_set_ipv4("1.0.0.1", 853, ctx->dnssrv_4.arr + 3)); - // Quad9 - prne_true_or_die(prne_net_ep_set_ipv4("9.9.9.10", 853, ctx->dnssrv_4.arr + 4)); - prne_true_or_die(prne_net_ep_set_ipv4("149.112.112.10", 853, ctx->dnssrv_4.arr + 5)); - // CleanBrowsing - prne_true_or_die(prne_net_ep_set_ipv4("185.228.168.9", 853, ctx->dnssrv_4.arr + 6)); - prne_true_or_die(prne_net_ep_set_ipv4("185.228.169.9", 853, ctx->dnssrv_4.arr + 7)); - // IPv6 servers - // Google - prne_true_or_die(prne_net_ep_set_ipv6("2001:4860:4860::8888", 853, ctx->dnssrv_6.arr + 0)); - prne_true_or_die(prne_net_ep_set_ipv6("2001:4860:4860::8844", 853, ctx->dnssrv_6.arr + 1)); - // Cloudflare - prne_true_or_die(prne_net_ep_set_ipv6("2606:4700:4700::1111", 853, ctx->dnssrv_6.arr + 2)); - prne_true_or_die(prne_net_ep_set_ipv6("2606:4700:4700::1001", 853, ctx->dnssrv_6.arr + 3)); - // Quad9 - prne_true_or_die(prne_net_ep_set_ipv6("2620:fe::fe", 853, ctx->dnssrv_6.arr + 4)); - prne_true_or_die(prne_net_ep_set_ipv6("2620:fe::9", 853, ctx->dnssrv_6.arr + 5)); - // CleanBrowsing - prne_true_or_die(prne_net_ep_set_ipv6("2a0d:2a00:1::2", 853, ctx->dnssrv_6.arr + 6)); - prne_true_or_die(prne_net_ep_set_ipv6("2a0d:2a00:2::2", 853, ctx->dnssrv_6.arr + 7)); - - OK_OR_ERR(pipe(ctx->evtfd)); - OK_OR_ERR(resolv_set_cmn_fd_opt(ctx->evtfd[0])); - OK_OR_ERR(resolv_set_cmn_fd_opt(ctx->evtfd[1])); - prne_set_pipe_size(ctx->evtfd[0], 1); - ctx->evt_pfd_slot->pfd.fd = ctx->evtfd[0]; - ctx->evt_pfd_slot->pfd.events = POLLIN; - - if (mbedtls_ssl_config_defaults(&ctx->ssl.conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { - goto ERR; - } - mbedtls_ssl_conf_rng(&ctx->ssl.conf, mbedtls_ctr_drbg_random, ctx->ssl.ctr_drbg); - mbedtls_ssl_conf_authmode(&ctx->ssl.conf, MBEDTLS_SSL_VERIFY_NONE); - - w->ctx = ctx; - w->free = resolv_wkr_free; - w->fin = resolv_wkr_fin; - w->work = resolv_wkr_work; - w->has_finalised = resolv_wkr_has_finalised; - return ctx; -ERR: - if (ctx != NULL) { - prne_free_wkr_timeout_slot(ctx->sckop_to_slot); - prne_free_wkr_timeout_slot(ctx->err_to_slot); - prne_free_wkr_pollfd_slot(ctx->evt_pfd_slot); - prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[0]); - prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[1]); - prne_free(ctx->dnssrv_4.arr); - prne_free(ctx->dnssrv_6.arr); - prne_free_llist(&ctx->qlist); - prne_free_imap(&ctx->qid_map); - mbedtls_ssl_config_free(&ctx->ssl.conf); - mbedtls_ssl_free(&ctx->ssl.ctx); - - prne_close(ctx->evtfd[0]); - prne_close(ctx->evtfd[1]); - - prne_free(ctx); - } - - return NULL; -} - -bool prne_resolv_prm_gethostbyname (prne_resolv_wkr_ctx_t wkr, const char *name, const prne_ipv_t ipv, prne_resolv_prm_t *out, const struct timespec *timeout) { - bool ret; - query_entry_t *q_ent; - prne_resolv_query_type_t qt; - - if (wkr->wkr_state != RESOLV_WKR_STATE_OK) { - errno = EPIPE; - return false; - } - - switch (ipv) { - case PRNE_IPV_4: qt = PRNE_RESOLV_QT_A; break; - case PRNE_IPV_6: qt = PRNE_RESOLV_QT_AAAA; break; - default: - errno = EINVAL; - return false; - } - - ret = resolv_qq(wkr, name, out, timeout, &q_ent); - if (ret) { - q_ent->ipv = ipv; - q_ent->type = qt; - } - - return ret; -} - -bool prne_resolv_prm_gettxtrec (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_prm_t *out, const struct timespec *timeout) { - bool ret; - query_entry_t *q_ent; - - if (wkr->wkr_state != RESOLV_WKR_STATE_OK) { - errno = EPIPE; - return false; - } - - ret = resolv_qq(wkr, name, out, timeout, &q_ent); - if (ret) { - q_ent->type = PRNE_RESOLV_QT_TXT; - } - - return ret; -} - -void prne_resolv_free_prm (prne_resolv_prm_t *prm) { - if (prm->ctx != NULL) { - query_entry_t *ent = (query_entry_t*)prm->ctx; - - if (ent->wkr != NULL) { - prne_llist_erase(&ent->wkr->qlist, ent->qlist_ent); - - if (prne_imap_lookup(&ent->wkr->qid_map, ent->qid) != NULL) { - prne_imap_insert(&ent->wkr->qid_map, ent->qid, 0); - } - } - resolv_free_q_ent(ent); - } - - prm->ctx = NULL; - prm->fut = NULL; - prm->evtfd = -1; -} - -void prne_resolv_init_prm (prne_resolv_prm_t *prm) { - prm->ctx = NULL; - prm->fut = NULL; - prm->evtfd = -1; -} - -void prne_init_resolv_fut (prne_resolv_fut_t *fut) { - fut->rr_cnt = 0; - fut->rr = NULL; - fut->qr = PRNE_RESOLV_QR_NONE; - fut->err = 0; - fut->status = 0; -} - -void prne_free_resolv_fut (prne_resolv_fut_t *fut) { - size_t i; - - for (i = 0; i < fut->rr_cnt; i += 1) { - prne_free_resolv_rr(fut->rr + i); - } - prne_free(fut->rr); - fut->rr = NULL; - fut->rr_cnt = 0; -} - -void prne_init_resolv_rr (prne_resolv_rr_t *rr) { - rr->name = NULL; - rr->rr_class = 0; - rr->rr_type = 0; - rr->rr_ttl = 0; - rr->rd_data = NULL; - rr->rd_len = 0; -} - -void prne_free_resolv_rr (prne_resolv_rr_t *rr) { - prne_free(rr->name); - prne_free(rr->rd_data); - rr->rd_data = NULL; - rr->rd_len = 0; -} - -const char *prne_resolv_qr_tostr (const prne_resolv_qr_t qr) { - switch (qr) { - case PRNE_RESOLV_QR_OK: return "OK"; - case PRNE_RESOLV_QR_ERR: return "ERR"; - case PRNE_RESOLV_QR_PRO_ERR: return "PRO_ERR"; - case PRNE_RESOLV_QR_FIN: return "FIN"; - case PRNE_RESOLV_QR_IMPL: return "IMPL"; - case PRNE_RESOLV_QR_TIMEOUT: return "TIMEOUT"; - case PRNE_RESOLV_QR_STATUS: return "STATUS"; - } - return NULL; -} - -const char *prne_resolv_rcode_tostr (const prne_resolv_rcode_t rc) { - switch (rc) { - case PRNE_RESOLV_RCODE_NOERROR: return "NOERROR"; - case PRNE_RESOLV_RCODE_FORMERR: return "FORMERR"; - case PRNE_RESOLV_RCODE_SERVFAIL: return "SERVFAIL"; - case PRNE_RESOLV_RCODE_NXDOMAIN: return "NXDOMAIN"; - case PRNE_RESOLV_RCODE_NOTIMP: return "NOTIMP"; - case PRNE_RESOLV_RCODE_REFUSED: return "REFUSED"; - } - return NULL; -} - -const char *prne_resolv_rrtype_tostr (const uint16_t rrt) { - switch (rrt) { - case PRNE_RESOLV_RTYPE_A: return "A"; - case PRNE_RESOLV_RTYPE_NS: return "NS"; - case PRNE_RESOLV_RTYPE_CNAME: return "CNAME"; - case PRNE_RESOLV_RTYPE_SOA: return "SOA"; - case PRNE_RESOLV_RTYPE_PTR: return "PTR"; - case PRNE_RESOLV_RTYPE_MX: return "MX"; - case PRNE_RESOLV_RTYPE_TXT: return "TXT"; - case PRNE_RESOLV_RTYPE_AAAA: return "AAAA"; - } - return NULL; -} -- cgit