1: /* 2: * Copyright (c) 1985,1989 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted provided 6: * that: (1) source distributions retain this entire copyright notice and 7: * comment, and (2) distributions including binaries display the following 8: * acknowledgement: ``This product includes software developed by the 9: * University of California, Berkeley and its contributors'' in the 10: * documentation or other materials provided with the distribution and in 11: * all advertising materials mentioning features or use of this software. 12: * Neither the name of the University nor the names of its contributors may 13: * be used to endorse or promote products derived from this software without 14: * specific prior written permission. 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 18: */ 19: 20: #if !defined(lint) && defined(DOSCCS) 21: static char sccsid[] = "@(#)debug.c 5.22 (Berkeley) 6/29/90"; 22: #endif 23: 24: /* 25: ******************************************************************************* 26: * 27: * debug.c -- 28: * 29: * Routines to print out packets received from a name server query. 30: * 31: * Modified version of 4.3BSD BIND res_debug.c 5.30 6/27/90 32: * 33: ******************************************************************************* 34: */ 35: 36: #include <sys/types.h> 37: #include <netinet/in.h> 38: #include <stdio.h> 39: #include <arpa/nameser.h> 40: #include <arpa/inet.h> 41: #include <resolv.h> 42: #include <netdb.h> 43: #include "res.h" 44: 45: extern char ctime(); 46: 47: /* 48: * Imported from res_debug.c 49: */ 50: extern char *_res_resultcodes[]; 51: extern char *_res_opcodes[]; 52: 53: /* 54: * Used to highlight the start of a record when printing it. 55: */ 56: #define INDENT " -> " 57: 58: 59: 60: /* 61: * Print the contents of a query. 62: * This is intended to be primarily a debugging routine. 63: */ 64: 65: Print_query(msg, eom, printHeader) 66: char *msg, *eom; 67: int printHeader; 68: { 69: Fprint_query(msg, eom, printHeader,stdout); 70: } 71: 72: Fprint_query(msg, eom, printHeader,file) 73: char *msg, *eom; 74: int printHeader; 75: FILE *file; 76: { 77: register char *cp; 78: register HEADER *hp; 79: register int n; 80: short class; 81: short type; 82: 83: /* 84: * Print header fields. 85: */ 86: hp = (HEADER *)msg; 87: cp = msg + sizeof(HEADER); 88: if (printHeader || (_res.options & RES_DEBUG2)) { 89: fprintf(file," HEADER:\n"); 90: fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); 91: fprintf(file,", id = %d", ntohs(hp->id)); 92: fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]); 93: fprintf(file,"\theader flags: "); 94: if (hp->qr) { 95: fprintf(file," response"); 96: } else { 97: fprintf(file," query"); 98: } 99: if (hp->aa) 100: fprintf(file,", auth. answer"); 101: if (hp->tc) 102: fprintf(file,", truncation"); 103: if (hp->rd) 104: fprintf(file,", want recursion"); 105: if (hp->ra) 106: fprintf(file,", recursion avail."); 107: if (hp->pr) 108: fprintf(file,", primary"); 109: fprintf(file,"\n\tquestions = %d", ntohs(hp->qdcount)); 110: fprintf(file,", answers = %d", ntohs(hp->ancount)); 111: fprintf(file,", authority records = %d", ntohs(hp->nscount)); 112: fprintf(file,", additional = %d\n\n", ntohs(hp->arcount)); 113: } 114: 115: /* 116: * Print question records. 117: */ 118: if (n = ntohs(hp->qdcount)) { 119: fprintf(file," QUESTIONS:\n"); 120: while (--n >= 0) { 121: fprintf(file,"\t"); 122: cp = Print_cdname(cp, msg, eom, file); 123: if (cp == NULL) 124: return; 125: type = _getshort(cp); 126: cp += sizeof(u_short); 127: class = _getshort(cp); 128: cp += sizeof(u_short); 129: fprintf(file,", type = %s", p_type(type)); 130: fprintf(file,", class = %s\n", p_class(class)); 131: } 132: } 133: /* 134: * Print authoritative answer records 135: */ 136: if (n = ntohs(hp->ancount)) { 137: fprintf(file," ANSWERS:\n"); 138: while (--n >= 0) { 139: fprintf(file, INDENT); 140: cp = Print_rr(cp, msg, eom, file); 141: if (cp == NULL) 142: return; 143: } 144: } 145: /* 146: * print name server records 147: */ 148: if (n = ntohs(hp->nscount)) { 149: fprintf(file," AUTHORITY RECORDS:\n"); 150: while (--n >= 0) { 151: fprintf(file, INDENT); 152: cp = Print_rr(cp, msg, eom, file); 153: if (cp == NULL) 154: return; 155: } 156: } 157: /* 158: * print additional records 159: */ 160: if (n = ntohs(hp->arcount)) { 161: fprintf(file," ADDITIONAL RECORDS:\n"); 162: while (--n >= 0) { 163: fprintf(file, INDENT); 164: cp = Print_rr(cp, msg, eom, file); 165: if (cp == NULL) 166: return; 167: } 168: } 169: fprintf(file,"\n------------\n"); 170: } 171: 172: 173: char * 174: Print_cdname_sub(cp, msg, eom, file, format) 175: char *cp, *msg, *eom; 176: FILE *file; 177: int format; 178: { 179: int n; 180: char name[MAXDNAME]; 181: extern char *strcpy(); 182: 183: if ((n = dn_expand(msg, eom, cp, name, sizeof(name))) < 0) 184: return (NULL); 185: if (name[0] == '\0') { 186: (void) strcpy(name, "(root)"); 187: } 188: if (format) { 189: fprintf(file, "%-30s", name); 190: } else { 191: fputs(name, file); 192: } 193: return (cp + n); 194: } 195: 196: char * 197: Print_cdname(cp, msg, eom, file) 198: char *cp, *msg, *eom; 199: FILE *file; 200: { 201: return(Print_cdname_sub(cp, msg, eom, file, 0)); 202: } 203: 204: char * 205: Print_cdname2(cp, msg, eom, file) 206: char *cp, *msg, *eom; 207: FILE *file; 208: { 209: return(Print_cdname_sub(cp, msg, eom, file, 1)); 210: } 211: 212: /* 213: * Print resource record fields in human readable form. 214: */ 215: char * 216: Print_rr(cp, msg, eom, file) 217: char *cp, *msg, *eom; 218: FILE *file; 219: { 220: int type, class, dlen, n, c; 221: u_long rrttl, ttl; 222: struct in_addr inaddr; 223: char *cp1, *cp2; 224: long debug; 225: 226: if ((cp = Print_cdname(cp, msg, eom, file)) == NULL) { 227: fprintf(file, "(name truncated?)\n"); 228: return (NULL); /* compression error */ 229: } 230: 231: type = _getshort(cp); 232: cp += sizeof(u_short); 233: class = _getshort(cp); 234: cp += sizeof(u_short); 235: rrttl = _getlong(cp); 236: cp += sizeof(u_long); 237: dlen = _getshort(cp); 238: cp += sizeof(u_short); 239: 240: debug = _res.options & (RES_DEBUG|RES_DEBUG2); 241: if (debug) { 242: if (_res.options & RES_DEBUG2) { 243: fprintf(file,"\n\ttype = %s, class = %s, dlen = %d", 244: p_type(type), p_class(class), dlen); 245: } 246: if (type == T_SOA) { 247: fprintf(file,"\n\tttl = %ld (%s)", rrttl, p_time(rrttl)); 248: } 249: (void) putc('\n', file); 250: } 251: 252: cp1 = cp; 253: 254: /* 255: * Print type specific data, if appropriate 256: */ 257: switch (type) { 258: case T_A: 259: switch (class) { 260: case C_IN: 261: case C_HS: 262: bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 263: if (dlen == 4) { 264: fprintf(file,"\tinternet address = %s\n", 265: inet_ntoa(inaddr)); 266: cp += dlen; 267: } else if (dlen == 7) { 268: fprintf(file,"\tinternet address = %s", 269: inet_ntoa(inaddr)); 270: fprintf(file,", protocol = %d", cp[4]); 271: fprintf(file,", port = %d\n", 272: (cp[5] << 8) + cp[6]); 273: cp += dlen; 274: } 275: break; 276: default: 277: fprintf(file,"\taddress, class = %d, len = %d\n", 278: class, dlen); 279: cp += dlen; 280: } 281: break; 282: 283: case T_CNAME: 284: fprintf(file,"\tcanonical name = "); 285: goto doname; 286: 287: case T_MG: 288: fprintf(file,"\tmail group member = "); 289: goto doname; 290: case T_MB: 291: fprintf(file,"\tmail box = "); 292: goto doname; 293: case T_MR: 294: fprintf(file,"\tmailbox rename = "); 295: goto doname; 296: case T_MX: 297: fprintf(file,"\tpreference = %u",_getshort(cp)); 298: cp += sizeof(u_short); 299: fprintf(file,", mail exchanger = "); 300: goto doname; 301: case T_NS: 302: fprintf(file,"\tnameserver = "); 303: goto doname; 304: case T_PTR: 305: fprintf(file,"\tname = "); 306: doname: 307: cp = Print_cdname(cp, msg, eom, file); 308: (void) putc('\n', file); 309: break; 310: 311: case T_HINFO: 312: if (n = *cp++) { 313: fprintf(file,"\tCPU = %.*s", n, cp); 314: cp += n; 315: } 316: if (n = *cp++) { 317: fprintf(file,"\tOS = %.*s\n", n, cp); 318: cp += n; 319: } 320: break; 321: 322: case T_SOA: 323: if (!debug) 324: (void) putc('\n', file); 325: fprintf(file,"\torigin = "); 326: cp = Print_cdname(cp, msg, eom, file); 327: fprintf(file,"\n\tmail addr = "); 328: cp = Print_cdname(cp, msg, eom, file); 329: fprintf(file,"\n\tserial = %ld", _getlong(cp)); 330: cp += sizeof(u_long); 331: ttl = _getlong(cp); 332: fprintf(file,"\n\trefresh = %ld (%s)", ttl, p_time(ttl)); 333: cp += sizeof(u_long); 334: ttl = _getlong(cp); 335: fprintf(file,"\n\tretry = %ld (%s)", ttl, p_time(ttl)); 336: cp += sizeof(u_long); 337: ttl = _getlong(cp); 338: fprintf(file,"\n\texpire = %ld (%s)", ttl, p_time(ttl)); 339: cp += sizeof(u_long); 340: ttl = _getlong(cp); 341: fprintf(file,"\n\tminimum ttl = %ld (%s)\n", ttl, p_time(ttl)); 342: cp += sizeof(u_long); 343: break; 344: 345: case T_MINFO: 346: if (!debug) 347: (void) putc('\n', file); 348: fprintf(file,"\trequests = "); 349: cp = Print_cdname(cp, msg, eom, file); 350: fprintf(file,"\n\terrors = "); 351: cp = Print_cdname(cp, msg, eom, file); 352: (void) putc('\n', file); 353: break; 354: 355: case T_TXT: 356: (void) fputs("\ttext = \"", file); 357: cp2 = cp1 + dlen; 358: while (cp < cp2) { 359: if (n = (unsigned char) *cp++) { 360: for (c = n; c > 0 && cp < cp2; c--) 361: if (*cp == '\n') { 362: (void) putc('\\', file); 363: (void) putc(*cp++, file); 364: } else 365: (void) putc(*cp++, file); 366: } 367: } 368: (void) fputs("\"\n", file); 369: break; 370: 371: case T_UINFO: 372: fprintf(file,"\tuser info = %s\n", cp); 373: cp += dlen; 374: break; 375: 376: case T_UID: 377: case T_GID: 378: if (dlen == 4) { 379: fprintf(file,"\t%cid = %ld\n",type == T_UID ? 'u' : 'g', 380: _getlong(cp)); 381: cp += sizeof(int); 382: } else { 383: fprintf(file,"\t%cid of length %d?\n", 384: type == T_UID ? 'u' : 'g', dlen); 385: cp += dlen; 386: } 387: break; 388: 389: case T_WKS: { 390: struct protoent *protoPtr; 391: 392: if (dlen < sizeof(u_long) + 1) 393: break; 394: if (!debug) 395: (void) putc('\n', file); 396: bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 397: cp += sizeof(u_long); 398: if ((protoPtr = getprotobynumber(*cp)) != NULL) { 399: fprintf(file,"\tinet address = %s, protocol = %s\n\t", 400: inet_ntoa(inaddr), protoPtr->p_name); 401: } else { 402: fprintf(file,"\tinet address = %s, protocol = %d\n\t", 403: inet_ntoa(inaddr), *cp); 404: } 405: cp++; 406: n = 0; 407: while (cp < cp1 + dlen) { 408: c = *cp++; 409: do { 410: struct servent *s; 411: 412: if (c & 0200) { 413: s = getservbyport(n, (char *)NULL); 414: if (s != NULL) { 415: fprintf(file," %s", s->s_name); 416: } else { 417: fprintf(file," #%d", n); 418: } 419: } 420: c <<= 1; 421: } while (++n & 07); 422: } 423: putc('\n',file); 424: } 425: break; 426: 427: case T_NULL: 428: fprintf(file, "\tNULL (dlen %d)\n", dlen); 429: cp += dlen; 430: break; 431: 432: default: 433: fprintf(file,"\t??? unknown type %d ???\n", type); 434: cp += dlen; 435: } 436: if (_res.options & RES_DEBUG && type != T_SOA) { 437: fprintf(file,"\tttl = %ld (%s)\n", rrttl, p_time(rrttl)); 438: } 439: if (cp != cp1 + dlen) { 440: fprintf(file, 441: "\n*** Error: record size incorrect (%d != %d)\n\n", 442: cp - cp1, dlen); 443: cp = NULL; 444: } 445: return (cp); 446: }