"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/dns/rcode.c" (4 Sep 2020, 16534 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 "rcode.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 #include <ctype.h>
   13 #include <inttypes.h>
   14 #include <stdbool.h>
   15 #include <stdlib.h>
   16 
   17 #include <isc/buffer.h>
   18 #include <isc/parseint.h>
   19 #include <isc/print.h>
   20 #include <isc/region.h>
   21 #include <isc/result.h>
   22 #include <isc/stdio.h>
   23 #include <isc/string.h>
   24 #include <isc/types.h>
   25 #include <isc/util.h>
   26 
   27 #include <pk11/site.h>
   28 
   29 #include <dns/cert.h>
   30 #include <dns/ds.h>
   31 #include <dns/dsdigest.h>
   32 #include <dns/keyflags.h>
   33 #include <dns/keyvalues.h>
   34 #include <dns/rcode.h>
   35 #include <dns/rdataclass.h>
   36 #include <dns/result.h>
   37 #include <dns/secalg.h>
   38 #include <dns/secproto.h>
   39 
   40 #define RETERR(x)                        \
   41     do {                             \
   42         isc_result_t _r = (x);   \
   43         if (_r != ISC_R_SUCCESS) \
   44             return ((_r));   \
   45     } while (0)
   46 
   47 #define NUMBERSIZE sizeof("037777777777") /* 2^32-1 octal + NUL */
   48 
   49 #define TOTEXTONLY 0x01
   50 
   51 #define RCODENAMES                                     \
   52     /* standard rcodes */                          \
   53     { dns_rcode_noerror, "NOERROR", 0 },           \
   54         { dns_rcode_formerr, "FORMERR", 0 },   \
   55         { dns_rcode_servfail, "SERVFAIL", 0 }, \
   56         { dns_rcode_nxdomain, "NXDOMAIN", 0 }, \
   57         { dns_rcode_notimp, "NOTIMP", 0 },     \
   58         { dns_rcode_refused, "REFUSED", 0 },   \
   59         { dns_rcode_yxdomain, "YXDOMAIN", 0 }, \
   60         { dns_rcode_yxrrset, "YXRRSET", 0 },   \
   61         { dns_rcode_nxrrset, "NXRRSET", 0 },   \
   62         { dns_rcode_notauth, "NOTAUTH", 0 },   \
   63         { dns_rcode_notzone, "NOTZONE", 0 },   \
   64         { 11, "RESERVED11", TOTEXTONLY },      \
   65         { 12, "RESERVED12", TOTEXTONLY },      \
   66         { 13, "RESERVED13", TOTEXTONLY },      \
   67         { 14, "RESERVED14", TOTEXTONLY },      \
   68         { 15, "RESERVED15", TOTEXTONLY },
   69 
   70 #define ERCODENAMES                                        \
   71     /* extended rcodes */                              \
   72     { dns_rcode_badvers, "BADVERS", 0 },               \
   73         { dns_rcode_badcookie, "BADCOOKIE", 0 }, { \
   74         0, NULL, 0                                 \
   75     }
   76 
   77 #define TSIGRCODENAMES                                       \
   78     /* extended rcodes */                                \
   79     { dns_tsigerror_badsig, "BADSIG", 0 },               \
   80         { dns_tsigerror_badkey, "BADKEY", 0 },       \
   81         { dns_tsigerror_badtime, "BADTIME", 0 },     \
   82         { dns_tsigerror_badmode, "BADMODE", 0 },     \
   83         { dns_tsigerror_badname, "BADNAME", 0 },     \
   84         { dns_tsigerror_badalg, "BADALG", 0 },       \
   85         { dns_tsigerror_badtrunc, "BADTRUNC", 0 }, { \
   86         0, NULL, 0                                   \
   87     }
   88 
   89 /* RFC4398 section 2.1 */
   90 
   91 #define CERTNAMES                                                           \
   92     { 1, "PKIX", 0 }, { 2, "SPKI", 0 }, { 3, "PGP", 0 },                \
   93         { 4, "IPKIX", 0 }, { 5, "ISPKI", 0 }, { 6, "IPGP", 0 },     \
   94         { 7, "ACPKIX", 0 }, { 8, "IACPKIX", 0 }, { 253, "URI", 0 }, \
   95         { 254, "OID", 0 }, {                                        \
   96         0, NULL, 0                                                  \
   97     }
   98 
   99 /* RFC2535 section 7, RFC3110 */
  100 
  101 #define SECALGNAMES                                                     \
  102     { DNS_KEYALG_RSAMD5, "RSAMD5", 0 }, { DNS_KEYALG_DH, "DH", 0 }, \
  103         { DNS_KEYALG_DSA, "DSA", 0 },                           \
  104         { DNS_KEYALG_RSASHA1, "RSASHA1", 0 },                   \
  105         { DNS_KEYALG_NSEC3DSA, "NSEC3DSA", 0 },                 \
  106         { DNS_KEYALG_NSEC3RSASHA1, "NSEC3RSASHA1", 0 },         \
  107         { DNS_KEYALG_RSASHA256, "RSASHA256", 0 },               \
  108         { DNS_KEYALG_RSASHA512, "RSASHA512", 0 },               \
  109         { DNS_KEYALG_ECCGOST, "ECCGOST", 0 },                   \
  110         { DNS_KEYALG_ECDSA256, "ECDSAP256SHA256", 0 },          \
  111         { DNS_KEYALG_ECDSA256, "ECDSA256", 0 },                 \
  112         { DNS_KEYALG_ECDSA384, "ECDSAP384SHA384", 0 },          \
  113         { DNS_KEYALG_ECDSA384, "ECDSA384", 0 },                 \
  114         { DNS_KEYALG_ED25519, "ED25519", 0 },                   \
  115         { DNS_KEYALG_ED448, "ED448", 0 },                       \
  116         { DNS_KEYALG_INDIRECT, "INDIRECT", 0 },                 \
  117         { DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 },             \
  118         { DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, {           \
  119         0, NULL, 0                                              \
  120     }
  121 
  122 /* RFC2535 section 7.1 */
  123 
  124 #define SECPROTONAMES                                                       \
  125     { 0, "NONE", 0 }, { 1, "TLS", 0 }, { 2, "EMAIL", 0 },               \
  126         { 3, "DNSSEC", 0 }, { 4, "IPSEC", 0 }, { 255, "ALL", 0 }, { \
  127         0, NULL, 0                                                  \
  128     }
  129 
  130 #define HASHALGNAMES \
  131     { 1, "SHA-1", 0 }, { 0, NULL, 0 }
  132 
  133 /* RFC3658, RFC4509, RFC5933, RFC6605 */
  134 
  135 #define DSDIGESTNAMES                                                        \
  136     { DNS_DSDIGEST_SHA1, "SHA-1", 0 }, { DNS_DSDIGEST_SHA1, "SHA1", 0 }, \
  137         { DNS_DSDIGEST_SHA256, "SHA-256", 0 },                       \
  138         { DNS_DSDIGEST_SHA256, "SHA256", 0 },                        \
  139         { DNS_DSDIGEST_GOST, "GOST", 0 },                            \
  140         { DNS_DSDIGEST_SHA384, "SHA-384", 0 },                       \
  141         { DNS_DSDIGEST_SHA384, "SHA384", 0 }, {                      \
  142         0, NULL, 0                                                   \
  143     }
  144 
  145 struct tbl {
  146     unsigned int value;
  147     const char *name;
  148     int flags;
  149 };
  150 
  151 static struct tbl rcodes[] = { RCODENAMES ERCODENAMES };
  152 static struct tbl tsigrcodes[] = { RCODENAMES TSIGRCODENAMES };
  153 static struct tbl certs[] = { CERTNAMES };
  154 static struct tbl secalgs[] = { SECALGNAMES };
  155 static struct tbl secprotos[] = { SECPROTONAMES };
  156 static struct tbl hashalgs[] = { HASHALGNAMES };
  157 static struct tbl dsdigests[] = { DSDIGESTNAMES };
  158 
  159 static struct keyflag {
  160     const char *name;
  161     unsigned int value;
  162     unsigned int mask;
  163 } keyflags[] = { { "NOCONF", 0x4000, 0xC000 },
  164          { "NOAUTH", 0x8000, 0xC000 },
  165          { "NOKEY", 0xC000, 0xC000 },
  166          { "FLAG2", 0x2000, 0x2000 },
  167          { "EXTEND", 0x1000, 0x1000 },
  168          { "FLAG4", 0x0800, 0x0800 },
  169          { "FLAG5", 0x0400, 0x0400 },
  170          { "USER", 0x0000, 0x0300 },
  171          { "ZONE", 0x0100, 0x0300 },
  172          { "HOST", 0x0200, 0x0300 },
  173          { "NTYP3", 0x0300, 0x0300 },
  174          { "FLAG8", 0x0080, 0x0080 },
  175          { "FLAG9", 0x0040, 0x0040 },
  176          { "FLAG10", 0x0020, 0x0020 },
  177          { "FLAG11", 0x0010, 0x0010 },
  178          { "SIG0", 0x0000, 0x000F },
  179          { "SIG1", 0x0001, 0x000F },
  180          { "SIG2", 0x0002, 0x000F },
  181          { "SIG3", 0x0003, 0x000F },
  182          { "SIG4", 0x0004, 0x000F },
  183          { "SIG5", 0x0005, 0x000F },
  184          { "SIG6", 0x0006, 0x000F },
  185          { "SIG7", 0x0007, 0x000F },
  186          { "SIG8", 0x0008, 0x000F },
  187          { "SIG9", 0x0009, 0x000F },
  188          { "SIG10", 0x000A, 0x000F },
  189          { "SIG11", 0x000B, 0x000F },
  190          { "SIG12", 0x000C, 0x000F },
  191          { "SIG13", 0x000D, 0x000F },
  192          { "SIG14", 0x000E, 0x000F },
  193          { "SIG15", 0x000F, 0x000F },
  194          { "KSK", DNS_KEYFLAG_KSK, DNS_KEYFLAG_KSK },
  195          { NULL, 0, 0 } };
  196 
  197 static isc_result_t
  198 str_totext(const char *source, isc_buffer_t *target) {
  199     unsigned int l;
  200     isc_region_t region;
  201 
  202     isc_buffer_availableregion(target, &region);
  203     l = strlen(source);
  204 
  205     if (l > region.length) {
  206         return (ISC_R_NOSPACE);
  207     }
  208 
  209     memmove(region.base, source, l);
  210     isc_buffer_add(target, l);
  211     return (ISC_R_SUCCESS);
  212 }
  213 
  214 static isc_result_t
  215 maybe_numeric(unsigned int *valuep, isc_textregion_t *source, unsigned int max,
  216           bool hex_allowed) {
  217     isc_result_t result;
  218     uint32_t n;
  219     char buffer[NUMBERSIZE];
  220     int v;
  221 
  222     if (!isdigit(source->base[0] & 0xff) || source->length > NUMBERSIZE - 1)
  223     {
  224         return (ISC_R_BADNUMBER);
  225     }
  226 
  227     /*
  228      * We have a potential number.  Try to parse it with
  229      * isc_parse_uint32().  isc_parse_uint32() requires
  230      * null termination, so we must make a copy.
  231      */
  232     v = snprintf(buffer, sizeof(buffer), "%.*s", (int)source->length,
  233              source->base);
  234     if (v < 0 || (unsigned)v != source->length) {
  235         return (ISC_R_BADNUMBER);
  236     }
  237     INSIST(buffer[source->length] == '\0');
  238 
  239     result = isc_parse_uint32(&n, buffer, 10);
  240     if (result == ISC_R_BADNUMBER && hex_allowed) {
  241         result = isc_parse_uint32(&n, buffer, 16);
  242     }
  243     if (result != ISC_R_SUCCESS) {
  244         return (result);
  245     }
  246     if (n > max) {
  247         return (ISC_R_RANGE);
  248     }
  249     *valuep = n;
  250     return (ISC_R_SUCCESS);
  251 }
  252 
  253 static isc_result_t
  254 dns_mnemonic_fromtext(unsigned int *valuep, isc_textregion_t *source,
  255               struct tbl *table, unsigned int max) {
  256     isc_result_t result;
  257     int i;
  258 
  259     result = maybe_numeric(valuep, source, max, false);
  260     if (result != ISC_R_BADNUMBER) {
  261         return (result);
  262     }
  263 
  264     for (i = 0; table[i].name != NULL; i++) {
  265         unsigned int n;
  266         n = strlen(table[i].name);
  267         if (n == source->length && (table[i].flags & TOTEXTONLY) == 0 &&
  268             strncasecmp(source->base, table[i].name, n) == 0)
  269         {
  270             *valuep = table[i].value;
  271             return (ISC_R_SUCCESS);
  272         }
  273     }
  274     return (DNS_R_UNKNOWN);
  275 }
  276 
  277 static isc_result_t
  278 dns_mnemonic_totext(unsigned int value, isc_buffer_t *target,
  279             struct tbl *table) {
  280     int i = 0;
  281     char buf[sizeof("4294967296")];
  282     while (table[i].name != NULL) {
  283         if (table[i].value == value) {
  284             return (str_totext(table[i].name, target));
  285         }
  286         i++;
  287     }
  288     snprintf(buf, sizeof(buf), "%u", value);
  289     return (str_totext(buf, target));
  290 }
  291 
  292 isc_result_t
  293 dns_rcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
  294     unsigned int value;
  295     RETERR(dns_mnemonic_fromtext(&value, source, rcodes, 0xffff));
  296     *rcodep = value;
  297     return (ISC_R_SUCCESS);
  298 }
  299 
  300 isc_result_t
  301 dns_rcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
  302     return (dns_mnemonic_totext(rcode, target, rcodes));
  303 }
  304 
  305 isc_result_t
  306 dns_tsigrcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
  307     unsigned int value;
  308     RETERR(dns_mnemonic_fromtext(&value, source, tsigrcodes, 0xffff));
  309     *rcodep = value;
  310     return (ISC_R_SUCCESS);
  311 }
  312 
  313 isc_result_t
  314 dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
  315     return (dns_mnemonic_totext(rcode, target, tsigrcodes));
  316 }
  317 
  318 isc_result_t
  319 dns_cert_fromtext(dns_cert_t *certp, isc_textregion_t *source) {
  320     unsigned int value;
  321     RETERR(dns_mnemonic_fromtext(&value, source, certs, 0xffff));
  322     *certp = value;
  323     return (ISC_R_SUCCESS);
  324 }
  325 
  326 isc_result_t
  327 dns_cert_totext(dns_cert_t cert, isc_buffer_t *target) {
  328     return (dns_mnemonic_totext(cert, target, certs));
  329 }
  330 
  331 isc_result_t
  332 dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) {
  333     unsigned int value;
  334     RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff));
  335     *secalgp = value;
  336     return (ISC_R_SUCCESS);
  337 }
  338 
  339 isc_result_t
  340 dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) {
  341     return (dns_mnemonic_totext(secalg, target, secalgs));
  342 }
  343 
  344 void
  345 dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) {
  346     isc_buffer_t b;
  347     isc_region_t r;
  348     isc_result_t result;
  349 
  350     REQUIRE(cp != NULL && size > 0);
  351     isc_buffer_init(&b, cp, size - 1);
  352     result = dns_secalg_totext(alg, &b);
  353     isc_buffer_usedregion(&b, &r);
  354     r.base[r.length] = 0;
  355     if (result != ISC_R_SUCCESS) {
  356         r.base[0] = 0;
  357     }
  358 }
  359 
  360 isc_result_t
  361 dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) {
  362     unsigned int value;
  363     RETERR(dns_mnemonic_fromtext(&value, source, secprotos, 0xff));
  364     *secprotop = value;
  365     return (ISC_R_SUCCESS);
  366 }
  367 
  368 isc_result_t
  369 dns_secproto_totext(dns_secproto_t secproto, isc_buffer_t *target) {
  370     return (dns_mnemonic_totext(secproto, target, secprotos));
  371 }
  372 
  373 isc_result_t
  374 dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source) {
  375     unsigned int value;
  376     RETERR(dns_mnemonic_fromtext(&value, source, hashalgs, 0xff));
  377     *hashalg = value;
  378     return (ISC_R_SUCCESS);
  379 }
  380 
  381 isc_result_t
  382 dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source) {
  383     isc_result_t result;
  384     char *text, *end;
  385     unsigned int value = 0;
  386 #ifdef notyet
  387     unsigned int mask = 0;
  388 #endif /* ifdef notyet */
  389 
  390     result = maybe_numeric(&value, source, 0xffff, true);
  391     if (result == ISC_R_SUCCESS) {
  392         *flagsp = value;
  393         return (ISC_R_SUCCESS);
  394     }
  395     if (result != ISC_R_BADNUMBER) {
  396         return (result);
  397     }
  398 
  399     text = source->base;
  400     end = source->base + source->length;
  401 
  402     while (text < end) {
  403         struct keyflag *p;
  404         unsigned int len;
  405         char *delim = memchr(text, '|', end - text);
  406         if (delim != NULL) {
  407             len = (unsigned int)(delim - text);
  408         } else {
  409             len = (unsigned int)(end - text);
  410         }
  411         for (p = keyflags; p->name != NULL; p++) {
  412             if (strncasecmp(p->name, text, len) == 0) {
  413                 break;
  414             }
  415         }
  416         if (p->name == NULL) {
  417             return (DNS_R_UNKNOWNFLAG);
  418         }
  419         value |= p->value;
  420 #ifdef notyet
  421         if ((mask & p->mask) != 0) {
  422             warn("overlapping key flags");
  423         }
  424         mask |= p->mask;
  425 #endif /* ifdef notyet */
  426         text += len;
  427         if (delim != NULL) {
  428             text++; /* Skip "|" */
  429         }
  430     }
  431     *flagsp = value;
  432     return (ISC_R_SUCCESS);
  433 }
  434 
  435 isc_result_t
  436 dns_dsdigest_fromtext(dns_dsdigest_t *dsdigestp, isc_textregion_t *source) {
  437     unsigned int value;
  438     RETERR(dns_mnemonic_fromtext(&value, source, dsdigests, 0xff));
  439     *dsdigestp = value;
  440     return (ISC_R_SUCCESS);
  441 }
  442 
  443 isc_result_t
  444 dns_dsdigest_totext(dns_dsdigest_t dsdigest, isc_buffer_t *target) {
  445     return (dns_mnemonic_totext(dsdigest, target, dsdigests));
  446 }
  447 
  448 void
  449 dns_dsdigest_format(dns_dsdigest_t typ, char *cp, unsigned int size) {
  450     isc_buffer_t b;
  451     isc_region_t r;
  452     isc_result_t result;
  453 
  454     REQUIRE(cp != NULL && size > 0);
  455     isc_buffer_init(&b, cp, size - 1);
  456     result = dns_dsdigest_totext(typ, &b);
  457     isc_buffer_usedregion(&b, &r);
  458     r.base[r.length] = 0;
  459     if (result != ISC_R_SUCCESS) {
  460         r.base[0] = 0;
  461     }
  462 }
  463 
  464 /*
  465  * This uses lots of hard coded values, but how often do we actually
  466  * add classes?
  467  */
  468 isc_result_t
  469 dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) {
  470 #define COMPARE(string, rdclass)                                      \
  471     if (((sizeof(string) - 1) == source->length) &&               \
  472         (strncasecmp(source->base, string, source->length) == 0)) \
  473     {                                                             \
  474         *classp = rdclass;                                    \
  475         return (ISC_R_SUCCESS);                               \
  476     }
  477 
  478     switch (tolower((unsigned char)source->base[0])) {
  479     case 'a':
  480         COMPARE("any", dns_rdataclass_any);
  481         break;
  482     case 'c':
  483         /*
  484          * RFC1035 says the mnemonic for the CHAOS class is CH,
  485          * but historical BIND practice is to call it CHAOS.
  486          * We will accept both forms, but only generate CH.
  487          */
  488         COMPARE("ch", dns_rdataclass_chaos);
  489         COMPARE("chaos", dns_rdataclass_chaos);
  490 
  491         if (source->length > 5 &&
  492             source->length < (5 + sizeof("65000")) &&
  493             strncasecmp("class", source->base, 5) == 0)
  494         {
  495             char buf[sizeof("65000")];
  496             char *endp;
  497             unsigned int val;
  498 
  499             /*
  500              * source->base is not required to be NUL terminated.
  501              * Copy up to remaining bytes and NUL terminate.
  502              */
  503             snprintf(buf, sizeof(buf), "%.*s",
  504                  (int)(source->length - 5), source->base + 5);
  505             val = strtoul(buf, &endp, 10);
  506             if (*endp == '\0' && val <= 0xffff) {
  507                 *classp = (dns_rdataclass_t)val;
  508                 return (ISC_R_SUCCESS);
  509             }
  510         }
  511         break;
  512     case 'h':
  513         COMPARE("hs", dns_rdataclass_hs);
  514         COMPARE("hesiod", dns_rdataclass_hs);
  515         break;
  516     case 'i':
  517         COMPARE("in", dns_rdataclass_in);
  518         break;
  519     case 'n':
  520         COMPARE("none", dns_rdataclass_none);
  521         break;
  522     case 'r':
  523         COMPARE("reserved0", dns_rdataclass_reserved0);
  524         break;
  525     }
  526 
  527 #undef COMPARE
  528 
  529     return (DNS_R_UNKNOWN);
  530 }
  531 
  532 isc_result_t
  533 dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
  534     switch (rdclass) {
  535     case dns_rdataclass_any:
  536         return (str_totext("ANY", target));
  537     case dns_rdataclass_chaos:
  538         return (str_totext("CH", target));
  539     case dns_rdataclass_hs:
  540         return (str_totext("HS", target));
  541     case dns_rdataclass_in:
  542         return (str_totext("IN", target));
  543     case dns_rdataclass_none:
  544         return (str_totext("NONE", target));
  545     case dns_rdataclass_reserved0:
  546         return (str_totext("RESERVED0", target));
  547     default:
  548         return (dns_rdataclass_tounknowntext(rdclass, target));
  549     }
  550 }
  551 
  552 isc_result_t
  553 dns_rdataclass_tounknowntext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
  554     char buf[sizeof("CLASS65535")];
  555 
  556     snprintf(buf, sizeof(buf), "CLASS%u", rdclass);
  557     return (str_totext(buf, target));
  558 }
  559 
  560 void
  561 dns_rdataclass_format(dns_rdataclass_t rdclass, char *array,
  562               unsigned int size) {
  563     isc_result_t result;
  564     isc_buffer_t buf;
  565 
  566     if (size == 0U) {
  567         return;
  568     }
  569 
  570     isc_buffer_init(&buf, array, size);
  571     result = dns_rdataclass_totext(rdclass, &buf);
  572     /*
  573      * Null terminate.
  574      */
  575     if (result == ISC_R_SUCCESS) {
  576         if (isc_buffer_availablelength(&buf) >= 1) {
  577             isc_buffer_putuint8(&buf, 0);
  578         } else {
  579             result = ISC_R_NOSPACE;
  580         }
  581     }
  582     if (result != ISC_R_SUCCESS) {
  583         strlcpy(array, "<unknown>", size);
  584     }
  585 }