2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.79 2002/01/20 22:12:25 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 column_info *cinfo, 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,
643 type_name = dns_type_name(type);
644 class_name = dns_class_name(class);
645 long_type_name = dns_long_type_name(type);
648 col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
649 if (dns_tree != NULL) {
650 tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s",
651 name, type_name, class_name);
652 q_tree = proto_item_add_subtree(tq, ett_dns_qd);
654 proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
657 proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
660 proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
664 return data_offset - data_start;
669 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
670 const char *name, int namelen, const char *type_name, const char *class_name,
671 u_int ttl, u_short data_len)
675 rr_tree = proto_item_add_subtree(trr, rr_type);
676 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
678 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
680 proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
682 proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
683 time_secs_to_str(ttl));
685 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
690 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
691 const char *name, int namelen, const char *type_name, int class,
692 u_int ttl, u_short data_len)
696 rr_tree = proto_item_add_subtree(trr, rr_type);
697 proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
699 proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
701 proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
704 proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
705 (ttl >> 24) & 0xff0);
707 proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
710 proto_tree_add_text(rr_tree, tvb, offset, 2, "Must be zero: 0x%x", ttl & 0xffff);
712 proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
717 * SIG, KEY, and CERT RR algorithms.
719 #define DNS_ALGO_RSAMD5 1 /* RSA/MD5 */
720 #define DNS_ALGO_DH 2 /* Diffie-Hellman */
721 #define DNS_ALGO_DSA 3 /* DSA */
722 #define DNS_ALGO_ECC 4 /* Elliptic curve crypto */
723 #define DNS_ALGO_INDIRECT 252 /* Indirect key */
724 #define DNS_ALGO_PRIVATEDNS 253 /* Private, domain name */
725 #define DNS_ALGO_PRIVATEOID 254 /* Private, OID */
727 static const value_string algo_vals[] = {
728 { DNS_ALGO_RSAMD5, "RSA/MD5" },
729 { DNS_ALGO_DH, "Diffie-Hellman" },
730 { DNS_ALGO_DSA, "DSA" },
731 { DNS_ALGO_ECC, "Elliptic curve crypto" },
732 { DNS_ALGO_INDIRECT, "Indirect key" },
733 { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
734 { DNS_ALGO_PRIVATEOID, "Private, OID" },
738 #define DNS_CERT_PGP 1 /* PGP */
739 #define DNS_CERT_PKIX 2 /* PKIX */
740 #define DNS_CERT_SPKI 3 /* SPKI */
741 #define DNS_CERT_PRIVATEURI 253 /* Private, URI */
742 #define DNS_CERT_PRIVATEOID 254 /* Private, OID */
744 static const value_string cert_vals[] = {
745 { DNS_CERT_PGP, "PGP" },
746 { DNS_CERT_PKIX, "PKIX" },
747 { DNS_CERT_SPKI, "SPKI" },
748 { DNS_CERT_PRIVATEURI, "Private, URI" },
749 { DNS_CERT_PRIVATEOID, "Private, OID" },
754 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
755 column_info *cinfo, proto_tree *dns_tree)
764 char *long_type_name;
770 proto_tree *rr_tree = NULL;
771 proto_item *trr = NULL;
773 data_start = data_offset = offset;
776 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
781 type_name = dns_type_name(type);
782 class_name = dns_class_name(class);
783 long_type_name = dns_long_type_name(type);
785 ttl = tvb_get_ntohl(tvb, data_offset);
789 data_len = tvb_get_ntohs(tvb, data_offset);
794 col_append_fstr(cinfo, COL_INFO, " %s", type_name);
795 if (dns_tree != NULL) {
796 trr = proto_tree_add_text(dns_tree, tvb, offset,
797 (data_offset - data_start) + data_len,
798 "%s: type %s, class %s",
799 name, type_name, class_name);
801 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
802 long_type_name, class_name, ttl, data_len);
804 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
805 long_type_name, class, ttl, data_len);
816 addr = tvb_get_ptr(tvb, cur_offset, 4);
818 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
819 if (dns_tree != NULL) {
820 proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
821 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
825 memcpy(&addr_int, addr, sizeof(addr_int));
826 add_host_name(addr_int, name);
833 char ns_name[MAXDNAME];
836 ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
838 col_append_fstr(cinfo, COL_INFO, " %s", ns_name);
839 if (dns_tree != NULL) {
840 proto_item_append_text(trr, ", ns %s", ns_name);
841 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
849 char cname[MAXDNAME];
852 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
854 col_append_fstr(cinfo, COL_INFO, " %s", cname);
855 if (dns_tree != NULL) {
856 proto_item_append_text(trr, ", cname %s", cname);
857 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
865 char mname[MAXDNAME];
867 char rname[MAXDNAME];
875 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
877 col_append_fstr(cinfo, COL_INFO, " %s", mname);
878 if (dns_tree != NULL) {
879 proto_item_append_text(trr, ", mname %s", mname);
880 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
882 cur_offset += mname_len;
884 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
885 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
887 cur_offset += rname_len;
889 serial = tvb_get_ntohl(tvb, cur_offset);
890 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
894 refresh = tvb_get_ntohl(tvb, cur_offset);
895 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
896 time_secs_to_str(refresh));
899 retry = tvb_get_ntohl(tvb, cur_offset);
900 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
901 time_secs_to_str(retry));
904 expire = tvb_get_ntohl(tvb, cur_offset);
905 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
906 time_secs_to_str(expire));
909 minimum = tvb_get_ntohl(tvb, cur_offset);
910 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
911 time_secs_to_str(minimum));
918 char pname[MAXDNAME];
921 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
923 col_append_fstr(cinfo, COL_INFO, " %s", pname);
924 if (dns_tree != NULL) {
925 proto_item_append_text(trr, ", ptr %s", pname);
926 proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
935 int rr_len = data_len;
936 const guint8 *wks_addr;
942 char bitnames[128+1];
943 char portnumstring[10+1];
945 wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
947 col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
948 if (dns_tree != NULL) {
949 proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
950 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
951 ip_to_str(wks_addr));
955 protocol = tvb_get_guint8(tvb, cur_offset);
956 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
957 ipprotostr(protocol));
962 while (rr_len != 0) {
963 bits = tvb_get_guint8(tvb, cur_offset);
967 for (i = 0; i < 8; i++) {
969 if (bitnames[0] != '\0')
970 strcat(bitnames, ", ");
974 strcat(bitnames, get_tcp_port(port_num));
978 strcat(bitnames, get_udp_port(port_num));
982 sprintf(portnumstring, "%u", port_num);
983 strcat(bitnames, portnumstring);
990 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
991 "Bits: 0x%02x (%s)", bits, bitnames);
1010 cpu_offset = cur_offset;
1011 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1012 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1013 os_offset = cpu_offset + 1 + cpu_len;
1014 os_len = tvb_get_guint8(tvb, os_offset);
1015 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1017 col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1019 if (dns_tree != NULL) {
1020 proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1021 cpu_len, cpu, os_len, os);
1022 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1024 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1033 guint16 preference = 0;
1034 char mx_name[MAXDNAME];
1037 preference = tvb_get_ntohs(tvb, cur_offset);
1038 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1040 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, mx_name);
1041 if (dns_tree != NULL) {
1042 proto_item_append_text(trr, ", preference %u, mx %s",
1043 preference, mx_name);
1044 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1045 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1053 int rr_len = data_len;
1057 if (dns_tree != NULL) {
1058 txt_offset = cur_offset;
1059 while (rr_len != 0) {
1060 txt_len = tvb_get_guint8(tvb, txt_offset);
1061 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1062 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1063 txt_offset += 1 + txt_len;
1064 rr_len -= 1 + txt_len;
1072 int rr_len = data_len;
1073 guint16 type_covered;
1075 char signer_name[MAXDNAME];
1076 int signer_name_len;
1078 if (dns_tree != NULL) {
1079 type_covered = tvb_get_ntohs(tvb, cur_offset);
1080 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1081 dns_type_name(type_covered),
1082 dns_long_type_name(type_covered));
1086 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1087 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1088 "Unknown (0x%02X)"));
1092 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1093 tvb_get_guint8(tvb, cur_offset));
1097 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1098 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1102 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1104 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1105 abs_time_to_str(&nstime));
1109 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1111 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1112 abs_time_to_str(&nstime));
1116 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1117 tvb_get_ntohs(tvb, cur_offset));
1121 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1122 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1123 "Signer's name: %s", signer_name);
1124 cur_offset += signer_name_len;
1125 rr_len -= signer_name_len;
1127 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1134 int rr_len = data_len;
1137 proto_tree *flags_tree;
1139 if (dns_tree != NULL) {
1140 flags = tvb_get_ntohs(tvb, cur_offset);
1141 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1142 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1143 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1144 decode_boolean_bitfield(flags, 0x8000,
1145 2*8, "Key prohibited for authentication",
1146 "Key allowed for authentication"));
1147 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1148 decode_boolean_bitfield(flags, 0x4000,
1149 2*8, "Key prohibited for confidentiality",
1150 "Key allowed for confidentiality"));
1151 if ((flags & 0xC000) != 0xC000) {
1153 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1154 decode_boolean_bitfield(flags, 0x2000,
1155 2*8, "Key is experimental or optional",
1156 "Key is required"));
1157 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1158 decode_boolean_bitfield(flags, 0x0400,
1159 2*8, "Key is associated with a user",
1160 "Key is not associated with a user"));
1161 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1162 decode_boolean_bitfield(flags, 0x0200,
1163 2*8, "Key is associated with the named entity",
1164 "Key is not associated with the named entity"));
1165 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1166 decode_boolean_bitfield(flags, 0x0100,
1167 2*8, "This is the zone key for the specified zone",
1168 "This is not a zone key"));
1169 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1170 decode_boolean_bitfield(flags, 0x0080,
1171 2*8, "Key is valid for use with IPSEC",
1172 "Key is not valid for use with IPSEC"));
1173 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1174 decode_boolean_bitfield(flags, 0x0040,
1175 2*8, "Key is valid for use with MIME security multiparts",
1176 "Key is not valid for use with MIME security multiparts"));
1177 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1178 decode_numeric_bitfield(flags, 0x000F,
1179 2*8, "Signatory = %u"));
1184 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1185 tvb_get_guint8(tvb, cur_offset));
1189 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1190 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1191 "Unknown (0x%02X)"));
1195 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1202 const guint8 *addr6;
1204 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1205 if (cinfo != NULL) {
1206 col_append_fstr(cinfo, COL_INFO, " %s",
1207 ip6_to_str((struct e_in6_addr *)addr6));
1209 if (dns_tree != NULL) {
1210 proto_item_append_text(trr, ", addr %s",
1211 ip6_to_str((struct e_in6_addr *)addr6));
1212 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1213 ip6_to_str((struct e_in6_addr *)addr6));
1220 unsigned short pre_len;
1221 unsigned short suf_len;
1222 unsigned short suf_octet_count;
1223 char pname[MAXDNAME];
1229 a6_offset = cur_offset;
1230 pre_len = tvb_get_guint8(tvb, cur_offset);
1232 suf_len = 128 - pre_len;
1233 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1235 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1236 suffix[suf_offset] = 0;
1238 for (; suf_offset < 16; suf_offset++) {
1239 suffix[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1244 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1245 pname, sizeof(pname));
1251 if (cinfo != NULL) {
1252 col_append_fstr(cinfo, COL_INFO, " %d %s %s",
1254 ip6_to_str((struct e_in6_addr *)&suffix),
1257 if (dns_tree != NULL) {
1258 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1259 "Prefix len: %u", pre_len);
1262 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1263 "Address suffix: %s",
1264 ip6_to_str((struct e_in6_addr *)&suffix));
1265 a6_offset += suf_octet_count;
1268 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1269 "Prefix name: %s", pname);
1271 proto_item_append_text(trr, ", addr %d %s %s",
1273 ip6_to_str((struct e_in6_addr *)&suffix),
1281 char dname[MAXDNAME];
1284 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1285 dname, sizeof(dname));
1287 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1288 if (dns_tree != NULL) {
1289 proto_item_append_text(trr, ", dname %s", dname);
1290 proto_tree_add_text(rr_tree, tvb, cur_offset,
1291 dname_len, "Target name: %s", dname);
1300 if (dns_tree != NULL) {
1301 version = tvb_get_guint8(tvb, cur_offset);
1302 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1304 /* Version 0, the only version RFC 1876 discusses. */
1307 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1308 rfc1867_size(tvb, cur_offset));
1311 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1312 rfc1867_size(tvb, cur_offset));
1315 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1316 rfc1867_size(tvb, cur_offset));
1319 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1320 rfc1867_angle(tvb, cur_offset, "NS"));
1323 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1324 rfc1867_angle(tvb, cur_offset, "EW"));
1327 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1328 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1330 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1338 int rr_len = data_len;
1339 char next_domain_name[MAXDNAME];
1340 int next_domain_name_len;
1346 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1347 next_domain_name, sizeof(next_domain_name));
1349 col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
1350 if (dns_tree != NULL) {
1351 proto_item_append_text(trr, ", next domain name %s",
1353 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1354 "Next domain name: %s", next_domain_name);
1355 cur_offset += next_domain_name_len;
1356 rr_len -= next_domain_name_len;
1358 while (rr_len != 0) {
1359 bits = tvb_get_guint8(tvb, cur_offset);
1361 for (i = 0; i < 8; i++) {
1363 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1364 "RR type in bit map: %s (%s)",
1365 dns_type_name(rr_type),
1366 dns_long_type_name(rr_type));
1380 guint16 preference = 0;
1381 char kx_name[MAXDNAME];
1384 preference = tvb_get_ntohs(tvb, cur_offset);
1385 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1387 col_append_fstr(cinfo, COL_INFO, " %u %s", preference, kx_name);
1388 if (dns_tree != NULL) {
1389 proto_item_append_text(trr, ", preference %u, kx %s",
1390 preference, kx_name);
1391 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1392 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1400 guint16 cert_type, cert_keytag;
1402 int rr_len = data_len;
1404 cert_type = tvb_get_ntohs(tvb, cur_offset);
1407 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1410 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1414 if (dns_tree != NULL) {
1415 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s",
1416 val_to_str(cert_keyalg, cert_vals,
1417 "Unknown (0x%02X)"));
1418 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1420 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1421 val_to_str(cert_keyalg, algo_vals,
1422 "Unknown (0x%02X)"));
1423 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1430 if (dns_tree != NULL)
1431 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1436 char tkey_algname[MAXDNAME];
1437 int tkey_algname_len;
1438 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1439 int rr_len = data_len;
1441 static const value_string tkey_modes[] = {
1442 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1443 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1444 { TKEYMODE_GSSAPI, "GSSAPI" },
1445 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1446 { TKEYMODE_DELETE, "Delete" },
1449 if (dns_tree != NULL) {
1450 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1451 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1452 "Algorithm name: %s", tkey_algname);
1453 cur_offset += tkey_algname_len;
1454 rr_len -= tkey_algname_len;
1456 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1458 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1459 abs_time_to_str(&nstime));
1463 nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1465 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1466 abs_time_to_str(&nstime));
1470 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1473 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Mode: %s",
1474 val_to_str(tkey_mode, tkey_modes,
1475 "Unknown (0x%02X)"));
1477 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1481 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Error: %s",
1482 val_to_str(tkey_error, rcode_vals,
1483 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1485 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1489 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1490 cur_offset += tkey_keylen;
1491 rr_len -= tkey_keylen;
1493 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1497 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1498 cur_offset += tkey_otherlen;
1499 rr_len -= tkey_otherlen;
1507 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1508 guint32 tsig_timelo;
1509 char tsig_algname[MAXDNAME];
1510 int tsig_algname_len;
1512 int rr_len = data_len;
1514 if (dns_tree != NULL) {
1515 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1516 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1517 "Algorithm name: %s", tsig_algname);
1518 cur_offset += tsig_algname_len;
1519 rr_len -= tsig_algname_len;
1521 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1522 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1523 nstime.secs = tsig_timelo;
1525 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1526 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
1530 tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1531 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1536 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1540 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1541 cur_offset += tsig_siglen;
1542 rr_len -= tsig_siglen;
1544 tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1545 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1550 tsig_error = tvb_get_ntohs(tvb, cur_offset);
1551 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1552 val_to_str(tsig_error, rcode_vals,
1553 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1557 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1561 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1562 cur_offset += tsig_otherlen;
1563 rr_len -= tsig_otherlen;
1570 int rr_len = data_len;
1572 guint32 lookup_timeout;
1573 guint32 cache_timeout;
1576 if (dns_tree != NULL) {
1577 local_flag = tvb_get_ntohl(tvb, cur_offset);
1578 if (dns_tree != NULL) {
1579 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1580 local_flag ? "true" : "false");
1585 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1586 if (dns_tree != NULL) {
1587 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1593 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1594 if (dns_tree != NULL) {
1595 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1601 nservers = tvb_get_ntohl(tvb, cur_offset);
1602 if (dns_tree != NULL) {
1603 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
1609 while (rr_len != 0 && nservers != 0) {
1610 if (dns_tree != NULL) {
1611 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
1612 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
1624 int rr_len = data_len;
1626 guint32 lookup_timeout;
1627 guint32 cache_timeout;
1628 char dname[MAXDNAME];
1631 local_flag = tvb_get_ntohl(tvb, cur_offset);
1632 if (dns_tree != NULL) {
1633 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1634 local_flag ? "true" : "false");
1639 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1640 if (dns_tree != NULL) {
1641 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1647 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1648 if (dns_tree != NULL) {
1649 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1655 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1657 col_append_fstr(cinfo, COL_INFO, " %s", dname);
1658 if (dns_tree != NULL) {
1659 proto_item_append_text(trr, ", name result domain %s", dname);
1660 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
1668 guint16 priority = 0;
1671 char target[MAXDNAME];
1674 priority = tvb_get_ntohs(tvb, cur_offset);
1675 weight = tvb_get_ntohs(tvb, cur_offset+2);
1676 port = tvb_get_ntohs(tvb, cur_offset+4);
1678 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1680 col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, target);
1681 if (dns_tree != NULL) {
1682 proto_item_append_text(trr,
1683 ", priority %u, weight %u, port %u, target %s",
1684 priority, weight, port, target);
1685 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
1686 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
1687 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
1688 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
1694 /* TODO: parse more record types */
1697 if (dns_tree != NULL)
1698 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1702 data_offset += data_len;
1704 return data_offset - data_start;
1708 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1709 int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
1711 int start_off, add_off;
1712 proto_tree *qatree = NULL;
1713 proto_item *ti = NULL;
1715 start_off = cur_off;
1717 char *s = (isupdate ? "Zone" : "Queries");
1718 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
1719 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1721 while (count-- > 0) {
1722 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
1726 proto_item_set_len(ti, cur_off - start_off);
1728 return cur_off - start_off;
1732 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1733 int count, column_info *cinfo, proto_tree *dns_tree, char *name)
1735 int start_off, add_off;
1736 proto_tree *qatree = NULL;
1737 proto_item *ti = NULL;
1739 start_off = cur_off;
1741 ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
1742 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1744 while (count-- > 0) {
1745 add_off = dissect_dns_answer(tvb, cur_off, dns_data_offset, cinfo, qatree);
1749 proto_item_set_len(ti, cur_off - start_off);
1751 return cur_off - start_off;
1755 dissect_dns_common(tvbuff_t *tvb, int offset, int msg_len, packet_info *pinfo,
1756 proto_tree *tree, gboolean is_tcp)
1758 int dns_data_offset;
1760 proto_tree *dns_tree = NULL, *field_tree;
1761 proto_item *ti, *tf;
1762 guint16 id, flags, quest, ans, auth, add;
1766 static const value_string opcode_vals[] = {
1767 { OPCODE_QUERY, "Standard query" },
1768 { OPCODE_IQUERY, "Inverse query" },
1769 { OPCODE_STATUS, "Server status request" },
1770 { OPCODE_NOTIFY, "Zone change notification" },
1771 { OPCODE_UPDATE, "Dynamic update" },
1774 dns_data_offset = offset;
1776 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1777 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
1778 if (check_col(pinfo->cinfo, COL_INFO))
1779 col_clear(pinfo->cinfo, COL_INFO);
1781 /* To do: check for errs, etc. */
1782 id = tvb_get_ntohs(tvb, offset + DNS_ID);
1783 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
1785 if (check_col(pinfo->cinfo, COL_INFO)) {
1786 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation (%x)"));
1787 if (flags & F_RESPONSE) {
1788 strcat(buf, " response");
1789 if ((flags & F_RCODE) != RCODE_NOERROR) {
1791 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1792 "Unknown error (%x)"));
1795 col_add_str(pinfo->cinfo, COL_INFO, buf);
1796 cinfo = pinfo->cinfo;
1798 /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
1799 dissectors, as a way of saying that they shouldn't add stuff
1800 to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
1801 is more expensive than a check that a pointer isn't NULL). */
1804 if ((flags & F_OPCODE) == OPCODE_UPDATE)
1810 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, offset, msg_len,
1811 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1813 dns_tree = proto_item_add_subtree(ti, ett_dns);
1816 /* Put the length indication into the tree. */
1817 proto_tree_add_uint(dns_tree, hf_dns_length, tvb, offset - 2, 2, msg_len);
1820 if (flags & F_RESPONSE)
1821 proto_tree_add_boolean_hidden(dns_tree, hf_dns_response, tvb, offset, 4, 1);
1823 proto_tree_add_boolean_hidden(dns_tree, hf_dns_query, tvb, offset, 4, 1);
1825 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
1826 offset + DNS_ID, 2, id);
1828 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
1829 if (flags & F_RESPONSE) {
1830 strcat(buf, " response");
1832 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1835 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
1836 offset + DNS_FLAGS, 2,
1838 "Flags: 0x%04x (%s)",
1840 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1841 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1842 decode_boolean_bitfield(flags, F_RESPONSE,
1843 2*8, "Response", "Query"));
1844 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1845 decode_enumerated_bitfield(flags, F_OPCODE,
1846 2*8, opcode_vals, "%s"));
1847 if (flags & F_RESPONSE) {
1848 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1849 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
1851 "Server is an authority for domain",
1852 "Server is not an authority for domain"));
1854 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1855 decode_boolean_bitfield(flags, F_TRUNCATED,
1857 "Message is truncated",
1858 "Message is not truncated"));
1859 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1860 decode_boolean_bitfield(flags, F_RECDESIRED,
1862 "Do query recursively",
1863 "Don't do query recursively"));
1864 if (flags & F_RESPONSE) {
1865 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1866 decode_boolean_bitfield(flags, F_RECAVAIL,
1868 "Server can do recursive queries",
1869 "Server can't do recursive queries"));
1870 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1871 decode_boolean_bitfield(flags, F_AUTHENTIC,
1873 "Answer/authority portion was authenticated by the server",
1874 "Answer/authority portion was not authenticated by the server"));
1876 if ((flags & F_RESPONSE) == 0) {
1877 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1878 decode_boolean_bitfield(flags, F_CHECKDISABLE,
1880 "Non-authenticated data is acceptable",
1881 "Non-authenticated data is unacceptable"));
1883 if (flags & F_RESPONSE) {
1884 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1885 decode_enumerated_bitfield(flags, F_RCODE,
1886 2*8, rcode_vals, "%s"));
1889 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
1891 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
1892 offset + DNS_QUEST, 2, quest);
1894 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
1896 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
1897 offset + DNS_ANS, 2, ans);
1899 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
1901 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
1902 offset + DNS_AUTH, 2, auth);
1904 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
1906 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
1907 offset + DNS_ADD, 2, add);
1910 cur_off = offset + DNS_HDRLEN;
1913 /* If this is a response, don't add information about the queries
1914 to the summary, just add information about the answers. */
1915 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
1916 (!(flags & F_RESPONSE) ? cinfo : NULL),
1917 dns_tree, isupdate);
1921 /* If this is a request, don't add information about the answers
1922 to the summary, just add information about the queries. */
1923 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
1924 ((flags & F_RESPONSE) ? cinfo : NULL),
1926 (isupdate ? "Prerequisites" : "Answers"));
1929 /* Don't add information about the authoritative name servers, or the
1930 additional records, to the summary. */
1932 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
1934 (isupdate ? "Updates" :
1935 "Authoritative nameservers"));
1939 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
1940 NULL, dns_tree, "Additional records");
1947 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1949 dissect_dns_common(tvb, 0, tvb_length(tvb), pinfo, tree, FALSE);
1953 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1960 * XXX - should handle a length field split across segment
1963 if (!tvb_bytes_exist(tvb, offset, 2))
1965 plen = tvb_get_ntohs(tvb, offset);
1968 * Desegmentation check.
1970 if (dns_desegment) {
1971 if (pinfo->can_desegment
1972 && plen > tvb_length_remaining(tvb, offset+2)) {
1974 * This frame doesn't have all of the data
1975 * for this message, but we can do reassembly
1978 * Tell the TCP dissector where the data for
1979 * this message starts in the data it handed
1980 * us, and how many more bytes we need, and
1983 pinfo->desegment_offset = offset;
1984 pinfo->desegment_len =
1985 plen - tvb_length_remaining(tvb, offset+2);
1993 * Is all of the DNS message in this TCP segment?
1995 if (tvb_reported_length_remaining(tvb, offset) < plen)
2001 offset = dissect_dns_common(tvb, offset, plen, pinfo, tree,
2007 proto_register_dns(void)
2009 static hf_register_info hf[] = {
2011 { "Length", "dns.length",
2012 FT_UINT16, BASE_DEC, NULL, 0x0,
2013 "Length of DNS-over-TCP request or response", HFILL }},
2015 { "Response", "dns.response",
2016 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2017 "TRUE if DNS response", HFILL }},
2019 { "Query", "dns.query",
2020 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2021 "TRUE if DNS query", HFILL }},
2023 { "Flags", "dns.flags",
2024 FT_UINT16, BASE_HEX, NULL, 0x0,
2026 { &hf_dns_transaction_id,
2027 { "Transaction ID", "dns.id",
2028 FT_UINT16, BASE_HEX, NULL, 0x0,
2029 "Identification of transaction", HFILL }},
2030 { &hf_dns_count_questions,
2031 { "Questions", "dns.count.queries",
2032 FT_UINT16, BASE_DEC, NULL, 0x0,
2033 "Number of queries in packet", HFILL }},
2034 { &hf_dns_count_answers,
2035 { "Answer RRs", "dns.count.answers",
2036 FT_UINT16, BASE_DEC, NULL, 0x0,
2037 "Number of answers in packet", HFILL }},
2038 { &hf_dns_count_auth_rr,
2039 { "Authority RRs", "dns.count.auth_rr",
2040 FT_UINT16, BASE_DEC, NULL, 0x0,
2041 "Number of authoritative records in packet", HFILL }},
2042 { &hf_dns_count_add_rr,
2043 { "Additional RRs", "dns.count.add_rr",
2044 FT_UINT16, BASE_DEC, NULL, 0x0,
2045 "Number of additional records in packet", HFILL }}
2047 static gint *ett[] = {
2056 module_t *dns_module;
2058 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2059 proto_register_field_array(proto_dns, hf, array_length(hf));
2060 proto_register_subtree_array(ett, array_length(ett));
2062 dns_module = prefs_register_protocol(proto_dns, NULL);
2063 prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2064 "Desegment all DNS messages spanning multiple TCP segments",
2065 "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
2070 proto_reg_handoff_dns(void)
2072 dissector_handle_t dns_udp_handle;
2073 dissector_handle_t dns_tcp_handle;
2075 dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
2076 dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
2077 dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
2078 dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);