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