Removed trailing whitespaces from .h and .c files using the
[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.91 2002/08/19 16:02:45 itojun 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 NEED_SNPRINTF_H
30 # include "snprintf.h"
31 #endif
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <memory.h>
36
37 #include <glib.h>
38 #include <epan/packet.h>
39 #include "ipproto.h"
40 #include <epan/resolv.h>
41 #include "packet-dns.h"
42 #include "packet-tcp.h"
43 #include "prefs.h"
44
45 static int proto_dns = -1;
46 static int hf_dns_length = -1;
47 static int hf_dns_flags = -1;
48 static int hf_dns_flags_response = -1;
49 static int hf_dns_flags_opcode = -1;
50 static int hf_dns_flags_authoritative = -1;
51 static int hf_dns_flags_truncated = -1;
52 static int hf_dns_flags_recdesired = -1;
53 static int hf_dns_flags_recavail = -1;
54 static int hf_dns_flags_authenticated = -1;
55 static int hf_dns_flags_checkdisable = -1;
56 static int hf_dns_flags_rcode = -1;
57 static int hf_dns_transaction_id = -1;
58 static int hf_dns_count_questions = -1;
59 static int hf_dns_count_answers = -1;
60 static int hf_dns_count_auth_rr = -1;
61 static int hf_dns_count_add_rr = -1;
62
63 static gint ett_dns = -1;
64 static gint ett_dns_qd = -1;
65 static gint ett_dns_rr = -1;
66 static gint ett_dns_qry = -1;
67 static gint ett_dns_ans = -1;
68 static gint ett_dns_flags = -1;
69 static gint ett_t_key_flags = -1;
70
71 /* desegmentation of DNS over TCP */
72 static gboolean dns_desegment = TRUE;
73
74 /* DNS structs and definitions */
75
76 /* Ports used for DNS. */
77 #define UDP_PORT_DNS     53
78 #define TCP_PORT_DNS     53
79 #define UDP_PORT_MDNS    5353
80 #define TCP_PORT_MDNS    5353
81
82 /* Offsets of fields in the DNS header. */
83 #define DNS_ID          0
84 #define DNS_FLAGS       2
85 #define DNS_QUEST       4
86 #define DNS_ANS         6
87 #define DNS_AUTH        8
88 #define DNS_ADD         10
89
90 /* Length of DNS header. */
91 #define DNS_HDRLEN      12
92
93 /* type values  */
94 #define T_A             1               /* host address */
95 #define T_NS            2               /* authoritative name server */
96 #define T_MD            3               /* mail destination (obsolete) */
97 #define T_MF            4               /* mail forwarder (obsolete) */
98 #define T_CNAME         5               /* canonical name */
99 #define T_SOA           6               /* start of authority zone */
100 #define T_MB            7               /* mailbox domain name (experimental) */
101 #define T_MG            8               /* mail group member (experimental) */
102 #define T_MR            9               /* mail rename domain name (experimental) */
103 #define T_NULL          10              /* null RR (experimental) */
104 #define T_WKS           11              /* well known service */
105 #define T_PTR           12              /* domain name pointer */
106 #define T_HINFO         13              /* host information */
107 #define T_MINFO         14              /* mailbox or mail list information */
108 #define T_MX            15              /* mail routing information */
109 #define T_TXT           16              /* text strings */
110 #define T_RP            17              /* responsible person (RFC 1183) */
111 #define T_AFSDB         18              /* AFS data base location (RFC 1183) */
112 #define T_X25           19              /* X.25 address (RFC 1183) */
113 #define T_ISDN          20              /* ISDN address (RFC 1183) */
114 #define T_RT            21              /* route-through (RFC 1183) */
115 #define T_NSAP          22              /* OSI NSAP (RFC 1706) */
116 #define T_NSAP_PTR      23              /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
117 #define T_SIG           24              /* digital signature (RFC 2535) */
118 #define T_KEY           25              /* public key (RFC 2535) */
119 #define T_PX            26              /* pointer to X.400/RFC822 mapping info (RFC 1664) */
120 #define T_GPOS          27              /* geographical position (RFC 1712) */
121 #define T_AAAA          28              /* IPv6 address (RFC 1886) */
122 #define T_LOC           29              /* geographical location (RFC 1876) */
123 #define T_NXT           30              /* "next" name (RFC 2535) */
124 #define T_EID           31              /* ??? (Nimrod?) */
125 #define T_NIMLOC        32              /* ??? (Nimrod?) */
126 #define T_SRV           33              /* service location (RFC 2052) */
127 #define T_ATMA          34              /* ??? */
128 #define T_NAPTR         35              /* naming authority pointer (RFC 2168) */
129 #define T_KX            36              /* Key Exchange (RFC 2230) */
130 #define T_CERT          37              /* Certificate (RFC 2538) */
131 #define T_A6            38              /* IPv6 address with indirection (RFC 2874) */
132 #define T_DNAME         39              /* Non-terminal DNS name redirection (RFC 2672) */
133 #define T_OPT           41              /* OPT pseudo-RR (RFC 2671) */
134 #define T_TKEY          249             /* Transaction Key (RFC 2930) */
135 #define T_TSIG          250             /* Transaction Signature (RFC 2845) */
136 #define T_WINS          65281           /* Microsoft's WINS RR */
137 #define T_WINS_R        65282           /* Microsoft's WINS-R RR */
138
139 /* Class values */
140 #define C_IN            1               /* the Internet */
141 #define C_CS            2               /* CSNET (obsolete) */
142 #define C_CH            3               /* CHAOS */
143 #define C_HS            4               /* Hesiod */
144 #define C_NONE          254             /* none */
145 #define C_ANY           255             /* any */
146
147 /* Bit fields in the flags */
148 #define F_RESPONSE      (1<<15)         /* packet is response */
149 #define F_OPCODE        (0xF<<11)       /* query opcode */
150 #define OPCODE_SHIFT    11
151 #define F_AUTHORITATIVE (1<<10)         /* response is authoritative */
152 #define F_TRUNCATED     (1<<9)          /* response is truncated */
153 #define F_RECDESIRED    (1<<8)          /* recursion desired */
154 #define F_RECAVAIL      (1<<7)          /* recursion available */
155 #define F_AUTHENTIC     (1<<5)          /* authentic data (RFC2535) */
156 #define F_CHECKDISABLE  (1<<4)          /* checking disabled (RFC2535) */
157 #define F_RCODE         (0xF<<0)        /* reply code */
158
159 static const true_false_string tfs_flags_response = {
160         "Message is a response",
161         "Message is a query"
162 };
163
164 static const true_false_string tfs_flags_authoritative = {
165         "Server is an authority for domain",
166         "Server is not an authority for domain"
167 };
168
169 static const true_false_string tfs_flags_truncated = {
170         "Message is truncated",
171         "Message is not truncated"
172 };
173
174 static const true_false_string tfs_flags_recdesired = {
175         "Do query recursively",
176         "Don't do query recursively"
177 };
178
179 static const true_false_string tfs_flags_recavail = {
180         "Server can do recursive queries",
181         "Server can't do recursive queries"
182 };
183
184 static const true_false_string tfs_flags_authenticated = {
185         "Answer/authority portion was authenticated by the server",
186         "Answer/authority portion was not authenticated by the server"
187 };
188
189 static const true_false_string tfs_flags_checkdisable = {
190         "Non-authenticated data is acceptable",
191         "Non-authenticated data is unacceptable"
192 };
193
194 /* Opcodes */
195 #define OPCODE_QUERY    0         /* standard query */
196 #define OPCODE_IQUERY   1         /* inverse query */
197 #define OPCODE_STATUS   2         /* server status request */
198 #define OPCODE_NOTIFY   4         /* zone change notification */
199 #define OPCODE_UPDATE   5         /* dynamic update */
200
201 static const value_string opcode_vals[] = {
202           { OPCODE_QUERY,  "Standard query"           },
203           { OPCODE_IQUERY, "Inverse query"            },
204           { OPCODE_STATUS, "Server status request"    },
205           { OPCODE_NOTIFY, "Zone change notification" },
206           { OPCODE_UPDATE, "Dynamic update"           },
207           { 0,              NULL                      } };
208
209 /* Reply codes */
210 #define RCODE_NOERROR   0
211 #define RCODE_FORMERR   1
212 #define RCODE_SERVFAIL  2
213 #define RCODE_NXDOMAIN  3
214 #define RCODE_NOTIMPL   4
215 #define RCODE_REFUSED   5
216 #define RCODE_YXDOMAIN  6
217 #define RCODE_YXRRSET   7
218 #define RCODE_NXRRSET   8
219 #define RCODE_NOTAUTH   9
220 #define RCODE_NOTZONE   10
221
222 static const value_string rcode_vals[] = {
223           { RCODE_NOERROR,   "No error"             },
224           { RCODE_FORMERR,   "Format error"         },
225           { RCODE_SERVFAIL,  "Server failure"       },
226           { RCODE_NXDOMAIN,  "No such name"         },
227           { RCODE_NOTIMPL,   "Not implemented"      },
228           { RCODE_REFUSED,   "Refused"              },
229           { RCODE_YXDOMAIN,  "Name exists"          },
230           { RCODE_YXRRSET,   "RRset exists"         },
231           { RCODE_NXRRSET,   "RRset does not exist" },
232           { RCODE_NOTAUTH,   "Not authoritative"    },
233           { RCODE_NOTZONE,   "Name out of zone"     },
234           { 0,               NULL                   } };
235
236 /* TSIG/TKEY extended errors */
237 #define TSIGERROR_BADSIG   (16)
238 #define TSIGERROR_BADKEY   (17)
239 #define TSIGERROR_BADTIME  (18)
240 #define TSIGERROR_BADMODE  (19)
241 #define TSIGERROR_BADNAME  (20)
242 #define TSIGERROR_BADALG   (21)
243
244 static const value_string tsigerror_vals[] = {
245           { TSIGERROR_BADSIG,   "Bad signature"        },
246           { TSIGERROR_BADKEY,   "Bad key"              },
247           { TSIGERROR_BADTIME,  "Bad time failure"     },
248           { TSIGERROR_BADMODE,  "Bad mode such name"   },
249           { TSIGERROR_BADNAME,  "Bad name implemented" },
250           { TSIGERROR_BADALG,   "Bad algorithm"        },
251           { 0,                  NULL                   } };
252
253 #define TKEYMODE_SERVERASSIGNED             (1)
254 #define TKEYMODE_DIFFIEHELLMAN              (2)
255 #define TKEYMODE_GSSAPI                     (3)
256 #define TKEYMODE_RESOLVERASSIGNED           (4)
257 #define TKEYMODE_DELETE                     (5)
258
259 /* See RFC 1035 for all RR types for which no RFC is listed, except for
260    the ones with "???", and for the Microsoft WINS and WINS-R RRs, for
261    which one should look at
262
263 http://www.windows.com/windows2000/en/server/help/sag_DNS_imp_UsingWinsLookup.htm
264    
265    and
266    
267 http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cncf/cncf_imp_wwaw.asp
268
269    which discuss them to some extent. */
270 static char *
271 dns_type_name (guint type)
272 {
273   char *type_names[] = {
274     "unused",
275     "A",
276     "NS",
277     "MD",
278     "MF",
279     "CNAME",
280     "SOA",
281     "MB",
282     "MG",
283     "MR",
284     "NULL",
285     "WKS",
286     "PTR",
287     "HINFO",
288     "MINFO",
289     "MX",
290     "TXT",
291     "RP",                               /* RFC 1183 */
292     "AFSDB",                            /* RFC 1183 */
293     "X25",                              /* RFC 1183 */
294     "ISDN",                             /* RFC 1183 */
295     "RT",                               /* RFC 1183 */
296     "NSAP",                             /* RFC 1706 */
297     "NSAP-PTR",                         /* RFC 1348 */
298     "SIG",                              /* RFC 2535 */
299     "KEY",                              /* RFC 2535 */
300     "PX",                               /* RFC 1664 */
301     "GPOS",                             /* RFC 1712 */
302     "AAAA",                             /* RFC 1886 */
303     "LOC",                              /* RFC 1876 */
304     "NXT",                              /* RFC 2535 */
305     "EID",
306     "NIMLOC",
307     "SRV",                              /* RFC 2052 */
308     "ATMA",
309     "NAPTR",                            /* RFC 2168 */
310     "KX",                               /* RFC 2230 */
311     "CERT",                             /* RFC 2538 */
312     "A6",                               /* RFC 2874 */
313     "DNAME",                            /* RFC 2672 */
314     NULL,
315     "OPT"                               /* RFC 2671 */
316   };
317   
318   if (type < sizeof(type_names)/sizeof(type_names[0]))
319     return type_names[type] ? type_names[type] : "unknown";
320   
321   /* special cases */
322   switch (type) 
323     {
324       /* non standard  */
325     case 100:
326       return "UINFO";
327     case 101:
328       return "UID";
329     case 102:
330       return "GID";
331     case 103:
332       return "UNSPEC";
333     case T_WINS:
334       return "WINS";
335     case T_WINS_R:
336       return "WINS-R";
337
338       /* meta */
339     case T_TKEY:
340       return "TKEY";
341     case T_TSIG:
342       return "TSIG";
343
344       /* queries  */
345     case 251:
346       return "IXFR";    /* RFC 1995 */
347     case 252:
348       return "AXFR";
349     case 253:
350       return "MAILB";
351     case 254:
352       return "MAILA";
353     case 255:
354       return "ANY";
355
356     }
357
358   return "unknown";
359 }
360
361
362 static char *
363 dns_long_type_name (guint type)
364 {
365   char *type_names[] = {
366     "unused",
367     "Host address",
368     "Authoritative name server",        
369     "Mail destination",
370     "Mail forwarder",
371     "Canonical name for an alias",
372     "Start of zone of authority",
373     "Mailbox domain name",
374     "Mail group member",
375     "Mail rename domain name",
376     "Null resource record",
377     "Well-known service description",
378     "Domain name pointer",
379     "Host information",
380     "Mailbox or mail list information",
381     "Mail exchange",
382     "Text strings",
383     "Responsible person",               /* RFC 1183 */
384     "AFS data base location",           /* RFC 1183 */
385     "X.25 address",                     /* RFC 1183 */
386     "ISDN number",                      /* RFC 1183 */
387     "Route through",                    /* RFC 1183 */
388     "OSI NSAP",                         /* RFC 1706 */
389     "OSI NSAP name pointer",            /* RFC 1348 */
390     "Signature",                        /* RFC 2535 */
391     "Public key",                       /* RFC 2535 */
392     "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
393     "Geographical position",            /* RFC 1712 */
394     "IPv6 address",                     /* RFC 1886 */
395     "Location",                         /* RFC 1876 */
396     "Next",                             /* RFC 2535 */
397     "EID",
398     "NIMLOC",
399     "Service location",                 /* RFC 2052 */
400     "ATMA",
401     "Naming authority pointer",         /* RFC 2168 */
402     "Key Exchange",                     /* RFC 2230 */
403     "Certificate",                      /* RFC 2538 */
404     "IPv6 address with indirection",    /* RFC 2874 */
405     "Non-terminal DNS name redirection", /* RFC 2672 */
406     NULL,
407     "EDNS0 option"                      /* RFC 2671 */
408   };
409   static char unkbuf[7+1+2+1+4+1+1+10+1+1];     /* "Unknown RR type (%d)" */
410   
411   if (type < sizeof(type_names)/sizeof(type_names[0]))
412     return type_names[type] ? type_names[type] : "unknown";
413   
414   /* special cases */
415   switch (type) 
416     {
417       /* non standard  */
418     case 100:
419       return "UINFO";
420     case 101:
421       return "UID";
422     case 102:
423       return "GID";
424     case 103:
425       return "UNSPEC";
426     case T_WINS:
427       return "WINS";
428     case T_WINS_R:
429       return "WINS-R";
430
431       /* meta */
432     case T_TKEY:
433       return "Transaction Key";
434     case T_TSIG:
435       return "Transaction Signature";
436
437       /* queries  */
438     case 251:
439       return "Request for incremental zone transfer";   /* RFC 1995 */
440     case 252:
441       return "Request for full zone transfer";
442     case 253:
443       return "Request for mailbox-related records";
444     case 254:
445       return "Request for mail agent resource records";
446     case 255:
447       return "Request for all records";
448     }
449   
450   sprintf(unkbuf, "Unknown RR type (%d)", type);
451   return unkbuf;
452 }
453
454
455 char *
456 dns_class_name(int class)
457 {
458   char *class_name;
459   
460   switch (class) {
461   case C_IN:
462     class_name = "inet";
463     break;
464   case C_CS:
465     class_name = "csnet";
466     break;
467   case C_CH:
468     class_name = "chaos";
469     break;
470   case C_HS:
471     class_name = "hesiod";
472     break;
473   case C_NONE:
474     class_name = "none";
475     break;
476   case C_ANY:
477     class_name = "any";
478     break;
479   default:
480     class_name = "unknown";
481   }
482
483   return class_name;
484 }
485
486 int
487 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
488     char *name, int maxname)
489 {
490   int start_offset = offset;
491   char *np = name;
492   int len = -1;
493   int chars_processed = 0;
494   int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
495   int component_len;
496   int indir_offset;
497
498   const int min_len = 1;        /* Minimum length of encoded name (for root) */
499         /* If we're about to return a value (probably negative) which is less
500          * than the minimum length, we're looking at bad data and we're liable
501          * to put the dissector into a loop.  Instead we throw an exception */
502
503   maxname--;    /* reserve space for the trailing '\0' */
504   for (;;) {
505     component_len = tvb_get_guint8(tvb, offset);
506     offset++;
507     if (component_len == 0)
508       break;
509     chars_processed++;
510     switch (component_len & 0xc0) {
511
512     case 0x00:
513       /* Label */
514       if (np != name) {
515         /* Not the first component - put in a '.'. */
516         if (maxname > 0) {
517           *np++ = '.';
518           maxname--;
519         }
520       }
521       while (component_len > 0) {
522         if (maxname > 0) {
523           *np++ = tvb_get_guint8(tvb, offset);
524           maxname--;
525         }
526         component_len--;
527         offset++;
528         chars_processed++;
529       }
530       break;
531
532     case 0x40:
533       /* Extended label (RFC 2673) */
534       switch (component_len & 0x3f) {
535
536       case 0x01:
537         /* Bitstring label */
538         {
539           int bit_count;
540           int label_len;
541           int print_len;
542
543           bit_count = tvb_get_guint8(tvb, offset);
544           offset++;
545           label_len = (bit_count - 1) / 8 + 1;
546         
547           if (maxname > 0) {
548             print_len = snprintf(np, maxname + 1, "\\[x");
549             if (print_len != -1) {
550               /* Some versions of snprintf return -1 if they'd truncate
551                  the output. */
552               np += print_len;
553               maxname -= print_len;
554             } else {
555               /* Nothing printed, as there's no room.
556                  Suppress all subsequent printing. */
557               maxname = 0;
558             }
559           }
560           while(label_len--) {
561             if (maxname > 0) {
562               print_len = snprintf(np, maxname + 1, "%02x",
563                 tvb_get_guint8(tvb, offset));
564               if (print_len != -1) {
565                 /* Some versions of snprintf return -1 if they'd truncate
566                  the output. */
567                 np += print_len;
568                 maxname -= print_len;
569               } else {
570                 /* Nothing printed, as there's no room.
571                    Suppress all subsequent printing. */
572                 maxname = 0;
573               }
574             }
575             offset++;
576           }
577           if (maxname > 0) {
578             print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
579             if (print_len != -1) {
580               /* Some versions of snprintf return -1 if they'd truncate
581                  the output. */
582               np += print_len;
583               maxname -= print_len;
584             } else {
585               /* Nothing printed, as there's no room.
586                  Suppress all subsequent printing. */
587               maxname = 0;
588             }
589           }
590         }
591         break;
592
593       default:
594         strcpy(name, "<Unknown extended label>");
595         /* Parsing will propably fail from here on, since the */
596         /* label length is unknown... */
597         len = offset - start_offset;
598         if (len < min_len)
599           THROW(ReportedBoundsError);
600         return len;
601       }
602       break;
603
604     case 0x80:
605       THROW(ReportedBoundsError);
606
607     case 0xc0:
608       /* Pointer. */
609       indir_offset = dns_data_offset +
610           (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
611       offset++;
612       chars_processed++;
613
614       /* If "len" is negative, we are still working on the original name,
615          not something pointed to by a pointer, and so we should set "len"
616          to the length of the original name. */
617       if (len < 0)
618         len = offset - start_offset;
619
620       /* If we've looked at every character in the message, this pointer
621          will make us look at some character again, which means we're
622          looping. */
623       if (chars_processed >= data_size) {
624         strcpy(name, "<Name contains a pointer that loops>");
625         if (len < min_len)
626           THROW(ReportedBoundsError);
627         return len;
628       }
629
630       offset = indir_offset;
631       break;    /* now continue processing from there */
632     }
633   }
634         
635   *np = '\0';
636   /* If "len" is negative, we haven't seen a pointer, and thus haven't
637      set the length, so set it. */
638   if (len < 0)
639     len = offset - start_offset;
640   /* Zero-length name means "root server" */
641   if (*name == '\0')
642     strcpy(name, "<Root>");
643   if (len < min_len)
644     THROW(ReportedBoundsError);
645   return len;
646 }
647
648
649 static int
650 get_dns_name_type_class(tvbuff_t *tvb, int offset, int dns_data_offset,
651     char *name_ret, int *name_len_ret, int *type_ret, int *class_ret)
652 {
653   int len;
654   int name_len;
655   int type;
656   int class;
657   char name[MAXDNAME];
658   int start_offset = offset;
659
660   name_len = get_dns_name(tvb, offset, dns_data_offset, name, sizeof(name));
661   offset += name_len;
662   
663   type = tvb_get_ntohs(tvb, offset);
664   offset += 2;
665
666   class = tvb_get_ntohs(tvb, offset);
667   offset += 2;
668
669   strcpy (name_ret, name);
670   *type_ret = type;
671   *class_ret = class;
672   *name_len_ret = name_len;
673
674   len = offset - start_offset;
675   return len;
676 }
677
678 static double
679 rfc1867_size(tvbuff_t *tvb, int offset)
680 {
681   guint8 val;
682   double size;
683   guint32 exponent;
684
685   val = tvb_get_guint8(tvb, offset);
686   size = (val & 0xF0) >> 4;
687   exponent = (val & 0x0F);
688   while (exponent != 0) {
689     size *= 10;
690     exponent--;
691   }
692   return size / 100;    /* return size in meters, not cm */
693 }
694
695 static char *
696 rfc1867_angle(tvbuff_t *tvb, int offset, const char *nsew)
697 {
698   guint32 angle;
699   char direction;
700   guint32 degrees, minutes, secs, tsecs;
701   static char buf[10+1+3+1 + 2+1+3+1 + 2+1+3+1+3+1 + 1 + 1];
702
703   angle = tvb_get_ntohl(tvb, offset);
704
705   if (angle < 0x80000000U) {
706     angle = 0x80000000U - angle;
707     direction = nsew[1];
708   } else {
709     angle = angle - 0x80000000U;
710     direction = nsew[0];
711   }
712   tsecs = angle % 1000;
713   angle = angle / 1000;
714   secs = angle % 60;
715   angle = angle / 60;
716   minutes = angle % 60;
717   degrees = angle / 60;
718   sprintf(buf, "%u deg %u min %u.%03u sec %c", degrees, minutes, secs,
719                 tsecs, direction);
720   return buf;
721 }
722
723 static int
724 dissect_dns_query(tvbuff_t *tvb, int offset, int dns_data_offset,
725   column_info *cinfo, proto_tree *dns_tree)
726 {
727   int len;
728   char name[MAXDNAME];
729   int name_len;
730   int type;
731   int class;
732   char *class_name;
733   char *type_name;
734   char *long_type_name;
735   int data_offset;
736   int data_start;
737   proto_tree *q_tree;
738   proto_item *tq;
739
740   data_start = data_offset = offset;
741
742   len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
743     &type, &class);
744   data_offset += len;
745
746   type_name = dns_type_name(type);
747   class_name = dns_class_name(class);
748   long_type_name = dns_long_type_name(type);
749
750   if (cinfo != NULL)
751     col_append_fstr(cinfo, COL_INFO, " %s %s", type_name, name);
752   if (dns_tree != NULL) {
753     tq = proto_tree_add_text(dns_tree, tvb, offset, len, "%s: type %s, class %s", 
754                    name, type_name, class_name);
755     q_tree = proto_item_add_subtree(tq, ett_dns_qd);
756
757     proto_tree_add_text(q_tree, tvb, offset, name_len, "Name: %s", name);
758     offset += name_len;
759
760     proto_tree_add_text(q_tree, tvb, offset, 2, "Type: %s", long_type_name);
761     offset += 2;
762
763     proto_tree_add_text(q_tree, tvb, offset, 2, "Class: %s", class_name);
764     offset += 2;
765   }
766   
767   return data_offset - data_start;
768 }
769
770
771 proto_tree *
772 add_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
773   const char *name, int namelen, const char *type_name, const char *class_name,
774   guint ttl, gushort data_len)
775 {
776   proto_tree *rr_tree;
777
778   rr_tree = proto_item_add_subtree(trr, rr_type);
779   proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
780   offset += namelen;
781   proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
782   offset += 2;
783   proto_tree_add_text(rr_tree, tvb, offset, 2, "Class: %s", class_name);
784   offset += 2;
785   proto_tree_add_text(rr_tree, tvb, offset, 4, "Time to live: %s",
786                                                 time_secs_to_str(ttl));
787   offset += 4;
788   proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
789   return rr_tree;
790 }
791
792 static proto_tree *
793 add_opt_rr_to_tree(proto_item *trr, int rr_type, tvbuff_t *tvb, int offset,
794   const char *name, int namelen, const char *type_name, int class,
795   guint ttl, gushort data_len)
796 {
797   proto_tree *rr_tree;
798
799   rr_tree = proto_item_add_subtree(trr, rr_type);
800   proto_tree_add_text(rr_tree, tvb, offset, namelen, "Name: %s", name);
801   offset += namelen;
802   proto_tree_add_text(rr_tree, tvb, offset, 2, "Type: %s", type_name);
803   offset += 2;
804   proto_tree_add_text(rr_tree, tvb, offset, 2, "UDP payload size: %u",
805       class & 0xffff);
806   offset += 2;
807   proto_tree_add_text(rr_tree, tvb, offset, 1, "Higher bits in extended RCODE: 0x%x",
808       (ttl >> 24) & 0xff0);
809   offset++;
810   proto_tree_add_text(rr_tree, tvb, offset, 1, "EDNS0 version: %u",
811       (ttl >> 16) & 0xff);
812   offset++;
813   proto_tree_add_text(rr_tree, tvb, offset, 2, "Must be zero: 0x%x", ttl & 0xffff);
814   offset += 2;
815   proto_tree_add_text(rr_tree, tvb, offset, 2, "Data length: %u", data_len);
816   return rr_tree;
817 }
818
819 /*
820  * SIG, KEY, and CERT RR algorithms.
821  */
822 #define DNS_ALGO_RSAMD5         1       /* RSA/MD5 */
823 #define DNS_ALGO_DH             2       /* Diffie-Hellman */
824 #define DNS_ALGO_DSA            3       /* DSA */
825 #define DNS_ALGO_ECC            4       /* Elliptic curve crypto */
826 #define DNS_ALGO_INDIRECT       252     /* Indirect key */
827 #define DNS_ALGO_PRIVATEDNS     253     /* Private, domain name  */
828 #define DNS_ALGO_PRIVATEOID     254     /* Private, OID */      
829
830 static const value_string algo_vals[] = {
831           { DNS_ALGO_RSAMD5,     "RSA/MD5" },
832           { DNS_ALGO_DH,         "Diffie-Hellman" },
833           { DNS_ALGO_DSA,        "DSA" },
834           { DNS_ALGO_ECC,        "Elliptic curve crypto" },
835           { DNS_ALGO_INDIRECT,   "Indirect key" },
836           { DNS_ALGO_PRIVATEDNS, "Private, domain name" },
837           { DNS_ALGO_PRIVATEOID, "Private, OID" },
838           { 0,                   NULL }
839 };
840
841 #define DNS_CERT_PGP            1       /* PGP */
842 #define DNS_CERT_PKIX           2       /* PKIX */
843 #define DNS_CERT_SPKI           3       /* SPKI */
844 #define DNS_CERT_PRIVATEURI     253     /* Private, URI */
845 #define DNS_CERT_PRIVATEOID     254     /* Private, OID */
846
847 static const value_string cert_vals[] = {
848           { DNS_CERT_PGP,        "PGP" },
849           { DNS_CERT_PKIX,       "PKIX" },
850           { DNS_CERT_SPKI,       "SPKI" },
851           { DNS_CERT_PRIVATEURI, "Private, URI" },
852           { DNS_CERT_PRIVATEOID, "Private, OID" },
853           { 0,                   NULL }
854 };
855
856 static int
857 dissect_dns_answer(tvbuff_t *tvb, int offset, int dns_data_offset,
858   column_info *cinfo, proto_tree *dns_tree)
859 {
860   int len;
861   char name[MAXDNAME];
862   int name_len;
863   int type;
864   int class;
865   char *class_name;
866   char *type_name;
867   char *long_type_name;
868   int data_offset;
869   int cur_offset;
870   int data_start;
871   guint ttl;
872   gushort data_len;
873   proto_tree *rr_tree = NULL;
874   proto_item *trr = NULL;
875
876   data_start = data_offset = offset;
877   cur_offset = offset;
878
879   len = get_dns_name_type_class(tvb, offset, dns_data_offset, name, &name_len,
880     &type, &class);
881   data_offset += len;
882   cur_offset += len;
883
884   type_name = dns_type_name(type);
885   class_name = dns_class_name(class);
886   long_type_name = dns_long_type_name(type);
887
888   ttl = tvb_get_ntohl(tvb, data_offset);
889   data_offset += 4;
890   cur_offset += 4;
891
892   data_len = tvb_get_ntohs(tvb, data_offset);
893   data_offset += 2;
894   cur_offset += 2;
895
896   if (cinfo != NULL)
897     col_append_fstr(cinfo, COL_INFO, " %s", type_name);
898   if (dns_tree != NULL) {
899     trr = proto_tree_add_text(dns_tree, tvb, offset,
900                                 (data_offset - data_start) + data_len,
901                                 "%s: type %s, class %s",
902                                 name, type_name, class_name);
903     if (type != T_OPT) {
904       rr_tree = add_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
905                      long_type_name, class_name, ttl, data_len);
906     } else  {
907       rr_tree = add_opt_rr_to_tree(trr, ett_dns_rr, tvb, offset, name, name_len,
908                      long_type_name, class, ttl, data_len);
909     }
910   }
911
912   switch (type) {
913
914   case T_A:
915     {
916       const guint8 *addr;
917       guint32 addr_int;
918
919       addr = tvb_get_ptr(tvb, cur_offset, 4);
920       if (cinfo != NULL)
921         col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(addr));
922       if (dns_tree != NULL) {
923         proto_item_append_text(trr, ", addr %s", ip_to_str(addr));
924         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
925                      ip_to_str(addr));
926       }
927       if (class == C_IN) {
928         memcpy(&addr_int, addr, sizeof(addr_int));
929         add_host_name(addr_int, name);
930       }
931     }
932     break;
933
934   case T_NS:
935     {
936       char ns_name[MAXDNAME];
937       int ns_name_len;
938       
939       ns_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, ns_name, sizeof(ns_name));
940       if (cinfo != NULL)
941         col_append_fstr(cinfo, COL_INFO, " %s", ns_name);
942       if (dns_tree != NULL) {
943         proto_item_append_text(trr, ", ns %s", ns_name);
944         proto_tree_add_text(rr_tree, tvb, cur_offset, ns_name_len, "Name server: %s",
945                         ns_name);
946       }
947     }
948     break;
949
950   case T_CNAME:
951     {
952       char cname[MAXDNAME];
953       int cname_len;
954       
955       cname_len = get_dns_name(tvb, cur_offset, dns_data_offset, cname, sizeof(cname));
956       if (cinfo != NULL)
957         col_append_fstr(cinfo, COL_INFO, " %s", cname);
958       if (dns_tree != NULL) {
959         proto_item_append_text(trr, ", cname %s", cname);
960         proto_tree_add_text(rr_tree, tvb, cur_offset, cname_len, "Primary name: %s",
961                         cname);
962       }
963     }
964     break;
965
966   case T_SOA:
967     {
968       char mname[MAXDNAME];
969       int mname_len;
970       char rname[MAXDNAME];
971       int rname_len;
972       guint32 serial;
973       guint32 refresh;
974       guint32 retry;
975       guint32 expire;
976       guint32 minimum;
977
978       mname_len = get_dns_name(tvb, cur_offset, dns_data_offset, mname, sizeof(mname));
979       if (cinfo != NULL)
980         col_append_fstr(cinfo, COL_INFO, " %s", mname);
981       if (dns_tree != NULL) {
982         proto_item_append_text(trr, ", mname %s", mname);
983         proto_tree_add_text(rr_tree, tvb, cur_offset, mname_len, "Primary name server: %s",
984                        mname);
985         cur_offset += mname_len;
986       
987         rname_len = get_dns_name(tvb, cur_offset, dns_data_offset, rname, sizeof(rname));
988         proto_tree_add_text(rr_tree, tvb, cur_offset, rname_len, "Responsible authority's mailbox: %s",
989                        rname);
990         cur_offset += rname_len;
991
992         serial = tvb_get_ntohl(tvb, cur_offset);
993         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Serial number: %u",
994                        serial);
995         cur_offset += 4;
996
997         refresh = tvb_get_ntohl(tvb, cur_offset);
998         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Refresh interval: %s",
999                        time_secs_to_str(refresh));
1000         cur_offset += 4;
1001
1002         retry = tvb_get_ntohl(tvb, cur_offset);
1003         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Retry interval: %s",
1004                        time_secs_to_str(retry));
1005         cur_offset += 4;
1006
1007         expire = tvb_get_ntohl(tvb, cur_offset);
1008         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Expiration limit: %s",
1009                        time_secs_to_str(expire));
1010         cur_offset += 4;
1011
1012         minimum = tvb_get_ntohl(tvb, cur_offset);
1013         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Minimum TTL: %s",
1014                        time_secs_to_str(minimum));
1015       }
1016     }
1017     break;
1018
1019   case T_PTR:
1020     {
1021       char pname[MAXDNAME];
1022       int pname_len;
1023       
1024       pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, pname, sizeof(pname));
1025       if (cinfo != NULL)
1026         col_append_fstr(cinfo, COL_INFO, " %s", pname);
1027       if (dns_tree != NULL) {
1028         proto_item_append_text(trr, ", ptr %s", pname);
1029         proto_tree_add_text(rr_tree, tvb, cur_offset, pname_len, "Domain name: %s",
1030                         pname);
1031       }
1032       break;
1033     }
1034     break;
1035
1036   case T_WKS:
1037     {
1038       int rr_len = data_len;
1039       const guint8 *wks_addr;
1040       guint8 protocol;
1041       guint8 bits;
1042       int mask;
1043       int port_num;
1044       int i;
1045       char bitnames[128+1];
1046       char portnumstring[10+1];
1047       
1048       wks_addr = tvb_get_ptr(tvb, cur_offset, 4);
1049       if (cinfo != NULL)
1050         col_append_fstr(cinfo, COL_INFO, " %s", ip_to_str(wks_addr));
1051       if (dns_tree != NULL) {
1052         proto_item_append_text(trr, ", addr %s", ip_to_str(wks_addr));
1053         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Addr: %s",
1054                      ip_to_str(wks_addr));
1055         cur_offset += 4;
1056         rr_len -= 4;
1057
1058         protocol = tvb_get_guint8(tvb, cur_offset);
1059         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %s",
1060                      ipprotostr(protocol));
1061         cur_offset += 1;
1062         rr_len -= 1;
1063
1064         port_num = 0;
1065         while (rr_len != 0) {
1066           bits = tvb_get_guint8(tvb, cur_offset);
1067           if (bits != 0) {
1068             mask = 1<<7;
1069             bitnames[0] = '\0';
1070             for (i = 0; i < 8; i++) {
1071               if (bits & mask) {
1072                 if (bitnames[0] != '\0')
1073                   strcat(bitnames, ", ");
1074                 switch (protocol) {
1075
1076                 case IP_PROTO_TCP:
1077                   strcat(bitnames, get_tcp_port(port_num));
1078                   break;
1079
1080                 case IP_PROTO_UDP:
1081                   strcat(bitnames, get_udp_port(port_num));
1082                   break;
1083
1084                 default:
1085                   sprintf(portnumstring, "%u", port_num);
1086                   strcat(bitnames, portnumstring);
1087                   break;
1088                 }
1089               }
1090               mask >>= 1;
1091               port_num++;
1092             }
1093             proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1094                 "Bits: 0x%02x (%s)", bits, bitnames);
1095           } else
1096             port_num += 8;
1097           cur_offset += 1;
1098           rr_len -= 1;
1099         }
1100       }
1101     }
1102     break;
1103
1104   case T_HINFO:
1105     {
1106       int cpu_offset;
1107       int cpu_len;
1108       const guint8 *cpu;
1109       int os_offset;
1110       int os_len;
1111       const guint8 *os;
1112
1113       cpu_offset = cur_offset;
1114       cpu_len = tvb_get_guint8(tvb, cpu_offset);
1115       cpu = tvb_get_ptr(tvb, cpu_offset + 1, cpu_len);
1116       os_offset = cpu_offset + 1 + cpu_len;
1117       os_len = tvb_get_guint8(tvb, os_offset);
1118       os = tvb_get_ptr(tvb, os_offset + 1, os_len);
1119       if (cinfo != NULL)
1120         col_append_fstr(cinfo, COL_INFO, " %.*s %.*s", cpu_len, cpu,
1121             os_len, os);
1122       if (dns_tree != NULL) {
1123         proto_item_append_text(trr, ", CPU %.*s, OS %.*s",
1124                      cpu_len, cpu, os_len, os);
1125         proto_tree_add_text(rr_tree, tvb, cpu_offset, 1 + cpu_len, "CPU: %.*s",
1126                         cpu_len, cpu);
1127         proto_tree_add_text(rr_tree, tvb, os_offset, 1 + os_len, "OS: %.*s",
1128                         os_len, os);
1129       }
1130       break;
1131     }
1132     break;
1133
1134   case T_MX:
1135     {
1136       guint16 preference = 0;
1137       char mx_name[MAXDNAME];
1138       int mx_name_len;
1139       
1140       preference = tvb_get_ntohs(tvb, cur_offset);
1141       mx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, mx_name, sizeof(mx_name));
1142       if (cinfo != NULL)
1143         col_append_fstr(cinfo, COL_INFO, " %u %s", preference, mx_name);
1144       if (dns_tree != NULL) {
1145         proto_item_append_text(trr, ", preference %u, mx %s",
1146                        preference, mx_name);
1147         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1148         proto_tree_add_text(rr_tree, tvb, cur_offset + 2, mx_name_len, "Mail exchange: %s",
1149                         mx_name);
1150       }
1151     }
1152     break;
1153
1154   case T_TXT:
1155     {
1156       int rr_len = data_len;
1157       int txt_offset;
1158       int txt_len;
1159
1160       if (dns_tree != NULL) {
1161         txt_offset = cur_offset;
1162         while (rr_len != 0) {
1163           txt_len = tvb_get_guint8(tvb, txt_offset);
1164           proto_tree_add_text(rr_tree, tvb, txt_offset, 1 + txt_len,
1165            "Text: %.*s", txt_len, tvb_get_ptr(tvb, txt_offset + 1, txt_len));
1166           txt_offset += 1 + txt_len;
1167           rr_len -= 1 + txt_len;
1168         }
1169       }
1170     }
1171     break;
1172
1173   case T_SIG:
1174     {
1175       int rr_len = data_len;
1176       guint16 type_covered;
1177       nstime_t nstime;
1178       char signer_name[MAXDNAME];
1179       int signer_name_len;
1180
1181       if (dns_tree != NULL) {
1182         type_covered = tvb_get_ntohs(tvb, cur_offset);
1183         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Type covered: %s (%s)",
1184                 dns_type_name(type_covered),
1185                 dns_long_type_name(type_covered));
1186         cur_offset += 2;
1187         rr_len -= 2;
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, 1, "Labels: %u",
1196                 tvb_get_guint8(tvb, cur_offset));
1197         cur_offset += 1;
1198         rr_len -= 1;
1199
1200         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Original TTL: %s",
1201                 time_secs_to_str(tvb_get_ntohl(tvb, cur_offset)));
1202         cur_offset += 4;
1203         rr_len -= 4;
1204
1205         nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1206         nstime.nsecs = 0;
1207         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1208                 abs_time_to_str(&nstime));
1209         cur_offset += 4;
1210         rr_len -= 4;
1211
1212         nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1213         nstime.nsecs = 0;
1214         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Time signed: %s",
1215                 abs_time_to_str(&nstime));
1216         cur_offset += 4;
1217         rr_len -= 4;
1218
1219         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1220                 tvb_get_ntohs(tvb, cur_offset));
1221         cur_offset += 2;
1222         rr_len -= 2;
1223
1224         signer_name_len = get_dns_name(tvb, cur_offset, dns_data_offset, signer_name, sizeof(signer_name));
1225         proto_tree_add_text(rr_tree, tvb, cur_offset, signer_name_len,
1226                 "Signer's name: %s", signer_name);
1227         cur_offset += signer_name_len;
1228         rr_len -= signer_name_len;
1229
1230         proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Signature");
1231       }
1232     }
1233     break;
1234
1235   case T_KEY:
1236     {
1237       int rr_len = data_len;
1238       guint16 flags;
1239       proto_item *tf;
1240       proto_tree *flags_tree;
1241
1242       if (dns_tree != NULL) {
1243         flags = tvb_get_ntohs(tvb, cur_offset);
1244         tf = proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Flags: 0x%04X", flags);
1245         flags_tree = proto_item_add_subtree(tf, ett_t_key_flags);
1246         proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1247                 decode_boolean_bitfield(flags, 0x8000,
1248                   2*8, "Key prohibited for authentication",
1249                        "Key allowed for authentication"));
1250         proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1251                 decode_boolean_bitfield(flags, 0x4000,
1252                   2*8, "Key prohibited for confidentiality",
1253                        "Key allowed for confidentiality"));
1254         if ((flags & 0xC000) != 0xC000) {
1255           /* We have a key */
1256           proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1257                 decode_boolean_bitfield(flags, 0x2000,
1258                   2*8, "Key is experimental or optional",
1259                        "Key is required"));
1260           proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1261                 decode_boolean_bitfield(flags, 0x0400,
1262                   2*8, "Key is associated with a user",
1263                        "Key is not associated with a user"));
1264           proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1265                 decode_boolean_bitfield(flags, 0x0200,
1266                   2*8, "Key is associated with the named entity",
1267                        "Key is not associated with the named entity"));
1268           proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1269                 decode_boolean_bitfield(flags, 0x0100,
1270                   2*8, "This is the zone key for the specified zone",
1271                        "This is not a zone key"));
1272           proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1273                 decode_boolean_bitfield(flags, 0x0080,
1274                   2*8, "Key is valid for use with IPSEC",
1275                        "Key is not valid for use with IPSEC"));
1276           proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1277                 decode_boolean_bitfield(flags, 0x0040,
1278                   2*8, "Key is valid for use with MIME security multiparts",
1279                        "Key is not valid for use with MIME security multiparts"));
1280           proto_tree_add_text(flags_tree, tvb, cur_offset, 2, "%s",
1281                 decode_numeric_bitfield(flags, 0x000F,
1282                   2*8, "Signatory = %u"));
1283         }
1284         cur_offset += 2;
1285         rr_len -= 2;
1286
1287         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Protocol: %u",
1288                 tvb_get_guint8(tvb, cur_offset));
1289         cur_offset += 1;
1290         rr_len -= 1;
1291
1292         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1293                 val_to_str(tvb_get_guint8(tvb, cur_offset), algo_vals,
1294                     "Unknown (0x%02X)"));
1295         cur_offset += 1;
1296                 rr_len -= 1;
1297
1298         proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1299       }
1300     }
1301     break;
1302
1303   case T_AAAA:
1304     {
1305       const guint8 *addr6;
1306
1307       addr6 = tvb_get_ptr(tvb, cur_offset, 16);
1308       if (cinfo != NULL) {
1309         col_append_fstr(cinfo, COL_INFO, " %s",
1310                         ip6_to_str((struct e_in6_addr *)addr6));
1311       }
1312       if (dns_tree != NULL) {
1313         proto_item_append_text(trr, ", addr %s",
1314                      ip6_to_str((struct e_in6_addr *)addr6));
1315         proto_tree_add_text(rr_tree, tvb, cur_offset, 16, "Addr: %s",
1316                      ip6_to_str((struct e_in6_addr *)addr6));
1317       }
1318     }
1319     break;
1320
1321   case T_A6:
1322     {
1323       unsigned short pre_len;
1324       unsigned short suf_len;
1325       unsigned short suf_octet_count;
1326       char pname[MAXDNAME];
1327       int pname_len;
1328       int a6_offset;
1329       int suf_offset;
1330       guint8 suffix[16];
1331
1332       a6_offset = cur_offset;
1333       pre_len = tvb_get_guint8(tvb, cur_offset);
1334       cur_offset++;
1335       suf_len = 128 - pre_len;
1336       suf_octet_count = suf_len ? (suf_len - 1) / 8 + 1 : 0;
1337       /* Pad prefix */
1338       for (suf_offset = 0; suf_offset < 16 - suf_octet_count; suf_offset++) {
1339         suffix[suf_offset] = 0;
1340       }
1341       for (; suf_offset < 16; suf_offset++) {
1342         suffix[suf_offset] = tvb_get_guint8(tvb, cur_offset);
1343         cur_offset++;
1344       }
1345
1346       if (pre_len > 0) {
1347         pname_len = get_dns_name(tvb, cur_offset, dns_data_offset, 
1348                                  pname, sizeof(pname));
1349       } else {
1350         strcpy(pname, "");   
1351         pname_len = 0;
1352       }
1353
1354       if (cinfo != NULL) {
1355         col_append_fstr(cinfo, COL_INFO, " %d %s %s", 
1356                         pre_len, 
1357                         ip6_to_str((struct e_in6_addr *)&suffix), 
1358                         pname);
1359       }
1360       if (dns_tree != NULL) {
1361         proto_tree_add_text(rr_tree, tvb, a6_offset, 1, 
1362                             "Prefix len: %u", pre_len);
1363         a6_offset++;
1364         if (suf_len) {
1365           proto_tree_add_text(rr_tree, tvb, a6_offset, suf_octet_count,
1366                               "Address suffix: %s", 
1367                               ip6_to_str((struct e_in6_addr *)&suffix));
1368           a6_offset += suf_octet_count;
1369         }
1370         if (pre_len > 0) {
1371           proto_tree_add_text(rr_tree, tvb, a6_offset, pname_len, 
1372                               "Prefix name: %s", pname);
1373         }
1374         proto_item_append_text(trr, ", addr %d %s %s",
1375                             pre_len, 
1376                             ip6_to_str((struct e_in6_addr *)&suffix), 
1377                             pname);
1378       }
1379     }
1380     break;
1381
1382   case T_DNAME:
1383     {
1384       char dname[MAXDNAME];
1385       int dname_len;
1386       
1387       dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, 
1388                                dname, sizeof(dname));
1389       if (cinfo != NULL)
1390         col_append_fstr(cinfo, COL_INFO, " %s", dname);
1391       if (dns_tree != NULL) {
1392         proto_item_append_text(trr, ", dname %s", dname);
1393         proto_tree_add_text(rr_tree, tvb, cur_offset, 
1394                             dname_len, "Target name: %s", dname);
1395       }
1396     }
1397     break;
1398
1399   case T_LOC:
1400     {
1401       guint8 version;
1402
1403       if (dns_tree != NULL) {
1404         version = tvb_get_guint8(tvb, cur_offset);
1405         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Version: %u", version);
1406         if (version == 0) {
1407           /* Version 0, the only version RFC 1876 discusses. */
1408           cur_offset++;
1409
1410           proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Size: %g m",
1411                                 rfc1867_size(tvb, cur_offset));
1412           cur_offset++;
1413
1414           proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Horizontal precision: %g m",
1415                                 rfc1867_size(tvb, cur_offset));
1416           cur_offset++;
1417
1418           proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Vertical precision: %g m",
1419                                 rfc1867_size(tvb, cur_offset));
1420           cur_offset++;
1421
1422           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Latitude: %s",
1423                                 rfc1867_angle(tvb, cur_offset, "NS"));
1424           cur_offset += 4;
1425
1426           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Longitude: %s",
1427                                 rfc1867_angle(tvb, cur_offset, "EW"));
1428           cur_offset += 4;
1429
1430           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Altitude: %g m",
1431                                 (tvb_get_ntohl(tvb, cur_offset) - 10000000)/100.0);
1432         } else
1433           proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1434       }
1435       break;
1436     }
1437     break;
1438       
1439   case T_NXT:
1440     {
1441       int rr_len = data_len;
1442       char next_domain_name[MAXDNAME];
1443       int next_domain_name_len;
1444       int rr_type;
1445       guint8 bits;
1446       int mask;
1447       int i;
1448
1449       next_domain_name_len = get_dns_name(tvb, cur_offset, dns_data_offset,
1450                         next_domain_name, sizeof(next_domain_name));
1451       if (cinfo != NULL)
1452         col_append_fstr(cinfo, COL_INFO, " %s", next_domain_name);
1453       if (dns_tree != NULL) {
1454         proto_item_append_text(trr, ", next domain name %s",
1455                      next_domain_name);
1456         proto_tree_add_text(rr_tree, tvb, cur_offset, next_domain_name_len,
1457                         "Next domain name: %s", next_domain_name);
1458         cur_offset += next_domain_name_len;
1459         rr_len -= next_domain_name_len;
1460         rr_type = 0;
1461         while (rr_len != 0) {
1462           bits = tvb_get_guint8(tvb, cur_offset);
1463           mask = 1<<7;
1464           for (i = 0; i < 8; i++) {
1465             if (bits & mask) {
1466               proto_tree_add_text(rr_tree, tvb, cur_offset, 1,
1467                         "RR type in bit map: %s (%s)",
1468                         dns_type_name(rr_type),
1469                         dns_long_type_name(rr_type));
1470             }
1471             mask >>= 1;
1472             rr_type++;
1473           }
1474           cur_offset += 1;
1475           rr_len -= 1;
1476         }
1477       }
1478     }
1479     break;
1480
1481   case T_KX:
1482     {
1483       guint16 preference = 0;
1484       char kx_name[MAXDNAME];
1485       int kx_name_len;
1486       
1487       preference = tvb_get_ntohs(tvb, cur_offset);
1488       kx_name_len = get_dns_name(tvb, cur_offset + 2, dns_data_offset, kx_name, sizeof(kx_name));
1489       if (cinfo != NULL)
1490         col_append_fstr(cinfo, COL_INFO, " %u %s", preference, kx_name);
1491       if (dns_tree != NULL) {
1492         proto_item_append_text(trr, ", preference %u, kx %s",
1493                        preference, kx_name);
1494         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Preference: %u", preference);
1495         proto_tree_add_text(rr_tree, tvb, cur_offset + 2, kx_name_len, "Key exchange: %s",
1496                         kx_name);
1497       }
1498     }
1499     break;
1500
1501   case T_CERT:
1502     {
1503       guint16 cert_type, cert_keytag;
1504       guint8 cert_keyalg;
1505       int rr_len = data_len;
1506
1507       cert_type = tvb_get_ntohs(tvb, cur_offset);
1508       cur_offset += 2;
1509       rr_len -= 2;
1510       cert_keytag = tvb_get_ntohs(tvb, cur_offset);
1511       cur_offset += 2;
1512       rr_len -= 2;
1513       cert_keyalg = tvb_get_guint8(tvb, cur_offset);
1514       cur_offset += 1;
1515       rr_len -= 1;
1516
1517       if (dns_tree != NULL) {
1518         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Type: %s",
1519                 val_to_str(cert_keyalg, cert_vals,
1520                     "Unknown (0x%02X)"));
1521         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Key footprint: 0x%04x",
1522                 cert_keytag);
1523         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Algorithm: %s",
1524                 val_to_str(cert_keyalg, algo_vals,
1525                     "Unknown (0x%02X)"));
1526         proto_tree_add_text(rr_tree, tvb, cur_offset, rr_len, "Public key");
1527       }
1528
1529     }
1530     break;
1531
1532   case T_OPT:
1533     if (dns_tree != NULL)
1534       proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1535     break;
1536
1537   case T_TKEY:
1538     {
1539       char tkey_algname[MAXDNAME];
1540       int tkey_algname_len;
1541       guint16 tkey_mode, tkey_error, tkey_keylen, tkey_otherlen;
1542       int rr_len = data_len;
1543       nstime_t nstime;
1544       static const value_string tkey_modes[] = {
1545                   { TKEYMODE_SERVERASSIGNED,   "Server assigned"   },
1546                   { TKEYMODE_DIFFIEHELLMAN,    "Diffie Hellman"    },
1547                   { TKEYMODE_GSSAPI,           "GSSAPI"            },
1548                   { TKEYMODE_RESOLVERASSIGNED, "Resolver assigned" },
1549                   { TKEYMODE_DELETE,           "Delete"            },
1550                   { 0,                         NULL                } };
1551
1552       if (dns_tree != NULL) {
1553         tkey_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tkey_algname, sizeof(tkey_algname));
1554         proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_algname_len,
1555                 "Algorithm name: %s", tkey_algname);
1556         cur_offset += tkey_algname_len;
1557         rr_len -= tkey_algname_len;
1558
1559         nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1560         nstime.nsecs = 0;
1561         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature inception: %s",
1562                 abs_time_to_str(&nstime));
1563         cur_offset += 4;
1564         rr_len -= 4;
1565
1566         nstime.secs = tvb_get_ntohl(tvb, cur_offset);
1567         nstime.nsecs = 0;
1568         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Signature expiration: %s",
1569                 abs_time_to_str(&nstime));
1570         cur_offset += 4;
1571         rr_len -= 4;
1572
1573         tkey_mode = tvb_get_ntohs(tvb, cur_offset);
1574         cur_offset += 2;
1575         rr_len -= 2;
1576         proto_tree_add_text(rr_tree, tvb, cur_offset, 1, "Mode: %s",
1577                 val_to_str(tkey_mode, tkey_modes,
1578                     "Unknown (0x%02X)"));
1579
1580         tkey_error = tvb_get_ntohs(tvb, cur_offset);
1581         cur_offset += 2;
1582         rr_len -= 2;
1583
1584         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Error: %s",
1585                 val_to_str(tkey_error, rcode_vals,
1586                 val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
1587
1588         tkey_keylen = tvb_get_ntohs(tvb, cur_offset);
1589         cur_offset += 2;
1590         rr_len -= 2;
1591
1592         proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_keylen, "Key");
1593         cur_offset += tkey_keylen;
1594         rr_len -= tkey_keylen;
1595
1596         tkey_otherlen = tvb_get_ntohs(tvb, cur_offset);
1597         cur_offset += 2;
1598         rr_len -= 2;
1599
1600         proto_tree_add_text(rr_tree, tvb, cur_offset, tkey_otherlen, "Other");
1601         cur_offset += tkey_otherlen;
1602         rr_len -= tkey_otherlen;
1603       }
1604     }
1605     break;
1606
1607   case T_TSIG:
1608     {
1609       guint16 tsig_fudge;
1610       guint16 tsig_originalid, tsig_error, tsig_timehi, tsig_siglen, tsig_otherlen;
1611       guint32 tsig_timelo;
1612       char tsig_algname[MAXDNAME];
1613       int tsig_algname_len;
1614       nstime_t nstime;
1615       int rr_len = data_len;
1616
1617       if (dns_tree != NULL) {
1618         tsig_algname_len = get_dns_name(tvb, cur_offset, dns_data_offset, tsig_algname, sizeof(tsig_algname));
1619         proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_algname_len,
1620                 "Algorithm name: %s", tsig_algname);
1621         cur_offset += tsig_algname_len;
1622         rr_len -= tsig_algname_len;
1623
1624         tsig_timehi = tvb_get_ntohs(tvb, cur_offset);
1625         tsig_timelo = tvb_get_ntohl(tvb, cur_offset + 2);
1626         nstime.secs = tsig_timelo;
1627         nstime.nsecs = 0;
1628         proto_tree_add_text(rr_tree, tvb, cur_offset, 6, "Time signed: %s%s",
1629                 abs_time_to_str(&nstime), tsig_timehi == 0 ? "" : "(high bits set)");
1630         cur_offset += 6;
1631         rr_len -= 6;
1632
1633         tsig_fudge = tvb_get_ntohs(tvb, cur_offset);
1634         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Fudge: %u",
1635                 tsig_fudge);
1636         cur_offset += 2;
1637         rr_len -= 2;
1638
1639         tsig_siglen = tvb_get_ntohs(tvb, cur_offset);
1640         cur_offset += 2;
1641         rr_len -= 2;
1642
1643         proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_siglen, "Signature");
1644         cur_offset += tsig_siglen;
1645         rr_len -= tsig_siglen;
1646
1647         tsig_originalid = tvb_get_ntohs(tvb, cur_offset);
1648         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Original id: %d",
1649                 tsig_originalid);
1650         cur_offset += 2;
1651         rr_len -= 2;
1652
1653         tsig_error = tvb_get_ntohs(tvb, cur_offset);
1654         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
1655                 val_to_str(tsig_error, rcode_vals,
1656                 val_to_str(tsig_error, tsigerror_vals, "Unknown error (%x)")));
1657         cur_offset += 2;
1658         rr_len -= 2;
1659
1660         tsig_otherlen = tvb_get_ntohs(tvb, cur_offset);
1661         cur_offset += 2;
1662         rr_len -= 2;
1663
1664         proto_tree_add_text(rr_tree, tvb, cur_offset, tsig_otherlen, "Other");
1665         cur_offset += tsig_otherlen;
1666         rr_len -= tsig_otherlen;
1667       }
1668     }
1669     break;
1670
1671   case T_WINS:
1672     {
1673       int rr_len = data_len;
1674       guint32 local_flag;
1675       guint32 lookup_timeout;
1676       guint32 cache_timeout;
1677       guint32 nservers;
1678
1679       if (dns_tree != NULL) {
1680         local_flag = tvb_get_ntohl(tvb, cur_offset);
1681         if (dns_tree != NULL) {
1682           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1683                        local_flag ? "true" : "false");
1684         }
1685         cur_offset += 4;
1686         rr_len -= 4;
1687
1688         lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1689         if (dns_tree != NULL) {
1690           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1691                        lookup_timeout);
1692         }
1693         cur_offset += 4;
1694         rr_len -= 4;
1695
1696         cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1697         if (dns_tree != NULL) {
1698           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1699                        cache_timeout);
1700         }
1701         cur_offset += 4;
1702         rr_len -= 4;
1703
1704         nservers = tvb_get_ntohl(tvb, cur_offset);
1705         if (dns_tree != NULL) {
1706           proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Number of WINS servers: %u",
1707                        nservers);
1708         }
1709         cur_offset += 4;
1710         rr_len -= 4;
1711
1712         while (rr_len != 0 && nservers != 0) {
1713           if (dns_tree != NULL) {
1714             proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "WINS server address: %s",
1715                      ip_to_str(tvb_get_ptr(tvb, cur_offset, 4)));
1716           }
1717           cur_offset += 4;
1718           rr_len -= 4;
1719           nservers--;
1720         }
1721       }
1722     }
1723     break;
1724
1725   case T_WINS_R:
1726     {
1727       int rr_len = data_len;
1728       guint32 local_flag;
1729       guint32 lookup_timeout;
1730       guint32 cache_timeout;
1731       char dname[MAXDNAME];
1732       int dname_len;
1733
1734       local_flag = tvb_get_ntohl(tvb, cur_offset);
1735       if (dns_tree != NULL) {
1736         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Local flag: %s",
1737                        local_flag ? "true" : "false");
1738       }
1739       cur_offset += 4;
1740       rr_len -= 4;
1741
1742       lookup_timeout = tvb_get_ntohl(tvb, cur_offset);
1743       if (dns_tree != NULL) {
1744         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Lookup timeout: %u seconds",
1745                        lookup_timeout);
1746       }
1747       cur_offset += 4;
1748       rr_len -= 4;
1749
1750       cache_timeout = tvb_get_ntohl(tvb, cur_offset);
1751       if (dns_tree != NULL) {
1752         proto_tree_add_text(rr_tree, tvb, cur_offset, 4, "Cache timeout: %u seconds",
1753                        cache_timeout);
1754       }
1755       cur_offset += 4;
1756       rr_len -= 4;
1757
1758       dname_len = get_dns_name(tvb, cur_offset, dns_data_offset, dname, sizeof(dname));
1759       if (cinfo != NULL)
1760         col_append_fstr(cinfo, COL_INFO, " %s", dname);
1761       if (dns_tree != NULL) {
1762         proto_item_append_text(trr, ", name result domain %s", dname);
1763         proto_tree_add_text(rr_tree, tvb, cur_offset, dname_len, "Name result domain: %s",
1764                         dname);
1765       }
1766     }
1767     break;
1768
1769   case T_SRV:
1770     {
1771       guint16 priority = 0;
1772       guint16 weight = 0;
1773       guint16 port = 0;
1774       char target[MAXDNAME];
1775       int target_len;
1776       
1777       priority = tvb_get_ntohs(tvb, cur_offset);
1778       weight = tvb_get_ntohs(tvb, cur_offset+2);
1779       port = tvb_get_ntohs(tvb, cur_offset+4);
1780
1781       target_len = get_dns_name(tvb, cur_offset + 6, dns_data_offset, target, sizeof(target));
1782       if (cinfo != NULL)
1783         col_append_fstr(cinfo, COL_INFO, " %u %u %u %s", priority, weight, port, target);
1784       if (dns_tree != NULL) {
1785         proto_item_append_text(trr,
1786                        ", priority %u, weight %u, port %u, target %s",
1787                        priority, weight, port, target);
1788         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Priority: %u", priority);
1789         proto_tree_add_text(rr_tree, tvb, cur_offset + 2, 2, "Weight: %u", weight);
1790         proto_tree_add_text(rr_tree, tvb, cur_offset + 4, 2, "Port: %u", port);
1791         proto_tree_add_text(rr_tree, tvb, cur_offset + 6, target_len, "Target: %s",
1792                         target);
1793       }
1794     }
1795     break;
1796
1797     /* TODO: parse more record types */
1798
1799   default:
1800     if (dns_tree != NULL)
1801       proto_tree_add_text(rr_tree, tvb, cur_offset, data_len, "Data");
1802     break;
1803   }
1804   
1805   data_offset += data_len;
1806         
1807   return data_offset - data_start;
1808 }
1809
1810 static int
1811 dissect_query_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1812     int count, column_info *cinfo, proto_tree *dns_tree, int isupdate)
1813 {
1814   int start_off, add_off;
1815   proto_tree *qatree = NULL;
1816   proto_item *ti = NULL;
1817   
1818   start_off = cur_off;
1819   if (dns_tree) {
1820     char *s = (isupdate ?  "Zone" : "Queries");
1821     ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, s);
1822     qatree = proto_item_add_subtree(ti, ett_dns_qry);
1823   }
1824   while (count-- > 0) {
1825     add_off = dissect_dns_query(tvb, cur_off, dns_data_offset, cinfo, qatree);
1826     cur_off += add_off;
1827   }
1828   if (ti)
1829     proto_item_set_len(ti, cur_off - start_off);
1830
1831   return cur_off - start_off;
1832 }
1833
1834 static int
1835 dissect_answer_records(tvbuff_t *tvb, int cur_off, int dns_data_offset,
1836     int count, column_info *cinfo, proto_tree *dns_tree, char *name)
1837 {
1838   int start_off, add_off;
1839   proto_tree *qatree = NULL;
1840   proto_item *ti = NULL;
1841   
1842   start_off = cur_off;
1843   if (dns_tree) {
1844     ti = proto_tree_add_text(dns_tree, tvb, start_off, -1, name);
1845     qatree = proto_item_add_subtree(ti, ett_dns_ans);
1846   }
1847   while (count-- > 0) {
1848     add_off = dissect_dns_answer(tvb, cur_off, dns_data_offset, cinfo, qatree);
1849     cur_off += add_off;
1850   }
1851   if (ti)
1852     proto_item_set_len(ti, cur_off - start_off);
1853
1854   return cur_off - start_off;
1855 }
1856
1857 static void
1858 dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1859     gboolean is_tcp)
1860 {
1861   int offset = is_tcp ? 2 : 0;
1862   int dns_data_offset;
1863   column_info *cinfo;
1864   proto_tree *dns_tree = NULL, *field_tree;
1865   proto_item *ti, *tf;
1866   guint16    id, flags, opcode, rcode, quest, ans, auth, add;
1867   char buf[128+1];
1868   int cur_off;
1869   int isupdate;
1870
1871   dns_data_offset = offset;
1872
1873   if (check_col(pinfo->cinfo, COL_PROTOCOL))
1874     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DNS");
1875   if (check_col(pinfo->cinfo, COL_INFO))
1876     col_clear(pinfo->cinfo, COL_INFO);
1877
1878   /* To do: check for errs, etc. */
1879   id    = tvb_get_ntohs(tvb, offset + DNS_ID);
1880   flags = tvb_get_ntohs(tvb, offset + DNS_FLAGS);
1881   opcode = (flags & F_OPCODE) >> OPCODE_SHIFT;
1882   rcode = (flags & F_RCODE);
1883
1884   if (check_col(pinfo->cinfo, COL_INFO)) {
1885     strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation (%u)"));
1886     if (flags & F_RESPONSE) {
1887       strcat(buf, " response");
1888       if ((flags & F_RCODE) != RCODE_NOERROR) {
1889         strcat(buf, ", ");
1890         strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1891             "Unknown error (%u)"));
1892       }
1893     }
1894     col_add_str(pinfo->cinfo, COL_INFO, buf);
1895     cinfo = pinfo->cinfo;
1896   } else {
1897     /* Set "cinfo" to NULL; we pass a NULL "cinfo" to the query and answer
1898        dissectors, as a way of saying that they shouldn't add stuff
1899        to the COL_INFO column (a call to "check_col(cinfo, COL_INFO)"
1900        is more expensive than a check that a pointer isn't NULL). */
1901     cinfo = NULL;
1902   }
1903   if (opcode == OPCODE_UPDATE)
1904     isupdate = 1;
1905   else
1906     isupdate = 0;
1907
1908   if (tree) {
1909     ti = proto_tree_add_protocol_format(tree, proto_dns, tvb, 0, -1,
1910       "Domain Name System (%s)", (flags & F_RESPONSE) ? "response" : "query");
1911     
1912     dns_tree = proto_item_add_subtree(ti, ett_dns);
1913
1914     if (is_tcp) {
1915       /* Put the length indication into the tree. */
1916       proto_tree_add_item(dns_tree, hf_dns_length, tvb, offset - 2, 2, FALSE);
1917     }
1918
1919     proto_tree_add_uint(dns_tree, hf_dns_transaction_id, tvb, 
1920                         offset + DNS_ID, 2, id);
1921
1922     strcpy(buf, val_to_str(opcode, opcode_vals, "Unknown operation"));
1923     if (flags & F_RESPONSE) {
1924       strcat(buf, " response");
1925       strcat(buf, ", ");
1926       strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
1927             "Unknown error"));
1928     }
1929     tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb, 
1930                                     offset + DNS_FLAGS, 2, 
1931                                     flags,
1932                                     "Flags: 0x%04x (%s)",
1933                                     flags, buf);
1934     field_tree = proto_item_add_subtree(tf, ett_dns_flags);
1935     proto_tree_add_item(field_tree, hf_dns_flags_response,
1936                         tvb, offset + DNS_FLAGS, 2, FALSE);
1937     proto_tree_add_item(field_tree, hf_dns_flags_opcode,
1938                         tvb, offset + DNS_FLAGS, 2, FALSE);
1939     if (flags & F_RESPONSE) {
1940       proto_tree_add_item(field_tree, hf_dns_flags_authoritative,
1941                           tvb, offset + DNS_FLAGS, 2, FALSE);
1942     }
1943     proto_tree_add_item(field_tree, hf_dns_flags_truncated,
1944                         tvb, offset + DNS_FLAGS, 2, FALSE);
1945     proto_tree_add_item(field_tree, hf_dns_flags_recdesired,
1946                         tvb, offset + DNS_FLAGS, 2, FALSE);
1947     if (flags & F_RESPONSE) {
1948       proto_tree_add_item(field_tree, hf_dns_flags_recavail,
1949                           tvb, offset + DNS_FLAGS, 2, FALSE);
1950       proto_tree_add_item(field_tree, hf_dns_flags_authenticated,
1951                           tvb, offset + DNS_FLAGS, 2, FALSE);
1952       proto_tree_add_item(field_tree, hf_dns_flags_rcode,
1953                           tvb, offset + DNS_FLAGS, 2, FALSE);
1954     } else {
1955       proto_tree_add_item(field_tree, hf_dns_flags_checkdisable,
1956                           tvb, offset + DNS_FLAGS, 2, FALSE);
1957     }
1958   }
1959   quest = tvb_get_ntohs(tvb, offset + DNS_QUEST);
1960   if (tree) {
1961     proto_tree_add_uint(dns_tree, hf_dns_count_questions, tvb, 
1962                         offset + DNS_QUEST, 2, quest);
1963   }
1964   ans = tvb_get_ntohs(tvb, offset + DNS_ANS);
1965   if (tree) {
1966     proto_tree_add_uint(dns_tree, hf_dns_count_answers, tvb, 
1967                         offset + DNS_ANS, 2, ans);
1968   }
1969   auth = tvb_get_ntohs(tvb, offset + DNS_AUTH);
1970   if (tree) {
1971     proto_tree_add_uint(dns_tree, hf_dns_count_auth_rr, tvb, 
1972                         offset + DNS_AUTH, 2, auth);
1973   }
1974   add = tvb_get_ntohs(tvb, offset + DNS_ADD);
1975   if (tree) {
1976     proto_tree_add_uint(dns_tree, hf_dns_count_add_rr, tvb, 
1977                         offset + DNS_ADD, 2, add);
1978
1979   }
1980   cur_off = offset + DNS_HDRLEN;
1981
1982   if (quest > 0) {
1983     /* If this is a response, don't add information about the queries
1984        to the summary, just add information about the answers. */
1985     cur_off += dissect_query_records(tvb, cur_off, dns_data_offset, quest,
1986                                      (!(flags & F_RESPONSE) ? cinfo : NULL),
1987                                      dns_tree, isupdate);
1988   }
1989     
1990   if (ans > 0) {
1991     /* If this is a request, don't add information about the answers
1992        to the summary, just add information about the queries. */
1993     cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, ans,
1994                                       ((flags & F_RESPONSE) ? cinfo : NULL),
1995                                       dns_tree,
1996                                       (isupdate ?  "Prerequisites" : "Answers"));
1997   }
1998     
1999   /* Don't add information about the authoritative name servers, or the
2000      additional records, to the summary. */
2001   if (auth > 0) {
2002     cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, auth,
2003                                       NULL, dns_tree,
2004                                       (isupdate ?  "Updates" :
2005                                                    "Authoritative nameservers"));
2006   }
2007
2008   if (add > 0) {
2009     cur_off += dissect_answer_records(tvb, cur_off, dns_data_offset, add,
2010                                       NULL, dns_tree, "Additional records");
2011   }
2012 }
2013
2014 static void
2015 dissect_dns_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2016 {
2017   dissect_dns_common(tvb, pinfo, tree, FALSE);
2018 }
2019
2020 static guint
2021 get_dns_pdu_len(tvbuff_t *tvb, int offset)
2022 {
2023   guint16 plen;
2024
2025   /*
2026    * Get the length of the DNS packet.
2027    */
2028   plen = tvb_get_ntohs(tvb, offset);
2029
2030   /*
2031    * That length doesn't include the length field itself; add that in.
2032    */
2033   return plen + 2;
2034 }
2035
2036 static void
2037 dissect_dns_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2038 {
2039   dissect_dns_common(tvb, pinfo, tree, TRUE);
2040 }
2041
2042 static void
2043 dissect_dns_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2044 {
2045   tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2, get_dns_pdu_len,
2046         dissect_dns_tcp_pdu);
2047 }
2048
2049 void
2050 proto_register_dns(void)
2051 {
2052   static hf_register_info hf[] = {
2053     { &hf_dns_length,
2054       { "Length",               "dns.length",
2055         FT_UINT16, BASE_DEC, NULL, 0x0,
2056         "Length of DNS-over-TCP request or response", HFILL }},
2057     { &hf_dns_flags,
2058       { "Flags",                "dns.flags",
2059         FT_UINT16, BASE_HEX, NULL, 0x0,
2060         "", HFILL }},
2061     { &hf_dns_flags_response,
2062       { "Response",             "dns.flags.response",
2063         FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
2064         "Is the message a response?", HFILL }},
2065     { &hf_dns_flags_opcode,
2066       { "Opcode",               "dns.flags.opcode",
2067         FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
2068         "Operation code", HFILL }},
2069     { &hf_dns_flags_authoritative,
2070       { "Authoritative",        "dns.flags.authoritative",
2071         FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
2072         "Is the server is an authority for the domain?", HFILL }},
2073     { &hf_dns_flags_truncated,
2074       { "Truncated",    "dns.flags.truncated",
2075         FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
2076         "Is the message truncated?", HFILL }},
2077     { &hf_dns_flags_recdesired,
2078       { "Recursion desired",    "dns.flags.recdesired",
2079         FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
2080         "Do query recursively?", HFILL }},
2081     { &hf_dns_flags_recavail,
2082       { "Recursion available",  "dns.flags.recavail",
2083         FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
2084         "Can the server do recursive queries?", HFILL }},
2085     { &hf_dns_flags_authenticated,
2086       { "Answer authenticated", "dns.flags.authenticated",
2087         FT_BOOLEAN, 16, TFS(&tfs_flags_authenticated), F_AUTHENTIC,
2088         "Was the reply data authenticated by the server?", HFILL }},
2089     { &hf_dns_flags_checkdisable,
2090       { "Non-authenticated data OK",    "dns.flags.checkdisable",
2091         FT_BOOLEAN, 16, TFS(&tfs_flags_checkdisable), F_CHECKDISABLE,
2092         "Is non-authenticated data acceptable?", HFILL }},
2093     { &hf_dns_flags_rcode,
2094       { "Reply code",           "dns.flags.rcode",
2095         FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
2096         "Reply code", HFILL }},
2097     { &hf_dns_transaction_id,
2098       { "Transaction ID",       "dns.id",  
2099         FT_UINT16, BASE_HEX, NULL, 0x0,
2100         "Identification of transaction", HFILL }},
2101     { &hf_dns_count_questions,
2102       { "Questions",            "dns.count.queries",  
2103         FT_UINT16, BASE_DEC, NULL, 0x0,
2104         "Number of queries in packet", HFILL }},
2105     { &hf_dns_count_answers,
2106       { "Answer RRs",           "dns.count.answers",  
2107         FT_UINT16, BASE_DEC, NULL, 0x0,
2108         "Number of answers in packet", HFILL }},
2109     { &hf_dns_count_auth_rr,
2110       { "Authority RRs",        "dns.count.auth_rr",  
2111         FT_UINT16, BASE_DEC, NULL, 0x0,
2112         "Number of authoritative records in packet", HFILL }},
2113     { &hf_dns_count_add_rr,
2114       { "Additional RRs",       "dns.count.add_rr",  
2115         FT_UINT16, BASE_DEC, NULL, 0x0,
2116         "Number of additional records in packet", HFILL }}
2117   };
2118   static gint *ett[] = {
2119     &ett_dns,
2120     &ett_dns_qd,
2121     &ett_dns_rr,
2122     &ett_dns_qry,
2123     &ett_dns_ans,
2124     &ett_dns_flags,
2125     &ett_t_key_flags,
2126   };
2127   module_t *dns_module;
2128
2129   proto_dns = proto_register_protocol("Domain Name Service", "DNS", "dns");
2130   proto_register_field_array(proto_dns, hf, array_length(hf));
2131   proto_register_subtree_array(ett, array_length(ett));
2132
2133   dns_module = prefs_register_protocol(proto_dns, NULL);
2134   prefs_register_bool_preference(dns_module, "desegment_dns_messages",
2135     "Desegment all DNS messages spanning multiple TCP segments",
2136     "Whether the DNS dissector should desegment all messages spanning multiple TCP segments",
2137     &dns_desegment);
2138 }
2139
2140 void
2141 proto_reg_handoff_dns(void)
2142 {
2143   dissector_handle_t dns_udp_handle;
2144   dissector_handle_t dns_tcp_handle;
2145
2146   dns_udp_handle = create_dissector_handle(dissect_dns_udp, proto_dns);
2147   dns_tcp_handle = create_dissector_handle(dissect_dns_tcp, proto_dns);
2148   dissector_add("udp.port", UDP_PORT_DNS, dns_udp_handle);
2149   dissector_add("tcp.port", TCP_PORT_DNS, dns_tcp_handle);
2150   dissector_add("udp.port", UDP_PORT_MDNS, dns_udp_handle);
2151   dissector_add("tcp.port", TCP_PORT_MDNS, dns_tcp_handle);
2152 }