Blame SOURCES/0078-autofs-convert-code-to-cache_req.patch

8d3578
From b0043a95f86b240d0beb551ef4e9ff9a4be99995 Mon Sep 17 00:00:00 2001
8d3578
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
8d3578
Date: Wed, 7 Aug 2019 13:59:04 +0200
8d3578
Subject: [PATCH 78/90] autofs: convert code to cache_req
8d3578
MIME-Version: 1.0
8d3578
Content-Type: text/plain; charset=UTF-8
8d3578
Content-Transfer-Encoding: 8bit
8d3578
8d3578
This will simplify the code a lot so it can be further extended.
8d3578
At this point the conversion is done 1:1, we will do additional
8d3578
changes in next patches.
8d3578
8d3578
Resolves:
8d3578
https://pagure.io/SSSD/sssd/issue/2607
8d3578
8d3578
Reviewed-by: Tomáš Halman <thalman@redhat.com>
8d3578
---
8d3578
 src/responder/autofs/autofs_private.h |   72 +-
8d3578
 src/responder/autofs/autofssrv.c      |    7 +-
8d3578
 src/responder/autofs/autofssrv_cmd.c  | 1651 ++++++++-----------------
8d3578
 3 files changed, 549 insertions(+), 1181 deletions(-)
8d3578
8d3578
diff --git a/src/responder/autofs/autofs_private.h b/src/responder/autofs/autofs_private.h
8d3578
index 6a39b17ad..3be25d4d9 100644
8d3578
--- a/src/responder/autofs/autofs_private.h
8d3578
+++ b/src/responder/autofs/autofs_private.h
8d3578
@@ -21,7 +21,9 @@
8d3578
 #ifndef _AUTOFSSRV_PRIVATE_H_
8d3578
 #define _AUTOFSSRV_PRIVATE_H_
8d3578
 
8d3578
+#include "responder/common/responder.h"
8d3578
 #include "responder/common/responder_sbus.h"
8d3578
+#include "responder/common/cache_req/cache_req.h"
8d3578
 
8d3578
 #define SSS_AUTOFS_PROTO_VERSION        0x001
8d3578
 
8d3578
@@ -33,75 +35,33 @@ struct autofs_ctx {
8d3578
     hash_table_t *maps;
8d3578
 };
8d3578
 
8d3578
-struct autofs_state_ctx {
8d3578
-    char *automntmap_name;
8d3578
-};
8d3578
-
8d3578
 struct autofs_cmd_ctx {
8d3578
-    struct cli_ctx *cctx;
8d3578
-    char *mapname;
8d3578
-    char *key;
8d3578
-    uint32_t cursor;
8d3578
+    struct autofs_ctx *autofs_ctx;
8d3578
+    struct cli_ctx *cli_ctx;
8d3578
+
8d3578
+    const char *mapname;
8d3578
+    const char *keyname;
8d3578
     uint32_t max_entries;
8d3578
-    bool check_next;
8d3578
+    uint32_t cursor;
8d3578
 };
8d3578
 
8d3578
-struct autofs_dom_ctx {
8d3578
-    struct autofs_cmd_ctx  *cmd_ctx;
8d3578
-    struct sss_domain_info *domain;
8d3578
-    bool check_provider;
8d3578
-
8d3578
-    /* cache results */
8d3578
-    struct ldb_message *map;
8d3578
-
8d3578
-    size_t entry_count;
8d3578
-    struct ldb_message **entries;
8d3578
-
8d3578
-    struct autofs_map_ctx *map_ctx;
8d3578
-};
8d3578
+struct autofs_enum_ctx {
8d3578
+    /* Results. First result is the map objects, next results are map entries. */
8d3578
+    struct cache_req_result *result;
8d3578
 
8d3578
-struct autofs_map_ctx {
8d3578
-    /* state of the map entry */
8d3578
-    bool ready;
8d3578
+    /* True if the map was found. */
8d3578
     bool found;
8d3578
 
8d3578
-    /* requests */
8d3578
-    struct setent_req_list *reqs;
8d3578
-
8d3578
-    hash_table_t *map_table;
8d3578
-    char *mapname;
8d3578
+    /* False if the result is being created. */
8d3578
+    bool ready;
8d3578
 
8d3578
-    /* map entry */
8d3578
-    struct ldb_message *map;
8d3578
-    size_t entry_count;
8d3578
-    struct ldb_message **entries;
8d3578
+    /* Requests that awaits the data. */
8d3578
+    struct setent_req_list *notify_list;
8d3578
 };
8d3578
 
8d3578
 struct sss_cmd_table *get_autofs_cmds(void);
8d3578
 int autofs_connection_setup(struct cli_ctx *cctx);
8d3578
 
8d3578
-void autofs_map_hash_delete_cb(hash_entry_t *item,
8d3578
-                               hash_destroy_enum deltype, void *pvt);
8d3578
-
8d3578
 errno_t autofs_orphan_maps(struct autofs_ctx *actx);
8d3578
 
8d3578
-enum sss_dp_autofs_type {
8d3578
-    SSS_DP_AUTOFS
8d3578
-};
8d3578
-
8d3578
-struct tevent_req *
8d3578
-sss_dp_get_autofs_send(TALLOC_CTX *mem_ctx,
8d3578
-                       struct resp_ctx *rctx,
8d3578
-                       struct sss_domain_info *dom,
8d3578
-                       bool fast_reply,
8d3578
-                       enum sss_dp_autofs_type type,
8d3578
-                       const char *name);
8d3578
-
8d3578
-errno_t
8d3578
-sss_dp_get_autofs_recv(TALLOC_CTX *mem_ctx,
8d3578
-                       struct tevent_req *req,
8d3578
-                       dbus_uint16_t *dp_err,
8d3578
-                       dbus_uint32_t *dp_ret,
8d3578
-                       char **err_msg);
8d3578
-
8d3578
 #endif /* _AUTOFSSRV_PRIVATE_H_ */
8d3578
diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c
8d3578
index 7d236f4d9..309ed76b1 100644
8d3578
--- a/src/responder/autofs/autofssrv.c
8d3578
+++ b/src/responder/autofs/autofssrv.c
8d3578
@@ -28,6 +28,7 @@
8d3578
 #include "responder/common/responder.h"
8d3578
 #include "providers/data_provider.h"
8d3578
 #include "responder/autofs/autofs_private.h"
8d3578
+#include "util/sss_ptr_hash.h"
8d3578
 
8d3578
 static int autofs_clean_hash_table(struct sbus_request *dbus_req, void *data);
8d3578
 
8d3578
@@ -105,7 +106,6 @@ autofs_process_init(TALLOC_CTX *mem_ctx,
8d3578
     struct autofs_ctx *autofs_ctx;
8d3578
     struct be_conn *iter;
8d3578
     int ret;
8d3578
-    int hret;
8d3578
     int max_retries;
8d3578
 
8d3578
     autofs_cmds = get_autofs_cmds();
8d3578
@@ -158,9 +158,8 @@ autofs_process_init(TALLOC_CTX *mem_ctx,
8d3578
     }
8d3578
 
8d3578
     /* Create the lookup table for setautomntent results */
8d3578
-    hret = sss_hash_create_ex(autofs_ctx, 10, &autofs_ctx->maps, 0, 0, 0, 0,
8d3578
-                              autofs_map_hash_delete_cb, NULL);
8d3578
-    if (hret != HASH_SUCCESS) {
8d3578
+    autofs_ctx->maps = sss_ptr_hash_create(autofs_ctx, NULL, NULL);
8d3578
+    if (autofs_ctx->maps == NULL) {
8d3578
         DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
               "Unable to initialize automount maps hash table\n");
8d3578
         ret = EIO;
8d3578
diff --git a/src/responder/autofs/autofssrv_cmd.c b/src/responder/autofs/autofssrv_cmd.c
8d3578
index 9ea2ab71b..670b6d50d 100644
8d3578
--- a/src/responder/autofs/autofssrv_cmd.c
8d3578
+++ b/src/responder/autofs/autofssrv_cmd.c
8d3578
@@ -25,20 +25,22 @@
8d3578
 #include "util/util.h"
8d3578
 #include "responder/common/responder.h"
8d3578
 #include "responder/common/responder_packet.h"
8d3578
+#include "responder/common/cache_req/cache_req.h"
8d3578
 #include "responder/autofs/autofs_private.h"
8d3578
 #include "db/sysdb.h"
8d3578
 #include "db/sysdb_autofs.h"
8d3578
 #include "confdb/confdb.h"
8d3578
+#include "util/sss_ptr_hash.h"
8d3578
 
8d3578
 static int autofs_cmd_send_error(struct autofs_cmd_ctx *cmdctx, int err)
8d3578
 {
8d3578
-    return sss_cmd_send_error(cmdctx->cctx, err);
8d3578
+    return sss_cmd_send_error(cmdctx->cli_ctx, err);
8d3578
 }
8d3578
 
8d3578
 static int
8d3578
 autofs_cmd_send_empty(struct autofs_cmd_ctx *cmdctx)
8d3578
 {
8d3578
-    return sss_cmd_send_empty(cmdctx->cctx);
8d3578
+    return sss_cmd_send_empty(cmdctx->cli_ctx);
8d3578
 }
8d3578
 
8d3578
 static int
8d3578
@@ -54,7 +56,7 @@ autofs_cmd_done(struct autofs_cmd_ctx *cmdctx, int ret)
8d3578
         if (ret) {
8d3578
             return EFAULT;
8d3578
         }
8d3578
-        sss_cmd_done(cmdctx->cctx, cmdctx);
8d3578
+        sss_cmd_done(cmdctx->cli_ctx, cmdctx);
8d3578
         break;
8d3578
 
8d3578
     case EAGAIN:
8d3578
@@ -70,7 +72,7 @@ autofs_cmd_done(struct autofs_cmd_ctx *cmdctx, int ret)
8d3578
         if (ret) {
8d3578
             return EFAULT;
8d3578
         }
8d3578
-        sss_cmd_done(cmdctx->cctx, cmdctx);
8d3578
+        sss_cmd_done(cmdctx->cli_ctx, cmdctx);
8d3578
         break;
8d3578
     }
8d3578
 
8d3578
@@ -78,1058 +80,524 @@ autofs_cmd_done(struct autofs_cmd_ctx *cmdctx, int ret)
8d3578
 }
8d3578
 
8d3578
 static errno_t
8d3578
-autofs_setent_add_ref(TALLOC_CTX *memctx,
8d3578
-                      struct autofs_map_ctx *map_ctx,
8d3578
-                      struct tevent_req *req)
8d3578
+autofs_fill_entry(struct ldb_message *entry, struct sss_packet *packet, size_t *rp)
8d3578
 {
8d3578
-    return setent_add_ref(memctx, &map_ctx->reqs, req);
8d3578
-}
8d3578
-
8d3578
-static void
8d3578
-autofs_setent_notify(struct autofs_map_ctx *map_ctx, errno_t ret)
8d3578
-{
8d3578
-    setent_notify(&map_ctx->reqs, ret);
8d3578
-}
8d3578
-
8d3578
-errno_t
8d3578
-autofs_orphan_maps(struct autofs_ctx *actx)
8d3578
-{
8d3578
-    int hret;
8d3578
-    unsigned long mcount;
8d3578
-    unsigned long i;
8d3578
-    hash_key_t *maps;
8d3578
+    errno_t ret;
8d3578
+    const char *key;
8d3578
+    size_t keylen;
8d3578
+    const char *value;
8d3578
+    size_t valuelen;
8d3578
+    uint8_t *body;
8d3578
+    size_t blen;
8d3578
+    size_t len;
8d3578
 
8d3578
-    if (!actx || !actx->maps) {
8d3578
+    key = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_KEY, NULL);
8d3578
+    value = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_VALUE, NULL);
8d3578
+    if (!key || !value) {
8d3578
+        DEBUG(SSSDBG_MINOR_FAILURE, "Incomplete entry\n");
8d3578
         return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    hret = hash_keys(actx->maps, &mcount, &maps);
8d3578
-    if (hret != HASH_SUCCESS) {
8d3578
-        return EIO;
8d3578
-    }
8d3578
-
8d3578
-    for (i = 0; i < mcount; i++) {
8d3578
-        hret = hash_delete(actx->maps, &maps[i]);
8d3578
-        if (hret != HASH_SUCCESS) {
8d3578
-            DEBUG(SSSDBG_MINOR_FAILURE, "Could not delete key from hash\n");
8d3578
-            continue;
8d3578
-        }
8d3578
-    }
8d3578
-
8d3578
-    return EOK;
8d3578
-}
8d3578
+    keylen = 1 + strlen(key);
8d3578
+    valuelen = 1 + strlen(value);
8d3578
+    len = sizeof(uint32_t) + sizeof(uint32_t) + keylen + sizeof(uint32_t) + valuelen;
8d3578
 
8d3578
-static errno_t
8d3578
-get_autofs_map(struct autofs_ctx *actx,
8d3578
-               char *mapname,
8d3578
-               struct autofs_map_ctx **map)
8d3578
-{
8d3578
-    hash_key_t key;
8d3578
-    hash_value_t value;
8d3578
-    int hret;
8d3578
-
8d3578
-    key.type = HASH_KEY_STRING;
8d3578
-    key.str = mapname;
8d3578
-
8d3578
-    hret = hash_lookup(actx->maps, &key, &value);
8d3578
-    if (hret == HASH_SUCCESS) {
8d3578
-        *map = talloc_get_type(value.ptr, struct autofs_map_ctx);
8d3578
-        return EOK;
8d3578
-    } else if (hret == HASH_ERROR_KEY_NOT_FOUND) {
8d3578
-        return ENOENT;
8d3578
+    ret = sss_packet_grow(packet, len);
8d3578
+    if (ret != EOK) {
8d3578
+        DEBUG(SSSDBG_OP_FAILURE, "Cannot grow packet\n");
8d3578
+        return ret;
8d3578
     }
8d3578
 
8d3578
-    DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-          "Unexpected error reading from autofs map hash [%d][%s]\n",
8d3578
-          hret, hash_error_string(hret));
8d3578
-    return EIO;
8d3578
-}
8d3578
-
8d3578
-static int autofs_map_hash_remove (TALLOC_CTX *ctx);
8d3578
+    sss_packet_get_body(packet, &body, &blen);
8d3578
 
8d3578
-void
8d3578
-autofs_map_hash_delete_cb(hash_entry_t *item,
8d3578
-                          hash_destroy_enum deltype, void *pvt)
8d3578
-{
8d3578
-    struct autofs_map_ctx *map;
8d3578
+    SAFEALIGN_SET_UINT32(&body[*rp], len, rp);
8d3578
+    SAFEALIGN_SET_UINT32(&body[*rp], keylen, rp);
8d3578
 
8d3578
-    if (deltype != HASH_ENTRY_DESTROY) {
8d3578
-        return;
8d3578
+    if (keylen == 1) {
8d3578
+        body[*rp] = '\0';
8d3578
+    } else {
8d3578
+        memcpy(&body[*rp], key, keylen);
8d3578
     }
8d3578
+    *rp += keylen;
8d3578
 
8d3578
-    map = talloc_get_type(item->value.ptr, struct autofs_map_ctx);
8d3578
-    if (!map) {
8d3578
-        DEBUG(SSSDBG_OP_FAILURE, "Invalid autofs map\n");
8d3578
-        return;
8d3578
+    SAFEALIGN_SET_UINT32(&body[*rp], valuelen, rp);
8d3578
+    if (valuelen == 1) {
8d3578
+        body[*rp] = '\0';
8d3578
+    } else {
8d3578
+        memcpy(&body[*rp], value, valuelen);
8d3578
     }
8d3578
+    *rp += valuelen;
8d3578
 
8d3578
-    /* So that the destructor wouldn't attempt to remove the map from hash
8d3578
-     * table */
8d3578
-    map->map_table = NULL;
8d3578
+    return EOK;
8d3578
 }
8d3578
 
8d3578
-static errno_t
8d3578
-set_autofs_map(struct autofs_ctx *actx,
8d3578
-               struct autofs_map_ctx *map)
8d3578
+errno_t
8d3578
+autofs_orphan_maps(struct autofs_ctx *autofs_ctx)
8d3578
 {
8d3578
-    hash_key_t key;
8d3578
-    hash_value_t value;
8d3578
-    int hret;
8d3578
-
8d3578
-    if (map->mapname == NULL) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE, "Missing autofs map name.\n");
8d3578
-        return EINVAL;
8d3578
-    }
8d3578
-
8d3578
-    /* Add this entry to the hash table */
8d3578
-    key.type = HASH_KEY_STRING;
8d3578
-    key.str = map->mapname;
8d3578
-    value.type = HASH_VALUE_PTR;
8d3578
-    value.ptr = map;
8d3578
-    hret = hash_enter(actx->maps, &key, &value);
8d3578
-    if (hret != EOK) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Unable to add hash table entry for [%s]\n", key.str);
8d3578
-        DEBUG(SSSDBG_MINOR_FAILURE,
8d3578
-              "Hash error [%d][%s]\n", hret, hash_error_string(hret));
8d3578
-        return EIO;
8d3578
-    }
8d3578
-    talloc_steal(actx->maps, map);
8d3578
-    talloc_set_destructor((TALLOC_CTX *) map, autofs_map_hash_remove);
8d3578
+    sss_ptr_hash_delete_all(autofs_ctx->maps, true);
8d3578
 
8d3578
     return EOK;
8d3578
 }
8d3578
 
8d3578
-static int
8d3578
-autofs_map_hash_remove(TALLOC_CTX *ctx)
8d3578
+static void
8d3578
+autofs_enumctx_lifetime_timeout(struct tevent_context *ev,
8d3578
+                                struct tevent_timer *te,
8d3578
+                                struct timeval current_time,
8d3578
+                                void *pvt)
8d3578
 {
8d3578
-    int hret;
8d3578
-    hash_key_t key;
8d3578
-    struct autofs_map_ctx *map =
8d3578
-            talloc_get_type(ctx, struct autofs_map_ctx);
8d3578
-
8d3578
-    if (map->map_table == NULL) {
8d3578
-        DEBUG(SSSDBG_TRACE_LIBS, "autofs map [%s] was already removed\n",
8d3578
-              map->mapname);
8d3578
-        return 0;
8d3578
-    }
8d3578
+    struct autofs_enum_ctx *enum_ctx;
8d3578
 
8d3578
-    key.type = HASH_KEY_STRING;
8d3578
-    key.str = map->mapname;
8d3578
+    enum_ctx = talloc_get_type(pvt, struct autofs_enum_ctx);
8d3578
 
8d3578
-    /* Remove the autofs map result object from the lookup table */
8d3578
-    hret = hash_delete(map->map_table, &key);
8d3578
-    if (hret != HASH_SUCCESS) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Could not remove key from table! [%d][%s]\n",
8d3578
-              hret, hash_error_string(hret));
8d3578
-        return -1;
8d3578
-    }
8d3578
-    return 0;
8d3578
+    /* Free the context. It will be automatically removed from the hash table. */
8d3578
+    talloc_free(enum_ctx);
8d3578
 }
8d3578
 
8d3578
-static struct tevent_req *
8d3578
-setautomntent_send(TALLOC_CTX *mem_ctx,
8d3578
-                   const char *rawname,
8d3578
-                   struct autofs_cmd_ctx *cmdctx);
8d3578
-static errno_t setautomntent_recv(struct tevent_req *req);
8d3578
-static void sss_autofs_cmd_setautomntent_done(struct tevent_req *req);
8d3578
-
8d3578
-/* FIXME - file a ticket to have per-responder private
8d3578
- * data instead of growing the cli_ctx structure */
8d3578
-static int
8d3578
-sss_autofs_cmd_setautomntent(struct cli_ctx *client)
8d3578
+static void
8d3578
+autofs_set_enumctx_lifetime(struct autofs_ctx *autofs_ctx,
8d3578
+                            struct autofs_enum_ctx *enum_ctx,
8d3578
+                            uint32_t lifetime)
8d3578
 {
8d3578
-    struct autofs_cmd_ctx *cmdctx;
8d3578
-    struct cli_protocol *pctx;
8d3578
-    uint8_t *body;
8d3578
-    size_t blen;
8d3578
-    errno_t ret = EOK;
8d3578
-    const char *rawname;
8d3578
-    struct tevent_req *req;
8d3578
-
8d3578
-    DEBUG(SSSDBG_TRACE_INTERNAL, "sss_autofs_cmd_setautomntent\n");
8d3578
-
8d3578
-    cmdctx = talloc_zero(client, struct autofs_cmd_ctx);
8d3578
-    if (!cmdctx) {
8d3578
-        return ENOMEM;
8d3578
-    }
8d3578
-    cmdctx->cctx = client;
8d3578
-
8d3578
-    pctx = talloc_get_type(cmdctx->cctx->protocol_ctx, struct cli_protocol);
8d3578
-
8d3578
-    sss_packet_get_body(pctx->creq->in, &body, &blen);
8d3578
-
8d3578
-    /* if not terminated fail */
8d3578
-    if (body[blen -1] != '\0') {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
-    }
8d3578
-
8d3578
-    /* If the body isn't valid UTF-8, fail */
8d3578
-    if (!sss_utf8_check(body, blen -1)) {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
-    }
8d3578
-
8d3578
-    rawname = (const char *)body;
8d3578
-    DEBUG(SSSDBG_TRACE_FUNC,
8d3578
-          "Got request for automount map named %s\n", rawname);
8d3578
+    struct timeval tv;
8d3578
+    struct tevent_timer *te;
8d3578
 
8d3578
-    req = setautomntent_send(cmdctx, rawname, cmdctx);
8d3578
-    if (!req) {
8d3578
+    tv = tevent_timeval_current_ofs(lifetime, 0);
8d3578
+    te = tevent_add_timer(autofs_ctx->rctx->ev, enum_ctx, tv,
8d3578
+                          autofs_enumctx_lifetime_timeout, enum_ctx);
8d3578
+    if (te == NULL) {
8d3578
         DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Fatal error calling setautomntent_send\n");
8d3578
-        ret = EIO;
8d3578
-        goto done;
8d3578
+              "Could not set up life timer for autofs maps. "
8d3578
+              "Entries may become stale.\n");
8d3578
     }
8d3578
-    tevent_req_set_callback(req, sss_autofs_cmd_setautomntent_done, cmdctx);
8d3578
-
8d3578
-    ret = EOK;
8d3578
-done:
8d3578
-    return autofs_cmd_done(cmdctx, ret);
8d3578
 }
8d3578
 
8d3578
-static void sss_autofs_cmd_setautomntent_done(struct tevent_req *req)
8d3578
+static struct autofs_enum_ctx *
8d3578
+autofs_create_enumeration_context(TALLOC_CTX *mem_ctx,
8d3578
+                                  struct autofs_ctx *autofs_ctx,
8d3578
+                                  const char *mapname)
8d3578
 {
8d3578
-    struct autofs_cmd_ctx *cmdctx =
8d3578
-        tevent_req_callback_data(req, struct autofs_cmd_ctx);
8d3578
-    struct cli_protocol *pctx;
8d3578
+    struct autofs_enum_ctx *enum_ctx;
8d3578
     errno_t ret;
8d3578
-    errno_t reqret;
8d3578
-    uint8_t *body;
8d3578
-    size_t blen;
8d3578
 
8d3578
-    DEBUG(SSSDBG_TRACE_INTERNAL, "setautomntent done\n");
8d3578
-
8d3578
-    reqret = setautomntent_recv(req);
8d3578
-    talloc_zfree(req);
8d3578
-    if (reqret != EOK && reqret != ENOENT) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_recv failed\n");
8d3578
-        autofs_cmd_done(cmdctx, reqret);
8d3578
-        return;
8d3578
+    enum_ctx = talloc_zero(mem_ctx, struct autofs_enum_ctx);
8d3578
+    if (enum_ctx == NULL) {
8d3578
+        return NULL;
8d3578
     }
8d3578
 
8d3578
-    pctx = talloc_get_type(cmdctx->cctx->protocol_ctx, struct cli_protocol);
8d3578
+    enum_ctx->ready = false;
8d3578
 
8d3578
-    /* Either we succeeded or no domains were eligible */
8d3578
-    ret = sss_packet_new(pctx->creq, 0,
8d3578
-                         sss_packet_get_cmd(pctx->creq->in),
8d3578
-                         &pctx->creq->out);
8d3578
-    if (ret == EOK) {
8d3578
-        if (reqret == ENOENT) {
8d3578
-            DEBUG(SSSDBG_TRACE_FUNC, "setautomntent did not find requested map\n");
8d3578
-            /* Notify the caller that this entry wasn't found */
8d3578
-            ret = sss_cmd_empty_packet(pctx->creq->out);
8d3578
-            if (ret != EOK) {
8d3578
-                DEBUG(SSSDBG_TRACE_INTERNAL,
8d3578
-                      "sss_cmd_empty_packet() failed: %s [%d]\n",
8d3578
-                      sss_strerror(ret), ret);
8d3578
-            }
8d3578
-        } else {
8d3578
-            DEBUG(SSSDBG_TRACE_FUNC, "setautomntent found data\n");
8d3578
-            ret = sss_packet_grow(pctx->creq->out, 2*sizeof(uint32_t));
8d3578
-            if (ret != EOK) {
8d3578
-                DEBUG(SSSDBG_CRIT_FAILURE, "Couldn't grow the packet\n");
8d3578
-                talloc_free(cmdctx);
8d3578
-                return;
8d3578
-            }
8d3578
-
8d3578
-            sss_packet_get_body(pctx->creq->out, &body, &blen);
8d3578
-
8d3578
-            /* Got some results */
8d3578
-            SAFEALIGN_SETMEM_UINT32(body, 1, NULL);
8d3578
-
8d3578
-            /* Reserved padding */
8d3578
-            SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), 0, NULL);
8d3578
-        }
8d3578
-
8d3578
-        sss_cmd_done(cmdctx->cctx, NULL);
8d3578
-        return;
8d3578
+    ret = sss_ptr_hash_add(autofs_ctx->maps, mapname,
8d3578
+                           enum_ctx, struct autofs_enum_ctx);
8d3578
+    if (ret != EOK) {
8d3578
+        talloc_free(enum_ctx);
8d3578
+        return NULL;
8d3578
     }
8d3578
 
8d3578
-    DEBUG(SSSDBG_CRIT_FAILURE, "Error creating packet\n");
8d3578
-    return;
8d3578
+    return enum_ctx;
8d3578
 }
8d3578
 
8d3578
-struct setautomntent_state {
8d3578
-    struct autofs_cmd_ctx *cmdctx;
8d3578
-    struct autofs_dom_ctx *dctx;
8d3578
-
8d3578
-    char *mapname;
8d3578
-    struct autofs_map_ctx *map;
8d3578
+struct autofs_setent_state {
8d3578
+    struct autofs_ctx *autofs_ctx;
8d3578
+    struct autofs_enum_ctx *enum_ctx;
8d3578
 };
8d3578
 
8d3578
-struct setautomntent_lookup_ctx {
8d3578
-    struct autofs_ctx *actx;
8d3578
-    struct autofs_dom_ctx *dctx;
8d3578
-    struct resp_ctx *rctx;
8d3578
-    struct cli_ctx *cctx;
8d3578
-
8d3578
-    bool returned_to_mainloop;
8d3578
-
8d3578
-    char *mapname;
8d3578
-    struct autofs_map_ctx *map;
8d3578
-};
8d3578
-
8d3578
-static errno_t
8d3578
-lookup_automntmap_step(struct setautomntent_lookup_ctx *lookup_ctx);
8d3578
-
8d3578
-static void
8d3578
-autofs_map_result_timeout(struct tevent_context *ev,
8d3578
-                          struct tevent_timer *te,
8d3578
-                          struct timeval current_time,
8d3578
-                          void *pvt)
8d3578
-{
8d3578
-    struct autofs_map_ctx *map =
8d3578
-            talloc_get_type(pvt, struct autofs_map_ctx);
8d3578
-
8d3578
-    /* Free the autofs map result context
8d3578
-     * The destructor for the autofs map will remove itself
8d3578
-     * from the hash table
8d3578
-     */
8d3578
-    talloc_free(map);
8d3578
-}
8d3578
-
8d3578
-static void
8d3578
-set_autofs_map_lifetime(uint32_t lifetime,
8d3578
-                        struct setautomntent_lookup_ctx *lookup_ctx,
8d3578
-                        struct autofs_map_ctx *map)
8d3578
-{
8d3578
-    struct timeval tv;
8d3578
-    struct tevent_timer *te;
8d3578
-
8d3578
-    tv = tevent_timeval_current_ofs(lifetime, 0);
8d3578
-    te = tevent_add_timer(lookup_ctx->rctx->ev,
8d3578
-                          map, tv,
8d3578
-                          autofs_map_result_timeout,
8d3578
-                          map);
8d3578
-    if (!te) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Could not set up life timer for autofs maps. "
8d3578
-               "Entries may become stale.\n");
8d3578
-    }
8d3578
-}
8d3578
-
8d3578
-static errno_t
8d3578
-setautomntent_get_autofs_map(struct autofs_ctx *actx,
8d3578
-                             char *mapname,
8d3578
-                             struct autofs_map_ctx **map);
8d3578
+static void autofs_setent_done(struct tevent_req *subreq);
8d3578
 
8d3578
 static struct tevent_req *
8d3578
-setautomntent_send(TALLOC_CTX *mem_ctx,
8d3578
-                   const char *rawname,
8d3578
-                   struct autofs_cmd_ctx *cmdctx)
8d3578
+autofs_setent_send(TALLOC_CTX *mem_ctx,
8d3578
+                   struct tevent_context *ev,
8d3578
+                   struct autofs_ctx *autofs_ctx,
8d3578
+                   const char *mapname)
8d3578
 {
8d3578
-    char *domname;
8d3578
-    errno_t ret;
8d3578
+    struct autofs_setent_state *state;
8d3578
+    struct tevent_req *subreq;
8d3578
     struct tevent_req *req;
8d3578
-    struct setautomntent_state *state;
8d3578
-    struct cli_ctx *client = cmdctx->cctx;
8d3578
-    struct autofs_dom_ctx *dctx;
8d3578
-    struct autofs_ctx *actx;
8d3578
-    struct autofs_state_ctx *state_ctx;
8d3578
-    struct setautomntent_lookup_ctx *lookup_ctx;
8d3578
-
8d3578
-    actx = talloc_get_type(client->rctx->pvt_ctx, struct autofs_ctx);
8d3578
-    state_ctx = talloc_get_type(client->state_ctx, struct autofs_state_ctx);
8d3578
-
8d3578
-    req = tevent_req_create(mem_ctx, &state, struct setautomntent_state);
8d3578
-    if (!req) {
8d3578
-        DEBUG(SSSDBG_FATAL_FAILURE,
8d3578
-              "Could not create tevent request for setautomntent\n");
8d3578
-        return NULL;
8d3578
-    }
8d3578
-    state->cmdctx = cmdctx;
8d3578
-
8d3578
-    dctx = talloc_zero(state, struct autofs_dom_ctx);
8d3578
-    if (!dctx) {
8d3578
-        DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory\n");
8d3578
-        ret = ENOMEM;
8d3578
-        goto fail;
8d3578
-    }
8d3578
-    dctx->cmd_ctx = state->cmdctx;
8d3578
-    state->dctx = dctx;
8d3578
+    errno_t ret;
8d3578
 
8d3578
-    ret = sss_parse_name_for_domains(state, client->rctx->domains,
8d3578
-                                     NULL, rawname,
8d3578
-                                     &domname, &state->mapname);
8d3578
-    if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_FATAL_FAILURE,
8d3578
-              "Invalid name received [%s]\n", rawname);
8d3578
-        goto fail;
8d3578
+    req = tevent_req_create(mem_ctx, &state, struct autofs_setent_state);
8d3578
+    if (req == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
8d3578
+        return NULL;
8d3578
     }
8d3578
 
8d3578
-    DEBUG(SSSDBG_TRACE_FUNC,
8d3578
-         "Requesting info for automount map [%s] from [%s]\n",
8d3578
-         state->mapname, domname?domname:"<ALL>");
8d3578
-
8d3578
-    if (domname) {
8d3578
-        dctx->domain = responder_get_domain(client->rctx, domname);
8d3578
-        if (!dctx->domain) {
8d3578
-            ret = EINVAL;
8d3578
-            goto fail;
8d3578
-        }
8d3578
+    state->autofs_ctx = autofs_ctx;
8d3578
 
8d3578
-        state_ctx->automntmap_name = talloc_strdup(client, rawname);
8d3578
-        if (!state_ctx->automntmap_name) {
8d3578
-            ret = ENOMEM;
8d3578
-            goto fail;
8d3578
-        }
8d3578
-    } else {
8d3578
-        /* this is a multidomain search */
8d3578
-        dctx->domain = client->rctx->domains;
8d3578
-        cmdctx->check_next = true;
8d3578
-
8d3578
-        state_ctx->automntmap_name = talloc_strdup(client, state->mapname);
8d3578
-        if (!state_ctx->automntmap_name) {
8d3578
-            ret = ENOMEM;
8d3578
-            goto fail;
8d3578
-        }
8d3578
-    }
8d3578
-
8d3578
-    dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
8d3578
-    /* Is the result context already available?
8d3578
-     * Check for existing lookups for this map
8d3578
-     */
8d3578
-    ret = setautomntent_get_autofs_map(actx, state->mapname, &state->map);
8d3578
-    if (ret == EOK) {
8d3578
-        /* Another process already requested this map
8d3578
-         * Check whether it's ready for processing.
8d3578
-         */
8d3578
-        if (state->map->ready) {
8d3578
-            if (state->map->found) {
8d3578
-                DEBUG(SSSDBG_TRACE_LIBS,
8d3578
-                      "Map %s is ready to be processed\n", state->mapname);
8d3578
-                tevent_req_done(req);
8d3578
-                tevent_req_post(req, actx->rctx->ev);
8d3578
-                return req;
8d3578
-            } else {
8d3578
-                DEBUG(SSSDBG_TRACE_LIBS,
8d3578
-                      "Map %s was marked as nonexistent\n", state->mapname);
8d3578
-                tevent_req_error(req, ENOENT);
8d3578
-                tevent_req_post(req, actx->rctx->ev);
8d3578
-                return req;
8d3578
-            }
8d3578
+    /* Lookup current results if available. */
8d3578
+    state->enum_ctx = sss_ptr_hash_lookup(autofs_ctx->maps, mapname,
8d3578
+                                          struct autofs_enum_ctx);
8d3578
+    if (state->enum_ctx != NULL) {
8d3578
+        if (state->enum_ctx->ready) {
8d3578
+            ret = EOK;
8d3578
+            goto done;
8d3578
         }
8d3578
 
8d3578
-        /* Result object is still being constructed
8d3578
-         * Register for notification when it's ready
8d3578
-         */
8d3578
-        DEBUG(SSSDBG_TRACE_LIBS,
8d3578
-              "Map %s is being looked up, registering for notification\n",
8d3578
-               state->mapname);
8d3578
-        ret = autofs_setent_add_ref(state, state->map, req);
8d3578
+        /* Map is still being created. We will watch the request. */
8d3578
+        ret = setent_add_ref(state, &state->enum_ctx->notify_list, req);
8d3578
         if (ret != EOK) {
8d3578
-            goto fail;
8d3578
-        }
8d3578
-        /* Will return control below */
8d3578
-    } else if (ret == ENOENT) {
8d3578
-        DEBUG(SSSDBG_TRACE_LIBS,
8d3578
-              "Map %s needs to be looked up\n", state->mapname);
8d3578
-
8d3578
-        state->map = talloc_zero(actx, struct autofs_map_ctx);
8d3578
-        if (!state->map) {
8d3578
-            ret = ENOMEM;
8d3578
-            goto fail;
8d3578
-        }
8d3578
-        dctx->map_ctx = state->map;
8d3578
-
8d3578
-        state->map->mapname = talloc_strdup(state->map, state->mapname);
8d3578
-        if (!state->map->mapname) {
8d3578
-            talloc_free(state->map);
8d3578
-            ret = ENOMEM;
8d3578
-            goto fail;
8d3578
+            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to watch enumeration request "
8d3578
+                  "[%d]: %s\n", ret, sss_strerror(ret));
8d3578
+            goto done;
8d3578
         }
8d3578
-        state->map->map_table = actx->maps;
8d3578
 
8d3578
-        ret = autofs_setent_add_ref(state, state->map, req);
8d3578
-        if (ret != EOK) {
8d3578
-            talloc_free(state->map);
8d3578
-            goto fail;
8d3578
-        }
8d3578
+        ret = EAGAIN;
8d3578
+        goto done;
8d3578
+    }
8d3578
 
8d3578
-        ret = set_autofs_map(actx, state->map);
8d3578
-        if (ret != EOK) {
8d3578
-            talloc_free(state->map);
8d3578
-            goto fail;
8d3578
-        }
8d3578
+    /* Map does not yet exist. Create the enumeration object and fetch data. */
8d3578
+    state->enum_ctx = autofs_create_enumeration_context(state, autofs_ctx, mapname);
8d3578
+    if (state->enum_ctx == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create enumeration context!\n");
8d3578
+        ret = ENOMEM;
8d3578
+        goto done;
8d3578
+    }
8d3578
 
8d3578
-        /* Perform lookup */
8d3578
-        lookup_ctx = talloc_zero(state->map, struct setautomntent_lookup_ctx);
8d3578
-        if (!lookup_ctx) {
8d3578
-            talloc_free(state->map);
8d3578
-            ret = ENOMEM;
8d3578
-            goto fail;
8d3578
-        }
8d3578
+    subreq = cache_req_autofs_map_entries_send(mem_ctx, ev, autofs_ctx->rctx,
8d3578
+                                               autofs_ctx->rctx->ncache,
8d3578
+                                               0, NULL, mapname);
8d3578
+    if (subreq == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
8d3578
+        ret = ENOMEM;
8d3578
+        goto done;
8d3578
+    }
8d3578
 
8d3578
-        /* Steal the dom_ctx onto the lookup_ctx so it doesn't go out of scope if
8d3578
-        * this request is canceled while other requests are in-progress.
8d3578
-        */
8d3578
-        lookup_ctx->dctx = talloc_steal(lookup_ctx, state->dctx);
8d3578
-        lookup_ctx->actx = actx;
8d3578
-        lookup_ctx->map = state->map;
8d3578
-        lookup_ctx->rctx = client->rctx;
8d3578
-        lookup_ctx->mapname =
8d3578
-                    talloc_strdup(lookup_ctx, state->mapname);
8d3578
-        if (!lookup_ctx->mapname) {
8d3578
-            talloc_free(state->map);
8d3578
-            ret = ENOMEM;
8d3578
-            goto fail;
8d3578
-        }
8d3578
+    tevent_req_set_callback(subreq, autofs_setent_done, req);
8d3578
 
8d3578
-        ret = lookup_automntmap_step(lookup_ctx);
8d3578
-        if (ret == EAGAIN) {
8d3578
-            DEBUG(SSSDBG_TRACE_INTERNAL, "lookup_automntmap_step "
8d3578
-                  "is refreshing the cache, re-entering the mainloop\n");
8d3578
-            return req;
8d3578
-        } else if (ret != EOK) {
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "Could not get data from cache\n");
8d3578
-            talloc_free(state->map);
8d3578
-            ret = ENOMEM;
8d3578
-            goto fail;
8d3578
-        }
8d3578
+    ret = EAGAIN;
8d3578
 
8d3578
+done:
8d3578
+    if (ret == EOK) {
8d3578
         tevent_req_done(req);
8d3578
-        tevent_req_post(req, cmdctx->cctx->ev);
8d3578
-        return req;
8d3578
-    } else {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Unexpected error from get_autofs_map [%d]: %s\n",
8d3578
-               ret, strerror(ret));
8d3578
-        goto fail;
8d3578
+        tevent_req_post(req, ev);
8d3578
+    } else if (ret != EAGAIN) {
8d3578
+        tevent_req_error(req, ret);
8d3578
+        tevent_req_post(req, ev);
8d3578
     }
8d3578
 
8d3578
     return req;
8d3578
-
8d3578
-fail:
8d3578
-    tevent_req_error(req, ret);
8d3578
-    tevent_req_post(req, actx->rctx->ev);
8d3578
-    return req;
8d3578
 }
8d3578
 
8d3578
-static errno_t
8d3578
-setautomntent_get_autofs_map(struct autofs_ctx *actx,
8d3578
-                             char *mapname,
8d3578
-                             struct autofs_map_ctx **map)
8d3578
+static void autofs_setent_done(struct tevent_req *subreq)
8d3578
 {
8d3578
+    struct autofs_setent_state *state;
8d3578
+    struct cache_req_result *result;
8d3578
+    struct tevent_req *req;
8d3578
     errno_t ret;
8d3578
 
8d3578
-    if (strcmp(mapname, "auto.master") == 0) {
8d3578
-        /* Iterate over the hash and remove all maps */
8d3578
-        ret = autofs_orphan_maps(actx);
8d3578
-        if (ret != EOK) {
8d3578
-            DEBUG(SSSDBG_MINOR_FAILURE, "Could not remove existing maps from hash\n");
8d3578
-        }
8d3578
-        return ENOENT;
8d3578
-    }
8d3578
+    req = tevent_req_callback_data(subreq, struct tevent_req);
8d3578
+    state = tevent_req_data(req, struct autofs_setent_state);
8d3578
 
8d3578
-    return get_autofs_map(actx, mapname, map);
8d3578
-}
8d3578
+    ret = cache_req_autofs_map_entries_recv(state, subreq, &result);
8d3578
+    talloc_zfree(subreq);
8d3578
 
8d3578
-static errno_t
8d3578
-lookup_automntmap_update_cache(struct setautomntent_lookup_ctx *lookup_ctx);
8d3578
-
8d3578
-static errno_t
8d3578
-lookup_automntmap_step(struct setautomntent_lookup_ctx *lookup_ctx)
8d3578
-{
8d3578
-    errno_t ret;
8d3578
-    struct sss_domain_info *dom = lookup_ctx->dctx->domain;
8d3578
-    struct autofs_dom_ctx *dctx = lookup_ctx->dctx;
8d3578
-    struct sysdb_ctx *sysdb;
8d3578
-    struct autofs_map_ctx *map;
8d3578
-
8d3578
-    /* Check each domain for this map name */
8d3578
-    while (dom) {
8d3578
-        if (dom != dctx->domain) {
8d3578
-            /* make sure we reset the check_provider flag when we check
8d3578
-             * a new domain */
8d3578
-            dctx->check_provider =
8d3578
-                    NEED_CHECK_PROVIDER(dom->provider);
8d3578
-        }
8d3578
+    switch (ret) {
8d3578
+    case EOK:
8d3578
+        state->enum_ctx->found = true;
8d3578
+        state->enum_ctx->result = talloc_steal(state->enum_ctx, result);
8d3578
+        autofs_set_enumctx_lifetime(state->autofs_ctx, state->enum_ctx,
8d3578
+                        state->enum_ctx->result->domain->autofsmap_timeout);
8d3578
+        break;
8d3578
+    case ENOENT:
8d3578
+        state->enum_ctx->found = false;
8d3578
+        state->enum_ctx->result = NULL;
8d3578
+        autofs_set_enumctx_lifetime(state->autofs_ctx, state->enum_ctx,
8d3578
+                                    state->autofs_ctx->neg_timeout);
8d3578
+        break;
8d3578
+    default:
8d3578
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to get map data [%d]: %s\n",
8d3578
+              ret, sss_strerror(ret));
8d3578
 
8d3578
-        /* make sure to update the dctx if we changed domain */
8d3578
-        dctx->domain = dom;
8d3578
+        setent_notify(&state->enum_ctx->notify_list, ret);
8d3578
+        talloc_zfree(state->enum_ctx);
8d3578
+        tevent_req_error(req, ret);
8d3578
+        return;
8d3578
+    }
8d3578
 
8d3578
-        DEBUG(SSSDBG_TRACE_FUNC, "Requesting info for [%s@%s]\n",
8d3578
-              lookup_ctx->mapname, dom->name);
8d3578
-        sysdb = dom->sysdb;
8d3578
-        if (sysdb == NULL) {
8d3578
-            DEBUG(SSSDBG_FATAL_FAILURE,
8d3578
-                  "Fatal: Sysdb CTX not found for this domain!\n");
8d3578
-            return EIO;
8d3578
-        }
8d3578
+    state->enum_ctx->ready = true;
8d3578
 
8d3578
-        /* Look into the cache */
8d3578
-        talloc_free(dctx->map);
8d3578
-        ret = sysdb_get_map_byname(dctx, dom, lookup_ctx->mapname,
8d3578
-                                   &dctx->map);
8d3578
-        if (ret != EOK && ret != ENOENT) {
8d3578
-            DEBUG(SSSDBG_OP_FAILURE, "Could not check cache\n");
8d3578
-            return ret;
8d3578
-        } else if (ret == ENOENT) {
8d3578
-            DEBUG(SSSDBG_MINOR_FAILURE,
8d3578
-                  "No automount map [%s] in cache for domain [%s]\n",
8d3578
-                   lookup_ctx->mapname, dom->name);
8d3578
-            if (!dctx->check_provider) {
8d3578
-                if (dctx->cmd_ctx->check_next) {
8d3578
-                    DEBUG(SSSDBG_TRACE_INTERNAL, "Moving on to next domain\n");
8d3578
-                    dom = get_next_domain(dom, 0);
8d3578
-                    continue;
8d3578
-                }
8d3578
-                else break;
8d3578
-            }
8d3578
-        }
8d3578
+    /* Make the enumeration context disappear with maps table. */
8d3578
+    talloc_steal(state->autofs_ctx->maps, state->enum_ctx);
8d3578
 
8d3578
-        ret = get_autofs_map(lookup_ctx->actx, lookup_ctx->mapname, &map);
8d3578
-        if (ret != EOK) {
8d3578
-            /* Something really bad happened! */
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "Autofs map entry was lost!\n");
8d3578
-            return ret;
8d3578
-        }
8d3578
+    setent_notify_done(&state->enum_ctx->notify_list);
8d3578
+    tevent_req_done(req);
8d3578
+    return;
8d3578
+}
8d3578
 
8d3578
-        if (dctx->map == NULL && !dctx->check_provider) {
8d3578
-            DEBUG(SSSDBG_MINOR_FAILURE,
8d3578
-                  "Autofs map not found, setting negative cache\n");
8d3578
-            map->ready = true;
8d3578
-            map->found = false;
8d3578
-            set_autofs_map_lifetime(lookup_ctx->actx->neg_timeout, lookup_ctx, map);
8d3578
-            return ENOENT;
8d3578
-        }
8d3578
+static errno_t
8d3578
+autofs_setent_recv(struct tevent_req *req,
8d3578
+                   struct autofs_enum_ctx **_enum_ctx)
8d3578
+{
8d3578
+    struct autofs_setent_state *state;
8d3578
+    state = tevent_req_data(req, struct autofs_setent_state);
8d3578
 
8d3578
-        if (dctx->check_provider) {
8d3578
-            ret = lookup_automntmap_update_cache(lookup_ctx);
8d3578
-            if (ret == EAGAIN) {
8d3578
-                DEBUG(SSSDBG_TRACE_INTERNAL,
8d3578
-                      "Looking up automount maps from the DP\n");
8d3578
-                return EAGAIN;
8d3578
-            } else if (ret != EOK) {
8d3578
-                DEBUG(SSSDBG_OP_FAILURE,
8d3578
-                      "Error looking up automount maps [%d]: %s\n",
8d3578
-                       ret, strerror(ret));
8d3578
-                return ret;
8d3578
-            }
8d3578
-        }
8d3578
+    TEVENT_REQ_RETURN_ON_ERROR(req);
8d3578
 
8d3578
-        /* OK, the map is in cache and valid.
8d3578
-         * Let's get all members and return it
8d3578
-         */
8d3578
-        ret = sysdb_autofs_entries_by_map(map, dom, map->mapname,
8d3578
-                                          &map->entry_count,
8d3578
-                                          &map->entries);
8d3578
-        if (ret != EOK && ret != ENOENT) {
8d3578
-            DEBUG(SSSDBG_OP_FAILURE,
8d3578
-                  "Error looking automount map entries [%d]: %s\n",
8d3578
-                  ret, strerror(ret));
8d3578
-            map->ready = true;
8d3578
-            map->found = false;
8d3578
-            set_autofs_map_lifetime(lookup_ctx->actx->neg_timeout, lookup_ctx, map);
8d3578
-            return EIO;
8d3578
-        }
8d3578
+    *_enum_ctx = state->enum_ctx;
8d3578
 
8d3578
-        map->map = talloc_steal(map, dctx->map);
8d3578
+    return EOK;
8d3578
+}
8d3578
 
8d3578
-        DEBUG(SSSDBG_TRACE_FUNC,
8d3578
-              "setautomntent done for map %s\n", lookup_ctx->mapname);
8d3578
-        map->ready = true;
8d3578
-        map->found = true;
8d3578
-        set_autofs_map_lifetime(dom->autofsmap_timeout, lookup_ctx, map);
8d3578
-        return EOK;
8d3578
-    }
8d3578
+static errno_t
8d3578
+autofs_read_setautomntent_input(struct cli_ctx *cli_ctx,
8d3578
+                                const char **_mapname)
8d3578
+{
8d3578
+    struct cli_protocol *pctx;
8d3578
+    uint8_t *body;
8d3578
+    size_t blen;
8d3578
 
8d3578
-    map = talloc_zero(lookup_ctx->actx, struct autofs_map_ctx);
8d3578
-    if (!map) {
8d3578
-        return ENOMEM;
8d3578
-    }
8d3578
+    pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol);
8d3578
 
8d3578
-    map->ready = true;
8d3578
-    map->found = false;
8d3578
-    map->map_table = lookup_ctx->actx->maps;
8d3578
+    sss_packet_get_body(pctx->creq->in, &body, &blen);
8d3578
 
8d3578
-    map->mapname = talloc_strdup(map, lookup_ctx->mapname);
8d3578
-    if (!map->mapname) {
8d3578
-        talloc_free(map);
8d3578
-        return ENOMEM;
8d3578
+    /* if not terminated fail */
8d3578
+    if (body[blen - 1] != '\0') {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    ret = set_autofs_map(lookup_ctx->actx, map);
8d3578
-    if (ret != EOK) {
8d3578
-        talloc_free(map);
8d3578
-        return ENOMEM;
8d3578
+    /* If the body isn't valid UTF-8, fail */
8d3578
+    if (!sss_utf8_check(body, blen - 1)) {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    set_autofs_map_lifetime(lookup_ctx->actx->neg_timeout, lookup_ctx, map);
8d3578
+    *_mapname = (const char *)body;
8d3578
 
8d3578
-    /* If we've gotten here, then no domain contained this map */
8d3578
-    return ENOENT;
8d3578
+    return EOK;
8d3578
 }
8d3578
 
8d3578
-static void lookup_automntmap_cache_updated(uint16_t err_maj, uint32_t err_min,
8d3578
-                                            const char *err_msg, void *ptr);
8d3578
-static void autofs_dp_send_map_req_done(struct tevent_req *req);
8d3578
-
8d3578
 static errno_t
8d3578
-lookup_automntmap_update_cache(struct setautomntent_lookup_ctx *lookup_ctx)
8d3578
+autofs_write_setautomntent_output(struct cli_ctx *cli_ctx,
8d3578
+                                  struct autofs_enum_ctx *enum_ctx)
8d3578
 {
8d3578
+    struct cli_protocol *pctx;
8d3578
+    uint8_t *body;
8d3578
+    size_t blen;
8d3578
     errno_t ret;
8d3578
-    uint64_t cache_expire = 0;
8d3578
-    struct autofs_dom_ctx *dctx = lookup_ctx->dctx;
8d3578
-    struct tevent_req *req = NULL;
8d3578
-    struct dp_callback_ctx *cb_ctx = NULL;
8d3578
-
8d3578
-    if (dctx->map != NULL) {
8d3578
-        if (strcmp(lookup_ctx->mapname, "auto.master") != 0) {
8d3578
-            cache_expire = ldb_msg_find_attr_as_uint64(dctx->map,
8d3578
-                                                       SYSDB_CACHE_EXPIRE, 0);
8d3578
-        }
8d3578
 
8d3578
-        /* if we have any reply let's check cache validity */
8d3578
-        ret = sss_cmd_check_cache(dctx->map, 0, cache_expire);
8d3578
-        if (ret == EOK) {
8d3578
-            DEBUG(SSSDBG_TRACE_FUNC, "Cached entry is valid, returning..\n");
8d3578
-            return EOK;
8d3578
-        } else if (ret != EAGAIN && ret != ENOENT) {
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "Error checking cache: %d\n", ret);
8d3578
-            goto error;
8d3578
-        }
8d3578
-    }
8d3578
+    pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol);
8d3578
 
8d3578
-    /* dont loop forever :-) */
8d3578
-    dctx->check_provider = false;
8d3578
-
8d3578
-    /* keep around current data in case backend is offline */
8d3578
-    /* FIXME - do this by default */
8d3578
-#if 0
8d3578
-    if (dctx->res->count) {
8d3578
-        dctx->res = talloc_steal(dctx, dctx->res);
8d3578
-    }
8d3578
-#endif
8d3578
-
8d3578
-    req = sss_dp_get_autofs_send(lookup_ctx->cctx, lookup_ctx->rctx,
8d3578
-                                 lookup_ctx->dctx->domain, true,
8d3578
-                                 SSS_DP_AUTOFS, lookup_ctx->mapname);
8d3578
-    if (!req) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Out of memory sending data provider request\n");
8d3578
-        ret = ENOMEM;
8d3578
-        goto error;
8d3578
+    ret = sss_packet_new(pctx->creq, 0, sss_packet_get_cmd(pctx->creq->in),
8d3578
+                         &pctx->creq->out);
8d3578
+    if (ret != EOK) {
8d3578
+        return ret;
8d3578
     }
8d3578
 
8d3578
-    cb_ctx = talloc_zero(lookup_ctx->dctx, struct dp_callback_ctx);
8d3578
-    if(!cb_ctx) {
8d3578
-        talloc_zfree(req);
8d3578
-        ret = ENOMEM;
8d3578
-        goto error;
8d3578
+    if (!enum_ctx->found) {
8d3578
+        DEBUG(SSSDBG_TRACE_FUNC, "Map was not found\n");
8d3578
+        return sss_cmd_empty_packet(pctx->creq->out);
8d3578
     }
8d3578
-    cb_ctx->callback = lookup_automntmap_cache_updated;
8d3578
-    cb_ctx->ptr = lookup_ctx;
8d3578
-    cb_ctx->cctx = lookup_ctx->dctx->cmd_ctx->cctx;
8d3578
-    cb_ctx->mem_ctx = lookup_ctx->dctx;
8d3578
-
8d3578
-    tevent_req_set_callback(req, autofs_dp_send_map_req_done, cb_ctx);
8d3578
 
8d3578
-    return EAGAIN;
8d3578
+    DEBUG(SSSDBG_TRACE_FUNC, "Map found\n");
8d3578
 
8d3578
-error:
8d3578
-    ret = autofs_cmd_send_error(lookup_ctx->dctx->cmd_ctx, ret);
8d3578
+    ret = sss_packet_grow(pctx->creq->out, 2 * sizeof(uint32_t));
8d3578
     if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE, "Fatal error, killing connection!\n");
8d3578
-        talloc_free(lookup_ctx->cctx);
8d3578
         return ret;
8d3578
     }
8d3578
-    autofs_cmd_done(lookup_ctx->dctx->cmd_ctx, ret);
8d3578
-    return EOK;
8d3578
-}
8d3578
-
8d3578
-static void autofs_dp_send_map_req_done(struct tevent_req *req)
8d3578
-{
8d3578
-    struct dp_callback_ctx *cb_ctx =
8d3578
-            tevent_req_callback_data(req, struct dp_callback_ctx);
8d3578
-    struct setautomntent_lookup_ctx *lookup_ctx =
8d3578
-            talloc_get_type(cb_ctx->ptr, struct setautomntent_lookup_ctx);
8d3578
-
8d3578
-    errno_t ret;
8d3578
-    dbus_uint16_t err_maj;
8d3578
-    dbus_uint32_t err_min;
8d3578
-    char *err_msg;
8d3578
-
8d3578
-    ret = sss_dp_get_autofs_recv(cb_ctx->mem_ctx, req,
8d3578
-                                 &err_maj, &err_min,
8d3578
-                                 &err_msg);
8d3578
-    talloc_free(req);
8d3578
-    if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE, "Fatal error, killing connection!\n");
8d3578
-        talloc_free(lookup_ctx->cctx);
8d3578
-        return;
8d3578
-    }
8d3578
-
8d3578
-    cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
8d3578
-}
8d3578
-
8d3578
-static void lookup_automntmap_cache_updated(uint16_t err_maj, uint32_t err_min,
8d3578
-                                            const char *err_msg, void *ptr)
8d3578
-{
8d3578
-    struct setautomntent_lookup_ctx *lookup_ctx =
8d3578
-            talloc_get_type(ptr, struct setautomntent_lookup_ctx);
8d3578
-    struct autofs_dom_ctx *dctx = lookup_ctx->dctx;
8d3578
-    errno_t ret;
8d3578
-
8d3578
-    if (err_maj) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Unable to get information from Data Provider\n"
8d3578
-              "Error: %u, %u, %s\n"
8d3578
-              "Will try to return what we have in cache\n",
8d3578
-               (unsigned int)err_maj, (unsigned int)err_min, err_msg);
8d3578
-
8d3578
-        /* Try to fall back to cache */
8d3578
-        ret = lookup_automntmap_step(lookup_ctx);
8d3578
-        if (ret == EOK) {
8d3578
-            /* We have cached results to return */
8d3578
-            autofs_setent_notify(lookup_ctx->map, ret);
8d3578
-            return;
8d3578
-        }
8d3578
 
8d3578
-        /* Otherwise try the next domain */
8d3578
-        if (dctx->cmd_ctx->check_next
8d3578
-                && (dctx->domain = get_next_domain(dctx->domain, 0))) {
8d3578
-            dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
8d3578
-        }
8d3578
-    }
8d3578
+    sss_packet_get_body(pctx->creq->out, &body, &blen);
8d3578
 
8d3578
-    ret = lookup_automntmap_step(lookup_ctx);
8d3578
-    if (ret != EOK) {
8d3578
-        if (ret == EAGAIN) {
8d3578
-            return;
8d3578
-        }
8d3578
-    }
8d3578
+    /* Got some results */
8d3578
+    SAFEALIGN_SETMEM_UINT32(body, 1, NULL);
8d3578
 
8d3578
-    /* We have results to return */
8d3578
-    autofs_setent_notify(lookup_ctx->map, ret);
8d3578
-}
8d3578
+    /* Reserved padding */
8d3578
+    SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), 0, NULL);
8d3578
 
8d3578
-static errno_t
8d3578
-setautomntent_recv(struct tevent_req *req)
8d3578
-{
8d3578
-    TEVENT_REQ_RETURN_ON_ERROR(req);
8d3578
     return EOK;
8d3578
 }
8d3578
 
8d3578
-static errno_t
8d3578
-getautomntent_process(struct autofs_cmd_ctx *cmdctx,
8d3578
-                      struct autofs_map_ctx *map,
8d3578
-                      uint32_t cursor, uint32_t max_entries);
8d3578
 static void
8d3578
-getautomntent_implicit_done(struct tevent_req *req);
8d3578
-static errno_t
8d3578
-fill_autofs_entry(struct ldb_message *entry, struct sss_packet *packet, size_t *rp);
8d3578
-
8d3578
+sss_autofs_cmd_setautomntent_done(struct tevent_req *req);
8d3578
 
8d3578
 static int
8d3578
-sss_autofs_cmd_getautomntent(struct cli_ctx *client)
8d3578
+sss_autofs_cmd_setautomntent(struct cli_ctx *cli_ctx)
8d3578
 {
8d3578
-    struct autofs_cmd_ctx *cmdctx;
8d3578
-    struct autofs_map_ctx *map;
8d3578
-    struct autofs_ctx *actx;
8d3578
-    struct cli_protocol *pctx;
8d3578
-    uint8_t *body;
8d3578
-    size_t blen;
8d3578
-    errno_t ret;
8d3578
-    uint32_t namelen;
8d3578
-    size_t c = 0;
8d3578
+    struct autofs_cmd_ctx *cmd_ctx;
8d3578
+    struct autofs_ctx *autofs_ctx;
8d3578
     struct tevent_req *req;
8d3578
+    errno_t ret;
8d3578
 
8d3578
-    DEBUG(SSSDBG_TRACE_INTERNAL, "sss_autofs_cmd_getautomntent\n");
8d3578
+    autofs_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct autofs_ctx);
8d3578
 
8d3578
-    cmdctx = talloc_zero(client, struct autofs_cmd_ctx);
8d3578
-    if (!cmdctx) {
8d3578
+    cmd_ctx = talloc_zero(cli_ctx, struct autofs_cmd_ctx);
8d3578
+    if (cmd_ctx == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create command context.\n");
8d3578
         return ENOMEM;
8d3578
     }
8d3578
-    cmdctx->cctx = client;
8d3578
 
8d3578
-    actx = talloc_get_type(client->rctx->pvt_ctx, struct autofs_ctx);
8d3578
-    if (!actx) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE, "Missing autofs context\n");
8d3578
-        return EIO;
8d3578
-    }
8d3578
+    cmd_ctx->cli_ctx = cli_ctx;
8d3578
+    cmd_ctx->autofs_ctx = autofs_ctx;
8d3578
 
8d3578
-    pctx = talloc_get_type(cmdctx->cctx->protocol_ctx, struct cli_protocol);
8d3578
-
8d3578
-    /* get autofs map name and index to query */
8d3578
-    sss_packet_get_body(pctx->creq->in, &body, &blen);
8d3578
-
8d3578
-    SAFEALIGN_COPY_UINT32_CHECK(&namelen, body+c, blen, &c);
8d3578
-
8d3578
-    if (namelen == 0 || namelen > blen - c) {
8d3578
-        ret = EINVAL;
8d3578
+    ret = autofs_read_setautomntent_input(cli_ctx, &cmd_ctx->mapname);
8d3578
+    if (ret != EOK) {
8d3578
         goto done;
8d3578
     }
8d3578
 
8d3578
-    cmdctx->mapname = (char *) body+c;
8d3578
+    DEBUG(SSSDBG_TRACE_FUNC, "Creating enumeration context for %s\n",
8d3578
+          cmd_ctx->mapname);
8d3578
 
8d3578
-    /* if not null-terminated fail */
8d3578
-    if (cmdctx->mapname[namelen] != '\0') {
8d3578
-        ret = EINVAL;
8d3578
+    req = autofs_setent_send(cli_ctx, cli_ctx->ev, autofs_ctx,
8d3578
+                             cmd_ctx->mapname);
8d3578
+    if (req == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request\n");
8d3578
+        ret = ENOMEM;
8d3578
         goto done;
8d3578
     }
8d3578
 
8d3578
-    /* If the name isn't valid UTF-8, fail */
8d3578
-    if (!sss_utf8_check((const uint8_t *) cmdctx->mapname, namelen -1)) {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
-    }
8d3578
+    tevent_req_set_callback(req, sss_autofs_cmd_setautomntent_done, cmd_ctx);
8d3578
 
8d3578
-    SAFEALIGN_COPY_UINT32_CHECK(&cmdctx->cursor, body+c+namelen+1, blen, &c);
8d3578
-    SAFEALIGN_COPY_UINT32_CHECK(&cmdctx->max_entries, body+c+namelen+1, blen, &c);
8d3578
+    ret = EOK;
8d3578
 
8d3578
-    DEBUG(SSSDBG_TRACE_FUNC,
8d3578
-          "Requested data of map %s cursor %d max entries %d\n",
8d3578
-           cmdctx->mapname, cmdctx->cursor, cmdctx->max_entries);
8d3578
+done:
8d3578
+    return autofs_cmd_done(cmd_ctx, ret);
8d3578
+}
8d3578
 
8d3578
-    ret = get_autofs_map(actx, cmdctx->mapname, &map);
8d3578
-    if (ret == ENOENT) {
8d3578
-        DEBUG(SSSDBG_TRACE_FUNC, "Performing implicit setautomntent\n");
8d3578
-        req = setautomntent_send(cmdctx, cmdctx->mapname, cmdctx);
8d3578
-        if (req == NULL) {
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_send failed\n");
8d3578
-            ret = EIO;
8d3578
-            goto done;
8d3578
-        }
8d3578
+static void
8d3578
+sss_autofs_cmd_setautomntent_done(struct tevent_req *req)
8d3578
+{
8d3578
+    struct autofs_enum_ctx *enum_ctx;
8d3578
+    struct autofs_cmd_ctx *cmd_ctx;
8d3578
+    errno_t ret;
8d3578
 
8d3578
-        tevent_req_set_callback(req, getautomntent_implicit_done, cmdctx);
8d3578
-        ret = EOK;
8d3578
-        goto done;
8d3578
-    } else if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_OP_FAILURE,
8d3578
-              "An unexpected error occurred: [%d][%s]\n",
8d3578
-              ret, strerror(ret));
8d3578
-        goto done;
8d3578
-    }
8d3578
+    cmd_ctx = tevent_req_callback_data(req, struct autofs_cmd_ctx);
8d3578
 
8d3578
-    if (map->ready == false) {
8d3578
-        DEBUG(SSSDBG_TRACE_FUNC, "Performing implicit setautomntent\n");
8d3578
-        req = setautomntent_send(cmdctx, cmdctx->mapname, cmdctx);
8d3578
-        if (req == NULL) {
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_send failed\n");
8d3578
-            ret = EIO;
8d3578
-            goto done;
8d3578
-        }
8d3578
+    ret = autofs_setent_recv(req, &enum_ctx);
8d3578
+    talloc_zfree(req);
8d3578
+    if (ret != EOK) {
8d3578
+        autofs_cmd_done(cmd_ctx, ret);
8d3578
+        return;
8d3578
+    }
8d3578
 
8d3578
-        tevent_req_set_callback(req, getautomntent_implicit_done, cmdctx);
8d3578
-        ret = EOK;
8d3578
-        goto done;
8d3578
-    } else if (map->found == false) {
8d3578
-        DEBUG(SSSDBG_TRACE_FUNC, "negative cache hit\n");
8d3578
-        ret = ENOENT;
8d3578
-        goto done;
8d3578
+    ret = autofs_write_setautomntent_output(cmd_ctx->cli_ctx, enum_ctx);
8d3578
+    if (ret != EOK) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create reply packet "
8d3578
+              "[%d]: %s\n", ret, sss_strerror(ret));
8d3578
+        autofs_cmd_done(cmd_ctx, ret);
8d3578
+        return;
8d3578
     }
8d3578
 
8d3578
-    DEBUG(SSSDBG_TRACE_INTERNAL,
8d3578
-          "returning entries for [%s]\n", map->mapname);
8d3578
+    sss_cmd_done(cmd_ctx->cli_ctx, NULL);
8d3578
+}
8d3578
 
8d3578
-    ret = getautomntent_process(cmdctx, map, cmdctx->cursor, cmdctx->max_entries);
8d3578
+static int
8d3578
+sss_autofs_cmd_endautomntent(struct cli_ctx *client)
8d3578
+{
8d3578
+    struct cli_protocol *pctx;
8d3578
+    errno_t ret;
8d3578
 
8d3578
-done:
8d3578
-    return autofs_cmd_done(cmdctx, ret);
8d3578
+    DEBUG(SSSDBG_TRACE_FUNC, "endautomntent called\n");
8d3578
+
8d3578
+    pctx = talloc_get_type(client->protocol_ctx, struct cli_protocol);
8d3578
+
8d3578
+    /* create response packet */
8d3578
+    ret = sss_packet_new(pctx->creq, 0,
8d3578
+                         sss_packet_get_cmd(pctx->creq->in),
8d3578
+                         &pctx->creq->out);
8d3578
+
8d3578
+    if (ret != EOK) {
8d3578
+        return ret;
8d3578
+    }
8d3578
+
8d3578
+    sss_cmd_done(client, NULL);
8d3578
+    return EOK;
8d3578
 }
8d3578
 
8d3578
-static void
8d3578
-getautomntent_implicit_done(struct tevent_req *req)
8d3578
+static errno_t
8d3578
+autofs_read_getautomntent_input(struct cli_ctx *cli_ctx,
8d3578
+                                const char **_mapname,
8d3578
+                                uint32_t *_cursor,
8d3578
+                                uint32_t *_max_entries)
8d3578
 {
8d3578
-    errno_t ret;
8d3578
-    struct autofs_map_ctx *map;
8d3578
-    struct autofs_cmd_ctx *cmdctx =
8d3578
-        tevent_req_callback_data(req, struct autofs_cmd_ctx);
8d3578
-    struct autofs_ctx *actx =
8d3578
-        talloc_get_type(cmdctx->cctx->rctx->pvt_ctx, struct autofs_ctx);
8d3578
+    struct cli_protocol *pctx;
8d3578
+    const char *mapname;
8d3578
+    uint32_t namelen;
8d3578
+    uint8_t *body;
8d3578
+    size_t blen;
8d3578
+    size_t c = 0;
8d3578
 
8d3578
-    ret = setautomntent_recv(req);
8d3578
-    talloc_zfree(req);
8d3578
-    if (ret != EOK) {
8d3578
-        if (ret != ENOENT) {
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_recv failed\n");
8d3578
-        } else {
8d3578
-            DEBUG(SSSDBG_MINOR_FAILURE, "No such map\n");
8d3578
-        }
8d3578
-        goto done;
8d3578
+    pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol);
8d3578
+
8d3578
+    sss_packet_get_body(pctx->creq->in, &body, &blen);
8d3578
+
8d3578
+    SAFEALIGN_COPY_UINT32_CHECK(&namelen, body+c, blen, &c);
8d3578
+    if (namelen == 0 || namelen > blen - c) {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    ret = get_autofs_map(actx, cmdctx->mapname, &map);
8d3578
-    if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Cannot get map after setautomntent succeeded?\n");
8d3578
-        goto done;
8d3578
+    mapname = (const char *)body + c;
8d3578
+
8d3578
+    /* if not null-terminated fail */
8d3578
+    if (mapname[namelen] != '\0') {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    if (map->ready == false) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Map not ready after setautomntent succeeded\n");
8d3578
-        goto done;
8d3578
+    /* If the name isn't valid UTF-8, fail */
8d3578
+    if (!sss_utf8_check((const uint8_t *)mapname, namelen - 1)) {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    ret = getautomntent_process(cmdctx, map,
8d3578
-                                cmdctx->cursor, cmdctx->max_entries);
8d3578
-done:
8d3578
-    autofs_cmd_done(cmdctx, ret);
8d3578
-    return;
8d3578
+    SAFEALIGN_COPY_UINT32_CHECK(_cursor, body + c + namelen + 1, blen, &c);
8d3578
+    SAFEALIGN_COPY_UINT32_CHECK(_max_entries, body + c + namelen + 1, blen, &c);
8d3578
+    *_mapname = mapname;
8d3578
+
8d3578
+    return EOK;
8d3578
 }
8d3578
 
8d3578
 static errno_t
8d3578
-getautomntent_process(struct autofs_cmd_ctx *cmdctx,
8d3578
-                      struct autofs_map_ctx *map,
8d3578
-                      uint32_t cursor, uint32_t max_entries)
8d3578
+autofs_write_getautomntent_output(struct cli_ctx *cli_ctx,
8d3578
+                                  struct autofs_enum_ctx *enum_ctx,
8d3578
+                                  uint32_t cursor,
8d3578
+                                  uint32_t max_entries)
8d3578
 {
8d3578
     struct cli_protocol *pctx;
8d3578
-    errno_t ret;
8d3578
+    struct ldb_message **entries;
8d3578
     struct ldb_message *entry;
8d3578
-    size_t rp;
8d3578
-    uint32_t i, stop, left, nentries;
8d3578
+    size_t count;
8d3578
+    size_t num_entries;
8d3578
     uint8_t *body;
8d3578
     size_t blen;
8d3578
+    size_t rp;
8d3578
+    uint32_t i;
8d3578
+    uint32_t stop;
8d3578
+    uint32_t left;
8d3578
+    errno_t ret;
8d3578
 
8d3578
-    pctx = talloc_get_type(cmdctx->cctx->protocol_ctx, struct cli_protocol);
8d3578
+    pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol);
8d3578
 
8d3578
-    /* create response packet */
8d3578
-    ret = sss_packet_new(pctx->creq, 0,
8d3578
-                         sss_packet_get_cmd(pctx->creq->in),
8d3578
+    count = enum_ctx->found ? enum_ctx->result->count - 1 : 0;
8d3578
+    entries = count > 0 ? enum_ctx->result->msgs + 1 : NULL;
8d3578
+
8d3578
+    ret = sss_packet_new(pctx->creq, 0, sss_packet_get_cmd(pctx->creq->in),
8d3578
                          &pctx->creq->out);
8d3578
     if (ret != EOK) {
8d3578
         return ret;
8d3578
     }
8d3578
 
8d3578
-    if (!map->map || !map->entries || !map->entries[0] ||
8d3578
-        cursor >= map->entry_count) {
8d3578
-        DEBUG(SSSDBG_MINOR_FAILURE, "No entries found\n");
8d3578
-        ret = sss_cmd_empty_packet(pctx->creq->out);
8d3578
-        if (ret != EOK) {
8d3578
-            return autofs_cmd_done(cmdctx, ret);
8d3578
-        }
8d3578
-        goto done;
8d3578
+    if (!enum_ctx->found || count == 0 || cursor >= count) {
8d3578
+        DEBUG(SSSDBG_TRACE_FUNC, "No entries was not found\n");
8d3578
+        return sss_cmd_empty_packet(pctx->creq->out);
8d3578
     }
8d3578
 
8d3578
     /* allocate memory for number of entries in the packet */
8d3578
     ret = sss_packet_grow(pctx->creq->out, sizeof(uint32_t));
8d3578
     if (ret != EOK) {
8d3578
         DEBUG(SSSDBG_OP_FAILURE, "Cannot grow packet\n");
8d3578
-        goto done;
8d3578
+        return ret;
8d3578
     }
8d3578
 
8d3578
-    rp = sizeof(uint32_t);  /* We'll write the number of entries here */
8d3578
-
8d3578
-    left = map->entry_count - cursor;
8d3578
+    rp = sizeof(uint32_t);  /* We will first write the elements. */
8d3578
+    left = count - cursor;
8d3578
     stop = max_entries < left ? max_entries : left;
8d3578
 
8d3578
-    nentries = 0;
8d3578
-    for (i=0; i < stop; i++) {
8d3578
-        entry = map->entries[cursor];
8d3578
+    num_entries = 0;
8d3578
+    for (i = 0; i < stop; i++) {
8d3578
+        entry = entries[cursor];
8d3578
         cursor++;
8d3578
 
8d3578
-        ret = fill_autofs_entry(entry, pctx->creq->out, &rp);
8d3578
+        ret = autofs_fill_entry(entry, pctx->creq->out, &rp);
8d3578
         if (ret != EOK) {
8d3578
             DEBUG(SSSDBG_MINOR_FAILURE,
8d3578
                   "Cannot fill entry %d/%d, skipping\n", i, stop);
8d3578
             continue;
8d3578
         }
8d3578
-        nentries++;
8d3578
+        num_entries++;
8d3578
     }
8d3578
 
8d3578
     /* packet grows in fill_autofs_entry, body pointer may change,
8d3578
@@ -1137,311 +605,212 @@ getautomntent_process(struct autofs_cmd_ctx *cmdctx,
8d3578
     sss_packet_get_body(pctx->creq->out, &body, &blen);
8d3578
 
8d3578
     rp = 0;
8d3578
-    SAFEALIGN_SET_UINT32(&body[rp], nentries, &rp);
8d3578
-
8d3578
-    ret = EOK;
8d3578
-done:
8d3578
-    sss_packet_set_error(pctx->creq->out, ret);
8d3578
-    sss_cmd_done(cmdctx->cctx, cmdctx);
8d3578
+    SAFEALIGN_SET_UINT32(&body[rp], num_entries, &rp);
8d3578
 
8d3578
     return EOK;
8d3578
 }
8d3578
 
8d3578
-static errno_t
8d3578
-fill_autofs_entry(struct ldb_message *entry, struct sss_packet *packet, size_t *rp)
8d3578
+static void
8d3578
+sss_autofs_cmd_getautomntent_done(struct tevent_req *req);
8d3578
+
8d3578
+static int
8d3578
+sss_autofs_cmd_getautomntent(struct cli_ctx *cli_ctx)
8d3578
 {
8d3578
+    struct autofs_cmd_ctx *cmd_ctx;
8d3578
+    struct autofs_ctx *autofs_ctx;
8d3578
+    struct tevent_req *req;
8d3578
     errno_t ret;
8d3578
-    const char *key;
8d3578
-    size_t keylen;
8d3578
-    const char *value;
8d3578
-    size_t valuelen;
8d3578
-    uint8_t *body;
8d3578
-    size_t blen;
8d3578
-    size_t len;
8d3578
 
8d3578
-    key = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_KEY, NULL);
8d3578
-    value = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_VALUE, NULL);
8d3578
-    if (!key || !value) {
8d3578
-        DEBUG(SSSDBG_MINOR_FAILURE, "Incomplete entry\n");
8d3578
-        return EINVAL;
8d3578
+    autofs_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct autofs_ctx);
8d3578
+
8d3578
+    cmd_ctx = talloc_zero(cli_ctx, struct autofs_cmd_ctx);
8d3578
+    if (cmd_ctx == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create command context.\n");
8d3578
+        return ENOMEM;
8d3578
     }
8d3578
 
8d3578
-    keylen = 1 + strlen(key);
8d3578
-    valuelen = 1 + strlen(value);
8d3578
-    len = sizeof(uint32_t) + sizeof(uint32_t) + keylen + sizeof(uint32_t) + valuelen;
8d3578
+    cmd_ctx->cli_ctx = cli_ctx;
8d3578
+    cmd_ctx->autofs_ctx = autofs_ctx;
8d3578
 
8d3578
-    ret = sss_packet_grow(packet, len);
8d3578
+    ret = autofs_read_getautomntent_input(cli_ctx, &cmd_ctx->mapname,
8d3578
+                                          &cmd_ctx->cursor,
8d3578
+                                          &cmd_ctx->max_entries);
8d3578
     if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_OP_FAILURE, "Cannot grow packet\n");
8d3578
-        return ret;
8d3578
+        goto done;
8d3578
     }
8d3578
 
8d3578
-    sss_packet_get_body(packet, &body, &blen);
8d3578
-
8d3578
-    SAFEALIGN_SET_UINT32(&body[*rp], len, rp);
8d3578
-    SAFEALIGN_SET_UINT32(&body[*rp], keylen, rp);
8d3578
+    DEBUG(SSSDBG_TRACE_FUNC, "Obtaining enumeration context for %s\n",
8d3578
+          cmd_ctx->mapname);
8d3578
 
8d3578
-    if (keylen == 1) {
8d3578
-        body[*rp] = '\0';
8d3578
-    } else {
8d3578
-        memcpy(&body[*rp], key, keylen);
8d3578
+    req = autofs_setent_send(cli_ctx, cli_ctx->ev, autofs_ctx, cmd_ctx->mapname);
8d3578
+    if (req == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request\n");
8d3578
+        ret = ENOMEM;
8d3578
+        goto done;
8d3578
     }
8d3578
-    *rp += keylen;
8d3578
 
8d3578
-    SAFEALIGN_SET_UINT32(&body[*rp], valuelen, rp);
8d3578
-    if (valuelen == 1) {
8d3578
-        body[*rp] = '\0';
8d3578
-    } else {
8d3578
-        memcpy(&body[*rp], value, valuelen);
8d3578
-    }
8d3578
-    *rp += valuelen;
8d3578
+    tevent_req_set_callback(req, sss_autofs_cmd_getautomntent_done, cmd_ctx);
8d3578
 
8d3578
-    return EOK;
8d3578
+    ret = EOK;
8d3578
+
8d3578
+done:
8d3578
+    return autofs_cmd_done(cmd_ctx, ret);
8d3578
 }
8d3578
 
8d3578
-static errno_t
8d3578
-getautomntbyname_process(struct autofs_cmd_ctx *cmdctx,
8d3578
-                         struct autofs_map_ctx *map,
8d3578
-                         const char *key);
8d3578
 static void
8d3578
-getautomntbyname_implicit_done(struct tevent_req *req);
8d3578
-
8d3578
-static int
8d3578
-sss_autofs_cmd_getautomntbyname(struct cli_ctx *client)
8d3578
+sss_autofs_cmd_getautomntent_done(struct tevent_req *req)
8d3578
 {
8d3578
+    struct autofs_enum_ctx *enum_ctx;
8d3578
+    struct autofs_cmd_ctx *cmd_ctx;
8d3578
     errno_t ret;
8d3578
-    struct autofs_cmd_ctx *cmdctx;
8d3578
-    struct autofs_map_ctx *map;
8d3578
-    struct autofs_ctx *actx;
8d3578
-    struct cli_protocol *pctx;
8d3578
-    uint8_t *body;
8d3578
-    size_t blen;
8d3578
-    uint32_t namelen;
8d3578
-    uint32_t keylen;
8d3578
-    size_t c = 0;
8d3578
-    struct tevent_req *req;
8d3578
 
8d3578
-    DEBUG(SSSDBG_TRACE_INTERNAL, "sss_autofs_cmd_getautomntbyname\n");
8d3578
+    cmd_ctx = tevent_req_callback_data(req, struct autofs_cmd_ctx);
8d3578
 
8d3578
-    cmdctx = talloc_zero(client, struct autofs_cmd_ctx);
8d3578
-    if (!cmdctx) {
8d3578
-        return ENOMEM;
8d3578
+    ret = autofs_setent_recv(req, &enum_ctx);
8d3578
+    talloc_zfree(req);
8d3578
+    if (ret != EOK) {
8d3578
+        autofs_cmd_done(cmd_ctx, ret);
8d3578
+        return;
8d3578
     }
8d3578
-    cmdctx->cctx = client;
8d3578
 
8d3578
-    actx = talloc_get_type(client->rctx->pvt_ctx, struct autofs_ctx);
8d3578
-    if (!actx) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE, "Missing autofs context\n");
8d3578
-        return EIO;
8d3578
+    ret = autofs_write_getautomntent_output(cmd_ctx->cli_ctx, enum_ctx,
8d3578
+                                            cmd_ctx->cursor,
8d3578
+                                            cmd_ctx->max_entries);
8d3578
+    if (ret != EOK) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create reply packet "
8d3578
+              "[%d]: %s\n", ret, sss_strerror(ret));
8d3578
+        autofs_cmd_done(cmd_ctx, ret);
8d3578
+        return;
8d3578
     }
8d3578
 
8d3578
-    pctx = talloc_get_type(cmdctx->cctx->protocol_ctx, struct cli_protocol);
8d3578
+    sss_cmd_done(cmd_ctx->cli_ctx, NULL);
8d3578
+}
8d3578
 
8d3578
-    /* get autofs map name and index to query */
8d3578
-    sss_packet_get_body(pctx->creq->in, &body, &blen);
8d3578
+static errno_t
8d3578
+autofs_read_getautomntbyname_input(struct cli_ctx *cli_ctx,
8d3578
+                                   const char **_mapname,
8d3578
+                                   const char **_keyname)
8d3578
+{
8d3578
+    struct cli_protocol *pctx;
8d3578
+    const char *mapname;
8d3578
+    const char *keyname;
8d3578
+    uint32_t namelen;
8d3578
+    uint32_t keylen;
8d3578
+    uint8_t *body;
8d3578
+    size_t blen;
8d3578
+    size_t c = 0;
8d3578
 
8d3578
-    /* FIXME - split out a function to get string from <len><str>\0 */
8d3578
-    SAFEALIGN_COPY_UINT32_CHECK(&namelen, body+c, blen, &c);
8d3578
+    pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol);
8d3578
+
8d3578
+    sss_packet_get_body(pctx->creq->in, &body, &blen);
8d3578
 
8d3578
+    /* Get map name. */
8d3578
+    SAFEALIGN_COPY_UINT32_CHECK(&namelen, body + c, blen, &c);
8d3578
     if (namelen == 0 || namelen > blen - c) {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    cmdctx->mapname = (char *) body+c;
8d3578
+    mapname = (const  char *) body + c;
8d3578
 
8d3578
     /* if not null-terminated fail */
8d3578
-    if (cmdctx->mapname[namelen] != '\0') {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
+    if (mapname[namelen] != '\0') {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
     /* If the name isn't valid UTF-8, fail */
8d3578
-    if (!sss_utf8_check((const uint8_t *) cmdctx->mapname, namelen -1)) {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
+    if (!sss_utf8_check((const uint8_t *)mapname, namelen - 1)) {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
     c += namelen + 1;
8d3578
 
8d3578
-    /* FIXME - split out a function to get string from <len><str>\0 */
8d3578
-    SAFEALIGN_COPY_UINT32_CHECK(&keylen, body+c, blen, &c);
8d3578
-
8d3578
+    /* Get key name. */
8d3578
+    SAFEALIGN_COPY_UINT32_CHECK(&keylen, body + c, blen, &c);
8d3578
     if (keylen == 0 || keylen > blen - c) {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    cmdctx->key = (char *) body+c;
8d3578
+    keyname = (const char *) body + c;
8d3578
 
8d3578
     /* if not null-terminated fail */
8d3578
-    if (cmdctx->key[keylen] != '\0') {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
+    if (keyname[keylen] != '\0') {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
     /* If the key isn't valid UTF-8, fail */
8d3578
-    if (!sss_utf8_check((const uint8_t *) cmdctx->key, keylen -1)) {
8d3578
-        ret = EINVAL;
8d3578
-        goto done;
8d3578
-    }
8d3578
-
8d3578
-    DEBUG(SSSDBG_TRACE_FUNC,
8d3578
-          "Requested data of map %s key %s\n", cmdctx->mapname, cmdctx->key);
8d3578
-
8d3578
-    ret = get_autofs_map(actx, cmdctx->mapname, &map);
8d3578
-    if (ret == ENOENT) {
8d3578
-        DEBUG(SSSDBG_TRACE_FUNC, "Performing implicit setautomntent\n");
8d3578
-        req = setautomntent_send(cmdctx, cmdctx->mapname, cmdctx);
8d3578
-        if (req == NULL) {
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_send failed\n");
8d3578
-            ret = EIO;
8d3578
-            goto done;
8d3578
-        }
8d3578
-
8d3578
-        tevent_req_set_callback(req, getautomntbyname_implicit_done, cmdctx);
8d3578
-        ret = EOK;
8d3578
-        goto done;
8d3578
-    } else if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_OP_FAILURE,
8d3578
-              "An unexpected error occurred: [%d][%s]\n",
8d3578
-              ret, strerror(ret));
8d3578
-        goto done;
8d3578
-    }
8d3578
-
8d3578
-    if (map->ready == false) {
8d3578
-        DEBUG(SSSDBG_TRACE_FUNC, "Performing implicit setautomntent\n");
8d3578
-        req = setautomntent_send(cmdctx, cmdctx->mapname, cmdctx);
8d3578
-        if (req == NULL) {
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_send failed\n");
8d3578
-            ret = EIO;
8d3578
-            goto done;
8d3578
-        }
8d3578
-
8d3578
-        tevent_req_set_callback(req, getautomntbyname_implicit_done, cmdctx);
8d3578
-        ret = EOK;
8d3578
-        goto done;
8d3578
-    } else if (map->found == false) {
8d3578
-        DEBUG(SSSDBG_TRACE_FUNC, "negative cache hit\n");
8d3578
-        ret = ENOENT;
8d3578
-        goto done;
8d3578
-    }
8d3578
-
8d3578
-    DEBUG(SSSDBG_TRACE_INTERNAL,
8d3578
-          "Looking up value for [%s] in [%s]\n", cmdctx->key, map->mapname);
8d3578
-
8d3578
-    ret = getautomntbyname_process(cmdctx, map, cmdctx->key);
8d3578
-
8d3578
-done:
8d3578
-    return autofs_cmd_done(cmdctx, ret);
8d3578
-}
8d3578
-
8d3578
-static void
8d3578
-getautomntbyname_implicit_done(struct tevent_req *req)
8d3578
-{
8d3578
-    errno_t ret;
8d3578
-    struct autofs_map_ctx *map;
8d3578
-    struct autofs_cmd_ctx *cmdctx =
8d3578
-        tevent_req_callback_data(req, struct autofs_cmd_ctx);
8d3578
-    struct autofs_ctx *actx =
8d3578
-        talloc_get_type(cmdctx->cctx->rctx->pvt_ctx, struct autofs_ctx);
8d3578
-
8d3578
-    ret = setautomntent_recv(req);
8d3578
-    talloc_zfree(req);
8d3578
-    if (ret != EOK) {
8d3578
-        if (ret != ENOENT) {
8d3578
-            DEBUG(SSSDBG_CRIT_FAILURE, "setautomntent_recv failed\n");
8d3578
-        } else {
8d3578
-            DEBUG(SSSDBG_MINOR_FAILURE, "No such map\n");
8d3578
-        }
8d3578
-        goto done;
8d3578
-    }
8d3578
-
8d3578
-    ret = get_autofs_map(actx, cmdctx->mapname, &map);
8d3578
-    if (ret != EOK) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Cannot get map after setautomntent succeeded?\n");
8d3578
-        goto done;
8d3578
+    if (!sss_utf8_check((const uint8_t *)keyname, keylen - 1)) {
8d3578
+        return EINVAL;
8d3578
     }
8d3578
 
8d3578
-    if (map->ready == false) {
8d3578
-        DEBUG(SSSDBG_CRIT_FAILURE,
8d3578
-              "Map not ready after setautomntent succeeded\n");
8d3578
-        goto done;
8d3578
-    }
8d3578
+    *_mapname = mapname;
8d3578
+    *_keyname = keyname;
8d3578
 
8d3578
-    ret = getautomntbyname_process(cmdctx, map, cmdctx->key);
8d3578
-done:
8d3578
-    autofs_cmd_done(cmdctx, ret);
8d3578
-    return;
8d3578
+    return EOK;
8d3578
 }
8d3578
 
8d3578
 static errno_t
8d3578
-getautomntbyname_process(struct autofs_cmd_ctx *cmdctx,
8d3578
-                         struct autofs_map_ctx *map,
8d3578
-                         const char *key)
8d3578
+autofs_write_getautomntbyname_output(struct cli_ctx *cli_ctx,
8d3578
+                                     struct autofs_enum_ctx *enum_ctx,
8d3578
+                                     const char *keyname)
8d3578
 {
8d3578
     struct cli_protocol *pctx;
8d3578
-    errno_t ret;
8d3578
-    size_t i;
8d3578
-    const char *k;
8d3578
+    struct ldb_message **entries;
8d3578
+    struct ldb_message *entry = NULL;
8d3578
+    const char *entry_key;
8d3578
     const char *value;
8d3578
-    size_t valuelen;
8d3578
+    size_t value_len;
8d3578
     size_t len;
8d3578
+    size_t count;
8d3578
     uint8_t *body;
8d3578
-    size_t blen, rp;
8d3578
+    size_t blen;
8d3578
+    size_t rp;
8d3578
+    size_t i;
8d3578
+    errno_t ret;
8d3578
 
8d3578
-    pctx = talloc_get_type(cmdctx->cctx->protocol_ctx, struct cli_protocol);
8d3578
+    pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol);
8d3578
 
8d3578
-    /* create response packet */
8d3578
-    ret = sss_packet_new(pctx->creq, 0,
8d3578
-                         sss_packet_get_cmd(pctx->creq->in),
8d3578
+    count = enum_ctx->found ? enum_ctx->result->count - 1 : 0;
8d3578
+    entries = count > 0 ? enum_ctx->result->msgs + 1 : NULL;
8d3578
+
8d3578
+    ret = sss_packet_new(pctx->creq, 0, sss_packet_get_cmd(pctx->creq->in),
8d3578
                          &pctx->creq->out);
8d3578
     if (ret != EOK) {
8d3578
         return ret;
8d3578
     }
8d3578
 
8d3578
-    if (!map->map || !map->entries || !map->entries[0]) {
8d3578
-        DEBUG(SSSDBG_MINOR_FAILURE, "No entries found\n");
8d3578
-        ret = sss_cmd_empty_packet(pctx->creq->out);
8d3578
-        if (ret != EOK) {
8d3578
-            return autofs_cmd_done(cmdctx, ret);
8d3578
-        }
8d3578
-        goto done;
8d3578
-    }
8d3578
-
8d3578
-    for (i=0; i < map->entry_count; i++) {
8d3578
-        k = ldb_msg_find_attr_as_string(map->entries[i],
8d3578
-                                        SYSDB_AUTOFS_ENTRY_KEY, NULL);
8d3578
-        if (!k) {
8d3578
+    for (i = 0; i < count; i++) {
8d3578
+        entry_key = ldb_msg_find_attr_as_string(entries[i],
8d3578
+                                                SYSDB_AUTOFS_ENTRY_KEY,
8d3578
+                                                NULL);
8d3578
+        if (entry_key == NULL) {
8d3578
             DEBUG(SSSDBG_MINOR_FAILURE, "Skipping incomplete entry\n");
8d3578
             continue;
8d3578
         }
8d3578
 
8d3578
-        if (strcmp(k, key) == 0) {
8d3578
-            DEBUG(SSSDBG_TRACE_INTERNAL, "Found key [%s]\n", key);
8d3578
+        if (strcmp(entry_key, keyname) == 0) {
8d3578
+            DEBUG(SSSDBG_TRACE_INTERNAL, "Found key [%s]\n", keyname);
8d3578
+            entry = entries[i];
8d3578
             break;
8d3578
         }
8d3578
     }
8d3578
 
8d3578
-    if (i >= map->entry_count) {
8d3578
-        DEBUG(SSSDBG_MINOR_FAILURE, "No key named [%s] found\n", key);
8d3578
-        ret = sss_cmd_empty_packet(pctx->creq->out);
8d3578
-        if (ret != EOK) {
8d3578
-            return autofs_cmd_done(cmdctx, ret);
8d3578
-        }
8d3578
-        goto done;
8d3578
+    if (!enum_ctx->found || count == 0 || entry == NULL) {
8d3578
+        DEBUG(SSSDBG_TRACE_FUNC, "Key [%s] was not found\n", keyname);
8d3578
+        return sss_cmd_empty_packet(pctx->creq->out);
8d3578
     }
8d3578
 
8d3578
-    value = ldb_msg_find_attr_as_string(map->entries[i],
8d3578
-                                        SYSDB_AUTOFS_ENTRY_VALUE, NULL);
8d3578
+    value = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_VALUE, NULL);
8d3578
+    if (value == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "No entry value found in [%s]\n", keyname);
8d3578
+        return EINVAL;
8d3578
+    }
8d3578
 
8d3578
-    valuelen = 1 + strlen(value);
8d3578
-    len = sizeof(uint32_t) + sizeof(uint32_t) + valuelen;
8d3578
+    value_len = 1 + strlen(value);
8d3578
+    len = sizeof(uint32_t) + sizeof(uint32_t) + value_len;
8d3578
 
8d3578
     ret = sss_packet_grow(pctx->creq->out, len);
8d3578
     if (ret != EOK) {
8d3578
-        goto done;
8d3578
+        return ret;
8d3578
     }
8d3578
 
8d3578
     sss_packet_get_body(pctx->creq->out, &body, &blen);
8d3578
@@ -1449,43 +818,88 @@ getautomntbyname_process(struct autofs_cmd_ctx *cmdctx,
8d3578
     rp = 0;
8d3578
     SAFEALIGN_SET_UINT32(&body[rp], len, &rp);
8d3578
 
8d3578
-    SAFEALIGN_SET_UINT32(&body[rp], valuelen, &rp);
8d3578
-    if (valuelen == 1) {
8d3578
+    SAFEALIGN_SET_UINT32(&body[rp], value_len, &rp);
8d3578
+    if (value_len == 1) {
8d3578
         body[rp] = '\0';
8d3578
     } else {
8d3578
-        memcpy(&body[rp], value, valuelen);
8d3578
+        memcpy(&body[rp], value, value_len);
8d3578
     }
8d3578
-    rp += valuelen;
8d3578
-
8d3578
-    ret = EOK;
8d3578
-done:
8d3578
-    sss_packet_set_error(pctx->creq->out, ret);
8d3578
-    sss_cmd_done(cmdctx->cctx, cmdctx);
8d3578
 
8d3578
     return EOK;
8d3578
 }
8d3578
 
8d3578
+static void
8d3578
+sss_autofs_cmd_getautomntbyname_done(struct tevent_req *req);
8d3578
+
8d3578
 static int
8d3578
-sss_autofs_cmd_endautomntent(struct cli_ctx *client)
8d3578
+sss_autofs_cmd_getautomntbyname(struct cli_ctx *cli_ctx)
8d3578
 {
8d3578
-    struct cli_protocol *pctx;
8d3578
+    struct autofs_cmd_ctx *cmd_ctx;
8d3578
+    struct autofs_ctx *autofs_ctx;
8d3578
+    struct tevent_req *req;
8d3578
     errno_t ret;
8d3578
 
8d3578
-    DEBUG(SSSDBG_TRACE_FUNC, "endautomntent called\n");
8d3578
+    autofs_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct autofs_ctx);
8d3578
 
8d3578
-    pctx = talloc_get_type(client->protocol_ctx, struct cli_protocol);
8d3578
+    cmd_ctx = talloc_zero(cli_ctx, struct autofs_cmd_ctx);
8d3578
+    if (cmd_ctx == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create command context.\n");
8d3578
+        return ENOMEM;
8d3578
+    }
8d3578
 
8d3578
-    /* create response packet */
8d3578
-    ret = sss_packet_new(pctx->creq, 0,
8d3578
-                         sss_packet_get_cmd(pctx->creq->in),
8d3578
-                         &pctx->creq->out);
8d3578
+    cmd_ctx->cli_ctx = cli_ctx;
8d3578
+    cmd_ctx->autofs_ctx = autofs_ctx;
8d3578
 
8d3578
+    ret = autofs_read_getautomntbyname_input(cli_ctx, &cmd_ctx->mapname,
8d3578
+                                             &cmd_ctx->keyname);
8d3578
     if (ret != EOK) {
8d3578
-        return ret;
8d3578
+        goto done;
8d3578
     }
8d3578
 
8d3578
-    sss_cmd_done(client, NULL);
8d3578
-    return EOK;
8d3578
+    DEBUG(SSSDBG_TRACE_FUNC, "Obtaining enumeration context for %s\n",
8d3578
+          cmd_ctx->mapname);
8d3578
+
8d3578
+    req = autofs_setent_send(cli_ctx, cli_ctx->ev, autofs_ctx, cmd_ctx->mapname);
8d3578
+    if (req == NULL) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request\n");
8d3578
+        ret = ENOMEM;
8d3578
+        goto done;
8d3578
+    }
8d3578
+
8d3578
+    tevent_req_set_callback(req, sss_autofs_cmd_getautomntbyname_done, cmd_ctx);
8d3578
+
8d3578
+    ret = EOK;
8d3578
+
8d3578
+done:
8d3578
+    return autofs_cmd_done(cmd_ctx, ret);
8d3578
+}
8d3578
+
8d3578
+static void
8d3578
+sss_autofs_cmd_getautomntbyname_done(struct tevent_req *req)
8d3578
+{
8d3578
+    struct autofs_enum_ctx *enum_ctx;
8d3578
+    struct autofs_cmd_ctx *cmd_ctx;
8d3578
+    errno_t ret;
8d3578
+
8d3578
+    cmd_ctx = tevent_req_callback_data(req, struct autofs_cmd_ctx);
8d3578
+
8d3578
+    ret = autofs_setent_recv(req, &enum_ctx);
8d3578
+    talloc_zfree(req);
8d3578
+    if (ret != EOK) {
8d3578
+        autofs_cmd_done(cmd_ctx, ret);
8d3578
+        return;
8d3578
+    }
8d3578
+
8d3578
+    ret = autofs_write_getautomntbyname_output(cmd_ctx->cli_ctx, enum_ctx,
8d3578
+                                               cmd_ctx->keyname);
8d3578
+    if (ret != EOK) {
8d3578
+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create reply packet "
8d3578
+              "[%d]: %s\n", ret, sss_strerror(ret));
8d3578
+        autofs_cmd_done(cmd_ctx, ret);
8d3578
+        return;
8d3578
+    }
8d3578
+
8d3578
+    sss_cmd_done(cmd_ctx->cli_ctx, NULL);
8d3578
 }
8d3578
 
8d3578
 struct cli_protocol_version *register_cli_protocol_version(void)
8d3578
@@ -1518,10 +932,5 @@ int autofs_connection_setup(struct cli_ctx *cctx)
8d3578
     ret = sss_connection_setup(cctx);
8d3578
     if (ret != EOK) return ret;
8d3578
 
8d3578
-    cctx->state_ctx = talloc_zero(cctx, struct autofs_state_ctx);
8d3578
-    if (!cctx->state_ctx) {
8d3578
-        return ENOMEM;
8d3578
-    }
8d3578
-
8d3578
     return EOK;
8d3578
 }
8d3578
-- 
8d3578
2.20.1
8d3578