2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.33 1999/12/29 10:36:13 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"
43 static int proto_dns = -1;
44 static int hf_dns_response = -1;
45 static int hf_dns_query = -1;
46 static int hf_dns_flags = -1;
47 static int hf_dns_transaction_id = -1;
48 static int hf_dns_count_questions = -1;
49 static int hf_dns_count_answers = -1;
50 static int hf_dns_count_auth_rr = -1;
51 static int hf_dns_count_add_rr = -1;
53 static gint ett_dns = -1;
54 static gint ett_dns_qd = -1;
55 static gint ett_dns_rr = -1;
56 static gint ett_dns_qry = -1;
57 static gint ett_dns_ans = -1;
58 static gint ett_dns_flags = -1;
59 static gint ett_t_key_flags = -1;
61 /* DNS structs and definitions */
63 /* Offsets of fields in the DNS header. */
71 /* Length of DNS header. */
75 #define T_A 1 /* host address */
76 #define T_NS 2 /* authoritative name server */
77 #define T_MD 3 /* mail destination (obsolete) */
78 #define T_MF 4 /* mail forwarder (obsolete) */
79 #define T_CNAME 5 /* canonical name */
80 #define T_SOA 6 /* start of authority zone */
81 #define T_MB 7 /* mailbox domain name (experimental) */
82 #define T_MG 8 /* mail group member (experimental) */
83 #define T_MR 9 /* mail rename domain name (experimental) */
84 #define T_NULL 10 /* null RR (experimental) */
85 #define T_WKS 11 /* well known service */
86 #define T_PTR 12 /* domain name pointer */
87 #define T_HINFO 13 /* host information */
88 #define T_MINFO 14 /* mailbox or mail list information */
89 #define T_MX 15 /* mail routing information */
90 #define T_TXT 16 /* text strings */
91 #define T_RP 17 /* responsible person (RFC 1183) */
92 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
93 #define T_X25 19 /* X.25 address (RFC 1183) */
94 #define T_ISDN 20 /* ISDN address (RFC 1183) */
95 #define T_RT 21 /* route-through (RFC 1183) */
96 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
97 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
98 #define T_SIG 24 /* digital signature (RFC 2065) */
99 #define T_KEY 25 /* public key (RFC 2065) */
100 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
101 #define T_GPOS 27 /* geographical position (RFC 1712) */
102 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
103 #define T_LOC 29 /* geographical location (RFC 1876) */
104 #define T_NXT 30 /* "next" name (RFC 2065) */
105 #define T_EID 31 /* ??? (Nimrod?) */
106 #define T_NIMLOC 32 /* ??? (Nimrod?) */
107 #define T_SRV 33 /* service location (RFC 2052) */
108 #define T_ATMA 34 /* ??? */
109 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
111 /* Bit fields in the flags */
112 #define F_RESPONSE (1<<15) /* packet is response */
113 #define F_OPCODE (0xF<<11) /* query opcode */
114 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
115 #define F_TRUNCATED (1<<9) /* response is truncated */
116 #define F_RECDESIRED (1<<8) /* recursion desired */
117 #define F_RECAVAIL (1<<7) /* recursion available */
118 #define F_RCODE (0xF<<0) /* reply code */
121 #define OPCODE_QUERY (0<<11) /* standard query */
122 #define OPCODE_IQUERY (1<<11) /* inverse query */
123 #define OPCODE_STATUS (2<<11) /* server status request */
126 #define RCODE_NOERROR (0<<0)
127 #define RCODE_FMTERROR (1<<0)
128 #define RCODE_SERVFAIL (2<<0)
129 #define RCODE_NAMEERROR (3<<0)
130 #define RCODE_NOTIMPL (4<<0)
131 #define RCODE_REFUSED (5<<0)
133 /* See RFC 1035 for all RR types for which no RFC is listed. */
135 dns_type_name (u_int type)
137 char *type_names[36] = {
156 "AFSDB", /* RFC 1183 */
157 "X25", /* RFC 1183 */
158 "ISDN", /* RFC 1183 */
160 "NSAP", /* RFC 1706 */
161 "NSAP-PTR", /* RFC 1348 */
162 "SIG", /* RFC 2065 */
163 "KEY", /* RFC 2065 */
165 "GPOS", /* RFC 1712 */
166 "AAAA", /* RFC 1886 */
167 "LOC", /* RFC 1876 */
168 "NXT", /* RFC 2065 */
171 "SRV", /* RFC 2052 */
173 "NAPTR" /* RFC 2168 */
177 return type_names[type];
194 return "IXFR"; /* RFC 1995 */
210 dns_long_type_name (u_int type)
212 char *type_names[36] = {
215 "Authoritative name server",
218 "Canonical name for an alias",
219 "Start of zone of authority",
220 "Mailbox domain name",
222 "Mail rename domain name",
223 "Null resource record",
224 "Well-known service description",
225 "Domain name pointer",
227 "Mailbox or mail list information",
230 "Responsible person", /* RFC 1183 */
231 "AFS data base location", /* RFC 1183 */
232 "X.25 address", /* RFC 1183 */
233 "ISDN number", /* RFC 1183 */
234 "Route through", /* RFC 1183 */
235 "OSI NSAP", /* RFC 1706 */
236 "OSI NSAP name pointer", /* RFC 1348 */
237 "Signature", /* RFC 2065 */
238 "Public key", /* RFC 2065 */
239 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
240 "Geographical position", /* RFC 1712 */
241 "IPv6 address", /* RFC 1886 */
242 "Location", /* RFC 1876 */
243 "Next", /* RFC 2065 */
246 "Service location", /* RFC 2052 */
248 "Naming authority pointer" /* RFC 2168 */
250 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%d)" */
253 return type_names[type];
270 return "Request for incremental zone transfer"; /* RFC 1995 */
272 return "Request for full zone transfer";
274 return "Request for mailbox-related records";
276 return "Request for mail agent resource records";
278 return "Request for all records";
281 sprintf(unkbuf, "Unknown RR type (%d)", type);
287 dns_class_name(int class)
296 class_name = "chaos";
299 class_name = "hesiod";
302 class_name = "unknown";
309 get_dns_name(const u_char *pd, int offset, int dns_data_offset,
310 char *name, int maxname)
312 const u_char *dp = pd + offset;
313 const u_char *dptr = dp;
318 maxname--; /* reserve space for the trailing '\0' */
320 if (!BYTES_ARE_IN_FRAME(offset, 1))
322 component_len = *dp++;
324 if (component_len == 0)
326 switch (component_len & 0xc0) {
331 /* Not the first component - put in a '.'. */
337 if (!BYTES_ARE_IN_FRAME(offset, component_len))
339 while (component_len > 0) {
352 goto error; /* error */
356 /* XXX - check to make sure we aren't looping, by keeping track
357 of how many characters are in the DNS packet, and of how many
358 characters we've looked at, and quitting if the latter
359 becomes bigger than the former. */
360 if (!BYTES_ARE_IN_FRAME(offset, 1))
362 offset = dns_data_offset + (((component_len & ~0xc0) << 8) | (*dp++));
363 /* If "len" is negative, we are still working on the original name,
364 not something pointed to by a pointer, and so we should set "len"
365 to the length of the original name. */
369 break; /* now continue processing from there */
375 /* If "len" is negative, we haven't seen a pointer, and thus haven't
376 set the length, so set it. */
379 /* Zero-length name means "root server" */
381 strcpy(name, "<Root>");
385 /* We ran past the end of the captured data in the packet. */
386 strcpy(name, "<Name goes past end of captured data in packet>");
387 /* If "len" is negative, we haven't seen a pointer, and thus haven't
388 set the length, so set it. */
396 get_dns_name_type_class(const u_char *pd, int offset, int dns_data_offset,
397 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
404 int start_offset = offset;
406 name_len = get_dns_name(pd, offset, dns_data_offset, name, sizeof(name));
409 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
410 /* We ran past the end of the captured data in the packet. */
413 type = pntohs(&pd[offset]);
416 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
417 /* We ran past the end of the captured data in the packet. */
420 class = pntohs(&pd[offset]);
423 strcpy (name_ret, name);
426 *name_len_ret = name_len;
428 len = offset - start_offset;
433 rfc1867_size(u_char val)
438 size = (val & 0xF0) >> 4;
439 exponent = (val & 0x0F);
440 while (exponent != 0) {
444 return size / 100; /* return size in meters, not cm */
448 rfc1867_angle(const u_char *dptr, const char *nsew)
452 guint32 degrees, minutes, secs, tsecs;
453 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
455 angle = pntohl(dptr);
457 if (angle < 0x80000000U) {
458 angle = 0x80000000U - angle;
461 angle = angle - 0x80000000U;
464 tsecs = angle % 1000;
465 angle = angle / 1000;
468 minutes = angle % 60;
469 degrees = angle / 60;
470 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
476 dissect_dns_query(const u_char *pd, int offset, int dns_data_offset,
477 frame_data *fd, proto_tree *dns_tree)
486 char *long_type_name;
488 const u_char *data_start;
492 data_start = dptr = pd + offset;
494 len = get_dns_name_type_class(pd, offset, dns_data_offset, name, &name_len,
497 /* We ran past the end of the data in the packet. */
502 type_name = dns_type_name(type);
503 class_name = dns_class_name(class);
504 long_type_name = dns_long_type_name(type);
507 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
508 if (dns_tree != NULL) {
509 tq = proto_tree_add_text(dns_tree, offset, len, "%s: type %s, class %s",
510 name, type_name, class_name);
511 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
513 proto_tree_add_text(q_tree, offset, name_len, "Name: %s", name);
516 proto_tree_add_text(q_tree, offset, 2, "Type: %s", long_type_name);
519 proto_tree_add_text(q_tree, offset, 2, "Class: %s", class_name);
523 return dptr - data_start;
528 add_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
529 int namelen, const char *type_name, const char *class_name, u_int ttl,
534 rr_tree = proto_item_add_subtree(trr, rr_type);
535 proto_tree_add_text(rr_tree, offset, namelen, "Name: %s", name);
537 proto_tree_add_text(rr_tree, offset, 2, "Type: %s", type_name);
539 proto_tree_add_text(rr_tree, offset, 2, "Class: %s", class_name);
541 proto_tree_add_text(rr_tree, offset, 4, "Time to live: %s",
542 time_secs_to_str(ttl));
544 proto_tree_add_text(rr_tree, offset, 2, "Data length: %u", data_len);
549 * SIG and KEY RR algorithms.
551 #define DNS_ALGO_MD5 1 /* MD5/RSA */
552 #define DNS_ALGO_EDATE 253 /* Expiration date */
553 #define DNS_ALGO_PRIVATE 254 /* Private use */
555 static const value_string algo_vals[] = {
556 { DNS_ALGO_MD5, "MD5/RSA" },
557 { DNS_ALGO_EDATE, "Expiration date" },
558 { DNS_ALGO_PRIVATE, "Private use" },
563 dissect_dns_answer(const u_char *pd, int offset, int dns_data_offset,
564 frame_data *fd, proto_tree *dns_tree)
573 char *long_type_name;
576 const u_char *data_start;
582 data_start = dptr = pd + offset;
585 len = get_dns_name_type_class(pd, offset, dns_data_offset, name, &name_len,
588 /* We ran past the end of the captured data in the packet. */
594 type_name = dns_type_name(type);
595 class_name = dns_class_name(class);
596 long_type_name = dns_long_type_name(type);
598 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
599 /* We ran past the end of the captured data in the packet. */
606 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
607 /* We ran past the end of the captured data in the packet. */
610 data_len = pntohs(dptr);
617 col_append_fstr(fd, COL_INFO, " %s %s", type_name,
618 ip_to_str((guint8 *)dptr));
620 if (dns_tree != NULL) {
621 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
622 "%s: type %s, class %s, addr %s",
623 name, type_name, class_name,
624 ip_to_str((guint8 *)dptr));
625 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
626 long_type_name, class_name, ttl, data_len);
627 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
628 /* We ran past the end of the captured data in the packet. */
631 proto_tree_add_text(rr_tree, cur_offset, 4, "Addr: %s",
632 ip_to_str((guint8 *)dptr));
638 char ns_name[MAXDNAME];
641 ns_name_len = get_dns_name(pd, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
643 col_append_fstr(fd, COL_INFO, " %s %s", type_name, ns_name);
644 if (dns_tree != NULL) {
645 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
646 "%s: type %s, class %s, ns %s",
647 name, type_name, class_name, ns_name);
648 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
649 long_type_name, class_name, ttl, data_len);
650 if (ns_name_len < 0) {
651 /* We ran past the end of the captured data in the packet. */
654 proto_tree_add_text(rr_tree, cur_offset, ns_name_len, "Name server: %s",
662 char cname[MAXDNAME];
665 cname_len = get_dns_name(pd, cur_offset, dns_data_offset, cname, sizeof(cname));
667 col_append_fstr(fd, COL_INFO, " %s %s", type_name, cname);
668 if (dns_tree != NULL) {
669 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
670 "%s: type %s, class %s, cname %s",
671 name, type_name, class_name, cname);
672 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
673 long_type_name, class_name, ttl, data_len);
675 /* We ran past the end of the captured data in the packet. */
678 proto_tree_add_text(rr_tree, cur_offset, cname_len, "Primary name: %s",
686 char mname[MAXDNAME];
688 char rname[MAXDNAME];
696 mname_len = get_dns_name(pd, cur_offset, dns_data_offset, mname, sizeof(mname));
698 rname_len = get_dns_name(pd, cur_offset + mname_len, dns_data_offset, rname, sizeof(rname));
700 /* We ran past the end of the captured data in the packet. */
704 col_append_fstr(fd, COL_INFO, " %s %s", type_name, mname);
705 if (dns_tree != NULL) {
706 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
707 "%s: type %s, class %s, mname %s",
708 name, type_name, class_name, mname);
709 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
710 long_type_name, class_name, ttl, data_len);
712 /* We ran past the end of the captured data in the packet. */
715 proto_tree_add_text(rr_tree, cur_offset, mname_len, "Primary name server: %s",
717 cur_offset += mname_len;
720 /* We ran past the end of the captured data in the packet. */
723 proto_tree_add_text(rr_tree, cur_offset, rname_len, "Responsible authority's mailbox: %s",
725 cur_offset += rname_len;
727 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
728 /* We ran past the end of the captured data in the packet. */
731 serial = pntohl(&pd[cur_offset]);
732 proto_tree_add_text(rr_tree, cur_offset, 4, "Serial number: %u",
736 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
737 /* We ran past the end of the captured data in the packet. */
740 refresh = pntohl(&pd[cur_offset]);
741 proto_tree_add_text(rr_tree, cur_offset, 4, "Refresh interval: %s",
742 time_secs_to_str(refresh));
745 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
746 /* We ran past the end of the captured data in the packet. */
749 retry = pntohl(&pd[cur_offset]);
750 proto_tree_add_text(rr_tree, cur_offset, 4, "Retry interval: %s",
751 time_secs_to_str(retry));
754 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
755 /* We ran past the end of the captured data in the packet. */
758 expire = pntohl(&pd[cur_offset]);
759 proto_tree_add_text(rr_tree, cur_offset, 4, "Expiration limit: %s",
760 time_secs_to_str(expire));
763 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
764 /* We ran past the end of the captured data in the packet. */
767 minimum = pntohl(&pd[cur_offset]);
768 proto_tree_add_text(rr_tree, cur_offset, 4, "Minimum TTL: %s",
769 time_secs_to_str(minimum));
776 char pname[MAXDNAME];
779 pname_len = get_dns_name(pd, cur_offset, dns_data_offset, pname, sizeof(pname));
781 col_append_fstr(fd, COL_INFO, " %s %s", type_name, pname);
782 if (dns_tree != NULL) {
783 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
784 "%s: type %s, class %s, ptr %s",
785 name, type_name, class_name, pname);
786 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
787 long_type_name, class_name, ttl, data_len);
789 /* We ran past the end of the captured data in the packet. */
792 proto_tree_add_text(rr_tree, cur_offset, pname_len, "Domain name: %s",
806 cpu_offset = cur_offset;
807 if (!BYTES_ARE_IN_FRAME(cpu_offset, 1)) {
808 /* We ran past the end of the captured data in the packet. */
809 if (dns_tree != NULL) {
810 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
811 "%s: type %s, class %s, <CPU goes past end of captured data in packet>",
812 name, type_name, class_name);
813 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
814 long_type_name, class_name, ttl, data_len);
818 cpu_len = pd[cpu_offset];
819 if (!BYTES_ARE_IN_FRAME(cpu_offset + 1, cpu_len)) {
820 /* We ran past the end of the captured data in the packet. */
821 if (dns_tree != NULL) {
822 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
823 "%s: type %s, class %s, <CPU goes past end of captured data in packet>",
824 name, type_name, class_name);
825 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
826 long_type_name, class_name, ttl, data_len);
830 os_offset = cpu_offset + 1 + cpu_len;
831 if (!BYTES_ARE_IN_FRAME(os_offset, 1)) {
832 /* We ran past the end of the captured data in the packet. */
833 if (dns_tree != NULL) {
834 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
835 "%s: type %s, class %s, CPU %.*s, <OS goes past end of captured data in packet>",
836 name, type_name, class_name, cpu_len, &pd[cpu_offset + 1]);
837 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
838 long_type_name, class_name, ttl, data_len);
842 os_len = pd[os_offset];
843 if (!BYTES_ARE_IN_FRAME(os_offset + 1, os_len)) {
844 /* We ran past the end of the captured data in the packet. */
845 if (dns_tree != NULL) {
846 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
847 "%s: type %s, class %s, CPU %*.s, <OS goes past end of captured data in packet>",
848 name, type_name, class_name, cpu_len, &pd[cpu_offset + 1]);
849 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
850 long_type_name, class_name, ttl, data_len);
855 col_append_fstr(fd, COL_INFO, " %s %.*s %.*s", type_name, cpu_len,
856 &pd[cpu_offset + 1], os_len, &pd[os_offset + 1]);
857 if (dns_tree != NULL) {
858 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
859 "%s: type %s, class %s, CPU %.*s, OS %.*s",
860 name, type_name, class_name,
861 cpu_len, &pd[cpu_offset + 1], os_len, &pd[os_offset + 1]);
862 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
863 long_type_name, class_name, ttl, data_len);
864 proto_tree_add_text(rr_tree, cpu_offset, 1 + cpu_len, "CPU: %.*s",
865 cpu_len, &pd[cpu_offset + 1]);
866 proto_tree_add_text(rr_tree, os_offset, 1 + os_len, "OS: %.*s",
867 os_len, &pd[os_offset + 1]);
875 guint16 preference = 0;
876 char mx_name[MAXDNAME];
879 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
880 /* We ran past the end of the captured data in the packet. */
881 if (dns_tree != NULL) {
882 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
883 "%s: type %s, class %s, <preference goes past end of captured data in packet>",
884 name, type_name, class_name);
885 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
886 long_type_name, class_name, ttl, data_len);
890 preference = pntohs(&pd[cur_offset]);
891 mx_name_len = get_dns_name(pd, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
892 if (mx_name_len < 0) {
893 /* We ran past the end of the captured data in the packet. */
894 if (dns_tree != NULL) {
895 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
896 "%s: type %s, class %s, preference %u, <mx goes past end of captured data in packet>",
897 name, type_name, class_name, preference);
898 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
899 long_type_name, class_name, ttl, data_len);
904 col_append_fstr(fd, COL_INFO, " %s %u %s", type_name, preference, mx_name);
905 if (dns_tree != NULL) {
906 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
907 "%s: type %s, class %s, preference %u, mx %s",
908 name, type_name, class_name, preference, mx_name);
909 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
910 long_type_name, class_name, ttl, data_len);
911 proto_tree_add_text(rr_tree, cur_offset, 2, "Preference: %u", preference);
912 proto_tree_add_text(rr_tree, cur_offset + 2, mx_name_len, "Mail exchange: %s",
920 int rr_len = data_len;
921 struct timeval unixtime;
922 char signer_name[MAXDNAME];
926 col_append_fstr(fd, COL_INFO, " %s", type_name);
927 if (dns_tree != NULL) {
928 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
929 "%s: type %s, class %s",
930 name, type_name, class_name);
931 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
932 long_type_name, class_name, ttl, data_len);
934 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
935 /* We ran past the end of the captured data in the packet. */
938 proto_tree_add_text(rr_tree, cur_offset, 2, "Type covered: %s (%s)",
939 dns_type_name(pntohs(&pd[cur_offset])),
940 dns_long_type_name(pntohs(&pd[cur_offset])));
944 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
945 /* We ran past the end of the captured data in the packet. */
948 proto_tree_add_text(rr_tree, cur_offset, 1, "Algorithm: %s",
949 val_to_str(pd[cur_offset], algo_vals,
950 "Unknown (0x%02X)"));
954 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
955 /* We ran past the end of the captured data in the packet. */
958 proto_tree_add_text(rr_tree, cur_offset, 1, "Labels: %u",
963 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
964 /* We ran past the end of the captured data in the packet. */
967 proto_tree_add_text(rr_tree, cur_offset, 4, "Original TTL: %s",
968 time_secs_to_str(pntohl(&pd[cur_offset])));
972 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
973 /* We ran past the end of the captured data in the packet. */
976 unixtime.tv_sec = pntohl(&pd[cur_offset]);
977 unixtime.tv_usec = 0;
978 proto_tree_add_text(rr_tree, cur_offset, 4, "Signature expiration: %s",
979 abs_time_to_str(&unixtime));
983 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
984 /* We ran past the end of the captured data in the packet. */
987 unixtime.tv_sec = pntohl(&pd[cur_offset]);
988 unixtime.tv_usec = 0;
989 proto_tree_add_text(rr_tree, cur_offset, 4, "Time signed: %s",
990 abs_time_to_str(&unixtime));
994 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
995 /* We ran past the end of the captured data in the packet. */
998 proto_tree_add_text(rr_tree, cur_offset, 2, "Key footprint: 0x%04x",
999 pntohs(&pd[cur_offset]));
1003 signer_name_len = get_dns_name(pd, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1004 if (signer_name_len < 0) {
1005 /* We ran past the end of the captured data in the packet. */
1008 proto_tree_add_text(rr_tree, cur_offset, signer_name_len,
1009 "Signer's name: %s", signer_name);
1010 cur_offset += signer_name_len;
1011 rr_len -= signer_name_len;
1013 proto_tree_add_text(rr_tree, cur_offset, rr_len, "Signature");
1020 int rr_len = data_len;
1023 proto_tree *flags_tree;
1026 col_append_fstr(fd, COL_INFO, " %s", type_name);
1027 if (dns_tree != NULL) {
1028 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1029 "%s: type %s, class %s",
1030 name, type_name, class_name);
1031 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1032 long_type_name, class_name, ttl, data_len);
1034 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1035 /* We ran past the end of the captured data in the packet. */
1038 flags = pntohs(&pd[cur_offset]);
1039 tf = proto_tree_add_text(rr_tree, cur_offset, 2, "Flags: 0x%04X", flags);
1040 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1041 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1042 decode_boolean_bitfield(flags, 0x8000,
1043 2*8, "Key prohibited for authentication",
1044 "Key allowed for authentication"));
1045 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1046 decode_boolean_bitfield(flags, 0x4000,
1047 2*8, "Key prohibited for confidentiality",
1048 "Key allowed for confidentiality"));
1049 if ((flags & 0xC000) != 0xC000) {
1051 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1052 decode_boolean_bitfield(flags, 0x2000,
1053 2*8, "Key is experimental or optional",
1054 "Key is required"));
1055 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1056 decode_boolean_bitfield(flags, 0x0400,
1057 2*8, "Key is associated with a user",
1058 "Key is not associated with a user"));
1059 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1060 decode_boolean_bitfield(flags, 0x0200,
1061 2*8, "Key is associated with the named entity",
1062 "Key is not associated with the named entity"));
1063 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1064 decode_boolean_bitfield(flags, 0x0100,
1065 2*8, "This is the zone key for the specified zone",
1066 "This is not a zone key"));
1067 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1068 decode_boolean_bitfield(flags, 0x0080,
1069 2*8, "Key is valid for use with IPSEC",
1070 "Key is not valid for use with IPSEC"));
1071 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1072 decode_boolean_bitfield(flags, 0x0040,
1073 2*8, "Key is valid for use with MIME security multiparts",
1074 "Key is not valid for use with MIME security multiparts"));
1075 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1076 decode_numeric_bitfield(flags, 0x000F,
1077 2*8, "Signatory = %u"));
1082 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1083 /* We ran past the end of the captured data in the packet. */
1086 proto_tree_add_text(rr_tree, cur_offset, 1, "Protocol: %u",
1091 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1092 /* We ran past the end of the captured data in the packet. */
1095 proto_tree_add_text(rr_tree, cur_offset, 1, "Algorithm: %s",
1096 val_to_str(pd[cur_offset], algo_vals,
1097 "Unknown (0x%02X)"));
1101 proto_tree_add_text(rr_tree, cur_offset, rr_len, "Public key");
1108 col_append_fstr(fd, COL_INFO, " %s %s", type_name,
1109 ip6_to_str((struct e_in6_addr *)dptr));
1111 if (dns_tree != NULL) {
1112 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1113 "%s: type %s, class %s, addr %s",
1114 name, type_name, class_name,
1115 ip6_to_str((struct e_in6_addr *)dptr));
1116 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1117 long_type_name, class_name, ttl, data_len);
1118 if (!BYTES_ARE_IN_FRAME(cur_offset, 16)) {
1119 /* We ran past the end of the captured data in the packet. */
1122 proto_tree_add_text(rr_tree, cur_offset, 16, "Addr: %s",
1123 ip6_to_str((struct e_in6_addr *)dptr));
1130 col_append_fstr(fd, COL_INFO, " %s", type_name);
1131 if (dns_tree != NULL) {
1132 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1133 "%s: type %s, class %s",
1134 name, type_name, class_name);
1135 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1136 long_type_name, class_name, ttl, data_len);
1137 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1138 /* We ran past the end of the captured data in the packet. */
1141 proto_tree_add_text(rr_tree, cur_offset, 1, "Version: %u", pd[cur_offset]);
1142 if (pd[cur_offset] == 0) {
1143 /* Version 0, the only version RFC 1876 discusses. */
1146 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1147 /* We ran past the end of the captured data in the packet. */
1150 proto_tree_add_text(rr_tree, cur_offset, 1, "Size: %g m",
1151 rfc1867_size(pd[cur_offset]));
1154 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1155 /* We ran past the end of the captured data in the packet. */
1158 proto_tree_add_text(rr_tree, cur_offset, 1, "Horizontal precision: %g m",
1159 rfc1867_size(pd[cur_offset]));
1162 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1163 /* We ran past the end of the captured data in the packet. */
1166 proto_tree_add_text(rr_tree, cur_offset, 1, "Vertical precision: %g m",
1167 rfc1867_size(pd[cur_offset]));
1170 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1171 /* We ran past the end of the captured data in the packet. */
1174 proto_tree_add_text(rr_tree, cur_offset, 4, "Latitude: %s",
1175 rfc1867_angle(&pd[cur_offset], "NS"));
1178 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1179 /* We ran past the end of the captured data in the packet. */
1182 proto_tree_add_text(rr_tree, cur_offset, 4, "Longitude: %s",
1183 rfc1867_angle(&pd[cur_offset], "EW"));
1186 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1187 /* We ran past the end of the captured data in the packet. */
1190 proto_tree_add_text(rr_tree, cur_offset, 4, "Altitude: %g m",
1191 (pntohl(&pd[cur_offset]) - 10000000)/100.0);
1193 proto_tree_add_text(rr_tree, cur_offset, data_len, "Data");
1201 int rr_len = data_len;
1202 char next_domain_name[MAXDNAME];
1203 int next_domain_name_len;
1209 next_domain_name_len = get_dns_name(pd, cur_offset, dns_data_offset,
1210 next_domain_name, sizeof(next_domain_name));
1212 col_append_fstr(fd, COL_INFO, " %s %s", type_name, next_domain_name);
1213 if (dns_tree != NULL) {
1214 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1215 "%s: type %s, class %s, next domain name %s",
1216 name, type_name, class_name, next_domain_name);
1217 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1218 long_type_name, class_name, ttl, data_len);
1219 if (next_domain_name_len < 0) {
1220 /* We ran past the end of the captured data in the packet. */
1223 proto_tree_add_text(rr_tree, cur_offset, next_domain_name_len,
1224 "Next domain name: %s", next_domain_name);
1225 cur_offset += next_domain_name_len;
1226 rr_len -= next_domain_name_len;
1228 while (rr_len != 0) {
1229 bits = pd[cur_offset];
1231 for (i = 0; i < 8; i++) {
1233 proto_tree_add_text(rr_tree, cur_offset, 1,
1234 "RR type in bit map: %s (%s)",
1235 dns_type_name(rr_type),
1236 dns_long_type_name(rr_type));
1248 /* TODO: parse more record types */
1252 col_append_fstr(fd, COL_INFO, " %s", type_name);
1253 if (dns_tree != NULL) {
1254 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1255 "%s: type %s, class %s",
1256 name, type_name, class_name);
1257 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1258 long_type_name, class_name, ttl, data_len);
1259 proto_tree_add_text(rr_tree, cur_offset, data_len, "Data");
1266 return dptr - data_start;
1270 dissect_query_records(const u_char *pd, int cur_off, int dns_data_offset,
1271 int count, frame_data *fd, proto_tree *dns_tree)
1273 int start_off, add_off;
1274 proto_tree *qatree = NULL;
1275 proto_item *ti = NULL;
1277 start_off = cur_off;
1279 ti = proto_tree_add_text(dns_tree, start_off, 0, "Queries");
1280 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1282 while (count-- > 0) {
1283 add_off = dissect_dns_query(pd, cur_off, dns_data_offset, fd, qatree);
1285 /* We ran past the end of the captured data in the packet. */
1291 proto_item_set_len(ti, cur_off - start_off);
1293 return cur_off - start_off;
1297 dissect_answer_records(const u_char *pd, int cur_off, int dns_data_offset,
1298 int count, frame_data *fd, proto_tree *dns_tree, char *name)
1300 int start_off, add_off;
1301 proto_tree *qatree = NULL;
1302 proto_item *ti = NULL;
1304 start_off = cur_off;
1306 ti = proto_tree_add_text(dns_tree, start_off, 0, name);
1307 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1309 while (count-- > 0) {
1310 add_off = dissect_dns_answer(pd, cur_off, dns_data_offset, fd, qatree);
1312 /* We ran past the end of the captured data in the packet. */
1318 proto_item_set_len(ti, cur_off - start_off);
1320 return cur_off - start_off;
1324 dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1326 int dns_data_offset;
1327 proto_tree *dns_tree = NULL, *field_tree;
1328 proto_item *ti, *tf;
1329 guint16 id, flags, quest, ans, auth, add;
1332 static const value_string opcode_vals[] = {
1333 { OPCODE_QUERY, "Standard query" },
1334 { OPCODE_IQUERY, "Inverse query" },
1335 { OPCODE_STATUS, "Server status request" },
1337 static const value_string rcode_vals[] = {
1338 { RCODE_NOERROR, "No error" },
1339 { RCODE_FMTERROR, "Format error" },
1340 { RCODE_SERVFAIL, "Server failure" },
1341 { RCODE_NAMEERROR, "Name error" },
1342 { RCODE_NOTIMPL, "Not implemented" },
1343 { RCODE_REFUSED, "Refused" },
1346 dns_data_offset = offset;
1348 if (check_col(fd, COL_PROTOCOL))
1349 col_add_str(fd, COL_PROTOCOL, "DNS");
1351 if (pi.captured_len < DNS_HDRLEN) {
1352 col_add_str(fd, COL_INFO, "Short DNS packet");
1353 dissect_data(pd, offset, fd, tree);
1357 /* To do: check for errs, etc. */
1358 id = pntohs(&pd[offset + DNS_ID]);
1359 flags = pntohs(&pd[offset + DNS_FLAGS]);
1360 quest = pntohs(&pd[offset + DNS_QUEST]);
1361 ans = pntohs(&pd[offset + DNS_ANS]);
1362 auth = pntohs(&pd[offset + DNS_AUTH]);
1363 add = pntohs(&pd[offset + DNS_ADD]);
1365 if (check_col(fd, COL_INFO)) {
1366 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation (%x)"));
1367 if (flags & F_RESPONSE) {
1368 strcat(buf, " response");
1369 if ((flags & F_RCODE) != RCODE_NOERROR) {
1371 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1372 "Unknown error (%x)"));
1375 col_add_str(fd, COL_INFO, buf);
1377 /* Set "fd" to NULL; we pass a NULL "fd" to the query and answer
1378 dissectors, as a way of saying that they shouldn't add stuff
1379 to the COL_INFO column (a call to "check_col(fd, COL_INFO)"
1380 is more expensive than a check that a pointer isn't NULL). */
1385 ti = proto_tree_add_item_format(tree, proto_dns, offset, 4, NULL,
1386 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1388 dns_tree = proto_item_add_subtree(ti, ett_dns);
1390 if (flags & F_RESPONSE)
1391 proto_tree_add_item_hidden(dns_tree, hf_dns_response, offset, 4, 1);
1393 proto_tree_add_item_hidden(dns_tree, hf_dns_query, offset, 4, 1);
1395 proto_tree_add_item(dns_tree, hf_dns_transaction_id,
1396 offset + DNS_ID, 2, id);
1398 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
1399 if (flags & F_RESPONSE) {
1400 strcat(buf, " response");
1402 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1405 tf = proto_tree_add_item_format(dns_tree, hf_dns_flags,
1406 offset + DNS_FLAGS, 2,
1408 "Flags: 0x%04x (%s)",
1410 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1411 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1412 decode_boolean_bitfield(flags, F_RESPONSE,
1413 2*8, "Response", "Query"));
1414 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1415 decode_enumerated_bitfield(flags, F_OPCODE,
1416 2*8, opcode_vals, "%s"));
1417 if (flags & F_RESPONSE) {
1418 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1419 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
1421 "Server is an authority for domain",
1422 "Server isn't an authority for domain"));
1424 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1425 decode_boolean_bitfield(flags, F_TRUNCATED,
1427 "Message is truncated",
1428 "Message is not truncated"));
1429 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1430 decode_boolean_bitfield(flags, F_RECDESIRED,
1432 "Do query recursively",
1433 "Don't do query recursively"));
1434 if (flags & F_RESPONSE) {
1435 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1436 decode_boolean_bitfield(flags, F_RECAVAIL,
1438 "Server can do recursive queries",
1439 "Server can't do recursive queries"));
1440 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1441 decode_enumerated_bitfield(flags, F_RCODE,
1442 2*8, rcode_vals, "%s"));
1444 proto_tree_add_item(dns_tree, hf_dns_count_questions,
1445 offset + DNS_QUEST, 2, quest);
1446 proto_tree_add_item(dns_tree, hf_dns_count_answers,
1447 offset + DNS_ANS, 2, ans);
1448 proto_tree_add_item(dns_tree, hf_dns_count_auth_rr,
1449 offset + DNS_AUTH, 2, auth);
1450 proto_tree_add_item(dns_tree, hf_dns_count_add_rr,
1451 offset + DNS_ADD, 2, add);
1454 cur_off = offset + DNS_HDRLEN;
1457 /* If this is a response, don't add information about the queries
1458 to the summary, just add information about the answers. */
1459 cur_off += dissect_query_records(pd, cur_off, dns_data_offset, quest,
1460 (!(flags & F_RESPONSE) ? fd : NULL),
1465 /* If this is a request, don't add information about the answers
1466 to the summary, just add information about the queries. */
1467 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, ans,
1468 ((flags & F_RESPONSE) ? fd : NULL),
1469 dns_tree, "Answers");
1473 /* Don't add information about the authoritative name servers, or the
1474 additional records, to the summary. */
1476 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, auth,
1477 NULL, dns_tree, "Authoritative nameservers");
1480 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, add,
1481 NULL, dns_tree, "Additional records");
1486 proto_register_dns(void)
1488 static hf_register_info hf[] = {
1490 { "Response", "dns.response",
1491 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1492 "TRUE if DNS response" }},
1494 { "Query", "dns.query",
1495 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1496 "TRUE if DNS query" }},
1498 { "Flags", "dns.flags",
1499 FT_UINT16, BASE_HEX, NULL, 0x0,
1501 { &hf_dns_transaction_id,
1502 { "Transaction ID", "dns.id",
1503 FT_UINT16, BASE_HEX, NULL, 0x0,
1504 "Identification of transaction" }},
1505 { &hf_dns_count_questions,
1506 { "Questions", "dns.count.queries",
1507 FT_UINT16, BASE_DEC, NULL, 0x0,
1508 "Number of queries in packet" }},
1509 { &hf_dns_count_answers,
1510 { "Answer RRs", "dns.count.answers",
1511 FT_UINT16, BASE_DEC, NULL, 0x0,
1512 "Number of answers in packet" }},
1513 { &hf_dns_count_auth_rr,
1514 { "Authority RRs", "dns.count.auth_rr",
1515 FT_UINT16, BASE_DEC, NULL, 0x0,
1516 "Number of authoritative records in packet" }},
1517 { &hf_dns_count_add_rr,
1518 { "Additional RRs", "dns.count.add_rr",
1519 FT_UINT16, BASE_DEC, NULL, 0x0,
1520 "Number of additional records in packet" }}
1522 static gint *ett[] = {
1532 proto_dns = proto_register_protocol("Domain Name Service", "dns");
1533 proto_register_field_array(proto_dns, hf, array_length(hf));
1534 proto_register_subtree_array(ett, array_length(ett));