release
[hcoop/zz_old/debian/djbdns.git] / printpacket.c
1 #include "uint16.h"
2 #include "uint32.h"
3 #include "error.h"
4 #include "byte.h"
5 #include "dns.h"
6 #include "printrecord.h"
7 #include "printpacket.h"
8
9 static char *d;
10
11 #define X(s) if (!stralloc_cats(out,s)) return 0;
12 #define NUM(u) if (!stralloc_catulong0(out,u,0)) return 0;
13
14 unsigned int printpacket_cat(stralloc *out,char *buf,unsigned int len)
15 {
16 uint16 numqueries;
17 uint16 numanswers;
18 uint16 numauthority;
19 uint16 numglue;
20 unsigned int pos;
21 char data[12];
22 uint16 type;
23
24 pos = dns_packet_copy(buf,len,0,data,12); if (!pos) return 0;
25
26 uint16_unpack_big(data + 4,&numqueries);
27 uint16_unpack_big(data + 6,&numanswers);
28 uint16_unpack_big(data + 8,&numauthority);
29 uint16_unpack_big(data + 10,&numglue);
30
31 NUM(len)
32 X(" bytes, ")
33 NUM(numqueries)
34 X("+")
35 NUM(numanswers)
36 X("+")
37 NUM(numauthority)
38 X("+")
39 NUM(numglue)
40 X(" records")
41
42 if (data[2] & 128) X(", response")
43 if (data[2] & 120) X(", weird op")
44 if (data[2] & 4) X(", authoritative")
45 if (data[2] & 2) X(", truncated")
46 if (data[2] & 1) X(", weird rd")
47 if (data[3] & 128) X(", weird ra")
48 switch(data[3] & 15) {
49 case 0: X(", noerror"); break;
50 case 3: X(", nxdomain"); break;
51 case 4: X(", notimp"); break;
52 case 5: X(", refused"); break;
53 default: X(", weird rcode");
54 }
55 if (data[3] & 112) X(", weird z")
56
57 X("\n")
58
59 while (numqueries) {
60 --numqueries;
61 X("query: ")
62
63 pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
64 pos = dns_packet_copy(buf,len,pos,data,4); if (!pos) return 0;
65
66 if (byte_diff(data + 2,2,DNS_C_IN)) {
67 X("weird class")
68 }
69 else {
70 uint16_unpack_big(data,&type);
71 NUM(type)
72 X(" ")
73 if (!dns_domain_todot_cat(out,d)) return 0;
74 }
75 X("\n")
76 }
77
78 for (;;) {
79 if (numanswers) { --numanswers; X("answer: ") }
80 else if (numauthority) { --numauthority; X("authority: ") }
81 else if (numglue) { --numglue; X("additional: ") }
82 else break;
83
84 pos = printrecord_cat(out,buf,len,pos,0,0);
85 if (!pos) return 0;
86 }
87
88 if (pos != len) { errno = error_proto; return 0; }
89 return 1;
90 }