-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$BINDId: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie Exp $";
-#endif
+/* Copyright (C) 1997-2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
/*
* Copyright (c) 1996,1999 by Internet Software Consortium.
#include "hesiod.h"
#include "hesiod_p.h"
-#undef DEF_RHS
#define _PATH_HESIOD_CONF "/etc/hesiod.conf"
/* Forward */
-int hesiod_init(void **context);
-void hesiod_end(void *context);
-char * hesiod_to_bind(void *context, const char *name,
- const char *type);
-char ** hesiod_resolve(void *context, const char *name,
- const char *type);
-void hesiod_free_list(void *context, char **list);
-
static int parse_config_file(struct hesiod_p *ctx, const char *filename);
static char ** get_txt_records(struct hesiod_p *ctx, int class,
const char *name);
-static int init(struct hesiod_p *ctx);
/* Public */
char *cp;
ctx = malloc(sizeof(struct hesiod_p));
- if (ctx == 0) {
- __set_errno(ENOMEM);
+ if (ctx == 0)
return (-1);
- }
ctx->LHS = NULL;
ctx->RHS = NULL;
- ctx->res = NULL;
+ /* Set default query classes. */
+ ctx->classes[0] = C_IN;
+ ctx->classes[1] = C_HS;
- configname = __secure_getenv("HESIOD_CONFIG");
+ configname = __libc_secure_getenv("HESIOD_CONFIG");
if (!configname)
configname = _PATH_HESIOD_CONF;
if (parse_config_file(ctx, configname) < 0) {
-#ifdef DEF_RHS
- /*
- * Use compiled in defaults.
- */
- ctx->LHS = malloc(strlen(DEF_LHS)+1);
- ctx->RHS = malloc(strlen(DEF_RHS)+1);
- if (ctx->LHS == 0 || ctx->RHS == 0) {
- __set_errno(ENOMEM);
- goto cleanup;
- }
- strcpy(ctx->LHS, DEF_LHS);
- strcpy(ctx->RHS, DEF_RHS);
-#else
goto cleanup;
-#endif
}
/*
* The default RHS can be overridden by an environment
* variable.
*/
- if ((cp = __secure_getenv("HES_DOMAIN")) != NULL) {
- if (ctx->RHS)
- free(ctx->RHS);
+ if ((cp = __libc_secure_getenv("HES_DOMAIN")) != NULL) {
+ free(ctx->RHS);
ctx->RHS = malloc(strlen(cp)+2);
- if (!ctx->RHS) {
- __set_errno(ENOMEM);
+ if (!ctx->RHS)
goto cleanup;
- }
if (cp[0] == '.')
strcpy(ctx->RHS, cp);
else {
- strcpy(ctx->RHS, ".");
- strcat(ctx->RHS, cp);
+ ctx->RHS[0] = '.';
+ strcpy(ctx->RHS + 1, cp);
}
}
__set_errno(ENOEXEC);
goto cleanup;
}
-
-#if 0
- if (res_ninit(ctx->res) < 0)
- goto cleanup;
-#endif
*context = ctx;
return (0);
struct hesiod_p *ctx = (struct hesiod_p *) context;
int save_errno = errno;
- if (ctx->res)
- res_nclose(ctx->res);
- if (ctx->RHS)
- free(ctx->RHS);
- if (ctx->LHS)
- free(ctx->LHS);
- if (ctx->res && ctx->free_res)
- (*ctx->free_res)(ctx->res);
+ free(ctx->RHS);
+ free(ctx->LHS);
free(ctx);
__set_errno(save_errno);
}
char *bindname;
char **rhs_list = NULL;
const char *RHS, *cp;
+ char *endp;
/* Decide what our RHS is, and set cp to the end of the actual name. */
if ((cp = strchr(name, '@')) != NULL) {
*/
if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) +
(ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) {
- __set_errno(ENOMEM);
if (rhs_list)
hesiod_free_list(context, rhs_list);
return NULL;
}
/* Now put together the DNS name. */
- memcpy(bindname, name, cp - name);
- bindname[cp - name] = '\0';
- strcat(bindname, ".");
- strcat(bindname, type);
+ endp = (char *) __mempcpy (bindname, name, cp - name);
+ *endp++ = '.';
+ endp = (char *) __stpcpy (endp, type);
if (ctx->LHS) {
if (ctx->LHS[0] != '.')
- strcat(bindname, ".");
- strcat(bindname, ctx->LHS);
+ *endp++ = '.';
+ endp = __stpcpy (endp, ctx->LHS);
}
if (RHS[0] != '.')
- strcat(bindname, ".");
- strcat(bindname, RHS);
+ *endp++ = '.';
+ strcpy (endp, RHS);
if (rhs_list)
hesiod_free_list(context, rhs_list);
if (bindname == NULL)
return (NULL);
- if (init(ctx) == -1) {
- free(bindname);
- return (NULL);
- }
- if ((retvec = get_txt_records(ctx, C_IN, bindname))) {
- free(bindname);
- return (retvec);
- }
-
- if (errno != ENOENT)
- return (NULL);
+ retvec = get_txt_records(ctx, ctx->classes[0], bindname);
+
+ if (retvec == NULL && (errno == ENOENT || errno == ECONNREFUSED) && ctx->classes[1])
+ retvec = get_txt_records(ctx, ctx->classes[1], bindname);
+
- retvec = get_txt_records(ctx, C_HS, bindname);
free(bindname);
return (retvec);
}
*/
static int
parse_config_file(struct hesiod_p *ctx, const char *filename) {
- char *key, *data, *cp, **cpp;
char buf[MAXDNAME+7];
FILE *fp;
* Clear the existing configuration variable, just in case
* they're set.
*/
- if (ctx->RHS)
- free(ctx->RHS);
- if (ctx->LHS)
- free(ctx->LHS);
+ free(ctx->RHS);
+ free(ctx->LHS);
ctx->RHS = ctx->LHS = 0;
+ /* Set default query classes. */
+ ctx->classes[0] = C_IN;
+ ctx->classes[1] = C_HS;
/*
* Now open and parse the file...
*/
- if (!(fp = fopen(filename, "r")))
+ if (!(fp = fopen(filename, "rce")))
return (-1);
-
+
while (fgets(buf, sizeof(buf), fp) != NULL) {
+ char *key, *data, *cp, **cpp;
+
cp = buf;
if (*cp == '#' || *cp == '\n' || *cp == '\r')
continue;
while(*cp != ' ' && *cp != '\t' && *cp != '=')
cp++;
*cp++ = '\0';
-
+
while(*cp == ' ' || *cp == '\t' || *cp == '=')
cp++;
data = cp;
cp++;
*cp++ = '\0';
- if (strcmp(key, "lhs") == 0)
+ cpp = NULL;
+ if (strcasecmp(key, "lhs") == 0)
cpp = &ctx->LHS;
- else if (strcmp(key, "rhs") == 0)
+ else if (strcasecmp(key, "rhs") == 0)
cpp = &ctx->RHS;
- else
- continue;
-
- *cpp = malloc(strlen(data) + 1);
- if (!*cpp) {
- __set_errno(ENOMEM);
- goto cleanup;
+ if (cpp) {
+ *cpp = strdup(data);
+ if (!*cpp)
+ goto cleanup;
+ } else if (strcasecmp(key, "classes") == 0) {
+ int n = 0;
+ while (*data && n < 2) {
+ cp = strchrnul(data, ',');
+ if (*cp != '\0')
+ *cp++ = '\0';
+ if (strcasecmp(data, "IN") == 0)
+ ctx->classes[n++] = C_IN;
+ else if (strcasecmp(data, "HS") == 0)
+ ctx->classes[n++] = C_HS;
+ data = cp;
+ }
+ if (n == 0) {
+ /* Restore the default. Better than
+ nother at all. */
+ ctx->classes[0] = C_IN;
+ ctx->classes[1] = C_HS;
+ } else if (n == 1
+ || ctx->classes[0] == ctx->classes[1])
+ ctx->classes[1] = 0;
}
- strcpy(*cpp, data);
}
fclose(fp);
return (0);
-
+
cleanup:
fclose(fp);
- if (ctx->RHS)
- free(ctx->RHS);
- if (ctx->LHS)
- free(ctx->LHS);
+ free(ctx->RHS);
+ free(ctx->LHS);
ctx->RHS = ctx->LHS = 0;
return (-1);
}
/*
* Construct the query and send it.
*/
- n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0,
+ n = res_mkquery(QUERY, name, class, T_TXT, NULL, 0,
NULL, qbuf, MAX_HESRESP);
if (n < 0) {
__set_errno(EMSGSIZE);
return (NULL);
}
- n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP);
+ n = res_send(qbuf, n, abuf, MAX_HESRESP);
if (n < 0) {
__set_errno(ECONNREFUSED);
return (NULL);
}
list = malloc((ancount + 1) * sizeof(char *));
- if (!list) {
- __set_errno(ENOMEM);
+ if (!list)
return (NULL);
- }
j = 0;
for (i = 0; i < ancount; i++) {
skip = dn_skipname(cp, eom);
cp += INT16SZ + INT32SZ; /* skip the ttl, too */
rr.dlen = ns_get16(cp);
cp += INT16SZ;
- if (cp + rr.dlen > eom) {
+ if (rr.dlen == 0 || cp + rr.dlen > eom) {
__set_errno(EMSGSIZE);
goto cleanup;
}
free(list);
return (NULL);
}
-
-struct __res_state *
-__hesiod_res_get(void *context) {
- struct hesiod_p *ctx = context;
-
- if (!ctx->res) {
- struct __res_state *res;
- res = (struct __res_state *)malloc(sizeof *res);
- if (res == NULL) {
- __set_errno(ENOMEM);
- return (NULL);
- }
- memset(res, 0, sizeof *res);
- __hesiod_res_set(ctx, res, free);
- }
-
- return (ctx->res);
-}
-
-void
-__hesiod_res_set(void *context, struct __res_state *res,
- void (*free_res)(void *)) {
- struct hesiod_p *ctx = context;
-
- if (ctx->res && ctx->free_res) {
- res_nclose(ctx->res);
- (*ctx->free_res)(ctx->res);
- }
-
- ctx->res = res;
- ctx->free_res = free_res;
-}
-
-static int
-init(struct hesiod_p *ctx) {
-
- if (!ctx->res && !__hesiod_res_get(ctx))
- return (-1);
-
- if (((ctx->res->options & RES_INIT) == 0) &&
- (res_ninit(ctx->res) == -1))
- return (-1);
-
- return (0);
-}