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