1/*	$NetBSD: info_hesiod.c,v 1.1.1.3 2015/01/17 16:34:15 christos Exp $	*/
2
3/*
4 * Copyright (c) 1997-2014 Erez Zadok
5 * Copyright (c) 1989 Jan-Simon Pendry
6 * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1989 The Regents of the University of California.
8 * All rights reserved.
9 *
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 *
38 * File: am-utils/amd/info_hesiod.c
39 *
40 */
41
42/*
43 * Get info from Hesiod
44 */
45
46#ifdef HAVE_CONFIG_H
47# include <config.h>
48#endif /* HAVE_CONFIG_H */
49#include <am_defs.h>
50#include <amd.h>
51#include <sun_map.h>
52
53#define	HES_PREFIX	"hesiod."
54#define	HES_PREFLEN	7
55
56#ifdef HAVE_HESIOD_INIT
57/* bsdi3 does not define this extern in any header file */
58extern char **hesiod_resolve(void *context, const char *name, const char *type);
59extern int hesiod_init(void **context);
60static voidp hesiod_context;
61#endif /* HAVE_HESIOD_INIT */
62
63/* forward declarations */
64int amu_hesiod_init(mnt_map *m, char *map, time_t *tp);
65int hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp);
66int hesiod_isup(mnt_map *m, char *map);
67
68/*
69 * No easy way to probe the server - check the map name begins with "hesiod."
70 * Note: this name includes 'amu_' so as to not conflict with libhesiod's
71 * hesiod_init() function.
72 */
73int
74amu_hesiod_init(mnt_map *m, char *map, time_t *tp)
75{
76  dlog("amu_hesiod_init(%s)", map);
77  *tp = 0;
78
79#ifdef HAVE_HESIOD_INIT
80  if (!hesiod_context && hesiod_init(&hesiod_context) != 0)
81    return ENOENT;
82#endif /* HAVE_HESIOD_INIT */
83
84  return NSTREQ(map, HES_PREFIX, HES_PREFLEN) ? 0 : ENOENT;
85}
86
87
88/*
89 * Do a Hesiod nameserver call.
90 * Modify time is ignored by Hesiod - XXX
91 */
92int
93hesiod_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp)
94{
95  char hes_key[MAXPATHLEN];
96  char **rvec;
97#ifndef HAVE_HESIOD_INIT
98  int error;
99#endif /* not HAVE_HESIOD_INIT */
100
101  dlog("hesiod_search(m=%lx, map=%s, key=%s, pval=%lx tp=%lx)",
102       (unsigned long) m, map, key, (unsigned long) pval, (unsigned long) tp);
103
104  if (key[0] == '.')
105    return ENOENT;
106
107  xsnprintf(hes_key, sizeof(hes_key), "%s.%s", key, map + HES_PREFLEN);
108
109  /*
110   * Call the resolver
111   */
112  dlog("Hesiod base is: %s\n", gopt.hesiod_base);
113  dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, gopt.hesiod_base);
114  if (amuDebug(D_INFO))
115    _res.options |= RES_DEBUG;
116
117#ifdef HAVE_HESIOD_INIT
118  /* new style hesiod */
119  rvec = hesiod_resolve(hesiod_context, hes_key, gopt.hesiod_base);
120#else /* not HAVE_HESIOD_INIT */
121  rvec = hes_resolve(hes_key, gopt.hesiod_base);
122#endif /* not HAVE_HESIOD_INIT */
123
124  /*
125   * If a reply was forthcoming then return
126   * it (and free subsequent replies)
127   */
128  if (rvec && *rvec) {
129    if (m->cfm && (m->cfm->cfm_flags & CFM_SUN_MAP_SYNTAX)) {
130      *pval = sun_entry2amd(key, *rvec);
131      XFREE(*rvec);
132    } else
133      *pval = *rvec;
134    while (*++rvec)
135      XFREE(*rvec);
136    return 0;
137  }
138
139#ifdef HAVE_HESIOD_INIT
140  /* new style hesiod */
141  return errno;
142#else /* not HAVE_HESIOD_INIT */
143  /*
144   * Otherwise reflect the hesiod error into a Un*x error
145   */
146  dlog("hesiod_search: Error: %d", hes_error());
147  switch (hes_error()) {
148  case HES_ER_NOTFOUND:
149    error = ENOENT;
150    break;
151  case HES_ER_CONFIG:
152    error = EIO;
153    break;
154  case HES_ER_NET:
155    error = ETIMEDOUT;
156    break;
157  default:
158    error = EINVAL;
159    break;
160  }
161  dlog("hesiod_search: Returning: %d", error);
162  return error;
163#endif /* not HAVE_HESIOD_INIT */
164}
165
166
167/*
168 * Check if Hesiod is up, so we can determine if to clear the map or not.
169 * Test it by querying for /defaults.
170 * Returns: 0 if Hesiod is down, 1 if it is up.
171 */
172int
173hesiod_isup(mnt_map *m, char *map)
174{
175  int error;
176  char *val;
177  time_t mtime;
178  static int last_status = 1;	/* assume up by default */
179
180  error = hesiod_search(m, map, "/defaults", &val, &mtime);
181  dlog("hesiod_isup(%s): %s", map, strerror(error));
182  if (error != 0 && error != ENOENT) {
183    plog(XLOG_ERROR,
184	 "hesiod_isup: error getting `/defaults' entry in map %s: %m", map);
185    last_status = 0;
186    return 0;			/* Hesiod is down */
187  }
188  if (last_status == 0) {	/* if was down before */
189    plog(XLOG_INFO, "hesiod_isup: Hesiod came back up for map %s", map);
190    last_status = 1;
191  }
192  return 1;			/* Hesiod is up */
193}
194