2 * Routines for light weight reslover (lwres, part of BIND9) packet disassembly
6 * Copyright (c) 2003 by Oleg Terletsky <oleg.terletsky@comverse.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
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.
38 #include <epan/packet.h>
39 #include <epan/prefs.h>
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
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
56 #define LWRES_OPCODE_NOOP 0x00000000U
57 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
58 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
59 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
61 static const value_string opcode_values[] = {
62 { LWRES_OPCODE_NOOP, "Noop" },
63 { LWRES_OPCODE_GETADDRSBYNAME, "getaddrbyname" },
64 { LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr" },
65 { LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname" },
70 #define LWRES_R_SUCCESS 0
71 #define LWRES_R_NOMEMORY 1
72 #define LWRES_R_TIMEOUT 2
73 #define LWRES_R_NOTFOUND 3
74 #define LWRES_R_UNEXPECTEDEND 4 /* unexpected end of input */
75 #define LWRES_R_FAILURE 5 /* generic failure */
76 #define LWRES_R_IOERROR 6
77 #define LWRES_R_NOTIMPLEMENTED 7
78 #define LWRES_R_UNEXPECTED 8
79 #define LWRES_R_TRAILINGDATA 9
80 #define LWRES_R_INCOMPLETE 10
81 #define LWRES_R_RETRY 11
82 #define LWRES_R_TYPENOTFOUND 12
83 #define LWRES_R_TOOLARGE 13
91 static const value_string t_types[] = {
102 static const value_string result_values[] = {
103 { LWRES_R_SUCCESS, "Success" },
104 { LWRES_R_NOMEMORY, "No memory" },
105 { LWRES_R_TIMEOUT, "Timeout" },
106 { LWRES_R_NOTFOUND, "Not found" },
107 { LWRES_R_UNEXPECTEDEND, "Unexpected end of input" },
108 { LWRES_R_FAILURE, "Generic failure" },
109 { LWRES_R_IOERROR, "I/O Error" },
110 { LWRES_R_UNEXPECTED, "Unexpected" },
111 { LWRES_R_TRAILINGDATA, "Trailing data" },
112 { LWRES_R_INCOMPLETE, "Incomplete" },
113 { LWRES_R_RETRY, "Retry" },
114 { LWRES_R_TYPENOTFOUND, "Type not found" },
115 { LWRES_R_TOOLARGE, "Too large" },
119 static int hf_length = -1;
120 static int hf_version = -1;
121 static int hf_flags = -1;
122 static int hf_serial = -1;
123 static int hf_opcode = -1;
124 static int hf_result = -1;
125 static int hf_recvlen = -1;
126 static int hf_authtype = -1;
127 static int hf_authlen = -1;
129 static int hf_rflags = -1;
130 static int hf_rdclass = -1;
131 static int hf_rdtype = -1;
132 static int hf_namelen = -1;
133 static int hf_req_name = -1;
135 static int hf_ttl = -1;
136 static int hf_nrdatas = -1;
137 static int hf_nsigs = -1;
138 static int hf_realnamelen = -1;
139 static int hf_realname = -1;
142 static int hf_a_record = -1;
143 static int hf_a_rec_len = -1;
144 static int hf_srv_prio = -1;
145 static int hf_srv_weight = -1;
146 static int hf_srv_port = -1;
148 static int hf_adn_flags = -1;
149 static int hf_adn_addrtype = -1;
150 static int hf_adn_namelen = -1;
151 static int hf_adn_name = -1;
153 static int hf_adn_realname = -1;
154 static int hf_adn_aliasname = -1;
156 static int hf_adn_naddrs = -1;
157 static int hf_adn_naliases = -1;
158 static int hf_adn_family = -1;
159 static int hf_adn_addr_len = -1;
160 static int hf_adn_addr_addr = -1;
163 static int ett_lwres = -1;
164 static int ett_rdata_req = -1;
165 static int ett_rdata_resp = -1;
166 static int ett_a_rec = -1;
167 static int ett_a_rec_addr = -1;
168 static int ett_srv_rec = -1;
169 static int ett_srv_rec_item = -1;
170 static int ett_adn_request = -1;
171 static int ett_adn_resp = -1;
172 static int ett_adn_alias = -1;
173 static int ett_adn_addr = -1;
174 static int ett_nba_request = -1;
175 static int ett_nba_resp = -1;
176 static int ett_noop = -1;
178 static int ett_mx_rec = -1;
179 static int ett_mx_rec_item = -1;
181 static int ett_ns_rec = -1;
182 static int ett_ns_rec_item = -1;
186 #define LWRES_UDP_PORT 921
188 static guint global_lwres_port = LWRES_UDP_PORT;
190 void proto_reg_handoff_lwres(void);
193 /* Define the lwres proto */
194 static int proto_lwres = -1;
197 /* Define many many headers for mgcp */
199 static const value_string message_types_values[] = {
208 lwres_get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
209 char *name, int maxname)
211 int start_offset = offset;
214 int chars_processed = 0;
215 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
219 const int min_len = 1; /* Minimum length of encoded name (for root) */
220 /* If we're about to return a value (probably negative) which is less
221 * than the minimum length, we're looking at bad data and we're liable
222 * to put the dissector into a loop. Instead we throw an exception */
224 maxname--; /* reserve space for the trailing '\0' */
226 component_len = tvb_get_guint8(tvb, offset);
228 if (component_len == 0)
231 switch (component_len & 0xc0) {
236 /* Not the first component - put in a '.'. */
242 while (component_len > 0) {
244 *np++ = tvb_get_guint8(tvb, offset);
254 /* Extended label (RFC 2673) */
255 switch (component_len & 0x3f) {
258 /* Bitstring label */
265 bit_count = tvb_get_guint8(tvb, offset);
267 label_len = (bit_count - 1) / 8 + 1;
271 print_len = g_snprintf(np, maxname + 1, "\\[x");
272 if (print_len != -1 && print_len < maxname + 1) {
273 /* Some versions of g_snprintf return -1 if they'd truncate
276 maxname -= print_len;
278 /* Nothing printed, as there's no room.
279 Suppress all subsequent printing. */
285 print_len = g_snprintf(np, maxname + 1, "%02x",
286 tvb_get_guint8(tvb, offset));
287 if (print_len != -1 && print_len < maxname + 1) {
288 /* Some versions of g_snprintf return -1 if they'd truncate
291 maxname -= print_len;
293 /* Nothing printed, as there's no room.
294 Suppress all subsequent printing. */
301 print_len = g_snprintf(np, maxname + 1, "/%d]", bit_count);
302 if (print_len != -1 && print_len < maxname + 1) {
303 /* Some versions of g_snprintf return -1 if they'd truncate
306 maxname -= print_len;
308 /* Nothing printed, as there's no room.
309 Suppress all subsequent printing. */
317 g_strlcpy(name, "<Unknown extended label>", maxname);
318 /* Parsing will propably fail from here on, since the */
319 /* label length is unknown... */
320 len = offset - start_offset;
322 THROW(ReportedBoundsError);
328 THROW(ReportedBoundsError);
332 indir_offset = dns_data_offset +
333 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
337 /* If "len" is negative, we are still working on the original name,
338 not something pointed to by a pointer, and so we should set "len"
339 to the length of the original name. */
341 len = offset - start_offset;
343 /* If we've looked at every character in the message, this pointer
344 will make us look at some character again, which means we're
346 if (chars_processed >= data_size) {
347 g_strlcpy(name, "<Name contains a pointer that loops>", maxname);
349 THROW(ReportedBoundsError);
353 offset = indir_offset;
354 break; /* now continue processing from there */
359 /* If "len" is negative, we haven't seen a pointer, and thus haven't
360 set the length, so set it. */
362 len = offset - start_offset;
363 /* Zero-length name means "root server" */
365 g_strlcpy(name, "<Root>", maxname);
367 THROW(ReportedBoundsError);
372 static void dissect_getnamebyaddr_request(tvbuff_t* tvb, proto_tree* lwres_tree)
374 guint32 flags,family;
375 guint16 addrlen, slen;
378 proto_item* nba_request_item;
379 proto_tree* nba_request_tree;
381 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
382 family = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
383 addrlen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
384 addr = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH + 10, 4);
385 slen = (int)strlen(ip_to_str(addr));
389 nba_request_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,LWRES_LWPACKET_LENGTH+14,"getnamebyaddr parameters");
390 nba_request_tree = proto_item_add_subtree(nba_request_item, ett_nba_request);
394 proto_tree_add_uint(nba_request_tree,
397 LWRES_LWPACKET_LENGTH,
401 proto_tree_add_uint(nba_request_tree,
404 LWRES_LWPACKET_LENGTH + 4,
408 proto_tree_add_uint(nba_request_tree,
411 LWRES_LWPACKET_LENGTH + 8,
415 proto_tree_add_string(nba_request_tree,
418 LWRES_LWPACKET_LENGTH + 10,
424 static void dissect_getnamebyaddr_response(tvbuff_t* tvb, proto_tree* lwres_tree)
426 guint32 flags,i, offset;
427 guint16 naliases,realnamelen,aliaslen;
432 proto_item* nba_resp_item;
433 proto_tree* nba_resp_tree;
435 proto_item* alias_item;
436 proto_tree* alias_tree;
440 nba_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10,"getnamebyaddr records");
441 nba_resp_tree = proto_item_add_subtree(nba_resp_item, ett_nba_resp);
445 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
446 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
447 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH + 4 + 2);
448 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 4 + 2 + 2, realnamelen, (guint8*)realname);
449 realname[realnamelen]='\0';
451 proto_tree_add_uint(nba_resp_tree,
454 LWRES_LWPACKET_LENGTH,
457 proto_tree_add_uint(nba_resp_tree,
460 LWRES_LWPACKET_LENGTH + 4,
464 proto_tree_add_uint(nba_resp_tree,
467 LWRES_LWPACKET_LENGTH + 6,
471 proto_tree_add_string(nba_resp_tree,
474 LWRES_LWPACKET_LENGTH + 8,
478 offset=LWRES_LWPACKET_LENGTH + 8 + realnamelen;
482 for(i=0; i<naliases; i++)
484 aliaslen = tvb_get_ntohs(tvb, offset);
485 tvb_get_nstringz(tvb, offset + 2, aliaslen, (guint8*)aliasname);
486 aliasname[aliaslen]='\0';
488 alias_item = proto_tree_add_text(nba_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
489 alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
491 proto_tree_add_uint(alias_tree,
498 proto_tree_add_string(alias_tree,
505 offset+=(2 + aliaslen + 1);
510 static void dissect_getaddrsbyname_request(tvbuff_t* tvb, proto_tree* lwres_tree)
512 guint32 flags,addrtype;
516 proto_item* adn_request_item;
517 proto_tree* adn_request_tree;
519 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
520 addrtype = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
521 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
522 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
527 adn_request_item = proto_tree_add_text(lwres_tree,tvb,
528 LWRES_LWPACKET_LENGTH,10+namelen+1,
529 "getaddrbyname parameters");
530 adn_request_tree = proto_item_add_subtree(adn_request_item, ett_adn_request);
536 proto_tree_add_uint(adn_request_tree,
539 LWRES_LWPACKET_LENGTH+0,
543 proto_tree_add_uint(adn_request_tree,
546 LWRES_LWPACKET_LENGTH+4,
550 proto_tree_add_uint(adn_request_tree,
553 LWRES_LWPACKET_LENGTH+8,
557 proto_tree_add_string(adn_request_tree,
560 LWRES_LWPACKET_LENGTH+10,
567 static void dissect_getaddrsbyname_response(tvbuff_t* tvb, proto_tree* lwres_tree)
569 guint32 flags, family ,i, offset;
570 guint16 naliases, naddrs, realnamelen, length, aliaslen;
576 proto_item* adn_resp_item;
577 proto_tree* adn_resp_tree;
578 proto_item* alias_item;
579 proto_tree* alias_tree;
580 proto_item* addr_item;
581 proto_tree* addr_tree;
587 adn_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "getaddrbyname records");
588 adn_resp_tree = proto_item_add_subtree(adn_resp_item, ett_adn_resp);
592 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
593 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
594 naddrs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 6);
595 realnamelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
596 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 10, realnamelen, (guint8*)realname);
597 realname[realnamelen]='\0';
600 proto_tree_add_uint(adn_resp_tree,
603 LWRES_LWPACKET_LENGTH,
607 proto_tree_add_uint(adn_resp_tree,
610 LWRES_LWPACKET_LENGTH + 4,
614 proto_tree_add_uint(adn_resp_tree,
617 LWRES_LWPACKET_LENGTH + 6,
621 proto_tree_add_uint(adn_resp_tree,
624 LWRES_LWPACKET_LENGTH + 8,
628 proto_tree_add_string(adn_resp_tree,
631 LWRES_LWPACKET_LENGTH + 10,
635 offset = LWRES_LWPACKET_LENGTH + 10 + realnamelen + 1;
639 for(i=0; i<naliases; i++)
641 aliaslen = tvb_get_ntohs(tvb, offset);
642 tvb_get_nstringz(tvb, offset + 2, aliaslen, (guint8*)aliasname);
643 aliasname[aliaslen]='\0';
645 alias_item = proto_tree_add_text(adn_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
646 alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
648 proto_tree_add_uint(alias_tree,
655 proto_tree_add_string(alias_tree,
662 offset+=(2 + aliaslen + 1);
668 for(i=0; i < naddrs; i++)
670 family = tvb_get_ntohl(tvb, offset);
671 length = tvb_get_ntohs(tvb, offset + 4);
672 addr = (gchar*)tvb_get_ptr(tvb, offset + 6, 4);
673 slen = (int)strlen((char*)ip_to_str((guint8*)addr));
675 addr_item = proto_tree_add_text(adn_resp_tree,tvb, offset, 4+2+4, "Address %s",ip_to_str((guint8*)addr));
676 addr_tree = proto_item_add_subtree(addr_item, ett_adn_addr);
678 proto_tree_add_uint(addr_tree,
685 proto_tree_add_uint(addr_tree,
692 proto_tree_add_string(addr_tree,
697 ip_to_str((guint8*)addr));
706 static void dissect_a_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
711 proto_item* a_rec_item;
712 proto_tree* a_rec_tree;
713 proto_item* addr_item;
714 proto_tree* addr_tree;
718 a_rec_item = proto_tree_add_text(tree,tvb,offset,
719 ((sizeof(guint32) + sizeof(guint16)) * nrec),"A records");
721 a_rec_tree = proto_item_add_subtree(a_rec_item, ett_a_rec);
726 for(i=0; i<nrec; i++)
729 curr = offset + ((sizeof(guint32)+sizeof(guint16)) * i);
731 len = tvb_get_ntohs(tvb,curr);
732 addr = (gchar*)tvb_get_ptr(tvb,curr+2,4);
736 addr_item = proto_tree_add_text(a_rec_tree,tvb, curr, 6,"IP Address");
737 addr_tree = proto_item_add_subtree(addr_item, ett_a_rec_addr);
738 proto_item_set_text(addr_item,"Address %s",ip_to_str((guint8*)addr));
742 proto_tree_add_uint(addr_tree,
749 proto_tree_add_text(addr_tree,
754 ip_to_str((guint8*)addr));
760 static void dissect_srv_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
763 guint16 len, priority, weight, port, namelen, dlen;
767 proto_item* srv_rec_item, *rec_item;
768 proto_item* srv_rec_tree, *rec_tree;
772 srv_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "SRV records");
773 srv_rec_tree = proto_item_add_subtree(srv_rec_item, ett_srv_rec);
774 proto_item_set_text(srv_rec_item, "SRV records (%d)", nrec);
780 for(i=0; i < nrec; i++)
782 len = tvb_get_ntohs(tvb, curr);
783 priority = tvb_get_ntohs(tvb, curr + 2);
784 weight = tvb_get_ntohs(tvb, curr + 4);
785 port = tvb_get_ntohs(tvb, curr + 6);
787 cmpname = (char*)tvb_get_ptr(tvb, curr + 8, namelen);
789 dlen = lwres_get_dns_name(tvb, curr + 8, curr, (gchar*)dname, sizeof(dname));
793 rec_item = proto_tree_add_text(srv_rec_tree, tvb, curr, 6," ");
794 rec_tree = proto_item_add_subtree(rec_item, ett_srv_rec_item);
795 proto_item_set_text(rec_item,
796 "SRV record:pri=%d,w=%d,port=%d,dname=%s",
804 proto_tree_add_uint(rec_tree,
811 proto_tree_add_uint(rec_tree,
818 proto_tree_add_uint(rec_tree,
826 proto_tree_add_text(rec_tree,
832 curr+=((sizeof(short)*4) + dlen);
838 static void dissect_mx_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
842 guint16 len, priority, dlen, namelen;
846 proto_item* mx_rec_item, *rec_item;
847 proto_tree* mx_rec_tree, *rec_tree;
852 mx_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "MX records (%d)", nrec);
853 mx_rec_tree = proto_item_add_subtree(mx_rec_item, ett_mx_rec);
859 for(i=0; i < nrec; i++)
861 len = tvb_get_ntohs(tvb, curr);
862 priority = tvb_get_ntohs(tvb, curr + 2);
864 cname = (char*)tvb_get_ptr(tvb, curr + 4, 4);
865 dlen = lwres_get_dns_name(tvb, curr + 4, curr, (gchar*)dname, sizeof(dname));
868 rec_item = proto_tree_add_text(mx_rec_tree, tvb, curr,6,"MX record: pri=%d,dname=%s",
870 rec_tree = proto_item_add_subtree(rec_item, ett_mx_rec_item);
876 proto_tree_add_uint(rec_tree,
883 proto_tree_add_text(rec_tree,
889 curr+=((sizeof(short)*2) + dlen);
896 static void dissect_ns_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
899 guint16 len, dlen, namelen;
902 proto_item* ns_rec_item, *rec_item;
903 proto_tree* ns_rec_tree, *rec_tree;
907 ns_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "NS record (%d)", nrec);
908 ns_rec_tree = proto_item_add_subtree(ns_rec_item, ett_ns_rec);
916 len = tvb_get_ntohs(tvb, curr);
918 dlen = lwres_get_dns_name(tvb, curr + 2, curr, (char*)dname, sizeof(dname));
921 rec_item = proto_tree_add_text(ns_rec_tree, tvb, curr,4, "NS record: dname=%s",dname);
922 rec_tree = proto_item_add_subtree(rec_item, ett_ns_rec_item);
927 proto_tree_add_text(rec_tree,
932 curr+=(sizeof(short) + dlen);
939 static void dissect_rdata_request(tvbuff_t* tvb, proto_tree* lwres_tree)
942 guint16 rdclass, rdtype, namelen;
945 proto_item* rdata_request_item;
946 proto_tree* rdata_request_tree;
948 rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
949 rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
950 rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
951 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+8);
952 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
958 proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,10+namelen+1,"RDATA request parameters");
959 rdata_request_tree = proto_item_add_subtree(rdata_request_item, ett_rdata_req);
964 proto_tree_add_uint(rdata_request_tree,
967 LWRES_LWPACKET_LENGTH+0,
971 proto_tree_add_uint(rdata_request_tree,
974 LWRES_LWPACKET_LENGTH+4,
978 proto_tree_add_uint(rdata_request_tree,
981 LWRES_LWPACKET_LENGTH+6,
985 proto_tree_add_uint(rdata_request_tree,
988 LWRES_LWPACKET_LENGTH+8,
992 proto_tree_add_string(rdata_request_tree,
995 LWRES_LWPACKET_LENGTH+10,
1001 static void dissect_rdata_response(tvbuff_t* tvb, proto_tree* lwres_tree)
1003 guint32 rflags, ttl, offset;
1004 guint16 rdclass, rdtype, nrdatas, nsigs, realnamelen;
1005 guint8 realname[120];
1007 proto_item* rdata_resp_item;
1008 proto_tree* rdata_resp_tree;
1010 rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
1011 rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
1012 rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
1013 ttl = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+8);
1014 nrdatas = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+12);
1015 nsigs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+14);
1016 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH+16);
1017 tvb_get_nstringz(tvb,LWRES_LWPACKET_LENGTH+18,realnamelen, realname);
1018 realname[realnamelen]='\0';
1020 offset = LWRES_LWPACKET_LENGTH + 18 + realnamelen + 1;
1024 rdata_resp_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH, 18+realnamelen+1,"RDATA response");
1025 rdata_resp_tree = proto_item_add_subtree(rdata_resp_item, ett_rdata_resp);
1030 proto_tree_add_uint(rdata_resp_tree,
1033 LWRES_LWPACKET_LENGTH+0,
1037 proto_tree_add_uint(rdata_resp_tree,
1040 LWRES_LWPACKET_LENGTH+4,
1044 proto_tree_add_uint(rdata_resp_tree,
1047 LWRES_LWPACKET_LENGTH+6,
1051 proto_tree_add_uint(rdata_resp_tree,
1054 LWRES_LWPACKET_LENGTH+8,
1058 proto_tree_add_uint(rdata_resp_tree,
1061 LWRES_LWPACKET_LENGTH+12,
1065 proto_tree_add_uint(rdata_resp_tree,
1068 LWRES_LWPACKET_LENGTH+14,
1072 proto_tree_add_uint(rdata_resp_tree,
1075 LWRES_LWPACKET_LENGTH+16,
1079 proto_tree_add_string(rdata_resp_tree,
1082 LWRES_LWPACKET_LENGTH+18,
1089 dissect_a_records(tvb,rdata_resp_tree,nrdatas,offset);
1093 dissect_srv_records(tvb,rdata_resp_tree,nrdatas, offset);
1097 dissect_mx_records(tvb,rdata_resp_tree,nrdatas, offset);
1101 dissect_ns_records(tvb,rdata_resp_tree,nrdatas, offset);
1107 static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
1112 proto_item* noop_item;
1113 proto_tree* noop_tree;
1115 datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);
1116 data = (char*)tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH, datalen);
1120 noop_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "Noop record");
1121 noop_tree = proto_item_add_subtree(noop_item, ett_noop);
1126 proto_tree_add_uint(noop_tree,
1129 LWRES_LWPACKET_LENGTH,
1135 static void dissect_getaddrsbyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1138 dissect_getaddrsbyname_request(tvb, lwres_tree);
1140 dissect_getaddrsbyname_response(tvb, lwres_tree);
1143 static void dissect_getnamebyaddr(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1146 dissect_getnamebyaddr_request(tvb, lwres_tree);
1148 dissect_getnamebyaddr_response(tvb, lwres_tree);
1151 static void dissect_getrdatabyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1154 dissect_rdata_request(tvb, lwres_tree);
1156 dissect_rdata_response(tvb, lwres_tree);
1160 dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1162 guint16 version, flags, authtype, authlength ;
1163 guint32 length, opcode, result, recvlength, serial;
1164 guint32 message_type;
1166 proto_item* lwres_item;
1167 proto_tree* lwres_tree;
1169 col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res");
1170 length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET);
1171 version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET);
1172 flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET);
1173 serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET);
1174 opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET);
1175 result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET);
1176 recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET);
1177 authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET);
1178 authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET);
1180 message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1;
1182 if (check_col(pinfo->cinfo, COL_INFO)) {
1183 col_clear(pinfo->cinfo, COL_INFO);
1185 if(flags & LWRES_LWPACKETFLAG_RESPONSE)
1187 col_add_fstr(pinfo->cinfo, COL_INFO,
1188 "%s, opcode=%s, serial=0x%x, result=%s",
1189 val_to_str((guint32)message_type,message_types_values,"unknown"),
1190 val_to_str(opcode, opcode_values, "unknown"),
1192 val_to_str(result,result_values,"unknown"));
1196 col_add_fstr(pinfo->cinfo, COL_INFO,
1197 "%s, opcode=%s, serial=0x%x",
1198 val_to_str((guint32)message_type,message_types_values,"unknown"),
1199 val_to_str(opcode, opcode_values, "unknown"),
1206 lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, FALSE);
1207 lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres);
1212 proto_tree_add_uint(lwres_tree,
1220 proto_tree_add_uint(lwres_tree,
1230 proto_tree_add_uint(lwres_tree,
1237 proto_tree_add_uint(lwres_tree,
1244 proto_tree_add_uint(lwres_tree,
1251 proto_tree_add_uint(lwres_tree,
1258 proto_tree_add_uint(lwres_tree,
1265 proto_tree_add_uint(lwres_tree,
1272 proto_tree_add_uint(lwres_tree,
1283 case LWRES_OPCODE_NOOP:
1284 dissect_noop(tvb, lwres_tree);
1287 case LWRES_OPCODE_GETADDRSBYNAME:
1288 dissect_getaddrsbyname(tvb, lwres_tree, message_type);
1291 case LWRES_OPCODE_GETNAMEBYADDR:
1292 dissect_getnamebyaddr(tvb, lwres_tree, message_type);
1295 case LWRES_OPCODE_GETRDATABYNAME:
1296 dissect_getrdatabyname(tvb, lwres_tree, message_type);
1305 proto_register_lwres(void)
1307 static hf_register_info hf[] = {
1309 { "Length", "lwres.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1310 "lwres length", HFILL }},
1313 { "Version", "lwres.version", FT_UINT16, BASE_DEC, NULL, 0x0,
1314 "lwres version", HFILL }},
1317 { "Packet Flags", "lwres.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1318 "lwres flags", HFILL }},
1321 { "Serial", "lwres.serial", FT_UINT32, BASE_HEX, NULL, 0x0,
1322 "lwres serial", HFILL }},
1325 { "Operation code", "lwres.opcode", FT_UINT32, BASE_DEC, VALS(opcode_values), 0x0,
1326 "lwres opcode", HFILL }},
1329 { "Result", "lwres.result", FT_UINT32, BASE_DEC, VALS(result_values), 0x0,
1330 "lwres result", HFILL }},
1333 { "Received length", "lwres.recvlen", FT_UINT32, BASE_DEC, NULL, 0x0,
1334 "lwres recvlen", HFILL }},
1337 { "Auth. type", "lwres.authtype", FT_UINT16, BASE_DEC, NULL, 0x0,
1338 "lwres authtype", HFILL }},
1341 { "Auth. length", "lwres.authlen" , FT_UINT16, BASE_DEC, NULL, 0x0,
1342 "lwres authlen", HFILL }},
1345 { "Flags", "lwres.rflags", FT_UINT32, BASE_HEX, NULL, 0x0,
1346 "lwres rflags", HFILL }},
1348 { "Class", "lwres.class", FT_UINT16, BASE_DEC, NULL, 0x0,
1349 "lwres class", HFILL }},
1352 { "Type", "lwres.type", FT_UINT16, BASE_DEC, VALS(t_types), 0x0,
1353 "lwres type" , HFILL }},
1356 { "Name length", "lwres.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1357 "lwres namelen", HFILL }},
1360 { "Domain name" , "lwres.reqdname" , FT_STRING, BASE_NONE, NULL, 0x0,
1361 "lwres reqdname", HFILL }},
1364 { "Time To Live", "lwres.ttl", FT_UINT32, BASE_DEC, NULL, 0x0,
1365 "lwres ttl", HFILL }},
1368 { "Number of rdata records", "lwres.nrdatas", FT_UINT16, BASE_DEC, NULL, 0x0,
1369 "lwres nrdatas" , HFILL }},
1372 { "Number of signature records", "lwres.nsigs", FT_UINT16, BASE_DEC, NULL, 0x0,
1373 "lwres nsigs" , HFILL }},
1376 { "Real name length", "lwres.realnamelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1377 "lwres realnamelen", HFILL }},
1380 { "Real doname name", "lwres.realname", FT_STRING, BASE_NONE, NULL, 0x0,
1381 "lwres realname", HFILL }},
1384 { "IPv4 Address", "lwres.arecord", FT_UINT32, BASE_DEC, NULL, 0x0,
1385 "lwres arecord", HFILL }},
1388 { "Length", "lwres.areclen", FT_UINT16, BASE_DEC, NULL, 0x0,
1389 "lwres areclen", HFILL }},
1392 { "Priority", "lwres.srv.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
1393 "lwres srv prio", HFILL }},
1396 { "Weight", "lwres.srv.weight", FT_UINT16, BASE_DEC, NULL, 0x0,
1397 "lwres srv weight", HFILL }},
1400 { "Port" , "lwres.srv.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1401 "lwres srv port", HFILL }},
1404 { "Flags", "lwres.adn.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
1405 "lwres adn flags", HFILL }},
1408 { "Address type", "lwres.adn.addrtype", FT_UINT32, BASE_DEC, NULL, 0x0,
1409 "lwres adn addrtype", HFILL }},
1412 { "Name length", "lwres.adn.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1413 "lwres adn namelen", HFILL }},
1416 { "Name", "lwres.adn.name", FT_STRING, BASE_NONE, NULL, 0x0,
1417 "lwres adn name", HFILL }},
1420 { "Number of aliases", "lwres.adn.naliases", FT_UINT16, BASE_DEC, NULL, 0x0,
1421 "lwres adn naliases", HFILL }},
1424 { "Number of addresses", "lwres.adn.naddrs", FT_UINT16, BASE_DEC, NULL, 0x0,
1425 "lwres adn naddrs", HFILL }},
1428 { "Real name", "lwres.adn.realname", FT_STRING, BASE_NONE, NULL, 0x0,
1429 "lwres adn realname", HFILL }},
1431 { &hf_adn_aliasname,
1432 { "Alias name", "lwres.adn.aliasname", FT_STRING, BASE_NONE, NULL, 0x0,
1433 "lwres adn aliasname", HFILL }},
1436 { "Address family", "lwres.adn.addr.family", FT_UINT32, BASE_DEC, NULL, 0x0,
1437 "lwres adn addr family", HFILL }},
1440 { "Address length", "lwres.adn.addr.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1441 "lwres adn addr length", HFILL }},
1443 { &hf_adn_addr_addr,
1444 { "IP Address", "lwres.adn.addr.addr", FT_STRING, BASE_NONE, NULL, 0x0,
1445 "lwres adn addr addr", HFILL }},
1447 /* Add more fields here */
1450 static gint *ett[] = {
1472 module_t *lwres_module;
1474 proto_lwres = proto_register_protocol("Light Weight DNS RESolver (BIND9)",
1477 proto_register_field_array(proto_lwres, hf, array_length(hf));
1478 proto_register_subtree_array(ett, array_length(ett));
1480 lwres_module = prefs_register_protocol(proto_lwres, proto_reg_handoff_lwres);
1482 prefs_register_uint_preference(lwres_module, "udp.lwres_port",
1483 "lwres listener UDP Port",
1484 "Set the UDP port for lwres daemon"
1485 "(if other than the default of 921)",
1486 10, &global_lwres_port);
1490 /* The registration hand-off routine */
1492 proto_reg_handoff_lwres(void)
1494 static gboolean lwres_prefs_initialized = FALSE;
1495 static dissector_handle_t lwres_handle;
1496 static guint lwres_port;
1498 if(!lwres_prefs_initialized) {
1499 lwres_handle = create_dissector_handle(dissect_lwres, proto_lwres);
1500 lwres_prefs_initialized = TRUE;
1503 dissector_delete("udp.port", lwres_port, lwres_handle);
1506 dissector_add("udp.port", global_lwres_port, lwres_handle);
1507 lwres_port = global_lwres_port;