Define some fcns & vars as static...
[metze/wireshark/wip.git] / epan / dissectors / 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  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
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 <stdlib.h>
32 #include <ctype.h>
33 #include <time.h>
34 #include <string.h>
35
36 #include <glib.h>
37 #include <epan/packet.h>
38 #include <epan/prefs.h>
39 #include "packet-dns.h"
40
41 #define LWRES_LWPACKET_LENGTH           (4 * 5 + 2 * 4)
42 #define LWRES_LWPACKETFLAG_RESPONSE     0x0001U /* if set, pkt is a response */
43 #define LWRES_LWPACKETVERSION_0         0
44
45 #define LW_LENGTH_OFFSET                0
46 #define LW_VERSION_OFFSET               4
47 #define LW_PKTFLASG_OFFSET              6
48 #define LW_SERIAL_OFFSET                8
49 #define LW_OPCODE_OFFSET                12
50 #define LW_RESULT_OFFSET                16
51 #define LW_RECVLEN_OFFSET               20
52 #define LW_AUTHTYPE_OFFSET              24
53 #define LW_AUTHLEN_OFFSET               26
54
55 #define LWRES_OPCODE_NOOP               0x00000000U
56 #define LWRES_OPCODE_GETADDRSBYNAME     0x00010001U
57 #define LWRES_OPCODE_GETNAMEBYADDR      0x00010002U
58 #define LWRES_OPCODE_GETRDATABYNAME     0x00010003U
59
60 static const value_string opcode_values[] = {
61         { LWRES_OPCODE_NOOP,                    "Noop" },
62         { LWRES_OPCODE_GETADDRSBYNAME,  "getaddrbyname" },
63         { LWRES_OPCODE_GETNAMEBYADDR,   "getnamebyaddr" },
64         { LWRES_OPCODE_GETRDATABYNAME,  "getrdatabyname" },
65         { 0, NULL },
66 };
67
68
69 #define LWRES_R_SUCCESS                 0
70 #define LWRES_R_NOMEMORY                1
71 #define LWRES_R_TIMEOUT                 2
72 #define LWRES_R_NOTFOUND                3
73 #define LWRES_R_UNEXPECTEDEND           4       /* unexpected end of input */
74 #define LWRES_R_FAILURE                 5       /* generic failure */
75 #define LWRES_R_IOERROR                 6
76 #define LWRES_R_NOTIMPLEMENTED          7
77 #define LWRES_R_UNEXPECTED              8
78 #define LWRES_R_TRAILINGDATA            9
79 #define LWRES_R_INCOMPLETE              10
80 #define LWRES_R_RETRY                   11
81 #define LWRES_R_TYPENOTFOUND            12
82 #define LWRES_R_TOOLARGE                13
83
84 #define T_A             1
85 #define T_NS    2
86 #define T_MX    15
87 #define T_SRV   33
88
89
90 static const value_string t_types[] = {
91         { T_A,          "T_A" },
92         { T_NS,         "T_NS" },
93         { T_MX,         "T_MX" },
94         { T_SRV,        "T_SRV" },
95         { 0,            NULL },
96 };
97
98
99
100
101 static const value_string result_values[]  = {
102         { LWRES_R_SUCCESS,              "Success" },
103         { LWRES_R_NOMEMORY,             "No memory" },
104         { LWRES_R_TIMEOUT,                      "Timeout" },
105         { LWRES_R_NOTFOUND,                     "Not found" },
106         { LWRES_R_UNEXPECTEDEND,        "Unexpected end of input" },
107         { LWRES_R_FAILURE,                      "Generic failure" },
108         { LWRES_R_IOERROR,                      "I/O Error" },
109         { LWRES_R_UNEXPECTED,           "Unexpected" },
110         { LWRES_R_TRAILINGDATA,         "Trailing data" },
111         { LWRES_R_INCOMPLETE,           "Incomplete" },
112         { LWRES_R_RETRY,                        "Retry" },
113         { LWRES_R_TYPENOTFOUND,         "Type not found" },
114         { LWRES_R_TOOLARGE,                     "Too large" },
115         { 0,                                            NULL },
116 };
117
118 static int hf_length = -1;
119 static int hf_version = -1;
120 static int hf_flags = -1;
121 static int hf_serial = -1;
122 static int hf_opcode = -1;
123 static int hf_result = -1;
124 static int hf_recvlen = -1;
125 static int hf_authtype = -1;
126 static int hf_authlen = -1;
127
128 static int hf_rflags = -1;
129 static int hf_rdclass = -1;
130 static int hf_rdtype = -1;
131 static int hf_namelen = -1;
132 static int hf_req_name = -1;
133
134 static int hf_ttl = -1;
135 static int hf_nrdatas = -1;
136 static int hf_nsigs = -1;
137 static int hf_realnamelen = -1;
138 static int hf_realname = -1;
139
140
141 static int hf_a_record = -1;
142 static int hf_a_rec_len = -1;
143 static int hf_srv_prio = -1;
144 static int hf_srv_weight = -1;
145 static int hf_srv_port = -1;
146
147 static int hf_adn_flags = -1;
148 static int hf_adn_addrtype = -1;
149 static int hf_adn_namelen = -1;
150 static int hf_adn_name = -1;
151
152 static int hf_adn_realname = -1;
153 static int hf_adn_aliasname = -1;
154
155 static int hf_adn_naddrs = -1;
156 static int hf_adn_naliases = -1;
157 static int hf_adn_family = -1;
158 static int hf_adn_addr_len = -1;
159 static int hf_adn_addr_addr = -1;
160
161
162 static int ett_lwres = -1;
163 static int ett_rdata_req = -1;
164 static int ett_rdata_resp = -1;
165 static int ett_a_rec = -1;
166 static int ett_a_rec_addr = -1;
167 static int ett_srv_rec = -1;
168 static int ett_srv_rec_item = -1;
169 static int ett_adn_request = -1;
170 static int ett_adn_resp = -1;
171 static int ett_adn_alias = -1;
172 static int ett_adn_addr = -1;
173 static int ett_nba_request = -1;
174 static int ett_nba_resp = -1;
175 static int ett_noop = -1;
176
177 static int ett_mx_rec = -1;
178 static int ett_mx_rec_item = -1;
179
180 static int ett_ns_rec = -1;
181 static int ett_ns_rec_item = -1;
182
183
184
185 #define LWRES_UDP_PORT 921
186
187 static guint global_lwres_port = LWRES_UDP_PORT;
188
189 void proto_reg_handoff_lwres(void);
190
191
192 /* Define the lwres proto */
193 static int proto_lwres = -1;
194
195
196 /* Define many many headers for mgcp */
197
198 static const value_string message_types_values[] = {
199     { 1,          "REQUEST " },
200     { 2,          "RESPONSE" },
201     { 0 ,                       NULL },
202 };
203
204 static void dissect_getnamebyaddr_request(tvbuff_t* tvb, proto_tree* lwres_tree)
205 {
206         guint32 flags,family;
207         guint16 addrlen, slen;
208         const guint8* addr;
209
210         proto_item* nba_request_item;
211         proto_tree* nba_request_tree;
212
213         flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
214         family = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
215         addrlen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
216         addr = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH + 10, 4);
217         slen = (int)strlen(ip_to_str(addr));
218
219         if(lwres_tree)
220         {
221                 nba_request_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,LWRES_LWPACKET_LENGTH+14,"getnamebyaddr parameters");
222                 nba_request_tree = proto_item_add_subtree(nba_request_item, ett_nba_request);
223         }
224         else return;
225
226                 proto_tree_add_uint(nba_request_tree,
227                                                                 hf_adn_flags,
228                                                                 tvb,
229                                                                 LWRES_LWPACKET_LENGTH,
230                                                                 4,
231                                                                 flags);
232
233                 proto_tree_add_uint(nba_request_tree,
234                                                                 hf_adn_family,
235                                                                 tvb,
236                                                                 LWRES_LWPACKET_LENGTH + 4,
237                                                                 4,
238                                                                 family);
239
240                 proto_tree_add_uint(nba_request_tree,
241                                                                 hf_adn_addr_len,
242                                                                 tvb,
243                                                                 LWRES_LWPACKET_LENGTH + 8,
244                                                                 2,
245                                                                 addrlen);
246
247                 proto_tree_add_string(nba_request_tree,
248                                                                 hf_adn_addr_addr,
249                                                                 tvb,
250                                                                 LWRES_LWPACKET_LENGTH + 10,
251                                                                 slen,
252                                                                 ip_to_str(addr));
253
254 }
255
256 static void dissect_getnamebyaddr_response(tvbuff_t* tvb, proto_tree* lwres_tree)
257 {
258         guint32 i, offset;
259         guint16 naliases,realnamelen,aliaslen;
260         gchar *aliasname;
261
262
263         proto_item* nba_resp_item;
264         proto_tree* nba_resp_tree;
265
266         proto_item* alias_item;
267         proto_tree* alias_tree;
268
269         if(lwres_tree)
270         {
271                 nba_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10,"getnamebyaddr records");
272                 nba_resp_tree = proto_item_add_subtree(nba_resp_item, ett_nba_resp);
273         }
274         else return;
275
276         naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
277         realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH + 4 + 2);
278
279         proto_tree_add_item(nba_resp_tree,
280                                                 hf_adn_flags,
281                                                 tvb,
282                                                 LWRES_LWPACKET_LENGTH,
283                                                 4,
284                                                 FALSE);
285         proto_tree_add_item(nba_resp_tree,
286                                                 hf_adn_naliases,
287                                                 tvb,
288                                                 LWRES_LWPACKET_LENGTH + 4,
289                                                 2,
290                                                 FALSE);
291
292         proto_tree_add_item(nba_resp_tree,
293                                                 hf_adn_namelen,
294                                                 tvb,
295                                                 LWRES_LWPACKET_LENGTH + 6,
296                                                 2,
297                                                 FALSE);
298
299         proto_tree_add_item(nba_resp_tree,
300                                                 hf_adn_realname,
301                                                 tvb,
302                                                 LWRES_LWPACKET_LENGTH + 8,
303                                                 realnamelen,
304                                                 FALSE);
305
306         offset=LWRES_LWPACKET_LENGTH + 8 + realnamelen;
307
308         if(naliases)
309         {
310                 for(i=0; i<naliases; i++)
311                 {
312                         aliaslen = tvb_get_ntohs(tvb, offset);
313                         aliasname = tvb_get_ephemeral_string(tvb, offset + 2, aliaslen);
314
315                         alias_item = proto_tree_add_text(nba_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
316                         alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
317
318                         proto_tree_add_item(alias_tree,
319                                                                 hf_adn_namelen,
320                                                                 tvb,
321                                                                 offset,
322                                                                 2,
323                                                                 FALSE);
324
325                         proto_tree_add_item(alias_tree,
326                                                                 hf_adn_aliasname,
327                                                                 tvb,
328                                                                 offset + 2,
329                                                                 aliaslen,
330                                                                 FALSE);
331
332                         offset+=(2 + aliaslen + 1);
333                 }
334         }
335 }
336
337 static void dissect_getaddrsbyname_request(tvbuff_t* tvb, proto_tree* lwres_tree)
338 {
339         guint16 namelen;
340
341         proto_item* adn_request_item;
342         proto_tree* adn_request_tree;
343
344         namelen  = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
345
346         if(lwres_tree)
347         {
348                 adn_request_item = proto_tree_add_text(lwres_tree,tvb,
349                                                 LWRES_LWPACKET_LENGTH,10+namelen+1,
350                                                 "getaddrbyname parameters");
351                 adn_request_tree = proto_item_add_subtree(adn_request_item, ett_adn_request);
352         }
353         else
354                 return;
355
356
357         proto_tree_add_item(adn_request_tree,
358                                 hf_adn_flags,
359                                 tvb,
360                                 LWRES_LWPACKET_LENGTH+0,
361                                 sizeof(guint32),
362                                 FALSE);
363
364         proto_tree_add_item(adn_request_tree,
365                                 hf_adn_addrtype,
366                                 tvb,
367                                 LWRES_LWPACKET_LENGTH+4,
368                                 sizeof(guint32),
369                                 FALSE);
370
371         proto_tree_add_item(adn_request_tree,
372                                 hf_adn_namelen,
373                                 tvb,
374                                 LWRES_LWPACKET_LENGTH+8,
375                                 sizeof(guint16),
376                                 FALSE);
377
378         proto_tree_add_item(adn_request_tree,
379                                 hf_adn_name,
380                                 tvb,
381                                 LWRES_LWPACKET_LENGTH+10,
382                                 namelen,
383                                 FALSE);
384
385 }
386
387
388 static void dissect_getaddrsbyname_response(tvbuff_t* tvb, proto_tree* lwres_tree)
389 {
390         guint32 family ,i, offset;
391         guint16 naliases, naddrs, realnamelen, length, aliaslen;
392         const gchar* addr;
393         guint slen;
394         gchar *aliasname;
395
396         proto_item* adn_resp_item;
397         proto_tree* adn_resp_tree;
398         proto_item* alias_item;
399         proto_tree* alias_tree;
400         proto_item* addr_item;
401         proto_tree* addr_tree;
402
403
404
405         if(lwres_tree)
406         {
407                 adn_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "getaddrbyname records");
408                 adn_resp_tree = proto_item_add_subtree(adn_resp_item, ett_adn_resp);
409         }
410         else return;
411
412         naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
413         naddrs   = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 6);
414         realnamelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
415
416
417         proto_tree_add_item(adn_resp_tree,
418                                                 hf_adn_flags,
419                                                 tvb,
420                                                 LWRES_LWPACKET_LENGTH,
421                                                 4,
422                                                 FALSE);
423
424         proto_tree_add_item(adn_resp_tree,
425                                                 hf_adn_naliases,
426                                                 tvb,
427                                                 LWRES_LWPACKET_LENGTH + 4,
428                                                 2,
429                                                 FALSE);
430
431         proto_tree_add_item(adn_resp_tree,
432                                                 hf_adn_naddrs,
433                                                 tvb,
434                                                 LWRES_LWPACKET_LENGTH + 6,
435                                                 2,
436                                                 FALSE);
437
438         proto_tree_add_item(adn_resp_tree,
439                                                 hf_adn_namelen,
440                                                 tvb,
441                                                 LWRES_LWPACKET_LENGTH + 8,
442                                                 2,
443                                                 FALSE);
444
445         proto_tree_add_item(adn_resp_tree,
446                                                 hf_adn_realname,
447                                                 tvb,
448                                                 LWRES_LWPACKET_LENGTH + 10,
449                                                 realnamelen,
450                                                 FALSE);
451
452         offset = LWRES_LWPACKET_LENGTH + 10 + realnamelen + 1;
453
454         if(naliases)
455         {
456                 for(i=0; i<naliases; i++)
457                 {
458                         aliaslen = tvb_get_ntohs(tvb, offset);
459                         aliasname = tvb_get_ephemeral_string(tvb, offset + 2, aliaslen);
460
461                         alias_item = proto_tree_add_text(adn_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
462                         alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
463
464                         proto_tree_add_uint(alias_tree,
465                                                                 hf_adn_namelen,
466                                                                 tvb,
467                                                                 offset,
468                                                                 2,
469                                                                 aliaslen);
470
471                         proto_tree_add_item(alias_tree,
472                                                                 hf_adn_aliasname,
473                                                                 tvb,
474                                                                 offset + 2,
475                                                                 aliaslen,
476                                                                 FALSE);
477
478                         offset+=(2 + aliaslen + 1);
479                 }
480         }
481
482         if(naddrs)
483         {
484                 for(i=0; i < naddrs; i++)
485                 {
486                         family = tvb_get_ntohl(tvb, offset);
487                         length = tvb_get_ntohs(tvb, offset + 4);
488                         addr = (gchar*)tvb_get_ptr(tvb, offset + 6, 4);
489                         slen = (int)strlen((char*)ip_to_str((guint8*)addr));
490
491                         addr_item = proto_tree_add_text(adn_resp_tree,tvb, offset, 4+2+4, "Address %s",ip_to_str((guint8*)addr));
492                         addr_tree = proto_item_add_subtree(addr_item, ett_adn_addr);
493
494                         proto_tree_add_uint(addr_tree,
495                                                                 hf_adn_family,
496                                                                 tvb,
497                                                                 offset,
498                                                                 4,
499                                                                 family);
500
501                         proto_tree_add_uint(addr_tree,
502                                                                 hf_adn_addr_len,
503                                                                 tvb,
504                                                                 offset + 4,
505                                                                 2,
506                                                                 length);
507
508                         proto_tree_add_string(addr_tree,
509                                                                 hf_adn_addr_addr,
510                                                                 tvb,
511                                                                 offset + 6,
512                                                                 slen,
513                                                                 ip_to_str((guint8*)addr));
514
515                         offset+= 4 + 2 + 4;
516                 }
517         }
518
519
520 }
521
522 static void dissect_a_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
523 {
524         guint32 i, curr;
525         const gchar* addr;
526         guint16 len;
527         proto_item* a_rec_item;
528         proto_tree* a_rec_tree;
529         proto_item* addr_item;
530         proto_tree* addr_tree;
531
532         if(tree)
533         {
534                 a_rec_item = proto_tree_add_text(tree,tvb,offset,
535                                         ((sizeof(guint32) + sizeof(guint16)) * nrec),"A records");
536
537                 a_rec_tree = proto_item_add_subtree(a_rec_item, ett_a_rec);
538         }
539         else
540                 return;
541
542         for(i=0; i<nrec; i++)
543         {
544
545                 curr = offset + ((sizeof(guint32)+sizeof(guint16)) * i);
546
547                 len  = tvb_get_ntohs(tvb,curr);
548                 addr = (gchar*)tvb_get_ptr(tvb,curr+2,4);
549
550                 if(a_rec_tree)
551                 {
552                         addr_item = proto_tree_add_text(a_rec_tree,tvb, curr, 6,"IP Address");
553                         addr_tree = proto_item_add_subtree(addr_item, ett_a_rec_addr);
554                         proto_item_set_text(addr_item,"Address %s",ip_to_str((guint8*)addr));
555                 }
556                 else return;
557
558                 proto_tree_add_uint(addr_tree,
559                                         hf_a_rec_len,
560                                         tvb,
561                                         curr,
562                                         sizeof(guint16),
563                                         len);
564
565                 proto_tree_add_text(addr_tree,
566                                                 tvb,
567                                                 curr + 2,
568                                                 4,
569                                                 "Addr: %s",
570                                                 ip_to_str((guint8*)addr));
571
572         }
573
574 }
575
576 static void dissect_srv_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
577 {
578         guint32 i, curr;
579         guint16 len, priority, weight, port, namelen, dlen;
580         const guchar *dname;
581
582         proto_item* srv_rec_item, *rec_item;
583         proto_item* srv_rec_tree, *rec_tree;
584
585         if(tree)
586         {
587                 srv_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "SRV records");
588                 srv_rec_tree = proto_item_add_subtree(srv_rec_item, ett_srv_rec);
589                                proto_item_set_text(srv_rec_item, "SRV records (%d)", nrec);
590         }
591         else return;
592
593         curr = offset;
594
595         for(i=0; i < nrec; i++)
596         {
597                 len =      tvb_get_ntohs(tvb, curr);
598                 priority = tvb_get_ntohs(tvb, curr + 2);
599                 weight   = tvb_get_ntohs(tvb, curr + 4);
600                 port     = tvb_get_ntohs(tvb, curr + 6);
601                 namelen = len - 8;
602
603                 dlen = get_dns_name(tvb, curr + 8, 0, curr + 8, &dname);
604
605                 if(srv_rec_tree)
606                 {
607                         rec_item = proto_tree_add_text(srv_rec_tree, tvb, curr, 6,"  ");
608                         rec_tree = proto_item_add_subtree(rec_item, ett_srv_rec_item);
609                         proto_item_set_text(rec_item,
610                                                 "SRV record:pri=%d,w=%d,port=%d,dname=%s",
611                                                 priority,
612                                                 weight,
613                                                 port,
614                                                 dname);
615                 }
616                 else return;
617
618                 proto_tree_add_uint(rec_tree,
619                                                 hf_srv_prio,
620                                                 tvb,
621                                                 curr + 2,
622                                                 2,
623                                                 priority);
624
625                 proto_tree_add_uint(rec_tree,
626                                                 hf_srv_weight,
627                                                 tvb,
628                                                 curr + 4,
629                                                 2,
630                                                 weight);
631
632                 proto_tree_add_uint(rec_tree,
633                                                 hf_srv_port,
634                                                 tvb,
635                                                 curr + 6,
636                                                 2,
637                                                 port);
638
639
640                 proto_tree_add_text(rec_tree,
641                                                         tvb,
642                                                         curr + 8,
643                                                         dlen,
644                                                         "DNAME: %s", dname);
645
646                 curr+=((sizeof(short)*4) + dlen);
647
648         }
649
650 }
651
652 static void dissect_mx_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
653 {
654
655         guint i, curr;
656         guint len, priority, dlen, namelen;
657         const guchar *dname;
658
659         proto_item* mx_rec_item, *rec_item;
660         proto_tree* mx_rec_tree, *rec_tree;
661
662
663         if(tree)
664         {
665                 mx_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "MX records (%d)", nrec);
666                 mx_rec_tree = proto_item_add_subtree(mx_rec_item, ett_mx_rec);
667         }
668         else
669                 return;
670
671         curr = offset;
672         for(i=0; i < nrec; i++)
673         {
674                 len =           tvb_get_ntohs(tvb, curr);
675                 priority =  tvb_get_ntohs(tvb, curr + 2);
676                 namelen  =  len - 4;
677                 dlen  = get_dns_name(tvb, curr + 4, 0, curr + 4, &dname);
678                 if(mx_rec_tree)
679                 {
680                         rec_item = proto_tree_add_text(mx_rec_tree, tvb, curr,6,"MX record: pri=%d,dname=%s",
681                                                 priority,dname);
682                         rec_tree = proto_item_add_subtree(rec_item, ett_mx_rec_item);
683                 }
684                 else
685                         return;
686
687
688                 proto_tree_add_uint(rec_tree,
689                                                         hf_srv_prio,
690                                                         tvb,
691                                                         curr + 2,
692                                                         2,
693                                                         priority);
694
695                 proto_tree_add_text(rec_tree,
696                                                         tvb,
697                                                         curr + 4,
698                                                         dlen,
699                                                         "name: %s", dname);
700
701                 curr+=((sizeof(short)*2) + dlen);
702
703
704         }
705
706 }
707
708 static void dissect_ns_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
709 {
710         guint i, curr;
711         guint len, dlen, namelen;
712         const guchar *dname;
713
714         proto_item* ns_rec_item, *rec_item;
715         proto_tree* ns_rec_tree, *rec_tree;
716
717         if(tree)
718         {
719                 ns_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "NS record (%d)", nrec);
720                 ns_rec_tree = proto_item_add_subtree(ns_rec_item, ett_ns_rec);
721         }
722         else
723                 return;
724         curr=offset;
725
726         for(i=0;i<nrec;i++)
727         {
728                 len = tvb_get_ntohs(tvb, curr);
729                 namelen = len - 2;
730                 dlen = get_dns_name(tvb, curr + 2, 0, curr + 2, &dname);
731                 if(ns_rec_tree)
732                 {
733                         rec_item = proto_tree_add_text(ns_rec_tree, tvb, curr,4, "NS record: dname=%s",dname);
734                         rec_tree = proto_item_add_subtree(rec_item, ett_ns_rec_item);
735                 }
736                 else
737                         return;
738
739                 proto_tree_add_text(rec_tree,
740                                                         tvb,
741                                                         curr + 2,
742                                                         dlen,
743                                                         "Name: %s", dname);
744                 curr+=(sizeof(short) + dlen);
745
746         }
747
748
749 }
750
751 static void dissect_rdata_request(tvbuff_t* tvb, proto_tree* lwres_tree)
752 {
753         guint16 namelen;
754
755         proto_item* rdata_request_item;
756         proto_tree* rdata_request_tree;
757
758         namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+8);
759
760         if(lwres_tree)
761         {
762                 rdata_request_item =
763                         proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,10+namelen+1,"RDATA request parameters");
764                 rdata_request_tree = proto_item_add_subtree(rdata_request_item, ett_rdata_req);
765         }
766         else
767                 return;
768
769         proto_tree_add_item(rdata_request_tree,
770                         hf_rflags,
771                         tvb,
772                         LWRES_LWPACKET_LENGTH+0,
773                         sizeof(guint32),
774                         FALSE);
775
776         proto_tree_add_item(rdata_request_tree,
777                         hf_rdclass,
778                         tvb,
779                         LWRES_LWPACKET_LENGTH+4,
780                         sizeof(guint16),
781                         FALSE);
782
783         proto_tree_add_item(rdata_request_tree,
784                         hf_rdtype,
785                         tvb,
786                         LWRES_LWPACKET_LENGTH+6,
787                         sizeof(guint16),
788                         FALSE);
789
790         proto_tree_add_item(rdata_request_tree,
791                         hf_namelen,
792                         tvb,
793                         LWRES_LWPACKET_LENGTH+8,
794                         sizeof(guint16),
795                         FALSE);
796
797         proto_tree_add_item(rdata_request_tree,
798                         hf_req_name,
799                         tvb,
800                         LWRES_LWPACKET_LENGTH+10,
801                         namelen,
802                         FALSE);
803
804 }
805
806 static void dissect_rdata_response(tvbuff_t* tvb, proto_tree* lwres_tree)
807 {
808         guint offset;
809         guint rdtype, nrdatas, realnamelen;
810
811         proto_item* rdata_resp_item;
812         proto_tree* rdata_resp_tree;
813
814         rdtype =  tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
815         nrdatas = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+12);
816         realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH+16);
817
818         offset = LWRES_LWPACKET_LENGTH + 18 + realnamelen + 1;
819
820         if(lwres_tree)
821         {
822                 rdata_resp_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH, 18+realnamelen+1,"RDATA response");
823                 rdata_resp_tree = proto_item_add_subtree(rdata_resp_item, ett_rdata_resp);
824         }
825         else
826                 return;
827
828         proto_tree_add_item(rdata_resp_tree,
829                         hf_rflags,
830                         tvb,
831                         LWRES_LWPACKET_LENGTH+0,
832                         sizeof(guint32),
833                         FALSE);
834
835         proto_tree_add_item(rdata_resp_tree,
836                         hf_rdclass,
837                         tvb,
838                         LWRES_LWPACKET_LENGTH+4,
839                         sizeof(guint16),
840                         FALSE);
841
842         proto_tree_add_item(rdata_resp_tree,
843                         hf_rdtype,
844                         tvb,
845                         LWRES_LWPACKET_LENGTH+6,
846                         sizeof(guint16),
847                         FALSE);
848
849         proto_tree_add_item(rdata_resp_tree,
850                         hf_ttl,
851                         tvb,
852                         LWRES_LWPACKET_LENGTH+8,
853                         sizeof(guint32),
854                         FALSE);
855
856         proto_tree_add_item(rdata_resp_tree,
857                         hf_nrdatas,
858                         tvb,
859                         LWRES_LWPACKET_LENGTH+12,
860                         sizeof(guint16),
861                         FALSE);
862
863         proto_tree_add_item(rdata_resp_tree,
864                         hf_nsigs,
865                         tvb,
866                         LWRES_LWPACKET_LENGTH+14,
867                         sizeof(guint16),
868                         FALSE);
869
870         proto_tree_add_item(rdata_resp_tree,
871                         hf_realnamelen,
872                         tvb,
873                         LWRES_LWPACKET_LENGTH+16,
874                         sizeof(guint16),
875                         FALSE);
876
877         proto_tree_add_item(rdata_resp_tree,
878                         hf_realname,
879                         tvb,
880                         LWRES_LWPACKET_LENGTH+18,
881                         realnamelen,
882                         FALSE);
883
884         switch(rdtype)
885         {
886                 case T_A:
887                         dissect_a_records(tvb,rdata_resp_tree,nrdatas,offset);
888                 break;
889
890                 case T_SRV:
891                         dissect_srv_records(tvb,rdata_resp_tree,nrdatas, offset);
892                 break;
893
894                 case T_MX:
895                         dissect_mx_records(tvb,rdata_resp_tree,nrdatas, offset);
896                 break;
897
898                 case T_NS:
899                         dissect_ns_records(tvb,rdata_resp_tree,nrdatas, offset);
900                 break;
901         }
902
903 }
904
905 static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
906 {
907         guint16 datalen;
908         const char* data;
909
910         proto_item* noop_item;
911         proto_tree* noop_tree;
912
913         datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);
914         data = (char*)tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH, datalen);
915
916         if(lwres_tree)
917         {
918                 noop_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "Noop record");
919                 noop_tree = proto_item_add_subtree(noop_item, ett_noop);
920         }
921         else
922                 return;
923
924         proto_tree_add_uint(noop_tree,
925                                                 hf_length,
926                                                 tvb,
927                                                 LWRES_LWPACKET_LENGTH,
928                                                 sizeof(guint16),
929                                                 datalen);
930
931 }
932
933 static void dissect_getaddrsbyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
934 {
935         if(type == 1)
936                 dissect_getaddrsbyname_request(tvb, lwres_tree);
937         else
938                 dissect_getaddrsbyname_response(tvb, lwres_tree);
939 }
940
941 static void dissect_getnamebyaddr(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
942 {
943         if(type == 1)
944                 dissect_getnamebyaddr_request(tvb, lwres_tree);
945         else
946                 dissect_getnamebyaddr_response(tvb, lwres_tree);
947 }
948
949 static void dissect_getrdatabyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
950 {
951         if(type == 1)
952                 dissect_rdata_request(tvb, lwres_tree);
953         else
954                 dissect_rdata_response(tvb, lwres_tree);
955 }
956
957 static void
958 dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
959 {
960         guint16 version, flags, authtype, authlength ;
961         guint32 length, opcode, result, recvlength, serial;
962         guint32 message_type;
963
964         proto_item* lwres_item;
965         proto_tree* lwres_tree;
966
967         col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res");
968         length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET);
969         version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET);
970         flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET);
971         serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET);
972         opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET);
973         result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET);
974         recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET);
975         authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET);
976         authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET);
977
978         message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1;
979
980         if (check_col(pinfo->cinfo, COL_INFO)) {
981                 col_clear(pinfo->cinfo, COL_INFO);
982
983                 if(flags & LWRES_LWPACKETFLAG_RESPONSE)
984                 {
985                         col_add_fstr(pinfo->cinfo, COL_INFO,
986                         "%s, opcode=%s, serial=0x%x, result=%s",
987                                 val_to_str((guint32)message_type,message_types_values,"unknown"),
988                                 val_to_str(opcode, opcode_values, "unknown"),
989                                                 serial,
990                                                 val_to_str(result,result_values,"unknown"));
991                 }
992                 else
993                 {
994                         col_add_fstr(pinfo->cinfo, COL_INFO,
995                                 "%s, opcode=%s, serial=0x%x",
996                                 val_to_str((guint32)message_type,message_types_values,"unknown"),
997                                                 val_to_str(opcode, opcode_values, "unknown"),
998                                 serial);
999                 }
1000         }
1001
1002         if(tree)
1003         {
1004                 lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, FALSE);
1005                 lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres);
1006         }
1007         else return;
1008
1009
1010         proto_tree_add_uint(lwres_tree,
1011                         hf_length,
1012                         tvb,
1013                         LW_LENGTH_OFFSET,
1014                         sizeof(guint32),
1015                         length);
1016
1017
1018         proto_tree_add_uint(lwres_tree,
1019                                 hf_version,
1020                                 tvb,
1021                                 LW_VERSION_OFFSET,
1022                                 sizeof(guint16),
1023                                 version);
1024
1025
1026
1027
1028         proto_tree_add_uint(lwres_tree,
1029                                 hf_flags,
1030                                 tvb,
1031                                 LW_PKTFLASG_OFFSET,
1032                                 sizeof(guint16),
1033                                 flags);
1034
1035         proto_tree_add_uint(lwres_tree,
1036                                 hf_serial,
1037                                 tvb,
1038                                 LW_SERIAL_OFFSET,
1039                                 sizeof(guint32),
1040                                 serial);
1041
1042         proto_tree_add_uint(lwres_tree,
1043                                 hf_opcode,
1044                                 tvb,
1045                                 LW_OPCODE_OFFSET,
1046                                 sizeof(guint32),
1047                                 opcode);
1048
1049         proto_tree_add_uint(lwres_tree,
1050                                 hf_result,
1051                                 tvb,
1052                                 LW_RESULT_OFFSET,
1053                                 sizeof(guint32),
1054                                 result);
1055
1056         proto_tree_add_uint(lwres_tree,
1057                                 hf_recvlen,
1058                                 tvb,
1059                                 LW_RECVLEN_OFFSET,
1060                                 sizeof(guint32),
1061                                 recvlength);
1062
1063         proto_tree_add_uint(lwres_tree,
1064                                 hf_authtype,
1065                                 tvb,
1066                                 LW_AUTHTYPE_OFFSET,
1067                                 sizeof(guint16),
1068                                 authtype);
1069
1070         proto_tree_add_uint(lwres_tree,
1071                                 hf_authlen,
1072                                 tvb,
1073                                 LW_AUTHLEN_OFFSET,
1074                                 sizeof(guint16),
1075                                 authlength);
1076
1077         if(!result)
1078         {
1079                 switch(opcode)
1080                 {
1081                         case LWRES_OPCODE_NOOP:
1082                                 dissect_noop(tvb, lwres_tree);
1083                         break;
1084
1085                         case LWRES_OPCODE_GETADDRSBYNAME:
1086                                 dissect_getaddrsbyname(tvb, lwres_tree, message_type);
1087                         break;
1088
1089                         case LWRES_OPCODE_GETNAMEBYADDR:
1090                                 dissect_getnamebyaddr(tvb, lwres_tree, message_type);
1091                         break;
1092
1093                         case LWRES_OPCODE_GETRDATABYNAME:
1094                                 dissect_getrdatabyname(tvb, lwres_tree, message_type);
1095                         break;
1096                 }
1097         }
1098 }
1099
1100
1101 void
1102 proto_register_lwres(void)
1103 {
1104   static hf_register_info hf[] = {
1105     { &hf_length,
1106       { "Length", "lwres.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1107         "lwres length", HFILL }},
1108
1109     { &hf_version,
1110       { "Version", "lwres.version", FT_UINT16, BASE_DEC, NULL, 0x0,
1111         "lwres version", HFILL }},
1112
1113     { &hf_flags,
1114       { "Packet Flags", "lwres.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1115         "lwres flags", HFILL }},
1116
1117     { &hf_serial,
1118       { "Serial", "lwres.serial", FT_UINT32, BASE_HEX, NULL, 0x0,
1119         "lwres serial", HFILL }},
1120
1121     { &hf_opcode,
1122       { "Operation code", "lwres.opcode", FT_UINT32, BASE_DEC, VALS(opcode_values), 0x0,
1123         "lwres opcode", HFILL }},
1124
1125     { &hf_result,
1126       { "Result", "lwres.result", FT_UINT32, BASE_DEC, VALS(result_values), 0x0,
1127         "lwres result", HFILL }},
1128
1129     { &hf_recvlen,
1130       { "Received length", "lwres.recvlen", FT_UINT32, BASE_DEC, NULL, 0x0,
1131         "lwres recvlen", HFILL }},
1132
1133     { &hf_authtype,
1134       { "Auth. type", "lwres.authtype", FT_UINT16, BASE_DEC, NULL, 0x0,
1135         "lwres authtype", HFILL }},
1136
1137     { &hf_authlen,
1138       { "Auth. length", "lwres.authlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1139         "lwres authlen", HFILL }},
1140
1141     { &hf_rflags,
1142       { "Flags", "lwres.rflags", FT_UINT32, BASE_HEX, NULL, 0x0,
1143         "lwres rflags", HFILL }},
1144     { &hf_rdclass,
1145       { "Class", "lwres.class", FT_UINT16, BASE_DEC, NULL, 0x0,
1146         "lwres class", HFILL }},
1147
1148     { &hf_rdtype,
1149       { "Type", "lwres.type", FT_UINT16, BASE_DEC, VALS(t_types), 0x0,
1150         "lwres type", HFILL }},
1151
1152     { &hf_namelen,
1153       { "Name length", "lwres.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1154         "lwres namelen", HFILL }},
1155
1156     { &hf_req_name,
1157       { "Domain name", "lwres.reqdname", FT_STRING, BASE_NONE, NULL, 0x0,
1158         "lwres reqdname", HFILL }},
1159
1160     { &hf_ttl,
1161       { "Time To Live", "lwres.ttl", FT_UINT32, BASE_DEC, NULL, 0x0,
1162         "lwres ttl", HFILL }},
1163
1164     { &hf_nrdatas,
1165       { "Number of rdata records", "lwres.nrdatas", FT_UINT16, BASE_DEC, NULL, 0x0,
1166         "lwres nrdatas", HFILL }},
1167
1168     { &hf_nsigs,
1169       { "Number of signature records", "lwres.nsigs", FT_UINT16, BASE_DEC, NULL, 0x0,
1170         "lwres nsigs", HFILL }},
1171
1172     { &hf_realnamelen,
1173       { "Real name length", "lwres.realnamelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1174         "lwres realnamelen", HFILL }},
1175
1176     { &hf_realname,
1177       { "Real doname name", "lwres.realname", FT_STRING, BASE_NONE, NULL, 0x0,
1178         "lwres realname", HFILL }},
1179
1180         { &hf_a_record,
1181         { "IPv4 Address", "lwres.arecord", FT_UINT32, BASE_DEC, NULL, 0x0,
1182           "lwres arecord", HFILL }},
1183
1184         { &hf_a_rec_len,
1185         { "Length", "lwres.areclen", FT_UINT16, BASE_DEC, NULL, 0x0,
1186         "lwres areclen", HFILL }},
1187
1188         { &hf_srv_prio,
1189         { "Priority", "lwres.srv.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
1190            "lwres srv prio", HFILL }},
1191
1192         { &hf_srv_weight,
1193         { "Weight", "lwres.srv.weight", FT_UINT16, BASE_DEC, NULL, 0x0,
1194         "lwres srv weight", HFILL }},
1195
1196         { &hf_srv_port,
1197         { "Port" , "lwres.srv.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1198         "lwres srv port", HFILL }},
1199
1200         { &hf_adn_flags,
1201         { "Flags", "lwres.adn.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
1202           "lwres adn flags", HFILL }},
1203
1204         { &hf_adn_addrtype,
1205         { "Address type", "lwres.adn.addrtype", FT_UINT32, BASE_DEC, NULL, 0x0,
1206           "lwres adn addrtype", HFILL }},
1207
1208         { &hf_adn_namelen,
1209         { "Name length", "lwres.adn.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1210           "lwres adn namelen", HFILL }},
1211
1212         { &hf_adn_name,
1213         { "Name", "lwres.adn.name", FT_STRING, BASE_NONE, NULL, 0x0,
1214           "lwres adn name", HFILL }},
1215
1216          { &hf_adn_naliases,
1217         { "Number of aliases", "lwres.adn.naliases", FT_UINT16, BASE_DEC, NULL, 0x0,
1218           "lwres adn naliases", HFILL }},
1219
1220           { &hf_adn_naddrs,
1221         { "Number of addresses", "lwres.adn.naddrs", FT_UINT16, BASE_DEC, NULL, 0x0,
1222           "lwres adn naddrs", HFILL }},
1223
1224                 { &hf_adn_realname,
1225         { "Real name", "lwres.adn.realname", FT_STRING, BASE_NONE, NULL, 0x0,
1226           "lwres adn realname", HFILL }},
1227
1228                 { &hf_adn_aliasname,
1229         { "Alias name", "lwres.adn.aliasname", FT_STRING, BASE_NONE, NULL, 0x0,
1230           "lwres adn aliasname", HFILL }},
1231
1232         { &hf_adn_family,
1233         { "Address family", "lwres.adn.addr.family", FT_UINT32, BASE_DEC, NULL, 0x0,
1234         "lwres adn addr family", HFILL }},
1235
1236         { &hf_adn_addr_len,
1237         { "Address length", "lwres.adn.addr.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1238         "lwres adn addr length", HFILL }},
1239
1240         { &hf_adn_addr_addr,
1241     { "IP Address", "lwres.adn.addr.addr", FT_STRING, BASE_NONE, NULL, 0x0,
1242           "lwres adn addr addr", HFILL }},
1243
1244     /* Add more fields here */
1245   };
1246
1247   static gint *ett[] = {
1248     &ett_lwres,
1249     &ett_rdata_req,
1250     &ett_rdata_resp,
1251         &ett_a_rec,
1252         &ett_a_rec_addr,
1253         &ett_srv_rec,
1254         &ett_srv_rec_item,
1255         &ett_adn_request,
1256         &ett_adn_resp,
1257         &ett_adn_alias,
1258         &ett_adn_addr,
1259         &ett_nba_request,
1260         &ett_nba_resp,
1261         &ett_mx_rec,
1262         &ett_mx_rec_item,
1263         &ett_ns_rec,
1264         &ett_ns_rec_item,
1265         &ett_noop,
1266   };
1267
1268
1269   module_t *lwres_module;
1270
1271   proto_lwres = proto_register_protocol("Light Weight DNS RESolver (BIND9)",
1272                                        "LWRES", "lwres");
1273
1274   proto_register_field_array(proto_lwres, hf, array_length(hf));
1275   proto_register_subtree_array(ett, array_length(ett));
1276
1277   lwres_module = prefs_register_protocol(proto_lwres, proto_reg_handoff_lwres);
1278
1279   prefs_register_uint_preference(lwres_module, "udp.lwres_port",
1280                                  "lwres listener UDP Port",
1281                                  "Set the UDP port for lwres daemon"
1282                                  "(if other than the default of 921)",
1283                                  10, &global_lwres_port);
1284
1285 }
1286
1287 /* The registration hand-off routine */
1288 void
1289 proto_reg_handoff_lwres(void)
1290 {
1291   static gboolean lwres_prefs_initialized = FALSE;
1292   static dissector_handle_t lwres_handle;
1293   static guint lwres_port;
1294
1295   if(!lwres_prefs_initialized) {
1296     lwres_handle = create_dissector_handle(dissect_lwres, proto_lwres);
1297     lwres_prefs_initialized = TRUE;
1298   }
1299   else {
1300     dissector_delete("udp.port", lwres_port, lwres_handle);
1301   }
1302
1303   dissector_add("udp.port", global_lwres_port, lwres_handle);
1304   lwres_port = global_lwres_port;
1305
1306 }