2 * ++Copyright++ 1985, 1990, 1993
4 * Copyright (c) 1985, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies, and that
40 * the name of Digital Equipment Corporation not be used in advertising or
41 * publicity pertaining to distribution of the document or software without
42 * specific, written prior permission.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
47 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
58 static char rcsid[] = "$Id: res_debug.c,v 8.12 1996/08/05 08:31:35 vixie Exp $";
59 #endif /* LIBC_SCCS and not lint */
61 #include <sys/param.h>
62 #include <sys/types.h>
63 #include <sys/socket.h>
64 #include <netinet/in.h>
65 #include <arpa/inet.h>
66 #include <arpa/nameser.h>
72 #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
75 # include "../conf/portability.h"
78 #if defined(USE_OPTIONS_H)
79 # include "../conf/options.h"
82 extern const char *_res_opcodes[];
83 extern const char *_res_resultcodes[];
85 /* XXX: we should use getservbyport() instead. */
94 case 7: return "echo";
95 case 9: return "discard";
96 case 11: return "systat";
97 case 13: return "daytime";
98 case 15: return "netstat";
99 case 17: return "qotd";
100 case 19: return "chargen";
101 case 20: return "ftp-data";
102 case 21: return "ftp";
103 case 23: return "telnet";
104 case 25: return "smtp";
105 case 37: return "time";
106 case 39: return "rlp";
107 case 42: return "name";
108 case 43: return "whois";
109 case 53: return "domain";
110 case 57: return "apts";
111 case 59: return "apfs";
112 case 67: return "bootps";
113 case 68: return "bootpc";
114 case 69: return "tftp";
115 case 77: return "rje";
116 case 79: return "finger";
117 case 87: return "link";
118 case 95: return "supdup";
119 case 100: return "newacct";
120 case 101: return "hostnames";
121 case 102: return "iso-tsap";
122 case 103: return "x400";
123 case 104: return "x400-snd";
124 case 105: return "csnet-ns";
125 case 109: return "pop-2";
126 case 111: return "sunrpc";
127 case 113: return "auth";
128 case 115: return "sftp";
129 case 117: return "uucp-path";
130 case 119: return "nntp";
131 case 121: return "erpc";
132 case 123: return "ntp";
133 case 133: return "statsrv";
134 case 136: return "profile";
135 case 144: return "NeWS";
136 case 161: return "snmp";
137 case 162: return "snmp-trap";
138 case 170: return "print-srv";
139 default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
143 /* XXX: we should use getprotobynumber() instead. */
148 static char nbuf[20];
151 case 1: return "icmp";
152 case 2: return "igmp";
153 case 3: return "ggp";
155 case 6: return "tcp";
156 case 7: return "ucl";
157 case 8: return "egp";
158 case 9: return "igp";
159 case 11: return "nvp-II";
160 case 12: return "pup";
161 case 16: return "chaos";
162 case 17: return "udp";
163 default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
167 static const u_char *
168 do_rrset(msg, len, cp, cnt, pflag, file, hs)
170 const u_char *cp, *msg;
178 * Print answer records.
180 sflag = (_res.pfcode & pflag);
181 if (n = ntohs(cnt)) {
182 if ((!_res.pfcode) ||
183 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
186 if ((!_res.pfcode) || sflag) {
187 cp = p_rr(cp, msg, file);
190 cp += __dn_skipname(cp, cp + MAXCDNAME);
194 dlen = _getshort((u_char*)cp);
198 if ((cp - msg) > len)
201 if ((!_res.pfcode) ||
202 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
212 __fp_query(msg, stdout);
216 /* ultrix 4.0's packaging has some icky packaging. alias for it here.
217 * there is more junk of this kind over in res_comp.c.
228 * Print the current options.
229 * This is intended to be primarily a debugging routine.
232 __fp_resstat(statp, file)
233 struct __res_state *statp;
236 register u_long mask;
238 fprintf(file, ";; res options:");
241 for (mask = 1; mask != 0; mask <<= 1)
242 if (statp->options & mask)
243 fprintf(file, " %s", p_option(mask));
248 * Print the contents of a query.
249 * This is intended to be primarily a debugging routine.
252 __fp_nquery(msg, len, file)
257 register const u_char *cp, *endMark;
258 register const HEADER *hp;
261 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
264 #define TruncTest(x) if (x >= endMark) goto trunc
265 #define ErrorTest(x) if (x == NULL) goto error
268 * Print header fields.
273 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
274 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
275 _res_opcodes[hp->opcode],
276 _res_resultcodes[hp->rcode],
280 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
282 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
283 fprintf(file, "; flags:");
285 fprintf(file, " qr");
287 fprintf(file, " aa");
289 fprintf(file, " tc");
291 fprintf(file, " rd");
293 fprintf(file, " ra");
295 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
296 fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
297 fprintf(file, ", Ans: %d", ntohs(hp->ancount));
298 fprintf(file, ", Auth: %d", ntohs(hp->nscount));
299 fprintf(file, ", Addit: %d", ntohs(hp->arcount));
301 if ((!_res.pfcode) || (_res.pfcode &
302 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
306 * Print question records.
308 if (n = ntohs(hp->qdcount)) {
309 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
310 fprintf(file, ";; QUESTIONS:\n");
312 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
313 fprintf(file, ";;\t");
315 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
316 cp = p_cdnname(cp, msg, len, file);
321 if ((n = dn_expand(msg, msg+len, cp, name,
329 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
330 fprintf(file, ", type = %s",
331 __p_type(_getshort((u_char*)cp)));
334 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
335 fprintf(file, ", class = %s\n",
336 __p_class(_getshort((u_char*)cp)));
338 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
343 * Print authoritative answer records
346 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
351 * print name server records
354 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
355 ";; AUTHORITY RECORDS:\n");
360 * print additional records
362 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
363 ";; ADDITIONAL RECORDS:\n");
367 fprintf(file, "\n;; ...truncated\n");
370 fprintf(file, "\n;; ...malformed\n");
374 __fp_query(msg, file)
378 fp_nquery(msg, PACKETSZ, file);
382 __p_cdnname(cp, msg, len, file)
383 const u_char *cp, *msg;
390 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
400 __p_cdname(cp, msg, file)
401 const u_char *cp, *msg;
404 return (p_cdnname(cp, msg, PACKETSZ, file));
407 /* XXX: the rest of these functions need to become length-limited, too. (vix)
411 __p_fqname(cp, msg, file)
412 const u_char *cp, *msg;
418 if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
420 if (name[0] == '\0') {
424 if (name[strlen(name) - 1] != '.')
431 * Print resource record fields in human readable form.
434 __p_rr(cp, msg, file)
435 const u_char *cp, *msg;
438 int type, class, dlen, n, c;
439 struct in_addr inaddr;
440 const u_char *cp1, *cp2;
444 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
445 h_errno = NETDB_INTERNAL;
448 if ((cp = p_fqname(cp, msg, file)) == NULL)
449 return (NULL); /* compression error */
450 type = _getshort((u_char*)cp);
452 class = _getshort((u_char*)cp);
454 tmpttl = _getlong((u_char*)cp);
456 dlen = _getshort((u_char*)cp);
459 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
460 fprintf(file, "\t%lu", (u_long)tmpttl);
461 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
462 fprintf(file, "\t%s", __p_class(class));
463 fprintf(file, "\t%s", __p_type(type));
465 * Print type specific data, if appropriate
472 bcopy(cp, (char *)&inaddr, INADDRSZ);
474 fprintf(file, "\t%s", inet_ntoa(inaddr));
476 } else if (dlen == 7) {
481 address = inet_ntoa(inaddr);
483 protocol = *(u_char*)cp;
484 cp += sizeof(u_char);
485 port = _getshort((u_char*)cp);
487 fprintf(file, "\t%s\t; proto %d, port %d",
488 address, protocol, port);
502 if ((cp = p_fqname(cp, msg, file)) == NULL)
508 (void) fputs("\t\"", file);
510 if ((n = (unsigned char) *cp++) != 0) {
511 for (c = n; c > 0 && cp < cp2; c--) {
512 if (strchr("\n\"\\", *cp))
513 (void) putc('\\', file);
514 (void) putc(*cp++, file);
518 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
519 (void) fputs ("\t\"", file);
520 for (c = n; c > 0 && cp < cp2; c--) {
521 if (strchr("\n\"\\", *cp))
522 (void) putc('\\', file);
523 (void) putc(*cp++, file);
526 } else if (type == T_HINFO) {
527 (void) fputs("\"?\"", file);
528 fprintf(file, "\n;; *** Warning *** OS-type missing");
534 if ((cp = p_fqname(cp, msg, file)) == NULL)
537 if ((cp = p_fqname(cp, msg, file)) == NULL)
540 t = _getlong((u_char*)cp); cp += INT32SZ;
541 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
542 t = _getlong((u_char*)cp); cp += INT32SZ;
543 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
544 (u_long)t, __p_time(t));
545 t = _getlong((u_char*)cp); cp += INT32SZ;
546 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
547 (u_long)t, __p_time(t));
548 t = _getlong((u_char*)cp); cp += INT32SZ;
549 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
550 (u_long)t, __p_time(t));
551 t = _getlong((u_char*)cp); cp += INT32SZ;
552 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
553 (u_long)t, __p_time(t));
559 fprintf(file, "\t%d ", _getshort((u_char*)cp));
561 if ((cp = p_fqname(cp, msg, file)) == NULL)
566 fprintf(file, "\t%d ", _getshort((u_char*)cp));
568 if ((cp = p_fqname(cp, msg, file)) == NULL)
571 if ((cp = p_fqname(cp, msg, file)) == NULL)
577 (void) fputs("\t\"", file);
580 if (n = (unsigned char) *cp++) {
581 for (c = n; c > 0 && cp < cp2; c--) {
582 if (strchr("\n\"\\", *cp))
583 (void) putc('\\', file);
584 (void) putc(*cp++, file);
592 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
597 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
599 fprintf(file, "\t%s\n", inet_ntop(AF_INET6, cp, t, sizeof t));
607 (void) fprintf(file, "\t%s\n", loc_ntoa(cp, t));
615 if ((cp = p_fqname(cp, msg, file)) == NULL)
618 if ((cp = p_fqname(cp, msg, file)) == NULL)
624 fputs((char *)cp, file);
631 fprintf(file, "\t%u", _getlong((u_char*)cp));
637 if (dlen < INT32SZ + 1)
639 bcopy(cp, (char *)&inaddr, INADDRSZ);
641 fprintf(file, "\t%s %s ( ",
644 cp += sizeof(u_char);
647 while (cp < cp1 + dlen) {
652 fputs("\n\t\t\t", file);
655 fputs(dewks(n), file);
665 #ifdef ALLOW_T_UNSPEC
672 if (dlen < NumBytes) NumBytes = dlen;
673 fprintf(file, "\tFirst %d bytes of hex data:",
675 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
676 fprintf(file, " %x", *DataPtr);
680 #endif /* ALLOW_T_UNSPEC */
683 fprintf(file, "\t?%d?", type);
687 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
691 if (cp - cp1 != dlen) {
692 fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
700 * Return a string for the type
706 static char nbuf[20];
709 case T_A: return "A";
710 case T_NS: return "NS";
711 case T_CNAME: return "CNAME";
712 case T_SOA: return "SOA";
713 case T_MB: return "MB";
714 case T_MG: return "MG";
715 case T_MR: return "MR";
716 case T_NULL: return "NULL";
717 case T_WKS: return "WKS";
718 case T_PTR: return "PTR";
719 case T_HINFO: return "HINFO";
720 case T_MINFO: return "MINFO";
721 case T_MX: return "MX";
722 case T_TXT: return "TXT";
723 case T_RP: return "RP";
724 case T_AFSDB: return "AFSDB";
725 case T_X25: return "X25";
726 case T_ISDN: return "ISDN";
727 case T_RT: return "RT";
728 case T_NSAP: return "NSAP";
729 case T_NSAP_PTR: return "NSAP_PTR";
730 case T_SIG: return "SIG";
731 case T_KEY: return "KEY";
732 case T_PX: return "PX";
733 case T_GPOS: return "GPOS";
734 case T_AAAA: return "AAAA";
735 case T_LOC: return "LOC";
736 case T_AXFR: return "AXFR";
737 case T_MAILB: return "MAILB";
738 case T_MAILA: return "MAILA";
739 case T_ANY: return "ANY";
740 case T_UINFO: return "UINFO";
741 case T_UID: return "UID";
742 case T_GID: return "GID";
743 #ifdef ALLOW_T_UNSPEC
744 case T_UNSPEC: return "UNSPEC";
745 #endif /* ALLOW_T_UNSPEC */
746 default: (void)sprintf(nbuf, "%d", type); return (nbuf);
751 * Return a mnemonic for class
757 static char nbuf[20];
760 case C_IN: return "IN";
761 case C_HS: return "HS";
762 case C_ANY: return "ANY";
763 default: (void)sprintf(nbuf, "%d", class); return (nbuf);
768 * Return a mnemonic for an option
774 static char nbuf[40];
777 case RES_INIT: return "init";
778 case RES_DEBUG: return "debug";
779 case RES_AAONLY: return "aaonly(unimpl)";
780 case RES_USEVC: return "usevc";
781 case RES_PRIMARY: return "primry(unimpl)";
782 case RES_IGNTC: return "igntc";
783 case RES_RECURSE: return "recurs";
784 case RES_DEFNAMES: return "defnam";
785 case RES_STAYOPEN: return "styopn";
786 case RES_DNSRCH: return "dnsrch";
787 case RES_INSECURE1: return "insecure1";
788 case RES_INSECURE2: return "insecure2";
789 default: sprintf(nbuf, "?0x%lx?", (u_long)option);
795 * Return a mnemonic for a time to live
801 static char nbuf[40];
802 int secs, mins, hours, days;
806 strcpy(nbuf, "0 secs");
819 #define PLURALIZE(x) x, (x == 1) ? "" : "s"
822 (void)sprintf(p, "%d day%s", PLURALIZE(days));
828 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
834 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
837 if (secs || ! (days || hours || mins)) {
838 if (days || hours || mins)
840 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
846 * routines to convert between on-the-wire RR format and zone file format.
847 * Does not contain conversion to/from decimal degrees; divide or multiply
848 * by 60*60*1000 for that.
851 static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
852 1000000,10000000,100000000,1000000000};
854 /* takes an XeY precision/size value, returns a string representation. */
859 static char retbuf[sizeof("90000000.00")];
861 int mantissa, exponent;
863 mantissa = (int)((prec >> 4) & 0x0f) % 10;
864 exponent = (int)((prec >> 0) & 0x0f) % 10;
866 val = mantissa * poweroften[exponent];
868 (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
872 /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
874 precsize_aton(strptr)
877 unsigned int mval = 0, cmval = 0;
880 register int exponent;
881 register int mantissa;
886 mval = mval * 10 + (*cp++ - '0');
888 if (*cp == '.') { /* centimeters */
891 cmval = (*cp++ - '0') * 10;
893 cmval += (*cp++ - '0');
897 cmval = (mval * 100) + cmval;
899 for (exponent = 0; exponent < 9; exponent++)
900 if (cmval < poweroften[exponent+1])
903 mantissa = cmval / poweroften[exponent];
907 retval = (mantissa << 4) | exponent;
914 /* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
916 latlon2ul(latlonstrptr,which)
922 int deg = 0, min = 0, secs = 0, secsfrac = 0;
927 deg = deg * 10 + (*cp++ - '0');
936 min = min * 10 + (*cp++ - '0');
945 secs = secs * 10 + (*cp++ - '0');
947 if (*cp == '.') { /* decimal seconds */
950 secsfrac = (*cp++ - '0') * 100;
952 secsfrac += (*cp++ - '0') * 10;
954 secsfrac += (*cp++ - '0');
960 while (!isspace(*cp)) /* if any trailing garbage */
970 retval = ((unsigned)1<<31)
971 + (((((deg * 60) + min) * 60) + secs) * 1000)
976 retval = ((unsigned)1<<31)
977 - (((((deg * 60) + min) * 60) + secs) * 1000)
981 retval = 0; /* invalid value -- indicates error */
988 *which = 1; /* latitude */
992 *which = 2; /* longitude */
995 *which = 0; /* error */
999 cp++; /* skip the hemisphere */
1001 while (!isspace(*cp)) /* if any trailing garbage */
1004 while (isspace(*cp)) /* move to next field */
1012 /* converts a zone file representation in a string to an RDATA on-the-wire
1013 * representation. */
1015 loc_aton(ascii, binary)
1019 const char *cp, *maxcp;
1022 u_int32_t latit = 0, longit = 0, alt = 0;
1023 u_int32_t lltemp1 = 0, lltemp2 = 0;
1024 int altmeters = 0, altfrac = 0, altsign = 1;
1025 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1026 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1027 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1028 int which1 = 0, which2 = 0;
1031 maxcp = cp + strlen(ascii);
1033 lltemp1 = latlon2ul(&cp, &which1);
1035 lltemp2 = latlon2ul(&cp, &which2);
1037 switch (which1 + which2) {
1038 case 3: /* 1 + 2, the only valid combination */
1039 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1042 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1045 } else { /* some kind of brokenness */
1049 default: /* we didn't get one of each */
1062 while (isdigit(*cp))
1063 altmeters = altmeters * 10 + (*cp++ - '0');
1065 if (*cp == '.') { /* decimal meters */
1068 altfrac = (*cp++ - '0') * 10;
1070 altfrac += (*cp++ - '0');
1075 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1077 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1080 while (isspace(*cp) && (cp < maxcp))
1086 siz = precsize_aton(&cp);
1088 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1091 while (isspace(*cp) && (cp < maxcp))
1097 hp = precsize_aton(&cp);
1099 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1102 while (isspace(*cp) && (cp < maxcp))
1108 vp = precsize_aton(&cp);
1113 *bcp++ = (u_int8_t) 0; /* version byte */
1118 PUTLONG(longit,bcp);
1121 return (16); /* size of RR in octets */
1124 /* takes an on-the-wire LOC RR and formats it in a human readable format. */
1126 loc_ntoa(binary, ascii)
1127 const u_char *binary;
1130 static char *error = "?";
1131 register const u_char *cp = binary;
1133 int latdeg, latmin, latsec, latsecfrac;
1134 int longdeg, longmin, longsec, longsecfrac;
1135 char northsouth, eastwest;
1136 int altmeters, altfrac, altsign;
1138 const int referencealt = 100000 * 100;
1140 int32_t latval, longval, altval;
1142 u_int8_t sizeval, hpval, vpval, versionval;
1144 char *sizestr, *hpstr, *vpstr;
1149 sprintf(ascii, "; error: unknown LOC RR version");
1159 latval = (templ - ((unsigned)1<<31));
1162 longval = (templ - ((unsigned)1<<31));
1165 if (templ < referencealt) { /* below WGS 84 spheroid */
1166 altval = referencealt - templ;
1169 altval = templ - referencealt;
1179 latsecfrac = latval % 1000;
1180 latval = latval / 1000;
1181 latsec = latval % 60;
1182 latval = latval / 60;
1183 latmin = latval % 60;
1184 latval = latval / 60;
1193 longsecfrac = longval % 1000;
1194 longval = longval / 1000;
1195 longsec = longval % 60;
1196 longval = longval / 60;
1197 longmin = longval % 60;
1198 longval = longval / 60;
1201 altfrac = altval % 100;
1202 altmeters = (altval / 100) * altsign;
1204 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1206 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1208 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1212 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1213 latdeg, latmin, latsec, latsecfrac, northsouth,
1214 longdeg, longmin, longsec, longsecfrac, eastwest,
1215 altmeters, altfrac, sizestr, hpstr, vpstr);
1217 if (sizestr != error)