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