Back to index

glibc  2.9
res_debug.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1985
00003  *    The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 4. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
00032  *
00033  * Permission to use, copy, modify, and distribute this software for any
00034  * purpose with or without fee is hereby granted, provided that the above
00035  * copyright notice and this permission notice appear in all copies, and that
00036  * the name of Digital Equipment Corporation not be used in advertising or
00037  * publicity pertaining to distribution of the document or software without
00038  * specific, written prior permission.
00039  *
00040  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
00041  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
00042  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
00043  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00044  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00045  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00046  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00047  * SOFTWARE.
00048  */
00049 
00050 /*
00051  * Portions Copyright (c) 1995 by International Business Machines, Inc.
00052  *
00053  * International Business Machines, Inc. (hereinafter called IBM) grants
00054  * permission under its copyrights to use, copy, modify, and distribute this
00055  * Software with or without fee, provided that the above copyright notice and
00056  * all paragraphs of this notice appear in all copies, and that the name of IBM
00057  * not be used in connection with the marketing of any product incorporating
00058  * the Software or modifications thereof, without specific, written prior
00059  * permission.
00060  *
00061  * To the extent it has a right to do so, IBM grants an immunity from suit
00062  * under its patents, if any, for the use, sale or manufacture of products to
00063  * the extent that such products are used for performing Domain Name System
00064  * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
00065  * granted for any product per se or for any other function of any product.
00066  *
00067  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
00068  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00069  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
00070  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
00071  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
00072  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
00073  */
00074 
00075 /*
00076  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
00077  *
00078  * Permission to use, copy, modify, and distribute this software for any
00079  * purpose with or without fee is hereby granted, provided that the above
00080  * copyright notice and this permission notice appear in all copies.
00081  *
00082  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
00083  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00084  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
00085  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00086  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00087  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00088  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00089  * SOFTWARE.
00090  */
00091 
00092 #if defined(LIBC_SCCS) && !defined(lint)
00093 static const char sccsid[] = "@(#)res_debug.c    8.1 (Berkeley) 6/4/93";
00094 static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vixie Exp $";
00095 #endif /* LIBC_SCCS and not lint */
00096 
00097 #include <sys/types.h>
00098 #include <sys/param.h>
00099 #include <sys/socket.h>
00100 
00101 #include <netinet/in.h>
00102 #include <arpa/inet.h>
00103 #include <arpa/nameser.h>
00104 
00105 #include <ctype.h>
00106 #include <errno.h>
00107 #include <math.h>
00108 #include <netdb.h>
00109 #include <resolv.h>
00110 #include <stdio.h>
00111 #include <stdlib.h>
00112 #include <string.h>
00113 #include <time.h>
00114 
00115 #ifdef SPRINTF_CHAR
00116 # define SPRINTF(x) strlen(sprintfx)
00117 #else
00118 # define SPRINTF(x) sprintf x
00119 #endif
00120 
00121 extern const char *_res_sectioncodes[] attribute_hidden;
00122 
00123 /*
00124  * Print the current options.
00125  */
00126 void
00127 fp_resstat(const res_state statp, FILE *file) {
00128        u_long mask;
00129 
00130        fprintf(file, ";; res options:");
00131        for (mask = 1;  mask != 0;  mask <<= 1)
00132               if (statp->options & mask)
00133                      fprintf(file, " %s", p_option(mask));
00134        putc('\n', file);
00135 }
00136 
00137 static void
00138 do_section(const res_state statp,
00139           ns_msg *handle, ns_sect section,
00140           int pflag, FILE *file)
00141 {
00142        int n, sflag, rrnum;
00143        static int buflen = 2048;
00144        char *buf;
00145        ns_opcode opcode;
00146        ns_rr rr;
00147 
00148        /*
00149         * Print answer records.
00150         */
00151        sflag = (statp->pfcode & pflag);
00152        if (statp->pfcode && !sflag)
00153               return;
00154 
00155        buf = malloc(buflen);
00156        if (buf == NULL) {
00157               fprintf(file, ";; memory allocation failure\n");
00158               return;
00159        }
00160 
00161        opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
00162        rrnum = 0;
00163        for (;;) {
00164               if (ns_parserr(handle, section, rrnum, &rr)) {
00165                      if (errno != ENODEV)
00166                             fprintf(file, ";; ns_parserr: %s\n",
00167                                    strerror(errno));
00168                      else if (rrnum > 0 && sflag != 0 &&
00169                              (statp->pfcode & RES_PRF_HEAD1))
00170                             putc('\n', file);
00171                      goto cleanup;
00172               }
00173               if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
00174                      fprintf(file, ";; %s SECTION:\n",
00175                             p_section(section, opcode));
00176               if (section == ns_s_qd)
00177                      fprintf(file, ";;\t%s, type = %s, class = %s\n",
00178                             ns_rr_name(rr),
00179                             p_type(ns_rr_type(rr)),
00180                             p_class(ns_rr_class(rr)));
00181               else {
00182                      n = ns_sprintrr(handle, &rr, NULL, NULL,
00183                                    buf, buflen);
00184                      if (n < 0) {
00185                             if (errno == ENOSPC) {
00186                                    free(buf);
00187                                    buf = NULL;
00188                                    if (buflen < 131072)
00189                                           buf = malloc(buflen += 1024);
00190                                    if (buf == NULL) {
00191                                           fprintf(file,
00192                                           ";; memory allocation failure\n");
00193                                          return;
00194                                    }
00195                                    continue;
00196                             }
00197                             fprintf(file, ";; ns_sprintrr: %s\n",
00198                                    strerror(errno));
00199                             goto cleanup;
00200                      }
00201                      fputs(buf, file);
00202                      fputc('\n', file);
00203               }
00204               rrnum++;
00205        }
00206  cleanup:
00207        free(buf);
00208 }
00209 
00210 /*
00211  * Print the contents of a query.
00212  * This is intended to be primarily a debugging routine.
00213  */
00214 void
00215 res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
00216        ns_msg handle;
00217        int qdcount, ancount, nscount, arcount;
00218        u_int opcode, rcode, id;
00219 
00220        if (ns_initparse(msg, len, &handle) < 0) {
00221               fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
00222               return;
00223        }
00224        opcode = ns_msg_getflag(handle, ns_f_opcode);
00225        rcode = ns_msg_getflag(handle, ns_f_rcode);
00226        id = ns_msg_id(handle);
00227        qdcount = ns_msg_count(handle, ns_s_qd);
00228        ancount = ns_msg_count(handle, ns_s_an);
00229        nscount = ns_msg_count(handle, ns_s_ns);
00230        arcount = ns_msg_count(handle, ns_s_ar);
00231 
00232        /*
00233         * Print header fields.
00234         */
00235        if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
00236               fprintf(file,
00237                      ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
00238                      _res_opcodes[opcode], p_rcode(rcode), id);
00239        if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
00240               putc(';', file);
00241        if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
00242               fprintf(file, "; flags:");
00243               if (ns_msg_getflag(handle, ns_f_qr))
00244                      fprintf(file, " qr");
00245               if (ns_msg_getflag(handle, ns_f_aa))
00246                      fprintf(file, " aa");
00247               if (ns_msg_getflag(handle, ns_f_tc))
00248                      fprintf(file, " tc");
00249               if (ns_msg_getflag(handle, ns_f_rd))
00250                      fprintf(file, " rd");
00251               if (ns_msg_getflag(handle, ns_f_ra))
00252                      fprintf(file, " ra");
00253               if (ns_msg_getflag(handle, ns_f_z))
00254                      fprintf(file, " ??");
00255               if (ns_msg_getflag(handle, ns_f_ad))
00256                      fprintf(file, " ad");
00257               if (ns_msg_getflag(handle, ns_f_cd))
00258                      fprintf(file, " cd");
00259        }
00260        if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
00261               fprintf(file, "; %s: %d",
00262                      p_section(ns_s_qd, opcode), qdcount);
00263               fprintf(file, ", %s: %d",
00264                      p_section(ns_s_an, opcode), ancount);
00265               fprintf(file, ", %s: %d",
00266                      p_section(ns_s_ns, opcode), nscount);
00267               fprintf(file, ", %s: %d",
00268                      p_section(ns_s_ar, opcode), arcount);
00269        }
00270        if ((!statp->pfcode) || (statp->pfcode &
00271               (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
00272               putc('\n',file);
00273        }
00274        /*
00275         * Print the various sections.
00276         */
00277        do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
00278        do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
00279        do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
00280        do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
00281        if (qdcount == 0 && ancount == 0 &&
00282            nscount == 0 && arcount == 0)
00283               putc('\n', file);
00284 }
00285 
00286 const u_char *
00287 p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
00288        char name[MAXDNAME];
00289        int n;
00290 
00291        if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
00292               return (NULL);
00293        if (name[0] == '\0')
00294               putc('.', file);
00295        else
00296               fputs(name, file);
00297        return (cp + n);
00298 }
00299 libresolv_hidden_def (p_cdnname)
00300 
00301 const u_char *
00302 p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
00303        return (p_cdnname(cp, msg, PACKETSZ, file));
00304 }
00305 
00306 /* Return a fully-qualified domain name from a compressed name (with
00307    length supplied).  */
00308 
00309 const u_char *
00310 p_fqnname(cp, msg, msglen, name, namelen)
00311        const u_char *cp, *msg;
00312        int msglen;
00313        char *name;
00314        int namelen;
00315 {
00316        int n, newlen;
00317 
00318        if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
00319               return (NULL);
00320        newlen = strlen(name);
00321        if (newlen == 0 || name[newlen - 1] != '.') {
00322               if (newlen + 1 >= namelen)  /* Lack space for final dot */
00323                      return (NULL);
00324               else
00325                      strcpy(name + newlen, ".");
00326        }
00327        return (cp + n);
00328 }
00329 libresolv_hidden_def (p_fqnname)
00330 
00331 /* XXX:       the rest of these functions need to become length-limited, too. */
00332 
00333 const u_char *
00334 p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
00335        char name[MAXDNAME];
00336        const u_char *n;
00337 
00338        n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
00339        if (n == NULL)
00340               return (NULL);
00341        fputs(name, file);
00342        return (n);
00343 }
00344 
00345 /*
00346  * Names of RR classes and qclasses.  Classes and qclasses are the same, except
00347  * that C_ANY is a qclass but not a class.  (You can ask for records of class
00348  * C_ANY, but you can't have any records of that class in the database.)
00349  */
00350 extern const struct res_sym __p_class_syms[];
00351 libresolv_hidden_proto (__p_class_syms)
00352 const struct res_sym __p_class_syms[] = {
00353        {C_IN,        "IN"},
00354        {C_CHAOS,     "CHAOS"},
00355        {C_HS,        "HS"},
00356        {C_HS,        "HESIOD"},
00357        {C_ANY,              "ANY"},
00358        {C_NONE,      "NONE"},
00359        {C_IN,               (char *)0}
00360 };
00361 libresolv_hidden_data_def (__p_class_syms)
00362 
00363 /*
00364  * Names of message sections.
00365  */
00366 const struct res_sym __p_default_section_syms[] attribute_hidden = {
00367        {ns_s_qd,     "QUERY"},
00368        {ns_s_an,     "ANSWER"},
00369        {ns_s_ns,     "AUTHORITY"},
00370        {ns_s_ar,     "ADDITIONAL"},
00371        {0,             (char *)0}
00372 };
00373 
00374 const struct res_sym __p_update_section_syms[] attribute_hidden = {
00375        {S_ZONE,      "ZONE"},
00376        {S_PREREQ,    "PREREQUISITE"},
00377        {S_UPDATE,    "UPDATE"},
00378        {S_ADDT,      "ADDITIONAL"},
00379        {0,             (char *)0}
00380 };
00381 
00382 const struct res_sym __p_key_syms[] attribute_hidden = {
00383        {NS_ALG_MD5RSA,             "RSA",        "RSA KEY with MD5 hash"},
00384        {NS_ALG_DH,          "DH",         "Diffie Hellman"},
00385        {NS_ALG_DSA,         "DSA",        "Digital Signature Algorithm"},
00386        {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"},
00387        {NS_ALG_PRIVATE_OID, "PRIVATE",    "Algorithm obtained from OID"},
00388        {0,                  NULL,         NULL}
00389 };
00390 
00391 const struct res_sym __p_cert_syms[] attribute_hidden = {
00392        {cert_t_pkix, "PKIX",              "PKIX (X.509v3) Certificate"},
00393        {cert_t_spki, "SPKI",              "SPKI certificate"},
00394        {cert_t_pgp,  "PGP",        "PGP certificate"},
00395        {cert_t_url,  "URL",        "URL Private"},
00396        {cert_t_oid,  "OID",        "OID Private"},
00397        {0,           NULL,         NULL}
00398 };
00399 
00400 /*
00401  * Names of RR types and qtypes.  Types and qtypes are the same, except
00402  * that T_ANY is a qtype but not a type.  (You can ask for records of type
00403  * T_ANY, but you can't have any records of that type in the database.)
00404  */
00405 extern const struct res_sym __p_type_syms[];
00406 libresolv_hidden_proto (__p_type_syms)
00407 const struct res_sym __p_type_syms[] = {
00408        {ns_t_a,      "A",          "address"},
00409        {ns_t_ns,     "NS",         "name server"},
00410        {ns_t_md,     "MD",         "mail destination (deprecated)"},
00411        {ns_t_mf,     "MF",         "mail forwarder (deprecated)"},
00412        {ns_t_cname,  "CNAME",      "canonical name"},
00413        {ns_t_soa,    "SOA",        "start of authority"},
00414        {ns_t_mb,     "MB",         "mailbox"},
00415        {ns_t_mg,     "MG",         "mail group member"},
00416        {ns_t_mr,     "MR",         "mail rename"},
00417        {ns_t_null,   "NULL",              "null"},
00418        {ns_t_wks,    "WKS",        "well-known service (deprecated)"},
00419        {ns_t_ptr,    "PTR",        "domain name pointer"},
00420        {ns_t_hinfo,  "HINFO",      "host information"},
00421        {ns_t_minfo,  "MINFO",      "mailbox information"},
00422        {ns_t_mx,     "MX",         "mail exchanger"},
00423        {ns_t_txt,    "TXT",        "text"},
00424        {ns_t_rp,     "RP",         "responsible person"},
00425        {ns_t_afsdb,  "AFSDB",      "DCE or AFS server"},
00426        {ns_t_x25,    "X25",        "X25 address"},
00427        {ns_t_isdn,   "ISDN",              "ISDN address"},
00428        {ns_t_rt,     "RT",         "router"},
00429        {ns_t_nsap,   "NSAP",              "nsap address"},
00430        {ns_t_nsap_ptr,      "NSAP_PTR",   "domain name pointer"},
00431        {ns_t_sig,    "SIG",        "signature"},
00432        {ns_t_key,    "KEY",        "key"},
00433        {ns_t_px,     "PX",         "mapping information"},
00434        {ns_t_gpos,   "GPOS",              "geographical position (withdrawn)"},
00435        {ns_t_aaaa,   "AAAA",              "IPv6 address"},
00436        {ns_t_loc,    "LOC",        "location"},
00437        {ns_t_nxt,    "NXT",        "next valid name (unimplemented)"},
00438        {ns_t_eid,    "EID",        "endpoint identifier (unimplemented)"},
00439        {ns_t_nimloc, "NIMLOC",     "NIMROD locator (unimplemented)"},
00440        {ns_t_srv,    "SRV",        "server selection"},
00441        {ns_t_atma,   "ATMA",              "ATM address (unimplemented)"},
00442        {ns_t_dname,  "DNAME",      "Non-terminal DNAME (for IPv6)"},
00443        {ns_t_tsig,   "TSIG",              "transaction signature"},
00444        {ns_t_ixfr,   "IXFR",              "incremental zone transfer"},
00445        {ns_t_axfr,   "AXFR",              "zone transfer"},
00446        {ns_t_zxfr,   "ZXFR",              "compressed zone transfer"},
00447        {ns_t_mailb,  "MAILB",      "mailbox-related data (deprecated)"},
00448        {ns_t_maila,  "MAILA",      "mail agent (deprecated)"},
00449        {ns_t_naptr,  "NAPTR",      "URN Naming Authority"},
00450        {ns_t_kx,     "KX",         "Key Exchange"},
00451        {ns_t_cert,   "CERT",              "Certificate"},
00452        {ns_t_any,    "ANY",        "\"any\""},
00453        {0,           NULL,         NULL}
00454 };
00455 libresolv_hidden_data_def (__p_type_syms)
00456 
00457 /*
00458  * Names of DNS rcodes.
00459  */
00460 const struct res_sym __p_rcode_syms[] attribute_hidden = {
00461        {ns_r_noerror,       "NOERROR",           "no error"},
00462        {ns_r_formerr,       "FORMERR",           "format error"},
00463        {ns_r_servfail,      "SERVFAIL",          "server failed"},
00464        {ns_r_nxdomain,      "NXDOMAIN",          "no such domain name"},
00465        {ns_r_notimpl,       "NOTIMP",            "not implemented"},
00466        {ns_r_refused,       "REFUSED",           "refused"},
00467        {ns_r_yxdomain,      "YXDOMAIN",          "domain name exists"},
00468        {ns_r_yxrrset,       "YXRRSET",           "rrset exists"},
00469        {ns_r_nxrrset,       "NXRRSET",           "rrset doesn't exist"},
00470        {ns_r_notauth,       "NOTAUTH",           "not authoritative"},
00471        {ns_r_notzone,       "NOTZONE",           "Not in zone"},
00472        {ns_r_max,    "",                  ""},
00473        {ns_r_badsig, "BADSIG",            "bad signature"},
00474        {ns_r_badkey, "BADKEY",            "bad key"},
00475        {ns_r_badtime,       "BADTIME",           "bad time"},
00476        {0,           NULL,                NULL}
00477 };
00478 
00479 int
00480 sym_ston(const struct res_sym *syms, const char *name, int *success) {
00481        for ((void)NULL; syms->name != 0; syms++) {
00482               if (strcasecmp (name, syms->name) == 0) {
00483                      if (success)
00484                             *success = 1;
00485                      return (syms->number);
00486               }
00487        }
00488        if (success)
00489               *success = 0;
00490        return (syms->number);             /* The default value. */
00491 }
00492 
00493 const char *
00494 sym_ntos(const struct res_sym *syms, int number, int *success) {
00495        static char unname[20];
00496 
00497        for ((void)NULL; syms->name != 0; syms++) {
00498               if (number == syms->number) {
00499                      if (success)
00500                             *success = 1;
00501                      return (syms->name);
00502               }
00503        }
00504 
00505        sprintf(unname, "%d", number);            /* XXX nonreentrant */
00506        if (success)
00507               *success = 0;
00508        return (unname);
00509 }
00510 libresolv_hidden_def (sym_ntos)
00511 
00512 const char *
00513 sym_ntop(const struct res_sym *syms, int number, int *success) {
00514        static char unname[20];
00515 
00516        for ((void)NULL; syms->name != 0; syms++) {
00517               if (number == syms->number) {
00518                      if (success)
00519                             *success = 1;
00520                      return (syms->humanname);
00521               }
00522        }
00523        sprintf(unname, "%d", number);            /* XXX nonreentrant */
00524        if (success)
00525               *success = 0;
00526        return (unname);
00527 }
00528 
00529 /*
00530  * Return a string for the type.
00531  */
00532 const char *
00533 p_type(int type) {
00534        return (sym_ntos(__p_type_syms, type, (int *)0));
00535 }
00536 libresolv_hidden_def (p_type)
00537 
00538 /*
00539  * Return a string for the type.
00540  */
00541 const char *
00542 p_section(int section, int opcode) {
00543        const struct res_sym *symbols;
00544 
00545        switch (opcode) {
00546        case ns_o_update:
00547               symbols = __p_update_section_syms;
00548               break;
00549        default:
00550               symbols = __p_default_section_syms;
00551               break;
00552        }
00553        return (sym_ntos(symbols, section, (int *)0));
00554 }
00555 
00556 /*
00557  * Return a mnemonic for class.
00558  */
00559 const char *
00560 p_class(int class) {
00561        return (sym_ntos(__p_class_syms, class, (int *)0));
00562 }
00563 libresolv_hidden_def (p_class)
00564 
00565 /*
00566  * Return a mnemonic for an option
00567  */
00568 const char *
00569 p_option(u_long option) {
00570        static char nbuf[40];
00571 
00572        switch (option) {
00573        case RES_INIT:              return "init";
00574        case RES_DEBUG:             return "debug";
00575        case RES_AAONLY:     return "aaonly(unimpl)";
00576        case RES_USEVC:             return "usevc";
00577        case RES_PRIMARY:    return "primry(unimpl)";
00578        case RES_IGNTC:             return "igntc";
00579        case RES_RECURSE:    return "recurs";
00580        case RES_DEFNAMES:   return "defnam";
00581        case RES_STAYOPEN:   return "styopn";
00582        case RES_DNSRCH:     return "dnsrch";
00583        case RES_INSECURE1:  return "insecure1";
00584        case RES_INSECURE2:  return "insecure2";
00585        case RES_USE_INET6:  return "inet6";
00586        case RES_ROTATE:     return "rotate";
00587        case RES_NOCHECKNAME:       return "no-check-names";
00588        case RES_USEBSTRING: return "ip6-bytstring";
00589                             /* XXX nonreentrant */
00590        default:             sprintf(nbuf, "?0x%lx?", (u_long)option);
00591                             return (nbuf);
00592        }
00593 }
00594 libresolv_hidden_def (p_option)
00595 
00596 /*
00597  * Return a mnemonic for a time to live.
00598  */
00599 const char *
00600 p_time(u_int32_t value) {
00601        static char nbuf[40];              /* XXX nonreentrant */
00602 
00603        if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
00604               sprintf(nbuf, "%u", value);
00605        return (nbuf);
00606 }
00607 
00608 /*
00609  * Return a string for the rcode.
00610  */
00611 const char *
00612 p_rcode(int rcode) {
00613        return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
00614 }
00615 libresolv_hidden_def (p_rcode)
00616 
00617 /*
00618  * routines to convert between on-the-wire RR format and zone file format.
00619  * Does not contain conversion to/from decimal degrees; divide or multiply
00620  * by 60*60*1000 for that.
00621  */
00622 
00623 static const unsigned int poweroften[10]=
00624   { 1, 10, 100, 1000, 10000, 100000,
00625     1000000,10000000,100000000,1000000000};
00626 
00627 /* takes an XeY precision/size value, returns a string representation. */
00628 static const char *
00629 precsize_ntoa (u_int8_t prec)
00630 {
00631        static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */
00632        unsigned long val;
00633        int mantissa, exponent;
00634 
00635        mantissa = (int)((prec >> 4) & 0x0f) % 10;
00636        exponent = (int)((prec >> 0) & 0x0f) % 10;
00637 
00638        val = mantissa * poweroften[exponent];
00639 
00640        (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
00641        return (retbuf);
00642 }
00643 
00644 /* converts ascii size/precision X * 10**Y(cm) to 0xXY.  moves pointer. */
00645 static u_int8_t
00646 precsize_aton (const char **strptr)
00647 {
00648        unsigned int mval = 0, cmval = 0;
00649        u_int8_t retval = 0;
00650        const char *cp;
00651        int exponent;
00652        int mantissa;
00653 
00654        cp = *strptr;
00655 
00656        while (isdigit(*cp))
00657               mval = mval * 10 + (*cp++ - '0');
00658 
00659        if (*cp == '.') {           /* centimeters */
00660               cp++;
00661               if (isdigit(*cp)) {
00662                      cmval = (*cp++ - '0') * 10;
00663                      if (isdigit(*cp)) {
00664                             cmval += (*cp++ - '0');
00665                      }
00666               }
00667        }
00668        cmval = (mval * 100) + cmval;
00669 
00670        for (exponent = 0; exponent < 9; exponent++)
00671               if (cmval < poweroften[exponent+1])
00672                      break;
00673 
00674        mantissa = cmval / poweroften[exponent];
00675        if (mantissa > 9)
00676               mantissa = 9;
00677 
00678        retval = (mantissa << 4) | exponent;
00679 
00680        *strptr = cp;
00681 
00682        return (retval);
00683 }
00684 
00685 /* converts ascii lat/lon to unsigned encoded 32-bit number.  moves pointer. */
00686 static u_int32_t
00687 latlon2ul (const char **latlonstrptr, int *which)
00688 {
00689        const char *cp;
00690        u_int32_t retval;
00691        int deg = 0, min = 0, secs = 0, secsfrac = 0;
00692 
00693        cp = *latlonstrptr;
00694 
00695        while (isdigit(*cp))
00696               deg = deg * 10 + (*cp++ - '0');
00697 
00698        while (isspace(*cp))
00699               cp++;
00700 
00701        if (!(isdigit(*cp)))
00702               goto fndhemi;
00703 
00704        while (isdigit(*cp))
00705               min = min * 10 + (*cp++ - '0');
00706 
00707        while (isspace(*cp))
00708               cp++;
00709 
00710        if (!(isdigit(*cp)))
00711               goto fndhemi;
00712 
00713        while (isdigit(*cp))
00714               secs = secs * 10 + (*cp++ - '0');
00715 
00716        if (*cp == '.') {           /* decimal seconds */
00717               cp++;
00718               if (isdigit(*cp)) {
00719                      secsfrac = (*cp++ - '0') * 100;
00720                      if (isdigit(*cp)) {
00721                             secsfrac += (*cp++ - '0') * 10;
00722                             if (isdigit(*cp)) {
00723                                    secsfrac += (*cp++ - '0');
00724                             }
00725                      }
00726               }
00727        }
00728 
00729        while (!isspace(*cp))       /* if any trailing garbage */
00730               cp++;
00731 
00732        while (isspace(*cp))
00733               cp++;
00734 
00735  fndhemi:
00736        switch (*cp) {
00737        case 'N': case 'n':
00738        case 'E': case 'e':
00739               retval = ((unsigned)1<<31)
00740                      + (((((deg * 60) + min) * 60) + secs) * 1000)
00741                      + secsfrac;
00742               break;
00743        case 'S': case 's':
00744        case 'W': case 'w':
00745               retval = ((unsigned)1<<31)
00746                      - (((((deg * 60) + min) * 60) + secs) * 1000)
00747                      - secsfrac;
00748               break;
00749        default:
00750               retval = 0;   /* invalid value -- indicates error */
00751               break;
00752        }
00753 
00754        switch (*cp) {
00755        case 'N': case 'n':
00756        case 'S': case 's':
00757               *which = 1;   /* latitude */
00758               break;
00759        case 'E': case 'e':
00760        case 'W': case 'w':
00761               *which = 2;   /* longitude */
00762               break;
00763        default:
00764               *which = 0;   /* error */
00765               break;
00766        }
00767 
00768        cp++;                /* skip the hemisphere */
00769 
00770        while (!isspace(*cp))       /* if any trailing garbage */
00771               cp++;
00772 
00773        while (isspace(*cp)) /* move to next field */
00774               cp++;
00775 
00776        *latlonstrptr = cp;
00777 
00778        return (retval);
00779 }
00780 
00781 /* converts a zone file representation in a string to an RDATA on-the-wire
00782  * representation. */
00783 int
00784 loc_aton(ascii, binary)
00785        const char *ascii;
00786        u_char *binary;
00787 {
00788        const char *cp, *maxcp;
00789        u_char *bcp;
00790 
00791        u_int32_t latit = 0, longit = 0, alt = 0;
00792        u_int32_t lltemp1 = 0, lltemp2 = 0;
00793        int altmeters = 0, altfrac = 0, altsign = 1;
00794        u_int8_t hp = 0x16;  /* default = 1e6 cm = 10000.00m = 10km */
00795        u_int8_t vp = 0x13;  /* default = 1e3 cm = 10.00m */
00796        u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
00797        int which1 = 0, which2 = 0;
00798 
00799        cp = ascii;
00800        maxcp = cp + strlen(ascii);
00801 
00802        lltemp1 = latlon2ul(&cp, &which1);
00803 
00804        lltemp2 = latlon2ul(&cp, &which2);
00805 
00806        switch (which1 + which2) {
00807        case 3:                     /* 1 + 2, the only valid combination */
00808               if ((which1 == 1) && (which2 == 2)) { /* normal case */
00809                      latit = lltemp1;
00810                      longit = lltemp2;
00811               } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
00812                      longit = lltemp1;
00813                      latit = lltemp2;
00814               } else {      /* some kind of brokenness */
00815                      return (0);
00816               }
00817               break;
00818        default:             /* we didn't get one of each */
00819               return (0);
00820        }
00821 
00822        /* altitude */
00823        if (*cp == '-') {
00824               altsign = -1;
00825               cp++;
00826        }
00827 
00828        if (*cp == '+')
00829               cp++;
00830 
00831        while (isdigit(*cp))
00832               altmeters = altmeters * 10 + (*cp++ - '0');
00833 
00834        if (*cp == '.') {           /* decimal meters */
00835               cp++;
00836               if (isdigit(*cp)) {
00837                      altfrac = (*cp++ - '0') * 10;
00838                      if (isdigit(*cp)) {
00839                             altfrac += (*cp++ - '0');
00840                      }
00841               }
00842        }
00843 
00844        alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
00845 
00846        while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
00847               cp++;
00848 
00849        while (isspace(*cp) && (cp < maxcp))
00850               cp++;
00851 
00852        if (cp >= maxcp)
00853               goto defaults;
00854 
00855        siz = precsize_aton(&cp);
00856 
00857        while (!isspace(*cp) && (cp < maxcp))     /* if trailing garbage or m */
00858               cp++;
00859 
00860        while (isspace(*cp) && (cp < maxcp))
00861               cp++;
00862 
00863        if (cp >= maxcp)
00864               goto defaults;
00865 
00866        hp = precsize_aton(&cp);
00867 
00868        while (!isspace(*cp) && (cp < maxcp))     /* if trailing garbage or m */
00869               cp++;
00870 
00871        while (isspace(*cp) && (cp < maxcp))
00872               cp++;
00873 
00874        if (cp >= maxcp)
00875               goto defaults;
00876 
00877        vp = precsize_aton(&cp);
00878 
00879  defaults:
00880 
00881        bcp = binary;
00882        *bcp++ = (u_int8_t) 0;      /* version byte */
00883        *bcp++ = siz;
00884        *bcp++ = hp;
00885        *bcp++ = vp;
00886        PUTLONG(latit,bcp);
00887        PUTLONG(longit,bcp);
00888        PUTLONG(alt,bcp);
00889 
00890        return (16);         /* size of RR in octets */
00891 }
00892 
00893 /* takes an on-the-wire LOC RR and formats it in a human readable format. */
00894 const char *
00895 loc_ntoa(binary, ascii)
00896        const u_char *binary;
00897        char *ascii;
00898 {
00899        static const char error[] = "?";
00900        static char tmpbuf[sizeof
00901 "1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
00902        const u_char *cp = binary;
00903 
00904        int latdeg, latmin, latsec, latsecfrac;
00905        int longdeg, longmin, longsec, longsecfrac;
00906        char northsouth, eastwest;
00907        int altmeters, altfrac, altsign;
00908 
00909        const u_int32_t referencealt = 100000 * 100;
00910 
00911        int32_t latval, longval, altval;
00912        u_int32_t templ;
00913        u_int8_t sizeval, hpval, vpval, versionval;
00914 
00915        char *sizestr, *hpstr, *vpstr;
00916 
00917        versionval = *cp++;
00918 
00919        if (ascii == NULL)
00920               ascii = tmpbuf;
00921 
00922        if (versionval) {
00923               (void) sprintf(ascii, "; error: unknown LOC RR version");
00924               return (ascii);
00925        }
00926 
00927        sizeval = *cp++;
00928 
00929        hpval = *cp++;
00930        vpval = *cp++;
00931 
00932        GETLONG(templ, cp);
00933        latval = (templ - ((unsigned)1<<31));
00934 
00935        GETLONG(templ, cp);
00936        longval = (templ - ((unsigned)1<<31));
00937 
00938        GETLONG(templ, cp);
00939        if (templ < referencealt) { /* below WGS 84 spheroid */
00940               altval = referencealt - templ;
00941               altsign = -1;
00942        } else {
00943               altval = templ - referencealt;
00944               altsign = 1;
00945        }
00946 
00947        if (latval < 0) {
00948               northsouth = 'S';
00949               latval = -latval;
00950        } else
00951               northsouth = 'N';
00952 
00953        latsecfrac = latval % 1000;
00954        latval = latval / 1000;
00955        latsec = latval % 60;
00956        latval = latval / 60;
00957        latmin = latval % 60;
00958        latval = latval / 60;
00959        latdeg = latval;
00960 
00961        if (longval < 0) {
00962               eastwest = 'W';
00963               longval = -longval;
00964        } else
00965               eastwest = 'E';
00966 
00967        longsecfrac = longval % 1000;
00968        longval = longval / 1000;
00969        longsec = longval % 60;
00970        longval = longval / 60;
00971        longmin = longval % 60;
00972        longval = longval / 60;
00973        longdeg = longval;
00974 
00975        altfrac = altval % 100;
00976        altmeters = (altval / 100) * altsign;
00977 
00978        if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
00979               sizestr = (char *) error;
00980        if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
00981               hpstr = (char *) error;
00982        if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
00983               vpstr = (char *) error;
00984 
00985        sprintf(ascii,
00986              "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
00987               latdeg, latmin, latsec, latsecfrac, northsouth,
00988               longdeg, longmin, longsec, longsecfrac, eastwest,
00989               altmeters, altfrac, sizestr, hpstr, vpstr);
00990 
00991        if (sizestr != (char *) error)
00992               free(sizestr);
00993        if (hpstr != (char *) error)
00994               free(hpstr);
00995        if (vpstr != (char *) error)
00996               free(vpstr);
00997 
00998        return (ascii);
00999 }
01000 libresolv_hidden_def (loc_ntoa)
01001 
01002 
01003 /* Return the number of DNS hierarchy levels in the name. */
01004 int
01005 dn_count_labels(const char *name) {
01006        int i, len, count;
01007 
01008        len = strlen(name);
01009        for (i = 0, count = 0; i < len; i++) {
01010               /* XXX need to check for \. or use named's nlabels(). */
01011               if (name[i] == '.')
01012                      count++;
01013        }
01014 
01015        /* don't count initial wildcard */
01016        if (name[0] == '*')
01017               if (count)
01018                      count--;
01019 
01020        /* don't count the null label for root. */
01021        /* if terminating '.' not found, must adjust */
01022        /* count to include last label */
01023        if (len > 0 && name[len-1] != '.')
01024               count++;
01025        return (count);
01026 }
01027 libresolv_hidden_def (__dn_count_labels)
01028 
01029 
01030 /*
01031  * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
01032  * SIG records are required to be printed like this, by the Secure DNS RFC.
01033  */
01034 char *
01035 p_secstodate (u_long secs) {
01036        /* XXX nonreentrant */
01037        static char output[15];            /* YYYYMMDDHHMMSS and null */
01038        time_t clock = secs;
01039        struct tm *time;
01040 
01041 #ifdef HAVE_TIME_R
01042        struct tm timebuf;
01043 
01044        time = gmtime_r(&clock, &timebuf);
01045 #else
01046        time = gmtime(&clock);
01047 #endif
01048        time->tm_year += 1900;
01049        time->tm_mon += 1;
01050        sprintf(output, "%04d%02d%02d%02d%02d%02d",
01051               time->tm_year, time->tm_mon, time->tm_mday,
01052               time->tm_hour, time->tm_min, time->tm_sec);
01053        return (output);
01054 }
01055 libresolv_hidden_def (__p_secstodate)