"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/lwres/lwres_gabn.c" (7 Sep 2020, 13710 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 "lwres_gabn.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 /* $Id: lwres_gabn.c,v 1.33 2007/06/19 23:47:22 tbox Exp $ */
   13 
   14 /*! \file lwres_gabn.c
   15    These are low-level routines for creating and parsing lightweight
   16    resolver name-to-address lookup request and response messages.
   17 
   18    There are four main functions for the getaddrbyname opcode. One render
   19    function converts a getaddrbyname request structure --
   20    lwres_gabnrequest_t -- to the lighweight resolver's canonical format.
   21    It is complemented by a parse function that converts a packet in this
   22    canonical format to a getaddrbyname request structure. Another render
   23    function converts the getaddrbyname response structure --
   24    lwres_gabnresponse_t -- to the canonical format. This is complemented
   25    by a parse function which converts a packet in canonical format to a
   26    getaddrbyname response structure.
   27 
   28    These structures are defined in \link lwres.h <lwres/lwres.h>.\endlink They are shown below.
   29 
   30 \code
   31 #define LWRES_OPCODE_GETADDRSBYNAME     0x00010001U
   32 
   33 typedef struct lwres_addr lwres_addr_t;
   34 typedef LWRES_LIST(lwres_addr_t) lwres_addrlist_t;
   35 
   36 typedef struct {
   37     uint32_t  flags;
   38     uint32_t  addrtypes;
   39     uint16_t  namelen;
   40     char           *name;
   41 } lwres_gabnrequest_t;
   42 
   43 typedef struct {
   44     uint32_t          flags;
   45     uint16_t          naliases;
   46     uint16_t          naddrs;
   47     char                   *realname;
   48     char                  **aliases;
   49     uint16_t          realnamelen;
   50     uint16_t         *aliaslen;
   51     lwres_addrlist_t        addrs;
   52     void                   *base;
   53     size_t                  baselen;
   54 } lwres_gabnresponse_t;
   55 \endcode
   56 
   57    lwres_gabnrequest_render() uses resolver context ctx to convert
   58    getaddrbyname request structure req to canonical format. The packet
   59    header structure pkt is initialised and transferred to buffer b. The
   60    contents of *req are then appended to the buffer in canonical format.
   61    lwres_gabnresponse_render() performs the same task, except it converts
   62    a getaddrbyname response structure lwres_gabnresponse_t to the
   63    lightweight resolver's canonical format.
   64 
   65    lwres_gabnrequest_parse() uses context ctx to convert the contents of
   66    packet pkt to a lwres_gabnrequest_t structure. Buffer b provides space
   67    to be used for storing this structure. When the function succeeds, the
   68    resulting lwres_gabnrequest_t is made available through *structp.
   69    lwres_gabnresponse_parse() offers the same semantics as
   70    lwres_gabnrequest_parse() except it yields a lwres_gabnresponse_t
   71    structure.
   72 
   73    lwres_gabnresponse_free() and lwres_gabnrequest_free() release the
   74    memory in resolver context ctx that was allocated to the
   75    lwres_gabnresponse_t or lwres_gabnrequest_t structures referenced via
   76    structp. Any memory associated with ancillary buffers and strings for
   77    those structures is also discarded.
   78 
   79 \section lwres_gabn_return Return Values
   80 
   81    The getaddrbyname opcode functions lwres_gabnrequest_render(),
   82    lwres_gabnresponse_render() lwres_gabnrequest_parse() and
   83    lwres_gabnresponse_parse() all return #LWRES_R_SUCCESS on success. They
   84    return #LWRES_R_NOMEMORY if memory allocation fails.
   85    #LWRES_R_UNEXPECTEDEND is returned if the available space in the buffer
   86    b is too small to accommodate the packet header or the
   87    lwres_gabnrequest_t and lwres_gabnresponse_t structures.
   88    lwres_gabnrequest_parse() and lwres_gabnresponse_parse() will return
   89    #LWRES_R_UNEXPECTEDEND if the buffer is not empty after decoding the
   90    received packet. These functions will return #LWRES_R_FAILURE if
   91    pktflags in the packet header structure #lwres_lwpacket_t indicate that
   92    the packet is not a response to an earlier query.
   93 
   94 \section lwres_gabn_see See Also
   95 
   96    \link lwpacket.c lwres_lwpacket \endlink
   97  */
   98 
   99 #include <config.h>
  100 
  101 #include <assert.h>
  102 #include <inttypes.h>
  103 #include <stdlib.h>
  104 #include <string.h>
  105 
  106 #include <lwres/lwbuffer.h>
  107 #include <lwres/lwpacket.h>
  108 #include <lwres/lwres.h>
  109 #include <lwres/result.h>
  110 
  111 #include "context_p.h"
  112 #include "assert_p.h"
  113 
  114 /*% uses resolver context ctx to convert getaddrbyname request structure req to canonical format. */
  115 lwres_result_t
  116 lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req,
  117              lwres_lwpacket_t *pkt, lwres_buffer_t *b)
  118 {
  119     unsigned char *buf;
  120     size_t buflen;
  121     int ret;
  122     size_t payload_length;
  123     uint16_t datalen;
  124 
  125     REQUIRE(ctx != NULL);
  126     REQUIRE(req != NULL);
  127     REQUIRE(req->name != NULL);
  128     REQUIRE(pkt != NULL);
  129     REQUIRE(b != NULL);
  130 
  131     datalen = (uint16_t) strlen(req->name);
  132 
  133     payload_length = 4 + 4 + 2 + req->namelen + 1;
  134 
  135     buflen = LWRES_LWPACKET_LENGTH + payload_length;
  136     buf = CTXMALLOC(buflen);
  137     if (buf == NULL)
  138         return (LWRES_R_NOMEMORY);
  139 
  140     lwres_buffer_init(b, buf, (unsigned int)buflen);
  141 
  142     pkt->length = (uint32_t)buflen;
  143     pkt->version = LWRES_LWPACKETVERSION_0;
  144     pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
  145     pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME;
  146     pkt->result = 0;
  147     pkt->authtype = 0;
  148     pkt->authlength = 0;
  149 
  150     ret = lwres_lwpacket_renderheader(b, pkt);
  151     if (ret != LWRES_R_SUCCESS) {
  152         lwres_buffer_invalidate(b);
  153         CTXFREE(buf, buflen);
  154         return (ret);
  155     }
  156 
  157     INSIST(SPACE_OK(b, payload_length));
  158 
  159     /*
  160      * Flags.
  161      */
  162     lwres_buffer_putuint32(b, req->flags);
  163 
  164     /*
  165      * Address types we'll accept.
  166      */
  167     lwres_buffer_putuint32(b, req->addrtypes);
  168 
  169     /*
  170      * Put the length and the data.  We know this will fit because we
  171      * just checked for it.
  172      */
  173     lwres_buffer_putuint16(b, datalen);
  174     lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
  175     lwres_buffer_putuint8(b, 0); /* trailing NUL */
  176 
  177     INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
  178 
  179     return (LWRES_R_SUCCESS);
  180 }
  181 /*% converts a getaddrbyname response structure lwres_gabnresponse_t to the lightweight resolver's canonical format. */
  182 lwres_result_t
  183 lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req,
  184               lwres_lwpacket_t *pkt, lwres_buffer_t *b)
  185 {
  186     unsigned char *buf;
  187     size_t buflen;
  188     int ret;
  189     size_t payload_length;
  190     uint16_t datalen;
  191     lwres_addr_t *addr;
  192     int x;
  193 
  194     REQUIRE(ctx != NULL);
  195     REQUIRE(req != NULL);
  196     REQUIRE(pkt != NULL);
  197     REQUIRE(b != NULL);
  198 
  199     /* naliases, naddrs */
  200     payload_length = 4 + 2 + 2;
  201     /* real name encoding */
  202     payload_length += 2 + req->realnamelen + 1;
  203     /* each alias */
  204     for (x = 0; x < req->naliases; x++)
  205         payload_length += 2 + req->aliaslen[x] + 1;
  206     /* each address */
  207     x = 0;
  208     addr = LWRES_LIST_HEAD(req->addrs);
  209     while (addr != NULL) {
  210         payload_length += 4 + 2;
  211         payload_length += addr->length;
  212         addr = LWRES_LIST_NEXT(addr, link);
  213         x++;
  214     }
  215     INSIST(x == req->naddrs);
  216 
  217     buflen = LWRES_LWPACKET_LENGTH + payload_length;
  218     buf = CTXMALLOC(buflen);
  219     if (buf == NULL)
  220         return (LWRES_R_NOMEMORY);
  221     lwres_buffer_init(b, buf, (unsigned int)buflen);
  222 
  223     pkt->length = (uint32_t)buflen;
  224     pkt->version = LWRES_LWPACKETVERSION_0;
  225     pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
  226     pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME;
  227     pkt->authtype = 0;
  228     pkt->authlength = 0;
  229 
  230     ret = lwres_lwpacket_renderheader(b, pkt);
  231     if (ret != LWRES_R_SUCCESS) {
  232         lwres_buffer_invalidate(b);
  233         CTXFREE(buf, buflen);
  234         return (ret);
  235     }
  236 
  237     /*
  238      * Check space needed here.
  239      */
  240     INSIST(SPACE_OK(b, payload_length));
  241 
  242     /* Flags. */
  243     lwres_buffer_putuint32(b, req->flags);
  244 
  245     /* encode naliases and naddrs */
  246     lwres_buffer_putuint16(b, req->naliases);
  247     lwres_buffer_putuint16(b, req->naddrs);
  248 
  249     /* encode the real name */
  250     datalen = req->realnamelen;
  251     lwres_buffer_putuint16(b, datalen);
  252     lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
  253     lwres_buffer_putuint8(b, 0);
  254 
  255     /* encode the aliases */
  256     for (x = 0; x < req->naliases; x++) {
  257         datalen = req->aliaslen[x];
  258         lwres_buffer_putuint16(b, datalen);
  259         lwres_buffer_putmem(b, (unsigned char *)req->aliases[x],
  260                     datalen);
  261         lwres_buffer_putuint8(b, 0);
  262     }
  263 
  264     /* encode the addresses */
  265     addr = LWRES_LIST_HEAD(req->addrs);
  266     while (addr != NULL) {
  267         lwres_buffer_putuint32(b, addr->family);
  268         lwres_buffer_putuint16(b, addr->length);
  269         lwres_buffer_putmem(b, addr->address, addr->length);
  270         addr = LWRES_LIST_NEXT(addr, link);
  271     }
  272 
  273     INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
  274     INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
  275 
  276     return (LWRES_R_SUCCESS);
  277 }
  278 /*% Uses context ctx to convert the contents of packet pkt to a lwres_gabnrequest_t structure. */
  279 lwres_result_t
  280 lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
  281             lwres_lwpacket_t *pkt, lwres_gabnrequest_t **structp)
  282 {
  283     int ret;
  284     char *name;
  285     lwres_gabnrequest_t *gabn;
  286     uint32_t addrtypes;
  287     uint32_t flags;
  288     uint16_t namelen;
  289 
  290     REQUIRE(ctx != NULL);
  291     REQUIRE(pkt != NULL);
  292     REQUIRE(b != NULL);
  293     REQUIRE(structp != NULL && *structp == NULL);
  294 
  295     if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
  296         return (LWRES_R_FAILURE);
  297 
  298     if (!SPACE_REMAINING(b, 4 + 4))
  299         return (LWRES_R_UNEXPECTEDEND);
  300 
  301     flags = lwres_buffer_getuint32(b);
  302     addrtypes = lwres_buffer_getuint32(b);
  303 
  304     /*
  305      * Pull off the name itself
  306      */
  307     ret = lwres_string_parse(b, &name, &namelen);
  308     if (ret != LWRES_R_SUCCESS)
  309         return (ret);
  310 
  311     if (LWRES_BUFFER_REMAINING(b) != 0)
  312         return (LWRES_R_TRAILINGDATA);
  313 
  314     gabn = CTXMALLOC(sizeof(lwres_gabnrequest_t));
  315     if (gabn == NULL)
  316         return (LWRES_R_NOMEMORY);
  317 
  318     gabn->flags = flags;
  319     gabn->addrtypes = addrtypes;
  320     gabn->name = name;
  321     gabn->namelen = namelen;
  322 
  323     *structp = gabn;
  324     return (LWRES_R_SUCCESS);
  325 }
  326 
  327 /*% Offers the same semantics as lwres_gabnrequest_parse() except it yields a lwres_gabnresponse_t structure. */
  328 
  329 lwres_result_t
  330 lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
  331             lwres_lwpacket_t *pkt, lwres_gabnresponse_t **structp)
  332 {
  333     lwres_result_t ret;
  334     unsigned int x;
  335     uint32_t flags;
  336     uint16_t naliases;
  337     uint16_t naddrs;
  338     lwres_gabnresponse_t *gabn;
  339     lwres_addrlist_t addrlist;
  340     lwres_addr_t *addr;
  341 
  342     REQUIRE(ctx != NULL);
  343     REQUIRE(pkt != NULL);
  344     REQUIRE(b != NULL);
  345     REQUIRE(structp != NULL && *structp == NULL);
  346 
  347     gabn = NULL;
  348 
  349     if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
  350         return (LWRES_R_FAILURE);
  351 
  352     /*
  353      * Pull off the name itself
  354      */
  355     if (!SPACE_REMAINING(b, 4 + 2 + 2))
  356         return (LWRES_R_UNEXPECTEDEND);
  357     flags = lwres_buffer_getuint32(b);
  358     naliases = lwres_buffer_getuint16(b);
  359     naddrs = lwres_buffer_getuint16(b);
  360 
  361     gabn = CTXMALLOC(sizeof(lwres_gabnresponse_t));
  362     if (gabn == NULL)
  363         return (LWRES_R_NOMEMORY);
  364     gabn->aliases = NULL;
  365     gabn->aliaslen = NULL;
  366     LWRES_LIST_INIT(gabn->addrs);
  367     gabn->base = NULL;
  368 
  369     gabn->flags = flags;
  370     gabn->naliases = naliases;
  371     gabn->naddrs = naddrs;
  372 
  373     LWRES_LIST_INIT(addrlist);
  374 
  375     if (naliases > 0) {
  376         gabn->aliases = CTXMALLOC(sizeof(char *) * naliases);
  377         if (gabn->aliases == NULL) {
  378             ret = LWRES_R_NOMEMORY;
  379             goto out;
  380         }
  381 
  382         gabn->aliaslen = CTXMALLOC(sizeof(uint16_t) * naliases);
  383         if (gabn->aliaslen == NULL) {
  384             ret = LWRES_R_NOMEMORY;
  385             goto out;
  386         }
  387     }
  388 
  389     for (x = 0; x < naddrs; x++) {
  390         addr = CTXMALLOC(sizeof(lwres_addr_t));
  391         if (addr == NULL) {
  392             ret = LWRES_R_NOMEMORY;
  393             goto out;
  394         }
  395         LWRES_LINK_INIT(addr, link);
  396         LWRES_LIST_APPEND(addrlist, addr, link);
  397     }
  398 
  399     /*
  400      * Now, pull off the real name.
  401      */
  402     ret = lwres_string_parse(b, &gabn->realname, &gabn->realnamelen);
  403     if (ret != LWRES_R_SUCCESS)
  404         goto out;
  405 
  406     /*
  407      * Parse off the aliases.
  408      */
  409     for (x = 0; x < gabn->naliases; x++) {
  410         ret = lwres_string_parse(b, &gabn->aliases[x],
  411                      &gabn->aliaslen[x]);
  412         if (ret != LWRES_R_SUCCESS)
  413             goto out;
  414     }
  415 
  416     /*
  417      * Pull off the addresses.  We already strung the linked list
  418      * up above.
  419      */
  420     addr = LWRES_LIST_HEAD(addrlist);
  421     for (x = 0; x < gabn->naddrs; x++) {
  422         INSIST(addr != NULL);
  423         ret = lwres_addr_parse(b, addr);
  424         if (ret != LWRES_R_SUCCESS)
  425             goto out;
  426         addr = LWRES_LIST_NEXT(addr, link);
  427     }
  428 
  429     if (LWRES_BUFFER_REMAINING(b) != 0) {
  430         ret = LWRES_R_TRAILINGDATA;
  431         goto out;
  432     }
  433 
  434     gabn->addrs = addrlist;
  435 
  436     *structp = gabn;
  437     return (LWRES_R_SUCCESS);
  438 
  439  out:
  440     if (gabn != NULL) {
  441         if (gabn->aliases != NULL)
  442             CTXFREE(gabn->aliases, sizeof(char *) * naliases);
  443         if (gabn->aliaslen != NULL)
  444             CTXFREE(gabn->aliaslen,
  445                 sizeof(uint16_t) * naliases);
  446         addr = LWRES_LIST_HEAD(addrlist);
  447         while (addr != NULL) {
  448             LWRES_LIST_UNLINK(addrlist, addr, link);
  449             CTXFREE(addr, sizeof(lwres_addr_t));
  450             addr = LWRES_LIST_HEAD(addrlist);
  451         }
  452         CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
  453     }
  454 
  455     return (ret);
  456 }
  457 
  458 /*% Release the memory in resolver context ctx that was allocated to the lwres_gabnrequest_t. */
  459 void
  460 lwres_gabnrequest_free(lwres_context_t *ctx, lwres_gabnrequest_t **structp)
  461 {
  462     lwres_gabnrequest_t *gabn;
  463 
  464     REQUIRE(ctx != NULL);
  465     REQUIRE(structp != NULL && *structp != NULL);
  466 
  467     gabn = *structp;
  468     *structp = NULL;
  469 
  470     CTXFREE(gabn, sizeof(lwres_gabnrequest_t));
  471 }
  472 
  473 /*% Release the memory in resolver context ctx that was allocated to the lwres_gabnresponse_t. */
  474 void
  475 lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp)
  476 {
  477     lwres_gabnresponse_t *gabn;
  478     lwres_addr_t *addr;
  479 
  480     REQUIRE(ctx != NULL);
  481     REQUIRE(structp != NULL && *structp != NULL);
  482 
  483     gabn = *structp;
  484     *structp = NULL;
  485 
  486     if (gabn->naliases > 0) {
  487         CTXFREE(gabn->aliases, sizeof(char *) * gabn->naliases);
  488         CTXFREE(gabn->aliaslen,
  489             sizeof(uint16_t) * gabn->naliases);
  490     }
  491     addr = LWRES_LIST_HEAD(gabn->addrs);
  492     while (addr != NULL) {
  493         LWRES_LIST_UNLINK(gabn->addrs, addr, link);
  494         CTXFREE(addr, sizeof(lwres_addr_t));
  495         addr = LWRES_LIST_HEAD(gabn->addrs);
  496     }
  497     if (gabn->base != NULL)
  498         CTXFREE(gabn->base, gabn->baselen);
  499     CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
  500 }