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