2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.104 2003/10/05 21:57:36 jmayer Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #ifdef NEED_SNPRINTF_H
34 # include "snprintf.h"
38 #include <epan/ipv6-utils.h>
39 #include <epan/packet.h>
41 #include <epan/resolv.h>
42 #include "packet-dns.h"
43 #include "packet-tcp.h"
46 static int proto_dns = -1;
47 static int hf_dns_length = -1;
48 static int hf_dns_flags = -1;
49 static int hf_dns_flags_response = -1;
50 static int hf_dns_flags_opcode = -1;
51 static int hf_dns_flags_authoritative = -1;
52 static int hf_dns_flags_truncated = -1;
53 static int hf_dns_flags_recdesired = -1;
54 static int hf_dns_flags_recavail = -1;
55 static int hf_dns_flags_z = -1;
56 static int hf_dns_flags_authenticated = -1;
57 static int hf_dns_flags_checkdisable = -1;
58 static int hf_dns_flags_rcode = -1;
59 static int hf_dns_transaction_id = -1;
60 static int hf_dns_count_questions = -1;
61 static int hf_dns_count_answers = -1;
62 static int hf_dns_count_auth_rr = -1;
63 static int hf_dns_count_add_rr = -1;
65 static gint ett_dns = -1;
66 static gint ett_dns_qd = -1;
67 static gint ett_dns_rr = -1;
68 static gint ett_dns_qry = -1;
69 static gint ett_dns_ans = -1;
70 static gint ett_dns_flags = -1;
71 static gint ett_t_key_flags = -1;
72 static gint ett_t_key = -1;
74 /* desegmentation of DNS over TCP */
75 static gboolean dns_desegment = TRUE;
77 /* Dissector handle for GSSAPI */
78 static dissector_handle_t gssapi_handle;
80 /* DNS structs and definitions */
82 /* Ports used for DNS. */
83 #define UDP_PORT_DNS 53
84 #define TCP_PORT_DNS 53
85 #define UDP_PORT_MDNS 5353
86 #define TCP_PORT_MDNS 5353
88 /* Offsets of fields in the DNS header. */
96 /* Length of DNS header. */
100 #define T_A 1 /* host address */
101 #define T_NS 2 /* authoritative name server */
102 #define T_MD 3 /* mail destination (obsolete) */
103 #define T_MF 4 /* mail forwarder (obsolete) */
104 #define T_CNAME 5 /* canonical name */
105 #define T_SOA 6 /* start of authority zone */
106 #define T_MB 7 /* mailbox domain name (experimental) */
107 #define T_MG 8 /* mail group member (experimental) */
108 #define T_MR 9 /* mail rename domain name (experimental) */
109 #define T_NULL 10 /* null RR (experimental) */
110 #define T_WKS 11 /* well known service */
111 #define T_PTR 12 /* domain name pointer */
112 #define T_HINFO 13 /* host information */
113 #define T_MINFO 14 /* mailbox or mail list information */
114 #define T_MX 15 /* mail routing information */
115 #define T_TXT 16 /* text strings */
116 #define T_RP 17 /* responsible person (RFC 1183) */
117 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
118 #define T_X25 19 /* X.25 address (RFC 1183) */
119 #define T_ISDN 20 /* ISDN address (RFC 1183) */
120 #define T_RT 21 /* route-through (RFC 1183) */
121 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
122 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
123 #define T_SIG 24 /* digital signature (RFC 2535) */
124 #define T_KEY 25 /* public key (RFC 2535) */
125 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
126 #define T_GPOS 27 /* geographical position (RFC 1712) */
127 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
128 #define T_LOC 29 /* geographical location (RFC 1876) */
129 #define T_NXT 30 /* "next" name (RFC 2535) */
130 #define T_EID 31 /* ??? (Nimrod?) */
131 #define T_NIMLOC 32 /* ??? (Nimrod?) */
132 #define T_SRV 33 /* service location (RFC 2052) */
133 #define T_ATMA 34 /* ??? */
134 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
135 #define T_KX 36 /* Key Exchange (RFC 2230) */
136 #define T_CERT 37 /* Certificate (RFC 2538) */
137 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
138 #define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
139 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
140 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
141 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
142 #define T_WINS 65281 /* Microsoft's WINS RR */
143 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
146 #define C_IN 1 /* the Internet */
147 #define C_CS 2 /* CSNET (obsolete) */
148 #define C_CH 3 /* CHAOS */
149 #define C_HS 4 /* Hesiod */
150 #define C_NONE 254 /* none */
151 #define C_ANY 255 /* any */
152 #define C_FLUSH (1<<15) /* High bit is set for MDNS cache flush */
154 /* Bit fields in the flags */
155 #define F_RESPONSE (1<<15) /* packet is response */
156 #define F_OPCODE (0xF<<11) /* query opcode */
157 #define OPCODE_SHIFT 11
158 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
159 #define F_TRUNCATED (1<<9) /* response is truncated */
160 #define F_RECDESIRED (1<<8) /* recursion desired */
161 #define F_RECAVAIL (1<<7) /* recursion available */
162 #define F_Z (1<<6) /* Z */
163 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
164 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
165 #define F_RCODE (0xF<<0) /* reply code */
167 static const true_false_string tfs_flags_response = {
168 "Message is a response",
172 static const true_false_string tfs_flags_authoritative = {
173 "Server is an authority for domain",
174 "Server is not an authority for domain"
177 static const true_false_string tfs_flags_truncated = {
178 "Message is truncated",
179 "Message is not truncated"
182 static const true_false_string tfs_flags_recdesired = {
183 "Do query recursively",
184 "Don't do query recursively"
187 static const true_false_string tfs_flags_recavail = {
188 "Server can do recursive queries",
189 "Server can't do recursive queries"
192 static const true_false_string tfs_flags_z = {
193 "reserved - incorrect!",
197 static const true_false_string tfs_flags_authenticated = {
198 "Answer/authority portion was authenticated by the server",
199 "Answer/authority portion was not authenticated by the server"
202 static const true_false_string tfs_flags_checkdisable = {
203 "Non-authenticated data is acceptable",
204 "Non-authenticated data is unacceptable"
208 #define OPCODE_QUERY 0 /* standard query */
209 #define OPCODE_IQUERY 1 /* inverse query */
210 #define OPCODE_STATUS 2 /* server status request */
211 #define OPCODE_NOTIFY 4 /* zone change notification */
212 #define OPCODE_UPDATE 5 /* dynamic update */
214 static const value_string opcode_vals[] = {
215 { OPCODE_QUERY, "Standard query" },
216 { OPCODE_IQUERY, "Inverse query" },
217 { OPCODE_STATUS, "Server status request" },
218 { OPCODE_NOTIFY, "Zone change notification" },
219 { OPCODE_UPDATE, "Dynamic update" },
223 #define RCODE_NOERROR 0
224 #define RCODE_FORMERR 1
225 #define RCODE_SERVFAIL 2
226 #define RCODE_NXDOMAIN 3
227 #define RCODE_NOTIMPL 4
228 #define RCODE_REFUSED 5
229 #define RCODE_YXDOMAIN 6
230 #define RCODE_YXRRSET 7
231 #define RCODE_NXRRSET 8
232 #define RCODE_NOTAUTH 9
233 #define RCODE_NOTZONE 10
235 static const value_string rcode_vals[] = {
236 { RCODE_NOERROR, "No error" },
237 { RCODE_FORMERR, "Format error" },
238 { RCODE_SERVFAIL, "Server failure" },
239 { RCODE_NXDOMAIN, "No such name" },
240 { RCODE_NOTIMPL, "Not implemented" },
241 { RCODE_REFUSED, "Refused" },
242 { RCODE_YXDOMAIN, "Name exists" },
243 { RCODE_YXRRSET, "RRset exists" },
244 { RCODE_NXRRSET, "RRset does not exist" },
245 { RCODE_NOTAUTH, "Not authoritative" },
246 { RCODE_NOTZONE, "Name out of zone" },
249 /* TSIG/TKEY extended errors */
250 #define TSIGERROR_BADSIG (16)
251 #define TSIGERROR_BADKEY (17)
252 #define TSIGERROR_BADTIME (18)
253 #define TSIGERROR_BADMODE (19)
254 #define TSIGERROR_BADNAME (20)
255 #define TSIGERROR_BADALG (21)
257 static const value_string tsigerror_vals[] = {
258 { TSIGERROR_BADSIG, "Bad signature" },
259 { TSIGERROR_BADKEY, "Bad key" },
260 { TSIGERROR_BADTIME, "Bad time failure" },
261 { TSIGERROR_BADMODE, "Bad mode such name" },
262 { TSIGERROR_BADNAME, "Bad name implemented" },
263 { TSIGERROR_BADALG, "Bad algorithm" },
266 #define TKEYMODE_SERVERASSIGNED (1)
267 #define TKEYMODE_DIFFIEHELLMAN (2)
268 #define TKEYMODE_GSSAPI (3)
269 #define TKEYMODE_RESOLVERASSIGNED (4)
270 #define TKEYMODE_DELETE (5)
272 /* See RFC 1035 for all RR types for which no RFC is listed, except for
273 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
274 which one should look at
276 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
280 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
282 which discuss them to some extent. */
284 dns_type_name (guint type)
286 char *type_names[] = {
305 "AFSDB", /* RFC 1183 */
306 "X25", /* RFC 1183 */
307 "ISDN", /* RFC 1183 */
309 "NSAP", /* RFC 1706 */
310 "NSAP-PTR", /* RFC 1348 */
311 "SIG", /* RFC 2535 */
312 "KEY", /* RFC 2535 */
314 "GPOS", /* RFC 1712 */
315 "AAAA", /* RFC 1886 */
316 "LOC", /* RFC 1876 */
317 "NXT", /* RFC 2535 */
320 "SRV", /* RFC 2052 */
322 "NAPTR", /* RFC 2168 */
324 "CERT", /* RFC 2538 */
326 "DNAME", /* RFC 2672 */
331 if (type < sizeof(type_names)/sizeof(type_names[0]))
332 return type_names[type] ? type_names[type] : "unknown";
359 return "IXFR"; /* RFC 1995 */
376 dns_long_type_name (guint type)
378 char *type_names[] = {
381 "Authoritative name server",
384 "Canonical name for an alias",
385 "Start of zone of authority",
386 "Mailbox domain name",
388 "Mail rename domain name",
389 "Null resource record",
390 "Well-known service description",
391 "Domain name pointer",
393 "Mailbox or mail list information",
396 "Responsible person", /* RFC 1183 */
397 "AFS data base location", /* RFC 1183 */
398 "X.25 address", /* RFC 1183 */
399 "ISDN number", /* RFC 1183 */
400 "Route through", /* RFC 1183 */
401 "OSI NSAP", /* RFC 1706 */
402 "OSI NSAP name pointer", /* RFC 1348 */
403 "Signature", /* RFC 2535 */
404 "Public key", /* RFC 2535 */
405 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
406 "Geographical position", /* RFC 1712 */
407 "IPv6 address", /* RFC 1886 */
408 "Location", /* RFC 1876 */
409 "Next", /* RFC 2535 */
412 "Service location", /* RFC 2052 */
414 "Naming authority pointer", /* RFC 2168 */
415 "Key Exchange", /* RFC 2230 */
416 "Certificate", /* RFC 2538 */
417 "IPv6 address with indirection", /* RFC 2874 */
418 "Non-terminal DNS name redirection", /* RFC 2672 */
420 "EDNS0 option" /* RFC 2671 */
422 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%u)" */
424 if (type < sizeof(type_names)/sizeof(type_names[0]))
425 return type_names[type] ? type_names[type] : "unknown";
446 return "Transaction Key";
448 return "Transaction Signature";
452 return "Request for incremental zone transfer"; /* RFC 1995 */
454 return "Request for full zone transfer";
456 return "Request for mailbox-related records";
458 return "Request for mail agent resource records";
460 return "Request for all records";
463 sprintf(unkbuf, "Unknown RR type (%u)", type);
469 dns_class_name(int class)
477 case ( C_IN | C_FLUSH ):
478 class_name = "inet (data flush)";
481 class_name = "csnet";
484 class_name = "chaos";
487 class_name = "hesiod";
496 class_name = "unknown";
503 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
504 char *name, int maxname)
506 int start_offset = offset;
509 int chars_processed = 0;
510 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
514 const int min_len = 1; /* Minimum length of encoded name (for root) */
515 /* If we're about to return a value (probably negative) which is less
516 * than the minimum length, we're looking at bad data and we're liable
517 * to put the dissector into a loop. Instead we throw an exception */
519 maxname--; /* reserve space for the trailing '\0' */
521 component_len = tvb_get_guint8(tvb, offset);
523 if (component_len == 0)
526 switch (component_len & 0xc0) {
531 /* Not the first component - put in a '.'. */
537 while (component_len > 0) {
539 *np++ = tvb_get_guint8(tvb, offset);
549 /* Extended label (RFC 2673) */
550 switch (component_len & 0x3f) {
553 /* Bitstring label */
559 bit_count = tvb_get_guint8(tvb, offset);
561 label_len = (bit_count - 1) / 8 + 1;
564 print_len = snprintf(np, maxname + 1, "\\[x");
565 if (print_len != -1 && print_len <= maxname) {
566 /* Some versions of snprintf return -1 if they'd truncate
567 the output. Others return <buf_size> or greater. */
569 maxname -= print_len;
571 /* Nothing printed, as there's no room.
572 Suppress all subsequent printing. */
578 print_len = snprintf(np, maxname + 1, "%02x",
579 tvb_get_guint8(tvb, offset));
580 if (print_len != -1 && print_len <= maxname) {
581 /* Some versions of snprintf return -1 if they'd truncate
582 the output. Others return <buf_size> or greater. */
584 maxname -= print_len;
586 /* Nothing printed, as there's no room.
587 Suppress all subsequent printing. */
594 print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
595 if (print_len != -1 && print_len <= maxname) {
596 /* Some versions of snprintf return -1 if they'd truncate
597 the output. Others return <buf_size> or greater. */
599 maxname -= print_len;
601 /* Nothing printed, as there's no room.
602 Suppress all subsequent printing. */
610 strcpy(name, "<Unknown extended label>");
611 /* Parsing will propably fail from here on, since the */
612 /* label length is unknown... */
613 len = offset - start_offset;
615 THROW(ReportedBoundsError);
621 THROW(ReportedBoundsError);
625 indir_offset = dns_data_offset +
626 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
630 /* If "len" is negative, we are still working on the original name,
631 not something pointed to by a pointer, and so we should set "len"
632 to the length of the original name. */
634 len = offset - start_offset;
636 /* If we've looked at every character in the message, this pointer
637 will make us look at some character again, which means we're
639 if (chars_processed >= data_size) {
640 strcpy(name, "<Name contains a pointer that loops>");
642 THROW(ReportedBoundsError);
646 offset = indir_offset;
647 break; /* now continue processing from there */
652 /* If "len" is negative, we haven't seen a pointer, and thus haven't
653 set the length, so set it. */
655 len = offset - start_offset;
656 /* Zero-length name means "root server" */
658 strcpy(name, "<Root>");
660 THROW(ReportedBoundsError);
666 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
667 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
674 int start_offset = offset;
676 name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
679 type = tvb_get_ntohs(tvb, offset);
682 class = tvb_get_ntohs(tvb, offset);
685 strcpy (name_ret, name);
688 *name_len_ret = name_len;
690 len = offset - start_offset;
695 rfc1867_size(tvbuff_t *tvb, int offset)
701 val = tvb_get_guint8(tvb, offset);
702 size = (val & 0xF0) >> 4;
703 exponent = (val & 0x0F);
704 while (exponent != 0) {
708 return size / 100; /* return size in meters, not cm */
712 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
716 guint32 degrees, minutes, secs, tsecs;
717 /* "%u deg %u min %u.%03u sec %c" */
718 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
720 angle = tvb_get_ntohl(tvb, offset);
722 if (angle < 0x80000000U) {
723 angle = 0x80000000U - angle;
726 angle = angle - 0x80000000U;
729 tsecs = angle % 1000;
730 angle = angle / 1000;
733 minutes = angle % 60;
734 degrees = angle / 60;
735 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
741 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
742 column_info *cinfo, proto_tree *dns_tree)
751 char *long_type_name;
757 data_start = data_offset = offset;
759 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
763 type_name = dns_type_name(type);
764 class_name = dns_class_name(class);
765 long_type_name = dns_long_type_name(type);
768 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
769 if (dns_tree != NULL) {
770 tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
771 name, type_name, class_name);
772 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
774 proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
777 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
780 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
784 return data_offset - data_start;
789 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
790 const char *name, int namelen, const char *type_name, const char *class_name,
791 guint ttl, gushort data_len)
795 rr_tree = proto_item_add_subtree(trr, rr_type);
796 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
798 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
800 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
802 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
803 time_secs_to_str(ttl));
805 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
810 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
811 const char *name, int namelen, const char *type_name, int class,
812 guint ttl, gushort data_len)
814 proto_tree *rr_tree, *Z_tree;
815 proto_item *Z_item = NULL;
817 rr_tree = proto_item_add_subtree(trr, rr_type);
818 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
820 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
822 proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
825 proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
826 (ttl >> 24) & 0xff0);
828 proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
831 Z_item = proto_tree_add_text(rr_tree, tvb, offset, 2, "Z: 0x%x", ttl & 0xffff);
833 Z_tree = proto_item_add_subtree(Z_item, rr_type);
834 proto_tree_add_text(Z_tree, tvb, offset, 2, "Bit 0 (DO bit): 1 (Accepts DNSSEC security RRs)");
835 proto_tree_add_text(Z_tree, tvb, offset, 2, "Bits 1-15: 0x%x (reserved)", (ttl >> 17) & 0xff);
838 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
843 * SIG, KEY, and CERT RR algorithms.
845 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
846 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
847 #define DNS_ALGO_DSA 3 /* DSA */
848 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
849 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
850 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
851 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
853 static const value_string algo_vals[] = {
854 { DNS_ALGO_RSAMD5, "RSA/MD5" },
855 { DNS_ALGO_DH, "Diffie-Hellman" },
856 { DNS_ALGO_DSA, "DSA" },
857 { DNS_ALGO_ECC, "Elliptic curve crypto" },
858 { DNS_ALGO_INDIRECT, "Indirect key" },
859 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
860 { DNS_ALGO_PRIVATEOID, "Private, OID" },
864 #define DNS_CERT_PGP 1 /* PGP */
865 #define DNS_CERT_PKIX 2 /* PKIX */
866 #define DNS_CERT_SPKI 3 /* SPKI */
867 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
868 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
870 static const value_string cert_vals[] = {
871 { DNS_CERT_PGP, "PGP" },
872 { DNS_CERT_PKIX, "PKIX" },
873 { DNS_CERT_SPKI, "SPKI" },
874 { DNS_CERT_PRIVATEURI, "Private, URI" },
875 { DNS_CERT_PRIVATEOID, "Private, OID" },
880 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
881 column_info *cinfo, proto_tree *dns_tree, packet_info *pinfo)
890 char *long_type_name;
896 proto_tree *rr_tree = NULL;
897 proto_item *trr = NULL;
899 data_start = data_offset = offset;
902 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
907 type_name = dns_type_name(type);
908 class_name = dns_class_name(class);
909 long_type_name = dns_long_type_name(type);
911 ttl = tvb_get_ntohl(tvb, data_offset);
915 data_len = tvb_get_ntohs(tvb, data_offset);
920 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
921 if (dns_tree != NULL) {
922 trr = proto_tree_add_text(dns_tree, tvb, offset,
923 (data_offset - data_start) + data_len,
924 "%s: type %s, class %s",
925 name, type_name, class_name);
927 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
928 long_type_name, class_name, ttl, data_len);
930 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
931 long_type_name, class, ttl, data_len);
942 addr = tvb_get_ptr(tvb, cur_offset, 4);
944 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
945 if (dns_tree != NULL) {
946 proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
947 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
950 if ((class & 0x7f) == C_IN) {
951 memcpy(&addr_int, addr, sizeof(addr_int));
952 add_host_name(addr_int, name);
959 char ns_name[MAXDNAME];
962 ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
964 col_append_fstr(cinfo, COL_INFO, " %s", ns_name);
965 if (dns_tree != NULL) {
966 proto_item_append_text(trr, ", ns %s", ns_name);
967 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
975 char cname[MAXDNAME];
978 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
980 col_append_fstr(cinfo, COL_INFO, " %s", cname);
981 if (dns_tree != NULL) {
982 proto_item_append_text(trr, ", cname %s", cname);
983 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
991 char mname[MAXDNAME];
993 char rname[MAXDNAME];
1001 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
1003 col_append_fstr(cinfo, COL_INFO, " %s", mname);
1004 if (dns_tree != NULL) {
1005 proto_item_append_text(trr, ", mname %s", mname);
1006 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
1008 cur_offset += mname_len;
1010 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
1011 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
1013 cur_offset += rname_len;
1015 serial = tvb_get_ntohl(tvb, cur_offset);
1016 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
1020 refresh = tvb_get_ntohl(tvb, cur_offset);
1021 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
1022 time_secs_to_str(refresh));
1025 retry = tvb_get_ntohl(tvb, cur_offset);
1026 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
1027 time_secs_to_str(retry));
1030 expire = tvb_get_ntohl(tvb, cur_offset);
1031 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
1032 time_secs_to_str(expire));
1035 minimum = tvb_get_ntohl(tvb, cur_offset);
1036 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
1037 time_secs_to_str(minimum));
1044 char pname[MAXDNAME];
1047 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
1049 col_append_fstr(cinfo, COL_INFO, " %s", pname);
1050 if (dns_tree != NULL) {
1051 proto_item_append_text(trr, ", %s", pname);
1052 proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
1061 int rr_len = data_len;
1062 const guint8 *wks_addr;
1068 static GString *bitnames = NULL;
1070 if (bitnames == NULL)
1071 bitnames = g_string_sized_new(128);
1073 wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
1075 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
1076 if (dns_tree != NULL) {
1077 proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
1078 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
1079 ip_to_str(wks_addr));
1083 protocol = tvb_get_guint8(tvb, cur_offset);
1084 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
1085 ipprotostr(protocol));
1090 while (rr_len != 0) {
1091 bits = tvb_get_guint8(tvb, cur_offset);
1094 g_string_truncate(bitnames, 0);
1095 for (i = 0; i < 8; i++) {
1097 if (bitnames->len != 0)
1098 g_string_append(bitnames, ", ");
1102 g_string_append(bitnames, get_tcp_port(port_num));
1106 g_string_append(bitnames, get_udp_port(port_num));
1110 g_string_sprintfa(bitnames, "%u", port_num);
1117 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1118 "Bits: 0x%02x (%s)", bits, bitnames->str);
1137 cpu_offset = cur_offset;
1138 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1139 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1140 os_offset = cpu_offset + 1 + cpu_len;
1141 os_len = tvb_get_guint8(tvb, os_offset);
1142 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1144 col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1146 if (dns_tree != NULL) {
1147 proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1148 cpu_len, cpu, os_len, os);
1149 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1151 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1160 guint16 preference = 0;
1161 char mx_name[MAXDNAME];
1164 preference = tvb_get_ntohs(tvb, cur_offset);
1165 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1167 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, mx_name);
1168 if (dns_tree != NULL) {
1169 proto_item_append_text(trr, ", preference %u, mx %s",
1170 preference, mx_name);
1171 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1172 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1180 int rr_len = data_len;
1184 if (dns_tree != NULL) {
1185 txt_offset = cur_offset;
1186 while (rr_len != 0) {
1187 txt_len = tvb_get_guint8(tvb, txt_offset);
1188 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1189 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1190 txt_offset += 1 + txt_len;
1191 rr_len -= 1 + txt_len;
1199 int rr_len = data_len;
1200 guint16 type_covered;
1202 char signer_name[MAXDNAME];
1203 int signer_name_len;
1205 if (dns_tree != NULL) {
1206 type_covered = tvb_get_ntohs(tvb, cur_offset);
1207 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1208 dns_type_name(type_covered),
1209 dns_long_type_name(type_covered));
1213 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1214 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1215 "Unknown (0x%02X)"));
1219 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1220 tvb_get_guint8(tvb, cur_offset));
1224 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1225 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1229 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1231 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1232 abs_time_to_str(&nstime));
1236 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1238 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1239 abs_time_to_str(&nstime));
1243 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1244 tvb_get_ntohs(tvb, cur_offset));
1248 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1249 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1250 "Signer's name: %s", signer_name);
1251 cur_offset += signer_name_len;
1252 rr_len -= signer_name_len;
1254 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1261 int rr_len = data_len;
1264 proto_tree *flags_tree;
1266 if (dns_tree != NULL) {
1267 flags = tvb_get_ntohs(tvb, cur_offset);
1268 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1269 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1270 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1271 decode_boolean_bitfield(flags, 0x8000,
1272 2*8, "Key prohibited for authentication",
1273 "Key allowed for authentication"));
1274 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1275 decode_boolean_bitfield(flags, 0x4000,
1276 2*8, "Key prohibited for confidentiality",
1277 "Key allowed for confidentiality"));
1278 if ((flags & 0xC000) != 0xC000) {
1280 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1281 decode_boolean_bitfield(flags, 0x2000,
1282 2*8, "Key is experimental or optional",
1283 "Key is required"));
1284 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1285 decode_boolean_bitfield(flags, 0x0400,
1286 2*8, "Key is associated with a user",
1287 "Key is not associated with a user"));
1288 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1289 decode_boolean_bitfield(flags, 0x0200,
1290 2*8, "Key is associated with the named entity",
1291 "Key is not associated with the named entity"));
1292 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1293 decode_boolean_bitfield(flags, 0x0100,
1294 2*8, "This is the zone key for the specified zone",
1295 "This is not a zone key"));
1296 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1297 decode_boolean_bitfield(flags, 0x0080,
1298 2*8, "Key is valid for use with IPSEC",
1299 "Key is not valid for use with IPSEC"));
1300 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1301 decode_boolean_bitfield(flags, 0x0040,
1302 2*8, "Key is valid for use with MIME security multiparts",
1303 "Key is not valid for use with MIME security multiparts"));
1304 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1305 decode_numeric_bitfield(flags, 0x000F,
1306 2*8, "Signatory = %u"));
1311 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1312 tvb_get_guint8(tvb, cur_offset));
1316 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1317 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1318 "Unknown (0x%02X)"));
1322 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1329 const guint8 *addr6;
1331 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1332 if (cinfo != NULL) {
1333 col_append_fstr(cinfo, COL_INFO, " %s",
1334 ip6_to_str((const struct e_in6_addr *)addr6));
1336 if (dns_tree != NULL) {
1337 proto_item_append_text(trr, ", addr %s",
1338 ip6_to_str((const struct e_in6_addr *)addr6));
1339 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1340 ip6_to_str((const struct e_in6_addr *)addr6));
1347 unsigned short pre_len;
1348 unsigned short suf_len;
1349 unsigned short suf_octet_count;
1350 char pname[MAXDNAME];
1354 struct e_in6_addr suffix;
1356 a6_offset = cur_offset;
1357 pre_len = tvb_get_guint8(tvb, cur_offset);
1359 suf_len = 128 - pre_len;
1360 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1362 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1363 suffix.s6_addr8[suf_offset] = 0;
1365 for (; suf_offset < 16; suf_offset++) {
1366 suffix.s6_addr8[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1371 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1372 pname, sizeof(pname));
1378 if (cinfo != NULL) {
1379 col_append_fstr(cinfo, COL_INFO, " %d %s %s",
1381 ip6_to_str(&suffix),
1384 if (dns_tree != NULL) {
1385 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1386 "Prefix len: %u", pre_len);
1389 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1390 "Address suffix: %s",
1391 ip6_to_str(&suffix));
1392 a6_offset += suf_octet_count;
1395 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1396 "Prefix name: %s", pname);
1398 proto_item_append_text(trr, ", addr %d %s %s",
1400 ip6_to_str(&suffix),
1408 char dname[MAXDNAME];
1411 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1412 dname, sizeof(dname));
1414 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1415 if (dns_tree != NULL) {
1416 proto_item_append_text(trr, ", dname %s", dname);
1417 proto_tree_add_text(rr_tree, tvb, cur_offset,
1418 dname_len, "Target name: %s", dname);
1427 if (dns_tree != NULL) {
1428 version = tvb_get_guint8(tvb, cur_offset);
1429 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1431 /* Version 0, the only version RFC 1876 discusses. */
1434 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1435 rfc1867_size(tvb, cur_offset));
1438 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1439 rfc1867_size(tvb, cur_offset));
1442 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1443 rfc1867_size(tvb, cur_offset));
1446 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1447 rfc1867_angle(tvb, cur_offset, "NS"));
1450 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1451 rfc1867_angle(tvb, cur_offset, "EW"));
1454 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1455 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1457 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1465 int rr_len = data_len;
1466 char next_domain_name[MAXDNAME];
1467 int next_domain_name_len;
1473 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1474 next_domain_name, sizeof(next_domain_name));
1476 col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
1477 if (dns_tree != NULL) {
1478 proto_item_append_text(trr, ", next domain name %s",
1480 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1481 "Next domain name: %s", next_domain_name);
1482 cur_offset += next_domain_name_len;
1483 rr_len -= next_domain_name_len;
1485 while (rr_len != 0) {
1486 bits = tvb_get_guint8(tvb, cur_offset);
1488 for (i = 0; i < 8; i++) {
1490 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1491 "RR type in bit map: %s (%s)",
1492 dns_type_name(rr_type),
1493 dns_long_type_name(rr_type));
1507 guint16 preference = 0;
1508 char kx_name[MAXDNAME];
1511 preference = tvb_get_ntohs(tvb, cur_offset);
1512 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1514 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, kx_name);
1515 if (dns_tree != NULL) {
1516 proto_item_append_text(trr, ", preference %u, kx %s",
1517 preference, kx_name);
1518 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1519 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1527 guint16 cert_type, cert_keytag;
1529 int rr_len = data_len;
1531 cert_type = tvb_get_ntohs(tvb, cur_offset);
1534 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1537 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1541 if (dns_tree != NULL) {
1542 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s",
1543 val_to_str(cert_keyalg, cert_vals,
1544 "Unknown (0x%02X)"));
1545 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1547 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1548 val_to_str(cert_keyalg, algo_vals,
1549 "Unknown (0x%02X)"));
1550 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1557 if (dns_tree != NULL)
1558 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1563 char tkey_algname[MAXDNAME];
1564 int tkey_algname_len;
1565 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1566 int rr_len = data_len;
1568 static const value_string tkey_modes[] = {
1569 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1570 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1571 { TKEYMODE_GSSAPI, "GSSAPI" },
1572 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1573 { TKEYMODE_DELETE, "Delete" },
1576 if (dns_tree != NULL) {
1577 proto_tree *key_tree;
1578 proto_item *key_item;
1580 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1581 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1582 "Algorithm name: %s", tkey_algname);
1583 cur_offset += tkey_algname_len;
1584 rr_len -= tkey_algname_len;
1586 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1588 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1589 abs_time_to_str(&nstime));
1593 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1595 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1596 abs_time_to_str(&nstime));
1600 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1603 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Mode: %s",
1604 val_to_str(tkey_mode, tkey_modes,
1605 "Unknown (0x%04X)"));
1607 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1610 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1611 val_to_str(tkey_error, rcode_vals,
1612 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1614 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1618 key_item = proto_tree_add_text(
1619 rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1621 key_tree = proto_item_add_subtree(key_item, ett_t_key);
1624 case TKEYMODE_GSSAPI: {
1625 tvbuff_t *gssapi_tvb;
1628 * XXX - in at least one capture, this appears to
1629 * be an NTLMSSP blob, with no ASN.1 in it, in
1634 * http://www.alternic.org/drafts/drafts-s-t/draft-skwan-gss-tsig-05.html
1636 * which might indicate what's going on here. (The key
1637 * is an output_token from GSS_Init_sec_context.)
1639 * How the heck do we know what method is being used,
1640 * so we know how to decode the key?
1642 gssapi_tvb = tvb_new_subset(
1643 tvb, cur_offset, tkey_keylen, tkey_keylen);
1645 call_dissector(gssapi_handle, gssapi_tvb, pinfo, key_tree);
1651 /* No dissector for this key mode */
1656 cur_offset += tkey_keylen;
1657 rr_len -= tkey_keylen;
1659 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1663 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1664 cur_offset += tkey_otherlen;
1665 rr_len -= tkey_otherlen;
1673 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1674 guint32 tsig_timelo;
1675 char tsig_algname[MAXDNAME];
1676 int tsig_algname_len;
1678 int rr_len = data_len;
1680 if (dns_tree != NULL) {
1681 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1682 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1683 "Algorithm name: %s", tsig_algname);
1684 cur_offset += tsig_algname_len;
1685 rr_len -= tsig_algname_len;
1687 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1688 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1689 nstime.secs = tsig_timelo;
1691 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1692 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
1696 tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1697 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1702 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1706 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1707 cur_offset += tsig_siglen;
1708 rr_len -= tsig_siglen;
1710 tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1711 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1716 tsig_error = tvb_get_ntohs(tvb, cur_offset);
1717 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1718 val_to_str(tsig_error, rcode_vals,
1719 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1723 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1727 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1728 cur_offset += tsig_otherlen;
1729 rr_len -= tsig_otherlen;
1736 int rr_len = data_len;
1738 guint32 lookup_timeout;
1739 guint32 cache_timeout;
1742 if (dns_tree != NULL) {
1743 local_flag = tvb_get_ntohl(tvb, cur_offset);
1744 if (dns_tree != NULL) {
1745 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1746 local_flag ? "true" : "false");
1751 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1752 if (dns_tree != NULL) {
1753 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1759 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1760 if (dns_tree != NULL) {
1761 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1767 nservers = tvb_get_ntohl(tvb, cur_offset);
1768 if (dns_tree != NULL) {
1769 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
1775 while (rr_len != 0 && nservers != 0) {
1776 if (dns_tree != NULL) {
1777 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
1778 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
1790 int rr_len = data_len;
1792 guint32 lookup_timeout;
1793 guint32 cache_timeout;
1794 char dname[MAXDNAME];
1797 local_flag = tvb_get_ntohl(tvb, cur_offset);
1798 if (dns_tree != NULL) {
1799 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1800 local_flag ? "true" : "false");
1805 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1806 if (dns_tree != NULL) {
1807 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1813 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1814 if (dns_tree != NULL) {
1815 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1821 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1823 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1824 if (dns_tree != NULL) {
1825 proto_item_append_text(trr, ", name result domain %s", dname);
1826 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
1834 guint16 priority = 0;
1837 char target[MAXDNAME];
1840 priority = tvb_get_ntohs(tvb, cur_offset);
1841 weight = tvb_get_ntohs(tvb, cur_offset+2);
1842 port = tvb_get_ntohs(tvb, cur_offset+4);
1844 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1846 col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, target);
1847 if (dns_tree != NULL) {
1848 proto_item_append_text(trr,
1849 ", priority %u, weight %u, port %u, target %s",
1850 priority, weight, port, target);
1851 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
1852 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
1853 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
1854 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
1860 /* TODO: parse more record types */
1863 if (dns_tree != NULL)
1864 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1868 data_offset += data_len;
1870 return data_offset - data_start;
1874 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1875 int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
1877 int start_off, add_off;
1878 proto_tree *qatree = NULL;
1879 proto_item *ti = NULL;
1881 start_off = cur_off;
1883 char *s = (isupdate ? "Zone" : "Queries");
1884 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
1885 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1887 while (count-- > 0) {
1888 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
1892 proto_item_set_len(ti, cur_off - start_off);
1894 return cur_off - start_off;
1898 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1899 int count, column_info *cinfo, proto_tree *dns_tree, char *name,
1902 int start_off, add_off;
1903 proto_tree *qatree = NULL;
1904 proto_item *ti = NULL;
1906 start_off = cur_off;
1908 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
1909 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1911 while (count-- > 0) {
1912 add_off = dissect_dns_answer(
1913 tvb, cur_off, dns_data_offset, cinfo, qatree, pinfo);
1917 proto_item_set_len(ti, cur_off - start_off);
1919 return cur_off - start_off;
1923 dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1926 int offset = is_tcp ? 2 : 0;
1927 int dns_data_offset;
1929 proto_tree *dns_tree = NULL, *field_tree;
1930 proto_item *ti, *tf;
1931 guint16 id, flags, opcode, rcode, quest, ans, auth, add;
1936 dns_data_offset = offset;
1938 if (check_col(pinfo->cinfo, COL_INFO))
1939 col_clear(pinfo->cinfo, COL_INFO);
1941 /* To do: check for errs, etc. */
1942 id = tvb_get_ntohs(tvb, offset + DNS_ID);
1943 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
1944 opcode = (flags & F_OPCODE) >> OPCODE_SHIFT;
1945 rcode = (flags & F_RCODE);
1947 if (check_col(pinfo->cinfo, COL_INFO)) {
1948 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation (%u)"));
1949 if (flags & F_RESPONSE) {
1950 strcat(buf, " response");
1951 if ((flags & F_RCODE) != RCODE_NOERROR) {
1953 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1954 "Unknown error (%u)"));
1957 col_add_str(pinfo->cinfo, COL_INFO, buf);
1958 cinfo = pinfo->cinfo;
1960 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
1961 dissectors, as a way of saying that they shouldn't add stuff
1962 to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
1963 is more expensive than a check that a pointer isn't NULL). */
1966 if (opcode == OPCODE_UPDATE)
1972 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
1973 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1975 dns_tree = proto_item_add_subtree(ti, ett_dns);
1978 /* Put the length indication into the tree. */
1979 proto_tree_add_item(dns_tree, hf_dns_length, tvb, offset - 2, 2, FALSE);
1982 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
1983 offset + DNS_ID, 2, id);
1985 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
1986 if (flags & F_RESPONSE) {
1987 strcat(buf, " response");
1989 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1992 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
1993 offset + DNS_FLAGS, 2,
1995 "Flags: 0x%04x (%s)",
1997 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1998 proto_tree_add_item(field_tree, hf_dns_flags_response,
1999 tvb, offset + DNS_FLAGS, 2, FALSE);
2000 proto_tree_add_item(field_tree, hf_dns_flags_opcode,
2001 tvb, offset + DNS_FLAGS, 2, FALSE);
2002 if (flags & F_RESPONSE) {
2003 proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
2004 tvb, offset + DNS_FLAGS, 2, FALSE);
2006 proto_tree_add_item(field_tree, hf_dns_flags_truncated,
2007 tvb, offset + DNS_FLAGS, 2, FALSE);
2008 proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
2009 tvb, offset + DNS_FLAGS, 2, FALSE);
2010 if (flags & F_RESPONSE) {
2011 proto_tree_add_item(field_tree, hf_dns_flags_recavail,
2012 tvb, offset + DNS_FLAGS, 2, FALSE);
2013 proto_tree_add_item(field_tree, hf_dns_flags_z,
2014 tvb, offset + DNS_FLAGS, 2, FALSE);
2015 proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
2016 tvb, offset + DNS_FLAGS, 2, FALSE);
2017 proto_tree_add_item(field_tree, hf_dns_flags_rcode,
2018 tvb, offset + DNS_FLAGS, 2, FALSE);
2020 proto_tree_add_item(field_tree, hf_dns_flags_z,
2021 tvb, offset + DNS_FLAGS, 2, FALSE);
2022 proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
2023 tvb, offset + DNS_FLAGS, 2, FALSE);
2026 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
2028 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
2029 offset + DNS_QUEST, 2, quest);
2031 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
2033 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
2034 offset + DNS_ANS, 2, ans);
2036 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
2038 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
2039 offset + DNS_AUTH, 2, auth);
2041 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
2043 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
2044 offset + DNS_ADD, 2, add);
2047 cur_off = offset + DNS_HDRLEN;
2050 /* If this is a response, don't add information about the queries
2051 to the summary, just add information about the answers. */
2052 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
2053 (!(flags & F_RESPONSE) ? cinfo : NULL),
2054 dns_tree, isupdate);
2058 /* If this is a request, don't add information about the answers
2059 to the summary, just add information about the queries. */
2060 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
2061 ((flags & F_RESPONSE) ? cinfo : NULL),
2062 dns_tree, (isupdate ?
2063 "Prerequisites" : "Answers"),
2067 /* Don't add information about the authoritative name servers, or the
2068 additional records, to the summary. */
2070 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
2072 (isupdate ? "Updates" :
2073 "Authoritative nameservers"),
2078 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
2079 NULL, dns_tree, "Additional records",
2085 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2087 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2088 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2090 dissect_dns_common(tvb, pinfo, tree, FALSE);
2094 dissect_mdns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2096 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2097 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDNS");
2099 dissect_dns_common(tvb, pinfo, tree, FALSE);
2104 get_dns_pdu_len(tvbuff_t *tvb, int offset)
2109 * Get the length of the DNS packet.
2111 plen = tvb_get_ntohs(tvb, offset);
2114 * That length doesn't include the length field itself; add that in.
2120 dissect_dns_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2122 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2123 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2125 dissect_dns_common(tvb, pinfo, tree, TRUE);
2129 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2131 tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2, get_dns_pdu_len,
2132 dissect_dns_tcp_pdu);
2136 proto_register_dns(void)
2138 static hf_register_info hf[] = {
2140 { "Length", "dns.length",
2141 FT_UINT16, BASE_DEC, NULL, 0x0,
2142 "Length of DNS-over-TCP request or response", HFILL }},
2144 { "Flags", "dns.flags",
2145 FT_UINT16, BASE_HEX, NULL, 0x0,
2147 { &hf_dns_flags_response,
2148 { "Response", "dns.flags.response",
2149 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
2150 "Is the message a response?", HFILL }},
2151 { &hf_dns_flags_opcode,
2152 { "Opcode", "dns.flags.opcode",
2153 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
2154 "Operation code", HFILL }},
2155 { &hf_dns_flags_authoritative,
2156 { "Authoritative", "dns.flags.authoritative",
2157 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
2158 "Is the server is an authority for the domain?", HFILL }},
2159 { &hf_dns_flags_truncated,
2160 { "Truncated", "dns.flags.truncated",
2161 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
2162 "Is the message truncated?", HFILL }},
2163 { &hf_dns_flags_recdesired,
2164 { "Recursion desired", "dns.flags.recdesired",
2165 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
2166 "Do query recursively?", HFILL }},
2167 { &hf_dns_flags_recavail,
2168 { "Recursion available", "dns.flags.recavail",
2169 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
2170 "Can the server do recursive queries?", HFILL }},
2172 { "Z", "dns.flags.z",
2173 FT_BOOLEAN, 16, TFS(&tfs_flags_z), F_Z,
2175 { &hf_dns_flags_authenticated,
2176 { "Answer authenticated", "dns.flags.authenticated",
2177 FT_BOOLEAN, 16, TFS(&tfs_flags_authenticated), F_AUTHENTIC,
2178 "Was the reply data authenticated by the server?", HFILL }},
2179 { &hf_dns_flags_checkdisable,
2180 { "Non-authenticated data OK", "dns.flags.checkdisable",
2181 FT_BOOLEAN, 16, TFS(&tfs_flags_checkdisable), F_CHECKDISABLE,
2182 "Is non-authenticated data acceptable?", HFILL }},
2183 { &hf_dns_flags_rcode,
2184 { "Reply code", "dns.flags.rcode",
2185 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
2186 "Reply code", HFILL }},
2187 { &hf_dns_transaction_id,
2188 { "Transaction ID", "dns.id",
2189 FT_UINT16, BASE_HEX, NULL, 0x0,
2190 "Identification of transaction", HFILL }},
2191 { &hf_dns_count_questions,
2192 { "Questions", "dns.count.queries",
2193 FT_UINT16, BASE_DEC, NULL, 0x0,
2194 "Number of queries in packet", HFILL }},
2195 { &hf_dns_count_answers,
2196 { "Answer RRs", "dns.count.answers",
2197 FT_UINT16, BASE_DEC, NULL, 0x0,
2198 "Number of answers in packet", HFILL }},
2199 { &hf_dns_count_auth_rr,
2200 { "Authority RRs", "dns.count.auth_rr",
2201 FT_UINT16, BASE_DEC, NULL, 0x0,
2202 "Number of authoritative records in packet", HFILL }},
2203 { &hf_dns_count_add_rr,
2204 { "Additional RRs", "dns.count.add_rr",
2205 FT_UINT16, BASE_DEC, NULL, 0x0,
2206 "Number of additional records in packet", HFILL }}
2208 static gint *ett[] = {
2218 module_t *dns_module;
2220 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2221 proto_register_field_array(proto_dns, hf, array_length(hf));
2222 proto_register_subtree_array(ett, array_length(ett));
2224 dns_module = prefs_register_protocol(proto_dns, NULL);
2225 prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2226 "Desegment all DNS messages spanning multiple TCP segments",
2227 "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
2232 proto_reg_handoff_dns(void)
2234 dissector_handle_t dns_udp_handle;
2235 dissector_handle_t dns_tcp_handle;
2236 dissector_handle_t mdns_udp_handle;
2238 dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
2239 dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
2240 mdns_udp_handle = create_dissector_handle(dissect_mdns_udp, proto_dns);
2242 dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
2243 dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
2244 dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
2245 dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
2247 gssapi_handle = find_dissector("gssapi");