Removed all references to gtk objects from packet*.[ch] files. They now
[metze/wireshark/wip.git] / packet-dns.c
1 /* packet-dns.c
2  * Routines for DNS packet disassembly
3  *
4  * $Id: packet-dns.c,v 1.17 1999/03/23 03:14:36 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <memory.h>
37
38 #include <glib.h>
39 #include "packet.h"
40 #include "packet-dns.h"
41 #include "util.h"
42
43
44 /* DNS structs and definitions */
45
46 /* Offsets of fields in the DNS header. */
47 #define DNS_ID          0
48 #define DNS_FLAGS       2
49 #define DNS_QUEST       4
50 #define DNS_ANS 6
51 #define DNS_AUTH        8
52 #define DNS_ADD 10
53
54 /* Length of DNS header. */
55 #define DNS_HDRLEN      12
56
57 /* type values  */
58 #define T_A             1               /* host address */
59 #define T_NS            2               /* authoritative name server */
60 #define T_MD            3               /* mail destination (obsolete) */
61 #define T_MF            4               /* mail forwarder (obsolete) */
62 #define T_CNAME         5               /* canonical name */
63 #define T_SOA           6               /* start of authority zone */
64 #define T_MB            7               /* mailbox domain name (experimental) */
65 #define T_MG            8               /* mail group member (experimental) */
66 #define T_MR            9               /* mail rename domain name (experimental) */
67 #define T_NULL          10              /* null RR (experimental) */
68 #define T_WKS           11              /* well known service */
69 #define T_PTR           12              /* domain name pointer */
70 #define T_HINFO         13              /* host information */
71 #define T_MINFO         14              /* mailbox or mail list information */
72 #define T_MX            15              /* mail routing information */
73 #define T_TXT           16              /* text strings */
74 #define T_RP            17              /* responsible person (RFC 1183) */
75 #define T_AFSDB         18              /* AFS data base location (RFC 1183) */
76 #define T_X25           19              /* X.25 address (RFC 1183) */
77 #define T_ISDN          20              /* ISDN address (RFC 1183) */
78 #define T_RT            21              /* route-through (RFC 1183) */
79 #define T_NSAP          22              /* OSI NSAP (RFC 1706) */
80 #define T_NSAP_PTR      23              /* PTR equivalent for OSI NSAP (RFC 1348 - obsolete) */
81 #define T_SIG           24              /* digital signature (RFC 2065) */
82 #define T_KEY           25              /* public key (RFC 2065) */
83 #define T_PX            26              /* pointer to X.400/RFC822 mapping info (RFC 1664) */
84 #define T_GPOS          27              /* geographical position (RFC 1712) */
85 #define T_AAAA          28              /* IPv6 address (RFC 1886) */
86 #define T_LOC           29              /* geographical location (RFC 1876) */
87 #define T_NXT           30              /* "next" name (RFC 2065) */
88 #define T_EID           31              /* ??? (Nimrod?) */
89 #define T_NIMLOC        32              /* ??? (Nimrod?) */
90 #define T_SRV           33              /* service location (RFC 2052) */
91 #define T_ATMA          34              /* ??? */
92 #define T_NAPTR         35              /* naming authority pointer (RFC 2168) */
93
94 /* Bit fields in the flags */
95 #define F_RESPONSE      (1<<15)         /* packet is response */
96 #define F_OPCODE        (0xF<<11)       /* query opcode */
97 #define F_AUTHORITATIVE (1<<10)         /* response is authoritative */
98 #define F_TRUNCATED     (1<<9)          /* response is truncated */
99 #define F_RECDESIRED    (1<<8)          /* recursion desired */
100 #define F_RECAVAIL      (1<<7)          /* recursion available */
101 #define F_RCODE         (0xF<<0)        /* reply code */
102
103 /* Opcodes */
104 #define OPCODE_QUERY    (0<<11)         /* standard query */
105 #define OPCODE_IQUERY   (1<<11)         /* inverse query */
106 #define OPCODE_STATUS   (2<<11)         /* server status request */
107
108 /* Reply codes */
109 #define RCODE_NOERROR   (0<<0)
110 #define RCODE_FMTERROR  (1<<0)
111 #define RCODE_SERVFAIL  (2<<0)
112 #define RCODE_NAMEERROR (3<<0)
113 #define RCODE_NOTIMPL   (4<<0)
114 #define RCODE_REFUSED   (5<<0)
115
116 /* See RFC 1035 for all RR types for which no RFC is listed. */
117 static char *
118 dns_type_name (int type)
119 {
120   char *type_names[36] = {
121     "unused",
122     "A",
123     "NS",
124     "MD",
125     "MF",
126     "CNAME",
127     "SOA",
128     "MB",
129     "MG",
130     "MR",
131     "NULL",
132     "WKS",
133     "PTR",
134     "HINFO",
135     "MINFO",
136     "MX",
137     "TXT",
138     "RP",                               /* RFC 1183 */
139     "AFSDB",                            /* RFC 1183 */
140     "X25",                              /* RFC 1183 */
141     "ISDN",                             /* RFC 1183 */
142     "RT",                               /* RFC 1183 */
143     "NSAP",                             /* RFC 1706 */
144     "NSAP-PTR",                         /* RFC 1348 */
145     "SIG",                              /* RFC 2065 */
146     "KEY",                              /* RFC 2065 */
147     "PX",                               /* RFC 1664 */
148     "GPOS",                             /* RFC 1712 */
149     "AAAA",                             /* RFC 1886 */
150     "LOC",                              /* RFC 1876 */
151     "NXT",                              /* RFC 2065 */
152     "EID",
153     "NIMLOC",
154     "SRV",                              /* RFC 2052 */
155     "ATMA",
156     "NAPTR"                             /* RFC 2168 */
157   };
158   
159   if (type <= 35)
160     return type_names[type];
161   
162   /* special cases */
163   switch (type) 
164     {
165       /* non standard  */
166     case 100:
167       return "UINFO";
168     case 101:
169       return "UID";
170     case 102:
171       return "GID";
172     case 103:
173       return "UNSPEC";
174       
175       /* queries  */
176     case 251:
177       return "IXFR";    /* RFC 1995 */
178     case 252:
179       return "AXFR";
180     case 253:
181       return "MAILB";
182     case 254:
183       return "MAILA";
184     case 255:
185       return "ANY";
186     }
187   
188   return "unknown";
189 }
190
191
192 static char *
193 dns_long_type_name (int type)
194 {
195   char *type_names[36] = {
196     "unused",
197     "Host address",
198     "Authoritative name server",        
199     "Mail destination",
200     "Mail forwarder",
201     "Canonical name for an alias",
202     "Start of zone of authority",
203     "Mailbox domain name",
204     "Mail group member",
205     "Mail rename domain name",
206     "Null resource record",
207     "Well-known service description",
208     "Domain name pointer",
209     "Host information",
210     "Mailbox or mail list information",
211     "Mail exchange",
212     "Text strings",
213     "Responsible person",               /* RFC 1183 */
214     "AFS data base location",           /* RFC 1183 */
215     "X.25 address",                     /* RFC 1183 */
216     "ISDN number",                      /* RFC 1183 */
217     "Route through",                    /* RFC 1183 */
218     "OSI NSAP",                         /* RFC 1706 */
219     "OSI NSAP name pointer",            /* RFC 1348 */
220     "Signature",                        /* RFC 2065 */
221     "Public key",                       /* RFC 2065 */
222     "Pointer to X.400/RFC822 mapping info", /* RFC 1664 */
223     "Geographical position",            /* RFC 1712 */
224     "IPv6 address",                     /* RFC 1886 */
225     "Location",                         /* RFC 1876 */
226     "Next",                             /* RFC 2065 */
227     "EID",
228     "NIMLOC",
229     "Service location",                 /* RFC 2052 */
230     "ATMA",
231     "Naming authority pointer"          /* RFC 2168 */
232   };
233   static char unkbuf[7+1+2+1+4+1+1+10+1+1];     /* "Unknown RR type (%d)" */
234   
235   if (type <= 35)
236     return type_names[type];
237   
238   /* special cases */
239   switch (type) 
240     {
241       /* non standard  */
242     case 100:
243       return "UINFO";
244     case 101:
245       return "UID";
246     case 102:
247       return "GID";
248     case 103:
249       return "UNSPEC";
250       
251       /* queries  */
252     case 251:
253       return "Request for incremental zone transfer";   /* RFC 1995 */
254     case 252:
255       return "Request for full zone transfer";
256     case 253:
257       return "Request for mailbox-related records";
258     case 254:
259       return "Request for mail agent resource records";
260     case 255:
261       return "Request for all records";
262     }
263   
264   sprintf(unkbuf, "Unknown RR type (%d)", type);
265   return unkbuf;
266 }
267
268
269 char *
270 dns_class_name(int class)
271 {
272   char *class_name;
273   
274   switch (class) {
275   case 1:
276     class_name = "inet";
277     break;
278   case 3:
279     class_name = "chaos";
280     break;
281   case 4:
282     class_name = "hesiod";
283     break;
284   default:
285     class_name = "unknown";
286   }
287
288   return class_name;
289 }
290   
291
292 static int
293 is_compressed_name(const u_char *foo)
294 {
295   return (0xc0 == (*foo & 0xc0));
296 }
297
298
299 static int
300 get_compressed_name_offset(const u_char *ptr)
301 {
302   return ((*ptr & ~0xc0) << 8) | *(ptr+1);
303 }
304
305
306 static int
307 copy_one_name_component(const u_char *dataptr, char *nameptr)
308 {
309   int len;
310   int n;
311   
312   len = n  = *dataptr++;
313   if (0 == len)
314     return 0;
315   
316   while (n-- > 0)
317     *nameptr++ = *dataptr++;
318
319   return len;
320 }
321
322
323 static int
324 copy_name_component_rec(const u_char *dns_data_ptr, const u_char *dataptr,
325   char *nameptr, int *real_string_len)
326 {
327   int len = 0;
328   int str_len;
329   int offset;
330   int compress = 0;
331   
332   if (is_compressed_name(dataptr)) {
333     compress = 1;
334     offset = get_compressed_name_offset(dataptr);
335     dataptr = dns_data_ptr + offset;
336     copy_name_component_rec(dns_data_ptr, dataptr, nameptr, &str_len);
337     *real_string_len += str_len;
338     nameptr += str_len;
339     len = 2;
340   }
341   else {
342     str_len = copy_one_name_component(dataptr, nameptr);
343     *real_string_len = str_len;
344     dataptr += str_len + 1;
345     len     += str_len + 1;
346     nameptr += str_len;
347   }
348
349   if (compress)
350     return len;
351   
352   (*real_string_len)++;
353
354   if (*dataptr > 0) {
355     *nameptr++ = '.';
356     len += copy_name_component_rec(dns_data_ptr, dataptr, nameptr, &str_len);
357     *real_string_len += str_len;
358     return len;
359   }
360
361   return len + 1;
362 }
363
364
365 int
366 get_dns_name(const u_char *dns_data_ptr, const u_char *pd, int offset,
367   char *nameptr, int maxname)
368 {
369   int len;
370   const u_char *dataptr = pd + offset;
371   int str_len = 0;
372
373   memset (nameptr, 0, maxname);
374   len = copy_name_component_rec(dns_data_ptr, dataptr, nameptr, &str_len);
375   
376   return len;
377 }
378
379
380 static int
381 get_dns_name_type_class (const u_char *dns_data_ptr,
382                          const u_char *pd,
383                          int offset,
384                          char *name_ret,
385                          int *name_len_ret,
386                          int *type_ret,
387                          int *class_ret)
388 {
389   int len;
390   int name_len;
391   int type;
392   int class;
393   char name[MAXDNAME];
394   const u_char *pd_save;
395
396   name_len = get_dns_name(dns_data_ptr, pd, offset, name, sizeof(name));
397   pd += offset;
398   pd_save = pd;
399   pd += name_len;
400   
401   type = pntohs(pd);
402   pd += 2;
403   class = pntohs(pd);
404   pd += 2;
405
406   strcpy (name_ret, name);
407   *type_ret = type;
408   *class_ret = class;
409   *name_len_ret = name_len;
410
411   len = pd - pd_save;
412   return len;
413 }
414
415
416 static int
417 dissect_dns_query(const u_char *dns_data_ptr, const u_char *pd, int offset,
418   proto_tree *dns_tree)
419 {
420   int len;
421   char name[MAXDNAME];
422   int name_len;
423   int type;
424   int class;
425   char *class_name;
426   char *type_name;
427   char *long_type_name;
428   const u_char *dptr;
429   const u_char *data_start;
430   proto_tree *q_tree;
431   proto_item *tq;
432
433   data_start = dptr = pd + offset;
434
435   len = get_dns_name_type_class(dns_data_ptr, pd, offset, name, &name_len,
436     &type, &class);
437   dptr += len;
438
439   type_name = dns_type_name(type);
440   class_name = dns_class_name(class);
441   long_type_name = dns_long_type_name(type);
442
443   tq = proto_tree_add_item(dns_tree, offset, len, "%s: type %s, class %s", 
444                    name, type_name, class_name);
445   q_tree = proto_tree_new();
446   proto_item_add_subtree(tq, q_tree, ETT_DNS_QD);
447
448   proto_tree_add_item(q_tree, offset, name_len, "Name: %s", name);
449   offset += name_len;
450
451   proto_tree_add_item(q_tree, offset, 2, "Type: %s", long_type_name);
452   offset += 2;
453
454   proto_tree_add_item(q_tree, offset, 2, "Class: %s", class_name);
455   offset += 2;
456   
457   return dptr - data_start;
458 }
459
460
461 proto_tree *
462 add_rr_to_tree(proto_item *trr, int rr_type, int offset, const char *name,
463   int namelen, const char *type_name, const char *class_name, u_int ttl,
464   u_short data_len)
465 {
466   proto_tree *rr_tree;
467
468   rr_tree = proto_tree_new();
469   proto_item_add_subtree(trr, rr_tree, rr_type);
470   proto_tree_add_item(rr_tree, offset, namelen, "Name: %s", name);
471   offset += namelen;
472   proto_tree_add_item(rr_tree, offset, 2, "Type: %s", type_name);
473   offset += 2;
474   proto_tree_add_item(rr_tree, offset, 2, "Class: %s", class_name);
475   offset += 2;
476   proto_tree_add_item(rr_tree, offset, 4, "Time to live: %s",
477                                                 time_secs_to_str(ttl));
478   offset += 4;
479   proto_tree_add_item(rr_tree, offset, 2, "Data length: %u", data_len);
480   return rr_tree;
481 }
482
483 static int
484 dissect_dns_answer(const u_char *dns_data_ptr, const u_char *pd, int offset,
485   proto_tree *dns_tree)
486 {
487   int len;
488   char name[MAXDNAME];
489   int name_len;
490   int type;
491   int class;
492   char *class_name;
493   char *type_name;
494   char *long_type_name;
495   const u_char *dptr;
496   const u_char *data_start;
497   u_int ttl;
498   u_short data_len;
499   proto_tree *rr_tree;
500   proto_item *trr;
501
502   data_start = dptr = pd + offset;
503
504   len = get_dns_name_type_class(dns_data_ptr, pd, offset, name, &name_len,
505     &type, &class);
506   dptr += len;
507
508   type_name = dns_type_name(type);
509   class_name = dns_class_name(class);
510   long_type_name = dns_long_type_name(type);
511
512   ttl = pntohl(dptr);
513   dptr += 4;
514
515   data_len = pntohs(dptr);
516   dptr += 2;
517
518   switch (type) {
519   case T_A:             /* "A" record */
520     trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
521                      "%s: type %s, class %s, addr %s",
522                      name, type_name, class_name,
523                      ip_to_str((guint8 *)dptr));
524     rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
525                      long_type_name, class_name, ttl, data_len);
526     offset += (dptr - data_start);
527     proto_tree_add_item(rr_tree, offset, 4, "Addr: %s",
528                      ip_to_str((guint8 *)dptr));
529     break;
530
531   case T_NS:            /* "NS" record */
532     {
533       char ns_name[MAXDNAME];
534       int ns_name_len;
535       
536       ns_name_len = get_dns_name(dns_data_ptr, dptr, 0, ns_name, sizeof(ns_name));
537       trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
538                        "%s: type %s, class %s, ns %s",
539                        name, type_name, class_name, ns_name);
540       rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
541                        long_type_name, class_name, ttl, data_len);
542       offset += (dptr - data_start);
543       proto_tree_add_item(rr_tree, offset, ns_name_len, "Name server: %s", ns_name);
544     }
545     break;
546
547   case T_CNAME:         /* "CNAME" record */
548     {
549       char cname[MAXDNAME];
550       int cname_len;
551       
552       cname_len = get_dns_name(dns_data_ptr, dptr, 0, cname, sizeof(cname));
553       trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
554                      "%s: type %s, class %s, cname %s",
555                      name, type_name, class_name, cname);
556       rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
557                        long_type_name, class_name, ttl, data_len);
558       offset += (dptr - data_start);
559       proto_tree_add_item(rr_tree, offset, data_len, "Primary name: %s", cname);
560     }
561     break;
562
563   case T_PTR:           /* "PTR" record */
564     {
565       char pname[MAXDNAME];
566       int pname_len;
567       
568       pname_len = get_dns_name(dns_data_ptr, dptr, 0, pname, sizeof(pname));
569       trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
570                      "%s: type %s, class %s, ptr %s",
571                      name, type_name, class_name, pname);
572       rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
573                        long_type_name, class_name, ttl, data_len);
574       offset += (dptr - data_start);
575       proto_tree_add_item(rr_tree, offset, data_len, "Domain name: %s", pname);
576       break;
577     }
578     break;
579       
580     /* TODO: parse more record types */
581
582   default:
583     trr = proto_tree_add_item(dns_tree, offset, (dptr - data_start) + data_len,
584                      "%s: type %s, class %s",
585                      name, type_name, class_name);
586     rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
587                        long_type_name, class_name, ttl, data_len);
588     offset += (dptr - data_start);
589     proto_tree_add_item(rr_tree, offset, data_len, "Data");
590   }
591   
592   dptr += data_len;
593         
594   return dptr - data_start;
595 }
596
597 static int
598 dissect_query_records(const u_char *dns_data_ptr, int count, const u_char *pd, 
599                       int cur_off, proto_tree *dns_tree)
600 {
601   int start_off;
602   proto_tree *qatree;
603   proto_item *ti;
604   
605   start_off = cur_off;
606   ti = proto_tree_add_item(dns_tree, start_off, 0, "Queries");
607   qatree = proto_tree_new();
608   proto_item_add_subtree(ti, qatree, ETT_DNS_QRY);
609   while (count-- > 0)
610     cur_off += dissect_dns_query(dns_data_ptr, pd, cur_off, qatree);
611   proto_item_set_len(ti, cur_off - start_off);
612
613   return cur_off - start_off;
614 }
615
616
617
618 static int
619 dissect_answer_records(const u_char *dns_data_ptr, int count,
620                        const u_char *pd, int cur_off, proto_tree *dns_tree,
621                        char *name)
622 {
623   int start_off;
624   proto_tree *qatree;
625   proto_item *ti;
626   
627   start_off = cur_off;
628   ti = proto_tree_add_item(dns_tree, start_off, 0, name);
629   qatree = proto_tree_new();
630   proto_item_add_subtree(ti, qatree, ETT_DNS_ANS);
631   while (count-- > 0)
632     cur_off += dissect_dns_answer(dns_data_ptr, pd, cur_off, qatree);
633   proto_item_set_len(ti, cur_off - start_off);
634
635   return cur_off - start_off;
636 }
637
638
639 void
640 dissect_dns(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
641   const u_char *dns_data_ptr;
642   proto_tree *dns_tree, *field_tree;
643   proto_item *ti, *tf;
644   guint16    id, flags, quest, ans, auth, add;
645   char buf[128+1];
646   int cur_off;
647   static const value_string opcode_vals[] = {
648                   { OPCODE_QUERY,  "Standard query"        },
649                   { OPCODE_IQUERY, "Inverse query"         },
650                   { OPCODE_STATUS, "Server status request" },
651                   { 0,              NULL                   } };
652   static const value_string rcode_vals[] = {
653                   { RCODE_NOERROR,   "No error"        },
654                   { RCODE_FMTERROR,  "Format error"    },
655                   { RCODE_SERVFAIL,  "Server failure"  },
656                   { RCODE_NAMEERROR, "Name error"      },
657                   { RCODE_NOTIMPL,   "Not implemented" },
658                   { RCODE_REFUSED,   "Refused"         },
659                   { 0,               NULL              } };
660
661   dns_data_ptr = &pd[offset];
662
663   /* To do: check for runts, errs, etc. */
664   id    = pntohs(&pd[offset + DNS_ID]);
665   flags = pntohs(&pd[offset + DNS_FLAGS]);
666   quest = pntohs(&pd[offset + DNS_QUEST]);
667   ans   = pntohs(&pd[offset + DNS_ANS]);
668   auth  = pntohs(&pd[offset + DNS_AUTH]);
669   add   = pntohs(&pd[offset + DNS_ADD]);
670   
671   if (check_col(fd, COL_PROTOCOL))
672     col_add_str(fd, COL_PROTOCOL, "DNS (UDP)");
673   if (check_col(fd, COL_INFO)) {
674     col_add_fstr(fd, COL_INFO, "%s%s",
675                 val_to_str(flags & F_OPCODE, opcode_vals,
676                            "Unknown operation (%x)"),
677                 (flags & F_RESPONSE) ? " response" : "");
678   }
679   
680   if (tree) {
681     ti = proto_tree_add_item(tree, offset, 4,
682                           (flags & F_RESPONSE) ? "DNS response" : "DNS query");
683     
684     dns_tree = proto_tree_new();
685     proto_item_add_subtree(ti, dns_tree, ETT_DNS);
686     
687     proto_tree_add_item(dns_tree, offset + DNS_ID, 2, "Transaction ID: 0x%04x",
688                         id);
689
690     strcpy(buf, val_to_str(flags & F_OPCODE, opcode_vals, "Unknown operation"));
691     if (flags & F_RESPONSE) {
692       strcat(buf, " response");
693       strcat(buf, ", ");
694       strcat(buf, val_to_str(flags & F_RCODE, rcode_vals,
695             "Unknown error"));
696     }
697     tf = proto_tree_add_item(dns_tree, offset + DNS_FLAGS, 2, "Flags: 0x%04x (%s)",
698                           flags, buf);
699     field_tree = proto_tree_new();
700     proto_item_add_subtree(tf, field_tree, ETT_DNS_FLAGS);
701     proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
702        decode_boolean_bitfield(flags, F_RESPONSE,
703             2*8, "Response", "Query"));
704     proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
705        decode_enumerated_bitfield(flags, F_OPCODE,
706             2*8, opcode_vals, "%s"));
707     if (flags & F_RESPONSE) {
708       proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
709          decode_boolean_bitfield(flags, F_AUTHORITATIVE,
710               2*8,
711               "Server is an authority for domain",
712               "Server isn't an authority for domain"));
713     }
714     proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
715        decode_boolean_bitfield(flags, F_TRUNCATED,
716             2*8,
717             "Message is truncated",
718             "Message is not truncated"));
719     proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
720        decode_boolean_bitfield(flags, F_RECDESIRED,
721             2*8,
722             "Do query recursively",
723             "Don't do query recursively"));
724     if (flags & F_RESPONSE) {
725       proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
726          decode_boolean_bitfield(flags, F_RECAVAIL,
727               2*8,
728               "Server can do recursive queries",
729               "Server can't do recursive queries"));
730       proto_tree_add_item(field_tree, offset + DNS_FLAGS, 2, "%s",
731          decode_enumerated_bitfield(flags, F_RCODE,
732               2*8, rcode_vals, "%s"));
733     }
734     proto_tree_add_item(dns_tree, offset + DNS_QUEST, 2, "Questions: %d", quest);
735     proto_tree_add_item(dns_tree, offset + DNS_ANS, 2, "Answer RRs: %d", ans);
736     proto_tree_add_item(dns_tree, offset + DNS_AUTH, 2, "Authority RRs: %d", auth);
737     proto_tree_add_item(dns_tree, offset + DNS_ADD, 2, "Additional RRs: %d", add);
738
739     cur_off = offset + DNS_HDRLEN;
740     
741     if (quest > 0)
742       cur_off += dissect_query_records(dns_data_ptr, quest, pd, cur_off,
743                                         dns_tree);
744     
745     if (ans > 0)
746       cur_off += dissect_answer_records(dns_data_ptr, ans, pd, cur_off,
747           dns_tree, "Answers");
748     
749     if (auth > 0)
750       cur_off += dissect_answer_records(dns_data_ptr, auth, pd, cur_off,
751           dns_tree, "Authoritative nameservers");
752
753     if (add > 0)
754       cur_off += dissect_answer_records(dns_data_ptr, add, pd, cur_off,
755           dns_tree, "Additional records");
756   }
757 }