Commit | Line | Data |
---|---|---|
b423e985 | 1 | /* |
8ea4199d DF |
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. | |
b423e985 RC |
5 | */ |
6 | ||
8ea4199d DF |
7 | #ifndef lint |
8 | static char sccsid[] = "@(#)res_debug.c 5.1 (Berkeley) %G%"; | |
9 | #endif not lint | |
10 | ||
0d22afd1 RC |
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 | */ | |
e515a559 RC |
61 | p_query(msg) |
62 | char *msg; | |
0d22afd1 RC |
63 | { |
64 | register char *cp; | |
65 | register HEADER *hp; | |
66 | register int n; | |
67 | ||
68 | /* | |
69 | * Print header fields. | |
70 | */ | |
e515a559 RC |
71 | hp = (HEADER *)msg; |
72 | cp = msg + sizeof(HEADER); | |
0d22afd1 RC |
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"); | |
e515a559 | 101 | cp = p_cdname(cp, msg); |
0d22afd1 RC |
102 | if (cp == NULL) |
103 | return; | |
11e57e73 | 104 | printf(", type = %s", p_type(getshort(cp))); |
0d22afd1 | 105 | cp += sizeof(u_short); |
11e57e73 | 106 | printf(", class = %s\n\n", p_class(getshort(cp))); |
0d22afd1 RC |
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"); | |
e515a559 | 117 | cp = p_rr(cp, msg); |
0d22afd1 RC |
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"); | |
e515a559 | 129 | cp = p_rr(cp, msg); |
0d22afd1 RC |
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"); | |
e515a559 | 141 | cp = p_rr(cp, msg); |
0d22afd1 RC |
142 | if (cp == NULL) |
143 | return; | |
144 | } | |
145 | } | |
146 | } | |
147 | ||
148 | char * | |
e515a559 RC |
149 | p_cdname(cp, msg) |
150 | char *cp, *msg; | |
0d22afd1 RC |
151 | { |
152 | char name[MAXDNAME]; | |
153 | int n; | |
154 | ||
e515a559 | 155 | if ((n = dn_expand(msg, cp, name, sizeof(name))) < 0) |
0d22afd1 RC |
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 * | |
e515a559 RC |
169 | p_rr(cp, msg) |
170 | char *cp, *msg; | |
0d22afd1 RC |
171 | { |
172 | int type, class, dlen, n, c; | |
173 | struct in_addr inaddr; | |
174 | char *cp1; | |
175 | ||
e515a559 | 176 | if ((cp = p_cdname(cp, msg)) == NULL) |
0d22afd1 | 177 | return (NULL); /* compression error */ |
11e57e73 | 178 | printf("\n\ttype = %s", p_type(type = getshort(cp))); |
0d22afd1 | 179 | cp += sizeof(u_short); |
11e57e73 | 180 | printf(", class = %s", p_class(class = getshort(cp))); |
0d22afd1 | 181 | cp += sizeof(u_short); |
11e57e73 | 182 | printf(", ttl = %ld", getlong(cp)); |
0d22afd1 | 183 | cp += sizeof(u_long); |
11e57e73 | 184 | printf(", dlen = %d\n", dlen = getshort(cp)); |
0d22afd1 RC |
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: | |
11e57e73 | 194 | bcopy(cp, (char *)&inaddr, sizeof(inaddr)); |
0d22afd1 RC |
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 = "); | |
e515a559 | 219 | cp = p_cdname(cp, msg); |
0d22afd1 RC |
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 = "); | |
e515a559 | 236 | cp = p_cdname(cp, msg); |
0d22afd1 | 237 | printf("\n\tmail addr = "); |
e515a559 | 238 | cp = p_cdname(cp, msg); |
11e57e73 | 239 | printf("\n\tserial=%ld", getlong(cp)); |
0d22afd1 | 240 | cp += sizeof(u_long); |
11e57e73 | 241 | printf(", refresh=%ld", getlong(cp)); |
0d22afd1 | 242 | cp += sizeof(u_long); |
11e57e73 | 243 | printf(", retry=%ld", getlong(cp)); |
0d22afd1 | 244 | cp += sizeof(u_long); |
11e57e73 | 245 | printf(", expire=%ld", getlong(cp)); |
0d22afd1 | 246 | cp += sizeof(u_long); |
11e57e73 | 247 | printf(", min=%ld\n", getlong(cp)); |
0d22afd1 RC |
248 | cp += sizeof(u_long); |
249 | break; | |
250 | ||
e515a559 RC |
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 | ||
0d22afd1 RC |
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) { | |
11e57e73 | 266 | printf("\t%ld\n", getlong(cp)); |
0d22afd1 RC |
267 | cp += sizeof(int); |
268 | } | |
269 | break; | |
270 | ||
271 | case T_WKS: | |
272 | if (dlen < sizeof(u_long) + 1) | |
273 | break; | |
11e57e73 | 274 | bcopy(cp, (char *)&inaddr, sizeof(inaddr)); |
0d22afd1 RC |
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 | } |