res_debug.c revision 7700f0f5c0ab90bf052e33fa0ddd2f2aa7e7893e
1/* 2 * Copyright (c) 1985 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Portions copyright (c) 1999, 2000 6 * Intel Corporation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * 23 * This product includes software developed by the University of 24 * California, Berkeley, Intel Corporation, and its contributors. 25 * 26 * 4. Neither the name of University, Intel Corporation, or their respective 27 * contributors may be used to endorse or promote products derived from 28 * this software without specific prior written permission. 29 * 30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND 31 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 32 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS, 34 * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 * 42 */ 43 44/* 45 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 46 * 47 * Permission to use, copy, modify, and distribute this software for any 48 * purpose with or without fee is hereby granted, provided that the above 49 * copyright notice and this permission notice appear in all copies, and that 50 * the name of Digital Equipment Corporation not be used in advertising or 51 * publicity pertaining to distribution of the document or software without 52 * specific, written prior permission. 53 * 54 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 55 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 56 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 57 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 58 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 59 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 60 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 61 * SOFTWARE. 62 */ 63 64/* 65 * Portions Copyright (c) 1995 by International Business Machines, Inc. 66 * 67 * International Business Machines, Inc. (hereinafter called IBM) grants 68 * permission under its copyrights to use, copy, modify, and distribute this 69 * Software with or without fee, provided that the above copyright notice and 70 * all paragraphs of this notice appear in all copies, and that the name of IBM 71 * not be used in connection with the marketing of any product incorporating 72 * the Software or modifications thereof, without specific, written prior 73 * permission. 74 * 75 * To the extent it has a right to do so, IBM grants an immunity from suit 76 * under its patents, if any, for the use, sale or manufacture of products to 77 * the extent that such products are used for performing Domain Name System 78 * dynamic updates in TCP/IP networks by means of the Software. No immunity is 79 * granted for any product per se or for any other function of any product. 80 * 81 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, 82 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 83 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, 84 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING 85 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN 86 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. 87 */ 88 89/* 90 * Portions Copyright (c) 1996 by Internet Software Consortium. 91 * 92 * Permission to use, copy, modify, and distribute this software for any 93 * purpose with or without fee is hereby granted, provided that the above 94 * copyright notice and this permission notice appear in all copies. 95 * 96 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 97 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 98 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 99 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 100 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 101 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 102 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 103 * SOFTWARE. 104 */ 105 106#if defined(LIBC_SCCS) && !defined(lint) 107static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; 108static char rcsid[] = "$Id: res_debug.c,v 1.1.1.1 2003/11/19 01:51:36 kyu3 Exp $"; 109#endif /* LIBC_SCCS and not lint */ 110 111#include <sys/types.h> 112#include <sys/param.h> 113#include <sys/socket.h> 114 115#include <netinet/in.h> 116#include <arpa/inet.h> 117#include <arpa/nameser.h> 118 119#include <ctype.h> 120#include <errno.h> 121#include <math.h> 122#include <netdb.h> 123#include <resolv.h> 124#include <stdio.h> 125#include <stdlib.h> 126#include <string.h> 127#include <time.h> 128 129#define SPRINTF(x) sprintf x 130 131extern const char *_res_opcodes[]; 132extern const char *_res_resultcodes[]; 133extern const char *_res_sectioncodes[]; 134 135/* 136 * Print the current options. 137 */ 138void 139fp_resstat(struct __res_state *statp, FILE *file) { 140 u_long mask; 141 142 fprintf(file, ";; res options:"); 143 if (!statp) 144 statp = &_res; 145 for (mask = 1; mask != 0; mask <<= 1) 146 if (statp->options & mask) 147 fprintf(file, " %s", p_option(mask)); 148 putc('\n', file); 149} 150 151static void 152do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) { 153 int n, sflag, rrnum; 154 ns_opcode opcode; 155 ns_rr rr; 156 157 /* 158 * Print answer records. 159 */ 160 sflag = (int)(_res.pfcode & pflag); 161 if (_res.pfcode && !sflag) 162 return; 163 164 opcode = ns_msg_getflag(*handle, ns_f_opcode); 165 rrnum = 0; 166 for (;;) { 167 if (ns_parserr(handle, section, rrnum, &rr)) { 168 if (errno != ENODEV) 169 fprintf(file, ";; ns_parserr: %s\n", 170 strerror(errno)); 171 else if (rrnum > 0 && sflag != 0 && 172 (_res.pfcode & RES_PRF_HEAD1)) 173 putc('\n', file); 174 return; 175 } 176 if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1)) 177 fprintf(file, ";; %s SECTION:\n", 178 p_section(section, opcode)); 179 if (section == ns_s_qd) 180 fprintf(file, ";;\t%s, type = %s, class = %s\n", 181 ns_rr_name(rr), 182 p_type(ns_rr_type(rr)), 183 p_class(ns_rr_class(rr))); 184 else { 185 char *buf; 186 buf = (char*)malloc(2024); 187 if (buf) { 188 n = ns_sprintrr(handle, &rr, NULL, NULL, 189 buf, sizeof buf); 190 if (n < 0) { 191 fprintf(file, ";; ns_sprintrr: %s\n", 192 strerror(errno)); 193 free(buf); 194 return; 195 } 196 fputs(buf, file); 197 fputc('\n', file); 198 free(buf); 199 } 200 } 201 rrnum++; 202 } 203} 204 205void 206p_query(const u_char *msg) { 207 fp_query(msg, stdout); 208} 209 210void 211fp_query(const u_char *msg, FILE *file) { 212 fp_nquery(msg, PACKETSZ, file); 213} 214 215/* 216 * Print the contents of a query. 217 * This is intended to be primarily a debugging routine. 218 */ 219void 220fp_nquery(const u_char *msg, int len, FILE *file) { 221 ns_msg handle; 222 int qdcount, ancount, nscount, arcount; 223 u_int opcode, rcode, id; 224 225 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 226 return; 227 228 if (ns_initparse(msg, len, &handle) < 0) { 229 fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); 230 return; 231 } 232 opcode = ns_msg_getflag(handle, ns_f_opcode); 233 rcode = ns_msg_getflag(handle, ns_f_rcode); 234 id = ns_msg_id(handle); 235 qdcount = ns_msg_count(handle, ns_s_qd); 236 ancount = ns_msg_count(handle, ns_s_an); 237 nscount = ns_msg_count(handle, ns_s_ns); 238 arcount = ns_msg_count(handle, ns_s_ar); 239 240 /* 241 * Print header fields. 242 */ 243 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode) 244 fprintf(file, 245 ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", 246 _res_opcodes[opcode], _res_resultcodes[rcode], (int)id); 247 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX)) 248 putc(';', file); 249 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { 250 fprintf(file, "; flags:"); 251 if (ns_msg_getflag(handle, ns_f_qr)) 252 fprintf(file, " qr"); 253 if (ns_msg_getflag(handle, ns_f_aa)) 254 fprintf(file, " aa"); 255 if (ns_msg_getflag(handle, ns_f_tc)) 256 fprintf(file, " tc"); 257 if (ns_msg_getflag(handle, ns_f_rd)) 258 fprintf(file, " rd"); 259 if (ns_msg_getflag(handle, ns_f_ra)) 260 fprintf(file, " ra"); 261 if (ns_msg_getflag(handle, ns_f_z)) 262 fprintf(file, " ??"); 263 if (ns_msg_getflag(handle, ns_f_ad)) 264 fprintf(file, " ad"); 265 if (ns_msg_getflag(handle, ns_f_cd)) 266 fprintf(file, " cd"); 267 } 268 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { 269 fprintf(file, "; %s: %d", 270 p_section(ns_s_qd, (int)opcode), qdcount); 271 fprintf(file, ", %s: %d", 272 p_section(ns_s_an, (int)opcode), ancount); 273 fprintf(file, ", %s: %d", 274 p_section(ns_s_ns, (int)opcode), nscount); 275 fprintf(file, ", %s: %d", 276 p_section(ns_s_ar, (int)opcode), arcount); 277 } 278 if ((!_res.pfcode) || (_res.pfcode & 279 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { 280 putc('\n',file); 281 } 282 /* 283 * Print the various sections. 284 */ 285 do_section(&handle, ns_s_qd, RES_PRF_QUES, file); 286 do_section(&handle, ns_s_an, RES_PRF_ANS, file); 287 do_section(&handle, ns_s_ns, RES_PRF_AUTH, file); 288 do_section(&handle, ns_s_ar, RES_PRF_ADD, file); 289 if (qdcount == 0 && ancount == 0 && 290 nscount == 0 && arcount == 0) 291 putc('\n', file); 292} 293 294const u_char * 295p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { 296 char name[MAXDNAME]; 297 int n; 298 299 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) 300 return (NULL); 301 if (name[0] == '\0') 302 putc('.', file); 303 else 304 fputs(name, file); 305 return (cp + n); 306} 307 308const u_char * 309p_cdname(const u_char *cp, const u_char *msg, FILE *file) { 310 return (p_cdnname(cp, msg, PACKETSZ, file)); 311} 312 313/* Return a fully-qualified domain name from a compressed name (with 314 length supplied). */ 315 316const u_char * 317p_fqnname( 318 const u_char *cp, 319 const u_char *msg, 320 int msglen, 321 char *name, 322 int namelen 323 ) 324{ 325 int n, newlen; 326 327 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) 328 return (NULL); 329 newlen = (int)strlen(name); 330 if (newlen == 0 || name[newlen - 1] != '.') { 331 if (newlen + 1 >= namelen) /* Lack space for final dot */ 332 return (NULL); 333 else 334 strcpy(name + newlen, "."); 335 } 336 return (cp + n); 337} 338 339/* XXX: the rest of these functions need to become length-limited, too. */ 340 341const u_char * 342p_fqname(const u_char *cp, const u_char *msg, FILE *file) { 343 char name[MAXDNAME]; 344 const u_char *n; 345 346 n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); 347 if (n == NULL) 348 return (NULL); 349 fputs(name, file); 350 return (n); 351} 352 353/* 354 * Names of RR classes and qclasses. Classes and qclasses are the same, except 355 * that C_ANY is a qclass but not a class. (You can ask for records of class 356 * C_ANY, but you can't have any records of that class in the database.) 357 */ 358const struct res_sym __p_class_syms[] = { 359 {C_IN, "IN"}, 360 {C_CHAOS, "CHAOS"}, 361 {C_HS, "HS"}, 362 {C_HS, "HESIOD"}, 363 {C_ANY, "ANY"}, 364 {C_NONE, "NONE"}, 365 {C_IN, (char *)0} 366}; 367 368/* 369 * Names of message sections. 370 */ 371const struct res_sym __p_default_section_syms[] = { 372 {ns_s_qd, "QUERY"}, 373 {ns_s_an, "ANSWER"}, 374 {ns_s_ns, "AUTHORITY"}, 375 {ns_s_ar, "ADDITIONAL"}, 376 {0, (char *)0} 377}; 378 379const struct res_sym __p_update_section_syms[] = { 380 {S_ZONE, "ZONE"}, 381 {S_PREREQ, "PREREQUISITE"}, 382 {S_UPDATE, "UPDATE"}, 383 {S_ADDT, "ADDITIONAL"}, 384 {0, (char *)0} 385}; 386 387/* 388 * Names of RR types and qtypes. Types and qtypes are the same, except 389 * that T_ANY is a qtype but not a type. (You can ask for records of type 390 * T_ANY, but you can't have any records of that type in the database.) 391 */ 392const struct res_sym __p_type_syms[] = { 393 {T_A, "A", "address"}, 394 {T_NS, "NS", "name server"}, 395 {T_MD, "MD", "mail destination (deprecated)"}, 396 {T_MF, "MF", "mail forwarder (deprecated)"}, 397 {T_CNAME, "CNAME", "canonical name"}, 398 {T_SOA, "SOA", "start of authority"}, 399 {T_MB, "MB", "mailbox"}, 400 {T_MG, "MG", "mail group member"}, 401 {T_MR, "MR", "mail rename"}, 402 {T_NULL, "NULL", "null"}, 403 {T_WKS, "WKS", "well-known service (deprecated)"}, 404 {T_PTR, "PTR", "domain name pointer"}, 405 {T_HINFO, "HINFO", "host information"}, 406 {T_MINFO, "MINFO", "mailbox information"}, 407 {T_MX, "MX", "mail exchanger"}, 408 {T_TXT, "TXT", "text"}, 409 {T_RP, "RP", "responsible person"}, 410 {T_AFSDB, "AFSDB", "DCE or AFS server"}, 411 {T_X25, "X25", "X25 address"}, 412 {T_ISDN, "ISDN", "ISDN address"}, 413 {T_RT, "RT", "router"}, 414 {T_NSAP, "NSAP", "nsap address"}, 415 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"}, 416 {T_SIG, "SIG", "signature"}, 417 {T_KEY, "KEY", "key"}, 418 {T_PX, "PX", "mapping information"}, 419 {T_GPOS, "GPOS", "geographical position (withdrawn)"}, 420 {T_AAAA, "AAAA", "IPv6 address"}, 421 {T_LOC, "LOC", "location"}, 422 {T_NXT, "NXT", "next valid name (unimplemented)"}, 423 {T_EID, "EID", "endpoint identifier (unimplemented)"}, 424 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"}, 425 {T_SRV, "SRV", "server selection"}, 426 {T_ATMA, "ATMA", "ATM address (unimplemented)"}, 427 {T_IXFR, "IXFR", "incremental zone transfer"}, 428 {T_AXFR, "AXFR", "zone transfer"}, 429 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"}, 430 {T_MAILA, "MAILA", "mail agent (deprecated)"}, 431 {T_NAPTR, "NAPTR", "URN Naming Authority"}, 432 {T_ANY, "ANY", "\"any\""}, 433 {0, NULL, NULL} 434}; 435 436int 437sym_ston(const struct res_sym *syms, const char *name, int *success) { 438 for ((void)NULL; syms->name != 0; syms++) { 439 if (strcasecmp (name, syms->name) == 0) { 440 if (success) 441 *success = 1; 442 return (syms->number); 443 } 444 } 445 if (success) 446 *success = 0; 447 return (syms->number); /* The default value. */ 448} 449 450const char * 451sym_ntos(const struct res_sym *syms, int number, int *success) { 452 static char unname[20]; 453 454 for ((void)NULL; syms->name != 0; syms++) { 455 if (number == syms->number) { 456 if (success) 457 *success = 1; 458 return (syms->name); 459 } 460 } 461 462 sprintf(unname, "%d", number); 463 if (success) 464 *success = 0; 465 return (unname); 466} 467 468const char * 469sym_ntop(const struct res_sym *syms, int number, int *success) { 470 static char unname[20]; 471 472 for ((void)NULL; syms->name != 0; syms++) { 473 if (number == syms->number) { 474 if (success) 475 *success = 1; 476 return (syms->humanname); 477 } 478 } 479 sprintf(unname, "%d", number); 480 if (success) 481 *success = 0; 482 return (unname); 483} 484 485/* 486 * Return a string for the type. 487 */ 488const char * 489p_type(int type) { 490 return (sym_ntos(__p_type_syms, type, (int *)0)); 491} 492 493/* 494 * Return a string for the type. 495 */ 496const char * 497p_section(int section, int opcode) { 498 const struct res_sym *symbols; 499 500 switch (opcode) { 501 case ns_o_update: 502 symbols = __p_update_section_syms; 503 break; 504 default: 505 symbols = __p_default_section_syms; 506 break; 507 } 508 return (sym_ntos(symbols, section, (int *)0)); 509} 510 511/* 512 * Return a mnemonic for class. 513 */ 514const char * 515p_class(int class) { 516 return (sym_ntos(__p_class_syms, class, (int *)0)); 517} 518 519/* 520 * Return a mnemonic for an option 521 */ 522const char * 523p_option(u_long option) { 524 static char nbuf[40]; 525 526 switch (option) { 527 case RES_INIT: return "init"; 528 case RES_DEBUG: return "debug"; 529 case RES_AAONLY: return "aaonly(unimpl)"; 530 case RES_USEVC: return "usevc"; 531 case RES_PRIMARY: return "primry(unimpl)"; 532 case RES_IGNTC: return "igntc"; 533 case RES_RECURSE: return "recurs"; 534 case RES_DEFNAMES: return "defnam"; 535 case RES_STAYOPEN: return "styopn"; 536 case RES_DNSRCH: return "dnsrch"; 537 case RES_INSECURE1: return "insecure1"; 538 case RES_INSECURE2: return "insecure2"; 539 default: sprintf(nbuf, "?0x%Lx?", (u_long)option); 540 return (nbuf); 541 } 542} 543 544/* 545 * Return a mnemonic for a time to live. 546 */ 547const char * 548p_time(u_int32_t value) { 549 static char nbuf[40]; 550 551 if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) 552 sprintf(nbuf, "%u", value); 553 return (nbuf); 554} 555 556 557/* 558 * routines to convert between on-the-wire RR format and zone file format. 559 * Does not contain conversion to/from decimal degrees; divide or multiply 560 * by 60*60*1000 for that. 561 */ 562 563static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, 564 1000000,10000000,100000000,1000000000}; 565 566/* takes an XeY precision/size value, returns a string representation. */ 567static const char * 568precsize_ntoa( 569 u_int8_t prec 570 ) 571{ 572 static char retbuf[sizeof "90000000.00"]; 573 unsigned long val; 574 int mantissa, exponent; 575 576 mantissa = (int)((prec >> 4) & 0x0f) % 10; 577 exponent = (int)((prec >> 0) & 0x0f) % 10; 578 579 val = mantissa * poweroften[exponent]; 580 581 (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100); 582 return (retbuf); 583} 584 585/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ 586static u_int8_t 587precsize_aton( 588 char **strptr 589 ) 590{ 591 unsigned int mval = 0, cmval = 0; 592 u_int8_t retval = 0; 593 char *cp; 594 int exponent; 595 int mantissa; 596 597 cp = *strptr; 598 599 while (isdigit(*cp)) 600 mval = mval * 10 + (*cp++ - '0'); 601 602 if (*cp == '.') { /* centimeters */ 603 cp++; 604 if (isdigit(*cp)) { 605 cmval = (*cp++ - '0') * 10; 606 if (isdigit(*cp)) { 607 cmval += (*cp++ - '0'); 608 } 609 } 610 } 611 cmval = (mval * 100) + cmval; 612 613 for (exponent = 0; exponent < 9; exponent++) 614 if (cmval < poweroften[exponent+1]) 615 break; 616 617 mantissa = cmval / poweroften[exponent]; 618 if (mantissa > 9) 619 mantissa = 9; 620 621 retval = (u_int8_t)((mantissa << 4) | exponent); 622 623 *strptr = cp; 624 625 return (retval); 626} 627 628/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */ 629static u_int32_t 630latlon2ul( 631 char **latlonstrptr, 632 int *which 633 ) 634{ 635 char *cp; 636 u_int32_t retval; 637 int deg = 0, min = 0, secs = 0, secsfrac = 0; 638 639 cp = *latlonstrptr; 640 641 while (isdigit(*cp)) 642 deg = deg * 10 + (*cp++ - '0'); 643 644 while (isspace(*cp)) 645 cp++; 646 647 if (!(isdigit(*cp))) 648 goto fndhemi; 649 650 while (isdigit(*cp)) 651 min = min * 10 + (*cp++ - '0'); 652 653 while (isspace(*cp)) 654 cp++; 655 656 if (!(isdigit(*cp))) 657 goto fndhemi; 658 659 while (isdigit(*cp)) 660 secs = secs * 10 + (*cp++ - '0'); 661 662 if (*cp == '.') { /* decimal seconds */ 663 cp++; 664 if (isdigit(*cp)) { 665 secsfrac = (*cp++ - '0') * 100; 666 if (isdigit(*cp)) { 667 secsfrac += (*cp++ - '0') * 10; 668 if (isdigit(*cp)) { 669 secsfrac += (*cp++ - '0'); 670 } 671 } 672 } 673 } 674 675 while (!isspace(*cp)) /* if any trailing garbage */ 676 cp++; 677 678 while (isspace(*cp)) 679 cp++; 680 681 fndhemi: 682 switch (*cp) { 683 case 'N': case 'n': 684 case 'E': case 'e': 685 retval = ((unsigned)1<<31) 686 + (((((deg * 60) + min) * 60) + secs) * 1000) 687 + secsfrac; 688 break; 689 case 'S': case 's': 690 case 'W': case 'w': 691 retval = ((unsigned)1<<31) 692 - (((((deg * 60) + min) * 60) + secs) * 1000) 693 - secsfrac; 694 break; 695 default: 696 retval = 0; /* invalid value -- indicates error */ 697 break; 698 } 699 700 switch (*cp) { 701 case 'N': case 'n': 702 case 'S': case 's': 703 *which = 1; /* latitude */ 704 break; 705 case 'E': case 'e': 706 case 'W': case 'w': 707 *which = 2; /* longitude */ 708 break; 709 default: 710 *which = 0; /* error */ 711 break; 712 } 713 714 cp++; /* skip the hemisphere */ 715 716 while (!isspace(*cp)) /* if any trailing garbage */ 717 cp++; 718 719 while (isspace(*cp)) /* move to next field */ 720 cp++; 721 722 *latlonstrptr = cp; 723 724 return (retval); 725} 726 727/* converts a zone file representation in a string to an RDATA on-the-wire 728 * representation. */ 729int 730loc_aton( 731 const char *ascii, 732 u_char *binary 733 ) 734{ 735 const char *cp, *maxcp; 736 u_char *bcp; 737 738 u_int32_t latit = 0, longit = 0, alt = 0; 739 u_int32_t lltemp1 = 0, lltemp2 = 0; 740 int altmeters = 0, altfrac = 0, altsign = 1; 741 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ 742 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ 743 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ 744 int which1 = 0, which2 = 0; 745 746 cp = ascii; 747 maxcp = cp + strlen(ascii); 748 749 lltemp1 = latlon2ul((char **)&cp, &which1); 750 751 lltemp2 = latlon2ul((char **)&cp, &which2); 752 753 switch (which1 + which2) { 754 case 3: /* 1 + 2, the only valid combination */ 755 if ((which1 == 1) && (which2 == 2)) { /* normal case */ 756 latit = lltemp1; 757 longit = lltemp2; 758 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */ 759 longit = lltemp1; 760 latit = lltemp2; 761 } else { /* some kind of brokenness */ 762 return (0); 763 } 764 break; 765 default: /* we didn't get one of each */ 766 return (0); 767 } 768 769 /* altitude */ 770 if (*cp == '-') { 771 altsign = -1; 772 cp++; 773 } 774 775 if (*cp == '+') 776 cp++; 777 778 while (isdigit(*cp)) 779 altmeters = altmeters * 10 + (*cp++ - '0'); 780 781 if (*cp == '.') { /* decimal meters */ 782 cp++; 783 if (isdigit(*cp)) { 784 altfrac = (*cp++ - '0') * 10; 785 if (isdigit(*cp)) { 786 altfrac += (*cp++ - '0'); 787 } 788 } 789 } 790 791 alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); 792 793 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ 794 cp++; 795 796 while (isspace(*cp) && (cp < maxcp)) 797 cp++; 798 799 if (cp >= maxcp) 800 goto defaults; 801 802 siz = precsize_aton((char **)&cp); 803 804 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ 805 cp++; 806 807 while (isspace(*cp) && (cp < maxcp)) 808 cp++; 809 810 if (cp >= maxcp) 811 goto defaults; 812 813 hp = precsize_aton((char **)&cp); 814 815 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ 816 cp++; 817 818 while (isspace(*cp) && (cp < maxcp)) 819 cp++; 820 821 if (cp >= maxcp) 822 goto defaults; 823 824 vp = precsize_aton((char **)&cp); 825 826 defaults: 827 828 bcp = binary; 829 *bcp++ = (u_int8_t) 0; /* version byte */ 830 *bcp++ = siz; 831 *bcp++ = hp; 832 *bcp++ = vp; 833 PUTLONG(latit,bcp); 834 PUTLONG(longit,bcp); 835 PUTLONG(alt,bcp); 836 837 return (16); /* size of RR in octets */ 838} 839 840/* takes an on-the-wire LOC RR and formats it in a human readable format. */ 841const char * 842loc_ntoa( 843 const u_char *binary, 844 char *ascii 845 ) 846{ 847 static char *error = "?"; 848 const u_char *cp = binary; 849 850 int latdeg, latmin, latsec, latsecfrac; 851 int longdeg, longmin, longsec, longsecfrac; 852 char northsouth, eastwest; 853 int altmeters, altfrac, altsign; 854 855 const u_int32_t referencealt = 100000 * 100; 856 857 int32_t latval, longval, altval; 858 u_int32_t templ; 859 u_int8_t sizeval, hpval, vpval, versionval; 860 861 char *sizestr, *hpstr, *vpstr; 862 863 versionval = *cp++; 864 865 if (versionval) { 866 (void) sprintf(ascii, "; error: unknown LOC RR version"); 867 return (ascii); 868 } 869 870 sizeval = *cp++; 871 872 hpval = *cp++; 873 vpval = *cp++; 874 875 GETLONG(templ, cp); 876 latval = (templ - ((unsigned)1<<31)); 877 878 GETLONG(templ, cp); 879 longval = (templ - ((unsigned)1<<31)); 880 881 GETLONG(templ, cp); 882 if (templ < referencealt) { /* below WGS 84 spheroid */ 883 altval = referencealt - templ; 884 altsign = -1; 885 } else { 886 altval = templ - referencealt; 887 altsign = 1; 888 } 889 890 if (latval < 0) { 891 northsouth = 'S'; 892 latval = -latval; 893 } else 894 northsouth = 'N'; 895 896 latsecfrac = latval % 1000; 897 latval = latval / 1000; 898 latsec = latval % 60; 899 latval = latval / 60; 900 latmin = latval % 60; 901 latval = latval / 60; 902 latdeg = latval; 903 904 if (longval < 0) { 905 eastwest = 'W'; 906 longval = -longval; 907 } else 908 eastwest = 'E'; 909 910 longsecfrac = longval % 1000; 911 longval = longval / 1000; 912 longsec = longval % 60; 913 longval = longval / 60; 914 longmin = longval % 60; 915 longval = longval / 60; 916 longdeg = longval; 917 918 altfrac = altval % 100; 919 altmeters = (altval / 100) * altsign; 920 921 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL) 922 sizestr = error; 923 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL) 924 hpstr = error; 925 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL) 926 vpstr = error; 927 928 sprintf(ascii, 929 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm", 930 latdeg, latmin, latsec, latsecfrac, northsouth, 931 longdeg, longmin, longsec, longsecfrac, eastwest, 932 altmeters, altfrac, sizestr, hpstr, vpstr); 933 934 if (sizestr != error) 935 free(sizestr); 936 if (hpstr != error) 937 free(hpstr); 938 if (vpstr != error) 939 free(vpstr); 940 941 return (ascii); 942} 943 944 945/* Return the number of DNS hierarchy levels in the name. */ 946int 947dn_count_labels(const char *name) { 948 int i, len, count; 949 950 len = (int)strlen(name); 951 for (i = 0, count = 0; i < len; i++) { 952 /* XXX need to check for \. or use named's nlabels(). */ 953 if (name[i] == '.') 954 count++; 955 } 956 957 /* don't count initial wildcard */ 958 if (name[0] == '*') 959 if (count) 960 count--; 961 962 /* don't count the null label for root. */ 963 /* if terminating '.' not found, must adjust */ 964 /* count to include last label */ 965 if (len > 0 && name[len-1] != '.') 966 count++; 967 return (count); 968} 969 970 971/* 972 * Make dates expressed in seconds-since-Jan-1-1970 easy to read. 973 * SIG records are required to be printed like this, by the Secure DNS RFC. 974 */ 975char * 976p_secstodate (u_long secs) { 977 static char output[15]; /* YYYYMMDDHHMMSS and null */ 978 time_t clock = (time_t)secs; 979 struct tm *time; 980 981 time = gmtime(&clock); 982 time->tm_year += 1900; 983 time->tm_mon += 1; 984 sprintf(output, "%04d%02d%02d%02d%02d%02d", 985 time->tm_year, time->tm_mon, time->tm_mday, 986 time->tm_hour, time->tm_min, time->tm_sec); 987 return (output); 988} 989