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