2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.75 2001/09/17 02:07:00 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>
41 #include "packet-dns.h"
44 static int proto_dns = -1;
45 static int hf_dns_length = -1;
46 static int hf_dns_response = -1;
47 static int hf_dns_query = -1;
48 static int hf_dns_flags = -1;
49 static int hf_dns_transaction_id = -1;
50 static int hf_dns_count_questions = -1;
51 static int hf_dns_count_answers = -1;
52 static int hf_dns_count_auth_rr = -1;
53 static int hf_dns_count_add_rr = -1;
55 static gint ett_dns = -1;
56 static gint ett_dns_qd = -1;
57 static gint ett_dns_rr = -1;
58 static gint ett_dns_qry = -1;
59 static gint ett_dns_ans = -1;
60 static gint ett_dns_flags = -1;
61 static gint ett_t_key_flags = -1;
63 /* desegmentation of DNS over TCP */
64 static gboolean dns_desegment = TRUE;
66 /* DNS structs and definitions */
68 /* Ports used for DNS. */
69 #define UDP_PORT_DNS 53
70 #define TCP_PORT_DNS 53
72 /* Offsets of fields in the DNS header. */
80 /* Length of DNS header. */
84 #define T_A 1 /* host address */
85 #define T_NS 2 /* authoritative name server */
86 #define T_MD 3 /* mail destination (obsolete) */
87 #define T_MF 4 /* mail forwarder (obsolete) */
88 #define T_CNAME 5 /* canonical name */
89 #define T_SOA 6 /* start of authority zone */
90 #define T_MB 7 /* mailbox domain name (experimental) */
91 #define T_MG 8 /* mail group member (experimental) */
92 #define T_MR 9 /* mail rename domain name (experimental) */
93 #define T_NULL 10 /* null RR (experimental) */
94 #define T_WKS 11 /* well known service */
95 #define T_PTR 12 /* domain name pointer */
96 #define T_HINFO 13 /* host information */
97 #define T_MINFO 14 /* mailbox or mail list information */
98 #define T_MX 15 /* mail routing information */
99 #define T_TXT 16 /* text strings */
100 #define T_RP 17 /* responsible person (RFC 1183) */
101 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
102 #define T_X25 19 /* X.25 address (RFC 1183) */
103 #define T_ISDN 20 /* ISDN address (RFC 1183) */
104 #define T_RT 21 /* route-through (RFC 1183) */
105 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
106 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
107 #define T_SIG 24 /* digital signature (RFC 2535) */
108 #define T_KEY 25 /* public key (RFC 2535) */
109 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
110 #define T_GPOS 27 /* geographical position (RFC 1712) */
111 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
112 #define T_LOC 29 /* geographical location (RFC 1876) */
113 #define T_NXT 30 /* "next" name (RFC 2535) */
114 #define T_EID 31 /* ??? (Nimrod?) */
115 #define T_NIMLOC 32 /* ??? (Nimrod?) */
116 #define T_SRV 33 /* service location (RFC 2052) */
117 #define T_ATMA 34 /* ??? */
118 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
119 #define T_KX 36 /* Key Exchange (RFC 2230) */
120 #define T_CERT 37 /* Certificate (RFC 2538) */
121 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
122 #define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
123 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
124 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
125 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
126 #define T_WINS 65281 /* Microsoft's WINS RR */
127 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
130 #define C_IN 1 /* the Internet */
131 #define C_CS 2 /* CSNET (obsolete) */
132 #define C_CH 3 /* CHAOS */
133 #define C_HS 4 /* Hesiod */
134 #define C_NONE 254 /* none */
135 #define C_ANY 255 /* any */
137 /* Bit fields in the flags */
138 #define F_RESPONSE (1<<15) /* packet is response */
139 #define F_OPCODE (0xF<<11) /* query opcode */
140 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
141 #define F_TRUNCATED (1<<9) /* response is truncated */
142 #define F_RECDESIRED (1<<8) /* recursion desired */
143 #define F_RECAVAIL (1<<7) /* recursion available */
144 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
145 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
146 #define F_RCODE (0xF<<0) /* reply code */
149 #define OPCODE_QUERY (0<<11) /* standard query */
150 #define OPCODE_IQUERY (1<<11) /* inverse query */
151 #define OPCODE_STATUS (2<<11) /* server status request */
152 #define OPCODE_NOTIFY (4<<11) /* zone change notification */
153 #define OPCODE_UPDATE (5<<11) /* dynamic update */
156 #define RCODE_NOERROR (0<<0)
157 #define RCODE_FORMERR (1<<0)
158 #define RCODE_SERVFAIL (2<<0)
159 #define RCODE_NXDOMAIN (3<<0)
160 #define RCODE_NOTIMPL (4<<0)
161 #define RCODE_REFUSED (5<<0)
162 #define RCODE_YXDOMAIN (6<<0)
163 #define RCODE_YXRRSET (7<<0)
164 #define RCODE_NXRRSET (8<<0)
165 #define RCODE_NOTAUTH (9<<0)
166 #define RCODE_NOTZONE (10<<0)
168 static const value_string rcode_vals[] = {
169 { RCODE_NOERROR, "No error" },
170 { RCODE_FORMERR, "Format error" },
171 { RCODE_SERVFAIL, "Server failure" },
172 { RCODE_NXDOMAIN, "No such name" },
173 { RCODE_NOTIMPL, "Not implemented" },
174 { RCODE_REFUSED, "Refused" },
175 { RCODE_YXDOMAIN, "Name exists" },
176 { RCODE_YXRRSET, "RRset exists" },
177 { RCODE_NXRRSET, "RRset does not exist" },
178 { RCODE_NOTAUTH, "Not authoritative" },
179 { RCODE_NOTZONE, "Name out of zone" },
182 /* TSIG/TKEY extended errors */
183 #define TSIGERROR_BADSIG (16)
184 #define TSIGERROR_BADKEY (17)
185 #define TSIGERROR_BADTIME (18)
186 #define TSIGERROR_BADMODE (19)
187 #define TSIGERROR_BADNAME (20)
188 #define TSIGERROR_BADALG (21)
190 static const value_string tsigerror_vals[] = {
191 { TSIGERROR_BADSIG, "Bad signature" },
192 { TSIGERROR_BADKEY, "Bad key" },
193 { TSIGERROR_BADTIME, "Bad time failure" },
194 { TSIGERROR_BADMODE, "Bad mode such name" },
195 { TSIGERROR_BADNAME, "Bad name implemented" },
196 { TSIGERROR_BADALG, "Bad algorithm" },
199 #define TKEYMODE_SERVERASSIGNED (1)
200 #define TKEYMODE_DIFFIEHELLMAN (2)
201 #define TKEYMODE_GSSAPI (3)
202 #define TKEYMODE_RESOLVERASSIGNED (4)
203 #define TKEYMODE_DELETE (5)
205 /* See RFC 1035 for all RR types for which no RFC is listed, except for
206 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
207 which one should look at
209 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
213 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
215 which discuss them to some extent. */
217 dns_type_name (u_int type)
219 char *type_names[] = {
238 "AFSDB", /* RFC 1183 */
239 "X25", /* RFC 1183 */
240 "ISDN", /* RFC 1183 */
242 "NSAP", /* RFC 1706 */
243 "NSAP-PTR", /* RFC 1348 */
244 "SIG", /* RFC 2535 */
245 "KEY", /* RFC 2535 */
247 "GPOS", /* RFC 1712 */
248 "AAAA", /* RFC 1886 */
249 "LOC", /* RFC 1876 */
250 "NXT", /* RFC 2535 */
253 "SRV", /* RFC 2052 */
255 "NAPTR", /* RFC 2168 */
257 "CERT", /* RFC 2538 */
259 "DNAME", /* RFC 2672 */
264 if (type < sizeof(type_names)/sizeof(type_names[0]))
265 return type_names[type] ? type_names[type] : "unknown";
292 return "IXFR"; /* RFC 1995 */
309 dns_long_type_name (u_int type)
311 char *type_names[] = {
314 "Authoritative name server",
317 "Canonical name for an alias",
318 "Start of zone of authority",
319 "Mailbox domain name",
321 "Mail rename domain name",
322 "Null resource record",
323 "Well-known service description",
324 "Domain name pointer",
326 "Mailbox or mail list information",
329 "Responsible person", /* RFC 1183 */
330 "AFS data base location", /* RFC 1183 */
331 "X.25 address", /* RFC 1183 */
332 "ISDN number", /* RFC 1183 */
333 "Route through", /* RFC 1183 */
334 "OSI NSAP", /* RFC 1706 */
335 "OSI NSAP name pointer", /* RFC 1348 */
336 "Signature", /* RFC 2535 */
337 "Public key", /* RFC 2535 */
338 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
339 "Geographical position", /* RFC 1712 */
340 "IPv6 address", /* RFC 1886 */
341 "Location", /* RFC 1876 */
342 "Next", /* RFC 2535 */
345 "Service location", /* RFC 2052 */
347 "Naming authority pointer", /* RFC 2168 */
348 "Key Exchange", /* RFC 2230 */
349 "Certificate", /* RFC 2538 */
350 "IPv6 address with indirection", /* RFC 2874 */
351 "Non-terminal DNS name redirection", /* RFC 2672 */
353 "EDNS0 option" /* RFC 2671 */
355 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%d)" */
357 if (type < sizeof(type_names)/sizeof(type_names[0]))
358 return type_names[type] ? type_names[type] : "unknown";
379 return "Transaction Key";
381 return "Transaction Signature";
385 return "Request for incremental zone transfer"; /* RFC 1995 */
387 return "Request for full zone transfer";
389 return "Request for mailbox-related records";
391 return "Request for mail agent resource records";
393 return "Request for all records";
396 sprintf(unkbuf, "Unknown RR type (%d)", type);
402 dns_class_name(int class)
411 class_name = "csnet";
414 class_name = "chaos";
417 class_name = "hesiod";
426 class_name = "unknown";
433 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
434 char *name, int maxname)
436 int start_offset = offset;
439 int chars_processed = 0;
440 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
444 maxname--; /* reserve space for the trailing '\0' */
446 component_len = tvb_get_guint8(tvb, offset);
448 if (component_len == 0)
451 switch (component_len & 0xc0) {
456 /* Not the first component - put in a '.'. */
462 while (component_len > 0) {
464 *np++ = tvb_get_guint8(tvb, offset);
474 /* Extended label (RFC 2673) */
475 switch (component_len & 0x3f) {
478 /* Bitstring label */
483 bit_count = tvb_get_guint8(tvb, offset);
485 label_len = (bit_count - 1) / 8 + 1;
487 np += sprintf(np, "\\[x");
489 np += sprintf(np, "%02x", tvb_get_guint8(tvb, offset));
492 np += sprintf(np, "/%d]", bit_count);
497 strcpy(name, "<Unknown extended label>");
498 /* Parsing will propably fail from here on, since the */
499 /* label length is unknown... */
500 return offset - start_offset;
505 goto error; /* error */
509 indir_offset = dns_data_offset +
510 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
514 /* If "len" is negative, we are still working on the original name,
515 not something pointed to by a pointer, and so we should set "len"
516 to the length of the original name. */
518 len = offset - start_offset;
520 /* If we've looked at every character in the message, this pointer
521 will make us look at some character again, which means we're
523 if (chars_processed >= data_size) {
524 strcpy(name, "<Name contains a pointer that loops>");
528 offset = indir_offset;
529 break; /* now continue processing from there */
535 /* If "len" is negative, we haven't seen a pointer, and thus haven't
536 set the length, so set it. */
538 len = offset - start_offset;
539 /* Zero-length name means "root server" */
541 strcpy(name, "<Root>");
547 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
548 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
555 int start_offset = offset;
557 name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
560 type = tvb_get_ntohs(tvb, offset);
563 class = tvb_get_ntohs(tvb, offset);
566 strcpy (name_ret, name);
569 *name_len_ret = name_len;
571 len = offset - start_offset;
576 rfc1867_size(tvbuff_t *tvb, int offset)
582 val = tvb_get_guint8(tvb, offset);
583 size = (val & 0xF0) >> 4;
584 exponent = (val & 0x0F);
585 while (exponent != 0) {
589 return size / 100; /* return size in meters, not cm */
593 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
597 guint32 degrees, minutes, secs, tsecs;
598 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
600 angle = tvb_get_ntohl(tvb, offset);
602 if (angle < 0x80000000U) {
603 angle = 0x80000000U - angle;
606 angle = angle - 0x80000000U;
609 tsecs = angle % 1000;
610 angle = angle / 1000;
613 minutes = angle % 60;
614 degrees = angle / 60;
615 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
621 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
622 frame_data *fd, proto_tree *dns_tree)
631 char *long_type_name;
637 data_start = data_offset = offset;
639 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
642 /* We ran past the end of the data in the packet. */
647 type_name = dns_type_name(type);
648 class_name = dns_class_name(class);
649 long_type_name = dns_long_type_name(type);
652 col_append_fstr(fd, COL_INFO, " %s %s", type_name, name);
653 if (dns_tree != NULL) {
654 tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
655 name, type_name, class_name);
656 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
658 proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
661 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
664 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
668 return data_offset - data_start;
673 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
674 const char *name, int namelen, const char *type_name, const char *class_name,
675 u_int ttl, u_short data_len)
679 rr_tree = proto_item_add_subtree(trr, rr_type);
680 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
682 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
684 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
686 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
687 time_secs_to_str(ttl));
689 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
694 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
695 const char *name, int namelen, const char *type_name, int class,
696 u_int ttl, u_short data_len)
700 rr_tree = proto_item_add_subtree(trr, rr_type);
701 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
703 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
705 proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
708 proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
709 (ttl >> 24) & 0xff0);
711 proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
714 proto_tree_add_text(rr_tree, tvb, offset, 2, "Must be zero: 0x%x", ttl & 0xffff);
716 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
721 * SIG, KEY, and CERT RR algorithms.
723 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
724 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
725 #define DNS_ALGO_DSA 3 /* DSA */
726 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
727 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
728 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
729 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
731 static const value_string algo_vals[] = {
732 { DNS_ALGO_RSAMD5, "RSA/MD5" },
733 { DNS_ALGO_DH, "Diffie-Hellman" },
734 { DNS_ALGO_DSA, "DSA" },
735 { DNS_ALGO_ECC, "Elliptic curve crypto" },
736 { DNS_ALGO_INDIRECT, "Indirect key" },
737 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
738 { DNS_ALGO_PRIVATEOID, "Private, OID" },
742 #define DNS_CERT_PGP 1 /* PGP */
743 #define DNS_CERT_PKIX 2 /* PKIX */
744 #define DNS_CERT_SPKI 3 /* SPKI */
745 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
746 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
748 static const value_string cert_vals[] = {
749 { DNS_CERT_PGP, "PGP" },
750 { DNS_CERT_PKIX, "PKIX" },
751 { DNS_CERT_SPKI, "SPKI" },
752 { DNS_CERT_PRIVATEURI, "Private, URI" },
753 { DNS_CERT_PRIVATEOID, "Private, OID" },
758 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
759 frame_data *fd, proto_tree *dns_tree)
768 char *long_type_name;
774 proto_tree *rr_tree = NULL;
775 proto_item *trr = NULL;
777 data_start = data_offset = offset;
780 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
785 type_name = dns_type_name(type);
786 class_name = dns_class_name(class);
787 long_type_name = dns_long_type_name(type);
789 ttl = tvb_get_ntohl(tvb, data_offset);
793 data_len = tvb_get_ntohs(tvb, data_offset);
798 col_append_fstr(fd, COL_INFO, " %s", type_name);
799 if (dns_tree != NULL) {
800 trr = proto_tree_add_text(dns_tree, tvb, offset,
801 (data_offset - data_start) + data_len,
802 "%s: type %s, class %s",
803 name, type_name, class_name);
805 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
806 long_type_name, class_name, ttl, data_len);
808 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
809 long_type_name, class, ttl, data_len);
820 addr = tvb_get_ptr(tvb, cur_offset, 4);
822 col_append_fstr(fd, COL_INFO, " %s", ip_to_str(addr));
823 if (dns_tree != NULL) {
824 proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
825 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
829 memcpy(&addr_int, addr, sizeof(addr_int));
830 add_host_name(addr_int, name);
837 char ns_name[MAXDNAME];
840 ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
842 col_append_fstr(fd, COL_INFO, " %s", ns_name);
843 if (dns_tree != NULL) {
844 proto_item_append_text(trr, ", ns %s", ns_name);
845 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
853 char cname[MAXDNAME];
856 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
858 col_append_fstr(fd, COL_INFO, " %s", cname);
859 if (dns_tree != NULL) {
860 proto_item_append_text(trr, ", cname %s", cname);
861 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
869 char mname[MAXDNAME];
871 char rname[MAXDNAME];
879 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
881 col_append_fstr(fd, COL_INFO, " %s", mname);
882 if (dns_tree != NULL) {
883 proto_item_append_text(trr, ", mname %s", mname);
884 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
886 cur_offset += mname_len;
888 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
889 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
891 cur_offset += rname_len;
893 serial = tvb_get_ntohl(tvb, cur_offset);
894 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
898 refresh = tvb_get_ntohl(tvb, cur_offset);
899 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
900 time_secs_to_str(refresh));
903 retry = tvb_get_ntohl(tvb, cur_offset);
904 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
905 time_secs_to_str(retry));
908 expire = tvb_get_ntohl(tvb, cur_offset);
909 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
910 time_secs_to_str(expire));
913 minimum = tvb_get_ntohl(tvb, cur_offset);
914 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
915 time_secs_to_str(minimum));
922 char pname[MAXDNAME];
925 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
927 col_append_fstr(fd, COL_INFO, " %s", pname);
928 if (dns_tree != NULL) {
929 proto_item_append_text(trr, ", ptr %s", pname);
930 proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
939 int rr_len = data_len;
940 const guint8 *wks_addr;
946 char bitnames[128+1];
947 char portnumstring[10+1];
949 wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
951 col_append_fstr(fd, COL_INFO, " %s", ip_to_str(wks_addr));
952 if (dns_tree != NULL) {
953 proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
954 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
955 ip_to_str(wks_addr));
959 protocol = tvb_get_guint8(tvb, cur_offset);
960 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
961 ipprotostr(protocol));
966 while (rr_len != 0) {
967 bits = tvb_get_guint8(tvb, cur_offset);
971 for (i = 0; i < 8; i++) {
973 if (bitnames[0] != '\0')
974 strcat(bitnames, ", ");
978 strcat(bitnames, get_tcp_port(port_num));
982 strcat(bitnames, get_udp_port(port_num));
986 sprintf(portnumstring, "%u", port_num);
987 strcat(bitnames, portnumstring);
994 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
995 "Bits: 0x%02x (%s)", bits, bitnames);
1014 cpu_offset = cur_offset;
1015 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1016 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1017 os_offset = cpu_offset + 1 + cpu_len;
1018 os_len = tvb_get_guint8(tvb, os_offset);
1019 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1021 col_append_fstr(fd, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1023 if (dns_tree != NULL) {
1024 proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1025 cpu_len, cpu, os_len, os);
1026 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1028 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1037 guint16 preference = 0;
1038 char mx_name[MAXDNAME];
1041 preference = tvb_get_ntohs(tvb, cur_offset);
1042 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1044 col_append_fstr(fd, COL_INFO, " %u %s", preference, mx_name);
1045 if (dns_tree != NULL) {
1046 proto_item_append_text(trr, ", preference %u, mx %s",
1047 preference, mx_name);
1048 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1049 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1057 int rr_len = data_len;
1061 if (dns_tree != NULL) {
1062 txt_offset = cur_offset;
1063 while (rr_len != 0) {
1064 txt_len = tvb_get_guint8(tvb, txt_offset);
1065 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1066 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1067 txt_offset += 1 + txt_len;
1068 rr_len -= 1 + txt_len;
1076 int rr_len = data_len;
1077 guint16 type_covered;
1079 char signer_name[MAXDNAME];
1080 int signer_name_len;
1082 if (dns_tree != NULL) {
1083 type_covered = tvb_get_ntohs(tvb, cur_offset);
1084 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1085 dns_type_name(type_covered),
1086 dns_long_type_name(type_covered));
1090 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1091 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1092 "Unknown (0x%02X)"));
1096 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1097 tvb_get_guint8(tvb, cur_offset));
1101 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1102 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1106 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1108 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1109 abs_time_to_str(&nstime));
1113 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1115 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1116 abs_time_to_str(&nstime));
1120 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1121 tvb_get_ntohs(tvb, cur_offset));
1125 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1126 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1127 "Signer's name: %s", signer_name);
1128 cur_offset += signer_name_len;
1129 rr_len -= signer_name_len;
1131 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1138 int rr_len = data_len;
1141 proto_tree *flags_tree;
1143 if (dns_tree != NULL) {
1144 flags = tvb_get_ntohs(tvb, cur_offset);
1145 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1146 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1147 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1148 decode_boolean_bitfield(flags, 0x8000,
1149 2*8, "Key prohibited for authentication",
1150 "Key allowed for authentication"));
1151 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1152 decode_boolean_bitfield(flags, 0x4000,
1153 2*8, "Key prohibited for confidentiality",
1154 "Key allowed for confidentiality"));
1155 if ((flags & 0xC000) != 0xC000) {
1157 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1158 decode_boolean_bitfield(flags, 0x2000,
1159 2*8, "Key is experimental or optional",
1160 "Key is required"));
1161 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1162 decode_boolean_bitfield(flags, 0x0400,
1163 2*8, "Key is associated with a user",
1164 "Key is not associated with a user"));
1165 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1166 decode_boolean_bitfield(flags, 0x0200,
1167 2*8, "Key is associated with the named entity",
1168 "Key is not associated with the named entity"));
1169 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1170 decode_boolean_bitfield(flags, 0x0100,
1171 2*8, "This is the zone key for the specified zone",
1172 "This is not a zone key"));
1173 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1174 decode_boolean_bitfield(flags, 0x0080,
1175 2*8, "Key is valid for use with IPSEC",
1176 "Key is not valid for use with IPSEC"));
1177 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1178 decode_boolean_bitfield(flags, 0x0040,
1179 2*8, "Key is valid for use with MIME security multiparts",
1180 "Key is not valid for use with MIME security multiparts"));
1181 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1182 decode_numeric_bitfield(flags, 0x000F,
1183 2*8, "Signatory = %u"));
1188 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1189 tvb_get_guint8(tvb, cur_offset));
1193 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1194 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1195 "Unknown (0x%02X)"));
1199 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1206 const guint8 *addr6;
1208 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1210 col_append_fstr(fd, COL_INFO, " %s",
1211 ip6_to_str((struct e_in6_addr *)addr6));
1213 if (dns_tree != NULL) {
1214 proto_item_append_text(trr, ", addr %s",
1215 ip6_to_str((struct e_in6_addr *)addr6));
1216 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1217 ip6_to_str((struct e_in6_addr *)addr6));
1224 unsigned short pre_len;
1225 unsigned short suf_len;
1226 unsigned short suf_octet_count;
1227 char pname[MAXDNAME];
1233 a6_offset = cur_offset;
1234 pre_len = tvb_get_guint8(tvb, cur_offset);
1236 suf_len = 128 - pre_len;
1237 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1239 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1240 suffix[suf_offset] = 0;
1242 for (; suf_offset < 16; suf_offset++) {
1243 suffix[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1248 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1249 pname, sizeof(pname));
1256 col_append_fstr(fd, COL_INFO, " %d %s %s",
1258 ip6_to_str((struct e_in6_addr *)&suffix),
1261 if (dns_tree != NULL) {
1262 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1263 "Prefix len: %u", pre_len);
1266 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1267 "Address suffix: %s",
1268 ip6_to_str((struct e_in6_addr *)&suffix));
1269 a6_offset += suf_octet_count;
1272 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1273 "Prefix name: %s", pname);
1275 proto_item_append_text(trr, ", addr %d %s %s",
1277 ip6_to_str((struct e_in6_addr *)&suffix),
1285 char dname[MAXDNAME];
1288 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1289 dname, sizeof(dname));
1291 col_append_fstr(fd, COL_INFO, " %s", dname);
1292 if (dns_tree != NULL) {
1293 proto_item_append_text(trr, ", dname %s", dname);
1294 proto_tree_add_text(rr_tree, tvb, cur_offset,
1295 dname_len, "Target name: %s", dname);
1304 if (dns_tree != NULL) {
1305 version = tvb_get_guint8(tvb, cur_offset);
1306 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1308 /* Version 0, the only version RFC 1876 discusses. */
1311 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1312 rfc1867_size(tvb, cur_offset));
1315 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1316 rfc1867_size(tvb, cur_offset));
1319 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1320 rfc1867_size(tvb, cur_offset));
1323 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1324 rfc1867_angle(tvb, cur_offset, "NS"));
1327 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1328 rfc1867_angle(tvb, cur_offset, "EW"));
1331 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1332 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1334 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1342 int rr_len = data_len;
1343 char next_domain_name[MAXDNAME];
1344 int next_domain_name_len;
1350 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1351 next_domain_name, sizeof(next_domain_name));
1353 col_append_fstr(fd, COL_INFO, " %s", next_domain_name);
1354 if (dns_tree != NULL) {
1355 proto_item_append_text(trr, ", next domain name %s",
1357 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1358 "Next domain name: %s", next_domain_name);
1359 cur_offset += next_domain_name_len;
1360 rr_len -= next_domain_name_len;
1362 while (rr_len != 0) {
1363 bits = tvb_get_guint8(tvb, cur_offset);
1365 for (i = 0; i < 8; i++) {
1367 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1368 "RR type in bit map: %s (%s)",
1369 dns_type_name(rr_type),
1370 dns_long_type_name(rr_type));
1384 guint16 preference = 0;
1385 char kx_name[MAXDNAME];
1388 preference = tvb_get_ntohs(tvb, cur_offset);
1389 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1391 col_append_fstr(fd, COL_INFO, " %u %s", preference, kx_name);
1392 if (dns_tree != NULL) {
1393 proto_item_append_text(trr, ", preference %u, kx %s",
1394 preference, kx_name);
1395 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1396 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1404 guint16 cert_type, cert_keytag;
1406 int rr_len = data_len;
1408 cert_type = tvb_get_ntohs(tvb, cur_offset);
1411 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1414 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1418 if (dns_tree != NULL) {
1419 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s",
1420 val_to_str(cert_keyalg, cert_vals,
1421 "Unknown (0x%02X)"));
1422 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1424 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1425 val_to_str(cert_keyalg, algo_vals,
1426 "Unknown (0x%02X)"));
1427 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1434 if (dns_tree != NULL)
1435 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1440 char tkey_algname[MAXDNAME];
1441 int tkey_algname_len;
1442 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1443 int rr_len = data_len;
1445 static const value_string tkey_modes[] = {
1446 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1447 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1448 { TKEYMODE_GSSAPI, "GSSAPI" },
1449 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1450 { TKEYMODE_DELETE, "Delete" },
1453 if (dns_tree != NULL) {
1454 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1455 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1456 "Algorithm name: %s", tkey_algname);
1457 cur_offset += tkey_algname_len;
1458 rr_len -= tkey_algname_len;
1460 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1462 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1463 abs_time_to_str(&nstime));
1467 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1469 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1470 abs_time_to_str(&nstime));
1474 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1477 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Mode: %s",
1478 val_to_str(tkey_mode, tkey_modes,
1479 "Unknown (0x%02X)"));
1481 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1485 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Error: %s",
1486 val_to_str(tkey_error, rcode_vals,
1487 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1489 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1493 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1494 cur_offset += tkey_keylen;
1495 rr_len -= tkey_keylen;
1497 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1501 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1502 cur_offset += tkey_otherlen;
1503 rr_len -= tkey_otherlen;
1511 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1512 guint32 tsig_timelo;
1513 char tsig_algname[MAXDNAME];
1514 int tsig_algname_len;
1516 int rr_len = data_len;
1518 if (dns_tree != NULL) {
1519 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1520 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1521 "Algorithm name: %s", tsig_algname);
1522 cur_offset += tsig_algname_len;
1523 rr_len -= tsig_algname_len;
1525 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1526 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1527 nstime.secs = tsig_timelo;
1529 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1530 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
1534 tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1535 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1540 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1544 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1545 cur_offset += tsig_siglen;
1546 rr_len -= tsig_siglen;
1548 tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1549 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1554 tsig_error = tvb_get_ntohs(tvb, cur_offset);
1555 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1556 val_to_str(tsig_error, rcode_vals,
1557 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1561 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1565 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1566 cur_offset += tsig_otherlen;
1567 rr_len -= tsig_otherlen;
1574 int rr_len = data_len;
1576 guint32 lookup_timeout;
1577 guint32 cache_timeout;
1580 if (dns_tree != NULL) {
1581 local_flag = tvb_get_ntohl(tvb, cur_offset);
1582 if (dns_tree != NULL) {
1583 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1584 local_flag ? "true" : "false");
1589 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1590 if (dns_tree != NULL) {
1591 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1597 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1598 if (dns_tree != NULL) {
1599 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1605 nservers = tvb_get_ntohl(tvb, cur_offset);
1606 if (dns_tree != NULL) {
1607 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
1613 while (rr_len != 0 && nservers != 0) {
1614 if (dns_tree != NULL) {
1615 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
1616 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
1628 int rr_len = data_len;
1630 guint32 lookup_timeout;
1631 guint32 cache_timeout;
1632 char dname[MAXDNAME];
1635 local_flag = tvb_get_ntohl(tvb, cur_offset);
1636 if (dns_tree != NULL) {
1637 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1638 local_flag ? "true" : "false");
1643 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1644 if (dns_tree != NULL) {
1645 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1651 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1652 if (dns_tree != NULL) {
1653 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1659 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1661 col_append_fstr(fd, COL_INFO, " %s", dname);
1662 if (dns_tree != NULL) {
1663 proto_item_append_text(trr, ", name result domain %s", dname);
1664 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
1672 guint16 priority = 0;
1675 char target[MAXDNAME];
1678 priority = tvb_get_ntohs(tvb, cur_offset);
1679 weight = tvb_get_ntohs(tvb, cur_offset+2);
1680 port = tvb_get_ntohs(tvb, cur_offset+4);
1682 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1684 col_append_fstr(fd, COL_INFO, " %u %u %u %s", priority, weight, port, target);
1685 if (dns_tree != NULL) {
1686 proto_item_append_text(trr,
1687 ", priority %u, weight %u, port %u, target %s",
1688 priority, weight, port, target);
1689 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
1690 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
1691 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
1692 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
1698 /* TODO: parse more record types */
1701 if (dns_tree != NULL)
1702 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1706 data_offset += data_len;
1708 return data_offset - data_start;
1712 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1713 int count, frame_data *fd, proto_tree *dns_tree, int isupdate)
1715 int start_off, add_off;
1716 proto_tree *qatree = NULL;
1717 proto_item *ti = NULL;
1719 start_off = cur_off;
1721 char *s = (isupdate ? "Zone" : "Queries");
1722 ti = proto_tree_add_text(dns_tree, tvb, start_off, 0, s);
1723 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1725 while (count-- > 0) {
1726 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, fd, qatree);
1728 /* We ran past the end of the captured data in the packet. */
1734 proto_item_set_len(ti, cur_off - start_off);
1736 return cur_off - start_off;
1740 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1741 int count, frame_data *fd, proto_tree *dns_tree, char *name)
1743 int start_off, add_off;
1744 proto_tree *qatree = NULL;
1745 proto_item *ti = NULL;
1747 start_off = cur_off;
1749 ti = proto_tree_add_text(dns_tree, tvb, start_off, 0, name);
1750 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1752 while (count-- > 0) {
1753 add_off = dissect_dns_answer(tvb, cur_off, dns_data_offset, fd, qatree);
1755 /* We ran past the end of the captured data in the packet. */
1761 proto_item_set_len(ti, cur_off - start_off);
1763 return cur_off - start_off;
1767 dissect_dns_common(tvbuff_t *tvb, int offset, int msg_len, packet_info *pinfo,
1768 proto_tree *tree, gboolean is_tcp)
1770 int dns_data_offset;
1772 proto_tree *dns_tree = NULL, *field_tree;
1773 proto_item *ti, *tf;
1774 guint16 id, flags, quest, ans, auth, add;
1778 static const value_string opcode_vals[] = {
1779 { OPCODE_QUERY, "Standard query" },
1780 { OPCODE_IQUERY, "Inverse query" },
1781 { OPCODE_STATUS, "Server status request" },
1782 { OPCODE_NOTIFY, "Zone change notification" },
1783 { OPCODE_UPDATE, "Dynamic update" },
1786 dns_data_offset = offset;
1788 if (check_col(pinfo->fd, COL_PROTOCOL))
1789 col_set_str(pinfo->fd, COL_PROTOCOL, "DNS");
1790 if (check_col(pinfo->fd, COL_INFO))
1791 col_clear(pinfo->fd, COL_INFO);
1793 /* To do: check for errs, etc. */
1794 id = tvb_get_ntohs(tvb, offset + DNS_ID);
1795 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
1797 if (check_col(pinfo->fd, COL_INFO)) {
1798 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation (%x)"));
1799 if (flags & F_RESPONSE) {
1800 strcat(buf, " response");
1801 if ((flags & F_RCODE) != RCODE_NOERROR) {
1803 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1804 "Unknown error (%x)"));
1807 col_add_str(pinfo->fd, COL_INFO, buf);
1810 /* Set "fd" to NULL; we pass a NULL "fd" to the query and answer
1811 dissectors, as a way of saying that they shouldn't add stuff
1812 to the COL_INFO column (a call to "check_col(fd, COL_INFO)"
1813 is more expensive than a check that a pointer isn't NULL). */
1816 if ((flags & F_OPCODE) == OPCODE_UPDATE)
1822 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, offset, msg_len,
1823 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1825 dns_tree = proto_item_add_subtree(ti, ett_dns);
1828 /* Put the length indication into the tree. */
1829 proto_tree_add_uint(dns_tree, hf_dns_length, tvb, offset - 2, 2, msg_len);
1832 if (flags & F_RESPONSE)
1833 proto_tree_add_boolean_hidden(dns_tree, hf_dns_response, tvb, offset, 4, 1);
1835 proto_tree_add_boolean_hidden(dns_tree, hf_dns_query, tvb, offset, 4, 1);
1837 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
1838 offset + DNS_ID, 2, id);
1840 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
1841 if (flags & F_RESPONSE) {
1842 strcat(buf, " response");
1844 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1847 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
1848 offset + DNS_FLAGS, 2,
1850 "Flags: 0x%04x (%s)",
1852 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1853 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1854 decode_boolean_bitfield(flags, F_RESPONSE,
1855 2*8, "Response", "Query"));
1856 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1857 decode_enumerated_bitfield(flags, F_OPCODE,
1858 2*8, opcode_vals, "%s"));
1859 if (flags & F_RESPONSE) {
1860 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1861 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
1863 "Server is an authority for domain",
1864 "Server is not an authority for domain"));
1866 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1867 decode_boolean_bitfield(flags, F_TRUNCATED,
1869 "Message is truncated",
1870 "Message is not truncated"));
1871 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1872 decode_boolean_bitfield(flags, F_RECDESIRED,
1874 "Do query recursively",
1875 "Don't do query recursively"));
1876 if (flags & F_RESPONSE) {
1877 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1878 decode_boolean_bitfield(flags, F_RECAVAIL,
1880 "Server can do recursive queries",
1881 "Server can't do recursive queries"));
1882 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1883 decode_boolean_bitfield(flags, F_AUTHENTIC,
1885 "Answer/authority portion was authenticated by the server",
1886 "Answer/authority portion was not authenticated by the server"));
1888 if ((flags & F_RESPONSE) == 0) {
1889 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1890 decode_boolean_bitfield(flags, F_CHECKDISABLE,
1892 "Non-authenticated data is acceptable",
1893 "Non-authenticated data is unacceptable"));
1895 if (flags & F_RESPONSE) {
1896 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1897 decode_enumerated_bitfield(flags, F_RCODE,
1898 2*8, rcode_vals, "%s"));
1901 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
1903 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
1904 offset + DNS_QUEST, 2, quest);
1906 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
1908 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
1909 offset + DNS_ANS, 2, ans);
1911 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
1913 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
1914 offset + DNS_AUTH, 2, auth);
1916 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
1918 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
1919 offset + DNS_ADD, 2, add);
1922 cur_off = offset + DNS_HDRLEN;
1925 /* If this is a response, don't add information about the queries
1926 to the summary, just add information about the answers. */
1927 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
1928 (!(flags & F_RESPONSE) ? fd : NULL),
1929 dns_tree, isupdate);
1933 /* If this is a request, don't add information about the answers
1934 to the summary, just add information about the queries. */
1935 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
1936 ((flags & F_RESPONSE) ? fd : NULL),
1938 (isupdate ? "Prerequisites" : "Answers"));
1941 /* Don't add information about the authoritative name servers, or the
1942 additional records, to the summary. */
1944 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
1946 (isupdate ? "Updates" :
1947 "Authoritative nameservers"));
1951 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
1952 NULL, dns_tree, "Additional records");
1959 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1961 dissect_dns_common(tvb, 0, tvb_length(tvb), pinfo, tree, FALSE);
1965 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1972 * XXX - should handle a length field split across segment
1975 if (!tvb_bytes_exist(tvb, offset, 2))
1977 plen = tvb_get_ntohs(tvb, offset);
1980 * Desegmentation check.
1982 if (dns_desegment) {
1983 if (pinfo->can_desegment
1984 && plen > tvb_length_remaining(tvb, offset+2)) {
1986 * This frame doesn't have all of the data
1987 * for this message, but we can do reassembly
1990 * Tell the TCP dissector where the data for
1991 * this message starts in the data it handed
1992 * us, and how many more bytes we need, and
1995 pinfo->desegment_offset = offset;
1996 pinfo->desegment_len =
1997 plen - tvb_length_remaining(tvb, offset+2);
2005 * Is all of the DNS message in this TCP segment?
2007 if (tvb_reported_length_remaining(tvb, offset) < plen)
2013 offset = dissect_dns_common(tvb, offset, plen, pinfo, tree,
2019 proto_register_dns(void)
2021 static hf_register_info hf[] = {
2023 { "Length", "dns.length",
2024 FT_UINT16, BASE_DEC, NULL, 0x0,
2025 "Length of DNS-over-TCP request or response", HFILL }},
2027 { "Response", "dns.response",
2028 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2029 "TRUE if DNS response", HFILL }},
2031 { "Query", "dns.query",
2032 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2033 "TRUE if DNS query", HFILL }},
2035 { "Flags", "dns.flags",
2036 FT_UINT16, BASE_HEX, NULL, 0x0,
2038 { &hf_dns_transaction_id,
2039 { "Transaction ID", "dns.id",
2040 FT_UINT16, BASE_HEX, NULL, 0x0,
2041 "Identification of transaction", HFILL }},
2042 { &hf_dns_count_questions,
2043 { "Questions", "dns.count.queries",
2044 FT_UINT16, BASE_DEC, NULL, 0x0,
2045 "Number of queries in packet", HFILL }},
2046 { &hf_dns_count_answers,
2047 { "Answer RRs", "dns.count.answers",
2048 FT_UINT16, BASE_DEC, NULL, 0x0,
2049 "Number of answers in packet", HFILL }},
2050 { &hf_dns_count_auth_rr,
2051 { "Authority RRs", "dns.count.auth_rr",
2052 FT_UINT16, BASE_DEC, NULL, 0x0,
2053 "Number of authoritative records in packet", HFILL }},
2054 { &hf_dns_count_add_rr,
2055 { "Additional RRs", "dns.count.add_rr",
2056 FT_UINT16, BASE_DEC, NULL, 0x0,
2057 "Number of additional records in packet", HFILL }}
2059 static gint *ett[] = {
2068 module_t *dns_module;
2070 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2071 proto_register_field_array(proto_dns, hf, array_length(hf));
2072 proto_register_subtree_array(ett, array_length(ett));
2074 dns_module = prefs_register_protocol(proto_dns, NULL);
2075 prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2076 "Desegment all DNS messages spanning multiple TCP segments",
2077 "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
2082 proto_reg_handoff_dns(void)
2084 dissector_add("udp.port", UDP_PORT_DNS, dissect_dns_udp, proto_dns);
2085 dissector_add("tcp.port", TCP_PORT_DNS, dissect_dns_tcp, proto_dns);