2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.84 2002/03/19 09:18:42 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
38 #include <epan/packet.h>
40 #include <epan/resolv.h>
41 #include "packet-dns.h"
42 #include "packet-frame.h"
45 static int proto_dns = -1;
46 static int hf_dns_length = -1;
47 static int hf_dns_response = -1;
48 static int hf_dns_query = -1;
49 static int hf_dns_flags = -1;
50 static int hf_dns_transaction_id = -1;
51 static int hf_dns_count_questions = -1;
52 static int hf_dns_count_answers = -1;
53 static int hf_dns_count_auth_rr = -1;
54 static int hf_dns_count_add_rr = -1;
56 static gint ett_dns = -1;
57 static gint ett_dns_qd = -1;
58 static gint ett_dns_rr = -1;
59 static gint ett_dns_qry = -1;
60 static gint ett_dns_ans = -1;
61 static gint ett_dns_flags = -1;
62 static gint ett_t_key_flags = -1;
64 /* desegmentation of DNS over TCP */
65 static gboolean dns_desegment = TRUE;
67 /* DNS structs and definitions */
69 /* Ports used for DNS. */
70 #define UDP_PORT_DNS 53
71 #define TCP_PORT_DNS 53
73 /* Offsets of fields in the DNS header. */
81 /* Length of DNS header. */
85 #define T_A 1 /* host address */
86 #define T_NS 2 /* authoritative name server */
87 #define T_MD 3 /* mail destination (obsolete) */
88 #define T_MF 4 /* mail forwarder (obsolete) */
89 #define T_CNAME 5 /* canonical name */
90 #define T_SOA 6 /* start of authority zone */
91 #define T_MB 7 /* mailbox domain name (experimental) */
92 #define T_MG 8 /* mail group member (experimental) */
93 #define T_MR 9 /* mail rename domain name (experimental) */
94 #define T_NULL 10 /* null RR (experimental) */
95 #define T_WKS 11 /* well known service */
96 #define T_PTR 12 /* domain name pointer */
97 #define T_HINFO 13 /* host information */
98 #define T_MINFO 14 /* mailbox or mail list information */
99 #define T_MX 15 /* mail routing information */
100 #define T_TXT 16 /* text strings */
101 #define T_RP 17 /* responsible person (RFC 1183) */
102 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
103 #define T_X25 19 /* X.25 address (RFC 1183) */
104 #define T_ISDN 20 /* ISDN address (RFC 1183) */
105 #define T_RT 21 /* route-through (RFC 1183) */
106 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
107 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
108 #define T_SIG 24 /* digital signature (RFC 2535) */
109 #define T_KEY 25 /* public key (RFC 2535) */
110 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
111 #define T_GPOS 27 /* geographical position (RFC 1712) */
112 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
113 #define T_LOC 29 /* geographical location (RFC 1876) */
114 #define T_NXT 30 /* "next" name (RFC 2535) */
115 #define T_EID 31 /* ??? (Nimrod?) */
116 #define T_NIMLOC 32 /* ??? (Nimrod?) */
117 #define T_SRV 33 /* service location (RFC 2052) */
118 #define T_ATMA 34 /* ??? */
119 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
120 #define T_KX 36 /* Key Exchange (RFC 2230) */
121 #define T_CERT 37 /* Certificate (RFC 2538) */
122 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
123 #define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
124 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
125 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
126 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
127 #define T_WINS 65281 /* Microsoft's WINS RR */
128 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
131 #define C_IN 1 /* the Internet */
132 #define C_CS 2 /* CSNET (obsolete) */
133 #define C_CH 3 /* CHAOS */
134 #define C_HS 4 /* Hesiod */
135 #define C_NONE 254 /* none */
136 #define C_ANY 255 /* any */
138 /* Bit fields in the flags */
139 #define F_RESPONSE (1<<15) /* packet is response */
140 #define F_OPCODE (0xF<<11) /* query opcode */
141 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
142 #define F_TRUNCATED (1<<9) /* response is truncated */
143 #define F_RECDESIRED (1<<8) /* recursion desired */
144 #define F_RECAVAIL (1<<7) /* recursion available */
145 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
146 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
147 #define F_RCODE (0xF<<0) /* reply code */
150 #define OPCODE_QUERY (0<<11) /* standard query */
151 #define OPCODE_IQUERY (1<<11) /* inverse query */
152 #define OPCODE_STATUS (2<<11) /* server status request */
153 #define OPCODE_NOTIFY (4<<11) /* zone change notification */
154 #define OPCODE_UPDATE (5<<11) /* dynamic update */
157 #define RCODE_NOERROR (0<<0)
158 #define RCODE_FORMERR (1<<0)
159 #define RCODE_SERVFAIL (2<<0)
160 #define RCODE_NXDOMAIN (3<<0)
161 #define RCODE_NOTIMPL (4<<0)
162 #define RCODE_REFUSED (5<<0)
163 #define RCODE_YXDOMAIN (6<<0)
164 #define RCODE_YXRRSET (7<<0)
165 #define RCODE_NXRRSET (8<<0)
166 #define RCODE_NOTAUTH (9<<0)
167 #define RCODE_NOTZONE (10<<0)
169 static const value_string rcode_vals[] = {
170 { RCODE_NOERROR, "No error" },
171 { RCODE_FORMERR, "Format error" },
172 { RCODE_SERVFAIL, "Server failure" },
173 { RCODE_NXDOMAIN, "No such name" },
174 { RCODE_NOTIMPL, "Not implemented" },
175 { RCODE_REFUSED, "Refused" },
176 { RCODE_YXDOMAIN, "Name exists" },
177 { RCODE_YXRRSET, "RRset exists" },
178 { RCODE_NXRRSET, "RRset does not exist" },
179 { RCODE_NOTAUTH, "Not authoritative" },
180 { RCODE_NOTZONE, "Name out of zone" },
183 /* TSIG/TKEY extended errors */
184 #define TSIGERROR_BADSIG (16)
185 #define TSIGERROR_BADKEY (17)
186 #define TSIGERROR_BADTIME (18)
187 #define TSIGERROR_BADMODE (19)
188 #define TSIGERROR_BADNAME (20)
189 #define TSIGERROR_BADALG (21)
191 static const value_string tsigerror_vals[] = {
192 { TSIGERROR_BADSIG, "Bad signature" },
193 { TSIGERROR_BADKEY, "Bad key" },
194 { TSIGERROR_BADTIME, "Bad time failure" },
195 { TSIGERROR_BADMODE, "Bad mode such name" },
196 { TSIGERROR_BADNAME, "Bad name implemented" },
197 { TSIGERROR_BADALG, "Bad algorithm" },
200 #define TKEYMODE_SERVERASSIGNED (1)
201 #define TKEYMODE_DIFFIEHELLMAN (2)
202 #define TKEYMODE_GSSAPI (3)
203 #define TKEYMODE_RESOLVERASSIGNED (4)
204 #define TKEYMODE_DELETE (5)
206 /* See RFC 1035 for all RR types for which no RFC is listed, except for
207 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
208 which one should look at
210 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
214 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
216 which discuss them to some extent. */
218 dns_type_name (u_int type)
220 char *type_names[] = {
239 "AFSDB", /* RFC 1183 */
240 "X25", /* RFC 1183 */
241 "ISDN", /* RFC 1183 */
243 "NSAP", /* RFC 1706 */
244 "NSAP-PTR", /* RFC 1348 */
245 "SIG", /* RFC 2535 */
246 "KEY", /* RFC 2535 */
248 "GPOS", /* RFC 1712 */
249 "AAAA", /* RFC 1886 */
250 "LOC", /* RFC 1876 */
251 "NXT", /* RFC 2535 */
254 "SRV", /* RFC 2052 */
256 "NAPTR", /* RFC 2168 */
258 "CERT", /* RFC 2538 */
260 "DNAME", /* RFC 2672 */
265 if (type < sizeof(type_names)/sizeof(type_names[0]))
266 return type_names[type] ? type_names[type] : "unknown";
293 return "IXFR"; /* RFC 1995 */
310 dns_long_type_name (u_int type)
312 char *type_names[] = {
315 "Authoritative name server",
318 "Canonical name for an alias",
319 "Start of zone of authority",
320 "Mailbox domain name",
322 "Mail rename domain name",
323 "Null resource record",
324 "Well-known service description",
325 "Domain name pointer",
327 "Mailbox or mail list information",
330 "Responsible person", /* RFC 1183 */
331 "AFS data base location", /* RFC 1183 */
332 "X.25 address", /* RFC 1183 */
333 "ISDN number", /* RFC 1183 */
334 "Route through", /* RFC 1183 */
335 "OSI NSAP", /* RFC 1706 */
336 "OSI NSAP name pointer", /* RFC 1348 */
337 "Signature", /* RFC 2535 */
338 "Public key", /* RFC 2535 */
339 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
340 "Geographical position", /* RFC 1712 */
341 "IPv6 address", /* RFC 1886 */
342 "Location", /* RFC 1876 */
343 "Next", /* RFC 2535 */
346 "Service location", /* RFC 2052 */
348 "Naming authority pointer", /* RFC 2168 */
349 "Key Exchange", /* RFC 2230 */
350 "Certificate", /* RFC 2538 */
351 "IPv6 address with indirection", /* RFC 2874 */
352 "Non-terminal DNS name redirection", /* RFC 2672 */
354 "EDNS0 option" /* RFC 2671 */
356 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%d)" */
358 if (type < sizeof(type_names)/sizeof(type_names[0]))
359 return type_names[type] ? type_names[type] : "unknown";
380 return "Transaction Key";
382 return "Transaction Signature";
386 return "Request for incremental zone transfer"; /* RFC 1995 */
388 return "Request for full zone transfer";
390 return "Request for mailbox-related records";
392 return "Request for mail agent resource records";
394 return "Request for all records";
397 sprintf(unkbuf, "Unknown RR type (%d)", type);
403 dns_class_name(int class)
412 class_name = "csnet";
415 class_name = "chaos";
418 class_name = "hesiod";
427 class_name = "unknown";
434 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
435 char *name, int maxname)
437 int start_offset = offset;
440 int chars_processed = 0;
441 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
445 maxname--; /* reserve space for the trailing '\0' */
447 component_len = tvb_get_guint8(tvb, offset);
449 if (component_len == 0)
452 switch (component_len & 0xc0) {
457 /* Not the first component - put in a '.'. */
463 while (component_len > 0) {
465 *np++ = tvb_get_guint8(tvb, offset);
475 /* Extended label (RFC 2673) */
476 switch (component_len & 0x3f) {
479 /* Bitstring label */
484 bit_count = tvb_get_guint8(tvb, offset);
486 label_len = (bit_count - 1) / 8 + 1;
488 np += sprintf(np, "\\[x");
490 np += sprintf(np, "%02x", tvb_get_guint8(tvb, offset));
493 np += sprintf(np, "/%d]", bit_count);
498 strcpy(name, "<Unknown extended label>");
499 /* Parsing will propably fail from here on, since the */
500 /* label length is unknown... */
501 return offset - start_offset;
506 goto error; /* error */
510 indir_offset = dns_data_offset +
511 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
515 /* If "len" is negative, we are still working on the original name,
516 not something pointed to by a pointer, and so we should set "len"
517 to the length of the original name. */
519 len = offset - start_offset;
521 /* If we've looked at every character in the message, this pointer
522 will make us look at some character again, which means we're
524 if (chars_processed >= data_size) {
525 strcpy(name, "<Name contains a pointer that loops>");
529 offset = indir_offset;
530 break; /* now continue processing from there */
536 /* If "len" is negative, we haven't seen a pointer, and thus haven't
537 set the length, so set it. */
539 len = offset - start_offset;
540 /* Zero-length name means "root server" */
542 strcpy(name, "<Root>");
548 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
549 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
556 int start_offset = offset;
558 name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
561 type = tvb_get_ntohs(tvb, offset);
564 class = tvb_get_ntohs(tvb, offset);
567 strcpy (name_ret, name);
570 *name_len_ret = name_len;
572 len = offset - start_offset;
577 rfc1867_size(tvbuff_t *tvb, int offset)
583 val = tvb_get_guint8(tvb, offset);
584 size = (val & 0xF0) >> 4;
585 exponent = (val & 0x0F);
586 while (exponent != 0) {
590 return size / 100; /* return size in meters, not cm */
594 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
598 guint32 degrees, minutes, secs, tsecs;
599 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
601 angle = tvb_get_ntohl(tvb, offset);
603 if (angle < 0x80000000U) {
604 angle = 0x80000000U - angle;
607 angle = angle - 0x80000000U;
610 tsecs = angle % 1000;
611 angle = angle / 1000;
614 minutes = angle % 60;
615 degrees = angle / 60;
616 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
622 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
623 column_info *cinfo, proto_tree *dns_tree)
632 char *long_type_name;
638 data_start = data_offset = offset;
640 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
644 type_name = dns_type_name(type);
645 class_name = dns_class_name(class);
646 long_type_name = dns_long_type_name(type);
649 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
650 if (dns_tree != NULL) {
651 tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
652 name, type_name, class_name);
653 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
655 proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
658 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
661 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
665 return data_offset - data_start;
670 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
671 const char *name, int namelen, const char *type_name, const char *class_name,
672 u_int ttl, u_short data_len)
676 rr_tree = proto_item_add_subtree(trr, rr_type);
677 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
679 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
681 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
683 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
684 time_secs_to_str(ttl));
686 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
691 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
692 const char *name, int namelen, const char *type_name, int class,
693 u_int ttl, u_short data_len)
697 rr_tree = proto_item_add_subtree(trr, rr_type);
698 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
700 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
702 proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
705 proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
706 (ttl >> 24) & 0xff0);
708 proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
711 proto_tree_add_text(rr_tree, tvb, offset, 2, "Must be zero: 0x%x", ttl & 0xffff);
713 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
718 * SIG, KEY, and CERT RR algorithms.
720 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
721 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
722 #define DNS_ALGO_DSA 3 /* DSA */
723 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
724 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
725 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
726 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
728 static const value_string algo_vals[] = {
729 { DNS_ALGO_RSAMD5, "RSA/MD5" },
730 { DNS_ALGO_DH, "Diffie-Hellman" },
731 { DNS_ALGO_DSA, "DSA" },
732 { DNS_ALGO_ECC, "Elliptic curve crypto" },
733 { DNS_ALGO_INDIRECT, "Indirect key" },
734 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
735 { DNS_ALGO_PRIVATEOID, "Private, OID" },
739 #define DNS_CERT_PGP 1 /* PGP */
740 #define DNS_CERT_PKIX 2 /* PKIX */
741 #define DNS_CERT_SPKI 3 /* SPKI */
742 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
743 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
745 static const value_string cert_vals[] = {
746 { DNS_CERT_PGP, "PGP" },
747 { DNS_CERT_PKIX, "PKIX" },
748 { DNS_CERT_SPKI, "SPKI" },
749 { DNS_CERT_PRIVATEURI, "Private, URI" },
750 { DNS_CERT_PRIVATEOID, "Private, OID" },
755 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
756 column_info *cinfo, proto_tree *dns_tree)
765 char *long_type_name;
771 proto_tree *rr_tree = NULL;
772 proto_item *trr = NULL;
774 data_start = data_offset = offset;
777 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
782 type_name = dns_type_name(type);
783 class_name = dns_class_name(class);
784 long_type_name = dns_long_type_name(type);
786 ttl = tvb_get_ntohl(tvb, data_offset);
790 data_len = tvb_get_ntohs(tvb, data_offset);
795 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
796 if (dns_tree != NULL) {
797 trr = proto_tree_add_text(dns_tree, tvb, offset,
798 (data_offset - data_start) + data_len,
799 "%s: type %s, class %s",
800 name, type_name, class_name);
802 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
803 long_type_name, class_name, ttl, data_len);
805 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
806 long_type_name, class, ttl, data_len);
817 addr = tvb_get_ptr(tvb, cur_offset, 4);
819 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
820 if (dns_tree != NULL) {
821 proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
822 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
826 memcpy(&addr_int, addr, sizeof(addr_int));
827 add_host_name(addr_int, name);
834 char ns_name[MAXDNAME];
837 ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
839 col_append_fstr(cinfo, COL_INFO, " %s", ns_name);
840 if (dns_tree != NULL) {
841 proto_item_append_text(trr, ", ns %s", ns_name);
842 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
850 char cname[MAXDNAME];
853 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
855 col_append_fstr(cinfo, COL_INFO, " %s", cname);
856 if (dns_tree != NULL) {
857 proto_item_append_text(trr, ", cname %s", cname);
858 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
866 char mname[MAXDNAME];
868 char rname[MAXDNAME];
876 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
878 col_append_fstr(cinfo, COL_INFO, " %s", mname);
879 if (dns_tree != NULL) {
880 proto_item_append_text(trr, ", mname %s", mname);
881 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
883 cur_offset += mname_len;
885 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
886 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
888 cur_offset += rname_len;
890 serial = tvb_get_ntohl(tvb, cur_offset);
891 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
895 refresh = tvb_get_ntohl(tvb, cur_offset);
896 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
897 time_secs_to_str(refresh));
900 retry = tvb_get_ntohl(tvb, cur_offset);
901 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
902 time_secs_to_str(retry));
905 expire = tvb_get_ntohl(tvb, cur_offset);
906 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
907 time_secs_to_str(expire));
910 minimum = tvb_get_ntohl(tvb, cur_offset);
911 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
912 time_secs_to_str(minimum));
919 char pname[MAXDNAME];
922 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
924 col_append_fstr(cinfo, COL_INFO, " %s", pname);
925 if (dns_tree != NULL) {
926 proto_item_append_text(trr, ", ptr %s", pname);
927 proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
936 int rr_len = data_len;
937 const guint8 *wks_addr;
943 char bitnames[128+1];
944 char portnumstring[10+1];
946 wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
948 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
949 if (dns_tree != NULL) {
950 proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
951 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
952 ip_to_str(wks_addr));
956 protocol = tvb_get_guint8(tvb, cur_offset);
957 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
958 ipprotostr(protocol));
963 while (rr_len != 0) {
964 bits = tvb_get_guint8(tvb, cur_offset);
968 for (i = 0; i < 8; i++) {
970 if (bitnames[0] != '\0')
971 strcat(bitnames, ", ");
975 strcat(bitnames, get_tcp_port(port_num));
979 strcat(bitnames, get_udp_port(port_num));
983 sprintf(portnumstring, "%u", port_num);
984 strcat(bitnames, portnumstring);
991 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
992 "Bits: 0x%02x (%s)", bits, bitnames);
1011 cpu_offset = cur_offset;
1012 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1013 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1014 os_offset = cpu_offset + 1 + cpu_len;
1015 os_len = tvb_get_guint8(tvb, os_offset);
1016 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1018 col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1020 if (dns_tree != NULL) {
1021 proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1022 cpu_len, cpu, os_len, os);
1023 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1025 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1034 guint16 preference = 0;
1035 char mx_name[MAXDNAME];
1038 preference = tvb_get_ntohs(tvb, cur_offset);
1039 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1041 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, mx_name);
1042 if (dns_tree != NULL) {
1043 proto_item_append_text(trr, ", preference %u, mx %s",
1044 preference, mx_name);
1045 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1046 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1054 int rr_len = data_len;
1058 if (dns_tree != NULL) {
1059 txt_offset = cur_offset;
1060 while (rr_len != 0) {
1061 txt_len = tvb_get_guint8(tvb, txt_offset);
1062 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1063 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1064 txt_offset += 1 + txt_len;
1065 rr_len -= 1 + txt_len;
1073 int rr_len = data_len;
1074 guint16 type_covered;
1076 char signer_name[MAXDNAME];
1077 int signer_name_len;
1079 if (dns_tree != NULL) {
1080 type_covered = tvb_get_ntohs(tvb, cur_offset);
1081 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1082 dns_type_name(type_covered),
1083 dns_long_type_name(type_covered));
1087 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1088 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1089 "Unknown (0x%02X)"));
1093 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1094 tvb_get_guint8(tvb, cur_offset));
1098 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1099 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1103 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1105 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1106 abs_time_to_str(&nstime));
1110 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1112 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1113 abs_time_to_str(&nstime));
1117 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1118 tvb_get_ntohs(tvb, cur_offset));
1122 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1123 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1124 "Signer's name: %s", signer_name);
1125 cur_offset += signer_name_len;
1126 rr_len -= signer_name_len;
1128 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1135 int rr_len = data_len;
1138 proto_tree *flags_tree;
1140 if (dns_tree != NULL) {
1141 flags = tvb_get_ntohs(tvb, cur_offset);
1142 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1143 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1144 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1145 decode_boolean_bitfield(flags, 0x8000,
1146 2*8, "Key prohibited for authentication",
1147 "Key allowed for authentication"));
1148 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1149 decode_boolean_bitfield(flags, 0x4000,
1150 2*8, "Key prohibited for confidentiality",
1151 "Key allowed for confidentiality"));
1152 if ((flags & 0xC000) != 0xC000) {
1154 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1155 decode_boolean_bitfield(flags, 0x2000,
1156 2*8, "Key is experimental or optional",
1157 "Key is required"));
1158 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1159 decode_boolean_bitfield(flags, 0x0400,
1160 2*8, "Key is associated with a user",
1161 "Key is not associated with a user"));
1162 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1163 decode_boolean_bitfield(flags, 0x0200,
1164 2*8, "Key is associated with the named entity",
1165 "Key is not associated with the named entity"));
1166 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1167 decode_boolean_bitfield(flags, 0x0100,
1168 2*8, "This is the zone key for the specified zone",
1169 "This is not a zone key"));
1170 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1171 decode_boolean_bitfield(flags, 0x0080,
1172 2*8, "Key is valid for use with IPSEC",
1173 "Key is not valid for use with IPSEC"));
1174 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1175 decode_boolean_bitfield(flags, 0x0040,
1176 2*8, "Key is valid for use with MIME security multiparts",
1177 "Key is not valid for use with MIME security multiparts"));
1178 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1179 decode_numeric_bitfield(flags, 0x000F,
1180 2*8, "Signatory = %u"));
1185 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1186 tvb_get_guint8(tvb, cur_offset));
1190 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1191 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1192 "Unknown (0x%02X)"));
1196 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1203 const guint8 *addr6;
1205 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1206 if (cinfo != NULL) {
1207 col_append_fstr(cinfo, COL_INFO, " %s",
1208 ip6_to_str((struct e_in6_addr *)addr6));
1210 if (dns_tree != NULL) {
1211 proto_item_append_text(trr, ", addr %s",
1212 ip6_to_str((struct e_in6_addr *)addr6));
1213 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1214 ip6_to_str((struct e_in6_addr *)addr6));
1221 unsigned short pre_len;
1222 unsigned short suf_len;
1223 unsigned short suf_octet_count;
1224 char pname[MAXDNAME];
1230 a6_offset = cur_offset;
1231 pre_len = tvb_get_guint8(tvb, cur_offset);
1233 suf_len = 128 - pre_len;
1234 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1236 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1237 suffix[suf_offset] = 0;
1239 for (; suf_offset < 16; suf_offset++) {
1240 suffix[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1245 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1246 pname, sizeof(pname));
1252 if (cinfo != NULL) {
1253 col_append_fstr(cinfo, COL_INFO, " %d %s %s",
1255 ip6_to_str((struct e_in6_addr *)&suffix),
1258 if (dns_tree != NULL) {
1259 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1260 "Prefix len: %u", pre_len);
1263 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1264 "Address suffix: %s",
1265 ip6_to_str((struct e_in6_addr *)&suffix));
1266 a6_offset += suf_octet_count;
1269 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1270 "Prefix name: %s", pname);
1272 proto_item_append_text(trr, ", addr %d %s %s",
1274 ip6_to_str((struct e_in6_addr *)&suffix),
1282 char dname[MAXDNAME];
1285 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1286 dname, sizeof(dname));
1288 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1289 if (dns_tree != NULL) {
1290 proto_item_append_text(trr, ", dname %s", dname);
1291 proto_tree_add_text(rr_tree, tvb, cur_offset,
1292 dname_len, "Target name: %s", dname);
1301 if (dns_tree != NULL) {
1302 version = tvb_get_guint8(tvb, cur_offset);
1303 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1305 /* Version 0, the only version RFC 1876 discusses. */
1308 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1309 rfc1867_size(tvb, cur_offset));
1312 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1313 rfc1867_size(tvb, cur_offset));
1316 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1317 rfc1867_size(tvb, cur_offset));
1320 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1321 rfc1867_angle(tvb, cur_offset, "NS"));
1324 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1325 rfc1867_angle(tvb, cur_offset, "EW"));
1328 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1329 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1331 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1339 int rr_len = data_len;
1340 char next_domain_name[MAXDNAME];
1341 int next_domain_name_len;
1347 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1348 next_domain_name, sizeof(next_domain_name));
1350 col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
1351 if (dns_tree != NULL) {
1352 proto_item_append_text(trr, ", next domain name %s",
1354 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1355 "Next domain name: %s", next_domain_name);
1356 cur_offset += next_domain_name_len;
1357 rr_len -= next_domain_name_len;
1359 while (rr_len != 0) {
1360 bits = tvb_get_guint8(tvb, cur_offset);
1362 for (i = 0; i < 8; i++) {
1364 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1365 "RR type in bit map: %s (%s)",
1366 dns_type_name(rr_type),
1367 dns_long_type_name(rr_type));
1381 guint16 preference = 0;
1382 char kx_name[MAXDNAME];
1385 preference = tvb_get_ntohs(tvb, cur_offset);
1386 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1388 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, kx_name);
1389 if (dns_tree != NULL) {
1390 proto_item_append_text(trr, ", preference %u, kx %s",
1391 preference, kx_name);
1392 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1393 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1401 guint16 cert_type, cert_keytag;
1403 int rr_len = data_len;
1405 cert_type = tvb_get_ntohs(tvb, cur_offset);
1408 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1411 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1415 if (dns_tree != NULL) {
1416 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s",
1417 val_to_str(cert_keyalg, cert_vals,
1418 "Unknown (0x%02X)"));
1419 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1421 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1422 val_to_str(cert_keyalg, algo_vals,
1423 "Unknown (0x%02X)"));
1424 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1431 if (dns_tree != NULL)
1432 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1437 char tkey_algname[MAXDNAME];
1438 int tkey_algname_len;
1439 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1440 int rr_len = data_len;
1442 static const value_string tkey_modes[] = {
1443 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1444 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1445 { TKEYMODE_GSSAPI, "GSSAPI" },
1446 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1447 { TKEYMODE_DELETE, "Delete" },
1450 if (dns_tree != NULL) {
1451 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1452 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1453 "Algorithm name: %s", tkey_algname);
1454 cur_offset += tkey_algname_len;
1455 rr_len -= tkey_algname_len;
1457 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1459 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1460 abs_time_to_str(&nstime));
1464 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1466 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1467 abs_time_to_str(&nstime));
1471 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1474 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Mode: %s",
1475 val_to_str(tkey_mode, tkey_modes,
1476 "Unknown (0x%02X)"));
1478 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1482 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Error: %s",
1483 val_to_str(tkey_error, rcode_vals,
1484 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1486 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1490 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1491 cur_offset += tkey_keylen;
1492 rr_len -= tkey_keylen;
1494 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1498 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1499 cur_offset += tkey_otherlen;
1500 rr_len -= tkey_otherlen;
1508 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1509 guint32 tsig_timelo;
1510 char tsig_algname[MAXDNAME];
1511 int tsig_algname_len;
1513 int rr_len = data_len;
1515 if (dns_tree != NULL) {
1516 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1517 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1518 "Algorithm name: %s", tsig_algname);
1519 cur_offset += tsig_algname_len;
1520 rr_len -= tsig_algname_len;
1522 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1523 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1524 nstime.secs = tsig_timelo;
1526 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1527 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
1531 tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1532 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1537 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1541 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1542 cur_offset += tsig_siglen;
1543 rr_len -= tsig_siglen;
1545 tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1546 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1551 tsig_error = tvb_get_ntohs(tvb, cur_offset);
1552 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1553 val_to_str(tsig_error, rcode_vals,
1554 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1558 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1562 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1563 cur_offset += tsig_otherlen;
1564 rr_len -= tsig_otherlen;
1571 int rr_len = data_len;
1573 guint32 lookup_timeout;
1574 guint32 cache_timeout;
1577 if (dns_tree != NULL) {
1578 local_flag = tvb_get_ntohl(tvb, cur_offset);
1579 if (dns_tree != NULL) {
1580 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1581 local_flag ? "true" : "false");
1586 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1587 if (dns_tree != NULL) {
1588 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1594 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1595 if (dns_tree != NULL) {
1596 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1602 nservers = tvb_get_ntohl(tvb, cur_offset);
1603 if (dns_tree != NULL) {
1604 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
1610 while (rr_len != 0 && nservers != 0) {
1611 if (dns_tree != NULL) {
1612 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
1613 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
1625 int rr_len = data_len;
1627 guint32 lookup_timeout;
1628 guint32 cache_timeout;
1629 char dname[MAXDNAME];
1632 local_flag = tvb_get_ntohl(tvb, cur_offset);
1633 if (dns_tree != NULL) {
1634 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1635 local_flag ? "true" : "false");
1640 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1641 if (dns_tree != NULL) {
1642 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1648 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1649 if (dns_tree != NULL) {
1650 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1656 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1658 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1659 if (dns_tree != NULL) {
1660 proto_item_append_text(trr, ", name result domain %s", dname);
1661 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
1669 guint16 priority = 0;
1672 char target[MAXDNAME];
1675 priority = tvb_get_ntohs(tvb, cur_offset);
1676 weight = tvb_get_ntohs(tvb, cur_offset+2);
1677 port = tvb_get_ntohs(tvb, cur_offset+4);
1679 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1681 col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, target);
1682 if (dns_tree != NULL) {
1683 proto_item_append_text(trr,
1684 ", priority %u, weight %u, port %u, target %s",
1685 priority, weight, port, target);
1686 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
1687 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
1688 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
1689 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
1695 /* TODO: parse more record types */
1698 if (dns_tree != NULL)
1699 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1703 data_offset += data_len;
1705 return data_offset - data_start;
1709 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1710 int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
1712 int start_off, add_off;
1713 proto_tree *qatree = NULL;
1714 proto_item *ti = NULL;
1716 start_off = cur_off;
1718 char *s = (isupdate ? "Zone" : "Queries");
1719 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
1720 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1722 while (count-- > 0) {
1723 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
1727 proto_item_set_len(ti, cur_off - start_off);
1729 return cur_off - start_off;
1733 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1734 int count, column_info *cinfo, proto_tree *dns_tree, char *name)
1736 int start_off, add_off;
1737 proto_tree *qatree = NULL;
1738 proto_item *ti = NULL;
1740 start_off = cur_off;
1742 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
1743 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1745 while (count-- > 0) {
1746 add_off = dissect_dns_answer(tvb, cur_off, dns_data_offset, cinfo, qatree);
1750 proto_item_set_len(ti, cur_off - start_off);
1752 return cur_off - start_off;
1756 dissect_dns_common(tvbuff_t *tvb, int msg_len, packet_info *pinfo,
1757 proto_tree *tree, gboolean is_tcp)
1759 int offset = is_tcp ? 2 : 0;
1760 int dns_data_offset;
1762 proto_tree *dns_tree = NULL, *field_tree;
1763 proto_item *ti, *tf;
1764 guint16 id, flags, quest, ans, auth, add;
1768 static const value_string opcode_vals[] = {
1769 { OPCODE_QUERY, "Standard query" },
1770 { OPCODE_IQUERY, "Inverse query" },
1771 { OPCODE_STATUS, "Server status request" },
1772 { OPCODE_NOTIFY, "Zone change notification" },
1773 { OPCODE_UPDATE, "Dynamic update" },
1776 dns_data_offset = offset;
1778 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1779 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
1780 if (check_col(pinfo->cinfo, COL_INFO))
1781 col_clear(pinfo->cinfo, COL_INFO);
1783 /* To do: check for errs, etc. */
1784 id = tvb_get_ntohs(tvb, offset + DNS_ID);
1785 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
1787 if (check_col(pinfo->cinfo, COL_INFO)) {
1788 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation (%x)"));
1789 if (flags & F_RESPONSE) {
1790 strcat(buf, " response");
1791 if ((flags & F_RCODE) != RCODE_NOERROR) {
1793 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1794 "Unknown error (%x)"));
1797 col_add_str(pinfo->cinfo, COL_INFO, buf);
1798 cinfo = pinfo->cinfo;
1800 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
1801 dissectors, as a way of saying that they shouldn't add stuff
1802 to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
1803 is more expensive than a check that a pointer isn't NULL). */
1806 if ((flags & F_OPCODE) == OPCODE_UPDATE)
1812 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
1813 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1815 dns_tree = proto_item_add_subtree(ti, ett_dns);
1818 /* Put the length indication into the tree. */
1819 proto_tree_add_uint(dns_tree, hf_dns_length, tvb, offset - 2, 2, msg_len);
1822 if (flags & F_RESPONSE)
1823 proto_tree_add_boolean_hidden(dns_tree, hf_dns_response, tvb, offset, 4, 1);
1825 proto_tree_add_boolean_hidden(dns_tree, hf_dns_query, tvb, offset, 4, 1);
1827 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
1828 offset + DNS_ID, 2, id);
1830 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
1831 if (flags & F_RESPONSE) {
1832 strcat(buf, " response");
1834 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1837 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
1838 offset + DNS_FLAGS, 2,
1840 "Flags: 0x%04x (%s)",
1842 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1843 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1844 decode_boolean_bitfield(flags, F_RESPONSE,
1845 2*8, "Response", "Query"));
1846 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1847 decode_enumerated_bitfield(flags, F_OPCODE,
1848 2*8, opcode_vals, "%s"));
1849 if (flags & F_RESPONSE) {
1850 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1851 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
1853 "Server is an authority for domain",
1854 "Server is not an authority for domain"));
1856 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1857 decode_boolean_bitfield(flags, F_TRUNCATED,
1859 "Message is truncated",
1860 "Message is not truncated"));
1861 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1862 decode_boolean_bitfield(flags, F_RECDESIRED,
1864 "Do query recursively",
1865 "Don't do query recursively"));
1866 if (flags & F_RESPONSE) {
1867 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1868 decode_boolean_bitfield(flags, F_RECAVAIL,
1870 "Server can do recursive queries",
1871 "Server can't do recursive queries"));
1872 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1873 decode_boolean_bitfield(flags, F_AUTHENTIC,
1875 "Answer/authority portion was authenticated by the server",
1876 "Answer/authority portion was not authenticated by the server"));
1878 if ((flags & F_RESPONSE) == 0) {
1879 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1880 decode_boolean_bitfield(flags, F_CHECKDISABLE,
1882 "Non-authenticated data is acceptable",
1883 "Non-authenticated data is unacceptable"));
1885 if (flags & F_RESPONSE) {
1886 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1887 decode_enumerated_bitfield(flags, F_RCODE,
1888 2*8, rcode_vals, "%s"));
1891 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
1893 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
1894 offset + DNS_QUEST, 2, quest);
1896 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
1898 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
1899 offset + DNS_ANS, 2, ans);
1901 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
1903 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
1904 offset + DNS_AUTH, 2, auth);
1906 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
1908 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
1909 offset + DNS_ADD, 2, add);
1912 cur_off = offset + DNS_HDRLEN;
1915 /* If this is a response, don't add information about the queries
1916 to the summary, just add information about the answers. */
1917 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
1918 (!(flags & F_RESPONSE) ? cinfo : NULL),
1919 dns_tree, isupdate);
1923 /* If this is a request, don't add information about the answers
1924 to the summary, just add information about the queries. */
1925 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
1926 ((flags & F_RESPONSE) ? cinfo : NULL),
1928 (isupdate ? "Prerequisites" : "Answers"));
1931 /* Don't add information about the authoritative name servers, or the
1932 additional records, to the summary. */
1934 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
1936 (isupdate ? "Updates" :
1937 "Authoritative nameservers"));
1941 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
1942 NULL, dns_tree, "Additional records");
1947 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1949 dissect_dns_common(tvb, -1, pinfo, tree, FALSE);
1953 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1955 volatile int offset = 0;
1956 int length_remaining;
1961 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1962 length_remaining = tvb_length_remaining(tvb, offset);
1965 * Can we do reassembly?
1967 if (dns_desegment && pinfo->can_desegment) {
1969 * Yes - is the DNS-over-TCP header split across
1970 * segment boundaries?
1972 if (length_remaining < 2) {
1974 * Yes. Tell the TCP dissector where
1975 * the data for this message starts in
1976 * the data it handed us, and how many
1977 * more bytes we need, and return.
1979 pinfo->desegment_offset = offset;
1980 pinfo->desegment_len = 2 - length_remaining;
1986 * Get the length of the DNS packet.
1988 plen = tvb_get_ntohs(tvb, offset);
1991 * Can we do reassembly?
1993 if (dns_desegment && pinfo->can_desegment) {
1995 * Yes - is the DNS packet split across segment
1998 if (length_remaining < plen + 2) {
2000 * Yes. Tell the TCP dissector where
2001 * the data for this message starts in
2002 * the data it handed us, and how many
2003 * more bytes we need, and return.
2005 pinfo->desegment_offset = offset;
2006 pinfo->desegment_len =
2007 (plen + 2) - length_remaining;
2013 * Construct a tvbuff containing the amount of the payload
2014 * we have available. Make its reported length the
2015 * amount of data in the DNS-over-TCP packet.
2017 * XXX - if reassembly isn't enabled. the subdissector
2018 * will throw a BoundsError exception, rather than a
2019 * ReportedBoundsError exception. We really want
2020 * a tvbuff where the length is "length", the reported
2021 * length is "plen + 2", and the "if the snapshot length
2022 * were infinite" length is the minimum of the
2023 * reported length of the tvbuff handed to us and "plen+2",
2024 * with a new type of exception thrown if the offset is
2025 * within the reported length but beyond that third length,
2026 * with that exception getting the "Unreassembled Packet"
2029 length = length_remaining;
2030 if (length > plen + 2)
2032 next_tvb = tvb_new_subset(tvb, offset, length, plen + 2);
2035 * Dissect the DNS-over-TCP packet.
2037 * Catch the ReportedBoundsError exception; if this
2038 * particular message happens to get a ReportedBoundsError
2039 * exception, that doesn't mean that we should stop
2040 * dissecting DNS-over-TCP messages within this frame or
2041 * chunk of reassembled data.
2043 * If it gets a BoundsError, we can stop, as there's nothing
2044 * more to see, so we just re-throw it.
2047 dissect_dns_common(next_tvb, plen, pinfo, tree, TRUE);
2049 CATCH(BoundsError) {
2052 CATCH(ReportedBoundsError) {
2053 show_reported_bounds_error(tvb, pinfo, tree);
2058 * Skip the DNS-over-TCP header and the payload.
2065 proto_register_dns(void)
2067 static hf_register_info hf[] = {
2069 { "Length", "dns.length",
2070 FT_UINT16, BASE_DEC, NULL, 0x0,
2071 "Length of DNS-over-TCP request or response", HFILL }},
2073 { "Response", "dns.response",
2074 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2075 "TRUE if DNS response", HFILL }},
2077 { "Query", "dns.query",
2078 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2079 "TRUE if DNS query", HFILL }},
2081 { "Flags", "dns.flags",
2082 FT_UINT16, BASE_HEX, NULL, 0x0,
2084 { &hf_dns_transaction_id,
2085 { "Transaction ID", "dns.id",
2086 FT_UINT16, BASE_HEX, NULL, 0x0,
2087 "Identification of transaction", HFILL }},
2088 { &hf_dns_count_questions,
2089 { "Questions", "dns.count.queries",
2090 FT_UINT16, BASE_DEC, NULL, 0x0,
2091 "Number of queries in packet", HFILL }},
2092 { &hf_dns_count_answers,
2093 { "Answer RRs", "dns.count.answers",
2094 FT_UINT16, BASE_DEC, NULL, 0x0,
2095 "Number of answers in packet", HFILL }},
2096 { &hf_dns_count_auth_rr,
2097 { "Authority RRs", "dns.count.auth_rr",
2098 FT_UINT16, BASE_DEC, NULL, 0x0,
2099 "Number of authoritative records in packet", HFILL }},
2100 { &hf_dns_count_add_rr,
2101 { "Additional RRs", "dns.count.add_rr",
2102 FT_UINT16, BASE_DEC, NULL, 0x0,
2103 "Number of additional records in packet", HFILL }}
2105 static gint *ett[] = {
2114 module_t *dns_module;
2116 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2117 proto_register_field_array(proto_dns, hf, array_length(hf));
2118 proto_register_subtree_array(ett, array_length(ett));
2120 dns_module = prefs_register_protocol(proto_dns, NULL);
2121 prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2122 "Desegment all DNS messages spanning multiple TCP segments",
2123 "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
2128 proto_reg_handoff_dns(void)
2130 dissector_handle_t dns_udp_handle;
2131 dissector_handle_t dns_tcp_handle;
2133 dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
2134 dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
2135 dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
2136 dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);