1156952Sume/* 2269867Sume * Portions Copyright (C) 2004, 2005, 2008, 2009 Internet Systems Consortium, Inc. ("ISC") 3269867Sume * Portions Copyright (C) 1996-2003 Internet Software Consortium. 4269867Sume * 5269867Sume * Permission to use, copy, modify, and/or distribute this software for any 6269867Sume * purpose with or without fee is hereby granted, provided that the above 7269867Sume * copyright notice and this permission notice appear in all copies. 8269867Sume * 9269867Sume * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10269867Sume * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11269867Sume * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12269867Sume * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13269867Sume * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14269867Sume * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15269867Sume * PERFORMANCE OF THIS SOFTWARE. 16269867Sume */ 17269867Sume 18331722Seadler/* 19156952Sume * Copyright (c) 1985 20156952Sume * The Regents of the University of California. All rights reserved. 21269867Sume * 22156952Sume * Redistribution and use in source and binary forms, with or without 23156952Sume * modification, are permitted provided that the following conditions 24156952Sume * are met: 25156952Sume * 1. Redistributions of source code must retain the above copyright 26156952Sume * notice, this list of conditions and the following disclaimer. 27156952Sume * 2. Redistributions in binary form must reproduce the above copyright 28156952Sume * notice, this list of conditions and the following disclaimer in the 29156952Sume * documentation and/or other materials provided with the distribution. 30156952Sume * 4. Neither the name of the University nor the names of its contributors 31156952Sume * may be used to endorse or promote products derived from this software 32156952Sume * without specific prior written permission. 33269867Sume * 34156952Sume * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 35156952Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36156952Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37156952Sume * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 38156952Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39156952Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40156952Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41156952Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42156952Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43156952Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44156952Sume * SUCH DAMAGE. 45156952Sume */ 46156952Sume 47156952Sume/* 48156952Sume * Portions Copyright (c) 1993 by Digital Equipment Corporation. 49269867Sume * 50156952Sume * Permission to use, copy, modify, and distribute this software for any 51156952Sume * purpose with or without fee is hereby granted, provided that the above 52156952Sume * copyright notice and this permission notice appear in all copies, and that 53156952Sume * the name of Digital Equipment Corporation not be used in advertising or 54156952Sume * publicity pertaining to distribution of the document or software without 55156952Sume * specific, written prior permission. 56269867Sume * 57156952Sume * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 58156952Sume * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 59156952Sume * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 60156952Sume * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 61156952Sume * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 62156952Sume * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 63156952Sume * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 64156952Sume * SOFTWARE. 65156952Sume */ 66156952Sume 67156952Sume/* 68156952Sume * Portions Copyright (c) 1995 by International Business Machines, Inc. 69156952Sume * 70156952Sume * International Business Machines, Inc. (hereinafter called IBM) grants 71156952Sume * permission under its copyrights to use, copy, modify, and distribute this 72156952Sume * Software with or without fee, provided that the above copyright notice and 73156952Sume * all paragraphs of this notice appear in all copies, and that the name of IBM 74156952Sume * not be used in connection with the marketing of any product incorporating 75156952Sume * the Software or modifications thereof, without specific, written prior 76156952Sume * permission. 77156952Sume * 78156952Sume * To the extent it has a right to do so, IBM grants an immunity from suit 79156952Sume * under its patents, if any, for the use, sale or manufacture of products to 80156952Sume * the extent that such products are used for performing Domain Name System 81156952Sume * dynamic updates in TCP/IP networks by means of the Software. No immunity is 82156952Sume * granted for any product per se or for any other function of any product. 83156952Sume * 84156952Sume * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 85156952Sume * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 86156952Sume * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 87156952Sume * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 88156952Sume * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 89156952Sume * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 90156952Sume */ 91156952Sume 92156952Sume#if defined(LIBC_SCCS) && !defined(lint) 93156952Sumestatic const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; 94269867Sumestatic const char rcsid[] = "$Id: res_debug.c,v 1.19 2009/02/26 11:20:20 tbox Exp $"; 95156952Sume#endif /* LIBC_SCCS and not lint */ 96156956Sume#include <sys/cdefs.h> 97156956Sume__FBSDID("$FreeBSD$"); 98156952Sume 99156952Sume#include "port_before.h" 100156952Sume 101156952Sume#include <sys/param.h> 102156952Sume#include <sys/socket.h> 103156952Sume 104156952Sume#include <netinet/in.h> 105156952Sume#include <arpa/inet.h> 106156952Sume#include <arpa/nameser.h> 107156952Sume 108156952Sume#include <ctype.h> 109156952Sume#include <errno.h> 110156952Sume#include <math.h> 111156952Sume#include <netdb.h> 112156952Sume#include <resolv.h> 113156952Sume#include <resolv_mt.h> 114156952Sume#include <stdio.h> 115156952Sume#include <stdlib.h> 116156952Sume#include <string.h> 117156952Sume#include <time.h> 118156952Sume 119156952Sume#include "port_after.h" 120156952Sume 121156952Sume#ifdef SPRINTF_CHAR 122156952Sume# define SPRINTF(x) strlen(sprintf/**/x) 123156952Sume#else 124156952Sume# define SPRINTF(x) sprintf x 125156952Sume#endif 126156952Sume 127156952Sumeextern const char *_res_opcodes[]; 128156952Sumeextern const char *_res_sectioncodes[]; 129156952Sume 130170244Sume/*% 131156952Sume * Print the current options. 132156952Sume */ 133156952Sumevoid 134156952Sumefp_resstat(const res_state statp, FILE *file) { 135156952Sume u_long mask; 136156952Sume 137156952Sume fprintf(file, ";; res options:"); 138156952Sume for (mask = 1; mask != 0U; mask <<= 1) 139156952Sume if (statp->options & mask) 140156952Sume fprintf(file, " %s", p_option(mask)); 141156952Sume putc('\n', file); 142156952Sume} 143156952Sume 144156952Sumestatic void 145156952Sumedo_section(const res_state statp, 146156952Sume ns_msg *handle, ns_sect section, 147156952Sume int pflag, FILE *file) 148156952Sume{ 149156952Sume int n, sflag, rrnum; 150156952Sume static int buflen = 2048; 151156952Sume char *buf; 152156952Sume ns_opcode opcode; 153156952Sume ns_rr rr; 154156952Sume 155156952Sume /* 156156952Sume * Print answer records. 157156952Sume */ 158156952Sume sflag = (statp->pfcode & pflag); 159156952Sume if (statp->pfcode && !sflag) 160156952Sume return; 161156952Sume 162156952Sume buf = malloc(buflen); 163156952Sume if (buf == NULL) { 164156952Sume fprintf(file, ";; memory allocation failure\n"); 165156952Sume return; 166156952Sume } 167156952Sume 168156952Sume opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode); 169156952Sume rrnum = 0; 170156952Sume for (;;) { 171156952Sume if (ns_parserr(handle, section, rrnum, &rr)) { 172156952Sume if (errno != ENODEV) 173156952Sume fprintf(file, ";; ns_parserr: %s\n", 174156952Sume strerror(errno)); 175156952Sume else if (rrnum > 0 && sflag != 0 && 176156952Sume (statp->pfcode & RES_PRF_HEAD1)) 177156952Sume putc('\n', file); 178156952Sume goto cleanup; 179156952Sume } 180156952Sume if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) 181156952Sume fprintf(file, ";; %s SECTION:\n", 182156952Sume p_section(section, opcode)); 183156952Sume if (section == ns_s_qd) 184156952Sume fprintf(file, ";;\t%s, type = %s, class = %s\n", 185156952Sume ns_rr_name(rr), 186156952Sume p_type(ns_rr_type(rr)), 187156952Sume p_class(ns_rr_class(rr))); 188156952Sume else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) { 189186090Sume u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr); 190156952Sume u_int32_t ttl = ns_rr_ttl(rr); 191186090Sume 192156952Sume fprintf(file, 193156952Sume "; EDNS: version: %u, udp=%u, flags=%04x\n", 194156952Sume (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff); 195186090Sume 196186090Sume while (rdatalen >= 4) { 197186090Sume const u_char *cp = ns_rr_rdata(rr); 198186090Sume int i; 199186090Sume 200186090Sume GETSHORT(optcode, cp); 201186090Sume GETSHORT(optlen, cp); 202186090Sume 203186090Sume if (optcode == NS_OPT_NSID) { 204186090Sume fputs("; NSID: ", file); 205186090Sume if (optlen == 0) { 206186090Sume fputs("; NSID\n", file); 207186090Sume } else { 208186090Sume fputs("; NSID: ", file); 209186090Sume for (i = 0; i < optlen; i++) 210186090Sume fprintf(file, "%02x ", 211186090Sume cp[i]); 212186090Sume fputs(" (",file); 213186090Sume for (i = 0; i < optlen; i++) 214186090Sume fprintf(file, "%c", 215186090Sume isprint(cp[i])? 216186090Sume cp[i] : '.'); 217186090Sume fputs(")\n", file); 218186090Sume } 219186090Sume } else { 220186090Sume if (optlen == 0) { 221186090Sume fprintf(file, "; OPT=%u\n", 222186090Sume optcode); 223186090Sume } else { 224186090Sume fprintf(file, "; OPT=%u: ", 225186090Sume optcode); 226186090Sume for (i = 0; i < optlen; i++) 227186090Sume fprintf(file, "%02x ", 228186090Sume cp[i]); 229186090Sume fputs(" (",file); 230186090Sume for (i = 0; i < optlen; i++) 231186090Sume fprintf(file, "%c", 232186090Sume isprint(cp[i]) ? 233186090Sume cp[i] : '.'); 234186090Sume fputs(")\n", file); 235186090Sume } 236186090Sume } 237186090Sume rdatalen -= 4 + optlen; 238186090Sume } 239156952Sume } else { 240156952Sume n = ns_sprintrr(handle, &rr, NULL, NULL, 241156952Sume buf, buflen); 242156952Sume if (n < 0) { 243156952Sume if (errno == ENOSPC) { 244156952Sume free(buf); 245156952Sume buf = NULL; 246156952Sume if (buflen < 131072) 247156952Sume buf = malloc(buflen += 1024); 248156952Sume if (buf == NULL) { 249156952Sume fprintf(file, 250186090Sume ";; memory allocation failure\n"); 251156952Sume return; 252156952Sume } 253156952Sume continue; 254156952Sume } 255156952Sume fprintf(file, ";; ns_sprintrr: %s\n", 256156952Sume strerror(errno)); 257156952Sume goto cleanup; 258156952Sume } 259156952Sume fputs(buf, file); 260156952Sume fputc('\n', file); 261156952Sume } 262156952Sume rrnum++; 263156952Sume } 264156952Sume cleanup: 265156952Sume if (buf != NULL) 266156952Sume free(buf); 267156952Sume} 268156952Sume 269170244Sume/*% 270156952Sume * Print the contents of a query. 271156952Sume * This is intended to be primarily a debugging routine. 272156952Sume */ 273156952Sumevoid 274156952Sumeres_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { 275156952Sume ns_msg handle; 276156952Sume int qdcount, ancount, nscount, arcount; 277156952Sume u_int opcode, rcode, id; 278156952Sume 279156952Sume if (ns_initparse(msg, len, &handle) < 0) { 280156952Sume fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); 281156952Sume return; 282156952Sume } 283156952Sume opcode = ns_msg_getflag(handle, ns_f_opcode); 284156952Sume rcode = ns_msg_getflag(handle, ns_f_rcode); 285156952Sume id = ns_msg_id(handle); 286156952Sume qdcount = ns_msg_count(handle, ns_s_qd); 287156952Sume ancount = ns_msg_count(handle, ns_s_an); 288156952Sume nscount = ns_msg_count(handle, ns_s_ns); 289156952Sume arcount = ns_msg_count(handle, ns_s_ar); 290156952Sume 291156952Sume /* 292156952Sume * Print header fields. 293156952Sume */ 294156952Sume if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode) 295156952Sume fprintf(file, 296156952Sume ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", 297156952Sume _res_opcodes[opcode], p_rcode(rcode), id); 298156952Sume if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX)) 299156952Sume putc(';', file); 300156952Sume if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) { 301156952Sume fprintf(file, "; flags:"); 302156952Sume if (ns_msg_getflag(handle, ns_f_qr)) 303156952Sume fprintf(file, " qr"); 304156952Sume if (ns_msg_getflag(handle, ns_f_aa)) 305156952Sume fprintf(file, " aa"); 306156952Sume if (ns_msg_getflag(handle, ns_f_tc)) 307156952Sume fprintf(file, " tc"); 308156952Sume if (ns_msg_getflag(handle, ns_f_rd)) 309156952Sume fprintf(file, " rd"); 310156952Sume if (ns_msg_getflag(handle, ns_f_ra)) 311156952Sume fprintf(file, " ra"); 312156952Sume if (ns_msg_getflag(handle, ns_f_z)) 313156952Sume fprintf(file, " ??"); 314156952Sume if (ns_msg_getflag(handle, ns_f_ad)) 315156952Sume fprintf(file, " ad"); 316156952Sume if (ns_msg_getflag(handle, ns_f_cd)) 317156952Sume fprintf(file, " cd"); 318156952Sume } 319156952Sume if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) { 320156952Sume fprintf(file, "; %s: %d", 321156952Sume p_section(ns_s_qd, opcode), qdcount); 322156952Sume fprintf(file, ", %s: %d", 323156952Sume p_section(ns_s_an, opcode), ancount); 324156952Sume fprintf(file, ", %s: %d", 325156952Sume p_section(ns_s_ns, opcode), nscount); 326156952Sume fprintf(file, ", %s: %d", 327156952Sume p_section(ns_s_ar, opcode), arcount); 328156952Sume } 329269867Sume if ((!statp->pfcode) || (statp->pfcode & 330156952Sume (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { 331156952Sume putc('\n',file); 332156952Sume } 333156952Sume /* 334156952Sume * Print the various sections. 335156952Sume */ 336156952Sume do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file); 337156952Sume do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file); 338156952Sume do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file); 339156952Sume do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file); 340156952Sume if (qdcount == 0 && ancount == 0 && 341156952Sume nscount == 0 && arcount == 0) 342156952Sume putc('\n', file); 343156952Sume} 344156952Sume 345156952Sumeconst u_char * 346156952Sumep_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { 347156952Sume char name[MAXDNAME]; 348156952Sume int n; 349156952Sume 350156952Sume if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) 351156952Sume return (NULL); 352156952Sume if (name[0] == '\0') 353156952Sume putc('.', file); 354156952Sume else 355156952Sume fputs(name, file); 356156952Sume return (cp + n); 357156952Sume} 358156952Sume 359156952Sumeconst u_char * 360156952Sumep_cdname(const u_char *cp, const u_char *msg, FILE *file) { 361156952Sume return (p_cdnname(cp, msg, PACKETSZ, file)); 362156952Sume} 363156952Sume 364170244Sume/*% 365170244Sume * Return a fully-qualified domain name from a compressed name (with 366156952Sume length supplied). */ 367156952Sume 368156952Sumeconst u_char * 369288114Srodrigcp_fqnname(const u_char *cp, const u_char *msg, int msglen, char *name, 370288114Srodrigc int namelen) 371156952Sume{ 372156952Sume int n, newlen; 373156952Sume 374156952Sume if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) 375156952Sume return (NULL); 376156952Sume newlen = strlen(name); 377156952Sume if (newlen == 0 || name[newlen - 1] != '.') { 378170244Sume if (newlen + 1 >= namelen) /*%< Lack space for final dot */ 379156952Sume return (NULL); 380156952Sume else 381156952Sume strcpy(name + newlen, "."); 382156952Sume } 383156952Sume return (cp + n); 384156952Sume} 385156952Sume 386156952Sume/* XXX: the rest of these functions need to become length-limited, too. */ 387156952Sume 388156952Sumeconst u_char * 389156952Sumep_fqname(const u_char *cp, const u_char *msg, FILE *file) { 390156952Sume char name[MAXDNAME]; 391156952Sume const u_char *n; 392156952Sume 393156952Sume n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); 394156952Sume if (n == NULL) 395156952Sume return (NULL); 396156952Sume fputs(name, file); 397156952Sume return (n); 398156952Sume} 399156952Sume 400170244Sume/*% 401156952Sume * Names of RR classes and qclasses. Classes and qclasses are the same, except 402156952Sume * that C_ANY is a qclass but not a class. (You can ask for records of class 403156952Sume * C_ANY, but you can't have any records of that class in the database.) 404156952Sume */ 405156952Sumeconst struct res_sym __p_class_syms[] = { 406156952Sume {C_IN, "IN", (char *)0}, 407156952Sume {C_CHAOS, "CH", (char *)0}, 408156952Sume {C_CHAOS, "CHAOS", (char *)0}, 409156952Sume {C_HS, "HS", (char *)0}, 410156952Sume {C_HS, "HESIOD", (char *)0}, 411156952Sume {C_ANY, "ANY", (char *)0}, 412156952Sume {C_NONE, "NONE", (char *)0}, 413156952Sume {C_IN, (char *)0, (char *)0} 414156952Sume}; 415156952Sume 416170244Sume/*% 417156952Sume * Names of message sections. 418156952Sume */ 419156956Sumestatic const struct res_sym __p_default_section_syms[] = { 420156952Sume {ns_s_qd, "QUERY", (char *)0}, 421156952Sume {ns_s_an, "ANSWER", (char *)0}, 422156952Sume {ns_s_ns, "AUTHORITY", (char *)0}, 423156952Sume {ns_s_ar, "ADDITIONAL", (char *)0}, 424186090Sume {0, (char *)0, (char *)0} 425156952Sume}; 426156952Sume 427156956Sumestatic const struct res_sym __p_update_section_syms[] = { 428156952Sume {S_ZONE, "ZONE", (char *)0}, 429156952Sume {S_PREREQ, "PREREQUISITE", (char *)0}, 430156952Sume {S_UPDATE, "UPDATE", (char *)0}, 431156952Sume {S_ADDT, "ADDITIONAL", (char *)0}, 432186090Sume {0, (char *)0, (char *)0} 433156952Sume}; 434156952Sume 435156952Sumeconst struct res_sym __p_key_syms[] = { 436156952Sume {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"}, 437156952Sume {NS_ALG_DH, "DH", "Diffie Hellman"}, 438156952Sume {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"}, 439156952Sume {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"}, 440156952Sume {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"}, 441156952Sume {0, NULL, NULL} 442156952Sume}; 443156952Sume 444156952Sumeconst struct res_sym __p_cert_syms[] = { 445156952Sume {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"}, 446156952Sume {cert_t_spki, "SPKI", "SPKI certificate"}, 447156952Sume {cert_t_pgp, "PGP", "PGP certificate"}, 448156952Sume {cert_t_url, "URL", "URL Private"}, 449156952Sume {cert_t_oid, "OID", "OID Private"}, 450156952Sume {0, NULL, NULL} 451156952Sume}; 452156952Sume 453170244Sume/*% 454156952Sume * Names of RR types and qtypes. Types and qtypes are the same, except 455156952Sume * that T_ANY is a qtype but not a type. (You can ask for records of type 456156952Sume * T_ANY, but you can't have any records of that type in the database.) 457156952Sume */ 458156952Sumeconst struct res_sym __p_type_syms[] = { 459156952Sume {ns_t_a, "A", "address"}, 460156952Sume {ns_t_ns, "NS", "name server"}, 461156952Sume {ns_t_md, "MD", "mail destination (deprecated)"}, 462156952Sume {ns_t_mf, "MF", "mail forwarder (deprecated)"}, 463156952Sume {ns_t_cname, "CNAME", "canonical name"}, 464156952Sume {ns_t_soa, "SOA", "start of authority"}, 465156952Sume {ns_t_mb, "MB", "mailbox"}, 466156952Sume {ns_t_mg, "MG", "mail group member"}, 467156952Sume {ns_t_mr, "MR", "mail rename"}, 468156952Sume {ns_t_null, "NULL", "null"}, 469156952Sume {ns_t_wks, "WKS", "well-known service (deprecated)"}, 470156952Sume {ns_t_ptr, "PTR", "domain name pointer"}, 471156952Sume {ns_t_hinfo, "HINFO", "host information"}, 472156952Sume {ns_t_minfo, "MINFO", "mailbox information"}, 473156952Sume {ns_t_mx, "MX", "mail exchanger"}, 474156952Sume {ns_t_txt, "TXT", "text"}, 475156952Sume {ns_t_rp, "RP", "responsible person"}, 476156952Sume {ns_t_afsdb, "AFSDB", "DCE or AFS server"}, 477156952Sume {ns_t_x25, "X25", "X25 address"}, 478156952Sume {ns_t_isdn, "ISDN", "ISDN address"}, 479156952Sume {ns_t_rt, "RT", "router"}, 480156952Sume {ns_t_nsap, "NSAP", "nsap address"}, 481156952Sume {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"}, 482156952Sume {ns_t_sig, "SIG", "signature"}, 483156952Sume {ns_t_key, "KEY", "key"}, 484156952Sume {ns_t_px, "PX", "mapping information"}, 485156952Sume {ns_t_gpos, "GPOS", "geographical position (withdrawn)"}, 486156952Sume {ns_t_aaaa, "AAAA", "IPv6 address"}, 487156952Sume {ns_t_loc, "LOC", "location"}, 488156952Sume {ns_t_nxt, "NXT", "next valid name (unimplemented)"}, 489156952Sume {ns_t_eid, "EID", "endpoint identifier (unimplemented)"}, 490156952Sume {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"}, 491156952Sume {ns_t_srv, "SRV", "server selection"}, 492156952Sume {ns_t_atma, "ATMA", "ATM address (unimplemented)"}, 493269867Sume {ns_t_naptr, "NAPTR", "naptr"}, 494269867Sume {ns_t_kx, "KX", "key exchange"}, 495269867Sume {ns_t_cert, "CERT", "certificate"}, 496269867Sume {ns_t_a6, "A", "IPv6 address (experminental)"}, 497269867Sume {ns_t_dname, "DNAME", "non-terminal redirection"}, 498269867Sume {ns_t_opt, "OPT", "opt"}, 499269867Sume {ns_t_apl, "apl", "apl"}, 500269867Sume {ns_t_ds, "DS", "delegation signer"}, 501269867Sume {ns_t_sshfp, "SSFP", "SSH fingerprint"}, 502269867Sume {ns_t_ipseckey, "IPSECKEY", "IPSEC key"}, 503269867Sume {ns_t_rrsig, "RRSIG", "rrsig"}, 504269867Sume {ns_t_nsec, "NSEC", "nsec"}, 505269867Sume {ns_t_dnskey, "DNSKEY", "DNS key"}, 506269867Sume {ns_t_dhcid, "DHCID", "dynamic host configuration identifier"}, 507269867Sume {ns_t_nsec3, "NSEC3", "nsec3"}, 508269867Sume {ns_t_nsec3param, "NSEC3PARAM", "NSEC3 parameters"}, 509269867Sume {ns_t_hip, "HIP", "host identity protocol"}, 510269867Sume {ns_t_spf, "SPF", "sender policy framework"}, 511156952Sume {ns_t_tkey, "TKEY", "tkey"}, 512156952Sume {ns_t_tsig, "TSIG", "transaction signature"}, 513156952Sume {ns_t_ixfr, "IXFR", "incremental zone transfer"}, 514156952Sume {ns_t_axfr, "AXFR", "zone transfer"}, 515156952Sume {ns_t_zxfr, "ZXFR", "compressed zone transfer"}, 516156952Sume {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"}, 517156952Sume {ns_t_maila, "MAILA", "mail agent (deprecated)"}, 518156952Sume {ns_t_naptr, "NAPTR", "URN Naming Authority"}, 519156952Sume {ns_t_kx, "KX", "Key Exchange"}, 520156952Sume {ns_t_cert, "CERT", "Certificate"}, 521156952Sume {ns_t_a6, "A6", "IPv6 Address"}, 522156952Sume {ns_t_dname, "DNAME", "dname"}, 523156952Sume {ns_t_sink, "SINK", "Kitchen Sink (experimental)"}, 524156952Sume {ns_t_opt, "OPT", "EDNS Options"}, 525156952Sume {ns_t_any, "ANY", "\"any\""}, 526269867Sume {ns_t_dlv, "DLV", "DNSSEC look-aside validation"}, 527156952Sume {0, NULL, NULL} 528156952Sume}; 529156952Sume 530170244Sume/*% 531156952Sume * Names of DNS rcodes. 532156952Sume */ 533168441Skanconst struct res_sym __p_rcode_syms[] = { 534156952Sume {ns_r_noerror, "NOERROR", "no error"}, 535156952Sume {ns_r_formerr, "FORMERR", "format error"}, 536156952Sume {ns_r_servfail, "SERVFAIL", "server failed"}, 537156952Sume {ns_r_nxdomain, "NXDOMAIN", "no such domain name"}, 538156952Sume {ns_r_notimpl, "NOTIMP", "not implemented"}, 539156952Sume {ns_r_refused, "REFUSED", "refused"}, 540156952Sume {ns_r_yxdomain, "YXDOMAIN", "domain name exists"}, 541156952Sume {ns_r_yxrrset, "YXRRSET", "rrset exists"}, 542156952Sume {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"}, 543156952Sume {ns_r_notauth, "NOTAUTH", "not authoritative"}, 544156952Sume {ns_r_notzone, "NOTZONE", "Not in zone"}, 545156952Sume {ns_r_max, "", ""}, 546156952Sume {ns_r_badsig, "BADSIG", "bad signature"}, 547156952Sume {ns_r_badkey, "BADKEY", "bad key"}, 548156952Sume {ns_r_badtime, "BADTIME", "bad time"}, 549156952Sume {0, NULL, NULL} 550156952Sume}; 551156952Sume 552156952Sumeint 553156952Sumesym_ston(const struct res_sym *syms, const char *name, int *success) { 554156952Sume for ((void)NULL; syms->name != 0; syms++) { 555156952Sume if (strcasecmp (name, syms->name) == 0) { 556156952Sume if (success) 557156952Sume *success = 1; 558156952Sume return (syms->number); 559156952Sume } 560156952Sume } 561156952Sume if (success) 562156952Sume *success = 0; 563170244Sume return (syms->number); /*%< The default value. */ 564156952Sume} 565156952Sume 566156952Sumeconst char * 567156952Sumesym_ntos(const struct res_sym *syms, int number, int *success) { 568156952Sume char *unname = sym_ntos_unname; 569156952Sume 570156952Sume for ((void)NULL; syms->name != 0; syms++) { 571156952Sume if (number == syms->number) { 572156952Sume if (success) 573156952Sume *success = 1; 574156952Sume return (syms->name); 575156952Sume } 576156952Sume } 577156952Sume 578170244Sume sprintf(unname, "%d", number); /*%< XXX nonreentrant */ 579156952Sume if (success) 580156952Sume *success = 0; 581156952Sume return (unname); 582156952Sume} 583156952Sume 584156952Sumeconst char * 585156952Sumesym_ntop(const struct res_sym *syms, int number, int *success) { 586156952Sume char *unname = sym_ntop_unname; 587156952Sume 588156952Sume for ((void)NULL; syms->name != 0; syms++) { 589156952Sume if (number == syms->number) { 590156952Sume if (success) 591156952Sume *success = 1; 592156952Sume return (syms->humanname); 593156952Sume } 594156952Sume } 595170244Sume sprintf(unname, "%d", number); /*%< XXX nonreentrant */ 596156952Sume if (success) 597156952Sume *success = 0; 598156952Sume return (unname); 599156952Sume} 600156952Sume 601170244Sume/*% 602156952Sume * Return a string for the type. 603156952Sume */ 604156952Sumeconst char * 605156952Sumep_type(int type) { 606156952Sume int success; 607156952Sume const char *result; 608156952Sume static char typebuf[20]; 609156952Sume 610156952Sume result = sym_ntos(__p_type_syms, type, &success); 611156952Sume if (success) 612156952Sume return (result); 613156952Sume if (type < 0 || type > 0xffff) 614156952Sume return ("BADTYPE"); 615156952Sume sprintf(typebuf, "TYPE%d", type); 616156952Sume return (typebuf); 617156952Sume} 618156952Sume 619170244Sume/*% 620156952Sume * Return a string for the type. 621156952Sume */ 622156952Sumeconst char * 623156952Sumep_section(int section, int opcode) { 624156952Sume const struct res_sym *symbols; 625156952Sume 626156952Sume switch (opcode) { 627156952Sume case ns_o_update: 628156952Sume symbols = __p_update_section_syms; 629156952Sume break; 630156952Sume default: 631156952Sume symbols = __p_default_section_syms; 632156952Sume break; 633156952Sume } 634156952Sume return (sym_ntos(symbols, section, (int *)0)); 635156952Sume} 636156952Sume 637170244Sume/*% 638156952Sume * Return a mnemonic for class. 639156952Sume */ 640156952Sumeconst char * 641156952Sumep_class(int class) { 642156952Sume int success; 643156952Sume const char *result; 644156952Sume static char classbuf[20]; 645156952Sume 646156952Sume result = sym_ntos(__p_class_syms, class, &success); 647156952Sume if (success) 648156952Sume return (result); 649156952Sume if (class < 0 || class > 0xffff) 650156952Sume return ("BADCLASS"); 651156952Sume sprintf(classbuf, "CLASS%d", class); 652156952Sume return (classbuf); 653156952Sume} 654156952Sume 655170244Sume/*% 656156952Sume * Return a mnemonic for an option 657156952Sume */ 658156952Sumeconst char * 659156952Sumep_option(u_long option) { 660156952Sume char *nbuf = p_option_nbuf; 661156952Sume 662156952Sume switch (option) { 663156952Sume case RES_INIT: return "init"; 664156952Sume case RES_DEBUG: return "debug"; 665156952Sume case RES_AAONLY: return "aaonly(unimpl)"; 666156952Sume case RES_USEVC: return "usevc"; 667156952Sume case RES_PRIMARY: return "primry(unimpl)"; 668156952Sume case RES_IGNTC: return "igntc"; 669156952Sume case RES_RECURSE: return "recurs"; 670156952Sume case RES_DEFNAMES: return "defnam"; 671156952Sume case RES_STAYOPEN: return "styopn"; 672156952Sume case RES_DNSRCH: return "dnsrch"; 673156952Sume case RES_INSECURE1: return "insecure1"; 674156952Sume case RES_INSECURE2: return "insecure2"; 675156952Sume case RES_NOALIASES: return "noaliases"; 676156952Sume case RES_USE_INET6: return "inet6"; 677170244Sume#ifdef RES_USE_EDNS0 /*%< KAME extension */ 678156952Sume case RES_USE_EDNS0: return "edns0"; 679186090Sume case RES_NSID: return "nsid"; 680156952Sume#endif 681156952Sume#ifdef RES_USE_DNAME 682156952Sume case RES_USE_DNAME: return "dname"; 683156952Sume#endif 684156952Sume#ifdef RES_USE_DNSSEC 685156952Sume case RES_USE_DNSSEC: return "dnssec"; 686156952Sume#endif 687156952Sume#ifdef RES_NOTLDQUERY 688156952Sume case RES_NOTLDQUERY: return "no-tld-query"; 689156952Sume#endif 690156952Sume#ifdef RES_NO_NIBBLE2 691156952Sume case RES_NO_NIBBLE2: return "no-nibble2"; 692156952Sume#endif 693156952Sume /* XXX nonreentrant */ 694156952Sume default: sprintf(nbuf, "?0x%lx?", (u_long)option); 695156952Sume return (nbuf); 696156952Sume } 697156952Sume} 698156952Sume 699170244Sume/*% 700156952Sume * Return a mnemonic for a time to live. 701156952Sume */ 702156952Sumeconst char * 703156952Sumep_time(u_int32_t value) { 704156952Sume char *nbuf = p_time_nbuf; 705156952Sume 706156952Sume if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) 707156952Sume sprintf(nbuf, "%u", value); 708156952Sume return (nbuf); 709156952Sume} 710156952Sume 711170244Sume/*% 712156952Sume * Return a string for the rcode. 713156952Sume */ 714156952Sumeconst char * 715156952Sumep_rcode(int rcode) { 716156952Sume return (sym_ntos(__p_rcode_syms, rcode, (int *)0)); 717156952Sume} 718156952Sume 719170244Sume/*% 720156952Sume * Return a string for a res_sockaddr_union. 721156952Sume */ 722156952Sumeconst char * 723156952Sumep_sockun(union res_sockaddr_union u, char *buf, size_t size) { 724156952Sume char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"]; 725156952Sume 726156952Sume switch (u.sin.sin_family) { 727156952Sume case AF_INET: 728156952Sume inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret); 729156952Sume break; 730156952Sume#ifdef HAS_INET6_STRUCTS 731156952Sume case AF_INET6: 732156952Sume inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret); 733156952Sume break; 734156952Sume#endif 735156952Sume default: 736156952Sume sprintf(ret, "[af%d]", u.sin.sin_family); 737156952Sume break; 738156952Sume } 739156952Sume if (size > 0U) { 740156952Sume strncpy(buf, ret, size - 1); 741156952Sume buf[size - 1] = '0'; 742156952Sume } 743156952Sume return (buf); 744156952Sume} 745156952Sume 746170244Sume/*% 747156952Sume * routines to convert between on-the-wire RR format and zone file format. 748156952Sume * Does not contain conversion to/from decimal degrees; divide or multiply 749156952Sume * by 60*60*1000 for that. 750156952Sume */ 751156952Sume 752156952Sumestatic unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, 753156952Sume 1000000,10000000,100000000,1000000000}; 754156952Sume 755170244Sume/*% takes an XeY precision/size value, returns a string representation. */ 756156952Sumestatic const char * 757288114Srodrigcprecsize_ntoa(u_int8_t prec) 758156952Sume{ 759156952Sume char *retbuf = precsize_ntoa_retbuf; 760156952Sume unsigned long val; 761156952Sume int mantissa, exponent; 762156952Sume 763156952Sume mantissa = (int)((prec >> 4) & 0x0f) % 10; 764156952Sume exponent = (int)((prec >> 0) & 0x0f) % 10; 765156952Sume 766156952Sume val = mantissa * poweroften[exponent]; 767156952Sume 768156952Sume (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100); 769156952Sume return (retbuf); 770156952Sume} 771156952Sume 772170244Sume/*% converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ 773156952Sumestatic u_int8_t 774156952Sumeprecsize_aton(const char **strptr) { 775156952Sume unsigned int mval = 0, cmval = 0; 776156952Sume u_int8_t retval = 0; 777156952Sume const char *cp; 778156952Sume int exponent; 779156952Sume int mantissa; 780156952Sume 781156952Sume cp = *strptr; 782156952Sume 783156952Sume while (isdigit((unsigned char)*cp)) 784156952Sume mval = mval * 10 + (*cp++ - '0'); 785156952Sume 786170244Sume if (*cp == '.') { /*%< centimeters */ 787156952Sume cp++; 788156952Sume if (isdigit((unsigned char)*cp)) { 789156952Sume cmval = (*cp++ - '0') * 10; 790156952Sume if (isdigit((unsigned char)*cp)) { 791156952Sume cmval += (*cp++ - '0'); 792156952Sume } 793156952Sume } 794156952Sume } 795156952Sume cmval = (mval * 100) + cmval; 796156952Sume 797156952Sume for (exponent = 0; exponent < 9; exponent++) 798156952Sume if (cmval < poweroften[exponent+1]) 799156952Sume break; 800156952Sume 801156952Sume mantissa = cmval / poweroften[exponent]; 802156952Sume if (mantissa > 9) 803156952Sume mantissa = 9; 804156952Sume 805156952Sume retval = (mantissa << 4) | exponent; 806156952Sume 807156952Sume *strptr = cp; 808156952Sume 809156952Sume return (retval); 810156952Sume} 811156952Sume 812170244Sume/*% converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */ 813156952Sumestatic u_int32_t 814156952Sumelatlon2ul(const char **latlonstrptr, int *which) { 815156952Sume const char *cp; 816156952Sume u_int32_t retval; 817156952Sume int deg = 0, min = 0, secs = 0, secsfrac = 0; 818156952Sume 819156952Sume cp = *latlonstrptr; 820156952Sume 821156952Sume while (isdigit((unsigned char)*cp)) 822156952Sume deg = deg * 10 + (*cp++ - '0'); 823156952Sume 824156952Sume while (isspace((unsigned char)*cp)) 825156952Sume cp++; 826156952Sume 827156952Sume if (!(isdigit((unsigned char)*cp))) 828156952Sume goto fndhemi; 829156952Sume 830156952Sume while (isdigit((unsigned char)*cp)) 831156952Sume min = min * 10 + (*cp++ - '0'); 832156952Sume 833156952Sume while (isspace((unsigned char)*cp)) 834156952Sume cp++; 835156952Sume 836156952Sume if (!(isdigit((unsigned char)*cp))) 837156952Sume goto fndhemi; 838156952Sume 839156952Sume while (isdigit((unsigned char)*cp)) 840156952Sume secs = secs * 10 + (*cp++ - '0'); 841156952Sume 842170244Sume if (*cp == '.') { /*%< decimal seconds */ 843156952Sume cp++; 844156952Sume if (isdigit((unsigned char)*cp)) { 845156952Sume secsfrac = (*cp++ - '0') * 100; 846156952Sume if (isdigit((unsigned char)*cp)) { 847156952Sume secsfrac += (*cp++ - '0') * 10; 848156952Sume if (isdigit((unsigned char)*cp)) { 849156952Sume secsfrac += (*cp++ - '0'); 850156952Sume } 851156952Sume } 852156952Sume } 853156952Sume } 854156952Sume 855170244Sume while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */ 856156952Sume cp++; 857156952Sume 858156952Sume while (isspace((unsigned char)*cp)) 859156952Sume cp++; 860156952Sume 861156952Sume fndhemi: 862156952Sume switch (*cp) { 863156952Sume case 'N': case 'n': 864156952Sume case 'E': case 'e': 865156952Sume retval = ((unsigned)1<<31) 866156952Sume + (((((deg * 60) + min) * 60) + secs) * 1000) 867156952Sume + secsfrac; 868156952Sume break; 869156952Sume case 'S': case 's': 870156952Sume case 'W': case 'w': 871156952Sume retval = ((unsigned)1<<31) 872156952Sume - (((((deg * 60) + min) * 60) + secs) * 1000) 873156952Sume - secsfrac; 874156952Sume break; 875156952Sume default: 876170244Sume retval = 0; /*%< invalid value -- indicates error */ 877156952Sume break; 878156952Sume } 879156952Sume 880156952Sume switch (*cp) { 881156952Sume case 'N': case 'n': 882156952Sume case 'S': case 's': 883170244Sume *which = 1; /*%< latitude */ 884156952Sume break; 885156952Sume case 'E': case 'e': 886156952Sume case 'W': case 'w': 887170244Sume *which = 2; /*%< longitude */ 888156952Sume break; 889156952Sume default: 890170244Sume *which = 0; /*%< error */ 891156952Sume break; 892156952Sume } 893156952Sume 894170244Sume cp++; /*%< skip the hemisphere */ 895170244Sume while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */ 896156952Sume cp++; 897156952Sume 898170244Sume while (isspace((unsigned char)*cp)) /*%< move to next field */ 899156952Sume cp++; 900156952Sume 901156952Sume *latlonstrptr = cp; 902156952Sume 903156952Sume return (retval); 904156952Sume} 905156952Sume 906170244Sume/*% 907170244Sume * converts a zone file representation in a string to an RDATA on-the-wire 908156952Sume * representation. */ 909156952Sumeint 910288114Srodrigcloc_aton(const char *ascii, u_char *binary) 911156952Sume{ 912156952Sume const char *cp, *maxcp; 913156952Sume u_char *bcp; 914156952Sume 915156952Sume u_int32_t latit = 0, longit = 0, alt = 0; 916156952Sume u_int32_t lltemp1 = 0, lltemp2 = 0; 917156952Sume int altmeters = 0, altfrac = 0, altsign = 1; 918170244Sume u_int8_t hp = 0x16; /*%< default = 1e6 cm = 10000.00m = 10km */ 919170244Sume u_int8_t vp = 0x13; /*%< default = 1e3 cm = 10.00m */ 920170244Sume u_int8_t siz = 0x12; /*%< default = 1e2 cm = 1.00m */ 921156952Sume int which1 = 0, which2 = 0; 922156952Sume 923156952Sume cp = ascii; 924156952Sume maxcp = cp + strlen(ascii); 925156952Sume 926156952Sume lltemp1 = latlon2ul(&cp, &which1); 927156952Sume 928156952Sume lltemp2 = latlon2ul(&cp, &which2); 929156952Sume 930156952Sume switch (which1 + which2) { 931170244Sume case 3: /*%< 1 + 2, the only valid combination */ 932170244Sume if ((which1 == 1) && (which2 == 2)) { /*%< normal case */ 933156952Sume latit = lltemp1; 934156952Sume longit = lltemp2; 935170244Sume } else if ((which1 == 2) && (which2 == 1)) { /*%< reversed */ 936156952Sume longit = lltemp1; 937156952Sume latit = lltemp2; 938170244Sume } else { /*%< some kind of brokenness */ 939156952Sume return (0); 940156952Sume } 941156952Sume break; 942170244Sume default: /*%< we didn't get one of each */ 943156952Sume return (0); 944156952Sume } 945156952Sume 946156952Sume /* altitude */ 947156952Sume if (*cp == '-') { 948156952Sume altsign = -1; 949156952Sume cp++; 950156952Sume } 951269867Sume 952156952Sume if (*cp == '+') 953156952Sume cp++; 954156952Sume 955156952Sume while (isdigit((unsigned char)*cp)) 956156952Sume altmeters = altmeters * 10 + (*cp++ - '0'); 957156952Sume 958170244Sume if (*cp == '.') { /*%< decimal meters */ 959156952Sume cp++; 960156952Sume if (isdigit((unsigned char)*cp)) { 961156952Sume altfrac = (*cp++ - '0') * 10; 962156952Sume if (isdigit((unsigned char)*cp)) { 963156952Sume altfrac += (*cp++ - '0'); 964156952Sume } 965156952Sume } 966156952Sume } 967156952Sume 968156952Sume alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); 969156952Sume 970170244Sume while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */ 971156952Sume cp++; 972156952Sume 973156952Sume while (isspace((unsigned char)*cp) && (cp < maxcp)) 974156952Sume cp++; 975156952Sume 976156952Sume if (cp >= maxcp) 977156952Sume goto defaults; 978156952Sume 979156952Sume siz = precsize_aton(&cp); 980269867Sume 981170244Sume while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */ 982156952Sume cp++; 983156952Sume 984156952Sume while (isspace((unsigned char)*cp) && (cp < maxcp)) 985156952Sume cp++; 986156952Sume 987156952Sume if (cp >= maxcp) 988156952Sume goto defaults; 989156952Sume 990156952Sume hp = precsize_aton(&cp); 991156952Sume 992170244Sume while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */ 993156952Sume cp++; 994156952Sume 995156952Sume while (isspace((unsigned char)*cp) && (cp < maxcp)) 996156952Sume cp++; 997156952Sume 998156952Sume if (cp >= maxcp) 999156952Sume goto defaults; 1000156952Sume 1001156952Sume vp = precsize_aton(&cp); 1002156952Sume 1003156952Sume defaults: 1004156952Sume 1005156952Sume bcp = binary; 1006170244Sume *bcp++ = (u_int8_t) 0; /*%< version byte */ 1007156952Sume *bcp++ = siz; 1008156952Sume *bcp++ = hp; 1009156952Sume *bcp++ = vp; 1010156952Sume PUTLONG(latit,bcp); 1011156952Sume PUTLONG(longit,bcp); 1012156952Sume PUTLONG(alt,bcp); 1013269867Sume 1014170244Sume return (16); /*%< size of RR in octets */ 1015156952Sume} 1016156952Sume 1017170244Sume/*% takes an on-the-wire LOC RR and formats it in a human readable format. */ 1018156952Sumeconst char * 1019288114Srodrigcloc_ntoa(const u_char *binary, char *ascii) 1020156952Sume{ 1021156952Sume static const char *error = "?"; 1022156952Sume static char tmpbuf[sizeof 1023156952Sume"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; 1024156952Sume const u_char *cp = binary; 1025156952Sume 1026156952Sume int latdeg, latmin, latsec, latsecfrac; 1027156952Sume int longdeg, longmin, longsec, longsecfrac; 1028156952Sume char northsouth, eastwest; 1029156952Sume const char *altsign; 1030156952Sume int altmeters, altfrac; 1031156952Sume 1032156952Sume const u_int32_t referencealt = 100000 * 100; 1033156952Sume 1034156952Sume int32_t latval, longval, altval; 1035156952Sume u_int32_t templ; 1036156952Sume u_int8_t sizeval, hpval, vpval, versionval; 1037269867Sume 1038156952Sume char *sizestr, *hpstr, *vpstr; 1039156952Sume 1040156952Sume versionval = *cp++; 1041156952Sume 1042156952Sume if (ascii == NULL) 1043156952Sume ascii = tmpbuf; 1044156952Sume 1045156952Sume if (versionval) { 1046156952Sume (void) sprintf(ascii, "; error: unknown LOC RR version"); 1047156952Sume return (ascii); 1048156952Sume } 1049156952Sume 1050156952Sume sizeval = *cp++; 1051156952Sume 1052156952Sume hpval = *cp++; 1053156952Sume vpval = *cp++; 1054156952Sume 1055156952Sume GETLONG(templ, cp); 1056156952Sume latval = (templ - ((unsigned)1<<31)); 1057156952Sume 1058156952Sume GETLONG(templ, cp); 1059156952Sume longval = (templ - ((unsigned)1<<31)); 1060156952Sume 1061156952Sume GETLONG(templ, cp); 1062170244Sume if (templ < referencealt) { /*%< below WGS 84 spheroid */ 1063156952Sume altval = referencealt - templ; 1064156952Sume altsign = "-"; 1065156952Sume } else { 1066156952Sume altval = templ - referencealt; 1067156952Sume altsign = ""; 1068156952Sume } 1069156952Sume 1070156952Sume if (latval < 0) { 1071156952Sume northsouth = 'S'; 1072156952Sume latval = -latval; 1073156952Sume } else 1074156952Sume northsouth = 'N'; 1075156952Sume 1076156952Sume latsecfrac = latval % 1000; 1077156952Sume latval = latval / 1000; 1078156952Sume latsec = latval % 60; 1079156952Sume latval = latval / 60; 1080156952Sume latmin = latval % 60; 1081156952Sume latval = latval / 60; 1082156952Sume latdeg = latval; 1083156952Sume 1084156952Sume if (longval < 0) { 1085156952Sume eastwest = 'W'; 1086156952Sume longval = -longval; 1087156952Sume } else 1088156952Sume eastwest = 'E'; 1089156952Sume 1090156952Sume longsecfrac = longval % 1000; 1091156952Sume longval = longval / 1000; 1092156952Sume longsec = longval % 60; 1093156952Sume longval = longval / 60; 1094156952Sume longmin = longval % 60; 1095156952Sume longval = longval / 60; 1096156952Sume longdeg = longval; 1097156952Sume 1098156952Sume altfrac = altval % 100; 1099156952Sume altmeters = (altval / 100); 1100156952Sume 1101156952Sume sizestr = strdup(precsize_ntoa(sizeval)); 1102156952Sume hpstr = strdup(precsize_ntoa(hpval)); 1103156952Sume vpstr = strdup(precsize_ntoa(vpval)); 1104156952Sume 1105156952Sume sprintf(ascii, 1106156952Sume "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm", 1107156952Sume latdeg, latmin, latsec, latsecfrac, northsouth, 1108156952Sume longdeg, longmin, longsec, longsecfrac, eastwest, 1109156952Sume altsign, altmeters, altfrac, 1110156952Sume (sizestr != NULL) ? sizestr : error, 1111156952Sume (hpstr != NULL) ? hpstr : error, 1112156952Sume (vpstr != NULL) ? vpstr : error); 1113156952Sume 1114156952Sume if (sizestr != NULL) 1115156952Sume free(sizestr); 1116156952Sume if (hpstr != NULL) 1117156952Sume free(hpstr); 1118156952Sume if (vpstr != NULL) 1119156952Sume free(vpstr); 1120156952Sume 1121156952Sume return (ascii); 1122156952Sume} 1123156952Sume 1124156952Sume 1125170244Sume/*% Return the number of DNS hierarchy levels in the name. */ 1126156952Sumeint 1127156952Sumedn_count_labels(const char *name) { 1128156952Sume int i, len, count; 1129156952Sume 1130156952Sume len = strlen(name); 1131156952Sume for (i = 0, count = 0; i < len; i++) { 1132156952Sume /* XXX need to check for \. or use named's nlabels(). */ 1133156952Sume if (name[i] == '.') 1134156952Sume count++; 1135156952Sume } 1136156952Sume 1137156952Sume /* don't count initial wildcard */ 1138156952Sume if (name[0] == '*') 1139156952Sume if (count) 1140156952Sume count--; 1141156952Sume 1142156952Sume /* don't count the null label for root. */ 1143156952Sume /* if terminating '.' not found, must adjust */ 1144156952Sume /* count to include last label */ 1145156952Sume if (len > 0 && name[len-1] != '.') 1146156952Sume count++; 1147156952Sume return (count); 1148156952Sume} 1149156952Sume 1150170244Sume/*% 1151269867Sume * Make dates expressed in seconds-since-Jan-1-1970 easy to read. 1152156952Sume * SIG records are required to be printed like this, by the Secure DNS RFC. 1153156952Sume */ 1154156952Sumechar * 1155156952Sumep_secstodate (u_long secs) { 1156156952Sume char *output = p_secstodate_output; 1157156952Sume time_t clock = secs; 1158156952Sume struct tm *time; 1159156952Sume#ifdef HAVE_TIME_R 1160156952Sume struct tm res; 1161269867Sume 1162156952Sume time = gmtime_r(&clock, &res); 1163156952Sume#else 1164156952Sume time = gmtime(&clock); 1165156952Sume#endif 1166156952Sume time->tm_year += 1900; 1167156952Sume time->tm_mon += 1; 1168156952Sume sprintf(output, "%04d%02d%02d%02d%02d%02d", 1169156952Sume time->tm_year, time->tm_mon, time->tm_mday, 1170156952Sume time->tm_hour, time->tm_min, time->tm_sec); 1171156952Sume return (output); 1172156952Sume} 1173156952Sume 1174156952Sumeu_int16_t 1175156952Sumeres_nametoclass(const char *buf, int *successp) { 1176156952Sume unsigned long result; 1177156952Sume char *endptr; 1178156952Sume int success; 1179156952Sume 1180156952Sume result = sym_ston(__p_class_syms, buf, &success); 1181156952Sume if (success) 1182156952Sume goto done; 1183156952Sume 1184156952Sume if (strncasecmp(buf, "CLASS", 5) != 0 || 1185156952Sume !isdigit((unsigned char)buf[5])) 1186156952Sume goto done; 1187156952Sume errno = 0; 1188156952Sume result = strtoul(buf + 5, &endptr, 10); 1189156952Sume if (errno == 0 && *endptr == '\0' && result <= 0xffffU) 1190156952Sume success = 1; 1191156952Sume done: 1192156952Sume if (successp) 1193156952Sume *successp = success; 1194156952Sume return (result); 1195156952Sume} 1196156952Sume 1197156952Sumeu_int16_t 1198156952Sumeres_nametotype(const char *buf, int *successp) { 1199156952Sume unsigned long result; 1200156952Sume char *endptr; 1201156952Sume int success; 1202156952Sume 1203156952Sume result = sym_ston(__p_type_syms, buf, &success); 1204156952Sume if (success) 1205156952Sume goto done; 1206156952Sume 1207156952Sume if (strncasecmp(buf, "type", 4) != 0 || 1208156952Sume !isdigit((unsigned char)buf[4])) 1209156952Sume goto done; 1210156952Sume errno = 0; 1211156952Sume result = strtoul(buf + 4, &endptr, 10); 1212156952Sume if (errno == 0 && *endptr == '\0' && result <= 0xffffU) 1213156952Sume success = 1; 1214156952Sume done: 1215156952Sume if (successp) 1216156952Sume *successp = success; 1217156952Sume return (result); 1218156952Sume} 1219156956Sume 1220156956Sume/* 1221156956Sume * Weak aliases for applications that use certain private entry points, 1222156956Sume * and fail to include <resolv.h>. 1223156956Sume */ 1224156956Sume#undef fp_resstat 1225156956Sume__weak_reference(__fp_resstat, fp_resstat); 1226156956Sume#undef p_fqnname 1227156956Sume__weak_reference(__p_fqnname, p_fqnname); 1228156956Sume#undef sym_ston 1229156956Sume__weak_reference(__sym_ston, sym_ston); 1230156956Sume#undef sym_ntos 1231156956Sume__weak_reference(__sym_ntos, sym_ntos); 1232156956Sume#undef sym_ntop 1233156956Sume__weak_reference(__sym_ntop, sym_ntop); 1234156956Sume#undef dn_count_labels 1235156956Sume__weak_reference(__dn_count_labels, dn_count_labels); 1236156956Sume#undef p_secstodate 1237156956Sume__weak_reference(__p_secstodate, p_secstodate); 1238170244Sume 1239170244Sume/*! \file */ 1240