2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.18 1999/05/27 05:35:07 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
40 #include "packet-dns.h"
44 /* DNS structs and definitions */
46 /* Offsets of fields in the DNS header. */
54 /* Length of DNS header. */
58 #define T_A 1 /* host address */
59 #define T_NS 2 /* authoritative name server */
60 #define T_MD 3 /* mail destination (obsolete) */
61 #define T_MF 4 /* mail forwarder (obsolete) */
62 #define T_CNAME 5 /* canonical name */
63 #define T_SOA 6 /* start of authority zone */
64 #define T_MB 7 /* mailbox domain name (experimental) */
65 #define T_MG 8 /* mail group member (experimental) */
66 #define T_MR 9 /* mail rename domain name (experimental) */
67 #define T_NULL 10 /* null RR (experimental) */
68 #define T_WKS 11 /* well known service */
69 #define T_PTR 12 /* domain name pointer */
70 #define T_HINFO 13 /* host information */
71 #define T_MINFO 14 /* mailbox or mail list information */
72 #define T_MX 15 /* mail routing information */
73 #define T_TXT 16 /* text strings */
74 #define T_RP 17 /* responsible person (RFC 1183) */
75 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
76 #define T_X25 19 /* X.25 address (RFC 1183) */
77 #define T_ISDN 20 /* ISDN address (RFC 1183) */
78 #define T_RT 21 /* route-through (RFC 1183) */
79 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
80 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
81 #define T_SIG 24 /* digital signature (RFC 2065) */
82 #define T_KEY 25 /* public key (RFC 2065) */
83 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
84 #define T_GPOS 27 /* geographical position (RFC 1712) */
85 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
86 #define T_LOC 29 /* geographical location (RFC 1876) */
87 #define T_NXT 30 /* "next" name (RFC 2065) */
88 #define T_EID 31 /* ??? (Nimrod?) */
89 #define T_NIMLOC 32 /* ??? (Nimrod?) */
90 #define T_SRV 33 /* service location (RFC 2052) */
91 #define T_ATMA 34 /* ??? */
92 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
94 /* Bit fields in the flags */
95 #define F_RESPONSE (1<<15) /* packet is response */
96 #define F_OPCODE (0xF<<11) /* query opcode */
97 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
98 #define F_TRUNCATED (1<<9) /* response is truncated */
99 #define F_RECDESIRED (1<<8) /* recursion desired */
100 #define F_RECAVAIL (1<<7) /* recursion available */
101 #define F_RCODE (0xF<<0) /* reply code */
104 #define OPCODE_QUERY (0<<11) /* standard query */
105 #define OPCODE_IQUERY (1<<11) /* inverse query */
106 #define OPCODE_STATUS (2<<11) /* server status request */
109 #define RCODE_NOERROR (0<<0)
110 #define RCODE_FMTERROR (1<<0)
111 #define RCODE_SERVFAIL (2<<0)
112 #define RCODE_NAMEERROR (3<<0)
113 #define RCODE_NOTIMPL (4<<0)
114 #define RCODE_REFUSED (5<<0)
116 /* See RFC 1035 for all RR types for which no RFC is listed. */
118 dns_type_name (int type)
120 char *type_names[36] = {
139 "AFSDB", /* RFC 1183 */
140 "X25", /* RFC 1183 */
141 "ISDN", /* RFC 1183 */
143 "NSAP", /* RFC 1706 */
144 "NSAP-PTR", /* RFC 1348 */
145 "SIG", /* RFC 2065 */
146 "KEY", /* RFC 2065 */
148 "GPOS", /* RFC 1712 */
149 "AAAA", /* RFC 1886 */
150 "LOC", /* RFC 1876 */
151 "NXT", /* RFC 2065 */
154 "SRV", /* RFC 2052 */
156 "NAPTR" /* RFC 2168 */
160 return type_names[type];
177 return "IXFR"; /* RFC 1995 */
193 dns_long_type_name (int type)
195 char *type_names[36] = {
198 "Authoritative name server",
201 "Canonical name for an alias",
202 "Start of zone of authority",
203 "Mailbox domain name",
205 "Mail rename domain name",
206 "Null resource record",
207 "Well-known service description",
208 "Domain name pointer",
210 "Mailbox or mail list information",
213 "Responsible person", /* RFC 1183 */
214 "AFS data base location", /* RFC 1183 */
215 "X.25 address", /* RFC 1183 */
216 "ISDN number", /* RFC 1183 */
217 "Route through", /* RFC 1183 */
218 "OSI NSAP", /* RFC 1706 */
219 "OSI NSAP name pointer", /* RFC 1348 */
220 "Signature", /* RFC 2065 */
221 "Public key", /* RFC 2065 */
222 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
223 "Geographical position", /* RFC 1712 */
224 "IPv6 address", /* RFC 1886 */
225 "Location", /* RFC 1876 */
226 "Next", /* RFC 2065 */
229 "Service location", /* RFC 2052 */
231 "Naming authority pointer" /* RFC 2168 */
233 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%d)" */
236 return type_names[type];
253 return "Request for incremental zone transfer"; /* RFC 1995 */
255 return "Request for full zone transfer";
257 return "Request for mailbox-related records";
259 return "Request for mail agent resource records";
261 return "Request for all records";
264 sprintf(unkbuf, "Unknown RR type (%d)", type);
270 dns_class_name(int class)
279 class_name = "chaos";
282 class_name = "hesiod";
285 class_name = "unknown";
292 get_dns_name(const u_char *dns_data_ptr, const u_char *dptr, char *name,
295 const u_char *dp = dptr;
301 maxname--; /* reserve space for the trailing '\0' */
302 while ((component_len = *dp++) != 0) {
303 switch (component_len & 0xc0) {
308 /* Not the first component - put in a '.'. */
314 while (component_len > 0) {
326 goto error; /* error */
330 /* XXX - check to make sure we aren't looping, by keeping track
331 of how many characters are in the DNS packet, and of how many
332 characters we've looked at, and quitting if the latter
333 becomes bigger than the former. */
334 offset = ((component_len & ~0xc0) << 8) | *dp++;
335 /* If "len" is negative, we are still working on the original name,
336 not something pointed to by a pointer, and so we should set "len"
337 to the length of the original name. */
340 dp = dns_data_ptr + offset;
341 break; /* now continue processing from there */
347 /* If "len" is negative, we haven't seen a pointer, and thus haven't
348 set the length, so set it. */
351 /* Zero-length name means "root server" */
353 strcpy(name, "<Root>");
359 get_dns_name_type_class (const u_char *dns_data_ptr,
371 const u_char *dptr_save;
373 name_len = get_dns_name(dns_data_ptr, dptr, name, sizeof(name));
379 class = pntohs(dptr);
382 strcpy (name_ret, name);
385 *name_len_ret = name_len;
387 len = dptr - dptr_save;
393 dissect_dns_query(const u_char *dns_data_ptr, const u_char *pd, int offset,
394 proto_tree *dns_tree)
403 char *long_type_name;
405 const u_char *data_start;
409 data_start = dptr = pd + offset;
411 len = get_dns_name_type_class(dns_data_ptr, dptr, name, &name_len,
415 type_name = dns_type_name(type);
416 class_name = dns_class_name(class);
417 long_type_name = dns_long_type_name(type);
419 tq = proto_tree_add_item(dns_tree, offset, len, "%s: type %s, class %s",
420 name, type_name, class_name);
421 q_tree = proto_tree_new();
422 proto_item_add_subtree(tq, q_tree, ETT_DNS_QD);
424 proto_tree_add_item(q_tree, offset, name_len, "Name: %s", name);
427 proto_tree_add_item(q_tree, offset, 2, "Type: %s", long_type_name);
430 proto_tree_add_item(q_tree, offset, 2, "Class: %s", class_name);
433 return dptr - data_start;
438 add_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
439 int namelen, const char *type_name, const char *class_name, u_int ttl,
444 rr_tree = proto_tree_new();
445 proto_item_add_subtree(trr, rr_tree, rr_type);
446 proto_tree_add_item(rr_tree, offset, namelen, "Name: %s", name);
448 proto_tree_add_item(rr_tree, offset, 2, "Type: %s", type_name);
450 proto_tree_add_item(rr_tree, offset, 2, "Class: %s", class_name);
452 proto_tree_add_item(rr_tree, offset, 4, "Time to live: %s",
453 time_secs_to_str(ttl));
455 proto_tree_add_item(rr_tree, offset, 2, "Data length: %u", data_len);
460 dissect_dns_answer(const u_char *dns_data_ptr, const u_char *pd, int offset,
461 proto_tree *dns_tree)
470 char *long_type_name;
472 const u_char *data_start;
479 data_start = dptr = pd + offset;
481 len = get_dns_name_type_class(dns_data_ptr, dptr, name, &name_len,
485 type_name = dns_type_name(type);
486 class_name = dns_class_name(class);
487 long_type_name = dns_long_type_name(type);
492 data_len = pntohs(dptr);
497 trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
498 "%s: type %s, class %s, addr %s",
499 name, type_name, class_name,
500 ip_to_str((guint8 *)dptr));
501 rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
502 long_type_name, class_name, ttl, data_len);
503 offset += (dptr - data_start);
504 proto_tree_add_item(rr_tree, offset, 4, "Addr: %s",
505 ip_to_str((guint8 *)dptr));
510 char ns_name[MAXDNAME];
513 ns_name_len = get_dns_name(dns_data_ptr, dptr, ns_name, sizeof(ns_name));
514 trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
515 "%s: type %s, class %s, ns %s",
516 name, type_name, class_name, ns_name);
517 rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
518 long_type_name, class_name, ttl, data_len);
519 offset += (dptr - data_start);
520 proto_tree_add_item(rr_tree, offset, ns_name_len, "Name server: %s", ns_name);
526 char cname[MAXDNAME];
529 cname_len = get_dns_name(dns_data_ptr, dptr, cname, sizeof(cname));
530 trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
531 "%s: type %s, class %s, cname %s",
532 name, type_name, class_name, cname);
533 rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
534 long_type_name, class_name, ttl, data_len);
535 offset += (dptr - data_start);
536 proto_tree_add_item(rr_tree, offset, cname_len, "Primary name: %s", cname);
542 char mname[MAXDNAME];
544 char rname[MAXDNAME];
553 mname_len = get_dns_name(dns_data_ptr, rrptr, mname, sizeof(mname));
555 trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
556 "%s: type %s, class %s, mname %s",
557 name, type_name, class_name, mname);
558 rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
559 long_type_name, class_name, ttl, data_len);
560 offset += (dptr - data_start);
561 proto_tree_add_item(rr_tree, offset, mname_len, "Primary name server: %s",
564 rname_len = get_dns_name(dns_data_ptr, rrptr, rname, sizeof(rname));
565 proto_tree_add_item(rr_tree, offset, rname_len, "Responsible authority's mailbox: %s",
569 serial = pntohl(rrptr);
570 proto_tree_add_item(rr_tree, offset, 4, "Serial number: %u",
574 refresh = pntohl(rrptr);
575 proto_tree_add_item(rr_tree, offset, 4, "Refresh interval: %s",
576 time_secs_to_str(refresh));
579 retry = pntohl(rrptr);
580 proto_tree_add_item(rr_tree, offset, 4, "Retry interval: %s",
581 time_secs_to_str(retry));
584 expire = pntohl(rrptr);
585 proto_tree_add_item(rr_tree, offset, 4, "Expiration limit: %s",
586 time_secs_to_str(expire));
589 minimum = pntohl(rrptr);
590 proto_tree_add_item(rr_tree, offset, 4, "Minimum TTL: %s",
591 time_secs_to_str(minimum));
597 char pname[MAXDNAME];
600 pname_len = get_dns_name(dns_data_ptr, dptr, pname, sizeof(pname));
601 trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
602 "%s: type %s, class %s, ptr %s",
603 name, type_name, class_name, pname);
604 rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
605 long_type_name, class_name, ttl, data_len);
606 offset += (dptr - data_start);
607 proto_tree_add_item(rr_tree, offset, pname_len, "Domain name: %s", pname);
612 /* TODO: parse more record types */
615 trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
616 "%s: type %s, class %s",
617 name, type_name, class_name);
618 rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
619 long_type_name, class_name, ttl, data_len);
620 offset += (dptr - data_start);
621 proto_tree_add_item(rr_tree, offset, data_len, "Data");
626 return dptr - data_start;
630 dissect_query_records(const u_char *dns_data_ptr, int count, const u_char *pd,
631 int cur_off, proto_tree *dns_tree)
638 ti = proto_tree_add_item(dns_tree, start_off, 0, "Queries");
639 qatree = proto_tree_new();
640 proto_item_add_subtree(ti, qatree, ETT_DNS_QRY);
642 cur_off += dissect_dns_query(dns_data_ptr, pd, cur_off, qatree);
643 proto_item_set_len(ti, cur_off - start_off);
645 return cur_off - start_off;
651 dissect_answer_records(const u_char *dns_data_ptr, int count,
652 const u_char *pd, int cur_off, proto_tree *dns_tree,
660 ti = proto_tree_add_item(dns_tree, start_off, 0, name);
661 qatree = proto_tree_new();
662 proto_item_add_subtree(ti, qatree, ETT_DNS_ANS);
664 cur_off += dissect_dns_answer(dns_data_ptr, pd, cur_off, qatree);
665 proto_item_set_len(ti, cur_off - start_off);
667 return cur_off - start_off;
672 dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
673 const u_char *dns_data_ptr;
674 proto_tree *dns_tree, *field_tree;
676 guint16 id, flags, quest, ans, auth, add;
679 static const value_string opcode_vals[] = {
680 { OPCODE_QUERY, "Standard query" },
681 { OPCODE_IQUERY, "Inverse query" },
682 { OPCODE_STATUS, "Server status request" },
684 static const value_string rcode_vals[] = {
685 { RCODE_NOERROR, "No error" },
686 { RCODE_FMTERROR, "Format error" },
687 { RCODE_SERVFAIL, "Server failure" },
688 { RCODE_NAMEERROR, "Name error" },
689 { RCODE_NOTIMPL, "Not implemented" },
690 { RCODE_REFUSED, "Refused" },
693 dns_data_ptr = &pd[offset];
695 /* To do: check for runts, errs, etc. */
696 id = pntohs(&pd[offset + DNS_ID]);
697 flags = pntohs(&pd[offset + DNS_FLAGS]);
698 quest = pntohs(&pd[offset + DNS_QUEST]);
699 ans = pntohs(&pd[offset + DNS_ANS]);
700 auth = pntohs(&pd[offset + DNS_AUTH]);
701 add = pntohs(&pd[offset + DNS_ADD]);
703 if (check_col(fd, COL_PROTOCOL))
704 col_add_str(fd, COL_PROTOCOL, "DNS (UDP)");
705 if (check_col(fd, COL_INFO)) {
706 col_add_fstr(fd, COL_INFO, "%s%s",
707 val_to_str(flags & F_OPCODE, opcode_vals,
708 "Unknown operation (%x)"),
709 (flags & F_RESPONSE) ? " response" : "");
713 ti = proto_tree_add_item(tree, offset, 4,
714 (flags & F_RESPONSE) ? "DNS response" : "DNS query");
716 dns_tree = proto_tree_new();
717 proto_item_add_subtree(ti, dns_tree, ETT_DNS);
719 proto_tree_add_item(dns_tree, offset + DNS_ID, 2, "Transaction ID: 0x%04x",
722 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
723 if (flags & F_RESPONSE) {
724 strcat(buf, " response");
726 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
729 tf = proto_tree_add_item(dns_tree, offset + DNS_FLAGS, 2, "Flags: 0x%04x (%s)",
731 field_tree = proto_tree_new();
732 proto_item_add_subtree(tf, field_tree, ETT_DNS_FLAGS);
733 proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
734 decode_boolean_bitfield(flags, F_RESPONSE,
735 2*8, "Response", "Query"));
736 proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
737 decode_enumerated_bitfield(flags, F_OPCODE,
738 2*8, opcode_vals, "%s"));
739 if (flags & F_RESPONSE) {
740 proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
741 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
743 "Server is an authority for domain",
744 "Server isn't an authority for domain"));
746 proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
747 decode_boolean_bitfield(flags, F_TRUNCATED,
749 "Message is truncated",
750 "Message is not truncated"));
751 proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
752 decode_boolean_bitfield(flags, F_RECDESIRED,
754 "Do query recursively",
755 "Don't do query recursively"));
756 if (flags & F_RESPONSE) {
757 proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
758 decode_boolean_bitfield(flags, F_RECAVAIL,
760 "Server can do recursive queries",
761 "Server can't do recursive queries"));
762 proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
763 decode_enumerated_bitfield(flags, F_RCODE,
764 2*8, rcode_vals, "%s"));
766 proto_tree_add_item(dns_tree, offset + DNS_QUEST, 2, "Questions: %d", quest);
767 proto_tree_add_item(dns_tree, offset + DNS_ANS, 2, "Answer RRs: %d", ans);
768 proto_tree_add_item(dns_tree, offset + DNS_AUTH, 2, "Authority RRs: %d", auth);
769 proto_tree_add_item(dns_tree, offset + DNS_ADD, 2, "Additional RRs: %d", add);
771 cur_off = offset + DNS_HDRLEN;
774 cur_off += dissect_query_records(dns_data_ptr, quest, pd, cur_off,
778 cur_off += dissect_answer_records(dns_data_ptr, ans, pd, cur_off,
779 dns_tree, "Answers");
782 cur_off += dissect_answer_records(dns_data_ptr, auth, pd, cur_off,
783 dns_tree, "Authoritative nameservers");
786 cur_off += dissect_answer_records(dns_data_ptr, add, pd, cur_off,
787 dns_tree, "Additional records");