nsssrv_services.c revision 4fcc50e133f90cd4c5931a3ac48c84cb628b16fc
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme Stephen Gallagher <sgallagh@redhat.com>
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme Copyright (C) 2012 Red Hat
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme This program is free software; you can redistribute it and/or modify
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme it under the terms of the GNU General Public License as published by
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme the Free Software Foundation; either version 3 of the License, or
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme (at your option) any later version.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme This program is distributed in the hope that it will be useful,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme but WITHOUT ANY WARRANTY; without even the implied warranty of
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim GNU General Public License for more details.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim You should have received a copy of the GNU General Public License
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme along with this program. If not, see <http://www.gnu.org/licenses/>.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemmestatic errno_t lookup_service_step(struct tevent_req *req);
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemmestatic void lookup_service_done(struct tevent_req *req);
59d316b83d42d2a07e25c20d8c35a07b369618bdsf#define SVC_NAME_CASED (dom->case_sensitive ? state->name \
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme#define SVC_PROTO_CASED (dom->case_sensitive ? state->proto \
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme/* Provider Lookup Logic:
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Iterate through the available caches. If the cached entry is
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * present and not expired, return it immediately(*). If it is
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * present and expired, add it to a list of domains eligible to
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * be checked. If it is in the negative cache, skip over it and
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * do not add it to the eligible domain list.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * Once we have searched all of the caches, if the entry has not
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * been determined to be available, search all domains in order
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * to see if any of them contain the requested entry.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * (*) Optionally perform a midpoint cache refresh if appropriate.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemmestatic struct tevent_req *
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme req = tevent_req_create(mem_ctx, &state, struct getserv_ctx);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick for (dom = cctx->rctx->domains; dom; dom = get_next_domain(dom, false)) {
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick /* Create an array of domains to check. To save resizes, we'll
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * assume that all will be checked
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Store both the case-sensitive and lowercased names
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * in the state object, to avoid recalculating the
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * lowercase in multiple domains.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme state->proto = talloc_strdup(state, service_protocol);
59d316b83d42d2a07e25c20d8c35a07b369618bdsf state->cased_proto = sss_get_cased_name(state, service_protocol,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* If we're looking up by name */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Store both the case-sensitive and lowercased names
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * in the state object, to avoid recalculating the
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * lowercase in multiple domains.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme state->cased_name = sss_get_cased_name(state, service_name,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* if it is a domainless search, skip domains that require fully
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * qualified names instead */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme if (!dom) break;
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme ("Critical: Sysdb CTX not found for [%s]!\n", dom->name));
024e70e05386a6367eb45d0d1cc406764520ff4cwrowe /* If we're looking up by name */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Check the negative cache */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* If negatively cached, return we didn't find it */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim ("Service [%s:%s] does not exist in [%s]! "
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim "(negative cache)\n",
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* If this is a multi-domain search, try the next one */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* This was a single-domain search.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * exit the loop. Since it was negatively-
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * cached, don't add it to the eligible
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * domains list.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Check the cache */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim ("Checking cache for [%s:%s@%s]\n",
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme } else { /* Looking up by port */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Check the negative cache */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* If negatively cached, return we didn't find it */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme "(negative cache)\n",
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* If this is a multi-domain search, try the next one */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* This was a single-domain search.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * exit the loop. Since it was negatively-
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * cached, don't add it to the eligible
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * domains list.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Check the cache */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Not found in the cache. Add this domain to the
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * list of eligible domains to check the provider.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* No provider to check. Set the negative cache here */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme ret = sss_ncache_set_service_name(nctx->ncache, false,
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* Failure to set the negative cache is non-fatal.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * We'll log an error and continue.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme ("Could not set negative cache for [%s][%s]\n",
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Failure to set the negative cache is non-fatal.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * We'll log an error and continue.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim ("Could not set negative cache for "
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* If this is a multi-domain search, try the next one */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* This was a single-domain search.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * exit the loop.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* Found a result. Check its validity */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim ("getservby* returned more than one result!\n"));
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme lastUpdate = ldb_msg_find_attr_as_uint64(state->res->msgs[0],
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim cacheExpire = ldb_msg_find_attr_as_uint64(state->res->msgs[0],
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme (cacheExpire - lastUpdate)*nctx->cache_refresh_percent/100.0;
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* If the percentage results in an expiration
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * less than ten seconds after the lastUpdate time,
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * that's too often we will simply set it to 10s
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* cache still valid */
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* We're past the cache refresh timeout
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * We'll return the value from the cache, but we'll also
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme * queue the cache entry for update out-of-band.
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme ("Performing midpoint cache update\n"));
70c233f481e297e0e07fb987072bc6d16dbf95e5sctemme /* Update the cache */
dom, true,
if (!subreq) {
goto immediate;
dom_idx++;
goto immediate;
return req;
return req;
dom,
return EOK;
char *err_msg;
&err_msg);
goto done;
dom,
dom,
goto done;
done:
static errno_t
return EOK;
static errno_t
const char *protocol,
unsigned int *count)
unsigned int num = 0;
const char *orig_name;
const char *orig_proto;
char *tmpstr;
rsize = 0;
for (i = 0; i < msg_count; i++) {
SYSDB_SVC_CLASS)) {
rsize = 0;
if (!port) {
if (protocol) {
num = 0;
goto done;
+ sizeof(uint32_t)
num = 0;
goto done;
if (!el) {
num_aliases = 0;
&rsize);
&rsize);
written_aliases = 0;
for (j = 0; j < num_aliases; j++) {
num = 0;
goto done;
&rsize);
num++;
done:
return ENOENT;
return ret;
char *default_domain,
char **domain_name,
char **service_name,
char **service_protocol);
char *domname;
char *service_name;
char *service_protocol;
if (!dctx) {
goto done;
goto done;
&domname,
goto done;
if (domname) {
goto done;
dctx);
if (!req) {
goto done;
done:
char *default_domain,
char **domain_name,
char **service_name,
char **service_protocol)
char *rawname;
char *domname;
char *svc_name;
char *protocol;
if (!rawname) {
goto done;
goto done;
namelen = i;
if (!protocol) {
goto done;
goto done;
goto done;
rawname));
goto done;
done:
return ret;
char **service_protocol)
size_t i, j;
char *protocol;
i = port_and_padding_len;
if (!protocol) {
goto done;
goto done;
goto done;
done:
return ret;
char *service_protocol;
if (!dctx) {
goto done;
goto done;
&port,
goto done;
if (!req) {
goto done;
done:
struct setservent_ctx {
static errno_t
static struct tevent_req *
static struct tevent_req *
unsigned int num_domains;
goto immediate;
goto immediate;
return req;
goto immediate;
num_domains = 0;
dom;
num_domains++;
struct dom_ctx,
goto immediate;
goto immediate;
if (!step_ctx) {
goto immediate;
return req;
return req;
static errno_t
if (!req) {
return ENOMEM;
return EOK;
struct lookup_servent_ctx {
static struct tevent_req *
goto immediate;
goto immediate;
goto immediate;
true, SSS_DP_SERVICES,
if (!subreq) {
goto immediate;
return req;
return req;
char *err_msg;
goto done;
done:
static errno_t
return EOK;
void *pvt);
if (!te) {
void *pvt)
static errno_t
return EOK;
if (!cmdctx) {
return ENOMEM;
if (!req) {
goto done;
done:
static errno_t
static errno_t
if (!cmdctx) {
return ENOMEM;
if (!req) {
return EIO;
cmdctx);
return EOK;
static errno_t
int ret;
return EINVAL;
return ret;
return EOK;
static errno_t
none:
return ret;
int ret;
return ret;
done:
return EOK;