2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.103 2003/05/24 21:05:36 gerald Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #ifdef NEED_SNPRINTF_H
34 # include "snprintf.h"
38 #include <epan/packet.h>
40 #include <epan/resolv.h>
41 #include "packet-dns.h"
42 #include "packet-tcp.h"
45 static int proto_dns = -1;
46 static int hf_dns_length = -1;
47 static int hf_dns_flags = -1;
48 static int hf_dns_flags_response = -1;
49 static int hf_dns_flags_opcode = -1;
50 static int hf_dns_flags_authoritative = -1;
51 static int hf_dns_flags_truncated = -1;
52 static int hf_dns_flags_recdesired = -1;
53 static int hf_dns_flags_recavail = -1;
54 static int hf_dns_flags_z = -1;
55 static int hf_dns_flags_authenticated = -1;
56 static int hf_dns_flags_checkdisable = -1;
57 static int hf_dns_flags_rcode = -1;
58 static int hf_dns_transaction_id = -1;
59 static int hf_dns_count_questions = -1;
60 static int hf_dns_count_answers = -1;
61 static int hf_dns_count_auth_rr = -1;
62 static int hf_dns_count_add_rr = -1;
64 static gint ett_dns = -1;
65 static gint ett_dns_qd = -1;
66 static gint ett_dns_rr = -1;
67 static gint ett_dns_qry = -1;
68 static gint ett_dns_ans = -1;
69 static gint ett_dns_flags = -1;
70 static gint ett_t_key_flags = -1;
71 static gint ett_t_key = -1;
73 /* desegmentation of DNS over TCP */
74 static gboolean dns_desegment = TRUE;
76 /* Dissector handle for GSSAPI */
77 static dissector_handle_t gssapi_handle;
79 /* DNS structs and definitions */
81 /* Ports used for DNS. */
82 #define UDP_PORT_DNS 53
83 #define TCP_PORT_DNS 53
84 #define UDP_PORT_MDNS 5353
85 #define TCP_PORT_MDNS 5353
87 /* Offsets of fields in the DNS header. */
95 /* Length of DNS header. */
99 #define T_A 1 /* host address */
100 #define T_NS 2 /* authoritative name server */
101 #define T_MD 3 /* mail destination (obsolete) */
102 #define T_MF 4 /* mail forwarder (obsolete) */
103 #define T_CNAME 5 /* canonical name */
104 #define T_SOA 6 /* start of authority zone */
105 #define T_MB 7 /* mailbox domain name (experimental) */
106 #define T_MG 8 /* mail group member (experimental) */
107 #define T_MR 9 /* mail rename domain name (experimental) */
108 #define T_NULL 10 /* null RR (experimental) */
109 #define T_WKS 11 /* well known service */
110 #define T_PTR 12 /* domain name pointer */
111 #define T_HINFO 13 /* host information */
112 #define T_MINFO 14 /* mailbox or mail list information */
113 #define T_MX 15 /* mail routing information */
114 #define T_TXT 16 /* text strings */
115 #define T_RP 17 /* responsible person (RFC 1183) */
116 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
117 #define T_X25 19 /* X.25 address (RFC 1183) */
118 #define T_ISDN 20 /* ISDN address (RFC 1183) */
119 #define T_RT 21 /* route-through (RFC 1183) */
120 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
121 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
122 #define T_SIG 24 /* digital signature (RFC 2535) */
123 #define T_KEY 25 /* public key (RFC 2535) */
124 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
125 #define T_GPOS 27 /* geographical position (RFC 1712) */
126 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
127 #define T_LOC 29 /* geographical location (RFC 1876) */
128 #define T_NXT 30 /* "next" name (RFC 2535) */
129 #define T_EID 31 /* ??? (Nimrod?) */
130 #define T_NIMLOC 32 /* ??? (Nimrod?) */
131 #define T_SRV 33 /* service location (RFC 2052) */
132 #define T_ATMA 34 /* ??? */
133 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
134 #define T_KX 36 /* Key Exchange (RFC 2230) */
135 #define T_CERT 37 /* Certificate (RFC 2538) */
136 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
137 #define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
138 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
139 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
140 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
141 #define T_WINS 65281 /* Microsoft's WINS RR */
142 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
145 #define C_IN 1 /* the Internet */
146 #define C_CS 2 /* CSNET (obsolete) */
147 #define C_CH 3 /* CHAOS */
148 #define C_HS 4 /* Hesiod */
149 #define C_NONE 254 /* none */
150 #define C_ANY 255 /* any */
151 #define C_FLUSH (1<<15) /* High bit is set for MDNS cache flush */
153 /* Bit fields in the flags */
154 #define F_RESPONSE (1<<15) /* packet is response */
155 #define F_OPCODE (0xF<<11) /* query opcode */
156 #define OPCODE_SHIFT 11
157 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
158 #define F_TRUNCATED (1<<9) /* response is truncated */
159 #define F_RECDESIRED (1<<8) /* recursion desired */
160 #define F_RECAVAIL (1<<7) /* recursion available */
161 #define F_Z (1<<6) /* Z */
162 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
163 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
164 #define F_RCODE (0xF<<0) /* reply code */
166 static const true_false_string tfs_flags_response = {
167 "Message is a response",
171 static const true_false_string tfs_flags_authoritative = {
172 "Server is an authority for domain",
173 "Server is not an authority for domain"
176 static const true_false_string tfs_flags_truncated = {
177 "Message is truncated",
178 "Message is not truncated"
181 static const true_false_string tfs_flags_recdesired = {
182 "Do query recursively",
183 "Don't do query recursively"
186 static const true_false_string tfs_flags_recavail = {
187 "Server can do recursive queries",
188 "Server can't do recursive queries"
191 static const true_false_string tfs_flags_z = {
192 "reserved - incorrect!",
196 static const true_false_string tfs_flags_authenticated = {
197 "Answer/authority portion was authenticated by the server",
198 "Answer/authority portion was not authenticated by the server"
201 static const true_false_string tfs_flags_checkdisable = {
202 "Non-authenticated data is acceptable",
203 "Non-authenticated data is unacceptable"
207 #define OPCODE_QUERY 0 /* standard query */
208 #define OPCODE_IQUERY 1 /* inverse query */
209 #define OPCODE_STATUS 2 /* server status request */
210 #define OPCODE_NOTIFY 4 /* zone change notification */
211 #define OPCODE_UPDATE 5 /* dynamic update */
213 static const value_string opcode_vals[] = {
214 { OPCODE_QUERY, "Standard query" },
215 { OPCODE_IQUERY, "Inverse query" },
216 { OPCODE_STATUS, "Server status request" },
217 { OPCODE_NOTIFY, "Zone change notification" },
218 { OPCODE_UPDATE, "Dynamic update" },
222 #define RCODE_NOERROR 0
223 #define RCODE_FORMERR 1
224 #define RCODE_SERVFAIL 2
225 #define RCODE_NXDOMAIN 3
226 #define RCODE_NOTIMPL 4
227 #define RCODE_REFUSED 5
228 #define RCODE_YXDOMAIN 6
229 #define RCODE_YXRRSET 7
230 #define RCODE_NXRRSET 8
231 #define RCODE_NOTAUTH 9
232 #define RCODE_NOTZONE 10
234 static const value_string rcode_vals[] = {
235 { RCODE_NOERROR, "No error" },
236 { RCODE_FORMERR, "Format error" },
237 { RCODE_SERVFAIL, "Server failure" },
238 { RCODE_NXDOMAIN, "No such name" },
239 { RCODE_NOTIMPL, "Not implemented" },
240 { RCODE_REFUSED, "Refused" },
241 { RCODE_YXDOMAIN, "Name exists" },
242 { RCODE_YXRRSET, "RRset exists" },
243 { RCODE_NXRRSET, "RRset does not exist" },
244 { RCODE_NOTAUTH, "Not authoritative" },
245 { RCODE_NOTZONE, "Name out of zone" },
248 /* TSIG/TKEY extended errors */
249 #define TSIGERROR_BADSIG (16)
250 #define TSIGERROR_BADKEY (17)
251 #define TSIGERROR_BADTIME (18)
252 #define TSIGERROR_BADMODE (19)
253 #define TSIGERROR_BADNAME (20)
254 #define TSIGERROR_BADALG (21)
256 static const value_string tsigerror_vals[] = {
257 { TSIGERROR_BADSIG, "Bad signature" },
258 { TSIGERROR_BADKEY, "Bad key" },
259 { TSIGERROR_BADTIME, "Bad time failure" },
260 { TSIGERROR_BADMODE, "Bad mode such name" },
261 { TSIGERROR_BADNAME, "Bad name implemented" },
262 { TSIGERROR_BADALG, "Bad algorithm" },
265 #define TKEYMODE_SERVERASSIGNED (1)
266 #define TKEYMODE_DIFFIEHELLMAN (2)
267 #define TKEYMODE_GSSAPI (3)
268 #define TKEYMODE_RESOLVERASSIGNED (4)
269 #define TKEYMODE_DELETE (5)
271 /* See RFC 1035 for all RR types for which no RFC is listed, except for
272 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
273 which one should look at
275 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
279 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
281 which discuss them to some extent. */
283 dns_type_name (guint type)
285 char *type_names[] = {
304 "AFSDB", /* RFC 1183 */
305 "X25", /* RFC 1183 */
306 "ISDN", /* RFC 1183 */
308 "NSAP", /* RFC 1706 */
309 "NSAP-PTR", /* RFC 1348 */
310 "SIG", /* RFC 2535 */
311 "KEY", /* RFC 2535 */
313 "GPOS", /* RFC 1712 */
314 "AAAA", /* RFC 1886 */
315 "LOC", /* RFC 1876 */
316 "NXT", /* RFC 2535 */
319 "SRV", /* RFC 2052 */
321 "NAPTR", /* RFC 2168 */
323 "CERT", /* RFC 2538 */
325 "DNAME", /* RFC 2672 */
330 if (type < sizeof(type_names)/sizeof(type_names[0]))
331 return type_names[type] ? type_names[type] : "unknown";
358 return "IXFR"; /* RFC 1995 */
375 dns_long_type_name (guint type)
377 char *type_names[] = {
380 "Authoritative name server",
383 "Canonical name for an alias",
384 "Start of zone of authority",
385 "Mailbox domain name",
387 "Mail rename domain name",
388 "Null resource record",
389 "Well-known service description",
390 "Domain name pointer",
392 "Mailbox or mail list information",
395 "Responsible person", /* RFC 1183 */
396 "AFS data base location", /* RFC 1183 */
397 "X.25 address", /* RFC 1183 */
398 "ISDN number", /* RFC 1183 */
399 "Route through", /* RFC 1183 */
400 "OSI NSAP", /* RFC 1706 */
401 "OSI NSAP name pointer", /* RFC 1348 */
402 "Signature", /* RFC 2535 */
403 "Public key", /* RFC 2535 */
404 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
405 "Geographical position", /* RFC 1712 */
406 "IPv6 address", /* RFC 1886 */
407 "Location", /* RFC 1876 */
408 "Next", /* RFC 2535 */
411 "Service location", /* RFC 2052 */
413 "Naming authority pointer", /* RFC 2168 */
414 "Key Exchange", /* RFC 2230 */
415 "Certificate", /* RFC 2538 */
416 "IPv6 address with indirection", /* RFC 2874 */
417 "Non-terminal DNS name redirection", /* RFC 2672 */
419 "EDNS0 option" /* RFC 2671 */
421 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%u)" */
423 if (type < sizeof(type_names)/sizeof(type_names[0]))
424 return type_names[type] ? type_names[type] : "unknown";
445 return "Transaction Key";
447 return "Transaction Signature";
451 return "Request for incremental zone transfer"; /* RFC 1995 */
453 return "Request for full zone transfer";
455 return "Request for mailbox-related records";
457 return "Request for mail agent resource records";
459 return "Request for all records";
462 sprintf(unkbuf, "Unknown RR type (%u)", type);
468 dns_class_name(int class)
476 case ( C_IN | C_FLUSH ):
477 class_name = "inet (data flush)";
480 class_name = "csnet";
483 class_name = "chaos";
486 class_name = "hesiod";
495 class_name = "unknown";
502 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
503 char *name, int maxname)
505 int start_offset = offset;
508 int chars_processed = 0;
509 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
513 const int min_len = 1; /* Minimum length of encoded name (for root) */
514 /* If we're about to return a value (probably negative) which is less
515 * than the minimum length, we're looking at bad data and we're liable
516 * to put the dissector into a loop. Instead we throw an exception */
518 maxname--; /* reserve space for the trailing '\0' */
520 component_len = tvb_get_guint8(tvb, offset);
522 if (component_len == 0)
525 switch (component_len & 0xc0) {
530 /* Not the first component - put in a '.'. */
536 while (component_len > 0) {
538 *np++ = tvb_get_guint8(tvb, offset);
548 /* Extended label (RFC 2673) */
549 switch (component_len & 0x3f) {
552 /* Bitstring label */
558 bit_count = tvb_get_guint8(tvb, offset);
560 label_len = (bit_count - 1) / 8 + 1;
563 print_len = snprintf(np, maxname + 1, "\\[x");
564 if (print_len != -1 && print_len <= maxname) {
565 /* Some versions of snprintf return -1 if they'd truncate
566 the output. Others return <buf_size> or greater. */
568 maxname -= print_len;
570 /* Nothing printed, as there's no room.
571 Suppress all subsequent printing. */
577 print_len = snprintf(np, maxname + 1, "%02x",
578 tvb_get_guint8(tvb, offset));
579 if (print_len != -1 && print_len <= maxname) {
580 /* Some versions of snprintf return -1 if they'd truncate
581 the output. Others return <buf_size> or greater. */
583 maxname -= print_len;
585 /* Nothing printed, as there's no room.
586 Suppress all subsequent printing. */
593 print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
594 if (print_len != -1 && print_len <= maxname) {
595 /* Some versions of snprintf return -1 if they'd truncate
596 the output. Others return <buf_size> or greater. */
598 maxname -= print_len;
600 /* Nothing printed, as there's no room.
601 Suppress all subsequent printing. */
609 strcpy(name, "<Unknown extended label>");
610 /* Parsing will propably fail from here on, since the */
611 /* label length is unknown... */
612 len = offset - start_offset;
614 THROW(ReportedBoundsError);
620 THROW(ReportedBoundsError);
624 indir_offset = dns_data_offset +
625 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
629 /* If "len" is negative, we are still working on the original name,
630 not something pointed to by a pointer, and so we should set "len"
631 to the length of the original name. */
633 len = offset - start_offset;
635 /* If we've looked at every character in the message, this pointer
636 will make us look at some character again, which means we're
638 if (chars_processed >= data_size) {
639 strcpy(name, "<Name contains a pointer that loops>");
641 THROW(ReportedBoundsError);
645 offset = indir_offset;
646 break; /* now continue processing from there */
651 /* If "len" is negative, we haven't seen a pointer, and thus haven't
652 set the length, so set it. */
654 len = offset - start_offset;
655 /* Zero-length name means "root server" */
657 strcpy(name, "<Root>");
659 THROW(ReportedBoundsError);
665 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
666 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
673 int start_offset = offset;
675 name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
678 type = tvb_get_ntohs(tvb, offset);
681 class = tvb_get_ntohs(tvb, offset);
684 strcpy (name_ret, name);
687 *name_len_ret = name_len;
689 len = offset - start_offset;
694 rfc1867_size(tvbuff_t *tvb, int offset)
700 val = tvb_get_guint8(tvb, offset);
701 size = (val & 0xF0) >> 4;
702 exponent = (val & 0x0F);
703 while (exponent != 0) {
707 return size / 100; /* return size in meters, not cm */
711 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
715 guint32 degrees, minutes, secs, tsecs;
716 /* "%u deg %u min %u.%03u sec %c" */
717 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
719 angle = tvb_get_ntohl(tvb, offset);
721 if (angle < 0x80000000U) {
722 angle = 0x80000000U - angle;
725 angle = angle - 0x80000000U;
728 tsecs = angle % 1000;
729 angle = angle / 1000;
732 minutes = angle % 60;
733 degrees = angle / 60;
734 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
740 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
741 column_info *cinfo, proto_tree *dns_tree)
750 char *long_type_name;
756 data_start = data_offset = offset;
758 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
762 type_name = dns_type_name(type);
763 class_name = dns_class_name(class);
764 long_type_name = dns_long_type_name(type);
767 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
768 if (dns_tree != NULL) {
769 tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
770 name, type_name, class_name);
771 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
773 proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
776 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
779 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
783 return data_offset - data_start;
788 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
789 const char *name, int namelen, const char *type_name, const char *class_name,
790 guint ttl, gushort data_len)
794 rr_tree = proto_item_add_subtree(trr, rr_type);
795 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
797 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
799 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
801 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
802 time_secs_to_str(ttl));
804 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
809 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
810 const char *name, int namelen, const char *type_name, int class,
811 guint ttl, gushort data_len)
813 proto_tree *rr_tree, *Z_tree;
814 proto_item *Z_item = NULL;
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, "UDP payload size: %u",
824 proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
825 (ttl >> 24) & 0xff0);
827 proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
830 Z_item = proto_tree_add_text(rr_tree, tvb, offset, 2, "Z: 0x%x", ttl & 0xffff);
832 Z_tree = proto_item_add_subtree(Z_item, rr_type);
833 proto_tree_add_text(Z_tree, tvb, offset, 2, "Bit 0 (DO bit): 1 (Accepts DNSSEC security RRs)");
834 proto_tree_add_text(Z_tree, tvb, offset, 2, "Bits 1-15: 0x%x (reserved)", (ttl >> 17) & 0xff);
837 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
842 * SIG, KEY, and CERT RR algorithms.
844 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
845 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
846 #define DNS_ALGO_DSA 3 /* DSA */
847 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
848 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
849 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
850 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
852 static const value_string algo_vals[] = {
853 { DNS_ALGO_RSAMD5, "RSA/MD5" },
854 { DNS_ALGO_DH, "Diffie-Hellman" },
855 { DNS_ALGO_DSA, "DSA" },
856 { DNS_ALGO_ECC, "Elliptic curve crypto" },
857 { DNS_ALGO_INDIRECT, "Indirect key" },
858 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
859 { DNS_ALGO_PRIVATEOID, "Private, OID" },
863 #define DNS_CERT_PGP 1 /* PGP */
864 #define DNS_CERT_PKIX 2 /* PKIX */
865 #define DNS_CERT_SPKI 3 /* SPKI */
866 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
867 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
869 static const value_string cert_vals[] = {
870 { DNS_CERT_PGP, "PGP" },
871 { DNS_CERT_PKIX, "PKIX" },
872 { DNS_CERT_SPKI, "SPKI" },
873 { DNS_CERT_PRIVATEURI, "Private, URI" },
874 { DNS_CERT_PRIVATEOID, "Private, OID" },
879 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
880 column_info *cinfo, proto_tree *dns_tree, packet_info *pinfo)
889 char *long_type_name;
895 proto_tree *rr_tree = NULL;
896 proto_item *trr = NULL;
898 data_start = data_offset = offset;
901 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
906 type_name = dns_type_name(type);
907 class_name = dns_class_name(class);
908 long_type_name = dns_long_type_name(type);
910 ttl = tvb_get_ntohl(tvb, data_offset);
914 data_len = tvb_get_ntohs(tvb, data_offset);
919 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
920 if (dns_tree != NULL) {
921 trr = proto_tree_add_text(dns_tree, tvb, offset,
922 (data_offset - data_start) + data_len,
923 "%s: type %s, class %s",
924 name, type_name, class_name);
926 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
927 long_type_name, class_name, ttl, data_len);
929 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
930 long_type_name, class, ttl, data_len);
941 addr = tvb_get_ptr(tvb, cur_offset, 4);
943 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
944 if (dns_tree != NULL) {
945 proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
946 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
949 if ((class & 0x7f) == C_IN) {
950 memcpy(&addr_int, addr, sizeof(addr_int));
951 add_host_name(addr_int, name);
958 char ns_name[MAXDNAME];
961 ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
963 col_append_fstr(cinfo, COL_INFO, " %s", ns_name);
964 if (dns_tree != NULL) {
965 proto_item_append_text(trr, ", ns %s", ns_name);
966 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
974 char cname[MAXDNAME];
977 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
979 col_append_fstr(cinfo, COL_INFO, " %s", cname);
980 if (dns_tree != NULL) {
981 proto_item_append_text(trr, ", cname %s", cname);
982 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
990 char mname[MAXDNAME];
992 char rname[MAXDNAME];
1000 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
1002 col_append_fstr(cinfo, COL_INFO, " %s", mname);
1003 if (dns_tree != NULL) {
1004 proto_item_append_text(trr, ", mname %s", mname);
1005 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
1007 cur_offset += mname_len;
1009 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
1010 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
1012 cur_offset += rname_len;
1014 serial = tvb_get_ntohl(tvb, cur_offset);
1015 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
1019 refresh = tvb_get_ntohl(tvb, cur_offset);
1020 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
1021 time_secs_to_str(refresh));
1024 retry = tvb_get_ntohl(tvb, cur_offset);
1025 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
1026 time_secs_to_str(retry));
1029 expire = tvb_get_ntohl(tvb, cur_offset);
1030 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
1031 time_secs_to_str(expire));
1034 minimum = tvb_get_ntohl(tvb, cur_offset);
1035 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
1036 time_secs_to_str(minimum));
1043 char pname[MAXDNAME];
1046 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
1048 col_append_fstr(cinfo, COL_INFO, " %s", pname);
1049 if (dns_tree != NULL) {
1050 proto_item_append_text(trr, ", %s", pname);
1051 proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
1060 int rr_len = data_len;
1061 const guint8 *wks_addr;
1067 static GString *bitnames = NULL;
1069 if (bitnames == NULL)
1070 bitnames = g_string_sized_new(128);
1072 wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
1074 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
1075 if (dns_tree != NULL) {
1076 proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
1077 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
1078 ip_to_str(wks_addr));
1082 protocol = tvb_get_guint8(tvb, cur_offset);
1083 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
1084 ipprotostr(protocol));
1089 while (rr_len != 0) {
1090 bits = tvb_get_guint8(tvb, cur_offset);
1093 g_string_truncate(bitnames, 0);
1094 for (i = 0; i < 8; i++) {
1096 if (bitnames->len != 0)
1097 g_string_append(bitnames, ", ");
1101 g_string_append(bitnames, get_tcp_port(port_num));
1105 g_string_append(bitnames, get_udp_port(port_num));
1109 g_string_sprintfa(bitnames, "%u", port_num);
1116 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1117 "Bits: 0x%02x (%s)", bits, bitnames->str);
1136 cpu_offset = cur_offset;
1137 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1138 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1139 os_offset = cpu_offset + 1 + cpu_len;
1140 os_len = tvb_get_guint8(tvb, os_offset);
1141 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1143 col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1145 if (dns_tree != NULL) {
1146 proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1147 cpu_len, cpu, os_len, os);
1148 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1150 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1159 guint16 preference = 0;
1160 char mx_name[MAXDNAME];
1163 preference = tvb_get_ntohs(tvb, cur_offset);
1164 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1166 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, mx_name);
1167 if (dns_tree != NULL) {
1168 proto_item_append_text(trr, ", preference %u, mx %s",
1169 preference, mx_name);
1170 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1171 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1179 int rr_len = data_len;
1183 if (dns_tree != NULL) {
1184 txt_offset = cur_offset;
1185 while (rr_len != 0) {
1186 txt_len = tvb_get_guint8(tvb, txt_offset);
1187 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1188 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1189 txt_offset += 1 + txt_len;
1190 rr_len -= 1 + txt_len;
1198 int rr_len = data_len;
1199 guint16 type_covered;
1201 char signer_name[MAXDNAME];
1202 int signer_name_len;
1204 if (dns_tree != NULL) {
1205 type_covered = tvb_get_ntohs(tvb, cur_offset);
1206 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1207 dns_type_name(type_covered),
1208 dns_long_type_name(type_covered));
1212 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1213 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1214 "Unknown (0x%02X)"));
1218 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1219 tvb_get_guint8(tvb, cur_offset));
1223 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1224 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1228 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1230 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1231 abs_time_to_str(&nstime));
1235 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1237 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1238 abs_time_to_str(&nstime));
1242 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1243 tvb_get_ntohs(tvb, cur_offset));
1247 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1248 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1249 "Signer's name: %s", signer_name);
1250 cur_offset += signer_name_len;
1251 rr_len -= signer_name_len;
1253 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1260 int rr_len = data_len;
1263 proto_tree *flags_tree;
1265 if (dns_tree != NULL) {
1266 flags = tvb_get_ntohs(tvb, cur_offset);
1267 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1268 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1269 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1270 decode_boolean_bitfield(flags, 0x8000,
1271 2*8, "Key prohibited for authentication",
1272 "Key allowed for authentication"));
1273 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1274 decode_boolean_bitfield(flags, 0x4000,
1275 2*8, "Key prohibited for confidentiality",
1276 "Key allowed for confidentiality"));
1277 if ((flags & 0xC000) != 0xC000) {
1279 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1280 decode_boolean_bitfield(flags, 0x2000,
1281 2*8, "Key is experimental or optional",
1282 "Key is required"));
1283 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1284 decode_boolean_bitfield(flags, 0x0400,
1285 2*8, "Key is associated with a user",
1286 "Key is not associated with a user"));
1287 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1288 decode_boolean_bitfield(flags, 0x0200,
1289 2*8, "Key is associated with the named entity",
1290 "Key is not associated with the named entity"));
1291 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1292 decode_boolean_bitfield(flags, 0x0100,
1293 2*8, "This is the zone key for the specified zone",
1294 "This is not a zone key"));
1295 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1296 decode_boolean_bitfield(flags, 0x0080,
1297 2*8, "Key is valid for use with IPSEC",
1298 "Key is not valid for use with IPSEC"));
1299 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1300 decode_boolean_bitfield(flags, 0x0040,
1301 2*8, "Key is valid for use with MIME security multiparts",
1302 "Key is not valid for use with MIME security multiparts"));
1303 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1304 decode_numeric_bitfield(flags, 0x000F,
1305 2*8, "Signatory = %u"));
1310 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1311 tvb_get_guint8(tvb, cur_offset));
1315 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1316 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1317 "Unknown (0x%02X)"));
1321 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1328 const guint8 *addr6;
1330 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1331 if (cinfo != NULL) {
1332 col_append_fstr(cinfo, COL_INFO, " %s",
1333 ip6_to_str((const struct e_in6_addr *)addr6));
1335 if (dns_tree != NULL) {
1336 proto_item_append_text(trr, ", addr %s",
1337 ip6_to_str((const struct e_in6_addr *)addr6));
1338 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1339 ip6_to_str((const struct e_in6_addr *)addr6));
1346 unsigned short pre_len;
1347 unsigned short suf_len;
1348 unsigned short suf_octet_count;
1349 char pname[MAXDNAME];
1355 a6_offset = cur_offset;
1356 pre_len = tvb_get_guint8(tvb, cur_offset);
1358 suf_len = 128 - pre_len;
1359 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1361 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1362 suffix[suf_offset] = 0;
1364 for (; suf_offset < 16; suf_offset++) {
1365 suffix[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1370 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1371 pname, sizeof(pname));
1377 if (cinfo != NULL) {
1378 col_append_fstr(cinfo, COL_INFO, " %d %s %s",
1380 ip6_to_str((struct e_in6_addr *)&suffix),
1383 if (dns_tree != NULL) {
1384 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1385 "Prefix len: %u", pre_len);
1388 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1389 "Address suffix: %s",
1390 ip6_to_str((struct e_in6_addr *)&suffix));
1391 a6_offset += suf_octet_count;
1394 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1395 "Prefix name: %s", pname);
1397 proto_item_append_text(trr, ", addr %d %s %s",
1399 ip6_to_str((struct e_in6_addr *)&suffix),
1407 char dname[MAXDNAME];
1410 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1411 dname, sizeof(dname));
1413 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1414 if (dns_tree != NULL) {
1415 proto_item_append_text(trr, ", dname %s", dname);
1416 proto_tree_add_text(rr_tree, tvb, cur_offset,
1417 dname_len, "Target name: %s", dname);
1426 if (dns_tree != NULL) {
1427 version = tvb_get_guint8(tvb, cur_offset);
1428 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1430 /* Version 0, the only version RFC 1876 discusses. */
1433 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1434 rfc1867_size(tvb, cur_offset));
1437 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1438 rfc1867_size(tvb, cur_offset));
1441 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1442 rfc1867_size(tvb, cur_offset));
1445 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1446 rfc1867_angle(tvb, cur_offset, "NS"));
1449 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1450 rfc1867_angle(tvb, cur_offset, "EW"));
1453 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1454 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1456 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1464 int rr_len = data_len;
1465 char next_domain_name[MAXDNAME];
1466 int next_domain_name_len;
1472 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1473 next_domain_name, sizeof(next_domain_name));
1475 col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
1476 if (dns_tree != NULL) {
1477 proto_item_append_text(trr, ", next domain name %s",
1479 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1480 "Next domain name: %s", next_domain_name);
1481 cur_offset += next_domain_name_len;
1482 rr_len -= next_domain_name_len;
1484 while (rr_len != 0) {
1485 bits = tvb_get_guint8(tvb, cur_offset);
1487 for (i = 0; i < 8; i++) {
1489 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1490 "RR type in bit map: %s (%s)",
1491 dns_type_name(rr_type),
1492 dns_long_type_name(rr_type));
1506 guint16 preference = 0;
1507 char kx_name[MAXDNAME];
1510 preference = tvb_get_ntohs(tvb, cur_offset);
1511 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1513 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, kx_name);
1514 if (dns_tree != NULL) {
1515 proto_item_append_text(trr, ", preference %u, kx %s",
1516 preference, kx_name);
1517 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1518 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1526 guint16 cert_type, cert_keytag;
1528 int rr_len = data_len;
1530 cert_type = tvb_get_ntohs(tvb, cur_offset);
1533 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1536 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1540 if (dns_tree != NULL) {
1541 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s",
1542 val_to_str(cert_keyalg, cert_vals,
1543 "Unknown (0x%02X)"));
1544 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1546 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1547 val_to_str(cert_keyalg, algo_vals,
1548 "Unknown (0x%02X)"));
1549 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1556 if (dns_tree != NULL)
1557 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1562 char tkey_algname[MAXDNAME];
1563 int tkey_algname_len;
1564 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1565 int rr_len = data_len;
1567 static const value_string tkey_modes[] = {
1568 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1569 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1570 { TKEYMODE_GSSAPI, "GSSAPI" },
1571 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1572 { TKEYMODE_DELETE, "Delete" },
1575 if (dns_tree != NULL) {
1576 proto_tree *key_tree;
1577 proto_item *key_item;
1579 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1580 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1581 "Algorithm name: %s", tkey_algname);
1582 cur_offset += tkey_algname_len;
1583 rr_len -= tkey_algname_len;
1585 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1587 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1588 abs_time_to_str(&nstime));
1592 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1594 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1595 abs_time_to_str(&nstime));
1599 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1602 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Mode: %s",
1603 val_to_str(tkey_mode, tkey_modes,
1604 "Unknown (0x%04X)"));
1606 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1609 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1610 val_to_str(tkey_error, rcode_vals,
1611 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1613 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1617 key_item = proto_tree_add_text(
1618 rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1620 key_tree = proto_item_add_subtree(key_item, ett_t_key);
1623 case TKEYMODE_GSSAPI: {
1624 tvbuff_t *gssapi_tvb;
1627 * XXX - in at least one capture, this appears to
1628 * be an NTLMSSP blob, with no ASN.1 in it, in
1633 * http://www.alternic.org/drafts/drafts-s-t/draft-skwan-gss-tsig-05.html
1635 * which might indicate what's going on here. (The key
1636 * is an output_token from GSS_Init_sec_context.)
1638 * How the heck do we know what method is being used,
1639 * so we know how to decode the key?
1641 gssapi_tvb = tvb_new_subset(
1642 tvb, cur_offset, tkey_keylen, tkey_keylen);
1644 call_dissector(gssapi_handle, gssapi_tvb, pinfo, key_tree);
1650 /* No dissector for this key mode */
1655 cur_offset += tkey_keylen;
1656 rr_len -= tkey_keylen;
1658 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1662 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1663 cur_offset += tkey_otherlen;
1664 rr_len -= tkey_otherlen;
1672 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1673 guint32 tsig_timelo;
1674 char tsig_algname[MAXDNAME];
1675 int tsig_algname_len;
1677 int rr_len = data_len;
1679 if (dns_tree != NULL) {
1680 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1681 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1682 "Algorithm name: %s", tsig_algname);
1683 cur_offset += tsig_algname_len;
1684 rr_len -= tsig_algname_len;
1686 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1687 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1688 nstime.secs = tsig_timelo;
1690 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1691 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
1695 tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1696 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1701 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1705 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1706 cur_offset += tsig_siglen;
1707 rr_len -= tsig_siglen;
1709 tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1710 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1715 tsig_error = tvb_get_ntohs(tvb, cur_offset);
1716 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1717 val_to_str(tsig_error, rcode_vals,
1718 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1722 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1726 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1727 cur_offset += tsig_otherlen;
1728 rr_len -= tsig_otherlen;
1735 int rr_len = data_len;
1737 guint32 lookup_timeout;
1738 guint32 cache_timeout;
1741 if (dns_tree != NULL) {
1742 local_flag = tvb_get_ntohl(tvb, cur_offset);
1743 if (dns_tree != NULL) {
1744 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1745 local_flag ? "true" : "false");
1750 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1751 if (dns_tree != NULL) {
1752 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1758 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1759 if (dns_tree != NULL) {
1760 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1766 nservers = tvb_get_ntohl(tvb, cur_offset);
1767 if (dns_tree != NULL) {
1768 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
1774 while (rr_len != 0 && nservers != 0) {
1775 if (dns_tree != NULL) {
1776 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
1777 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
1789 int rr_len = data_len;
1791 guint32 lookup_timeout;
1792 guint32 cache_timeout;
1793 char dname[MAXDNAME];
1796 local_flag = tvb_get_ntohl(tvb, cur_offset);
1797 if (dns_tree != NULL) {
1798 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1799 local_flag ? "true" : "false");
1804 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1805 if (dns_tree != NULL) {
1806 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1812 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1813 if (dns_tree != NULL) {
1814 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1820 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1822 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1823 if (dns_tree != NULL) {
1824 proto_item_append_text(trr, ", name result domain %s", dname);
1825 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
1833 guint16 priority = 0;
1836 char target[MAXDNAME];
1839 priority = tvb_get_ntohs(tvb, cur_offset);
1840 weight = tvb_get_ntohs(tvb, cur_offset+2);
1841 port = tvb_get_ntohs(tvb, cur_offset+4);
1843 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1845 col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, target);
1846 if (dns_tree != NULL) {
1847 proto_item_append_text(trr,
1848 ", priority %u, weight %u, port %u, target %s",
1849 priority, weight, port, target);
1850 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
1851 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
1852 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
1853 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
1859 /* TODO: parse more record types */
1862 if (dns_tree != NULL)
1863 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1867 data_offset += data_len;
1869 return data_offset - data_start;
1873 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1874 int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
1876 int start_off, add_off;
1877 proto_tree *qatree = NULL;
1878 proto_item *ti = NULL;
1880 start_off = cur_off;
1882 char *s = (isupdate ? "Zone" : "Queries");
1883 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
1884 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1886 while (count-- > 0) {
1887 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
1891 proto_item_set_len(ti, cur_off - start_off);
1893 return cur_off - start_off;
1897 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1898 int count, column_info *cinfo, proto_tree *dns_tree, char *name,
1901 int start_off, add_off;
1902 proto_tree *qatree = NULL;
1903 proto_item *ti = NULL;
1905 start_off = cur_off;
1907 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
1908 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1910 while (count-- > 0) {
1911 add_off = dissect_dns_answer(
1912 tvb, cur_off, dns_data_offset, cinfo, qatree, pinfo);
1916 proto_item_set_len(ti, cur_off - start_off);
1918 return cur_off - start_off;
1922 dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1925 int offset = is_tcp ? 2 : 0;
1926 int dns_data_offset;
1928 proto_tree *dns_tree = NULL, *field_tree;
1929 proto_item *ti, *tf;
1930 guint16 id, flags, opcode, rcode, quest, ans, auth, add;
1935 dns_data_offset = offset;
1937 if (check_col(pinfo->cinfo, COL_INFO))
1938 col_clear(pinfo->cinfo, COL_INFO);
1940 /* To do: check for errs, etc. */
1941 id = tvb_get_ntohs(tvb, offset + DNS_ID);
1942 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
1943 opcode = (flags & F_OPCODE) >> OPCODE_SHIFT;
1944 rcode = (flags & F_RCODE);
1946 if (check_col(pinfo->cinfo, COL_INFO)) {
1947 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation (%u)"));
1948 if (flags & F_RESPONSE) {
1949 strcat(buf, " response");
1950 if ((flags & F_RCODE) != RCODE_NOERROR) {
1952 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1953 "Unknown error (%u)"));
1956 col_add_str(pinfo->cinfo, COL_INFO, buf);
1957 cinfo = pinfo->cinfo;
1959 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
1960 dissectors, as a way of saying that they shouldn't add stuff
1961 to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
1962 is more expensive than a check that a pointer isn't NULL). */
1965 if (opcode == OPCODE_UPDATE)
1971 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
1972 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1974 dns_tree = proto_item_add_subtree(ti, ett_dns);
1977 /* Put the length indication into the tree. */
1978 proto_tree_add_item(dns_tree, hf_dns_length, tvb, offset - 2, 2, FALSE);
1981 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
1982 offset + DNS_ID, 2, id);
1984 strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
1985 if (flags & F_RESPONSE) {
1986 strcat(buf, " response");
1988 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1991 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
1992 offset + DNS_FLAGS, 2,
1994 "Flags: 0x%04x (%s)",
1996 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1997 proto_tree_add_item(field_tree, hf_dns_flags_response,
1998 tvb, offset + DNS_FLAGS, 2, FALSE);
1999 proto_tree_add_item(field_tree, hf_dns_flags_opcode,
2000 tvb, offset + DNS_FLAGS, 2, FALSE);
2001 if (flags & F_RESPONSE) {
2002 proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
2003 tvb, offset + DNS_FLAGS, 2, FALSE);
2005 proto_tree_add_item(field_tree, hf_dns_flags_truncated,
2006 tvb, offset + DNS_FLAGS, 2, FALSE);
2007 proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
2008 tvb, offset + DNS_FLAGS, 2, FALSE);
2009 if (flags & F_RESPONSE) {
2010 proto_tree_add_item(field_tree, hf_dns_flags_recavail,
2011 tvb, offset + DNS_FLAGS, 2, FALSE);
2012 proto_tree_add_item(field_tree, hf_dns_flags_z,
2013 tvb, offset + DNS_FLAGS, 2, FALSE);
2014 proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
2015 tvb, offset + DNS_FLAGS, 2, FALSE);
2016 proto_tree_add_item(field_tree, hf_dns_flags_rcode,
2017 tvb, offset + DNS_FLAGS, 2, FALSE);
2019 proto_tree_add_item(field_tree, hf_dns_flags_z,
2020 tvb, offset + DNS_FLAGS, 2, FALSE);
2021 proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
2022 tvb, offset + DNS_FLAGS, 2, FALSE);
2025 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
2027 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
2028 offset + DNS_QUEST, 2, quest);
2030 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
2032 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
2033 offset + DNS_ANS, 2, ans);
2035 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
2037 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
2038 offset + DNS_AUTH, 2, auth);
2040 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
2042 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
2043 offset + DNS_ADD, 2, add);
2046 cur_off = offset + DNS_HDRLEN;
2049 /* If this is a response, don't add information about the queries
2050 to the summary, just add information about the answers. */
2051 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
2052 (!(flags & F_RESPONSE) ? cinfo : NULL),
2053 dns_tree, isupdate);
2057 /* If this is a request, don't add information about the answers
2058 to the summary, just add information about the queries. */
2059 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
2060 ((flags & F_RESPONSE) ? cinfo : NULL),
2061 dns_tree, (isupdate ?
2062 "Prerequisites" : "Answers"),
2066 /* Don't add information about the authoritative name servers, or the
2067 additional records, to the summary. */
2069 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
2071 (isupdate ? "Updates" :
2072 "Authoritative nameservers"),
2077 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
2078 NULL, dns_tree, "Additional records",
2084 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2086 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2087 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2089 dissect_dns_common(tvb, pinfo, tree, FALSE);
2093 dissect_mdns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2095 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2096 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MDNS");
2098 dissect_dns_common(tvb, pinfo, tree, FALSE);
2103 get_dns_pdu_len(tvbuff_t *tvb, int offset)
2108 * Get the length of the DNS packet.
2110 plen = tvb_get_ntohs(tvb, offset);
2113 * That length doesn't include the length field itself; add that in.
2119 dissect_dns_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2121 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2122 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
2124 dissect_dns_common(tvb, pinfo, tree, TRUE);
2128 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2130 tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2, get_dns_pdu_len,
2131 dissect_dns_tcp_pdu);
2135 proto_register_dns(void)
2137 static hf_register_info hf[] = {
2139 { "Length", "dns.length",
2140 FT_UINT16, BASE_DEC, NULL, 0x0,
2141 "Length of DNS-over-TCP request or response", HFILL }},
2143 { "Flags", "dns.flags",
2144 FT_UINT16, BASE_HEX, NULL, 0x0,
2146 { &hf_dns_flags_response,
2147 { "Response", "dns.flags.response",
2148 FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
2149 "Is the message a response?", HFILL }},
2150 { &hf_dns_flags_opcode,
2151 { "Opcode", "dns.flags.opcode",
2152 FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
2153 "Operation code", HFILL }},
2154 { &hf_dns_flags_authoritative,
2155 { "Authoritative", "dns.flags.authoritative",
2156 FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
2157 "Is the server is an authority for the domain?", HFILL }},
2158 { &hf_dns_flags_truncated,
2159 { "Truncated", "dns.flags.truncated",
2160 FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
2161 "Is the message truncated?", HFILL }},
2162 { &hf_dns_flags_recdesired,
2163 { "Recursion desired", "dns.flags.recdesired",
2164 FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
2165 "Do query recursively?", HFILL }},
2166 { &hf_dns_flags_recavail,
2167 { "Recursion available", "dns.flags.recavail",
2168 FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
2169 "Can the server do recursive queries?", HFILL }},
2171 { "Z", "dns.flags.z",
2172 FT_BOOLEAN, 16, TFS(&tfs_flags_z), F_Z,
2174 { &hf_dns_flags_authenticated,
2175 { "Answer authenticated", "dns.flags.authenticated",
2176 FT_BOOLEAN, 16, TFS(&tfs_flags_authenticated), F_AUTHENTIC,
2177 "Was the reply data authenticated by the server?", HFILL }},
2178 { &hf_dns_flags_checkdisable,
2179 { "Non-authenticated data OK", "dns.flags.checkdisable",
2180 FT_BOOLEAN, 16, TFS(&tfs_flags_checkdisable), F_CHECKDISABLE,
2181 "Is non-authenticated data acceptable?", HFILL }},
2182 { &hf_dns_flags_rcode,
2183 { "Reply code", "dns.flags.rcode",
2184 FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
2185 "Reply code", HFILL }},
2186 { &hf_dns_transaction_id,
2187 { "Transaction ID", "dns.id",
2188 FT_UINT16, BASE_HEX, NULL, 0x0,
2189 "Identification of transaction", HFILL }},
2190 { &hf_dns_count_questions,
2191 { "Questions", "dns.count.queries",
2192 FT_UINT16, BASE_DEC, NULL, 0x0,
2193 "Number of queries in packet", HFILL }},
2194 { &hf_dns_count_answers,
2195 { "Answer RRs", "dns.count.answers",
2196 FT_UINT16, BASE_DEC, NULL, 0x0,
2197 "Number of answers in packet", HFILL }},
2198 { &hf_dns_count_auth_rr,
2199 { "Authority RRs", "dns.count.auth_rr",
2200 FT_UINT16, BASE_DEC, NULL, 0x0,
2201 "Number of authoritative records in packet", HFILL }},
2202 { &hf_dns_count_add_rr,
2203 { "Additional RRs", "dns.count.add_rr",
2204 FT_UINT16, BASE_DEC, NULL, 0x0,
2205 "Number of additional records in packet", HFILL }}
2207 static gint *ett[] = {
2217 module_t *dns_module;
2219 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2220 proto_register_field_array(proto_dns, hf, array_length(hf));
2221 proto_register_subtree_array(ett, array_length(ett));
2223 dns_module = prefs_register_protocol(proto_dns, NULL);
2224 prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2225 "Desegment all DNS messages spanning multiple TCP segments",
2226 "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
2231 proto_reg_handoff_dns(void)
2233 dissector_handle_t dns_udp_handle;
2234 dissector_handle_t dns_tcp_handle;
2235 dissector_handle_t mdns_udp_handle;
2237 dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
2238 dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
2239 mdns_udp_handle = create_dissector_handle(dissect_mdns_udp, proto_dns);
2241 dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
2242 dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
2243 dissector_add("udp.port", UDP_PORT_MDNS, mdns_udp_handle);
2244 dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
2246 gssapi_handle = find_dissector("gssapi");