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