2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.34 2000/01/16 02:54:45 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"
42 static int proto_dns = -1;
43 static int hf_dns_response = -1;
44 static int hf_dns_query = -1;
45 static int hf_dns_flags = -1;
46 static int hf_dns_transaction_id = -1;
47 static int hf_dns_count_questions = -1;
48 static int hf_dns_count_answers = -1;
49 static int hf_dns_count_auth_rr = -1;
50 static int hf_dns_count_add_rr = -1;
52 static gint ett_dns = -1;
53 static gint ett_dns_qd = -1;
54 static gint ett_dns_rr = -1;
55 static gint ett_dns_qry = -1;
56 static gint ett_dns_ans = -1;
57 static gint ett_dns_flags = -1;
58 static gint ett_t_key_flags = -1;
60 /* DNS structs and definitions */
62 /* Offsets of fields in the DNS header. */
70 /* Length of DNS header. */
74 #define T_A 1 /* host address */
75 #define T_NS 2 /* authoritative name server */
76 #define T_MD 3 /* mail destination (obsolete) */
77 #define T_MF 4 /* mail forwarder (obsolete) */
78 #define T_CNAME 5 /* canonical name */
79 #define T_SOA 6 /* start of authority zone */
80 #define T_MB 7 /* mailbox domain name (experimental) */
81 #define T_MG 8 /* mail group member (experimental) */
82 #define T_MR 9 /* mail rename domain name (experimental) */
83 #define T_NULL 10 /* null RR (experimental) */
84 #define T_WKS 11 /* well known service */
85 #define T_PTR 12 /* domain name pointer */
86 #define T_HINFO 13 /* host information */
87 #define T_MINFO 14 /* mailbox or mail list information */
88 #define T_MX 15 /* mail routing information */
89 #define T_TXT 16 /* text strings */
90 #define T_RP 17 /* responsible person (RFC 1183) */
91 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
92 #define T_X25 19 /* X.25 address (RFC 1183) */
93 #define T_ISDN 20 /* ISDN address (RFC 1183) */
94 #define T_RT 21 /* route-through (RFC 1183) */
95 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
96 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
97 #define T_SIG 24 /* digital signature (RFC 2065) */
98 #define T_KEY 25 /* public key (RFC 2065) */
99 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
100 #define T_GPOS 27 /* geographical position (RFC 1712) */
101 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
102 #define T_LOC 29 /* geographical location (RFC 1876) */
103 #define T_NXT 30 /* "next" name (RFC 2065) */
104 #define T_EID 31 /* ??? (Nimrod?) */
105 #define T_NIMLOC 32 /* ??? (Nimrod?) */
106 #define T_SRV 33 /* service location (RFC 2052) */
107 #define T_ATMA 34 /* ??? */
108 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
110 /* Bit fields in the flags */
111 #define F_RESPONSE (1<<15) /* packet is response */
112 #define F_OPCODE (0xF<<11) /* query opcode */
113 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
114 #define F_TRUNCATED (1<<9) /* response is truncated */
115 #define F_RECDESIRED (1<<8) /* recursion desired */
116 #define F_RECAVAIL (1<<7) /* recursion available */
117 #define F_RCODE (0xF<<0) /* reply code */
120 #define OPCODE_QUERY (0<<11) /* standard query */
121 #define OPCODE_IQUERY (1<<11) /* inverse query */
122 #define OPCODE_STATUS (2<<11) /* server status request */
125 #define RCODE_NOERROR (0<<0)
126 #define RCODE_FMTERROR (1<<0)
127 #define RCODE_SERVFAIL (2<<0)
128 #define RCODE_NAMEERROR (3<<0)
129 #define RCODE_NOTIMPL (4<<0)
130 #define RCODE_REFUSED (5<<0)
132 /* See RFC 1035 for all RR types for which no RFC is listed. */
134 dns_type_name (u_int type)
136 char *type_names[36] = {
155 "AFSDB", /* RFC 1183 */
156 "X25", /* RFC 1183 */
157 "ISDN", /* RFC 1183 */
159 "NSAP", /* RFC 1706 */
160 "NSAP-PTR", /* RFC 1348 */
161 "SIG", /* RFC 2065 */
162 "KEY", /* RFC 2065 */
164 "GPOS", /* RFC 1712 */
165 "AAAA", /* RFC 1886 */
166 "LOC", /* RFC 1876 */
167 "NXT", /* RFC 2065 */
170 "SRV", /* RFC 2052 */
172 "NAPTR" /* RFC 2168 */
176 return type_names[type];
193 return "IXFR"; /* RFC 1995 */
209 dns_long_type_name (u_int type)
211 char *type_names[36] = {
214 "Authoritative name server",
217 "Canonical name for an alias",
218 "Start of zone of authority",
219 "Mailbox domain name",
221 "Mail rename domain name",
222 "Null resource record",
223 "Well-known service description",
224 "Domain name pointer",
226 "Mailbox or mail list information",
229 "Responsible person", /* RFC 1183 */
230 "AFS data base location", /* RFC 1183 */
231 "X.25 address", /* RFC 1183 */
232 "ISDN number", /* RFC 1183 */
233 "Route through", /* RFC 1183 */
234 "OSI NSAP", /* RFC 1706 */
235 "OSI NSAP name pointer", /* RFC 1348 */
236 "Signature", /* RFC 2065 */
237 "Public key", /* RFC 2065 */
238 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
239 "Geographical position", /* RFC 1712 */
240 "IPv6 address", /* RFC 1886 */
241 "Location", /* RFC 1876 */
242 "Next", /* RFC 2065 */
245 "Service location", /* RFC 2052 */
247 "Naming authority pointer" /* RFC 2168 */
249 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%d)" */
252 return type_names[type];
269 return "Request for incremental zone transfer"; /* RFC 1995 */
271 return "Request for full zone transfer";
273 return "Request for mailbox-related records";
275 return "Request for mail agent resource records";
277 return "Request for all records";
280 sprintf(unkbuf, "Unknown RR type (%d)", type);
286 dns_class_name(int class)
295 class_name = "chaos";
298 class_name = "hesiod";
301 class_name = "unknown";
308 get_dns_name(const u_char *pd, int offset, int dns_data_offset,
309 char *name, int maxname)
311 const u_char *dp = pd + offset;
312 const u_char *dptr = dp;
317 maxname--; /* reserve space for the trailing '\0' */
319 if (!BYTES_ARE_IN_FRAME(offset, 1))
321 component_len = *dp++;
323 if (component_len == 0)
325 switch (component_len & 0xc0) {
330 /* Not the first component - put in a '.'. */
336 if (!BYTES_ARE_IN_FRAME(offset, component_len))
338 while (component_len > 0) {
351 goto error; /* error */
355 /* XXX - check to make sure we aren't looping, by keeping track
356 of how many characters are in the DNS packet, and of how many
357 characters we've looked at, and quitting if the latter
358 becomes bigger than the former. */
359 if (!BYTES_ARE_IN_FRAME(offset, 1))
361 offset = dns_data_offset + (((component_len & ~0xc0) << 8) | (*dp++));
362 /* If "len" is negative, we are still working on the original name,
363 not something pointed to by a pointer, and so we should set "len"
364 to the length of the original name. */
368 break; /* now continue processing from there */
374 /* If "len" is negative, we haven't seen a pointer, and thus haven't
375 set the length, so set it. */
378 /* Zero-length name means "root server" */
380 strcpy(name, "<Root>");
384 /* We ran past the end of the captured data in the packet. */
385 strcpy(name, "<Name goes past end of captured data in packet>");
386 /* If "len" is negative, we haven't seen a pointer, and thus haven't
387 set the length, so set it. */
395 get_dns_name_type_class(const u_char *pd, int offset, int dns_data_offset,
396 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
403 int start_offset = offset;
405 name_len = get_dns_name(pd, offset, dns_data_offset, name, sizeof(name));
408 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
409 /* We ran past the end of the captured data in the packet. */
412 type = pntohs(&pd[offset]);
415 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
416 /* We ran past the end of the captured data in the packet. */
419 class = pntohs(&pd[offset]);
422 strcpy (name_ret, name);
425 *name_len_ret = name_len;
427 len = offset - start_offset;
432 rfc1867_size(u_char val)
437 size = (val & 0xF0) >> 4;
438 exponent = (val & 0x0F);
439 while (exponent != 0) {
443 return size / 100; /* return size in meters, not cm */
447 rfc1867_angle(const u_char *dptr, const char *nsew)
451 guint32 degrees, minutes, secs, tsecs;
452 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
454 angle = pntohl(dptr);
456 if (angle < 0x80000000U) {
457 angle = 0x80000000U - angle;
460 angle = angle - 0x80000000U;
463 tsecs = angle % 1000;
464 angle = angle / 1000;
467 minutes = angle % 60;
468 degrees = angle / 60;
469 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
475 dissect_dns_query(const u_char *pd, int offset, int dns_data_offset,
476 frame_data *fd, proto_tree *dns_tree)
485 char *long_type_name;
487 const u_char *data_start;
491 data_start = dptr = pd + offset;
493 len = get_dns_name_type_class(pd, offset, dns_data_offset, name, &name_len,
496 /* We ran past the end of the data in the packet. */
501 type_name = dns_type_name(type);
502 class_name = dns_class_name(class);
503 long_type_name = dns_long_type_name(type);
506 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
507 if (dns_tree != NULL) {
508 tq = proto_tree_add_text(dns_tree, offset, len, "%s: type %s, class %s",
509 name, type_name, class_name);
510 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
512 proto_tree_add_text(q_tree, offset, name_len, "Name: %s", name);
515 proto_tree_add_text(q_tree, offset, 2, "Type: %s", long_type_name);
518 proto_tree_add_text(q_tree, offset, 2, "Class: %s", class_name);
522 return dptr - data_start;
527 add_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
528 int namelen, const char *type_name, const char *class_name, u_int ttl,
533 rr_tree = proto_item_add_subtree(trr, rr_type);
534 proto_tree_add_text(rr_tree, offset, namelen, "Name: %s", name);
536 proto_tree_add_text(rr_tree, offset, 2, "Type: %s", type_name);
538 proto_tree_add_text(rr_tree, offset, 2, "Class: %s", class_name);
540 proto_tree_add_text(rr_tree, offset, 4, "Time to live: %s",
541 time_secs_to_str(ttl));
543 proto_tree_add_text(rr_tree, offset, 2, "Data length: %u", data_len);
548 * SIG and KEY RR algorithms.
550 #define DNS_ALGO_MD5 1 /* MD5/RSA */
551 #define DNS_ALGO_EDATE 253 /* Expiration date */
552 #define DNS_ALGO_PRIVATE 254 /* Private use */
554 static const value_string algo_vals[] = {
555 { DNS_ALGO_MD5, "MD5/RSA" },
556 { DNS_ALGO_EDATE, "Expiration date" },
557 { DNS_ALGO_PRIVATE, "Private use" },
562 dissect_dns_answer(const u_char *pd, int offset, int dns_data_offset,
563 frame_data *fd, proto_tree *dns_tree)
572 char *long_type_name;
575 const u_char *data_start;
581 data_start = dptr = pd + offset;
584 len = get_dns_name_type_class(pd, offset, dns_data_offset, name, &name_len,
587 /* We ran past the end of the captured data in the packet. */
593 type_name = dns_type_name(type);
594 class_name = dns_class_name(class);
595 long_type_name = dns_long_type_name(type);
597 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
598 /* We ran past the end of the captured data in the packet. */
605 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
606 /* We ran past the end of the captured data in the packet. */
609 data_len = pntohs(dptr);
616 col_append_fstr(fd, COL_INFO, " %s %s", type_name,
617 ip_to_str((guint8 *)dptr));
619 if (dns_tree != NULL) {
620 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
621 "%s: type %s, class %s, addr %s",
622 name, type_name, class_name,
623 ip_to_str((guint8 *)dptr));
624 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
625 long_type_name, class_name, ttl, data_len);
626 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
627 /* We ran past the end of the captured data in the packet. */
630 proto_tree_add_text(rr_tree, cur_offset, 4, "Addr: %s",
631 ip_to_str((guint8 *)dptr));
637 char ns_name[MAXDNAME];
640 ns_name_len = get_dns_name(pd, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
642 col_append_fstr(fd, COL_INFO, " %s %s", type_name, ns_name);
643 if (dns_tree != NULL) {
644 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
645 "%s: type %s, class %s, ns %s",
646 name, type_name, class_name, ns_name);
647 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
648 long_type_name, class_name, ttl, data_len);
649 if (ns_name_len < 0) {
650 /* We ran past the end of the captured data in the packet. */
653 proto_tree_add_text(rr_tree, cur_offset, ns_name_len, "Name server: %s",
661 char cname[MAXDNAME];
664 cname_len = get_dns_name(pd, cur_offset, dns_data_offset, cname, sizeof(cname));
666 col_append_fstr(fd, COL_INFO, " %s %s", type_name, cname);
667 if (dns_tree != NULL) {
668 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
669 "%s: type %s, class %s, cname %s",
670 name, type_name, class_name, cname);
671 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
672 long_type_name, class_name, ttl, data_len);
674 /* We ran past the end of the captured data in the packet. */
677 proto_tree_add_text(rr_tree, cur_offset, cname_len, "Primary name: %s",
685 char mname[MAXDNAME];
687 char rname[MAXDNAME];
695 mname_len = get_dns_name(pd, cur_offset, dns_data_offset, mname, sizeof(mname));
697 rname_len = get_dns_name(pd, cur_offset + mname_len, dns_data_offset, rname, sizeof(rname));
699 /* We ran past the end of the captured data in the packet. */
703 col_append_fstr(fd, COL_INFO, " %s %s", type_name, mname);
704 if (dns_tree != NULL) {
705 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
706 "%s: type %s, class %s, mname %s",
707 name, type_name, class_name, mname);
708 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
709 long_type_name, class_name, ttl, data_len);
711 /* We ran past the end of the captured data in the packet. */
714 proto_tree_add_text(rr_tree, cur_offset, mname_len, "Primary name server: %s",
716 cur_offset += mname_len;
719 /* We ran past the end of the captured data in the packet. */
722 proto_tree_add_text(rr_tree, cur_offset, rname_len, "Responsible authority's mailbox: %s",
724 cur_offset += rname_len;
726 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
727 /* We ran past the end of the captured data in the packet. */
730 serial = pntohl(&pd[cur_offset]);
731 proto_tree_add_text(rr_tree, cur_offset, 4, "Serial number: %u",
735 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
736 /* We ran past the end of the captured data in the packet. */
739 refresh = pntohl(&pd[cur_offset]);
740 proto_tree_add_text(rr_tree, cur_offset, 4, "Refresh interval: %s",
741 time_secs_to_str(refresh));
744 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
745 /* We ran past the end of the captured data in the packet. */
748 retry = pntohl(&pd[cur_offset]);
749 proto_tree_add_text(rr_tree, cur_offset, 4, "Retry interval: %s",
750 time_secs_to_str(retry));
753 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
754 /* We ran past the end of the captured data in the packet. */
757 expire = pntohl(&pd[cur_offset]);
758 proto_tree_add_text(rr_tree, cur_offset, 4, "Expiration limit: %s",
759 time_secs_to_str(expire));
762 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
763 /* We ran past the end of the captured data in the packet. */
766 minimum = pntohl(&pd[cur_offset]);
767 proto_tree_add_text(rr_tree, cur_offset, 4, "Minimum TTL: %s",
768 time_secs_to_str(minimum));
775 char pname[MAXDNAME];
778 pname_len = get_dns_name(pd, cur_offset, dns_data_offset, pname, sizeof(pname));
780 col_append_fstr(fd, COL_INFO, " %s %s", type_name, pname);
781 if (dns_tree != NULL) {
782 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
783 "%s: type %s, class %s, ptr %s",
784 name, type_name, class_name, pname);
785 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
786 long_type_name, class_name, ttl, data_len);
788 /* We ran past the end of the captured data in the packet. */
791 proto_tree_add_text(rr_tree, cur_offset, pname_len, "Domain name: %s",
805 cpu_offset = cur_offset;
806 if (!BYTES_ARE_IN_FRAME(cpu_offset, 1)) {
807 /* We ran past the end of the captured data in the packet. */
808 if (dns_tree != NULL) {
809 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
810 "%s: type %s, class %s, <CPU goes past end of captured data in packet>",
811 name, type_name, class_name);
812 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
813 long_type_name, class_name, ttl, data_len);
817 cpu_len = pd[cpu_offset];
818 if (!BYTES_ARE_IN_FRAME(cpu_offset + 1, cpu_len)) {
819 /* We ran past the end of the captured data in the packet. */
820 if (dns_tree != NULL) {
821 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
822 "%s: type %s, class %s, <CPU goes past end of captured data in packet>",
823 name, type_name, class_name);
824 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
825 long_type_name, class_name, ttl, data_len);
829 os_offset = cpu_offset + 1 + cpu_len;
830 if (!BYTES_ARE_IN_FRAME(os_offset, 1)) {
831 /* We ran past the end of the captured data in the packet. */
832 if (dns_tree != NULL) {
833 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
834 "%s: type %s, class %s, CPU %.*s, <OS goes past end of captured data in packet>",
835 name, type_name, class_name, cpu_len, &pd[cpu_offset + 1]);
836 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
837 long_type_name, class_name, ttl, data_len);
841 os_len = pd[os_offset];
842 if (!BYTES_ARE_IN_FRAME(os_offset + 1, os_len)) {
843 /* We ran past the end of the captured data in the packet. */
844 if (dns_tree != NULL) {
845 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
846 "%s: type %s, class %s, CPU %*.s, <OS goes past end of captured data in packet>",
847 name, type_name, class_name, cpu_len, &pd[cpu_offset + 1]);
848 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
849 long_type_name, class_name, ttl, data_len);
854 col_append_fstr(fd, COL_INFO, " %s %.*s %.*s", type_name, cpu_len,
855 &pd[cpu_offset + 1], os_len, &pd[os_offset + 1]);
856 if (dns_tree != NULL) {
857 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
858 "%s: type %s, class %s, CPU %.*s, OS %.*s",
859 name, type_name, class_name,
860 cpu_len, &pd[cpu_offset + 1], os_len, &pd[os_offset + 1]);
861 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
862 long_type_name, class_name, ttl, data_len);
863 proto_tree_add_text(rr_tree, cpu_offset, 1 + cpu_len, "CPU: %.*s",
864 cpu_len, &pd[cpu_offset + 1]);
865 proto_tree_add_text(rr_tree, os_offset, 1 + os_len, "OS: %.*s",
866 os_len, &pd[os_offset + 1]);
874 guint16 preference = 0;
875 char mx_name[MAXDNAME];
878 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
879 /* We ran past the end of the captured data in the packet. */
880 if (dns_tree != NULL) {
881 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
882 "%s: type %s, class %s, <preference goes past end of captured data in packet>",
883 name, type_name, class_name);
884 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
885 long_type_name, class_name, ttl, data_len);
889 preference = pntohs(&pd[cur_offset]);
890 mx_name_len = get_dns_name(pd, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
891 if (mx_name_len < 0) {
892 /* We ran past the end of the captured data in the packet. */
893 if (dns_tree != NULL) {
894 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
895 "%s: type %s, class %s, preference %u, <mx goes past end of captured data in packet>",
896 name, type_name, class_name, preference);
897 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
898 long_type_name, class_name, ttl, data_len);
903 col_append_fstr(fd, COL_INFO, " %s %u %s", type_name, preference, mx_name);
904 if (dns_tree != NULL) {
905 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
906 "%s: type %s, class %s, preference %u, mx %s",
907 name, type_name, class_name, preference, mx_name);
908 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
909 long_type_name, class_name, ttl, data_len);
910 proto_tree_add_text(rr_tree, cur_offset, 2, "Preference: %u", preference);
911 proto_tree_add_text(rr_tree, cur_offset + 2, mx_name_len, "Mail exchange: %s",
919 int rr_len = data_len;
920 struct timeval unixtime;
921 char signer_name[MAXDNAME];
925 col_append_fstr(fd, COL_INFO, " %s", type_name);
926 if (dns_tree != NULL) {
927 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
928 "%s: type %s, class %s",
929 name, type_name, class_name);
930 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
931 long_type_name, class_name, ttl, data_len);
933 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
934 /* We ran past the end of the captured data in the packet. */
937 proto_tree_add_text(rr_tree, cur_offset, 2, "Type covered: %s (%s)",
938 dns_type_name(pntohs(&pd[cur_offset])),
939 dns_long_type_name(pntohs(&pd[cur_offset])));
943 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
944 /* We ran past the end of the captured data in the packet. */
947 proto_tree_add_text(rr_tree, cur_offset, 1, "Algorithm: %s",
948 val_to_str(pd[cur_offset], algo_vals,
949 "Unknown (0x%02X)"));
953 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
954 /* We ran past the end of the captured data in the packet. */
957 proto_tree_add_text(rr_tree, cur_offset, 1, "Labels: %u",
962 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
963 /* We ran past the end of the captured data in the packet. */
966 proto_tree_add_text(rr_tree, cur_offset, 4, "Original TTL: %s",
967 time_secs_to_str(pntohl(&pd[cur_offset])));
971 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
972 /* We ran past the end of the captured data in the packet. */
975 unixtime.tv_sec = pntohl(&pd[cur_offset]);
976 unixtime.tv_usec = 0;
977 proto_tree_add_text(rr_tree, cur_offset, 4, "Signature expiration: %s",
978 abs_time_to_str(&unixtime));
982 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
983 /* We ran past the end of the captured data in the packet. */
986 unixtime.tv_sec = pntohl(&pd[cur_offset]);
987 unixtime.tv_usec = 0;
988 proto_tree_add_text(rr_tree, cur_offset, 4, "Time signed: %s",
989 abs_time_to_str(&unixtime));
993 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
994 /* We ran past the end of the captured data in the packet. */
997 proto_tree_add_text(rr_tree, cur_offset, 2, "Key footprint: 0x%04x",
998 pntohs(&pd[cur_offset]));
1002 signer_name_len = get_dns_name(pd, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1003 if (signer_name_len < 0) {
1004 /* We ran past the end of the captured data in the packet. */
1007 proto_tree_add_text(rr_tree, cur_offset, signer_name_len,
1008 "Signer's name: %s", signer_name);
1009 cur_offset += signer_name_len;
1010 rr_len -= signer_name_len;
1012 proto_tree_add_text(rr_tree, cur_offset, rr_len, "Signature");
1019 int rr_len = data_len;
1022 proto_tree *flags_tree;
1025 col_append_fstr(fd, COL_INFO, " %s", type_name);
1026 if (dns_tree != NULL) {
1027 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1028 "%s: type %s, class %s",
1029 name, type_name, class_name);
1030 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1031 long_type_name, class_name, ttl, data_len);
1033 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1034 /* We ran past the end of the captured data in the packet. */
1037 flags = pntohs(&pd[cur_offset]);
1038 tf = proto_tree_add_text(rr_tree, cur_offset, 2, "Flags: 0x%04X", flags);
1039 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1040 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1041 decode_boolean_bitfield(flags, 0x8000,
1042 2*8, "Key prohibited for authentication",
1043 "Key allowed for authentication"));
1044 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1045 decode_boolean_bitfield(flags, 0x4000,
1046 2*8, "Key prohibited for confidentiality",
1047 "Key allowed for confidentiality"));
1048 if ((flags & 0xC000) != 0xC000) {
1050 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1051 decode_boolean_bitfield(flags, 0x2000,
1052 2*8, "Key is experimental or optional",
1053 "Key is required"));
1054 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1055 decode_boolean_bitfield(flags, 0x0400,
1056 2*8, "Key is associated with a user",
1057 "Key is not associated with a user"));
1058 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1059 decode_boolean_bitfield(flags, 0x0200,
1060 2*8, "Key is associated with the named entity",
1061 "Key is not associated with the named entity"));
1062 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1063 decode_boolean_bitfield(flags, 0x0100,
1064 2*8, "This is the zone key for the specified zone",
1065 "This is not a zone key"));
1066 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1067 decode_boolean_bitfield(flags, 0x0080,
1068 2*8, "Key is valid for use with IPSEC",
1069 "Key is not valid for use with IPSEC"));
1070 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1071 decode_boolean_bitfield(flags, 0x0040,
1072 2*8, "Key is valid for use with MIME security multiparts",
1073 "Key is not valid for use with MIME security multiparts"));
1074 proto_tree_add_text(flags_tree, cur_offset, 2, "%s",
1075 decode_numeric_bitfield(flags, 0x000F,
1076 2*8, "Signatory = %u"));
1081 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1082 /* We ran past the end of the captured data in the packet. */
1085 proto_tree_add_text(rr_tree, cur_offset, 1, "Protocol: %u",
1090 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1091 /* We ran past the end of the captured data in the packet. */
1094 proto_tree_add_text(rr_tree, cur_offset, 1, "Algorithm: %s",
1095 val_to_str(pd[cur_offset], algo_vals,
1096 "Unknown (0x%02X)"));
1100 proto_tree_add_text(rr_tree, cur_offset, rr_len, "Public key");
1107 col_append_fstr(fd, COL_INFO, " %s %s", type_name,
1108 ip6_to_str((struct e_in6_addr *)dptr));
1110 if (dns_tree != NULL) {
1111 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1112 "%s: type %s, class %s, addr %s",
1113 name, type_name, class_name,
1114 ip6_to_str((struct e_in6_addr *)dptr));
1115 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1116 long_type_name, class_name, ttl, data_len);
1117 if (!BYTES_ARE_IN_FRAME(cur_offset, 16)) {
1118 /* We ran past the end of the captured data in the packet. */
1121 proto_tree_add_text(rr_tree, cur_offset, 16, "Addr: %s",
1122 ip6_to_str((struct e_in6_addr *)dptr));
1129 col_append_fstr(fd, COL_INFO, " %s", type_name);
1130 if (dns_tree != NULL) {
1131 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1132 "%s: type %s, class %s",
1133 name, type_name, class_name);
1134 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1135 long_type_name, class_name, ttl, data_len);
1136 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1137 /* We ran past the end of the captured data in the packet. */
1140 proto_tree_add_text(rr_tree, cur_offset, 1, "Version: %u", pd[cur_offset]);
1141 if (pd[cur_offset] == 0) {
1142 /* Version 0, the only version RFC 1876 discusses. */
1145 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1146 /* We ran past the end of the captured data in the packet. */
1149 proto_tree_add_text(rr_tree, cur_offset, 1, "Size: %g m",
1150 rfc1867_size(pd[cur_offset]));
1153 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1154 /* We ran past the end of the captured data in the packet. */
1157 proto_tree_add_text(rr_tree, cur_offset, 1, "Horizontal precision: %g m",
1158 rfc1867_size(pd[cur_offset]));
1161 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1162 /* We ran past the end of the captured data in the packet. */
1165 proto_tree_add_text(rr_tree, cur_offset, 1, "Vertical precision: %g m",
1166 rfc1867_size(pd[cur_offset]));
1169 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1170 /* We ran past the end of the captured data in the packet. */
1173 proto_tree_add_text(rr_tree, cur_offset, 4, "Latitude: %s",
1174 rfc1867_angle(&pd[cur_offset], "NS"));
1177 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1178 /* We ran past the end of the captured data in the packet. */
1181 proto_tree_add_text(rr_tree, cur_offset, 4, "Longitude: %s",
1182 rfc1867_angle(&pd[cur_offset], "EW"));
1185 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1186 /* We ran past the end of the captured data in the packet. */
1189 proto_tree_add_text(rr_tree, cur_offset, 4, "Altitude: %g m",
1190 (pntohl(&pd[cur_offset]) - 10000000)/100.0);
1192 proto_tree_add_text(rr_tree, cur_offset, data_len, "Data");
1200 int rr_len = data_len;
1201 char next_domain_name[MAXDNAME];
1202 int next_domain_name_len;
1208 next_domain_name_len = get_dns_name(pd, cur_offset, dns_data_offset,
1209 next_domain_name, sizeof(next_domain_name));
1211 col_append_fstr(fd, COL_INFO, " %s %s", type_name, next_domain_name);
1212 if (dns_tree != NULL) {
1213 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1214 "%s: type %s, class %s, next domain name %s",
1215 name, type_name, class_name, next_domain_name);
1216 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1217 long_type_name, class_name, ttl, data_len);
1218 if (next_domain_name_len < 0) {
1219 /* We ran past the end of the captured data in the packet. */
1222 proto_tree_add_text(rr_tree, cur_offset, next_domain_name_len,
1223 "Next domain name: %s", next_domain_name);
1224 cur_offset += next_domain_name_len;
1225 rr_len -= next_domain_name_len;
1227 while (rr_len != 0) {
1228 bits = pd[cur_offset];
1230 for (i = 0; i < 8; i++) {
1232 proto_tree_add_text(rr_tree, cur_offset, 1,
1233 "RR type in bit map: %s (%s)",
1234 dns_type_name(rr_type),
1235 dns_long_type_name(rr_type));
1247 /* TODO: parse more record types */
1251 col_append_fstr(fd, COL_INFO, " %s", type_name);
1252 if (dns_tree != NULL) {
1253 trr = proto_tree_add_text(dns_tree, offset, (dptr - data_start) + data_len,
1254 "%s: type %s, class %s",
1255 name, type_name, class_name);
1256 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
1257 long_type_name, class_name, ttl, data_len);
1258 proto_tree_add_text(rr_tree, cur_offset, data_len, "Data");
1265 return dptr - data_start;
1269 dissect_query_records(const u_char *pd, int cur_off, int dns_data_offset,
1270 int count, frame_data *fd, proto_tree *dns_tree)
1272 int start_off, add_off;
1273 proto_tree *qatree = NULL;
1274 proto_item *ti = NULL;
1276 start_off = cur_off;
1278 ti = proto_tree_add_text(dns_tree, start_off, 0, "Queries");
1279 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1281 while (count-- > 0) {
1282 add_off = dissect_dns_query(pd, cur_off, dns_data_offset, fd, qatree);
1284 /* We ran past the end of the captured data in the packet. */
1290 proto_item_set_len(ti, cur_off - start_off);
1292 return cur_off - start_off;
1296 dissect_answer_records(const u_char *pd, int cur_off, int dns_data_offset,
1297 int count, frame_data *fd, proto_tree *dns_tree, char *name)
1299 int start_off, add_off;
1300 proto_tree *qatree = NULL;
1301 proto_item *ti = NULL;
1303 start_off = cur_off;
1305 ti = proto_tree_add_text(dns_tree, start_off, 0, name);
1306 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1308 while (count-- > 0) {
1309 add_off = dissect_dns_answer(pd, cur_off, dns_data_offset, fd, qatree);
1311 /* We ran past the end of the captured data in the packet. */
1317 proto_item_set_len(ti, cur_off - start_off);
1319 return cur_off - start_off;
1323 dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1325 int dns_data_offset;
1326 proto_tree *dns_tree = NULL, *field_tree;
1327 proto_item *ti, *tf;
1328 guint16 id, flags, quest, ans, auth, add;
1331 static const value_string opcode_vals[] = {
1332 { OPCODE_QUERY, "Standard query" },
1333 { OPCODE_IQUERY, "Inverse query" },
1334 { OPCODE_STATUS, "Server status request" },
1336 static const value_string rcode_vals[] = {
1337 { RCODE_NOERROR, "No error" },
1338 { RCODE_FMTERROR, "Format error" },
1339 { RCODE_SERVFAIL, "Server failure" },
1340 { RCODE_NAMEERROR, "Name error" },
1341 { RCODE_NOTIMPL, "Not implemented" },
1342 { RCODE_REFUSED, "Refused" },
1345 dns_data_offset = offset;
1347 if (check_col(fd, COL_PROTOCOL))
1348 col_add_str(fd, COL_PROTOCOL, "DNS");
1350 if (pi.captured_len < DNS_HDRLEN) {
1351 col_add_str(fd, COL_INFO, "Short DNS packet");
1352 dissect_data(pd, offset, fd, tree);
1356 /* To do: check for errs, etc. */
1357 id = pntohs(&pd[offset + DNS_ID]);
1358 flags = pntohs(&pd[offset + DNS_FLAGS]);
1359 quest = pntohs(&pd[offset + DNS_QUEST]);
1360 ans = pntohs(&pd[offset + DNS_ANS]);
1361 auth = pntohs(&pd[offset + DNS_AUTH]);
1362 add = pntohs(&pd[offset + DNS_ADD]);
1364 if (check_col(fd, COL_INFO)) {
1365 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation (%x)"));
1366 if (flags & F_RESPONSE) {
1367 strcat(buf, " response");
1368 if ((flags & F_RCODE) != RCODE_NOERROR) {
1370 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1371 "Unknown error (%x)"));
1374 col_add_str(fd, COL_INFO, buf);
1376 /* Set "fd" to NULL; we pass a NULL "fd" to the query and answer
1377 dissectors, as a way of saying that they shouldn't add stuff
1378 to the COL_INFO column (a call to "check_col(fd, COL_INFO)"
1379 is more expensive than a check that a pointer isn't NULL). */
1384 ti = proto_tree_add_item_format(tree, proto_dns, offset, 4, NULL,
1385 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1387 dns_tree = proto_item_add_subtree(ti, ett_dns);
1389 if (flags & F_RESPONSE)
1390 proto_tree_add_item_hidden(dns_tree, hf_dns_response, offset, 4, 1);
1392 proto_tree_add_item_hidden(dns_tree, hf_dns_query, offset, 4, 1);
1394 proto_tree_add_item(dns_tree, hf_dns_transaction_id,
1395 offset + DNS_ID, 2, id);
1397 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
1398 if (flags & F_RESPONSE) {
1399 strcat(buf, " response");
1401 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1404 tf = proto_tree_add_item_format(dns_tree, hf_dns_flags,
1405 offset + DNS_FLAGS, 2,
1407 "Flags: 0x%04x (%s)",
1409 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1410 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1411 decode_boolean_bitfield(flags, F_RESPONSE,
1412 2*8, "Response", "Query"));
1413 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1414 decode_enumerated_bitfield(flags, F_OPCODE,
1415 2*8, opcode_vals, "%s"));
1416 if (flags & F_RESPONSE) {
1417 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1418 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
1420 "Server is an authority for domain",
1421 "Server isn't an authority for domain"));
1423 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1424 decode_boolean_bitfield(flags, F_TRUNCATED,
1426 "Message is truncated",
1427 "Message is not truncated"));
1428 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1429 decode_boolean_bitfield(flags, F_RECDESIRED,
1431 "Do query recursively",
1432 "Don't do query recursively"));
1433 if (flags & F_RESPONSE) {
1434 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1435 decode_boolean_bitfield(flags, F_RECAVAIL,
1437 "Server can do recursive queries",
1438 "Server can't do recursive queries"));
1439 proto_tree_add_text(field_tree, offset + DNS_FLAGS, 2, "%s",
1440 decode_enumerated_bitfield(flags, F_RCODE,
1441 2*8, rcode_vals, "%s"));
1443 proto_tree_add_item(dns_tree, hf_dns_count_questions,
1444 offset + DNS_QUEST, 2, quest);
1445 proto_tree_add_item(dns_tree, hf_dns_count_answers,
1446 offset + DNS_ANS, 2, ans);
1447 proto_tree_add_item(dns_tree, hf_dns_count_auth_rr,
1448 offset + DNS_AUTH, 2, auth);
1449 proto_tree_add_item(dns_tree, hf_dns_count_add_rr,
1450 offset + DNS_ADD, 2, add);
1453 cur_off = offset + DNS_HDRLEN;
1456 /* If this is a response, don't add information about the queries
1457 to the summary, just add information about the answers. */
1458 cur_off += dissect_query_records(pd, cur_off, dns_data_offset, quest,
1459 (!(flags & F_RESPONSE) ? fd : NULL),
1464 /* If this is a request, don't add information about the answers
1465 to the summary, just add information about the queries. */
1466 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, ans,
1467 ((flags & F_RESPONSE) ? fd : NULL),
1468 dns_tree, "Answers");
1472 /* Don't add information about the authoritative name servers, or the
1473 additional records, to the summary. */
1475 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, auth,
1476 NULL, dns_tree, "Authoritative nameservers");
1479 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, add,
1480 NULL, dns_tree, "Additional records");
1485 proto_register_dns(void)
1487 static hf_register_info hf[] = {
1489 { "Response", "dns.response",
1490 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1491 "TRUE if DNS response" }},
1493 { "Query", "dns.query",
1494 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1495 "TRUE if DNS query" }},
1497 { "Flags", "dns.flags",
1498 FT_UINT16, BASE_HEX, NULL, 0x0,
1500 { &hf_dns_transaction_id,
1501 { "Transaction ID", "dns.id",
1502 FT_UINT16, BASE_HEX, NULL, 0x0,
1503 "Identification of transaction" }},
1504 { &hf_dns_count_questions,
1505 { "Questions", "dns.count.queries",
1506 FT_UINT16, BASE_DEC, NULL, 0x0,
1507 "Number of queries in packet" }},
1508 { &hf_dns_count_answers,
1509 { "Answer RRs", "dns.count.answers",
1510 FT_UINT16, BASE_DEC, NULL, 0x0,
1511 "Number of answers in packet" }},
1512 { &hf_dns_count_auth_rr,
1513 { "Authority RRs", "dns.count.auth_rr",
1514 FT_UINT16, BASE_DEC, NULL, 0x0,
1515 "Number of authoritative records in packet" }},
1516 { &hf_dns_count_add_rr,
1517 { "Additional RRs", "dns.count.add_rr",
1518 FT_UINT16, BASE_DEC, NULL, 0x0,
1519 "Number of additional records in packet" }}
1521 static gint *ett[] = {
1531 proto_dns = proto_register_protocol("Domain Name Service", "dns");
1532 proto_register_field_array(proto_dns, hf, array_length(hf));
1533 proto_register_subtree_array(ett, array_length(ett));