2 * Routines for light weight reslover (lwres, part of BIND9) packet disassembly
6 * Copyright (c) 2003 by Oleg Terletsky <oleg.terletsky@comverse.com>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1999 Gerald Combs
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.
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.
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.
31 #include "plugins/plugin_api.h"
32 #include "moduleinfo.h"
41 #include <epan/packet.h>
42 #include <epan/prefs.h>
44 #include "plugins/plugin_api_defs.h"
46 #define LWRES_LWPACKET_LENGTH (4 * 5 + 2 * 4)
47 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
48 #define LWRES_LWPACKETVERSION_0 0
50 #define LW_LENGTH_OFFSET 0
51 #define LW_VERSION_OFFSET 4
52 #define LW_PKTFLASG_OFFSET 6
53 #define LW_SERIAL_OFFSET 8
54 #define LW_OPCODE_OFFSET 12
55 #define LW_RESULT_OFFSET 16
56 #define LW_RECVLEN_OFFSET 20
57 #define LW_AUTHTYPE_OFFSET 24
58 #define LW_AUTHLEN_OFFSET 26
61 #define LWRES_OPCODE_NOOP 0x00000000U
62 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
63 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
64 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
66 static const value_string opcode_values[] = {
67 { LWRES_OPCODE_NOOP, "Noop" },
68 { LWRES_OPCODE_GETADDRSBYNAME, "getaddrbyname" },
69 { LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr" },
70 { LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname" },
75 #define LWRES_R_SUCCESS 0
76 #define LWRES_R_NOMEMORY 1
77 #define LWRES_R_TIMEOUT 2
78 #define LWRES_R_NOTFOUND 3
79 #define LWRES_R_UNEXPECTEDEND 4 /* unexpected end of input */
80 #define LWRES_R_FAILURE 5 /* generic failure */
81 #define LWRES_R_IOERROR 6
82 #define LWRES_R_NOTIMPLEMENTED 7
83 #define LWRES_R_UNEXPECTED 8
84 #define LWRES_R_TRAILINGDATA 9
85 #define LWRES_R_INCOMPLETE 10
86 #define LWRES_R_RETRY 11
87 #define LWRES_R_TYPENOTFOUND 12
88 #define LWRES_R_TOOLARGE 13
96 static const value_string t_types[] = {
107 static const value_string result_values[] = {
108 { LWRES_R_SUCCESS, "Success" },
109 { LWRES_R_NOMEMORY, "No memory" },
110 { LWRES_R_TIMEOUT, "Timeout" },
111 { LWRES_R_NOTFOUND, "Not found" },
112 { LWRES_R_UNEXPECTEDEND, "Unexpected end of input" },
113 { LWRES_R_FAILURE, "Generic failure" },
114 { LWRES_R_IOERROR, "I/O Error" },
115 { LWRES_R_UNEXPECTED, "Unexpected" },
116 { LWRES_R_TRAILINGDATA, "Trailing data" },
117 { LWRES_R_INCOMPLETE, "Incompete" },
118 { LWRES_R_RETRY, "Retry" },
119 { LWRES_R_TYPENOTFOUND, "Type not found" },
120 { LWRES_R_TOOLARGE, "Too large" },
124 static int hf_length = -1;
125 static int hf_version = -1;
126 static int hf_flags = -1;
127 static int hf_serial = -1;
128 static int hf_opcode = -1;
129 static int hf_result = -1;
130 static int hf_recvlen = -1;
131 static int hf_authtype = -1;
132 static int hf_authlen = -1;
134 static int hf_rflags = -1;
135 static int hf_rdclass = -1;
136 static int hf_rdtype = -1;
137 static int hf_namelen = -1;
138 static int hf_req_name = -1;
140 static int hf_ttl = -1;
141 static int hf_nrdatas = -1;
142 static int hf_nsigs = -1;
143 static int hf_realnamelen = -1;
144 static int hf_realname = -1;
147 static int hf_a_record = -1;
148 static int hf_a_rec_len = -1;
149 static int hf_srv_prio = -1;
150 static int hf_srv_weight = -1;
151 static int hf_srv_port = -1;
153 static int hf_adn_flags = -1;
154 static int hf_adn_addrtype = -1;
155 static int hf_adn_namelen = -1;
156 static int hf_adn_name = -1;
158 static int hf_adn_realname = -1;
159 static int hf_adn_aliasname = -1;
161 static int hf_adn_naddrs = -1;
162 static int hf_adn_naliases = -1;
163 static int hf_adn_family = -1;
164 static int hf_adn_addr_len = -1;
165 static int hf_adn_addr_addr = -1;
168 static int ett_lwres = -1;
169 static int ett_rdata_req = -1;
170 static int ett_rdata_resp = -1;
171 static int ett_a_rec = -1;
172 static int ett_a_rec_addr = -1;
173 static int ett_srv_rec = -1;
174 static int ett_srv_rec_item = -1;
175 static int ett_adn_request = -1;
176 static int ett_adn_resp = -1;
177 static int ett_adn_alias = -1;
178 static int ett_adn_addr = -1;
179 static int ett_nba_request = -1;
180 static int ett_nba_resp = -1;
181 static int ett_noop = -1;
183 static int ett_mx_rec = -1;
184 static int ett_mx_rec_item = -1;
186 static int ett_ns_rec = -1;
187 static int ett_ns_rec_item = -1;
191 #ifndef ENABLE_STATIC
192 G_MODULE_EXPORT const gchar version[] = VERSION;
196 #define LWRES_UDP_PORT 921
198 static guint global_lwres_port = LWRES_UDP_PORT;
199 static guint lwres_port = LWRES_UDP_PORT;
201 void proto_reg_handoff_lwres(void);
204 /* Define the lwres proto */
205 static int proto_lwres = -1;
208 /* Define many many headers for mgcp */
210 static const value_string message_types_values[] = {
219 lwres_get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
220 char *name, int maxname)
222 int start_offset = offset;
225 int chars_processed = 0;
226 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
230 const int min_len = 1; /* Minimum length of encoded name (for root) */
231 /* If we're about to return a value (probably negative) which is less
232 * than the minimum length, we're looking at bad data and we're liable
233 * to put the dissector into a loop. Instead we throw an exception */
235 maxname--; /* reserve space for the trailing '\0' */
237 component_len = tvb_get_guint8(tvb, offset);
239 if (component_len == 0)
242 switch (component_len & 0xc0) {
247 /* Not the first component - put in a '.'. */
253 while (component_len > 0) {
255 *np++ = tvb_get_guint8(tvb, offset);
265 /* Extended label (RFC 2673) */
266 switch (component_len & 0x3f) {
269 /* Bitstring label */
276 bit_count = tvb_get_guint8(tvb, offset);
278 label_len = (bit_count - 1) / 8 + 1;
282 print_len = snprintf(np, maxname + 1, "\\[x");
283 if (print_len != -1) {
284 /* Some versions of snprintf return -1 if they'd truncate
287 maxname -= print_len;
289 /* Nothing printed, as there's no room.
290 Suppress all subsequent printing. */
296 print_len = snprintf(np, maxname + 1, "%02x",
297 tvb_get_guint8(tvb, offset));
298 if (print_len != -1) {
299 /* Some versions of snprintf return -1 if they'd truncate
302 maxname -= print_len;
304 /* Nothing printed, as there's no room.
305 Suppress all subsequent printing. */
312 print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
313 if (print_len != -1) {
314 /* Some versions of snprintf return -1 if they'd truncate
317 maxname -= print_len;
319 /* Nothing printed, as there's no room.
320 Suppress all subsequent printing. */
328 strcpy(name, "<Unknown extended label>");
329 /* Parsing will propably fail from here on, since the */
330 /* label length is unknown... */
331 len = offset - start_offset;
333 THROW(ReportedBoundsError);
339 THROW(ReportedBoundsError);
343 indir_offset = dns_data_offset +
344 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
348 /* If "len" is negative, we are still working on the original name,
349 not something pointed to by a pointer, and so we should set "len"
350 to the length of the original name. */
352 len = offset - start_offset;
354 /* If we've looked at every character in the message, this pointer
355 will make us look at some character again, which means we're
357 if (chars_processed >= data_size) {
358 strcpy(name, "<Name contains a pointer that loops>");
360 THROW(ReportedBoundsError);
364 offset = indir_offset;
365 break; /* now continue processing from there */
370 /* If "len" is negative, we haven't seen a pointer, and thus haven't
371 set the length, so set it. */
373 len = offset - start_offset;
374 /* Zero-length name means "root server" */
376 strcpy(name, "<Root>");
378 THROW(ReportedBoundsError);
383 static void dissect_getnamebyaddr_request(tvbuff_t* tvb, proto_tree* lwres_tree)
385 guint32 flags,family;
386 guint16 addrlen, slen;
389 proto_item* nba_request_item;
390 proto_tree* nba_request_tree;
392 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
393 family = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
394 addrlen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
395 addr = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH + 10, 4);
396 slen = strlen((char*)ip_to_str(addr));
400 nba_request_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,LWRES_LWPACKET_LENGTH+14,"getnamebyaddr parameters");
401 nba_request_tree = proto_item_add_subtree(nba_request_item, ett_nba_request);
405 proto_tree_add_uint(nba_request_tree,
408 LWRES_LWPACKET_LENGTH,
412 proto_tree_add_uint(nba_request_tree,
415 LWRES_LWPACKET_LENGTH + 4,
419 proto_tree_add_uint(nba_request_tree,
422 LWRES_LWPACKET_LENGTH + 8,
426 proto_tree_add_string(nba_request_tree,
429 LWRES_LWPACKET_LENGTH + 10,
435 static void dissect_getnamebyaddr_response(tvbuff_t* tvb, proto_tree* lwres_tree)
437 guint32 flags,i, offset;
438 guint16 naliases,realnamelen,aliaslen;
443 proto_item* nba_resp_item;
444 proto_tree* nba_resp_tree;
446 proto_item* alias_item;
447 proto_tree* alias_tree;
451 nba_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10,"getnamebyaddr records");
452 nba_resp_tree = proto_item_add_subtree(nba_resp_item, ett_nba_resp);
456 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
457 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
458 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH + 4 + 2);
459 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 4 + 2 + 2, realnamelen, realname);
460 realname[realnamelen]='\0';
462 proto_tree_add_uint(nba_resp_tree,
465 LWRES_LWPACKET_LENGTH,
468 proto_tree_add_uint(nba_resp_tree,
471 LWRES_LWPACKET_LENGTH + 4,
475 proto_tree_add_uint(nba_resp_tree,
478 LWRES_LWPACKET_LENGTH + 6,
482 proto_tree_add_string(nba_resp_tree,
485 LWRES_LWPACKET_LENGTH + 8,
489 offset=LWRES_LWPACKET_LENGTH + 8 + realnamelen;
493 for(i=0; i<naliases; i++)
495 aliaslen = tvb_get_ntohs(tvb, offset);
496 tvb_get_nstringz(tvb, offset + 2, aliaslen, aliasname);
497 aliasname[aliaslen]='\0';
499 alias_item = proto_tree_add_text(nba_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
500 alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
502 proto_tree_add_uint(alias_tree,
509 proto_tree_add_string(alias_tree,
516 offset+=(2 + aliaslen + 1);
521 static void dissect_getaddrsbyname_request(tvbuff_t* tvb, proto_tree* lwres_tree)
523 guint32 flags,addrtype;
527 proto_item* adn_request_item;
528 proto_tree* adn_request_tree;
530 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
531 addrtype = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
532 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
533 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
538 adn_request_item = proto_tree_add_text(lwres_tree,tvb,
539 LWRES_LWPACKET_LENGTH,10+namelen+1,
540 "getaddrbyname parameters");
541 adn_request_tree = proto_item_add_subtree(adn_request_item, ett_adn_request);
547 proto_tree_add_uint(adn_request_tree,
550 LWRES_LWPACKET_LENGTH+0,
554 proto_tree_add_uint(adn_request_tree,
557 LWRES_LWPACKET_LENGTH+4,
561 proto_tree_add_uint(adn_request_tree,
564 LWRES_LWPACKET_LENGTH+8,
568 proto_tree_add_string(adn_request_tree,
571 LWRES_LWPACKET_LENGTH+10,
578 static void dissect_getaddrsbyname_response(tvbuff_t* tvb, proto_tree* lwres_tree)
580 guint32 flags, family ,i, offset;
581 guint16 naliases, naddrs, realnamelen, length, aliaslen;
587 proto_item* adn_resp_item;
588 proto_tree* adn_resp_tree;
589 proto_item* alias_item;
590 proto_tree* alias_tree;
591 proto_item* addr_item;
592 proto_tree* addr_tree;
598 adn_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "getaddrbyname records");
599 adn_resp_tree = proto_item_add_subtree(adn_resp_item, ett_adn_resp);
603 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
604 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
605 naddrs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 6);
606 realnamelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
607 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 10, realnamelen, realname);
608 realname[realnamelen]='\0';
611 proto_tree_add_uint(adn_resp_tree,
614 LWRES_LWPACKET_LENGTH,
618 proto_tree_add_uint(adn_resp_tree,
621 LWRES_LWPACKET_LENGTH + 4,
625 proto_tree_add_uint(adn_resp_tree,
628 LWRES_LWPACKET_LENGTH + 6,
632 proto_tree_add_uint(adn_resp_tree,
635 LWRES_LWPACKET_LENGTH + 8,
639 proto_tree_add_string(adn_resp_tree,
642 LWRES_LWPACKET_LENGTH + 10,
646 offset = LWRES_LWPACKET_LENGTH + 10 + realnamelen + 1;
650 for(i=0; i<naliases; i++)
652 aliaslen = tvb_get_ntohs(tvb, offset);
653 tvb_get_nstringz(tvb, offset + 2, aliaslen, aliasname);
654 aliasname[aliaslen]='\0';
656 alias_item = proto_tree_add_text(adn_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
657 alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
659 proto_tree_add_uint(alias_tree,
666 proto_tree_add_string(alias_tree,
673 offset+=(2 + aliaslen + 1);
679 for(i=0; i < naddrs; i++)
681 family = tvb_get_ntohl(tvb, offset);
682 length = tvb_get_ntohs(tvb, offset + 4);
683 addr = tvb_get_ptr(tvb, offset + 6, 4);
684 slen = strlen((char*)ip_to_str(addr));
686 addr_item = proto_tree_add_text(adn_resp_tree,tvb, offset, 4+2+4, "Address %s",ip_to_str(addr));
687 addr_tree = proto_item_add_subtree(addr_item, ett_adn_addr);
689 proto_tree_add_uint(addr_tree,
696 proto_tree_add_uint(addr_tree,
703 proto_tree_add_string(addr_tree,
717 static void dissect_a_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
722 proto_item* a_rec_item;
723 proto_tree* a_rec_tree;
724 proto_item* addr_item;
725 proto_tree* addr_tree;
729 a_rec_item = proto_tree_add_text(tree,tvb,offset,
730 ((sizeof(guint32) + sizeof(guint16)) * nrec),"A records");
732 a_rec_tree = proto_item_add_subtree(a_rec_item, ett_a_rec);
737 for(i=0; i<nrec; i++)
740 curr = offset + ((sizeof(guint32)+sizeof(guint16)) * i);
742 len = tvb_get_ntohs(tvb,curr);
743 addr = tvb_get_ptr(tvb,curr+2,4);
747 addr_item = proto_tree_add_text(a_rec_tree,tvb, curr, 6,"IP Address");
748 addr_tree = proto_item_add_subtree(addr_item, ett_a_rec_addr);
749 proto_item_set_text(addr_item,"Address %s",ip_to_str(addr));
753 proto_tree_add_uint(addr_tree,
760 proto_tree_add_text(addr_tree,
771 static void dissect_srv_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
774 guint16 len, priority, weight, port, namelen, dlen;
778 proto_item* srv_rec_item, *rec_item;
779 proto_item* srv_rec_tree, *rec_tree;
783 srv_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "SRV records");
784 srv_rec_tree = proto_item_add_subtree(srv_rec_item, ett_srv_rec);
785 proto_item_set_text(srv_rec_item, "SRV records (%d)", nrec);
791 for(i=0; i < nrec; i++)
793 len = tvb_get_ntohs(tvb, curr);
794 priority = tvb_get_ntohs(tvb, curr + 2);
795 weight = tvb_get_ntohs(tvb, curr + 4);
796 port = tvb_get_ntohs(tvb, curr + 6);
798 cmpname = tvb_get_ptr(tvb, curr + 8, namelen);
800 dlen = lwres_get_dns_name(tvb, curr + 8, curr, dname, sizeof(dname));
804 rec_item = proto_tree_add_text(srv_rec_tree, tvb, curr, 6," ");
805 rec_tree = proto_item_add_subtree(rec_item, ett_srv_rec_item);
806 proto_item_set_text(rec_item,
807 "SRV record:pri=%d,w=%d,port=%d,dname=%s",
815 proto_tree_add_uint(rec_tree,
822 proto_tree_add_uint(rec_tree,
829 proto_tree_add_uint(rec_tree,
837 proto_tree_add_text(rec_tree,
843 curr+=((sizeof(short)*4) + dlen);
849 static void dissect_mx_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
853 guint16 len, priority, dlen, namelen;
857 proto_item* mx_rec_item, *rec_item;
858 proto_tree* mx_rec_tree, *rec_tree;
863 mx_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "MX records (%d)", nrec);
864 mx_rec_tree = proto_item_add_subtree(mx_rec_item, ett_mx_rec);
870 for(i=0; i < nrec; i++)
872 len = tvb_get_ntohs(tvb, curr);
873 priority = tvb_get_ntohs(tvb, curr + 2);
875 cname = tvb_get_ptr(tvb, curr + 4, 4);
876 dlen = lwres_get_dns_name(tvb, curr + 4, curr, dname, sizeof(dname));
879 rec_item = proto_tree_add_text(mx_rec_tree, tvb, curr,6,"MX record: pri=%d,dname=%s",
881 rec_tree = proto_item_add_subtree(rec_item, ett_mx_rec_item);
887 proto_tree_add_uint(rec_tree,
894 proto_tree_add_text(rec_tree,
900 curr+=((sizeof(short)*2) + dlen);
907 static void dissect_ns_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
910 guint16 len, dlen, namelen;
913 proto_item* ns_rec_item, *rec_item;
914 proto_tree* ns_rec_tree, *rec_tree;
918 ns_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "NS record (%d)", nrec);
919 ns_rec_tree = proto_item_add_subtree(ns_rec_item, ett_ns_rec);
927 len = tvb_get_ntohs(tvb, curr);
929 dlen = lwres_get_dns_name(tvb, curr + 2, curr, dname, sizeof(dname));
932 rec_item = proto_tree_add_text(ns_rec_tree, tvb, curr,4, "NS record: dname=%s",dname);
933 rec_tree = proto_item_add_subtree(rec_item, ett_ns_rec_item);
938 proto_tree_add_text(rec_tree,
943 curr+=(sizeof(short) + dlen);
950 static void dissect_rdata_request(tvbuff_t* tvb, proto_tree* lwres_tree)
953 guint16 rdclass, rdtype, namelen;
956 proto_item* rdata_request_item;
957 proto_tree* rdata_request_tree;
959 rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
960 rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
961 rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
962 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+8);
963 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
969 proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,10+namelen+1,"RDATA request parameters");
970 rdata_request_tree = proto_item_add_subtree(rdata_request_item, ett_rdata_req);
975 proto_tree_add_uint(rdata_request_tree,
978 LWRES_LWPACKET_LENGTH+0,
982 proto_tree_add_uint(rdata_request_tree,
985 LWRES_LWPACKET_LENGTH+4,
989 proto_tree_add_uint(rdata_request_tree,
992 LWRES_LWPACKET_LENGTH+6,
996 proto_tree_add_uint(rdata_request_tree,
999 LWRES_LWPACKET_LENGTH+8,
1003 proto_tree_add_string(rdata_request_tree,
1006 LWRES_LWPACKET_LENGTH+10,
1012 static void dissect_rdata_response(tvbuff_t* tvb, proto_tree* lwres_tree)
1014 guint32 rflags, ttl, offset;
1015 guint16 rdclass, rdtype, nrdatas, nsigs, realnamelen;
1016 guint8 realname[120];
1018 proto_item* rdata_resp_item;
1019 proto_tree* rdata_resp_tree;
1021 rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
1022 rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
1023 rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
1024 ttl = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+8);
1025 nrdatas = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+12);
1026 nsigs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+14);
1027 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH+16);
1028 tvb_get_nstringz(tvb,LWRES_LWPACKET_LENGTH+18,realnamelen, realname);
1029 realname[realnamelen]='\0';
1031 offset = LWRES_LWPACKET_LENGTH + 18 + realnamelen + 1;
1035 rdata_resp_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH, 18+realnamelen+1,"RDATA response");
1036 rdata_resp_tree = proto_item_add_subtree(rdata_resp_item, ett_rdata_resp);
1041 proto_tree_add_uint(rdata_resp_tree,
1044 LWRES_LWPACKET_LENGTH+0,
1048 proto_tree_add_uint(rdata_resp_tree,
1051 LWRES_LWPACKET_LENGTH+4,
1055 proto_tree_add_uint(rdata_resp_tree,
1058 LWRES_LWPACKET_LENGTH+6,
1062 proto_tree_add_uint(rdata_resp_tree,
1065 LWRES_LWPACKET_LENGTH+8,
1069 proto_tree_add_uint(rdata_resp_tree,
1072 LWRES_LWPACKET_LENGTH+12,
1076 proto_tree_add_uint(rdata_resp_tree,
1079 LWRES_LWPACKET_LENGTH+14,
1083 proto_tree_add_uint(rdata_resp_tree,
1086 LWRES_LWPACKET_LENGTH+16,
1090 proto_tree_add_string(rdata_resp_tree,
1093 LWRES_LWPACKET_LENGTH+18,
1100 dissect_a_records(tvb,rdata_resp_tree,nrdatas,offset);
1104 dissect_srv_records(tvb,rdata_resp_tree,nrdatas, offset);
1108 dissect_mx_records(tvb,rdata_resp_tree,nrdatas, offset);
1112 dissect_ns_records(tvb,rdata_resp_tree,nrdatas, offset);
1118 static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
1123 proto_item* noop_item;
1124 proto_tree* noop_tree;
1126 datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);
1127 data = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH, datalen);
1131 noop_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "Noop record");
1132 noop_tree = proto_item_add_subtree(noop_item, ett_noop);
1137 proto_tree_add_uint(noop_tree,
1140 LWRES_LWPACKET_LENGTH,
1146 static void dissect_getaddrsbyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1149 dissect_getaddrsbyname_request(tvb, lwres_tree);
1151 dissect_getaddrsbyname_response(tvb, lwres_tree);
1154 static void dissect_getnamebyaddr(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1157 dissect_getnamebyaddr_request(tvb, lwres_tree);
1159 dissect_getnamebyaddr_response(tvb, lwres_tree);
1162 static void dissect_getrdatabyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1165 dissect_rdata_request(tvb, lwres_tree);
1167 dissect_rdata_response(tvb, lwres_tree);
1171 dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1173 guint16 version, flags, authtype, authlength ;
1174 guint32 length, opcode, result, recvlength, serial;
1175 guint32 message_type;
1177 proto_item* lwres_item;
1178 proto_tree* lwres_tree;
1180 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1181 col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res");
1182 length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET);
1183 version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET);
1184 flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET);
1185 serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET);
1186 opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET);
1187 result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET);
1188 recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET);
1189 authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET);
1190 authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET);
1192 message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1;
1194 if (check_col(pinfo->cinfo, COL_INFO)) {
1195 col_clear(pinfo->cinfo, COL_INFO);
1197 if(flags & LWRES_LWPACKETFLAG_RESPONSE)
1199 col_add_fstr(pinfo->cinfo, COL_INFO,
1200 "%s, opcode=%s, serial=0x%x, result=%s",
1201 val_to_str((guint32)message_type,message_types_values,"unknown"),
1202 val_to_str(opcode, opcode_values, "unknown"),
1204 val_to_str(result,result_values,"unknown"));
1208 col_add_fstr(pinfo->cinfo, COL_INFO,
1209 "%s, opcode=%s, serial=0x%x",
1210 val_to_str((guint32)message_type,message_types_values,"unknown"),
1211 val_to_str(opcode, opcode_values, "unknown"),
1218 lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, FALSE);
1219 lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres);
1224 proto_tree_add_uint(lwres_tree,
1232 proto_tree_add_uint(lwres_tree,
1242 proto_tree_add_uint(lwres_tree,
1249 proto_tree_add_uint(lwres_tree,
1256 proto_tree_add_uint(lwres_tree,
1263 proto_tree_add_uint(lwres_tree,
1270 proto_tree_add_uint(lwres_tree,
1277 proto_tree_add_uint(lwres_tree,
1284 proto_tree_add_uint(lwres_tree,
1295 case LWRES_OPCODE_NOOP:
1296 dissect_noop(tvb, lwres_tree);
1299 case LWRES_OPCODE_GETADDRSBYNAME:
1300 dissect_getaddrsbyname(tvb, lwres_tree, message_type);
1303 case LWRES_OPCODE_GETNAMEBYADDR:
1304 dissect_getnamebyaddr(tvb, lwres_tree, message_type);
1307 case LWRES_OPCODE_GETRDATABYNAME:
1308 dissect_getrdatabyname(tvb, lwres_tree, message_type);
1317 proto_register_lwres(void)
1319 static hf_register_info hf[] = {
1321 { "Length", "lwres.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1322 "lwres length", HFILL }},
1325 { "Version", "lwres.version", FT_UINT16, BASE_DEC, NULL, 0x0,
1326 "lwres legth", HFILL }},
1329 { "Packet Flags", "lwres.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1330 "lwres flags", HFILL }},
1333 { "Serial", "lwres.serial", FT_UINT32, BASE_HEX, NULL, 0x0,
1334 "lwres serial", HFILL }},
1337 { "Operation code", "lwres.opcode", FT_UINT32, BASE_DEC, VALS(opcode_values), 0x0,
1338 "lwres opcode", HFILL }},
1341 { "Result", "lwres.result", FT_UINT32, BASE_DEC, VALS(result_values), 0x0,
1342 "lwres result", HFILL }},
1345 { "Received length", "lwres.recvlen", FT_UINT32, BASE_DEC, NULL, 0x0,
1346 "lwres recvlen", HFILL }},
1349 { "Auth. type", "lwres.authtype", FT_UINT16, BASE_DEC, NULL, 0x0,
1350 "lwres authtype", HFILL }},
1353 { "Auth. length", "lwres.authlen" , FT_UINT16, BASE_DEC, NULL, 0x0,
1354 "lwres authlen", HFILL }},
1357 { "Flags", "lwres.rflags", FT_UINT32, BASE_HEX, NULL, 0x0,
1358 "lwres rflags", HFILL }},
1360 { "Class", "lwres.class", FT_UINT16, BASE_DEC, NULL, 0x0,
1361 "lwres class", HFILL }},
1364 { "Type", "lwres.type", FT_UINT16, BASE_DEC, VALS(t_types), 0x0,
1365 "lwres type" , HFILL }},
1368 { "Name length", "lwres.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1369 "lwres namelen", HFILL }},
1372 { "Domain name" , "lwres.reqdname" , FT_STRING, BASE_DEC, NULL, 0x0,
1373 "lwres reqdname", HFILL }},
1376 { "Time To Live", "lwres.ttl", FT_UINT32, BASE_DEC, NULL, 0x0,
1377 "lwres ttl", HFILL }},
1380 { "Number of rdata records", "lwres.nrdatas", FT_UINT16, BASE_DEC, NULL, 0x0,
1381 "lwres nrdatas" , HFILL }},
1384 { "Number of signature records", "lwres.nsigs", FT_UINT16, BASE_DEC, NULL, 0x0,
1385 "lwres nsigs" , HFILL }},
1388 { "Real name length", "lwres.realnamelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1389 "lwres realnamelen", HFILL }},
1392 { "Real doname name", "lwres.realname", FT_STRING, BASE_DEC, NULL, 0x0,
1393 "lwres realname", HFILL }},
1396 { "IPv4 Address", "lwres.arecord", FT_UINT32, BASE_DEC, NULL, 0x0,
1397 "lwres arecord", HFILL }},
1400 { "Length", "lwres.areclen", FT_UINT16, BASE_DEC, NULL, 0x0,
1401 "lwres areclen", HFILL }},
1404 { "Priority", "lwres.srv.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
1405 "lwres srv prio", HFILL }},
1408 { "Weight", "lwres.srv.weight", FT_UINT16, BASE_DEC, NULL, 0x0,
1409 "lwres srv weight", HFILL }},
1412 { "Port" , "lwres.srv.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1413 "lwres srv port", HFILL }},
1416 { "Flags", "lwres.adn.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
1417 "lwres adn flags", HFILL }},
1420 { "Address type", "lwres.adn.addrtype", FT_UINT32, BASE_DEC, NULL, 0x0,
1421 "lwres adn addrtype", HFILL }},
1424 { "Name length", "lwres.adn.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1425 "lwres adn namelen", HFILL }},
1428 { "Name", "lwres.adn.name", FT_STRING, BASE_DEC, NULL, 0x0,
1429 "lwres adn name", HFILL }},
1432 { "Number of aliases", "lwres.adn.naliases", FT_UINT16, BASE_DEC, NULL, 0x0,
1433 "lwres adn naliases", HFILL }},
1436 { "Number of addresses", "lwres.adn.naddrs", FT_UINT16, BASE_DEC, NULL, 0x0,
1437 "lwres adn naddrs", HFILL }},
1440 { "Real name", "lwres.adn.realname", FT_STRING, BASE_DEC, NULL, 0x0,
1441 "lwres adn realname", HFILL }},
1443 { &hf_adn_aliasname,
1444 { "Alias name", "lwres.adn.aliasname", FT_STRING, BASE_DEC, NULL, 0x0,
1445 "lwres adn aliasname", HFILL }},
1448 { "Address family", "lwres.adn.addr.family", FT_UINT32, BASE_DEC, NULL, 0x0,
1449 "lwres adn addr family", HFILL }},
1452 { "Address length", "lwres.adn.addr.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1453 "lwres adn addr length", HFILL }},
1455 { &hf_adn_addr_addr,
1456 { "IP Address", "lwres.adn.addr.addr", FT_STRING, BASE_DEC, NULL, 0x0,
1457 "lwres adn addr addr", HFILL }},
1459 /* Add more fields here */
1462 static gint *ett[] = {
1484 module_t *lwres_module;
1486 proto_lwres = proto_register_protocol("Light Weight DNS RESolver (BIND9)",
1489 proto_register_field_array(proto_lwres, hf, array_length(hf));
1490 proto_register_subtree_array(ett, array_length(ett));
1492 lwres_module = prefs_register_protocol(proto_lwres, proto_reg_handoff_lwres);
1494 prefs_register_uint_preference(lwres_module, "udp.lwres_port",
1495 "lwres listener UDP Port",
1496 "Set the UDP port for lwres daemon"
1497 "(if other than the default of 921)",
1498 10, &global_lwres_port);
1502 /* The registration hand-off routine */
1504 proto_reg_handoff_lwres(void)
1506 static int lwres_prefs_initialized = FALSE;
1507 static dissector_handle_t lwres_handle;
1509 if(!lwres_prefs_initialized) {
1510 lwres_handle = create_dissector_handle(dissect_lwres, proto_lwres);
1511 lwres_prefs_initialized = TRUE;
1514 dissector_delete("udp.port",global_lwres_port, lwres_handle);
1518 lwres_port = global_lwres_port;
1520 dissector_add("udp.port", lwres_port, lwres_handle);
1524 /* Start the functions we need for the plugin stuff */
1526 #ifndef ENABLE_STATIC
1528 G_MODULE_EXPORT void
1529 plugin_reg_handoff(void){
1530 proto_reg_handoff_lwres();
1533 G_MODULE_EXPORT void
1534 plugin_init(plugin_address_table_t *pat
1535 #ifndef PLUGINS_NEED_ADDRESS_TABLE
1539 /* initialise the table of pointers needed in Win32 DLLs */
1540 plugin_address_table_init(pat);
1541 /* register the new protocol, protocol fields, and subtrees */
1542 if (proto_lwres == -1) { /* execute protocol initialization only once */
1543 proto_register_lwres();
1549 /* End the functions we need for plugin stuff */