bd8999d515744aad94740497bc3b6ae7fe529c2d
[obnox/wireshark/wip.git] / packet-dns.c
1 /* packet-dns.c
2  * Routines for DNS packet disassembly
3  *
4  * $Id: packet-dns.c,v 1.79 2002/01/20 22:12:25 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  * 
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.
14  * 
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.
19  * 
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <memory.h>
36
37 #include <glib.h>
38 #include "packet.h"
39 #include "ipproto.h"
40 #include "resolv.h"
41 #include "packet-dns.h"
42 #include "prefs.h"
43
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;
54
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;
62
63 /* desegmentation of DNS over TCP */
64 static gboolean dns_desegment = TRUE;
65
66 /* DNS structs and definitions */
67
68 /* Ports used for DNS. */
69 #define UDP_PORT_DNS     53
70 #define TCP_PORT_DNS     53
71
72 /* Offsets of fields in the DNS header. */
73 #define DNS_ID          0
74 #define DNS_FLAGS       2
75 #define DNS_QUEST       4
76 #define DNS_ANS         6
77 #define DNS_AUTH        8
78 #define DNS_ADD         10
79
80 /* Length of DNS header. */
81 #define DNS_HDRLEN      12
82
83 /* type values  */
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 */
128
129 /* Class values */
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 */
136
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 */
147
148 /* Opcodes */
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 */
154
155 /* Reply codes */
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)
167
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"     },
180           { 0,               NULL                   } };
181
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)
189
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"        },
197           { 0,                  NULL                   } };
198
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)
204
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
208
209 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
210    
211    and
212    
213 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
214
215    which discuss them to some extent. */
216 static char *
217 dns_type_name (u_int type)
218 {
219   char *type_names[] = {
220     "unused",
221     "A",
222     "NS",
223     "MD",
224     "MF",
225     "CNAME",
226     "SOA",
227     "MB",
228     "MG",
229     "MR",
230     "NULL",
231     "WKS",
232     "PTR",
233     "HINFO",
234     "MINFO",
235     "MX",
236     "TXT",
237     "RP",                               /* RFC 1183 */
238     "AFSDB",                            /* RFC 1183 */
239     "X25",                              /* RFC 1183 */
240     "ISDN",                             /* RFC 1183 */
241     "RT",                               /* RFC 1183 */
242     "NSAP",                             /* RFC 1706 */
243     "NSAP-PTR",                         /* RFC 1348 */
244     "SIG",                              /* RFC 2535 */
245     "KEY",                              /* RFC 2535 */
246     "PX",                               /* RFC 1664 */
247     "GPOS",                             /* RFC 1712 */
248     "AAAA",                             /* RFC 1886 */
249     "LOC",                              /* RFC 1876 */
250     "NXT",                              /* RFC 2535 */
251     "EID",
252     "NIMLOC",
253     "SRV",                              /* RFC 2052 */
254     "ATMA",
255     "NAPTR",                            /* RFC 2168 */
256     "KX",                               /* RFC 2230 */
257     "CERT",                             /* RFC 2538 */
258     "A6",                               /* RFC 2874 */
259     "DNAME",                            /* RFC 2672 */
260     NULL,
261     "OPT"                               /* RFC 2671 */
262   };
263   
264   if (type < sizeof(type_names)/sizeof(type_names[0]))
265     return type_names[type] ? type_names[type] : "unknown";
266   
267   /* special cases */
268   switch (type) 
269     {
270       /* non standard  */
271     case 100:
272       return "UINFO";
273     case 101:
274       return "UID";
275     case 102:
276       return "GID";
277     case 103:
278       return "UNSPEC";
279     case T_WINS:
280       return "WINS";
281     case T_WINS_R:
282       return "WINS-R";
283
284       /* meta */
285     case T_TKEY:
286       return "TKEY";
287     case T_TSIG:
288       return "TSIG";
289
290       /* queries  */
291     case 251:
292       return "IXFR";    /* RFC 1995 */
293     case 252:
294       return "AXFR";
295     case 253:
296       return "MAILB";
297     case 254:
298       return "MAILA";
299     case 255:
300       return "ANY";
301
302     }
303
304   return "unknown";
305 }
306
307
308 static char *
309 dns_long_type_name (u_int type)
310 {
311   char *type_names[] = {
312     "unused",
313     "Host address",
314     "Authoritative name server",        
315     "Mail destination",
316     "Mail forwarder",
317     "Canonical name for an alias",
318     "Start of zone of authority",
319     "Mailbox domain name",
320     "Mail group member",
321     "Mail rename domain name",
322     "Null resource record",
323     "Well-known service description",
324     "Domain name pointer",
325     "Host information",
326     "Mailbox or mail list information",
327     "Mail exchange",
328     "Text strings",
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 */
343     "EID",
344     "NIMLOC",
345     "Service location",                 /* RFC 2052 */
346     "ATMA",
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 */
352     NULL,
353     "EDNS0 option"                      /* RFC 2671 */
354   };
355   static char unkbuf[7+1+2+1+4+1+1+10+1+1];     /* "Unknown RR type (%d)" */
356   
357   if (type < sizeof(type_names)/sizeof(type_names[0]))
358     return type_names[type] ? type_names[type] : "unknown";
359   
360   /* special cases */
361   switch (type) 
362     {
363       /* non standard  */
364     case 100:
365       return "UINFO";
366     case 101:
367       return "UID";
368     case 102:
369       return "GID";
370     case 103:
371       return "UNSPEC";
372     case T_WINS:
373       return "WINS";
374     case T_WINS_R:
375       return "WINS-R";
376
377       /* meta */
378     case T_TKEY:
379       return "Transaction Key";
380     case T_TSIG:
381       return "Transaction Signature";
382
383       /* queries  */
384     case 251:
385       return "Request for incremental zone transfer";   /* RFC 1995 */
386     case 252:
387       return "Request for full zone transfer";
388     case 253:
389       return "Request for mailbox-related records";
390     case 254:
391       return "Request for mail agent resource records";
392     case 255:
393       return "Request for all records";
394     }
395   
396   sprintf(unkbuf, "Unknown RR type (%d)", type);
397   return unkbuf;
398 }
399
400
401 char *
402 dns_class_name(int class)
403 {
404   char *class_name;
405   
406   switch (class) {
407   case C_IN:
408     class_name = "inet";
409     break;
410   case C_CS:
411     class_name = "csnet";
412     break;
413   case C_CH:
414     class_name = "chaos";
415     break;
416   case C_HS:
417     class_name = "hesiod";
418     break;
419   case C_NONE:
420     class_name = "none";
421     break;
422   case C_ANY:
423     class_name = "any";
424     break;
425   default:
426     class_name = "unknown";
427   }
428
429   return class_name;
430 }
431
432 int
433 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
434     char *name, int maxname)
435 {
436   int start_offset = offset;
437   char *np = name;
438   int len = -1;
439   int chars_processed = 0;
440   int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
441   int component_len;
442   int indir_offset;
443
444   maxname--;    /* reserve space for the trailing '\0' */
445   for (;;) {
446     component_len = tvb_get_guint8(tvb, offset);
447     offset++;
448     if (component_len == 0)
449       break;
450     chars_processed++;
451     switch (component_len & 0xc0) {
452
453     case 0x00:
454       /* Label */
455       if (np != name) {
456         /* Not the first component - put in a '.'. */
457         if (maxname > 0) {
458           *np++ = '.';
459           maxname--;
460         }
461       }
462       while (component_len > 0) {
463         if (maxname > 0) {
464           *np++ = tvb_get_guint8(tvb, offset);
465           maxname--;
466         }
467         component_len--;
468         offset++;
469         chars_processed++;
470       }
471       break;
472
473     case 0x40:
474       /* Extended label (RFC 2673) */
475       switch (component_len & 0x3f) {
476
477       case 0x01:
478         /* Bitstring label */
479         {
480           int bit_count;
481           int label_len;
482
483           bit_count = tvb_get_guint8(tvb, offset);
484           offset++;
485           label_len = (bit_count - 1) / 8 + 1;
486         
487           np += sprintf(np, "\\[x");
488           while(label_len--) {
489             np += sprintf(np, "%02x", tvb_get_guint8(tvb, offset));
490             offset++;
491           }
492           np += sprintf(np, "/%d]", bit_count);
493         }
494         break;
495
496       default:
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;
501       }
502       break;
503
504     case 0x80:
505       goto error;       /* error */
506
507     case 0xc0:
508       /* Pointer. */
509       indir_offset = dns_data_offset +
510           (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
511       offset++;
512       chars_processed++;
513
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. */
517       if (len < 0)
518         len = offset - start_offset;
519
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
522          looping. */
523       if (chars_processed >= data_size) {
524         strcpy(name, "<Name contains a pointer that loops>");
525         return len;
526       }
527
528       offset = indir_offset;
529       break;    /* now continue processing from there */
530     }
531   }
532         
533 error:
534   *np = '\0';
535   /* If "len" is negative, we haven't seen a pointer, and thus haven't
536      set the length, so set it. */
537   if (len < 0)
538     len = offset - start_offset;
539   /* Zero-length name means "root server" */
540   if (*name == '\0')
541     strcpy(name, "<Root>");
542   return len;
543 }
544
545
546 static int
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)
549 {
550   int len;
551   int name_len;
552   int type;
553   int class;
554   char name[MAXDNAME];
555   int start_offset = offset;
556
557   name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
558   offset += name_len;
559   
560   type = tvb_get_ntohs(tvb, offset);
561   offset += 2;
562
563   class = tvb_get_ntohs(tvb, offset);
564   offset += 2;
565
566   strcpy (name_ret, name);
567   *type_ret = type;
568   *class_ret = class;
569   *name_len_ret = name_len;
570
571   len = offset - start_offset;
572   return len;
573 }
574
575 static double
576 rfc1867_size(tvbuff_t *tvb, int offset)
577 {
578   guint8 val;
579   double size;
580   guint32 exponent;
581
582   val = tvb_get_guint8(tvb, offset);
583   size = (val & 0xF0) >> 4;
584   exponent = (val & 0x0F);
585   while (exponent != 0) {
586     size *= 10;
587     exponent--;
588   }
589   return size / 100;    /* return size in meters, not cm */
590 }
591
592 static char *
593 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
594 {
595   guint32 angle;
596   char direction;
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];
599
600   angle = tvb_get_ntohl(tvb, offset);
601
602   if (angle < 0x80000000U) {
603     angle = 0x80000000U - angle;
604     direction = nsew[1];
605   } else {
606     angle = angle - 0x80000000U;
607     direction = nsew[0];
608   }
609   tsecs = angle % 1000;
610   angle = angle / 1000;
611   secs = angle % 60;
612   angle = angle / 60;
613   minutes = angle % 60;
614   degrees = angle / 60;
615   sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
616                 tsecs, direction);
617   return buf;
618 }
619
620 static int
621 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
622   column_info *cinfo, proto_tree *dns_tree)
623 {
624   int len;
625   char name[MAXDNAME];
626   int name_len;
627   int type;
628   int class;
629   char *class_name;
630   char *type_name;
631   char *long_type_name;
632   int data_offset;
633   int data_start;
634   proto_tree *q_tree;
635   proto_item *tq;
636
637   data_start = data_offset = offset;
638
639   len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
640     &type, &class);
641   data_offset += len;
642
643   type_name = dns_type_name(type);
644   class_name = dns_class_name(class);
645   long_type_name = dns_long_type_name(type);
646
647   if (cinfo != NULL)
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);
653
654     proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
655     offset += name_len;
656
657     proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
658     offset += 2;
659
660     proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
661     offset += 2;
662   }
663   
664   return data_offset - data_start;
665 }
666
667
668 proto_tree *
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)
672 {
673   proto_tree *rr_tree;
674
675   rr_tree = proto_item_add_subtree(trr, rr_type);
676   proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
677   offset += namelen;
678   proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
679   offset += 2;
680   proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
681   offset += 2;
682   proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
683                                                 time_secs_to_str(ttl));
684   offset += 4;
685   proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
686   return rr_tree;
687 }
688
689 static proto_tree *
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)
693 {
694   proto_tree *rr_tree;
695
696   rr_tree = proto_item_add_subtree(trr, rr_type);
697   proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
698   offset += namelen;
699   proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
700   offset += 2;
701   proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
702       class & 0xffff);
703   offset += 2;
704   proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
705       (ttl >> 24) & 0xff0);
706   offset++;
707   proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
708       (ttl >> 16) & 0xff);
709   offset++;
710   proto_tree_add_text(rr_tree, tvb, offset, 2, "Must be zero: 0x%x", ttl & 0xffff);
711   offset += 2;
712   proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
713   return rr_tree;
714 }
715
716 /*
717  * SIG, KEY, and CERT RR algorithms.
718  */
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 */      
726
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" },
735           { 0,                   NULL }
736 };
737
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 */
743
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" },
750           { 0,                   NULL }
751 };
752
753 static int
754 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
755   column_info *cinfo, proto_tree *dns_tree)
756 {
757   int len;
758   char name[MAXDNAME];
759   int name_len;
760   int type;
761   int class;
762   char *class_name;
763   char *type_name;
764   char *long_type_name;
765   int data_offset;
766   int cur_offset;
767   int data_start;
768   u_int ttl;
769   u_short data_len;
770   proto_tree *rr_tree = NULL;
771   proto_item *trr = NULL;
772
773   data_start = data_offset = offset;
774   cur_offset = offset;
775
776   len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
777     &type, &class);
778   data_offset += len;
779   cur_offset += len;
780
781   type_name = dns_type_name(type);
782   class_name = dns_class_name(class);
783   long_type_name = dns_long_type_name(type);
784
785   ttl = tvb_get_ntohl(tvb, data_offset);
786   data_offset += 4;
787   cur_offset += 4;
788
789   data_len = tvb_get_ntohs(tvb, data_offset);
790   data_offset += 2;
791   cur_offset += 2;
792
793   if (cinfo != NULL)
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);
800     if (type != T_OPT) {
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);
803     } else  {
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);
806     }
807   }
808
809   switch (type) {
810
811   case T_A:
812     {
813       const guint8 *addr;
814       guint32 addr_int;
815
816       addr = tvb_get_ptr(tvb, cur_offset, 4);
817       if (cinfo != NULL)
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",
822                      ip_to_str(addr));
823       }
824       if (class == C_IN) {
825         memcpy(&addr_int, addr, sizeof(addr_int));
826         add_host_name(addr_int, name);
827       }
828     }
829     break;
830
831   case T_NS:
832     {
833       char ns_name[MAXDNAME];
834       int ns_name_len;
835       
836       ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
837       if (cinfo != NULL)
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",
842                         ns_name);
843       }
844     }
845     break;
846
847   case T_CNAME:
848     {
849       char cname[MAXDNAME];
850       int cname_len;
851       
852       cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
853       if (cinfo != NULL)
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",
858                         cname);
859       }
860     }
861     break;
862
863   case T_SOA:
864     {
865       char mname[MAXDNAME];
866       int mname_len;
867       char rname[MAXDNAME];
868       int rname_len;
869       guint32 serial;
870       guint32 refresh;
871       guint32 retry;
872       guint32 expire;
873       guint32 minimum;
874
875       mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
876       if (cinfo != NULL)
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",
881                        mname);
882         cur_offset += mname_len;
883       
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",
886                        rname);
887         cur_offset += rname_len;
888
889         serial = tvb_get_ntohl(tvb, cur_offset);
890         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
891                        serial);
892         cur_offset += 4;
893
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));
897         cur_offset += 4;
898
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));
902         cur_offset += 4;
903
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));
907         cur_offset += 4;
908
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));
912       }
913     }
914     break;
915
916   case T_PTR:
917     {
918       char pname[MAXDNAME];
919       int pname_len;
920       
921       pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
922       if (cinfo != NULL)
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",
927                         pname);
928       }
929       break;
930     }
931     break;
932
933   case T_WKS:
934     {
935       int rr_len = data_len;
936       const guint8 *wks_addr;
937       guint8 protocol;
938       guint8 bits;
939       int mask;
940       int port_num;
941       int i;
942       char bitnames[128+1];
943       char portnumstring[10+1];
944       
945       wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
946       if (cinfo != NULL)
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));
952         cur_offset += 4;
953         rr_len -= 4;
954
955         protocol = tvb_get_guint8(tvb, cur_offset);
956         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
957                      ipprotostr(protocol));
958         cur_offset += 1;
959         rr_len -= 1;
960
961         port_num = 0;
962         while (rr_len != 0) {
963           bits = tvb_get_guint8(tvb, cur_offset);
964           if (bits != 0) {
965             mask = 1<<7;
966             bitnames[0] = '\0';
967             for (i = 0; i < 8; i++) {
968               if (bits & mask) {
969                 if (bitnames[0] != '\0')
970                   strcat(bitnames, ", ");
971                 switch (protocol) {
972
973                 case IP_PROTO_TCP:
974                   strcat(bitnames, get_tcp_port(port_num));
975                   break;
976
977                 case IP_PROTO_UDP:
978                   strcat(bitnames, get_udp_port(port_num));
979                   break;
980
981                 default:
982                   sprintf(portnumstring, "%u", port_num);
983                   strcat(bitnames, portnumstring);
984                   break;
985                 }
986               }
987               mask >>= 1;
988               port_num++;
989             }
990             proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
991                 "Bits: 0x%02x (%s)", bits, bitnames);
992           } else
993             port_num += 8;
994           cur_offset += 1;
995           rr_len -= 1;
996         }
997       }
998     }
999     break;
1000
1001   case T_HINFO:
1002     {
1003       int cpu_offset;
1004       int cpu_len;
1005       const guint8 *cpu;
1006       int os_offset;
1007       int os_len;
1008       const guint8 *os;
1009
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);
1016       if (cinfo != NULL)
1017         col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1018             os_len, os);
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",
1023                         cpu_len, cpu);
1024         proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1025                         os_len, os);
1026       }
1027       break;
1028     }
1029     break;
1030
1031   case T_MX:
1032     {
1033       guint16 preference = 0;
1034       char mx_name[MAXDNAME];
1035       int mx_name_len;
1036       
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));
1039       if (cinfo != NULL)
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",
1046                         mx_name);
1047       }
1048     }
1049     break;
1050
1051   case T_TXT:
1052     {
1053       int rr_len = data_len;
1054       int txt_offset;
1055       int txt_len;
1056
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;
1065         }
1066       }
1067     }
1068     break;
1069
1070   case T_SIG:
1071     {
1072       int rr_len = data_len;
1073       guint16 type_covered;
1074       nstime_t nstime;
1075       char signer_name[MAXDNAME];
1076       int signer_name_len;
1077
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));
1083         cur_offset += 2;
1084         rr_len -= 2;
1085
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)"));
1089         cur_offset += 1;
1090         rr_len -= 1;
1091
1092         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Labels: %u",
1093                 tvb_get_guint8(tvb, cur_offset));
1094         cur_offset += 1;
1095         rr_len -= 1;
1096
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)));
1099         cur_offset += 4;
1100         rr_len -= 4;
1101
1102         nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1103         nstime.nsecs = 0;
1104         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1105                 abs_time_to_str(&nstime));
1106         cur_offset += 4;
1107         rr_len -= 4;
1108
1109         nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1110         nstime.nsecs = 0;
1111         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1112                 abs_time_to_str(&nstime));
1113         cur_offset += 4;
1114         rr_len -= 4;
1115
1116         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1117                 tvb_get_ntohs(tvb, cur_offset));
1118         cur_offset += 2;
1119         rr_len -= 2;
1120
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;
1126
1127         proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1128       }
1129     }
1130     break;
1131
1132   case T_KEY:
1133     {
1134       int rr_len = data_len;
1135       guint16 flags;
1136       proto_item *tf;
1137       proto_tree *flags_tree;
1138
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) {
1152           /* We have a key */
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"));
1180         }
1181         cur_offset += 2;
1182         rr_len -= 2;
1183
1184         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1185                 tvb_get_guint8(tvb, cur_offset));
1186         cur_offset += 1;
1187         rr_len -= 1;
1188
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)"));
1192         cur_offset += 1;
1193                 rr_len -= 1;
1194
1195         proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1196       }
1197     }
1198     break;
1199
1200   case T_AAAA:
1201     {
1202       const guint8 *addr6;
1203
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));
1208       }
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));
1214       }
1215     }
1216     break;
1217
1218   case T_A6:
1219     {
1220       unsigned short pre_len;
1221       unsigned short suf_len;
1222       unsigned short suf_octet_count;
1223       char pname[MAXDNAME];
1224       int pname_len;
1225       int a6_offset;
1226       int suf_offset;
1227       guint8 suffix[16];
1228
1229       a6_offset = cur_offset;
1230       pre_len = tvb_get_guint8(tvb, cur_offset);
1231       cur_offset++;
1232       suf_len = 128 - pre_len;
1233       suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1234       /* Pad prefix */
1235       for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1236         suffix[suf_offset] = 0;
1237       }
1238       for (; suf_offset < 16; suf_offset++) {
1239         suffix[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1240         cur_offset++;
1241       }
1242
1243       if (pre_len > 0) {
1244         pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, 
1245                                  pname, sizeof(pname));
1246       } else {
1247         strcpy(pname, "");   
1248         pname_len = 0;
1249       }
1250
1251       if (cinfo != NULL) {
1252         col_append_fstr(cinfo, COL_INFO, " %d %s %s", 
1253                         pre_len, 
1254                         ip6_to_str((struct e_in6_addr *)&suffix), 
1255                         pname);
1256       }
1257       if (dns_tree != NULL) {
1258         proto_tree_add_text(rr_tree, tvb, a6_offset, 1, 
1259                             "Prefix len: %u", pre_len);
1260         a6_offset++;
1261         if (suf_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;
1266         }
1267         if (pre_len > 0) {
1268           proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len, 
1269                               "Prefix name: %s", pname);
1270         }
1271         proto_item_append_text(trr, ", addr %d %s %s",
1272                             pre_len, 
1273                             ip6_to_str((struct e_in6_addr *)&suffix), 
1274                             pname);
1275       }
1276     }
1277     break;
1278
1279   case T_DNAME:
1280     {
1281       char dname[MAXDNAME];
1282       int dname_len;
1283       
1284       dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, 
1285                                dname, sizeof(dname));
1286       if (cinfo != NULL)
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);
1292       }
1293     }
1294     break;
1295
1296   case T_LOC:
1297     {
1298       guint8 version;
1299
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);
1303         if (version == 0) {
1304           /* Version 0, the only version RFC 1876 discusses. */
1305           cur_offset++;
1306
1307           proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1308                                 rfc1867_size(tvb, cur_offset));
1309           cur_offset++;
1310
1311           proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1312                                 rfc1867_size(tvb, cur_offset));
1313           cur_offset++;
1314
1315           proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1316                                 rfc1867_size(tvb, cur_offset));
1317           cur_offset++;
1318
1319           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1320                                 rfc1867_angle(tvb, cur_offset, "NS"));
1321           cur_offset += 4;
1322
1323           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1324                                 rfc1867_angle(tvb, cur_offset, "EW"));
1325           cur_offset += 4;
1326
1327           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1328                                 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1329         } else
1330           proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1331       }
1332       break;
1333     }
1334     break;
1335       
1336   case T_NXT:
1337     {
1338       int rr_len = data_len;
1339       char next_domain_name[MAXDNAME];
1340       int next_domain_name_len;
1341       int rr_type;
1342       guint8 bits;
1343       int mask;
1344       int i;
1345
1346       next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1347                         next_domain_name, sizeof(next_domain_name));
1348       if (cinfo != NULL)
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",
1352                      next_domain_name);
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;
1357         rr_type = 0;
1358         while (rr_len != 0) {
1359           bits = tvb_get_guint8(tvb, cur_offset);
1360           mask = 1<<7;
1361           for (i = 0; i < 8; i++) {
1362             if (bits & mask) {
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));
1367             }
1368             mask >>= 1;
1369             rr_type++;
1370           }
1371           cur_offset += 1;
1372           rr_len -= 1;
1373         }
1374       }
1375     }
1376     break;
1377
1378   case T_KX:
1379     {
1380       guint16 preference = 0;
1381       char kx_name[MAXDNAME];
1382       int kx_name_len;
1383       
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));
1386       if (cinfo != NULL)
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",
1393                         kx_name);
1394       }
1395     }
1396     break;
1397
1398   case T_CERT:
1399     {
1400       guint16 cert_type, cert_keytag;
1401       guint8 cert_keyalg;
1402       int rr_len = data_len;
1403
1404       cert_type = tvb_get_ntohs(tvb, cur_offset);
1405       cur_offset += 2;
1406       rr_len -= 2;
1407       cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1408       cur_offset += 2;
1409       rr_len -= 2;
1410       cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1411       cur_offset += 1;
1412       rr_len -= 1;
1413
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",
1419                 cert_keytag);
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");
1424       }
1425
1426     }
1427     break;
1428
1429   case T_OPT:
1430     if (dns_tree != NULL)
1431       proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1432     break;
1433
1434   case T_TKEY:
1435     {
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;
1440       nstime_t nstime;
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"            },
1447                   { 0,                         NULL                } };
1448
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;
1455
1456         nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1457         nstime.nsecs = 0;
1458         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1459                 abs_time_to_str(&nstime));
1460         cur_offset += 4;
1461         rr_len -= 4;
1462
1463         nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1464         nstime.nsecs = 0;
1465         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1466                 abs_time_to_str(&nstime));
1467         cur_offset += 4;
1468         rr_len -= 4;
1469
1470         tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1471         cur_offset += 2;
1472         rr_len -= 2;
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)"));
1476
1477         tkey_error = tvb_get_ntohs(tvb, cur_offset);
1478         cur_offset += 2;
1479         rr_len -= 2;
1480
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)")));
1484
1485         tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1486         cur_offset += 2;
1487         rr_len -= 2;
1488
1489         proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1490         cur_offset += tkey_keylen;
1491         rr_len -= tkey_keylen;
1492
1493         tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1494         cur_offset += 2;
1495         rr_len -= 2;
1496
1497         proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1498         cur_offset += tkey_otherlen;
1499         rr_len -= tkey_otherlen;
1500       }
1501     }
1502     break;
1503
1504   case T_TSIG:
1505     {
1506       guint16 tsig_fudge;
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;
1511       nstime_t nstime;
1512       int rr_len = data_len;
1513
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;
1520
1521         tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1522         tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1523         nstime.secs = tsig_timelo;
1524         nstime.nsecs = 0;
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)");
1527         cur_offset += 6;
1528         rr_len -= 6;
1529
1530         tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1531         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1532                 tsig_fudge);
1533         cur_offset += 2;
1534         rr_len -= 2;
1535
1536         tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1537         cur_offset += 2;
1538         rr_len -= 2;
1539
1540         proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1541         cur_offset += tsig_siglen;
1542         rr_len -= tsig_siglen;
1543
1544         tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1545         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1546                 tsig_originalid);
1547         cur_offset += 2;
1548         rr_len -= 2;
1549
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)")));
1554         cur_offset += 2;
1555         rr_len -= 2;
1556
1557         tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1558         cur_offset += 2;
1559         rr_len -= 2;
1560
1561         proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1562         cur_offset += tsig_otherlen;
1563         rr_len -= tsig_otherlen;
1564       }
1565     }
1566     break;
1567
1568   case T_WINS:
1569     {
1570       int rr_len = data_len;
1571       guint32 local_flag;
1572       guint32 lookup_timeout;
1573       guint32 cache_timeout;
1574       guint32 nservers;
1575
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");
1581         }
1582         cur_offset += 4;
1583         rr_len -= 4;
1584
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",
1588                        lookup_timeout);
1589         }
1590         cur_offset += 4;
1591         rr_len -= 4;
1592
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",
1596                        cache_timeout);
1597         }
1598         cur_offset += 4;
1599         rr_len -= 4;
1600
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",
1604                        nservers);
1605         }
1606         cur_offset += 4;
1607         rr_len -= 4;
1608
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)));
1613           }
1614           cur_offset += 4;
1615           rr_len -= 4;
1616           nservers--;
1617         }
1618       }
1619     }
1620     break;
1621
1622   case T_WINS_R:
1623     {
1624       int rr_len = data_len;
1625       guint32 local_flag;
1626       guint32 lookup_timeout;
1627       guint32 cache_timeout;
1628       char dname[MAXDNAME];
1629       int dname_len;
1630
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");
1635       }
1636       cur_offset += 4;
1637       rr_len -= 4;
1638
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",
1642                        lookup_timeout);
1643       }
1644       cur_offset += 4;
1645       rr_len -= 4;
1646
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",
1650                        cache_timeout);
1651       }
1652       cur_offset += 4;
1653       rr_len -= 4;
1654
1655       dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1656       if (cinfo != NULL)
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",
1661                         dname);
1662       }
1663     }
1664     break;
1665
1666   case T_SRV:
1667     {
1668       guint16 priority = 0;
1669       guint16 weight = 0;
1670       guint16 port = 0;
1671       char target[MAXDNAME];
1672       int target_len;
1673       
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);
1677
1678       target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1679       if (cinfo != NULL)
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",
1689                         target);
1690       }
1691     }
1692     break;
1693
1694     /* TODO: parse more record types */
1695
1696   default:
1697     if (dns_tree != NULL)
1698       proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1699     break;
1700   }
1701   
1702   data_offset += data_len;
1703         
1704   return data_offset - data_start;
1705 }
1706
1707 static int
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)
1710 {
1711   int start_off, add_off;
1712   proto_tree *qatree = NULL;
1713   proto_item *ti = NULL;
1714   
1715   start_off = cur_off;
1716   if (dns_tree) {
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);
1720   }
1721   while (count-- > 0) {
1722     add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
1723     cur_off += add_off;
1724   }
1725   if (ti)
1726     proto_item_set_len(ti, cur_off - start_off);
1727
1728   return cur_off - start_off;
1729 }
1730
1731 static int
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)
1734 {
1735   int start_off, add_off;
1736   proto_tree *qatree = NULL;
1737   proto_item *ti = NULL;
1738   
1739   start_off = cur_off;
1740   if (dns_tree) {
1741     ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
1742     qatree = proto_item_add_subtree(ti, ett_dns_ans);
1743   }
1744   while (count-- > 0) {
1745     add_off = dissect_dns_answer(tvb, cur_off, dns_data_offset, cinfo, qatree);
1746     cur_off += add_off;
1747   }
1748   if (ti)
1749     proto_item_set_len(ti, cur_off - start_off);
1750
1751   return cur_off - start_off;
1752 }
1753
1754 static int
1755 dissect_dns_common(tvbuff_t *tvb, int offset, int msg_len, packet_info *pinfo,
1756         proto_tree *tree, gboolean is_tcp)
1757 {
1758   int dns_data_offset;
1759   column_info *cinfo;
1760   proto_tree *dns_tree = NULL, *field_tree;
1761   proto_item *ti, *tf;
1762   guint16    id, flags, quest, ans, auth, add;
1763   char buf[128+1];
1764   int cur_off;
1765   int isupdate;
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"           },
1772                   { 0,              NULL                      } };
1773
1774   dns_data_offset = offset;
1775
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);
1780
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);
1784
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) {
1790         strcat(buf, ", ");
1791         strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1792             "Unknown error (%x)"));
1793       }
1794     }
1795     col_add_str(pinfo->cinfo, COL_INFO, buf);
1796     cinfo = pinfo->cinfo;
1797   } else {
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). */
1802     cinfo = NULL;
1803   }
1804   if ((flags & F_OPCODE) == OPCODE_UPDATE)
1805     isupdate = 1;
1806   else
1807     isupdate = 0;
1808
1809   if (tree) {
1810     ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, offset, msg_len,
1811       "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1812     
1813     dns_tree = proto_item_add_subtree(ti, ett_dns);
1814
1815     if (is_tcp) {
1816       /* Put the length indication into the tree. */
1817       proto_tree_add_uint(dns_tree, hf_dns_length, tvb, offset - 2, 2, msg_len);
1818     }
1819
1820     if (flags & F_RESPONSE)
1821       proto_tree_add_boolean_hidden(dns_tree, hf_dns_response, tvb, offset, 4, 1);
1822     else
1823       proto_tree_add_boolean_hidden(dns_tree, hf_dns_query, tvb, offset, 4, 1);
1824
1825     proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb, 
1826                         offset + DNS_ID, 2, id);
1827
1828     strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
1829     if (flags & F_RESPONSE) {
1830       strcat(buf, " response");
1831       strcat(buf, ", ");
1832       strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1833             "Unknown error"));
1834     }
1835     tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb, 
1836                                     offset + DNS_FLAGS, 2, 
1837                                     flags,
1838                                     "Flags: 0x%04x (%s)",
1839                                     flags, buf);
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,
1850               2*8,
1851               "Server is an authority for domain",
1852               "Server is not an authority for domain"));
1853     }
1854     proto_tree_add_text(field_tree, tvb, offset + DNS_FLAGS, 2, "%s",
1855        decode_boolean_bitfield(flags, F_TRUNCATED,
1856             2*8,
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,
1861             2*8,
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,
1867               2*8,
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,
1872             2*8,
1873             "Answer/authority portion was authenticated by the server",
1874             "Answer/authority portion was not authenticated by the server"));
1875     }
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,
1879             2*8,
1880             "Non-authenticated data is acceptable",
1881             "Non-authenticated data is unacceptable"));
1882     }
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"));
1887     }
1888   }
1889   quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
1890   if (tree) {
1891     proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb, 
1892                         offset + DNS_QUEST, 2, quest);
1893   }
1894   ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
1895   if (tree) {
1896     proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb, 
1897                         offset + DNS_ANS, 2, ans);
1898   }
1899   auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
1900   if (tree) {
1901     proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb, 
1902                         offset + DNS_AUTH, 2, auth);
1903   }
1904   add = tvb_get_ntohs(tvb, offset + DNS_ADD);
1905   if (tree) {
1906     proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb, 
1907                         offset + DNS_ADD, 2, add);
1908
1909   }
1910   cur_off = offset + DNS_HDRLEN;
1911
1912   if (quest > 0) {
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);
1918   }
1919     
1920   if (ans > 0) {
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),
1925                                       dns_tree,
1926                                       (isupdate ?  "Prerequisites" : "Answers"));
1927   }
1928     
1929   /* Don't add information about the authoritative name servers, or the
1930      additional records, to the summary. */
1931   if (auth > 0) {
1932     cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
1933                                       NULL, dns_tree,
1934                                       (isupdate ?  "Updates" :
1935                                                    "Authoritative nameservers"));
1936   }
1937
1938   if (add > 0) {
1939     cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
1940                                       NULL, dns_tree, "Additional records");
1941   }
1942
1943   return cur_off;
1944 }
1945
1946 static void
1947 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1948 {
1949         dissect_dns_common(tvb, 0, tvb_length(tvb), pinfo, tree, FALSE);
1950 }
1951
1952 static void
1953 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1954 {
1955         int offset = 0;
1956         guint16 plen;
1957
1958         for (;;) {
1959                 /*
1960                  * XXX - should handle a length field split across segment
1961                  * boundaries.
1962                  */
1963                 if (!tvb_bytes_exist(tvb, offset, 2))
1964                         break;
1965                 plen = tvb_get_ntohs(tvb, offset);
1966
1967                 /*
1968                  * Desegmentation check.
1969                  */
1970                 if (dns_desegment) {
1971                         if (pinfo->can_desegment
1972                             && plen > tvb_length_remaining(tvb, offset+2)) {
1973                                 /*
1974                                  * This frame doesn't have all of the data
1975                                  * for this message, but we can do reassembly
1976                                  * on it.
1977                                  *
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
1981                                  * return.
1982                                  */
1983                                 pinfo->desegment_offset = offset;
1984                                 pinfo->desegment_len =
1985                                     plen - tvb_length_remaining(tvb, offset+2);
1986                                 return;
1987                         }
1988                 }
1989
1990                 offset += 2;
1991
1992                 /*
1993                  * Is all of the DNS message in this TCP segment?
1994                  */
1995                 if (tvb_reported_length_remaining(tvb, offset) < plen)
1996                         break;
1997
1998                 /*
1999                  * Yes - dissect it.
2000                  */
2001                 offset = dissect_dns_common(tvb, offset, plen, pinfo, tree,
2002                     TRUE);
2003         }
2004 }
2005
2006 void
2007 proto_register_dns(void)
2008 {
2009   static hf_register_info hf[] = {
2010     { &hf_dns_length,
2011       { "Length",               "dns.length",  
2012         FT_UINT16, BASE_DEC, NULL, 0x0,
2013         "Length of DNS-over-TCP request or response", HFILL }},
2014     { &hf_dns_response,
2015       { "Response",             "dns.response",  
2016         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2017         "TRUE if DNS response", HFILL }},
2018     { &hf_dns_query,
2019       { "Query",                "dns.query",  
2020         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2021         "TRUE if DNS query", HFILL }},
2022     { &hf_dns_flags,
2023       { "Flags",                "dns.flags",  
2024         FT_UINT16, BASE_HEX, NULL, 0x0,
2025         "", HFILL }},
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 }}
2046   };
2047   static gint *ett[] = {
2048     &ett_dns,
2049     &ett_dns_qd,
2050     &ett_dns_rr,
2051     &ett_dns_qry,
2052     &ett_dns_ans,
2053     &ett_dns_flags,
2054     &ett_t_key_flags,
2055   };
2056   module_t *dns_module;
2057
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));
2061
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",
2066     &dns_desegment);
2067 }
2068
2069 void
2070 proto_reg_handoff_dns(void)
2071 {
2072   dissector_handle_t dns_udp_handle;
2073   dissector_handle_t dns_tcp_handle;
2074
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);
2079 }