[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.9

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

CVSweb <webmaster@jp.NetBSD.org>