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

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