2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.120 2004/01/23 19:16:52 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/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_DS 43 /* Delegation Signature(RFC 3658) */
141 #define T_RRSIG 46 /* future RFC 2535bis */
142 #define T_NSEC 47 /* future RFC 2535bis */
143 #define T_DNSKEY 48 /* future RFC 2535bis */
144 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
145 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
146 #define T_WINS 65281 /* Microsoft's WINS RR */
147 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
150 #define C_IN 1 /* the Internet */
151 #define C_CS 2 /* CSNET (obsolete) */
152 #define C_CH 3 /* CHAOS */
153 #define C_HS 4 /* Hesiod */
154 #define C_NONE 254 /* none */
155 #define C_ANY 255 /* any */
156 #define C_FLUSH (1<<15) /* High bit is set for MDNS cache flush */
158 /* Bit fields in the flags */
159 #define F_RESPONSE (1<<15) /* packet is response */
160 #define F_OPCODE (0xF<<11) /* query opcode */
161 #define OPCODE_SHIFT 11
162 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
163 #define F_TRUNCATED (1<<9) /* response is truncated */
164 #define F_RECDESIRED (1<<8) /* recursion desired */
165 #define F_RECAVAIL (1<<7) /* recursion available */
166 #define F_Z (1<<6) /* Z */
167 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
168 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
169 #define F_RCODE (0xF<<0) /* reply code */
171 static const true_false_string tfs_flags_response = {
172 "Message is a response",
176 static const true_false_string tfs_flags_authoritative = {
177 "Server is an authority for domain",
178 "Server is not an authority for domain"
181 static const true_false_string tfs_flags_truncated = {
182 "Message is truncated",
183 "Message is not truncated"
186 static const true_false_string tfs_flags_recdesired = {
187 "Do query recursively",
188 "Don't do query recursively"
191 static const true_false_string tfs_flags_recavail = {
192 "Server can do recursive queries",
193 "Server can't do recursive queries"
196 static const true_false_string tfs_flags_z = {
197 "reserved - incorrect!",
201 static const true_false_string tfs_flags_authenticated = {
202 "Answer/authority portion was authenticated by the server",
203 "Answer/authority portion was not authenticated by the server"
206 static const true_false_string tfs_flags_checkdisable = {
207 "Non-authenticated data is acceptable",
208 "Non-authenticated data is unacceptable"
212 #define OPCODE_QUERY 0 /* standard query */
213 #define OPCODE_IQUERY 1 /* inverse query */
214 #define OPCODE_STATUS 2 /* server status request */
215 #define OPCODE_NOTIFY 4 /* zone change notification */
216 #define OPCODE_UPDATE 5 /* dynamic update */
218 static const value_string opcode_vals[] = {
219 { OPCODE_QUERY, "Standard query" },
220 { OPCODE_IQUERY, "Inverse query" },
221 { OPCODE_STATUS, "Server status request" },
222 { OPCODE_NOTIFY, "Zone change notification" },
223 { OPCODE_UPDATE, "Dynamic update" },
227 #define RCODE_NOERROR 0
228 #define RCODE_FORMERR 1
229 #define RCODE_SERVFAIL 2
230 #define RCODE_NXDOMAIN 3
231 #define RCODE_NOTIMPL 4
232 #define RCODE_REFUSED 5
233 #define RCODE_YXDOMAIN 6
234 #define RCODE_YXRRSET 7
235 #define RCODE_NXRRSET 8
236 #define RCODE_NOTAUTH 9
237 #define RCODE_NOTZONE 10
239 static const value_string rcode_vals[] = {
240 { RCODE_NOERROR, "No error" },
241 { RCODE_FORMERR, "Format error" },
242 { RCODE_SERVFAIL, "Server failure" },
243 { RCODE_NXDOMAIN, "No such name" },
244 { RCODE_NOTIMPL, "Not implemented" },
245 { RCODE_REFUSED, "Refused" },
246 { RCODE_YXDOMAIN, "Name exists" },
247 { RCODE_YXRRSET, "RRset exists" },
248 { RCODE_NXRRSET, "RRset does not exist" },
249 { RCODE_NOTAUTH, "Not authoritative" },
250 { RCODE_NOTZONE, "Name out of zone" },
253 /* TSIG/TKEY extended errors */
254 #define TSIGERROR_BADSIG (16)
255 #define TSIGERROR_BADKEY (17)
256 #define TSIGERROR_BADTIME (18)
257 #define TSIGERROR_BADMODE (19)
258 #define TSIGERROR_BADNAME (20)
259 #define TSIGERROR_BADALG (21)
261 static const value_string tsigerror_vals[] = {
262 { TSIGERROR_BADSIG, "Bad signature" },
263 { TSIGERROR_BADKEY, "Bad key" },
264 { TSIGERROR_BADTIME, "Bad time failure" },
265 { TSIGERROR_BADMODE, "Bad mode such name" },
266 { TSIGERROR_BADNAME, "Bad name implemented" },
267 { TSIGERROR_BADALG, "Bad algorithm" },
270 #define TKEYMODE_SERVERASSIGNED (1)
271 #define TKEYMODE_DIFFIEHELLMAN (2)
272 #define TKEYMODE_GSSAPI (3)
273 #define TKEYMODE_RESOLVERASSIGNED (4)
274 #define TKEYMODE_DELETE (5)
276 #define TDSDIGEST_RESERVED (0)
277 #define TDSDIGEST_SHA1 (1)
279 /* See RFC 1035 for all RR types for which no RFC is listed, except for
280 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
281 which one should look at
283 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
287 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
289 which discuss them to some extent. */
291 dns_type_name (guint type)
293 char *type_names[] = {
312 "AFSDB", /* RFC 1183 */
313 "X25", /* RFC 1183 */
314 "ISDN", /* RFC 1183 */
316 "NSAP", /* RFC 1706 */
317 "NSAP-PTR", /* RFC 1348 */
318 "SIG", /* RFC 2535 */
319 "KEY", /* RFC 2535 */
321 "GPOS", /* RFC 1712 */
322 "AAAA", /* RFC 1886 */
323 "LOC", /* RFC 1876 */
324 "NXT", /* RFC 2535 */
327 "SRV", /* RFC 2052 */
329 "NAPTR", /* RFC 2168 */
331 "CERT", /* RFC 2538 */
333 "DNAME", /* RFC 2672 */
335 "OPT", /* RFC 2671 */
340 "RRSIG", /* future RFC 2535bis */
341 "NSEC", /* future RFC 2535bis */
342 "DNSKEY" /* future RFC 2535bis */
345 if (type < sizeof(type_names)/sizeof(type_names[0]))
346 return type_names[type] ? type_names[type] : "unknown";
373 return "IXFR"; /* RFC 1995 */
390 dns_long_type_name (guint type)
392 char *type_names[] = {
395 "Authoritative name server",
398 "Canonical name for an alias",
399 "Start of zone of authority",
400 "Mailbox domain name",
402 "Mail rename domain name",
403 "Null resource record",
404 "Well-known service description",
405 "Domain name pointer",
407 "Mailbox or mail list information",
410 "Responsible person", /* RFC 1183 */
411 "AFS data base location", /* RFC 1183 */
412 "X.25 address", /* RFC 1183 */
413 "ISDN number", /* RFC 1183 */
414 "Route through", /* RFC 1183 */
415 "OSI NSAP", /* RFC 1706 */
416 "OSI NSAP name pointer", /* RFC 1348 */
417 "Signature", /* RFC 2535 */
418 "Public key", /* RFC 2535 */
419 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
420 "Geographical position", /* RFC 1712 */
421 "IPv6 address", /* RFC 1886 */
422 "Location", /* RFC 1876 */
423 "Next", /* RFC 2535 */
426 "Service location", /* RFC 2052 */
428 "Naming authority pointer", /* RFC 2168 */
429 "Key Exchange", /* RFC 2230 */
430 "Certificate", /* RFC 2538 */
431 "IPv6 address with indirection", /* RFC 2874 */
432 "Non-terminal DNS name redirection", /* RFC 2672 */
434 "EDNS0 option", /* RFC 2671 */
436 "Delegation Signer", /* RFC 3658 */
439 "RR signature", /* future RFC 2535bis */
440 "Next secured", /* future RFC 2535bis */
441 "DNS public key" /* future RFC 2535bis */
443 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%u)" */
445 if (type < sizeof(type_names)/sizeof(type_names[0]))
446 return type_names[type] ? type_names[type] : "unknown";
467 return "Transaction Key";
469 return "Transaction Signature";
473 return "Request for incremental zone transfer"; /* RFC 1995 */
475 return "Request for full zone transfer";
477 return "Request for mailbox-related records";
479 return "Request for mail agent resource records";
481 return "Request for all records";
484 sprintf(unkbuf, "Unknown RR type (%u)", type);
490 dns_class_name(int class)
498 case ( C_IN | C_FLUSH ):
499 class_name = "inet (data flush)";
502 class_name = "csnet";
505 class_name = "chaos";
508 class_name = "hesiod";
517 class_name = "unknown";
524 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
525 char *name, int maxname)
527 int start_offset = offset;
530 int chars_processed = 0;
531 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
535 const int min_len = 1; /* Minimum length of encoded name (for root) */
536 /* If we're about to return a value (probably negative) which is less
537 * than the minimum length, we're looking at bad data and we're liable
538 * to put the dissector into a loop. Instead we throw an exception */
540 maxname--; /* reserve space for the trailing '\0' */
542 component_len = tvb_get_guint8(tvb, offset);
544 if (component_len == 0)
547 switch (component_len & 0xc0) {
552 /* Not the first component - put in a '.'. */
558 while (component_len > 0) {
560 *np++ = tvb_get_guint8(tvb, offset);
570 /* Extended label (RFC 2673) */
571 switch (component_len & 0x3f) {
574 /* Bitstring label */
580 bit_count = tvb_get_guint8(tvb, offset);
582 label_len = (bit_count - 1) / 8 + 1;
585 print_len = snprintf(np, maxname + 1, "\\[x");
586 if (print_len != -1 && print_len <= maxname) {
587 /* Some versions of snprintf return -1 if they'd truncate
588 the output. Others return <buf_size> or greater. */
590 maxname -= print_len;
592 /* Nothing printed, as there's no room.
593 Suppress all subsequent printing. */
599 print_len = snprintf(np, maxname + 1, "%02x",
600 tvb_get_guint8(tvb, offset));
601 if (print_len != -1 && print_len <= maxname) {
602 /* Some versions of snprintf return -1 if they'd truncate
603 the output. Others return <buf_size> or greater. */
605 maxname -= print_len;
607 /* Nothing printed, as there's no room.
608 Suppress all subsequent printing. */
615 print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
616 if (print_len != -1 && print_len <= maxname) {
617 /* Some versions of snprintf return -1 if they'd truncate
618 the output. Others return <buf_size> or greater. */
620 maxname -= print_len;
622 /* Nothing printed, as there's no room.
623 Suppress all subsequent printing. */
631 strcpy(name, "<Unknown extended label>");
632 /* Parsing will propably fail from here on, since the */
633 /* label length is unknown... */
634 len = offset - start_offset;
636 THROW(ReportedBoundsError);
642 THROW(ReportedBoundsError);
646 indir_offset = dns_data_offset +
647 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
651 /* If "len" is negative, we are still working on the original name,
652 not something pointed to by a pointer, and so we should set "len"
653 to the length of the original name. */
655 len = offset - start_offset;
657 /* If we've looked at every character in the message, this pointer
658 will make us look at some character again, which means we're
660 if (chars_processed >= data_size) {
661 strcpy(name, "<Name contains a pointer that loops>");
663 THROW(ReportedBoundsError);
667 offset = indir_offset;
668 break; /* now continue processing from there */
673 /* If "len" is negative, we haven't seen a pointer, and thus haven't
674 set the length, so set it. */
676 len = offset - start_offset;
677 /* Zero-length name means "root server" */
679 strcpy(name, "<Root>");
681 THROW(ReportedBoundsError);
687 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
688 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
695 int start_offset = offset;
697 name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
700 type = tvb_get_ntohs(tvb, offset);
703 class = tvb_get_ntohs(tvb, offset);
706 strcpy (name_ret, name);
709 *name_len_ret = name_len;
711 len = offset - start_offset;
716 rfc1867_size(tvbuff_t *tvb, int offset)
722 val = tvb_get_guint8(tvb, offset);
723 size = (val & 0xF0) >> 4;
724 exponent = (val & 0x0F);
725 while (exponent != 0) {
729 return size / 100; /* return size in meters, not cm */
733 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
737 guint32 degrees, minutes, secs, tsecs;
738 /* "%u deg %u min %u.%03u sec %c" */
739 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
741 angle = tvb_get_ntohl(tvb, offset);
743 if (angle < 0x80000000U) {
744 angle = 0x80000000U - angle;
747 angle = angle - 0x80000000U;
750 tsecs = angle % 1000;
751 angle = angle / 1000;
754 minutes = angle % 60;
755 degrees = angle / 60;
756 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
762 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
763 column_info *cinfo, proto_tree *dns_tree)
772 char *long_type_name;
778 data_start = data_offset = offset;
780 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
784 type_name = dns_type_name(type);
785 class_name = dns_class_name(class);
786 long_type_name = dns_long_type_name(type);
789 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
790 if (dns_tree != NULL) {
791 tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
792 name, type_name, class_name);
793 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
795 proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
798 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
801 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
805 return data_offset - data_start;
810 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
811 const char *name, int namelen, const char *type_name, const char *class_name,
812 guint ttl, gushort data_len)
816 rr_tree = proto_item_add_subtree(trr, rr_type);
817 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
819 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
821 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
823 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
824 time_secs_to_str(ttl));
826 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
831 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
832 const char *name, int namelen, const char *type_name, int class,
833 guint ttl, gushort data_len)
835 proto_tree *rr_tree, *Z_tree;
836 proto_item *Z_item = NULL;
838 rr_tree = proto_item_add_subtree(trr, rr_type);
839 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
841 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
843 proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
846 proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
847 (ttl >> 24) & 0xff0);
849 proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
852 Z_item = proto_tree_add_text(rr_tree, tvb, offset, 2, "Z: 0x%x", ttl & 0xffff);
854 Z_tree = proto_item_add_subtree(Z_item, rr_type);
855 proto_tree_add_text(Z_tree, tvb, offset, 2, "Bit 0 (DO bit): 1 (Accepts DNSSEC security RRs)");
856 proto_tree_add_text(Z_tree, tvb, offset, 2, "Bits 1-15: 0x%x (reserved)", (ttl >> 17) & 0xff);
859 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
864 * SIG, KEY, and CERT RR algorithms.
866 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
867 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
868 #define DNS_ALGO_DSA 3 /* DSA */
869 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
870 #define DNS_ALGO_RSASHA1 5 /* RSA/SHA1 */
871 #define DNS_ALGO_HMACMD5 157 /* HMAC/MD5 */
872 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
873 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
874 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
876 static const value_string algo_vals[] = {
877 { DNS_ALGO_RSAMD5, "RSA/MD5" },
878 { DNS_ALGO_DH, "Diffie-Hellman" },
879 { DNS_ALGO_DSA, "DSA" },
880 { DNS_ALGO_ECC, "Elliptic curve crypto" },
881 { DNS_ALGO_RSASHA1, "RSA/SHA1" },
882 { DNS_ALGO_HMACMD5, "HMAC/MD5" },
883 { DNS_ALGO_INDIRECT, "Indirect key" },
884 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
885 { DNS_ALGO_PRIVATEOID, "Private, OID" },
889 #define DNS_CERT_PGP 1 /* PGP */
890 #define DNS_CERT_PKIX 2 /* PKIX */
891 #define DNS_CERT_SPKI 3 /* SPKI */
892 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
893 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
895 static const value_string cert_vals[] = {
896 { DNS_CERT_PGP, "PGP" },
897 { DNS_CERT_PKIX, "PKIX" },
898 { DNS_CERT_SPKI, "SPKI" },
899 { DNS_CERT_PRIVATEURI, "Private, URI" },
900 { DNS_CERT_PRIVATEOID, "Private, OID" },
905 * Compute the key id of a KEY RR depending of the algorithm used.
908 compute_key_id(tvbuff_t *tvb, int offset, int size, guint8 algo)
916 case DNS_ALGO_RSAMD5:
917 return (guint16)(tvb_get_guint8(tvb, offset + size - 3) << 8) + tvb_get_guint8( tvb, offset + size - 2 );
919 for (ac = 0; size > 1; size -= 2, offset += 2) {
920 c1 = tvb_get_guint8( tvb, offset );
921 c2 = tvb_get_guint8( tvb, offset + 1 );
922 ac += (c1 << 8) + c2 ;
925 c1 = tvb_get_guint8( tvb, offset );
928 ac += (ac >> 16) & 0xffff;
929 return (guint16)(ac & 0xffff);
935 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
936 column_info *cinfo, proto_tree *dns_tree, packet_info *pinfo)
945 char *long_type_name;
951 proto_tree *rr_tree = NULL;
952 proto_item *trr = NULL;
954 data_start = data_offset = offset;
957 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
962 type_name = dns_type_name(type);
963 class_name = dns_class_name(class);
964 long_type_name = dns_long_type_name(type);
966 ttl = tvb_get_ntohl(tvb, data_offset);
970 data_len = tvb_get_ntohs(tvb, data_offset);
975 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
976 if (dns_tree != NULL) {
977 trr = proto_tree_add_text(dns_tree, tvb, offset,
978 (data_offset - data_start) + data_len,
979 "%s: type %s, class %s",
980 name, type_name, class_name);
982 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
983 long_type_name, class_name, ttl, data_len);
985 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
986 long_type_name, class, ttl, data_len);
997 addr = tvb_get_ptr(tvb, cur_offset, 4);
999 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
1000 if (dns_tree != NULL) {
1001 proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
1002 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
1005 if ((class & 0x7f) == C_IN) {
1006 memcpy(&addr_int, addr, sizeof(addr_int));
1007 add_host_name(addr_int, name);
1014 char ns_name[MAXDNAME];
1017 ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
1019 col_append_fstr(cinfo, COL_INFO, " %s", ns_name);
1020 if (dns_tree != NULL) {
1021 proto_item_append_text(trr, ", ns %s", ns_name);
1022 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
1030 char cname[MAXDNAME];
1033 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
1035 col_append_fstr(cinfo, COL_INFO, " %s", cname);
1036 if (dns_tree != NULL) {
1037 proto_item_append_text(trr, ", cname %s", cname);
1038 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
1046 char mname[MAXDNAME];
1048 char rname[MAXDNAME];
1056 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
1058 col_append_fstr(cinfo, COL_INFO, " %s", mname);
1059 if (dns_tree != NULL) {
1060 proto_item_append_text(trr, ", mname %s", mname);
1061 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
1063 cur_offset += mname_len;
1065 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
1066 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
1068 cur_offset += rname_len;
1070 serial = tvb_get_ntohl(tvb, cur_offset);
1071 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
1075 refresh = tvb_get_ntohl(tvb, cur_offset);
1076 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
1077 time_secs_to_str(refresh));
1080 retry = tvb_get_ntohl(tvb, cur_offset);
1081 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
1082 time_secs_to_str(retry));
1085 expire = tvb_get_ntohl(tvb, cur_offset);
1086 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
1087 time_secs_to_str(expire));
1090 minimum = tvb_get_ntohl(tvb, cur_offset);
1091 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
1092 time_secs_to_str(minimum));
1099 char pname[MAXDNAME];
1102 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
1104 col_append_fstr(cinfo, COL_INFO, " %s", pname);
1105 if (dns_tree != NULL) {
1106 proto_item_append_text(trr, ", %s", pname);
1107 proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
1116 int rr_len = data_len;
1117 const guint8 *wks_addr;
1123 static GString *bitnames = NULL;
1125 if (bitnames == NULL)
1126 bitnames = g_string_sized_new(128);
1129 if (dns_tree != NULL)
1133 wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
1135 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
1136 if (dns_tree != NULL) {
1137 proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
1138 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
1139 ip_to_str(wks_addr));
1145 protocol = tvb_get_guint8(tvb, cur_offset);
1146 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
1147 ipprotostr(protocol));
1152 while (rr_len != 0) {
1153 bits = tvb_get_guint8(tvb, cur_offset);
1156 g_string_truncate(bitnames, 0);
1157 for (i = 0; i < 8; i++) {
1159 if (bitnames->len != 0)
1160 g_string_append(bitnames, ", ");
1164 g_string_append(bitnames, get_tcp_port(port_num));
1168 g_string_append(bitnames, get_udp_port(port_num));
1172 g_string_sprintfa(bitnames, "%u", port_num);
1179 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1180 "Bits: 0x%02x (%s)", bits, bitnames->str);
1199 cpu_offset = cur_offset;
1200 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1201 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1202 os_offset = cpu_offset + 1 + cpu_len;
1203 os_len = tvb_get_guint8(tvb, os_offset);
1204 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1206 col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1208 if (dns_tree != NULL) {
1209 proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1210 cpu_len, cpu, os_len, os);
1211 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1213 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1222 guint16 preference = 0;
1223 char mx_name[MAXDNAME];
1226 preference = tvb_get_ntohs(tvb, cur_offset);
1227 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1229 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, mx_name);
1230 if (dns_tree != NULL) {
1231 proto_item_append_text(trr, ", preference %u, mx %s",
1232 preference, mx_name);
1233 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1234 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1242 int rr_len = data_len;
1246 if (dns_tree != NULL) {
1247 txt_offset = cur_offset;
1248 while (rr_len != 0) {
1249 txt_len = tvb_get_guint8(tvb, txt_offset);
1250 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1251 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1252 txt_offset += 1 + txt_len;
1253 rr_len -= 1 + txt_len;
1262 int rr_len = data_len;
1263 guint16 type_covered;
1265 char signer_name[MAXDNAME];
1266 int signer_name_len;
1268 if (dns_tree != NULL) {
1271 type_covered = tvb_get_ntohs(tvb, cur_offset);
1272 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1273 dns_type_name(type_covered),
1274 dns_long_type_name(type_covered));
1280 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1281 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1282 "Unknown (0x%02X)"));
1288 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1289 tvb_get_guint8(tvb, cur_offset));
1295 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1296 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1302 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1304 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1305 abs_time_to_str(&nstime));
1311 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1313 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1314 abs_time_to_str(&nstime));
1320 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Id of signing key(footprint): %u",
1321 tvb_get_ntohs(tvb, cur_offset));
1325 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1326 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1327 "Signer's name: %s", signer_name);
1328 cur_offset += signer_name_len;
1329 rr_len -= signer_name_len;
1332 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1340 int rr_len = data_len;
1343 proto_tree *flags_tree;
1347 if (dns_tree != NULL) {
1350 flags = tvb_get_ntohs(tvb, cur_offset);
1351 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1352 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1353 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1354 decode_boolean_bitfield(flags, 0x8000,
1355 2*8, "Key prohibited for authentication",
1356 "Key allowed for authentication"));
1357 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1358 decode_boolean_bitfield(flags, 0x4000,
1359 2*8, "Key prohibited for confidentiality",
1360 "Key allowed for confidentiality"));
1361 if ((flags & 0xC000) != 0xC000) {
1363 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1364 decode_boolean_bitfield(flags, 0x2000,
1365 2*8, "Key is experimental or optional",
1366 "Key is required"));
1367 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1368 decode_boolean_bitfield(flags, 0x0400,
1369 2*8, "Key is associated with a user",
1370 "Key is not associated with a user"));
1371 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1372 decode_boolean_bitfield(flags, 0x0200,
1373 2*8, "Key is associated with the named entity",
1374 "Key is not associated with the named entity"));
1375 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1376 decode_boolean_bitfield(flags, 0x0100,
1377 2*8, "This is the zone key for the specified zone",
1378 "This is not a zone key"));
1379 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1380 decode_boolean_bitfield(flags, 0x0080,
1381 2*8, "Key is valid for use with IPSEC",
1382 "Key is not valid for use with IPSEC"));
1383 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1384 decode_boolean_bitfield(flags, 0x0040,
1385 2*8, "Key is valid for use with MIME security multiparts",
1386 "Key is not valid for use with MIME security multiparts"));
1387 if( type != T_DNSKEY )
1388 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1389 decode_numeric_bitfield(flags, 0x000F,
1390 2*8, "Signatory = %u"));
1391 else proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1392 decode_boolean_bitfield(flags, 0x0001,
1393 2*8, "Key is a Key Signing Key",
1394 "Key is a Zone Signing Key") );
1401 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1402 tvb_get_guint8(tvb, cur_offset));
1408 algo = tvb_get_guint8(tvb, cur_offset);
1409 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1410 val_to_str(algo, algo_vals, "Unknown (0x%02X)"));
1414 key_id = compute_key_id(tvb, cur_offset-4, rr_len+4, algo);
1415 proto_tree_add_text(rr_tree, tvb, 0, 0, "Key id: %u", key_id);
1418 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1425 const guint8 *addr6;
1427 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1428 if (cinfo != NULL) {
1429 col_append_fstr(cinfo, COL_INFO, " %s",
1430 ip6_to_str((const struct e_in6_addr *)addr6));
1432 if (dns_tree != NULL) {
1433 proto_item_append_text(trr, ", addr %s",
1434 ip6_to_str((const struct e_in6_addr *)addr6));
1435 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1436 ip6_to_str((const struct e_in6_addr *)addr6));
1443 unsigned short pre_len;
1444 unsigned short suf_len;
1445 unsigned short suf_octet_count;
1446 char pname[MAXDNAME];
1450 struct e_in6_addr suffix;
1452 a6_offset = cur_offset;
1453 pre_len = tvb_get_guint8(tvb, cur_offset);
1455 suf_len = 128 - pre_len;
1456 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1458 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1459 suffix.s6_addr8[suf_offset] = 0;
1461 for (; suf_offset < 16; suf_offset++) {
1462 suffix.s6_addr8[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1467 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1468 pname, sizeof(pname));
1474 if (cinfo != NULL) {
1475 col_append_fstr(cinfo, COL_INFO, " %d %s %s",
1477 ip6_to_str(&suffix),
1480 if (dns_tree != NULL) {
1481 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1482 "Prefix len: %u", pre_len);
1485 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1486 "Address suffix: %s",
1487 ip6_to_str(&suffix));
1488 a6_offset += suf_octet_count;
1491 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1492 "Prefix name: %s", pname);
1494 proto_item_append_text(trr, ", addr %d %s %s",
1496 ip6_to_str(&suffix),
1504 char dname[MAXDNAME];
1507 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1508 dname, sizeof(dname));
1510 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1511 if (dns_tree != NULL) {
1512 proto_item_append_text(trr, ", dname %s", dname);
1513 proto_tree_add_text(rr_tree, tvb, cur_offset,
1514 dname_len, "Target name: %s", dname);
1523 if (dns_tree != NULL) {
1524 version = tvb_get_guint8(tvb, cur_offset);
1525 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1527 /* Version 0, the only version RFC 1876 discusses. */
1530 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1531 rfc1867_size(tvb, cur_offset));
1534 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1535 rfc1867_size(tvb, cur_offset));
1538 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1539 rfc1867_size(tvb, cur_offset));
1542 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1543 rfc1867_angle(tvb, cur_offset, "NS"));
1546 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1547 rfc1867_angle(tvb, cur_offset, "EW"));
1550 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1551 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1553 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1560 int rr_len = data_len;
1561 char next_domain_name[MAXDNAME];
1562 int next_domain_name_len;
1565 int mask, blockbase, blocksize;
1568 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1569 next_domain_name, sizeof(next_domain_name));
1571 col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
1572 if (dns_tree != NULL) {
1573 proto_item_append_text(trr, ", next domain name %s",
1575 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1576 "Next domain name: %s", next_domain_name);
1577 cur_offset += next_domain_name_len;
1578 rr_len -= next_domain_name_len;
1580 while (rr_len != 0) {
1581 blockbase = tvb_get_guint8(tvb, cur_offset);
1582 blocksize = tvb_get_guint8(tvb, cur_offset + 1);
1585 rr_type = blockbase * 256;
1586 for( ; blocksize; blocksize-- ) {
1587 bits = tvb_get_guint8(tvb, cur_offset);
1589 for (i = 0; i < 8; i++) {
1591 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1592 "RR type in bit map: %s (%s)",
1593 dns_type_name(rr_type),
1594 dns_long_type_name(rr_type));
1609 int rr_len = data_len;
1610 char next_domain_name[MAXDNAME];
1611 int next_domain_name_len;
1617 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1618 next_domain_name, sizeof(next_domain_name));
1620 col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
1621 if (dns_tree != NULL) {
1622 proto_item_append_text(trr, ", next domain name %s",
1624 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1625 "Next domain name: %s", next_domain_name);
1626 cur_offset += next_domain_name_len;
1627 rr_len -= next_domain_name_len;
1629 while (rr_len != 0) {
1630 bits = tvb_get_guint8(tvb, cur_offset);
1632 for (i = 0; i < 8; i++) {
1634 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1635 "RR type in bit map: %s (%s)",
1636 dns_type_name(rr_type),
1637 dns_long_type_name(rr_type));
1651 guint16 preference = 0;
1652 char kx_name[MAXDNAME];
1655 preference = tvb_get_ntohs(tvb, cur_offset);
1656 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1658 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, kx_name);
1659 if (dns_tree != NULL) {
1660 proto_item_append_text(trr, ", preference %u, kx %s",
1661 preference, kx_name);
1662 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1663 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1671 guint16 cert_type, cert_keytag;
1673 int rr_len = data_len;
1675 if (dns_tree != NULL) {
1678 cert_type = tvb_get_ntohs(tvb, cur_offset);
1679 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type: %s",
1680 val_to_str(cert_type, cert_vals,
1681 "Unknown (0x%02X)"));
1687 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1688 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1695 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1696 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1697 val_to_str(cert_keyalg, algo_vals,
1698 "Unknown (0x%02X)"));
1703 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1709 if (dns_tree != NULL)
1710 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1715 guint16 keytag, digest_data_size = -1;
1716 guint8 ds_algorithm, ds_digest;
1717 int rr_len = data_len;
1719 static const value_string tds_digests[] = {
1720 { TDSDIGEST_RESERVED, "Reserved digest" },
1721 { TDSDIGEST_SHA1, "SHA-1" },
1725 if (dns_tree != NULL) {
1728 keytag = tvb_get_ntohs(tvb, cur_offset);
1729 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key id: %04u", keytag);
1735 ds_algorithm = tvb_get_guint8(tvb, cur_offset);
1736 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s", val_to_str(ds_algorithm, algo_vals,"Unknown (0x%02X)") );
1742 ds_digest = tvb_get_guint8(tvb, cur_offset);
1743 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Digest type: %s", val_to_str(ds_digest, tds_digests, "Unknown (0x%02X)"));
1747 if (ds_digest == TDSDIGEST_SHA1)
1748 digest_data_size = 20; /* SHA1 key is always 20 bytes long */
1749 if (digest_data_size > 0) {
1750 if (rr_len < digest_data_size)
1752 proto_tree_add_text(rr_tree, tvb, cur_offset, digest_data_size, "Public key");
1760 char tkey_algname[MAXDNAME];
1761 int tkey_algname_len;
1762 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1763 int rr_len = data_len;
1765 static const value_string tkey_modes[] = {
1766 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1767 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1768 { TKEYMODE_GSSAPI, "GSSAPI" },
1769 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1770 { TKEYMODE_DELETE, "Delete" },
1773 if (dns_tree != NULL) {
1774 proto_tree *key_tree;
1775 proto_item *key_item;
1777 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1778 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1779 "Algorithm name: %s", tkey_algname);
1780 cur_offset += tkey_algname_len;
1781 rr_len -= tkey_algname_len;
1785 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1787 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1788 abs_time_to_str(&nstime));
1794 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1796 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1797 abs_time_to_str(&nstime));
1803 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1806 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Mode: %s",
1807 val_to_str(tkey_mode, tkey_modes,
1808 "Unknown (0x%04X)"));
1812 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1815 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1816 val_to_str(tkey_error, rcode_vals,
1817 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1819 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1820 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key Size: %u",
1825 if (tkey_keylen != 0) {
1826 key_item = proto_tree_add_text(
1827 rr_tree, tvb, cur_offset, tkey_keylen, "Key Data");
1829 key_tree = proto_item_add_subtree(key_item, ett_t_key);
1832 case TKEYMODE_GSSAPI: {
1833 tvbuff_t *gssapi_tvb;
1836 * XXX - in at least one capture, this appears to
1837 * be an NTLMSSP blob, with no ASN.1 in it, in
1840 * See RFC 3645 which might indicate what's going
1841 * on here. (The key is an output_token from
1842 * GSS_Init_sec_context.)
1844 * How the heck do we know what method is being
1845 * used, so we know how to decode the key? Do we
1846 * have to look at the algorithm name, e.g.
1847 * "gss.microsoft.com"? The SMB dissector
1848 * checks whether the security blob begins
1849 * with "NTLMSSP" in some cases.
1851 gssapi_tvb = tvb_new_subset(
1852 tvb, cur_offset, tkey_keylen, tkey_keylen);
1854 call_dissector(gssapi_handle, gssapi_tvb, pinfo,
1861 /* No dissector for this key mode */
1866 cur_offset += tkey_keylen;
1867 rr_len -= tkey_keylen;
1872 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1873 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Other Size: %u",
1878 if (tkey_otherlen != 0) {
1879 if (rr_len < tkey_otherlen)
1881 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other Data");
1882 cur_offset += tkey_otherlen;
1883 rr_len -= tkey_otherlen;
1892 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1893 guint32 tsig_timelo;
1894 char tsig_algname[MAXDNAME];
1895 int tsig_algname_len;
1897 int rr_len = data_len;
1899 if (dns_tree != NULL) {
1900 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1901 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1902 "Algorithm name: %s", tsig_algname);
1903 cur_offset += tsig_algname_len;
1904 rr_len -= tsig_algname_len;
1908 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1909 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1910 nstime.secs = tsig_timelo;
1912 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1913 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
1919 tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1920 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1927 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1931 if (tsig_siglen != 0) {
1932 if (rr_len < tsig_siglen)
1934 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1935 cur_offset += tsig_siglen;
1936 rr_len -= tsig_siglen;
1941 tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1942 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1949 tsig_error = tvb_get_ntohs(tvb, cur_offset);
1950 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1951 val_to_str(tsig_error, rcode_vals,
1952 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1958 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1962 if (tsig_otherlen != 0) {
1963 if (rr_len < tsig_otherlen)
1965 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1966 cur_offset += tsig_otherlen;
1967 rr_len -= tsig_otherlen;
1975 int rr_len = data_len;
1977 guint32 lookup_timeout;
1978 guint32 cache_timeout;
1981 if (dns_tree != NULL) {
1984 local_flag = tvb_get_ntohl(tvb, cur_offset);
1985 if (dns_tree != NULL) {
1986 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1987 local_flag ? "true" : "false");
1994 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1995 if (dns_tree != NULL) {
1996 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
2004 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
2005 if (dns_tree != NULL) {
2006 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
2014 nservers = tvb_get_ntohl(tvb, cur_offset);
2015 if (dns_tree != NULL) {
2016 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
2022 while (rr_len != 0 && nservers != 0) {
2025 if (dns_tree != NULL) {
2026 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
2027 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
2039 int rr_len = data_len;
2041 guint32 lookup_timeout;
2042 guint32 cache_timeout;
2043 char dname[MAXDNAME];
2048 local_flag = tvb_get_ntohl(tvb, cur_offset);
2049 if (dns_tree != NULL) {
2050 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
2051 local_flag ? "true" : "false");
2058 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
2059 if (dns_tree != NULL) {
2060 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
2068 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
2069 if (dns_tree != NULL) {
2070 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
2076 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
2078 col_append_fstr(cinfo, COL_INFO, " %s", dname);
2079 if (dns_tree != NULL) {
2080 proto_item_append_text(trr, ", name result domain %s", dname);
2081 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
2089 guint16 priority = 0;
2092 char target[MAXDNAME];
2095 priority = tvb_get_ntohs(tvb, cur_offset);
2096 weight = tvb_get_ntohs(tvb, cur_offset+2);
2097 port = tvb_get_ntohs(tvb, cur_offset+4);
2099 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
2101 col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, target);
2102 if (dns_tree != NULL) {
2103 proto_item_append_text(trr,
2104 ", priority %u, weight %u, port %u, target %s",
2105 priority, weight, port, target);
2106 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
2107 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
2108 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
2109 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
2115 /* TODO: parse more record types */
2118 if (dns_tree != NULL)
2119 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
2123 data_offset += data_len;
2125 return data_offset - data_start;
2128 if (dns_tree != NULL) {
2129 proto_item_append_text(trr, ", bad RR length %d, too short",
2133 data_offset += data_len;
2135 return data_offset - data_start;
2139 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
2140 int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
2142 int start_off, add_off;
2143 proto_tree *qatree = NULL;
2144 proto_item *ti = NULL;
2146 start_off = cur_off;
2148 char *s = (isupdate ? "Zone" : "Queries");
2149 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
2150 qatree = proto_item_add_subtree(ti, ett_dns_qry);
2152 while (count-- > 0) {
2153 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
2157 proto_item_set_len(ti, cur_off - start_off);
2159 return cur_off - start_off;
2163 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
2164 int count, column_info *cinfo, proto_tree *dns_tree, char *name,
2167 int start_off, add_off;
2168 proto_tree *qatree = NULL;
2169 proto_item *ti = NULL;
2171 start_off = cur_off;
2173 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
2174 qatree = proto_item_add_subtree(ti, ett_dns_ans);
2176 while (count-- > 0) {
2177 add_off = dissect_dns_answer(
2178 tvb, cur_off, dns_data_offset, cinfo, qatree, pinfo);
2182 proto_item_set_len(ti, cur_off - start_off);
2184 return cur_off - start_off;
2188 dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2191 int offset = is_tcp ? 2 : 0;
2192 int dns_data_offset;
2194 proto_tree *dns_tree = NULL, *field_tree;
2195 proto_item *ti, *tf;
2196 guint16 id, flags, opcode, rcode, quest, ans, auth, add;
2201 dns_data_offset = offset;
2203 if (check_col(pinfo->cinfo, COL_INFO))
2204 col_clear(pinfo->cinfo, COL_INFO);
2206 /* To do: check for errs, etc. */
2207 id = tvb_get_ntohs(tvb, offset + DNS_ID);
2208 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
2209 opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
2210 rcode = (guint16) (flags & F_RCODE);
2212 if (check_col(pinfo->cinfo, COL_INFO)) {
2213 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation (%u)"));
2214 if (flags & F_RESPONSE) {
2215 strcat(buf, " response");
2216 if ((flags & F_RCODE) != RCODE_NOERROR) {
2218 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
2219 "Unknown error (%u)"));
2222 col_add_str(pinfo->cinfo, COL_INFO, buf);
2223 cinfo = pinfo->cinfo;
2225 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
2226 dissectors, as a way of saying that they shouldn't add stuff
2227 to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
2228 is more expensive than a check that a pointer isn't NULL). */
2231 if (opcode == OPCODE_UPDATE)
2237 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
2238 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
2240 dns_tree = proto_item_add_subtree(ti, ett_dns);
2243 /* Put the length indication into the tree. */
2244 proto_tree_add_item(dns_tree, hf_dns_length, tvb, offset - 2, 2, FALSE);
2247 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
2248 offset + DNS_ID, 2, id);
2250 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
2251 if (flags & F_RESPONSE) {
2252 strcat(buf, " response");
2254 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
2257 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
2258 offset + DNS_FLAGS, 2,
2260 "Flags: 0x%04x (%s)",
2262 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
2263 proto_tree_add_item(field_tree, hf_dns_flags_response,
2264 tvb, offset + DNS_FLAGS, 2, FALSE);
2265 proto_tree_add_item(field_tree, hf_dns_flags_opcode,
2266 tvb, offset + DNS_FLAGS, 2, FALSE);
2267 if (flags & F_RESPONSE) {
2268 proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
2269 tvb, offset + DNS_FLAGS, 2, FALSE);
2271 proto_tree_add_item(field_tree, hf_dns_flags_truncated,
2272 tvb, offset + DNS_FLAGS, 2, FALSE);
2273 proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
2274 tvb, offset + DNS_FLAGS, 2, FALSE);
2275 if (flags & F_RESPONSE) {
2276 proto_tree_add_item(field_tree, hf_dns_flags_recavail,
2277 tvb, offset + DNS_FLAGS, 2, FALSE);
2278 proto_tree_add_item(field_tree, hf_dns_flags_z,
2279 tvb, offset + DNS_FLAGS, 2, FALSE);
2280 proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
2281 tvb, offset + DNS_FLAGS, 2, FALSE);
2282 proto_tree_add_item(field_tree, hf_dns_flags_rcode,
2283 tvb, offset + DNS_FLAGS, 2, FALSE);
2285 proto_tree_add_item(field_tree, hf_dns_flags_z,
2286 tvb, offset + DNS_FLAGS, 2, FALSE);
2287 proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
2288 tvb, offset + DNS_FLAGS, 2, FALSE);
2291 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
2293 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
2294 offset + DNS_QUEST, 2, quest);
2296 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
2298 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
2299 offset + DNS_ANS, 2, ans);
2301 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
2303 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
2304 offset + DNS_AUTH, 2, auth);
2306 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
2308 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
2309 offset + DNS_ADD, 2, add);
2312 cur_off = offset + DNS_HDRLEN;
2315 /* If this is a response, don't add information about the queries
2316 to the summary, just add information about the answers. */
2317 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
2318 (!(flags & F_RESPONSE) ? cinfo : NULL),
2319 dns_tree, isupdate);
2323 /* If this is a request, don't add information about the answers
2324 to the summary, just add information about the queries. */
2325 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
2326 ((flags & F_RESPONSE) ? cinfo : NULL),
2327 dns_tree, (isupdate ?
2328 "Prerequisites" : "Answers"),
2332 /* Don't add information about the authoritative name servers, or the
2333 additional records, to the summary. */
2335 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
2337 (isupdate ? "Updates" :
2338 "Authoritative nameservers"),
2343 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
2344 NULL, dns_tree, "Additional records",
2350 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2352 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2353 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2355 dissect_dns_common(tvb, pinfo, tree, FALSE);
2359 dissect_mdns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2361 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2362 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDNS");
2364 dissect_dns_common(tvb, pinfo, tree, FALSE);
2369 get_dns_pdu_len(tvbuff_t *tvb, int offset)
2374 * Get the length of the DNS packet.
2376 plen = tvb_get_ntohs(tvb, offset);
2379 * That length doesn't include the length field itself; add that in.
2385 dissect_dns_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2387 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2388 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2390 dissect_dns_common(tvb, pinfo, tree, TRUE);
2394 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2396 tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2, get_dns_pdu_len,
2397 dissect_dns_tcp_pdu);
2401 proto_register_dns(void)
2403 static hf_register_info hf[] = {
2405 { "Length", "dns.length",
2406 FT_UINT16, BASE_DEC, NULL, 0x0,
2407 "Length of DNS-over-TCP request or response", HFILL }},
2409 { "Flags", "dns.flags",
2410 FT_UINT16, BASE_HEX, NULL, 0x0,
2412 { &hf_dns_flags_response,
2413 { "Response", "dns.flags.response",
2414 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
2415 "Is the message a response?", HFILL }},
2416 { &hf_dns_flags_opcode,
2417 { "Opcode", "dns.flags.opcode",
2418 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
2419 "Operation code", HFILL }},
2420 { &hf_dns_flags_authoritative,
2421 { "Authoritative", "dns.flags.authoritative",
2422 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
2423 "Is the server is an authority for the domain?", HFILL }},
2424 { &hf_dns_flags_truncated,
2425 { "Truncated", "dns.flags.truncated",
2426 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
2427 "Is the message truncated?", HFILL }},
2428 { &hf_dns_flags_recdesired,
2429 { "Recursion desired", "dns.flags.recdesired",
2430 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
2431 "Do query recursively?", HFILL }},
2432 { &hf_dns_flags_recavail,
2433 { "Recursion available", "dns.flags.recavail",
2434 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
2435 "Can the server do recursive queries?", HFILL }},
2437 { "Z", "dns.flags.z",
2438 FT_BOOLEAN, 16, TFS(&tfs_flags_z), F_Z,
2440 { &hf_dns_flags_authenticated,
2441 { "Answer authenticated", "dns.flags.authenticated",
2442 FT_BOOLEAN, 16, TFS(&tfs_flags_authenticated), F_AUTHENTIC,
2443 "Was the reply data authenticated by the server?", HFILL }},
2444 { &hf_dns_flags_checkdisable,
2445 { "Non-authenticated data OK", "dns.flags.checkdisable",
2446 FT_BOOLEAN, 16, TFS(&tfs_flags_checkdisable), F_CHECKDISABLE,
2447 "Is non-authenticated data acceptable?", HFILL }},
2448 { &hf_dns_flags_rcode,
2449 { "Reply code", "dns.flags.rcode",
2450 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
2451 "Reply code", HFILL }},
2452 { &hf_dns_transaction_id,
2453 { "Transaction ID", "dns.id",
2454 FT_UINT16, BASE_HEX, NULL, 0x0,
2455 "Identification of transaction", HFILL }},
2456 { &hf_dns_count_questions,
2457 { "Questions", "dns.count.queries",
2458 FT_UINT16, BASE_DEC, NULL, 0x0,
2459 "Number of queries in packet", HFILL }},
2460 { &hf_dns_count_answers,
2461 { "Answer RRs", "dns.count.answers",
2462 FT_UINT16, BASE_DEC, NULL, 0x0,
2463 "Number of answers in packet", HFILL }},
2464 { &hf_dns_count_auth_rr,
2465 { "Authority RRs", "dns.count.auth_rr",
2466 FT_UINT16, BASE_DEC, NULL, 0x0,
2467 "Number of authoritative records in packet", HFILL }},
2468 { &hf_dns_count_add_rr,
2469 { "Additional RRs", "dns.count.add_rr",
2470 FT_UINT16, BASE_DEC, NULL, 0x0,
2471 "Number of additional records in packet", HFILL }}
2473 static gint *ett[] = {
2483 module_t *dns_module;
2485 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2486 proto_register_field_array(proto_dns, hf, array_length(hf));
2487 proto_register_subtree_array(ett, array_length(ett));
2489 dns_module = prefs_register_protocol(proto_dns, NULL);
2490 prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2491 "Desegment all DNS messages spanning multiple TCP segments",
2492 "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
2497 proto_reg_handoff_dns(void)
2499 dissector_handle_t dns_udp_handle;
2500 dissector_handle_t dns_tcp_handle;
2501 dissector_handle_t mdns_udp_handle;
2503 dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
2504 dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
2505 mdns_udp_handle = create_dissector_handle(dissect_mdns_udp, proto_dns);
2507 dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
2508 dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
2509 dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
2510 dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
2512 gssapi_handle = find_dissector("gssapi");