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