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 } 203