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