summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/responder/common/responder.h16
-rw-r--r--src/responder/common/responder_cmd.c79
-rw-r--r--src/responder/nss/nsssrv_cmd.c75
-rw-r--r--src/responder/nss/nsssrv_netgroup.c14
-rw-r--r--src/responder/nss/nsssrv_private.h22
-rw-r--r--src/responder/nss/nsssrv_services.c27
6 files changed, 133 insertions, 100 deletions
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 1c85b9d2..0eabe647 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -94,11 +94,6 @@ struct resp_ctx {
void *pvt_ctx;
};
-/* Needed for the NSS responder */
-struct getent_ref_tracker {
- void *pvt;
-};
-
struct cli_ctx {
struct tevent_context *ev;
struct resp_ctx *rctx;
@@ -163,6 +158,17 @@ void sss_cmd_done(struct cli_ctx *cctx, void *freectx);
int sss_cmd_get_version(struct cli_ctx *cctx);
struct cli_protocol_version *register_cli_protocol_version(void);
+struct setent_req_list;
+
+/* A facility for notifying setent requests */
+struct tevent_req *setent_get_req(struct setent_req_list *sl);
+errno_t setent_add_ref(TALLOC_CTX *memctx,
+ void *pvt,
+ struct setent_req_list **list,
+ struct tevent_req *req);
+void setent_notify(struct setent_req_list *list, errno_t err);
+void setent_notify_done(struct setent_req_list *list);
+
typedef void (*sss_dp_callback_t)(uint16_t err_maj, uint32_t err_min,
const char *err_msg, void *ptr);
diff --git a/src/responder/common/responder_cmd.c b/src/responder/common/responder_cmd.c
index bfac8f97..28315e06 100644
--- a/src/responder/common/responder_cmd.c
+++ b/src/responder/common/responder_cmd.c
@@ -155,3 +155,82 @@ int sss_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds)
return EINVAL;
}
+
+struct setent_req_list {
+ struct setent_req_list *prev;
+ struct setent_req_list *next;
+ /* Need to point to the head of the list from a talloc destructor */
+ struct setent_req_list *head;
+
+ void *pvt;
+
+ struct tevent_req *req;
+};
+
+struct tevent_req *
+setent_get_req(struct setent_req_list *sl)
+{
+ return sl->req;
+}
+
+int setent_remove_ref(TALLOC_CTX *ctx)
+{
+ struct setent_req_list *entry =
+ talloc_get_type(ctx, struct setent_req_list);
+ DLIST_REMOVE(entry->head, entry);
+ return 0;
+}
+
+errno_t setent_add_ref(TALLOC_CTX *memctx,
+ void *pvt,
+ struct setent_req_list **list,
+ struct tevent_req *req)
+{
+ struct setent_req_list *entry;
+
+ entry = talloc_zero(memctx, struct setent_req_list);
+ if (!entry) {
+ return ENOMEM;
+ }
+
+ entry->req = req;
+ entry->pvt = pvt;
+ DLIST_ADD_END(*list, entry, struct setent_req_list *);
+ entry->head = *list;
+
+ talloc_set_destructor((TALLOC_CTX *)entry, setent_remove_ref);
+ return EOK;
+}
+
+void setent_notify(struct setent_req_list *list, errno_t err)
+{
+ struct setent_req_list *reql;
+
+ /* Notify the waiting clients */
+ while ((reql = list)) {
+ /* Each tevent_req_done() call will free
+ * the request, removing it from the list.
+ */
+ if (err == EOK) {
+ tevent_req_done(reql->req);
+ } else {
+ tevent_req_error(reql->req, err);
+ }
+
+ if (reql == list) {
+ /* The consumer failed to free the
+ * request. Log a bug and continue.
+ */
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("BUG: a callback did not free its request. "
+ "May leak memory\n"));
+ /* Skip to the next since a memory leak is non-fatal */
+ list = list->next;
+ }
+ }
+}
+
+void setent_notify_done(struct setent_req_list *list)
+{
+ return setent_notify(list, EOK);
+}
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 1dff829e..43ae947c 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -77,31 +77,26 @@ int nss_cmd_done(struct nss_cmd_ctx *cmdctx, int ret)
/***************************
* Enumeration procedures *
***************************/
-
-errno_t setent_add_ref(TALLOC_CTX *memctx,
- struct getent_ctx *getent_ctx,
- struct tevent_req *req)
+struct tevent_req *nss_setent_get_req(struct getent_ctx *getent_ctx)
{
- struct setent_req_list *entry =
- talloc_zero(memctx, struct setent_req_list);
- if (!entry) {
- return ENOMEM;
- }
+ return setent_get_req(getent_ctx->reqs);
+}
- entry->req = req;
- entry->getent_ctx = getent_ctx;
- DLIST_ADD_END(getent_ctx->reqs, entry, struct setent_req_list *);
+errno_t nss_setent_add_ref(TALLOC_CTX *memctx,
+ struct getent_ctx *getent_ctx,
+ struct tevent_req *req)
+{
+ return setent_add_ref(memctx, getent_ctx, &getent_ctx->reqs, req);
+}
- talloc_set_destructor((TALLOC_CTX *)entry, setent_remove_ref);
- return EOK;
+void nss_setent_notify_error(struct getent_ctx *getent_ctx, errno_t ret)
+{
+ return setent_notify(getent_ctx->reqs, ret);
}
-int setent_remove_ref(TALLOC_CTX *ctx)
+void nss_setent_notify_done(struct getent_ctx *getent_ctx)
{
- struct setent_req_list *entry =
- talloc_get_type(ctx, struct setent_req_list);
- DLIST_REMOVE(entry->getent_ctx->reqs, entry);
- return 0;
+ return setent_notify_done(getent_ctx->reqs);
}
struct setent_ctx {
@@ -1246,7 +1241,7 @@ struct tevent_req *nss_cmd_setpwent_send(TALLOC_CTX *mem_ctx,
* Register for notification when it's
* ready.
*/
- ret = setent_add_ref(state->client, state->nctx->pctx, req);
+ ret = nss_setent_add_ref(state->client, state->nctx->pctx, req);
if (ret != EOK) {
talloc_free(req);
return NULL;
@@ -1268,7 +1263,8 @@ struct tevent_req *nss_cmd_setpwent_send(TALLOC_CTX *mem_ctx,
state->getent_ctx = nctx->pctx;
/* Add a callback reference for ourselves */
- setent_add_ref(state->client, state->nctx->pctx, req);
+ ret = nss_setent_add_ref(state->client, state->nctx->pctx, req);
+ if (ret) goto error;
/* ok, start the searches */
step_ctx = talloc_zero(state->getent_ctx, struct setent_step_ctx);
@@ -1323,7 +1319,6 @@ static errno_t nss_cmd_setpwent_step(struct setent_step_ctx *step_ctx)
struct nss_ctx *nctx = step_ctx->nctx;
struct sysdb_ctx *sysdb;
struct ldb_result *res;
- struct setent_req_list *req;
struct timeval tv;
struct tevent_timer *te;
struct tevent_req *dpreq;
@@ -1434,13 +1429,7 @@ static errno_t nss_cmd_setpwent_step(struct setent_step_ctx *step_ctx)
}
/* Notify the waiting clients */
- while (nctx->pctx->reqs) {
- tevent_req_done(nctx->pctx->reqs->req);
- /* Freeing each entry in the list removes it from the dlist */
- req = nctx->pctx->reqs;
- nctx->pctx->reqs = nctx->pctx->reqs->next;
- talloc_free(req);
- }
+ setent_notify_done(nctx->pctx->reqs);
if (step_ctx->returned_to_mainloop) {
return EAGAIN;
@@ -1470,7 +1459,6 @@ static void nss_cmd_setpwent_dp_callback(uint16_t err_maj, uint32_t err_min,
{
struct setent_step_ctx *step_ctx =
talloc_get_type(ptr, struct setent_step_ctx);
- struct getent_ctx *pctx = step_ctx->nctx->pctx;
int ret;
if (err_maj) {
@@ -1483,11 +1471,7 @@ static void nss_cmd_setpwent_dp_callback(uint16_t err_maj, uint32_t err_min,
ret = nss_cmd_setpwent_step(step_ctx);
if (ret != EOK && ret != EAGAIN) {
/* Notify any waiting processes of failure */
- while(step_ctx->nctx->pctx->reqs) {
- tevent_req_error(pctx->reqs->req, ret);
- /* Freeing each entry in the list removes it from the dlist */
- talloc_free(pctx->reqs);
- }
+ nss_setent_notify_error(step_ctx->nctx->pctx, ret);
}
}
@@ -2555,7 +2539,7 @@ struct tevent_req *nss_cmd_setgrent_send(TALLOC_CTX *mem_ctx,
* Register for notification when it's
* ready.
*/
- ret = setent_add_ref(state->client, state->nctx->gctx, req);
+ ret = nss_setent_add_ref(state->client, state->nctx->gctx, req);
if (ret != EOK) {
talloc_free(req);
return NULL;
@@ -2577,7 +2561,8 @@ struct tevent_req *nss_cmd_setgrent_send(TALLOC_CTX *mem_ctx,
state->getent_ctx = nctx->gctx;
/* Add a callback reference for ourselves */
- setent_add_ref(state->client, state->nctx->gctx, req);
+ ret = nss_setent_add_ref(state->client, state->nctx->gctx, req);
+ if (ret) goto error;
/* ok, start the searches */
step_ctx = talloc_zero(state->getent_ctx, struct setent_step_ctx);
@@ -2632,7 +2617,6 @@ static errno_t nss_cmd_setgrent_step(struct setent_step_ctx *step_ctx)
struct nss_ctx *nctx = step_ctx->nctx;
struct sysdb_ctx *sysdb;
struct ldb_result *res;
- struct setent_req_list *req;
struct timeval tv;
struct tevent_timer *te;
struct tevent_req *dpreq;
@@ -2741,13 +2725,7 @@ static errno_t nss_cmd_setgrent_step(struct setent_step_ctx *step_ctx)
}
/* Notify the waiting clients */
- while (nctx->gctx->reqs) {
- tevent_req_done(nctx->gctx->reqs->req);
- /* Freeing each entry in the list removes it from the dlist */
- req = nctx->gctx->reqs;
- nctx->gctx->reqs = nctx->gctx->reqs->next;
- talloc_free(req);
- }
+ setent_notify_done(nctx->gctx->reqs);
if (step_ctx->returned_to_mainloop) {
return EAGAIN;
@@ -2778,7 +2756,6 @@ static void nss_cmd_setgrent_dp_callback(uint16_t err_maj, uint32_t err_min,
{
struct setent_step_ctx *step_ctx =
talloc_get_type(ptr, struct setent_step_ctx);
- struct getent_ctx *gctx = step_ctx->nctx->gctx;
int ret;
if (err_maj) {
@@ -2791,11 +2768,7 @@ static void nss_cmd_setgrent_dp_callback(uint16_t err_maj, uint32_t err_min,
ret = nss_cmd_setgrent_step(step_ctx);
if (ret != EOK && ret != EAGAIN) {
/* Notify any waiting processes of failure */
- while(step_ctx->nctx->gctx->reqs) {
- tevent_req_error(gctx->reqs->req, ret);
- /* Freeing each entry in the list removes it from the dlist */
- talloc_free(gctx->reqs);
- }
+ nss_setent_notify_error(step_ctx->nctx->gctx, ret);
}
}
diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c
index 2b9707ab..9943bca6 100644
--- a/src/responder/nss/nsssrv_netgroup.c
+++ b/src/responder/nss/nsssrv_netgroup.c
@@ -254,7 +254,7 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx,
/* Result object is still being constructed
* Register for notification when it's ready
*/
- ret = setent_add_ref(cmdctx->cctx, state->netgr, req);
+ ret = nss_setent_add_ref(cmdctx->cctx, state->netgr, req);
if (ret != EOK) {
goto error;
}
@@ -281,7 +281,7 @@ static struct tevent_req *setnetgrent_send(TALLOC_CTX *mem_ctx,
state->netgr->lookup_table = nctx->netgroups;
/* Add a reference for ourselves */
- ret = setent_add_ref(cmdctx->cctx, state->netgr, req);
+ ret = nss_setent_add_ref(cmdctx->cctx, state->netgr, req);
if (ret != EOK) {
talloc_free(state->netgr);
goto error;
@@ -557,15 +557,7 @@ static void lookup_netgr_dp_callback(uint16_t err_maj, uint32_t err_min,
}
/* We have results to return */
- while(dctx->netgr->reqs) {
- if (ret == EOK) {
- tevent_req_done(dctx->netgr->reqs->req);
- } else {
- tevent_req_error(dctx->netgr->reqs->req, ret);
- }
- /* Freeing each entry in the list removes it from the dlist */
- talloc_free(dctx->netgr->reqs);
- }
+ nss_setent_notify_error(dctx->netgr, ret);
}
static void setnetgrent_result_timeout(struct tevent_context *ev,
diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h
index 876552fb..0f581574 100644
--- a/src/responder/nss/nsssrv_private.h
+++ b/src/responder/nss/nsssrv_private.h
@@ -45,14 +45,6 @@ struct dom_ctx {
struct ldb_result *res;
};
-struct setent_req_list {
- struct setent_req_list *prev;
- struct setent_req_list *next;
- struct getent_ctx *getent_ctx;
-
- struct tevent_req *req;
-};
-
struct getent_ctx {
struct dom_ctx *doms;
int num;
@@ -109,10 +101,16 @@ struct setent_step_ctx {
/* Finish the request */
int nss_cmd_done(struct nss_cmd_ctx *cmdctx, int ret);
-int setent_remove_ref(TALLOC_CTX *ctx);
-errno_t setent_add_ref(TALLOC_CTX *memctx,
- struct getent_ctx *getent_ctx,
- struct tevent_req *req);
+/* Respond with no entries */
+int fill_empty(struct sss_packet *packet);
+
+errno_t nss_setent_add_ref(TALLOC_CTX *memctx,
+ struct getent_ctx *getent_ctx,
+ struct tevent_req *req);
+struct tevent_req *nss_setent_get_req(struct getent_ctx *getent_ctx);
+
+void nss_setent_notify_error(struct getent_ctx *getent_ctx, errno_t ret);
+void nss_setent_notify_done(struct getent_ctx *getent_ctx);
errno_t check_cache(struct nss_dom_ctx *dctx,
struct nss_ctx *nctx,
diff --git a/src/responder/nss/nsssrv_services.c b/src/responder/nss/nsssrv_services.c
index da37708b..3ce3d090 100644
--- a/src/responder/nss/nsssrv_services.c
+++ b/src/responder/nss/nsssrv_services.c
@@ -1215,7 +1215,7 @@ setservent_send(TALLOC_CTX *mem_ctx, struct cli_ctx *cctx)
* Register for notification when it's
* ready.
*/
- ret = setent_add_ref(state, state->nctx->svcctx, req);
+ ret = nss_setent_add_ref(state, state->nctx->svcctx, req);
if (ret != EOK) goto immediate;
}
return req;
@@ -1252,7 +1252,10 @@ setservent_send(TALLOC_CTX *mem_ctx, struct cli_ctx *cctx)
}
/* Add a callback reference for ourselves */
- setent_add_ref(state, state->nctx->svcctx, req);
+ ret = nss_setent_add_ref(state, state->nctx->svcctx, req);
+ if (ret != EOK) {
+ goto immediate;
+ }
/* ok, start the searches */
step_ctx = talloc_zero(state->getent_ctx, struct setent_step_ctx);
@@ -1510,7 +1513,6 @@ setservent_finalize(struct setent_step_ctx *step_ctx)
struct resp_ctx *rctx = step_ctx->rctx;
struct timeval tv;
struct tevent_timer *te;
- struct setent_req_list *reql;
/* We've finished all our lookups
* The result object is now safe to read.
@@ -1530,24 +1532,7 @@ setservent_finalize(struct setent_step_ctx *step_ctx)
"Entries may become stale.\n"));
}
- /* Notify the waiting clients */
- while ((reql = nctx->svcctx->reqs)) {
- /* Each tevent_req_done() call will free
- * the request, removing it from the list.
- */
- tevent_req_done(reql->req);
-
- if (reql == nctx->svcctx->reqs) {
- /* The consumer failed to free the
- * request. Log a bug and continue.
- */
- DEBUG(SSSDBG_FATAL_FAILURE,
- ("BUG: a callback did not free its request. "
- "May leak memory\n"));
- /* Skip to the next since a memory leak is non-fatal */
- nctx->svcctx->reqs = nctx->svcctx->reqs->next;
- }
- }
+ nss_setent_notify_done(nctx->svcctx);
}
static void