2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.99 2003/01/31 08:29:09 guy 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/packet.h>
40 #include <epan/resolv.h>
41 #include "packet-dns.h"
42 #include "packet-tcp.h"
45 static int proto_dns = -1;
46 static int hf_dns_length = -1;
47 static int hf_dns_flags = -1;
48 static int hf_dns_flags_response = -1;
49 static int hf_dns_flags_opcode = -1;
50 static int hf_dns_flags_authoritative = -1;
51 static int hf_dns_flags_truncated = -1;
52 static int hf_dns_flags_recdesired = -1;
53 static int hf_dns_flags_recavail = -1;
54 static int hf_dns_flags_authenticated = -1;
55 static int hf_dns_flags_checkdisable = -1;
56 static int hf_dns_flags_rcode = -1;
57 static int hf_dns_transaction_id = -1;
58 static int hf_dns_count_questions = -1;
59 static int hf_dns_count_answers = -1;
60 static int hf_dns_count_auth_rr = -1;
61 static int hf_dns_count_add_rr = -1;
63 static gint ett_dns = -1;
64 static gint ett_dns_qd = -1;
65 static gint ett_dns_rr = -1;
66 static gint ett_dns_qry = -1;
67 static gint ett_dns_ans = -1;
68 static gint ett_dns_flags = -1;
69 static gint ett_t_key_flags = -1;
70 static gint ett_t_key = -1;
72 /* desegmentation of DNS over TCP */
73 static gboolean dns_desegment = TRUE;
75 /* Dissector handle for GSSAPI */
76 static dissector_handle_t gssapi_handle;
78 /* DNS structs and definitions */
80 /* Ports used for DNS. */
81 #define UDP_PORT_DNS 53
82 #define TCP_PORT_DNS 53
83 #define UDP_PORT_MDNS 5353
84 #define TCP_PORT_MDNS 5353
86 /* Offsets of fields in the DNS header. */
94 /* Length of DNS header. */
98 #define T_A 1 /* host address */
99 #define T_NS 2 /* authoritative name server */
100 #define T_MD 3 /* mail destination (obsolete) */
101 #define T_MF 4 /* mail forwarder (obsolete) */
102 #define T_CNAME 5 /* canonical name */
103 #define T_SOA 6 /* start of authority zone */
104 #define T_MB 7 /* mailbox domain name (experimental) */
105 #define T_MG 8 /* mail group member (experimental) */
106 #define T_MR 9 /* mail rename domain name (experimental) */
107 #define T_NULL 10 /* null RR (experimental) */
108 #define T_WKS 11 /* well known service */
109 #define T_PTR 12 /* domain name pointer */
110 #define T_HINFO 13 /* host information */
111 #define T_MINFO 14 /* mailbox or mail list information */
112 #define T_MX 15 /* mail routing information */
113 #define T_TXT 16 /* text strings */
114 #define T_RP 17 /* responsible person (RFC 1183) */
115 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
116 #define T_X25 19 /* X.25 address (RFC 1183) */
117 #define T_ISDN 20 /* ISDN address (RFC 1183) */
118 #define T_RT 21 /* route-through (RFC 1183) */
119 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
120 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
121 #define T_SIG 24 /* digital signature (RFC 2535) */
122 #define T_KEY 25 /* public key (RFC 2535) */
123 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
124 #define T_GPOS 27 /* geographical position (RFC 1712) */
125 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
126 #define T_LOC 29 /* geographical location (RFC 1876) */
127 #define T_NXT 30 /* "next" name (RFC 2535) */
128 #define T_EID 31 /* ??? (Nimrod?) */
129 #define T_NIMLOC 32 /* ??? (Nimrod?) */
130 #define T_SRV 33 /* service location (RFC 2052) */
131 #define T_ATMA 34 /* ??? */
132 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
133 #define T_KX 36 /* Key Exchange (RFC 2230) */
134 #define T_CERT 37 /* Certificate (RFC 2538) */
135 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
136 #define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
137 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
138 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
139 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
140 #define T_WINS 65281 /* Microsoft's WINS RR */
141 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
144 #define C_IN 1 /* the Internet */
145 #define C_CS 2 /* CSNET (obsolete) */
146 #define C_CH 3 /* CHAOS */
147 #define C_HS 4 /* Hesiod */
148 #define C_NONE 254 /* none */
149 #define C_ANY 255 /* any */
150 #define C_FLUSH (1<<15) /* High bit is set for MDNS cache flush */
152 /* Bit fields in the flags */
153 #define F_RESPONSE (1<<15) /* packet is response */
154 #define F_OPCODE (0xF<<11) /* query opcode */
155 #define OPCODE_SHIFT 11
156 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
157 #define F_TRUNCATED (1<<9) /* response is truncated */
158 #define F_RECDESIRED (1<<8) /* recursion desired */
159 #define F_RECAVAIL (1<<7) /* recursion available */
160 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
161 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
162 #define F_RCODE (0xF<<0) /* reply code */
164 static const true_false_string tfs_flags_response = {
165 "Message is a response",
169 static const true_false_string tfs_flags_authoritative = {
170 "Server is an authority for domain",
171 "Server is not an authority for domain"
174 static const true_false_string tfs_flags_truncated = {
175 "Message is truncated",
176 "Message is not truncated"
179 static const true_false_string tfs_flags_recdesired = {
180 "Do query recursively",
181 "Don't do query recursively"
184 static const true_false_string tfs_flags_recavail = {
185 "Server can do recursive queries",
186 "Server can't do recursive queries"
189 static const true_false_string tfs_flags_authenticated = {
190 "Answer/authority portion was authenticated by the server",
191 "Answer/authority portion was not authenticated by the server"
194 static const true_false_string tfs_flags_checkdisable = {
195 "Non-authenticated data is acceptable",
196 "Non-authenticated data is unacceptable"
200 #define OPCODE_QUERY 0 /* standard query */
201 #define OPCODE_IQUERY 1 /* inverse query */
202 #define OPCODE_STATUS 2 /* server status request */
203 #define OPCODE_NOTIFY 4 /* zone change notification */
204 #define OPCODE_UPDATE 5 /* dynamic update */
206 static const value_string opcode_vals[] = {
207 { OPCODE_QUERY, "Standard query" },
208 { OPCODE_IQUERY, "Inverse query" },
209 { OPCODE_STATUS, "Server status request" },
210 { OPCODE_NOTIFY, "Zone change notification" },
211 { OPCODE_UPDATE, "Dynamic update" },
215 #define RCODE_NOERROR 0
216 #define RCODE_FORMERR 1
217 #define RCODE_SERVFAIL 2
218 #define RCODE_NXDOMAIN 3
219 #define RCODE_NOTIMPL 4
220 #define RCODE_REFUSED 5
221 #define RCODE_YXDOMAIN 6
222 #define RCODE_YXRRSET 7
223 #define RCODE_NXRRSET 8
224 #define RCODE_NOTAUTH 9
225 #define RCODE_NOTZONE 10
227 static const value_string rcode_vals[] = {
228 { RCODE_NOERROR, "No error" },
229 { RCODE_FORMERR, "Format error" },
230 { RCODE_SERVFAIL, "Server failure" },
231 { RCODE_NXDOMAIN, "No such name" },
232 { RCODE_NOTIMPL, "Not implemented" },
233 { RCODE_REFUSED, "Refused" },
234 { RCODE_YXDOMAIN, "Name exists" },
235 { RCODE_YXRRSET, "RRset exists" },
236 { RCODE_NXRRSET, "RRset does not exist" },
237 { RCODE_NOTAUTH, "Not authoritative" },
238 { RCODE_NOTZONE, "Name out of zone" },
241 /* TSIG/TKEY extended errors */
242 #define TSIGERROR_BADSIG (16)
243 #define TSIGERROR_BADKEY (17)
244 #define TSIGERROR_BADTIME (18)
245 #define TSIGERROR_BADMODE (19)
246 #define TSIGERROR_BADNAME (20)
247 #define TSIGERROR_BADALG (21)
249 static const value_string tsigerror_vals[] = {
250 { TSIGERROR_BADSIG, "Bad signature" },
251 { TSIGERROR_BADKEY, "Bad key" },
252 { TSIGERROR_BADTIME, "Bad time failure" },
253 { TSIGERROR_BADMODE, "Bad mode such name" },
254 { TSIGERROR_BADNAME, "Bad name implemented" },
255 { TSIGERROR_BADALG, "Bad algorithm" },
258 #define TKEYMODE_SERVERASSIGNED (1)
259 #define TKEYMODE_DIFFIEHELLMAN (2)
260 #define TKEYMODE_GSSAPI (3)
261 #define TKEYMODE_RESOLVERASSIGNED (4)
262 #define TKEYMODE_DELETE (5)
264 /* See RFC 1035 for all RR types for which no RFC is listed, except for
265 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
266 which one should look at
268 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
272 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
274 which discuss them to some extent. */
276 dns_type_name (guint type)
278 char *type_names[] = {
297 "AFSDB", /* RFC 1183 */
298 "X25", /* RFC 1183 */
299 "ISDN", /* RFC 1183 */
301 "NSAP", /* RFC 1706 */
302 "NSAP-PTR", /* RFC 1348 */
303 "SIG", /* RFC 2535 */
304 "KEY", /* RFC 2535 */
306 "GPOS", /* RFC 1712 */
307 "AAAA", /* RFC 1886 */
308 "LOC", /* RFC 1876 */
309 "NXT", /* RFC 2535 */
312 "SRV", /* RFC 2052 */
314 "NAPTR", /* RFC 2168 */
316 "CERT", /* RFC 2538 */
318 "DNAME", /* RFC 2672 */
323 if (type < sizeof(type_names)/sizeof(type_names[0]))
324 return type_names[type] ? type_names[type] : "unknown";
351 return "IXFR"; /* RFC 1995 */
368 dns_long_type_name (guint type)
370 char *type_names[] = {
373 "Authoritative name server",
376 "Canonical name for an alias",
377 "Start of zone of authority",
378 "Mailbox domain name",
380 "Mail rename domain name",
381 "Null resource record",
382 "Well-known service description",
383 "Domain name pointer",
385 "Mailbox or mail list information",
388 "Responsible person", /* RFC 1183 */
389 "AFS data base location", /* RFC 1183 */
390 "X.25 address", /* RFC 1183 */
391 "ISDN number", /* RFC 1183 */
392 "Route through", /* RFC 1183 */
393 "OSI NSAP", /* RFC 1706 */
394 "OSI NSAP name pointer", /* RFC 1348 */
395 "Signature", /* RFC 2535 */
396 "Public key", /* RFC 2535 */
397 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
398 "Geographical position", /* RFC 1712 */
399 "IPv6 address", /* RFC 1886 */
400 "Location", /* RFC 1876 */
401 "Next", /* RFC 2535 */
404 "Service location", /* RFC 2052 */
406 "Naming authority pointer", /* RFC 2168 */
407 "Key Exchange", /* RFC 2230 */
408 "Certificate", /* RFC 2538 */
409 "IPv6 address with indirection", /* RFC 2874 */
410 "Non-terminal DNS name redirection", /* RFC 2672 */
412 "EDNS0 option" /* RFC 2671 */
414 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%u)" */
416 if (type < sizeof(type_names)/sizeof(type_names[0]))
417 return type_names[type] ? type_names[type] : "unknown";
438 return "Transaction Key";
440 return "Transaction Signature";
444 return "Request for incremental zone transfer"; /* RFC 1995 */
446 return "Request for full zone transfer";
448 return "Request for mailbox-related records";
450 return "Request for mail agent resource records";
452 return "Request for all records";
455 sprintf(unkbuf, "Unknown RR type (%u)", type);
461 dns_class_name(int class)
469 case ( C_IN | C_FLUSH ):
470 class_name = "inet (data flush)";
473 class_name = "csnet";
476 class_name = "chaos";
479 class_name = "hesiod";
488 class_name = "unknown";
495 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
496 char *name, int maxname)
498 int start_offset = offset;
501 int chars_processed = 0;
502 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
506 const int min_len = 1; /* Minimum length of encoded name (for root) */
507 /* If we're about to return a value (probably negative) which is less
508 * than the minimum length, we're looking at bad data and we're liable
509 * to put the dissector into a loop. Instead we throw an exception */
511 maxname--; /* reserve space for the trailing '\0' */
513 component_len = tvb_get_guint8(tvb, offset);
515 if (component_len == 0)
518 switch (component_len & 0xc0) {
523 /* Not the first component - put in a '.'. */
529 while (component_len > 0) {
531 *np++ = tvb_get_guint8(tvb, offset);
541 /* Extended label (RFC 2673) */
542 switch (component_len & 0x3f) {
545 /* Bitstring label */
551 bit_count = tvb_get_guint8(tvb, offset);
553 label_len = (bit_count - 1) / 8 + 1;
556 print_len = snprintf(np, maxname + 1, "\\[x");
557 if (print_len != -1) {
558 /* Some versions of snprintf return -1 if they'd truncate
561 maxname -= print_len;
563 /* Nothing printed, as there's no room.
564 Suppress all subsequent printing. */
570 print_len = snprintf(np, maxname + 1, "%02x",
571 tvb_get_guint8(tvb, offset));
572 if (print_len != -1) {
573 /* Some versions of snprintf return -1 if they'd truncate
576 maxname -= print_len;
578 /* Nothing printed, as there's no room.
579 Suppress all subsequent printing. */
586 print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
587 if (print_len != -1) {
588 /* Some versions of snprintf return -1 if they'd truncate
591 maxname -= print_len;
593 /* Nothing printed, as there's no room.
594 Suppress all subsequent printing. */
602 strcpy(name, "<Unknown extended label>");
603 /* Parsing will propably fail from here on, since the */
604 /* label length is unknown... */
605 len = offset - start_offset;
607 THROW(ReportedBoundsError);
613 THROW(ReportedBoundsError);
617 indir_offset = dns_data_offset +
618 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
622 /* If "len" is negative, we are still working on the original name,
623 not something pointed to by a pointer, and so we should set "len"
624 to the length of the original name. */
626 len = offset - start_offset;
628 /* If we've looked at every character in the message, this pointer
629 will make us look at some character again, which means we're
631 if (chars_processed >= data_size) {
632 strcpy(name, "<Name contains a pointer that loops>");
634 THROW(ReportedBoundsError);
638 offset = indir_offset;
639 break; /* now continue processing from there */
644 /* If "len" is negative, we haven't seen a pointer, and thus haven't
645 set the length, so set it. */
647 len = offset - start_offset;
648 /* Zero-length name means "root server" */
650 strcpy(name, "<Root>");
652 THROW(ReportedBoundsError);
658 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
659 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
666 int start_offset = offset;
668 name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
671 type = tvb_get_ntohs(tvb, offset);
674 class = tvb_get_ntohs(tvb, offset);
677 strcpy (name_ret, name);
680 *name_len_ret = name_len;
682 len = offset - start_offset;
687 rfc1867_size(tvbuff_t *tvb, int offset)
693 val = tvb_get_guint8(tvb, offset);
694 size = (val & 0xF0) >> 4;
695 exponent = (val & 0x0F);
696 while (exponent != 0) {
700 return size / 100; /* return size in meters, not cm */
704 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
708 guint32 degrees, minutes, secs, tsecs;
709 /* "%u deg %u min %u.%03u sec %c" */
710 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
712 angle = tvb_get_ntohl(tvb, offset);
714 if (angle < 0x80000000U) {
715 angle = 0x80000000U - angle;
718 angle = angle - 0x80000000U;
721 tsecs = angle % 1000;
722 angle = angle / 1000;
725 minutes = angle % 60;
726 degrees = angle / 60;
727 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
733 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
734 column_info *cinfo, proto_tree *dns_tree)
743 char *long_type_name;
749 data_start = data_offset = offset;
751 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
755 type_name = dns_type_name(type);
756 class_name = dns_class_name(class);
757 long_type_name = dns_long_type_name(type);
760 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
761 if (dns_tree != NULL) {
762 tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
763 name, type_name, class_name);
764 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
766 proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
769 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
772 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
776 return data_offset - data_start;
781 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
782 const char *name, int namelen, const char *type_name, const char *class_name,
783 guint ttl, gushort data_len)
787 rr_tree = proto_item_add_subtree(trr, rr_type);
788 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
790 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
792 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
794 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
795 time_secs_to_str(ttl));
797 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
802 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
803 const char *name, int namelen, const char *type_name, int class,
804 guint ttl, gushort data_len)
808 rr_tree = proto_item_add_subtree(trr, rr_type);
809 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
811 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
813 proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
816 proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
817 (ttl >> 24) & 0xff0);
819 proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
822 proto_tree_add_text(rr_tree, tvb, offset, 2, "Must be zero: 0x%x", ttl & 0xffff);
824 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
829 * SIG, KEY, and CERT RR algorithms.
831 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
832 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
833 #define DNS_ALGO_DSA 3 /* DSA */
834 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
835 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
836 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
837 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
839 static const value_string algo_vals[] = {
840 { DNS_ALGO_RSAMD5, "RSA/MD5" },
841 { DNS_ALGO_DH, "Diffie-Hellman" },
842 { DNS_ALGO_DSA, "DSA" },
843 { DNS_ALGO_ECC, "Elliptic curve crypto" },
844 { DNS_ALGO_INDIRECT, "Indirect key" },
845 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
846 { DNS_ALGO_PRIVATEOID, "Private, OID" },
850 #define DNS_CERT_PGP 1 /* PGP */
851 #define DNS_CERT_PKIX 2 /* PKIX */
852 #define DNS_CERT_SPKI 3 /* SPKI */
853 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
854 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
856 static const value_string cert_vals[] = {
857 { DNS_CERT_PGP, "PGP" },
858 { DNS_CERT_PKIX, "PKIX" },
859 { DNS_CERT_SPKI, "SPKI" },
860 { DNS_CERT_PRIVATEURI, "Private, URI" },
861 { DNS_CERT_PRIVATEOID, "Private, OID" },
866 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
867 column_info *cinfo, proto_tree *dns_tree, packet_info *pinfo)
876 char *long_type_name;
882 proto_tree *rr_tree = NULL;
883 proto_item *trr = NULL;
885 data_start = data_offset = offset;
888 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
893 type_name = dns_type_name(type);
894 class_name = dns_class_name(class);
895 long_type_name = dns_long_type_name(type);
897 ttl = tvb_get_ntohl(tvb, data_offset);
901 data_len = tvb_get_ntohs(tvb, data_offset);
906 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
907 if (dns_tree != NULL) {
908 trr = proto_tree_add_text(dns_tree, tvb, offset,
909 (data_offset - data_start) + data_len,
910 "%s: type %s, class %s",
911 name, type_name, class_name);
913 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
914 long_type_name, class_name, ttl, data_len);
916 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
917 long_type_name, class, ttl, data_len);
928 addr = tvb_get_ptr(tvb, cur_offset, 4);
930 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
931 if (dns_tree != NULL) {
932 proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
933 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
936 if ((class & 0x7f) == C_IN) {
937 memcpy(&addr_int, addr, sizeof(addr_int));
938 add_host_name(addr_int, name);
945 char ns_name[MAXDNAME];
948 ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
950 col_append_fstr(cinfo, COL_INFO, " %s", ns_name);
951 if (dns_tree != NULL) {
952 proto_item_append_text(trr, ", ns %s", ns_name);
953 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
961 char cname[MAXDNAME];
964 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
966 col_append_fstr(cinfo, COL_INFO, " %s", cname);
967 if (dns_tree != NULL) {
968 proto_item_append_text(trr, ", cname %s", cname);
969 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
977 char mname[MAXDNAME];
979 char rname[MAXDNAME];
987 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
989 col_append_fstr(cinfo, COL_INFO, " %s", mname);
990 if (dns_tree != NULL) {
991 proto_item_append_text(trr, ", mname %s", mname);
992 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
994 cur_offset += mname_len;
996 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
997 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
999 cur_offset += rname_len;
1001 serial = tvb_get_ntohl(tvb, cur_offset);
1002 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
1006 refresh = tvb_get_ntohl(tvb, cur_offset);
1007 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
1008 time_secs_to_str(refresh));
1011 retry = tvb_get_ntohl(tvb, cur_offset);
1012 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
1013 time_secs_to_str(retry));
1016 expire = tvb_get_ntohl(tvb, cur_offset);
1017 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
1018 time_secs_to_str(expire));
1021 minimum = tvb_get_ntohl(tvb, cur_offset);
1022 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
1023 time_secs_to_str(minimum));
1030 char pname[MAXDNAME];
1033 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
1035 col_append_fstr(cinfo, COL_INFO, " %s", pname);
1036 if (dns_tree != NULL) {
1037 proto_item_append_text(trr, ", %s", pname);
1038 proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
1047 int rr_len = data_len;
1048 const guint8 *wks_addr;
1054 char bitnames[128+1];
1055 char portnumstring[10+1];
1057 wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
1059 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
1060 if (dns_tree != NULL) {
1061 proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
1062 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
1063 ip_to_str(wks_addr));
1067 protocol = tvb_get_guint8(tvb, cur_offset);
1068 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
1069 ipprotostr(protocol));
1074 while (rr_len != 0) {
1075 bits = tvb_get_guint8(tvb, cur_offset);
1079 for (i = 0; i < 8; i++) {
1081 if (bitnames[0] != '\0')
1082 strcat(bitnames, ", ");
1086 strcat(bitnames, get_tcp_port(port_num));
1090 strcat(bitnames, get_udp_port(port_num));
1094 sprintf(portnumstring, "%u", port_num);
1095 strcat(bitnames, portnumstring);
1102 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1103 "Bits: 0x%02x (%s)", bits, bitnames);
1122 cpu_offset = cur_offset;
1123 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1124 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1125 os_offset = cpu_offset + 1 + cpu_len;
1126 os_len = tvb_get_guint8(tvb, os_offset);
1127 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1129 col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1131 if (dns_tree != NULL) {
1132 proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1133 cpu_len, cpu, os_len, os);
1134 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1136 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1145 guint16 preference = 0;
1146 char mx_name[MAXDNAME];
1149 preference = tvb_get_ntohs(tvb, cur_offset);
1150 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1152 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, mx_name);
1153 if (dns_tree != NULL) {
1154 proto_item_append_text(trr, ", preference %u, mx %s",
1155 preference, mx_name);
1156 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1157 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1165 int rr_len = data_len;
1169 if (dns_tree != NULL) {
1170 txt_offset = cur_offset;
1171 while (rr_len != 0) {
1172 txt_len = tvb_get_guint8(tvb, txt_offset);
1173 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1174 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1175 txt_offset += 1 + txt_len;
1176 rr_len -= 1 + txt_len;
1184 int rr_len = data_len;
1185 guint16 type_covered;
1187 char signer_name[MAXDNAME];
1188 int signer_name_len;
1190 if (dns_tree != NULL) {
1191 type_covered = tvb_get_ntohs(tvb, cur_offset);
1192 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1193 dns_type_name(type_covered),
1194 dns_long_type_name(type_covered));
1198 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1199 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1200 "Unknown (0x%02X)"));
1204 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1205 tvb_get_guint8(tvb, cur_offset));
1209 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1210 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1214 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1216 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1217 abs_time_to_str(&nstime));
1221 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1223 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1224 abs_time_to_str(&nstime));
1228 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1229 tvb_get_ntohs(tvb, cur_offset));
1233 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1234 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1235 "Signer's name: %s", signer_name);
1236 cur_offset += signer_name_len;
1237 rr_len -= signer_name_len;
1239 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1246 int rr_len = data_len;
1249 proto_tree *flags_tree;
1251 if (dns_tree != NULL) {
1252 flags = tvb_get_ntohs(tvb, cur_offset);
1253 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1254 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1255 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1256 decode_boolean_bitfield(flags, 0x8000,
1257 2*8, "Key prohibited for authentication",
1258 "Key allowed for authentication"));
1259 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1260 decode_boolean_bitfield(flags, 0x4000,
1261 2*8, "Key prohibited for confidentiality",
1262 "Key allowed for confidentiality"));
1263 if ((flags & 0xC000) != 0xC000) {
1265 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1266 decode_boolean_bitfield(flags, 0x2000,
1267 2*8, "Key is experimental or optional",
1268 "Key is required"));
1269 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1270 decode_boolean_bitfield(flags, 0x0400,
1271 2*8, "Key is associated with a user",
1272 "Key is not associated with a user"));
1273 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1274 decode_boolean_bitfield(flags, 0x0200,
1275 2*8, "Key is associated with the named entity",
1276 "Key is not associated with the named entity"));
1277 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1278 decode_boolean_bitfield(flags, 0x0100,
1279 2*8, "This is the zone key for the specified zone",
1280 "This is not a zone key"));
1281 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1282 decode_boolean_bitfield(flags, 0x0080,
1283 2*8, "Key is valid for use with IPSEC",
1284 "Key is not valid for use with IPSEC"));
1285 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1286 decode_boolean_bitfield(flags, 0x0040,
1287 2*8, "Key is valid for use with MIME security multiparts",
1288 "Key is not valid for use with MIME security multiparts"));
1289 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1290 decode_numeric_bitfield(flags, 0x000F,
1291 2*8, "Signatory = %u"));
1296 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1297 tvb_get_guint8(tvb, cur_offset));
1301 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1302 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1303 "Unknown (0x%02X)"));
1307 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1314 const guint8 *addr6;
1316 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1317 if (cinfo != NULL) {
1318 col_append_fstr(cinfo, COL_INFO, " %s",
1319 ip6_to_str((const struct e_in6_addr *)addr6));
1321 if (dns_tree != NULL) {
1322 proto_item_append_text(trr, ", addr %s",
1323 ip6_to_str((const struct e_in6_addr *)addr6));
1324 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1325 ip6_to_str((const struct e_in6_addr *)addr6));
1332 unsigned short pre_len;
1333 unsigned short suf_len;
1334 unsigned short suf_octet_count;
1335 char pname[MAXDNAME];
1341 a6_offset = cur_offset;
1342 pre_len = tvb_get_guint8(tvb, cur_offset);
1344 suf_len = 128 - pre_len;
1345 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1347 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1348 suffix[suf_offset] = 0;
1350 for (; suf_offset < 16; suf_offset++) {
1351 suffix[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1356 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1357 pname, sizeof(pname));
1363 if (cinfo != NULL) {
1364 col_append_fstr(cinfo, COL_INFO, " %d %s %s",
1366 ip6_to_str((struct e_in6_addr *)&suffix),
1369 if (dns_tree != NULL) {
1370 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1371 "Prefix len: %u", pre_len);
1374 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1375 "Address suffix: %s",
1376 ip6_to_str((struct e_in6_addr *)&suffix));
1377 a6_offset += suf_octet_count;
1380 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1381 "Prefix name: %s", pname);
1383 proto_item_append_text(trr, ", addr %d %s %s",
1385 ip6_to_str((struct e_in6_addr *)&suffix),
1393 char dname[MAXDNAME];
1396 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1397 dname, sizeof(dname));
1399 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1400 if (dns_tree != NULL) {
1401 proto_item_append_text(trr, ", dname %s", dname);
1402 proto_tree_add_text(rr_tree, tvb, cur_offset,
1403 dname_len, "Target name: %s", dname);
1412 if (dns_tree != NULL) {
1413 version = tvb_get_guint8(tvb, cur_offset);
1414 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1416 /* Version 0, the only version RFC 1876 discusses. */
1419 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1420 rfc1867_size(tvb, cur_offset));
1423 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1424 rfc1867_size(tvb, cur_offset));
1427 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1428 rfc1867_size(tvb, cur_offset));
1431 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1432 rfc1867_angle(tvb, cur_offset, "NS"));
1435 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1436 rfc1867_angle(tvb, cur_offset, "EW"));
1439 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1440 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1442 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1450 int rr_len = data_len;
1451 char next_domain_name[MAXDNAME];
1452 int next_domain_name_len;
1458 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1459 next_domain_name, sizeof(next_domain_name));
1461 col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
1462 if (dns_tree != NULL) {
1463 proto_item_append_text(trr, ", next domain name %s",
1465 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1466 "Next domain name: %s", next_domain_name);
1467 cur_offset += next_domain_name_len;
1468 rr_len -= next_domain_name_len;
1470 while (rr_len != 0) {
1471 bits = tvb_get_guint8(tvb, cur_offset);
1473 for (i = 0; i < 8; i++) {
1475 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1476 "RR type in bit map: %s (%s)",
1477 dns_type_name(rr_type),
1478 dns_long_type_name(rr_type));
1492 guint16 preference = 0;
1493 char kx_name[MAXDNAME];
1496 preference = tvb_get_ntohs(tvb, cur_offset);
1497 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1499 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, kx_name);
1500 if (dns_tree != NULL) {
1501 proto_item_append_text(trr, ", preference %u, kx %s",
1502 preference, kx_name);
1503 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1504 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1512 guint16 cert_type, cert_keytag;
1514 int rr_len = data_len;
1516 cert_type = tvb_get_ntohs(tvb, cur_offset);
1519 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1522 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1526 if (dns_tree != NULL) {
1527 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s",
1528 val_to_str(cert_keyalg, cert_vals,
1529 "Unknown (0x%02X)"));
1530 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1532 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1533 val_to_str(cert_keyalg, algo_vals,
1534 "Unknown (0x%02X)"));
1535 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1542 if (dns_tree != NULL)
1543 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1548 char tkey_algname[MAXDNAME];
1549 int tkey_algname_len;
1550 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1551 int rr_len = data_len;
1553 static const value_string tkey_modes[] = {
1554 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1555 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1556 { TKEYMODE_GSSAPI, "GSSAPI" },
1557 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1558 { TKEYMODE_DELETE, "Delete" },
1561 if (dns_tree != NULL) {
1562 proto_tree *key_tree;
1563 proto_item *key_item;
1565 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1566 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1567 "Algorithm name: %s", tkey_algname);
1568 cur_offset += tkey_algname_len;
1569 rr_len -= tkey_algname_len;
1571 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1573 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1574 abs_time_to_str(&nstime));
1578 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1580 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1581 abs_time_to_str(&nstime));
1585 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1588 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Mode: %s",
1589 val_to_str(tkey_mode, tkey_modes,
1590 "Unknown (0x%04X)"));
1592 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1595 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1596 val_to_str(tkey_error, rcode_vals,
1597 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1599 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1603 key_item = proto_tree_add_text(
1604 rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1606 key_tree = proto_item_add_subtree(key_item, ett_t_key);
1609 case TKEYMODE_GSSAPI: {
1610 tvbuff_t *gssapi_tvb;
1613 * XXX - in at least one capture, this appears to
1614 * be an NTLMSSP blob, with no ASN.1 in it, in
1619 * http://www.alternic.org/drafts/drafts-s-t/draft-skwan-gss-tsig-05.html
1621 * which might indicate what's going on here. (The key
1622 * is an output_token from GSS_Init_sec_context.)
1624 * How the heck do we know what method is being used,
1625 * so we know how to decode the key?
1627 gssapi_tvb = tvb_new_subset(
1628 tvb, cur_offset, tkey_keylen, tkey_keylen);
1630 call_dissector(gssapi_handle, gssapi_tvb, pinfo, key_tree);
1636 /* No dissector for this key mode */
1641 cur_offset += tkey_keylen;
1642 rr_len -= tkey_keylen;
1644 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1648 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1649 cur_offset += tkey_otherlen;
1650 rr_len -= tkey_otherlen;
1658 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1659 guint32 tsig_timelo;
1660 char tsig_algname[MAXDNAME];
1661 int tsig_algname_len;
1663 int rr_len = data_len;
1665 if (dns_tree != NULL) {
1666 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1667 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1668 "Algorithm name: %s", tsig_algname);
1669 cur_offset += tsig_algname_len;
1670 rr_len -= tsig_algname_len;
1672 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1673 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1674 nstime.secs = tsig_timelo;
1676 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1677 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
1681 tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1682 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1687 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1691 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1692 cur_offset += tsig_siglen;
1693 rr_len -= tsig_siglen;
1695 tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1696 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1701 tsig_error = tvb_get_ntohs(tvb, cur_offset);
1702 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1703 val_to_str(tsig_error, rcode_vals,
1704 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1708 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1712 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1713 cur_offset += tsig_otherlen;
1714 rr_len -= tsig_otherlen;
1721 int rr_len = data_len;
1723 guint32 lookup_timeout;
1724 guint32 cache_timeout;
1727 if (dns_tree != NULL) {
1728 local_flag = tvb_get_ntohl(tvb, cur_offset);
1729 if (dns_tree != NULL) {
1730 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1731 local_flag ? "true" : "false");
1736 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1737 if (dns_tree != NULL) {
1738 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1744 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1745 if (dns_tree != NULL) {
1746 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1752 nservers = tvb_get_ntohl(tvb, cur_offset);
1753 if (dns_tree != NULL) {
1754 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
1760 while (rr_len != 0 && nservers != 0) {
1761 if (dns_tree != NULL) {
1762 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
1763 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
1775 int rr_len = data_len;
1777 guint32 lookup_timeout;
1778 guint32 cache_timeout;
1779 char dname[MAXDNAME];
1782 local_flag = tvb_get_ntohl(tvb, cur_offset);
1783 if (dns_tree != NULL) {
1784 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1785 local_flag ? "true" : "false");
1790 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1791 if (dns_tree != NULL) {
1792 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1798 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1799 if (dns_tree != NULL) {
1800 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1806 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1808 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1809 if (dns_tree != NULL) {
1810 proto_item_append_text(trr, ", name result domain %s", dname);
1811 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
1819 guint16 priority = 0;
1822 char target[MAXDNAME];
1825 priority = tvb_get_ntohs(tvb, cur_offset);
1826 weight = tvb_get_ntohs(tvb, cur_offset+2);
1827 port = tvb_get_ntohs(tvb, cur_offset+4);
1829 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1831 col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, target);
1832 if (dns_tree != NULL) {
1833 proto_item_append_text(trr,
1834 ", priority %u, weight %u, port %u, target %s",
1835 priority, weight, port, target);
1836 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
1837 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
1838 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
1839 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
1845 /* TODO: parse more record types */
1848 if (dns_tree != NULL)
1849 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1853 data_offset += data_len;
1855 return data_offset - data_start;
1859 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1860 int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
1862 int start_off, add_off;
1863 proto_tree *qatree = NULL;
1864 proto_item *ti = NULL;
1866 start_off = cur_off;
1868 char *s = (isupdate ? "Zone" : "Queries");
1869 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
1870 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1872 while (count-- > 0) {
1873 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
1877 proto_item_set_len(ti, cur_off - start_off);
1879 return cur_off - start_off;
1883 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1884 int count, column_info *cinfo, proto_tree *dns_tree, char *name,
1887 int start_off, add_off;
1888 proto_tree *qatree = NULL;
1889 proto_item *ti = NULL;
1891 start_off = cur_off;
1893 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
1894 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1896 while (count-- > 0) {
1897 add_off = dissect_dns_answer(
1898 tvb, cur_off, dns_data_offset, cinfo, qatree, pinfo);
1902 proto_item_set_len(ti, cur_off - start_off);
1904 return cur_off - start_off;
1908 dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1911 int offset = is_tcp ? 2 : 0;
1912 int dns_data_offset;
1914 proto_tree *dns_tree = NULL, *field_tree;
1915 proto_item *ti, *tf;
1916 guint16 id, flags, opcode, rcode, quest, ans, auth, add;
1921 dns_data_offset = offset;
1923 if (check_col(pinfo->cinfo, COL_INFO))
1924 col_clear(pinfo->cinfo, COL_INFO);
1926 /* To do: check for errs, etc. */
1927 id = tvb_get_ntohs(tvb, offset + DNS_ID);
1928 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
1929 opcode = (flags & F_OPCODE) >> OPCODE_SHIFT;
1930 rcode = (flags & F_RCODE);
1932 if (check_col(pinfo->cinfo, COL_INFO)) {
1933 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation (%u)"));
1934 if (flags & F_RESPONSE) {
1935 strcat(buf, " response");
1936 if ((flags & F_RCODE) != RCODE_NOERROR) {
1938 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1939 "Unknown error (%u)"));
1942 col_add_str(pinfo->cinfo, COL_INFO, buf);
1943 cinfo = pinfo->cinfo;
1945 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
1946 dissectors, as a way of saying that they shouldn't add stuff
1947 to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
1948 is more expensive than a check that a pointer isn't NULL). */
1951 if (opcode == OPCODE_UPDATE)
1957 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
1958 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1960 dns_tree = proto_item_add_subtree(ti, ett_dns);
1963 /* Put the length indication into the tree. */
1964 proto_tree_add_item(dns_tree, hf_dns_length, tvb, offset - 2, 2, FALSE);
1967 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
1968 offset + DNS_ID, 2, id);
1970 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
1971 if (flags & F_RESPONSE) {
1972 strcat(buf, " response");
1974 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1977 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
1978 offset + DNS_FLAGS, 2,
1980 "Flags: 0x%04x (%s)",
1982 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1983 proto_tree_add_item(field_tree, hf_dns_flags_response,
1984 tvb, offset + DNS_FLAGS, 2, FALSE);
1985 proto_tree_add_item(field_tree, hf_dns_flags_opcode,
1986 tvb, offset + DNS_FLAGS, 2, FALSE);
1987 if (flags & F_RESPONSE) {
1988 proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
1989 tvb, offset + DNS_FLAGS, 2, FALSE);
1991 proto_tree_add_item(field_tree, hf_dns_flags_truncated,
1992 tvb, offset + DNS_FLAGS, 2, FALSE);
1993 proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
1994 tvb, offset + DNS_FLAGS, 2, FALSE);
1995 if (flags & F_RESPONSE) {
1996 proto_tree_add_item(field_tree, hf_dns_flags_recavail,
1997 tvb, offset + DNS_FLAGS, 2, FALSE);
1998 proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
1999 tvb, offset + DNS_FLAGS, 2, FALSE);
2000 proto_tree_add_item(field_tree, hf_dns_flags_rcode,
2001 tvb, offset + DNS_FLAGS, 2, FALSE);
2003 proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
2004 tvb, offset + DNS_FLAGS, 2, FALSE);
2007 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
2009 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
2010 offset + DNS_QUEST, 2, quest);
2012 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
2014 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
2015 offset + DNS_ANS, 2, ans);
2017 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
2019 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
2020 offset + DNS_AUTH, 2, auth);
2022 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
2024 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
2025 offset + DNS_ADD, 2, add);
2028 cur_off = offset + DNS_HDRLEN;
2031 /* If this is a response, don't add information about the queries
2032 to the summary, just add information about the answers. */
2033 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
2034 (!(flags & F_RESPONSE) ? cinfo : NULL),
2035 dns_tree, isupdate);
2039 /* If this is a request, don't add information about the answers
2040 to the summary, just add information about the queries. */
2041 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
2042 ((flags & F_RESPONSE) ? cinfo : NULL),
2043 dns_tree, (isupdate ?
2044 "Prerequisites" : "Answers"),
2048 /* Don't add information about the authoritative name servers, or the
2049 additional records, to the summary. */
2051 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
2053 (isupdate ? "Updates" :
2054 "Authoritative nameservers"),
2059 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
2060 NULL, dns_tree, "Additional records",
2066 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2068 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2069 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2071 dissect_dns_common(tvb, pinfo, tree, FALSE);
2075 dissect_mdns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2077 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2078 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDNS");
2080 dissect_dns_common(tvb, pinfo, tree, FALSE);
2085 get_dns_pdu_len(tvbuff_t *tvb, int offset)
2090 * Get the length of the DNS packet.
2092 plen = tvb_get_ntohs(tvb, offset);
2095 * That length doesn't include the length field itself; add that in.
2101 dissect_dns_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2103 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2104 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2106 dissect_dns_common(tvb, pinfo, tree, TRUE);
2110 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2112 tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2, get_dns_pdu_len,
2113 dissect_dns_tcp_pdu);
2117 proto_register_dns(void)
2119 static hf_register_info hf[] = {
2121 { "Length", "dns.length",
2122 FT_UINT16, BASE_DEC, NULL, 0x0,
2123 "Length of DNS-over-TCP request or response", HFILL }},
2125 { "Flags", "dns.flags",
2126 FT_UINT16, BASE_HEX, NULL, 0x0,
2128 { &hf_dns_flags_response,
2129 { "Response", "dns.flags.response",
2130 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
2131 "Is the message a response?", HFILL }},
2132 { &hf_dns_flags_opcode,
2133 { "Opcode", "dns.flags.opcode",
2134 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
2135 "Operation code", HFILL }},
2136 { &hf_dns_flags_authoritative,
2137 { "Authoritative", "dns.flags.authoritative",
2138 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
2139 "Is the server is an authority for the domain?", HFILL }},
2140 { &hf_dns_flags_truncated,
2141 { "Truncated", "dns.flags.truncated",
2142 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
2143 "Is the message truncated?", HFILL }},
2144 { &hf_dns_flags_recdesired,
2145 { "Recursion desired", "dns.flags.recdesired",
2146 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
2147 "Do query recursively?", HFILL }},
2148 { &hf_dns_flags_recavail,
2149 { "Recursion available", "dns.flags.recavail",
2150 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
2151 "Can the server do recursive queries?", HFILL }},
2152 { &hf_dns_flags_authenticated,
2153 { "Answer authenticated", "dns.flags.authenticated",
2154 FT_BOOLEAN, 16, TFS(&tfs_flags_authenticated), F_AUTHENTIC,
2155 "Was the reply data authenticated by the server?", HFILL }},
2156 { &hf_dns_flags_checkdisable,
2157 { "Non-authenticated data OK", "dns.flags.checkdisable",
2158 FT_BOOLEAN, 16, TFS(&tfs_flags_checkdisable), F_CHECKDISABLE,
2159 "Is non-authenticated data acceptable?", HFILL }},
2160 { &hf_dns_flags_rcode,
2161 { "Reply code", "dns.flags.rcode",
2162 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
2163 "Reply code", HFILL }},
2164 { &hf_dns_transaction_id,
2165 { "Transaction ID", "dns.id",
2166 FT_UINT16, BASE_HEX, NULL, 0x0,
2167 "Identification of transaction", HFILL }},
2168 { &hf_dns_count_questions,
2169 { "Questions", "dns.count.queries",
2170 FT_UINT16, BASE_DEC, NULL, 0x0,
2171 "Number of queries in packet", HFILL }},
2172 { &hf_dns_count_answers,
2173 { "Answer RRs", "dns.count.answers",
2174 FT_UINT16, BASE_DEC, NULL, 0x0,
2175 "Number of answers in packet", HFILL }},
2176 { &hf_dns_count_auth_rr,
2177 { "Authority RRs", "dns.count.auth_rr",
2178 FT_UINT16, BASE_DEC, NULL, 0x0,
2179 "Number of authoritative records in packet", HFILL }},
2180 { &hf_dns_count_add_rr,
2181 { "Additional RRs", "dns.count.add_rr",
2182 FT_UINT16, BASE_DEC, NULL, 0x0,
2183 "Number of additional records in packet", HFILL }}
2185 static gint *ett[] = {
2195 module_t *dns_module;
2197 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2198 proto_register_field_array(proto_dns, hf, array_length(hf));
2199 proto_register_subtree_array(ett, array_length(ett));
2201 dns_module = prefs_register_protocol(proto_dns, NULL);
2202 prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2203 "Desegment all DNS messages spanning multiple TCP segments",
2204 "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
2209 proto_reg_handoff_dns(void)
2211 dissector_handle_t dns_udp_handle;
2212 dissector_handle_t dns_tcp_handle;
2213 dissector_handle_t mdns_udp_handle;
2215 dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
2216 dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
2217 mdns_udp_handle = create_dissector_handle(dissect_mdns_udp, proto_dns);
2219 dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
2220 dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
2221 dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
2222 dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
2224 gssapi_handle = find_dissector("gssapi");