"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/byaddr.c" (7 Sep 2020, 7758 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 "byaddr.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 
   13 /*! \file */
   14 
   15 #include <config.h>
   16 
   17 #include <stdbool.h>
   18 
   19 #include <isc/mem.h>
   20 #include <isc/netaddr.h>
   21 #include <isc/print.h>
   22 #include <isc/string.h>     /* Required for HP/UX (and others?) */
   23 #include <isc/task.h>
   24 #include <isc/util.h>
   25 
   26 #include <dns/byaddr.h>
   27 #include <dns/db.h>
   28 #include <dns/events.h>
   29 #include <dns/lookup.h>
   30 #include <dns/rdata.h>
   31 #include <dns/rdataset.h>
   32 #include <dns/rdatastruct.h>
   33 #include <dns/resolver.h>
   34 #include <dns/result.h>
   35 #include <dns/view.h>
   36 
   37 /*
   38  * XXXRTH  We could use a static event...
   39  */
   40 
   41 static char hex_digits[] = {
   42     '0', '1', '2', '3', '4', '5', '6', '7',
   43     '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
   44 };
   45 
   46 isc_result_t
   47 dns_byaddr_createptrname(isc_netaddr_t *address, bool nibble,
   48              dns_name_t *name)
   49 {
   50     /*
   51      * We dropped bitstring labels, so all lookups will use nibbles.
   52      */
   53     UNUSED(nibble);
   54 
   55     return (dns_byaddr_createptrname2(address,
   56                       DNS_BYADDROPT_IPV6INT, name));
   57 }
   58 
   59 isc_result_t
   60 dns_byaddr_createptrname2(isc_netaddr_t *address, unsigned int options,
   61               dns_name_t *name)
   62 {
   63     char textname[128];
   64     unsigned char *bytes;
   65     int i;
   66     char *cp;
   67     isc_buffer_t buffer;
   68     unsigned int len;
   69 
   70     REQUIRE(address != NULL);
   71 
   72     /*
   73      * We create the text representation and then convert to a
   74      * dns_name_t.  This is not maximally efficient, but it keeps all
   75      * of the knowledge of wire format in the dns_name_ routines.
   76      */
   77 
   78     bytes = (unsigned char *)(&address->type);
   79     if (address->family == AF_INET) {
   80         (void)snprintf(textname, sizeof(textname),
   81                    "%u.%u.%u.%u.in-addr.arpa.",
   82                    ((unsigned int)bytes[3] & 0xffU),
   83                    ((unsigned int)bytes[2] & 0xffU),
   84                    ((unsigned int)bytes[1] & 0xffU),
   85                    ((unsigned int)bytes[0] & 0xffU));
   86     } else if (address->family == AF_INET6) {
   87         size_t remaining;
   88 
   89         cp = textname;
   90         for (i = 15; i >= 0; i--) {
   91             *cp++ = hex_digits[bytes[i] & 0x0f];
   92             *cp++ = '.';
   93             *cp++ = hex_digits[(bytes[i] >> 4) & 0x0f];
   94             *cp++ = '.';
   95         }
   96         remaining = sizeof(textname) - (cp - textname);
   97         if ((options & DNS_BYADDROPT_IPV6INT) != 0) {
   98             strlcpy(cp, "ip6.int.", remaining);
   99         } else {
  100             strlcpy(cp, "ip6.arpa.", remaining);
  101         }
  102     } else
  103         return (ISC_R_NOTIMPLEMENTED);
  104 
  105     len = (unsigned int)strlen(textname);
  106     isc_buffer_init(&buffer, textname, len);
  107     isc_buffer_add(&buffer, len);
  108     return (dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL));
  109 }
  110 
  111 struct dns_byaddr {
  112     /* Unlocked. */
  113     unsigned int        magic;
  114     isc_mem_t *     mctx;
  115     isc_mutex_t     lock;
  116     dns_fixedname_t     name;
  117     /* Locked by lock. */
  118     unsigned int        options;
  119     dns_lookup_t *      lookup;
  120     isc_task_t *        task;
  121     dns_byaddrevent_t * event;
  122     bool        canceled;
  123 };
  124 
  125 #define BYADDR_MAGIC            ISC_MAGIC('B', 'y', 'A', 'd')
  126 #define VALID_BYADDR(b)         ISC_MAGIC_VALID(b, BYADDR_MAGIC)
  127 
  128 #define MAX_RESTARTS 16
  129 
  130 static inline isc_result_t
  131 copy_ptr_targets(dns_byaddr_t *byaddr, dns_rdataset_t *rdataset) {
  132     isc_result_t result;
  133     dns_name_t *name;
  134     dns_rdata_t rdata = DNS_RDATA_INIT;
  135 
  136     /*
  137      * The caller must be holding the byaddr's lock.
  138      */
  139 
  140     result = dns_rdataset_first(rdataset);
  141     while (result == ISC_R_SUCCESS) {
  142         dns_rdata_ptr_t ptr;
  143         dns_rdataset_current(rdataset, &rdata);
  144         result = dns_rdata_tostruct(&rdata, &ptr, NULL);
  145         if (result != ISC_R_SUCCESS)
  146             return (result);
  147         name = isc_mem_get(byaddr->mctx, sizeof(*name));
  148         if (name == NULL) {
  149             dns_rdata_freestruct(&ptr);
  150             return (ISC_R_NOMEMORY);
  151         }
  152         dns_name_init(name, NULL);
  153         result = dns_name_dup(&ptr.ptr, byaddr->mctx, name);
  154         dns_rdata_freestruct(&ptr);
  155         if (result != ISC_R_SUCCESS) {
  156             isc_mem_put(byaddr->mctx, name, sizeof(*name));
  157             return (ISC_R_NOMEMORY);
  158         }
  159         ISC_LIST_APPEND(byaddr->event->names, name, link);
  160         dns_rdata_reset(&rdata);
  161         result = dns_rdataset_next(rdataset);
  162     }
  163     if (result == ISC_R_NOMORE)
  164         result = ISC_R_SUCCESS;
  165 
  166     return (result);
  167 }
  168 
  169 static void
  170 lookup_done(isc_task_t *task, isc_event_t *event) {
  171     dns_byaddr_t *byaddr = event->ev_arg;
  172     dns_lookupevent_t *levent;
  173     isc_result_t result;
  174 
  175     REQUIRE(event->ev_type == DNS_EVENT_LOOKUPDONE);
  176     REQUIRE(VALID_BYADDR(byaddr));
  177     REQUIRE(byaddr->task == task);
  178 
  179     UNUSED(task);
  180 
  181     levent = (dns_lookupevent_t *)event;
  182 
  183     if (levent->result == ISC_R_SUCCESS) {
  184         result = copy_ptr_targets(byaddr, levent->rdataset);
  185         byaddr->event->result = result;
  186     } else
  187         byaddr->event->result = levent->result;
  188     isc_event_free(&event);
  189     isc_task_sendanddetach(&byaddr->task, (isc_event_t **)&byaddr->event);
  190 }
  191 
  192 static void
  193 bevent_destroy(isc_event_t *event) {
  194     dns_byaddrevent_t *bevent;
  195     dns_name_t *name, *next_name;
  196     isc_mem_t *mctx;
  197 
  198     REQUIRE(event->ev_type == DNS_EVENT_BYADDRDONE);
  199     mctx = event->ev_destroy_arg;
  200     bevent = (dns_byaddrevent_t *)event;
  201 
  202     for (name = ISC_LIST_HEAD(bevent->names);
  203          name != NULL;
  204          name = next_name) {
  205         next_name = ISC_LIST_NEXT(name, link);
  206         ISC_LIST_UNLINK(bevent->names, name, link);
  207         dns_name_free(name, mctx);
  208         isc_mem_put(mctx, name, sizeof(*name));
  209     }
  210     isc_mem_put(mctx, event, event->ev_size);
  211 }
  212 
  213 isc_result_t
  214 dns_byaddr_create(isc_mem_t *mctx, isc_netaddr_t *address, dns_view_t *view,
  215           unsigned int options, isc_task_t *task,
  216           isc_taskaction_t action, void *arg, dns_byaddr_t **byaddrp)
  217 {
  218     isc_result_t result;
  219     dns_byaddr_t *byaddr;
  220     isc_event_t *ievent;
  221 
  222     byaddr = isc_mem_get(mctx, sizeof(*byaddr));
  223     if (byaddr == NULL)
  224         return (ISC_R_NOMEMORY);
  225     byaddr->mctx = NULL;
  226     isc_mem_attach(mctx, &byaddr->mctx);
  227     byaddr->options = options;
  228 
  229     byaddr->event = isc_mem_get(mctx, sizeof(*byaddr->event));
  230     if (byaddr->event == NULL) {
  231         result = ISC_R_NOMEMORY;
  232         goto cleanup_byaddr;
  233     }
  234     ISC_EVENT_INIT(byaddr->event, sizeof(*byaddr->event), 0, NULL,
  235                DNS_EVENT_BYADDRDONE, action, arg, byaddr,
  236                bevent_destroy, mctx);
  237     byaddr->event->result = ISC_R_FAILURE;
  238     ISC_LIST_INIT(byaddr->event->names);
  239 
  240     byaddr->task = NULL;
  241     isc_task_attach(task, &byaddr->task);
  242 
  243     result = isc_mutex_init(&byaddr->lock);
  244     if (result != ISC_R_SUCCESS)
  245         goto cleanup_event;
  246 
  247     dns_fixedname_init(&byaddr->name);
  248 
  249     result = dns_byaddr_createptrname2(address, options,
  250                        dns_fixedname_name(&byaddr->name));
  251     if (result != ISC_R_SUCCESS)
  252         goto cleanup_lock;
  253 
  254     byaddr->lookup = NULL;
  255     result = dns_lookup_create(mctx, dns_fixedname_name(&byaddr->name),
  256                    dns_rdatatype_ptr, view, 0, task,
  257                    lookup_done, byaddr, &byaddr->lookup);
  258     if (result != ISC_R_SUCCESS)
  259         goto cleanup_lock;
  260 
  261     byaddr->canceled = false;
  262     byaddr->magic = BYADDR_MAGIC;
  263 
  264     *byaddrp = byaddr;
  265 
  266     return (ISC_R_SUCCESS);
  267 
  268  cleanup_lock:
  269     DESTROYLOCK(&byaddr->lock);
  270 
  271  cleanup_event:
  272     ievent = (isc_event_t *)byaddr->event;
  273     isc_event_free(&ievent);
  274     byaddr->event = NULL;
  275 
  276     isc_task_detach(&byaddr->task);
  277 
  278  cleanup_byaddr:
  279     isc_mem_putanddetach(&mctx, byaddr, sizeof(*byaddr));
  280 
  281     return (result);
  282 }
  283 
  284 void
  285 dns_byaddr_cancel(dns_byaddr_t *byaddr) {
  286     REQUIRE(VALID_BYADDR(byaddr));
  287 
  288     LOCK(&byaddr->lock);
  289 
  290     if (!byaddr->canceled) {
  291         byaddr->canceled = true;
  292         if (byaddr->lookup != NULL)
  293             dns_lookup_cancel(byaddr->lookup);
  294     }
  295 
  296     UNLOCK(&byaddr->lock);
  297 }
  298 
  299 void
  300 dns_byaddr_destroy(dns_byaddr_t **byaddrp) {
  301     dns_byaddr_t *byaddr;
  302 
  303     REQUIRE(byaddrp != NULL);
  304     byaddr = *byaddrp;
  305     REQUIRE(VALID_BYADDR(byaddr));
  306     REQUIRE(byaddr->event == NULL);
  307     REQUIRE(byaddr->task == NULL);
  308     dns_lookup_destroy(&byaddr->lookup);
  309 
  310     DESTROYLOCK(&byaddr->lock);
  311     byaddr->magic = 0;
  312     isc_mem_putanddetach(&byaddr->mctx, byaddr, sizeof(*byaddr));
  313 
  314     *byaddrp = NULL;
  315 }