Blame modules/lookup_hesiod.c

Packit 8480eb
/*
Packit 8480eb
 * lookup_hesiod.c
Packit 8480eb
 *
Packit 8480eb
 * Module for Linux automountd to access automount maps in hesiod filsys
Packit 8480eb
 * entries.
Packit 8480eb
 *
Packit 8480eb
 */
Packit 8480eb
Packit 8480eb
#include <sys/types.h>
Packit 8480eb
#include <ctype.h>
Packit 8480eb
#include <limits.h>
Packit 8480eb
#include <string.h>
Packit 8480eb
#include <stdlib.h>
Packit 8480eb
#include <netinet/in.h>
Packit 8480eb
#include <arpa/nameser.h>
Packit 8480eb
#include <resolv.h>
Packit 8480eb
#include <hesiod.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	   "hesiod"
Packit 8480eb
#define AMD_MAP_PREFIX	   "hesiod."
Packit 8480eb
#define AMD_MAP_PREFIX_LEN 7
Packit 8480eb
Packit 8480eb
#define MODPREFIX "lookup(hesiod): "
Packit 8480eb
#define HESIOD_LEN 512
Packit 8480eb
Packit 8480eb
struct lookup_context {
Packit 8480eb
	const char *mapname;
Packit 8480eb
	struct parse_mod *parser;
Packit 8480eb
	void *hesiod_context;
Packit 8480eb
};
Packit 8480eb
Packit 8480eb
static pthread_mutex_t hesiod_mutex = PTHREAD_MUTEX_INITIALIZER;
Packit 8480eb
Packit 8480eb
int lookup_version = AUTOFS_LOOKUP_VERSION;	/* Required by protocol */
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 ret = 0;
Packit 8480eb
Packit 8480eb
	/* Initialize the resolver. */
Packit 8480eb
	res_init();
Packit 8480eb
Packit 8480eb
	/* Initialize the hesiod context. */
Packit 8480eb
	if (hesiod_init(&(ctxt->hesiod_context)) != 0) {
Packit 8480eb
		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
		logerr(MODPREFIX "hesiod_init(): %s", estr);
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* If a map type isn't explicitly given, parse it as hesiod entries. */
Packit 8480eb
	if (!mapfmt)
Packit 8480eb
		mapfmt = MAPFMT_DEFAULT;
Packit 8480eb
Packit 8480eb
	if (!strcmp(mapfmt, "amd")) {
Packit 8480eb
		/* amd formated hesiod maps have a map name */
Packit 8480eb
		const char *mapname = argv[0];
Packit 8480eb
		if (strncmp(mapname, AMD_MAP_PREFIX, AMD_MAP_PREFIX_LEN)) {
Packit 8480eb
			hesiod_end(ctxt->hesiod_context);
Packit 8480eb
			logerr(MODPREFIX
Packit 8480eb
			      "incorrect prefix for hesiod map %s", mapname);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		ctxt->mapname = mapname;
Packit 8480eb
		argc--;
Packit 8480eb
		argv++;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (reinit) {
Packit 8480eb
		ret = reinit_parse(ctxt->parser, mapfmt,
Packit 8480eb
				   MODPREFIX, argc - 1, argv - 1);
Packit 8480eb
		if (ret)
Packit 8480eb
			logerr(MODPREFIX "failed to reinit parse context");
Packit 8480eb
	} else {
Packit 8480eb
		ctxt->parser = open_parse(mapfmt,
Packit 8480eb
					  MODPREFIX, argc - 1, argv + 1);
Packit 8480eb
		if (!ctxt->parser) {
Packit 8480eb
			logerr(MODPREFIX "failed to open parse context");
Packit 8480eb
			ret = 1;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (ret)
Packit 8480eb
		hesiod_end(ctxt->hesiod_context);
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* This initializes a context (persistent non-global data) for queries to
Packit 8480eb
   this module. */
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
	int ret;
Packit 8480eb
Packit 8480eb
	*context = NULL;
Packit 8480eb
Packit 8480eb
	/* If we can't build a context, bail. */
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
	ret = do_init(mapfmt, argc, argv, ctxt, 0);
Packit 8480eb
	if (ret) {
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
	/* If we can't build a context, bail. */
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->parser = ctxt->parser;
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
	hesiod_end(ctxt->hesiod_context);
Packit 8480eb
	free(ctxt);
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
	return NSS_STATUS_UNKNOWN;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
Packit 8480eb
{
Packit 8480eb
	ap->entry->current = NULL;
Packit 8480eb
	master_source_current_signal(ap->entry);
Packit 8480eb
Packit 8480eb
	return NSS_STATUS_UNKNOWN;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/*
Packit 8480eb
 * Lookup and act on a filesystem name.  In this case, lookup the "filsys"
Packit 8480eb
 * record in hesiod.  If it's an AFS or NFS filesystem, parse it out.  If
Packit 8480eb
 * it's an ERR filesystem, it's an error message we should log.  Otherwise,
Packit 8480eb
 * assume it's something we know how to deal with already (generic).
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 **hes_result;
Packit 8480eb
	char **record, *best_record = NULL, *p;
Packit 8480eb
	int priority, lowest_priority = INT_MAX;
Packit 8480eb
	int ret, status;
Packit 8480eb
Packit 8480eb
	mc = source->mc;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&hesiod_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	hes_result = hesiod_resolve(ctxt->hesiod_context, key, "filsys");
Packit 8480eb
	if (!hes_result || !hes_result[0]) {
Packit 8480eb
		int err = errno;
Packit 8480eb
		if (!defaults_disable_not_found_message()) {
Packit 8480eb
			error(ap->logopt,
Packit 8480eb
			      MODPREFIX "key \"%s\" not found in map", key);
Packit 8480eb
		}
Packit 8480eb
		status = pthread_mutex_unlock(&hesiod_mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		if (err == HES_ER_NOTFOUND)
Packit 8480eb
			return CHE_MISSING;
Packit 8480eb
		else
Packit 8480eb
			return CHE_FAIL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* autofs doesn't support falling back to alternate records, so just
Packit 8480eb
	   find the record with the lowest priority and hope it works.
Packit 8480eb
	   -- Aaron Ucko <amu@alum.mit.edu> 2002-03-11 */
Packit 8480eb
	for (record = hes_result; *record; ++record) {
Packit 8480eb
	    p = strrchr(*record, ' ');
Packit 8480eb
	    if ( p && isdigit(p[1]) ) {
Packit 8480eb
		priority = atoi(p+1);
Packit 8480eb
	    } else {
Packit 8480eb
		priority = INT_MAX - 1;
Packit 8480eb
	    }
Packit 8480eb
	    if (priority < lowest_priority) {
Packit 8480eb
		lowest_priority = priority;
Packit 8480eb
		best_record = *record;
Packit 8480eb
	    }
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	cache_writelock(mc);
Packit 8480eb
	ret = cache_update(mc, source, key, best_record, monotonic_time(NULL));
Packit 8480eb
	cache_unlock(mc);
Packit 8480eb
	if (ret == CHE_FAIL) {
Packit 8480eb
		hesiod_free_list(ctxt->hesiod_context, hes_result);
Packit 8480eb
		status = pthread_mutex_unlock(&hesiod_mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		return ret;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	debug(ap->logopt,
Packit 8480eb
	      MODPREFIX "lookup for \"%s\" gave \"%s\"",
Packit 8480eb
	      key, best_record);
Packit 8480eb
Packit 8480eb
	hesiod_free_list(ctxt->hesiod_context, hes_result);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&hesiod_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int lookup_one_amd(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 *hesiod_base;
Packit 8480eb
	char **hes_result;
Packit 8480eb
	char *lkp_key;
Packit 8480eb
	int status, ret;
Packit 8480eb
Packit 8480eb
	mc = source->mc;
Packit 8480eb
Packit 8480eb
	hesiod_base = conf_amd_get_hesiod_base();
Packit 8480eb
	if (!hesiod_base)
Packit 8480eb
		return CHE_FAIL;
Packit 8480eb
Packit 8480eb
	lkp_key = malloc(key_len + strlen(ctxt->mapname) - 7 + 2);
Packit 8480eb
	if (!lkp_key) {
Packit 8480eb
		free(hesiod_base);
Packit 8480eb
		return CHE_FAIL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	strcpy(lkp_key, key);
Packit 8480eb
	strcat(lkp_key, ".");
Packit 8480eb
	strcat(lkp_key, ctxt->mapname + AMD_MAP_PREFIX_LEN);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&hesiod_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	hes_result = hesiod_resolve(ctxt->hesiod_context, lkp_key, hesiod_base);
Packit 8480eb
	if (!hes_result || !hes_result[0]) {
Packit 8480eb
		int err = errno;
Packit 8480eb
		if (err == HES_ER_NOTFOUND)
Packit 8480eb
			ret = CHE_MISSING;
Packit 8480eb
		else
Packit 8480eb
			ret = CHE_FAIL;
Packit 8480eb
		goto done;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	cache_writelock(mc);
Packit 8480eb
	ret = cache_update(mc, source, lkp_key, *hes_result, monotonic_time(NULL));
Packit 8480eb
	cache_unlock(mc);
Packit 8480eb
Packit 8480eb
	if (hes_result)
Packit 8480eb
		hesiod_free_list(ctxt->hesiod_context, hes_result);
Packit 8480eb
done:
Packit 8480eb
	free(lkp_key);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&hesiod_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int match_amd_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
	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_amd(ap, source, key, key_len, ctxt);
Packit 8480eb
	if (ret == CHE_OK || ret == CHE_UPDATED)
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_amd(ap, source, match, len, ctxt);
Packit 8480eb
		free(match);
Packit 8480eb
		if (ret == CHE_OK || ret == CHE_UPDATED)
Packit 8480eb
			goto done;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* Lastly try the wildcard */
Packit 8480eb
	ret = lookup_one_amd(ap, source, "*", 1, ctxt);
Packit 8480eb
done:
Packit 8480eb
	free(lkp_key);
Packit 8480eb
	return ret;
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
	char buf[MAX_ERR_BUF];
Packit 8480eb
	struct map_source *source;
Packit 8480eb
	struct mapent *me;
Packit 8480eb
	char key[KEY_MAX_LEN + 1];
Packit 8480eb
	size_t key_len;
Packit 8480eb
	char *lkp_key;
Packit 8480eb
	size_t len;
Packit 8480eb
	char *mapent;
Packit 8480eb
	int rv;
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
	debug(ap->logopt,
Packit 8480eb
	      MODPREFIX "looking up root=\"%s\", name=\"%s\"",
Packit 8480eb
	      ap->path, 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
		expandamdent(name, key, NULL);
Packit 8480eb
		key[key_len] = '\0';
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, name, 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, name);
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, name);
Packit 8480eb
				}
Packit 8480eb
				cache_unlock(smc);
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* If this is not here the filesystem stays busy, for some reason... */
Packit 8480eb
	if (chdir("/"))
Packit 8480eb
		warn(ap->logopt,
Packit 8480eb
		     MODPREFIX "failed to set working directory to \"/\"");
Packit 8480eb
Packit 8480eb
	len = key_len;
Packit 8480eb
	if (!(source->flags & MAP_FLAG_FORMAT_AMD))
Packit 8480eb
		lkp_key = strdup(key);
Packit 8480eb
	else {
Packit 8480eb
		rv = lookup_one_amd(ap, source, "/defaults", 9, ctxt);
Packit 8480eb
		if (rv == CHE_FAIL)
Packit 8480eb
			warn(ap->logopt,
Packit 8480eb
			     MODPREFIX "failed to lookup \"/defaults\" entry");
Packit 8480eb
Packit 8480eb
		if (!ap->pref)
Packit 8480eb
			lkp_key = strdup(key);
Packit 8480eb
		else {
Packit 8480eb
			len += strlen(ap->pref);
Packit 8480eb
			lkp_key = malloc(len + 1);
Packit 8480eb
			if (lkp_key) {
Packit 8480eb
				strcpy(lkp_key, ap->pref);
Packit 8480eb
				strcat(lkp_key, name);
Packit 8480eb
			}
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, "malloc: %s", estr);
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (source->flags & MAP_FLAG_FORMAT_AMD)
Packit 8480eb
		rv = match_amd_key(ap, source, lkp_key, len, ctxt);
Packit 8480eb
	else
Packit 8480eb
		rv = lookup_one(ap, source, lkp_key, len, ctxt);
Packit 8480eb
Packit 8480eb
	if (rv == CHE_FAIL) {
Packit 8480eb
		free(lkp_key);
Packit 8480eb
		return NSS_STATUS_UNAVAIL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	me = match_cached_key(ap, MODPREFIX, source, lkp_key);
Packit 8480eb
Packit 8480eb
	if (!me) {
Packit 8480eb
		free(lkp_key);
Packit 8480eb
		return NSS_STATUS_NOTFOUND;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (!me->mapent) {
Packit 8480eb
		free(lkp_key);
Packit 8480eb
		return NSS_STATUS_UNAVAIL;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	mapent = strdup(me->mapent);
Packit 8480eb
	if (!mapent) {
Packit 8480eb
		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
		error(ap->logopt, "malloc: %s", estr);
Packit 8480eb
		free(lkp_key);
Packit 8480eb
		return NSS_STATUS_UNKNOWN;
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
	rv = ctxt->parser->parse_mount(ap, key, key_len,
Packit 8480eb
				       mapent, ctxt->parser->context);
Packit 8480eb
	free(mapent);
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * Unavailable due to error such as module load fail 
Packit 8480eb
	 * or out of memory, etc.
Packit 8480eb
	 */
Packit 8480eb
	if (rv == 1 || rv == -1)
Packit 8480eb
		return NSS_STATUS_UNAVAIL;
Packit 8480eb
Packit 8480eb
	return NSS_STATUS_SUCCESS;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* This destroys a context for queries to this module.  It releases the parser
Packit 8480eb
   structure (unloading the module) and frees the memory used by the context. */
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->parser);
Packit 8480eb
Packit 8480eb
	hesiod_end(ctxt->hesiod_context);
Packit 8480eb
	free(ctxt);
Packit 8480eb
	return rv;
Packit 8480eb
}