]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - hesiod/hesiod.c
Regenerate charmap-kw.h, locfile-kw.h
[thirdparty/glibc.git] / hesiod / hesiod.c
index 3a01fd076bd48042ffa62133ba2706758d640702..bfb95633e352d029b0ffcc3436712e9b205c832b 100644 (file)
@@ -1,6 +1,19 @@
-#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.
@@ -46,24 +59,14 @@ static const char rcsid[] = "$BINDId: hesiod.c,v 1.21 2000/02/28 14:51:08 vixie
 
 #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 */
 
@@ -77,52 +80,35 @@ hesiod_init(void **context) {
        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);
                }
        }
 
@@ -134,11 +120,6 @@ hesiod_init(void **context) {
                __set_errno(ENOEXEC);
                goto cleanup;
        }
-       
-#if 0
-       if (res_ninit(ctx->res) < 0)
-               goto cleanup;
-#endif
 
        *context = ctx;
        return (0);
@@ -156,14 +137,8 @@ hesiod_end(void *context) {
        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);
 }
@@ -178,6 +153,7 @@ hesiod_to_bind(void *context, const char *name, const char *type) {
        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) {
@@ -201,25 +177,23 @@ hesiod_to_bind(void *context, const char *name, const char *type) {
         */
        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);
@@ -239,20 +213,13 @@ hesiod_resolve(void *context, const char *name, const char *type) {
 
        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);
 }
@@ -271,7 +238,6 @@ hesiod_free_list(void *context, char **list) {
  */
 static int
 parse_config_file(struct hesiod_p *ctx, const char *filename) {
-       char *key, *data, *cp, **cpp;
        char buf[MAXDNAME+7];
        FILE *fp;
 
@@ -279,19 +245,22 @@ parse_config_file(struct hesiod_p *ctx, const char *filename) {
         * 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;
@@ -301,7 +270,7 @@ parse_config_file(struct hesiod_p *ctx, const char *filename) {
                while(*cp != ' ' && *cp != '\t' && *cp != '=')
                        cp++;
                *cp++ = '\0';
-               
+
                while(*cp == ' ' || *cp == '\t' || *cp == '=')
                        cp++;
                data = cp;
@@ -309,29 +278,44 @@ parse_config_file(struct hesiod_p *ctx, const char *filename) {
                        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);
 }
@@ -358,13 +342,13 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
        /*
         * 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);
@@ -394,10 +378,8 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
        }
 
        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);
@@ -416,7 +398,7 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
                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;
                }
@@ -459,48 +441,3 @@ get_txt_records(struct hesiod_p *ctx, int class, const char *name) {
        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);
-}