2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.60 2001/01/03 06:55:27 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>
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 /* Ports used for DNS. */
65 #define UDP_PORT_DNS 53
66 #define TCP_PORT_DNS 53
68 /* Offsets of fields in the DNS header. */
76 /* Length of DNS header. */
80 #define T_A 1 /* host address */
81 #define T_NS 2 /* authoritative name server */
82 #define T_MD 3 /* mail destination (obsolete) */
83 #define T_MF 4 /* mail forwarder (obsolete) */
84 #define T_CNAME 5 /* canonical name */
85 #define T_SOA 6 /* start of authority zone */
86 #define T_MB 7 /* mailbox domain name (experimental) */
87 #define T_MG 8 /* mail group member (experimental) */
88 #define T_MR 9 /* mail rename domain name (experimental) */
89 #define T_NULL 10 /* null RR (experimental) */
90 #define T_WKS 11 /* well known service */
91 #define T_PTR 12 /* domain name pointer */
92 #define T_HINFO 13 /* host information */
93 #define T_MINFO 14 /* mailbox or mail list information */
94 #define T_MX 15 /* mail routing information */
95 #define T_TXT 16 /* text strings */
96 #define T_RP 17 /* responsible person (RFC 1183) */
97 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
98 #define T_X25 19 /* X.25 address (RFC 1183) */
99 #define T_ISDN 20 /* ISDN address (RFC 1183) */
100 #define T_RT 21 /* route-through (RFC 1183) */
101 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
102 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
103 #define T_SIG 24 /* digital signature (RFC 2535) */
104 #define T_KEY 25 /* public key (RFC 2535) */
105 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
106 #define T_GPOS 27 /* geographical position (RFC 1712) */
107 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
108 #define T_LOC 29 /* geographical location (RFC 1876) */
109 #define T_NXT 30 /* "next" name (RFC 2535) */
110 #define T_EID 31 /* ??? (Nimrod?) */
111 #define T_NIMLOC 32 /* ??? (Nimrod?) */
112 #define T_SRV 33 /* service location (RFC 2052) */
113 #define T_ATMA 34 /* ??? */
114 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
115 #define T_KX 36 /* Key Exchange (RFC 2230) */
116 #define T_CERT 37 /* Certificate (RFC 2538) */
117 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
118 #define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
119 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
120 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
121 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
122 #define T_WINS 65281 /* Microsoft's WINS RR */
123 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
126 #define C_IN 1 /* the Internet */
127 #define C_CS 2 /* CSNET (obsolete) */
128 #define C_CH 3 /* CHAOS */
129 #define C_HS 4 /* Hesiod */
130 #define C_NONE 254 /* none */
131 #define C_ANY 255 /* any */
133 /* Bit fields in the flags */
134 #define F_RESPONSE (1<<15) /* packet is response */
135 #define F_OPCODE (0xF<<11) /* query opcode */
136 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
137 #define F_TRUNCATED (1<<9) /* response is truncated */
138 #define F_RECDESIRED (1<<8) /* recursion desired */
139 #define F_RECAVAIL (1<<7) /* recursion available */
140 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
141 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
142 #define F_RCODE (0xF<<0) /* reply code */
145 #define OPCODE_QUERY (0<<11) /* standard query */
146 #define OPCODE_IQUERY (1<<11) /* inverse query */
147 #define OPCODE_STATUS (2<<11) /* server status request */
148 #define OPCODE_NOTIFY (4<<11) /* zone change notification */
149 #define OPCODE_UPDATE (5<<11) /* dynamic update */
152 #define RCODE_NOERROR (0<<0)
153 #define RCODE_FORMERR (1<<0)
154 #define RCODE_SERVFAIL (2<<0)
155 #define RCODE_NXDOMAIN (3<<0)
156 #define RCODE_NOTIMPL (4<<0)
157 #define RCODE_REFUSED (5<<0)
158 #define RCODE_YXDOMAIN (6<<0)
159 #define RCODE_YXRRSET (7<<0)
160 #define RCODE_NXRRSET (8<<0)
161 #define RCODE_NOTAUTH (9<<0)
162 #define RCODE_NOTZONE (10<<0)
164 static const value_string rcode_vals[] = {
165 { RCODE_NOERROR, "No error" },
166 { RCODE_FORMERR, "Format error" },
167 { RCODE_SERVFAIL, "Server failure" },
168 { RCODE_NXDOMAIN, "No such name" },
169 { RCODE_NOTIMPL, "Not implemented" },
170 { RCODE_REFUSED, "Refused" },
171 { RCODE_YXDOMAIN, "Name exists" },
172 { RCODE_YXRRSET, "RRset exists" },
173 { RCODE_NXRRSET, "RRset does not exist" },
174 { RCODE_NOTAUTH, "Not authoritative" },
175 { RCODE_NOTZONE, "Name out of zone" },
178 /* TSIG/TKEY extended errors */
179 #define TSIGERROR_BADSIG (16)
180 #define TSIGERROR_BADKEY (17)
181 #define TSIGERROR_BADTIME (18)
182 #define TSIGERROR_BADMODE (19)
183 #define TSIGERROR_BADNAME (20)
184 #define TSIGERROR_BADALG (21)
186 static const value_string tsigerror_vals[] = {
187 { TSIGERROR_BADSIG, "Bad signature" },
188 { TSIGERROR_BADKEY, "Bad key" },
189 { TSIGERROR_BADTIME, "Bad time failure" },
190 { TSIGERROR_BADMODE, "Bad mode such name" },
191 { TSIGERROR_BADNAME, "Bad name implemented" },
192 { TSIGERROR_BADALG, "Bad algorithm" },
195 #define TKEYMODE_SERVERASSIGNED (1)
196 #define TKEYMODE_DIFFIEHELLMAN (2)
197 #define TKEYMODE_GSSAPI (3)
198 #define TKEYMODE_RESOLVERASSIGNED (4)
199 #define TKEYMODE_DELETE (5)
201 /* See RFC 1035 for all RR types for which no RFC is listed, except for
202 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
203 which one should look at
205 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
209 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
211 which discuss them to some extent. */
213 dns_type_name (u_int type)
215 char *type_names[] = {
234 "AFSDB", /* RFC 1183 */
235 "X25", /* RFC 1183 */
236 "ISDN", /* RFC 1183 */
238 "NSAP", /* RFC 1706 */
239 "NSAP-PTR", /* RFC 1348 */
240 "SIG", /* RFC 2535 */
241 "KEY", /* RFC 2535 */
243 "GPOS", /* RFC 1712 */
244 "AAAA", /* RFC 1886 */
245 "LOC", /* RFC 1876 */
246 "NXT", /* RFC 2535 */
249 "SRV", /* RFC 2052 */
251 "NAPTR", /* RFC 2168 */
253 "CERT", /* RFC 2538 */
255 "DNAME", /* RFC 2672 */
260 if (type < sizeof(type_names)/sizeof(type_names[0]))
261 return type_names[type] ? type_names[type] : "unknown";
288 return "IXFR"; /* RFC 1995 */
305 dns_long_type_name (u_int type)
307 char *type_names[] = {
310 "Authoritative name server",
313 "Canonical name for an alias",
314 "Start of zone of authority",
315 "Mailbox domain name",
317 "Mail rename domain name",
318 "Null resource record",
319 "Well-known service description",
320 "Domain name pointer",
322 "Mailbox or mail list information",
325 "Responsible person", /* RFC 1183 */
326 "AFS data base location", /* RFC 1183 */
327 "X.25 address", /* RFC 1183 */
328 "ISDN number", /* RFC 1183 */
329 "Route through", /* RFC 1183 */
330 "OSI NSAP", /* RFC 1706 */
331 "OSI NSAP name pointer", /* RFC 1348 */
332 "Signature", /* RFC 2535 */
333 "Public key", /* RFC 2535 */
334 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
335 "Geographical position", /* RFC 1712 */
336 "IPv6 address", /* RFC 1886 */
337 "Location", /* RFC 1876 */
338 "Next", /* RFC 2535 */
341 "Service location", /* RFC 2052 */
343 "Naming authority pointer", /* RFC 2168 */
344 "Key Exchange", /* RFC 2230 */
345 "Certificate", /* RFC 2538 */
346 "IPv6 address with indirection", /* RFC 2874 */
347 "Non-terminal DNS name redirection", /* RFC 2672 */
349 "EDNS0 option" /* RFC 2671 */
351 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%d)" */
353 if (type < sizeof(type_names)/sizeof(type_names[0]))
354 return type_names[type] ? type_names[type] : "unknown";
375 return "Transaction Key";
377 return "Transaction Signature";
381 return "Request for incremental zone transfer"; /* RFC 1995 */
383 return "Request for full zone transfer";
385 return "Request for mailbox-related records";
387 return "Request for mail agent resource records";
389 return "Request for all records";
392 sprintf(unkbuf, "Unknown RR type (%d)", type);
398 dns_class_name(int class)
407 class_name = "csnet";
410 class_name = "chaos";
413 class_name = "hesiod";
422 class_name = "unknown";
429 get_dns_name(const u_char *pd, int offset, int dns_data_offset,
430 char *name, int maxname)
432 const u_char *dp = pd + offset;
433 const u_char *dptr = dp;
436 int chars_processed = 0;
437 int data_size = pi.len - dns_data_offset;
440 maxname--; /* reserve space for the trailing '\0' */
442 if (!BYTES_ARE_IN_FRAME(offset, 1))
444 component_len = *dp++;
446 if (component_len == 0)
449 switch (component_len & 0xc0) {
454 /* Not the first component - put in a '.'. */
460 if (!BYTES_ARE_IN_FRAME(offset, component_len))
462 while (component_len > 0) {
475 /* Extended label (RFC 2673) */
476 switch (component_len & 0x3f) {
479 /* Bitstring label */
485 label_len = (bit_count - 1) / 8 + 1;
487 np += sprintf(np, "\\[x");
489 np += sprintf(np, "%02x", *dp++);
491 np += sprintf(np, "/%d]", bit_count);
496 strcpy(name, "<Unknown extended label>");
497 /* Parsing will propably fail from here on, since the */
498 /* label length is unknown... */
504 goto error; /* error */
508 if (!BYTES_ARE_IN_FRAME(offset, 1))
510 offset = dns_data_offset + (((component_len & ~0xc0) << 8) | (*dp++));
513 /* If "len" is negative, we are still working on the original name,
514 not something pointed to by a pointer, and so we should set "len"
515 to the length of the original name. */
519 if (offset >= pi.len) {
520 strcpy(name, "<Name contains a pointer that goes past the end of the packet>");
524 /* If we've looked at every character in the message, this pointer
525 will make us look at some character again, which means we're
527 if (chars_processed >= data_size) {
528 strcpy(name, "<Name contains a pointer that loops>");
533 break; /* now continue processing from there */
539 /* If "len" is negative, we haven't seen a pointer, and thus haven't
540 set the length, so set it. */
543 /* Zero-length name means "root server" */
545 strcpy(name, "<Root>");
549 /* We ran past the end of the captured data in the packet. */
550 strcpy(name, "<Name goes past end of captured data in packet>");
551 /* If "len" is negative, we haven't seen a pointer, and thus haven't
552 set the length, so set it. */
560 get_dns_name_type_class(const u_char *pd, int offset, int dns_data_offset,
561 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
568 int start_offset = offset;
570 name_len = get_dns_name(pd, offset, dns_data_offset, name, sizeof(name));
573 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
574 /* We ran past the end of the captured data in the packet. */
577 type = pntohs(&pd[offset]);
580 if (!BYTES_ARE_IN_FRAME(offset, 2)) {
581 /* We ran past the end of the captured data in the packet. */
584 class = pntohs(&pd[offset]);
587 strcpy (name_ret, name);
590 *name_len_ret = name_len;
592 len = offset - start_offset;
597 rfc1867_size(u_char val)
602 size = (val & 0xF0) >> 4;
603 exponent = (val & 0x0F);
604 while (exponent != 0) {
608 return size / 100; /* return size in meters, not cm */
612 rfc1867_angle(const u_char *dptr, const char *nsew)
616 guint32 degrees, minutes, secs, tsecs;
617 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
619 angle = pntohl(dptr);
621 if (angle < 0x80000000U) {
622 angle = 0x80000000U - angle;
625 angle = angle - 0x80000000U;
628 tsecs = angle % 1000;
629 angle = angle / 1000;
632 minutes = angle % 60;
633 degrees = angle / 60;
634 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
640 dissect_dns_query(const u_char *pd, int offset, int dns_data_offset,
641 frame_data *fd, proto_tree *dns_tree)
650 char *long_type_name;
652 const u_char *data_start;
656 data_start = dptr = pd + offset;
658 len = get_dns_name_type_class(pd, offset, dns_data_offset, name, &name_len,
661 /* We ran past the end of the data in the packet. */
666 type_name = dns_type_name(type);
667 class_name = dns_class_name(class);
668 long_type_name = dns_long_type_name(type);
671 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
672 if (dns_tree != NULL) {
673 tq = proto_tree_add_text(dns_tree, NullTVB, offset, len, "%s: type %s, class %s",
674 name, type_name, class_name);
675 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
677 proto_tree_add_text(q_tree, NullTVB, offset, name_len, "Name: %s", name);
680 proto_tree_add_text(q_tree, NullTVB, offset, 2, "Type: %s", long_type_name);
683 proto_tree_add_text(q_tree, NullTVB, offset, 2, "Class: %s", class_name);
687 return dptr - data_start;
692 add_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
693 int namelen, const char *type_name, const char *class_name, u_int ttl,
698 rr_tree = proto_item_add_subtree(trr, rr_type);
699 proto_tree_add_text(rr_tree, NullTVB, offset, namelen, "Name: %s", name);
701 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Type: %s", type_name);
703 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Class: %s", class_name);
705 proto_tree_add_text(rr_tree, NullTVB, offset, 4, "Time to live: %s",
706 time_secs_to_str(ttl));
708 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Data length: %u", data_len);
713 add_opt_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
714 int namelen, const char *type_name, int class, u_int ttl, u_short data_len)
718 rr_tree = proto_item_add_subtree(trr, rr_type);
719 proto_tree_add_text(rr_tree, NullTVB, offset, namelen, "Name: %s", name);
721 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Type: %s", type_name);
723 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "UDP payload size: %u",
726 proto_tree_add_text(rr_tree, NullTVB, offset, 1, "Higher bits in extended RCODE: 0x%x",
727 (ttl >> 24) & 0xff0);
729 proto_tree_add_text(rr_tree, NullTVB, offset, 1, "EDNS0 version: %u",
732 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Must be zero: 0x%x", ttl & 0xffff);
734 proto_tree_add_text(rr_tree, NullTVB, offset, 2, "Data length: %u", data_len);
739 * SIG, KEY, and CERT RR algorithms.
741 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
742 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
743 #define DNS_ALGO_DSA 3 /* DSA */
744 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
745 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
746 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
747 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
749 static const value_string algo_vals[] = {
750 { DNS_ALGO_RSAMD5, "RSA/MD5" },
751 { DNS_ALGO_DH, "Diffie-Hellman" },
752 { DNS_ALGO_DSA, "DSA" },
753 { DNS_ALGO_ECC, "Elliptic curve crypto" },
754 { DNS_ALGO_INDIRECT, "Indirect key" },
755 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
756 { DNS_ALGO_PRIVATEOID, "Private, OID" },
760 #define DNS_CERT_PGP 1 /* PGP */
761 #define DNS_CERT_PKIX 2 /* PKIX */
762 #define DNS_CERT_SPKI 3 /* SPKI */
763 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
764 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
766 static const value_string cert_vals[] = {
767 { DNS_CERT_PGP, "PGP" },
768 { DNS_CERT_PKIX, "PKIX" },
769 { DNS_CERT_SPKI, "SPKI" },
770 { DNS_CERT_PRIVATEURI, "Private, URI" },
771 { DNS_CERT_PRIVATEOID, "Private, OID" },
776 dissect_dns_answer(const u_char *pd, int offset, int dns_data_offset,
777 frame_data *fd, proto_tree *dns_tree)
786 char *long_type_name;
789 const u_char *data_start;
792 proto_tree *rr_tree = NULL;
793 proto_item *trr = NULL;
795 data_start = dptr = pd + offset;
798 len = get_dns_name_type_class(pd, offset, dns_data_offset, name, &name_len,
801 /* We ran past the end of the captured data in the packet. */
807 type_name = dns_type_name(type);
808 class_name = dns_class_name(class);
809 long_type_name = dns_long_type_name(type);
811 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
812 /* We ran past the end of the captured data in the packet. */
819 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
820 /* We ran past the end of the captured data in the packet. */
823 data_len = pntohs(dptr);
828 col_append_fstr(fd, COL_INFO, " %s", type_name);
829 if (dns_tree != NULL) {
830 trr = proto_tree_add_notext(dns_tree, NullTVB, offset,
831 (dptr - data_start) + data_len);
833 rr_tree = add_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
834 long_type_name, class_name, ttl, data_len);
836 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, offset, name, name_len,
837 long_type_name, class, ttl, data_len);
844 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
845 /* We ran past the end of the captured data in the packet. */
846 if (dns_tree != NULL) {
847 proto_item_set_text(trr,
848 "%s: type %s, class %s, <Address goes past end of captured data in packet>",
849 name, type_name, class_name);
854 col_append_fstr(fd, COL_INFO, " %s", ip_to_str((guint8 *)dptr));
855 if (dns_tree != NULL) {
856 proto_item_set_text(trr, "%s: type %s, class %s, addr %s",
857 name, type_name, class_name,
858 ip_to_str((guint8 *)dptr));
859 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Addr: %s",
860 ip_to_str((guint8 *)dptr));
864 memcpy(&addr, dptr, sizeof(addr));
865 add_host_name(addr, name);
871 char ns_name[MAXDNAME];
874 ns_name_len = get_dns_name(pd, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
875 if (ns_name_len < 0) {
876 /* We ran past the end of the captured data in the packet. */
877 if (dns_tree != NULL) {
878 proto_item_set_text(trr,
879 "%s: type %s, class %s, <Nameserver name goes past end of captured data in packet>",
880 name, type_name, class_name);
885 col_append_fstr(fd, COL_INFO, " %s", ns_name);
886 if (dns_tree != NULL) {
887 proto_item_set_text(trr, "%s: type %s, class %s, ns %s",
888 name, type_name, class_name, ns_name);
889 proto_tree_add_text(rr_tree, NullTVB, cur_offset, ns_name_len, "Name server: %s",
897 char cname[MAXDNAME];
900 cname_len = get_dns_name(pd, cur_offset, dns_data_offset, cname, sizeof(cname));
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, <Primary name goes past end of captured data in packet>",
906 name, type_name, class_name);
911 col_append_fstr(fd, COL_INFO, " %s", cname);
912 if (dns_tree != NULL) {
913 proto_item_set_text(trr, "%s: type %s, class %s, cname %s",
914 name, type_name, class_name, cname);
915 proto_tree_add_text(rr_tree, NullTVB, cur_offset, cname_len, "Primary name: %s",
923 char mname[MAXDNAME];
925 char rname[MAXDNAME];
933 mname_len = get_dns_name(pd, cur_offset, dns_data_offset, mname, sizeof(mname));
935 /* We ran past the end of the captured data in the packet. */
936 if (dns_tree != NULL) {
937 proto_item_set_text(trr,
938 "%s: type %s, class %s, <mname goes past end of captured data in packet>",
939 name, type_name, class_name);
944 col_append_fstr(fd, COL_INFO, " %s", mname);
945 if (dns_tree != NULL) {
946 proto_item_set_text(trr, "%s: type %s, class %s, mname %s",
947 name, type_name, class_name, mname);
948 proto_tree_add_text(rr_tree, NullTVB, cur_offset, mname_len, "Primary name server: %s",
950 cur_offset += mname_len;
952 rname_len = get_dns_name(pd, cur_offset, dns_data_offset, rname, sizeof(rname));
954 /* We ran past the end of the captured data in the packet. */
957 proto_tree_add_text(rr_tree, NullTVB, cur_offset, rname_len, "Responsible authority's mailbox: %s",
959 cur_offset += rname_len;
961 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
962 /* We ran past the end of the captured data in the packet. */
965 serial = pntohl(&pd[cur_offset]);
966 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Serial number: %u",
970 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
971 /* We ran past the end of the captured data in the packet. */
974 refresh = pntohl(&pd[cur_offset]);
975 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Refresh interval: %s",
976 time_secs_to_str(refresh));
979 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
980 /* We ran past the end of the captured data in the packet. */
983 retry = pntohl(&pd[cur_offset]);
984 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Retry interval: %s",
985 time_secs_to_str(retry));
988 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
989 /* We ran past the end of the captured data in the packet. */
992 expire = pntohl(&pd[cur_offset]);
993 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Expiration limit: %s",
994 time_secs_to_str(expire));
997 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
998 /* We ran past the end of the captured data in the packet. */
1001 minimum = pntohl(&pd[cur_offset]);
1002 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Minimum TTL: %s",
1003 time_secs_to_str(minimum));
1010 char pname[MAXDNAME];
1013 pname_len = get_dns_name(pd, cur_offset, dns_data_offset, pname, sizeof(pname));
1014 if (pname_len < 0) {
1015 /* We ran past the end of the captured data in the packet. */
1016 if (dns_tree != NULL) {
1017 proto_item_set_text(trr,
1018 "%s: type %s, class %s, <Domain name goes past end of captured data in packet>",
1019 name, type_name, class_name);
1024 col_append_fstr(fd, COL_INFO, " %s", pname);
1025 if (dns_tree != NULL) {
1026 proto_item_set_text(trr, "%s: type %s, class %s, ptr %s",
1027 name, type_name, class_name, pname);
1028 proto_tree_add_text(rr_tree, NullTVB, cur_offset, pname_len, "Domain name: %s",
1037 int rr_len = data_len;
1043 char bitnames[128+1];
1044 char portnumstring[10+1];
1046 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1047 /* We ran past the end of the captured data in the packet. */
1048 if (dns_tree != NULL) {
1049 proto_item_set_text(trr,
1050 "%s: type %s, class %s, <Address goes past end of captured data in packet>",
1051 name, type_name, class_name);
1056 col_append_fstr(fd, COL_INFO, " %s", ip_to_str((guint8 *)dptr));
1057 if (dns_tree != NULL) {
1058 proto_item_set_text(trr, "%s: type %s, class %s, addr %s",
1059 name, type_name, class_name,
1060 ip_to_str((guint8 *)dptr));
1061 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Addr: %s",
1062 ip_to_str((guint8 *)dptr));
1066 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1067 /* We ran past the end of the captured data in the packet. */
1068 proto_tree_add_text(rr_tree, NullTVB, cur_offset, END_OF_FRAME,
1069 "<Protocol goes past end of captured data in packet>");
1072 protocol = pd[cur_offset];
1073 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Protocol: %s",
1074 ipprotostr(protocol));
1079 while (rr_len != 0) {
1080 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1081 /* We ran past the end of the captured data in the packet. */
1082 proto_tree_add_text(rr_tree, NullTVB, cur_offset, END_OF_FRAME,
1083 "<Bit map goes past end of captured data in packet>");
1086 bits = pd[cur_offset];
1090 for (i = 0; i < 8; i++) {
1092 if (bitnames[0] != '\0')
1093 strcat(bitnames, ", ");
1097 strcat(bitnames, get_tcp_port(port_num));
1101 strcat(bitnames, get_udp_port(port_num));
1105 sprintf(portnumstring, "%u", port_num);
1106 strcat(bitnames, portnumstring);
1113 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1,
1114 "Bits: 0x%02x (%s)", bits, bitnames);
1131 cpu_offset = cur_offset;
1132 if (!BYTES_ARE_IN_FRAME(cpu_offset, 1)) {
1133 /* We ran past the end of the captured data in the packet. */
1134 if (dns_tree != NULL) {
1135 proto_item_set_text(trr,
1136 "%s: type %s, class %s, <CPU goes past end of captured data in packet>",
1137 name, type_name, class_name);
1141 cpu_len = pd[cpu_offset];
1142 if (!BYTES_ARE_IN_FRAME(cpu_offset + 1, cpu_len)) {
1143 /* We ran past the end of the captured data in the packet. */
1144 if (dns_tree != NULL) {
1145 proto_item_set_text(trr,
1146 "%s: type %s, class %s, <CPU goes past end of captured data in packet>",
1147 name, type_name, class_name);
1151 os_offset = cpu_offset + 1 + cpu_len;
1152 if (!BYTES_ARE_IN_FRAME(os_offset, 1)) {
1153 /* We ran past the end of the captured data in the packet. */
1154 if (dns_tree != NULL) {
1155 proto_item_set_text(trr,
1156 "%s: type %s, class %s, CPU %.*s, <OS goes past end of captured data in packet>",
1157 name, type_name, class_name, cpu_len, &pd[cpu_offset + 1]);
1161 os_len = pd[os_offset];
1162 if (!BYTES_ARE_IN_FRAME(os_offset + 1, os_len)) {
1163 /* We ran past the end of the captured data in the packet. */
1164 if (dns_tree != NULL) {
1165 proto_item_set_text(trr,
1166 "%s: type %s, class %s, CPU %.*s, <OS goes past end of captured data in packet>",
1167 name, type_name, class_name, cpu_len, &pd[cpu_offset + 1]);
1172 col_append_fstr(fd, COL_INFO, " %.*s %.*s", cpu_len,
1173 &pd[cpu_offset + 1], os_len, &pd[os_offset + 1]);
1174 if (dns_tree != NULL) {
1175 proto_item_set_text(trr,
1176 "%s: type %s, class %s, CPU %.*s, OS %.*s",
1177 name, type_name, class_name,
1178 cpu_len, &pd[cpu_offset + 1], os_len, &pd[os_offset + 1]);
1179 proto_tree_add_text(rr_tree, NullTVB, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1180 cpu_len, &pd[cpu_offset + 1]);
1181 proto_tree_add_text(rr_tree, NullTVB, os_offset, 1 + os_len, "OS: %.*s",
1182 os_len, &pd[os_offset + 1]);
1190 guint16 preference = 0;
1191 char mx_name[MAXDNAME];
1194 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1195 /* We ran past the end of the captured data in the packet. */
1196 if (dns_tree != NULL) {
1197 proto_item_set_text(trr,
1198 "%s: type %s, class %s, <preference goes past end of captured data in packet>",
1199 name, type_name, class_name);
1203 preference = pntohs(&pd[cur_offset]);
1204 mx_name_len = get_dns_name(pd, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1205 if (mx_name_len < 0) {
1206 /* We ran past the end of the captured data in the packet. */
1207 if (dns_tree != NULL) {
1208 proto_item_set_text(trr,
1209 "%s: type %s, class %s, preference %u, <mx goes past end of captured data in packet>",
1210 name, type_name, class_name, preference);
1215 col_append_fstr(fd, COL_INFO, " %u %s", preference, mx_name);
1216 if (dns_tree != NULL) {
1217 proto_item_set_text(trr,
1218 "%s: type %s, class %s, preference %u, mx %s",
1219 name, type_name, class_name, preference, mx_name);
1220 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Preference: %u", preference);
1221 proto_tree_add_text(rr_tree, NullTVB, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1229 int rr_len = data_len;
1233 if (dns_tree != NULL) {
1234 proto_item_set_text(trr,
1235 "%s: type %s, class %s", name, type_name, class_name);
1237 txt_offset = cur_offset;
1238 while (rr_len != 0) {
1239 if (!BYTES_ARE_IN_FRAME(txt_offset, 1)) {
1240 /* We ran past the end of the captured data in the packet. */
1241 proto_tree_add_text(rr_tree, NullTVB, txt_offset, END_OF_FRAME,
1242 "<String goes past end of captured data in packet>");
1245 txt_len = pd[txt_offset];
1246 if (!BYTES_ARE_IN_FRAME(txt_offset + 1, txt_len)) {
1247 /* We ran past the end of the captured data in the packet. */
1248 proto_tree_add_text(rr_tree, NullTVB, txt_offset, END_OF_FRAME,
1249 "<String goes past end of captured data in packet>");
1252 proto_tree_add_text(rr_tree, NullTVB, txt_offset, 1 + txt_len,
1253 "Text: %.*s", txt_len, &pd[txt_offset + 1]);
1254 txt_offset += 1 + txt_len;
1255 rr_len -= 1 + txt_len;
1263 int rr_len = data_len;
1264 struct timeval unixtime;
1265 char signer_name[MAXDNAME];
1266 int signer_name_len;
1268 if (dns_tree != NULL) {
1269 proto_item_set_text(trr,
1270 "%s: type %s, class %s", name, type_name, class_name);
1272 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1273 /* We ran past the end of the captured data in the packet. */
1276 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Type covered: %s (%s)",
1277 dns_type_name(pntohs(&pd[cur_offset])),
1278 dns_long_type_name(pntohs(&pd[cur_offset])));
1282 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1283 /* We ran past the end of the captured data in the packet. */
1286 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Algorithm: %s",
1287 val_to_str(pd[cur_offset], algo_vals,
1288 "Unknown (0x%02X)"));
1292 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1293 /* We ran past the end of the captured data in the packet. */
1296 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Labels: %u",
1301 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1302 /* We ran past the end of the captured data in the packet. */
1305 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Original TTL: %s",
1306 time_secs_to_str(pntohl(&pd[cur_offset])));
1310 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1311 /* We ran past the end of the captured data in the packet. */
1314 unixtime.tv_sec = pntohl(&pd[cur_offset]);
1315 unixtime.tv_usec = 0;
1316 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Signature expiration: %s",
1317 abs_time_to_str(&unixtime));
1321 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1322 /* We ran past the end of the captured data in the packet. */
1325 unixtime.tv_sec = pntohl(&pd[cur_offset]);
1326 unixtime.tv_usec = 0;
1327 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Time signed: %s",
1328 abs_time_to_str(&unixtime));
1332 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1333 /* We ran past the end of the captured data in the packet. */
1336 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Key footprint: 0x%04x",
1337 pntohs(&pd[cur_offset]));
1341 signer_name_len = get_dns_name(pd, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1342 if (signer_name_len < 0) {
1343 /* We ran past the end of the captured data in the packet. */
1346 proto_tree_add_text(rr_tree, NullTVB, cur_offset, signer_name_len,
1347 "Signer's name: %s", signer_name);
1348 cur_offset += signer_name_len;
1349 rr_len -= signer_name_len;
1351 proto_tree_add_text(rr_tree, NullTVB, cur_offset, rr_len, "Signature");
1358 int rr_len = data_len;
1361 proto_tree *flags_tree;
1363 if (dns_tree != NULL) {
1364 proto_item_set_text(trr,
1365 "%s: type %s, class %s", name, type_name, class_name);
1367 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1368 /* We ran past the end of the captured data in the packet. */
1371 flags = pntohs(&pd[cur_offset]);
1372 tf = proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Flags: 0x%04X", flags);
1373 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1374 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1375 decode_boolean_bitfield(flags, 0x8000,
1376 2*8, "Key prohibited for authentication",
1377 "Key allowed for authentication"));
1378 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1379 decode_boolean_bitfield(flags, 0x4000,
1380 2*8, "Key prohibited for confidentiality",
1381 "Key allowed for confidentiality"));
1382 if ((flags & 0xC000) != 0xC000) {
1384 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1385 decode_boolean_bitfield(flags, 0x2000,
1386 2*8, "Key is experimental or optional",
1387 "Key is required"));
1388 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1389 decode_boolean_bitfield(flags, 0x0400,
1390 2*8, "Key is associated with a user",
1391 "Key is not associated with a user"));
1392 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1393 decode_boolean_bitfield(flags, 0x0200,
1394 2*8, "Key is associated with the named entity",
1395 "Key is not associated with the named entity"));
1396 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1397 decode_boolean_bitfield(flags, 0x0100,
1398 2*8, "This is the zone key for the specified zone",
1399 "This is not a zone key"));
1400 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1401 decode_boolean_bitfield(flags, 0x0080,
1402 2*8, "Key is valid for use with IPSEC",
1403 "Key is not valid for use with IPSEC"));
1404 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1405 decode_boolean_bitfield(flags, 0x0040,
1406 2*8, "Key is valid for use with MIME security multiparts",
1407 "Key is not valid for use with MIME security multiparts"));
1408 proto_tree_add_text(flags_tree, NullTVB, cur_offset, 2, "%s",
1409 decode_numeric_bitfield(flags, 0x000F,
1410 2*8, "Signatory = %u"));
1415 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1416 /* We ran past the end of the captured data in the packet. */
1419 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Protocol: %u",
1424 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1425 /* We ran past the end of the captured data in the packet. */
1428 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Algorithm: %s",
1429 val_to_str(pd[cur_offset], algo_vals,
1430 "Unknown (0x%02X)"));
1434 proto_tree_add_text(rr_tree, NullTVB, cur_offset, rr_len, "Public key");
1440 if (!BYTES_ARE_IN_FRAME(cur_offset, 16)) {
1441 /* We ran past the end of the captured data in the packet. */
1442 if (dns_tree != NULL) {
1443 proto_item_set_text(trr,
1444 "%s: type %s, class %s, <Address goes past end of captured data in packet>",
1445 name, type_name, class_name);
1450 col_append_fstr(fd, COL_INFO, " %s",
1451 ip6_to_str((struct e_in6_addr *)dptr));
1453 if (dns_tree != NULL) {
1454 proto_item_set_text(trr, "%s: type %s, class %s, addr %s",
1455 name, type_name, class_name,
1456 ip6_to_str((struct e_in6_addr *)dptr));
1457 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 16, "Addr: %s",
1458 ip6_to_str((struct e_in6_addr *)dptr));
1464 unsigned short pre_len;
1465 unsigned short suf_len;
1466 unsigned short suf_octet_count;
1467 char pname[MAXDNAME];
1473 a6_offset = cur_offset;
1474 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1475 /* We ran past the end of the captured data in the packet. */
1478 pre_len = pd[cur_offset++];
1479 suf_len = 128 - pre_len;
1480 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1481 if (!BYTES_ARE_IN_FRAME(cur_offset, suf_octet_count)) {
1482 /* We ran past the end of the captured data in the packet. */
1486 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1487 suffix[suf_offset] = 0;
1489 for (; suf_offset < 16; suf_offset++) {
1490 suffix[suf_offset] = pd[cur_offset++];
1494 pname_len = get_dns_name(pd, cur_offset, dns_data_offset,
1495 pname, sizeof(pname));
1496 if (pname_len < 0) {
1497 /* We ran past the end of the captured data in the packet. */
1505 col_append_fstr(fd, COL_INFO, " %d %s %s",
1507 ip6_to_str((struct e_in6_addr *)&suffix),
1510 if (dns_tree != NULL) {
1511 proto_tree_add_text(rr_tree, NullTVB, a6_offset, 1,
1512 "Prefix len: %u", pre_len);
1515 proto_tree_add_text(rr_tree, NullTVB, a6_offset, suf_octet_count,
1516 "Address suffix: %s",
1517 ip6_to_str((struct e_in6_addr *)&suffix));
1518 a6_offset += suf_octet_count;
1521 proto_tree_add_text(rr_tree, NullTVB, a6_offset, pname_len,
1522 "Prefix name: %s", pname);
1524 proto_item_set_text(trr, "%s: type %s, class %s, addr %d %s %s",
1529 ip6_to_str((struct e_in6_addr *)&suffix),
1537 char dname[MAXDNAME];
1540 dname_len = get_dns_name(pd, cur_offset, dns_data_offset,
1541 dname, sizeof(dname));
1542 if (dname_len < 0) {
1543 /* We ran past the end of the captured data in the packet. */
1544 if (dns_tree != NULL) {
1545 proto_item_set_text(trr,
1546 "%s: type %s, class %s, <Primary name goes past end of captured data in packet>",
1547 name, type_name, class_name);
1552 col_append_fstr(fd, COL_INFO, " %s", dname);
1553 if (dns_tree != NULL) {
1554 proto_item_set_text(trr, "%s: type %s, class %s, dname %s",
1555 name, type_name, class_name, dname);
1556 proto_tree_add_text(rr_tree, NullTVB, cur_offset,
1557 dname_len, "Target name: %s", dname);
1564 if (dns_tree != NULL) {
1565 proto_item_set_text(trr,
1566 "%s: type %s, class %s", name, type_name, class_name);
1568 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1569 /* We ran past the end of the captured data in the packet. */
1572 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Version: %u", pd[cur_offset]);
1573 if (pd[cur_offset] == 0) {
1574 /* Version 0, the only version RFC 1876 discusses. */
1577 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1578 /* We ran past the end of the captured data in the packet. */
1581 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Size: %g m",
1582 rfc1867_size(pd[cur_offset]));
1585 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1586 /* We ran past the end of the captured data in the packet. */
1589 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Horizontal precision: %g m",
1590 rfc1867_size(pd[cur_offset]));
1593 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1594 /* We ran past the end of the captured data in the packet. */
1597 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Vertical precision: %g m",
1598 rfc1867_size(pd[cur_offset]));
1601 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1602 /* We ran past the end of the captured data in the packet. */
1605 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Latitude: %s",
1606 rfc1867_angle(&pd[cur_offset], "NS"));
1609 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1610 /* We ran past the end of the captured data in the packet. */
1613 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Longitude: %s",
1614 rfc1867_angle(&pd[cur_offset], "EW"));
1617 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1618 /* We ran past the end of the captured data in the packet. */
1621 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Altitude: %g m",
1622 (pntohl(&pd[cur_offset]) - 10000000)/100.0);
1624 proto_tree_add_text(rr_tree, NullTVB, cur_offset, data_len, "Data");
1632 int rr_len = data_len;
1633 char next_domain_name[MAXDNAME];
1634 int next_domain_name_len;
1640 next_domain_name_len = get_dns_name(pd, cur_offset, dns_data_offset,
1641 next_domain_name, sizeof(next_domain_name));
1642 if (next_domain_name_len < 0) {
1643 /* We ran past the end of the captured data in the packet. */
1644 if (dns_tree != NULL) {
1645 proto_item_set_text(trr,
1646 "%s: type %s, class %s, <Next domain name goes past end of captured data in packet>",
1647 name, type_name, class_name);
1652 col_append_fstr(fd, COL_INFO, " %s", next_domain_name);
1653 if (dns_tree != NULL) {
1654 proto_item_set_text(trr, "%s: type %s, class %s, next domain name %s",
1655 name, type_name, class_name, next_domain_name);
1656 proto_tree_add_text(rr_tree, NullTVB, cur_offset, next_domain_name_len,
1657 "Next domain name: %s", next_domain_name);
1658 cur_offset += next_domain_name_len;
1659 rr_len -= next_domain_name_len;
1661 while (rr_len != 0) {
1662 if (!BYTES_ARE_IN_FRAME(cur_offset, 1)) {
1663 /* We ran past the end of the captured data in the packet. */
1664 proto_tree_add_text(rr_tree, NullTVB, cur_offset, END_OF_FRAME,
1665 "<Bit map goes past end of captured data in packet>");
1668 bits = pd[cur_offset];
1670 for (i = 0; i < 8; i++) {
1672 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1,
1673 "RR type in bit map: %s (%s)",
1674 dns_type_name(rr_type),
1675 dns_long_type_name(rr_type));
1689 guint16 preference = 0;
1690 char kx_name[MAXDNAME];
1693 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1694 /* We ran past the end of the captured data in the packet. */
1695 if (dns_tree != NULL) {
1696 proto_item_set_text(trr,
1697 "%s: type %s, class %s, <preference goes past end of captured data in packet>",
1698 name, type_name, class_name);
1702 preference = pntohs(&pd[cur_offset]);
1703 kx_name_len = get_dns_name(pd, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1704 if (kx_name_len < 0) {
1705 /* We ran past the end of the captured data in the packet. */
1706 if (dns_tree != NULL) {
1707 proto_item_set_text(trr,
1708 "%s: type %s, class %s, preference %u, <kx goes past end of captured data in packet>",
1709 name, type_name, class_name, preference);
1714 col_append_fstr(fd, COL_INFO, " %u %s", preference, kx_name);
1715 if (dns_tree != NULL) {
1716 proto_item_set_text(trr,
1717 "%s: type %s, class %s, preference %u, kx %s",
1718 name, type_name, class_name, preference, kx_name);
1719 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Preference: %u", preference);
1720 proto_tree_add_text(rr_tree, NullTVB, cur_offset + 2, kx_name_len, "Key exchange: %s",
1728 guint16 cert_type, cert_keytag;
1730 int rr_len = data_len;
1732 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1733 /* We ran past the end of the captured data in the packet. */
1734 if (dns_tree != NULL) {
1735 proto_item_set_text(trr,
1736 "%s: type %s, class %s, <preference goes past end of captured data in packet>",
1737 name, type_name, class_name);
1741 cert_type = pntohs(&pd[cur_offset]);
1744 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1745 /* We ran past the end of the captured data in the packet. */
1746 if (dns_tree != NULL) {
1747 proto_item_set_text(trr,
1748 "%s: type %s, class %s, <preference goes past end of captured data in packet>",
1749 name, type_name, class_name);
1753 cert_keytag = pntohs(&pd[cur_offset]);
1756 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1757 /* We ran past the end of the captured data in the packet. */
1758 if (dns_tree != NULL) {
1759 proto_item_set_text(trr,
1760 "%s: type %s, class %s, <preference goes past end of captured data in packet>",
1761 name, type_name, class_name);
1765 cert_keyalg = pd[cur_offset];
1769 if (dns_tree != NULL) {
1770 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Type: %s",
1771 val_to_str(cert_keyalg, cert_vals,
1772 "Unknown (0x%02X)"));
1773 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Key footprint: 0x%04x",
1775 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Algorithm: %s",
1776 val_to_str(cert_keyalg, algo_vals,
1777 "Unknown (0x%02X)"));
1778 proto_tree_add_text(rr_tree, NullTVB, cur_offset, rr_len, "Public key");
1785 if (dns_tree != NULL) {
1786 proto_item_set_text(trr, "%s: type %s", name, type_name);
1787 proto_tree_add_text(rr_tree, NullTVB, cur_offset, data_len, "Data");
1793 char tkey_algname[MAXDNAME];
1794 int tkey_algname_len;
1795 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1796 int rr_len = data_len;
1797 struct timeval unixtime;
1798 static const value_string tkey_modes[] = {
1799 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1800 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1801 { TKEYMODE_GSSAPI, "GSSAPI " },
1802 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1803 { TKEYMODE_DELETE, "Delete" },
1806 if (dns_tree != NULL) {
1807 proto_item_set_text(trr,
1808 "%s: type %s, class %s", name, type_name, class_name);
1809 tkey_algname_len = get_dns_name(pd, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1810 if (tkey_algname_len < 0) {
1811 /* We ran past the end of the captured data in the packet. */
1814 proto_tree_add_text(rr_tree, NullTVB, cur_offset, tkey_algname_len,
1815 "Algorithm name: %s", tkey_algname);
1816 cur_offset += tkey_algname_len;
1817 rr_len -= tkey_algname_len;
1819 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1820 /* We ran past the end of the captured data in the packet. */
1823 unixtime.tv_sec = pntohl(&pd[cur_offset]);
1824 unixtime.tv_usec = 0;
1825 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Signature inception: %s",
1826 abs_time_to_str(&unixtime));
1830 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
1831 /* We ran past the end of the captured data in the packet. */
1834 unixtime.tv_sec = pntohl(&pd[cur_offset]);
1835 unixtime.tv_usec = 0;
1836 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Signature expiration: %s",
1837 abs_time_to_str(&unixtime));
1841 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1842 /* We ran past the end of the captured data in the packet. */
1845 tkey_mode = pntohs(&pd[cur_offset]);
1848 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 1, "Mode: %s",
1849 val_to_str(tkey_mode, tkey_modes,
1850 "Unknown (0x%02X)"));
1852 tkey_error = pntohs(&pd[cur_offset]);
1856 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Error: %s",
1857 val_to_str(tkey_error, rcode_vals,
1858 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1860 tkey_keylen = pntohs(&pd[cur_offset]);
1864 if (!BYTES_ARE_IN_FRAME(cur_offset, tkey_keylen)) {
1865 /* We ran past the end of the captured data in the packet. */
1869 proto_tree_add_text(rr_tree, NullTVB, cur_offset, tkey_keylen, "Key");
1870 cur_offset += tkey_keylen;
1871 rr_len -= tkey_keylen;
1873 tkey_otherlen = pntohs(&pd[cur_offset]);
1877 if (!BYTES_ARE_IN_FRAME(cur_offset, tkey_otherlen)) {
1878 /* We ran past the end of the captured data in the packet. */
1882 proto_tree_add_text(rr_tree, NullTVB, cur_offset, tkey_otherlen, "Other");
1883 cur_offset += tkey_otherlen;
1884 rr_len -= tkey_otherlen;
1892 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1893 guint32 tsig_timelo;
1894 char tsig_algname[MAXDNAME];
1895 int tsig_algname_len;
1896 struct timeval unixtime;
1897 int rr_len = data_len;
1899 if (dns_tree != NULL) {
1900 proto_item_set_text(trr,
1901 "%s: type %s, class %s", name, type_name, class_name);
1902 tsig_algname_len = get_dns_name(pd, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1903 if (tsig_algname_len < 0) {
1904 /* We ran past the end of the captured data in the packet. */
1907 proto_tree_add_text(rr_tree, NullTVB, cur_offset, tsig_algname_len,
1908 "Algorithm name: %s", tsig_algname);
1909 cur_offset += tsig_algname_len;
1910 rr_len -= tsig_algname_len;
1912 if (!BYTES_ARE_IN_FRAME(cur_offset, 6)) {
1913 /* We ran past the end of the captured data in the packet. */
1917 tsig_timehi = pntohs(&pd[cur_offset]);
1921 tsig_timelo = pntohl(&pd[cur_offset]);
1925 unixtime.tv_sec = tsig_timelo;
1926 unixtime.tv_usec = 0;
1927 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 6, "Time signed: %s%s",
1928 abs_time_to_str(&unixtime), tsig_timehi == 0 ? "" : "(high bits set)");
1930 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1931 /* We ran past the end of the captured data in the packet. */
1935 tsig_fudge = pntohs(&pd[cur_offset]);
1939 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 2, "Fudge: %d",
1942 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1943 /* We ran past the end of the captured data in the packet. */
1947 tsig_siglen = pntohs(&pd[cur_offset]);
1951 if (!BYTES_ARE_IN_FRAME(cur_offset, tsig_siglen)) {
1952 /* We ran past the end of the captured data in the packet. */
1956 proto_tree_add_text(rr_tree, NullTVB, cur_offset, tsig_siglen, "Signature");
1957 cur_offset += tsig_siglen;
1958 rr_len -= tsig_siglen;
1960 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1961 /* We ran past the end of the captured data in the packet. */
1965 tsig_originalid = pntohs(&pd[cur_offset]);
1969 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Original id: %d",
1972 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1973 /* We ran past the end of the captured data in the packet. */
1977 tsig_error = pntohs(&pd[cur_offset]);
1981 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Error: %s",
1982 val_to_str(tsig_error, rcode_vals,
1983 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1985 if (!BYTES_ARE_IN_FRAME(cur_offset, 2)) {
1986 /* We ran past the end of the captured data in the packet. */
1990 tsig_otherlen = pntohs(&pd[cur_offset]);
1994 if (!BYTES_ARE_IN_FRAME(cur_offset, tsig_otherlen)) {
1995 /* We ran past the end of the captured data in the packet. */
1999 proto_tree_add_text(rr_tree, NullTVB, cur_offset, tsig_otherlen, "Other");
2000 cur_offset += tsig_otherlen;
2001 rr_len -= tsig_otherlen;
2008 int rr_len = data_len;
2010 guint32 lookup_timeout;
2011 guint32 cache_timeout;
2014 if (dns_tree != NULL) {
2015 proto_item_set_text(trr, "%s: type %s, class %s", name, type_name,
2017 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
2018 /* We ran past the end of the captured data in the packet. */
2021 local_flag = pntohl(&pd[cur_offset]);
2022 if (dns_tree != NULL) {
2023 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Local flag: %s",
2024 local_flag ? "true" : "false");
2029 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
2030 /* We ran past the end of the captured data in the packet. */
2033 lookup_timeout = pntohl(&pd[cur_offset]);
2034 if (dns_tree != NULL) {
2035 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Lookup timeout: %u seconds",
2041 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
2042 /* We ran past the end of the captured data in the packet. */
2045 cache_timeout = pntohl(&pd[cur_offset]);
2046 if (dns_tree != NULL) {
2047 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Cache timeout: %u seconds",
2053 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
2054 /* We ran past the end of the captured data in the packet. */
2057 nservers = pntohl(&pd[cur_offset]);
2058 if (dns_tree != NULL) {
2059 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Number of WINS servers: %u",
2065 while (rr_len != 0 && nservers != 0) {
2066 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
2067 /* We ran past the end of the captured data in the packet. */
2070 if (dns_tree != NULL) {
2071 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "WINS server address: %s",
2072 ip_to_str((guint8 *)&pd[cur_offset]));
2084 int rr_len = data_len;
2086 guint32 lookup_timeout;
2087 guint32 cache_timeout;
2088 char dname[MAXDNAME];
2091 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
2092 /* We ran past the end of the captured data in the packet. */
2093 if (dns_tree != NULL) {
2094 proto_item_set_text(trr,
2095 "%s: type %s, class %s, <Local flag goes past end of captured data in packet>",
2096 name, type_name, class_name);
2100 local_flag = pntohl(&pd[cur_offset]);
2101 if (dns_tree != NULL) {
2102 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Local flag: %s",
2103 local_flag ? "true" : "false");
2108 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
2109 /* We ran past the end of the captured data in the packet. */
2110 if (dns_tree != NULL) {
2111 proto_item_set_text(trr,
2112 "%s: type %s, class %s, <Lookup timeout goes past end of captured data in packet>",
2113 name, type_name, class_name);
2117 lookup_timeout = pntohl(&pd[cur_offset]);
2118 if (dns_tree != NULL) {
2119 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Lookup timeout: %u seconds",
2125 if (!BYTES_ARE_IN_FRAME(cur_offset, 4)) {
2126 /* We ran past the end of the captured data in the packet. */
2127 if (dns_tree != NULL) {
2128 proto_item_set_text(trr,
2129 "%s: type %s, class %s, <Cache timeout goes past end of captured data in packet>",
2130 name, type_name, class_name);
2134 cache_timeout = pntohl(&pd[cur_offset]);
2135 if (dns_tree != NULL) {
2136 proto_tree_add_text(rr_tree, NullTVB, cur_offset, 4, "Cache timeout: %u seconds",
2142 dname_len = get_dns_name(pd, cur_offset, dns_data_offset, dname, sizeof(dname));
2143 if (dname_len < 0) {
2144 /* We ran past the end of the captured data in the packet. */
2145 if (dns_tree != NULL) {
2146 proto_item_set_text(trr,
2147 "%s: type %s, class %s, <Name result domain goes past end of captured data in packet>",
2148 name, type_name, class_name);
2153 col_append_fstr(fd, COL_INFO, " %s", dname);
2154 if (dns_tree != NULL) {
2155 proto_item_set_text(trr, "%s: type %s, class %s, name result domain %s",
2156 name, type_name, class_name, dname);
2157 proto_tree_add_text(rr_tree, NullTVB, cur_offset, dname_len, "Name result domain: %s",
2163 /* TODO: parse more record types */
2166 if (dns_tree != NULL) {
2167 proto_item_set_text(trr,
2168 "%s: type %s, class %s", name, type_name, class_name);
2169 proto_tree_add_text(rr_tree, NullTVB, cur_offset, data_len, "Data");
2176 return dptr - data_start;
2180 dissect_query_records(const u_char *pd, int cur_off, int dns_data_offset,
2181 int count, frame_data *fd, proto_tree *dns_tree, int isupdate)
2183 int start_off, add_off;
2184 proto_tree *qatree = NULL;
2185 proto_item *ti = NULL;
2187 start_off = cur_off;
2189 char *s = (isupdate ? "Zone" : "Queries");
2190 ti = proto_tree_add_text(dns_tree, NullTVB, start_off, 0, s);
2191 qatree = proto_item_add_subtree(ti, ett_dns_qry);
2193 while (count-- > 0) {
2194 add_off = dissect_dns_query(pd, cur_off, dns_data_offset, fd, qatree);
2196 /* We ran past the end of the captured data in the packet. */
2202 proto_item_set_len(ti, cur_off - start_off);
2204 return cur_off - start_off;
2208 dissect_answer_records(const u_char *pd, int cur_off, int dns_data_offset,
2209 int count, frame_data *fd, proto_tree *dns_tree, char *name)
2211 int start_off, add_off;
2212 proto_tree *qatree = NULL;
2213 proto_item *ti = NULL;
2215 start_off = cur_off;
2217 ti = proto_tree_add_text(dns_tree, NullTVB, start_off, 0, name);
2218 qatree = proto_item_add_subtree(ti, ett_dns_ans);
2220 while (count-- > 0) {
2221 add_off = dissect_dns_answer(pd, cur_off, dns_data_offset, fd, qatree);
2223 /* We ran past the end of the captured data in the packet. */
2229 proto_item_set_len(ti, cur_off - start_off);
2231 return cur_off - start_off;
2235 dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
2237 int dns_data_offset;
2238 proto_tree *dns_tree = NULL, *field_tree;
2239 proto_item *ti, *tf;
2240 guint16 id, flags, quest, ans, auth, add;
2244 static const value_string opcode_vals[] = {
2245 { OPCODE_QUERY, "Standard query" },
2246 { OPCODE_IQUERY, "Inverse query" },
2247 { OPCODE_STATUS, "Server status request" },
2248 { OPCODE_NOTIFY, "Zone change notification" },
2249 { OPCODE_UPDATE, "Dynamic update" },
2252 OLD_CHECK_DISPLAY_AS_DATA(proto_dns, pd, offset, fd, tree);
2254 dns_data_offset = offset;
2256 if (check_col(fd, COL_PROTOCOL))
2257 col_set_str(fd, COL_PROTOCOL, "DNS");
2259 if (!BYTES_ARE_IN_FRAME(offset, DNS_HDRLEN)) {
2260 if (check_col(fd, COL_INFO)) {
2261 col_set_str(fd, COL_INFO, "Short DNS packet");
2263 old_dissect_data(pd, offset, fd, tree);
2267 /* To do: check for errs, etc. */
2268 id = pntohs(&pd[offset + DNS_ID]);
2269 flags = pntohs(&pd[offset + DNS_FLAGS]);
2270 quest = pntohs(&pd[offset + DNS_QUEST]);
2271 ans = pntohs(&pd[offset + DNS_ANS]);
2272 auth = pntohs(&pd[offset + DNS_AUTH]);
2273 add = pntohs(&pd[offset + DNS_ADD]);
2275 if (check_col(fd, COL_INFO)) {
2276 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation (%x)"));
2277 if (flags & F_RESPONSE) {
2278 strcat(buf, " response");
2279 if ((flags & F_RCODE) != RCODE_NOERROR) {
2281 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
2282 "Unknown error (%x)"));
2285 col_add_str(fd, COL_INFO, buf);
2287 /* Set "fd" to NULL; we pass a NULL "fd" to the query and answer
2288 dissectors, as a way of saying that they shouldn't add stuff
2289 to the COL_INFO column (a call to "check_col(fd, COL_INFO)"
2290 is more expensive than a check that a pointer isn't NULL). */
2293 if ((flags & F_OPCODE) == OPCODE_UPDATE)
2299 ti = proto_tree_add_protocol_format(tree, proto_dns, NullTVB, offset, 4,
2300 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
2302 dns_tree = proto_item_add_subtree(ti, ett_dns);
2304 if (flags & F_RESPONSE)
2305 proto_tree_add_boolean_hidden(dns_tree, hf_dns_response, NullTVB, offset, 4, 1);
2307 proto_tree_add_boolean_hidden(dns_tree, hf_dns_query, NullTVB, offset, 4, 1);
2309 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, NullTVB,
2310 offset + DNS_ID, 2, id);
2312 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
2313 if (flags & F_RESPONSE) {
2314 strcat(buf, " response");
2316 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
2319 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, NullTVB,
2320 offset + DNS_FLAGS, 2,
2322 "Flags: 0x%04x (%s)",
2324 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
2325 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2326 decode_boolean_bitfield(flags, F_RESPONSE,
2327 2*8, "Response", "Query"));
2328 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2329 decode_enumerated_bitfield(flags, F_OPCODE,
2330 2*8, opcode_vals, "%s"));
2331 if (flags & F_RESPONSE) {
2332 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2333 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
2335 "Server is an authority for domain",
2336 "Server is not an authority for domain"));
2338 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2339 decode_boolean_bitfield(flags, F_TRUNCATED,
2341 "Message is truncated",
2342 "Message is not truncated"));
2343 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2344 decode_boolean_bitfield(flags, F_RECDESIRED,
2346 "Do query recursively",
2347 "Don't do query recursively"));
2348 if (flags & F_RESPONSE) {
2349 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2350 decode_boolean_bitfield(flags, F_RECAVAIL,
2352 "Server can do recursive queries",
2353 "Server can't do recursive queries"));
2354 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2355 decode_boolean_bitfield(flags, F_AUTHENTIC,
2357 "Answer/authority portion was authenticated by the server",
2358 "Answer/authority portion was not authenticated by the server"));
2360 if ((flags & F_RESPONSE) == 0) {
2361 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2362 decode_boolean_bitfield(flags, F_CHECKDISABLE,
2364 "Non-authenticated data is acceptable",
2365 "Non-authenticated data is unacceptable"));
2367 if (flags & F_RESPONSE) {
2368 proto_tree_add_text(field_tree, NullTVB, offset + DNS_FLAGS, 2, "%s",
2369 decode_enumerated_bitfield(flags, F_RCODE,
2370 2*8, rcode_vals, "%s"));
2372 proto_tree_add_uint(dns_tree, hf_dns_count_questions, NullTVB,
2373 offset + DNS_QUEST, 2, quest);
2374 proto_tree_add_uint(dns_tree, hf_dns_count_answers, NullTVB,
2375 offset + DNS_ANS, 2, ans);
2376 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, NullTVB,
2377 offset + DNS_AUTH, 2, auth);
2378 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, NullTVB,
2379 offset + DNS_ADD, 2, add);
2382 cur_off = offset + DNS_HDRLEN;
2385 /* If this is a response, don't add information about the queries
2386 to the summary, just add information about the answers. */
2387 cur_off += dissect_query_records(pd, cur_off, dns_data_offset, quest,
2388 (!(flags & F_RESPONSE) ? fd : NULL),
2389 dns_tree, isupdate);
2393 /* If this is a request, don't add information about the answers
2394 to the summary, just add information about the queries. */
2395 char *s = (isupdate ? "Prerequisites" : "Answers");
2396 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, ans,
2397 ((flags & F_RESPONSE) ? fd : NULL),
2402 /* Don't add information about the authoritative name servers, or the
2403 additional records, to the summary. */
2405 char *s = (isupdate ? "Updates" : "Authoritative nameservers");
2406 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, auth,
2411 cur_off += dissect_answer_records(pd, cur_off, dns_data_offset, add,
2412 NULL, dns_tree, "Additional records");
2417 dissect_dns_tcp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
2421 if (pi.captured_len < 2)
2423 plen = pntohs(&pd[offset]);
2425 if (END_OF_FRAME != plen)
2427 dissect_dns(pd, offset, fd, tree);
2431 proto_register_dns(void)
2433 static hf_register_info hf[] = {
2435 { "Response", "dns.response",
2436 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2437 "TRUE if DNS response" }},
2439 { "Query", "dns.query",
2440 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2441 "TRUE if DNS query" }},
2443 { "Flags", "dns.flags",
2444 FT_UINT16, BASE_HEX, NULL, 0x0,
2446 { &hf_dns_transaction_id,
2447 { "Transaction ID", "dns.id",
2448 FT_UINT16, BASE_HEX, NULL, 0x0,
2449 "Identification of transaction" }},
2450 { &hf_dns_count_questions,
2451 { "Questions", "dns.count.queries",
2452 FT_UINT16, BASE_DEC, NULL, 0x0,
2453 "Number of queries in packet" }},
2454 { &hf_dns_count_answers,
2455 { "Answer RRs", "dns.count.answers",
2456 FT_UINT16, BASE_DEC, NULL, 0x0,
2457 "Number of answers in packet" }},
2458 { &hf_dns_count_auth_rr,
2459 { "Authority RRs", "dns.count.auth_rr",
2460 FT_UINT16, BASE_DEC, NULL, 0x0,
2461 "Number of authoritative records in packet" }},
2462 { &hf_dns_count_add_rr,
2463 { "Additional RRs", "dns.count.add_rr",
2464 FT_UINT16, BASE_DEC, NULL, 0x0,
2465 "Number of additional records in packet" }}
2467 static gint *ett[] = {
2477 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2478 proto_register_field_array(proto_dns, hf, array_length(hf));
2479 proto_register_subtree_array(ett, array_length(ett));
2483 proto_reg_handoff_dns(void)
2485 old_dissector_add("udp.port", UDP_PORT_DNS, dissect_dns);
2486 old_dissector_add("tcp.port", TCP_PORT_DNS, dissect_dns_tcp);