summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordefanor <defanor@uberspace.net>2021-09-21 21:39:52 +0300
committerdefanor <defanor@uberspace.net>2021-09-21 21:39:52 +0300
commit18f1f8f8d12131402ca13b53488870f2ab21d3d1 (patch)
tree33b885ef6495d3745265d17e598fdf21268a2553 /src
parentbec43cf7a9d33cd0ad393c86ffdd005c45f0f419 (diff)
Make libunbound optional
Just use gethostbyname when it's disabled. Possibly will add c-ares, getaddrinfo_a, and other options in the future.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/rexmpp.c118
-rw-r--r--src/rexmpp.h12
-rw-r--r--src/rexmpp_dns.c291
-rw-r--r--src/rexmpp_dns.h48
-rw-r--r--src/rexmpp_tcp.c62
-rw-r--r--src/rexmpp_tcp.h31
7 files changed, 420 insertions, 144 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index deb3ac6..51a5da7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,7 +32,7 @@ include_HEADERS = config.h rexmpp_roster.h rexmpp_tcp.h rexmpp_socks.h rexmpp.h
rexmpp_pubsub.h
librexmpp_la_CFLAGS = $(AM_CFLAGS) $(LIBXML_CFLAGS) \
$(GNUTLS_CFLAGS) $(LIBDANE_CFLAGS) $(OPENSSL_CFLAGS) \
- $(GSASL_CFLAGS) $(UNBOUND_CFLAGS) $(GPGME_CFLAGS)
+ $(GSASL_CFLAGS) $(UNBOUND_CFLAGS) $(GPGME_CFLAGS) \
$(ICU_I18N_CFLAGS) $(NETTLE_CFLAGS)
librexmpp_la_LIBADD = $(LIBXML_LIBS) \
$(GNUTLS_LIBS) $(LIBDANE_LIBS) $(OPENSSL_LIBS) \
diff --git a/src/rexmpp.c b/src/rexmpp.c
index 8998ea9..b35e40a 100644
--- a/src/rexmpp.c
+++ b/src/rexmpp.c
@@ -400,7 +400,6 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s,
s->tls_policy = REXMPP_TLS_REQUIRE;
s->send_buffer = NULL;
s->send_queue = NULL;
- s->resolver_ctx = NULL;
s->server_srv = NULL;
s->server_srv_cur = -1;
s->server_srv_tls = NULL;
@@ -458,30 +457,13 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s,
return REXMPP_E_XML;
}
- s->resolver_ctx = ub_ctx_create();
- if (s->resolver_ctx == NULL) {
- rexmpp_log(s, LOG_CRIT, "Failed to create resolver context");
+ if (rexmpp_dns_ctx_init(s)) {
xmlFreeParserCtxt(s->xml_parser);
return REXMPP_E_DNS;
}
- err = ub_ctx_resolvconf(s->resolver_ctx, 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);
- if (err != 0) {
- rexmpp_log(s, LOG_WARNING, "Failed to read hosts file: %s",
- ub_strerror(err));
- }
- /* todo: better to make this path configurable, not to hardcode it */
- err = ub_ctx_add_ta_file(s->resolver_ctx, DNSSEC_TRUST_ANCHOR_FILE);
- if (err != 0) {
- rexmpp_log(s, LOG_WARNING, "Failed to set root key file for DNSSEC: %s",
- ub_strerror(err));
- }
if (rexmpp_tls_init(s)) {
+ rexmpp_dns_ctx_deinit(s);
xmlFreeParserCtxt(s->xml_parser);
return REXMPP_E_TLS;
}
@@ -491,6 +473,7 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s,
rexmpp_log(s, LOG_CRIT, "gsasl initialisation error: %s",
gsasl_strerror(err));
rexmpp_tls_deinit(s);
+ rexmpp_dns_ctx_deinit(s);
xmlFreeParserCtxt(s->xml_parser);
return REXMPP_E_SASL;
}
@@ -505,6 +488,7 @@ rexmpp_err_t rexmpp_init (rexmpp_t *s,
gpgme_strerror(err));
gsasl_done(s->sasl_ctx);
rexmpp_tls_deinit(s);
+ rexmpp_dns_ctx_deinit(s);
xmlFreeParserCtxt(s->xml_parser);
return REXMPP_E_PGP;
}
@@ -559,12 +543,12 @@ void rexmpp_cleanup (rexmpp_t *s) {
s->input_queue_last = NULL;
}
if (s->server_srv != NULL) {
- ub_resolve_free(s->server_srv);
+ rexmpp_dns_result_free(s->server_srv);
s->server_srv = NULL;
s->server_srv_cur = -1;
}
if (s->server_srv_tls != NULL) {
- ub_resolve_free(s->server_srv_tls);
+ rexmpp_dns_result_free(s->server_srv_tls);
s->server_srv_tls = NULL;
s->server_srv_tls_cur = -1;
}
@@ -580,10 +564,7 @@ void rexmpp_done (rexmpp_t *s) {
#endif
gsasl_done(s->sasl_ctx);
rexmpp_tls_deinit(s);
- if (s->resolver_ctx != NULL) {
- ub_ctx_delete(s->resolver_ctx);
- s->resolver_ctx = NULL;
- }
+ rexmpp_dns_ctx_deinit(s);
xmlFreeParserCtxt(s->xml_parser);
if (s->stream_id != NULL) {
free(s->stream_id);
@@ -1148,8 +1129,8 @@ rexmpp_err_t rexmpp_start_connecting (rexmpp_t *s) {
s->server_host, s->server_port);
return
rexmpp_process_conn_err(s,
- rexmpp_tcp_conn_init(&s->server_connection,
- s->resolver_ctx,
+ rexmpp_tcp_conn_init(s,
+ &s->server_connection,
s->server_host,
s->server_port));
} else {
@@ -1157,15 +1138,15 @@ rexmpp_err_t rexmpp_start_connecting (rexmpp_t *s) {
s->server_host, s->server_port,
s->socks_host, s->socks_port);
return rexmpp_process_conn_err(s,
- rexmpp_tcp_conn_init(&s->server_connection,
- s->resolver_ctx,
+ rexmpp_tcp_conn_init(s,
+ &s->server_connection,
s->socks_host,
s->socks_port));
}
}
rexmpp_err_t rexmpp_try_next_host (rexmpp_t *s) {
- struct ub_result *cur_result;
+ rexmpp_dns_result_t *cur_result;
int cur_number;
/* todo: check priorities and weights */
s->tls_state = REXMPP_TLS_INACTIVE;
@@ -1301,34 +1282,22 @@ rexmpp_process_conn_err (rexmpp_t *s,
return REXMPP_E_AGAIN;
}
-void rexmpp_srv_cb (void *s_ptr,
- int err,
- struct ub_result *result)
+void rexmpp_srv_cb (rexmpp_t *s,
+ void *ptr,
+ rexmpp_dns_result_t *result)
{
- rexmpp_t *s = s_ptr;
- if (err == 0) {
- if (result->bogus) {
- rexmpp_log(s, LOG_WARNING,
- "Received a bogus SRV resolution result for %s",
- result->qname);
- } else if (result->havedata) {
- rexmpp_log(s,
- result->secure ? LOG_DEBUG : LOG_WARNING,
- "Resolved %s SRV record (%s)",
- result->qname, result->secure ? "secure" : "not secure");
- if (strncmp("_xmpp-", result->qname, 6) == 0) {
- s->server_srv = result;
- } else {
- s->server_srv_tls = result;
- }
+ (void)ptr;
+ if (result != NULL) {
+ rexmpp_log(s,
+ result->secure ? LOG_DEBUG : LOG_WARNING,
+ "Resolved %s SRV record (%s)",
+ result->qname, result->secure ? "secure" : "not secure");
+ if (strncmp("_xmpp-", result->qname, 6) == 0) {
+ s->server_srv = result;
} else {
- rexmpp_log(s, LOG_DEBUG, "No data in the %s SRV result", result->qname);
+ s->server_srv_tls = result;
}
- } else {
- rexmpp_log(s, LOG_WARNING, "Failed to query %s SRV records: %s",
- result->qname, ub_strerror(err));
}
-
if (s->resolver_state == REXMPP_RESOLVER_SRV) {
s->resolver_state = REXMPP_RESOLVER_SRV_2;
} else if (s->resolver_state == REXMPP_RESOLVER_SRV_2) {
@@ -2257,24 +2226,15 @@ rexmpp_err_t rexmpp_run (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) {
if (srv_query == NULL) {
return REXMPP_E_MALLOC;
}
+ s->resolver_state = REXMPP_RESOLVER_SRV;
snprintf(srv_query, srv_query_buf_len,
"_xmpps-client._tcp.%s.", s->initial_jid.domain);
- int err;
- err = ub_resolve_async(s->resolver_ctx, srv_query, 33, 1,
- s, rexmpp_srv_cb, NULL);
- if (err) {
- rexmpp_log(s, LOG_ERR, "Failed to query %s SRV record: %s",
- srv_query, ub_strerror(err));
- }
+ rexmpp_dns_resolve(s, srv_query, 33, 1,
+ NULL, rexmpp_srv_cb);
snprintf(srv_query, srv_query_buf_len,
"_xmpp-client._tcp.%s.", s->initial_jid.domain);
- err = ub_resolve_async(s->resolver_ctx, srv_query, 33, 1,
- s, rexmpp_srv_cb, NULL);
- if (err) {
- rexmpp_log(s, LOG_ERR, "Failed to query %s SRV record: %s",
- srv_query, ub_strerror(err));
- }
- s->resolver_state = REXMPP_RESOLVER_SRV;
+ rexmpp_dns_resolve(s, srv_query, 33, 1,
+ NULL, rexmpp_srv_cb);
free(srv_query);
} else {
/* A host is configured manually, connect there. */
@@ -2303,13 +2263,8 @@ rexmpp_err_t rexmpp_run (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) {
rexmpp_srv_cb. */
if (s->resolver_state != REXMPP_RESOLVER_NONE &&
s->resolver_state != REXMPP_RESOLVER_READY) {
- if (ub_poll(s->resolver_ctx)) {
- int err = ub_process(s->resolver_ctx);
- if (err != 0) {
- rexmpp_log(s, LOG_ERR, "DNS query processing error: %s",
- ub_strerror(err));
- return REXMPP_E_DNS;
- }
+ if (rexmpp_dns_process(s, read_fds, write_fds)) {
+ return REXMPP_E_DNS;
}
}
@@ -2332,7 +2287,7 @@ rexmpp_err_t rexmpp_run (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) {
if (s->tcp_state == REXMPP_TCP_CONNECTING) {
rexmpp_err_t err =
rexmpp_process_conn_err(s,
- rexmpp_tcp_conn_proceed(&s->server_connection,
+ rexmpp_tcp_conn_proceed(s, &s->server_connection,
read_fds, write_fds));
if (err > REXMPP_E_AGAIN) {
return err;
@@ -2449,14 +2404,11 @@ int rexmpp_fds(rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) {
if (s->resolver_state != REXMPP_RESOLVER_NONE &&
s->resolver_state != REXMPP_RESOLVER_READY) {
- max_fd = ub_fd(s->resolver_ctx) + 1;
- if (max_fd != 0) {
- FD_SET(max_fd - 1, read_fds);
- }
+ max_fd = rexmpp_dns_fds(s, read_fds, write_fds);
}
if (s->tcp_state == REXMPP_TCP_CONNECTING) {
- conn_fd = rexmpp_tcp_conn_fds(&s->server_connection, read_fds, write_fds);
+ conn_fd = rexmpp_tcp_conn_fds(s, &s->server_connection, read_fds, write_fds);
if (conn_fd > max_fd) {
max_fd = conn_fd;
}
@@ -2503,7 +2455,7 @@ struct timeval *rexmpp_timeout (rexmpp_t *s,
s->resolver_state != REXMPP_RESOLVER_READY) {
} else if (s->tcp_state == REXMPP_TCP_CONNECTING) {
- ret = rexmpp_tcp_conn_timeout(&s->server_connection, max_tv, tv);
+ ret = rexmpp_tcp_conn_timeout(s, &s->server_connection, max_tv, tv);
}
struct timeval now;
gettimeofday(&now, NULL);
diff --git a/src/rexmpp.h b/src/rexmpp.h
index a7b376a..d8d5e86 100644
--- a/src/rexmpp.h
+++ b/src/rexmpp.h
@@ -13,7 +13,6 @@
#include "config.h"
-#include <unbound.h>
#include <gsasl.h>
#include <libxml/tree.h>
#ifdef HAVE_GPGME
@@ -311,10 +310,15 @@ struct rexmpp
time_t last_network_activity;
/* DNS-related structures. */
- struct ub_ctx *resolver_ctx;
- struct ub_result *server_srv;
+ /* struct ub_ctx *resolver_ctx; */
+ /* struct ub_result *server_srv; */
+ /* int server_srv_cur; */
+ /* struct ub_result *server_srv_tls; */
+ /* int server_srv_tls_cur; */
+ rexmpp_dns_ctx_t resolver;
+ rexmpp_dns_result_t *server_srv;
int server_srv_cur;
- struct ub_result *server_srv_tls;
+ rexmpp_dns_result_t *server_srv_tls;
int server_srv_tls_cur;
struct rexmpp_dns_srv server_active_srv;
diff --git a/src/rexmpp_dns.c b/src/rexmpp_dns.c
index 6a8e743..5b3fd9e 100644
--- a/src/rexmpp_dns.c
+++ b/src/rexmpp_dns.c
@@ -6,31 +6,298 @@
@copyright MIT license.
*/
-#include "rexmpp_dns.h"
#include <memory.h>
+#include <syslog.h>
+
+#include "config.h"
+
+#if defined(USE_UNBOUND)
+#include <unbound.h>
+#else
+#include <netdb.h>
+#endif
+
+#include "rexmpp.h"
+#include "rexmpp_dns.h"
+
+
+struct rexmpp_dns_query_cb_data {
+ rexmpp_t *s;
+ dns_query_cb_t cb;
+ void *ptr;
+};
+
+
/* https://tools.ietf.org/html/rfc1035#section-3.1 */
+
+int rexmpp_dns_parse_qname (char *in, int in_len, char *out, int out_len) {
+ int i = 0;
+ while (i < in_len && in[i]) {
+ if (i + in[i] < in_len && i + in[i] < out_len) {
+ memcpy(out + i, in + i + 1, in[i]);
+ i += in[i];
+ out[i] = '.';
+ i++;
+ out[i] = '\0';
+ } else {
+ return -1;
+ }
+ }
+ return i;
+}
+
int rexmpp_parse_srv (char *in, int in_len, struct rexmpp_dns_srv *out) {
- int i;
- char *name;
if (in_len < 7 || in_len > 255 + 6) {
return -1;
}
out->priority = in[0] * 0x100 + in[1];
out->weight = in[2] * 0x100 + in[3];
out->port = in[4] * 0x100 + in[5];
- name = in + 6;
- i = 0;
- while (name[i]) {
- if (i + name[i] < 255) {
- memcpy(out->target + i, name + i + 1, name[i]);
- i += name[i];
- out->target[i] = '.';
- i++;
- out->target[i] = '\0';
+ if (rexmpp_dns_parse_qname(in + 6, in_len - 6, out->target, 255) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+
+void rexmpp_dns_result_free (rexmpp_dns_result_t *result) {
+ if (result->data != NULL) {
+ int i;
+ for (i = 0; result->data[i] != NULL; i++) {
+ free(result->data[i]);
+ }
+ free(result->data);
+ result->data = NULL;
+ }
+ if (result->len != NULL) {
+ free(result->len);
+ result->len = NULL;
+ }
+ if (result->qname != NULL) {
+ free(result->qname);
+ result->qname = NULL;
+ }
+ free(result);
+}
+
+
+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) {
+ rexmpp_log(s, LOG_CRIT, "Failed to create resolver context");
+ return 1;
+ }
+ err = ub_ctx_resolvconf(s->resolver.ctx, 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);
+ 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);
+ if (err != 0) {
+ rexmpp_log(s, LOG_WARNING, "Failed to set root key file for DNSSEC: %s",
+ ub_strerror(err));
+ }
+ return 0;
+#else
+ (void)s;
+ return 0;
+#endif
+}
+
+void rexmpp_dns_ctx_cleanup (rexmpp_t *s) {
+#if defined(USE_UNBOUND)
+ (void)s;
+ return;
+#else
+ (void)s;
+ return;
+#endif
+}
+
+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;
+ }
+#else
+ (void)s;
+#endif
+}
+
+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;
+ if (max_fd != 0) {
+ FD_SET(max_fd - 1, read_fds);
+ }
+ return max_fd;
+#else
+ (void)s;
+ (void)read_fds;
+ (void)write_fds;
+ return 0;
+#endif
+}
+
+struct timeval * rexmpp_dns_timeout (rexmpp_t *s,
+ struct timeval *max_tv,
+ struct timeval *tv)
+{
+#if defined(USE_UNBOUND)
+ (void)s;
+ (void)tv;
+ return max_tv;
+#else
+ (void)s;
+ (void)max_tv;
+ (void)tv;
+ return max_tv;
+#endif
+}
+
+#if defined(USE_UNBOUND)
+void rexmpp_dns_cb (void *ptr,
+ int err,
+ struct ub_result *result)
+{
+ struct rexmpp_dns_query_cb_data *d = ptr;
+ rexmpp_t *s = d->s;
+
+ if (err != 0) {
+ rexmpp_log(s, LOG_WARNING, "%s DNS query failure: %s",
+ result->qname, ub_strerror(err));
+ ub_resolve_free(result);
+ d->cb(s, d->ptr, NULL);
+ return;
+ }
+
+ if (result->bogus) {
+ rexmpp_log(s, LOG_WARNING,
+ "Received a bogus DNS resolution result for %s",
+ result->qname);
+ ub_resolve_free(result);
+ d->cb(s, d->ptr, NULL);
+ return;
+ }
+
+ if (! result->havedata) {
+ rexmpp_log(s, LOG_DEBUG, "No data in the %s query result", result->qname);
+ ub_resolve_free(result);
+ d->cb(s, d->ptr, NULL);
+ return;
+ }
+
+ int i, size = 0;
+ while (result->data[size] != NULL) {
+ size++;
+ }
+ rexmpp_dns_result_t *res = malloc(sizeof(rexmpp_dns_result_t));
+ res->data = malloc(sizeof(char *) * (size + 1));
+ res->len = malloc(sizeof(int) * size);
+ for (i = 0; i < size; i++) {
+ res->len[i] = result->len[i];
+ res->data[i] = malloc(res->len[i]);
+ memcpy(res->data[i], result->data[i], res->len[i]);
+ }
+ res->data[size] = NULL;
+ res->secure = result->secure;
+ res->qname = strdup(result->qname);
+ ub_resolve_free(result);
+ d->cb(s, d->ptr, res);
+ free(d);
+}
+#endif
+
+
+int rexmpp_dns_resolve (rexmpp_t *s,
+ const char *query,
+ int rrtype,
+ int rrclass,
+ void* ptr,
+ dns_query_cb_t callback)
+{
+#if defined(USE_UNBOUND)
+ struct rexmpp_dns_query_cb_data *d =
+ malloc(sizeof(struct rexmpp_dns_query_cb_data));
+ d->s = s;
+ d->cb = callback;
+ d->ptr = ptr;
+ int err = ub_resolve_async(s->resolver.ctx, query, rrtype, rrclass,
+ d, rexmpp_dns_cb, NULL);
+ if (err) {
+ rexmpp_log(s, LOG_ERR, "Failed to query %s: %s",
+ query, ub_strerror(err));
+ return 1;
+ }
+#else
+ rexmpp_dns_result_t *r = malloc(sizeof(rexmpp_dns_result_t));;
+ if (rrclass == 1) {
+ if (rrtype == 1 || rrtype == 28) {
+ struct hostent *hostinfo = gethostbyname(query);
+ if (hostinfo == NULL) {
+ rexmpp_log(s, LOG_ERR, "Failed to lookup %s", query);
+ callback(s, ptr, NULL);
+ } else {
+ r->qname = strdup(query);
+ r->secure = 0;
+ int i, size = 0;
+ while (hostinfo->h_addr_list[size] != NULL) {
+ size++;
+ }
+ r->data = malloc(sizeof(char *) * (size + 1));
+ r->len = malloc(sizeof(int) * size);
+ 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);
+ }
+ r->data[size] = NULL;
+ callback(s, ptr, r);
+ }
+ } else if (rrtype == 33) {
+ rexmpp_log(s, LOG_WARNING, "rexmpp is built without SRV lookup support");
+ callback(s, ptr, NULL);
} else {
+ rexmpp_log(s, LOG_ERR, "A DNS lookup of unrecognized type is requested");
+ callback(s, ptr, NULL);
return -1;
}
+ } else {
+ rexmpp_log(s, LOG_ERR, "A DNS lookup of unrecognized class is requested");
+ callback(s, ptr, NULL);
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+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 (err != 0) {
+ rexmpp_log(s, LOG_ERR, "DNS query processing error: %s",
+ ub_strerror(err));
+ return 1;
+ }
}
return 0;
+#else
+ (void)s;
+ (void)read_fds;
+ (void)write_fds;
+ return 0;
+#endif
}
diff --git a/src/rexmpp_dns.h b/src/rexmpp_dns.h
index 9d9f271..3c94e90 100644
--- a/src/rexmpp_dns.h
+++ b/src/rexmpp_dns.h
@@ -11,6 +11,22 @@
#define REXMPP_DNS_H
#include <stdint.h>
+#include "config.h"
+
+#include "rexmpp.h"
+
+#if defined(USE_UNBOUND)
+#include <unbound.h>
+struct rexmpp_dns_ctx {
+ struct ub_ctx *ctx;
+};
+#else
+struct rexmpp_dns_ctx {
+ int dummy;
+};
+#endif
+
+typedef struct rexmpp_dns_ctx rexmpp_dns_ctx_t;
struct rexmpp_dns_srv {
uint16_t priority;
@@ -19,6 +35,13 @@ struct rexmpp_dns_srv {
char target[256];
};
+struct rexmpp_dns_result {
+ char **data;
+ int *len;
+ char *qname;
+ int secure;
+};
+
/**
@brief Parses an SRV DNS RR's RDATA.
@param[in] in SRV record's RDATA.
@@ -29,4 +52,29 @@ struct rexmpp_dns_srv {
int
rexmpp_parse_srv (char *in, int in_len, struct rexmpp_dns_srv *out);
+typedef struct rexmpp_dns_result rexmpp_dns_result_t;
+
+/* struct rexmpp_dns_result *rexmpp_dns_result_init (int len); */
+void rexmpp_dns_result_free (rexmpp_dns_result_t *result);
+
+int rexmpp_dns_ctx_init (rexmpp_t *s);
+void rexmpp_dns_ctx_cleanup (rexmpp_t *s);
+void rexmpp_dns_ctx_deinit (rexmpp_t *s);
+int rexmpp_dns_fds (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds);
+struct timeval * rexmpp_dns_timeout (rexmpp_t *s,
+ struct timeval *max_tv,
+ struct timeval *tv);
+
+typedef void (*dns_query_cb_t) (rexmpp_t *s, void *ptr, rexmpp_dns_result_t *result);
+
+int rexmpp_dns_resolve (rexmpp_t *s,
+ const char *query,
+ int rrtype,
+ int rrclass,
+ void* ptr,
+ dns_query_cb_t callback);
+
+int rexmpp_dns_process (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds);
+
+
#endif
diff --git a/src/rexmpp_tcp.c b/src/rexmpp_tcp.c
index 27c3ba4..a4d5018 100644
--- a/src/rexmpp_tcp.c
+++ b/src/rexmpp_tcp.c
@@ -6,7 +6,6 @@
@copyright MIT license.
*/
-#include <unbound.h>
#include <netdb.h>
#include <arpa/nameser.h>
#include <sys/socket.h>
@@ -19,17 +18,19 @@
#include <arpa/inet.h>
#include <fcntl.h>
+#include "rexmpp.h"
#include "rexmpp_tcp.h"
+#include "rexmpp_dns.h"
-void rexmpp_dns_aaaa_cb (void *ptr,
- int status,
- struct ub_result *result)
+void rexmpp_tcp_dns_aaaa_cb (rexmpp_t *s,
+ void *ptr,
+ rexmpp_dns_result_t *result)
{
+ (void)s;
rexmpp_tcp_conn_t *conn = ptr;
- conn->resolver_status_v6 = status;
conn->resolved_v6 = result;
- if (status == 0 && ! result->bogus && result->havedata) {
+ if (result != NULL) {
conn->resolution_v6 = REXMPP_CONN_RESOLUTION_SUCCESS;
conn->addr_cur_v6 = -1;
} else {
@@ -37,14 +38,14 @@ void rexmpp_dns_aaaa_cb (void *ptr,
}
}
-void rexmpp_dns_a_cb (void *ptr,
- int status,
- struct ub_result *result)
+void rexmpp_tcp_dns_a_cb (rexmpp_t *s,
+ void *ptr,
+ rexmpp_dns_result_t *result)
{
+ (void)s;
rexmpp_tcp_conn_t *conn = ptr;
- conn->resolver_status_v4 = status;
conn->resolved_v4 = result;
- if (status == 0 && ! result->bogus && result->havedata) {
+ if (result != NULL) {
conn->resolution_v4 = REXMPP_CONN_RESOLUTION_SUCCESS;
conn->addr_cur_v4 = -1;
if (conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) {
@@ -74,11 +75,11 @@ void rexmpp_tcp_cleanup (rexmpp_tcp_conn_t *conn) {
conn->resolution_v6 = REXMPP_CONN_RESOLUTION_INACTIVE;
}
if (conn->resolved_v4 != NULL) {
- ub_resolve_free(conn->resolved_v4);
+ rexmpp_dns_result_free(conn->resolved_v4);
conn->resolved_v4 = NULL;
}
if (conn->resolved_v6 != NULL) {
- ub_resolve_free(conn->resolved_v6);
+ rexmpp_dns_result_free(conn->resolved_v6);
conn->resolved_v6 = NULL;
}
}
@@ -99,8 +100,8 @@ rexmpp_tcp_connected (rexmpp_tcp_conn_t *conn, int fd) {
}
rexmpp_tcp_conn_error_t
-rexmpp_tcp_conn_init (rexmpp_tcp_conn_t *conn,
- struct ub_ctx *resolver_ctx,
+rexmpp_tcp_conn_init (rexmpp_t *s,
+ rexmpp_tcp_conn_t *conn,
const char *host,
uint16_t port)
{
@@ -165,12 +166,11 @@ rexmpp_tcp_conn_init (rexmpp_tcp_conn_t *conn,
}
conn->resolution_v4 = REXMPP_CONN_RESOLUTION_WAITING;
conn->resolution_v6 = REXMPP_CONN_RESOLUTION_WAITING;
- conn->resolver_ctx = resolver_ctx;
- ub_resolve_async(conn->resolver_ctx, host, 28, 1,
- conn, rexmpp_dns_aaaa_cb, NULL);
- ub_resolve_async(conn->resolver_ctx, host, 1, 1,
- conn, rexmpp_dns_a_cb, NULL);
+ rexmpp_dns_resolve(s, host, 28, 1,
+ conn, rexmpp_tcp_dns_aaaa_cb);
+ rexmpp_dns_resolve(s, host, 1, 1,
+ conn, rexmpp_tcp_dns_a_cb);
return REXMPP_CONN_IN_PROGRESS;
}
@@ -193,7 +193,8 @@ int rexmpp_tcp_conn_ipv6_available(rexmpp_tcp_conn_t *conn) {
}
rexmpp_tcp_conn_error_t
-rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn,
+rexmpp_tcp_conn_proceed (rexmpp_t *s,
+ rexmpp_tcp_conn_t *conn,
fd_set *read_fds,
fd_set *write_fds)
{
@@ -222,9 +223,7 @@ rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn,
/* Name resolution. */
if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING ||
conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) {
- if (ub_poll(conn->resolver_ctx)) {
- ub_process(conn->resolver_ctx);
- }
+ rexmpp_dns_process(s, read_fds, write_fds);
}
if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_FAILURE &&
@@ -344,17 +343,15 @@ rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn,
}
}
-int rexmpp_tcp_conn_fds (rexmpp_tcp_conn_t *conn,
+int rexmpp_tcp_conn_fds (rexmpp_t *s,
+ rexmpp_tcp_conn_t *conn,
fd_set *read_fds,
fd_set *write_fds)
{
int max_fd = 0, i;
if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING ||
conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) {
- max_fd = ub_fd(conn->resolver_ctx) + 1;
- if (max_fd != 0) {
- FD_SET(max_fd - 1, read_fds);
- }
+ max_fd = rexmpp_dns_fds(s, read_fds, write_fds);
}
for (i = 0; i < REXMPP_TCP_MAX_CONNECTION_ATTEMPTS; i++) {
if (conn->sockets[i] != -1) {
@@ -367,12 +364,17 @@ int rexmpp_tcp_conn_fds (rexmpp_tcp_conn_t *conn,
return max_fd;
}
-struct timeval *rexmpp_tcp_conn_timeout (rexmpp_tcp_conn_t *conn,
+struct timeval *rexmpp_tcp_conn_timeout (rexmpp_t *s,
+ rexmpp_tcp_conn_t *conn,
struct timeval *max_tv,
struct timeval *tv)
{
struct timeval now;
struct timeval *ret = max_tv;
+ if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_WAITING ||
+ conn->resolution_v6 == REXMPP_CONN_RESOLUTION_WAITING) {
+ ret = rexmpp_dns_timeout(s, max_tv, tv);
+ }
if (conn->resolution_v4 == REXMPP_CONN_RESOLUTION_SUCCESS ||
conn->resolution_v6 == REXMPP_CONN_RESOLUTION_SUCCESS ||
(conn->resolution_v4 == REXMPP_CONN_RESOLUTION_INACTIVE &&
diff --git a/src/rexmpp_tcp.h b/src/rexmpp_tcp.h
index 1e13ca3..5a296cc 100644
--- a/src/rexmpp_tcp.h
+++ b/src/rexmpp_tcp.h
@@ -21,6 +21,9 @@
#include <sys/time.h>
+#include "rexmpp.h"
+#include "rexmpp_dns.h"
+
#define REXMPP_TCP_MAX_CONNECTION_ATTEMPTS 20
#define REXMPP_TCP_IPV6_DELAY_MS 50
#define REXMPP_TCP_CONN_DELAY_MS 250
@@ -70,19 +73,13 @@ struct rexmpp_tcp_connection {
/** @brief A port we are connecting to. */
uint16_t port;
- /** @brief Resolver context. */
- struct ub_ctx *resolver_ctx;
- /** @brief Resolver error is stored here when
- ::REXMPP_CONN_RESOLVER_ERROR is returned. */
- int resolver_error;
-
/** @brief State of A record resolution. */
enum rexmpp_tcp_conn_resolution_status resolution_v4;
/** @brief Status of A record resolution, as returned by the
resolver. */
int resolver_status_v4;
/** @brief Resolved A records. */
- struct ub_result *resolved_v4;
+ rexmpp_dns_result_t *resolved_v4;
/** @brief The AF_INET address number we are currently at. */
int addr_cur_v4;
@@ -92,7 +89,7 @@ struct rexmpp_tcp_connection {
resolver. */
int resolver_status_v6;
/** @brief Resolved AAAA records. */
- struct ub_result *resolved_v6;
+ rexmpp_dns_result_t *resolved_v6;
/** @brief The AF_INET6 address number we are currently at. */
int addr_cur_v6;
@@ -112,28 +109,30 @@ struct rexmpp_tcp_connection {
/**
@brief Initiates a connection.
+ @param[in] s ::rexmpp
@param[out] conn An allocated connection structure.
- @param[in] resolver_ctx Resolver context to use.
@param[in] host A host to connect to. This could be a domain name,
or a textual representation of an IPv4 or an IPv6 address.
@param[in] port A port to connect to.
@returns A ::rexmpp_tcp_conn_error state.
*/
rexmpp_tcp_conn_error_t
-rexmpp_tcp_conn_init (rexmpp_tcp_conn_t *conn,
- struct ub_ctx *resolver_ctx,
+rexmpp_tcp_conn_init (rexmpp_t *s,
+ rexmpp_tcp_conn_t *conn,
const char *host,
uint16_t port);
/**
@brief Continues a connection process.
+ @param[in] s ::rexmpp
@param[in,out] conn An active connection structure.
@param[in] read_fds File descriptors available for reading from.
@param[in] write_fds File descriptors available for writing to.
@returns A ::rexmpp_tcp_conn_error state.
*/
rexmpp_tcp_conn_error_t
-rexmpp_tcp_conn_proceed (rexmpp_tcp_conn_t *conn,
+rexmpp_tcp_conn_proceed (rexmpp_t *s,
+ rexmpp_tcp_conn_t *conn,
fd_set *read_fds,
fd_set *write_fds);
@@ -158,6 +157,7 @@ int rexmpp_tcp_conn_finish (rexmpp_tcp_conn_t *conn);
File descriptors are only added to an @c fd_set, so the ones it
already contains will not be lost.
+ @param[in] s ::rexmpp
@param[in] conn An active connection structure.
@param[out] read_fds File descriptors a connection process is
interested in reading from.
@@ -165,19 +165,22 @@ int rexmpp_tcp_conn_finish (rexmpp_tcp_conn_t *conn);
interested in writing to.
@returns Maximum file descriptor number, plus 1.
*/
-int rexmpp_tcp_conn_fds (rexmpp_tcp_conn_t *conn,
+int rexmpp_tcp_conn_fds (rexmpp_t *s,
+ rexmpp_tcp_conn_t *conn,
fd_set *read_fds,
fd_set *write_fds);
/**
@brief Reports timeouts.
+ @param[in] s ::rexmpp
@param[in] conn An active connection structure.
@param[in] max_tv An existing maximum timeout.
@param[out] tv A timeval structure to store a new timeout in.
@returns A pointer to either max_tv or tv, depending on which one
is smaller.
*/
-struct timeval *rexmpp_tcp_conn_timeout (rexmpp_tcp_conn_t *conn,
+struct timeval *rexmpp_tcp_conn_timeout (rexmpp_t *s,
+ rexmpp_tcp_conn_t *conn,
struct timeval *max_tv,
struct timeval *tv);