138494Sobrien/*
2174294Sobrien * Copyright (c) 1997-2006 Erez Zadok
338494Sobrien * Copyright (c) 1989 Jan-Simon Pendry
438494Sobrien * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
538494Sobrien * Copyright (c) 1989 The Regents of the University of California.
638494Sobrien * All rights reserved.
738494Sobrien *
838494Sobrien * This code is derived from software contributed to Berkeley by
938494Sobrien * Jan-Simon Pendry at Imperial College, London.
1038494Sobrien *
1138494Sobrien * Redistribution and use in source and binary forms, with or without
1238494Sobrien * modification, are permitted provided that the following conditions
1338494Sobrien * are met:
1438494Sobrien * 1. Redistributions of source code must retain the above copyright
1538494Sobrien *    notice, this list of conditions and the following disclaimer.
1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer in the
1838494Sobrien *    documentation and/or other materials provided with the distribution.
1938494Sobrien * 3. All advertising materials mentioning features or use of this software
2042629Sobrien *    must display the following acknowledgment:
2138494Sobrien *      This product includes software developed by the University of
2238494Sobrien *      California, Berkeley and its contributors.
2338494Sobrien * 4. Neither the name of the University nor the names of its contributors
2438494Sobrien *    may be used to endorse or promote products derived from this software
2538494Sobrien *    without specific prior written permission.
2638494Sobrien *
2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738494Sobrien * SUCH DAMAGE.
3838494Sobrien *
3938494Sobrien *
40174294Sobrien * File: am-utils/amd/info_hesiod.c
4138494Sobrien *
4238494Sobrien */
4338494Sobrien
4438494Sobrien/*
4538494Sobrien * Get info from Hesiod
4638494Sobrien */
4738494Sobrien
4838494Sobrien#ifdef HAVE_CONFIG_H
4938494Sobrien# include <config.h>
5038494Sobrien#endif /* HAVE_CONFIG_H */
5138494Sobrien#include <am_defs.h>
5238494Sobrien#include <amd.h>
5338494Sobrien
5438494Sobrien#define	HES_PREFIX	"hesiod."
5538494Sobrien#define	HES_PREFLEN	7
5638494Sobrien
5738494Sobrien#ifdef HAVE_HESIOD_INIT
5838494Sobrien/* bsdi3 does not define this extern in any header file */
5938494Sobrienextern char **hesiod_resolve(void *context, const char *name, const char *type);
6051292Sobrienextern int hesiod_init(void **context);
6138494Sobrienstatic voidp hesiod_context;
6238494Sobrien#endif /* HAVE_HESIOD_INIT */
6338494Sobrien
6451292Sobrien/* forward declarations */
6551292Sobrienint amu_hesiod_init(mnt_map *m, char *map, time_t *tp);
6651292Sobrienint hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
6751292Sobrienint hesiod_isup(mnt_map *m, char *map);
6851292Sobrien
6938494Sobrien/*
7038494Sobrien * No easy way to probe the server - check the map name begins with "hesiod."
7138494Sobrien * Note: this name includes 'amu_' so as to not conflict with libhesiod's
7238494Sobrien * hesiod_init() function.
7338494Sobrien */
7438494Sobrienint
7538494Sobrienamu_hesiod_init(mnt_map *m, char *map, time_t *tp)
7638494Sobrien{
7738494Sobrien  dlog("amu_hesiod_init(%s)", map);
7838494Sobrien  *tp = 0;
7938494Sobrien
8038494Sobrien#ifdef HAVE_HESIOD_INIT
81174294Sobrien  if (!hesiod_context && hesiod_init(&hesiod_context) != 0)
8238494Sobrien    return ENOENT;
8338494Sobrien#endif /* HAVE_HESIOD_INIT */
8438494Sobrien
8538494Sobrien  return NSTREQ(map, HES_PREFIX, HES_PREFLEN) ? 0 : ENOENT;
8638494Sobrien}
8738494Sobrien
8838494Sobrien
8938494Sobrien/*
9038494Sobrien * Do a Hesiod nameserver call.
9138494Sobrien * Modify time is ignored by Hesiod - XXX
9238494Sobrien */
9338494Sobrienint
9438494Sobrienhesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
9538494Sobrien{
9638494Sobrien  char hes_key[MAXPATHLEN];
9738494Sobrien  char **rvec;
9838494Sobrien#ifndef HAVE_HESIOD_INIT
9938494Sobrien  int error;
10038494Sobrien#endif /* not HAVE_HESIOD_INIT */
10138494Sobrien
10251292Sobrien  dlog("hesiod_search(m=%lx, map=%s, key=%s, pval=%lx tp=%lx)",
10351292Sobrien       (unsigned long) m, map, key, (unsigned long) pval, (unsigned long) tp);
10438494Sobrien
105174294Sobrien  if (key[0] == '.')
106174294Sobrien    return ENOENT;
10738494Sobrien
108174294Sobrien  xsnprintf(hes_key, sizeof(hes_key), "%s.%s", key, map + HES_PREFLEN);
109174294Sobrien
11038494Sobrien  /*
11138494Sobrien   * Call the resolver
11238494Sobrien   */
11338494Sobrien  dlog("Hesiod base is: %s\n", gopt.hesiod_base);
11438494Sobrien  dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, gopt.hesiod_base);
115174294Sobrien  if (amuDebug(D_INFO))
11638494Sobrien    _res.options |= RES_DEBUG;
11738494Sobrien
11838494Sobrien#ifdef HAVE_HESIOD_INIT
11938494Sobrien  /* new style hesiod */
12038494Sobrien  rvec = hesiod_resolve(hesiod_context, hes_key, gopt.hesiod_base);
12138494Sobrien#else /* not HAVE_HESIOD_INIT */
12238494Sobrien  rvec = hes_resolve(hes_key, gopt.hesiod_base);
12338494Sobrien#endif /* not HAVE_HESIOD_INIT */
12438494Sobrien
12538494Sobrien  /*
12638494Sobrien   * If a reply was forthcoming then return
12738494Sobrien   * it (and free subsequent replies)
12838494Sobrien   */
12938494Sobrien  if (rvec && *rvec) {
13038494Sobrien    *pval = *rvec;
13138494Sobrien    while (*++rvec)
13238494Sobrien      XFREE(*rvec);
13338494Sobrien    return 0;
13438494Sobrien  }
13538494Sobrien
13638494Sobrien#ifdef HAVE_HESIOD_INIT
13738494Sobrien  /* new style hesiod */
13838494Sobrien  return errno;
13938494Sobrien#else /* not HAVE_HESIOD_INIT */
14038494Sobrien  /*
14138494Sobrien   * Otherwise reflect the hesiod error into a Un*x error
14238494Sobrien   */
14338494Sobrien  dlog("hesiod_search: Error: %d", hes_error());
14438494Sobrien  switch (hes_error()) {
14538494Sobrien  case HES_ER_NOTFOUND:
14638494Sobrien    error = ENOENT;
14738494Sobrien    break;
14838494Sobrien  case HES_ER_CONFIG:
14938494Sobrien    error = EIO;
15038494Sobrien    break;
15138494Sobrien  case HES_ER_NET:
15238494Sobrien    error = ETIMEDOUT;
15338494Sobrien    break;
15438494Sobrien  default:
15538494Sobrien    error = EINVAL;
15638494Sobrien    break;
15738494Sobrien  }
15838494Sobrien  dlog("hesiod_search: Returning: %d", error);
15938494Sobrien  return error;
16038494Sobrien#endif /* not HAVE_HESIOD_INIT */
16138494Sobrien}
16251292Sobrien
16351292Sobrien
16451292Sobrien/*
16551292Sobrien * Check if Hesiod is up, so we can determine if to clear the map or not.
16651292Sobrien * Test it by querying for /defaults.
16751292Sobrien * Returns: 0 if Hesiod is down, 1 if it is up.
16851292Sobrien */
16951292Sobrienint
17051292Sobrienhesiod_isup(mnt_map *m, char *map)
17151292Sobrien{
17251292Sobrien  int error;
17351292Sobrien  char *val;
17451292Sobrien  time_t mtime;
17551292Sobrien  static int last_status = 1;	/* assume up by default */
17651292Sobrien
17751292Sobrien  error = hesiod_search(m, map, "/defaults", &val, &mtime);
17851292Sobrien  dlog("hesiod_isup(%s): %s", map, strerror(error));
17951292Sobrien  if (error != 0 && error != ENOENT) {
18051292Sobrien    plog(XLOG_ERROR,
18151292Sobrien	 "hesiod_isup: error getting `/defaults' entry in map %s: %m", map);
18251292Sobrien    last_status = 0;
18351292Sobrien    return 0;			/* Hesiod is down */
18451292Sobrien  }
18551292Sobrien  if (last_status == 0) {	/* if was down before */
18651292Sobrien    plog(XLOG_INFO, "hesiod_isup: Hesiod came back up for map %s", map);
18751292Sobrien    last_status = 1;
18851292Sobrien  }
18951292Sobrien  return 1;			/* Hesiod is up */
19051292Sobrien}
191