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