"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/dns/ttl.c" (4 Sep 2020, 4826 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


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 "ttl.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 #include <ctype.h>
   15 #include <errno.h>
   16 #include <inttypes.h>
   17 #include <stdbool.h>
   18 #include <stdio.h>
   19 #include <stdlib.h>
   20 
   21 #include <isc/buffer.h>
   22 #include <isc/parseint.h>
   23 #include <isc/print.h>
   24 #include <isc/region.h>
   25 #include <isc/string.h>
   26 #include <isc/util.h>
   27 
   28 #include <dns/result.h>
   29 #include <dns/ttl.h>
   30 
   31 #define RETERR(x)                        \
   32     do {                             \
   33         isc_result_t _r = (x);   \
   34         if (_r != ISC_R_SUCCESS) \
   35             return ((_r));   \
   36     } while (0)
   37 
   38 static isc_result_t
   39 bind_ttl(isc_textregion_t *source, uint32_t *ttl);
   40 
   41 /*
   42  * Helper for dns_ttl_totext().
   43  */
   44 static isc_result_t
   45 ttlfmt(unsigned int t, const char *s, bool verbose, bool space,
   46        isc_buffer_t *target) {
   47     char tmp[60];
   48     unsigned int len;
   49     isc_region_t region;
   50 
   51     if (verbose) {
   52         len = snprintf(tmp, sizeof(tmp), "%s%u %s%s", space ? " " : "",
   53                    t, s, t == 1 ? "" : "s");
   54     } else {
   55         len = snprintf(tmp, sizeof(tmp), "%u%c", t, s[0]);
   56     }
   57 
   58     INSIST(len + 1 <= sizeof(tmp));
   59     isc_buffer_availableregion(target, &region);
   60     if (len > region.length) {
   61         return (ISC_R_NOSPACE);
   62     }
   63     memmove(region.base, tmp, len);
   64     isc_buffer_add(target, len);
   65 
   66     return (ISC_R_SUCCESS);
   67 }
   68 
   69 /*
   70  * Derived from bind8 ns_format_ttl().
   71  */
   72 isc_result_t
   73 dns_ttl_totext(uint32_t src, bool verbose, bool upcase, isc_buffer_t *target) {
   74     unsigned secs, mins, hours, days, weeks, x;
   75 
   76     secs = src % 60;
   77     src /= 60;
   78     mins = src % 60;
   79     src /= 60;
   80     hours = src % 24;
   81     src /= 24;
   82     days = src % 7;
   83     src /= 7;
   84     weeks = src;
   85     src = 0;
   86     POST(src);
   87 
   88     x = 0;
   89     if (weeks != 0) {
   90         RETERR(ttlfmt(weeks, "week", verbose, (x > 0), target));
   91         x++;
   92     }
   93     if (days != 0) {
   94         RETERR(ttlfmt(days, "day", verbose, (x > 0), target));
   95         x++;
   96     }
   97     if (hours != 0) {
   98         RETERR(ttlfmt(hours, "hour", verbose, (x > 0), target));
   99         x++;
  100     }
  101     if (mins != 0) {
  102         RETERR(ttlfmt(mins, "minute", verbose, (x > 0), target));
  103         x++;
  104     }
  105     if (secs != 0 || (weeks == 0 && days == 0 && hours == 0 && mins == 0)) {
  106         RETERR(ttlfmt(secs, "second", verbose, (x > 0), target));
  107         x++;
  108     }
  109     INSIST(x > 0);
  110     /*
  111      * If only a single unit letter is printed, print it
  112      * in upper case. (Why?  Because BIND 8 does that.
  113      * Presumably it has a reason.)
  114      */
  115     if (x == 1 && upcase && !verbose) {
  116         isc_region_t region;
  117         /*
  118          * The unit letter is the last character in the
  119          * used region of the buffer.
  120          *
  121          * toupper() does not need its argument to be masked of cast
  122          * here because region.base is type unsigned char *.
  123          */
  124         isc_buffer_usedregion(target, &region);
  125         region.base[region.length - 1] =
  126             toupper(region.base[region.length - 1]);
  127     }
  128     return (ISC_R_SUCCESS);
  129 }
  130 
  131 isc_result_t
  132 dns_counter_fromtext(isc_textregion_t *source, uint32_t *ttl) {
  133     return (bind_ttl(source, ttl));
  134 }
  135 
  136 isc_result_t
  137 dns_ttl_fromtext(isc_textregion_t *source, uint32_t *ttl) {
  138     isc_result_t result;
  139 
  140     result = bind_ttl(source, ttl);
  141     if (result != ISC_R_SUCCESS && result != ISC_R_RANGE) {
  142         result = DNS_R_BADTTL;
  143     }
  144     return (result);
  145 }
  146 
  147 static isc_result_t
  148 bind_ttl(isc_textregion_t *source, uint32_t *ttl) {
  149     uint64_t tmp = 0ULL;
  150     uint32_t n;
  151     char *s;
  152     char buf[64];
  153     char nbuf[64]; /* Number buffer */
  154 
  155     /*
  156      * Copy the buffer as it may not be NULL terminated.
  157      * No legal counter / ttl is longer that 63 characters.
  158      */
  159     if (source->length > sizeof(buf) - 1) {
  160         return (DNS_R_SYNTAX);
  161     }
  162     /* Copy source->length bytes and NUL terminate. */
  163     snprintf(buf, sizeof(buf), "%.*s", (int)source->length, source->base);
  164     s = buf;
  165 
  166     do {
  167         isc_result_t result;
  168 
  169         char *np = nbuf;
  170         while (*s != '\0' && isdigit((unsigned char)*s)) {
  171             *np++ = *s++;
  172         }
  173         *np++ = '\0';
  174         INSIST(np - nbuf <= (int)sizeof(nbuf));
  175         result = isc_parse_uint32(&n, nbuf, 10);
  176         if (result != ISC_R_SUCCESS) {
  177             return (DNS_R_SYNTAX);
  178         }
  179         switch (*s) {
  180         case 'w':
  181         case 'W':
  182             tmp += (uint64_t)n * 7 * 24 * 3600;
  183             s++;
  184             break;
  185         case 'd':
  186         case 'D':
  187             tmp += (uint64_t)n * 24 * 3600;
  188             s++;
  189             break;
  190         case 'h':
  191         case 'H':
  192             tmp += (uint64_t)n * 3600;
  193             s++;
  194             break;
  195         case 'm':
  196         case 'M':
  197             tmp += (uint64_t)n * 60;
  198             s++;
  199             break;
  200         case 's':
  201         case 'S':
  202             tmp += (uint64_t)n;
  203             s++;
  204             break;
  205         case '\0':
  206             /* Plain number? */
  207             if (tmp != 0ULL) {
  208                 return (DNS_R_SYNTAX);
  209             }
  210             tmp = n;
  211             break;
  212         default:
  213             return (DNS_R_SYNTAX);
  214         }
  215     } while (*s != '\0');
  216 
  217     if (tmp > 0xffffffffULL) {
  218         return (ISC_R_RANGE);
  219     }
  220 
  221     *ttl = (uint32_t)(tmp & 0xffffffffUL);
  222     return (ISC_R_SUCCESS);
  223 }