diff options
-rw-r--r-- | src/responder/common/responder.h | 16 | ||||
-rw-r--r-- | src/responder/common/responder_cmd.c | 79 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_cmd.c | 75 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_netgroup.c | 14 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_private.h | 22 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_services.c | 27 |
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 |