|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* lookup_yp.c - module for Linux automountd to access a YP (NIS)
|
|
Packit |
8480eb |
* automount map
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 1997 Transmeta Corporation - All Rights Reserved
|
|
Packit |
8480eb |
* Copyright 2001-2003 Ian Kent <raven@themaw.net>
|
|
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 <time.h>
|
|
Packit |
8480eb |
#include <signal.h>
|
|
Packit |
8480eb |
#include <ctype.h>
|
|
Packit |
8480eb |
#include <sys/param.h>
|
|
Packit |
8480eb |
#include <sys/types.h>
|
|
Packit |
8480eb |
#include <sys/stat.h>
|
|
Packit |
8480eb |
#include <rpc/rpc.h>
|
|
Packit |
8480eb |
#include <rpc/xdr.h>
|
|
Packit |
8480eb |
#include <rpcsvc/yp_prot.h>
|
|
Packit |
8480eb |
#include <rpcsvc/ypclnt.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 |
8480eb |
#define MODPREFIX "lookup(yp): "
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct lookup_context {
|
|
Packit |
8480eb |
char *domainname;
|
|
Packit |
8480eb |
const char *mapname;
|
|
Packit |
8480eb |
unsigned long order;
|
|
Packit |
8480eb |
unsigned int check_defaults;
|
|
Packit |
8480eb |
struct parse_mod *parse;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct callback_master_data {
|
|
Packit |
8480eb |
unsigned timeout;
|
|
Packit |
8480eb |
unsigned logging;
|
|
Packit |
8480eb |
unsigned logopt;
|
|
Packit |
8480eb |
time_t age;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct callback_data {
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
unsigned logopt;
|
|
Packit |
8480eb |
time_t age;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int get_map_order(const char *domain, const char *map)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char key[] = "YP_LAST_MODIFIED";
|
|
Packit |
8480eb |
int key_len = strlen(key);
|
|
Packit |
8480eb |
char *order;
|
|
Packit |
8480eb |
int order_len;
|
|
Packit |
8480eb |
char *mapname;
|
|
Packit |
8480eb |
long last_changed;
|
|
Packit |
8480eb |
int err;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mapname = alloca(strlen(map) + 1);
|
|
Packit |
8480eb |
if (!mapname)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(mapname, map);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = yp_match(domain, mapname, key, key_len, &order, &order_len);
|
|
Packit |
8480eb |
if (err != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
if (err == YPERR_MAP) {
|
|
Packit |
8480eb |
char *usc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((usc = strchr(mapname, '_')))
|
|
Packit |
8480eb |
*usc = '.';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = yp_match(domain, mapname,
|
|
Packit |
8480eb |
key, key_len, &order, &order_len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err != YPERR_SUCCESS)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
last_changed = atol(order);
|
|
Packit |
8480eb |
free(order);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return (unsigned int) last_changed;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
last_changed = atol(order);
|
|
Packit |
8480eb |
free(order);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return (unsigned int) last_changed;
|
|
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 |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int err;
|
|
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 |
ctxt->check_defaults = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (mapfmt && !strcmp(mapfmt, "amd"))
|
|
Packit |
8480eb |
ctxt->domainname = conf_amd_get_nis_domain();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!ctxt->domainname) {
|
|
Packit |
8480eb |
char *domainname;
|
|
Packit |
8480eb |
/* This should, but doesn't, take a const char ** */
|
|
Packit |
8480eb |
err = yp_get_default_domain(&domainname);
|
|
Packit |
8480eb |
if (err) {
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ctxt->domainname = strdup(domainname);
|
|
Packit |
8480eb |
if (!ctxt->domainname) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr(MODPREFIX "strdup: %s", estr);
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
goto out;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt->order = get_map_order(ctxt->domainname, ctxt->mapname);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mapfmt)
|
|
Packit |
8480eb |
mapfmt = MAPFMT_DEFAULT;
|
|
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 |
ret = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
out:
|
|
Packit |
8480eb |
if (ret && ctxt->domainname)
|
|
Packit |
8480eb |
free(ctxt->domainname);
|
|
Packit |
8480eb |
|
|
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 |
|
|
Packit |
8480eb |
*context = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ctxt = malloc(sizeof(struct lookup_context));
|
|
Packit |
8480eb |
if (!ctxt) {
|
|
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 |
memset(ctxt, 0, sizeof(struct lookup_context));
|
|
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 |
memset(new, 0, sizeof(struct lookup_context));
|
|
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 |
*context = new;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(ctxt->domainname);
|
|
Packit |
8480eb |
free(ctxt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int yp_all_master_callback(int status, char *ypkey, int ypkeylen,
|
|
Packit |
8480eb |
char *val, int vallen, char *ypcb_data)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct callback_master_data *cbdata =
|
|
Packit |
8480eb |
(struct callback_master_data *) ypcb_data;
|
|
Packit |
8480eb |
unsigned int timeout = cbdata->timeout;
|
|
Packit |
8480eb |
unsigned int logging = cbdata->logging;
|
|
Packit |
8480eb |
unsigned int logopt = cbdata->logopt;
|
|
Packit |
8480eb |
time_t age = cbdata->age;
|
|
Packit |
8480eb |
char *buffer;
|
|
Packit |
8480eb |
unsigned int len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (status != YP_TRUE)
|
|
Packit |
8480eb |
return status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Ignore zero length and single non-printable char keys */
|
|
Packit |
8480eb |
if (ypkeylen == 0 || (ypkeylen == 1 && !isprint(*ypkey))) {
|
|
Packit |
8480eb |
warn(logopt, MODPREFIX
|
|
Packit |
8480eb |
"ignoring invalid map entry, zero length or "
|
|
Packit |
8480eb |
"single character non-printable key");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
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 (*ypkey == '+')
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*(ypkey + ypkeylen) = '\0';
|
|
Packit |
8480eb |
*(val + vallen) = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = ypkeylen + 1 + vallen + 2;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
buffer = alloca(len);
|
|
Packit |
8480eb |
if (!buffer) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX "could not malloc parse buffer");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
memset(buffer, 0, len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcat(buffer, ypkey);
|
|
Packit |
8480eb |
strcat(buffer, " ");
|
|
Packit |
8480eb |
strcat(buffer, val);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_parse_entry(buffer, timeout, logging, age);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
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 |
struct ypall_callback ypcb;
|
|
Packit |
8480eb |
struct callback_master_data ypcb_data;
|
|
Packit |
8480eb |
unsigned int logging = master->default_logging;
|
|
Packit |
8480eb |
unsigned int logopt = master->logopt;
|
|
Packit |
8480eb |
char *mapname;
|
|
Packit |
8480eb |
int err;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mapname = malloc(strlen(ctxt->mapname) + 1);
|
|
Packit |
8480eb |
if (!mapname)
|
|
Packit |
8480eb |
return NSS_STATUS_UNKNOWN;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(mapname, ctxt->mapname);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ypcb_data.timeout = master->default_timeout;
|
|
Packit |
8480eb |
ypcb_data.logging = logging;
|
|
Packit |
8480eb |
ypcb_data.logopt = logopt;
|
|
Packit |
8480eb |
ypcb_data.age = age;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ypcb.foreach = yp_all_master_callback;
|
|
Packit |
8480eb |
ypcb.data = (char *) &ypcb_data;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = yp_all((char *) ctxt->domainname, mapname, &ypcb);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
if (err == YPERR_MAP) {
|
|
Packit |
8480eb |
char *usc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((usc = strchr(mapname, '_')))
|
|
Packit |
8480eb |
*usc = '.';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = yp_all((char *) ctxt->domainname, mapname, &ypcb);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err == YPERR_SUCCESS) {
|
|
Packit |
8480eb |
free(mapname);
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
info(logopt,
|
|
Packit |
8480eb |
MODPREFIX "read of master map %s failed: %s",
|
|
Packit |
8480eb |
mapname, yperr_string(err));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(mapname);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err == YPERR_YPSERV || err == YPERR_DOMAIN)
|
|
Packit |
8480eb |
return NSS_STATUS_UNAVAIL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(mapname);
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int yp_all_callback(int status, char *ypkey, int ypkeylen,
|
|
Packit |
8480eb |
char *val, int vallen, char *ypcb_data)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct callback_data *cbdata = (struct callback_data *) ypcb_data;
|
|
Packit |
8480eb |
struct autofs_point *ap = cbdata->ap;
|
|
Packit |
8480eb |
struct map_source *source = cbdata->source;
|
|
Packit |
8480eb |
struct mapent_cache *mc = source->mc;
|
|
Packit |
8480eb |
unsigned int logopt = cbdata->logopt;
|
|
Packit |
8480eb |
time_t age = cbdata->age;
|
|
Packit |
8480eb |
char *key, *mapent;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (status != YP_TRUE)
|
|
Packit |
8480eb |
return status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Ignore zero length and single non-printable char keys */
|
|
Packit |
8480eb |
if (ypkeylen == 0 || (ypkeylen == 1 && !isprint(*ypkey))) {
|
|
Packit |
8480eb |
warn(logopt, MODPREFIX
|
|
Packit |
8480eb |
"ignoring invalid map entry, zero length or "
|
|
Packit |
8480eb |
"single character non-printable key");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
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 (*ypkey == '+')
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!(source->flags & MAP_FLAG_FORMAT_AMD))
|
|
Packit |
8480eb |
key = sanitize_path(ypkey, ypkeylen, ap->type, ap->logopt);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
/* Don't fail on "/" in key => type == 0 */
|
|
Packit |
8480eb |
key = sanitize_path(ypkey, ypkeylen, 0, ap->logopt);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!key) {
|
|
Packit |
8480eb |
error(logopt, MODPREFIX "invalid path %s", ypkey);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mapent = alloca(vallen + 1);
|
|
Packit |
8480eb |
strncpy(mapent, val, vallen);
|
|
Packit |
8480eb |
*(mapent + vallen) = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
ret = cache_update(mc, source, key, mapent, age);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret == CHE_FAIL)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
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 ypall_callback ypcb;
|
|
Packit |
8480eb |
struct callback_data ypcb_data;
|
|
Packit |
8480eb |
unsigned int logopt = ap->logopt;
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
char *mapname;
|
|
Packit |
8480eb |
int err;
|
|
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 |
/*
|
|
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 |
8480eb |
ypcb_data.ap = ap;
|
|
Packit |
8480eb |
ypcb_data.source = source;
|
|
Packit |
8480eb |
ypcb_data.logopt = logopt;
|
|
Packit |
8480eb |
ypcb_data.age = age;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ypcb.foreach = yp_all_callback;
|
|
Packit |
8480eb |
ypcb.data = (char *) &ypcb_data;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mapname = alloca(strlen(ctxt->mapname) + 1);
|
|
Packit |
8480eb |
if (!mapname)
|
|
Packit |
8480eb |
return NSS_STATUS_UNKNOWN;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(mapname, ctxt->mapname);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = yp_all((char *) ctxt->domainname, mapname, &ypcb);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
if (err == YPERR_MAP) {
|
|
Packit |
8480eb |
char *usc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((usc = strchr(mapname, '_')))
|
|
Packit |
8480eb |
*usc = '.';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
err = yp_all((char *) ctxt->domainname, mapname, &ypcb);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "read of map %s failed: %s",
|
|
Packit |
8480eb |
ap->path, yperr_string(err));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (err == YPERR_PMAP || err == YPERR_YPSERV)
|
|
Packit |
8480eb |
return NSS_STATUS_UNAVAIL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source->age = age;
|
|
Packit |
8480eb |
pthread_mutex_lock(&ap->entry->current_mutex);
|
|
Packit |
8480eb |
ctxt->check_defaults = 0;
|
|
Packit |
8480eb |
pthread_mutex_unlock(&ap->entry->current_mutex);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int lookup_one(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct map_source *source,
|
|
Packit |
8480eb |
const char *key, int key_len,
|
|
Packit |
8480eb |
struct lookup_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
char *mapname;
|
|
Packit |
8480eb |
char *mapent;
|
|
Packit |
8480eb |
int mapent_len;
|
|
Packit |
8480eb |
time_t age = monotonic_time(NULL);
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mapname = alloca(strlen(ctxt->mapname) + 1);
|
|
Packit |
8480eb |
if (!mapname)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(mapname, ctxt->mapname);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* For reasons unknown, the standard YP definitions doesn't
|
|
Packit |
8480eb |
* define input strings as const char *. However, my
|
|
Packit |
8480eb |
* understanding is that they will not be modified by the
|
|
Packit |
8480eb |
* library.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
ret = yp_match((char *) ctxt->domainname, mapname,
|
|
Packit |
8480eb |
(char *) key, key_len, &mapent, &mapent_len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
if (ret == YPERR_MAP) {
|
|
Packit |
8480eb |
char *usc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((usc = strchr(mapname, '_')))
|
|
Packit |
8480eb |
*usc = '.';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = yp_match((char *) ctxt->domainname,
|
|
Packit |
8480eb |
mapname, key, key_len, &mapent, &mapent_len);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
if (ret == YPERR_KEY)
|
|
Packit |
8480eb |
return CHE_MISSING;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return -ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
ret = cache_update(mc, source, key, mapent, age);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
free(mapent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int match_key(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct map_source *source,
|
|
Packit |
8480eb |
const char *key, int key_len,
|
|
Packit |
8480eb |
struct lookup_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned int is_amd_format = source->flags & MAP_FLAG_FORMAT_AMD;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *lkp_key;
|
|
Packit |
8480eb |
char *prefix;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = lookup_one(ap, source, key, strlen(key), ctxt);
|
|
Packit |
8480eb |
if (ret < 0)
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
if (ret == CHE_OK || ret == CHE_UPDATED || !is_amd_format)
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
lkp_key = strdup(key);
|
|
Packit |
8480eb |
if (!lkp_key) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "strdup: %s", estr);
|
|
Packit |
8480eb |
return CHE_FAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = CHE_MISSING;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Now strip successive directory components and try a
|
|
Packit |
8480eb |
* match against map entries ending with a wildcard and
|
|
Packit |
8480eb |
* finally try the wilcard entry itself.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
while ((prefix = strrchr(lkp_key, '/'))) {
|
|
Packit |
8480eb |
char *match;
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
*prefix = '\0';
|
|
Packit |
8480eb |
len = strlen(lkp_key) + 3;
|
|
Packit |
8480eb |
match = malloc(len);
|
|
Packit |
8480eb |
if (!match) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
ret = CHE_FAIL;
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
len--;
|
|
Packit |
8480eb |
strcpy(match, lkp_key);
|
|
Packit |
8480eb |
strcat(match, "/*");
|
|
Packit |
8480eb |
ret = lookup_one(ap, source, match, len, ctxt);
|
|
Packit |
8480eb |
free(match);
|
|
Packit |
8480eb |
if (ret < 0)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
if (ret == CHE_OK || ret == CHE_UPDATED)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
free(lkp_key);
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int lookup_wild(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct map_source *source, struct lookup_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
char *mapname;
|
|
Packit |
8480eb |
char *mapent;
|
|
Packit |
8480eb |
int mapent_len;
|
|
Packit |
8480eb |
time_t age = monotonic_time(NULL);
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mapname = alloca(strlen(ctxt->mapname) + 1);
|
|
Packit |
8480eb |
if (!mapname)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(mapname, ctxt->mapname);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = yp_match((char *) ctxt->domainname,
|
|
Packit |
8480eb |
mapname, "*", 1, &mapent, &mapent_len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
if (ret == YPERR_MAP) {
|
|
Packit |
8480eb |
char *usc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((usc = strchr(mapname, '_')))
|
|
Packit |
8480eb |
*usc = '.';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = yp_match((char *) ctxt->domainname,
|
|
Packit |
8480eb |
mapname, "*", 1, &mapent, &mapent_len);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
if (ret == YPERR_KEY)
|
|
Packit |
8480eb |
return CHE_MISSING;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return -ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
ret = cache_update(mc, source, "*", mapent, age);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
free(mapent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int lookup_amd_defaults(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct map_source *source,
|
|
Packit |
8480eb |
struct lookup_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mapent_cache *mc = source->mc;
|
|
Packit |
8480eb |
char *mapname;
|
|
Packit |
8480eb |
char *mapent;
|
|
Packit |
8480eb |
int mapent_len;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mapname = malloc(strlen(ctxt->mapname) + 1);
|
|
Packit |
8480eb |
if (!mapname)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
strcpy(mapname, ctxt->mapname);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = yp_match((char *) ctxt->domainname, mapname,
|
|
Packit |
8480eb |
(char *) "/defaults", 9, &mapent, &mapent_len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret != YPERR_SUCCESS) {
|
|
Packit |
8480eb |
if (ret == YPERR_MAP) {
|
|
Packit |
8480eb |
char *usc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((usc = strchr(mapname, '_')))
|
|
Packit |
8480eb |
*usc = '.';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = yp_match((char *) ctxt->domainname, mapname,
|
|
Packit |
8480eb |
"/defaults", 9, &mapent, &mapent_len);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free(mapname);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* No /defaults entry */
|
|
Packit |
8480eb |
if (ret == YPERR_KEY)
|
|
Packit |
8480eb |
return CHE_OK;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret != YPERR_SUCCESS)
|
|
Packit |
8480eb |
return CHE_FAIL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
ret = cache_update(mc, source, "/defaults", mapent, monotonic_time(NULL));
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int check_map_indirect(struct autofs_point *ap,
|
|
Packit |
8480eb |
struct map_source *source,
|
|
Packit |
8480eb |
char *key, int key_len,
|
|
Packit |
8480eb |
struct lookup_context *ctxt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
struct mapent *exists;
|
|
Packit |
8480eb |
unsigned int map_order;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Only read map if it has been modified */
|
|
Packit |
8480eb |
pthread_mutex_lock(&ap->entry->current_mutex);
|
|
Packit |
8480eb |
map_order = get_map_order(ctxt->domainname, ctxt->mapname);
|
|
Packit |
8480eb |
if (map_order > ctxt->order) {
|
|
Packit |
8480eb |
ctxt->order = map_order;
|
|
Packit |
8480eb |
source->stale = 1;
|
|
Packit |
8480eb |
ctxt->check_defaults = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (source->flags & MAP_FLAG_FORMAT_AMD && ctxt->check_defaults) {
|
|
Packit |
8480eb |
/* Check for a /defaults entry to update the map source */
|
|
Packit |
8480eb |
if (lookup_amd_defaults(ap, source, ctxt) == CHE_FAIL) {
|
|
Packit |
8480eb |
warn(ap->logopt, MODPREFIX
|
|
Packit |
8480eb |
"error getting /defaults from map %s",
|
|
Packit |
8480eb |
ctxt->mapname);
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
ctxt->check_defaults = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
pthread_mutex_unlock(&ap->entry->current_mutex);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* check map and if change is detected re-read map */
|
|
Packit |
8480eb |
ret = match_key(ap, source, key, key_len, ctxt);
|
|
Packit |
8480eb |
if (ret == CHE_FAIL)
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret < 0) {
|
|
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 |
cache_readlock(mc);
|
|
Packit |
8480eb |
if (source->flags & MAP_FLAG_FORMAT_AMD)
|
|
Packit |
8480eb |
exists = match_cached_key(ap, MODPREFIX, source, key);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
exists = cache_lookup(mc, key);
|
|
Packit |
8480eb |
if (exists && exists->source == source) {
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
MODPREFIX "lookup for %s failed: %s",
|
|
Packit |
8480eb |
key, yperr_string(-ret));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NSS_STATUS_UNAVAIL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
if (source->flags & MAP_FLAG_FORMAT_AMD)
|
|
Packit |
8480eb |
exists = match_cached_key(ap, MODPREFIX, source, key);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
exists = cache_lookup_distinct(mc, key);
|
|
Packit |
8480eb |
/* Not found in the map but found in the cache */
|
|
Packit |
8480eb |
if (exists && exists->source == source && ret & CHE_MISSING) {
|
|
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 |
|
|
Packit |
8480eb |
if (ret == CHE_MISSING) {
|
|
Packit |
8480eb |
struct mapent *we;
|
|
Packit |
8480eb |
int wild = CHE_MISSING;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
wild = lookup_wild(ap, source, ctxt);
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Check for map change and update as needed for
|
|
Packit |
8480eb |
* following cache lookup.
|
|
Packit |
8480eb |
*/
|
|
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 && (wild & CHE_MISSING)) {
|
|
Packit |
8480eb |
cache_delete(mc, "*");
|
|
Packit |
8480eb |
source->stale = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
/* Wildcard not in map but now is */
|
|
Packit |
8480eb |
if (wild & (CHE_OK | CHE_UPDATED))
|
|
Packit |
8480eb |
source->stale = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (wild & (CHE_OK | CHE_UPDATED))
|
|
Packit |
8480eb |
return NSS_STATUS_SUCCESS;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret == CHE_MISSING)
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
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 |
char key[KEY_MAX_LEN + 1];
|
|
Packit |
8480eb |
int key_len;
|
|
Packit |
8480eb |
char *lkp_key;
|
|
Packit |
8480eb |
char *mapent = NULL;
|
|
Packit |
8480eb |
int mapent_len;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
int status = 0;
|
|
Packit |
8480eb |
int ret = 1;
|
|
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 |
if (!(source->flags & MAP_FLAG_FORMAT_AMD)) {
|
|
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 |
} else {
|
|
Packit |
8480eb |
key_len = expandamdent(name, NULL, NULL);
|
|
Packit |
8480eb |
if (key_len > KEY_MAX_LEN)
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
memset(key, 0, KEY_MAX_LEN + 1);
|
|
Packit |
8480eb |
expandamdent(name, key, NULL);
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX "expanded key: \"%s\"", key);
|
|
Packit |
8480eb |
}
|
|
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 |
cache_readlock(mc);
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, key);
|
|
Packit Service |
1b0899 |
if (me && IS_MM(me))
|
|
Packit Service |
1b0899 |
lkp_key = strdup(MM_ROOT(me)->key);
|
|
Packit |
8480eb |
else if (!ap->pref)
|
|
Packit |
8480eb |
lkp_key = strdup(key);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1);
|
|
Packit |
8480eb |
if (lkp_key) {
|
|
Packit |
8480eb |
strcpy(lkp_key, ap->pref);
|
|
Packit |
8480eb |
strcat(lkp_key, key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!lkp_key) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
return NSS_STATUS_UNKNOWN;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = check_map_indirect(ap, source,
|
|
Packit |
8480eb |
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 |
* case.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->flags & MOUNT_FLAG_REMOUNT)
|
|
Packit |
8480eb |
cache_readlock(mc);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
cache_writelock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!ap->pref)
|
|
Packit |
8480eb |
lkp_key = strdup(key);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
lkp_key = malloc(strlen(ap->pref) + strlen(key) + 1);
|
|
Packit |
8480eb |
if (lkp_key) {
|
|
Packit |
8480eb |
strcpy(lkp_key, ap->pref);
|
|
Packit |
8480eb |
strcat(lkp_key, key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!lkp_key) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, MODPREFIX "malloc: %s", estr);
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
return NSS_STATUS_UNKNOWN;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
me = match_cached_key(ap, MODPREFIX, source, lkp_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 |
mapent_len = strlen(me->mapent);
|
|
Packit |
8480eb |
mapent = alloca(mapent_len + 1);
|
|
Packit |
8480eb |
strcpy(mapent, me->mapent);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!me) {
|
|
Packit |
8480eb |
free(lkp_key);
|
|
Packit |
8480eb |
return NSS_STATUS_NOTFOUND;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mapent) {
|
|
Packit |
8480eb |
free(lkp_key);
|
|
Packit |
8480eb |
return NSS_STATUS_TRYAGAIN;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, MODPREFIX "%s -> %s", lkp_key, mapent);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(lkp_key);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_current_wait(ap->entry);
|
|
Packit |
8480eb |
ap->entry->current = source;
|
|
Packit |
8480eb |
|
|
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 |
free(ctxt->domainname);
|
|
Packit |
8480eb |
free(ctxt);
|
|
Packit |
8480eb |
return rv;
|
|
Packit |
8480eb |
}
|