diff options
Diffstat (limited to 'src/rexmpp_dns.c')
-rw-r--r-- | src/rexmpp_dns.c | 137 |
1 files changed, 110 insertions, 27 deletions
diff --git a/src/rexmpp_dns.c b/src/rexmpp_dns.c index 5c3f4f6..d56aa10 100644 --- a/src/rexmpp_dns.c +++ b/src/rexmpp_dns.c @@ -7,6 +7,7 @@ */ #include <memory.h> +#include <stdlib.h> #include <syslog.h> #include "config.h" @@ -64,6 +65,7 @@ int rexmpp_parse_srv (char *in, int in_len, struct rexmpp_dns_srv *out) { } +#ifndef USE_RUST void rexmpp_dns_result_free (rexmpp_dns_result_t *result) { if (result->data != NULL) { int i; @@ -79,20 +81,37 @@ void rexmpp_dns_result_free (rexmpp_dns_result_t *result) { } free(result); } +#endif rexmpp_dns_result_t *result_from_hostent (struct hostent *hostinfo) { rexmpp_dns_result_t *r = malloc(sizeof(rexmpp_dns_result_t)); + if (r == NULL) { + return NULL; + } r->secure = 0; int i, size = 0; while (hostinfo->h_addr_list[size] != NULL) { size++; } r->data = malloc(sizeof(void *) * (size + 1)); + if (r->data == NULL) { + free(r); + return NULL; + } r->len = malloc(sizeof(int) * size); + if (r->len == NULL) { + free(r->data); + free(r); + return NULL; + } for (i = 0; i < size; i++) { r->len[i] = hostinfo->h_length; r->data[i] = malloc(r->len[i]); - memcpy(r->data[i], hostinfo->h_addr_list[i], hostinfo->h_length); + if (r->data[i] != NULL) { + memcpy(r->data[i], hostinfo->h_addr_list[i], hostinfo->h_length); + } else { + return r; + } } r->data[size] = NULL; return r; @@ -102,22 +121,22 @@ rexmpp_dns_result_t *result_from_hostent (struct hostent *hostinfo) { int rexmpp_dns_ctx_init (rexmpp_t *s) { #if defined(USE_UNBOUND) int err; - s->resolver.ctx = ub_ctx_create(); - if (s->resolver.ctx == NULL) { + s->resolver = ub_ctx_create(); + if (s->resolver == NULL) { rexmpp_log(s, LOG_CRIT, "Failed to create resolver context"); return 1; } - err = ub_ctx_resolvconf(s->resolver.ctx, NULL); + err = ub_ctx_resolvconf(s->resolver, NULL); if (err != 0) { rexmpp_log(s, LOG_WARNING, "Failed to read resolv.conf: %s", ub_strerror(err)); } - err = ub_ctx_hosts(s->resolver.ctx, NULL); + err = ub_ctx_hosts(s->resolver, NULL); if (err != 0) { rexmpp_log(s, LOG_WARNING, "Failed to read hosts file: %s", ub_strerror(err)); } - err = ub_ctx_add_ta_file(s->resolver.ctx, DNSSEC_TRUST_ANCHOR_FILE); + err = ub_ctx_add_ta_file(s->resolver, DNSSEC_TRUST_ANCHOR_FILE); if (err != 0) { rexmpp_log(s, LOG_WARNING, "Failed to set root key file for DNSSEC: %s", ub_strerror(err)); @@ -130,7 +149,7 @@ int rexmpp_dns_ctx_init (rexmpp_t *s) { ares_strerror(err)); return 1; } - err = ares_init(&(s->resolver.channel)); + err = ares_init(&(s->resolver)); if (err) { rexmpp_log(s, LOG_CRIT, "ares channel initialisation error: %s", ares_strerror(err)); @@ -139,7 +158,7 @@ int rexmpp_dns_ctx_init (rexmpp_t *s) { } return 0; #else - (void)s; + s->resolver = NULL; return 0; #endif } @@ -151,12 +170,15 @@ void rexmpp_dns_ctx_cleanup (rexmpp_t *s) { void rexmpp_dns_ctx_deinit (rexmpp_t *s) { #if defined(USE_UNBOUND) - if (s->resolver.ctx != NULL) { - ub_ctx_delete(s->resolver.ctx); - s->resolver.ctx = NULL; + if (s->resolver != NULL) { + ub_ctx_delete(s->resolver); + s->resolver = NULL; } #elif defined(USE_CARES) - ares_destroy(s->resolver.channel); + if (s->resolver != NULL) { + ares_destroy(s->resolver); + s->resolver = NULL; + } ares_library_cleanup(); #else (void)s; @@ -166,13 +188,13 @@ void rexmpp_dns_ctx_deinit (rexmpp_t *s) { int rexmpp_dns_fds (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { #if defined(USE_UNBOUND) (void)write_fds; - int max_fd = ub_fd(s->resolver.ctx) + 1; + int max_fd = ub_fd(s->resolver) + 1; if (max_fd != 0) { FD_SET(max_fd - 1, read_fds); } return max_fd; #elif defined(USE_CARES) - return ares_fds(s->resolver.channel, read_fds, write_fds); + return ares_fds(s->resolver, read_fds, write_fds); #else (void)s; (void)read_fds; @@ -181,16 +203,30 @@ int rexmpp_dns_fds (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { #endif } -struct timeval * rexmpp_dns_timeout (rexmpp_t *s, - struct timeval *max_tv, - struct timeval *tv) +struct timespec * rexmpp_dns_timeout (rexmpp_t *s, + struct timespec *max_tv, + struct timespec *tv) { #if defined(USE_UNBOUND) (void)s; (void)tv; return max_tv; #elif defined(USE_CARES) - return ares_timeout(s->resolver.channel, max_tv, tv); + struct timeval tv_ms; + struct timeval *max_tv_ms = NULL; + if (max_tv != NULL) { + max_tv_ms = &tv_ms; + tv_ms.tv_sec = tv->tv_sec; + tv_ms.tv_usec = tv->tv_nsec / 1000; + } + struct timeval *ret_ms = ares_timeout(s->resolver, max_tv_ms, &tv_ms); + if (ret_ms == max_tv_ms) { + return max_tv; + } else { + tv->tv_sec = tv_ms.tv_sec; + tv->tv_nsec = tv_ms.tv_usec * 1000; + return tv; + } #else (void)s; (void)max_tv; @@ -237,20 +273,54 @@ void rexmpp_dns_cb (void *ptr, size++; } rexmpp_dns_result_t *res = malloc(sizeof(rexmpp_dns_result_t)); - res->data = malloc(sizeof(void *) * (size + 1)); + if (res == NULL) { + rexmpp_log(s, LOG_DEBUG, + "Failed to allocate memory for a DNS resolution result"); + ub_resolve_free(result); + d->cb(s, d->ptr, NULL); + free(d); + return; + } + res->data = calloc((size + 1), sizeof(void *)); + if (res->data == NULL) { + rexmpp_log(s, LOG_DEBUG, + "Failed to allocate memory for a DNS resolution result's data"); + free(res); + ub_resolve_free(result); + d->cb(s, d->ptr, NULL); + free(d); + return; + } res->len = malloc(sizeof(int) * size); + if (res->len == NULL) { + rexmpp_log(s, LOG_DEBUG, + "Failed to allocate memory for a DNS resolution result's len"); + free(res->data); + free(res); + ub_resolve_free(result); + d->cb(s, d->ptr, NULL); + free(d); + return; + } for (i = 0; i < size; i++) { if (result->qtype == 33) { /* SRV */ res->len[i] = sizeof(rexmpp_dns_srv_t); res->data[i] = malloc(res->len[i]); + if (res->data[i] == NULL) { + rexmpp_log(s, LOG_ERR, + "Failed to allocate memory for an SRV record"); + d->cb(s, d->ptr, res); + rexmpp_dns_result_free(res); + free(d); + return; + } int err = rexmpp_parse_srv(result->data[i], result->len[i], (rexmpp_dns_srv_t*)res->data[i]); if (err) { rexmpp_log(s, LOG_WARNING, "Failed to parse an SRV record"); - res->data[i + 1] = NULL; + d->cb(s, d->ptr, res); rexmpp_dns_result_free(res); - d->cb(s, d->ptr, NULL); free(d); return; } @@ -258,7 +328,12 @@ void rexmpp_dns_cb (void *ptr, /* Non-SRV, for now that's just A or AAAA */ res->len[i] = result->len[i]; res->data[i] = malloc(res->len[i]); - memcpy(res->data[i], result->data[i], res->len[i]); + if (res->data[i] == NULL) { + rexmpp_log(s, LOG_WARNING, + "Failed to allocate memory for a DNS result's data record"); + } else { + memcpy(res->data[i], result->data[i], res->len[i]); + } } } res->data[size] = NULL; @@ -332,10 +407,14 @@ int rexmpp_dns_resolve (rexmpp_t *s, #if defined(USE_UNBOUND) struct rexmpp_dns_query_cb_data *d = malloc(sizeof(struct rexmpp_dns_query_cb_data)); + if (d == NULL) { + rexmpp_log(s, LOG_ERR, "Failed to allocate memory for a DNS query"); + return 1; + } d->s = s; d->cb = callback; d->ptr = ptr; - int err = ub_resolve_async(s->resolver.ctx, query, rrtype, rrclass, + int err = ub_resolve_async(s->resolver, query, rrtype, rrclass, d, rexmpp_dns_cb, NULL); if (err) { rexmpp_log(s, LOG_ERR, "Failed to query %s: %s", @@ -345,10 +424,14 @@ int rexmpp_dns_resolve (rexmpp_t *s, #elif defined(USE_CARES) struct rexmpp_dns_query_cb_data *d = malloc(sizeof(struct rexmpp_dns_query_cb_data)); + if (d == NULL) { + rexmpp_log(s, LOG_ERR, "Failed to allocate memory for a DNS query"); + return 1; + } d->s = s; d->cb = callback; d->ptr = ptr; - ares_query(s->resolver.channel, query, rrclass, rrtype, rexmpp_dns_cb, d); + ares_query(s->resolver, query, rrclass, rrtype, rexmpp_dns_cb, d); #else if (rrclass == 1) { if (rrtype == 1 || rrtype == 28) { @@ -381,8 +464,8 @@ int rexmpp_dns_process (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { #if defined(USE_UNBOUND) (void)read_fds; (void)write_fds; - if (ub_poll(s->resolver.ctx)) { - int err = ub_process(s->resolver.ctx); + if (ub_poll(s->resolver)) { + int err = ub_process(s->resolver); if (err != 0) { rexmpp_log(s, LOG_ERR, "DNS query processing error: %s", ub_strerror(err)); @@ -391,7 +474,7 @@ int rexmpp_dns_process (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { } return 0; #elif defined(USE_CARES) - ares_process(s->resolver.channel, read_fds, write_fds); + ares_process(s->resolver, read_fds, write_fds); return 0; #else (void)s; |