1 /****************************************************************************
2 ** File: dns.c
3 **
4 ** Author: Mike Borella
5 **
6 ** Comments: Dump DNS header information
7 **
8 ** $Id: dns.c,v 1.21 2002/01/03 00:04:01 mborella Exp $
9 **
10 ** This program is free software; you can redistribute it and/or modify
11 ** it under the terms of the GNU General Public License as published by
12 ** the Free Software Foundation; either version 2 of the License, or
13 ** (at your option) any later version.
14 **
15 ** This program is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ** GNU Library General Public License for more details.
19 **
20 ** You should have received a copy of the GNU General Public License
21 ** along with this program; if not, write to the Free Software
22 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 **
24 *****************************************************************************/
25
26 #include "dns.h"
27 #include "ns_labels.h"
28
29 #define HOLDER_SIZE 256
30
31 /*
32 * QR flag map
33 */
34
35 strmap_t dns_qrflag_map [] =
36 {
37 { DNS_QRFLAG_QUERY, "query" },
38 { DNS_QRFLAG_RESPONSE, "response" },
39 { 0, "" }
40 };
41
42 /*
43 * Opcode flag map
44 */
45
46 strmap_t dns_opcodeflag_map [] =
47 {
48 { DNS_OPCODEFLAG_STANDARD, "standard" },
49 { DNS_OPCODEFLAG_INVERSE, "inverse" },
50 { DNS_OPCODEFLAG_STATUS, "status" },
51 { 0, "" }
52 };
53
54
55 /*
56 * Rcode (return code) flag map
57 */
58
59 strmap_t dns_rcodeflag_map [] =
60 {
61 { DNS_RCODEFLAG_NOERROR, "no error" },
62 { DNS_RCODEFLAG_FORMATERROR, "format error" },
63 { DNS_RCODEFLAG_SERVERERROR, "server error" },
64 { DNS_RCODEFLAG_NAMEERROR, "name error" },
65 { DNS_RCODEFLAG_NOTIMPLEMENTED, "not implemented" },
66 { DNS_RCODEFLAG_SERVICEREFUSED, "service refused" },
67 { 0, "" }
68 };
69
70 /*
71 * Query type map
72 */
73
74 strmap_t dns_querytype_map [] =
75 {
76 { DNS_QUERYTYPE_A, "A - IP address" },
77 { DNS_QUERYTYPE_NS, "NS - name server" },
78 { DNS_QUERYTYPE_CNAME, "CNAME - canonical name" },
79 { DNS_QUERYTYPE_SOA, "SOA - start of auth record" },
80 { DNS_QUERYTYPE_PTR, "PTR - pointer record" },
81 { DNS_QUERYTYPE_HINFO, "HINFO - host info" },
82 { DNS_QUERYTYPE_MX, "MX - mail exchange record" },
83 { DNS_QUERYTYPE_AAAA, "AAAA - IPv6 address" },
84 { DNS_QUERYTYPE_AXFR, "AXFR - zone transfer request" },
85 { DNS_QUERYTYPE_ANY, "ANY - all records request" },
86 { 0, "" }
87 };
88
89 /*
90 * Query class map
91 */
92
93 strmap_t dns_queryclass_map [] =
94 {
95 { DNS_QUERYCLASS_IP, "Internet" },
96 { 0, "" }
97 };
98
99 extern struct arg_t *my_args;
100
101 /*----------------------------------------------------------------------------
102 **
103 ** dump_dns_questions()
104 **
105 ** Parse DNS questions and display them
106 **
107 **----------------------------------------------------------------------------
108 */
109
dump_dns_questions(packet_t * pkt,u_int8_t num)110 void dump_dns_questions(packet_t *pkt, u_int8_t num)
111 {
112 char holder[HOLDER_SIZE];
113 u_int16_t query_type, query_class;
114
115 while(num > 0)
116 {
117 /*
118 * Parse the name
119 */
120
121 parse_ns_labels(pkt, holder);
122
123 /*
124 * Parse the query type and class
125 */
126
127 if (get_packet_bytes((u_int8_t *) &query_type, pkt, 2) == 0)
128 return;
129 if (get_packet_bytes((u_int8_t *) &query_class, pkt, 2) == 0)
130 return;
131
132 /*
133 * Conversions
134 */
135
136 query_type = ntohs(query_type);
137 query_class = ntohs(query_class);
138
139 /*
140 * Dump the info
141 */
142
143 if (my_args->m)
144 {
145 display_minimal_string(holder);
146 display_minimal_string(" ");
147 }
148 else
149 {
150 display_string("Query", holder);
151 snprintf(holder, HOLDER_SIZE, "%d (%s)", query_type,
152 map2str(dns_querytype_map, query_type));
153 display_string(" Query type", holder);
154 snprintf(holder, HOLDER_SIZE, "%d (%s)", query_class,
155 map2str(dns_queryclass_map, query_class));
156 display_string(" Query class", holder);
157 }
158
159 num --;
160 }
161 }
162
163 /*----------------------------------------------------------------------------
164 **
165 ** dump_dns_answers()
166 **
167 ** Parse DNS answers and display them
168 **
169 **----------------------------------------------------------------------------
170 */
dump_dns_answers(packet_t * pkt,u_int8_t num,char * answer_type)171 void dump_dns_answers(packet_t *pkt, u_int8_t num, char *answer_type)
172 {
173 char holder[HOLDER_SIZE];
174 u_int16_t query_type, query_class;
175 u_int32_t ttl;
176 u_int16_t rdl;
177 u_int8_t resource_data[64];
178
179 while(num > 0)
180 {
181 /*
182 * Parse the name
183 */
184
185 parse_ns_labels(pkt, holder);
186
187 /*
188 * Parse the query type and class
189 */
190
191 if (get_packet_bytes((u_int8_t *) &query_type, pkt, 2) == 0)
192 return;
193 if (get_packet_bytes((u_int8_t *) &query_class, pkt, 2) == 0)
194 return;
195 if (get_packet_bytes((u_int8_t *) &ttl, pkt, 4) == 0)
196 return;
197 if (get_packet_bytes((u_int8_t *) &rdl, pkt, 2) == 0)
198 return;
199
200 /*
201 * Conversions
202 */
203
204 query_type = ntohs(query_type);
205 query_class = ntohs(query_class);
206 ttl = ntohl(ttl);
207 rdl = ntohs(rdl);
208
209 /*
210 * Get the resource data
211 */
212
213 switch (query_type)
214 {
215 case DNS_QUERYTYPE_NS:
216 case DNS_QUERYTYPE_CNAME:
217 case DNS_QUERYTYPE_SOA:
218 case DNS_QUERYTYPE_PTR:
219 parse_ns_labels(pkt, resource_data);
220 break;
221
222 case DNS_QUERYTYPE_A:
223 default:
224 if (get_packet_bytes((u_int8_t *) &resource_data, pkt,
225 rdl) == 0)
226 return;
227 break;
228
229 }
230
231 /*
232 * Dump the info
233 */
234
235 if (my_args->m)
236 {
237 if (query_type == DNS_QUERYTYPE_A && !strcmp(answer_type, "Answers"))
238 {
239 display_minimal_ipv4((u_int8_t *) resource_data);
240 display_minimal_string(" ");
241 }
242 if (query_type == DNS_QUERYTYPE_AAAA &&
243 !strcmp(answer_type, "Answers") && rdl == 16 )
244 {
245 display_minimal_ipv6((u_int8_t *) resource_data);
246 display_minimal_string(" ");
247 }
248 }
249 else
250 {
251 display_string(answer_type, holder);
252 snprintf(holder, HOLDER_SIZE, "%d (%s)", query_type,
253 map2str(dns_querytype_map, query_type));
254 display_string(" Query type", holder);
255 snprintf(holder, HOLDER_SIZE, "%d (%s)", query_class,
256 map2str(dns_queryclass_map, query_class));
257 display_string(" Query class", holder);
258 display(" TTL", (u_int8_t *) &ttl, 4, DISP_DEC);
259 display(" Resource data length", (u_int8_t *) &rdl, 2,
260 DISP_DEC);
261 switch(query_type)
262 {
263 case DNS_QUERYTYPE_A:
264 display_ipv4(" Resource data", (u_int8_t *) resource_data);
265 break;
266
267 case DNS_QUERYTYPE_AAAA:
268 display_ipv6(" Resource data", (u_int8_t *) resource_data);
269 break;
270
271 case DNS_QUERYTYPE_NS:
272 case DNS_QUERYTYPE_CNAME:
273 case DNS_QUERYTYPE_SOA:
274 case DNS_QUERYTYPE_PTR:
275 display_string(" Resource data", resource_data);
276 break;
277
278 default:
279 display(" Resource data", (u_int8_t *) resource_data, rdl,
280 DISP_HEX);
281 }
282 }
283
284 num --;
285 }
286
287 }
288
289 /*----------------------------------------------------------------------------
290 **
291 ** dump_dns()
292 **
293 ** Parse DNS packet and dump fields
294 **
295 **----------------------------------------------------------------------------
296 */
297
dump_dns(packet_t * pkt)298 void dump_dns(packet_t *pkt)
299 {
300 dns_header_t dns;
301 u_int8_t f_qr, f_opcode, f_aa, f_tc, f_rd, f_ra, f_zero, f_rcode;
302 char holder[HOLDER_SIZE];
303
304 /* Set the layer */
305 set_layer(LAYER_APPLICATION);
306
307 /*
308 * Mark the beginning of the DNS portion so that labels can be stored
309 * properly
310 */
311
312 set_packet_mark(pkt);
313
314 /*
315 * Reset the DNS labels structures for a new DNS packet
316 */
317
318 reset_nslabels();
319
320 /*
321 * Get the header
322 */
323
324 if (get_packet_bytes((u_int8_t *) &dns, pkt, 12) == 0)
325 return;
326
327 /*
328 * Conversions
329 */
330
331 dns.id = ntohs(dns.id);
332 dns.number_questions = ntohs(dns.number_questions);
333 dns.number_answers = ntohs(dns.number_answers);
334 dns.number_authority = ntohs(dns.number_authority);
335 dns.number_additional = ntohs(dns.number_additional);
336 f_qr = dns.flag_qr;
337 f_opcode = dns.flag_opcode;
338 f_aa = dns.flag_aa;
339 f_tc = dns.flag_tc;
340 f_rd = dns.flag_rd;
341 f_ra = dns.flag_ra;
342 f_zero = dns.flag_zero;
343 f_rcode = dns.flag_rcode;
344
345 /*
346 * Print it
347 */
348
349 if (my_args->m)
350 {
351 display_minimal_string("| DNS ");
352 display_minimal_string(map2str(dns_qrflag_map, f_qr));
353 display_minimal_string(" ");
354 }
355 else
356 {
357 /* announcement */
358 display_header_banner("DNS Header");
359
360 /* identification */
361 display("Identification", (u_int8_t *) &dns.id, 2, DISP_DEC);
362
363 /* flags */
364 snprintf(holder, HOLDER_SIZE, "%d (%s)", f_qr,
365 map2str(dns_qrflag_map, f_qr));
366 display_string("Flag query/response", holder);
367 snprintf(holder, HOLDER_SIZE, "%d (%s)", f_opcode,
368 map2str(dns_opcodeflag_map, f_opcode));
369 display_string("Flag opcode", holder);
370 display("Flag auth answer", (u_int8_t *) &f_aa, 1, DISP_BINNLZ);
371 display("Flag trunctated", (u_int8_t *) &f_tc, 1, DISP_BINNLZ);
372 display("Flag recursion desired", (u_int8_t *) &f_ra, 1, DISP_BINNLZ);
373 display("Flag recursion available", (u_int8_t *) &f_ra, 1, DISP_BINNLZ);
374 display("Flag zero", (u_int8_t *) &f_zero, 1, DISP_BINNLZ);
375 snprintf(holder, HOLDER_SIZE, "%d (%s)", f_rcode,
376 map2str(dns_rcodeflag_map, f_rcode));
377 display_string("Flag return code", holder);
378
379 /* numbers of questions and answers */
380 display("# of questions", (u_int8_t *) &dns.number_questions, 2,
381 DISP_DEC);
382 display("# of answers", (u_int8_t *) &dns.number_answers, 2,
383 DISP_DEC);
384 display("# of authorization RRs", (u_int8_t *) &dns.number_authority, 2,
385 DISP_DEC);
386 display("# of additional RRs", (u_int8_t *) &dns.number_additional, 2,
387 DISP_DEC);
388 }
389
390 /*
391 * Parse the question and answers
392 */
393
394 dump_dns_questions(pkt, dns.number_questions);
395 dump_dns_answers(pkt, dns.number_answers, "Answers");
396 dump_dns_answers(pkt, dns.number_authority, "Auth answers");
397 dump_dns_answers(pkt, dns.number_additional, "Addtl answers");
398
399 /* dump the hex buffer */
400 hexbuffer_flush();
401
402 }
403
404
405
406
407
408