]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - testcode/pktview.c
Apply upstream fix 08968baec1122a58bb90d8f97ad948a75f8a5d69:
[FreeBSD/FreeBSD.git] / testcode / pktview.c
1 /*
2  * testcode/pktview.c - debug program to disassemble a DNS packet.
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * 
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  * 
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  * 
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 /**
37  * \file
38  *
39  * This program shows a dns packet wire format.
40  */
41
42 #include "config.h"
43 #include "util/log.h"
44 #include "util/data/dname.h"
45 #include "util/data/msgparse.h"
46 #include "testcode/unitmain.h"
47 #include "testcode/readhex.h"
48 #include "sldns/sbuffer.h"
49 #include "sldns/parseutil.h"
50
51 /** usage information for pktview */
52 static void usage(char* argv[])
53 {
54         printf("usage: %s\n", argv[0]);
55         printf("present hex packet on stdin.\n");
56         exit(1);
57 }
58
59 /** read hex input */
60 static void read_input(sldns_buffer* pkt, FILE* in)
61 {
62         char buf[102400];
63         char* np = buf;
64         while(fgets(np, (int)sizeof(buf) - (np-buf), in)) {
65                 if(buf[0] == ';') /* comment */
66                         continue;
67                 np = &np[strlen(np)];
68         }
69         hex_to_buf(pkt, buf);
70 }
71
72 /** analyze domain name in packet, possibly compressed */
73 static void analyze_dname(sldns_buffer* pkt)
74 {
75         size_t oldpos = sldns_buffer_position(pkt);
76         size_t len;
77         printf("[pos %d] dname: ", (int)oldpos);
78         dname_print(stdout, pkt, sldns_buffer_current(pkt));
79         len = pkt_dname_len(pkt);
80         printf(" len=%d", (int)len);
81         if(sldns_buffer_position(pkt)-oldpos != len)
82                 printf(" comprlen=%d\n", 
83                         (int)(sldns_buffer_position(pkt)-oldpos));
84         else    printf("\n");
85 }
86
87 /** analyze rdata in packet */
88 static void analyze_rdata(sldns_buffer*pkt, const sldns_rr_descriptor* desc, 
89         uint16_t rdlen)
90 {
91         int rdf = 0;
92         int count = (int)desc->_dname_count;
93         size_t len, oldpos;
94         while(rdlen > 0 && count) {
95                 switch(desc->_wireformat[rdf]) {
96                 case LDNS_RDF_TYPE_DNAME:
97                         oldpos = sldns_buffer_position(pkt);
98                         analyze_dname(pkt);
99                         rdlen -= sldns_buffer_position(pkt)-oldpos;
100                         count --;
101                         len = 0;
102                         break;
103                 case LDNS_RDF_TYPE_STR:
104                         len = sldns_buffer_current(pkt)[0] + 1;
105                         break;
106                 default:
107                         len = get_rdf_size(desc->_wireformat[rdf]);
108                 }
109                 if(len) {
110                         printf(" wf[%d]", (int)len);
111                         sldns_buffer_skip(pkt, (ssize_t)len);
112                         rdlen -= len;
113                 }
114                 rdf++;
115         }
116         if(rdlen) {
117                 size_t i;
118                 printf(" remain[%d]\n", (int)rdlen);
119                 for(i=0; i<rdlen; i++)
120                         printf(" %2.2X", (unsigned)sldns_buffer_current(pkt)[i]);
121                 printf("\n");
122         }
123         else    printf("\n");
124         sldns_buffer_skip(pkt, (ssize_t)rdlen);
125 }
126
127 /** analyze rr in packet */
128 static void analyze_rr(sldns_buffer* pkt, int q)
129 {
130         uint16_t type, dclass, len;
131         uint32_t ttl;
132         analyze_dname(pkt);
133         type = sldns_buffer_read_u16(pkt);
134         dclass = sldns_buffer_read_u16(pkt);
135         printf("type %s(%d)", sldns_rr_descript(type)?  
136                 sldns_rr_descript(type)->_name: "??" , (int)type);
137         printf(" class %s(%d) ", sldns_lookup_by_id(sldns_rr_classes, 
138                 (int)dclass)?sldns_lookup_by_id(sldns_rr_classes, 
139                 (int)dclass)->name:"??", (int)dclass);
140         if(q) {
141                 printf("\n");
142         } else {
143                 ttl = sldns_buffer_read_u32(pkt);
144                 printf(" ttl %d (0x%x)", (int)ttl, (unsigned)ttl);
145                 len = sldns_buffer_read_u16(pkt);
146                 printf(" rdata len %d:\n", (int)len);
147                 if(sldns_rr_descript(type))
148                         analyze_rdata(pkt, sldns_rr_descript(type), len);
149                 else sldns_buffer_skip(pkt, (ssize_t)len);
150         }
151 }
152
153 /** analyse pkt */
154 static void analyze(sldns_buffer* pkt)
155 {
156         uint16_t i, f, qd, an, ns, ar;
157         int rrnum = 0;
158         printf("packet length %d\n", (int)sldns_buffer_limit(pkt));
159         if(sldns_buffer_limit(pkt) < 12) return;
160
161         i = sldns_buffer_read_u16(pkt);
162         printf("id (hostorder): %d (0x%x)\n", (int)i, (unsigned)i);
163         f = sldns_buffer_read_u16(pkt);
164         printf("flags: 0x%x\n", (unsigned)f);
165         qd = sldns_buffer_read_u16(pkt);
166         printf("qdcount: %d\n", (int)qd);
167         an = sldns_buffer_read_u16(pkt);
168         printf("ancount: %d\n", (int)an);
169         ns = sldns_buffer_read_u16(pkt);
170         printf("nscount: %d\n", (int)ns);
171         ar = sldns_buffer_read_u16(pkt);
172         printf("arcount: %d\n", (int)ar);
173         
174         printf(";-- query section\n");
175         while(sldns_buffer_remaining(pkt) > 0) {
176                 if(rrnum == (int)qd) 
177                         printf(";-- answer section\n");
178                 if(rrnum == (int)qd+(int)an) 
179                         printf(";-- authority section\n");
180                 if(rrnum == (int)qd+(int)an+(int)ns) 
181                         printf(";-- additional section\n");
182                 printf("rr %d ", rrnum);
183                 analyze_rr(pkt, rrnum < (int)qd);
184                 rrnum++;
185         }
186 }
187
188 /** main program for pktview */
189 int main(int argc, char* argv[]) 
190 {
191         sldns_buffer* pkt = sldns_buffer_new(65553);
192         if(argc != 1) {
193                 usage(argv);
194         }
195         if(!pkt) fatal_exit("out of memory");
196
197         read_input(pkt, stdin);
198         analyze(pkt);
199
200         sldns_buffer_free(pkt);
201         return 0;
202 }