]> git.ipfire.org Git - thirdparty/glibc.git/blame - resolv/res_debug.c
Update.
[thirdparty/glibc.git] / resolv / res_debug.c
CommitLineData
28f540f4
RM
1/*
2 * ++Copyright++ 1985, 1990, 1993
3 * -
4 * Copyright (c) 1985, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
fa0bc87c 6 *
28f540f4
RM
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
fa0bc87c 22 *
28f540f4
RM
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
33 * SUCH DAMAGE.
34 * -
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
fa0bc87c 36 *
28f540f4
RM
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.
fa0bc87c 43 *
28f540f4
RM
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
51 * SOFTWARE.
52 * -
df21c858
UD
53 * Portions Copyright (c) 1995 by International Business Machines, Inc.
54 *
55 * International Business Machines, Inc. (hereinafter called IBM) grants
56 * permission under its copyrights to use, copy, modify, and distribute this
57 * Software with or without fee, provided that the above copyright notice and
58 * all paragraphs of this notice appear in all copies, and that the name of IBM
59 * not be used in connection with the marketing of any product incorporating
60 * the Software or modifications thereof, without specific, written prior
61 * permission.
62 *
63 * To the extent it has a right to do so, IBM grants an immunity from suit
64 * under its patents, if any, for the use, sale or manufacture of products to
65 * the extent that such products are used for performing Domain Name System
66 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
67 * granted for any product per se or for any other function of any product.
68 *
69 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
70 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
71 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
72 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
73 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
74 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
28f540f4
RM
75 * --Copyright--
76 */
77
78#if defined(LIBC_SCCS) && !defined(lint)
79static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
80static char rcsid[] = "$Id$";
81#endif /* LIBC_SCCS and not lint */
82
83#include <sys/param.h>
fa0bc87c
RM
84#include <sys/types.h>
85#include <sys/socket.h>
28f540f4
RM
86#include <netinet/in.h>
87#include <arpa/inet.h>
88#include <arpa/nameser.h>
89
58e07151 90#include <ctype.h>
3d61b63c 91#include <netdb.h>
28f540f4 92#include <resolv.h>
df21c858
UD
93#include <stdio.h>
94#include <time.h>
95
fa0bc87c 96#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
df21c858 97# include <stdlib.h>
28f540f4
RM
98# include <string.h>
99#else
100# include "../conf/portability.h"
101#endif
102
103#if defined(USE_OPTIONS_H)
104# include "../conf/options.h"
105#endif
106
a2e1b046
RM
107extern const char *_res_opcodes[];
108extern const char *_res_resultcodes[];
28f540f4 109
3d61b63c 110/* XXX: we should use getservbyport() instead. */
28f540f4
RM
111static const char *
112dewks(wks)
113 int wks;
114{
3d61b63c
RM
115 static char nbuf[20];
116
28f540f4
RM
117 switch (wks) {
118 case 5: return "rje";
119 case 7: return "echo";
120 case 9: return "discard";
121 case 11: return "systat";
122 case 13: return "daytime";
123 case 15: return "netstat";
124 case 17: return "qotd";
125 case 19: return "chargen";
126 case 20: return "ftp-data";
127 case 21: return "ftp";
128 case 23: return "telnet";
129 case 25: return "smtp";
130 case 37: return "time";
131 case 39: return "rlp";
132 case 42: return "name";
133 case 43: return "whois";
134 case 53: return "domain";
135 case 57: return "apts";
136 case 59: return "apfs";
137 case 67: return "bootps";
138 case 68: return "bootpc";
139 case 69: return "tftp";
140 case 77: return "rje";
141 case 79: return "finger";
142 case 87: return "link";
143 case 95: return "supdup";
144 case 100: return "newacct";
145 case 101: return "hostnames";
146 case 102: return "iso-tsap";
147 case 103: return "x400";
148 case 104: return "x400-snd";
149 case 105: return "csnet-ns";
150 case 109: return "pop-2";
151 case 111: return "sunrpc";
152 case 113: return "auth";
153 case 115: return "sftp";
154 case 117: return "uucp-path";
155 case 119: return "nntp";
156 case 121: return "erpc";
157 case 123: return "ntp";
158 case 133: return "statsrv";
159 case 136: return "profile";
160 case 144: return "NeWS";
161 case 161: return "snmp";
162 case 162: return "snmp-trap";
163 case 170: return "print-srv";
3d61b63c 164 default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
28f540f4
RM
165 }
166}
167
3d61b63c 168/* XXX: we should use getprotobynumber() instead. */
28f540f4
RM
169static const char *
170deproto(protonum)
171 int protonum;
172{
3d61b63c
RM
173 static char nbuf[20];
174
28f540f4
RM
175 switch (protonum) {
176 case 1: return "icmp";
177 case 2: return "igmp";
178 case 3: return "ggp";
179 case 5: return "st";
180 case 6: return "tcp";
181 case 7: return "ucl";
182 case 8: return "egp";
183 case 9: return "igp";
184 case 11: return "nvp-II";
185 case 12: return "pup";
186 case 16: return "chaos";
187 case 17: return "udp";
3d61b63c 188 default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
28f540f4
RM
189 }
190}
191
192static const u_char *
3d61b63c
RM
193do_rrset(msg, len, cp, cnt, pflag, file, hs)
194 int cnt, pflag, len;
28f540f4
RM
195 const u_char *cp, *msg;
196 const char *hs;
197 FILE *file;
198{
199 int n;
200 int sflag;
201
202 /*
203 * Print answer records.
204 */
205 sflag = (_res.pfcode & pflag);
6796bc80 206 if ((n = ntohs(cnt))) {
28f540f4
RM
207 if ((!_res.pfcode) ||
208 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
209 fprintf(file, hs);
210 while (--n >= 0) {
211 if ((!_res.pfcode) || sflag) {
212 cp = p_rr(cp, msg, file);
213 } else {
214 unsigned int dlen;
215 cp += __dn_skipname(cp, cp + MAXCDNAME);
216 cp += INT16SZ;
217 cp += INT16SZ;
218 cp += INT32SZ;
219 dlen = _getshort((u_char*)cp);
220 cp += INT16SZ;
221 cp += dlen;
222 }
3d61b63c 223 if ((cp - msg) > len)
28f540f4
RM
224 return (NULL);
225 }
226 if ((!_res.pfcode) ||
227 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
228 putc('\n', file);
229 }
230 return (cp);
231}
232
233void
234__p_query(msg)
235 const u_char *msg;
236{
237 __fp_query(msg, stdout);
238}
239
240#ifdef ultrix
845dcb57 241#undef p_query
28f540f4
RM
242/* ultrix 4.0's packaging has some icky packaging. alias for it here.
243 * there is more junk of this kind over in res_comp.c.
244 */
245void
246p_query(msg)
247 const u_char *msg;
248{
249 __p_query(msg);
250}
251#endif
252
253/*
254 * Print the current options.
255 * This is intended to be primarily a debugging routine.
256 */
257void
258__fp_resstat(statp, file)
259 struct __res_state *statp;
260 FILE *file;
261{
262 register u_long mask;
263
264 fprintf(file, ";; res options:");
265 if (!statp)
266 statp = &_res;
267 for (mask = 1; mask != 0; mask <<= 1)
268 if (statp->options & mask)
269 fprintf(file, " %s", p_option(mask));
270 putc('\n', file);
271}
272
273/*
274 * Print the contents of a query.
275 * This is intended to be primarily a debugging routine.
276 */
277void
278__fp_nquery(msg, len, file)
279 const u_char *msg;
280 int len;
281 FILE *file;
282{
283 register const u_char *cp, *endMark;
284 register const HEADER *hp;
285 register int n;
286
3d61b63c
RM
287 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
288 return;
289
6d52618b 290#define TruncTest(x) if (x > endMark) goto trunc
28f540f4
RM
291#define ErrorTest(x) if (x == NULL) goto error
292
293 /*
294 * Print header fields.
295 */
296 hp = (HEADER *)msg;
297 cp = msg + HFIXEDSZ;
26761c28 298 endMark = msg + len;
28f540f4
RM
299 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
300 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
301 _res_opcodes[hp->opcode],
302 _res_resultcodes[hp->rcode],
303 ntohs(hp->id));
304 putc('\n', file);
305 }
a4219bc4 306 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
a2e1b046 307 putc(';', file);
28f540f4
RM
308 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
309 fprintf(file, "; flags:");
310 if (hp->qr)
311 fprintf(file, " qr");
312 if (hp->aa)
313 fprintf(file, " aa");
314 if (hp->tc)
315 fprintf(file, " tc");
316 if (hp->rd)
317 fprintf(file, " rd");
318 if (hp->ra)
319 fprintf(file, " ra");
df21c858
UD
320 if (hp->unused)
321 fprintf(file, " UNUSED-BIT-ON");
322 if (hp->ad)
323 fprintf(file, " ad");
324 if (hp->cd)
325 fprintf(file, " cd");
28f540f4
RM
326 }
327 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
328 fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
329 fprintf(file, ", Ans: %d", ntohs(hp->ancount));
330 fprintf(file, ", Auth: %d", ntohs(hp->nscount));
331 fprintf(file, ", Addit: %d", ntohs(hp->arcount));
332 }
fa0bc87c 333 if ((!_res.pfcode) || (_res.pfcode &
28f540f4
RM
334 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
335 putc('\n',file);
336 }
337 /*
338 * Print question records.
339 */
6796bc80 340 if ((n = ntohs(hp->qdcount))) {
28f540f4
RM
341 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
342 fprintf(file, ";; QUESTIONS:\n");
343 while (--n >= 0) {
a4219bc4 344 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
a2e1b046 345 fprintf(file, ";;\t");
28f540f4 346 TruncTest(cp);
a4219bc4 347 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
a2e1b046 348 cp = p_cdnname(cp, msg, len, file);
a4219bc4
RM
349 else {
350 int n;
351 char name[MAXDNAME];
352
353 if ((n = dn_expand(msg, msg+len, cp, name,
354 sizeof name)) < 0)
355 cp = NULL;
356 else
357 cp += n;
358 }
28f540f4
RM
359 ErrorTest(cp);
360 TruncTest(cp);
361 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
362 fprintf(file, ", type = %s",
363 __p_type(_getshort((u_char*)cp)));
364 cp += INT16SZ;
365 TruncTest(cp);
366 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
367 fprintf(file, ", class = %s\n",
368 __p_class(_getshort((u_char*)cp)));
369 cp += INT16SZ;
a4219bc4 370 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
a2e1b046 371 putc('\n', file);
28f540f4
RM
372 }
373 }
374 /*
375 * Print authoritative answer records
376 */
377 TruncTest(cp);
3d61b63c 378 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
28f540f4
RM
379 ";; ANSWERS:\n");
380 ErrorTest(cp);
381
382 /*
383 * print name server records
384 */
385 TruncTest(cp);
3d61b63c 386 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
28f540f4
RM
387 ";; AUTHORITY RECORDS:\n");
388 ErrorTest(cp);
389
390 TruncTest(cp);
391 /*
392 * print additional records
393 */
3d61b63c 394 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
28f540f4
RM
395 ";; ADDITIONAL RECORDS:\n");
396 ErrorTest(cp);
397 return;
398 trunc:
399 fprintf(file, "\n;; ...truncated\n");
400 return;
401 error:
402 fprintf(file, "\n;; ...malformed\n");
403}
404
405void
406__fp_query(msg, file)
407 const u_char *msg;
408 FILE *file;
409{
410 fp_nquery(msg, PACKETSZ, file);
411}
412
413const u_char *
414__p_cdnname(cp, msg, len, file)
415 const u_char *cp, *msg;
416 int len;
417 FILE *file;
418{
419 char name[MAXDNAME];
420 int n;
421
422 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
423 return (NULL);
424 if (name[0] == '\0')
425 putc('.', file);
426 else
427 fputs(name, file);
428 return (cp + n);
429}
430
431const u_char *
432__p_cdname(cp, msg, file)
433 const u_char *cp, *msg;
434 FILE *file;
435{
436 return (p_cdnname(cp, msg, PACKETSZ, file));
437}
438
df21c858
UD
439
440/* Return a fully-qualified domain name from a compressed name (with
441 length supplied). */
442
443const u_char *
444__p_fqnname(cp, msg, msglen, name, namelen)
445 const u_char *cp, *msg;
446 int msglen;
447 char *name;
448 int namelen;
449{
450 int n, newlen;
451
452 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
453 return (NULL);
454 newlen = strlen (name);
455 if (newlen == 0 || name[newlen - 1] != '.')
456 if (newlen+1 >= namelen) /* Lack space for final dot */
457 return (NULL);
458 else
459 strcpy(name + newlen, ".");
460 return (cp + n);
461}
462
28f540f4
RM
463/* XXX: the rest of these functions need to become length-limited, too. (vix)
464 */
465
466const u_char *
467__p_fqname(cp, msg, file)
468 const u_char *cp, *msg;
469 FILE *file;
470{
471 char name[MAXDNAME];
df21c858 472 const u_char *n;
28f540f4 473
df21c858
UD
474 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
475 if (n == NULL)
28f540f4 476 return (NULL);
df21c858
UD
477 fputs(name, file);
478 return (n);
28f540f4
RM
479}
480
481/*
482 * Print resource record fields in human readable form.
483 */
484const u_char *
485__p_rr(cp, msg, file)
486 const u_char *cp, *msg;
487 FILE *file;
488{
489 int type, class, dlen, n, c;
490 struct in_addr inaddr;
491 const u_char *cp1, *cp2;
492 u_int32_t tmpttl, t;
493 int lcnt;
df21c858
UD
494 u_int16_t keyflags;
495 char rrname[MAXDNAME]; /* The fqdn of this RR */
496 char base64_key[MAX_KEY_BASE64];
28f540f4 497
3d61b63c 498 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
a68b0d31 499 __set_h_errno (NETDB_INTERNAL);
3d61b63c
RM
500 return (NULL);
501 }
df21c858
UD
502 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
503 if (!cp)
28f540f4 504 return (NULL); /* compression error */
df21c858
UD
505 fputs(rrname, file);
506
28f540f4
RM
507 type = _getshort((u_char*)cp);
508 cp += INT16SZ;
509 class = _getshort((u_char*)cp);
510 cp += INT16SZ;
511 tmpttl = _getlong((u_char*)cp);
512 cp += INT32SZ;
513 dlen = _getshort((u_char*)cp);
514 cp += INT16SZ;
515 cp1 = cp;
516 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
3d61b63c 517 fprintf(file, "\t%lu", (u_long)tmpttl);
28f540f4
RM
518 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
519 fprintf(file, "\t%s", __p_class(class));
520 fprintf(file, "\t%s", __p_type(type));
521 /*
522 * Print type specific data, if appropriate
523 */
524 switch (type) {
525 case T_A:
526 switch (class) {
527 case C_IN:
528 case C_HS:
529 bcopy(cp, (char *)&inaddr, INADDRSZ);
530 if (dlen == 4) {
531 fprintf(file, "\t%s", inet_ntoa(inaddr));
532 cp += dlen;
533 } else if (dlen == 7) {
534 char *address;
535 u_char protocol;
536 u_short port;
537
538 address = inet_ntoa(inaddr);
539 cp += INADDRSZ;
540 protocol = *(u_char*)cp;
df21c858 541 cp += sizeof (u_char);
28f540f4
RM
542 port = _getshort((u_char*)cp);
543 cp += INT16SZ;
544 fprintf(file, "\t%s\t; proto %d, port %d",
545 address, protocol, port);
546 }
547 break;
548 default:
549 cp += dlen;
550 }
551 break;
552 case T_CNAME:
553 case T_MB:
554 case T_MG:
555 case T_MR:
556 case T_NS:
557 case T_PTR:
558 putc('\t', file);
559 if ((cp = p_fqname(cp, msg, file)) == NULL)
560 return (NULL);
561 break;
562
563 case T_HINFO:
564 case T_ISDN:
565 cp2 = cp + dlen;
df21c858 566 (void) fputs("\t\"", file);
55707265
RM
567 if ((n = (unsigned char) *cp++) != 0) {
568 for (c = n; c > 0 && cp < cp2; c--) {
569 if (strchr("\n\"\\", *cp))
570 (void) putc('\\', file);
571 (void) putc(*cp++, file);
572 }
28f540f4 573 }
df21c858 574 putc('"', file);
55707265
RM
575 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
576 (void) fputs ("\t\"", file);
577 for (c = n; c > 0 && cp < cp2; c--) {
578 if (strchr("\n\"\\", *cp))
579 (void) putc('\\', file);
580 (void) putc(*cp++, file);
581 }
582 putc('"', file);
583 } else if (type == T_HINFO) {
584 (void) fputs("\"?\"", file);
28f540f4 585 fprintf(file, "\n;; *** Warning *** OS-type missing");
55707265 586 }
28f540f4
RM
587 break;
588
589 case T_SOA:
590 putc('\t', file);
591 if ((cp = p_fqname(cp, msg, file)) == NULL)
592 return (NULL);
593 putc(' ', file);
594 if ((cp = p_fqname(cp, msg, file)) == NULL)
595 return (NULL);
596 fputs(" (\n", file);
597 t = _getlong((u_char*)cp); cp += INT32SZ;
3d61b63c 598 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
28f540f4 599 t = _getlong((u_char*)cp); cp += INT32SZ;
3d61b63c
RM
600 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
601 (u_long)t, __p_time(t));
28f540f4 602 t = _getlong((u_char*)cp); cp += INT32SZ;
3d61b63c
RM
603 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
604 (u_long)t, __p_time(t));
28f540f4 605 t = _getlong((u_char*)cp); cp += INT32SZ;
3d61b63c
RM
606 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
607 (u_long)t, __p_time(t));
28f540f4 608 t = _getlong((u_char*)cp); cp += INT32SZ;
3d61b63c
RM
609 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
610 (u_long)t, __p_time(t));
28f540f4
RM
611 break;
612
613 case T_MX:
614 case T_AFSDB:
615 case T_RT:
616 fprintf(file, "\t%d ", _getshort((u_char*)cp));
617 cp += INT16SZ;
618 if ((cp = p_fqname(cp, msg, file)) == NULL)
619 return (NULL);
620 break;
621
622 case T_PX:
623 fprintf(file, "\t%d ", _getshort((u_char*)cp));
624 cp += INT16SZ;
625 if ((cp = p_fqname(cp, msg, file)) == NULL)
626 return (NULL);
627 putc(' ', file);
628 if ((cp = p_fqname(cp, msg, file)) == NULL)
629 return (NULL);
630 break;
631
28f540f4 632 case T_X25:
df21c858 633 cp2 = cp + dlen;
28f540f4 634 (void) fputs("\t\"", file);
df21c858
UD
635 if ((n = (unsigned char) *cp++) != 0) {
636 for (c = n; c > 0 && cp < cp2; c--) {
637 if (strchr("\n\"\\", *cp))
638 (void) putc('\\', file);
639 (void) putc(*cp++, file);
640 }
641 }
642 putc('"', file);
643 break;
644
645 case T_TXT:
646 (void) putc('\t', file);
28f540f4
RM
647 cp2 = cp1 + dlen;
648 while (cp < cp2) {
df21c858 649 putc('"', file);
6796bc80 650 if ((n = (unsigned char) *cp++)) {
55707265
RM
651 for (c = n; c > 0 && cp < cp2; c--) {
652 if (strchr("\n\"\\", *cp))
653 (void) putc('\\', file);
654 (void) putc(*cp++, file);
655 }
28f540f4 656 }
df21c858
UD
657 putc('"', file);
658 if (cp < cp2)
659 putc(' ', file);
28f540f4 660 }
28f540f4
RM
661 break;
662
663 case T_NSAP:
664 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
665 cp += dlen;
666 break;
667
fa0bc87c
RM
668 case T_AAAA: {
669 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
670
14bab8de 671 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
ee188d55
RM
672 cp += dlen;
673 break;
1f64ac13 674 }
ee188d55
RM
675
676 case T_LOC: {
677 char t[255];
678
14bab8de 679 (void) fprintf(file, "\t%s", loc_ntoa(cp, t));
ee188d55 680 cp += dlen;
fa0bc87c 681 break;
1f64ac13
UD
682 }
683
684 case T_NAPTR: {
685 u_int order, preference;
686
687 order = _getshort(cp); cp += INT16SZ;
688 preference = _getshort(cp); cp += INT16SZ;
689 fprintf(file, "\t%u %u ",order, preference);
690 /* Flags */
691 n = *cp++;
692 fprintf(file,"\"%.*s\" ", (int)n, cp);
693 cp += n;
694 /* Service */
695 n = *cp++;
696 fprintf(file,"\"%.*s\" ", (int)n, cp);
697 cp += n;
698 /* Regexp */
699 n = *cp++;
700 fprintf(file,"\"%.*s\" ", (int)n, cp);
701 cp += n;
702 if ((cp = p_fqname(cp, msg, file)) == NULL)
703 return (NULL);
704 break;
705 }
fa0bc87c 706
14bab8de
UD
707 case T_SRV: {
708 u_int priority, weight, port;
709
710 priority = _getshort(cp); cp += INT16SZ;
711 weight = _getshort(cp); cp += INT16SZ;
712 port = _getshort(cp); cp += INT16SZ;
713 fprintf(file, "\t%u %u %u ", priority, weight, port);
714 if ((cp = p_fqname(cp, msg, file)) == NULL)
715 return (NULL);
716 break;
1f64ac13 717 }
14bab8de 718
28f540f4
RM
719 case T_MINFO:
720 case T_RP:
721 putc('\t', file);
722 if ((cp = p_fqname(cp, msg, file)) == NULL)
723 return (NULL);
724 putc(' ', file);
725 if ((cp = p_fqname(cp, msg, file)) == NULL)
726 return (NULL);
727 break;
728
729 case T_UINFO:
730 putc('\t', file);
731 fputs((char *)cp, file);
732 cp += dlen;
733 break;
734
735 case T_UID:
736 case T_GID:
737 if (dlen == 4) {
738 fprintf(file, "\t%u", _getlong((u_char*)cp));
739 cp += INT32SZ;
740 }
741 break;
742
743 case T_WKS:
744 if (dlen < INT32SZ + 1)
745 break;
746 bcopy(cp, (char *)&inaddr, INADDRSZ);
747 cp += INT32SZ;
748 fprintf(file, "\t%s %s ( ",
749 inet_ntoa(inaddr),
750 deproto((int) *cp));
df21c858 751 cp += sizeof (u_char);
28f540f4
RM
752 n = 0;
753 lcnt = 0;
754 while (cp < cp1 + dlen) {
755 c = *cp++;
756 do {
757 if (c & 0200) {
758 if (lcnt == 0) {
759 fputs("\n\t\t\t", file);
760 lcnt = 5;
761 }
762 fputs(dewks(n), file);
763 putc(' ', file);
764 lcnt--;
765 }
766 c <<= 1;
767 } while (++n & 07);
768 }
769 putc(')', file);
770 break;
771
df21c858
UD
772 case T_KEY:
773 putc('\t', file);
774 keyflags = _getshort(cp);
775 cp += 2;
776 fprintf(file,"0x%04x", keyflags ); /* flags */
777 fprintf(file," %u", *cp++); /* protocol */
778 fprintf(file," %u (", *cp++); /* algorithm */
779
780 n = b64_ntop(cp, (cp1 + dlen) - cp,
781 base64_key, sizeof base64_key);
782 for (c = 0; c < n; ++c) {
783 if (0 == (c & 0x3F))
784 fprintf(file, "\n\t");
785 putc(base64_key[c], file); /* public key data */
786 }
787
788 fprintf(file, " )");
789 if (n < 0)
790 fprintf(file, "\t; BAD BASE64");
791 fflush(file);
792 cp = cp1 + dlen;
793 break;
794
795 case T_SIG:
796 type = _getshort((u_char*)cp);
797 cp += INT16SZ;
798 fprintf(file, " %s", p_type(type));
799 fprintf(file, "\t%d", *cp++); /* algorithm */
800 /* Check label value and print error if wrong. */
801 n = *cp++;
802 c = dn_count_labels (rrname);
803 if (n != c)
804 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
805 n, c);
806 /* orig ttl */
807 n = _getlong((u_char*)cp);
df4ef2ab 808 if ((u_int32_t) n != tmpttl)
df21c858
UD
809 fprintf(file, " %u", n);
810 cp += INT32SZ;
811 /* sig expire */
812 fprintf(file, " (\n\t%s",
813 __p_secstodate(_getlong((u_char*)cp)));
814 cp += INT32SZ;
815 /* time signed */
816 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
817 cp += INT32SZ;
818 /* sig footprint */
819 fprintf(file," %u ", _getshort((u_char*)cp));
820 cp += INT16SZ;
821 /* signer's name */
822 cp = p_fqname(cp, msg, file);
823 n = b64_ntop(cp, (cp1 + dlen) - cp,
824 base64_key, sizeof base64_key);
825 for (c = 0; c < n; c++) {
826 if (0 == (c & 0x3F))
827 fprintf (file, "\n\t");
828 putc(base64_key[c], file); /* signature */
829 }
830 /* Clean up... */
831 fprintf(file, " )");
832 if (n < 0)
833 fprintf(file, "\t; BAD BASE64");
834 fflush(file);
835 cp = cp1+dlen;
836 break;
837
28f540f4
RM
838#ifdef ALLOW_T_UNSPEC
839 case T_UNSPEC:
840 {
841 int NumBytes = 8;
842 u_char *DataPtr;
843 int i;
844
845 if (dlen < NumBytes) NumBytes = dlen;
846 fprintf(file, "\tFirst %d bytes of hex data:",
847 NumBytes);
848 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
849 fprintf(file, " %x", *DataPtr);
850 cp += dlen;
851 }
852 break;
853#endif /* ALLOW_T_UNSPEC */
854
855 default:
856 fprintf(file, "\t?%d?", type);
857 cp += dlen;
858 }
859#if 0
860 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
861#else
862 putc('\n', file);
863#endif
864 if (cp - cp1 != dlen) {
a4242e25
RM
865 fprintf(file,
866 ";; packet size error (found %lu, dlen was %d)\n",
867 (unsigned long) (cp - cp1), dlen);
28f540f4
RM
868 cp = NULL;
869 }
870 return (cp);
871}
872
df21c858
UD
873/*
874 * Names of RR classes and qclasses. Classes and qclasses are the same, except
875 * that C_ANY is a qclass but not a class. (You can ask for records of class
876 * C_ANY, but you can't have any records of that class in the database.)
877 */
878const struct res_sym __p_class_syms[] = {
879 {C_IN, "IN"},
880 {C_CHAOS, "CHAOS"},
881 {C_HS, "HS"},
882 {C_HS, "HESIOD"},
883 {C_ANY, "ANY"},
884 {C_IN, (char *)0}
885};
886
887/*
888 * Names of RR types and qtypes. Types and qtypes are the same, except
889 * that T_ANY is a qtype but not a type. (You can ask for records of type
890 * T_ANY, but you can't have any records of that type in the database.)
891 */
892const struct res_sym __p_type_syms[] = {
893 {T_A, "A", "address"},
894 {T_NS, "NS", "name server"},
14bab8de
UD
895 {T_MD, "MD", "mail destination (deprecated)"},
896 {T_MF, "MF", "mail forwarder (deprecated)"},
df21c858
UD
897 {T_CNAME, "CNAME", "canonical name"},
898 {T_SOA, "SOA", "start of authority"},
899 {T_MB, "MB", "mailbox"},
900 {T_MG, "MG", "mail group member"},
901 {T_MR, "MR", "mail rename"},
902 {T_NULL, "NULL", "null"},
14bab8de 903 {T_WKS, "WKS", "well-known service (deprecated)"},
df21c858
UD
904 {T_PTR, "PTR", "domain name pointer"},
905 {T_HINFO, "HINFO", "host information"},
906 {T_MINFO, "MINFO", "mailbox information"},
907 {T_MX, "MX", "mail exchanger"},
908 {T_TXT, "TXT", "text"},
909 {T_RP, "RP", "responsible person"},
910 {T_AFSDB, "AFSDB", "DCE or AFS server"},
911 {T_X25, "X25", "X25 address"},
912 {T_ISDN, "ISDN", "ISDN address"},
913 {T_RT, "RT", "router"},
914 {T_NSAP, "NSAP", "nsap address"},
915 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
916 {T_SIG, "SIG", "signature"},
917 {T_KEY, "KEY", "key"},
df21c858 918 {T_PX, "PX", "mapping information"},
14bab8de 919 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
df21c858
UD
920 {T_AAAA, "AAAA", "IPv6 address"},
921 {T_LOC, "LOC", "location"},
14bab8de
UD
922 {T_NXT, "NXT", "next valid name (unimplemented)"},
923 {T_EID, "EID", "endpoint identifier (unimplemented)"},
924 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
925 {T_SRV, "SRV", "server selection"},
926 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
927 {T_IXFR, "IXFR", "incremental zone transfer"},
df21c858 928 {T_AXFR, "AXFR", "zone transfer"},
14bab8de
UD
929 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
930 {T_MAILA, "MAILA", "mail agent (deprecated)"},
931 {T_UINFO, "UINFO", "user information (nonstandard)"},
932 {T_UID, "UID", "user ID (nonstandard)"},
933 {T_GID, "GID", "group ID (nonstandard)"},
1f64ac13 934 {T_NAPTR, "NAPTR", "URN Naming Authority"},
df21c858 935#ifdef ALLOW_T_UNSPEC
14bab8de 936 {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
df21c858
UD
937#endif /* ALLOW_T_UNSPEC */
938 {T_ANY, "ANY", "\"any\""},
14bab8de 939 {0, NULL, NULL}
df21c858
UD
940};
941
942int
943__sym_ston(syms, name, success)
944 const struct res_sym *syms;
945 char *name;
946 int *success;
947{
948#ifdef _LIBC
949 /* Changed to prevent warning. --drepper@gnu */
950 for (; syms->name != 0; syms++) {
951#else
952 for (NULL; syms->name != 0; syms++) {
953#endif
954 if (strcasecmp (name, syms->name) == 0) {
955 if (success)
956 *success = 1;
957 return (syms->number);
958 }
959 }
960 if (success)
961 *success = 0;
962 return (syms->number); /* The default value. */
963}
964
965const char *
966__sym_ntos(syms, number, success)
967 const struct res_sym *syms;
968 int number;
969 int *success;
970{
971 static char unname[20];
972
973#ifdef _LIBC
974 /* Changed to prevent warning. --drepper@gnu */
975 for (; syms->name != 0; syms++) {
976#else
977 for (NULL; syms->name != 0; syms++) {
978#endif
979 if (number == syms->number) {
980 if (success)
981 *success = 1;
982 return (syms->name);
983 }
984 }
985
986 sprintf (unname, "%d", number);
987 if (success)
988 *success = 0;
989 return (unname);
990}
991
992
993const char *
994__sym_ntop(syms, number, success)
995 const struct res_sym *syms;
996 int number;
997 int *success;
998{
999 static char unname[20];
1000
1001#ifdef _LIBC
1002 /* Changed to prevent warning. --drepper@gnu */
1003 for (; syms->name != 0; syms++) {
1004#else
1005 for (NULL; syms->name != 0; syms++) {
1006#endif
1007 if (number == syms->number) {
1008 if (success)
1009 *success = 1;
1010 return (syms->humanname);
1011 }
1012 }
1013 sprintf(unname, "%d", number);
1014 if (success)
1015 *success = 0;
1016 return (unname);
1017}
1018
28f540f4
RM
1019/*
1020 * Return a string for the type
1021 */
1022const char *
1023__p_type(type)
1024 int type;
1025{
df21c858 1026 return (__sym_ntos (__p_type_syms, type, (int *)0));
28f540f4
RM
1027}
1028
1029/*
1030 * Return a mnemonic for class
1031 */
1032const char *
1033__p_class(class)
1034 int class;
1035{
df21c858 1036 return (__sym_ntos (__p_class_syms, class, (int *)0));
28f540f4
RM
1037}
1038
1039/*
1040 * Return a mnemonic for an option
1041 */
1042const char *
1043__p_option(option)
1044 u_long option;
1045{
3d61b63c
RM
1046 static char nbuf[40];
1047
28f540f4
RM
1048 switch (option) {
1049 case RES_INIT: return "init";
1050 case RES_DEBUG: return "debug";
3d61b63c 1051 case RES_AAONLY: return "aaonly(unimpl)";
28f540f4 1052 case RES_USEVC: return "usevc";
3d61b63c 1053 case RES_PRIMARY: return "primry(unimpl)";
28f540f4
RM
1054 case RES_IGNTC: return "igntc";
1055 case RES_RECURSE: return "recurs";
1056 case RES_DEFNAMES: return "defnam";
1057 case RES_STAYOPEN: return "styopn";
1058 case RES_DNSRCH: return "dnsrch";
1059 case RES_INSECURE1: return "insecure1";
1060 case RES_INSECURE2: return "insecure2";
3d61b63c
RM
1061 default: sprintf(nbuf, "?0x%lx?", (u_long)option);
1062 return (nbuf);
28f540f4
RM
1063 }
1064}
1065
1066/*
1067 * Return a mnemonic for a time to live
1068 */
845dcb57
UD
1069const char *
1070p_time(value)
28f540f4
RM
1071 u_int32_t value;
1072{
d68171ed 1073 static char nbuf[60];
28f540f4
RM
1074 int secs, mins, hours, days;
1075 register char *p;
1076
1077 if (value == 0) {
1078 strcpy(nbuf, "0 secs");
1079 return (nbuf);
1080 }
1081
1082 secs = value % 60;
1083 value /= 60;
1084 mins = value % 60;
1085 value /= 60;
1086 hours = value % 24;
1087 value /= 24;
1088 days = value;
1089 value = 0;
1090
1091#define PLURALIZE(x) x, (x == 1) ? "" : "s"
1092 p = nbuf;
1093 if (days) {
1094 (void)sprintf(p, "%d day%s", PLURALIZE(days));
1095 while (*++p);
1096 }
1097 if (hours) {
1098 if (days)
1099 *p++ = ' ';
1100 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
1101 while (*++p);
1102 }
1103 if (mins) {
1104 if (days || hours)
1105 *p++ = ' ';
1106 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
1107 while (*++p);
1108 }
1109 if (secs || ! (days || hours || mins)) {
1110 if (days || hours || mins)
1111 *p++ = ' ';
1112 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
1113 }
1114 return (nbuf);
1115}
ee188d55
RM
1116
1117/*
1118 * routines to convert between on-the-wire RR format and zone file format.
1119 * Does not contain conversion to/from decimal degrees; divide or multiply
1120 * by 60*60*1000 for that.
1121 */
1122
1123static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1124 1000000,10000000,100000000,1000000000};
1125
1126/* takes an XeY precision/size value, returns a string representation. */
1127static const char *
1128precsize_ntoa(prec)
1129 u_int8_t prec;
1130{
df21c858 1131 static char retbuf[sizeof "90000000.00"];
ee188d55
RM
1132 unsigned long val;
1133 int mantissa, exponent;
1134
1135 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1136 exponent = (int)((prec >> 0) & 0x0f) % 10;
1137
1138 val = mantissa * poweroften[exponent];
1139
1140 (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
1141 return (retbuf);
1142}
1143
1144/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1145static u_int8_t
1146precsize_aton(strptr)
1147 char **strptr;
1148{
ee188d55 1149 u_int8_t retval = 0;
76b87c03
UD
1150 char *cp;
1151 int exponent = 0;
1152 int mantissa = 0;
ee188d55
RM
1153
1154 cp = *strptr;
76b87c03
UD
1155 while (isdigit(*cp)) {
1156 if (mantissa == 0)
1157 mantissa = *cp - '0';
1158 else
1159 exponent++;
1160 cp++;
1161 }
ee188d55 1162
76b87c03 1163 if (*cp == '.') {
ee188d55
RM
1164 cp++;
1165 if (isdigit(*cp)) {
76b87c03
UD
1166 if (mantissa == 0)
1167 mantissa = *cp - '0';
1168 else
1169 exponent++;
1170 cp++;
1171
ee188d55 1172 if (isdigit(*cp)) {
76b87c03
UD
1173 if (mantissa == 0)
1174 mantissa = *cp - '0';
1175 else
1176 exponent++;
1177 cp++;
ee188d55 1178 }
76b87c03
UD
1179 else
1180 exponent++;
ee188d55
RM
1181 }
1182 }
76b87c03
UD
1183 else
1184 exponent += 2;
ee188d55 1185
76b87c03
UD
1186 if (mantissa == 0)
1187 exponent = 0;
ee188d55 1188 retval = (mantissa << 4) | exponent;
ee188d55 1189 *strptr = cp;
ee188d55
RM
1190 return (retval);
1191}
1192
1193/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1194static u_int32_t
1195latlon2ul(latlonstrptr,which)
1196 char **latlonstrptr;
1197 int *which;
1198{
1199 register char *cp;
1200 u_int32_t retval;
1201 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1202
1203 cp = *latlonstrptr;
1204
1205 while (isdigit(*cp))
1206 deg = deg * 10 + (*cp++ - '0');
1207
1208 while (isspace(*cp))
1209 cp++;
1210
1211 if (!(isdigit(*cp)))
1212 goto fndhemi;
1213
1214 while (isdigit(*cp))
1215 min = min * 10 + (*cp++ - '0');
1216
1217 while (isspace(*cp))
1218 cp++;
1219
1220 if (!(isdigit(*cp)))
1221 goto fndhemi;
1222
1223 while (isdigit(*cp))
1224 secs = secs * 10 + (*cp++ - '0');
1225
1226 if (*cp == '.') { /* decimal seconds */
1227 cp++;
1228 if (isdigit(*cp)) {
1229 secsfrac = (*cp++ - '0') * 100;
1230 if (isdigit(*cp)) {
1231 secsfrac += (*cp++ - '0') * 10;
1232 if (isdigit(*cp)) {
1233 secsfrac += (*cp++ - '0');
1234 }
1235 }
1236 }
1237 }
1238
1239 while (!isspace(*cp)) /* if any trailing garbage */
1240 cp++;
1241
1242 while (isspace(*cp))
1243 cp++;
1244
1245 fndhemi:
1246 switch (*cp) {
1247 case 'N': case 'n':
1248 case 'E': case 'e':
1249 retval = ((unsigned)1<<31)
1250 + (((((deg * 60) + min) * 60) + secs) * 1000)
1251 + secsfrac;
1252 break;
1253 case 'S': case 's':
1254 case 'W': case 'w':
1255 retval = ((unsigned)1<<31)
1256 - (((((deg * 60) + min) * 60) + secs) * 1000)
1257 - secsfrac;
1258 break;
1259 default:
1260 retval = 0; /* invalid value -- indicates error */
1261 break;
1262 }
1263
1264 switch (*cp) {
1265 case 'N': case 'n':
1266 case 'S': case 's':
1267 *which = 1; /* latitude */
1268 break;
1269 case 'E': case 'e':
1270 case 'W': case 'w':
1271 *which = 2; /* longitude */
1272 break;
1273 default:
1274 *which = 0; /* error */
1275 break;
1276 }
1277
1278 cp++; /* skip the hemisphere */
1279
1280 while (!isspace(*cp)) /* if any trailing garbage */
1281 cp++;
1282
1283 while (isspace(*cp)) /* move to next field */
1284 cp++;
1285
1286 *latlonstrptr = cp;
1287
1288 return (retval);
1289}
1290
1291/* converts a zone file representation in a string to an RDATA on-the-wire
1292 * representation. */
1293int
1294loc_aton(ascii, binary)
1295 const char *ascii;
1296 u_char *binary;
1297{
1298 const char *cp, *maxcp;
1299 u_char *bcp;
1300
1301 u_int32_t latit = 0, longit = 0, alt = 0;
1302 u_int32_t lltemp1 = 0, lltemp2 = 0;
1303 int altmeters = 0, altfrac = 0, altsign = 1;
1304 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1305 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1306 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1307 int which1 = 0, which2 = 0;
1308
1309 cp = ascii;
1310 maxcp = cp + strlen(ascii);
1311
1312 lltemp1 = latlon2ul(&cp, &which1);
1313
1314 lltemp2 = latlon2ul(&cp, &which2);
1315
1316 switch (which1 + which2) {
1317 case 3: /* 1 + 2, the only valid combination */
1318 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1319 latit = lltemp1;
1320 longit = lltemp2;
1321 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1322 longit = lltemp1;
1323 latit = lltemp2;
1324 } else { /* some kind of brokenness */
df21c858 1325 return (0);
ee188d55
RM
1326 }
1327 break;
1328 default: /* we didn't get one of each */
df21c858 1329 return (0);
ee188d55
RM
1330 }
1331
1332 /* altitude */
1333 if (*cp == '-') {
1334 altsign = -1;
1335 cp++;
1336 }
1337
1338 if (*cp == '+')
1339 cp++;
1340
1341 while (isdigit(*cp))
1342 altmeters = altmeters * 10 + (*cp++ - '0');
1343
1344 if (*cp == '.') { /* decimal meters */
1345 cp++;
1346 if (isdigit(*cp)) {
1347 altfrac = (*cp++ - '0') * 10;
1348 if (isdigit(*cp)) {
1349 altfrac += (*cp++ - '0');
1350 }
1351 }
1352 }
1353
1354 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1355
1356 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1357 cp++;
1358
1359 while (isspace(*cp) && (cp < maxcp))
1360 cp++;
1361
1362 if (cp >= maxcp)
1363 goto defaults;
1364
1365 siz = precsize_aton(&cp);
1366
1367 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1368 cp++;
1369
1370 while (isspace(*cp) && (cp < maxcp))
1371 cp++;
1372
1373 if (cp >= maxcp)
1374 goto defaults;
1375
1376 hp = precsize_aton(&cp);
1377
1378 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1379 cp++;
1380
1381 while (isspace(*cp) && (cp < maxcp))
1382 cp++;
1383
1384 if (cp >= maxcp)
1385 goto defaults;
1386
1387 vp = precsize_aton(&cp);
1388
1389 defaults:
1390
1391 bcp = binary;
1392 *bcp++ = (u_int8_t) 0; /* version byte */
1393 *bcp++ = siz;
1394 *bcp++ = hp;
1395 *bcp++ = vp;
1396 PUTLONG(latit,bcp);
1397 PUTLONG(longit,bcp);
1398 PUTLONG(alt,bcp);
1399
1400 return (16); /* size of RR in octets */
1401}
1402
1403/* takes an on-the-wire LOC RR and formats it in a human readable format. */
845dcb57 1404const char *
ee188d55
RM
1405loc_ntoa(binary, ascii)
1406 const u_char *binary;
1407 char *ascii;
1408{
1409 static char *error = "?";
1410 register const u_char *cp = binary;
1411
1412 int latdeg, latmin, latsec, latsecfrac;
1413 int longdeg, longmin, longsec, longsecfrac;
1414 char northsouth, eastwest;
1415 int altmeters, altfrac, altsign;
1416
1417 const int referencealt = 100000 * 100;
1418
1419 int32_t latval, longval, altval;
1420 u_int32_t templ;
1421 u_int8_t sizeval, hpval, vpval, versionval;
1422
1423 char *sizestr, *hpstr, *vpstr;
1424
1425 versionval = *cp++;
1426
1427 if (versionval) {
1428 sprintf(ascii, "; error: unknown LOC RR version");
1429 return (ascii);
1430 }
1431
1432 sizeval = *cp++;
1433
1434 hpval = *cp++;
1435 vpval = *cp++;
1436
1437 GETLONG(templ, cp);
1438 latval = (templ - ((unsigned)1<<31));
1439
1440 GETLONG(templ, cp);
1441 longval = (templ - ((unsigned)1<<31));
1442
1443 GETLONG(templ, cp);
df4ef2ab 1444 if (templ < (u_int32_t) referencealt) { /* below WGS 84 spheroid */
ee188d55
RM
1445 altval = referencealt - templ;
1446 altsign = -1;
1447 } else {
1448 altval = templ - referencealt;
1449 altsign = 1;
1450 }
1451
1452 if (latval < 0) {
1453 northsouth = 'S';
1454 latval = -latval;
1455 } else
1456 northsouth = 'N';
1457
1458 latsecfrac = latval % 1000;
1459 latval = latval / 1000;
1460 latsec = latval % 60;
1461 latval = latval / 60;
1462 latmin = latval % 60;
1463 latval = latval / 60;
1464 latdeg = latval;
1465
1466 if (longval < 0) {
1467 eastwest = 'W';
1468 longval = -longval;
1469 } else
1470 eastwest = 'E';
1471
1472 longsecfrac = longval % 1000;
1473 longval = longval / 1000;
1474 longsec = longval % 60;
1475 longval = longval / 60;
1476 longmin = longval % 60;
1477 longval = longval / 60;
1478 longdeg = longval;
1479
1480 altfrac = altval % 100;
1481 altmeters = (altval / 100) * altsign;
1482
1483 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1484 sizestr = error;
1485 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1486 hpstr = error;
1487 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1488 vpstr = error;
1489
1490 sprintf(ascii,
1491 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1492 latdeg, latmin, latsec, latsecfrac, northsouth,
1493 longdeg, longmin, longsec, longsecfrac, eastwest,
1494 altmeters, altfrac, sizestr, hpstr, vpstr);
1495
1496 if (sizestr != error)
1497 free(sizestr);
1498 if (hpstr != error)
1499 free(hpstr);
1500 if (vpstr != error)
1501 free(vpstr);
1502
1503 return (ascii);
1504}
df21c858
UD
1505
1506
1507/* Return the number of DNS hierarchy levels in the name. */
1508int
1509__dn_count_labels(name)
1510 char *name;
1511{
1512 int i, len, count;
1513
1514 len = strlen(name);
1515
1516 for(i = 0, count = 0; i < len; i++) {
1517 if (name[i] == '.')
1518 count++;
1519 }
1520
1521 /* don't count initial wildcard */
1522 if (name[0] == '*')
1523 if (count)
1524 count--;
1525
1526 /* don't count the null label for root. */
1527 /* if terminating '.' not found, must adjust */
1528 /* count to include last label */
1529 if (len > 0 && name[len-1] != '.')
1530 count++;
1531 return (count);
1532}
1533
1534
1535/*
1536 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1537 * SIG records are required to be printed like this, by the Secure DNS RFC.
1538 */
1539char *
1540__p_secstodate (secs)
1541 unsigned long secs;
1542{
1543 static char output[15]; /* YYYYMMDDHHMMSS and null */
1544 time_t clock = secs;
dcf0671d 1545 struct tm time;
df21c858 1546
dcf0671d
UD
1547 __gmtime_r(&clock, &time);
1548 time.tm_year += 1900;
1549 time.tm_mon += 1;
df21c858 1550 sprintf(output, "%04d%02d%02d%02d%02d%02d",
dcf0671d
UD
1551 time.tm_year, time.tm_mon, time.tm_mday,
1552 time.tm_hour, time.tm_min, time.tm_sec);
df21c858
UD
1553 return (output);
1554}