2 * Routines for DNS packet disassembly
5 * RFC 2136 for dynamic DNS
9 * Copyright 2004, Nicolas DICHTEL - 6WIND - <nicolas.dichtel@6wind.com>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #include <epan/packet.h>
39 #include <epan/conversation.h>
40 #include <epan/emem.h>
41 #include <epan/ipproto.h>
42 #include <epan/addr_resolv.h>
43 #include "packet-dns.h"
44 #include "packet-tcp.h"
45 #include <epan/prefs.h>
46 #include <epan/strutil.h>
47 #include <epan/emem.h>
49 static int proto_dns = -1;
50 static int hf_dns_length = -1;
51 static int hf_dns_flags = -1;
52 static int hf_dns_flags_response = -1;
53 static int hf_dns_flags_opcode = -1;
54 static int hf_dns_flags_authoritative = -1;
55 static int hf_dns_flags_truncated = -1;
56 static int hf_dns_flags_recdesired = -1;
57 static int hf_dns_flags_recavail = -1;
58 static int hf_dns_flags_z = -1;
59 static int hf_dns_flags_authenticated = -1;
60 static int hf_dns_flags_checkdisable = -1;
61 static int hf_dns_flags_rcode = -1;
62 static int hf_dns_transaction_id = -1;
63 static int hf_dns_count_questions = -1;
64 static int hf_dns_count_zones = -1;
65 static int hf_dns_count_answers = -1;
66 static int hf_dns_count_prerequisites = -1;
67 static int hf_dns_count_updates = -1;
68 static int hf_dns_count_auth_rr = -1;
69 static int hf_dns_count_add_rr = -1;
70 static int hf_dns_qry_name = -1;
71 static int hf_dns_qry_type = -1;
72 static int hf_dns_qry_class = -1;
73 static int hf_dns_rr_name = -1;
74 static int hf_dns_rr_type = -1;
75 static int hf_dns_rr_class = -1;
76 static int hf_dns_rr_ttl = -1;
77 static int hf_dns_rr_len = -1;
78 static int hf_dns_tsig_error = -1;
79 static int hf_dns_tsig_fudge = -1;
80 static int hf_dns_tsig_mac_size = -1;
81 static int hf_dns_tsig_mac = -1;
82 static int hf_dns_tsig_original_id = -1;
83 static int hf_dns_tsig_algorithm_name = -1;
84 static int hf_dns_tsig_other_len = -1;
85 static int hf_dns_tsig_other_data = -1;
86 static int hf_dns_response_in = -1;
87 static int hf_dns_response_to = -1;
88 static int hf_dns_time = -1;
90 static gint ett_dns = -1;
91 static gint ett_dns_qd = -1;
92 static gint ett_dns_rr = -1;
93 static gint ett_dns_qry = -1;
94 static gint ett_dns_ans = -1;
95 static gint ett_dns_flags = -1;
96 static gint ett_t_key_flags = -1;
97 static gint ett_t_key = -1;
98 static gint ett_dns_mac = -1;
100 static dissector_table_t dns_tsig_dissector_table=NULL;
102 /* desegmentation of DNS over TCP */
103 static gboolean dns_desegment = TRUE;
105 /* Dissector handle for GSSAPI */
106 static dissector_handle_t gssapi_handle;
107 static dissector_handle_t ntlmssp_handle;
109 /* Structure containing transaction specific information */
110 typedef struct _dns_transaction_t {
116 /* Structure containing conversation specific information */
117 typedef struct _dns_conv_info_t {
121 /* DNS structs and definitions */
123 /* Ports used for DNS. */
124 #define UDP_PORT_DNS 53
125 #define TCP_PORT_DNS 53
126 #define UDP_PORT_MDNS 5353
127 #define TCP_PORT_MDNS 5353
129 /* Offsets of fields in the DNS header. */
137 /* Length of DNS header. */
138 #define DNS_HDRLEN 12
141 #define T_A 1 /* host address */
142 #define T_NS 2 /* authoritative name server */
143 #define T_MD 3 /* mail destination (obsolete) */
144 #define T_MF 4 /* mail forwarder (obsolete) */
145 #define T_CNAME 5 /* canonical name */
146 #define T_SOA 6 /* start of authority zone */
147 #define T_MB 7 /* mailbox domain name (experimental) */
148 #define T_MG 8 /* mail group member (experimental) */
149 #define T_MR 9 /* mail rename domain name (experimental) */
150 #define T_NULL 10 /* null RR (experimental) */
151 #define T_WKS 11 /* well known service */
152 #define T_PTR 12 /* domain name pointer */
153 #define T_HINFO 13 /* host information */
154 #define T_MINFO 14 /* mailbox or mail list information */
155 #define T_MX 15 /* mail routing information */
156 #define T_TXT 16 /* text strings */
157 #define T_RP 17 /* responsible person (RFC 1183) */
158 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
159 #define T_X25 19 /* X.25 address (RFC 1183) */
160 #define T_ISDN 20 /* ISDN address (RFC 1183) */
161 #define T_RT 21 /* route-through (RFC 1183) */
162 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
163 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
164 #define T_SIG 24 /* digital signature (RFC 2535) */
165 #define T_KEY 25 /* public key (RFC 2535) */
166 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
167 #define T_GPOS 27 /* geographical position (RFC 1712) */
168 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
169 #define T_LOC 29 /* geographical location (RFC 1876) */
170 #define T_NXT 30 /* "next" name (RFC 2535) */
171 #define T_EID 31 /* ??? (Nimrod?) */
172 #define T_NIMLOC 32 /* ??? (Nimrod?) */
173 #define T_SRV 33 /* service location (RFC 2052) */
174 #define T_ATMA 34 /* ??? */
175 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
176 #define T_KX 36 /* Key Exchange (RFC 2230) */
177 #define T_CERT 37 /* Certificate (RFC 2538) */
178 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
179 #define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
180 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
181 #define T_DS 43 /* Delegation Signature(RFC 3658) */
182 #define T_IPSECKEY 45 /* draft-ietf-ipseckey-rr */
183 #define T_RRSIG 46 /* future RFC 2535bis */
184 #define T_NSEC 47 /* future RFC 2535bis */
185 #define T_DNSKEY 48 /* future RFC 2535bis */
186 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
187 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
188 #define T_WINS 65281 /* Microsoft's WINS RR */
189 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
192 #define C_IN 1 /* the Internet */
193 #define C_CS 2 /* CSNET (obsolete) */
194 #define C_CH 3 /* CHAOS */
195 #define C_HS 4 /* Hesiod */
196 #define C_NONE 254 /* none */
197 #define C_ANY 255 /* any */
198 #define C_FLUSH (1<<15) /* High bit is set for MDNS cache flush */
200 /* Bit fields in the flags */
201 #define F_RESPONSE (1<<15) /* packet is response */
202 #define F_OPCODE (0xF<<11) /* query opcode */
203 #define OPCODE_SHIFT 11
204 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
205 #define F_TRUNCATED (1<<9) /* response is truncated */
206 #define F_RECDESIRED (1<<8) /* recursion desired */
207 #define F_RECAVAIL (1<<7) /* recursion available */
208 #define F_Z (1<<6) /* Z */
209 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
210 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
211 #define F_RCODE (0xF<<0) /* reply code */
213 static const true_false_string tfs_flags_response = {
214 "Message is a response",
218 static const true_false_string tfs_flags_authoritative = {
219 "Server is an authority for domain",
220 "Server is not an authority for domain"
223 static const true_false_string tfs_flags_truncated = {
224 "Message is truncated",
225 "Message is not truncated"
228 static const true_false_string tfs_flags_recdesired = {
229 "Do query recursively",
230 "Don't do query recursively"
233 static const true_false_string tfs_flags_recavail = {
234 "Server can do recursive queries",
235 "Server can't do recursive queries"
238 static const true_false_string tfs_flags_z = {
239 "reserved - incorrect!",
243 static const true_false_string tfs_flags_authenticated = {
244 "Answer/authority portion was authenticated by the server",
245 "Answer/authority portion was not authenticated by the server"
248 static const true_false_string tfs_flags_checkdisable = {
249 "Non-authenticated data is acceptable",
250 "Non-authenticated data is unacceptable"
254 #define OPCODE_QUERY 0 /* standard query */
255 #define OPCODE_IQUERY 1 /* inverse query */
256 #define OPCODE_STATUS 2 /* server status request */
257 #define OPCODE_NOTIFY 4 /* zone change notification */
258 #define OPCODE_UPDATE 5 /* dynamic update */
260 static const value_string opcode_vals[] = {
261 { OPCODE_QUERY, "Standard query" },
262 { OPCODE_IQUERY, "Inverse query" },
263 { OPCODE_STATUS, "Server status request" },
264 { OPCODE_NOTIFY, "Zone change notification" },
265 { OPCODE_UPDATE, "Dynamic update" },
269 #define RCODE_NOERROR 0
270 #define RCODE_FORMERR 1
271 #define RCODE_SERVFAIL 2
272 #define RCODE_NXDOMAIN 3
273 #define RCODE_NOTIMPL 4
274 #define RCODE_REFUSED 5
275 #define RCODE_YXDOMAIN 6
276 #define RCODE_YXRRSET 7
277 #define RCODE_NXRRSET 8
278 #define RCODE_NOTAUTH 9
279 #define RCODE_NOTZONE 10
281 static const value_string rcode_vals[] = {
282 { RCODE_NOERROR, "No error" },
283 { RCODE_FORMERR, "Format error" },
284 { RCODE_SERVFAIL, "Server failure" },
285 { RCODE_NXDOMAIN, "No such name" },
286 { RCODE_NOTIMPL, "Not implemented" },
287 { RCODE_REFUSED, "Refused" },
288 { RCODE_YXDOMAIN, "Name exists" },
289 { RCODE_YXRRSET, "RRset exists" },
290 { RCODE_NXRRSET, "RRset does not exist" },
291 { RCODE_NOTAUTH, "Not authoritative" },
292 { RCODE_NOTZONE, "Name out of zone" },
295 /* TSIG/TKEY extended errors */
296 #define TSIGERROR_BADSIG (16)
297 #define TSIGERROR_BADKEY (17)
298 #define TSIGERROR_BADTIME (18)
299 #define TSIGERROR_BADMODE (19)
300 #define TSIGERROR_BADNAME (20)
301 #define TSIGERROR_BADALG (21)
303 static const value_string tsigerror_vals[] = {
304 { TSIGERROR_BADSIG, "Bad signature" },
305 { TSIGERROR_BADKEY, "Bad key" },
306 { TSIGERROR_BADTIME, "Bad time failure" },
307 { TSIGERROR_BADMODE, "Bad mode such name" },
308 { TSIGERROR_BADNAME, "Bad name implemented" },
309 { TSIGERROR_BADALG, "Bad algorithm" },
312 #define TKEYMODE_SERVERASSIGNED (1)
313 #define TKEYMODE_DIFFIEHELLMAN (2)
314 #define TKEYMODE_GSSAPI (3)
315 #define TKEYMODE_RESOLVERASSIGNED (4)
316 #define TKEYMODE_DELETE (5)
318 #define TDSDIGEST_RESERVED (0)
319 #define TDSDIGEST_SHA1 (1)
321 /* See RFC 1035 for all RR types for which no RFC is listed, except for
322 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
323 which one should look at
325 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
329 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
331 which discuss them to some extent. */
333 static const value_string dns_types[] = {
339 { T_CNAME, "CNAME" },
347 { T_HINFO, "HINFO" },
348 { T_MINFO, "MINFO" },
351 { T_RP, "RP" }, /* RFC 1183 */
352 { T_AFSDB, "AFSDB" }, /* RFC 1183 */
353 { T_X25, "X25" }, /* RFC 1183 */
354 { T_ISDN, "ISDN" }, /* RFC 1183 */
355 { T_RT, "RT" }, /* RFC 1183 */
356 { T_NSAP, "NSAP" }, /* RFC 1706 */
357 { T_NSAP_PTR, "NSAP-PTR" }, /* RFC 1348 */
358 { T_SIG, "SIG" }, /* RFC 2535 */
359 { T_KEY, "KEY" }, /* RFC 2535 */
360 { T_PX, "PX" }, /* RFC 1664 */
361 { T_GPOS, "GPOS" }, /* RFC 1712 */
362 { T_AAAA, "AAAA" }, /* RFC 1886 */
363 { T_LOC, "LOC" }, /* RFC 1886 */
364 { T_NXT, "NXT" }, /* RFC 1876 */
366 { T_NIMLOC, "NIMLOC" },
367 { T_SRV, "SRV" }, /* RFC 2052 */
369 { T_NAPTR, "NAPTR" }, /* RFC 2168 */
370 { T_KX, "KX" }, /* RFC 2230 */
371 { T_CERT, "CERT" }, /* RFC 2538 */
372 { T_A6, "A6" }, /* RFC 2874 */
373 { T_DNAME, "DNAME" }, /* RFC 2672 */
375 { T_OPT, "OPT" }, /* RFC 2671 */
377 { T_DS, "DS" }, /* RFC 3658 */
379 { T_IPSECKEY, "IPSECKEY" }, /* draft-ietf-ipseckey-rr */
380 { T_RRSIG, "RRSIG" }, /* future RFC 2535bis */
381 { T_NSEC, "NSEC" }, /* future RFC 2535bis */
382 { T_DNSKEY, "DNSKEY" }, /* future RFC 2535bis */
393 { T_WINS_R, "WINS-R"},
405 dns_type_name (guint type)
407 return val_to_str(type, dns_types, "Unknown (%u)");
411 dns_type_description (guint type)
413 static const char *type_names[] = {
416 "Authoritative name server",
419 "Canonical name for an alias",
420 "Start of zone of authority",
421 "Mailbox domain name",
423 "Mail rename domain name",
424 "Null resource record",
425 "Well-known service description",
426 "Domain name pointer",
428 "Mailbox or mail list information",
431 "Responsible person", /* RFC 1183 */
432 "AFS data base location", /* RFC 1183 */
433 "X.25 address", /* RFC 1183 */
434 "ISDN number", /* RFC 1183 */
435 "Route through", /* RFC 1183 */
436 "OSI NSAP", /* RFC 1706 */
437 "OSI NSAP name pointer", /* RFC 1348 */
438 "Signature", /* RFC 2535 */
439 "Public key", /* RFC 2535 */
440 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
441 "Geographical position", /* RFC 1712 */
442 "IPv6 address", /* RFC 1886 */
443 "Location", /* RFC 1876 */
444 "Next", /* RFC 2535 */
447 "Service location", /* RFC 2052 */
449 "Naming authority pointer", /* RFC 2168 */
450 "Key Exchange", /* RFC 2230 */
451 "Certificate", /* RFC 2538 */
452 "IPv6 address with indirection", /* RFC 2874 */
453 "Non-terminal DNS name redirection", /* RFC 2672 */
455 "EDNS0 option", /* RFC 2671 */
457 "Delegation Signer", /* RFC 3658 */
459 "key to use with IPSEC", /* draft-ietf-ipseckey-rr */
460 "RR signature", /* future RFC 2535bis */
461 "Next secured", /* future RFC 2535bis */
462 "DNS public key" /* future RFC 2535bis */
464 const char *short_name;
465 const char *long_name;
466 #define MAX_STRBUF_LEN 1024
469 strbuf=ep_alloc(MAX_STRBUF_LEN);
470 short_name = dns_type_name(type);
471 if (short_name == NULL) {
472 g_snprintf(strbuf, MAX_STRBUF_LEN, "Unknown (%u)", type);
475 if (type < sizeof(type_names)/sizeof(type_names[0]))
476 long_name = type_names[type];
482 long_name = "Transaction Key";
485 long_name = "Transaction Signature";
490 long_name = "Request for incremental zone transfer"; /* RFC 1995 */
493 long_name = "Request for full zone transfer";
496 long_name = "Request for mailbox-related records";
499 long_name = "Request for mail agent resource records";
502 long_name = "Request for all records";
510 if (long_name != NULL)
511 g_snprintf(strbuf, MAX_STRBUF_LEN, "%s (%s)", short_name, long_name);
513 g_snprintf(strbuf, MAX_STRBUF_LEN, "%s", short_name);
517 static const value_string dns_classes[] = {
524 {C_IN | C_FLUSH, "FLUSH"},
529 dns_class_name(int class)
531 return val_to_str(class, dns_classes, "Unknown (%u)");
534 /* This function returns the number of bytes consumed and the expanded string
536 * The string is allocated with ep scope and does not need to be free()d.
537 * it will be automatically free()d when the packet has been dissected.
540 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
543 int start_offset = offset;
546 int chars_processed = 0;
547 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
552 const int min_len = 1; /* Minimum length of encoded name (for root) */
553 /* If we're about to return a value (probably negative) which is less
554 * than the minimum length, we're looking at bad data and we're liable
555 * to put the dissector into a loop. Instead we throw an exception */
558 *name=ep_alloc(maxname);
561 maxname--; /* reserve space for the trailing '\0' */
563 component_len = tvb_get_guint8(tvb, offset);
565 if (component_len == 0)
568 switch (component_len & 0xc0) {
573 /* Not the first component - put in a '.'. */
579 while (component_len > 0) {
581 *np++ = tvb_get_guint8(tvb, offset);
591 /* Extended label (RFC 2673) */
592 switch (component_len & 0x3f) {
595 /* Bitstring label */
601 bit_count = tvb_get_guint8(tvb, offset);
603 label_len = (bit_count - 1) / 8 + 1;
606 print_len = g_snprintf(np, maxname + 1, "\\[x");
607 if (print_len != -1 && print_len <= maxname) {
608 /* Some versions of g_snprintf return -1 if they'd truncate
609 the output. Others return <buf_size> or greater. */
611 maxname -= print_len;
613 /* Nothing printed, as there's no room.
614 Suppress all subsequent printing. */
620 print_len = g_snprintf(np, maxname + 1, "%02x",
621 tvb_get_guint8(tvb, offset));
622 if (print_len != -1 && print_len <= maxname) {
623 /* Some versions of g_snprintf return -1 if they'd truncate
624 the output. Others return <buf_size> or greater. */
626 maxname -= print_len;
628 /* Nothing printed, as there's no room.
629 Suppress all subsequent printing. */
636 print_len = g_snprintf(np, maxname + 1, "/%d]", bit_count);
637 if (print_len != -1 && print_len <= maxname) {
638 /* Some versions of g_snprintf return -1 if they'd truncate
639 the output. Others return <buf_size> or greater. */
641 maxname -= print_len;
643 /* Nothing printed, as there's no room.
644 Suppress all subsequent printing. */
652 *name="<Unknown extended label>";
653 /* Parsing will propably fail from here on, since the */
654 /* label length is unknown... */
655 len = offset - start_offset;
657 THROW(ReportedBoundsError);
663 THROW(ReportedBoundsError);
667 indir_offset = dns_data_offset +
668 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
672 /* If "len" is negative, we are still working on the original name,
673 not something pointed to by a pointer, and so we should set "len"
674 to the length of the original name. */
676 len = offset - start_offset;
678 /* If we've looked at every character in the message, this pointer
679 will make us look at some character again, which means we're
681 if (chars_processed >= data_size) {
682 *name="<Name contains a pointer that loops>";
684 THROW(ReportedBoundsError);
688 offset = indir_offset;
689 break; /* now continue processing from there */
694 /* If "len" is negative, we haven't seen a pointer, and thus haven't
695 set the length, so set it. */
697 len = offset - start_offset;
698 /* Zero-length name means "root server" */
702 THROW(ReportedBoundsError);
708 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
709 char **name_ret, int *name_len_ret, int *type_ret, int *class_ret)
715 int start_offset = offset;
717 name_len = get_dns_name(tvb, offset, dns_data_offset, name_ret);
720 type = tvb_get_ntohs(tvb, offset);
723 class = tvb_get_ntohs(tvb, offset);
728 *name_len_ret = name_len;
730 len = offset - start_offset;
735 rfc1867_size(tvbuff_t *tvb, int offset)
741 val = tvb_get_guint8(tvb, offset);
742 size = (val & 0xF0) >> 4;
743 exponent = (val & 0x0F);
744 while (exponent != 0) {
748 return size / 100; /* return size in meters, not cm */
752 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
756 guint32 degrees, minutes, secs, tsecs;
757 /* "%u deg %u min %u.%03u sec %c" */
758 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
760 angle = tvb_get_ntohl(tvb, offset);
762 if (angle < 0x80000000U) {
763 angle = 0x80000000U - angle;
766 angle = angle - 0x80000000U;
769 tsecs = angle % 1000;
770 angle = angle / 1000;
773 minutes = angle % 60;
774 degrees = angle / 60;
775 g_snprintf(buf, sizeof(buf), "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
781 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
782 column_info *cinfo, proto_tree *dns_tree)
790 const char *type_name;
796 data_start = data_offset = offset;
798 len = get_dns_name_type_class(tvb, offset, dns_data_offset, &name, &name_len,
802 type_name = dns_type_name(type);
805 * The name might contain octets that aren't printable characters,
806 * format it for display.
808 name_out = format_text(name, strlen(name));
811 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name_out);
813 if (dns_tree != NULL) {
814 tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
815 name_out, type_name, dns_class_name(class));
816 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
818 proto_tree_add_string(q_tree, hf_dns_qry_name, tvb, offset, name_len, name);
821 proto_tree_add_uint_format(q_tree, hf_dns_qry_type, tvb, offset, 2, type,
822 "Type: %s", dns_type_description(type));
825 proto_tree_add_uint(q_tree, hf_dns_qry_class, tvb, offset, 2, class);
829 return data_offset - data_start;
834 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
835 const char *name, int namelen, int type, int class,
836 guint ttl, gushort data_len)
840 rr_tree = proto_item_add_subtree(trr, rr_type);
841 proto_tree_add_string(rr_tree, hf_dns_rr_name, tvb, offset, namelen, name);
843 proto_tree_add_uint_format(rr_tree, hf_dns_rr_type, tvb, offset, 2, type,
844 "Type: %s", dns_type_description(type));
846 proto_tree_add_uint(rr_tree, hf_dns_rr_class, tvb, offset, 2, class);
848 proto_tree_add_uint_format(rr_tree, hf_dns_rr_ttl, tvb, offset, 4, ttl,
849 "Time to live: %s", time_secs_to_str(ttl));
851 proto_tree_add_uint(rr_tree, hf_dns_rr_len, tvb, offset, 2, data_len);
857 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
858 const char *name, int namelen, int type, int class,
859 guint ttl, gushort data_len)
861 proto_tree *rr_tree, *Z_tree;
862 proto_item *Z_item = NULL;
864 rr_tree = proto_item_add_subtree(trr, rr_type);
865 proto_tree_add_string(rr_tree, hf_dns_rr_name, tvb, offset, namelen, name);
867 proto_tree_add_uint_format(rr_tree, hf_dns_rr_type, tvb, offset, 2, type,
868 "Type: %s", dns_type_description(type));
870 proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
873 proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
874 (ttl >> 24) & 0xff0);
876 proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
879 Z_item = proto_tree_add_text(rr_tree, tvb, offset, 2, "Z: 0x%x", ttl & 0xffff);
881 Z_tree = proto_item_add_subtree(Z_item, rr_type);
882 proto_tree_add_text(Z_tree, tvb, offset, 2, "Bit 0 (DO bit): 1 (Accepts DNSSEC security RRs)");
883 proto_tree_add_text(Z_tree, tvb, offset, 2, "Bits 1-15: 0x%x (reserved)", (ttl >> 17) & 0xff);
886 proto_tree_add_uint(rr_tree, hf_dns_rr_len, tvb, offset, 2, data_len);
891 * SIG, KEY, and CERT RR algorithms.
893 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
894 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
895 #define DNS_ALGO_DSA 3 /* DSA */
896 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
897 #define DNS_ALGO_RSASHA1 5 /* RSA/SHA1 */
898 #define DNS_ALGO_HMACMD5 157 /* HMAC/MD5 */
899 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
900 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
901 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
903 static const value_string algo_vals[] = {
904 { DNS_ALGO_RSAMD5, "RSA/MD5" },
905 { DNS_ALGO_DH, "Diffie-Hellman" },
906 { DNS_ALGO_DSA, "DSA" },
907 { DNS_ALGO_ECC, "Elliptic curve crypto" },
908 { DNS_ALGO_RSASHA1, "RSA/SHA1" },
909 { DNS_ALGO_HMACMD5, "HMAC/MD5" },
910 { DNS_ALGO_INDIRECT, "Indirect key" },
911 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
912 { DNS_ALGO_PRIVATEOID, "Private, OID" },
916 #define DNS_CERT_PGP 1 /* PGP */
917 #define DNS_CERT_PKIX 2 /* PKIX */
918 #define DNS_CERT_SPKI 3 /* SPKI */
919 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
920 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
922 static const value_string cert_vals[] = {
923 { DNS_CERT_PGP, "PGP" },
924 { DNS_CERT_PKIX, "PKIX" },
925 { DNS_CERT_SPKI, "SPKI" },
926 { DNS_CERT_PRIVATEURI, "Private, URI" },
927 { DNS_CERT_PRIVATEOID, "Private, OID" },
932 * Compute the key id of a KEY RR depending of the algorithm used.
935 compute_key_id(tvbuff_t *tvb, int offset, int size, guint8 algo)
940 DISSECTOR_ASSERT(size >= 4);
943 case DNS_ALGO_RSAMD5:
944 return (guint16)(tvb_get_guint8(tvb, offset + size - 3) << 8) + tvb_get_guint8( tvb, offset + size - 2 );
946 for (ac = 0; size > 1; size -= 2, offset += 2) {
947 c1 = tvb_get_guint8( tvb, offset );
948 c2 = tvb_get_guint8( tvb, offset + 1 );
949 ac += (c1 << 8) + c2 ;
952 c1 = tvb_get_guint8( tvb, offset );
955 ac += (ac >> 16) & 0xffff;
956 return (guint16)(ac & 0xffff);
962 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
963 column_info *cinfo, proto_tree *dns_tree, packet_info *pinfo)
971 const char *class_name;
972 const char *type_name;
978 proto_tree *rr_tree = NULL;
979 proto_item *trr = NULL;
981 data_start = data_offset = offset;
984 len = get_dns_name_type_class(tvb, offset, dns_data_offset, &name, &name_len,
989 type_name = dns_type_name(type);
990 class_name = dns_class_name(class);
992 ttl = tvb_get_ntohl(tvb, data_offset);
996 data_len = tvb_get_ntohs(tvb, data_offset);
1001 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
1002 if (dns_tree != NULL) {
1004 * The name might contain octets that aren't printable characters,
1005 * format it for display.
1007 name_out = format_text(name, strlen(name));
1008 if (type != T_OPT) {
1009 trr = proto_tree_add_text(dns_tree, tvb, offset,
1010 (data_offset - data_start) + data_len,
1011 "%s: type %s, class %s",
1012 name_out, type_name, class_name);
1013 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
1014 type, class, ttl, data_len);
1016 trr = proto_tree_add_text(dns_tree, tvb, offset,
1017 (data_offset - data_start) + data_len,
1018 "%s: type %s", name_out, type_name);
1019 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
1020 type, class, ttl, data_len);
1025 return data_offset - data_start;
1034 addr = tvb_get_ptr(tvb, cur_offset, 4);
1036 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
1037 if (dns_tree != NULL) {
1038 proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
1039 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
1042 if ((class & 0x7f) == C_IN) {
1043 memcpy(&addr_int, addr, sizeof(addr_int));
1044 add_ipv4_name(addr_int, name);
1054 ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, &ns_name);
1055 name_out = format_text(ns_name, strlen(ns_name));
1057 col_append_fstr(cinfo, COL_INFO, " %s", name_out);
1058 if (dns_tree != NULL) {
1059 proto_item_append_text(trr, ", ns %s", name_out);
1060 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
1071 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, &cname);
1072 name_out = format_text(cname, strlen(cname));
1074 col_append_fstr(cinfo, COL_INFO, " %s", name_out);
1075 if (dns_tree != NULL) {
1076 proto_item_append_text(trr, ", cname %s", name_out);
1077 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
1095 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, &mname);
1096 name_out = format_text(mname, strlen(mname));
1098 col_append_fstr(cinfo, COL_INFO, " %s", name_out);
1099 if (dns_tree != NULL) {
1100 proto_item_append_text(trr, ", mname %s", name_out);
1101 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
1103 cur_offset += mname_len;
1105 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, &rname);
1106 name_out = format_text(rname, strlen(rname));
1107 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
1109 cur_offset += rname_len;
1111 serial = tvb_get_ntohl(tvb, cur_offset);
1112 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
1116 refresh = tvb_get_ntohl(tvb, cur_offset);
1117 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
1118 time_secs_to_str(refresh));
1121 retry = tvb_get_ntohl(tvb, cur_offset);
1122 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
1123 time_secs_to_str(retry));
1126 expire = tvb_get_ntohl(tvb, cur_offset);
1127 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
1128 time_secs_to_str(expire));
1131 minimum = tvb_get_ntohl(tvb, cur_offset);
1132 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
1133 time_secs_to_str(minimum));
1143 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, &pname);
1144 name_out = format_text(pname, strlen(pname));
1146 col_append_fstr(cinfo, COL_INFO, " %s", name_out);
1147 if (dns_tree != NULL) {
1148 proto_item_append_text(trr, ", %s", name_out);
1149 proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
1158 int rr_len = data_len;
1159 const guint8 *wks_addr;
1165 char *bitnames, *strptr;
1167 #define MAX_STR_LEN 128
1168 bitnames=ep_alloc(MAX_STR_LEN);
1173 if (dns_tree != NULL)
1177 wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
1179 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
1180 if (dns_tree != NULL) {
1181 proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
1182 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
1183 ip_to_str(wks_addr));
1189 protocol = tvb_get_guint8(tvb, cur_offset);
1190 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
1191 ipprotostr(protocol));
1196 while (rr_len != 0) {
1197 bits = tvb_get_guint8(tvb, cur_offset);
1202 for (i = 0; i < 8; i++) {
1204 if (strptr!=bitnames)
1205 strptr += MIN(MAX_STR_LEN-(strptr-bitnames),
1206 g_snprintf(strptr, MAX_STR_LEN-(strptr-bitnames), ", "));
1210 strptr += MIN(MAX_STR_LEN-(strptr-bitnames),
1211 g_snprintf(strptr, MAX_STR_LEN-(strptr-bitnames), get_tcp_port(port_num)));
1215 strptr += MIN(MAX_STR_LEN-(strptr-bitnames),
1216 g_snprintf(strptr, MAX_STR_LEN-(strptr-bitnames), get_udp_port(port_num)));
1220 strptr += MIN(MAX_STR_LEN-(strptr-bitnames),
1221 g_snprintf(strptr, MAX_STR_LEN-(strptr-bitnames), "%u", port_num));
1228 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1229 "Bits: 0x%02x (%s)", bits, bitnames);
1248 cpu_offset = cur_offset;
1249 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1250 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1251 os_offset = cpu_offset + 1 + cpu_len;
1252 os_len = tvb_get_guint8(tvb, os_offset);
1253 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1255 col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1257 if (dns_tree != NULL) {
1258 proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1259 cpu_len, cpu, os_len, os);
1260 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1262 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1271 guint16 preference = 0;
1275 preference = tvb_get_ntohs(tvb, cur_offset);
1276 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, &mx_name);
1277 name_out = format_text(mx_name, strlen(mx_name));
1279 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, name_out);
1280 if (dns_tree != NULL) {
1281 proto_item_append_text(trr, ", preference %u, mx %s",
1282 preference, name_out);
1283 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1284 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1292 int rr_len = data_len;
1296 if (dns_tree != NULL) {
1297 txt_offset = cur_offset;
1298 while (rr_len != 0) {
1299 txt_len = tvb_get_guint8(tvb, txt_offset);
1300 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1301 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1302 txt_offset += 1 + txt_len;
1303 rr_len -= 1 + txt_len;
1312 int rr_len = data_len;
1313 guint16 type_covered;
1316 int signer_name_len;
1318 if (dns_tree != NULL) {
1321 type_covered = tvb_get_ntohs(tvb, cur_offset);
1322 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s",
1323 dns_type_description(type_covered));
1329 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1330 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1331 "Unknown (0x%02X)"));
1337 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1338 tvb_get_guint8(tvb, cur_offset));
1344 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1345 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1351 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1353 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1354 abs_time_to_str(&nstime));
1360 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1362 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1363 abs_time_to_str(&nstime));
1369 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Id of signing key(footprint): %u",
1370 tvb_get_ntohs(tvb, cur_offset));
1374 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, &signer_name);
1375 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1376 "Signer's name: %s",
1377 format_text(signer_name, strlen(signer_name)));
1378 cur_offset += signer_name_len;
1379 rr_len -= signer_name_len;
1382 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1390 int rr_len = data_len;
1393 proto_tree *flags_tree;
1397 if (dns_tree != NULL) {
1400 flags = tvb_get_ntohs(tvb, cur_offset);
1401 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1402 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1403 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1404 decode_boolean_bitfield(flags, 0x8000,
1405 2*8, "Key prohibited for authentication",
1406 "Key allowed for authentication"));
1407 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1408 decode_boolean_bitfield(flags, 0x4000,
1409 2*8, "Key prohibited for confidentiality",
1410 "Key allowed for confidentiality"));
1411 if ((flags & 0xC000) != 0xC000) {
1413 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1414 decode_boolean_bitfield(flags, 0x2000,
1415 2*8, "Key is experimental or optional",
1416 "Key is required"));
1417 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1418 decode_boolean_bitfield(flags, 0x0400,
1419 2*8, "Key is associated with a user",
1420 "Key is not associated with a user"));
1421 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1422 decode_boolean_bitfield(flags, 0x0200,
1423 2*8, "Key is associated with the named entity",
1424 "Key is not associated with the named entity"));
1425 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1426 decode_boolean_bitfield(flags, 0x0100,
1427 2*8, "This is the zone key for the specified zone",
1428 "This is not a zone key"));
1429 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1430 decode_boolean_bitfield(flags, 0x0080,
1431 2*8, "Key is valid for use with IPSEC",
1432 "Key is not valid for use with IPSEC"));
1433 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1434 decode_boolean_bitfield(flags, 0x0040,
1435 2*8, "Key is valid for use with MIME security multiparts",
1436 "Key is not valid for use with MIME security multiparts"));
1437 if( type != T_DNSKEY )
1438 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1439 decode_numeric_bitfield(flags, 0x000F,
1440 2*8, "Signatory = %u"));
1441 else proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1442 decode_boolean_bitfield(flags, 0x0001,
1443 2*8, "Key is a Key Signing Key",
1444 "Key is a Zone Signing Key") );
1451 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1452 tvb_get_guint8(tvb, cur_offset));
1458 algo = tvb_get_guint8(tvb, cur_offset);
1459 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1460 val_to_str(algo, algo_vals, "Unknown (0x%02X)"));
1464 key_id = compute_key_id(tvb, cur_offset-4, rr_len+4, algo);
1465 proto_tree_add_text(rr_tree, tvb, 0, 0, "Key id: %u", key_id);
1468 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1474 int rr_len = data_len;
1475 guint8 gw_type, algo;
1479 static const value_string gw_algo[] = {
1486 if( dns_tree != NULL ) {
1490 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Gateway precedence: %u",
1491 tvb_get_guint8(tvb, cur_offset));
1495 gw_type = tvb_get_guint8(tvb, cur_offset);
1499 algo = tvb_get_guint8(tvb, cur_offset);
1500 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1501 val_to_str(algo, gw_algo, "Unknown (0x%02X)"));
1506 proto_tree_add_text(rr_tree, tvb, cur_offset, 0, "Gateway: no gateway");
1509 addr = tvb_get_ptr(tvb, cur_offset, 4);
1510 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Gateway: %s",
1517 addr = tvb_get_ptr(tvb, cur_offset, 16);
1518 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Gateway: %s",
1519 ip6_to_str((const struct e_in6_addr *)addr));
1525 gw_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, &gw);
1526 proto_tree_add_text(rr_tree, tvb, cur_offset, gw_name_len,
1527 "Gateway: %s", format_text(gw, strlen(gw)));
1529 cur_offset += gw_name_len;
1530 rr_len -= gw_name_len;
1533 proto_tree_add_text(rr_tree, tvb, cur_offset, 0, "Gateway: Unknow gateway type(%u)", gw_type);
1537 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1544 const guint8 *addr6;
1545 struct e_in6_addr addr_in6;
1547 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1548 if (cinfo != NULL) {
1549 col_append_fstr(cinfo, COL_INFO, " %s",
1550 ip6_to_str((const struct e_in6_addr *)addr6));
1552 if (dns_tree != NULL) {
1553 proto_item_append_text(trr, ", addr %s",
1554 ip6_to_str((const struct e_in6_addr *)addr6));
1555 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1556 ip6_to_str((const struct e_in6_addr *)addr6));
1558 if ((class & 0x7f) == C_IN) {
1559 memcpy(&addr_in6, addr6, sizeof(addr_in6));
1560 add_ipv6_name(&addr_in6, name);
1567 unsigned short pre_len;
1568 unsigned short suf_len;
1569 unsigned short suf_octet_count;
1574 struct e_in6_addr suffix;
1576 a6_offset = cur_offset;
1577 pre_len = tvb_get_guint8(tvb, cur_offset);
1579 suf_len = 128 - pre_len;
1580 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1582 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1583 suffix.bytes[suf_offset] = 0;
1585 for (; suf_offset < 16; suf_offset++) {
1586 suffix.bytes[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1591 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1597 name_out = format_text(pname, strlen(pname));
1599 if (cinfo != NULL) {
1600 col_append_fstr(cinfo, COL_INFO, " %d %s %s",
1602 ip6_to_str(&suffix),
1605 if (dns_tree != NULL) {
1606 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1607 "Prefix len: %u", pre_len);
1610 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1611 "Address suffix: %s",
1612 ip6_to_str(&suffix));
1613 a6_offset += suf_octet_count;
1616 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1617 "Prefix name: %s", name_out);
1619 proto_item_append_text(trr, ", addr %d %s %s",
1621 ip6_to_str(&suffix),
1632 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1634 name_out = format_text(dname, strlen(dname));
1636 col_append_fstr(cinfo, COL_INFO, " %s", name_out);
1637 if (dns_tree != NULL) {
1638 proto_item_append_text(trr, ", dname %s", name_out);
1639 proto_tree_add_text(rr_tree, tvb, cur_offset,
1640 dname_len, "Target name: %s", name_out);
1649 if (dns_tree != NULL) {
1650 version = tvb_get_guint8(tvb, cur_offset);
1651 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1653 /* Version 0, the only version RFC 1876 discusses. */
1656 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1657 rfc1867_size(tvb, cur_offset));
1660 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1661 rfc1867_size(tvb, cur_offset));
1664 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1665 rfc1867_size(tvb, cur_offset));
1668 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1669 rfc1867_angle(tvb, cur_offset, "NS"));
1672 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1673 rfc1867_angle(tvb, cur_offset, "EW"));
1676 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1677 ((gint32)tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1679 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1686 int rr_len = data_len;
1687 char *next_domain_name;
1688 int next_domain_name_len;
1691 int mask, blockbase, blocksize;
1694 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1696 name_out = format_text(next_domain_name, strlen(next_domain_name));
1698 col_append_fstr(cinfo, COL_INFO, " %s", name_out);
1699 if (dns_tree != NULL) {
1700 proto_item_append_text(trr, ", next domain name %s", name_out);
1701 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1702 "Next domain name: %s", name_out);
1703 cur_offset += next_domain_name_len;
1704 rr_len -= next_domain_name_len;
1706 while (rr_len != 0) {
1707 blockbase = tvb_get_guint8(tvb, cur_offset);
1708 blocksize = tvb_get_guint8(tvb, cur_offset + 1);
1711 rr_type = blockbase * 256;
1712 for( ; blocksize; blocksize-- ) {
1713 bits = tvb_get_guint8(tvb, cur_offset);
1715 for (i = 0; i < 8; i++) {
1717 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1718 "RR type in bit map: %s",
1719 dns_type_description(rr_type));
1734 int rr_len = data_len;
1735 char *next_domain_name;
1736 int next_domain_name_len;
1742 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1744 name_out = format_text(next_domain_name, strlen(next_domain_name));
1746 col_append_fstr(cinfo, COL_INFO, " %s", name_out);
1747 if (dns_tree != NULL) {
1748 proto_item_append_text(trr, ", next domain name %s", name_out);
1749 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1750 "Next domain name: %s", name_out);
1751 cur_offset += next_domain_name_len;
1752 rr_len -= next_domain_name_len;
1754 while (rr_len != 0) {
1755 bits = tvb_get_guint8(tvb, cur_offset);
1757 for (i = 0; i < 8; i++) {
1759 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1760 "RR type in bit map: %s",
1761 dns_type_description(rr_type));
1775 guint16 preference = 0;
1779 preference = tvb_get_ntohs(tvb, cur_offset);
1780 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, &kx_name);
1781 name_out = format_text(kx_name, strlen(kx_name));
1783 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, name_out);
1784 if (dns_tree != NULL) {
1785 proto_item_append_text(trr, ", preference %u, kx %s",
1786 preference, name_out);
1787 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1788 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1796 guint16 cert_type, cert_keytag;
1798 int rr_len = data_len;
1800 if (dns_tree != NULL) {
1803 cert_type = tvb_get_ntohs(tvb, cur_offset);
1804 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type: %s",
1805 val_to_str(cert_type, cert_vals,
1806 "Unknown (0x%02X)"));
1812 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1813 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1820 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1821 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1822 val_to_str(cert_keyalg, algo_vals,
1823 "Unknown (0x%02X)"));
1828 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1834 if (dns_tree != NULL)
1835 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1840 guint16 keytag, digest_data_size = -1;
1841 guint8 ds_algorithm, ds_digest;
1842 int rr_len = data_len;
1844 static const value_string tds_digests[] = {
1845 { TDSDIGEST_RESERVED, "Reserved digest" },
1846 { TDSDIGEST_SHA1, "SHA-1" },
1850 if (dns_tree != NULL) {
1853 keytag = tvb_get_ntohs(tvb, cur_offset);
1854 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key id: %04u", keytag);
1860 ds_algorithm = tvb_get_guint8(tvb, cur_offset);
1861 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s", val_to_str(ds_algorithm, algo_vals,"Unknown (0x%02X)") );
1867 ds_digest = tvb_get_guint8(tvb, cur_offset);
1868 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Digest type: %s", val_to_str(ds_digest, tds_digests, "Unknown (0x%02X)"));
1872 if (ds_digest == TDSDIGEST_SHA1)
1873 digest_data_size = 20; /* SHA1 key is always 20 bytes long */
1874 if (digest_data_size > 0) {
1875 if (rr_len < digest_data_size)
1877 proto_tree_add_text(rr_tree, tvb, cur_offset, digest_data_size, "Public key");
1886 int tkey_algname_len;
1887 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1888 int rr_len = data_len;
1890 static const value_string tkey_modes[] = {
1891 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1892 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1893 { TKEYMODE_GSSAPI, "GSSAPI" },
1894 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1895 { TKEYMODE_DELETE, "Delete" },
1898 if (dns_tree != NULL) {
1899 proto_tree *key_tree;
1900 proto_item *key_item;
1902 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, &tkey_algname);
1903 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1904 "Algorithm name: %s",
1905 format_text(tkey_algname, strlen(tkey_algname)));
1906 cur_offset += tkey_algname_len;
1907 rr_len -= tkey_algname_len;
1911 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1913 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1914 abs_time_to_str(&nstime));
1920 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1922 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1923 abs_time_to_str(&nstime));
1929 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1930 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Mode: %s",
1931 val_to_str(tkey_mode, tkey_modes,
1932 "Unknown (0x%04X)"));
1938 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1939 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1940 val_to_str(tkey_error, rcode_vals,
1941 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1945 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1946 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key Size: %u",
1951 if (tkey_keylen != 0) {
1952 key_item = proto_tree_add_text(
1953 rr_tree, tvb, cur_offset, tkey_keylen, "Key Data");
1955 key_tree = proto_item_add_subtree(key_item, ett_t_key);
1958 case TKEYMODE_GSSAPI: {
1959 tvbuff_t *gssapi_tvb;
1962 * XXX - in at least one capture, this appears to
1963 * be an NTLMSSP blob, with no ASN.1 in it, in
1966 * See RFC 3645 which might indicate what's going
1967 * on here. (The key is an output_token from
1968 * GSS_Init_sec_context.)
1970 * How the heck do we know what method is being
1971 * used, so we know how to decode the key? Do we
1972 * have to look at the algorithm name, e.g.
1973 * "gss.microsoft.com"? We currently do as the
1974 * the SMB dissector does in some cases, and check
1975 * whether the security blob begins with "NTLMSSP".
1977 gssapi_tvb = tvb_new_subset(
1978 tvb, cur_offset, tkey_keylen, tkey_keylen);
1979 if(tvb_strneql(gssapi_tvb, 0, "NTLMSSP", 7) == 0)
1980 call_dissector(ntlmssp_handle, gssapi_tvb, pinfo, key_tree);
1982 call_dissector(gssapi_handle, gssapi_tvb, pinfo,
1989 /* No dissector for this key mode */
1994 cur_offset += tkey_keylen;
1995 rr_len -= tkey_keylen;
2000 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
2001 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Other Size: %u",
2006 if (tkey_otherlen != 0) {
2007 if (rr_len < tkey_otherlen)
2009 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other Data");
2010 cur_offset += tkey_otherlen;
2011 rr_len -= tkey_otherlen;
2019 guint16 tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
2020 guint32 tsig_timelo;
2021 char *tsig_raw_algname, *tsig_algname;
2022 int tsig_algname_len;
2024 int rr_len = data_len;
2026 if (dns_tree != NULL) {
2027 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, &tsig_raw_algname);
2028 tsig_algname=format_text(tsig_raw_algname, strlen(tsig_raw_algname));
2029 proto_tree_add_string(rr_tree, hf_dns_tsig_algorithm_name, tvb, cur_offset, tsig_algname_len, tsig_algname);
2030 cur_offset += tsig_algname_len;
2031 rr_len -= tsig_algname_len;
2035 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
2036 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
2037 nstime.secs = tsig_timelo;
2039 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
2040 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
2047 proto_tree_add_item(rr_tree, hf_dns_tsig_fudge, tvb, cur_offset, 2, FALSE);
2053 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
2054 proto_tree_add_item(rr_tree, hf_dns_tsig_mac_size, tvb, cur_offset, 2, FALSE);
2058 if (tsig_siglen != 0) {
2059 proto_item *mac_item;
2060 proto_tree *mac_tree;
2063 if (rr_len < tsig_siglen)
2066 mac_item = proto_tree_add_item(rr_tree, hf_dns_tsig_mac, tvb, cur_offset, tsig_siglen, FALSE);
2067 mac_tree = proto_item_add_subtree(mac_item, ett_dns_mac);
2069 sub_tvb=tvb_new_subset(tvb, cur_offset, tsig_siglen, tsig_siglen);
2071 if(!dissector_try_string(dns_tsig_dissector_table, tsig_algname, sub_tvb, pinfo, mac_tree)){
2072 proto_tree_add_text(mac_tree, sub_tvb, 0, tvb_length(sub_tvb), "No dissector for algorithm:%s", tsig_algname);
2075 cur_offset += tsig_siglen;
2076 rr_len -= tsig_siglen;
2081 proto_tree_add_item(rr_tree, hf_dns_tsig_original_id, tvb, cur_offset, 2, FALSE);
2087 tsig_error = tvb_get_ntohs(tvb, cur_offset);
2088 proto_tree_add_uint_format(rr_tree, hf_dns_tsig_error, tvb, cur_offset, 2, tsig_error, "Error: %s (%d)",
2089 val_to_str(tsig_error, rcode_vals,val_to_str(tsig_error, tsigerror_vals, "Unknown error")),
2096 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
2097 proto_tree_add_item(rr_tree, hf_dns_tsig_other_len, tvb, cur_offset, 2, FALSE);
2101 if (tsig_otherlen != 0) {
2102 if (rr_len < tsig_otherlen)
2104 proto_tree_add_item(rr_tree, hf_dns_tsig_other_data, tvb, cur_offset, tsig_otherlen, FALSE);
2105 cur_offset += tsig_otherlen;
2106 rr_len -= tsig_otherlen;
2114 int rr_len = data_len;
2116 guint32 lookup_timeout;
2117 guint32 cache_timeout;
2120 if (dns_tree != NULL) {
2123 local_flag = tvb_get_ntohl(tvb, cur_offset);
2124 if (dns_tree != NULL) {
2125 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
2126 local_flag ? "true" : "false");
2133 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
2134 if (dns_tree != NULL) {
2135 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
2143 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
2144 if (dns_tree != NULL) {
2145 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
2153 nservers = tvb_get_ntohl(tvb, cur_offset);
2154 if (dns_tree != NULL) {
2155 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
2161 while (rr_len != 0 && nservers != 0) {
2164 if (dns_tree != NULL) {
2165 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
2166 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
2178 int rr_len = data_len;
2180 guint32 lookup_timeout;
2181 guint32 cache_timeout;
2187 local_flag = tvb_get_ntohl(tvb, cur_offset);
2188 if (dns_tree != NULL) {
2189 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
2190 local_flag ? "true" : "false");
2197 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
2198 if (dns_tree != NULL) {
2199 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
2207 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
2208 if (dns_tree != NULL) {
2209 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
2215 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, &dname);
2216 name_out = format_text(dname, strlen(dname));
2218 col_append_fstr(cinfo, COL_INFO, " %s", name_out);
2219 if (dns_tree != NULL) {
2220 proto_item_append_text(trr, ", name result domain %s", name_out);
2221 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
2229 guint16 priority = 0;
2235 priority = tvb_get_ntohs(tvb, cur_offset);
2236 weight = tvb_get_ntohs(tvb, cur_offset+2);
2237 port = tvb_get_ntohs(tvb, cur_offset+4);
2239 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, &target);
2240 name_out = format_text(target, strlen(target));
2242 col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, name_out);
2243 if (dns_tree != NULL) {
2244 proto_item_append_text(trr,
2245 ", priority %u, weight %u, port %u, target %s",
2246 priority, weight, port, name_out);
2247 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
2248 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
2249 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
2250 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
2256 /* TODO: parse more record types */
2259 if (dns_tree != NULL)
2260 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
2264 data_offset += data_len;
2266 return data_offset - data_start;
2269 if (dns_tree != NULL) {
2270 proto_item_append_text(trr, ", bad RR length %d, too short",
2274 data_offset += data_len;
2276 return data_offset - data_start;
2280 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
2281 int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
2283 int start_off, add_off;
2284 proto_tree *qatree = NULL;
2285 proto_item *ti = NULL;
2287 start_off = cur_off;
2289 const char *s = (isupdate ? "Zone" : "Queries");
2290 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
2291 qatree = proto_item_add_subtree(ti, ett_dns_qry);
2293 while (count-- > 0) {
2294 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
2298 proto_item_set_len(ti, cur_off - start_off);
2300 return cur_off - start_off;
2304 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
2305 int count, column_info *cinfo, proto_tree *dns_tree, const char *name,
2308 int start_off, add_off;
2309 proto_tree *qatree = NULL;
2310 proto_item *ti = NULL;
2312 start_off = cur_off;
2314 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
2315 qatree = proto_item_add_subtree(ti, ett_dns_ans);
2317 while (count-- > 0) {
2318 add_off = dissect_dns_answer(
2319 tvb, cur_off, dns_data_offset, cinfo, qatree, pinfo);
2323 proto_item_set_len(ti, cur_off - start_off);
2325 return cur_off - start_off;
2329 dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2332 int offset = is_tcp ? 2 : 0;
2333 int dns_data_offset;
2335 proto_tree *dns_tree = NULL, *field_tree;
2336 proto_item *ti, *tf;
2337 guint16 id, flags, opcode, rcode, quest, ans, auth, add;
2342 conversation_t *conversation;
2343 dns_conv_info_t *dns_info;
2344 dns_transaction_t *dns_trans;
2346 dns_data_offset = offset;
2348 if (check_col(pinfo->cinfo, COL_INFO))
2349 col_clear(pinfo->cinfo, COL_INFO);
2351 #define MAX_BUF_SIZE (128+1)
2352 buf=ep_alloc(MAX_BUF_SIZE);
2356 /* To do: check for errs, etc. */
2357 id = tvb_get_ntohs(tvb, offset + DNS_ID);
2358 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
2359 opcode = (guint16) ((flags & F_OPCODE) >> OPCODE_SHIFT);
2360 rcode = (guint16) (flags & F_RCODE);
2362 if (check_col(pinfo->cinfo, COL_INFO)) {
2364 bufpos+=MIN(MAX_BUF_SIZE-bufpos,
2365 g_snprintf(buf+bufpos, MAX_BUF_SIZE-bufpos, "%s%s",
2366 val_to_str(opcode, opcode_vals, "Unknown operation (%u)"),
2367 (flags&F_RESPONSE)?" response":""));
2369 if (flags & F_RESPONSE) {
2370 if ((flags & F_RCODE) != RCODE_NOERROR) {
2371 bufpos+=MIN(MAX_BUF_SIZE-bufpos,
2372 g_snprintf(buf+bufpos, MAX_BUF_SIZE-bufpos, ", %s",
2373 val_to_str(flags & F_RCODE, rcode_vals, "Unknown error (%u)")));
2376 col_add_str(pinfo->cinfo, COL_INFO, buf);
2377 cinfo = pinfo->cinfo;
2379 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
2380 dissectors, as a way of saying that they shouldn't add stuff
2381 to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
2382 is more expensive than a check that a pointer isn't NULL). */
2385 if (opcode == OPCODE_UPDATE)
2391 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
2392 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
2394 dns_tree = proto_item_add_subtree(ti, ett_dns);
2397 * Do we have a conversation for this connection?
2399 conversation = find_conversation(pinfo->fd->num,
2400 &pinfo->src, &pinfo->dst,
2402 pinfo->srcport, pinfo->destport, 0);
2403 if (conversation == NULL) {
2404 /* We don't yet have a conversation, so create one. */
2405 conversation = conversation_new(pinfo->fd->num,
2406 &pinfo->src, &pinfo->dst,
2408 pinfo->srcport, pinfo->destport, 0);
2411 * Do we already have a state structure for this conv
2413 dns_info = conversation_get_proto_data(conversation, proto_dns);
2415 /* No. Attach that information to the conversation, and add
2416 * it to the list of information structures.
2418 dns_info = se_alloc(sizeof(dns_conv_info_t));
2419 dns_info->pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "dns_pdus");
2420 conversation_add_proto_data(conversation, proto_dns, dns_info);
2422 if(!pinfo->fd->flags.visited){
2423 if(!(flags&F_RESPONSE)){
2424 /* This is a request */
2425 dns_trans=se_alloc(sizeof(dns_transaction_t));
2426 dns_trans->req_frame=pinfo->fd->num;
2427 dns_trans->rep_frame=0;
2428 dns_trans->req_time=pinfo->fd->abs_ts;
2429 se_tree_insert32(dns_info->pdus, id, (void *)dns_trans);
2431 dns_trans=se_tree_lookup32(dns_info->pdus, id);
2433 dns_trans->rep_frame=pinfo->fd->num;
2437 dns_trans=se_tree_lookup32(dns_info->pdus, id);
2440 /* create a "fake" pana_trans structure */
2441 dns_trans=ep_alloc(sizeof(dns_transaction_t));
2442 dns_trans->req_frame=0;
2443 dns_trans->rep_frame=0;
2444 dns_trans->req_time=pinfo->fd->abs_ts;
2447 /* print state tracking in the tree */
2448 if(!(flags&F_RESPONSE)){
2449 /* This is a request */
2450 if(dns_trans->rep_frame){
2453 it=proto_tree_add_uint(dns_tree, hf_dns_response_in, tvb, 0, 0, dns_trans->rep_frame);
2454 PROTO_ITEM_SET_GENERATED(it);
2457 /* This is a reply */
2458 if(dns_trans->req_frame){
2462 it=proto_tree_add_uint(dns_tree, hf_dns_response_to, tvb, 0, 0, dns_trans->req_frame);
2463 PROTO_ITEM_SET_GENERATED(it);
2465 nstime_delta(&ns, &pinfo->fd->abs_ts, &dns_trans->req_time);
2466 it=proto_tree_add_time(dns_tree, hf_dns_time, tvb, 0, 0, &ns);
2467 PROTO_ITEM_SET_GENERATED(it);
2472 /* Put the length indication into the tree. */
2473 proto_tree_add_item(dns_tree, hf_dns_length, tvb, offset - 2, 2, FALSE);
2476 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
2477 offset + DNS_ID, 2, id);
2480 bufpos+=MIN(MAX_BUF_SIZE-bufpos,
2481 g_snprintf(buf+bufpos, MAX_BUF_SIZE-bufpos, "%s",
2482 val_to_str(opcode, opcode_vals, "Unknown operation")));
2483 if (flags & F_RESPONSE) {
2484 bufpos+=MIN(MAX_BUF_SIZE-bufpos,
2485 g_snprintf(buf+bufpos, MAX_BUF_SIZE-bufpos, " response, %s",
2486 val_to_str(flags & F_RCODE, rcode_vals, "Unknown error")));
2488 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
2489 offset + DNS_FLAGS, 2,
2491 "Flags: 0x%04x (%s)",
2493 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
2494 proto_tree_add_item(field_tree, hf_dns_flags_response,
2495 tvb, offset + DNS_FLAGS, 2, FALSE);
2496 proto_tree_add_item(field_tree, hf_dns_flags_opcode,
2497 tvb, offset + DNS_FLAGS, 2, FALSE);
2498 if (flags & F_RESPONSE) {
2499 proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
2500 tvb, offset + DNS_FLAGS, 2, FALSE);
2502 proto_tree_add_item(field_tree, hf_dns_flags_truncated,
2503 tvb, offset + DNS_FLAGS, 2, FALSE);
2504 proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
2505 tvb, offset + DNS_FLAGS, 2, FALSE);
2506 if (flags & F_RESPONSE) {
2507 proto_tree_add_item(field_tree, hf_dns_flags_recavail,
2508 tvb, offset + DNS_FLAGS, 2, FALSE);
2509 proto_tree_add_item(field_tree, hf_dns_flags_z,
2510 tvb, offset + DNS_FLAGS, 2, FALSE);
2511 proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
2512 tvb, offset + DNS_FLAGS, 2, FALSE);
2513 proto_tree_add_item(field_tree, hf_dns_flags_rcode,
2514 tvb, offset + DNS_FLAGS, 2, FALSE);
2516 proto_tree_add_item(field_tree, hf_dns_flags_z,
2517 tvb, offset + DNS_FLAGS, 2, FALSE);
2518 proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
2519 tvb, offset + DNS_FLAGS, 2, FALSE);
2522 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
2525 proto_tree_add_uint(dns_tree, hf_dns_count_zones, tvb,
2526 offset + DNS_QUEST, 2, quest);
2528 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
2529 offset + DNS_QUEST, 2, quest);
2532 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
2535 proto_tree_add_uint(dns_tree, hf_dns_count_prerequisites, tvb,
2536 offset + DNS_ANS, 2, ans);
2538 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
2539 offset + DNS_ANS, 2, ans);
2542 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
2545 proto_tree_add_uint(dns_tree, hf_dns_count_updates, tvb,
2546 offset + DNS_AUTH, 2, auth);
2548 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
2549 offset + DNS_AUTH, 2, auth);
2552 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
2554 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
2555 offset + DNS_ADD, 2, add);
2558 cur_off = offset + DNS_HDRLEN;
2561 /* If this is a response, don't add information about the queries
2562 to the summary, just add information about the answers. */
2563 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
2564 (!(flags & F_RESPONSE) ? cinfo : NULL),
2565 dns_tree, isupdate);
2569 /* If this is a request, don't add information about the answers
2570 to the summary, just add information about the queries. */
2571 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
2572 ((flags & F_RESPONSE) ? cinfo : NULL),
2573 dns_tree, (isupdate ?
2574 "Prerequisites" : "Answers"),
2578 /* Don't add information about the authoritative name servers, or the
2579 additional records, to the summary. */
2581 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
2583 (isupdate ? "Updates" :
2584 "Authoritative nameservers"),
2589 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
2590 NULL, dns_tree, "Additional records",
2596 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2598 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2599 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2601 dissect_dns_common(tvb, pinfo, tree, FALSE);
2605 dissect_mdns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2607 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2608 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDNS");
2610 dissect_dns_common(tvb, pinfo, tree, FALSE);
2615 get_dns_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
2620 * Get the length of the DNS packet.
2622 plen = tvb_get_ntohs(tvb, offset);
2625 * That length doesn't include the length field itself; add that in.
2631 dissect_dns_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2633 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2634 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2636 dissect_dns_common(tvb, pinfo, tree, TRUE);
2640 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2642 tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2, get_dns_pdu_len,
2643 dissect_dns_tcp_pdu);
2647 proto_register_dns(void)
2649 static hf_register_info hf[] = {
2651 { "Length", "dns.length",
2652 FT_UINT16, BASE_DEC, NULL, 0x0,
2653 "Length of DNS-over-TCP request or response", HFILL }},
2655 { "Flags", "dns.flags",
2656 FT_UINT16, BASE_HEX, NULL, 0x0,
2658 { &hf_dns_flags_response,
2659 { "Response", "dns.flags.response",
2660 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
2661 "Is the message a response?", HFILL }},
2662 { &hf_dns_flags_opcode,
2663 { "Opcode", "dns.flags.opcode",
2664 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
2665 "Operation code", HFILL }},
2666 { &hf_dns_flags_authoritative,
2667 { "Authoritative", "dns.flags.authoritative",
2668 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
2669 "Is the server is an authority for the domain?", HFILL }},
2670 { &hf_dns_flags_truncated,
2671 { "Truncated", "dns.flags.truncated",
2672 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
2673 "Is the message truncated?", HFILL }},
2674 { &hf_dns_flags_recdesired,
2675 { "Recursion desired", "dns.flags.recdesired",
2676 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
2677 "Do query recursively?", HFILL }},
2678 { &hf_dns_flags_recavail,
2679 { "Recursion available", "dns.flags.recavail",
2680 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
2681 "Can the server do recursive queries?", HFILL }},
2683 { "Z", "dns.flags.z",
2684 FT_BOOLEAN, 16, TFS(&tfs_flags_z), F_Z,
2686 { &hf_dns_flags_authenticated,
2687 { "Answer authenticated", "dns.flags.authenticated",
2688 FT_BOOLEAN, 16, TFS(&tfs_flags_authenticated), F_AUTHENTIC,
2689 "Was the reply data authenticated by the server?", HFILL }},
2690 { &hf_dns_flags_checkdisable,
2691 { "Non-authenticated data OK", "dns.flags.checkdisable",
2692 FT_BOOLEAN, 16, TFS(&tfs_flags_checkdisable), F_CHECKDISABLE,
2693 "Is non-authenticated data acceptable?", HFILL }},
2694 { &hf_dns_flags_rcode,
2695 { "Reply code", "dns.flags.rcode",
2696 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
2697 "Reply code", HFILL }},
2698 { &hf_dns_transaction_id,
2699 { "Transaction ID", "dns.id",
2700 FT_UINT16, BASE_HEX, NULL, 0x0,
2701 "Identification of transaction", HFILL }},
2703 { "Type", "dns.qry.type",
2704 FT_UINT16, BASE_HEX, VALS(dns_types), 0x0,
2705 "Query Type", HFILL }},
2706 { &hf_dns_qry_class,
2707 { "Class", "dns.qry.class",
2708 FT_UINT16, BASE_HEX, VALS(dns_classes), 0x0,
2709 "Query Class", HFILL }},
2711 { "Name", "dns.qry.name",
2712 FT_STRING, BASE_NONE, NULL, 0x0,
2713 "Query Name", HFILL }},
2715 { "Type", "dns.resp.type",
2716 FT_UINT16, BASE_HEX, VALS(dns_types), 0x0,
2717 "Response Type", HFILL }},
2719 { "Class", "dns.resp.class",
2720 FT_UINT16, BASE_HEX, VALS(dns_classes), 0x0,
2721 "Response Class", HFILL }},
2723 { "Name", "dns.resp.name",
2724 FT_STRING, BASE_NONE, NULL, 0x0,
2725 "Response Name", HFILL }},
2727 { "Time to live", "dns.resp.ttl",
2728 FT_UINT32, BASE_DEC, NULL, 0x0,
2729 "Response TTL", HFILL }},
2731 { "Data length", "dns.resp.len",
2732 FT_UINT32, BASE_DEC, NULL, 0x0,
2733 "Response Length", HFILL }},
2734 { &hf_dns_count_questions,
2735 { "Questions", "dns.count.queries",
2736 FT_UINT16, BASE_DEC, NULL, 0x0,
2737 "Number of queries in packet", HFILL }},
2738 { &hf_dns_count_zones,
2739 { "Zones", "dns.count.zones",
2740 FT_UINT16, BASE_DEC, NULL, 0x0,
2741 "Number of zones in packet", HFILL }},
2742 { &hf_dns_count_answers,
2743 { "Answer RRs", "dns.count.answers",
2744 FT_UINT16, BASE_DEC, NULL, 0x0,
2745 "Number of answers in packet", HFILL }},
2746 { &hf_dns_count_prerequisites,
2747 { "Prerequisites", "dns.count.prerequisites",
2748 FT_UINT16, BASE_DEC, NULL, 0x0,
2749 "Number of prerequisites in packet", HFILL }},
2750 { &hf_dns_count_auth_rr,
2751 { "Authority RRs", "dns.count.auth_rr",
2752 FT_UINT16, BASE_DEC, NULL, 0x0,
2753 "Number of authoritative records in packet", HFILL }},
2754 { &hf_dns_count_updates,
2755 { "Updates", "dns.count.updates",
2756 FT_UINT16, BASE_DEC, NULL, 0x0,
2757 "Number of updates records in packet", HFILL }},
2758 { &hf_dns_tsig_original_id,
2759 { "Original Id", "dns.tsig.original_id",
2760 FT_UINT16, BASE_DEC, NULL, 0x0,
2761 "Original Id", HFILL }},
2762 { &hf_dns_tsig_error,
2763 { "Error", "dns.tsig.error",
2764 FT_UINT16, BASE_DEC, NULL, 0x0,
2765 "Expanded RCODE for TSIG", HFILL }},
2766 { &hf_dns_tsig_fudge,
2767 { "Fudge", "dns.tsig.fudge",
2768 FT_UINT16, BASE_DEC, NULL, 0x0,
2769 "Number of bytes for the MAC", HFILL }},
2770 { &hf_dns_tsig_mac_size,
2771 { "MAC Size", "dns.tsig.mac_size",
2772 FT_UINT16, BASE_DEC, NULL, 0x0,
2773 "Number of bytes for the MAC", HFILL }},
2774 { &hf_dns_tsig_other_len,
2775 { "Other Len", "dns.tsig.other_len",
2776 FT_UINT16, BASE_DEC, NULL, 0x0,
2777 "Number of bytes for Other Data", HFILL }},
2779 { "MAC", "dns.tsig.mac",
2780 FT_NONE, BASE_NONE, NULL, 0x0,
2782 { &hf_dns_tsig_other_data,
2783 { "Other Data", "dns.tsig.other_data",
2784 FT_BYTES, BASE_HEX, NULL, 0x0,
2785 "Other Data", HFILL }},
2786 { &hf_dns_tsig_algorithm_name,
2787 { "Algorithm Name", "dns.tsig.algorithm_name",
2788 FT_STRING, BASE_NONE, NULL, 0x0,
2789 "Name of algorithm used for the MAC", HFILL }},
2790 { &hf_dns_response_in,
2791 { "Response In", "dns.response_in",
2792 FT_FRAMENUM, BASE_DEC, NULL, 0x0,
2793 "The response to this DNS query is in this frame", HFILL }},
2794 { &hf_dns_response_to,
2795 { "Request In", "dns.response_to",
2796 FT_FRAMENUM, BASE_DEC, NULL, 0x0,
2797 "This is a response to the DNS query in this frame", HFILL }},
2799 { "Time", "dns.time",
2800 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
2801 "The time between the Query and the Response", HFILL }},
2802 { &hf_dns_count_add_rr,
2803 { "Additional RRs", "dns.count.add_rr",
2804 FT_UINT16, BASE_DEC, NULL, 0x0,
2805 "Number of additional records in packet", HFILL }}
2807 static gint *ett[] = {
2818 module_t *dns_module;
2820 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2821 proto_register_field_array(proto_dns, hf, array_length(hf));
2822 proto_register_subtree_array(ett, array_length(ett));
2824 dns_module = prefs_register_protocol(proto_dns, NULL);
2825 prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2826 "Reassemble DNS messages spanning multiple TCP segments",
2827 "Whether the DNS dissector should reassemble messages spanning multiple TCP segments."
2828 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2831 dns_tsig_dissector_table = register_dissector_table("dns.tsig.mac", "DNS TSIG MAC Dissectors", FT_STRING, BASE_NONE);
2835 proto_reg_handoff_dns(void)
2837 dissector_handle_t dns_udp_handle;
2838 dissector_handle_t dns_tcp_handle;
2839 dissector_handle_t mdns_udp_handle;
2841 dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
2842 dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
2843 mdns_udp_handle = create_dissector_handle(dissect_mdns_udp, proto_dns);
2845 dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
2846 dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
2847 dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
2848 dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
2850 gssapi_handle = find_dissector("gssapi");
2851 ntlmssp_handle = find_dissector("ntlmssp");