2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.53 2000/08/18 09:05:02 itojun 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>
41 #include "packet-dns.h"
42 #include "packet-ip.h"
44 static int proto_dns = -1;
45 static int hf_dns_response = -1;
46 static int hf_dns_query = -1;
47 static int hf_dns_flags = -1;
48 static int hf_dns_transaction_id = -1;
49 static int hf_dns_count_questions = -1;
50 static int hf_dns_count_answers = -1;
51 static int hf_dns_count_auth_rr = -1;
52 static int hf_dns_count_add_rr = -1;
54 static gint ett_dns = -1;
55 static gint ett_dns_qd = -1;
56 static gint ett_dns_rr = -1;
57 static gint ett_dns_qry = -1;
58 static gint ett_dns_ans = -1;
59 static gint ett_dns_flags = -1;
60 static gint ett_t_key_flags = -1;
62 /* DNS structs and definitions */
64 /* Port used for DNS. */
65 #define UDP_PORT_DNS 53
67 /* Offsets of fields in the DNS header. */
75 /* Length of DNS header. */
79 #define T_A 1 /* host address */
80 #define T_NS 2 /* authoritative name server */
81 #define T_MD 3 /* mail destination (obsolete) */
82 #define T_MF 4 /* mail forwarder (obsolete) */
83 #define T_CNAME 5 /* canonical name */
84 #define T_SOA 6 /* start of authority zone */
85 #define T_MB 7 /* mailbox domain name (experimental) */
86 #define T_MG 8 /* mail group member (experimental) */
87 #define T_MR 9 /* mail rename domain name (experimental) */
88 #define T_NULL 10 /* null RR (experimental) */
89 #define T_WKS 11 /* well known service */
90 #define T_PTR 12 /* domain name pointer */
91 #define T_HINFO 13 /* host information */
92 #define T_MINFO 14 /* mailbox or mail list information */
93 #define T_MX 15 /* mail routing information */
94 #define T_TXT 16 /* text strings */
95 #define T_RP 17 /* responsible person (RFC 1183) */
96 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
97 #define T_X25 19 /* X.25 address (RFC 1183) */
98 #define T_ISDN 20 /* ISDN address (RFC 1183) */
99 #define T_RT 21 /* route-through (RFC 1183) */
100 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
101 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
102 #define T_SIG 24 /* digital signature (RFC 2065) */
103 #define T_KEY 25 /* public key (RFC 2065) */
104 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
105 #define T_GPOS 27 /* geographical position (RFC 1712) */
106 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
107 #define T_LOC 29 /* geographical location (RFC 1876) */
108 #define T_NXT 30 /* "next" name (RFC 2065) */
109 #define T_EID 31 /* ??? (Nimrod?) */
110 #define T_NIMLOC 32 /* ??? (Nimrod?) */
111 #define T_SRV 33 /* service location (RFC 2052) */
112 #define T_ATMA 34 /* ??? */
113 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
114 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
115 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
116 #define T_WINS 65281 /* Microsoft's WINS RR */
117 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
120 #define C_IN 1 /* the Internet */
121 #define C_CS 2 /* CSNET (obsolete) */
122 #define C_CH 3 /* CHAOS */
123 #define C_HS 4 /* Hesiod */
125 /* Bit fields in the flags */
126 #define F_RESPONSE (1<<15) /* packet is response */
127 #define F_OPCODE (0xF<<11) /* query opcode */
128 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
129 #define F_TRUNCATED (1<<9) /* response is truncated */
130 #define F_RECDESIRED (1<<8) /* recursion desired */
131 #define F_RECAVAIL (1<<7) /* recursion available */
132 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
133 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
134 #define F_RCODE (0xF<<0) /* reply code */
137 #define OPCODE_QUERY (0<<11) /* standard query */
138 #define OPCODE_IQUERY (1<<11) /* inverse query */
139 #define OPCODE_STATUS (2<<11) /* server status request */
142 #define RCODE_NOERROR (0<<0)
143 #define RCODE_FMTERROR (1<<0)
144 #define RCODE_SERVFAIL (2<<0)
145 #define RCODE_NAMEERROR (3<<0)
146 #define RCODE_NOTIMPL (4<<0)
147 #define RCODE_REFUSED (5<<0)
149 /* See RFC 1035 for all RR types for which no RFC is listed, except for
150 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
151 which one should look at
153 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
157 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
159 which discuss them to some extent. */
161 dns_type_name (u_int type)
163 char *type_names[] = {
182 "AFSDB", /* RFC 1183 */
183 "X25", /* RFC 1183 */
184 "ISDN", /* RFC 1183 */
186 "NSAP", /* RFC 1706 */
187 "NSAP-PTR", /* RFC 1348 */
188 "SIG", /* RFC 2065 */
189 "KEY", /* RFC 2065 */
191 "GPOS", /* RFC 1712 */
192 "AAAA", /* RFC 1886 */
193 "LOC", /* RFC 1876 */
194 "NXT", /* RFC 2065 */
197 "SRV", /* RFC 2052 */
199 "NAPTR", /* RFC 2168 */
208 if (type < sizeof(type_names)/sizeof(type_names[0]))
209 return type_names[type] ? type_names[type] : "unknown";
230 return "IXFR"; /* RFC 1995 */
247 dns_long_type_name (u_int type)
249 char *type_names[] = {
252 "Authoritative name server",
255 "Canonical name for an alias",
256 "Start of zone of authority",
257 "Mailbox domain name",
259 "Mail rename domain name",
260 "Null resource record",
261 "Well-known service description",
262 "Domain name pointer",
264 "Mailbox or mail list information",
267 "Responsible person", /* RFC 1183 */
268 "AFS data base location", /* RFC 1183 */
269 "X.25 address", /* RFC 1183 */
270 "ISDN number", /* RFC 1183 */
271 "Route through", /* RFC 1183 */
272 "OSI NSAP", /* RFC 1706 */
273 "OSI NSAP name pointer", /* RFC 1348 */
274 "Signature", /* RFC 2065 */
275 "Public key", /* RFC 2065 */
276 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
277 "Geographical position", /* RFC 1712 */
278 "IPv6 address", /* RFC 1886 */
279 "Location", /* RFC 1876 */
280 "Next", /* RFC 2065 */
283 "Service location", /* RFC 2052 */
285 "Naming authority pointer", /* RFC 2168 */
288 "IPv6 address with indirection", /* RFC 2874 */
291 "EDNS0 option" /* RFC 2671 */
293 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%d)" */
295 if (type < sizeof(type_names)/sizeof(type_names[0]))
296 return type_names[type] ? type_names[type] : "unknown";
317 return "Request for incremental zone transfer"; /* RFC 1995 */
319 return "Request for full zone transfer";
321 return "Request for mailbox-related records";
323 return "Request for mail agent resource records";
325 return "Request for all records";
328 sprintf(unkbuf, "Unknown RR type (%d)", type);
334 dns_class_name(int class)
343 class_name = "csnet";
346 class_name = "chaos";
349 class_name = "hesiod";
352 class_name = "unknown";
359 get_dns_name(const u_char *pd, int offset, int dns_data_offset,
360 char *name, int maxname)
362 const u_char *dp = pd + offset;
363 const u_char *dptr = dp;
366 int chars_processed = 0;
367 int data_size = pi.len - dns_data_offset;
370 maxname--; /* reserve space for the trailing '\0' */
372 if (!BYTES_ARE_IN_FRAME(offset, 1))
374 component_len = *dp++;
376 if (component_len == 0)
379 switch (component_len & 0xc0) {
384 /* Not the first component - put in a '.'. */
390 if (!BYTES_ARE_IN_FRAME(offset, component_len))
392 while (component_len > 0) {
406 goto error; /* error */
410 if (!BYTES_ARE_IN_FRAME(offset, 1))
412 offset = dns_data_offset + (((component_len & ~0xc0) << 8) | (*dp++));
415 /* If "len" is negative, we are still working on the original name,
416 not something pointed to by a pointer, and so we should set "len"
417 to the length of the original name. */
421 if (offset >= pi.len) {
422 strcpy(name, "<Name contains a pointer that goes past the end of the packet>");
426 /* If we've looked at every character in the message, this pointer
427 will make us look at some character again, which means we're
429 if (chars_processed >= data_size) {
430 strcpy(name, "<Name contains a pointer that loops>");
435 break; /* now continue processing from there */
441 /* If "len" is negative, we haven't seen a pointer, and thus haven't
442 set the length, so set it. */
445 /* Zero-length name means "root server" */
447 strcpy(name, "<Root>");
451 /* We ran past the end of the captured data in the packet. */
452 strcpy(name, "<Name goes past end of captured data in packet>");
453 /* If "len" is negative, we haven't seen a pointer, and thus haven't
454 set the length, so set it. */
462 get_dns_name_type_class(const u_char *pd, int offset, int dns_data_offset,
463 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
470 int start_offset = offset;
472 name_len = get_dns_name(pd, offset, dns_data_offset, name, sizeof(name));
475 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
476 /* We ran past the end of the captured data in the packet. */
479 type = pntohs(&pd[offset]);
482 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
483 /* We ran past the end of the captured data in the packet. */
486 class = pntohs(&pd[offset]);
489 strcpy (name_ret, name);
492 *name_len_ret = name_len;
494 len = offset - start_offset;
499 rfc1867_size(u_char val)
504 size = (val & 0xF0) >> 4;
505 exponent = (val & 0x0F);
506 while (exponent != 0) {
510 return size / 100; /* return size in meters, not cm */
514 rfc1867_angle(const u_char *dptr, const char *nsew)
518 guint32 degrees, minutes, secs, tsecs;
519 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
521 angle = pntohl(dptr);
523 if (angle < 0x80000000U) {
524 angle = 0x80000000U - angle;
527 angle = angle - 0x80000000U;
530 tsecs = angle % 1000;
531 angle = angle / 1000;
534 minutes = angle % 60;
535 degrees = angle / 60;
536 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
542 dissect_dns_query(const u_char *pd, int offset, int dns_data_offset,
543 frame_data *fd, proto_tree *dns_tree)
552 char *long_type_name;
554 const u_char *data_start;
558 data_start = dptr = pd + offset;
560 len = get_dns_name_type_class(pd, offset, dns_data_offset, name, &name_len,
563 /* We ran past the end of the data in the packet. */
568 type_name = dns_type_name(type);
569 class_name = dns_class_name(class);
570 long_type_name = dns_long_type_name(type);
573 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
574 if (dns_tree != NULL) {
575 tq = proto_tree_add_text(dns_tree, NullTVB, offset, len, "%s: type %s, class %s",
576 name, type_name, class_name);
577 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
579 proto_tree_add_text(q_tree, NullTVB, offset, name_len, "Name: %s", name);
582 proto_tree_add_text(q_tree, NullTVB, offset, 2, "Type: %s", long_type_name);
585 proto_tree_add_text(q_tree, NullTVB, offset, 2, "Class: %s", class_name);
589 return dptr - data_start;
594 add_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
595 int namelen, const char *type_name, const char *class_name, u_int ttl,
600 rr_tree = proto_item_add_subtree(trr, rr_type);
601 proto_tree_add_text(rr_tree, NullTVB, offset, namelen, "Name: %s", name);
603 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Type: %s", type_name);
605 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Class: %s", class_name);
607 proto_tree_add_text(rr_tree, NullTVB, offset, 4, "Time to live: %s",
608 time_secs_to_str(ttl));
610 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Data length: %u", data_len);
615 add_opt_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
616 int namelen, const char *type_name, int class, u_int ttl, u_short data_len)
620 rr_tree = proto_item_add_subtree(trr, rr_type);
621 proto_tree_add_text(rr_tree, NullTVB, offset, namelen, "Name: %s", name);
623 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Type: %s", type_name);
625 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "UDP payload size: %u",
628 proto_tree_add_text(rr_tree, NullTVB, offset, 1, "Higher bits in extended RCODE: 0x%x",
629 (ttl >> 24) & 0xff0);
631 proto_tree_add_text(rr_tree, NullTVB, offset, 1, "EDNS0 version: %u",
634 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Must be zero: 0x%x", ttl & 0xffff);
636 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Data length: %u", data_len);
641 * SIG and KEY RR algorithms.
643 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
644 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
645 #define DNS_ALGO_DSA 3 /* DSA */
646 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
647 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
648 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
649 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
651 static const value_string algo_vals[] = {
652 { DNS_ALGO_RSAMD5, "RSA/MD5" },
653 { DNS_ALGO_DH, "Diffie-Hellman" },
654 { DNS_ALGO_DSA, "DSA" },
655 { DNS_ALGO_ECC, "Elliptic curve crypto" },
656 { DNS_ALGO_INDIRECT, "Indirect key" },
657 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
658 { DNS_ALGO_PRIVATEOID, "Private, OID" },
663 dissect_dns_answer(const u_char *pd, int offset, int dns_data_offset,
664 frame_data *fd, proto_tree *dns_tree)
673 char *long_type_name;
676 const u_char *data_start;
679 proto_tree *rr_tree = NULL;
680 proto_item *trr = NULL;
682 data_start = dptr = pd + offset;
685 len = get_dns_name_type_class(pd, offset, dns_data_offset, name, &name_len,
688 /* We ran past the end of the captured data in the packet. */
694 type_name = dns_type_name(type);
695 class_name = dns_class_name(class);
696 long_type_name = dns_long_type_name(type);
698 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
699 /* We ran past the end of the captured data in the packet. */
706 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
707 /* We ran past the end of the captured data in the packet. */
710 data_len = pntohs(dptr);
715 col_append_fstr(fd, COL_INFO, " %s", type_name);
716 if (dns_tree != NULL) {
717 trr = proto_tree_add_notext(dns_tree, NullTVB, offset,
718 (dptr - data_start) + data_len);
720 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
721 long_type_name, class_name, ttl, data_len);
723 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
724 long_type_name, class, ttl, data_len);
731 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
732 /* We ran past the end of the captured data in the packet. */
733 if (dns_tree != NULL) {
734 proto_item_set_text(trr,
735 "%s: type %s, class %s, <Address goes past end of captured data in packet>",
736 name, type_name, class_name);
741 col_append_fstr(fd, COL_INFO, " %s", ip_to_str((guint8 *)dptr));
742 if (dns_tree != NULL) {
743 proto_item_set_text(trr, "%s: type %s, class %s, addr %s",
744 name, type_name, class_name,
745 ip_to_str((guint8 *)dptr));
746 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Addr: %s",
747 ip_to_str((guint8 *)dptr));
751 memcpy(&addr, dptr, sizeof(addr));
752 add_host_name(addr, name);
758 char ns_name[MAXDNAME];
761 ns_name_len = get_dns_name(pd, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
762 if (ns_name_len < 0) {
763 /* We ran past the end of the captured data in the packet. */
764 if (dns_tree != NULL) {
765 proto_item_set_text(trr,
766 "%s: type %s, class %s, <Nameserver name goes past end of captured data in packet>",
767 name, type_name, class_name);
772 col_append_fstr(fd, COL_INFO, " %s", ns_name);
773 if (dns_tree != NULL) {
774 proto_item_set_text(trr, "%s: type %s, class %s, ns %s",
775 name, type_name, class_name, ns_name);
776 proto_tree_add_text(rr_tree, NullTVB, cur_offset, ns_name_len, "Name server: %s",
784 char cname[MAXDNAME];
787 cname_len = get_dns_name(pd, cur_offset, dns_data_offset, cname, sizeof(cname));
789 /* We ran past the end of the captured data in the packet. */
790 if (dns_tree != NULL) {
791 proto_item_set_text(trr,
792 "%s: type %s, class %s, <Primary name goes past end of captured data in packet>",
793 name, type_name, class_name);
798 col_append_fstr(fd, COL_INFO, " %s", cname);
799 if (dns_tree != NULL) {
800 proto_item_set_text(trr, "%s: type %s, class %s, cname %s",
801 name, type_name, class_name, cname);
802 proto_tree_add_text(rr_tree, NullTVB, cur_offset, cname_len, "Primary name: %s",
810 char mname[MAXDNAME];
812 char rname[MAXDNAME];
820 mname_len = get_dns_name(pd, cur_offset, dns_data_offset, mname, sizeof(mname));
822 /* We ran past the end of the captured data in the packet. */
823 if (dns_tree != NULL) {
824 proto_item_set_text(trr,
825 "%s: type %s, class %s, <mname goes past end of captured data in packet>",
826 name, type_name, class_name);
831 col_append_fstr(fd, COL_INFO, " %s", mname);
832 if (dns_tree != NULL) {
833 proto_item_set_text(trr, "%s: type %s, class %s, mname %s",
834 name, type_name, class_name, mname);
835 proto_tree_add_text(rr_tree, NullTVB, cur_offset, mname_len, "Primary name server: %s",
837 cur_offset += mname_len;
839 rname_len = get_dns_name(pd, cur_offset, dns_data_offset, rname, sizeof(rname));
841 /* We ran past the end of the captured data in the packet. */
844 proto_tree_add_text(rr_tree, NullTVB, cur_offset, rname_len, "Responsible authority's mailbox: %s",
846 cur_offset += rname_len;
848 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
849 /* We ran past the end of the captured data in the packet. */
852 serial = pntohl(&pd[cur_offset]);
853 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Serial number: %u",
857 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
858 /* We ran past the end of the captured data in the packet. */
861 refresh = pntohl(&pd[cur_offset]);
862 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Refresh interval: %s",
863 time_secs_to_str(refresh));
866 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
867 /* We ran past the end of the captured data in the packet. */
870 retry = pntohl(&pd[cur_offset]);
871 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Retry interval: %s",
872 time_secs_to_str(retry));
875 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
876 /* We ran past the end of the captured data in the packet. */
879 expire = pntohl(&pd[cur_offset]);
880 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Expiration limit: %s",
881 time_secs_to_str(expire));
884 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
885 /* We ran past the end of the captured data in the packet. */
888 minimum = pntohl(&pd[cur_offset]);
889 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Minimum TTL: %s",
890 time_secs_to_str(minimum));
897 char pname[MAXDNAME];
900 pname_len = get_dns_name(pd, cur_offset, dns_data_offset, pname, sizeof(pname));
902 /* We ran past the end of the captured data in the packet. */
903 if (dns_tree != NULL) {
904 proto_item_set_text(trr,
905 "%s: type %s, class %s, <Domain name goes past end of captured data in packet>",
906 name, type_name, class_name);
911 col_append_fstr(fd, COL_INFO, " %s", pname);
912 if (dns_tree != NULL) {
913 proto_item_set_text(trr, "%s: type %s, class %s, ptr %s",
914 name, type_name, class_name, pname);
915 proto_tree_add_text(rr_tree, NullTVB, cur_offset, pname_len, "Domain name: %s",
924 int rr_len = data_len;
930 char bitnames[128+1];
931 char portnumstring[10+1];
933 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
934 /* We ran past the end of the captured data in the packet. */
935 if (dns_tree != NULL) {
936 proto_item_set_text(trr,
937 "%s: type %s, class %s, <Address goes past end of captured data in packet>",
938 name, type_name, class_name);
943 col_append_fstr(fd, COL_INFO, " %s", ip_to_str((guint8 *)dptr));
944 if (dns_tree != NULL) {
945 proto_item_set_text(trr, "%s: type %s, class %s, addr %s",
946 name, type_name, class_name,
947 ip_to_str((guint8 *)dptr));
948 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Addr: %s",
949 ip_to_str((guint8 *)dptr));
953 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
954 /* We ran past the end of the captured data in the packet. */
955 proto_tree_add_text(rr_tree, NullTVB, cur_offset, END_OF_FRAME,
956 "<Protocol goes past end of captured data in packet>");
959 protocol = pd[cur_offset];
960 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Protocol: %s",
961 ipprotostr(protocol));
966 while (rr_len != 0) {
967 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
968 /* We ran past the end of the captured data in the packet. */
969 proto_tree_add_text(rr_tree, NullTVB, cur_offset, END_OF_FRAME,
970 "<Bit map goes past end of captured data in packet>");
973 bits = pd[cur_offset];
977 for (i = 0; i < 8; i++) {
979 if (bitnames[0] != '\0')
980 strcat(bitnames, ", ");
984 strcat(bitnames, get_tcp_port(port_num));
988 strcat(bitnames, get_udp_port(port_num));
992 sprintf(portnumstring, "%u", port_num);
993 strcat(bitnames, portnumstring);
1000 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1,
1001 "Bits: 0x%02x (%s)", bits, bitnames);
1018 cpu_offset = cur_offset;
1019 if (!BYTES_ARE_IN_FRAME(cpu_offset, 1)) {
1020 /* We ran past the end of the captured data in the packet. */
1021 if (dns_tree != NULL) {
1022 proto_item_set_text(trr,
1023 "%s: type %s, class %s, <CPU goes past end of captured data in packet>",
1024 name, type_name, class_name);
1028 cpu_len = pd[cpu_offset];
1029 if (!BYTES_ARE_IN_FRAME(cpu_offset + 1, cpu_len)) {
1030 /* We ran past the end of the captured data in the packet. */
1031 if (dns_tree != NULL) {
1032 proto_item_set_text(trr,
1033 "%s: type %s, class %s, <CPU goes past end of captured data in packet>",
1034 name, type_name, class_name);
1038 os_offset = cpu_offset + 1 + cpu_len;
1039 if (!BYTES_ARE_IN_FRAME(os_offset, 1)) {
1040 /* We ran past the end of the captured data in the packet. */
1041 if (dns_tree != NULL) {
1042 proto_item_set_text(trr,
1043 "%s: type %s, class %s, CPU %.*s, <OS goes past end of captured data in packet>",
1044 name, type_name, class_name, cpu_len, &pd[cpu_offset + 1]);
1048 os_len = pd[os_offset];
1049 if (!BYTES_ARE_IN_FRAME(os_offset + 1, os_len)) {
1050 /* We ran past the end of the captured data in the packet. */
1051 if (dns_tree != NULL) {
1052 proto_item_set_text(trr,
1053 "%s: type %s, class %s, CPU %.*s, <OS goes past end of captured data in packet>",
1054 name, type_name, class_name, cpu_len, &pd[cpu_offset + 1]);
1059 col_append_fstr(fd, COL_INFO, " %.*s %.*s", cpu_len,
1060 &pd[cpu_offset + 1], os_len, &pd[os_offset + 1]);
1061 if (dns_tree != NULL) {
1062 proto_item_set_text(trr,
1063 "%s: type %s, class %s, CPU %.*s, OS %.*s",
1064 name, type_name, class_name,
1065 cpu_len, &pd[cpu_offset + 1], os_len, &pd[os_offset + 1]);
1066 proto_tree_add_text(rr_tree, NullTVB, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1067 cpu_len, &pd[cpu_offset + 1]);
1068 proto_tree_add_text(rr_tree, NullTVB, os_offset, 1 + os_len, "OS: %.*s",
1069 os_len, &pd[os_offset + 1]);
1077 guint16 preference = 0;
1078 char mx_name[MAXDNAME];
1081 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1082 /* We ran past the end of the captured data in the packet. */
1083 if (dns_tree != NULL) {
1084 proto_item_set_text(trr,
1085 "%s: type %s, class %s, <preference goes past end of captured data in packet>",
1086 name, type_name, class_name);
1090 preference = pntohs(&pd[cur_offset]);
1091 mx_name_len = get_dns_name(pd, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1092 if (mx_name_len < 0) {
1093 /* We ran past the end of the captured data in the packet. */
1094 if (dns_tree != NULL) {
1095 proto_item_set_text(trr,
1096 "%s: type %s, class %s, preference %u, <mx goes past end of captured data in packet>",
1097 name, type_name, class_name, preference);
1102 col_append_fstr(fd, COL_INFO, " %u %s", preference, mx_name);
1103 if (dns_tree != NULL) {
1104 proto_item_set_text(trr,
1105 "%s: type %s, class %s, preference %u, mx %s",
1106 name, type_name, class_name, preference, mx_name);
1107 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Preference: %u", preference);
1108 proto_tree_add_text(rr_tree, NullTVB, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1116 int rr_len = data_len;
1120 if (dns_tree != NULL) {
1121 proto_item_set_text(trr,
1122 "%s: type %s, class %s", name, type_name, class_name);
1124 txt_offset = cur_offset;
1125 while (rr_len != 0) {
1126 if (!BYTES_ARE_IN_FRAME(txt_offset, 1)) {
1127 /* We ran past the end of the captured data in the packet. */
1128 proto_tree_add_text(rr_tree, NullTVB, txt_offset, END_OF_FRAME,
1129 "<String goes past end of captured data in packet>");
1132 txt_len = pd[txt_offset];
1133 if (!BYTES_ARE_IN_FRAME(txt_offset + 1, txt_len)) {
1134 /* We ran past the end of the captured data in the packet. */
1135 proto_tree_add_text(rr_tree, NullTVB, txt_offset, END_OF_FRAME,
1136 "<String goes past end of captured data in packet>");
1139 proto_tree_add_text(rr_tree, NullTVB, txt_offset, 1 + txt_len,
1140 "Text: %.*s", txt_len, &pd[txt_offset + 1]);
1141 txt_offset += 1 + txt_len;
1142 rr_len -= 1 + txt_len;
1150 int rr_len = data_len;
1151 struct timeval unixtime;
1152 char signer_name[MAXDNAME];
1153 int signer_name_len;
1155 if (dns_tree != NULL) {
1156 proto_item_set_text(trr,
1157 "%s: type %s, class %s", name, type_name, class_name);
1159 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1160 /* We ran past the end of the captured data in the packet. */
1163 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Type covered: %s (%s)",
1164 dns_type_name(pntohs(&pd[cur_offset])),
1165 dns_long_type_name(pntohs(&pd[cur_offset])));
1169 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1170 /* We ran past the end of the captured data in the packet. */
1173 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Algorithm: %s",
1174 val_to_str(pd[cur_offset], algo_vals,
1175 "Unknown (0x%02X)"));
1179 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1180 /* We ran past the end of the captured data in the packet. */
1183 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Labels: %u",
1188 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1189 /* We ran past the end of the captured data in the packet. */
1192 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Original TTL: %s",
1193 time_secs_to_str(pntohl(&pd[cur_offset])));
1197 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1198 /* We ran past the end of the captured data in the packet. */
1201 unixtime.tv_sec = pntohl(&pd[cur_offset]);
1202 unixtime.tv_usec = 0;
1203 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Signature expiration: %s",
1204 abs_time_to_str(&unixtime));
1208 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1209 /* We ran past the end of the captured data in the packet. */
1212 unixtime.tv_sec = pntohl(&pd[cur_offset]);
1213 unixtime.tv_usec = 0;
1214 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Time signed: %s",
1215 abs_time_to_str(&unixtime));
1219 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1220 /* We ran past the end of the captured data in the packet. */
1223 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Key footprint: 0x%04x",
1224 pntohs(&pd[cur_offset]));
1228 signer_name_len = get_dns_name(pd, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1229 if (signer_name_len < 0) {
1230 /* We ran past the end of the captured data in the packet. */
1233 proto_tree_add_text(rr_tree, NullTVB, cur_offset, signer_name_len,
1234 "Signer's name: %s", signer_name);
1235 cur_offset += signer_name_len;
1236 rr_len -= signer_name_len;
1238 proto_tree_add_text(rr_tree, NullTVB, cur_offset, rr_len, "Signature");
1245 int rr_len = data_len;
1248 proto_tree *flags_tree;
1250 if (dns_tree != NULL) {
1251 proto_item_set_text(trr,
1252 "%s: type %s, class %s", name, type_name, class_name);
1254 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1255 /* We ran past the end of the captured data in the packet. */
1258 flags = pntohs(&pd[cur_offset]);
1259 tf = proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Flags: 0x%04X", flags);
1260 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1261 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1262 decode_boolean_bitfield(flags, 0x8000,
1263 2*8, "Key prohibited for authentication",
1264 "Key allowed for authentication"));
1265 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1266 decode_boolean_bitfield(flags, 0x4000,
1267 2*8, "Key prohibited for confidentiality",
1268 "Key allowed for confidentiality"));
1269 if ((flags & 0xC000) != 0xC000) {
1271 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1272 decode_boolean_bitfield(flags, 0x2000,
1273 2*8, "Key is experimental or optional",
1274 "Key is required"));
1275 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1276 decode_boolean_bitfield(flags, 0x0400,
1277 2*8, "Key is associated with a user",
1278 "Key is not associated with a user"));
1279 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1280 decode_boolean_bitfield(flags, 0x0200,
1281 2*8, "Key is associated with the named entity",
1282 "Key is not associated with the named entity"));
1283 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1284 decode_boolean_bitfield(flags, 0x0100,
1285 2*8, "This is the zone key for the specified zone",
1286 "This is not a zone key"));
1287 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1288 decode_boolean_bitfield(flags, 0x0080,
1289 2*8, "Key is valid for use with IPSEC",
1290 "Key is not valid for use with IPSEC"));
1291 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1292 decode_boolean_bitfield(flags, 0x0040,
1293 2*8, "Key is valid for use with MIME security multiparts",
1294 "Key is not valid for use with MIME security multiparts"));
1295 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1296 decode_numeric_bitfield(flags, 0x000F,
1297 2*8, "Signatory = %u"));
1302 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1303 /* We ran past the end of the captured data in the packet. */
1306 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Protocol: %u",
1311 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1312 /* We ran past the end of the captured data in the packet. */
1315 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Algorithm: %s",
1316 val_to_str(pd[cur_offset], algo_vals,
1317 "Unknown (0x%02X)"));
1321 proto_tree_add_text(rr_tree, NullTVB, cur_offset, rr_len, "Public key");
1327 if (!BYTES_ARE_IN_FRAME(cur_offset, 16)) {
1328 /* We ran past the end of the captured data in the packet. */
1329 if (dns_tree != NULL) {
1330 proto_item_set_text(trr,
1331 "%s: type %s, class %s, <Address goes past end of captured data in packet>",
1332 name, type_name, class_name);
1337 col_append_fstr(fd, COL_INFO, " %s",
1338 ip6_to_str((struct e_in6_addr *)dptr));
1340 if (dns_tree != NULL) {
1341 proto_item_set_text(trr, "%s: type %s, class %s, addr %s",
1342 name, type_name, class_name,
1343 ip6_to_str((struct e_in6_addr *)dptr));
1344 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 16, "Addr: %s",
1345 ip6_to_str((struct e_in6_addr *)dptr));
1351 if (dns_tree != NULL) {
1352 proto_item_set_text(trr,
1353 "%s: type %s, class %s", name, type_name, class_name);
1355 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1356 /* We ran past the end of the captured data in the packet. */
1359 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Version: %u", pd[cur_offset]);
1360 if (pd[cur_offset] == 0) {
1361 /* Version 0, the only version RFC 1876 discusses. */
1364 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1365 /* We ran past the end of the captured data in the packet. */
1368 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Size: %g m",
1369 rfc1867_size(pd[cur_offset]));
1372 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1373 /* We ran past the end of the captured data in the packet. */
1376 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Horizontal precision: %g m",
1377 rfc1867_size(pd[cur_offset]));
1380 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1381 /* We ran past the end of the captured data in the packet. */
1384 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Vertical precision: %g m",
1385 rfc1867_size(pd[cur_offset]));
1388 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1389 /* We ran past the end of the captured data in the packet. */
1392 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Latitude: %s",
1393 rfc1867_angle(&pd[cur_offset], "NS"));
1396 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1397 /* We ran past the end of the captured data in the packet. */
1400 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Longitude: %s",
1401 rfc1867_angle(&pd[cur_offset], "EW"));
1404 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1405 /* We ran past the end of the captured data in the packet. */
1408 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Altitude: %g m",
1409 (pntohl(&pd[cur_offset]) - 10000000)/100.0);
1411 proto_tree_add_text(rr_tree, NullTVB, cur_offset, data_len, "Data");
1419 int rr_len = data_len;
1420 char next_domain_name[MAXDNAME];
1421 int next_domain_name_len;
1427 next_domain_name_len = get_dns_name(pd, cur_offset, dns_data_offset,
1428 next_domain_name, sizeof(next_domain_name));
1429 if (next_domain_name_len < 0) {
1430 /* We ran past the end of the captured data in the packet. */
1431 if (dns_tree != NULL) {
1432 proto_item_set_text(trr,
1433 "%s: type %s, class %s, <Next domain name goes past end of captured data in packet>",
1434 name, type_name, class_name);
1439 col_append_fstr(fd, COL_INFO, " %s", next_domain_name);
1440 if (dns_tree != NULL) {
1441 proto_item_set_text(trr, "%s: type %s, class %s, next domain name %s",
1442 name, type_name, class_name, next_domain_name);
1443 proto_tree_add_text(rr_tree, NullTVB, cur_offset, next_domain_name_len,
1444 "Next domain name: %s", next_domain_name);
1445 cur_offset += next_domain_name_len;
1446 rr_len -= next_domain_name_len;
1448 while (rr_len != 0) {
1449 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1450 /* We ran past the end of the captured data in the packet. */
1451 proto_tree_add_text(rr_tree, NullTVB, cur_offset, END_OF_FRAME,
1452 "<Bit map goes past end of captured data in packet>");
1455 bits = pd[cur_offset];
1457 for (i = 0; i < 8; i++) {
1459 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1,
1460 "RR type in bit map: %s (%s)",
1461 dns_type_name(rr_type),
1462 dns_long_type_name(rr_type));
1475 if (dns_tree != NULL) {
1476 proto_item_set_text(trr, "%s: type %s", name, type_name);
1477 proto_tree_add_text(rr_tree, NullTVB, cur_offset, data_len, "Data");
1483 int rr_len = data_len;
1485 guint32 lookup_timeout;
1486 guint32 cache_timeout;
1489 if (dns_tree != NULL) {
1490 proto_item_set_text(trr, "%s: type %s, class %s", name, type_name,
1492 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1493 /* We ran past the end of the captured data in the packet. */
1496 local_flag = pntohl(&pd[cur_offset]);
1497 if (dns_tree != NULL) {
1498 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Local flag: %s",
1499 local_flag ? "true" : "false");
1504 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1505 /* We ran past the end of the captured data in the packet. */
1508 lookup_timeout = pntohl(&pd[cur_offset]);
1509 if (dns_tree != NULL) {
1510 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Lookup timeout: %u seconds",
1516 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1517 /* We ran past the end of the captured data in the packet. */
1520 cache_timeout = pntohl(&pd[cur_offset]);
1521 if (dns_tree != NULL) {
1522 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Cache timeout: %u seconds",
1528 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1529 /* We ran past the end of the captured data in the packet. */
1532 nservers = pntohl(&pd[cur_offset]);
1533 if (dns_tree != NULL) {
1534 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Number of WINS servers: %u",
1540 while (rr_len != 0 && nservers != 0) {
1541 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1542 /* We ran past the end of the captured data in the packet. */
1545 if (dns_tree != NULL) {
1546 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "WINS server address: %s",
1547 ip_to_str((guint8 *)&pd[cur_offset]));
1559 int rr_len = data_len;
1561 guint32 lookup_timeout;
1562 guint32 cache_timeout;
1563 char dname[MAXDNAME];
1566 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1567 /* We ran past the end of the captured data in the packet. */
1568 if (dns_tree != NULL) {
1569 proto_item_set_text(trr,
1570 "%s: type %s, class %s, <Local flag goes past end of captured data in packet>",
1571 name, type_name, class_name);
1575 local_flag = pntohl(&pd[cur_offset]);
1576 if (dns_tree != NULL) {
1577 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Local flag: %s",
1578 local_flag ? "true" : "false");
1583 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1584 /* We ran past the end of the captured data in the packet. */
1585 if (dns_tree != NULL) {
1586 proto_item_set_text(trr,
1587 "%s: type %s, class %s, <Lookup timeout goes past end of captured data in packet>",
1588 name, type_name, class_name);
1592 lookup_timeout = pntohl(&pd[cur_offset]);
1593 if (dns_tree != NULL) {
1594 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Lookup timeout: %u seconds",
1600 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1601 /* We ran past the end of the captured data in the packet. */
1602 if (dns_tree != NULL) {
1603 proto_item_set_text(trr,
1604 "%s: type %s, class %s, <Cache timeout goes past end of captured data in packet>",
1605 name, type_name, class_name);
1609 cache_timeout = pntohl(&pd[cur_offset]);
1610 if (dns_tree != NULL) {
1611 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Cache timeout: %u seconds",
1617 dname_len = get_dns_name(pd, cur_offset, dns_data_offset, dname, sizeof(dname));
1618 if (dname_len < 0) {
1619 /* We ran past the end of the captured data in the packet. */
1620 if (dns_tree != NULL) {
1621 proto_item_set_text(trr,
1622 "%s: type %s, class %s, <Name result domain goes past end of captured data in packet>",
1623 name, type_name, class_name);
1628 col_append_fstr(fd, COL_INFO, " %s", dname);
1629 if (dns_tree != NULL) {
1630 proto_item_set_text(trr, "%s: type %s, class %s, name result domain %s",
1631 name, type_name, class_name, dname);
1632 proto_tree_add_text(rr_tree, NullTVB, cur_offset, dname_len, "Name result domain: %s",
1638 /* TODO: parse more record types */
1641 if (dns_tree != NULL) {
1642 proto_item_set_text(trr,
1643 "%s: type %s, class %s", name, type_name, class_name);
1644 proto_tree_add_text(rr_tree, NullTVB, cur_offset, data_len, "Data");
1651 return dptr - data_start;
1655 dissect_query_records(const u_char *pd, int cur_off, int dns_data_offset,
1656 int count, frame_data *fd, proto_tree *dns_tree)
1658 int start_off, add_off;
1659 proto_tree *qatree = NULL;
1660 proto_item *ti = NULL;
1662 start_off = cur_off;
1664 ti = proto_tree_add_text(dns_tree, NullTVB, start_off, 0, "Queries");
1665 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1667 while (count-- > 0) {
1668 add_off = dissect_dns_query(pd, cur_off, dns_data_offset, fd, qatree);
1670 /* We ran past the end of the captured data in the packet. */
1676 proto_item_set_len(ti, cur_off - start_off);
1678 return cur_off - start_off;
1682 dissect_answer_records(const u_char *pd, int cur_off, int dns_data_offset,
1683 int count, frame_data *fd, proto_tree *dns_tree, char *name)
1685 int start_off, add_off;
1686 proto_tree *qatree = NULL;
1687 proto_item *ti = NULL;
1689 start_off = cur_off;
1691 ti = proto_tree_add_text(dns_tree, NullTVB, start_off, 0, name);
1692 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1694 while (count-- > 0) {
1695 add_off = dissect_dns_answer(pd, cur_off, dns_data_offset, fd, qatree);
1697 /* We ran past the end of the captured data in the packet. */
1703 proto_item_set_len(ti, cur_off - start_off);
1705 return cur_off - start_off;
1709 dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1711 int dns_data_offset;
1712 proto_tree *dns_tree = NULL, *field_tree;
1713 proto_item *ti, *tf;
1714 guint16 id, flags, quest, ans, auth, add;
1717 static const value_string opcode_vals[] = {
1718 { OPCODE_QUERY, "Standard query" },
1719 { OPCODE_IQUERY, "Inverse query" },
1720 { OPCODE_STATUS, "Server status request" },
1722 static const value_string rcode_vals[] = {
1723 { RCODE_NOERROR, "No error" },
1724 { RCODE_FMTERROR, "Format error" },
1725 { RCODE_SERVFAIL, "Server failure" },
1726 { RCODE_NAMEERROR, "Name error" },
1727 { RCODE_NOTIMPL, "Not implemented" },
1728 { RCODE_REFUSED, "Refused" },
1731 OLD_CHECK_DISPLAY_AS_DATA(proto_dns, pd, offset, fd, tree);
1733 dns_data_offset = offset;
1735 if (check_col(fd, COL_PROTOCOL))
1736 col_add_str(fd, COL_PROTOCOL, "DNS");
1738 if (pi.captured_len < DNS_HDRLEN) {
1739 col_add_str(fd, COL_INFO, "Short DNS packet");
1740 old_dissect_data(pd, offset, fd, tree);
1744 /* To do: check for errs, etc. */
1745 id = pntohs(&pd[offset + DNS_ID]);
1746 flags = pntohs(&pd[offset + DNS_FLAGS]);
1747 quest = pntohs(&pd[offset + DNS_QUEST]);
1748 ans = pntohs(&pd[offset + DNS_ANS]);
1749 auth = pntohs(&pd[offset + DNS_AUTH]);
1750 add = pntohs(&pd[offset + DNS_ADD]);
1752 if (check_col(fd, COL_INFO)) {
1753 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation (%x)"));
1754 if (flags & F_RESPONSE) {
1755 strcat(buf, " response");
1756 if ((flags & F_RCODE) != RCODE_NOERROR) {
1758 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1759 "Unknown error (%x)"));
1762 col_add_str(fd, COL_INFO, buf);
1764 /* Set "fd" to NULL; we pass a NULL "fd" to the query and answer
1765 dissectors, as a way of saying that they shouldn't add stuff
1766 to the COL_INFO column (a call to "check_col(fd, COL_INFO)"
1767 is more expensive than a check that a pointer isn't NULL). */
1772 ti = proto_tree_add_protocol_format(tree, proto_dns, NullTVB, offset, 4,
1773 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1775 dns_tree = proto_item_add_subtree(ti, ett_dns);
1777 if (flags & F_RESPONSE)
1778 proto_tree_add_boolean_hidden(dns_tree, hf_dns_response, NullTVB, offset, 4, 1);
1780 proto_tree_add_boolean_hidden(dns_tree, hf_dns_query, NullTVB, offset, 4, 1);
1782 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, NullTVB,
1783 offset + DNS_ID, 2, id);
1785 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
1786 if (flags & F_RESPONSE) {
1787 strcat(buf, " response");
1789 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1792 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, NullTVB,
1793 offset + DNS_FLAGS, 2,
1795 "Flags: 0x%04x (%s)",
1797 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1798 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1799 decode_boolean_bitfield(flags, F_RESPONSE,
1800 2*8, "Response", "Query"));
1801 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1802 decode_enumerated_bitfield(flags, F_OPCODE,
1803 2*8, opcode_vals, "%s"));
1804 if (flags & F_RESPONSE) {
1805 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1806 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
1808 "Server is an authority for domain",
1809 "Server isn't an authority for domain"));
1811 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1812 decode_boolean_bitfield(flags, F_TRUNCATED,
1814 "Message is truncated",
1815 "Message is not truncated"));
1816 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1817 decode_boolean_bitfield(flags, F_RECDESIRED,
1819 "Do query recursively",
1820 "Don't do query recursively"));
1821 if (flags & F_RESPONSE) {
1822 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1823 decode_boolean_bitfield(flags, F_RECAVAIL,
1825 "Server can do recursive queries",
1826 "Server can't do recursive queries"));
1827 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1828 decode_boolean_bitfield(flags, F_AUTHENTIC,
1830 "Answer/authority portion was autenticated by the server",
1831 "Answer/authority portion was not autenticated by the server"));
1833 if ((flags & F_RESPONSE) == 0) {
1834 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1835 decode_boolean_bitfield(flags, F_CHECKDISABLE,
1837 "Non-authenticated data is acceptable",
1838 "Non-authenticated data is unacceptable"));
1840 if (flags & F_RESPONSE) {
1841 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
1842 decode_enumerated_bitfield(flags, F_RCODE,
1843 2*8, rcode_vals, "%s"));
1845 proto_tree_add_uint(dns_tree, hf_dns_count_questions, NullTVB,
1846 offset + DNS_QUEST, 2, quest);
1847 proto_tree_add_uint(dns_tree, hf_dns_count_answers, NullTVB,
1848 offset + DNS_ANS, 2, ans);
1849 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, NullTVB,
1850 offset + DNS_AUTH, 2, auth);
1851 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, NullTVB,
1852 offset + DNS_ADD, 2, add);
1855 cur_off = offset + DNS_HDRLEN;
1858 /* If this is a response, don't add information about the queries
1859 to the summary, just add information about the answers. */
1860 cur_off += dissect_query_records(pd, cur_off, dns_data_offset, quest,
1861 (!(flags & F_RESPONSE) ? fd : NULL),
1866 /* If this is a request, don't add information about the answers
1867 to the summary, just add information about the queries. */
1868 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, ans,
1869 ((flags & F_RESPONSE) ? fd : NULL),
1870 dns_tree, "Answers");
1874 /* Don't add information about the authoritative name servers, or the
1875 additional records, to the summary. */
1877 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, auth,
1878 NULL, dns_tree, "Authoritative nameservers");
1881 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, add,
1882 NULL, dns_tree, "Additional records");
1887 proto_register_dns(void)
1889 static hf_register_info hf[] = {
1891 { "Response", "dns.response",
1892 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1893 "TRUE if DNS response" }},
1895 { "Query", "dns.query",
1896 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1897 "TRUE if DNS query" }},
1899 { "Flags", "dns.flags",
1900 FT_UINT16, BASE_HEX, NULL, 0x0,
1902 { &hf_dns_transaction_id,
1903 { "Transaction ID", "dns.id",
1904 FT_UINT16, BASE_HEX, NULL, 0x0,
1905 "Identification of transaction" }},
1906 { &hf_dns_count_questions,
1907 { "Questions", "dns.count.queries",
1908 FT_UINT16, BASE_DEC, NULL, 0x0,
1909 "Number of queries in packet" }},
1910 { &hf_dns_count_answers,
1911 { "Answer RRs", "dns.count.answers",
1912 FT_UINT16, BASE_DEC, NULL, 0x0,
1913 "Number of answers in packet" }},
1914 { &hf_dns_count_auth_rr,
1915 { "Authority RRs", "dns.count.auth_rr",
1916 FT_UINT16, BASE_DEC, NULL, 0x0,
1917 "Number of authoritative records in packet" }},
1918 { &hf_dns_count_add_rr,
1919 { "Additional RRs", "dns.count.add_rr",
1920 FT_UINT16, BASE_DEC, NULL, 0x0,
1921 "Number of additional records in packet" }}
1923 static gint *ett[] = {
1933 proto_dns = proto_register_protocol("Domain Name Service", "dns");
1934 proto_register_field_array(proto_dns, hf, array_length(hf));
1935 proto_register_subtree_array(ett, array_length(ett));
1939 proto_reg_handoff_dns(void)
1941 old_dissector_add("udp.port", UDP_PORT_DNS, dissect_dns);