[BACK]Return to res_debug.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / resolv

Annotation of src/lib/libc/resolv/res_debug.c, Revision 1.4

1.4     ! christos    1: /*     $NetBSD: res_debug.c,v 1.3 2004/05/20 19:31:52 christos Exp $   */
1.1       christos    2:
                      3: /*
                      4:  * Copyright (c) 1985
                      5:  *    The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: /*
                     37:  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
                     38:  *
                     39:  * Permission to use, copy, modify, and distribute this software for any
                     40:  * purpose with or without fee is hereby granted, provided that the above
                     41:  * copyright notice and this permission notice appear in all copies, and that
                     42:  * the name of Digital Equipment Corporation not be used in advertising or
                     43:  * publicity pertaining to distribution of the document or software without
                     44:  * specific, written prior permission.
                     45:  *
                     46:  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
                     47:  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
                     48:  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
                     49:  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     50:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     51:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
                     52:  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     53:  * SOFTWARE.
                     54:  */
                     55:
                     56: /*
                     57:  * Portions Copyright (c) 1995 by International Business Machines, Inc.
                     58:  *
                     59:  * International Business Machines, Inc. (hereinafter called IBM) grants
                     60:  * permission under its copyrights to use, copy, modify, and distribute this
                     61:  * Software with or without fee, provided that the above copyright notice and
                     62:  * all paragraphs of this notice appear in all copies, and that the name of IBM
                     63:  * not be used in connection with the marketing of any product incorporating
                     64:  * the Software or modifications thereof, without specific, written prior
                     65:  * permission.
                     66:  *
                     67:  * To the extent it has a right to do so, IBM grants an immunity from suit
                     68:  * under its patents, if any, for the use, sale or manufacture of products to
                     69:  * the extent that such products are used for performing Domain Name System
                     70:  * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
                     71:  * granted for any product per se or for any other function of any product.
                     72:  *
                     73:  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
                     74:  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
                     75:  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
                     76:  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
                     77:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
                     78:  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
                     79:  */
                     80:
                     81: /*
                     82:  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
                     83:  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
                     84:  *
                     85:  * Permission to use, copy, modify, and distribute this software for any
                     86:  * purpose with or without fee is hereby granted, provided that the above
                     87:  * copyright notice and this permission notice appear in all copies.
                     88:  *
                     89:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     90:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     91:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     92:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     93:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     94:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     95:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     96:  */
                     97:
1.4     ! christos   98: #include <sys/cdefs.h>
1.1       christos   99: #if defined(LIBC_SCCS) && !defined(lint)
1.4     ! christos  100: #ifdef notdef
1.1       christos  101: static const char sccsid[] = "@(#)res_debug.c  8.1 (Berkeley) 6/4/93";
                    102: static const char rcsid[] = "Id: res_debug.c,v 1.3.2.5.4.4 2004/04/13 06:53:20 marka Exp";
1.4     ! christos  103: #else
        !           104: __RCSID("$NetBSD$");
        !           105: #endif
1.1       christos  106: #endif /* LIBC_SCCS and not lint */
                    107:
                    108: #include "port_before.h"
                    109:
                    110: #include <sys/types.h>
                    111: #include <sys/param.h>
                    112: #include <sys/socket.h>
                    113:
                    114: #include <netinet/in.h>
                    115: #include <arpa/inet.h>
                    116: #include <arpa/nameser.h>
                    117:
                    118: #include <ctype.h>
                    119: #include <errno.h>
                    120: #include <math.h>
                    121: #include <netdb.h>
                    122: #include <resolv.h>
                    123: #include <stdio.h>
                    124: #include <stdlib.h>
                    125: #include <string.h>
                    126: #include <time.h>
                    127:
                    128: #include "port_after.h"
                    129:
                    130: #ifdef SPRINTF_CHAR
                    131: # define SPRINTF(x) strlen(sprintf/**/x)
                    132: #else
                    133: # define SPRINTF(x) sprintf x
                    134: #endif
                    135:
1.2       christos  136: static const char *precsize_ntoa(u_int32_t);
                    137:
1.1       christos  138: extern const char *_res_opcodes[];
                    139: extern const char *_res_sectioncodes[];
                    140:
                    141: /*
                    142:  * Print the current options.
                    143:  */
                    144: void
                    145: fp_resstat(const res_state statp, FILE *file) {
                    146:        u_long mask;
                    147:
                    148:        fprintf(file, ";; res options:");
                    149:        for (mask = 1;  mask != 0U;  mask <<= 1)
                    150:                if (statp->options & mask)
                    151:                        fprintf(file, " %s", p_option(mask));
                    152:        putc('\n', file);
                    153: }
                    154:
                    155: static void
                    156: do_section(const res_state statp,
                    157:           ns_msg *handle, ns_sect section,
                    158:           int pflag, FILE *file)
                    159: {
                    160:        int n, sflag, rrnum;
                    161:        static int buflen = 2048;
                    162:        char *buf;
                    163:        ns_opcode opcode;
                    164:        ns_rr rr;
                    165:
                    166:        /*
                    167:         * Print answer records.
                    168:         */
                    169:        sflag = (statp->pfcode & pflag);
                    170:        if (statp->pfcode && !sflag)
                    171:                return;
                    172:
1.2       christos  173:        buf = malloc((size_t)buflen);
1.1       christos  174:        if (buf == NULL) {
                    175:                fprintf(file, ";; memory allocation failure\n");
                    176:                return;
                    177:        }
                    178:
                    179:        opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
                    180:        rrnum = 0;
                    181:        for (;;) {
                    182:                if (ns_parserr(handle, section, rrnum, &rr)) {
                    183:                        if (errno != ENODEV)
                    184:                                fprintf(file, ";; ns_parserr: %s\n",
                    185:                                        strerror(errno));
                    186:                        else if (rrnum > 0 && sflag != 0 &&
                    187:                                 (statp->pfcode & RES_PRF_HEAD1))
                    188:                                putc('\n', file);
                    189:                        goto cleanup;
                    190:                }
                    191:                if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
                    192:                        fprintf(file, ";; %s SECTION:\n",
                    193:                                p_section(section, opcode));
                    194:                if (section == ns_s_qd)
                    195:                        fprintf(file, ";;\t%s, type = %s, class = %s\n",
                    196:                                ns_rr_name(rr),
                    197:                                p_type(ns_rr_type(rr)),
                    198:                                p_class(ns_rr_class(rr)));
                    199:                else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
                    200:                        u_int32_t ttl = ns_rr_ttl(rr);
                    201:                        fprintf(file,
                    202:                                "; EDNS: version: %u, udp=%u, flags=%04x\n",
                    203:                                (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
                    204:                } else {
                    205:                        n = ns_sprintrr(handle, &rr, NULL, NULL,
1.2       christos  206:                                        buf, (u_int)buflen);
1.1       christos  207:                        if (n < 0) {
                    208:                                if (errno == ENOSPC) {
                    209:                                        free(buf);
                    210:                                        buf = NULL;
                    211:                                        if (buflen < 131072)
1.2       christos  212:                                                buf = malloc((size_t)(buflen += 1024));
1.1       christos  213:                                        if (buf == NULL) {
                    214:                                                fprintf(file,
                    215:                                              ";; memory allocation failure\n");
                    216:                                              return;
                    217:                                        }
                    218:                                        continue;
                    219:                                }
                    220:                                fprintf(file, ";; ns_sprintrr: %s\n",
                    221:                                        strerror(errno));
                    222:                                goto cleanup;
                    223:                        }
                    224:                        fputs(buf, file);
                    225:                        fputc('\n', file);
                    226:                }
                    227:                rrnum++;
                    228:        }
                    229:  cleanup:
                    230:        if (buf != NULL)
                    231:                free(buf);
                    232: }
                    233:
                    234: /*
                    235:  * Print the contents of a query.
                    236:  * This is intended to be primarily a debugging routine.
                    237:  */
                    238: void
                    239: res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
                    240:        ns_msg handle;
                    241:        int qdcount, ancount, nscount, arcount;
                    242:        u_int opcode, rcode, id;
                    243:
                    244:        if (ns_initparse(msg, len, &handle) < 0) {
                    245:                fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
                    246:                return;
                    247:        }
                    248:        opcode = ns_msg_getflag(handle, ns_f_opcode);
                    249:        rcode = ns_msg_getflag(handle, ns_f_rcode);
                    250:        id = ns_msg_id(handle);
                    251:        qdcount = ns_msg_count(handle, ns_s_qd);
                    252:        ancount = ns_msg_count(handle, ns_s_an);
                    253:        nscount = ns_msg_count(handle, ns_s_ns);
                    254:        arcount = ns_msg_count(handle, ns_s_ar);
                    255:
                    256:        /*
                    257:         * Print header fields.
                    258:         */
                    259:        if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
                    260:                fprintf(file,
                    261:                        ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
1.2       christos  262:                        _res_opcodes[opcode], p_rcode((int)rcode), id);
1.1       christos  263:        if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
                    264:                putc(';', file);
                    265:        if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
                    266:                fprintf(file, "; flags:");
                    267:                if (ns_msg_getflag(handle, ns_f_qr))
                    268:                        fprintf(file, " qr");
                    269:                if (ns_msg_getflag(handle, ns_f_aa))
                    270:                        fprintf(file, " aa");
                    271:                if (ns_msg_getflag(handle, ns_f_tc))
                    272:                        fprintf(file, " tc");
                    273:                if (ns_msg_getflag(handle, ns_f_rd))
                    274:                        fprintf(file, " rd");
                    275:                if (ns_msg_getflag(handle, ns_f_ra))
                    276:                        fprintf(file, " ra");
                    277:                if (ns_msg_getflag(handle, ns_f_z))
                    278:                        fprintf(file, " ??");
                    279:                if (ns_msg_getflag(handle, ns_f_ad))
                    280:                        fprintf(file, " ad");
                    281:                if (ns_msg_getflag(handle, ns_f_cd))
                    282:                        fprintf(file, " cd");
                    283:        }
                    284:        if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
                    285:                fprintf(file, "; %s: %d",
1.2       christos  286:                        p_section(ns_s_qd, (int)opcode), qdcount);
1.1       christos  287:                fprintf(file, ", %s: %d",
1.2       christos  288:                        p_section(ns_s_an, (int)opcode), ancount);
1.1       christos  289:                fprintf(file, ", %s: %d",
1.2       christos  290:                        p_section(ns_s_ns, (int)opcode), nscount);
1.1       christos  291:                fprintf(file, ", %s: %d",
1.2       christos  292:                        p_section(ns_s_ar, (int)opcode), arcount);
1.1       christos  293:        }
                    294:        if ((!statp->pfcode) || (statp->pfcode &
                    295:                (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
                    296:                putc('\n',file);
                    297:        }
                    298:        /*
                    299:         * Print the various sections.
                    300:         */
                    301:        do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
                    302:        do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
                    303:        do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
                    304:        do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
                    305:        if (qdcount == 0 && ancount == 0 &&
                    306:            nscount == 0 && arcount == 0)
                    307:                putc('\n', file);
                    308: }
                    309:
                    310: const u_char *
                    311: p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
                    312:        char name[MAXDNAME];
                    313:        int n;
                    314:
                    315:        if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
                    316:                return (NULL);
                    317:        if (name[0] == '\0')
                    318:                putc('.', file);
                    319:        else
                    320:                fputs(name, file);
                    321:        return (cp + n);
                    322: }
                    323:
                    324: const u_char *
                    325: p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
                    326:        return (p_cdnname(cp, msg, PACKETSZ, file));
                    327: }
                    328:
                    329: /* Return a fully-qualified domain name from a compressed name (with
                    330:    length supplied).  */
                    331:
                    332: const u_char *
                    333: p_fqnname(cp, msg, msglen, name, namelen)
                    334:        const u_char *cp, *msg;
                    335:        int msglen;
                    336:        char *name;
                    337:        int namelen;
                    338: {
                    339:        int n, newlen;
                    340:
                    341:        if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
                    342:                return (NULL);
                    343:        newlen = strlen(name);
                    344:        if (newlen == 0 || name[newlen - 1] != '.') {
                    345:                if (newlen + 1 >= namelen)      /* Lack space for final dot */
                    346:                        return (NULL);
                    347:                else
                    348:                        strcpy(name + newlen, ".");
                    349:        }
                    350:        return (cp + n);
                    351: }
                    352:
                    353: /* XXX:        the rest of these functions need to become length-limited, too. */
                    354:
                    355: const u_char *
                    356: p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
                    357:        char name[MAXDNAME];
                    358:        const u_char *n;
                    359:
                    360:        n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
                    361:        if (n == NULL)
                    362:                return (NULL);
                    363:        fputs(name, file);
                    364:        return (n);
                    365: }
                    366:
                    367: /*
                    368:  * Names of RR classes and qclasses.  Classes and qclasses are the same, except
                    369:  * that C_ANY is a qclass but not a class.  (You can ask for records of class
                    370:  * C_ANY, but you can't have any records of that class in the database.)
                    371:  */
                    372: const struct res_sym __p_class_syms[] = {
                    373:        {C_IN,          "IN",           (char *)0},
                    374:        {C_CHAOS,       "CH",           (char *)0},
                    375:        {C_CHAOS,       "CHAOS",        (char *)0},
                    376:        {C_HS,          "HS",           (char *)0},
                    377:        {C_HS,          "HESIOD",       (char *)0},
                    378:        {C_ANY,         "ANY",          (char *)0},
                    379:        {C_NONE,        "NONE",         (char *)0},
                    380:        {C_IN,          (char *)0,      (char *)0}
                    381: };
                    382:
                    383: /*
                    384:  * Names of message sections.
                    385:  */
                    386: const struct res_sym __p_default_section_syms[] = {
                    387:        {ns_s_qd,       "QUERY",        (char *)0},
                    388:        {ns_s_an,       "ANSWER",       (char *)0},
                    389:        {ns_s_ns,       "AUTHORITY",    (char *)0},
                    390:        {ns_s_ar,       "ADDITIONAL",   (char *)0},
                    391:        {0,             (char *)0,      (char *)0}
                    392: };
                    393:
                    394: const struct res_sym __p_update_section_syms[] = {
                    395:        {S_ZONE,        "ZONE",         (char *)0},
                    396:        {S_PREREQ,      "PREREQUISITE", (char *)0},
                    397:        {S_UPDATE,      "UPDATE",       (char *)0},
                    398:        {S_ADDT,        "ADDITIONAL",   (char *)0},
                    399:        {0,             (char *)0,      (char *)0}
                    400: };
                    401:
                    402: const struct res_sym __p_key_syms[] = {
                    403:        {NS_ALG_MD5RSA,         "RSA",          "RSA KEY with MD5 hash"},
                    404:        {NS_ALG_DH,             "DH",           "Diffie Hellman"},
                    405:        {NS_ALG_DSA,            "DSA",          "Digital Signature Algorithm"},
                    406:        {NS_ALG_EXPIRE_ONLY,    "EXPIREONLY",   "No algorithm"},
                    407:        {NS_ALG_PRIVATE_OID,    "PRIVATE",      "Algorithm obtained from OID"},
                    408:        {0,                     NULL,           NULL}
                    409: };
                    410:
                    411: const struct res_sym __p_cert_syms[] = {
                    412:        {cert_t_pkix,   "PKIX",         "PKIX (X.509v3) Certificate"},
                    413:        {cert_t_spki,   "SPKI",         "SPKI certificate"},
                    414:        {cert_t_pgp,    "PGP",          "PGP certificate"},
                    415:        {cert_t_url,    "URL",          "URL Private"},
                    416:        {cert_t_oid,    "OID",          "OID Private"},
                    417:        {0,             NULL,           NULL}
                    418: };
                    419:
                    420: /*
                    421:  * Names of RR types and qtypes.  Types and qtypes are the same, except
                    422:  * that T_ANY is a qtype but not a type.  (You can ask for records of type
                    423:  * T_ANY, but you can't have any records of that type in the database.)
                    424:  */
                    425: const struct res_sym __p_type_syms[] = {
                    426:        {ns_t_a,        "A",            "address"},
                    427:        {ns_t_ns,       "NS",           "name server"},
                    428:        {ns_t_md,       "MD",           "mail destination (deprecated)"},
                    429:        {ns_t_mf,       "MF",           "mail forwarder (deprecated)"},
                    430:        {ns_t_cname,    "CNAME",        "canonical name"},
                    431:        {ns_t_soa,      "SOA",          "start of authority"},
                    432:        {ns_t_mb,       "MB",           "mailbox"},
                    433:        {ns_t_mg,       "MG",           "mail group member"},
                    434:        {ns_t_mr,       "MR",           "mail rename"},
                    435:        {ns_t_null,     "NULL",         "null"},
                    436:        {ns_t_wks,      "WKS",          "well-known service (deprecated)"},
                    437:        {ns_t_ptr,      "PTR",          "domain name pointer"},
                    438:        {ns_t_hinfo,    "HINFO",        "host information"},
                    439:        {ns_t_minfo,    "MINFO",        "mailbox information"},
                    440:        {ns_t_mx,       "MX",           "mail exchanger"},
                    441:        {ns_t_txt,      "TXT",          "text"},
                    442:        {ns_t_rp,       "RP",           "responsible person"},
                    443:        {ns_t_afsdb,    "AFSDB",        "DCE or AFS server"},
                    444:        {ns_t_x25,      "X25",          "X25 address"},
                    445:        {ns_t_isdn,     "ISDN",         "ISDN address"},
                    446:        {ns_t_rt,       "RT",           "router"},
                    447:        {ns_t_nsap,     "NSAP",         "nsap address"},
                    448:        {ns_t_nsap_ptr, "NSAP_PTR",     "domain name pointer"},
                    449:        {ns_t_sig,      "SIG",          "signature"},
                    450:        {ns_t_key,      "KEY",          "key"},
                    451:        {ns_t_px,       "PX",           "mapping information"},
                    452:        {ns_t_gpos,     "GPOS",         "geographical position (withdrawn)"},
                    453:        {ns_t_aaaa,     "AAAA",         "IPv6 address"},
                    454:        {ns_t_loc,      "LOC",          "location"},
                    455:        {ns_t_nxt,      "NXT",          "next valid name (unimplemented)"},
                    456:        {ns_t_eid,      "EID",          "endpoint identifier (unimplemented)"},
                    457:        {ns_t_nimloc,   "NIMLOC",       "NIMROD locator (unimplemented)"},
                    458:        {ns_t_srv,      "SRV",          "server selection"},
                    459:        {ns_t_atma,     "ATMA",         "ATM address (unimplemented)"},
                    460:        {ns_t_tkey,     "TKEY",         "tkey"},
                    461:        {ns_t_tsig,     "TSIG",         "transaction signature"},
                    462:        {ns_t_ixfr,     "IXFR",         "incremental zone transfer"},
                    463:        {ns_t_axfr,     "AXFR",         "zone transfer"},
                    464:        {ns_t_zxfr,     "ZXFR",         "compressed zone transfer"},
                    465:        {ns_t_mailb,    "MAILB",        "mailbox-related data (deprecated)"},
                    466:        {ns_t_maila,    "MAILA",        "mail agent (deprecated)"},
                    467:        {ns_t_naptr,    "NAPTR",        "URN Naming Authority"},
                    468:        {ns_t_kx,       "KX",           "Key Exchange"},
                    469:        {ns_t_cert,     "CERT",         "Certificate"},
                    470:        {ns_t_a6,       "A6",           "IPv6 Address"},
                    471:        {ns_t_dname,    "DNAME",        "dname"},
                    472:        {ns_t_sink,     "SINK",         "Kitchen Sink (experimental)"},
                    473:        {ns_t_opt,      "OPT",          "EDNS Options"},
                    474:        {ns_t_any,      "ANY",          "\"any\""},
                    475:        {0,             NULL,           NULL}
                    476: };
                    477:
                    478: /*
                    479:  * Names of DNS rcodes.
                    480:  */
                    481: const struct res_sym __p_rcode_syms[] = {
                    482:        {ns_r_noerror,  "NOERROR",              "no error"},
                    483:        {ns_r_formerr,  "FORMERR",              "format error"},
                    484:        {ns_r_servfail, "SERVFAIL",             "server failed"},
                    485:        {ns_r_nxdomain, "NXDOMAIN",             "no such domain name"},
                    486:        {ns_r_notimpl,  "NOTIMP",               "not implemented"},
                    487:        {ns_r_refused,  "REFUSED",              "refused"},
                    488:        {ns_r_yxdomain, "YXDOMAIN",             "domain name exists"},
                    489:        {ns_r_yxrrset,  "YXRRSET",              "rrset exists"},
                    490:        {ns_r_nxrrset,  "NXRRSET",              "rrset doesn't exist"},
                    491:        {ns_r_notauth,  "NOTAUTH",              "not authoritative"},
                    492:        {ns_r_notzone,  "NOTZONE",              "Not in zone"},
                    493:        {ns_r_max,      "",                     ""},
                    494:        {ns_r_badsig,   "BADSIG",               "bad signature"},
                    495:        {ns_r_badkey,   "BADKEY",               "bad key"},
                    496:        {ns_r_badtime,  "BADTIME",              "bad time"},
                    497:        {0,             NULL,                   NULL}
                    498: };
                    499:
                    500: int
                    501: sym_ston(const struct res_sym *syms, const char *name, int *success) {
1.3       christos  502:        for (; syms->name != 0; syms++) {
1.1       christos  503:                if (strcasecmp (name, syms->name) == 0) {
                    504:                        if (success)
                    505:                                *success = 1;
                    506:                        return (syms->number);
                    507:                }
                    508:        }
                    509:        if (success)
                    510:                *success = 0;
                    511:        return (syms->number);          /* The default value. */
                    512: }
                    513:
                    514: const char *
                    515: sym_ntos(const struct res_sym *syms, int number, int *success) {
                    516:        static char unname[20];
                    517:
1.2       christos  518:        for (; syms->name != 0; syms++) {
1.1       christos  519:                if (number == syms->number) {
                    520:                        if (success)
                    521:                                *success = 1;
                    522:                        return (syms->name);
                    523:                }
                    524:        }
                    525:
                    526:        sprintf(unname, "%d", number);          /* XXX nonreentrant */
                    527:        if (success)
                    528:                *success = 0;
                    529:        return (unname);
                    530: }
                    531:
                    532: const char *
                    533: sym_ntop(const struct res_sym *syms, int number, int *success) {
                    534:        static char unname[20];
                    535:
1.2       christos  536:        for (; syms->name != 0; syms++) {
1.1       christos  537:                if (number == syms->number) {
                    538:                        if (success)
                    539:                                *success = 1;
                    540:                        return (syms->humanname);
                    541:                }
                    542:        }
                    543:        sprintf(unname, "%d", number);          /* XXX nonreentrant */
                    544:        if (success)
                    545:                *success = 0;
                    546:        return (unname);
                    547: }
                    548:
                    549: /*
                    550:  * Return a string for the type.
                    551:  */
                    552: const char *
                    553: p_type(int type) {
                    554:        int success;
                    555:        const char *result;
                    556:        static char typebuf[20];
                    557:
                    558:        result = sym_ntos(__p_type_syms, type, &success);
                    559:        if (success)
                    560:                return (result);
                    561:        if (type < 0 || type > 0xfff)
                    562:                return ("BADTYPE");
                    563:        sprintf(typebuf, "TYPE%d", type);
                    564:        return (typebuf);
                    565: }
                    566:
                    567: /*
                    568:  * Return a string for the type.
                    569:  */
                    570: const char *
                    571: p_section(int section, int opcode) {
                    572:        const struct res_sym *symbols;
                    573:
                    574:        switch (opcode) {
                    575:        case ns_o_update:
                    576:                symbols = __p_update_section_syms;
                    577:                break;
                    578:        default:
                    579:                symbols = __p_default_section_syms;
                    580:                break;
                    581:        }
                    582:        return (sym_ntos(symbols, section, (int *)0));
                    583: }
                    584:
                    585: /*
                    586:  * Return a mnemonic for class.
                    587:  */
                    588: const char *
                    589: p_class(int class) {
                    590:        int success;
                    591:        const char *result;
                    592:        static char classbuf[20];
                    593:
                    594:        result = sym_ntos(__p_class_syms, class, &success);
                    595:        if (success)
                    596:                return (result);
                    597:        if (class < 0 || class > 0xfff)
                    598:                return ("BADCLASS");
                    599:        sprintf(classbuf, "CLASS%d", class);
                    600:        return (classbuf);
                    601: }
                    602:
                    603: /*
                    604:  * Return a mnemonic for an option
                    605:  */
                    606: const char *
                    607: p_option(u_long option) {
                    608:        static char nbuf[40];
                    609:
                    610:        switch (option) {
                    611:        case RES_INIT:          return "init";
                    612:        case RES_DEBUG:         return "debug";
                    613:        case RES_AAONLY:        return "aaonly(unimpl)";
                    614:        case RES_USEVC:         return "usevc";
                    615:        case RES_PRIMARY:       return "primry(unimpl)";
                    616:        case RES_IGNTC:         return "igntc";
                    617:        case RES_RECURSE:       return "recurs";
                    618:        case RES_DEFNAMES:      return "defnam";
                    619:        case RES_STAYOPEN:      return "styopn";
                    620:        case RES_DNSRCH:        return "dnsrch";
                    621:        case RES_INSECURE1:     return "insecure1";
                    622:        case RES_INSECURE2:     return "insecure2";
                    623:        case RES_NOALIASES:     return "noaliases";
                    624:        case RES_USE_INET6:     return "inet6";
                    625: #ifdef RES_USE_EDNS0   /* KAME extension */
                    626:        case RES_USE_EDNS0:     return "edns0";
                    627: #endif
                    628: #ifdef RES_USE_DNAME
                    629:        case RES_USE_DNAME:     return "dname";
                    630: #endif
                    631: #ifdef RES_USE_DNSSEC
                    632:        case RES_USE_DNSSEC:    return "dnssec";
                    633: #endif
                    634: #ifdef RES_NOTLDQUERY
                    635:        case RES_NOTLDQUERY:    return "no-tld-query";
                    636: #endif
                    637: #ifdef RES_NO_NIBBLE2
                    638:        case RES_NO_NIBBLE2:    return "no-nibble2";
                    639: #endif
                    640:                                /* XXX nonreentrant */
                    641:        default:                sprintf(nbuf, "?0x%lx?", (u_long)option);
                    642:                                return (nbuf);
                    643:        }
                    644: }
                    645:
                    646: /*
                    647:  * Return a mnemonic for a time to live.
                    648:  */
                    649: const char *
                    650: p_time(u_int32_t value) {
                    651:        static char nbuf[40];           /* XXX nonreentrant */
                    652:
1.2       christos  653:        if (ns_format_ttl((u_long)value, nbuf, sizeof nbuf) < 0)
1.1       christos  654:                sprintf(nbuf, "%u", value);
                    655:        return (nbuf);
                    656: }
                    657:
                    658: /*
                    659:  * Return a string for the rcode.
                    660:  */
                    661: const char *
                    662: p_rcode(int rcode) {
                    663:        return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
                    664: }
                    665:
                    666: /*
                    667:  * Return a string for a res_sockaddr_union.
                    668:  */
                    669: const char *
                    670: p_sockun(union res_sockaddr_union u, char *buf, size_t size) {
                    671:        char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"];
                    672:
                    673:        switch (u.sin.sin_family) {
                    674:        case AF_INET:
                    675:                inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret);
                    676:                break;
                    677: #ifdef HAS_INET6_STRUCTS
                    678:        case AF_INET6:
                    679:                inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret);
                    680:                break;
                    681: #endif
                    682:        default:
                    683:                sprintf(ret, "[af%d]", u.sin.sin_family);
                    684:                break;
                    685:        }
                    686:        if (size > 0U) {
                    687:                strncpy(buf, ret, size - 1);
                    688:                buf[size - 1] = '0';
                    689:        }
                    690:        return (buf);
                    691: }
                    692:
                    693: /*
                    694:  * routines to convert between on-the-wire RR format and zone file format.
                    695:  * Does not contain conversion to/from decimal degrees; divide or multiply
                    696:  * by 60*60*1000 for that.
                    697:  */
                    698:
                    699: static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
                    700:                                      1000000,10000000,100000000,1000000000};
                    701:
                    702: /* takes an XeY precision/size value, returns a string representation. */
                    703: static const char *
                    704: precsize_ntoa(prec)
1.3       christos  705:        u_int32_t prec;
1.1       christos  706: {
                    707:        static char retbuf[sizeof "90000000.00"];       /* XXX nonreentrant */
                    708:        unsigned long val;
                    709:        int mantissa, exponent;
                    710:
                    711:        mantissa = (int)((prec >> 4) & 0x0f) % 10;
                    712:        exponent = (int)((prec >> 0) & 0x0f) % 10;
                    713:
                    714:        val = mantissa * poweroften[exponent];
                    715:
                    716:        (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100);
                    717:        return (retbuf);
                    718: }
                    719:
                    720: /* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
                    721: static u_int8_t
                    722: precsize_aton(const char **strptr) {
                    723:        unsigned int mval = 0, cmval = 0;
                    724:        u_int8_t retval = 0;
                    725:        const char *cp;
                    726:        int exponent;
                    727:        int mantissa;
                    728:
                    729:        cp = *strptr;
                    730:
                    731:        while (isdigit((unsigned char)*cp))
                    732:                mval = mval * 10 + (*cp++ - '0');
                    733:
                    734:        if (*cp == '.') {               /* centimeters */
                    735:                cp++;
                    736:                if (isdigit((unsigned char)*cp)) {
                    737:                        cmval = (*cp++ - '0') * 10;
                    738:                        if (isdigit((unsigned char)*cp)) {
                    739:                                cmval += (*cp++ - '0');
                    740:                        }
                    741:                }
                    742:        }
                    743:        cmval = (mval * 100) + cmval;
                    744:
                    745:        for (exponent = 0; exponent < 9; exponent++)
                    746:                if (cmval < poweroften[exponent+1])
                    747:                        break;
                    748:
                    749:        mantissa = cmval / poweroften[exponent];
                    750:        if (mantissa > 9)
                    751:                mantissa = 9;
                    752:
                    753:        retval = (mantissa << 4) | exponent;
                    754:
                    755:        *strptr = cp;
                    756:
                    757:        return (retval);
                    758: }
                    759:
                    760: /* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
                    761: static u_int32_t
                    762: latlon2ul(const char **latlonstrptr, int *which) {
                    763:        const char *cp;
                    764:        u_int32_t retval;
                    765:        int deg = 0, min = 0, secs = 0, secsfrac = 0;
                    766:
                    767:        cp = *latlonstrptr;
                    768:
                    769:        while (isdigit((unsigned char)*cp))
                    770:                deg = deg * 10 + (*cp++ - '0');
                    771:
                    772:        while (isspace((unsigned char)*cp))
                    773:                cp++;
                    774:
                    775:        if (!(isdigit((unsigned char)*cp)))
                    776:                goto fndhemi;
                    777:
                    778:        while (isdigit((unsigned char)*cp))
                    779:                min = min * 10 + (*cp++ - '0');
                    780:
                    781:        while (isspace((unsigned char)*cp))
                    782:                cp++;
                    783:
                    784:        if (!(isdigit((unsigned char)*cp)))
                    785:                goto fndhemi;
                    786:
                    787:        while (isdigit((unsigned char)*cp))
                    788:                secs = secs * 10 + (*cp++ - '0');
                    789:
                    790:        if (*cp == '.') {               /* decimal seconds */
                    791:                cp++;
                    792:                if (isdigit((unsigned char)*cp)) {
                    793:                        secsfrac = (*cp++ - '0') * 100;
                    794:                        if (isdigit((unsigned char)*cp)) {
                    795:                                secsfrac += (*cp++ - '0') * 10;
                    796:                                if (isdigit((unsigned char)*cp)) {
                    797:                                        secsfrac += (*cp++ - '0');
                    798:                                }
                    799:                        }
                    800:                }
                    801:        }
                    802:
                    803:        while (!isspace((unsigned char)*cp))    /* if any trailing garbage */
                    804:                cp++;
                    805:
                    806:        while (isspace((unsigned char)*cp))
                    807:                cp++;
                    808:
                    809:  fndhemi:
                    810:        switch (*cp) {
                    811:        case 'N': case 'n':
                    812:        case 'E': case 'e':
                    813:                retval = ((unsigned)1<<31)
                    814:                        + (((((deg * 60) + min) * 60) + secs) * 1000)
                    815:                        + secsfrac;
                    816:                break;
                    817:        case 'S': case 's':
                    818:        case 'W': case 'w':
                    819:                retval = ((unsigned)1<<31)
                    820:                        - (((((deg * 60) + min) * 60) + secs) * 1000)
                    821:                        - secsfrac;
                    822:                break;
                    823:        default:
                    824:                retval = 0;     /* invalid value -- indicates error */
                    825:                break;
                    826:        }
                    827:
                    828:        switch (*cp) {
                    829:        case 'N': case 'n':
                    830:        case 'S': case 's':
                    831:                *which = 1;     /* latitude */
                    832:                break;
                    833:        case 'E': case 'e':
                    834:        case 'W': case 'w':
                    835:                *which = 2;     /* longitude */
                    836:                break;
                    837:        default:
                    838:                *which = 0;     /* error */
                    839:                break;
                    840:        }
                    841:
                    842:        cp++;                   /* skip the hemisphere */
                    843:
                    844:        while (!isspace((unsigned char)*cp))    /* if any trailing garbage */
                    845:                cp++;
                    846:
                    847:        while (isspace((unsigned char)*cp))     /* move to next field */
                    848:                cp++;
                    849:
                    850:        *latlonstrptr = cp;
                    851:
                    852:        return (retval);
                    853: }
                    854:
                    855: /* converts a zone file representation in a string to an RDATA on-the-wire
                    856:  * representation. */
                    857: int
                    858: loc_aton(ascii, binary)
                    859:        const char *ascii;
                    860:        u_char *binary;
                    861: {
                    862:        const char *cp, *maxcp;
                    863:        u_char *bcp;
                    864:
                    865:        u_int32_t latit = 0, longit = 0, alt = 0;
                    866:        u_int32_t lltemp1 = 0, lltemp2 = 0;
                    867:        int altmeters = 0, altfrac = 0, altsign = 1;
                    868:        u_int8_t hp = 0x16;     /* default = 1e6 cm = 10000.00m = 10km */
                    869:        u_int8_t vp = 0x13;     /* default = 1e3 cm = 10.00m */
                    870:        u_int8_t siz = 0x12;    /* default = 1e2 cm = 1.00m */
                    871:        int which1 = 0, which2 = 0;
                    872:
                    873:        cp = ascii;
                    874:        maxcp = cp + strlen(ascii);
                    875:
                    876:        lltemp1 = latlon2ul(&cp, &which1);
                    877:
                    878:        lltemp2 = latlon2ul(&cp, &which2);
                    879:
                    880:        switch (which1 + which2) {
                    881:        case 3:                 /* 1 + 2, the only valid combination */
                    882:                if ((which1 == 1) && (which2 == 2)) { /* normal case */
                    883:                        latit = lltemp1;
                    884:                        longit = lltemp2;
                    885:                } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
                    886:                        longit = lltemp1;
                    887:                        latit = lltemp2;
                    888:                } else {        /* some kind of brokenness */
                    889:                        return (0);
                    890:                }
                    891:                break;
                    892:        default:                /* we didn't get one of each */
                    893:                return (0);
                    894:        }
                    895:
                    896:        /* altitude */
                    897:        if (*cp == '-') {
                    898:                altsign = -1;
                    899:                cp++;
                    900:        }
                    901:
                    902:        if (*cp == '+')
                    903:                cp++;
                    904:
                    905:        while (isdigit((unsigned char)*cp))
                    906:                altmeters = altmeters * 10 + (*cp++ - '0');
                    907:
                    908:        if (*cp == '.') {               /* decimal meters */
                    909:                cp++;
                    910:                if (isdigit((unsigned char)*cp)) {
                    911:                        altfrac = (*cp++ - '0') * 10;
                    912:                        if (isdigit((unsigned char)*cp)) {
                    913:                                altfrac += (*cp++ - '0');
                    914:                        }
                    915:                }
                    916:        }
                    917:
                    918:        alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
                    919:
                    920:        while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */
                    921:                cp++;
                    922:
                    923:        while (isspace((unsigned char)*cp) && (cp < maxcp))
                    924:                cp++;
                    925:
                    926:        if (cp >= maxcp)
                    927:                goto defaults;
                    928:
                    929:        siz = precsize_aton(&cp);
                    930:
                    931:        while (!isspace((unsigned char)*cp) && (cp < maxcp))    /* if trailing garbage or m */
                    932:                cp++;
                    933:
                    934:        while (isspace((unsigned char)*cp) && (cp < maxcp))
                    935:                cp++;
                    936:
                    937:        if (cp >= maxcp)
                    938:                goto defaults;
                    939:
                    940:        hp = precsize_aton(&cp);
                    941:
                    942:        while (!isspace((unsigned char)*cp) && (cp < maxcp))    /* if trailing garbage or m */
                    943:                cp++;
                    944:
                    945:        while (isspace((unsigned char)*cp) && (cp < maxcp))
                    946:                cp++;
                    947:
                    948:        if (cp >= maxcp)
                    949:                goto defaults;
                    950:
                    951:        vp = precsize_aton(&cp);
                    952:
                    953:  defaults:
                    954:
                    955:        bcp = binary;
                    956:        *bcp++ = (u_int8_t) 0;  /* version byte */
                    957:        *bcp++ = siz;
                    958:        *bcp++ = hp;
                    959:        *bcp++ = vp;
                    960:        PUTLONG(latit,bcp);
                    961:        PUTLONG(longit,bcp);
                    962:        PUTLONG(alt,bcp);
                    963:
                    964:        return (16);            /* size of RR in octets */
                    965: }
                    966:
                    967: /* takes an on-the-wire LOC RR and formats it in a human readable format. */
                    968: const char *
                    969: loc_ntoa(binary, ascii)
                    970:        const u_char *binary;
                    971:        char *ascii;
                    972: {
                    973:        static const char *error = "?";
                    974:        static char tmpbuf[sizeof
                    975: "1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
                    976:        const u_char *cp = binary;
                    977:
                    978:        int latdeg, latmin, latsec, latsecfrac;
                    979:        int longdeg, longmin, longsec, longsecfrac;
                    980:        char northsouth, eastwest;
                    981:        const char *altsign;
                    982:        int altmeters, altfrac;
                    983:
                    984:        const u_int32_t referencealt = 100000 * 100;
                    985:
                    986:        int32_t latval, longval, altval;
                    987:        u_int32_t templ;
                    988:        u_int8_t sizeval, hpval, vpval, versionval;
                    989:
                    990:        char *sizestr, *hpstr, *vpstr;
                    991:
                    992:        versionval = *cp++;
                    993:
                    994:        if (ascii == NULL)
                    995:                ascii = tmpbuf;
                    996:
                    997:        if (versionval) {
                    998:                (void) sprintf(ascii, "; error: unknown LOC RR version");
                    999:                return (ascii);
                   1000:        }
                   1001:
                   1002:        sizeval = *cp++;
                   1003:
                   1004:        hpval = *cp++;
                   1005:        vpval = *cp++;
                   1006:
                   1007:        GETLONG(templ, cp);
                   1008:        latval = (templ - ((unsigned)1<<31));
                   1009:
                   1010:        GETLONG(templ, cp);
                   1011:        longval = (templ - ((unsigned)1<<31));
                   1012:
                   1013:        GETLONG(templ, cp);
                   1014:        if (templ < referencealt) { /* below WGS 84 spheroid */
                   1015:                altval = referencealt - templ;
                   1016:                altsign = "-";
                   1017:        } else {
                   1018:                altval = templ - referencealt;
                   1019:                altsign = "";
                   1020:        }
                   1021:
                   1022:        if (latval < 0) {
                   1023:                northsouth = 'S';
                   1024:                latval = -latval;
                   1025:        } else
                   1026:                northsouth = 'N';
                   1027:
                   1028:        latsecfrac = latval % 1000;
                   1029:        latval = latval / 1000;
                   1030:        latsec = latval % 60;
                   1031:        latval = latval / 60;
                   1032:        latmin = latval % 60;
                   1033:        latval = latval / 60;
                   1034:        latdeg = latval;
                   1035:
                   1036:        if (longval < 0) {
                   1037:                eastwest = 'W';
                   1038:                longval = -longval;
                   1039:        } else
                   1040:                eastwest = 'E';
                   1041:
                   1042:        longsecfrac = longval % 1000;
                   1043:        longval = longval / 1000;
                   1044:        longsec = longval % 60;
                   1045:        longval = longval / 60;
                   1046:        longmin = longval % 60;
                   1047:        longval = longval / 60;
                   1048:        longdeg = longval;
                   1049:
                   1050:        altfrac = altval % 100;
                   1051:        altmeters = (altval / 100);
                   1052:
1.2       christos 1053:        sizestr = strdup(precsize_ntoa((u_int32_t)sizeval));
                   1054:        hpstr = strdup(precsize_ntoa((u_int32_t)hpval));
                   1055:        vpstr = strdup(precsize_ntoa((u_int32_t)vpval));
1.1       christos 1056:
                   1057:        sprintf(ascii,
                   1058:            "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm",
                   1059:                latdeg, latmin, latsec, latsecfrac, northsouth,
                   1060:                longdeg, longmin, longsec, longsecfrac, eastwest,
                   1061:                altsign, altmeters, altfrac,
                   1062:                (sizestr != NULL) ? sizestr : error,
                   1063:                (hpstr != NULL) ? hpstr : error,
                   1064:                (vpstr != NULL) ? vpstr : error);
                   1065:
                   1066:        if (sizestr != NULL)
                   1067:                free(sizestr);
                   1068:        if (hpstr != NULL)
                   1069:                free(hpstr);
                   1070:        if (vpstr != NULL)
                   1071:                free(vpstr);
                   1072:
                   1073:        return (ascii);
                   1074: }
                   1075:
                   1076:
                   1077: /* Return the number of DNS hierarchy levels in the name. */
                   1078: int
                   1079: dn_count_labels(const char *name) {
                   1080:        int i, len, count;
                   1081:
                   1082:        len = strlen(name);
                   1083:        for (i = 0, count = 0; i < len; i++) {
                   1084:                /* XXX need to check for \. or use named's nlabels(). */
                   1085:                if (name[i] == '.')
                   1086:                        count++;
                   1087:        }
                   1088:
                   1089:        /* don't count initial wildcard */
                   1090:        if (name[0] == '*')
                   1091:                if (count)
                   1092:                        count--;
                   1093:
                   1094:        /* don't count the null label for root. */
                   1095:        /* if terminating '.' not found, must adjust */
                   1096:        /* count to include last label */
                   1097:        if (len > 0 && name[len-1] != '.')
                   1098:                count++;
                   1099:        return (count);
                   1100: }
                   1101:
                   1102:
                   1103: /*
                   1104:  * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
                   1105:  * SIG records are required to be printed like this, by the Secure DNS RFC.
                   1106:  */
                   1107: char *
                   1108: p_secstodate (u_long secs) {
                   1109:        /* XXX nonreentrant */
                   1110:        static char output[15];         /* YYYYMMDDHHMMSS and null */
1.2       christos 1111:        time_t myclock = secs;
                   1112:        struct tm *mytime;
1.1       christos 1113: #ifdef HAVE_TIME_R
                   1114:        struct tm res;
                   1115:
1.2       christos 1116:        mytime = gmtime_r(&myclock, &res);
1.1       christos 1117: #else
1.2       christos 1118:        mytime = gmtime(&myclock);
1.1       christos 1119: #endif
1.2       christos 1120:        mytime->tm_year += 1900;
                   1121:        mytime->tm_mon += 1;
1.1       christos 1122:        sprintf(output, "%04d%02d%02d%02d%02d%02d",
1.2       christos 1123:                mytime->tm_year, mytime->tm_mon, mytime->tm_mday,
                   1124:                mytime->tm_hour, mytime->tm_min, mytime->tm_sec);
1.1       christos 1125:        return (output);
                   1126: }
                   1127:
                   1128: u_int16_t
                   1129: res_nametoclass(const char *buf, int *successp) {
                   1130:        unsigned long result;
                   1131:        char *endptr;
                   1132:        int success;
                   1133:
                   1134:        result = sym_ston(__p_class_syms, buf, &success);
                   1135:        if (success)
                   1136:                goto done;
                   1137:
                   1138:        if (strncasecmp(buf, "CLASS", 5) != 0 ||
                   1139:            !isdigit((unsigned char)buf[5]))
                   1140:                goto done;
                   1141:        errno = 0;
                   1142:        result = strtoul(buf + 5, &endptr, 10);
                   1143:        if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
                   1144:                success = 1;
                   1145:  done:
                   1146:        if (successp)
                   1147:                *successp = success;
1.2       christos 1148:        return (u_int16_t)(result);
1.1       christos 1149: }
                   1150:
                   1151: u_int16_t
                   1152: res_nametotype(const char *buf, int *successp) {
                   1153:        unsigned long result;
                   1154:        char *endptr;
                   1155:        int success;
                   1156:
                   1157:        result = sym_ston(__p_type_syms, buf, &success);
                   1158:        if (success)
                   1159:                goto done;
                   1160:
                   1161:        if (strncasecmp(buf, "type", 4) != 0 ||
                   1162:            !isdigit((unsigned char)buf[4]))
                   1163:                goto done;
                   1164:        errno = 0;
                   1165:        result = strtoul(buf + 4, &endptr, 10);
                   1166:        if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
                   1167:                success = 1;
                   1168:  done:
                   1169:        if (successp)
                   1170:                *successp = success;
1.2       christos 1171:        return (u_int16_t)(result);
1.1       christos 1172: }

CVSweb <webmaster@jp.NetBSD.org>