Commit | Line | Data |
---|---|---|
b423e985 | 1 | /* |
8ea4199d | 2 | * Copyright (c) 1985 Regents of the University of California. |
6b2f9dd0 KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
f4f66d2c KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
b423e985 RC |
16 | */ |
17 | ||
2ce81398 | 18 | #if defined(LIBC_SCCS) && !defined(lint) |
f4f66d2c | 19 | static char sccsid[] = "@(#)res_debug.c 5.24 (Berkeley) %G%"; |
6b2f9dd0 | 20 | #endif /* LIBC_SCCS and not lint */ |
8ea4199d | 21 | |
d1c1ab68 JB |
22 | #if defined(lint) && !defined(DEBUG) |
23 | #define DEBUG | |
24 | #endif | |
25 | ||
0d22afd1 RC |
26 | #include <sys/types.h> |
27 | #include <netinet/in.h> | |
28 | #include <stdio.h> | |
02a51825 | 29 | #include <arpa/nameser.h> |
0d22afd1 | 30 | |
7134abf2 | 31 | extern char *p_cdname(), *p_rr(), *p_type(), *p_class(), *p_time(); |
0d22afd1 RC |
32 | extern char *inet_ntoa(); |
33 | ||
cd43bd6a | 34 | char *_res_opcodes[] = { |
0d22afd1 RC |
35 | "QUERY", |
36 | "IQUERY", | |
37 | "CQUERYM", | |
38 | "CQUERYU", | |
39 | "4", | |
40 | "5", | |
41 | "6", | |
42 | "7", | |
43 | "8", | |
0d22afd1 RC |
44 | "UPDATEA", |
45 | "UPDATED", | |
3e8361d9 | 46 | "UPDATEDA", |
0d22afd1 | 47 | "UPDATEM", |
3e8361d9 | 48 | "UPDATEMA", |
0d22afd1 RC |
49 | "ZONEINIT", |
50 | "ZONEREF", | |
51 | }; | |
52 | ||
cd43bd6a | 53 | char *_res_resultcodes[] = { |
0d22afd1 RC |
54 | "NOERROR", |
55 | "FORMERR", | |
56 | "SERVFAIL", | |
57 | "NXDOMAIN", | |
58 | "NOTIMP", | |
59 | "REFUSED", | |
60 | "6", | |
61 | "7", | |
62 | "8", | |
63 | "9", | |
64 | "10", | |
65 | "11", | |
66 | "12", | |
67 | "13", | |
68 | "14", | |
69 | "NOCHANGE", | |
70 | }; | |
71 | ||
a73d974c KD |
72 | p_query(msg) |
73 | char *msg; | |
74 | { | |
d1c1ab68 | 75 | #ifdef DEBUG |
a73d974c | 76 | fp_query(msg,stdout); |
d1c1ab68 | 77 | #endif |
a73d974c KD |
78 | } |
79 | ||
0d22afd1 RC |
80 | /* |
81 | * Print the contents of a query. | |
82 | * This is intended to be primarily a debugging routine. | |
83 | */ | |
a73d974c | 84 | fp_query(msg,file) |
e515a559 | 85 | char *msg; |
a73d974c | 86 | FILE *file; |
0d22afd1 | 87 | { |
d1c1ab68 | 88 | #ifdef DEBUG |
0d22afd1 RC |
89 | register char *cp; |
90 | register HEADER *hp; | |
91 | register int n; | |
92 | ||
93 | /* | |
94 | * Print header fields. | |
95 | */ | |
e515a559 RC |
96 | hp = (HEADER *)msg; |
97 | cp = msg + sizeof(HEADER); | |
a73d974c | 98 | fprintf(file,"HEADER:\n"); |
d7070d01 | 99 | fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); |
a73d974c | 100 | fprintf(file,", id = %d", ntohs(hp->id)); |
d7070d01 | 101 | fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]); |
a73d974c | 102 | fprintf(file,"\theader flags: "); |
0d22afd1 | 103 | if (hp->qr) |
a73d974c | 104 | fprintf(file," qr"); |
0d22afd1 | 105 | if (hp->aa) |
a73d974c | 106 | fprintf(file," aa"); |
0d22afd1 | 107 | if (hp->tc) |
a73d974c | 108 | fprintf(file," tc"); |
0d22afd1 | 109 | if (hp->rd) |
a73d974c | 110 | fprintf(file," rd"); |
0d22afd1 | 111 | if (hp->ra) |
a73d974c | 112 | fprintf(file," ra"); |
0d22afd1 | 113 | if (hp->pr) |
a73d974c KD |
114 | fprintf(file," pr"); |
115 | fprintf(file,"\n\tqdcount = %d", ntohs(hp->qdcount)); | |
116 | fprintf(file,", ancount = %d", ntohs(hp->ancount)); | |
117 | fprintf(file,", nscount = %d", ntohs(hp->nscount)); | |
118 | fprintf(file,", arcount = %d\n\n", ntohs(hp->arcount)); | |
0d22afd1 RC |
119 | /* |
120 | * Print question records. | |
121 | */ | |
122 | if (n = ntohs(hp->qdcount)) { | |
a73d974c | 123 | fprintf(file,"QUESTIONS:\n"); |
0d22afd1 | 124 | while (--n >= 0) { |
a73d974c KD |
125 | fprintf(file,"\t"); |
126 | cp = p_cdname(cp, msg, file); | |
0d22afd1 RC |
127 | if (cp == NULL) |
128 | return; | |
20087cad | 129 | fprintf(file,", type = %s", p_type(_getshort(cp))); |
0d22afd1 | 130 | cp += sizeof(u_short); |
20087cad | 131 | fprintf(file,", class = %s\n\n", p_class(_getshort(cp))); |
0d22afd1 RC |
132 | cp += sizeof(u_short); |
133 | } | |
134 | } | |
135 | /* | |
136 | * Print authoritative answer records | |
137 | */ | |
138 | if (n = ntohs(hp->ancount)) { | |
a73d974c | 139 | fprintf(file,"ANSWERS:\n"); |
0d22afd1 | 140 | while (--n >= 0) { |
a73d974c KD |
141 | fprintf(file,"\t"); |
142 | cp = p_rr(cp, msg, file); | |
0d22afd1 RC |
143 | if (cp == NULL) |
144 | return; | |
145 | } | |
146 | } | |
147 | /* | |
148 | * print name server records | |
149 | */ | |
150 | if (n = ntohs(hp->nscount)) { | |
a73d974c | 151 | fprintf(file,"NAME SERVERS:\n"); |
0d22afd1 | 152 | while (--n >= 0) { |
a73d974c KD |
153 | fprintf(file,"\t"); |
154 | cp = p_rr(cp, msg, file); | |
0d22afd1 RC |
155 | if (cp == NULL) |
156 | return; | |
157 | } | |
158 | } | |
159 | /* | |
160 | * print additional records | |
161 | */ | |
162 | if (n = ntohs(hp->arcount)) { | |
a73d974c | 163 | fprintf(file,"ADDITIONAL RECORDS:\n"); |
0d22afd1 | 164 | while (--n >= 0) { |
a73d974c KD |
165 | fprintf(file,"\t"); |
166 | cp = p_rr(cp, msg, file); | |
0d22afd1 RC |
167 | if (cp == NULL) |
168 | return; | |
169 | } | |
170 | } | |
d1c1ab68 | 171 | #endif |
0d22afd1 RC |
172 | } |
173 | ||
174 | char * | |
a73d974c | 175 | p_cdname(cp, msg, file) |
e515a559 | 176 | char *cp, *msg; |
a73d974c | 177 | FILE *file; |
0d22afd1 | 178 | { |
d1c1ab68 | 179 | #ifdef DEBUG |
0d22afd1 RC |
180 | char name[MAXDNAME]; |
181 | int n; | |
182 | ||
127b68cb | 183 | if ((n = dn_expand(msg, msg + 512, cp, name, sizeof(name))) < 0) |
0d22afd1 RC |
184 | return (NULL); |
185 | if (name[0] == '\0') { | |
186 | name[0] = '.'; | |
187 | name[1] = '\0'; | |
188 | } | |
a73d974c | 189 | fputs(name, file); |
0d22afd1 | 190 | return (cp + n); |
d1c1ab68 | 191 | #endif |
0d22afd1 RC |
192 | } |
193 | ||
194 | /* | |
195 | * Print resource record fields in human readable form. | |
196 | */ | |
197 | char * | |
a73d974c | 198 | p_rr(cp, msg, file) |
e515a559 | 199 | char *cp, *msg; |
a73d974c | 200 | FILE *file; |
0d22afd1 | 201 | { |
d1c1ab68 | 202 | #ifdef DEBUG |
0d22afd1 RC |
203 | int type, class, dlen, n, c; |
204 | struct in_addr inaddr; | |
205 | char *cp1; | |
206 | ||
a73d974c | 207 | if ((cp = p_cdname(cp, msg, file)) == NULL) |
0d22afd1 | 208 | return (NULL); /* compression error */ |
20087cad | 209 | fprintf(file,"\n\ttype = %s", p_type(type = _getshort(cp))); |
0d22afd1 | 210 | cp += sizeof(u_short); |
20087cad | 211 | fprintf(file,", class = %s", p_class(class = _getshort(cp))); |
0d22afd1 | 212 | cp += sizeof(u_short); |
7134abf2 | 213 | fprintf(file,", ttl = %s", p_time(cp)); |
0d22afd1 | 214 | cp += sizeof(u_long); |
20087cad | 215 | fprintf(file,", dlen = %d\n", dlen = _getshort(cp)); |
0d22afd1 RC |
216 | cp += sizeof(u_short); |
217 | cp1 = cp; | |
218 | /* | |
219 | * Print type specific data, if appropriate | |
220 | */ | |
221 | switch (type) { | |
222 | case T_A: | |
223 | switch (class) { | |
224 | case C_IN: | |
11e57e73 | 225 | bcopy(cp, (char *)&inaddr, sizeof(inaddr)); |
0d22afd1 | 226 | if (dlen == 4) { |
a73d974c | 227 | fprintf(file,"\tinternet address = %s\n", |
0d22afd1 RC |
228 | inet_ntoa(inaddr)); |
229 | cp += dlen; | |
230 | } else if (dlen == 7) { | |
a73d974c | 231 | fprintf(file,"\tinternet address = %s", |
0d22afd1 | 232 | inet_ntoa(inaddr)); |
a73d974c KD |
233 | fprintf(file,", protocol = %d", cp[4]); |
234 | fprintf(file,", port = %d\n", | |
0d22afd1 RC |
235 | (cp[5] << 8) + cp[6]); |
236 | cp += dlen; | |
237 | } | |
238 | break; | |
e0dd8906 KD |
239 | default: |
240 | cp += dlen; | |
0d22afd1 RC |
241 | } |
242 | break; | |
243 | case T_CNAME: | |
244 | case T_MB: | |
018df4a9 | 245 | #ifdef OLDRR |
0d22afd1 RC |
246 | case T_MD: |
247 | case T_MF: | |
018df4a9 | 248 | #endif /* OLDRR */ |
0d22afd1 RC |
249 | case T_MG: |
250 | case T_MR: | |
251 | case T_NS: | |
252 | case T_PTR: | |
a73d974c KD |
253 | fprintf(file,"\tdomain name = "); |
254 | cp = p_cdname(cp, msg, file); | |
255 | fprintf(file,"\n"); | |
0d22afd1 RC |
256 | break; |
257 | ||
258 | case T_HINFO: | |
259 | if (n = *cp++) { | |
a73d974c | 260 | fprintf(file,"\tCPU=%.*s\n", n, cp); |
0d22afd1 RC |
261 | cp += n; |
262 | } | |
263 | if (n = *cp++) { | |
a73d974c | 264 | fprintf(file,"\tOS=%.*s\n", n, cp); |
0d22afd1 RC |
265 | cp += n; |
266 | } | |
267 | break; | |
268 | ||
269 | case T_SOA: | |
a73d974c KD |
270 | fprintf(file,"\torigin = "); |
271 | cp = p_cdname(cp, msg, file); | |
272 | fprintf(file,"\n\tmail addr = "); | |
273 | cp = p_cdname(cp, msg, file); | |
20087cad | 274 | fprintf(file,"\n\tserial=%ld", _getlong(cp)); |
0d22afd1 | 275 | cp += sizeof(u_long); |
7134abf2 | 276 | fprintf(file,", refresh=%s", p_time(cp)); |
0d22afd1 | 277 | cp += sizeof(u_long); |
7134abf2 | 278 | fprintf(file,", retry=%s", p_time(cp)); |
0d22afd1 | 279 | cp += sizeof(u_long); |
7134abf2 | 280 | fprintf(file,", expire=%s", p_time(cp)); |
0d22afd1 | 281 | cp += sizeof(u_long); |
7134abf2 | 282 | fprintf(file,", min=%s\n", p_time(cp)); |
0d22afd1 RC |
283 | cp += sizeof(u_long); |
284 | break; | |
285 | ||
73546a32 | 286 | case T_MX: |
20087cad | 287 | fprintf(file,"\tpreference = %ld,",_getshort(cp)); |
018df4a9 KD |
288 | cp += sizeof(u_short); |
289 | fprintf(file," name = "); | |
73546a32 | 290 | cp = p_cdname(cp, msg, file); |
73546a32 KD |
291 | break; |
292 | ||
e515a559 | 293 | case T_MINFO: |
a73d974c KD |
294 | fprintf(file,"\trequests = "); |
295 | cp = p_cdname(cp, msg, file); | |
296 | fprintf(file,"\n\terrors = "); | |
297 | cp = p_cdname(cp, msg, file); | |
e515a559 RC |
298 | break; |
299 | ||
0d22afd1 | 300 | case T_UINFO: |
a73d974c | 301 | fprintf(file,"\t%s\n", cp); |
0d22afd1 RC |
302 | cp += dlen; |
303 | break; | |
304 | ||
305 | case T_UID: | |
306 | case T_GID: | |
307 | if (dlen == 4) { | |
20087cad | 308 | fprintf(file,"\t%ld\n", _getlong(cp)); |
0d22afd1 RC |
309 | cp += sizeof(int); |
310 | } | |
311 | break; | |
312 | ||
313 | case T_WKS: | |
314 | if (dlen < sizeof(u_long) + 1) | |
315 | break; | |
11e57e73 | 316 | bcopy(cp, (char *)&inaddr, sizeof(inaddr)); |
0d22afd1 | 317 | cp += sizeof(u_long); |
a73d974c | 318 | fprintf(file,"\tinternet address = %s, protocol = %d\n\t", |
0d22afd1 RC |
319 | inet_ntoa(inaddr), *cp++); |
320 | n = 0; | |
321 | while (cp < cp1 + dlen) { | |
322 | c = *cp++; | |
323 | do { | |
a943feed | 324 | if (c & 0200) |
a73d974c | 325 | fprintf(file," %d", n); |
a943feed | 326 | c <<= 1; |
0d22afd1 RC |
327 | } while (++n & 07); |
328 | } | |
a73d974c | 329 | putc('\n',file); |
0d22afd1 RC |
330 | break; |
331 | ||
3bf25746 | 332 | #ifdef ALLOW_T_UNSPEC |
1e12917d KB |
333 | case T_UNSPEC: |
334 | { | |
335 | int NumBytes = 8; | |
336 | char *DataPtr; | |
337 | int i; | |
3bf25746 | 338 | |
1e12917d KB |
339 | if (dlen < NumBytes) NumBytes = dlen; |
340 | fprintf(file, "\tFirst %d bytes of hex data:", | |
341 | NumBytes); | |
342 | for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++) | |
343 | fprintf(file, " %x", *DataPtr); | |
344 | fputs("\n", file); | |
345 | cp += dlen; | |
346 | } | |
347 | break; | |
348 | #endif /* ALLOW_T_UNSPEC */ | |
3bf25746 | 349 | |
0d22afd1 | 350 | default: |
a73d974c | 351 | fprintf(file,"\t???\n"); |
0d22afd1 RC |
352 | cp += dlen; |
353 | } | |
354 | if (cp != cp1 + dlen) | |
a73d974c KD |
355 | fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen); |
356 | fprintf(file,"\n"); | |
0d22afd1 | 357 | return (cp); |
d1c1ab68 | 358 | #endif |
0d22afd1 RC |
359 | } |
360 | ||
7134abf2 | 361 | static char nbuf[40]; |
0d22afd1 RC |
362 | |
363 | /* | |
364 | * Return a string for the type | |
365 | */ | |
366 | char * | |
367 | p_type(type) | |
368 | int type; | |
369 | { | |
0d22afd1 RC |
370 | switch (type) { |
371 | case T_A: | |
372 | return("A"); | |
373 | case T_NS: /* authoritative server */ | |
374 | return("NS"); | |
018df4a9 | 375 | #ifdef OLDRR |
0d22afd1 RC |
376 | case T_MD: /* mail destination */ |
377 | return("MD"); | |
378 | case T_MF: /* mail forwarder */ | |
379 | return("MF"); | |
018df4a9 | 380 | #endif /* OLDRR */ |
0d22afd1 RC |
381 | case T_CNAME: /* connonical name */ |
382 | return("CNAME"); | |
383 | case T_SOA: /* start of authority zone */ | |
384 | return("SOA"); | |
385 | case T_MB: /* mailbox domain name */ | |
386 | return("MB"); | |
387 | case T_MG: /* mail group member */ | |
388 | return("MG"); | |
73546a32 KD |
389 | case T_MX: /* mail routing info */ |
390 | return("MX"); | |
0d22afd1 RC |
391 | case T_MR: /* mail rename name */ |
392 | return("MR"); | |
393 | case T_NULL: /* null resource record */ | |
394 | return("NULL"); | |
395 | case T_WKS: /* well known service */ | |
396 | return("WKS"); | |
397 | case T_PTR: /* domain name pointer */ | |
398 | return("PTR"); | |
399 | case T_HINFO: /* host information */ | |
400 | return("HINFO"); | |
401 | case T_MINFO: /* mailbox information */ | |
402 | return("MINFO"); | |
403 | case T_AXFR: /* zone transfer */ | |
404 | return("AXFR"); | |
405 | case T_MAILB: /* mail box */ | |
406 | return("MAILB"); | |
407 | case T_MAILA: /* mail address */ | |
408 | return("MAILA"); | |
409 | case T_ANY: /* matches any type */ | |
410 | return("ANY"); | |
411 | case T_UINFO: | |
412 | return("UINFO"); | |
413 | case T_UID: | |
414 | return("UID"); | |
415 | case T_GID: | |
416 | return("GID"); | |
3bf25746 | 417 | #ifdef ALLOW_T_UNSPEC |
1e12917d KB |
418 | case T_UNSPEC: |
419 | return("UNSPEC"); | |
420 | #endif /* ALLOW_T_UNSPEC */ | |
0d22afd1 | 421 | default: |
06eef7c4 KB |
422 | (void)sprintf(nbuf, "%d", type); |
423 | return(nbuf); | |
0d22afd1 RC |
424 | } |
425 | } | |
426 | ||
427 | /* | |
428 | * Return a mnemonic for class | |
429 | */ | |
430 | char * | |
431 | p_class(class) | |
432 | int class; | |
433 | { | |
434 | ||
435 | switch (class) { | |
436 | case C_IN: /* internet class */ | |
437 | return("IN"); | |
0d22afd1 RC |
438 | case C_ANY: /* matches any class */ |
439 | return("ANY"); | |
440 | default: | |
06eef7c4 KB |
441 | (void)sprintf(nbuf, "%d", class); |
442 | return(nbuf); | |
0d22afd1 RC |
443 | } |
444 | } | |
7134abf2 MK |
445 | |
446 | /* | |
447 | * Return a mnemonic for a time to live | |
448 | */ | |
449 | char | |
450 | *p_time(value) | |
451 | u_long value; | |
452 | { | |
453 | int secs, mins, hours; | |
454 | register char *p; | |
455 | ||
456 | secs = value % 60; | |
457 | value /= 60; | |
458 | mins = value % 60; | |
459 | value /= 60; | |
460 | hours = value % 24; | |
461 | value /= 24; | |
462 | ||
463 | #define PLURALIZE(x) x, (x == 1) ? "" : "s" | |
464 | p = nbuf; | |
465 | if (value) { | |
466 | (void)sprintf(p, "%d day%s", PLURALIZE(value)); | |
467 | while (*++p); | |
468 | } | |
469 | if (hours) { | |
470 | if (p != nbuf) | |
471 | *p++ = ' '; | |
472 | (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); | |
473 | while (*++p); | |
474 | } | |
475 | if (mins) { | |
476 | if (p != nbuf) | |
477 | *p++ = ' '; | |
478 | (void)sprintf(p, "%d min%s", PLURALIZE(mins)); | |
479 | while (*++p); | |
480 | } | |
481 | if (secs) { | |
482 | if (p != nbuf) | |
483 | *p++ = ' '; | |
484 | (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); | |
485 | while (*++p); | |
486 | } | |
487 | return(nbuf); | |
488 | } |