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