16de34150d864298965ae84c331196ad72dbb09b
[obnox/wireshark/wip.git] / plugins / lwres / packet-lwres.c
1 /* packet-lwres.c
2  * Routines for light weight reslover (lwres, part of BIND9) packet disassembly
3  *
4  * $Id$
5  *
6  * Copyright (c) 2003 by Oleg Terletsky <oleg.terletsky@comverse.com>
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1999 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "plugins/plugin_api.h"
32 #include "moduleinfo.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <gmodule.h>
37 #include <ctype.h>
38 #include <time.h>
39 #include <string.h>
40
41 #include <epan/packet.h>
42 #include <epan/prefs.h>
43
44 #include "plugins/plugin_api_defs.h"
45
46 #define LWRES_LWPACKET_LENGTH           (4 * 5 + 2 * 4)
47 #define LWRES_LWPACKETFLAG_RESPONSE     0x0001U /* if set, pkt is a response */
48 #define LWRES_LWPACKETVERSION_0         0
49
50 #define LW_LENGTH_OFFSET                0 
51 #define LW_VERSION_OFFSET               4 
52 #define LW_PKTFLASG_OFFSET              6
53 #define LW_SERIAL_OFFSET                8 
54 #define LW_OPCODE_OFFSET                12 
55 #define LW_RESULT_OFFSET                16 
56 #define LW_RECVLEN_OFFSET               20 
57 #define LW_AUTHTYPE_OFFSET              24 
58 #define LW_AUTHLEN_OFFSET               26 
59
60
61 #define LWRES_OPCODE_NOOP               0x00000000U
62 #define LWRES_OPCODE_GETADDRSBYNAME     0x00010001U
63 #define LWRES_OPCODE_GETNAMEBYADDR      0x00010002U
64 #define LWRES_OPCODE_GETRDATABYNAME     0x00010003U
65
66 static const value_string opcode_values[] = {
67         { LWRES_OPCODE_NOOP,                    "Noop" },
68         { LWRES_OPCODE_GETADDRSBYNAME,  "getaddrbyname" },
69         { LWRES_OPCODE_GETNAMEBYADDR,   "getnamebyaddr" },
70         { LWRES_OPCODE_GETRDATABYNAME,  "getrdatabyname" },
71         { 0, NULL },
72 };
73
74
75 #define LWRES_R_SUCCESS                 0
76 #define LWRES_R_NOMEMORY                1
77 #define LWRES_R_TIMEOUT                 2
78 #define LWRES_R_NOTFOUND                3
79 #define LWRES_R_UNEXPECTEDEND           4       /* unexpected end of input */
80 #define LWRES_R_FAILURE                 5       /* generic failure */
81 #define LWRES_R_IOERROR                 6
82 #define LWRES_R_NOTIMPLEMENTED          7
83 #define LWRES_R_UNEXPECTED              8
84 #define LWRES_R_TRAILINGDATA            9
85 #define LWRES_R_INCOMPLETE              10
86 #define LWRES_R_RETRY                   11
87 #define LWRES_R_TYPENOTFOUND            12
88 #define LWRES_R_TOOLARGE                13
89
90 #define T_A             1
91 #define T_NS    2
92 #define T_MX    15
93 #define T_SRV   33
94
95
96 static const value_string t_types[] = {
97         { T_A,          "T_A" },
98         { T_NS,         "T_NS" },
99         { T_MX,         "T_MX" },
100         { T_SRV,        "T_SRV" },
101         { 0,            NULL },
102 };
103         
104
105
106
107 static const value_string result_values[]  = {
108         { LWRES_R_SUCCESS,              "Success" },
109         { LWRES_R_NOMEMORY,             "No memory" },
110         { LWRES_R_TIMEOUT,                      "Timeout" },
111         { LWRES_R_NOTFOUND,                     "Not found" },
112         { LWRES_R_UNEXPECTEDEND,        "Unexpected end of input" },
113         { LWRES_R_FAILURE,                      "Generic failure" },
114         { LWRES_R_IOERROR,                      "I/O Error" },
115         { LWRES_R_UNEXPECTED,           "Unexpected" },
116         { LWRES_R_TRAILINGDATA,         "Trailing data" },
117         { LWRES_R_INCOMPLETE,           "Incompete" },
118         { LWRES_R_RETRY,                        "Retry" },
119         { LWRES_R_TYPENOTFOUND,         "Type not found" },
120         { LWRES_R_TOOLARGE,                     "Too large" },
121         { 0,                                            NULL },
122 };
123
124 static int hf_length = -1;
125 static int hf_version = -1;
126 static int hf_flags = -1;
127 static int hf_serial = -1;
128 static int hf_opcode = -1;
129 static int hf_result = -1;
130 static int hf_recvlen = -1;
131 static int hf_authtype = -1;
132 static int hf_authlen = -1;
133
134 static int hf_rflags = -1;
135 static int hf_rdclass = -1;
136 static int hf_rdtype = -1;
137 static int hf_namelen = -1;
138 static int hf_req_name = -1;
139
140 static int hf_ttl = -1;
141 static int hf_nrdatas = -1;
142 static int hf_nsigs = -1;
143 static int hf_realnamelen = -1;
144 static int hf_realname = -1;
145
146
147 static int hf_a_record = -1;
148 static int hf_a_rec_len = -1;
149 static int hf_srv_prio = -1;
150 static int hf_srv_weight = -1;
151 static int hf_srv_port = -1;
152
153 static int hf_adn_flags = -1;
154 static int hf_adn_addrtype = -1;
155 static int hf_adn_namelen = -1;
156 static int hf_adn_name = -1;
157
158 static int hf_adn_realname = -1;
159 static int hf_adn_aliasname = -1;
160
161 static int hf_adn_naddrs = -1;
162 static int hf_adn_naliases = -1;
163 static int hf_adn_family = -1;
164 static int hf_adn_addr_len = -1;
165 static int hf_adn_addr_addr = -1;
166
167
168 static int ett_lwres = -1;
169 static int ett_rdata_req = -1;
170 static int ett_rdata_resp = -1;
171 static int ett_a_rec = -1;
172 static int ett_a_rec_addr = -1;
173 static int ett_srv_rec = -1;
174 static int ett_srv_rec_item = -1;
175 static int ett_adn_request = -1;
176 static int ett_adn_resp = -1;
177 static int ett_adn_alias = -1;
178 static int ett_adn_addr = -1;
179 static int ett_nba_request = -1;
180 static int ett_nba_resp = -1;
181 static int ett_noop = -1;
182
183 static int ett_mx_rec = -1;
184 static int ett_mx_rec_item = -1;
185
186 static int ett_ns_rec = -1;
187 static int ett_ns_rec_item = -1;
188
189
190
191 #ifndef ENABLE_STATIC
192 G_MODULE_EXPORT const gchar version[] = VERSION;
193 #endif
194
195
196 #define LWRES_UDP_PORT 921
197
198 static guint global_lwres_port = LWRES_UDP_PORT;
199 static guint lwres_port = LWRES_UDP_PORT;
200
201 void proto_reg_handoff_lwres(void);
202
203
204 /* Define the lwres proto */
205 static int proto_lwres = -1;
206
207
208 /* Define many many headers for mgcp */
209
210 static const value_string message_types_values[] = {
211         { 1,          "REQUEST " },
212     { 2,          "RESPONSE" },
213     { 0 ,                       NULL },
214 };
215
216
217
218 static int
219 lwres_get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
220     char *name, int maxname)
221 {
222   int start_offset = offset;
223   char *np = name;
224   int len = -1;
225   int chars_processed = 0;
226   int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
227   int component_len;
228   int indir_offset;
229
230   const int min_len = 1;        /* Minimum length of encoded name (for root) */
231         /* If we're about to return a value (probably negative) which is less
232          * than the minimum length, we're looking at bad data and we're liable
233          * to put the dissector into a loop.  Instead we throw an exception */
234
235   maxname--;    /* reserve space for the trailing '\0' */
236   for (;;) {
237     component_len = tvb_get_guint8(tvb, offset);
238     offset++;
239     if (component_len == 0)
240       break;
241     chars_processed++;
242     switch (component_len & 0xc0) {
243
244     case 0x00:
245       /* Label */
246       if (np != name) {
247         /* Not the first component - put in a '.'. */
248         if (maxname > 0) {
249           *np++ = '.';
250           maxname--;
251         }
252       }
253       while (component_len > 0) {
254         if (maxname > 0) {
255           *np++ = tvb_get_guint8(tvb, offset);
256           maxname--;
257         }
258         component_len--;
259         offset++;
260         chars_processed++;
261       }
262       break;
263
264     case 0x40:
265       /* Extended label (RFC 2673) */
266       switch (component_len & 0x3f) {
267
268       case 0x01:
269         /* Bitstring label */
270         {
271           int bit_count;
272           int label_len;
273           int print_len;
274
275
276           bit_count = tvb_get_guint8(tvb, offset);
277           offset++;
278           label_len = (bit_count - 1) / 8 + 1;
279
280
281           if (maxname > 0) {
282             print_len = snprintf(np, maxname + 1, "\\[x");
283             if (print_len != -1) {
284               /* Some versions of snprintf return -1 if they'd truncate
285                  the output. */
286               np += print_len;
287               maxname -= print_len;
288             } else {
289               /* Nothing printed, as there's no room.
290                  Suppress all subsequent printing. */
291               maxname = 0;
292             }
293           }
294           while(label_len--) {
295             if (maxname > 0) {
296               print_len = snprintf(np, maxname + 1, "%02x",
297                 tvb_get_guint8(tvb, offset));
298               if (print_len != -1) {
299                 /* Some versions of snprintf return -1 if they'd truncate
300                  the output. */
301                 np += print_len;
302                 maxname -= print_len;
303               } else {
304                 /* Nothing printed, as there's no room.
305                    Suppress all subsequent printing. */
306                 maxname = 0;
307               }
308             }
309             offset++;
310           }
311           if (maxname > 0) {
312             print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
313             if (print_len != -1) {
314               /* Some versions of snprintf return -1 if they'd truncate
315                  the output. */
316               np += print_len;
317               maxname -= print_len;
318             } else {
319               /* Nothing printed, as there's no room.
320                  Suppress all subsequent printing. */
321               maxname = 0;
322             }
323           }
324         }
325         break;
326
327       default:
328         strcpy(name, "<Unknown extended label>");
329         /* Parsing will propably fail from here on, since the */
330         /* label length is unknown... */
331         len = offset - start_offset;
332         if (len < min_len)
333           THROW(ReportedBoundsError);
334         return len;
335       }
336       break;
337
338     case 0x80:
339       THROW(ReportedBoundsError);
340
341     case 0xc0:
342       /* Pointer. */
343       indir_offset = dns_data_offset +
344           (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
345       offset++;
346       chars_processed++;
347
348       /* If "len" is negative, we are still working on the original name,
349          not something pointed to by a pointer, and so we should set "len"
350          to the length of the original name. */
351       if (len < 0)
352         len = offset - start_offset;
353
354       /* If we've looked at every character in the message, this pointer
355          will make us look at some character again, which means we're
356          looping. */
357       if (chars_processed >= data_size) {
358         strcpy(name, "<Name contains a pointer that loops>");
359         if (len < min_len)
360           THROW(ReportedBoundsError);
361         return len;
362       }
363
364       offset = indir_offset;
365       break;    /* now continue processing from there */
366     }
367   }
368
369   *np = '\0';
370   /* If "len" is negative, we haven't seen a pointer, and thus haven't
371      set the length, so set it. */
372   if (len < 0)
373     len = offset - start_offset;
374   /* Zero-length name means "root server" */
375   if (*name == '\0')
376     strcpy(name, "<Root>");
377   if (len < min_len)
378     THROW(ReportedBoundsError);
379   return len;
380 }
381
382
383 static void dissect_getnamebyaddr_request(tvbuff_t* tvb, proto_tree* lwres_tree)
384 {
385         guint32 flags,family;
386         guint16 addrlen, slen;
387         const gchar* addr;
388
389         proto_item* nba_request_item;
390         proto_tree* nba_request_tree;
391
392         flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
393         family = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
394         addrlen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
395         addr = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH + 10, 4);
396         slen = strlen((char*)ip_to_str(addr));
397
398         if(lwres_tree)
399         {
400                 nba_request_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,LWRES_LWPACKET_LENGTH+14,"getnamebyaddr parameters");
401                 nba_request_tree = proto_item_add_subtree(nba_request_item, ett_nba_request);
402         }
403         else return;
404
405                 proto_tree_add_uint(nba_request_tree,
406                                                                 hf_adn_flags,
407                                                                 tvb,
408                                                                 LWRES_LWPACKET_LENGTH,
409                                                                 4,
410                                                                 flags);
411
412                 proto_tree_add_uint(nba_request_tree,
413                                                                 hf_adn_family,
414                                                                 tvb,
415                                                                 LWRES_LWPACKET_LENGTH + 4,
416                                                                 4,
417                                                                 family);
418
419                 proto_tree_add_uint(nba_request_tree,
420                                                                 hf_adn_addr_len,
421                                                                 tvb,
422                                                                 LWRES_LWPACKET_LENGTH + 8,
423                                                                 2,
424                                                                 addrlen);
425
426                 proto_tree_add_string(nba_request_tree,
427                                                                 hf_adn_addr_addr,
428                                                                 tvb,
429                                                                 LWRES_LWPACKET_LENGTH + 10,
430                                                                 slen,
431                                                                 ip_to_str(addr));
432
433 }
434
435 static void dissect_getnamebyaddr_response(tvbuff_t* tvb, proto_tree* lwres_tree)
436 {
437         guint32 flags,i, offset;
438         guint16 naliases,realnamelen,aliaslen;
439         char aliasname[120];
440         char realname[120];
441         
442
443         proto_item* nba_resp_item;
444         proto_tree* nba_resp_tree;
445
446         proto_item* alias_item;
447         proto_tree* alias_tree;
448
449         if(lwres_tree)
450         {
451                 nba_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10,"getnamebyaddr records");
452                 nba_resp_tree = proto_item_add_subtree(nba_resp_item, ett_nba_resp);
453         }
454         else return;
455
456         flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
457         naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
458         realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH + 4 + 2);
459         tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 4 + 2 + 2, realnamelen, realname);
460         realname[realnamelen]='\0';
461
462         proto_tree_add_uint(nba_resp_tree,
463                                                 hf_adn_flags,
464                                                 tvb,
465                                                 LWRES_LWPACKET_LENGTH,
466                                                 4,
467                                                 flags);
468         proto_tree_add_uint(nba_resp_tree,
469                                                 hf_adn_naliases,
470                                                 tvb,
471                                                 LWRES_LWPACKET_LENGTH + 4,
472                                                 2,
473                                                 naliases);
474
475         proto_tree_add_uint(nba_resp_tree,
476                                                 hf_adn_namelen,
477                                                 tvb,
478                                                 LWRES_LWPACKET_LENGTH + 6,
479                                                 2, 
480                                                 realnamelen);
481
482         proto_tree_add_string(nba_resp_tree,
483                                                   hf_adn_realname,
484                                                   tvb,
485                                                   LWRES_LWPACKET_LENGTH + 8,
486                                                   realnamelen,
487                                                   realname);
488
489         offset=LWRES_LWPACKET_LENGTH + 8 + realnamelen;
490
491         if(naliases)
492         {
493                 for(i=0; i<naliases; i++)
494                 {
495                         aliaslen = tvb_get_ntohs(tvb, offset);
496                         tvb_get_nstringz(tvb, offset + 2, aliaslen, aliasname);
497                         aliasname[aliaslen]='\0';
498
499                         alias_item = proto_tree_add_text(nba_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
500                         alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
501
502                         proto_tree_add_uint(alias_tree,
503                                                                 hf_adn_namelen,
504                                                                 tvb,
505                                                                 offset,
506                                                                 2,
507                                                                 aliaslen);
508
509                         proto_tree_add_string(alias_tree,
510                                                                 hf_adn_aliasname,
511                                                                 tvb,
512                                                                 offset + 2,
513                                                                 aliaslen,
514                                                                 aliasname);
515
516                         offset+=(2 + aliaslen + 1);
517                 }
518         }
519 }
520
521 static void dissect_getaddrsbyname_request(tvbuff_t* tvb, proto_tree* lwres_tree)
522 {
523         guint32 flags,addrtype;
524         guint16 namelen;
525         guint8  name[120];
526
527         proto_item* adn_request_item;
528         proto_tree* adn_request_tree;
529         
530         flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
531         addrtype = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
532         namelen  = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
533         tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
534         name[namelen]='\0';
535
536         if(lwres_tree)
537         {
538                 adn_request_item = proto_tree_add_text(lwres_tree,tvb,
539                                                 LWRES_LWPACKET_LENGTH,10+namelen+1,
540                                                 "getaddrbyname parameters");
541                 adn_request_tree = proto_item_add_subtree(adn_request_item, ett_adn_request);
542         }
543         else
544                 return;
545
546
547         proto_tree_add_uint(adn_request_tree,
548                                 hf_adn_flags,
549                                 tvb,
550                                 LWRES_LWPACKET_LENGTH+0,
551                                 sizeof(guint32),
552                                 flags);
553
554         proto_tree_add_uint(adn_request_tree,
555                                 hf_adn_addrtype,
556                                 tvb,
557                                 LWRES_LWPACKET_LENGTH+4,
558                                 sizeof(guint32),
559                                 addrtype);
560
561         proto_tree_add_uint(adn_request_tree,
562                                 hf_adn_namelen,
563                                 tvb,
564                                 LWRES_LWPACKET_LENGTH+8,
565                                 sizeof(guint16),
566                                 namelen);
567
568         proto_tree_add_string(adn_request_tree,
569                                 hf_adn_name,
570                                 tvb,
571                                 LWRES_LWPACKET_LENGTH+10,
572                                 namelen,
573                                 name);
574         
575 }
576
577
578 static void dissect_getaddrsbyname_response(tvbuff_t* tvb, proto_tree* lwres_tree)
579 {
580         guint32 flags, family ,i, offset;
581         guint16 naliases, naddrs, realnamelen, length, aliaslen;
582         const gchar* addr;
583         guint slen;
584         char realname[120];
585         char aliasname[120];
586
587         proto_item* adn_resp_item;
588         proto_tree* adn_resp_tree;
589         proto_item* alias_item;
590         proto_tree* alias_tree;
591         proto_item* addr_item;
592         proto_tree* addr_tree;
593
594         
595
596         if(lwres_tree)
597         {
598                 adn_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "getaddrbyname records");
599                 adn_resp_tree = proto_item_add_subtree(adn_resp_item, ett_adn_resp);
600         }
601         else return;
602
603         flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
604         naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
605         naddrs   = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 6);
606         realnamelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
607         tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 10, realnamelen, realname);
608         realname[realnamelen]='\0';
609
610         
611         proto_tree_add_uint(adn_resp_tree,
612                                                 hf_adn_flags,
613                                                 tvb, 
614                                                 LWRES_LWPACKET_LENGTH,
615                                                 4,
616                                                 flags);
617
618         proto_tree_add_uint(adn_resp_tree,
619                                                 hf_adn_naliases,
620                                                 tvb, 
621                                                 LWRES_LWPACKET_LENGTH + 4,
622                                                 2,
623                                                 naliases);
624
625         proto_tree_add_uint(adn_resp_tree,
626                                                 hf_adn_naddrs,
627                                                 tvb,
628                                                 LWRES_LWPACKET_LENGTH + 6,
629                                                 2,
630                                                 naddrs);
631
632         proto_tree_add_uint(adn_resp_tree,
633                                                 hf_adn_namelen,
634                                                 tvb,
635                                                 LWRES_LWPACKET_LENGTH + 8,
636                                                 2, 
637                                                 realnamelen);
638         
639         proto_tree_add_string(adn_resp_tree,
640                                                 hf_adn_realname,
641                                                 tvb,
642                                                 LWRES_LWPACKET_LENGTH + 10,
643                                                 realnamelen,
644                                                 realname);
645
646         offset = LWRES_LWPACKET_LENGTH + 10 + realnamelen + 1;
647
648         if(naliases)
649         {
650                 for(i=0; i<naliases; i++)
651                 {
652                         aliaslen = tvb_get_ntohs(tvb, offset);
653                         tvb_get_nstringz(tvb, offset + 2, aliaslen, aliasname);
654                         aliasname[aliaslen]='\0';
655
656                         alias_item = proto_tree_add_text(adn_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
657                         alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
658
659                         proto_tree_add_uint(alias_tree,
660                                                                 hf_adn_namelen,
661                                                                 tvb,
662                                                                 offset,
663                                                                 2,
664                                                                 aliaslen);
665
666                         proto_tree_add_string(alias_tree,
667                                                                 hf_adn_aliasname,
668                                                                 tvb,
669                                                                 offset + 2,
670                                                                 aliaslen,
671                                                                 aliasname);
672
673                         offset+=(2 + aliaslen + 1);
674                 }
675         }
676
677         if(naddrs)
678         {
679                 for(i=0; i < naddrs; i++)
680                 {
681                         family = tvb_get_ntohl(tvb, offset);
682                         length = tvb_get_ntohs(tvb, offset + 4);
683                         addr = tvb_get_ptr(tvb, offset + 6, 4);
684                         slen = strlen((char*)ip_to_str(addr));
685                 
686                         addr_item = proto_tree_add_text(adn_resp_tree,tvb, offset, 4+2+4, "Address %s",ip_to_str(addr));
687                         addr_tree = proto_item_add_subtree(addr_item, ett_adn_addr);
688
689                         proto_tree_add_uint(addr_tree, 
690                                                                 hf_adn_family,
691                                                                 tvb, 
692                                                                 offset, 
693                                                                 4,
694                                                                 family);
695
696                         proto_tree_add_uint(addr_tree,
697                                                                 hf_adn_addr_len,
698                                                                 tvb,
699                                                                 offset + 4,
700                                                                 2,
701                                                                 length);
702
703                         proto_tree_add_string(addr_tree,
704                                                                 hf_adn_addr_addr,
705                                                                 tvb,
706                                                                 offset + 6,
707                                                                 slen,
708                                                                 ip_to_str(addr));
709
710                         offset+= 4 + 2 + 4;
711                 }
712         }
713
714
715 }
716
717 static void dissect_a_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
718 {
719         guint32 i, curr;
720         const gchar* addr;
721         guint16 len;
722         proto_item* a_rec_item;
723         proto_tree* a_rec_tree;
724         proto_item* addr_item;
725         proto_tree* addr_tree;
726
727         if(tree)
728         {
729                 a_rec_item = proto_tree_add_text(tree,tvb,offset,
730                                         ((sizeof(guint32) + sizeof(guint16)) * nrec),"A records");
731
732                 a_rec_tree = proto_item_add_subtree(a_rec_item, ett_a_rec);
733         }
734         else 
735                 return;
736
737         for(i=0; i<nrec; i++)
738         {
739         
740                 curr = offset + ((sizeof(guint32)+sizeof(guint16)) * i);
741
742                 len  = tvb_get_ntohs(tvb,curr);
743                 addr = tvb_get_ptr(tvb,curr+2,4);
744
745                 if(a_rec_tree)
746                 {
747                         addr_item = proto_tree_add_text(a_rec_tree,tvb, curr, 6,"IP Address");
748                         addr_tree = proto_item_add_subtree(addr_item, ett_a_rec_addr);
749                         proto_item_set_text(addr_item,"Address %s",ip_to_str(addr));
750                 }
751                 else return;
752                 
753                 proto_tree_add_uint(addr_tree,
754                                         hf_a_rec_len,
755                                         tvb,
756                                         curr,
757                                         sizeof(guint16),
758                                         len);
759
760                 proto_tree_add_text(addr_tree, 
761                                                 tvb,
762                                                 curr + 2, 
763                                                 4, 
764                                                 "Addr: %s",
765                                                 ip_to_str(addr));
766                 
767         }
768
769 }
770
771 static void dissect_srv_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
772 {
773         guint32 i, curr;
774         guint16 len, priority, weight, port, namelen, dlen;
775         const char *cmpname;
776         guint8 dname[120];
777
778         proto_item* srv_rec_item, *rec_item;
779         proto_item* srv_rec_tree, *rec_tree;
780
781         if(tree)
782         {
783                 srv_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "SRV records");
784                 srv_rec_tree = proto_item_add_subtree(srv_rec_item, ett_srv_rec);
785                                proto_item_set_text(srv_rec_item, "SRV records (%d)", nrec);
786         }
787         else return;
788
789         curr = offset;
790
791         for(i=0; i < nrec; i++)
792         {
793                 len =      tvb_get_ntohs(tvb, curr);
794                 priority = tvb_get_ntohs(tvb, curr + 2);
795                 weight   = tvb_get_ntohs(tvb, curr + 4);
796                 port     = tvb_get_ntohs(tvb, curr + 6);
797                 namelen = len - 8;
798                 cmpname  = tvb_get_ptr(tvb, curr + 8, namelen);
799
800                 dlen = lwres_get_dns_name(tvb, curr + 8, curr, dname, sizeof(dname));
801
802                 if(srv_rec_tree)
803                 {
804                         rec_item = proto_tree_add_text(srv_rec_tree, tvb, curr, 6,"  ");
805                         rec_tree = proto_item_add_subtree(rec_item, ett_srv_rec_item);
806                         proto_item_set_text(rec_item,
807                                                 "SRV record:pri=%d,w=%d,port=%d,dname=%s",
808                                                 priority,
809                                                 weight,
810                                                 port,
811                                                 dname); 
812                 }
813                 else return;
814
815                 proto_tree_add_uint(rec_tree,
816                                                 hf_srv_prio,
817                                                 tvb,
818                                                 curr + 2,
819                                                 2,
820                                                 priority);
821
822                 proto_tree_add_uint(rec_tree,
823                                                 hf_srv_weight,
824                                                 tvb,
825                                                 curr + 4,
826                                                 2,
827                                                 weight);
828
829                 proto_tree_add_uint(rec_tree,
830                                                 hf_srv_port,
831                                                 tvb,
832                                                 curr + 6,
833                                                 2,
834                                                 port);
835
836
837                 proto_tree_add_text(rec_tree,
838                                                         tvb,
839                                                         curr + 8,
840                                                         dlen,
841                                                         "DNAME: %s", dname);
842
843                 curr+=((sizeof(short)*4) + dlen);
844                                                         
845         }
846
847 }
848
849 static void dissect_mx_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
850 {
851         
852         guint32 i, curr;
853         guint16 len, priority, dlen, namelen;
854         const char* cname;
855         guint8 dname[120];
856
857         proto_item* mx_rec_item, *rec_item;
858         proto_tree* mx_rec_tree, *rec_tree;
859         
860
861         if(tree)
862         {
863                 mx_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "MX records (%d)", nrec);
864                 mx_rec_tree = proto_item_add_subtree(mx_rec_item, ett_mx_rec);
865         }
866         else
867                 return;
868         
869         curr = offset;
870         for(i=0; i < nrec; i++)
871         {
872                 len =           tvb_get_ntohs(tvb, curr);
873                 priority =  tvb_get_ntohs(tvb, curr + 2);
874                 namelen  =  len - 4;
875                 cname = tvb_get_ptr(tvb, curr + 4, 4);
876                 dlen  = lwres_get_dns_name(tvb, curr + 4, curr, dname, sizeof(dname));
877                 if(mx_rec_tree)
878                 {
879                         rec_item = proto_tree_add_text(mx_rec_tree, tvb, curr,6,"MX record: pri=%d,dname=%s",
880                                                 priority,dname);
881                         rec_tree = proto_item_add_subtree(rec_item, ett_mx_rec_item);
882                 }
883                 else 
884                         return;
885
886                 
887                 proto_tree_add_uint(rec_tree,
888                                                         hf_srv_prio,
889                                                         tvb,
890                                                         curr + 2,
891                                                         2,
892                                                         priority);
893         
894                 proto_tree_add_text(rec_tree,
895                                                         tvb,
896                                                         curr + 4,
897                                                         dlen,
898                                                         "name: %s", dname);
899
900                 curr+=((sizeof(short)*2) + dlen);
901         
902
903         }
904         
905 }
906
907 static void dissect_ns_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
908 {
909         guint32 i, curr;
910         guint16 len, dlen, namelen;
911         guint8 dname[120];
912
913         proto_item* ns_rec_item, *rec_item;
914         proto_tree* ns_rec_tree, *rec_tree;
915         
916         if(tree)
917         {
918                 ns_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "NS record (%d)", nrec);
919                 ns_rec_tree = proto_item_add_subtree(ns_rec_item, ett_ns_rec);
920         }
921         else
922                 return;
923         curr=offset;
924
925         for(i=0;i<nrec;i++)
926         {
927                 len = tvb_get_ntohs(tvb, curr);
928                 namelen = len - 2;
929                 dlen = lwres_get_dns_name(tvb, curr + 2, curr, dname, sizeof(dname));
930                 if(ns_rec_tree)
931                 {
932                         rec_item = proto_tree_add_text(ns_rec_tree, tvb, curr,4, "NS record: dname=%s",dname);
933                         rec_tree = proto_item_add_subtree(rec_item, ett_ns_rec_item);
934                 }
935                 else
936                         return;
937
938                 proto_tree_add_text(rec_tree,
939                                                         tvb,
940                                                         curr + 2,
941                                                         dlen,
942                                                         "Name: %s", dname);
943                 curr+=(sizeof(short) + dlen);
944                                                         
945         }
946         
947
948 }
949
950 static void dissect_rdata_request(tvbuff_t* tvb, proto_tree* lwres_tree)
951 {
952         guint32 rflags;
953         guint16 rdclass, rdtype, namelen;
954         guint8 name[120];
955
956         proto_item* rdata_request_item;
957         proto_tree* rdata_request_tree;
958
959         rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
960         rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
961         rdtype =  tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
962         namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+8);
963         tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
964         name[namelen]='\0';
965
966         if(lwres_tree)
967         {
968                 rdata_request_item = 
969                         proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,10+namelen+1,"RDATA request parameters");
970                 rdata_request_tree = proto_item_add_subtree(rdata_request_item, ett_rdata_req);
971         }
972         else 
973                 return;
974
975         proto_tree_add_uint(rdata_request_tree,
976                         hf_rflags,
977                         tvb,
978                         LWRES_LWPACKET_LENGTH+0,
979                         sizeof(guint32),
980                         rflags);
981
982         proto_tree_add_uint(rdata_request_tree,
983                         hf_rdclass,
984                         tvb,
985                         LWRES_LWPACKET_LENGTH+4,
986                         sizeof(guint16),
987                         rdclass);
988
989         proto_tree_add_uint(rdata_request_tree,
990                         hf_rdtype,
991                         tvb,
992                         LWRES_LWPACKET_LENGTH+6,
993                         sizeof(guint16),
994                         rdtype);
995
996         proto_tree_add_uint(rdata_request_tree,
997                         hf_namelen,
998                         tvb,
999                         LWRES_LWPACKET_LENGTH+8,
1000                         sizeof(guint16),
1001                         namelen);
1002
1003         proto_tree_add_string(rdata_request_tree,
1004                         hf_req_name,
1005                         tvb,
1006                         LWRES_LWPACKET_LENGTH+10,
1007                         namelen,
1008                         name);
1009
1010 }
1011
1012 static void dissect_rdata_response(tvbuff_t* tvb, proto_tree* lwres_tree)
1013 {
1014         guint32 rflags, ttl, offset;
1015         guint16 rdclass, rdtype, nrdatas, nsigs, realnamelen;
1016         guint8 realname[120];
1017
1018         proto_item* rdata_resp_item;
1019         proto_tree* rdata_resp_tree;
1020
1021         rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
1022         rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
1023         rdtype =  tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
1024         ttl    =  tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+8);
1025         nrdatas = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+12);
1026         nsigs   = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+14);
1027         realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH+16);
1028         tvb_get_nstringz(tvb,LWRES_LWPACKET_LENGTH+18,realnamelen, realname);
1029         realname[realnamelen]='\0';
1030
1031         offset = LWRES_LWPACKET_LENGTH + 18 + realnamelen + 1;
1032
1033         if(lwres_tree)
1034         {
1035                 rdata_resp_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH, 18+realnamelen+1,"RDATA response");
1036                 rdata_resp_tree = proto_item_add_subtree(rdata_resp_item, ett_rdata_resp);
1037         }
1038         else
1039                 return;
1040
1041         proto_tree_add_uint(rdata_resp_tree,
1042                         hf_rflags,
1043                         tvb,
1044                         LWRES_LWPACKET_LENGTH+0,
1045                         sizeof(guint32),
1046                         rflags);
1047
1048         proto_tree_add_uint(rdata_resp_tree,
1049                         hf_rdclass,
1050                         tvb,
1051                         LWRES_LWPACKET_LENGTH+4,
1052                         sizeof(guint16),
1053                         rdclass);
1054
1055         proto_tree_add_uint(rdata_resp_tree,
1056                         hf_rdtype,
1057                         tvb,
1058                         LWRES_LWPACKET_LENGTH+6,
1059                         sizeof(guint16),
1060                         rdtype);
1061
1062         proto_tree_add_uint(rdata_resp_tree,
1063                         hf_ttl,
1064                         tvb,
1065                         LWRES_LWPACKET_LENGTH+8,
1066                         sizeof(guint32),
1067                         ttl);
1068
1069         proto_tree_add_uint(rdata_resp_tree,
1070                         hf_nrdatas,
1071                         tvb,
1072                         LWRES_LWPACKET_LENGTH+12,
1073                         sizeof(guint16),
1074                         nrdatas);
1075
1076         proto_tree_add_uint(rdata_resp_tree,
1077                         hf_nsigs,
1078                         tvb,
1079                         LWRES_LWPACKET_LENGTH+14,
1080                         sizeof(guint16),
1081                         nsigs);
1082
1083         proto_tree_add_uint(rdata_resp_tree,
1084                         hf_realnamelen,
1085                         tvb,
1086                         LWRES_LWPACKET_LENGTH+16,
1087                         sizeof(guint16),
1088                         realnamelen);
1089
1090         proto_tree_add_string(rdata_resp_tree,
1091                         hf_realname,
1092                         tvb,
1093                         LWRES_LWPACKET_LENGTH+18,
1094                         realnamelen,
1095                         realname);
1096
1097         switch(rdtype)
1098         {
1099                 case T_A:
1100                         dissect_a_records(tvb,rdata_resp_tree,nrdatas,offset);
1101                 break;
1102
1103                 case T_SRV:
1104                         dissect_srv_records(tvb,rdata_resp_tree,nrdatas, offset);
1105                 break;
1106
1107                 case T_MX:
1108                         dissect_mx_records(tvb,rdata_resp_tree,nrdatas, offset);
1109                 break;
1110
1111                 case T_NS:
1112                         dissect_ns_records(tvb,rdata_resp_tree,nrdatas, offset);
1113                 break;
1114         }
1115
1116 }
1117
1118 static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
1119 {
1120         guint16 datalen;
1121         const char* data;
1122
1123         proto_item* noop_item;
1124         proto_tree* noop_tree;
1125
1126         datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);
1127         data = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH, datalen);
1128         
1129         if(lwres_tree)
1130         {
1131                 noop_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "Noop record");
1132                 noop_tree = proto_item_add_subtree(noop_item, ett_noop);
1133         }
1134         else
1135                 return;
1136
1137         proto_tree_add_uint(noop_tree,
1138                                                 hf_length,
1139                                                 tvb,
1140                                                 LWRES_LWPACKET_LENGTH,
1141                                                 sizeof(guint16),
1142                                                 datalen);
1143
1144 }
1145
1146 static void dissect_getaddrsbyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1147 {
1148         if(type == 1)
1149                 dissect_getaddrsbyname_request(tvb, lwres_tree);
1150         else
1151                 dissect_getaddrsbyname_response(tvb, lwres_tree);
1152 }
1153
1154 static void dissect_getnamebyaddr(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1155 {
1156         if(type == 1)
1157                 dissect_getnamebyaddr_request(tvb, lwres_tree);
1158         else
1159                 dissect_getnamebyaddr_response(tvb, lwres_tree);
1160 }
1161
1162 static void dissect_getrdatabyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1163 {
1164         if(type == 1) 
1165                 dissect_rdata_request(tvb, lwres_tree);
1166         else            
1167                 dissect_rdata_response(tvb, lwres_tree);
1168 }
1169
1170 static void
1171 dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1172 {
1173         guint16 version, flags, authtype, authlength ;
1174         guint32 length, opcode, result, recvlength, serial;
1175         guint32 message_type;
1176
1177         proto_item* lwres_item;
1178         proto_tree* lwres_tree;
1179
1180         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1181                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res");
1182         length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET);
1183         version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET);
1184         flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET);
1185         serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET);
1186         opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET);
1187         result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET);
1188         recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET);
1189         authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET);
1190         authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET);
1191
1192         message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1;
1193
1194         if (check_col(pinfo->cinfo, COL_INFO)) {
1195                 col_clear(pinfo->cinfo, COL_INFO);
1196
1197                 if(flags & LWRES_LWPACKETFLAG_RESPONSE)
1198                 {
1199                         col_add_fstr(pinfo->cinfo, COL_INFO,
1200                         "%s, opcode=%s, serial=0x%x, result=%s",
1201                                 val_to_str((guint32)message_type,message_types_values,"unknown"),
1202                                 val_to_str(opcode, opcode_values, "unknown"),
1203                                                 serial,
1204                                                 val_to_str(result,result_values,"unknown"));
1205                 }
1206                 else
1207                 {
1208                         col_add_fstr(pinfo->cinfo, COL_INFO,
1209                                 "%s, opcode=%s, serial=0x%x",
1210                                 val_to_str((guint32)message_type,message_types_values,"unknown"),
1211                                                 val_to_str(opcode, opcode_values, "unknown"),
1212                                 serial);
1213                 }
1214         }
1215
1216         if(tree)
1217         {
1218                 lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, FALSE);
1219                 lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres);
1220         }
1221         else return;
1222
1223
1224         proto_tree_add_uint(lwres_tree,
1225                         hf_length,
1226                         tvb,
1227                         LW_LENGTH_OFFSET,
1228                         sizeof(guint32),
1229                         length);
1230
1231
1232         proto_tree_add_uint(lwres_tree,
1233                                 hf_version,
1234                                 tvb,
1235                                 LW_VERSION_OFFSET,
1236                                 sizeof(guint16),
1237                                 version);
1238                 
1239
1240
1241
1242         proto_tree_add_uint(lwres_tree,
1243                                 hf_flags,
1244                                 tvb,
1245                                 LW_PKTFLASG_OFFSET,
1246                                 sizeof(guint16),
1247                                 flags);
1248
1249         proto_tree_add_uint(lwres_tree,
1250                                 hf_serial,
1251                                 tvb,
1252                                 LW_SERIAL_OFFSET,
1253                                 sizeof(guint32),
1254                                 serial);
1255
1256         proto_tree_add_uint(lwres_tree,
1257                                 hf_opcode,
1258                                 tvb,
1259                                 LW_OPCODE_OFFSET,
1260                                 sizeof(guint32),
1261                                 opcode);
1262
1263         proto_tree_add_uint(lwres_tree,
1264                                 hf_result,
1265                                 tvb,
1266                                 LW_RESULT_OFFSET,
1267                                 sizeof(guint32),
1268                                 result);
1269
1270         proto_tree_add_uint(lwres_tree,
1271                                 hf_recvlen,
1272                                 tvb,
1273                                 LW_RECVLEN_OFFSET,
1274                                 sizeof(guint32),
1275                                 recvlength);
1276
1277         proto_tree_add_uint(lwres_tree,
1278                                 hf_authtype,
1279                                 tvb,
1280                                 LW_AUTHTYPE_OFFSET,
1281                                 sizeof(guint16),
1282                                 authtype);
1283
1284         proto_tree_add_uint(lwres_tree,
1285                                 hf_authlen,
1286                                 tvb,
1287                                 LW_AUTHLEN_OFFSET,
1288                                 sizeof(guint16),
1289                                 authlength);
1290
1291         if(!result)
1292         {
1293                 switch(opcode)
1294                 {
1295                         case LWRES_OPCODE_NOOP:
1296                                 dissect_noop(tvb, lwres_tree);
1297                         break;
1298
1299                         case LWRES_OPCODE_GETADDRSBYNAME:
1300                                 dissect_getaddrsbyname(tvb, lwres_tree, message_type);
1301                         break;
1302
1303                         case LWRES_OPCODE_GETNAMEBYADDR:
1304                                 dissect_getnamebyaddr(tvb, lwres_tree, message_type);
1305                         break;
1306
1307                         case LWRES_OPCODE_GETRDATABYNAME:
1308                                 dissect_getrdatabyname(tvb, lwres_tree, message_type);
1309                         break;
1310                 }
1311         }
1312
1313 }
1314
1315
1316 void
1317 proto_register_lwres(void)
1318 {
1319   static hf_register_info hf[] = {
1320     { &hf_length,
1321       { "Length", "lwres.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1322         "lwres length", HFILL }},
1323
1324     { &hf_version,
1325       { "Version", "lwres.version", FT_UINT16, BASE_DEC, NULL, 0x0,
1326         "lwres legth", HFILL }},
1327
1328     { &hf_flags,
1329       { "Packet Flags", "lwres.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1330         "lwres flags", HFILL }},
1331
1332     { &hf_serial,
1333       { "Serial", "lwres.serial", FT_UINT32, BASE_HEX, NULL, 0x0,
1334         "lwres serial", HFILL }},
1335
1336     { &hf_opcode,
1337       { "Operation code", "lwres.opcode", FT_UINT32, BASE_DEC, VALS(opcode_values), 0x0,
1338         "lwres opcode", HFILL }},
1339
1340     { &hf_result,
1341       { "Result", "lwres.result", FT_UINT32, BASE_DEC, VALS(result_values), 0x0,
1342         "lwres result", HFILL }},
1343
1344     { &hf_recvlen, 
1345       { "Received length", "lwres.recvlen", FT_UINT32, BASE_DEC, NULL, 0x0,
1346         "lwres recvlen", HFILL }},
1347
1348     { &hf_authtype,
1349       { "Auth. type", "lwres.authtype", FT_UINT16, BASE_DEC, NULL, 0x0,
1350         "lwres authtype", HFILL }},
1351
1352     { &hf_authlen,
1353       { "Auth. length", "lwres.authlen" , FT_UINT16, BASE_DEC, NULL, 0x0,
1354         "lwres authlen", HFILL }},
1355
1356     { &hf_rflags, 
1357       { "Flags", "lwres.rflags", FT_UINT32, BASE_HEX, NULL, 0x0,
1358         "lwres rflags", HFILL }},
1359     { &hf_rdclass,
1360       { "Class", "lwres.class", FT_UINT16, BASE_DEC, NULL, 0x0,
1361         "lwres class", HFILL }},
1362
1363     { &hf_rdtype,
1364       { "Type", "lwres.type", FT_UINT16, BASE_DEC, VALS(t_types), 0x0,
1365         "lwres type" , HFILL }},
1366
1367     { &hf_namelen,
1368       { "Name length", "lwres.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1369         "lwres namelen", HFILL }},
1370
1371     { &hf_req_name,
1372       { "Domain name" , "lwres.reqdname" , FT_STRING, BASE_DEC, NULL, 0x0,
1373         "lwres reqdname", HFILL }},
1374
1375     { &hf_ttl,
1376       { "Time To Live", "lwres.ttl", FT_UINT32, BASE_DEC, NULL, 0x0, 
1377         "lwres ttl", HFILL }},
1378
1379     { &hf_nrdatas,
1380       { "Number of rdata records", "lwres.nrdatas", FT_UINT16, BASE_DEC, NULL, 0x0,
1381         "lwres nrdatas" , HFILL }},
1382    
1383     { &hf_nsigs,
1384       { "Number of signature records", "lwres.nsigs", FT_UINT16, BASE_DEC, NULL, 0x0,
1385         "lwres nsigs" , HFILL }},
1386
1387     { &hf_realnamelen,
1388       { "Real name length", "lwres.realnamelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1389         "lwres realnamelen", HFILL }},
1390
1391     { &hf_realname,
1392       { "Real doname name", "lwres.realname", FT_STRING, BASE_DEC, NULL, 0x0,
1393         "lwres realname", HFILL }},
1394
1395         { &hf_a_record,
1396         { "IPv4 Address", "lwres.arecord", FT_UINT32, BASE_DEC, NULL, 0x0,
1397           "lwres arecord", HFILL }},
1398
1399         { &hf_a_rec_len,
1400         { "Length", "lwres.areclen", FT_UINT16, BASE_DEC, NULL, 0x0,
1401         "lwres areclen", HFILL }},
1402
1403         { &hf_srv_prio,
1404         { "Priority", "lwres.srv.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
1405            "lwres srv prio", HFILL }},
1406
1407         { &hf_srv_weight,
1408         { "Weight", "lwres.srv.weight", FT_UINT16, BASE_DEC, NULL, 0x0,
1409         "lwres srv weight", HFILL }},
1410
1411         { &hf_srv_port,
1412         { "Port" , "lwres.srv.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1413         "lwres srv port", HFILL }},
1414
1415         { &hf_adn_flags,
1416         { "Flags", "lwres.adn.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
1417           "lwres adn flags", HFILL }},
1418
1419         { &hf_adn_addrtype,
1420         { "Address type", "lwres.adn.addrtype", FT_UINT32, BASE_DEC, NULL, 0x0,
1421           "lwres adn addrtype", HFILL }},
1422
1423         { &hf_adn_namelen,
1424         { "Name length", "lwres.adn.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1425           "lwres adn namelen", HFILL }},
1426
1427         { &hf_adn_name,
1428         { "Name", "lwres.adn.name", FT_STRING, BASE_DEC, NULL, 0x0,
1429           "lwres adn name", HFILL }}, 
1430
1431          { &hf_adn_naliases,
1432         { "Number of aliases", "lwres.adn.naliases", FT_UINT16, BASE_DEC, NULL, 0x0,
1433           "lwres adn naliases", HFILL }}, 
1434
1435           { &hf_adn_naddrs,
1436         { "Number of addresses", "lwres.adn.naddrs", FT_UINT16, BASE_DEC, NULL, 0x0,
1437           "lwres adn naddrs", HFILL }}, 
1438
1439                 { &hf_adn_realname,
1440         { "Real name", "lwres.adn.realname", FT_STRING, BASE_DEC, NULL, 0x0,
1441           "lwres adn realname", HFILL }}, 
1442
1443                 { &hf_adn_aliasname,
1444         { "Alias name", "lwres.adn.aliasname", FT_STRING, BASE_DEC, NULL, 0x0,
1445           "lwres adn aliasname", HFILL }}, 
1446
1447         { &hf_adn_family,
1448         { "Address family", "lwres.adn.addr.family", FT_UINT32, BASE_DEC, NULL, 0x0,
1449         "lwres adn addr family", HFILL }},
1450
1451         { &hf_adn_addr_len,
1452         { "Address length", "lwres.adn.addr.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1453         "lwres adn addr length", HFILL }},
1454
1455         { &hf_adn_addr_addr,
1456     { "IP Address", "lwres.adn.addr.addr", FT_STRING, BASE_DEC, NULL, 0x0,
1457           "lwres adn addr addr", HFILL }},
1458
1459     /* Add more fields here */
1460   };
1461
1462   static gint *ett[] = {
1463     &ett_lwres,
1464     &ett_rdata_req,
1465     &ett_rdata_resp,
1466         &ett_a_rec,
1467         &ett_a_rec_addr,
1468         &ett_srv_rec,
1469         &ett_srv_rec_item,
1470         &ett_adn_request,
1471         &ett_adn_resp,
1472         &ett_adn_alias,
1473         &ett_adn_addr,
1474         &ett_nba_request,
1475         &ett_nba_resp,
1476         &ett_mx_rec,
1477         &ett_mx_rec_item,
1478         &ett_ns_rec,
1479         &ett_ns_rec_item,
1480         &ett_noop,
1481   };
1482
1483
1484   module_t *lwres_module;
1485
1486   proto_lwres = proto_register_protocol("Light Weight DNS RESolver (BIND9)",
1487                                        "LWRES", "lwres");
1488
1489   proto_register_field_array(proto_lwres, hf, array_length(hf));
1490   proto_register_subtree_array(ett, array_length(ett));
1491
1492   lwres_module = prefs_register_protocol(proto_lwres, proto_reg_handoff_lwres);
1493
1494   prefs_register_uint_preference(lwres_module, "udp.lwres_port",
1495                                  "lwres listener UDP Port",
1496                                  "Set the UDP port for lwres daemon"
1497                                  "(if other than the default of 921)",
1498                                  10, &global_lwres_port);
1499
1500 }
1501
1502 /* The registration hand-off routine */
1503 void
1504 proto_reg_handoff_lwres(void)
1505 {
1506   static int lwres_prefs_initialized = FALSE;
1507   static dissector_handle_t lwres_handle;
1508
1509   if(!lwres_prefs_initialized) {
1510                 lwres_handle = create_dissector_handle(dissect_lwres, proto_lwres);
1511                 lwres_prefs_initialized = TRUE;
1512         }
1513         else {
1514                 dissector_delete("udp.port",global_lwres_port, lwres_handle);
1515
1516         }
1517
1518         lwres_port = global_lwres_port;
1519
1520   dissector_add("udp.port", lwres_port, lwres_handle);
1521
1522 }
1523
1524 /* Start the functions we need for the plugin stuff */
1525
1526 #ifndef ENABLE_STATIC
1527
1528 G_MODULE_EXPORT void
1529 plugin_reg_handoff(void){
1530   proto_reg_handoff_lwres();
1531 }
1532
1533 G_MODULE_EXPORT void
1534 plugin_init(plugin_address_table_t *pat
1535 #ifndef PLUGINS_NEED_ADDRESS_TABLE
1536 _U_
1537 #endif
1538 ){
1539   /* initialise the table of pointers needed in Win32 DLLs */
1540   plugin_address_table_init(pat);
1541   /* register the new protocol, protocol fields, and subtrees */
1542   if (proto_lwres == -1) { /* execute protocol initialization only once */
1543     proto_register_lwres();
1544   }
1545 }
1546
1547 #endif
1548
1549 /* End the functions we need for plugin stuff */