|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* lookup_sss.c - module for Linux automount to query sss service
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 2012 Ian Kent <raven@themaw.net>
|
|
Packit |
8480eb |
* Copyright 2012 Red Hat, Inc.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8480eb |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8480eb |
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
|
|
Packit |
8480eb |
* USA; either version 2 of the License, or (at your option) any later
|
|
Packit |
8480eb |
* version; incorporated herein by reference.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* ----------------------------------------------------------------------- */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include <stdio.h>
|
|
Packit |
8480eb |
#include <malloc.h>
|
|
Packit |
8480eb |
#include <stdlib.h>
|
|
Packit |
8480eb |
#include <ctype.h>
|
|
Packit |
8480eb |
#include <dlfcn.h>
|
|
Packit |
8480eb |
#include <errno.h>
|
|
Packit |
8480eb |
#include <string.h>
|
|
Packit |
8480eb |
#include <sys/param.h>
|
|
Packit |
8480eb |
#include <sys/types.h>
|
|
Packit |
8480eb |
#include <sys/stat.h>
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MODULE_LOOKUP
|
|
Packit |
8480eb |
#include "automount.h"
|
|
Packit |
8480eb |
#include "nsswitch.h"
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MAPFMT_DEFAULT "sun"
|
|
Packit |
8480eb |
|
|
Packit Bot |
911e0c |
/* One second between retries */
|
|
Packit Bot |
911e0c |
#define SSS_WAIT_INTERVAL 1
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MODPREFIX "lookup(sss): "
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define SSS_SO_NAME "libsss_autofs"
|
|
Packit |
8480eb |
|
|
Packit Bot |
f53394 |
/* If the sss library protocol version is greater than 0 there are
|
|
Packit Bot |
f53394 |
* more possibile error returns from the sss autofs library calls.
|
|
Packit Bot |
f53394 |
*
|
|
Packit Bot |
f53394 |
* If ECONNREFUSED is returned then sssd is not running or not
|
|
Packit Bot |
f53394 |
* configured on the system, immediately return an unavailable
|
|
Packit Bot |
f53394 |
* status.
|
|
Packit Bot |
f53394 |
*
|
|
Packit Bot |
f53394 |
* A return of EHOSTDOWN means sss backend server is down so we
|
|
Packit Bot |
f53394 |
* should retry.
|
|
Packit Bot |
f53394 |
*
|
|
Packit Bot |
f53394 |
* With older sss ilibrary we can get a return of ENOENT for the
|
|
Packit Bot |
f53394 |
* above cases so also wait in that case since we can't be sure
|
|
Packit Bot |
f53394 |
* the map doesn't exist.
|
|
Packit Bot |
f53394 |
*/
|
|
Packit Bot |
f53394 |
#define SSS_PROTO_VERSION 1
|
|
Packit Bot |
f53394 |
|
|
Packit Bot |
30c946 |
#define SSS_DEFAULT_WAIT 10
|
|
Packit Bot |
30c946 |
|
|
Packit Bot |
30c946 |
/* When the master map is being read a retry loop is used by the
|
|
Packit Bot |
30c946 |
* caller to try harder to read the master map because it is required
|
|
Packit Bot |
30c946 |
* for autofs to start up.
|
|
Packit Bot |
30c946 |
*
|
|
Packit Bot |
30c946 |
* But when reading dependent maps or looking up a key that loop isn't
|
|
Packit Bot |
30c946 |
* used so a longer retry is needed for those cases.
|
|
Packit Bot |
30c946 |
*
|
|
Packit Bot |
30c946 |
* Introduce a flag to indicate which map is being read or if a lookup
|
|
Packit Bot |
30c946 |
* is being done so the number of retries can be adjusted accordingly.
|
|
Packit Bot |
30c946 |
*/
|
|
Packit Bot |
30c946 |
#define SSS_READ_NONE 0x00
|
|
Packit Bot |
30c946 |
#define SSS_READ_MASTER_MAP 0x01
|
|
Packit Bot |
30c946 |
#define SSS_REREAD_MASTER_MAP 0x02
|
|
Packit Bot |
30c946 |
#define SSS_READ_DEPENDENT_MAP 0x04
|
|
Packit Bot |
30c946 |
#define SSS_LOOKUP_KEY 0x08
|
|
Packit Bot |
30c946 |
|
|
Packit Bot |
f53394 |
unsigned int _sss_auto_protocol_version(unsigned int);
|
|
Packit |
8480eb |
int _sss_setautomntent(const char *, void **);
|
|
Packit |
8480eb |
int _sss_getautomntent_r(char **, char **, void *);
|
|
Packit |
8480eb |
int _sss_getautomntbyname_r(char *, char **, void *);
|
|
Packit |
8480eb |
int _sss_endautomntent(void **);
|
|
Packit |
8480eb |
|
|
Packit Bot |
f53394 |
typedef unsigned int (*protocol_version_t) (unsigned int);
|
|
Packit |
8480eb |
typedef int (*setautomntent_t) (const char *, void **);
|
|
Packit |
8480eb |
typedef int (*getautomntent_t) (char **, char **, void *);
|
|
Packit |
8480eb |
typedef int (*getautomntbyname_t) (char *, char **, void *);
|
|
Packit |
8480eb |
typedef int (*endautomntent_t) (void **);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct lookup_context {
|
|
Packit |
8480eb |
const char *mapname;
|
|
Packit |
8480eb |
void *dlhandle;
|
|
Packit Bot |
f53394 |
protocol_version_t protocol_version;
|
|
Packit |
8480eb |
setautomntent_t setautomntent;
|
|
Packit |
8480eb |
getautomntent_t getautomntent_r;
|
|
Packit |
8480eb |
getautomntbyname_t getautomntbyname_r;
|
|
Packit |
8480eb |
endautomntent_t endautomntent;
|
|
Packit |
8480eb |
struct parse_mod *parse;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */
|
|
Packit Bot |
f53394 |
int sss_proto_version = SSS_PROTO_VERSION; /* 0 => initial version,
|
|
Packit Bot |
f53394 |
* >= 1 => new error handling. */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int open_sss_lib(struct lookup_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char dlbuf[PATH_MAX];
|
|
Packit |
8480eb |
char *estr;
|
|
Packit |
8480eb |
void *dh;
|
|
Packit |
8480eb |
size_t size;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
size = snprintf(dlbuf, sizeof(dlbuf),
|
|
Packit |
8480eb |
"%s/%s.so", SSS_LIB_DIR, SSS_SO_NAME);
|
|
Packit |
8480eb |
if (size >= sizeof(dlbuf)) {
|
|
Packit |
8480eb |
logmsg(MODPREFIX "sss library path too long");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
dh = dlopen(dlbuf, RTLD_LAZY);
|
|
Packit |
8480eb |
if (!dh)
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
ctxt->dlhandle = dh;
|
|
Packit |
8480eb |
|
|
Packit Bot |
f53394 |
/* Don't fail on NULL, it's simply not present in this version of the
|
|
Packit Bot |
f53394 |
* sss autofs library.
|
|
Packit Bot |
f53394 |
*/
|
|
Packit Bot |
f53394 |
ctxt->protocol_version = (protocol_version_t) dlsym(dh, "_sss_auto_protocol_version");
|
|
Packit Bot |
f53394 |
|
|
Packit |
8480eb |
ctxt->setautomntent = (setautomntent_t) dlsym(dh, "_sss_setautomntent");
|
|
Packit |
8480eb |
if (!ctxt->setautomntent)
|
|
Packit |
8480eb |
goto lib_names_fail;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt->getautomntent_r = (getautomntent_t) dlsym(dh, "_sss_getautomntent_r");
|
|
Packit |
8480eb |
if (!ctxt->getautomntent_r)
|
|
Packit |
8480eb |
goto lib_names_fail;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt->getautomntbyname_r = (getautomntbyname_t) dlsym(dh, "_sss_getautomntbyname_r");
|
|
Packit |
8480eb |
if (!ctxt->getautomntbyname_r)
|
|
Packit |
8480eb |
goto lib_names_fail;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt->endautomntent = (endautomntent_t) dlsym(dh, "_sss_endautomntent");
|
|
Packit Bot |
8c7b8f |
if (!ctxt->endautomntent)
|
|
Packit |
8480eb |
goto lib_names_fail;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
lib_names_fail:
|
|
Packit |
8480eb |
if ((estr = dlerror()) == NULL)
|
|
Packit |
8480eb |
logmsg(MODPREFIX "failed to locate sss library entry points");
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
logerr(MODPREFIX "dlsym: %s", estr);
|
|
Packit |
8480eb |
dlclose(dh);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int do_init(const char *mapfmt,
|
|
Packit |
8480eb |
int argc, const char *const *argv,
|
|
Packit |
8480eb |
struct lookup_context *ctxt, unsigned int reinit)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (argc < 1) {
|
|
Packit |
8480eb |
logerr(MODPREFIX "No map name");
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ctxt->mapname = argv[0];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mapfmt)
|
|
Packit |
8480eb |
mapfmt = MAPFMT_DEFAULT;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!reinit) {
|
|
Packit |
8480eb |
ret = open_sss_lib(ctxt);
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (reinit) {
|
|
Packit |
8480eb |
ret = reinit_parse(ctxt->parse, mapfmt, MODPREFIX, argc - 1, argv + 1);
|
|
Packit |
8480eb |
if (ret)
|
|
Packit |
8480eb |
logmsg(MODPREFIX "failed to reinit parse context");
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
|
|
Packit |
8480eb |
if (!ctxt->parse) {
|
|
Packit |
8480eb |
logmsg(MODPREFIX "failed to open parse context");
|
|
Packit |
8480eb |
dlclose(ctxt->dlhandle);
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int lookup_init(const char *mapfmt,
|
|
Packit |
8480eb |
int argc, const char *const *argv, void **context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct lookup_context *ctxt;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *estr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*context = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt = malloc(sizeof(struct lookup_context));
|
|
Packit |
8480eb |
if (!ctxt) {
|
|
Packit |
8480eb |
estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (do_init(mapfmt, argc, argv, ctxt, 0)) {
|
|
Packit |
8480eb |
free(ctxt);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*context = ctxt;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int lookup_reinit(const char *mapfmt,
|
|
Packit |
8480eb |
int argc, const char *const *argv, void **context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct lookup_context *ctxt = (struct lookup_context *) *context;
|
|
Packit |
8480eb |
struct lookup_context *new;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new = malloc(sizeof(struct lookup_context));
|
|
Packit |
8480eb |
if (!new) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new->parse = ctxt->parse;
|
|
Packit |
8480eb |
ret = do_init(mapfmt, argc, argv, new, 1);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
free(new);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new->dlhandle = ctxt->dlhandle;
|
|
Packit Bot |
f53394 |
new->protocol_version = ctxt->protocol_version;
|
|
Packit |
8480eb |
new->setautomntent = ctxt->setautomntent;
|
|
Packit |
8480eb |
new->getautomntent_r = ctxt->getautomntent_r;
|
|
Packit |
8480eb |
new->getautomntbyname_r = ctxt->getautomntbyname_r;
|
|
Packit |
8480eb |
new->endautomntent = ctxt->endautomntent;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*context = new;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Bot |
f53394 |
static unsigned int proto_version(struct lookup_context *ctxt)
|
|
Packit Bot |
f53394 |
{
|
|
Packit Bot |
f53394 |
unsigned int proto_version = 0;
|
|
Packit Bot |
f53394 |
|
|
Packit Bot |
f53394 |
if (ctxt->protocol_version) {
|
|
Packit Bot |
f53394 |
/* If ctxt->protocol_version() is defined it's assumed
|
|
Packit Bot |
f53394 |
* that for sss_proto_version <= sss autofs library
|
|
Packit Bot |
f53394 |
* protocol version ctxt->protocol_version() will
|
|
Packit Bot |
f53394 |
* return the version requested by autofs to indicate
|
|
Packit Bot |
f53394 |
* it userstands what the autofs module is capable of
|
|
Packit Bot |
f53394 |
* handling.
|
|
Packit Bot |
f53394 |
*/
|
|
Packit Bot |
f53394 |
proto_version = ctxt->protocol_version(sss_proto_version);
|
|
Packit Bot |
f53394 |
}
|
|
Packit Bot |
f53394 |
return proto_version;
|
|
Packit Bot |
f53394 |
}
|
|
Packit Bot |
f53394 |
|
|
Packit Bot |
30c946 |
static unsigned int calculate_retry_count(struct lookup_context *ctxt, unsigned int flags)
|
|
Packit Service |
d36279 |
{
|
|
Packit Bot |
fa8e22 |
int retries;
|
|
Packit Service |
d36279 |
|
|
Packit Bot |
410fe4 |
retries = defaults_get_sss_master_map_wait();
|
|
Packit Bot |
9e51da |
|
|
Packit Bot |
9e51da |
/* If sss_master_map_wait is not set in the autofs
|
|
Packit Bot |
9e51da |
* configuration give it a sensible value since we
|
|
Packit Bot |
9e51da |
* want to wait for a host that's down in case it
|
|
Packit Bot |
9e51da |
* comes back up.
|
|
Packit Bot |
fa8e22 |
*
|
|
Packit Bot |
fa8e22 |
* Use the sss_master_map_wait configuration option
|
|
Packit Bot |
fa8e22 |
* for the time to wait when reading a dependednt map
|
|
Packit Bot |
fa8e22 |
* or performing a key lookup too.
|
|
Packit Bot |
9e51da |
*/
|
|
Packit Bot |
9e51da |
if (retries <= 0) {
|
|
Packit Bot |
9e51da |
/* Protocol version 0 cant't tell us about
|
|
Packit Bot |
fa8e22 |
* a host being down, return 0 for retries.
|
|
Packit Bot |
9e51da |
*/
|
|
Packit Bot |
9e51da |
if (proto_version(ctxt) == 0)
|
|
Packit Bot |
30c946 |
return 0;
|
|
Packit Bot |
fa8e22 |
else
|
|
Packit Bot |
30c946 |
retries = SSS_DEFAULT_WAIT;
|
|
Packit Bot |
fa8e22 |
}
|
|
Packit Bot |
30c946 |
|
|
Packit Bot |
30c946 |
if (proto_version(ctxt) == 0)
|
|
Packit Bot |
30c946 |
return retries;
|
|
Packit Bot |
30c946 |
|
|
Packit Bot |
30c946 |
/* When the master map is being read there's an additional
|
|
Packit Bot |
30c946 |
* outer wait loop.
|
|
Packit Bot |
30c946 |
*
|
|
Packit Bot |
30c946 |
* If master map wait is set in the configuration there
|
|
Packit Bot |
30c946 |
* will be an outer loop interating master_map_wait / 2
|
|
Packit Bot |
30c946 |
* times so adjust the number of retries here to account
|
|
Packit Bot |
30c946 |
* for this for the cases where the master map isn't being
|
|
Packit Bot |
30c946 |
* read.
|
|
Packit Bot |
30c946 |
*/
|
|
Packit Bot |
30c946 |
|
|
Packit Bot |
30c946 |
if (!(flags & SSS_READ_MASTER_MAP) ||
|
|
Packit Bot |
30c946 |
(flags & SSS_REREAD_MASTER_MAP)) {
|
|
Packit Bot |
30c946 |
unsigned int master_map_wait = defaults_get_master_wait();
|
|
Packit Bot |
30c946 |
unsigned int m_wait;
|
|
Packit Bot |
30c946 |
|
|
Packit Bot |
30c946 |
m_wait = master_map_wait ? master_map_wait : SSS_DEFAULT_WAIT;
|
|
Packit Bot |
30c946 |
retries *= (m_wait / 2);
|
|
Packit Bot |
30c946 |
}
|
|
Packit Bot |
30c946 |
|
|
Packit Bot |
fa8e22 |
return retries;
|
|
Packit Bot |
fa8e22 |
}
|
|
Packit Bot |
fa8e22 |
|
|
Packit Bot |
fa8e22 |
static int setautomntent_wait(unsigned int logopt,
|
|
Packit Bot |
30c946 |
struct lookup_context *ctxt, void **sss_ctxt,
|
|
Packit Bot |
30c946 |
unsigned int flags)
|
|
Packit Bot |
fa8e22 |
{
|
|
Packit Bot |
fa8e22 |
unsigned int retries;
|
|
Packit Bot |
fa8e22 |
unsigned int retry = 0;
|
|
Packit Bot |
fa8e22 |
int ret = 0;
|
|
Packit Bot |
fa8e22 |
|
|
Packit Bot |
fa8e22 |
*sss_ctxt = NULL;
|
|
Packit Bot |
fa8e22 |
|
|
Packit Bot |
30c946 |
retries = calculate_retry_count(ctxt, flags);
|
|
Packit Bot |
fa8e22 |
if (retries == 0) {
|
|
Packit Bot |
fa8e22 |
if (proto_version(ctxt) == 0)
|
|
Packit Bot |
fa8e22 |
return EINVAL;
|
|
Packit Bot |
fa8e22 |
return ENOENT;
|
|
Packit Bot |
9e51da |
}
|
|
Packit Bot |
9e51da |
|
|
Packit Bot |
9e51da |
warn(logopt,
|
|
Packit Bot |
9e51da |
"can't connect to sssd, retry for %d seconds",
|
|
Packit Bot |
9e51da |
retries);
|
|
Packit Bot |
410fe4 |
|
|
Packit Bot |
911e0c |
while (++retry <= retries) {
|
|
Packit Bot |
911e0c |
struct timespec t = { SSS_WAIT_INTERVAL, 0 };
|
|
Packit |
8480eb |
struct timespec r;
|
|
Packit |
8480eb |
|
|
Packit Bot |
0162f1 |
ret = ctxt->setautomntent(ctxt->mapname, sss_ctxt);
|
|
Packit Bot |
9e51da |
if (proto_version(ctxt) == 0) {
|
|
Packit Bot |
9e51da |
if (ret != ENOENT)
|
|
Packit Bot |
9e51da |
break;
|
|
Packit Bot |
9e51da |
} else {
|
|
Packit Bot |
9e51da |
if (ret != EHOSTDOWN)
|
|
Packit Bot |
9e51da |
break;
|
|
Packit Bot |
9e51da |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*sss_ctxt) {
|
|
Packit |
8480eb |
free(*sss_ctxt);
|
|
Packit |
8480eb |
*sss_ctxt = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (nanosleep(&t, &r) == -1 && errno == EINTR)
|
|
Packit |
8480eb |
memcpy(&t, &r, sizeof(struct timespec));
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Bot |
9e51da |
if (!ret)
|
|
Packit Bot |
9e51da |
info(logopt, "successfully connected to sssd");
|
|
Packit Bot |
9e51da |
else {
|
|
Packit |
8480eb |
if (*sss_ctxt) {
|
|
Packit |
8480eb |
free(*sss_ctxt);
|
|
Packit |
8480eb |
*sss_ctxt = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Bot |
9e51da |
if (proto_version(ctxt) == 0 && retry > retries)
|
|
Packit |
8480eb |
ret = ETIMEDOUT;
|
|
Packit Service |
f147de |
}
|
|
Packit Bot |
06041b |
return ret;
|
|
Packit Service |
f147de |
}
|
|
Packit Service |
f147de |
|
|
Packit Bot |
410fe4 |
static int setautomntent(unsigned int logopt,
|
|
Packit Bot |
30c946 |
struct lookup_context *ctxt, void **sss_ctxt,
|
|
Packit Bot |
30c946 |
unsigned int flags)
|
|
Packit Bot |
410fe4 |
{
|
|
Packit Bot |
410fe4 |
char buf[MAX_ERR_BUF];
|
|
Packit Bot |
410fe4 |
char *estr;
|
|
Packit Bot |
9e51da |
int err = NSS_STATUS_UNAVAIL;
|
|
Packit Bot |
410fe4 |
int ret;
|
|
Packit Bot |
410fe4 |
|
|
Packit Bot |
410fe4 |
ret = ctxt->setautomntent(ctxt->mapname, sss_ctxt);
|
|
Packit Bot |
410fe4 |
if (ret) {
|
|
Packit Bot |
9e51da |
if (ret == ECONNREFUSED) {
|
|
Packit Bot |
9e51da |
err = NSS_STATUS_UNKNOWN;
|
|
Packit Bot |
410fe4 |
goto error;
|
|
Packit Bot |
9e51da |
}
|
|
Packit Bot |
9e51da |
|
|
Packit Bot |
9e51da |
if (proto_version(ctxt) == 0) {
|
|
Packit Bot |
9e51da |
if (ret != ENOENT)
|
|
Packit Bot |
9e51da |
goto error;
|
|
Packit Bot |
9e51da |
} else {
|
|
Packit Bot |
9e51da |
if (ret != ENOENT && ret != EHOSTDOWN)
|
|
Packit Bot |
9e51da |
goto error;
|
|
Packit Bot |
9e51da |
}
|
|
Packit Bot |
410fe4 |
|
|
Packit Bot |
30c946 |
ret = setautomntent_wait(logopt, ctxt, sss_ctxt, flags);
|
|
Packit Bot |
410fe4 |
if (ret) {
|
|
Packit Bot |
9e51da |
if (ret == ECONNREFUSED) {
|
|
Packit Bot |
9e51da |
err = NSS_STATUS_UNKNOWN;
|
|
Packit Bot |
9e51da |
goto error;
|
|
Packit Bot |
9e51da |
}
|
|
Packit Bot |
9e51da |
if (ret == ETIMEDOUT)
|
|
Packit Bot |
9e51da |
goto error;
|
|
Packit Bot |
fa8e22 |
/* sss proto version 0 and sss timeout not set */
|
|
Packit Bot |
fa8e22 |
if (ret == EINVAL)
|
|
Packit Bot |
fa8e22 |
goto free;
|
|
Packit Bot |
9e51da |
if (ret == ENOENT) {
|
|
Packit Bot |
9e51da |
err = NSS_STATUS_NOTFOUND;
|
|
Packit Bot |
9e51da |
goto free;
|
|
Packit Bot |
9e51da |
}
|
|
Packit Bot |
410fe4 |
goto error;
|
|
Packit Bot |
410fe4 |
}
|
|
Packit Bot |
410fe4 |
}
|
|
Packit Bot |
9e51da |
return NSS_STATUS_SUCCESS;
|
|
Packit Bot |
410fe4 |
|
|
Packit Bot |
410fe4 |
error:
|
|
Packit Bot |
410fe4 |
estr = strerror_r(ret, buf, MAX_ERR_BUF);
|
|
Packit Bot |
410fe4 |
error(logopt, MODPREFIX "setautomntent: %s", estr);
|
|
Packit Bot |
9e51da |
free:
|
|
Packit Bot |
410fe4 |
if (*sss_ctxt) {
|
|
Packit Bot |
410fe4 |
free(*sss_ctxt);
|
|
Packit Bot |
410fe4 |
*sss_ctxt = NULL;
|
|
Packit Bot |
410fe4 |
}
|
|
Packit Bot |
9e51da |
return err;
|
|
Packit Bot |
410fe4 |
}
|
|
Packit Bot |
410fe4 |
|
|
Packit |
8480eb |
static int endautomntent(unsigned int logopt,
|
|
Packit |
8480eb |
struct lookup_context *ctxt, void **sss_ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int ret = ctxt->endautomntent(sss_ctxt);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *estr = strerror_r(ret, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(logopt, MODPREFIX "endautomntent: %s", estr);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Bot |
468a14 |
static int getautomntent_wait(unsigned int logopt,
|
|
Packit Bot |
468a14 |
struct lookup_context *ctxt,
|
|
Packit Bot |
30c946 |
char **key, char **value, void *sss_ctxt,
|
|
Packit Bot |
30c946 |
unsigned int flags)
|
|
Packit Bot |
468a14 |
{
|
|
Packit Bot |
468a14 |
unsigned int retries;
|
|
Packit Bot |
468a14 |
unsigned int retry = 0;
|
|
Packit Bot |
468a14 |
int ret = 0;
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
30c946 |
retries = calculate_retry_count(ctxt, flags);
|
|
Packit Bot |
fa8e22 |
if (retries == 0) {
|
|
Packit Bot |
468a14 |
if (proto_version(ctxt) == 0)
|
|
Packit Bot |
fa8e22 |
return EINVAL;
|
|
Packit Bot |
fa8e22 |
return ENOENT;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
468a14 |
warn(logopt,
|
|
Packit Bot |
468a14 |
"can't contact sssd to to get map entry, retry for %d seconds",
|
|
Packit Bot |
468a14 |
retries);
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
468a14 |
while (++retry <= retries) {
|
|
Packit Bot |
468a14 |
struct timespec t = { SSS_WAIT_INTERVAL, 0 };
|
|
Packit Bot |
468a14 |
struct timespec r;
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
468a14 |
ret = ctxt->getautomntent_r(key, value, sss_ctxt);
|
|
Packit Bot |
468a14 |
if (proto_version(ctxt) == 0) {
|
|
Packit Bot |
468a14 |
if (ret != ENOENT)
|
|
Packit Bot |
468a14 |
break;
|
|
Packit Bot |
468a14 |
} else {
|
|
Packit Bot |
468a14 |
if (ret != EHOSTDOWN)
|
|
Packit Bot |
468a14 |
break;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
468a14 |
while (nanosleep(&t, &r) == -1 && errno == EINTR)
|
|
Packit Bot |
468a14 |
memcpy(&t, &r, sizeof(struct timespec));
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
468a14 |
if (!ret)
|
|
Packit Bot |
468a14 |
info(logopt,
|
|
Packit Bot |
468a14 |
"successfully contacted sssd to get map entry");
|
|
Packit Bot |
468a14 |
else {
|
|
Packit Bot |
468a14 |
if (retry == retries)
|
|
Packit Bot |
468a14 |
ret = ETIMEDOUT;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
return ret;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
db7f4e |
static int getautomntent(unsigned int logopt,
|
|
Packit Bot |
db7f4e |
struct lookup_context *ctxt,
|
|
Packit Bot |
30c946 |
char **key, char **value, int count,
|
|
Packit Bot |
30c946 |
void *sss_ctxt, unsigned int flags)
|
|
Packit Bot |
db7f4e |
{
|
|
Packit Bot |
db7f4e |
char buf[MAX_ERR_BUF];
|
|
Packit Bot |
db7f4e |
char *estr;
|
|
Packit Bot |
468a14 |
int err = NSS_STATUS_UNAVAIL;
|
|
Packit Bot |
468a14 |
int ret;
|
|
Packit Bot |
db7f4e |
|
|
Packit Bot |
db7f4e |
ret = ctxt->getautomntent_r(key, value, sss_ctxt);
|
|
Packit Bot |
db7f4e |
if (ret) {
|
|
Packit Bot |
db7f4e |
/* Host has gone down */
|
|
Packit Bot |
468a14 |
if (ret == ECONNREFUSED) {
|
|
Packit Bot |
468a14 |
err = NSS_STATUS_UNKNOWN;
|
|
Packit Bot |
db7f4e |
goto error;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
468a14 |
if (proto_version(ctxt) == 0) {
|
|
Packit Bot |
468a14 |
if (ret != ENOENT)
|
|
Packit Bot |
468a14 |
goto error;
|
|
Packit Bot |
468a14 |
/* For prorocol version 0 ENOENT can only be
|
|
Packit Bot |
468a14 |
* used to indicate we've read all entries.
|
|
Packit Bot |
468a14 |
* So even if we haven't got any values yet we
|
|
Packit Bot |
468a14 |
* can't use it to determine if we need to wait
|
|
Packit Bot |
468a14 |
* on sss.
|
|
Packit Bot |
468a14 |
*/
|
|
Packit Bot |
468a14 |
err = NSS_STATUS_NOTFOUND;
|
|
Packit Bot |
468a14 |
if (count)
|
|
Packit Bot |
468a14 |
err = NSS_STATUS_SUCCESS;
|
|
Packit Bot |
db7f4e |
goto free;
|
|
Packit Bot |
468a14 |
} else {
|
|
Packit Bot |
468a14 |
if (ret == ENOENT) {
|
|
Packit Bot |
468a14 |
err = NSS_STATUS_NOTFOUND;
|
|
Packit Bot |
468a14 |
if (count)
|
|
Packit Bot |
468a14 |
err = NSS_STATUS_SUCCESS;
|
|
Packit Bot |
468a14 |
goto free;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
if (ret != EHOSTDOWN)
|
|
Packit Bot |
468a14 |
goto error;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
|
|
Packit Bot |
468a14 |
ret = getautomntent_wait(logopt, ctxt,
|
|
Packit Bot |
30c946 |
key, value, sss_ctxt, flags);
|
|
Packit Bot |
468a14 |
if (ret) {
|
|
Packit Bot |
468a14 |
if (ret == ECONNREFUSED) {
|
|
Packit Bot |
468a14 |
err = NSS_STATUS_UNKNOWN;
|
|
Packit Bot |
468a14 |
goto free;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
if (ret == ETIMEDOUT)
|
|
Packit Bot |
468a14 |
goto error;
|
|
Packit Bot |
fa8e22 |
/* sss proto version 0 and sss timeout not set => EINVAL */
|
|
Packit Bot |
fa8e22 |
if (ret == ENOENT || ret == EINVAL) {
|
|
Packit Bot |
468a14 |
err = NSS_STATUS_NOTFOUND;
|
|
Packit Bot |
468a14 |
if (count)
|
|
Packit Bot |
468a14 |
err = NSS_STATUS_SUCCESS;
|
|
Packit Bot |
468a14 |
goto free;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
goto error;
|
|
Packit Bot |
db7f4e |
}
|
|
Packit Bot |
db7f4e |
}
|
|
Packit Bot |
468a14 |
return NSS_STATUS_SUCCESS;
|
|
Packit Bot |
db7f4e |
|
|
Packit Bot |
db7f4e |
error:
|
|
Packit Bot |
db7f4e |
estr = strerror_r(ret, buf, MAX_ERR_BUF);
|
|
Packit Bot |
db7f4e |
error(logopt, MODPREFIX "getautomntent: %s", estr);
|
|
Packit Bot |
db7f4e |
free:
|
|
Packit Bot |
468a14 |
if (*key) {
|
|
Packit Bot |
db7f4e |
free(*key);
|
|
Packit Bot |
468a14 |
*key = NULL;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
if (*value) {
|
|
Packit Bot |
db7f4e |
free(*value);
|
|
Packit Bot |
468a14 |
*value = NULL;
|
|
Packit Bot |
468a14 |
}
|
|
Packit Bot |
468a14 |
return err;
|
|
Packit Bot |
db7f4e |
}
|
|
Packit Bot |
db7f4e |
|
|
Packit Bot |
64c555 |
static int getautomntbyname_wait(unsigned int logopt,
|
|
Packit Bot |
64c555 |
struct lookup_context *ctxt,
|
|
Packit Bot |
64c555 |
char *key, char **value, void *sss_ctxt,
|
|
Packit Bot |
64c555 |
unsigned int flags)
|
|
Packit Bot |
64c555 |
{
|
|
Packit Bot |
64c555 |
unsigned int retries;
|
|
Packit Bot |
64c555 |
unsigned int retry = 0;
|
|
Packit Bot |
64c555 |
int ret = 0;
|
|
Packit Bot |
64c555 |
|
|
Packit Bot |
64c555 |
retries = calculate_retry_count(ctxt, flags);
|
|
Packit Bot |
64c555 |
if (retries == 0) {
|
|
Packit Bot |
64c555 |
if (proto_version(ctxt) == 0)
|
|
Packit Bot |
64c555 |
return EINVAL;
|
|
Packit Bot |
64c555 |
return ENOENT;
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
64c555 |
|
|
Packit Bot |
64c555 |
warn(logopt,
|
|
Packit Bot |
64c555 |
"can't contact sssd to to lookup key value, retry for %d seconds",
|
|
Packit Bot |
64c555 |
retries);
|
|
Packit Bot |
64c555 |
|
|
Packit Bot |
64c555 |
while (++retry <= retries) {
|
|
Packit Bot |
64c555 |
struct timespec t = { SSS_WAIT_INTERVAL, 0 };
|
|
Packit Bot |
64c555 |
struct timespec r;
|
|
Packit Bot |
64c555 |
|
|
Packit Bot |
64c555 |
ret = ctxt->getautomntbyname_r(key, value, sss_ctxt);
|
|
Packit Bot |
64c555 |
if (proto_version(ctxt) == 0) {
|
|
Packit Bot |
64c555 |
if (ret != ENOENT)
|
|
Packit Bot |
64c555 |
break;
|
|
Packit Bot |
64c555 |
} else {
|
|
Packit Bot |
64c555 |
if (ret != EHOSTDOWN)
|
|
Packit Bot |
64c555 |
break;
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
64c555 |
|
|
Packit Bot |
64c555 |
while (nanosleep(&t, &r) == -1 && errno == EINTR)
|
|
Packit Bot |
64c555 |
memcpy(&t, &r, sizeof(struct timespec));
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
64c555 |
|
|
Packit Bot |
64c555 |
if (!ret)
|
|
Packit Bot |
64c555 |
info(logopt,
|
|
Packit Bot |
64c555 |
"successfully contacted sssd to lookup key value");
|
|
Packit Bot |
64c555 |
else {
|
|
Packit Bot |
64c555 |
if (proto_version(ctxt) == 0 && retry > retries)
|
|
Packit Bot |
64c555 |
ret = ETIMEDOUT;
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
64c555 |
return ret;
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
64c555 |
|
|
Packit Bot |
48deea |
static int getautomntbyname(unsigned int logopt,
|
|
Packit Bot |
48deea |
struct lookup_context *ctxt,
|
|
Packit Bot |
64c555 |
char *key, char **value, void *sss_ctxt,
|
|
Packit Bot |
64c555 |
unsigned int flags)
|
|
Packit Bot |
48deea |
{
|
|
Packit Bot |
48deea |
char buf[MAX_ERR_BUF];
|
|
Packit Bot |
48deea |
char *estr;
|
|
Packit Bot |
64c555 |
int err = NSS_STATUS_UNAVAIL;
|
|
Packit Bot |
64c555 |
int ret;
|
|
Packit Bot |
48deea |
|
|
Packit Bot |
48deea |
ret = ctxt->getautomntbyname_r(key, value, sss_ctxt);
|
|
Packit Bot |
48deea |
if (ret) {
|
|
Packit Bot |
48deea |
/* Host has gone down */
|
|
Packit Bot |
48deea |
if (ret == ECONNREFUSED)
|
|
Packit Bot |
48deea |
goto error;
|
|
Packit Bot |
48deea |
|
|
Packit Bot |
64c555 |
if (proto_version(ctxt) == 0) {
|
|
Packit Bot |
64c555 |
if (ret != ENOENT)
|
|
Packit Bot |
64c555 |
goto error;
|
|
Packit Bot |
64c555 |
/* For prorocol version 0 ENOENT can only be
|
|
Packit Bot |
64c555 |
* used to indicate no entry was found. So it
|
|
Packit Bot |
64c555 |
* can't be used to determine if we need to wait
|
|
Packit Bot |
64c555 |
* on sss.
|
|
Packit Bot |
64c555 |
*/
|
|
Packit Bot |
64c555 |
err = NSS_STATUS_NOTFOUND;
|
|
Packit Bot |
64c555 |
goto free;
|
|
Packit Bot |
64c555 |
} else {
|
|
Packit Bot |
64c555 |
if (ret == ENOENT) {
|
|
Packit Bot |
64c555 |
err = NSS_STATUS_NOTFOUND;
|
|
Packit Bot |
64c555 |
goto free;
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
64c555 |
if (ret != EHOSTDOWN)
|
|
Packit Bot |
64c555 |
goto error;
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
64c555 |
|
|
Packit Bot |
64c555 |
ret = getautomntbyname_wait(logopt, ctxt,
|
|
Packit Bot |
64c555 |
key, value, sss_ctxt, flags);
|
|
Packit Bot |
64c555 |
if (ret) {
|
|
Packit Bot |
64c555 |
if (ret == ECONNREFUSED)
|
|
Packit Bot |
64c555 |
goto free;
|
|
Packit Bot |
64c555 |
if (ret == ETIMEDOUT)
|
|
Packit Bot |
64c555 |
goto error;
|
|
Packit Bot |
64c555 |
/* sss proto version 0 and sss timeout not set */
|
|
Packit Bot |
64c555 |
if (ret == EINVAL)
|
|
Packit Bot |
64c555 |
goto free;
|
|
Packit Bot |
64c555 |
if (ret == ENOENT) {
|
|
Packit Bot |
64c555 |
err = NSS_STATUS_NOTFOUND;
|
|
Packit Bot |
64c555 |
goto free;
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
64c555 |
goto error;
|
|
Packit Bot |
64c555 |
}
|
|
Packit Bot |
48deea |
}
|
|
Packit Bot |
64c555 |
return NSS_STATUS_SUCCESS;
|
|
Packit Bot |
48deea |
|
|
Packit Bot |
48deea |
error:
|
|
Packit Bot |
48deea |
estr = strerror_r(ret, buf, MAX_ERR_BUF);
|
|
Packit Bot |
48deea |
error(logopt, MODPREFIX "getautomntbyname: %s", estr);
|
|
Packit Bot |
48deea |
free:
|
|
Packit Bot |
48deea |
if (*value) {
|
|
Packit Bot |
48deea |
free(*value);
|
|
Packit Bot |
48deea |
*value = NULL;
|
|
Packit Bot |
48deea |
}
|
|
Packit Bot |
64c555 |
return err;
|
|
Packit Bot |
48deea |
}
|
|
Packit Bot |
48deea |
|
|
Packit |
8480eb |
int lookup_read_master(struct master *master, time_t age, void *context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct lookup_context *ctxt = (struct lookup_context *) context;
|
|
Packit |
8480eb |
unsigned int timeout = master->default_timeout;
|
|
Packit |
8480eb |
unsigned int logging = master->default_logging;
|
|
Packit |
8480eb |
unsigned int logopt = master->logopt;
|
|
Packit |
8480eb |
void *sss_ctxt = NULL;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *buffer;
|
|
Packit |
8480eb |
size_t buffer_len;
|
|
Packit |
8480eb |
char *key;
|
|
Packit |
8480eb |
char *value = NULL;
|
|
Packit |
8480eb |
int count, ret;
|
|
Packit Bot |
30c946 |
unsigned int flags;
|
|
Packit Bot |
30c946 |
|
|
Packit Bot |
30c946 |
flags = SSS_READ_MASTER_MAP;
|
|
Packit Bot |
30c946 |
if (master->readall)
|
|
Packit Bot |
30c946 |
flags |= SSS_REREAD_MASTER_MAP;
|
|
Packit Service |
ed9eb2 |
|
|
Packit Bot |
30c946 |
ret = setautomntent(logopt, ctxt, &sss_ctxt, flags);
|
|
Packit Bot |
410fe4 |
if (ret)
|
|
Packit Bot |
410fe4 |
return ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
count = 0;
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
key = NULL;
|
|
Packit |
8480eb |
value = NULL;
|
|
Packit Bot |
30c946 |
ret = getautomntent(logopt, ctxt,
|
|
Packit Bot |
30c946 |
&key, &value, count,
|
|
Packit Bot |
30c946 |
sss_ctxt, SSS_READ_MASTER_MAP);
|
|
Packit Bot |
db7f4e |
if (ret) {
|
|
Packit |
8480eb |
endautomntent(logopt, ctxt, &sss_ctxt);
|
|
Packit Bot |
db7f4e |
return ret;
|
|
Packit Bot |
06041b |
}
|
|
Packit Bot |
db7f4e |
|
|
Packit Bot |
468a14 |
if (!key || !value)
|
|
Packit Bot |
468a14 |
break;
|
|
Packit Bot |
468a14 |
|
|
Packit |
8480eb |
count++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
buffer_len = strlen(key) + 1 + strlen(value) + 2;
|
|
Packit |
8480eb |
buffer = malloc(buffer_len);
|
|
Packit |
8480eb |
if (!buffer) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(logopt, MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
endautomntent(logopt, ctxt, &sss_ctxt);
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
free(value);
|
|
Packit |
8480eb |
return NSS_STATUS_UNAVAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* TODO: implement sun % hack for key translation for
|
|
Packit |
8480eb |
* mixed case keys in schema that are single case only.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(buffer, key);
|
|
Packit |
8480eb |
strcat(buffer, " ");
|
|
Packit |
8480eb |
strcat(buffer, value);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* TODO: handle cancelation. This almost certainly isn't
|
|
Packit |
8480eb |
* handled properly by other lookup modules either so it
|
|
Packit |
8480eb |
* should be done when cancelation is reviewed for the
|
|
Packit |
8480eb |
* other modules. Ditto for the other lookup module entry
|
|
Packit |
8480eb |
* points.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
master_parse_entry(buffer, timeout, logging, age);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(buffer);
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
free(value);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
endautomntent(logopt, ctxt, &sss_ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct lookup_context *ctxt = (struct lookup_context *) context;
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
void *sss_ctxt = NULL;
|
|
Packit |
8480eb |
char *key;
|
|
Packit |
8480eb |
char *value = NULL;
|
|
Packit |
8480eb |
char *s_key;
|
|
Packit |
8480eb |
int count, ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = ap->entry->current;
|
|
Packit |
8480eb |
ap->entry->current = NULL;
|
|
Packit |
8480eb |
master_source_current_signal(ap->entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If we don't need to create directories (or don't need
|
|
Packit |
8480eb |
* to read an amd cache:=all map) then there's no use
|
|
Packit |
8480eb |
* reading the map. We always need to read the whole map
|
|
Packit |
8480eb |
* for direct mounts in order to mount the triggers.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->type != LKP_DIRECT &&
|
|
Packit |
8480eb |
!(ap->flags & (MOUNT_FLAG_GHOST|MOUNT_FLAG_AMD_CACHE_ALL))) {
|
|
Packit |
8480eb |
debug(ap->logopt, "map read not needed, so not done");
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Bot |
30c946 |
ret = setautomntent(ap->logopt, ctxt,
|
|
Packit Bot |
30c946 |
&sss_ctxt, SSS_READ_DEPENDENT_MAP);
|
|
Packit Bot |
410fe4 |
if (ret)
|
|
Packit Bot |
410fe4 |
return ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
count = 0;
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
key = NULL;
|
|
Packit |
8480eb |
value = NULL;
|
|
Packit Bot |
30c946 |
ret = getautomntent(ap->logopt, ctxt,
|
|
Packit Bot |
30c946 |
&key, &value, count,
|
|
Packit Bot |
30c946 |
sss_ctxt, SSS_READ_DEPENDENT_MAP);
|
|
Packit Bot |
db7f4e |
if (ret) {
|
|
Packit |
8480eb |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit Bot |
db7f4e |
return ret;
|
|
Packit Bot |
06041b |
}
|
|
Packit Service |
81e5af |
|
|
Packit Bot |
468a14 |
if (!key || !value)
|
|
Packit Bot |
468a14 |
break;
|
|
Packit Bot |
468a14 |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Ignore keys beginning with '+' as plus map
|
|
Packit |
8480eb |
* inclusion is only valid in file maps.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (*key == '+') {
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "ignoring '+' map entry - not in file map");
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
free(value);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*key == '/' && strlen(key) == 1) {
|
|
Packit |
8480eb |
if (ap->type == LKP_DIRECT) {
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
free(value);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
*key = '*';
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* TODO: implement sun % hack for key translation for
|
|
Packit |
8480eb |
* mixed case keys in schema that are single case only.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
s_key = sanitize_path(key, strlen(key), ap->type, ap->logopt);
|
|
Packit |
8480eb |
if (!s_key) {
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "invalid path %s", key);
|
|
Packit |
8480eb |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
free(value);
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
count++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
cache_update(mc, source, s_key, value, age);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(s_key);
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
free(value);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source->age = age;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int lookup_one(struct autofs_point *ap,
|
|
Packit |
8480eb |
char *qKey, int qKey_len, struct lookup_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
struct mapent *we;
|
|
Packit |
8480eb |
void *sss_ctxt = NULL;
|
|
Packit |
8480eb |
time_t age = monotonic_time(NULL);
|
|
Packit |
8480eb |
char *value = NULL;
|
|
Packit |
8480eb |
char *s_key;
|
|
Packit Bot |
2d2ce7 |
int err, ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = ap->entry->current;
|
|
Packit |
8480eb |
ap->entry->current = NULL;
|
|
Packit |
8480eb |
master_source_current_signal(ap->entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit Bot |
30c946 |
ret = setautomntent(ap->logopt, ctxt, &sss_ctxt, SSS_LOOKUP_KEY);
|
|
Packit Bot |
410fe4 |
if (ret)
|
|
Packit Bot |
410fe4 |
return ret;
|
|
Packit Service |
94cc8a |
|
|
Packit Bot |
64c555 |
ret = getautomntbyname(ap->logopt, ctxt,
|
|
Packit Bot |
64c555 |
qKey, &value, sss_ctxt, SSS_LOOKUP_KEY);
|
|
Packit Bot |
48deea |
if (ret == NSS_STATUS_NOTFOUND)
|
|
Packit Bot |
48deea |
goto wild;
|
|
Packit Bot |
48deea |
if (ret) {
|
|
Packit Bot |
06041b |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit Bot |
48deea |
return ret;
|
|
Packit Bot |
06041b |
}
|
|
Packit Bot |
48deea |
|
|
Packit Bot |
48deea |
/*
|
|
Packit Bot |
48deea |
* TODO: implement sun % hack for key translation for
|
|
Packit Bot |
48deea |
* mixed case keys in schema that are single case only.
|
|
Packit Bot |
48deea |
*/
|
|
Packit Bot |
48deea |
s_key = sanitize_path(qKey, qKey_len, ap->type, ap->logopt);
|
|
Packit Bot |
48deea |
if (!s_key) {
|
|
Packit |
8480eb |
free(value);
|
|
Packit Bot |
48deea |
value = NULL;
|
|
Packit Bot |
48deea |
goto wild;
|
|
Packit |
8480eb |
}
|
|
Packit Bot |
48deea |
cache_writelock(mc);
|
|
Packit Bot |
2d2ce7 |
err = cache_update(mc, source, s_key, value, age);
|
|
Packit Bot |
48deea |
cache_unlock(mc);
|
|
Packit Bot |
2d2ce7 |
/* Entry in map but not in cache, map is stale */
|
|
Packit Bot |
2d2ce7 |
if (err & CHE_UPDATED)
|
|
Packit Bot |
2d2ce7 |
source->stale = 1;
|
|
Packit Bot |
48deea |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit Bot |
48deea |
free(s_key);
|
|
Packit Bot |
48deea |
free(value);
|
|
Packit Bot |
48deea |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
wild:
|
|
Packit Bot |
64c555 |
ret = getautomntbyname(ap->logopt, ctxt,
|
|
Packit Bot |
64c555 |
"/", &value, sss_ctxt, SSS_LOOKUP_KEY);
|
|
Packit Bot |
48deea |
if (ret) {
|
|
Packit Bot |
48deea |
if (ret != NSS_STATUS_NOTFOUND) {
|
|
Packit Service |
94cc8a |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit Bot |
48deea |
return ret;
|
|
Packit Bot |
48deea |
}
|
|
Packit Bot |
64c555 |
ret = getautomntbyname(ap->logopt, ctxt,
|
|
Packit Bot |
64c555 |
"*", &value, sss_ctxt, SSS_LOOKUP_KEY);
|
|
Packit Bot |
48deea |
if (ret && ret != NSS_STATUS_NOTFOUND) {
|
|
Packit Bot |
48deea |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit Bot |
48deea |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit Bot |
48deea |
if (ret == NSS_STATUS_NOTFOUND) {
|
|
Packit |
8480eb |
/* Failed to find wild entry, update cache if needed */
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
we = cache_lookup_distinct(mc, "*");
|
|
Packit |
8480eb |
if (we) {
|
|
Packit |
8480eb |
/* Wildcard entry existed and is now gone */
|
|
Packit |
8480eb |
if (we->source == source) {
|
|
Packit |
8480eb |
cache_delete(mc, "*");
|
|
Packit |
8480eb |
source->stale = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Not found in the map but found in the cache */
|
|
Packit |
8480eb |
struct mapent *exists = cache_lookup_distinct(mc, qKey);
|
|
Packit |
8480eb |
if (exists && exists->source == source) {
|
|
Packit |
8480eb |
if (exists->mapent) {
|
|
Packit |
8480eb |
free(exists->mapent);
|
|
Packit |
8480eb |
exists->mapent = NULL;
|
|
Packit |
8480eb |
source->stale = 1;
|
|
Packit |
8480eb |
exists->status = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit Bot |
2d2ce7 |
/* Wildcard in map but not in cache, update it */
|
|
Packit Bot |
2d2ce7 |
err = cache_update(mc, source, "*", value, age);
|
|
Packit Bot |
06041b |
cache_unlock(mc);
|
|
Packit Bot |
2d2ce7 |
/* Wildcard in map but not in cache, map is stale */
|
|
Packit Bot |
2d2ce7 |
if (err & CHE_UPDATED)
|
|
Packit Bot |
2d2ce7 |
source->stale = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
endautomntent(ap->logopt, ctxt, &sss_ctxt);
|
|
Packit |
8480eb |
free(value);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int check_map_indirect(struct autofs_point *ap,
|
|
Packit |
8480eb |
char *key, int key_len,
|
|
Packit |
8480eb |
struct lookup_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
int ret, cur_state;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = ap->entry->current;
|
|
Packit |
8480eb |
ap->entry->current = NULL;
|
|
Packit |
8480eb |
master_source_current_signal(ap->entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_current_wait(ap->entry);
|
|
Packit |
8480eb |
ap->entry->current = source;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
ret = lookup_one(ap, key, key_len, ctxt);
|
|
Packit |
8480eb |
if (ret == NSS_STATUS_NOTFOUND) {
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
} else if (ret == NSS_STATUS_UNAVAIL) {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If the server is down and the entry exists in the cache
|
|
Packit |
8480eb |
* and belongs to this map return success and use the entry.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
struct mapent *exists = cache_lookup(mc, key);
|
|
Packit |
8480eb |
if (exists && exists->source == source) {
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "lookup for %s failed: connection failed", key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct lookup_context *ctxt = (struct lookup_context *) context;
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
char key[KEY_MAX_LEN + 1];
|
|
Packit |
8480eb |
int key_len;
|
|
Packit |
8480eb |
char *mapent = NULL;
|
|
Packit |
8480eb |
char mapent_buf[MAPENT_MAX_LEN + 1];
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = ap->entry->current;
|
|
Packit |
8480eb |
ap->entry->current = NULL;
|
|
Packit |
8480eb |
master_source_current_signal(ap->entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX "looking up %s", name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name);
|
|
Packit |
8480eb |
if (key_len > KEY_MAX_LEN)
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Check if we recorded a mount fail for this key anywhere */
|
|
Packit |
8480eb |
me = lookup_source_mapent(ap, key, LKP_DISTINCT);
|
|
Packit |
8480eb |
if (me) {
|
|
Packit |
8480eb |
if (me->status >= monotonic_time(NULL)) {
|
|
Packit |
8480eb |
cache_unlock(me->mc);
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
struct mapent_cache *smc = me->mc;
|
|
Packit |
8480eb |
struct mapent *sme;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (me->mapent)
|
|
Packit |
8480eb |
cache_unlock(smc);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
cache_unlock(smc);
|
|
Packit |
8480eb |
cache_writelock(smc);
|
|
Packit |
8480eb |
sme = cache_lookup_distinct(smc, key);
|
|
Packit |
8480eb |
/* Negative timeout expired for non-existent entry. */
|
|
Packit |
8480eb |
if (sme && !sme->mapent) {
|
|
Packit |
8480eb |
if (cache_pop_mapent(sme) == CHE_FAIL)
|
|
Packit |
8480eb |
cache_delete(smc, key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(smc);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* We can't check the direct mount map as if it's not in
|
|
Packit |
8480eb |
* the map cache already we never get a mount lookup, so
|
|
Packit |
8480eb |
* we never know about it.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->type == LKP_INDIRECT && *key != '/') {
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
char *lkp_key;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_readlock(mc);
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, key);
|
|
Packit Bot |
7bc25c |
if (me && IS_MM(me))
|
|
Packit Bot |
7bc25c |
lkp_key = strdup(MM_ROOT(me)->key);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
lkp_key = strdup(key);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!lkp_key)
|
|
Packit |
8480eb |
return NSS_STATUS_UNKNOWN;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_current_wait(ap->entry);
|
|
Packit |
8480eb |
ap->entry->current = source;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
|
|
Packit |
8480eb |
free(lkp_key);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
return status;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* We can't take the writelock for direct mounts. If we're
|
|
Packit |
8480eb |
* starting up or trying to re-connect to an existing direct
|
|
Packit |
8480eb |
* mount we could be iterating through the map entries with
|
|
Packit |
8480eb |
* the readlock held. But we don't need to update the cache
|
|
Packit |
8480eb |
* when we're starting up so just take the readlock in that
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->flags & MOUNT_FLAG_REMOUNT)
|
|
Packit Bot |
06041b |
cache_readlock(mc);
|
|
Packit Bot |
0ed855 |
else
|
|
Packit Bot |
0ed855 |
cache_writelock(mc);
|
|
Packit |
8480eb |
me = cache_lookup(mc, key);
|
|
Packit |
8480eb |
/* Stale mapent => check for entry in alternate source or wildcard */
|
|
Packit |
8480eb |
if (me && !me->mapent) {
|
|
Packit |
8480eb |
while ((me = cache_lookup_key_next(me)))
|
|
Packit |
8480eb |
if (me->source == source)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
if (!me)
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, "*");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (me && me->mapent) {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If this is a lookup add wildcard match for later validation
|
|
Packit |
8480eb |
* checks and negative cache lookups.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->type == LKP_INDIRECT && *me->key == '*' &&
|
|
Packit |
8480eb |
!(ap->flags & MOUNT_FLAG_REMOUNT)) {
|
|
Packit |
8480eb |
ret = cache_update(mc, source, key, me->mapent, me->age);
|
|
Packit |
8480eb |
if (!(ret & (CHE_OK | CHE_UPDATED)))
|
|
Packit |
8480eb |
me = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (me && (me->source == source || *me->key == '/')) {
|
|
Packit |
8480eb |
strcpy(mapent_buf, me->mapent);
|
|
Packit |
8480eb |
mapent = mapent_buf;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mapent)
|
|
Packit |
8480eb |
return NSS_STATUS_TRYAGAIN;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_current_wait(ap->entry);
|
|
Packit |
8480eb |
ap->entry->current = source;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
|
|
Packit |
8480eb |
ret = ctxt->parse->parse_mount(ap, key, key_len,
|
|
Packit |
8480eb |
mapent, ctxt->parse->context);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
/* Don't update negative cache when re-connecting */
|
|
Packit |
8480eb |
if (ap->flags & MOUNT_FLAG_REMOUNT)
|
|
Packit |
8480eb |
return NSS_STATUS_TRYAGAIN;
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
cache_update_negative(mc, source, key, ap->negative_timeout);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
return NSS_STATUS_TRYAGAIN;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int lookup_done(void *context)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct lookup_context *ctxt = (struct lookup_context *) context;
|
|
Packit |
8480eb |
int rv = close_parse(ctxt->parse);
|
|
Packit |
8480eb |
dlclose(ctxt->dlhandle);
|
|
Packit |
8480eb |
free(ctxt);
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|