|
|
ca1eb8 |
From e73e35f2a1ef037d89f73b4ce5609e2567dc8714 Mon Sep 17 00:00:00 2001
|
|
|
ca1eb8 |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
ca1eb8 |
Date: Mon, 25 Jun 2018 12:46:51 +0200
|
|
|
ca1eb8 |
Subject: [PATCH] RESOLV: Add a resolv_hostport_list request
|
|
|
ca1eb8 |
|
|
|
ca1eb8 |
Adds a request that resolves a list of (host,port) tuples and returns a
|
|
|
ca1eb8 |
list of structures that contain the resolv_hostent structure as other
|
|
|
ca1eb8 |
resolver requests do, but also a pointer to the original request tuple.
|
|
|
ca1eb8 |
|
|
|
ca1eb8 |
This is done because the request skips any unresolvable inputs, so it
|
|
|
ca1eb8 |
might be handy to know which input an output maps to.
|
|
|
ca1eb8 |
|
|
|
ca1eb8 |
It is expected that the request will be used in the future also for cases
|
|
|
ca1eb8 |
where we want to e.g. try the connectivity to a serve using a mechanism
|
|
|
ca1eb8 |
such as an LDAP ping.
|
|
|
ca1eb8 |
|
|
|
ca1eb8 |
Related:
|
|
|
ca1eb8 |
https://pagure.io/SSSD/sssd/issue/3291
|
|
|
ca1eb8 |
|
|
|
ca1eb8 |
Reviewed-by: Sumit Bose <sbose@redhat.com>
|
|
|
ca1eb8 |
(cherry picked from commit 6f80bccc6f8203381c387080bd0563ba10994487)
|
|
|
ca1eb8 |
---
|
|
|
ca1eb8 |
src/resolv/async_resolv.c | 187 ++++++++++++++++++++++++++++++++++++++
|
|
|
ca1eb8 |
src/resolv/async_resolv.h | 30 ++++++
|
|
|
ca1eb8 |
2 files changed, 217 insertions(+)
|
|
|
ca1eb8 |
|
|
|
ca1eb8 |
diff --git a/src/resolv/async_resolv.c b/src/resolv/async_resolv.c
|
|
|
ca1eb8 |
index ba6fabf285533153ea440394ce1cc224aa42cbd3..bb27011548b73c0cc62f6638401847ab9e0b175c 100644
|
|
|
ca1eb8 |
--- a/src/resolv/async_resolv.c
|
|
|
ca1eb8 |
+++ b/src/resolv/async_resolv.c
|
|
|
ca1eb8 |
@@ -2322,3 +2322,190 @@ resolv_sort_srv_reply(struct ares_srv_reply **reply)
|
|
|
ca1eb8 |
|
|
|
ca1eb8 |
return EOK;
|
|
|
ca1eb8 |
}
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+struct resolv_hostport_list_state {
|
|
|
ca1eb8 |
+ struct tevent_context *ev;
|
|
|
ca1eb8 |
+ struct resolv_ctx *ctx;
|
|
|
ca1eb8 |
+ struct resolv_hostport *hostport_list;
|
|
|
ca1eb8 |
+ size_t list_size;
|
|
|
ca1eb8 |
+ size_t limit;
|
|
|
ca1eb8 |
+ enum restrict_family family_order;
|
|
|
ca1eb8 |
+ enum host_database *db;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ size_t hpindex;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ struct resolv_hostport_addr **rhp_addrs;
|
|
|
ca1eb8 |
+ size_t addrindex;
|
|
|
ca1eb8 |
+};
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+static errno_t resolv_hostport_list_step(struct tevent_req *req);
|
|
|
ca1eb8 |
+static void resolv_hostport_list_resolv_hostname_done(struct tevent_req *subreq);
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+struct tevent_req *resolv_hostport_list_send(TALLOC_CTX *mem_ctx,
|
|
|
ca1eb8 |
+ struct tevent_context *ev,
|
|
|
ca1eb8 |
+ struct resolv_ctx *ctx,
|
|
|
ca1eb8 |
+ struct resolv_hostport *hostport_list,
|
|
|
ca1eb8 |
+ size_t list_size,
|
|
|
ca1eb8 |
+ size_t limit,
|
|
|
ca1eb8 |
+ enum restrict_family family_order,
|
|
|
ca1eb8 |
+ enum host_database *db)
|
|
|
ca1eb8 |
+{
|
|
|
ca1eb8 |
+ struct resolv_hostport_list_state *state;
|
|
|
ca1eb8 |
+ struct tevent_req *req;
|
|
|
ca1eb8 |
+ errno_t ret;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ req = tevent_req_create(mem_ctx, &state,
|
|
|
ca1eb8 |
+ struct resolv_hostport_list_state);
|
|
|
ca1eb8 |
+ if (req == NULL) {
|
|
|
ca1eb8 |
+ return NULL;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+ state->ev = ev;
|
|
|
ca1eb8 |
+ state->ctx = ctx;
|
|
|
ca1eb8 |
+ state->hostport_list = hostport_list;
|
|
|
ca1eb8 |
+ state->family_order = family_order;
|
|
|
ca1eb8 |
+ state->db = db;
|
|
|
ca1eb8 |
+ state->list_size = list_size;
|
|
|
ca1eb8 |
+ state->limit = limit;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ state->rhp_addrs = talloc_array(state,
|
|
|
ca1eb8 |
+ struct resolv_hostport_addr *,
|
|
|
ca1eb8 |
+ state->list_size);
|
|
|
ca1eb8 |
+ if (state->rhp_addrs == NULL) {
|
|
|
ca1eb8 |
+ ret = ENOMEM;
|
|
|
ca1eb8 |
+ goto immediately;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ ret = resolv_hostport_list_step(req);
|
|
|
ca1eb8 |
+ if (ret != EAGAIN) {
|
|
|
ca1eb8 |
+ goto immediately;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ return req;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+immediately:
|
|
|
ca1eb8 |
+ if (ret != EOK) {
|
|
|
ca1eb8 |
+ tevent_req_error(req, ret);
|
|
|
ca1eb8 |
+ } else {
|
|
|
ca1eb8 |
+ tevent_req_done(req);
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+ tevent_req_post(req, ev);
|
|
|
ca1eb8 |
+ return req;
|
|
|
ca1eb8 |
+}
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+static errno_t resolv_hostport_list_step(struct tevent_req *req)
|
|
|
ca1eb8 |
+{
|
|
|
ca1eb8 |
+ struct tevent_req *subreq = NULL;
|
|
|
ca1eb8 |
+ struct resolv_hostport_list_state *state = tevent_req_data(req,
|
|
|
ca1eb8 |
+ struct resolv_hostport_list_state);
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ if (state->hpindex >= state->list_size) {
|
|
|
ca1eb8 |
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Done\n");
|
|
|
ca1eb8 |
+ return EOK;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ subreq = resolv_gethostbyname_send(state,
|
|
|
ca1eb8 |
+ state->ev,
|
|
|
ca1eb8 |
+ state->ctx,
|
|
|
ca1eb8 |
+ state->hostport_list[state->hpindex].host,
|
|
|
ca1eb8 |
+ state->family_order,
|
|
|
ca1eb8 |
+ state->db);
|
|
|
ca1eb8 |
+ if (subreq == NULL) {
|
|
|
ca1eb8 |
+ return ENOMEM;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+ tevent_req_set_callback(subreq,
|
|
|
ca1eb8 |
+ resolv_hostport_list_resolv_hostname_done, req);
|
|
|
ca1eb8 |
+ return EAGAIN;
|
|
|
ca1eb8 |
+}
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+static struct resolv_hostport_addr*
|
|
|
ca1eb8 |
+resolv_hostport_addr_new(TALLOC_CTX *mem_ctx,
|
|
|
ca1eb8 |
+ const char *host,
|
|
|
ca1eb8 |
+ int port,
|
|
|
ca1eb8 |
+ struct resolv_hostent *reply)
|
|
|
ca1eb8 |
+{
|
|
|
ca1eb8 |
+ struct resolv_hostport_addr *rhp_addr;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ rhp_addr = talloc_zero(mem_ctx, struct resolv_hostport_addr);
|
|
|
ca1eb8 |
+ if (rhp_addr == NULL) {
|
|
|
ca1eb8 |
+ return NULL;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ rhp_addr->origin.host = talloc_strdup(rhp_addr, host);
|
|
|
ca1eb8 |
+ if (rhp_addr->origin.host == NULL) {
|
|
|
ca1eb8 |
+ return NULL;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ rhp_addr->origin.port = port;
|
|
|
ca1eb8 |
+ rhp_addr->reply = talloc_steal(rhp_addr, reply);
|
|
|
ca1eb8 |
+ return rhp_addr;
|
|
|
ca1eb8 |
+}
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+static void resolv_hostport_list_resolv_hostname_done(struct tevent_req *subreq)
|
|
|
ca1eb8 |
+{
|
|
|
ca1eb8 |
+ errno_t ret;
|
|
|
ca1eb8 |
+ struct tevent_req *req =
|
|
|
ca1eb8 |
+ tevent_req_callback_data(subreq, struct tevent_req);
|
|
|
ca1eb8 |
+ struct resolv_hostport_list_state *state = tevent_req_data(req,
|
|
|
ca1eb8 |
+ struct resolv_hostport_list_state);
|
|
|
ca1eb8 |
+ struct resolv_hostent *rhostent;
|
|
|
ca1eb8 |
+ int resolv_status;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ ret = resolv_gethostbyname_recv(subreq, state, &resolv_status, NULL,
|
|
|
ca1eb8 |
+ &rhostent);
|
|
|
ca1eb8 |
+ talloc_zfree(subreq);
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ if (ret != EOK) {
|
|
|
ca1eb8 |
+ /* Don't abort the request, just go to the next one */
|
|
|
ca1eb8 |
+ DEBUG(SSSDBG_OP_FAILURE,
|
|
|
ca1eb8 |
+ "Could not resolve address for this machine, error [%d]: %s, "
|
|
|
ca1eb8 |
+ "resolver returned: [%d]: %s\n", ret, sss_strerror(ret),
|
|
|
ca1eb8 |
+ resolv_status, resolv_strerror(resolv_status));
|
|
|
ca1eb8 |
+ } else {
|
|
|
ca1eb8 |
+ state->rhp_addrs[state->addrindex] = \
|
|
|
ca1eb8 |
+ resolv_hostport_addr_new(state->rhp_addrs,
|
|
|
ca1eb8 |
+ state->hostport_list[state->hpindex].host,
|
|
|
ca1eb8 |
+ state->hostport_list[state->hpindex].port,
|
|
|
ca1eb8 |
+ rhostent);
|
|
|
ca1eb8 |
+ state->addrindex++;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ if (state->limit > 0 && state->addrindex >= state->limit) {
|
|
|
ca1eb8 |
+ DEBUG(SSSDBG_TRACE_INTERNAL,
|
|
|
ca1eb8 |
+ "Reached the limit or addresses to resolve\n");
|
|
|
ca1eb8 |
+ tevent_req_done(req);
|
|
|
ca1eb8 |
+ return;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ state->hpindex++;
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ ret = resolv_hostport_list_step(req);
|
|
|
ca1eb8 |
+ if (ret == EOK) {
|
|
|
ca1eb8 |
+ tevent_req_done(req);
|
|
|
ca1eb8 |
+ return;
|
|
|
ca1eb8 |
+ } else if (ret != EAGAIN) {
|
|
|
ca1eb8 |
+ tevent_req_error(req, ret);
|
|
|
ca1eb8 |
+ return;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+ /* Next iteration .. */
|
|
|
ca1eb8 |
+}
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+int resolv_hostport_list_recv(struct tevent_req *req,
|
|
|
ca1eb8 |
+ TALLOC_CTX *mem_ctx,
|
|
|
ca1eb8 |
+ size_t *_rhp_len,
|
|
|
ca1eb8 |
+ struct resolv_hostport_addr ***_rhp_addrs)
|
|
|
ca1eb8 |
+{
|
|
|
ca1eb8 |
+ struct resolv_hostport_list_state *state = tevent_req_data(req,
|
|
|
ca1eb8 |
+ struct resolv_hostport_list_state);
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ if (_rhp_len) {
|
|
|
ca1eb8 |
+ *_rhp_len = state->addrindex;
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ if (_rhp_addrs) {
|
|
|
ca1eb8 |
+ *_rhp_addrs = talloc_steal(mem_ctx, state->rhp_addrs);
|
|
|
ca1eb8 |
+ }
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+ return EOK;
|
|
|
ca1eb8 |
+}
|
|
|
ca1eb8 |
diff --git a/src/resolv/async_resolv.h b/src/resolv/async_resolv.h
|
|
|
ca1eb8 |
index b602a425c21b5f3bfd0098ce3208f6750d4ed1ad..90ed037075c7becb0f8bcd580b218092f2d8579e 100644
|
|
|
ca1eb8 |
--- a/src/resolv/async_resolv.h
|
|
|
ca1eb8 |
+++ b/src/resolv/async_resolv.h
|
|
|
ca1eb8 |
@@ -112,6 +112,36 @@ int resolv_gethostbyname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
|
|
|
ca1eb8 |
int *status, int *timeouts,
|
|
|
ca1eb8 |
struct resolv_hostent **rhostent);
|
|
|
ca1eb8 |
|
|
|
ca1eb8 |
+struct resolv_hostport {
|
|
|
ca1eb8 |
+ const char *host;
|
|
|
ca1eb8 |
+ int port;
|
|
|
ca1eb8 |
+};
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+struct resolv_hostport_addr {
|
|
|
ca1eb8 |
+ struct resolv_hostport origin;
|
|
|
ca1eb8 |
+ struct resolv_hostent *reply;
|
|
|
ca1eb8 |
+};
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+/* Resolves a list of resolv_hostport tuples into a list of
|
|
|
ca1eb8 |
+ * resolv_hostport_addr. Any unresolvable addresses are skipped.
|
|
|
ca1eb8 |
+ *
|
|
|
ca1eb8 |
+ * Optionally takes a limit argument and stops after the request
|
|
|
ca1eb8 |
+ * had resolved addresses up to the limit.
|
|
|
ca1eb8 |
+ */
|
|
|
ca1eb8 |
+struct tevent_req *resolv_hostport_list_send(TALLOC_CTX *mem_ctx,
|
|
|
ca1eb8 |
+ struct tevent_context *ev,
|
|
|
ca1eb8 |
+ struct resolv_ctx *ctx,
|
|
|
ca1eb8 |
+ struct resolv_hostport *hostport_list,
|
|
|
ca1eb8 |
+ size_t list_size,
|
|
|
ca1eb8 |
+ size_t limit,
|
|
|
ca1eb8 |
+ enum restrict_family family_order,
|
|
|
ca1eb8 |
+ enum host_database *db);
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
+int resolv_hostport_list_recv(struct tevent_req *req,
|
|
|
ca1eb8 |
+ TALLOC_CTX *mem_ctx,
|
|
|
ca1eb8 |
+ size_t *_rhp_len,
|
|
|
ca1eb8 |
+ struct resolv_hostport_addr ***_rhp_addrs);
|
|
|
ca1eb8 |
+
|
|
|
ca1eb8 |
char *
|
|
|
ca1eb8 |
resolv_get_string_address_index(TALLOC_CTX *mem_ctx,
|
|
|
ca1eb8 |
struct resolv_hostent *hostent,
|
|
|
ca1eb8 |
--
|
|
|
ca1eb8 |
2.17.1
|
|
|
ca1eb8 |
|