📄 info_hes.c
字号:
/* * Copyright (c) 1989 Jan-Simon Pendry * Copyright (c) 1989 Imperial College of Science, Technology & Medicine * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Jan-Simon Pendry at Imperial College, London. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)info_hes.c 8.1 (Berkeley) 6/6/93 * * $Id: info_hes.c,v 5.2.2.1 1992/02/09 15:08:29 jsp beta $ * *//* * Get info from Hesiod * * Zone transfer code from Bruce Cole <cole@cs.wisc.edu> */#include "am.h"#ifdef HAS_HESIOD_MAPS#include <hesiod.h>#define HES_PREFIX "hesiod."#define HES_PREFLEN 7#ifdef HAS_HESIOD_RELOAD#include <arpa/nameser.h>#include <resolv.h>#include <sys/uio.h>#include <netdb.h>/* * Patch up broken system include files */#ifndef C_HS#define C_HS 4#endif#ifndef T_TXT#define T_TXT 16#endifstatic int soacnt;static struct timeval hs_timeout;static int servernum;#endif /* HAS_HESIOD_RELOAD *//* * No easy way to probe the server - check the map name begins with "hesiod." */int hesiod_init P((char *map, time_t *tp));int hesiod_init(map, tp)char *map;time_t *tp;{#ifdef DEBUG dlog("hesiod_init(%s)", map);#endif *tp = 0; return strncmp(map, HES_PREFIX, HES_PREFLEN) == 0 ? 0 : ENOENT;}/* * Make Hesiod name. Skip past the "hesiod." * at the start of the map name and append * ".automount". The net effect is that a lookup * of /defaults in hesiod.home will result in a * call to hes_resolve("/defaults", "home.automount"); */#ifdef notdef#define MAKE_HES_NAME(dest, src) sprintf(dest, "%s%s", src + HES_PREFLEN, ".automount")#endif/* * Do a Hesiod nameserver call. * Modify time is ignored by Hesiod - XXX */int hesiod_search P((mnt_map *m, char *map, char **pval, time_t *tp));int hesiod_search(m, map, key, pval, tp)mnt_map *m;char *map;char *key;char **pval;time_t *tp;{ int error; char hes_key[MAXPATHLEN]; char **rvec;#ifdef DEBUG dlog("hesiod_search(m=%x, map=%s, key=%s, pval=%x tp=%x)", m, map, key, pval, tp);#endif /*MAKE_HES_NAME(hes_map, map);*/ sprintf(hes_key, "%s.%s", key, map+HES_PREFLEN); /* * Call the resolver */#ifdef DEBUG dlog("hesiod_search: hes_resolve(%s, %s)", hes_key, "automount");#ifdef HAS_HESIOD_RELOAD if (debug_flags & D_FULL) _res.options |= RES_DEBUG;#endif#endif rvec = hes_resolve(hes_key, "automount"); /* * If a reply was forthcoming then return * it (and free subsequent replies) */ if (rvec && *rvec) { *pval = *rvec; while (*++rvec) free(*rvec); return 0; } /* * Otherwise reflect the hesiod error into a Un*x error */#ifdef DEBUG dlog("hesiod_search: Error: %d", hes_error());#endif switch (hes_error()) { case HES_ER_NOTFOUND: error = ENOENT; break; case HES_ER_CONFIG: error = EIO; break; case HES_ER_NET: error = ETIMEDOUT; break; default: error = EINVAL; break; }#ifdef DEBUG dlog("hesiod_search: Returning: %d", error);#endif return error;}#ifdef HAS_HESIOD_RELOAD/* * Zone transfer... */#define MAXHSNS 8#define MAX_NSADDR 16static char *hs_domain;static mnt_map *hs_map;static int hs_nscount;static char nsaddr_list[MAX_NSADDR][sizeof(struct in_addr)];int hesiod_reload P((mnt_map *m, char *map, void (*fn)()));int hesiod_reload(m, map, fn)mnt_map *m;char *map;void (*fn)();{ char *zone_name, *cp; short domainlen; int status;#ifdef DEBUG dlog("hesiod_reload (%x %s %x)", m, map, fn);#endif DEBUG if (status = res_init()) {#ifdef DEBUG dlog("hesiod_reload: res_init failed with %d", status);#endif return(status); } _res.retrans = 90; hs_map = m; domainlen = strlen(hostdomain); zone_name = hes_to_bind(map+HES_PREFLEN, "automount"); if (*zone_name == '.') zone_name++; hs_domain = zone_name; /* Traverse the DNS tree until we find an SOA we can transfer from. (Our initial zone_name is likely to just be a subtree of a real zone). */ do { /* If we can't find any NS records, go up a level in the DNS tree */ if (hs_get_ns_list(zone_name) == 0 && hs_zone_transfer(zone_name) == 0) return(0); /* Move up DNS tree by one component */ if (cp = strchr(zone_name, '.')) zone_name = ++cp; else break; } while (strlen(zone_name) >= domainlen);#ifdef DEBUG dlog("hesiod_reload: Giving up on %s", hs_domain);#endif return(-1);}hs_zone_transfer(domain)char *domain;{ int status, len; char buf[PACKETSZ]; /* Want to make sure ansbuf is well alligned */ long ansbuf[PACKETSZ/sizeof(long)];#ifdef DEBUG dlog("hs_zone_transfer (%s)", domain);#endif if ((len = res_mkquery(QUERY, domain, C_HS, T_AXFR, (char *)NULL, 0, NULL, buf, PACKETSZ)) == -1) {#ifdef DEBUG dlog("hs_zone_transfer: res_mkquery failed");#endif errno = 0; return(-1); } if ((status = hs_res_send(buf, len, (char *)ansbuf, PACKETSZ)) == -1) {#ifdef DEBUG dlog("hs_zone_transfer: hs_res_send failed. status %d errno %d", status, errno);#endif errno = 0; return(-1); } return(0);}#define hs_server_addr(ns) ((struct in_addr *) nsaddr_list[ns])hs_res_send(buf, buflen, answer, anslen)char *buf;int buflen;char *answer;int anslen;{ int retry, ns; u_short id, len; HEADER *hp = (HEADER *) buf; struct iovec iov[2]; static int s = -1; int status; struct sockaddr_in server; soacnt = 0; id = hp->id; /* * Send request, RETRY times, or until successful */ for (retry = _res.retry; retry > 0; retry--) { for (ns = 0; ns < hs_nscount; ns++) { hs_timeout.tv_sec = (_res.retrans << (_res.retry - retry)) / hs_nscount; if (hs_timeout.tv_sec <= 0) hs_timeout.tv_sec = 1; hs_timeout.tv_usec = 0; if (s < 0) { s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { continue; } servernum = ns; bcopy(hs_server_addr(ns), &server.sin_addr, sizeof(struct in_addr)); server.sin_family = AF_INET; server.sin_port = htons(NAMESERVER_PORT); if (connect(s, &server, sizeof(struct sockaddr)) < 0) { (void) close(s); s = -1; continue; } } /* * Send length & message */ len = htons((u_short)buflen); iov[0].iov_base = (caddr_t)&len; iov[0].iov_len = sizeof(len); iov[1].iov_base = buf; iov[1].iov_len = buflen; if (writev(s, iov, 2) != sizeof(len) + buflen) { (void) close(s); s = -1; continue; } status = 0; while (s != -1 && soacnt < 2 && status != -2) { if ((status = hs_readresp(s, answer, anslen)) == -1) { (void) close(s); s = -1; continue; } } if (status == -2) { /* There was a permanent error transfering this zone. Give up. */ if (s != -1) { (void) close(s); s = -1; } return(-1); } if (s == -1) continue; return (0); } } if (errno == 0) errno = ETIMEDOUT; return (-1);}/* Returns: 0: Success -1: Error -2: Permanent failure*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -