summaryrefslogtreecommitdiffstats
path: root/server/responder/nss/nsssrv_cmd.c
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-03-12 22:59:31 -0400
committerSimo Sorce <ssorce@redhat.com>2009-03-13 13:47:38 -0400
commitdd4d867835a1443cb5a10b7a678d1d12400690d6 (patch)
treea78b211c0ae56369ba22a8dc7add0de3f13c7a77 /server/responder/nss/nsssrv_cmd.c
parent063ef0f15dfc32d15d2e9bdcba819906aa99b948 (diff)
downloadsssd-dd4d867835a1443cb5a10b7a678d1d12400690d6.tar.gz
sssd-dd4d867835a1443cb5a10b7a678d1d12400690d6.tar.xz
sssd-dd4d867835a1443cb5a10b7a678d1d12400690d6.zip
Implement Negative cache for NSS
As for positive caches, negative caches are implement for all queries except enumerations. Also set the correct requires in sssd.spec as we now depend directly on tdb as well.
Diffstat (limited to 'server/responder/nss/nsssrv_cmd.c')
-rw-r--r--server/responder/nss/nsssrv_cmd.c259
1 files changed, 256 insertions, 3 deletions
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index 4117f9771..ef9dd31d5 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -23,6 +23,7 @@
#include "util/btreemap.h"
#include "responder/common/responder_packet.h"
#include "responder/nss/nsssrv.h"
+#include "responder/nss/nsssrv_nc.h"
#include "db/sysdb.h"
#include <time.h>
#include "confdb/confdb.h"
@@ -54,6 +55,9 @@ struct nss_dom_ctx {
struct sss_domain_info *domain;
bool add_domain;
bool check_provider;
+
+ /* cache results */
+ struct ldb_result *res;
};
struct nss_cmd_table {
@@ -267,7 +271,7 @@ done:
}
static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr);
+ const char *err_msg, void *ptr);
static void nss_cmd_getpwnam_callback(void *ptr, int status,
struct ldb_result *res)
@@ -280,6 +284,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
if (status != LDB_SUCCESS) {
@@ -316,12 +321,38 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_user(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ dctx->domain->name, cmdctx->name);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for getpwnam call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = true;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* dont loop forever :-) */
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getpwnam_dp_callback, dctx,
timeout, dctx->domain->name, NSS_DP_USER,
@@ -343,6 +374,15 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status,
DEBUG(2, ("No results for getpwnam call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_user(cctx->nctx->ncache,
+ dctx->domain->name, cmdctx->name);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -383,7 +423,7 @@ done:
}
static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
- const char *err_msg, void *ptr)
+ const char *err_msg, void *ptr)
{
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
@@ -395,13 +435,28 @@ static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getpwnam_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->name,
nss_cmd_getpwnam_callback, dctx);
+
+done:
if (ret != EOK) {
- DEBUG(1, ("Failed to make request to our cache!\n"));
+ DEBUG(1, ("Failed to make request to our cache! (%d [%s])\n",
+ ret, strerror(ret)));
ret = nss_cmd_send_error(cmdctx, ret);
if (ret != EOK) {
@@ -481,6 +536,7 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
/* one less to go */
@@ -529,6 +585,27 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_uid(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ cmdctx->id);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for getpwuid call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = true;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* yet one more call to go */
@@ -538,6 +615,11 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getpwuid_dp_callback, dctx,
timeout, dctx->domain->name, NSS_DP_USER,
@@ -563,6 +645,14 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status,
DEBUG(2, ("No results for getpwuid call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_uid(cctx->nctx->ncache, cmdctx->id);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -620,11 +710,25 @@ static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getpwnam_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getpwuid(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->id,
nss_cmd_getpwuid_callback, dctx);
+
+done:
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1249,6 +1353,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
if (status != LDB_SUCCESS) {
@@ -1277,12 +1382,38 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_group(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ dctx->domain->name, cmdctx->name);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for getgrnam call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = true;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* dont loop forever :-) */
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getgrnam_dp_callback, dctx,
timeout, dctx->domain->name, NSS_DP_GROUP,
@@ -1305,6 +1436,15 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status,
DEBUG(2, ("No results for getgrnam call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_group(cctx->nctx->ncache,
+ dctx->domain->name, cmdctx->name);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -1352,11 +1492,25 @@ static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getgrnam_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getgrnam(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->name,
nss_cmd_getgrnam_callback, dctx);
+
+done:
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -1437,6 +1591,7 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
/* one less to go */
@@ -1476,6 +1631,27 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_gid(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ cmdctx->id);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for getgrgid call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = true;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* yet one more call to go */
@@ -1485,6 +1661,11 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getgrgid_dp_callback, dctx,
timeout, dctx->domain->name, NSS_DP_GROUP,
@@ -1510,6 +1691,14 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status,
DEBUG(2, ("No results for getgrgid call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_gid(cctx->nctx->ncache, cmdctx->id);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);
@@ -1561,11 +1750,25 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getgrgid_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getgrgid(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->id,
nss_cmd_getgrgid_callback, dctx);
+
+done:
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -2082,11 +2285,25 @@ static void nss_cmd_getinitnam_callback(uint16_t err_maj, uint32_t err_min,
"Error: %u, %u, %s\n"
"Will try to return what we have in cache\n",
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
+
+ if (!dctx->res) {
+ /* return 0 results */
+ dctx->res = talloc_zero(dctx, struct ldb_result);
+ if (!dctx->res) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ nss_cmd_getinit_callback(dctx, LDB_SUCCESS, dctx->res);
+ return;
}
ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
dctx->domain, cmdctx->name,
nss_cmd_getinit_callback, dctx);
+
+done:
if (ret != EOK) {
DEBUG(1, ("Failed to make request to our cache!\n"));
@@ -2109,6 +2326,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
uint8_t *body;
size_t blen;
bool call_provider = false;
+ bool neghit = false;
int ret;
if (status != LDB_SUCCESS) {
@@ -2136,12 +2354,38 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
}
}
+ if (call_provider && res->count == 0) {
+ /* check negative cache before potentially expensive remote call */
+ ret = nss_ncache_check_user(cctx->nctx->ncache,
+ cctx->nctx->neg_timeout,
+ dctx->domain->name, cmdctx->name);
+ switch (ret) {
+ case EEXIST:
+ DEBUG(2, ("Negative cache hit for initgr call\n"));
+ res->count = 0;
+ call_provider = false;
+ neghit = false;
+ break;
+ case ENOENT:
+ break;
+ default:
+ DEBUG(4,("Error processing ncache request: %d [%s]\n",
+ ret, strerror(ret)));
+ }
+ ret = EOK;
+ }
+
if (call_provider) {
/* dont loop forever :-) */
dctx->check_provider = false;
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
+ /* keep around current data in case backend is offline */
+ if (res->count) {
+ dctx->res = talloc_steal(dctx, res);
+ }
+
ret = nss_dp_send_acct_req(cctx->nctx, cmdctx,
nss_cmd_getinitnam_callback, dctx,
timeout, dctx->domain->name, NSS_DP_USER,
@@ -2164,6 +2408,15 @@ static void nss_cmd_getinit_callback(void *ptr, int status,
DEBUG(2, ("No results for initgroups call\n"));
+ /* set negative cache only if not result of cache check */
+ if (!neghit) {
+ ret = nss_ncache_set_user(cctx->nctx->ncache,
+ dctx->domain->name, cmdctx->name);
+ if (ret != EOK) {
+ NSS_CMD_FATAL_ERROR(cctx);
+ }
+ }
+
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
sss_packet_get_cmd(cctx->creq->in),
&cctx->creq->out);