diff options
Diffstat (limited to 'resolv/res_debug.c')
-rw-r--r-- | resolv/res_debug.c | 419 |
1 files changed, 348 insertions, 71 deletions
diff --git a/resolv/res_debug.c b/resolv/res_debug.c index 62cd81cd0f..dfb3b4706f 100644 --- a/resolv/res_debug.c +++ b/resolv/res_debug.c @@ -50,6 +50,28 @@ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. * --Copyright-- */ @@ -65,11 +87,14 @@ static char rcsid[] = "$Id$"; #include <arpa/inet.h> #include <arpa/nameser.h> -#include <stdio.h> #include <ctype.h> #include <netdb.h> #include <resolv.h> +#include <stdio.h> +#include <time.h> + #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6) +# include <stdlib.h> # include <string.h> #else # include "../conf/portability.h" @@ -291,6 +316,12 @@ __fp_nquery(msg, len, file) fprintf(file, " rd"); if (hp->ra) fprintf(file, " ra"); + if (hp->unused) + fprintf(file, " UNUSED-BIT-ON"); + if (hp->ad) + fprintf(file, " ad"); + if (hp->cd) + fprintf(file, " cd"); } if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { fprintf(file, "; Ques: %d", ntohs(hp->qdcount)); @@ -404,6 +435,30 @@ __p_cdname(cp, msg, file) return (p_cdnname(cp, msg, PACKETSZ, file)); } + +/* Return a fully-qualified domain name from a compressed name (with + length supplied). */ + +const u_char * +__p_fqnname(cp, msg, msglen, name, namelen) + const u_char *cp, *msg; + int msglen; + char *name; + int namelen; +{ + int n, newlen; + + if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) + return (NULL); + newlen = strlen (name); + if (newlen == 0 || name[newlen - 1] != '.') + if (newlen+1 >= namelen) /* Lack space for final dot */ + return (NULL); + else + strcpy(name + newlen, "."); + return (cp + n); +} + /* XXX: the rest of these functions need to become length-limited, too. (vix) */ @@ -413,18 +468,13 @@ __p_fqname(cp, msg, file) FILE *file; { char name[MAXDNAME]; - int n; + const u_char *n; - if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0) + n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); + if (n == NULL) return (NULL); - if (name[0] == '\0') { - putc('.', file); - } else { - fputs(name, file); - if (name[strlen(name) - 1] != '.') - putc('.', file); - } - return (cp + n); + fputs(name, file); + return (n); } /* @@ -440,13 +490,19 @@ __p_rr(cp, msg, file) const u_char *cp1, *cp2; u_int32_t tmpttl, t; int lcnt; + u_int16_t keyflags; + char rrname[MAXDNAME]; /* The fqdn of this RR */ + char base64_key[MAX_KEY_BASE64]; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (NULL); } - if ((cp = p_fqname(cp, msg, file)) == NULL) + cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname); + if (!cp) return (NULL); /* compression error */ + fputs(rrname, file); + type = _getshort((u_char*)cp); cp += INT16SZ; class = _getshort((u_char*)cp); @@ -481,7 +537,7 @@ __p_rr(cp, msg, file) address = inet_ntoa(inaddr); cp += INADDRSZ; protocol = *(u_char*)cp; - cp += sizeof(u_char); + cp += sizeof (u_char); port = _getshort((u_char*)cp); cp += INT16SZ; fprintf(file, "\t%s\t; proto %d, port %d", @@ -505,16 +561,16 @@ __p_rr(cp, msg, file) case T_HINFO: case T_ISDN: - (void) fputs("\t\"", file); cp2 = cp + dlen; + (void) fputs("\t\"", file); if ((n = (unsigned char) *cp++) != 0) { for (c = n; c > 0 && cp < cp2; c--) { if (strchr("\n\"\\", *cp)) (void) putc('\\', file); (void) putc(*cp++, file); } - putc('"', file); } + putc('"', file); if (cp < cp2 && (n = (unsigned char) *cp++) != 0) { (void) fputs ("\t\"", file); for (c = n; c > 0 && cp < cp2; c--) { @@ -572,11 +628,24 @@ __p_rr(cp, msg, file) return (NULL); break; - case T_TXT: case T_X25: + cp2 = cp + dlen; (void) fputs("\t\"", file); + if ((n = (unsigned char) *cp++) != 0) { + for (c = n; c > 0 && cp < cp2; c--) { + if (strchr("\n\"\\", *cp)) + (void) putc('\\', file); + (void) putc(*cp++, file); + } + } + putc('"', file); + break; + + case T_TXT: + (void) putc('\t', file); cp2 = cp1 + dlen; while (cp < cp2) { + putc('"', file); if (n = (unsigned char) *cp++) { for (c = n; c > 0 && cp < cp2; c--) { if (strchr("\n\"\\", *cp)) @@ -584,8 +653,10 @@ __p_rr(cp, msg, file) (void) putc(*cp++, file); } } + putc('"', file); + if (cp < cp2) + putc(' ', file); } - putc('"', file); break; case T_NSAP: @@ -641,7 +712,7 @@ __p_rr(cp, msg, file) fprintf(file, "\t%s %s ( ", inet_ntoa(inaddr), deproto((int) *cp)); - cp += sizeof(u_char); + cp += sizeof (u_char); n = 0; lcnt = 0; while (cp < cp1 + dlen) { @@ -662,6 +733,72 @@ __p_rr(cp, msg, file) putc(')', file); break; + case T_KEY: + putc('\t', file); + keyflags = _getshort(cp); + cp += 2; + fprintf(file,"0x%04x", keyflags ); /* flags */ + fprintf(file," %u", *cp++); /* protocol */ + fprintf(file," %u (", *cp++); /* algorithm */ + + n = b64_ntop(cp, (cp1 + dlen) - cp, + base64_key, sizeof base64_key); + for (c = 0; c < n; ++c) { + if (0 == (c & 0x3F)) + fprintf(file, "\n\t"); + putc(base64_key[c], file); /* public key data */ + } + + fprintf(file, " )"); + if (n < 0) + fprintf(file, "\t; BAD BASE64"); + fflush(file); + cp = cp1 + dlen; + break; + + case T_SIG: + type = _getshort((u_char*)cp); + cp += INT16SZ; + fprintf(file, " %s", p_type(type)); + fprintf(file, "\t%d", *cp++); /* algorithm */ + /* Check label value and print error if wrong. */ + n = *cp++; + c = dn_count_labels (rrname); + if (n != c) + fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t", + n, c); + /* orig ttl */ + n = _getlong((u_char*)cp); + if (n != tmpttl) + fprintf(file, " %u", n); + cp += INT32SZ; + /* sig expire */ + fprintf(file, " (\n\t%s", + __p_secstodate(_getlong((u_char*)cp))); + cp += INT32SZ; + /* time signed */ + fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp))); + cp += INT32SZ; + /* sig footprint */ + fprintf(file," %u ", _getshort((u_char*)cp)); + cp += INT16SZ; + /* signer's name */ + cp = p_fqname(cp, msg, file); + n = b64_ntop(cp, (cp1 + dlen) - cp, + base64_key, sizeof base64_key); + for (c = 0; c < n; c++) { + if (0 == (c & 0x3F)) + fprintf (file, "\n\t"); + putc(base64_key[c], file); /* signature */ + } + /* Clean up... */ + fprintf(file, " )"); + if (n < 0) + fprintf(file, "\t; BAD BASE64"); + fflush(file); + cp = cp1+dlen; + break; + #ifdef ALLOW_T_UNSPEC case T_UNSPEC: { @@ -698,54 +835,151 @@ __p_rr(cp, msg, file) } /* + * Names of RR classes and qclasses. Classes and qclasses are the same, except + * that C_ANY is a qclass but not a class. (You can ask for records of class + * C_ANY, but you can't have any records of that class in the database.) + */ +const struct res_sym __p_class_syms[] = { + {C_IN, "IN"}, + {C_CHAOS, "CHAOS"}, + {C_HS, "HS"}, + {C_HS, "HESIOD"}, + {C_ANY, "ANY"}, + {C_IN, (char *)0} +}; + +/* + * Names of RR types and qtypes. Types and qtypes are the same, except + * that T_ANY is a qtype but not a type. (You can ask for records of type + * T_ANY, but you can't have any records of that type in the database.) + */ +const struct res_sym __p_type_syms[] = { + {T_A, "A", "address"}, + {T_NS, "NS", "name server"}, + {T_CNAME, "CNAME", "canonical name"}, + {T_SOA, "SOA", "start of authority"}, + {T_MB, "MB", "mailbox"}, + {T_MG, "MG", "mail group member"}, + {T_MR, "MR", "mail rename"}, + {T_NULL, "NULL", "null"}, + {T_WKS, "WKS", "well-known service"}, + {T_PTR, "PTR", "domain name pointer"}, + {T_HINFO, "HINFO", "host information"}, + {T_MINFO, "MINFO", "mailbox information"}, + {T_MX, "MX", "mail exchanger"}, + {T_TXT, "TXT", "text"}, + {T_RP, "RP", "responsible person"}, + {T_AFSDB, "AFSDB", "DCE or AFS server"}, + {T_X25, "X25", "X25 address"}, + {T_ISDN, "ISDN", "ISDN address"}, + {T_RT, "RT", "router"}, + {T_NSAP, "NSAP", "nsap address"}, + {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"}, + {T_SIG, "SIG", "signature"}, + {T_KEY, "KEY", "key"}, + {T_NXT, "NXT", "next valid name"}, + {T_PX, "PX", "mapping information"}, + {T_GPOS, "GPOS", "geographical position"}, + {T_AAAA, "AAAA", "IPv6 address"}, + {T_LOC, "LOC", "location"}, + {T_AXFR, "AXFR", "zone transfer"}, + {T_MAILB, "MAILB", "mailbox-related data"}, + {T_MAILA, "MAILA", "mail agent"}, + {T_UINFO, "UINFO", "user information"}, + {T_UID, "UID", "user ID"}, + {T_GID, "GID", "group ID"}, +#ifdef ALLOW_T_UNSPEC + {T_UNSPEC, "UNSPEC", "unspecified data"}, +#endif /* ALLOW_T_UNSPEC */ + {T_ANY, "ANY", "\"any\""}, + {0, (char *)0, (char *)0} +}; + +int +__sym_ston(syms, name, success) + const struct res_sym *syms; + char *name; + int *success; +{ +#ifdef _LIBC + /* Changed to prevent warning. --drepper@gnu */ + for (; syms->name != 0; syms++) { +#else + for (NULL; syms->name != 0; syms++) { +#endif + if (strcasecmp (name, syms->name) == 0) { + if (success) + *success = 1; + return (syms->number); + } + } + if (success) + *success = 0; + return (syms->number); /* The default value. */ +} + +const char * +__sym_ntos(syms, number, success) + const struct res_sym *syms; + int number; + int *success; +{ + static char unname[20]; + +#ifdef _LIBC + /* Changed to prevent warning. --drepper@gnu */ + for (; syms->name != 0; syms++) { +#else + for (NULL; syms->name != 0; syms++) { +#endif + if (number == syms->number) { + if (success) + *success = 1; + return (syms->name); + } + } + + sprintf (unname, "%d", number); + if (success) + *success = 0; + return (unname); +} + + +const char * +__sym_ntop(syms, number, success) + const struct res_sym *syms; + int number; + int *success; +{ + static char unname[20]; + +#ifdef _LIBC + /* Changed to prevent warning. --drepper@gnu */ + for (; syms->name != 0; syms++) { +#else + for (NULL; syms->name != 0; syms++) { +#endif + if (number == syms->number) { + if (success) + *success = 1; + return (syms->humanname); + } + } + sprintf(unname, "%d", number); + if (success) + *success = 0; + return (unname); +} + +/* * Return a string for the type */ const char * __p_type(type) int type; { - static char nbuf[20]; - - switch (type) { - case T_A: return "A"; - case T_NS: return "NS"; - case T_CNAME: return "CNAME"; - case T_SOA: return "SOA"; - case T_MB: return "MB"; - case T_MG: return "MG"; - case T_MR: return "MR"; - case T_NULL: return "NULL"; - case T_WKS: return "WKS"; - case T_PTR: return "PTR"; - case T_HINFO: return "HINFO"; - case T_MINFO: return "MINFO"; - case T_MX: return "MX"; - case T_TXT: return "TXT"; - case T_RP: return "RP"; - case T_AFSDB: return "AFSDB"; - case T_X25: return "X25"; - case T_ISDN: return "ISDN"; - case T_RT: return "RT"; - case T_NSAP: return "NSAP"; - case T_NSAP_PTR: return "NSAP_PTR"; - case T_SIG: return "SIG"; - case T_KEY: return "KEY"; - case T_PX: return "PX"; - case T_GPOS: return "GPOS"; - case T_AAAA: return "AAAA"; - case T_LOC: return "LOC"; - case T_AXFR: return "AXFR"; - case T_MAILB: return "MAILB"; - case T_MAILA: return "MAILA"; - case T_ANY: 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 (__sym_ntos (__p_type_syms, type, (int *)0)); } /* @@ -755,14 +989,7 @@ const char * __p_class(class) int class; { - static char nbuf[20]; - - switch (class) { - case C_IN: return "IN"; - case C_HS: return "HS"; - case C_ANY: return "ANY"; - default: (void)sprintf(nbuf, "%d", class); return (nbuf); - } + return (__sym_ntos (__p_class_syms, class, (int *)0)); } /* @@ -857,7 +1084,7 @@ static const char * precsize_ntoa(prec) u_int8_t prec; { - static char retbuf[sizeof("90000000.00")]; + static char retbuf[sizeof "90000000.00"]; unsigned long val; int mantissa, exponent; @@ -1044,11 +1271,11 @@ loc_aton(ascii, binary) longit = lltemp1; latit = lltemp2; } else { /* some kind of brokenness */ - return 0; + return (0); } break; default: /* we didn't get one of each */ - return 0; + return (0); } /* altitude */ @@ -1224,3 +1451,53 @@ loc_ntoa(binary, ascii) return (ascii); } + + +/* Return the number of DNS hierarchy levels in the name. */ +int +__dn_count_labels(name) + char *name; +{ + int i, len, count; + + len = strlen(name); + + for(i = 0, count = 0; i < len; i++) { + if (name[i] == '.') + count++; + } + + /* don't count initial wildcard */ + if (name[0] == '*') + if (count) + count--; + + /* don't count the null label for root. */ + /* if terminating '.' not found, must adjust */ + /* count to include last label */ + if (len > 0 && name[len-1] != '.') + count++; + return (count); +} + + +/* + * Make dates expressed in seconds-since-Jan-1-1970 easy to read. + * SIG records are required to be printed like this, by the Secure DNS RFC. + */ +char * +__p_secstodate (secs) + unsigned long secs; +{ + static char output[15]; /* YYYYMMDDHHMMSS and null */ + time_t clock = secs; + struct tm *time; + + time = gmtime(&clock); + time->tm_year += 1900; + time->tm_mon += 1; + sprintf(output, "%04d%02d%02d%02d%02d%02d", + time->tm_year, time->tm_mon, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); + return (output); +} |