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