Blame SOURCES/0024-RESOLV-Add-a-resolv_hostport_list-request.patch

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