2 * Routines for DNS packet disassembly
4 * $Id: packet-dns.c,v 1.70 2001/07/02 07:29:03 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"
43 static int proto_dns = -1;
44 static int hf_dns_length = -1;
45 static int hf_dns_response = -1;
46 static int hf_dns_query = -1;
47 static int hf_dns_flags = -1;
48 static int hf_dns_transaction_id = -1;
49 static int hf_dns_count_questions = -1;
50 static int hf_dns_count_answers = -1;
51 static int hf_dns_count_auth_rr = -1;
52 static int hf_dns_count_add_rr = -1;
54 static gint ett_dns = -1;
55 static gint ett_dns_qd = -1;
56 static gint ett_dns_rr = -1;
57 static gint ett_dns_qry = -1;
58 static gint ett_dns_ans = -1;
59 static gint ett_dns_flags = -1;
60 static gint ett_t_key_flags = -1;
62 /* DNS structs and definitions */
64 /* Ports used for DNS. */
65 #define UDP_PORT_DNS 53
66 #define TCP_PORT_DNS 53
68 /* Offsets of fields in the DNS header. */
76 /* Length of DNS header. */
80 #define T_A 1 /* host address */
81 #define T_NS 2 /* authoritative name server */
82 #define T_MD 3 /* mail destination (obsolete) */
83 #define T_MF 4 /* mail forwarder (obsolete) */
84 #define T_CNAME 5 /* canonical name */
85 #define T_SOA 6 /* start of authority zone */
86 #define T_MB 7 /* mailbox domain name (experimental) */
87 #define T_MG 8 /* mail group member (experimental) */
88 #define T_MR 9 /* mail rename domain name (experimental) */
89 #define T_NULL 10 /* null RR (experimental) */
90 #define T_WKS 11 /* well known service */
91 #define T_PTR 12 /* domain name pointer */
92 #define T_HINFO 13 /* host information */
93 #define T_MINFO 14 /* mailbox or mail list information */
94 #define T_MX 15 /* mail routing information */
95 #define T_TXT 16 /* text strings */
96 #define T_RP 17 /* responsible person (RFC 1183) */
97 #define T_AFSDB 18 /* AFS data base location (RFC 1183) */
98 #define T_X25 19 /* X.25 address (RFC 1183) */
99 #define T_ISDN 20 /* ISDN address (RFC 1183) */
100 #define T_RT 21 /* route-through (RFC 1183) */
101 #define T_NSAP 22 /* OSI NSAP (RFC 1706) */
102 #define T_NSAP_PTR 23 /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
103 #define T_SIG 24 /* digital signature (RFC 2535) */
104 #define T_KEY 25 /* public key (RFC 2535) */
105 #define T_PX 26 /* pointer to X.400/RFC822 mapping info (RFC 1664) */
106 #define T_GPOS 27 /* geographical position (RFC 1712) */
107 #define T_AAAA 28 /* IPv6 address (RFC 1886) */
108 #define T_LOC 29 /* geographical location (RFC 1876) */
109 #define T_NXT 30 /* "next" name (RFC 2535) */
110 #define T_EID 31 /* ??? (Nimrod?) */
111 #define T_NIMLOC 32 /* ??? (Nimrod?) */
112 #define T_SRV 33 /* service location (RFC 2052) */
113 #define T_ATMA 34 /* ??? */
114 #define T_NAPTR 35 /* naming authority pointer (RFC 2168) */
115 #define T_KX 36 /* Key Exchange (RFC 2230) */
116 #define T_CERT 37 /* Certificate (RFC 2538) */
117 #define T_A6 38 /* IPv6 address with indirection (RFC 2874) */
118 #define T_DNAME 39 /* Non-terminal DNS name redirection (RFC 2672) */
119 #define T_OPT 41 /* OPT pseudo-RR (RFC 2671) */
120 #define T_TKEY 249 /* Transaction Key (RFC 2930) */
121 #define T_TSIG 250 /* Transaction Signature (RFC 2845) */
122 #define T_WINS 65281 /* Microsoft's WINS RR */
123 #define T_WINS_R 65282 /* Microsoft's WINS-R RR */
126 #define C_IN 1 /* the Internet */
127 #define C_CS 2 /* CSNET (obsolete) */
128 #define C_CH 3 /* CHAOS */
129 #define C_HS 4 /* Hesiod */
130 #define C_NONE 254 /* none */
131 #define C_ANY 255 /* any */
133 /* Bit fields in the flags */
134 #define F_RESPONSE (1<<15) /* packet is response */
135 #define F_OPCODE (0xF<<11) /* query opcode */
136 #define F_AUTHORITATIVE (1<<10) /* response is authoritative */
137 #define F_TRUNCATED (1<<9) /* response is truncated */
138 #define F_RECDESIRED (1<<8) /* recursion desired */
139 #define F_RECAVAIL (1<<7) /* recursion available */
140 #define F_AUTHENTIC (1<<5) /* authentic data (RFC2535) */
141 #define F_CHECKDISABLE (1<<4) /* checking disabled (RFC2535) */
142 #define F_RCODE (0xF<<0) /* reply code */
145 #define OPCODE_QUERY (0<<11) /* standard query */
146 #define OPCODE_IQUERY (1<<11) /* inverse query */
147 #define OPCODE_STATUS (2<<11) /* server status request */
148 #define OPCODE_NOTIFY (4<<11) /* zone change notification */
149 #define OPCODE_UPDATE (5<<11) /* dynamic update */
152 #define RCODE_NOERROR (0<<0)
153 #define RCODE_FORMERR (1<<0)
154 #define RCODE_SERVFAIL (2<<0)
155 #define RCODE_NXDOMAIN (3<<0)
156 #define RCODE_NOTIMPL (4<<0)
157 #define RCODE_REFUSED (5<<0)
158 #define RCODE_YXDOMAIN (6<<0)
159 #define RCODE_YXRRSET (7<<0)
160 #define RCODE_NXRRSET (8<<0)
161 #define RCODE_NOTAUTH (9<<0)
162 #define RCODE_NOTZONE (10<<0)
164 static const value_string rcode_vals[] = {
165 { RCODE_NOERROR, "No error" },
166 { RCODE_FORMERR, "Format error" },
167 { RCODE_SERVFAIL, "Server failure" },
168 { RCODE_NXDOMAIN, "No such name" },
169 { RCODE_NOTIMPL, "Not implemented" },
170 { RCODE_REFUSED, "Refused" },
171 { RCODE_YXDOMAIN, "Name exists" },
172 { RCODE_YXRRSET, "RRset exists" },
173 { RCODE_NXRRSET, "RRset does not exist" },
174 { RCODE_NOTAUTH, "Not authoritative" },
175 { RCODE_NOTZONE, "Name out of zone" },
178 /* TSIG/TKEY extended errors */
179 #define TSIGERROR_BADSIG (16)
180 #define TSIGERROR_BADKEY (17)
181 #define TSIGERROR_BADTIME (18)
182 #define TSIGERROR_BADMODE (19)
183 #define TSIGERROR_BADNAME (20)
184 #define TSIGERROR_BADALG (21)
186 static const value_string tsigerror_vals[] = {
187 { TSIGERROR_BADSIG, "Bad signature" },
188 { TSIGERROR_BADKEY, "Bad key" },
189 { TSIGERROR_BADTIME, "Bad time failure" },
190 { TSIGERROR_BADMODE, "Bad mode such name" },
191 { TSIGERROR_BADNAME, "Bad name implemented" },
192 { TSIGERROR_BADALG, "Bad algorithm" },
195 #define TKEYMODE_SERVERASSIGNED (1)
196 #define TKEYMODE_DIFFIEHELLMAN (2)
197 #define TKEYMODE_GSSAPI (3)
198 #define TKEYMODE_RESOLVERASSIGNED (4)
199 #define TKEYMODE_DELETE (5)
201 /* See RFC 1035 for all RR types for which no RFC is listed, except for
202 the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
203 which one should look at
205 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
209 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
211 which discuss them to some extent. */
213 dns_type_name (u_int type)
215 char *type_names[] = {
234 "AFSDB", /* RFC 1183 */
235 "X25", /* RFC 1183 */
236 "ISDN", /* RFC 1183 */
238 "NSAP", /* RFC 1706 */
239 "NSAP-PTR", /* RFC 1348 */
240 "SIG", /* RFC 2535 */
241 "KEY", /* RFC 2535 */
243 "GPOS", /* RFC 1712 */
244 "AAAA", /* RFC 1886 */
245 "LOC", /* RFC 1876 */
246 "NXT", /* RFC 2535 */
249 "SRV", /* RFC 2052 */
251 "NAPTR", /* RFC 2168 */
253 "CERT", /* RFC 2538 */
255 "DNAME", /* RFC 2672 */
260 if (type < sizeof(type_names)/sizeof(type_names[0]))
261 return type_names[type] ? type_names[type] : "unknown";
288 return "IXFR"; /* RFC 1995 */
305 dns_long_type_name (u_int type)
307 char *type_names[] = {
310 "Authoritative name server",
313 "Canonical name for an alias",
314 "Start of zone of authority",
315 "Mailbox domain name",
317 "Mail rename domain name",
318 "Null resource record",
319 "Well-known service description",
320 "Domain name pointer",
322 "Mailbox or mail list information",
325 "Responsible person", /* RFC 1183 */
326 "AFS data base location", /* RFC 1183 */
327 "X.25 address", /* RFC 1183 */
328 "ISDN number", /* RFC 1183 */
329 "Route through", /* RFC 1183 */
330 "OSI NSAP", /* RFC 1706 */
331 "OSI NSAP name pointer", /* RFC 1348 */
332 "Signature", /* RFC 2535 */
333 "Public key", /* RFC 2535 */
334 "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
335 "Geographical position", /* RFC 1712 */
336 "IPv6 address", /* RFC 1886 */
337 "Location", /* RFC 1876 */
338 "Next", /* RFC 2535 */
341 "Service location", /* RFC 2052 */
343 "Naming authority pointer", /* RFC 2168 */
344 "Key Exchange", /* RFC 2230 */
345 "Certificate", /* RFC 2538 */
346 "IPv6 address with indirection", /* RFC 2874 */
347 "Non-terminal DNS name redirection", /* RFC 2672 */
349 "EDNS0 option" /* RFC 2671 */
351 static char unkbuf[7+1+2+1+4+1+1+10+1+1]; /* "Unknown RR type (%d)" */
353 if (type < sizeof(type_names)/sizeof(type_names[0]))
354 return type_names[type] ? type_names[type] : "unknown";
375 return "Transaction Key";
377 return "Transaction Signature";
381 return "Request for incremental zone transfer"; /* RFC 1995 */
383 return "Request for full zone transfer";
385 return "Request for mailbox-related records";
387 return "Request for mail agent resource records";
389 return "Request for all records";
392 sprintf(unkbuf, "Unknown RR type (%d)", type);
398 dns_class_name(int class)
407 class_name = "csnet";
410 class_name = "chaos";
413 class_name = "hesiod";
422 class_name = "unknown";
429 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
430 char *name, int maxname)
432 int start_offset = offset;
435 int chars_processed = 0;
436 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
440 maxname--; /* reserve space for the trailing '\0' */
442 component_len = tvb_get_guint8(tvb, offset);
444 if (component_len == 0)
447 switch (component_len & 0xc0) {
452 /* Not the first component - put in a '.'. */
458 while (component_len > 0) {
460 *np++ = tvb_get_guint8(tvb, offset);
470 /* Extended label (RFC 2673) */
471 switch (component_len & 0x3f) {
474 /* Bitstring label */
479 bit_count = tvb_get_guint8(tvb, offset);
481 label_len = (bit_count - 1) / 8 + 1;
483 np += sprintf(np, "\\[x");
485 np += sprintf(np, "%02x", tvb_get_guint8(tvb, offset));
488 np += sprintf(np, "/%d]", bit_count);
493 strcpy(name, "<Unknown extended label>");
494 /* Parsing will propably fail from here on, since the */
495 /* label length is unknown... */
496 return offset - start_offset;
501 goto error; /* error */
505 indir_offset = dns_data_offset +
506 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
510 /* If "len" is negative, we are still working on the original name,
511 not something pointed to by a pointer, and so we should set "len"
512 to the length of the original name. */
514 len = offset - start_offset;
516 /* If we've looked at every character in the message, this pointer
517 will make us look at some character again, which means we're
519 if (chars_processed >= data_size) {
520 strcpy(name, "<Name contains a pointer that loops>");
524 offset = indir_offset;
525 break; /* now continue processing from there */
531 /* If "len" is negative, we haven't seen a pointer, and thus haven't
532 set the length, so set it. */
534 len = offset - start_offset;
535 /* Zero-length name means "root server" */
537 strcpy(name, "<Root>");
543 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
544 char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
551 int start_offset = offset;
553 name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
556 type = tvb_get_ntohs(tvb, offset);
559 class = tvb_get_ntohs(tvb, offset);
562 strcpy (name_ret, name);
565 *name_len_ret = name_len;
567 len = offset - start_offset;
572 rfc1867_size(tvbuff_t *tvb, int offset)
578 val = tvb_get_guint8(tvb, offset);
579 size = (val & 0xF0) >> 4;
580 exponent = (val & 0x0F);
581 while (exponent != 0) {
585 return size / 100; /* return size in meters, not cm */
589 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
593 guint32 degrees, minutes, secs, tsecs;
594 static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
596 angle = tvb_get_ntohl(tvb, offset);
598 if (angle < 0x80000000U) {
599 angle = 0x80000000U - angle;
602 angle = angle - 0x80000000U;
605 tsecs = angle % 1000;
606 angle = angle / 1000;
609 minutes = angle % 60;
610 degrees = angle / 60;
611 sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
617 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
618 frame_data *fd, proto_tree *dns_tree)
627 char *long_type_name;
633 data_start = data_offset = offset;
635 len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
638 /* We ran past the end of the data in the packet. */
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(fd, 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 frame_data *fd, 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(fd, COL_INFO, " %s", type_name);
795 if (dns_tree != NULL) {
796 trr = proto_tree_add_notext(dns_tree, tvb, offset,
797 (data_offset - data_start) + data_len);
799 rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
800 long_type_name, class_name, ttl, data_len);
802 rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
803 long_type_name, class, ttl, data_len);
814 addr = tvb_get_ptr(tvb, cur_offset, 4);
816 col_append_fstr(fd, COL_INFO, " %s", ip_to_str(addr));
817 if (dns_tree != NULL) {
818 proto_item_set_text(trr, "%s: type %s, class %s, addr %s",
819 name, type_name, class_name,
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(fd, COL_INFO, " %s", ns_name);
839 if (dns_tree != NULL) {
840 proto_item_set_text(trr, "%s: type %s, class %s, ns %s",
841 name, type_name, class_name, ns_name);
842 proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
850 char cname[MAXDNAME];
853 cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
855 col_append_fstr(fd, COL_INFO, " %s", cname);
856 if (dns_tree != NULL) {
857 proto_item_set_text(trr, "%s: type %s, class %s, cname %s",
858 name, type_name, class_name, cname);
859 proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
867 char mname[MAXDNAME];
869 char rname[MAXDNAME];
877 mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
879 col_append_fstr(fd, COL_INFO, " %s", mname);
880 if (dns_tree != NULL) {
881 proto_item_set_text(trr, "%s: type %s, class %s, mname %s",
882 name, type_name, class_name, mname);
883 proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
885 cur_offset += mname_len;
887 rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
888 proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
890 cur_offset += rname_len;
892 serial = tvb_get_ntohl(tvb, cur_offset);
893 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
897 refresh = tvb_get_ntohl(tvb, cur_offset);
898 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
899 time_secs_to_str(refresh));
902 retry = tvb_get_ntohl(tvb, cur_offset);
903 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
904 time_secs_to_str(retry));
907 expire = tvb_get_ntohl(tvb, cur_offset);
908 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
909 time_secs_to_str(expire));
912 minimum = tvb_get_ntohl(tvb, cur_offset);
913 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
914 time_secs_to_str(minimum));
921 char pname[MAXDNAME];
924 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
926 col_append_fstr(fd, COL_INFO, " %s", pname);
927 if (dns_tree != NULL) {
928 proto_item_set_text(trr, "%s: type %s, class %s, ptr %s",
929 name, type_name, class_name, 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_set_text(trr, "%s: type %s, class %s, addr %s",
954 name, type_name, class_name,
955 ip_to_str(wks_addr));
956 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
957 ip_to_str(wks_addr));
961 protocol = tvb_get_guint8(tvb, cur_offset);
962 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
963 ipprotostr(protocol));
968 while (rr_len != 0) {
969 bits = tvb_get_guint8(tvb, cur_offset);
973 for (i = 0; i < 8; i++) {
975 if (bitnames[0] != '\0')
976 strcat(bitnames, ", ");
980 strcat(bitnames, get_tcp_port(port_num));
984 strcat(bitnames, get_udp_port(port_num));
988 sprintf(portnumstring, "%u", port_num);
989 strcat(bitnames, portnumstring);
996 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
997 "Bits: 0x%02x (%s)", bits, bitnames);
1016 cpu_offset = cur_offset;
1017 cpu_len = tvb_get_guint8(tvb, cpu_offset);
1018 cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1019 os_offset = cpu_offset + 1 + cpu_len;
1020 os_len = tvb_get_guint8(tvb, os_offset);
1021 os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1023 col_append_fstr(fd, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1025 if (dns_tree != NULL) {
1026 proto_item_set_text(trr,
1027 "%s: type %s, class %s, CPU %.*s, OS %.*s",
1028 name, type_name, class_name,
1029 cpu_len, cpu, os_len, os);
1030 proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1032 proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1041 guint16 preference = 0;
1042 char mx_name[MAXDNAME];
1045 preference = tvb_get_ntohs(tvb, cur_offset);
1046 mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1048 col_append_fstr(fd, COL_INFO, " %u %s", preference, mx_name);
1049 if (dns_tree != NULL) {
1050 proto_item_set_text(trr,
1051 "%s: type %s, class %s, preference %u, mx %s",
1052 name, type_name, class_name, preference, mx_name);
1053 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1054 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1062 int rr_len = data_len;
1066 if (dns_tree != NULL) {
1067 proto_item_set_text(trr,
1068 "%s: type %s, class %s", name, type_name, class_name);
1070 txt_offset = cur_offset;
1071 while (rr_len != 0) {
1072 txt_len = tvb_get_guint8(tvb, txt_offset);
1073 proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1074 "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1075 txt_offset += 1 + txt_len;
1076 rr_len -= 1 + txt_len;
1084 int rr_len = data_len;
1085 guint16 type_covered;
1086 struct timeval unixtime;
1087 char signer_name[MAXDNAME];
1088 int signer_name_len;
1090 if (dns_tree != NULL) {
1091 proto_item_set_text(trr,
1092 "%s: type %s, class %s", name, type_name, class_name);
1094 type_covered = tvb_get_ntohs(tvb, cur_offset);
1095 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1096 dns_type_name(type_covered),
1097 dns_long_type_name(type_covered));
1101 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1102 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1103 "Unknown (0x%02X)"));
1107 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1108 tvb_get_guint8(tvb, cur_offset));
1112 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1113 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1117 unixtime.tv_sec = tvb_get_ntohl(tvb, cur_offset);
1118 unixtime.tv_usec = 0;
1119 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1120 abs_time_to_str(&unixtime));
1124 unixtime.tv_sec = tvb_get_ntohl(tvb, cur_offset);
1125 unixtime.tv_usec = 0;
1126 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1127 abs_time_to_str(&unixtime));
1131 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1132 tvb_get_ntohs(tvb, cur_offset));
1136 signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1137 proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1138 "Signer's name: %s", signer_name);
1139 cur_offset += signer_name_len;
1140 rr_len -= signer_name_len;
1142 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1149 int rr_len = data_len;
1152 proto_tree *flags_tree;
1154 if (dns_tree != NULL) {
1155 proto_item_set_text(trr,
1156 "%s: type %s, class %s", name, type_name, class_name);
1158 flags = tvb_get_ntohs(tvb, cur_offset);
1159 tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1160 flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1161 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1162 decode_boolean_bitfield(flags, 0x8000,
1163 2*8, "Key prohibited for authentication",
1164 "Key allowed for authentication"));
1165 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1166 decode_boolean_bitfield(flags, 0x4000,
1167 2*8, "Key prohibited for confidentiality",
1168 "Key allowed for confidentiality"));
1169 if ((flags & 0xC000) != 0xC000) {
1171 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1172 decode_boolean_bitfield(flags, 0x2000,
1173 2*8, "Key is experimental or optional",
1174 "Key is required"));
1175 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1176 decode_boolean_bitfield(flags, 0x0400,
1177 2*8, "Key is associated with a user",
1178 "Key is not associated with a user"));
1179 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1180 decode_boolean_bitfield(flags, 0x0200,
1181 2*8, "Key is associated with the named entity",
1182 "Key is not associated with the named entity"));
1183 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1184 decode_boolean_bitfield(flags, 0x0100,
1185 2*8, "This is the zone key for the specified zone",
1186 "This is not a zone key"));
1187 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1188 decode_boolean_bitfield(flags, 0x0080,
1189 2*8, "Key is valid for use with IPSEC",
1190 "Key is not valid for use with IPSEC"));
1191 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1192 decode_boolean_bitfield(flags, 0x0040,
1193 2*8, "Key is valid for use with MIME security multiparts",
1194 "Key is not valid for use with MIME security multiparts"));
1195 proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1196 decode_numeric_bitfield(flags, 0x000F,
1197 2*8, "Signatory = %u"));
1202 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1203 tvb_get_guint8(tvb, cur_offset));
1207 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1208 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1209 "Unknown (0x%02X)"));
1213 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1220 const guint8 *addr6;
1222 addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1224 col_append_fstr(fd, COL_INFO, " %s",
1225 ip6_to_str((struct e_in6_addr *)addr6));
1227 if (dns_tree != NULL) {
1228 proto_item_set_text(trr, "%s: type %s, class %s, addr %s",
1229 name, type_name, class_name,
1230 ip6_to_str((struct e_in6_addr *)addr6));
1231 proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1232 ip6_to_str((struct e_in6_addr *)addr6));
1239 unsigned short pre_len;
1240 unsigned short suf_len;
1241 unsigned short suf_octet_count;
1242 char pname[MAXDNAME];
1248 a6_offset = cur_offset;
1249 pre_len = tvb_get_guint8(tvb, cur_offset);
1251 suf_len = 128 - pre_len;
1252 suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1254 for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1255 suffix[suf_offset] = 0;
1257 for (; suf_offset < 16; suf_offset++) {
1258 suffix[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1263 pname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1264 pname, sizeof(pname));
1271 col_append_fstr(fd, COL_INFO, " %d %s %s",
1273 ip6_to_str((struct e_in6_addr *)&suffix),
1276 if (dns_tree != NULL) {
1277 proto_tree_add_text(rr_tree, tvb, a6_offset, 1,
1278 "Prefix len: %u", pre_len);
1281 proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1282 "Address suffix: %s",
1283 ip6_to_str((struct e_in6_addr *)&suffix));
1284 a6_offset += suf_octet_count;
1287 proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len,
1288 "Prefix name: %s", pname);
1290 proto_item_set_text(trr, "%s: type %s, class %s, addr %d %s %s",
1295 ip6_to_str((struct e_in6_addr *)&suffix),
1303 char dname[MAXDNAME];
1306 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1307 dname, sizeof(dname));
1309 col_append_fstr(fd, COL_INFO, " %s", dname);
1310 if (dns_tree != NULL) {
1311 proto_item_set_text(trr, "%s: type %s, class %s, dname %s",
1312 name, type_name, class_name, dname);
1313 proto_tree_add_text(rr_tree, tvb, cur_offset,
1314 dname_len, "Target name: %s", dname);
1323 if (dns_tree != NULL) {
1324 proto_item_set_text(trr,
1325 "%s: type %s, class %s", name, type_name, class_name);
1327 version = tvb_get_guint8(tvb, cur_offset);
1328 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1330 /* Version 0, the only version RFC 1876 discusses. */
1333 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1334 rfc1867_size(tvb, cur_offset));
1337 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1338 rfc1867_size(tvb, cur_offset));
1341 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1342 rfc1867_size(tvb, cur_offset));
1345 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1346 rfc1867_angle(tvb, cur_offset, "NS"));
1349 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1350 rfc1867_angle(tvb, cur_offset, "EW"));
1353 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1354 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1356 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1364 int rr_len = data_len;
1365 char next_domain_name[MAXDNAME];
1366 int next_domain_name_len;
1372 next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1373 next_domain_name, sizeof(next_domain_name));
1375 col_append_fstr(fd, COL_INFO, " %s", next_domain_name);
1376 if (dns_tree != NULL) {
1377 proto_item_set_text(trr, "%s: type %s, class %s, next domain name %s",
1378 name, type_name, class_name, next_domain_name);
1379 proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1380 "Next domain name: %s", next_domain_name);
1381 cur_offset += next_domain_name_len;
1382 rr_len -= next_domain_name_len;
1384 while (rr_len != 0) {
1385 bits = tvb_get_guint8(tvb, cur_offset);
1387 for (i = 0; i < 8; i++) {
1389 proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1390 "RR type in bit map: %s (%s)",
1391 dns_type_name(rr_type),
1392 dns_long_type_name(rr_type));
1406 guint16 preference = 0;
1407 char kx_name[MAXDNAME];
1410 preference = tvb_get_ntohs(tvb, cur_offset);
1411 kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1413 col_append_fstr(fd, COL_INFO, " %u %s", preference, kx_name);
1414 if (dns_tree != NULL) {
1415 proto_item_set_text(trr,
1416 "%s: type %s, class %s, preference %u, kx %s",
1417 name, type_name, class_name, preference, kx_name);
1418 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1419 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1427 guint16 cert_type, cert_keytag;
1429 int rr_len = data_len;
1431 cert_type = tvb_get_ntohs(tvb, cur_offset);
1434 cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1437 cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1441 if (dns_tree != NULL) {
1442 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s",
1443 val_to_str(cert_keyalg, cert_vals,
1444 "Unknown (0x%02X)"));
1445 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1447 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1448 val_to_str(cert_keyalg, algo_vals,
1449 "Unknown (0x%02X)"));
1450 proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1457 if (dns_tree != NULL) {
1458 proto_item_set_text(trr, "%s: type %s", name, type_name);
1459 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1465 char tkey_algname[MAXDNAME];
1466 int tkey_algname_len;
1467 guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1468 int rr_len = data_len;
1469 struct timeval unixtime;
1470 static const value_string tkey_modes[] = {
1471 { TKEYMODE_SERVERASSIGNED, "Server assigned" },
1472 { TKEYMODE_DIFFIEHELLMAN, "Diffie Hellman" },
1473 { TKEYMODE_GSSAPI, "GSSAPI " },
1474 { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1475 { TKEYMODE_DELETE, "Delete" },
1478 if (dns_tree != NULL) {
1479 proto_item_set_text(trr,
1480 "%s: type %s, class %s", name, type_name, class_name);
1481 tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1482 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1483 "Algorithm name: %s", tkey_algname);
1484 cur_offset += tkey_algname_len;
1485 rr_len -= tkey_algname_len;
1487 unixtime.tv_sec = tvb_get_ntohl(tvb, cur_offset);
1488 unixtime.tv_usec = 0;
1489 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1490 abs_time_to_str(&unixtime));
1494 unixtime.tv_sec = tvb_get_ntohl(tvb, cur_offset);
1495 unixtime.tv_usec = 0;
1496 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1497 abs_time_to_str(&unixtime));
1501 tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1504 proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Mode: %s",
1505 val_to_str(tkey_mode, tkey_modes,
1506 "Unknown (0x%02X)"));
1508 tkey_error = tvb_get_ntohs(tvb, cur_offset);
1512 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Error: %s",
1513 val_to_str(tkey_error, rcode_vals,
1514 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1516 tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1520 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1521 cur_offset += tkey_keylen;
1522 rr_len -= tkey_keylen;
1524 tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1528 proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1529 cur_offset += tkey_otherlen;
1530 rr_len -= tkey_otherlen;
1538 guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1539 guint32 tsig_timelo;
1540 char tsig_algname[MAXDNAME];
1541 int tsig_algname_len;
1542 struct timeval unixtime;
1543 int rr_len = data_len;
1545 if (dns_tree != NULL) {
1546 proto_item_set_text(trr,
1547 "%s: type %s, class %s", name, type_name, class_name);
1548 tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1549 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1550 "Algorithm name: %s", tsig_algname);
1551 cur_offset += tsig_algname_len;
1552 rr_len -= tsig_algname_len;
1554 tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1555 tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1556 unixtime.tv_sec = tsig_timelo;
1557 unixtime.tv_usec = 0;
1558 proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1559 abs_time_to_str(&unixtime), tsig_timehi == 0 ? "" : "(high bits set)");
1563 tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1564 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1569 tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1573 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1574 cur_offset += tsig_siglen;
1575 rr_len -= tsig_siglen;
1577 tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1578 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1583 tsig_error = tvb_get_ntohs(tvb, cur_offset);
1584 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1585 val_to_str(tsig_error, rcode_vals,
1586 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1590 tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1594 proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1595 cur_offset += tsig_otherlen;
1596 rr_len -= tsig_otherlen;
1603 int rr_len = data_len;
1605 guint32 lookup_timeout;
1606 guint32 cache_timeout;
1609 if (dns_tree != NULL) {
1610 proto_item_set_text(trr, "%s: type %s, class %s", name, type_name,
1612 local_flag = tvb_get_ntohl(tvb, cur_offset);
1613 if (dns_tree != NULL) {
1614 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1615 local_flag ? "true" : "false");
1620 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1621 if (dns_tree != NULL) {
1622 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1628 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1629 if (dns_tree != NULL) {
1630 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1636 nservers = tvb_get_ntohl(tvb, cur_offset);
1637 if (dns_tree != NULL) {
1638 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
1644 while (rr_len != 0 && nservers != 0) {
1645 if (dns_tree != NULL) {
1646 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
1647 ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
1659 int rr_len = data_len;
1661 guint32 lookup_timeout;
1662 guint32 cache_timeout;
1663 char dname[MAXDNAME];
1666 local_flag = tvb_get_ntohl(tvb, cur_offset);
1667 if (dns_tree != NULL) {
1668 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1669 local_flag ? "true" : "false");
1674 lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1675 if (dns_tree != NULL) {
1676 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1682 cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1683 if (dns_tree != NULL) {
1684 proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1690 dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1692 col_append_fstr(fd, COL_INFO, " %s", dname);
1693 if (dns_tree != NULL) {
1694 proto_item_set_text(trr, "%s: type %s, class %s, name result domain %s",
1695 name, type_name, class_name, dname);
1696 proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
1704 guint16 priority = 0;
1707 char target[MAXDNAME];
1710 priority = tvb_get_ntohs(tvb, cur_offset);
1711 weight = tvb_get_ntohs(tvb, cur_offset+2);
1712 port = tvb_get_ntohs(tvb, cur_offset+4);
1714 target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1716 col_append_fstr(fd, COL_INFO, " %u %u %u %s", priority, weight, port, target);
1717 if (dns_tree != NULL) {
1718 proto_item_set_text(trr,
1719 "%s: type %s, class %s, priority %u, weight %u, port %u, target %s",
1720 name, type_name, class_name, priority, weight, port, target);
1721 proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
1722 proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
1723 proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
1724 proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
1730 /* TODO: parse more record types */
1733 if (dns_tree != NULL) {
1734 proto_item_set_text(trr,
1735 "%s: type %s, class %s", name, type_name, class_name);
1736 proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1741 data_offset += data_len;
1743 return data_offset - data_start;
1747 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1748 int count, frame_data *fd, proto_tree *dns_tree, int isupdate)
1750 int start_off, add_off;
1751 proto_tree *qatree = NULL;
1752 proto_item *ti = NULL;
1754 start_off = cur_off;
1756 char *s = (isupdate ? "Zone" : "Queries");
1757 ti = proto_tree_add_text(dns_tree, tvb, start_off, 0, s);
1758 qatree = proto_item_add_subtree(ti, ett_dns_qry);
1760 while (count-- > 0) {
1761 add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, fd, qatree);
1763 /* We ran past the end of the captured data in the packet. */
1769 proto_item_set_len(ti, cur_off - start_off);
1771 return cur_off - start_off;
1775 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1776 int count, frame_data *fd, proto_tree *dns_tree, char *name)
1778 int start_off, add_off;
1779 proto_tree *qatree = NULL;
1780 proto_item *ti = NULL;
1782 start_off = cur_off;
1784 ti = proto_tree_add_text(dns_tree, tvb, start_off, 0, name);
1785 qatree = proto_item_add_subtree(ti, ett_dns_ans);
1787 while (count-- > 0) {
1788 add_off = dissect_dns_answer(tvb, cur_off, dns_data_offset, fd, qatree);
1790 /* We ran past the end of the captured data in the packet. */
1796 proto_item_set_len(ti, cur_off - start_off);
1798 return cur_off - start_off;
1802 dissect_dns_common(tvbuff_t *tvb, int offset, int cap_len, packet_info *pinfo,
1803 proto_tree *tree, gboolean is_tcp)
1805 int dns_data_offset;
1807 proto_tree *dns_tree = NULL, *field_tree;
1808 proto_item *ti, *tf;
1809 guint16 id, flags, quest, ans, auth, add;
1813 static const value_string opcode_vals[] = {
1814 { OPCODE_QUERY, "Standard query" },
1815 { OPCODE_IQUERY, "Inverse query" },
1816 { OPCODE_STATUS, "Server status request" },
1817 { OPCODE_NOTIFY, "Zone change notification" },
1818 { OPCODE_UPDATE, "Dynamic update" },
1821 dns_data_offset = offset;
1823 if (check_col(pinfo->fd, COL_PROTOCOL))
1824 col_set_str(pinfo->fd, COL_PROTOCOL, "DNS");
1825 if (check_col(pinfo->fd, COL_INFO))
1826 col_clear(pinfo->fd, COL_INFO);
1828 /* To do: check for errs, etc. */
1829 id = tvb_get_ntohs(tvb, offset + DNS_ID);
1830 flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
1832 if (check_col(pinfo->fd, COL_INFO)) {
1833 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation (%x)"));
1834 if (flags & F_RESPONSE) {
1835 strcat(buf, " response");
1836 if ((flags & F_RCODE) != RCODE_NOERROR) {
1838 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1839 "Unknown error (%x)"));
1842 col_add_str(pinfo->fd, COL_INFO, buf);
1845 /* Set "fd" to NULL; we pass a NULL "fd" to the query and answer
1846 dissectors, as a way of saying that they shouldn't add stuff
1847 to the COL_INFO column (a call to "check_col(fd, COL_INFO)"
1848 is more expensive than a check that a pointer isn't NULL). */
1851 if ((flags & F_OPCODE) == OPCODE_UPDATE)
1857 ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, offset, cap_len,
1858 "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1860 dns_tree = proto_item_add_subtree(ti, ett_dns);
1863 /* Put the length indication into the tree. */
1864 proto_tree_add_uint(dns_tree, hf_dns_length, tvb, offset - 2, 2, cap_len);
1867 if (flags & F_RESPONSE)
1868 proto_tree_add_boolean_hidden(dns_tree, hf_dns_response, tvb, offset, 4, 1);
1870 proto_tree_add_boolean_hidden(dns_tree, hf_dns_query, tvb, offset, 4, 1);
1872 proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb,
1873 offset + DNS_ID, 2, id);
1875 strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
1876 if (flags & F_RESPONSE) {
1877 strcat(buf, " response");
1879 strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1882 tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
1883 offset + DNS_FLAGS, 2,
1885 "Flags: 0x%04x (%s)",
1887 field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1888 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1889 decode_boolean_bitfield(flags, F_RESPONSE,
1890 2*8, "Response", "Query"));
1891 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1892 decode_enumerated_bitfield(flags, F_OPCODE,
1893 2*8, opcode_vals, "%s"));
1894 if (flags & F_RESPONSE) {
1895 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1896 decode_boolean_bitfield(flags, F_AUTHORITATIVE,
1898 "Server is an authority for domain",
1899 "Server is not an authority for domain"));
1901 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1902 decode_boolean_bitfield(flags, F_TRUNCATED,
1904 "Message is truncated",
1905 "Message is not truncated"));
1906 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1907 decode_boolean_bitfield(flags, F_RECDESIRED,
1909 "Do query recursively",
1910 "Don't do query recursively"));
1911 if (flags & F_RESPONSE) {
1912 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1913 decode_boolean_bitfield(flags, F_RECAVAIL,
1915 "Server can do recursive queries",
1916 "Server can't do recursive queries"));
1917 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1918 decode_boolean_bitfield(flags, F_AUTHENTIC,
1920 "Answer/authority portion was authenticated by the server",
1921 "Answer/authority portion was not authenticated by the server"));
1923 if ((flags & F_RESPONSE) == 0) {
1924 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1925 decode_boolean_bitfield(flags, F_CHECKDISABLE,
1927 "Non-authenticated data is acceptable",
1928 "Non-authenticated data is unacceptable"));
1930 if (flags & F_RESPONSE) {
1931 proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1932 decode_enumerated_bitfield(flags, F_RCODE,
1933 2*8, rcode_vals, "%s"));
1936 quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
1938 proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb,
1939 offset + DNS_QUEST, 2, quest);
1941 ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
1943 proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb,
1944 offset + DNS_ANS, 2, ans);
1946 auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
1948 proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb,
1949 offset + DNS_AUTH, 2, auth);
1951 add = tvb_get_ntohs(tvb, offset + DNS_ADD);
1953 proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb,
1954 offset + DNS_ADD, 2, add);
1957 cur_off = offset + DNS_HDRLEN;
1960 /* If this is a response, don't add information about the queries
1961 to the summary, just add information about the answers. */
1962 cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
1963 (!(flags & F_RESPONSE) ? fd : NULL),
1964 dns_tree, isupdate);
1968 /* If this is a request, don't add information about the answers
1969 to the summary, just add information about the queries. */
1970 char *s = (isupdate ? "Prerequisites" : "Answers");
1971 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
1972 ((flags & F_RESPONSE) ? fd : NULL),
1977 /* Don't add information about the authoritative name servers, or the
1978 additional records, to the summary. */
1980 char *s = (isupdate ? "Updates" : "Authoritative nameservers");
1981 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
1986 cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
1987 NULL, dns_tree, "Additional records");
1992 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1994 dissect_dns_common(tvb, 0, tvb_length(tvb), pinfo, tree, FALSE);
1998 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2004 if (!tvb_bytes_exist(tvb, offset, 2))
2006 plen = tvb_get_ntohs(tvb, offset);
2010 * Is all of the DNS message in this TCP segment?
2012 if (tvb_reported_length_remaining(tvb, offset) < plen)
2018 dissect_dns_common(tvb, offset, plen, pinfo, tree, TRUE);
2023 proto_register_dns(void)
2025 static hf_register_info hf[] = {
2027 { "Length", "dns.length",
2028 FT_UINT16, BASE_DEC, NULL, 0x0,
2029 "Length of DNS-over-TCP request or response", HFILL }},
2031 { "Response", "dns.response",
2032 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2033 "TRUE if DNS response", HFILL }},
2035 { "Query", "dns.query",
2036 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2037 "TRUE if DNS query", HFILL }},
2039 { "Flags", "dns.flags",
2040 FT_UINT16, BASE_HEX, NULL, 0x0,
2042 { &hf_dns_transaction_id,
2043 { "Transaction ID", "dns.id",
2044 FT_UINT16, BASE_HEX, NULL, 0x0,
2045 "Identification of transaction", HFILL }},
2046 { &hf_dns_count_questions,
2047 { "Questions", "dns.count.queries",
2048 FT_UINT16, BASE_DEC, NULL, 0x0,
2049 "Number of queries in packet", HFILL }},
2050 { &hf_dns_count_answers,
2051 { "Answer RRs", "dns.count.answers",
2052 FT_UINT16, BASE_DEC, NULL, 0x0,
2053 "Number of answers in packet", HFILL }},
2054 { &hf_dns_count_auth_rr,
2055 { "Authority RRs", "dns.count.auth_rr",
2056 FT_UINT16, BASE_DEC, NULL, 0x0,
2057 "Number of authoritative records in packet", HFILL }},
2058 { &hf_dns_count_add_rr,
2059 { "Additional RRs", "dns.count.add_rr",
2060 FT_UINT16, BASE_DEC, NULL, 0x0,
2061 "Number of additional records in packet", HFILL }}
2063 static gint *ett[] = {
2073 proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2074 proto_register_field_array(proto_dns, hf, array_length(hf));
2075 proto_register_subtree_array(ett, array_length(ett));
2079 proto_reg_handoff_dns(void)
2081 dissector_add("udp.port", UDP_PORT_DNS, dissect_dns_udp, proto_dns);
2082 dissector_add("tcp.port", TCP_PORT_DNS, dissect_dns_tcp, proto_dns);