1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)res_debug.c 5.5 (Berkeley) 09/11/85"; 9 #endif not lint 10 11 #include <sys/types.h> 12 #include <netinet/in.h> 13 #include <stdio.h> 14 #include <arpa/nameser.h> 15 16 extern char *p_cdname(), *p_rr(), *p_type(), *p_class(); 17 extern char *inet_ntoa(); 18 19 char *opcodes[] = { 20 "QUERY", 21 "IQUERY", 22 "CQUERYM", 23 "CQUERYU", 24 "4", 25 "5", 26 "6", 27 "7", 28 "8", 29 "9", 30 "10", 31 "UPDATEA", 32 "UPDATED", 33 "UPDATEM", 34 "ZONEINIT", 35 "ZONEREF", 36 }; 37 38 char *rcodes[] = { 39 "NOERROR", 40 "FORMERR", 41 "SERVFAIL", 42 "NXDOMAIN", 43 "NOTIMP", 44 "REFUSED", 45 "6", 46 "7", 47 "8", 48 "9", 49 "10", 50 "11", 51 "12", 52 "13", 53 "14", 54 "NOCHANGE", 55 }; 56 57 p_query(msg) 58 char *msg; 59 { 60 fp_query(msg,stdout); 61 } 62 63 /* 64 * Print the contents of a query. 65 * This is intended to be primarily a debugging routine. 66 */ 67 fp_query(msg,file) 68 char *msg; 69 FILE *file; 70 { 71 register char *cp; 72 register HEADER *hp; 73 register int n; 74 75 /* 76 * Print header fields. 77 */ 78 hp = (HEADER *)msg; 79 cp = msg + sizeof(HEADER); 80 fprintf(file,"HEADER:\n"); 81 fprintf(file,"\topcode = %s", opcodes[hp->opcode]); 82 fprintf(file,", id = %d", ntohs(hp->id)); 83 fprintf(file,", rcode = %s\n", rcodes[hp->rcode]); 84 fprintf(file,"\theader flags: "); 85 if (hp->qr) 86 fprintf(file," qr"); 87 if (hp->aa) 88 fprintf(file," aa"); 89 if (hp->tc) 90 fprintf(file," tc"); 91 if (hp->rd) 92 fprintf(file," rd"); 93 if (hp->ra) 94 fprintf(file," ra"); 95 if (hp->pr) 96 fprintf(file," pr"); 97 fprintf(file,"\n\tqdcount = %d", ntohs(hp->qdcount)); 98 fprintf(file,", ancount = %d", ntohs(hp->ancount)); 99 fprintf(file,", nscount = %d", ntohs(hp->nscount)); 100 fprintf(file,", arcount = %d\n\n", ntohs(hp->arcount)); 101 /* 102 * Print question records. 103 */ 104 if (n = ntohs(hp->qdcount)) { 105 fprintf(file,"QUESTIONS:\n"); 106 while (--n >= 0) { 107 fprintf(file,"\t"); 108 cp = p_cdname(cp, msg, file); 109 if (cp == NULL) 110 return; 111 fprintf(file,", type = %s", p_type(getshort(cp))); 112 cp += sizeof(u_short); 113 fprintf(file,", class = %s\n\n", p_class(getshort(cp))); 114 cp += sizeof(u_short); 115 } 116 } 117 /* 118 * Print authoritative answer records 119 */ 120 if (n = ntohs(hp->ancount)) { 121 fprintf(file,"ANSWERS:\n"); 122 while (--n >= 0) { 123 fprintf(file,"\t"); 124 cp = p_rr(cp, msg, file); 125 if (cp == NULL) 126 return; 127 } 128 } 129 /* 130 * print name server records 131 */ 132 if (n = ntohs(hp->nscount)) { 133 fprintf(file,"NAME SERVERS:\n"); 134 while (--n >= 0) { 135 fprintf(file,"\t"); 136 cp = p_rr(cp, msg, file); 137 if (cp == NULL) 138 return; 139 } 140 } 141 /* 142 * print additional records 143 */ 144 if (n = ntohs(hp->arcount)) { 145 fprintf(file,"ADDITIONAL RECORDS:\n"); 146 while (--n >= 0) { 147 fprintf(file,"\t"); 148 cp = p_rr(cp, msg, file); 149 if (cp == NULL) 150 return; 151 } 152 } 153 } 154 155 char * 156 p_cdname(cp, msg, file) 157 char *cp, *msg; 158 FILE *file; 159 { 160 char name[MAXDNAME]; 161 int n; 162 163 if ((n = dn_expand(msg, cp, name, sizeof(name))) < 0) 164 return (NULL); 165 if (name[0] == '\0') { 166 name[0] = '.'; 167 name[1] = '\0'; 168 } 169 fputs(name, file); 170 return (cp + n); 171 } 172 173 /* 174 * Print resource record fields in human readable form. 175 */ 176 char * 177 p_rr(cp, msg, file) 178 char *cp, *msg; 179 FILE *file; 180 { 181 int type, class, dlen, n, c; 182 struct in_addr inaddr; 183 char *cp1; 184 185 if ((cp = p_cdname(cp, msg, file)) == NULL) 186 return (NULL); /* compression error */ 187 fprintf(file,"\n\ttype = %s", p_type(type = getshort(cp))); 188 cp += sizeof(u_short); 189 fprintf(file,", class = %s", p_class(class = getshort(cp))); 190 cp += sizeof(u_short); 191 fprintf(file,", ttl = %u", getlong(cp)); 192 cp += sizeof(u_long); 193 fprintf(file,", dlen = %d\n", dlen = getshort(cp)); 194 cp += sizeof(u_short); 195 cp1 = cp; 196 /* 197 * Print type specific data, if appropriate 198 */ 199 switch (type) { 200 case T_A: 201 switch (class) { 202 case C_IN: 203 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 204 if (dlen == 4) { 205 fprintf(file,"\tinternet address = %s\n", 206 inet_ntoa(inaddr)); 207 cp += dlen; 208 } else if (dlen == 7) { 209 fprintf(file,"\tinternet address = %s", 210 inet_ntoa(inaddr)); 211 fprintf(file,", protocol = %d", cp[4]); 212 fprintf(file,", port = %d\n", 213 (cp[5] << 8) + cp[6]); 214 cp += dlen; 215 } 216 break; 217 } 218 break; 219 case T_CNAME: 220 case T_MB: 221 case T_MD: 222 case T_MF: 223 case T_MG: 224 case T_MR: 225 case T_NS: 226 case T_PTR: 227 fprintf(file,"\tdomain name = "); 228 cp = p_cdname(cp, msg, file); 229 fprintf(file,"\n"); 230 break; 231 232 case T_HINFO: 233 if (n = *cp++) { 234 fprintf(file,"\tCPU=%.*s\n", n, cp); 235 cp += n; 236 } 237 if (n = *cp++) { 238 fprintf(file,"\tOS=%.*s\n", n, cp); 239 cp += n; 240 } 241 break; 242 243 case T_SOA: 244 fprintf(file,"\torigin = "); 245 cp = p_cdname(cp, msg, file); 246 fprintf(file,"\n\tmail addr = "); 247 cp = p_cdname(cp, msg, file); 248 fprintf(file,"\n\tserial=%ld", getlong(cp)); 249 cp += sizeof(u_long); 250 fprintf(file,", refresh=%ld", getlong(cp)); 251 cp += sizeof(u_long); 252 fprintf(file,", retry=%ld", getlong(cp)); 253 cp += sizeof(u_long); 254 fprintf(file,", expire=%ld", getlong(cp)); 255 cp += sizeof(u_long); 256 fprintf(file,", min=%ld\n", getlong(cp)); 257 cp += sizeof(u_long); 258 break; 259 260 case T_MINFO: 261 fprintf(file,"\trequests = "); 262 cp = p_cdname(cp, msg, file); 263 fprintf(file,"\n\terrors = "); 264 cp = p_cdname(cp, msg, file); 265 break; 266 267 case T_UINFO: 268 fprintf(file,"\t%s\n", cp); 269 cp += dlen; 270 break; 271 272 case T_UID: 273 case T_GID: 274 if (dlen == 4) { 275 fprintf(file,"\t%ld\n", getlong(cp)); 276 cp += sizeof(int); 277 } 278 break; 279 280 case T_WKS: 281 if (dlen < sizeof(u_long) + 1) 282 break; 283 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 284 cp += sizeof(u_long); 285 fprintf(file,"\tinternet address = %s, protocol = %d\n\t", 286 inet_ntoa(inaddr), *cp++); 287 n = 0; 288 while (cp < cp1 + dlen) { 289 c = *cp++; 290 do { 291 if (c & 0200) 292 fprintf(file," %d", n); 293 c <<= 1; 294 } while (++n & 07); 295 } 296 putc('\n',file); 297 break; 298 299 default: 300 fprintf(file,"\t???\n"); 301 cp += dlen; 302 } 303 if (cp != cp1 + dlen) 304 fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen); 305 fprintf(file,"\n"); 306 return (cp); 307 } 308 309 static char nbuf[20]; 310 extern char *sprintf(); 311 312 /* 313 * Return a string for the type 314 */ 315 char * 316 p_type(type) 317 int type; 318 { 319 320 switch (type) { 321 case T_A: 322 return("A"); 323 case T_NS: /* authoritative server */ 324 return("NS"); 325 case T_MD: /* mail destination */ 326 return("MD"); 327 case T_MF: /* mail forwarder */ 328 return("MF"); 329 case T_CNAME: /* connonical name */ 330 return("CNAME"); 331 case T_SOA: /* start of authority zone */ 332 return("SOA"); 333 case T_MB: /* mailbox domain name */ 334 return("MB"); 335 case T_MG: /* mail group member */ 336 return("MG"); 337 case T_MR: /* mail rename name */ 338 return("MR"); 339 case T_NULL: /* null resource record */ 340 return("NULL"); 341 case T_WKS: /* well known service */ 342 return("WKS"); 343 case T_PTR: /* domain name pointer */ 344 return("PTR"); 345 case T_HINFO: /* host information */ 346 return("HINFO"); 347 case T_MINFO: /* mailbox information */ 348 return("MINFO"); 349 case T_AXFR: /* zone transfer */ 350 return("AXFR"); 351 case T_MAILB: /* mail box */ 352 return("MAILB"); 353 case T_MAILA: /* mail address */ 354 return("MAILA"); 355 case T_ANY: /* matches any type */ 356 return("ANY"); 357 case T_UINFO: 358 return("UINFO"); 359 case T_UID: 360 return("UID"); 361 case T_GID: 362 return("GID"); 363 default: 364 return (sprintf(nbuf, "%d", type)); 365 } 366 } 367 368 /* 369 * Return a mnemonic for class 370 */ 371 char * 372 p_class(class) 373 int class; 374 { 375 376 switch (class) { 377 case C_IN: /* internet class */ 378 return("IN"); 379 case C_CS: /* csnet class */ 380 return("CS"); 381 case C_ANY: /* matches any class */ 382 return("ANY"); 383 default: 384 return (sprintf(nbuf, "%d", class)); 385 } 386 } 387 388