one more try at getting the buffer end checking right in dn_expand
[unix-history] / usr / src / lib / libc / net / res_debug.c
CommitLineData
b423e985 1/*
ad5ac231 2 * Copyright (c) 1985, 1990 Regents of the University of California.
6b2f9dd0
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
f4f66d2c
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
b423e985
RC
16 */
17
2ce81398 18#if defined(LIBC_SCCS) && !defined(lint)
4a7d845b 19static char sccsid[] = "@(#)res_debug.c 5.29 (Berkeley) %G%";
6b2f9dd0 20#endif /* LIBC_SCCS and not lint */
8ea4199d 21
0d22afd1
RC
22#include <sys/types.h>
23#include <netinet/in.h>
24#include <stdio.h>
02a51825 25#include <arpa/nameser.h>
0d22afd1 26
7134abf2 27extern char *p_cdname(), *p_rr(), *p_type(), *p_class(), *p_time();
0d22afd1
RC
28extern char *inet_ntoa();
29
cd43bd6a 30char *_res_opcodes[] = {
0d22afd1
RC
31 "QUERY",
32 "IQUERY",
33 "CQUERYM",
34 "CQUERYU",
35 "4",
36 "5",
37 "6",
38 "7",
39 "8",
0d22afd1
RC
40 "UPDATEA",
41 "UPDATED",
3e8361d9 42 "UPDATEDA",
0d22afd1 43 "UPDATEM",
3e8361d9 44 "UPDATEMA",
0d22afd1
RC
45 "ZONEINIT",
46 "ZONEREF",
47};
48
cd43bd6a 49char *_res_resultcodes[] = {
0d22afd1
RC
50 "NOERROR",
51 "FORMERR",
52 "SERVFAIL",
53 "NXDOMAIN",
54 "NOTIMP",
55 "REFUSED",
56 "6",
57 "7",
58 "8",
59 "9",
60 "10",
61 "11",
62 "12",
63 "13",
64 "14",
65 "NOCHANGE",
66};
67
a73d974c
KD
68p_query(msg)
69 char *msg;
70{
71 fp_query(msg,stdout);
72}
73
0d22afd1
RC
74/*
75 * Print the contents of a query.
76 * This is intended to be primarily a debugging routine.
77 */
a73d974c 78fp_query(msg,file)
e515a559 79 char *msg;
a73d974c 80 FILE *file;
0d22afd1
RC
81{
82 register char *cp;
83 register HEADER *hp;
84 register int n;
85
86 /*
87 * Print header fields.
88 */
e515a559
RC
89 hp = (HEADER *)msg;
90 cp = msg + sizeof(HEADER);
a73d974c 91 fprintf(file,"HEADER:\n");
d7070d01 92 fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]);
a73d974c 93 fprintf(file,", id = %d", ntohs(hp->id));
d7070d01 94 fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]);
a73d974c 95 fprintf(file,"\theader flags: ");
0d22afd1 96 if (hp->qr)
a73d974c 97 fprintf(file," qr");
0d22afd1 98 if (hp->aa)
a73d974c 99 fprintf(file," aa");
0d22afd1 100 if (hp->tc)
a73d974c 101 fprintf(file," tc");
0d22afd1 102 if (hp->rd)
a73d974c 103 fprintf(file," rd");
0d22afd1 104 if (hp->ra)
a73d974c 105 fprintf(file," ra");
0d22afd1 106 if (hp->pr)
a73d974c
KD
107 fprintf(file," pr");
108 fprintf(file,"\n\tqdcount = %d", ntohs(hp->qdcount));
109 fprintf(file,", ancount = %d", ntohs(hp->ancount));
110 fprintf(file,", nscount = %d", ntohs(hp->nscount));
111 fprintf(file,", arcount = %d\n\n", ntohs(hp->arcount));
0d22afd1
RC
112 /*
113 * Print question records.
114 */
115 if (n = ntohs(hp->qdcount)) {
a73d974c 116 fprintf(file,"QUESTIONS:\n");
0d22afd1 117 while (--n >= 0) {
a73d974c
KD
118 fprintf(file,"\t");
119 cp = p_cdname(cp, msg, file);
0d22afd1
RC
120 if (cp == NULL)
121 return;
20087cad 122 fprintf(file,", type = %s", p_type(_getshort(cp)));
0d22afd1 123 cp += sizeof(u_short);
20087cad 124 fprintf(file,", class = %s\n\n", p_class(_getshort(cp)));
0d22afd1
RC
125 cp += sizeof(u_short);
126 }
127 }
128 /*
129 * Print authoritative answer records
130 */
131 if (n = ntohs(hp->ancount)) {
a73d974c 132 fprintf(file,"ANSWERS:\n");
0d22afd1 133 while (--n >= 0) {
a73d974c
KD
134 fprintf(file,"\t");
135 cp = p_rr(cp, msg, file);
0d22afd1
RC
136 if (cp == NULL)
137 return;
138 }
139 }
140 /*
141 * print name server records
142 */
143 if (n = ntohs(hp->nscount)) {
a73d974c 144 fprintf(file,"NAME SERVERS:\n");
0d22afd1 145 while (--n >= 0) {
a73d974c
KD
146 fprintf(file,"\t");
147 cp = p_rr(cp, msg, file);
0d22afd1
RC
148 if (cp == NULL)
149 return;
150 }
151 }
152 /*
153 * print additional records
154 */
155 if (n = ntohs(hp->arcount)) {
a73d974c 156 fprintf(file,"ADDITIONAL RECORDS:\n");
0d22afd1 157 while (--n >= 0) {
a73d974c
KD
158 fprintf(file,"\t");
159 cp = p_rr(cp, msg, file);
0d22afd1
RC
160 if (cp == NULL)
161 return;
162 }
163 }
164}
165
166char *
a73d974c 167p_cdname(cp, msg, file)
e515a559 168 char *cp, *msg;
a73d974c 169 FILE *file;
0d22afd1
RC
170{
171 char name[MAXDNAME];
172 int n;
173
127b68cb 174 if ((n = dn_expand(msg, msg + 512, cp, name, sizeof(name))) < 0)
0d22afd1
RC
175 return (NULL);
176 if (name[0] == '\0') {
177 name[0] = '.';
178 name[1] = '\0';
179 }
a73d974c 180 fputs(name, file);
0d22afd1
RC
181 return (cp + n);
182}
183
184/*
185 * Print resource record fields in human readable form.
186 */
187char *
a73d974c 188p_rr(cp, msg, file)
e515a559 189 char *cp, *msg;
a73d974c 190 FILE *file;
0d22afd1
RC
191{
192 int type, class, dlen, n, c;
193 struct in_addr inaddr;
4a7d845b 194 char *cp1, *cp2;
0d22afd1 195
a73d974c 196 if ((cp = p_cdname(cp, msg, file)) == NULL)
0d22afd1 197 return (NULL); /* compression error */
20087cad 198 fprintf(file,"\n\ttype = %s", p_type(type = _getshort(cp)));
0d22afd1 199 cp += sizeof(u_short);
20087cad 200 fprintf(file,", class = %s", p_class(class = _getshort(cp)));
0d22afd1 201 cp += sizeof(u_short);
606dc84e 202 fprintf(file,", ttl = %s", p_time(_getlong(cp)));
0d22afd1 203 cp += sizeof(u_long);
20087cad 204 fprintf(file,", dlen = %d\n", dlen = _getshort(cp));
0d22afd1
RC
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:
ad5ac231 214 case C_HS:
11e57e73 215 bcopy(cp, (char *)&inaddr, sizeof(inaddr));
0d22afd1 216 if (dlen == 4) {
a73d974c 217 fprintf(file,"\tinternet address = %s\n",
0d22afd1
RC
218 inet_ntoa(inaddr));
219 cp += dlen;
220 } else if (dlen == 7) {
a73d974c 221 fprintf(file,"\tinternet address = %s",
0d22afd1 222 inet_ntoa(inaddr));
a73d974c
KD
223 fprintf(file,", protocol = %d", cp[4]);
224 fprintf(file,", port = %d\n",
0d22afd1
RC
225 (cp[5] << 8) + cp[6]);
226 cp += dlen;
227 }
228 break;
e0dd8906
KD
229 default:
230 cp += dlen;
0d22afd1
RC
231 }
232 break;
233 case T_CNAME:
234 case T_MB:
0d22afd1
RC
235 case T_MG:
236 case T_MR:
237 case T_NS:
238 case T_PTR:
a73d974c
KD
239 fprintf(file,"\tdomain name = ");
240 cp = p_cdname(cp, msg, file);
241 fprintf(file,"\n");
0d22afd1
RC
242 break;
243
244 case T_HINFO:
245 if (n = *cp++) {
a73d974c 246 fprintf(file,"\tCPU=%.*s\n", n, cp);
0d22afd1
RC
247 cp += n;
248 }
249 if (n = *cp++) {
a73d974c 250 fprintf(file,"\tOS=%.*s\n", n, cp);
0d22afd1
RC
251 cp += n;
252 }
253 break;
254
255 case T_SOA:
a73d974c
KD
256 fprintf(file,"\torigin = ");
257 cp = p_cdname(cp, msg, file);
258 fprintf(file,"\n\tmail addr = ");
259 cp = p_cdname(cp, msg, file);
606dc84e 260 fprintf(file,"\n\tserial = %ld", _getlong(cp));
0d22afd1 261 cp += sizeof(u_long);
606dc84e 262 fprintf(file,"\n\trefresh = %s", p_time(_getlong(cp)));
0d22afd1 263 cp += sizeof(u_long);
606dc84e 264 fprintf(file,"\n\tretry = %s", p_time(_getlong(cp)));
0d22afd1 265 cp += sizeof(u_long);
606dc84e 266 fprintf(file,"\n\texpire = %s", p_time(_getlong(cp)));
0d22afd1 267 cp += sizeof(u_long);
606dc84e 268 fprintf(file,"\n\tmin = %s\n", p_time(_getlong(cp)));
0d22afd1
RC
269 cp += sizeof(u_long);
270 break;
271
73546a32 272 case T_MX:
20087cad 273 fprintf(file,"\tpreference = %ld,",_getshort(cp));
018df4a9
KD
274 cp += sizeof(u_short);
275 fprintf(file," name = ");
73546a32 276 cp = p_cdname(cp, msg, file);
73546a32
KD
277 break;
278
ad5ac231
JB
279 case T_TXT:
280 (void) fputs("\t\"", file);
281 cp2 = cp1 + dlen;
282 while (cp < cp2) {
283 if (n = (unsigned char) *cp++) {
284 for (c = n; c > 0 && cp < cp2; c--)
285 if (*cp == '\n') {
286 (void) putc('\\', file);
287 (void) putc(*cp++, file);
288 } else
289 (void) putc(*cp++, file);
290 }
291 }
292 (void) fputs("\"\n", file);
293 break;
0af159f3 294
e515a559 295 case T_MINFO:
a73d974c
KD
296 fprintf(file,"\trequests = ");
297 cp = p_cdname(cp, msg, file);
298 fprintf(file,"\n\terrors = ");
299 cp = p_cdname(cp, msg, file);
e515a559
RC
300 break;
301
0d22afd1 302 case T_UINFO:
a73d974c 303 fprintf(file,"\t%s\n", cp);
0d22afd1
RC
304 cp += dlen;
305 break;
306
307 case T_UID:
308 case T_GID:
309 if (dlen == 4) {
20087cad 310 fprintf(file,"\t%ld\n", _getlong(cp));
0d22afd1
RC
311 cp += sizeof(int);
312 }
313 break;
314
315 case T_WKS:
316 if (dlen < sizeof(u_long) + 1)
317 break;
11e57e73 318 bcopy(cp, (char *)&inaddr, sizeof(inaddr));
0d22afd1 319 cp += sizeof(u_long);
a73d974c 320 fprintf(file,"\tinternet address = %s, protocol = %d\n\t",
0d22afd1
RC
321 inet_ntoa(inaddr), *cp++);
322 n = 0;
323 while (cp < cp1 + dlen) {
324 c = *cp++;
325 do {
a943feed 326 if (c & 0200)
a73d974c 327 fprintf(file," %d", n);
a943feed 328 c <<= 1;
0d22afd1
RC
329 } while (++n & 07);
330 }
a73d974c 331 putc('\n',file);
0d22afd1
RC
332 break;
333
3bf25746 334#ifdef ALLOW_T_UNSPEC
1e12917d
KB
335 case T_UNSPEC:
336 {
337 int NumBytes = 8;
338 char *DataPtr;
339 int i;
3bf25746 340
1e12917d
KB
341 if (dlen < NumBytes) NumBytes = dlen;
342 fprintf(file, "\tFirst %d bytes of hex data:",
343 NumBytes);
344 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
345 fprintf(file, " %x", *DataPtr);
346 fputs("\n", file);
347 cp += dlen;
348 }
349 break;
350#endif /* ALLOW_T_UNSPEC */
3bf25746 351
0d22afd1 352 default:
a73d974c 353 fprintf(file,"\t???\n");
0d22afd1
RC
354 cp += dlen;
355 }
90e07ed6 356 if (cp != cp1 + dlen) {
a73d974c 357 fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen);
90e07ed6
JB
358 cp = NULL;
359 }
a73d974c 360 fprintf(file,"\n");
0d22afd1
RC
361 return (cp);
362}
363
7134abf2 364static char nbuf[40];
0d22afd1
RC
365
366/*
367 * Return a string for the type
368 */
369char *
370p_type(type)
371 int type;
372{
0d22afd1
RC
373 switch (type) {
374 case T_A:
375 return("A");
376 case T_NS: /* authoritative server */
377 return("NS");
0af159f3 378 case T_CNAME: /* canonical name */
0d22afd1
RC
379 return("CNAME");
380 case T_SOA: /* start of authority zone */
381 return("SOA");
382 case T_MB: /* mailbox domain name */
383 return("MB");
384 case T_MG: /* mail group member */
385 return("MG");
386 case T_MR: /* mail rename name */
387 return("MR");
388 case T_NULL: /* null resource record */
389 return("NULL");
390 case T_WKS: /* well known service */
391 return("WKS");
392 case T_PTR: /* domain name pointer */
393 return("PTR");
394 case T_HINFO: /* host information */
395 return("HINFO");
396 case T_MINFO: /* mailbox information */
397 return("MINFO");
606dc84e
JB
398 case T_MX: /* mail routing info */
399 return("MX");
400 case T_TXT: /* text */
401 return("TXT");
0d22afd1
RC
402 case T_AXFR: /* zone transfer */
403 return("AXFR");
404 case T_MAILB: /* mail box */
405 return("MAILB");
406 case T_MAILA: /* mail address */
407 return("MAILA");
408 case T_ANY: /* matches any type */
409 return("ANY");
410 case T_UINFO:
411 return("UINFO");
412 case T_UID:
413 return("UID");
414 case T_GID:
415 return("GID");
3bf25746 416#ifdef ALLOW_T_UNSPEC
1e12917d
KB
417 case T_UNSPEC:
418 return("UNSPEC");
419#endif /* ALLOW_T_UNSPEC */
0d22afd1 420 default:
06eef7c4
KB
421 (void)sprintf(nbuf, "%d", type);
422 return(nbuf);
0d22afd1
RC
423 }
424}
425
426/*
427 * Return a mnemonic for class
428 */
429char *
430p_class(class)
431 int class;
432{
433
434 switch (class) {
435 case C_IN: /* internet class */
436 return("IN");
0af159f3
JB
437 case C_HS: /* hesiod class */
438 return("HS");
0d22afd1
RC
439 case C_ANY: /* matches any class */
440 return("ANY");
441 default:
06eef7c4
KB
442 (void)sprintf(nbuf, "%d", class);
443 return(nbuf);
0d22afd1
RC
444 }
445}
7134abf2
MK
446
447/*
448 * Return a mnemonic for a time to live
449 */
0af159f3
JB
450char *
451p_time(value)
7134abf2
MK
452 u_long value;
453{
454 int secs, mins, hours;
455 register char *p;
456
457 secs = value % 60;
458 value /= 60;
459 mins = value % 60;
460 value /= 60;
461 hours = value % 24;
462 value /= 24;
463
464#define PLURALIZE(x) x, (x == 1) ? "" : "s"
465 p = nbuf;
466 if (value) {
467 (void)sprintf(p, "%d day%s", PLURALIZE(value));
468 while (*++p);
469 }
470 if (hours) {
0af159f3 471 if (value)
7134abf2
MK
472 *p++ = ' ';
473 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
474 while (*++p);
475 }
476 if (mins) {
0af159f3 477 if (value || hours)
7134abf2
MK
478 *p++ = ' ';
479 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
480 while (*++p);
481 }
0af159f3
JB
482 if (secs || ! (value || hours || mins)) {
483 if (value || hours || mins)
7134abf2
MK
484 *p++ = ' ';
485 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
7134abf2
MK
486 }
487 return(nbuf);
488}