summaryrefslogtreecommitdiff
path: root/lib/libc/net/res_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/net/res_debug.c')
-rw-r--r--lib/libc/net/res_debug.c518
1 files changed, 518 insertions, 0 deletions
diff --git a/lib/libc/net/res_debug.c b/lib/libc/net/res_debug.c
new file mode 100644
index 000000000000..83dff2d382ca
--- /dev/null
+++ b/lib/libc/net/res_debug.c
@@ -0,0 +1,518 @@
+/*-
+ * Copyright (c) 1985, 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)res_debug.c 5.36 (Berkeley) 3/6/91
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_debug.c 5.36 (Berkeley) 3/6/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+
+void __fp_query();
+char *__p_class(), *__p_time(), *__p_type();
+static char *p_cdname(), *p_rr();
+
+char *_res_opcodes[] = {
+ "QUERY",
+ "IQUERY",
+ "CQUERYM",
+ "CQUERYU",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "UPDATEA",
+ "UPDATED",
+ "UPDATEDA",
+ "UPDATEM",
+ "UPDATEMA",
+ "ZONEINIT",
+ "ZONEREF",
+};
+
+char *_res_resultcodes[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "NOCHANGE",
+};
+
+__p_query(msg)
+ char *msg;
+{
+ __fp_query(msg,stdout);
+}
+
+/*
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+__fp_query(msg,file)
+ char *msg;
+ FILE *file;
+{
+ register char *cp;
+ register HEADER *hp;
+ register int n;
+
+ /*
+ * Print header fields.
+ */
+ hp = (HEADER *)msg;
+ cp = msg + sizeof(HEADER);
+ fprintf(file,"HEADER:\n");
+ fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]);
+ fprintf(file,", id = %d", ntohs(hp->id));
+ fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]);
+ fprintf(file,"\theader flags: ");
+ if (hp->qr)
+ fprintf(file," qr");
+ if (hp->aa)
+ fprintf(file," aa");
+ if (hp->tc)
+ fprintf(file," tc");
+ if (hp->rd)
+ fprintf(file," rd");
+ if (hp->ra)
+ fprintf(file," ra");
+ if (hp->pr)
+ fprintf(file," pr");
+ fprintf(file,"\n\tqdcount = %d", ntohs(hp->qdcount));
+ fprintf(file,", ancount = %d", ntohs(hp->ancount));
+ fprintf(file,", nscount = %d", ntohs(hp->nscount));
+ fprintf(file,", arcount = %d\n\n", ntohs(hp->arcount));
+ /*
+ * Print question records.
+ */
+ if (n = ntohs(hp->qdcount)) {
+ fprintf(file,"QUESTIONS:\n");
+ while (--n >= 0) {
+ fprintf(file,"\t");
+ cp = p_cdname(cp, msg, file);
+ if (cp == NULL)
+ return;
+ fprintf(file,", type = %s", __p_type(_getshort(cp)));
+ cp += sizeof(u_short);
+ fprintf(file,
+ ", class = %s\n\n", __p_class(_getshort(cp)));
+ cp += sizeof(u_short);
+ }
+ }
+ /*
+ * Print authoritative answer records
+ */
+ if (n = ntohs(hp->ancount)) {
+ fprintf(file,"ANSWERS:\n");
+ while (--n >= 0) {
+ fprintf(file,"\t");
+ cp = p_rr(cp, msg, file);
+ if (cp == NULL)
+ return;
+ }
+ }
+ /*
+ * print name server records
+ */
+ if (n = ntohs(hp->nscount)) {
+ fprintf(file,"NAME SERVERS:\n");
+ while (--n >= 0) {
+ fprintf(file,"\t");
+ cp = p_rr(cp, msg, file);
+ if (cp == NULL)
+ return;
+ }
+ }
+ /*
+ * print additional records
+ */
+ if (n = ntohs(hp->arcount)) {
+ fprintf(file,"ADDITIONAL RECORDS:\n");
+ while (--n >= 0) {
+ fprintf(file,"\t");
+ cp = p_rr(cp, msg, file);
+ if (cp == NULL)
+ return;
+ }
+ }
+}
+
+static char *
+p_cdname(cp, msg, file)
+ char *cp, *msg;
+ FILE *file;
+{
+ char name[MAXDNAME];
+ int n;
+
+ if ((n = dn_expand((u_char *)msg, (u_char *)msg + 512, (u_char *)cp,
+ (u_char *)name, sizeof(name))) < 0)
+ return (NULL);
+ if (name[0] == '\0') {
+ name[0] = '.';
+ name[1] = '\0';
+ }
+ fputs(name, file);
+ return (cp + n);
+}
+
+/*
+ * Print resource record fields in human readable form.
+ */
+static char *
+p_rr(cp, msg, file)
+ char *cp, *msg;
+ FILE *file;
+{
+ int type, class, dlen, n, c;
+ struct in_addr inaddr;
+ char *cp1, *cp2;
+
+ if ((cp = p_cdname(cp, msg, file)) == NULL)
+ return (NULL); /* compression error */
+ fprintf(file,"\n\ttype = %s", __p_type(type = _getshort(cp)));
+ cp += sizeof(u_short);
+ fprintf(file,", class = %s", __p_class(class = _getshort(cp)));
+ cp += sizeof(u_short);
+ fprintf(file,", ttl = %s", __p_time(_getlong(cp)));
+ cp += sizeof(u_long);
+ fprintf(file,", dlen = %d\n", dlen = _getshort(cp));
+ cp += sizeof(u_short);
+ cp1 = cp;
+ /*
+ * Print type specific data, if appropriate
+ */
+ switch (type) {
+ case T_A:
+ switch (class) {
+ case C_IN:
+ case C_HS:
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ if (dlen == 4) {
+ fprintf(file,"\tinternet address = %s\n",
+ inet_ntoa(inaddr));
+ cp += dlen;
+ } else if (dlen == 7) {
+ fprintf(file,"\tinternet address = %s",
+ inet_ntoa(inaddr));
+ fprintf(file,", protocol = %d", cp[4]);
+ fprintf(file,", port = %d\n",
+ (cp[5] << 8) + cp[6]);
+ cp += dlen;
+ }
+ break;
+ default:
+ cp += dlen;
+ }
+ break;
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ fprintf(file,"\tdomain name = ");
+ cp = p_cdname(cp, msg, file);
+ fprintf(file,"\n");
+ break;
+
+ case T_HINFO:
+ if (n = *cp++) {
+ fprintf(file,"\tCPU=%.*s\n", n, cp);
+ cp += n;
+ }
+ if (n = *cp++) {
+ fprintf(file,"\tOS=%.*s\n", n, cp);
+ cp += n;
+ }
+ break;
+
+ case T_SOA:
+ fprintf(file,"\torigin = ");
+ cp = p_cdname(cp, msg, file);
+ fprintf(file,"\n\tmail addr = ");
+ cp = p_cdname(cp, msg, file);
+ fprintf(file,"\n\tserial = %ld", _getlong(cp));
+ cp += sizeof(u_long);
+ fprintf(file,"\n\trefresh = %s", __p_time(_getlong(cp)));
+ cp += sizeof(u_long);
+ fprintf(file,"\n\tretry = %s", __p_time(_getlong(cp)));
+ cp += sizeof(u_long);
+ fprintf(file,"\n\texpire = %s", __p_time(_getlong(cp)));
+ cp += sizeof(u_long);
+ fprintf(file,"\n\tmin = %s\n", __p_time(_getlong(cp)));
+ cp += sizeof(u_long);
+ break;
+
+ case T_MX:
+ fprintf(file,"\tpreference = %ld,",_getshort(cp));
+ cp += sizeof(u_short);
+ fprintf(file," name = ");
+ cp = p_cdname(cp, msg, file);
+ break;
+
+ case T_TXT:
+ (void) fputs("\t\"", file);
+ cp2 = cp1 + dlen;
+ while (cp < cp2) {
+ if (n = (unsigned char) *cp++) {
+ for (c = n; c > 0 && cp < cp2; c--)
+ if (*cp == '\n') {
+ (void) putc('\\', file);
+ (void) putc(*cp++, file);
+ } else
+ (void) putc(*cp++, file);
+ }
+ }
+ (void) fputs("\"\n", file);
+ break;
+
+ case T_MINFO:
+ fprintf(file,"\trequests = ");
+ cp = p_cdname(cp, msg, file);
+ fprintf(file,"\n\terrors = ");
+ cp = p_cdname(cp, msg, file);
+ break;
+
+ case T_UINFO:
+ fprintf(file,"\t%s\n", cp);
+ cp += dlen;
+ break;
+
+ case T_UID:
+ case T_GID:
+ if (dlen == 4) {
+ fprintf(file,"\t%ld\n", _getlong(cp));
+ cp += sizeof(int);
+ }
+ break;
+
+ case T_WKS:
+ if (dlen < sizeof(u_long) + 1)
+ break;
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ cp += sizeof(u_long);
+ fprintf(file,"\tinternet address = %s, protocol = %d\n\t",
+ inet_ntoa(inaddr), *cp++);
+ n = 0;
+ while (cp < cp1 + dlen) {
+ c = *cp++;
+ do {
+ if (c & 0200)
+ fprintf(file," %d", n);
+ c <<= 1;
+ } while (++n & 07);
+ }
+ putc('\n',file);
+ break;
+
+#ifdef ALLOW_T_UNSPEC
+ case T_UNSPEC:
+ {
+ int NumBytes = 8;
+ char *DataPtr;
+ int i;
+
+ if (dlen < NumBytes) NumBytes = dlen;
+ fprintf(file, "\tFirst %d bytes of hex data:",
+ NumBytes);
+ for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
+ fprintf(file, " %x", *DataPtr);
+ fputs("\n", file);
+ cp += dlen;
+ }
+ break;
+#endif /* ALLOW_T_UNSPEC */
+
+ default:
+ fprintf(file,"\t???\n");
+ cp += dlen;
+ }
+ if (cp != cp1 + dlen) {
+ fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen);
+ cp = NULL;
+ }
+ fprintf(file,"\n");
+ return (cp);
+}
+
+static char nbuf[40];
+
+/*
+ * Return a string for the type
+ */
+char *
+__p_type(type)
+ int type;
+{
+ switch (type) {
+ case T_A:
+ return("A");
+ case T_NS: /* authoritative server */
+ return("NS");
+ case T_CNAME: /* canonical name */
+ return("CNAME");
+ case T_SOA: /* start of authority zone */
+ return("SOA");
+ case T_MB: /* mailbox domain name */
+ return("MB");
+ case T_MG: /* mail group member */
+ return("MG");
+ case T_MR: /* mail rename name */
+ return("MR");
+ case T_NULL: /* null resource record */
+ return("NULL");
+ case T_WKS: /* well known service */
+ return("WKS");
+ case T_PTR: /* domain name pointer */
+ return("PTR");
+ case T_HINFO: /* host information */
+ return("HINFO");
+ case T_MINFO: /* mailbox information */
+ return("MINFO");
+ case T_MX: /* mail routing info */
+ return("MX");
+ case T_TXT: /* text */
+ return("TXT");
+ case T_AXFR: /* zone transfer */
+ return("AXFR");
+ case T_MAILB: /* mail box */
+ return("MAILB");
+ case T_MAILA: /* mail address */
+ return("MAILA");
+ case T_ANY: /* matches any type */
+ return("ANY");
+ case T_UINFO:
+ return("UINFO");
+ case T_UID:
+ return("UID");
+ case T_GID:
+ return("GID");
+#ifdef ALLOW_T_UNSPEC
+ case T_UNSPEC:
+ return("UNSPEC");
+#endif /* ALLOW_T_UNSPEC */
+ default:
+ (void)sprintf(nbuf, "%d", type);
+ return(nbuf);
+ }
+}
+
+/*
+ * Return a mnemonic for class
+ */
+char *
+__p_class(class)
+ int class;
+{
+
+ switch (class) {
+ case C_IN: /* internet class */
+ return("IN");
+ case C_HS: /* hesiod class */
+ return("HS");
+ case C_ANY: /* matches any class */
+ return("ANY");
+ default:
+ (void)sprintf(nbuf, "%d", class);
+ return(nbuf);
+ }
+}
+
+/*
+ * Return a mnemonic for a time to live
+ */
+char *
+__p_time(value)
+ u_long value;
+{
+ int secs, mins, hours;
+ register char *p;
+
+ if (value == 0) {
+ strcpy(nbuf, "0 secs");
+ return(nbuf);
+ }
+
+ secs = value % 60;
+ value /= 60;
+ mins = value % 60;
+ value /= 60;
+ hours = value % 24;
+ value /= 24;
+
+#define PLURALIZE(x) x, (x == 1) ? "" : "s"
+ p = nbuf;
+ if (value) {
+ (void)sprintf(p, "%d day%s", PLURALIZE(value));
+ while (*++p);
+ }
+ if (hours) {
+ if (value)
+ *p++ = ' ';
+ (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
+ while (*++p);
+ }
+ if (mins) {
+ if (value || hours)
+ *p++ = ' ';
+ (void)sprintf(p, "%d min%s", PLURALIZE(mins));
+ while (*++p);
+ }
+ if (secs || ! (value || hours || mins)) {
+ if (value || hours || mins)
+ *p++ = ' ';
+ (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
+ }
+ return(nbuf);
+}