"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/lwres/getrrset.c" (7 Sep 2020, 8536 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "getrrset.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 /**
   15  * DESCRIPTION
   16  *
   17  *    lwres_getrrsetbyname() gets a set of resource records associated with
   18  *    a hostname, class, and type. hostname is a pointer a to
   19  *    null-terminated string. The flags field is currently unused and must
   20  *    be zero.
   21  *
   22  *    After a successful call to lwres_getrrsetbyname(), *res is a pointer
   23  *    to an #rrsetinfo structure, containing a list of one or more #rdatainfo
   24  *    structures containing resource records and potentially another list of
   25  *    rdatainfo structures containing SIG resource records associated with
   26  *    those records. The members #rri_rdclass and #rri_rdtype are copied from
   27  *    the parameters. #rri_ttl and #rri_name are properties of the obtained
   28  *    rrset. The resource records contained in #rri_rdatas and #rri_sigs are
   29  *    in uncompressed DNS wire format. Properties of the rdataset are
   30  *    represented in the #rri_flags bitfield. If the #RRSET_VALIDATED bit is
   31  *    set, the data has been DNSSEC validated and the signatures verified.
   32  *
   33  *    All of the information returned by lwres_getrrsetbyname() is
   34  *    dynamically allocated: the rrsetinfo and rdatainfo structures, and the
   35  *    canonical host name strings pointed to by the rrsetinfostructure.
   36  *    Memory allocated for the dynamically allocated structures created by a
   37  *    successful call to lwres_getrrsetbyname() is released by
   38  *    lwres_freerrset(). rrset is a pointer to a struct rrset created by a
   39  *    call to lwres_getrrsetbyname().
   40  *
   41  *    The following structures are used:
   42  *
   43  * \code
   44  * struct  rdatainfo {
   45  *         unsigned int            rdi_length;     // length of data
   46  *         unsigned char           *rdi_data;      // record data
   47  * };
   48  *
   49  * struct  rrsetinfo {
   50  *         unsigned int            rri_flags;      // RRSET_VALIDATED...
   51  *         unsigned int            rri_rdclass;    // class number
   52  *         unsigned int            rri_rdtype;     // RR type number
   53  *         unsigned int            rri_ttl;        // time to live
   54  *         unsigned int            rri_nrdatas;    // size of rdatas array
   55  *         unsigned int            rri_nsigs;      // size of sigs array
   56  *         char                    *rri_name;      // canonical name
   57  *         struct rdatainfo        *rri_rdatas;    // individual records
   58  *         struct rdatainfo        *rri_sigs;      // individual signatures
   59  * };
   60  * \endcode
   61  *
   62  * \section getrrset_return Return Values
   63  *
   64  *    lwres_getrrsetbyname() returns zero on success, and one of the
   65  *    following error codes if an error occurred:
   66  *
   67  * \li   #ERRSET_NONAME: the name does not exist
   68  *
   69  * \li   #ERRSET_NODATA:
   70  *           the name exists, but does not have data of the desired type
   71  *
   72  * \li   #ERRSET_NOMEMORY:
   73  *           memory could not be allocated
   74  *
   75  * \li   #ERRSET_INVAL:
   76  *           a parameter is invalid
   77  *
   78  * \li   #ERRSET_FAIL:
   79  *           other failure
   80  */
   81 
   82 #include <config.h>
   83 
   84 #include <inttypes.h>
   85 #include <string.h>
   86 #include <errno.h>
   87 #include <stdlib.h>
   88 
   89 #include <lwres/lwres.h>
   90 #include <lwres/net.h>
   91 #include <lwres/netdb.h>    /* XXX #include <netdb.h> */
   92 
   93 #include "assert_p.h"
   94 
   95 /*!
   96  * Structure to map results
   97  */
   98 static unsigned int
   99 lwresult_to_result(lwres_result_t lwresult) {
  100     switch (lwresult) {
  101     case LWRES_R_SUCCESS:   return (ERRSET_SUCCESS);
  102     case LWRES_R_NOMEMORY:  return (ERRSET_NOMEMORY);
  103     case LWRES_R_NOTFOUND:  return (ERRSET_NONAME);
  104     case LWRES_R_TYPENOTFOUND: return (ERRSET_NODATA);
  105     default:        return (ERRSET_FAIL);
  106     }
  107 }
  108 
  109 /*@{*/
  110 /*!
  111  * malloc / calloc functions that guarantee to only
  112  * return NULL if there is an error, like they used
  113  * to before the ANSI C committee broke them.
  114  */
  115 
  116 static void *
  117 sane_malloc(size_t size) {
  118     if (size == 0U)
  119         size = 1;
  120     /* cppcheck-suppress leakNoVarFunctionCall */
  121     return (malloc(size));
  122 }
  123 
  124 static void *
  125 sane_calloc(size_t number, size_t size) {
  126     size_t len = number * size;
  127     void *mem  = sane_malloc(len);
  128     if (mem != NULL)
  129         memset(mem, 0, len);
  130     return (mem);
  131 }
  132 /*@}*/
  133 
  134 /*% Returns a set of resource records associated with a hostname, class, and type. hostname is a pointer a to null-terminated string. */
  135 int
  136 lwres_getrrsetbyname(const char *hostname, unsigned int rdclass,
  137              unsigned int rdtype, unsigned int flags,
  138              struct rrsetinfo **res)
  139 {
  140     lwres_context_t *lwrctx = NULL;
  141     lwres_result_t lwresult;
  142     lwres_grbnresponse_t *response = NULL;
  143     struct rrsetinfo *rrset = NULL;
  144     unsigned int i;
  145     unsigned int lwflags;
  146     unsigned int result;
  147 
  148     if (rdclass > 0xffff || rdtype > 0xffff) {
  149         result = ERRSET_INVAL;
  150         goto fail;
  151     }
  152 
  153     /*
  154      * Don't allow queries of class or type ANY
  155      */
  156     if (rdclass == 0xff || rdtype == 0xff) {
  157         result = ERRSET_INVAL;
  158         goto fail;
  159     }
  160 
  161     lwresult = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
  162     if (lwresult != LWRES_R_SUCCESS) {
  163         result = lwresult_to_result(lwresult);
  164         goto fail;
  165     }
  166     (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
  167 
  168     /*
  169      * If any input flags were defined, lwflags would be set here
  170      * based on them
  171      */
  172     UNUSED(flags);
  173     lwflags = 0;
  174 
  175     lwresult = lwres_getrdatabyname(lwrctx, hostname,
  176                     (uint16_t)rdclass,
  177                     (uint16_t)rdtype,
  178                     lwflags, &response);
  179     if (lwresult != LWRES_R_SUCCESS) {
  180         result = lwresult_to_result(lwresult);
  181         goto fail;
  182     }
  183 
  184     rrset = sane_malloc(sizeof(struct rrsetinfo));
  185     if (rrset == NULL) {
  186         result = ERRSET_NOMEMORY;
  187         goto fail;
  188     }
  189     rrset->rri_name = NULL;
  190     rrset->rri_rdclass = response->rdclass;
  191     rrset->rri_rdtype = response->rdtype;
  192     rrset->rri_ttl = response->ttl;
  193     rrset->rri_flags = 0;
  194     rrset->rri_nrdatas = 0;
  195     rrset->rri_rdatas = NULL;
  196     rrset->rri_nsigs = 0;
  197     rrset->rri_sigs = NULL;
  198 
  199     rrset->rri_name = sane_malloc(response->realnamelen + 1);
  200     if (rrset->rri_name == NULL) {
  201         result = ERRSET_NOMEMORY;
  202         goto fail;
  203     }
  204     strncpy(rrset->rri_name, response->realname, response->realnamelen);
  205     rrset->rri_name[response->realnamelen] = 0;
  206 
  207     if ((response->flags & LWRDATA_VALIDATED) != 0)
  208         rrset->rri_flags |= RRSET_VALIDATED;
  209 
  210     rrset->rri_nrdatas = response->nrdatas;
  211     rrset->rri_rdatas = sane_calloc(rrset->rri_nrdatas,
  212                    sizeof(struct rdatainfo));
  213     if (rrset->rri_rdatas == NULL) {
  214         result = ERRSET_NOMEMORY;
  215         goto fail;
  216     }
  217     for (i = 0; i < rrset->rri_nrdatas; i++) {
  218         rrset->rri_rdatas[i].rdi_length = response->rdatalen[i];
  219         rrset->rri_rdatas[i].rdi_data =
  220                 sane_malloc(rrset->rri_rdatas[i].rdi_length);
  221         if (rrset->rri_rdatas[i].rdi_data == NULL) {
  222             result = ERRSET_NOMEMORY;
  223             goto fail;
  224         }
  225         memmove(rrset->rri_rdatas[i].rdi_data, response->rdatas[i],
  226             rrset->rri_rdatas[i].rdi_length);
  227     }
  228     rrset->rri_nsigs = response->nsigs;
  229     rrset->rri_sigs = sane_calloc(rrset->rri_nsigs,
  230                       sizeof(struct rdatainfo));
  231     if (rrset->rri_sigs == NULL) {
  232         result = ERRSET_NOMEMORY;
  233         goto fail;
  234     }
  235     for (i = 0; i < rrset->rri_nsigs; i++) {
  236         rrset->rri_sigs[i].rdi_length = response->siglen[i];
  237         rrset->rri_sigs[i].rdi_data =
  238                 sane_malloc(rrset->rri_sigs[i].rdi_length);
  239         if (rrset->rri_sigs[i].rdi_data == NULL) {
  240             result = ERRSET_NOMEMORY;
  241             goto fail;
  242         }
  243         memmove(rrset->rri_sigs[i].rdi_data, response->sigs[i],
  244             rrset->rri_sigs[i].rdi_length);
  245     }
  246 
  247     lwres_grbnresponse_free(lwrctx, &response);
  248     lwres_conf_clear(lwrctx);
  249     lwres_context_destroy(&lwrctx);
  250     *res = rrset;
  251     return (ERRSET_SUCCESS);
  252  fail:
  253     if (rrset != NULL)
  254         lwres_freerrset(rrset);
  255     if (response != NULL)
  256         lwres_grbnresponse_free(lwrctx, &response);
  257     if (lwrctx != NULL) {
  258         lwres_conf_clear(lwrctx);
  259         lwres_context_destroy(&lwrctx);
  260     }
  261     return (result);
  262 }
  263 
  264 /*% Releases memory allocated for the dynamically allocated structures created by a successful call to lwres_getrrsetbyname(). */
  265 void
  266 lwres_freerrset(struct rrsetinfo *rrset) {
  267     unsigned int i;
  268     if (rrset->rri_rdatas != NULL) {
  269         for (i = 0; i < rrset->rri_nrdatas; i++) {
  270             if (rrset->rri_rdatas[i].rdi_data == NULL)
  271                 break;
  272             free(rrset->rri_rdatas[i].rdi_data);
  273         }
  274         free(rrset->rri_rdatas);
  275     }
  276     if (rrset->rri_sigs != NULL) {
  277         for (i = 0; i < rrset->rri_nsigs; i++) {
  278             if (rrset->rri_sigs[i].rdi_data == NULL)
  279                 break;
  280             free(rrset->rri_sigs[i].rdi_data);
  281         }
  282         free(rrset->rri_sigs);
  283     }
  284     free(rrset->rri_name);
  285     free(rrset);
  286 }