2 * Routines for light weight reslover (lwres, part of BIND9) packet disassembly
4 * $Id: packet-lwres.c,v 1.1 2003/08/05 05:03:30 guy Exp $
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"
40 #include "plugins/plugin_api_defs.h"
42 #define LWRES_LWPACKET_LENGTH (4 * 5 + 2 * 4)
43 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
44 #define LWRES_LWPACKETVERSION_0 0
46 #define LW_LENGTH_OFFSET 0
47 #define LW_VERSION_OFFSET 4
48 #define LW_PKTFLASG_OFFSET 6
49 #define LW_SERIAL_OFFSET 8
50 #define LW_OPCODE_OFFSET 12
51 #define LW_RESULT_OFFSET 16
52 #define LW_RECVLEN_OFFSET 20
53 #define LW_AUTHTYPE_OFFSET 24
54 #define LW_AUTHLEN_OFFSET 26
57 #define LWRES_OPCODE_NOOP 0x00000000U
58 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
59 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
60 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
62 static const value_string opcode_values[] = {
63 { LWRES_OPCODE_NOOP, "Noop" },
64 { LWRES_OPCODE_GETADDRSBYNAME, "getaddrbyname" },
65 { LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr" },
66 { LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname" },
71 #define LWRES_R_SUCCESS 0
72 #define LWRES_R_NOMEMORY 1
73 #define LWRES_R_TIMEOUT 2
74 #define LWRES_R_NOTFOUND 3
75 #define LWRES_R_UNEXPECTEDEND 4 /* unexpected end of input */
76 #define LWRES_R_FAILURE 5 /* generic failure */
77 #define LWRES_R_IOERROR 6
78 #define LWRES_R_NOTIMPLEMENTED 7
79 #define LWRES_R_UNEXPECTED 8
80 #define LWRES_R_TRAILINGDATA 9
81 #define LWRES_R_INCOMPLETE 10
82 #define LWRES_R_RETRY 11
83 #define LWRES_R_TYPENOTFOUND 12
84 #define LWRES_R_TOOLARGE 13
92 static const value_string t_types[] = {
103 static const value_string result_values[] = {
104 { LWRES_R_SUCCESS, "Success" },
105 { LWRES_R_NOMEMORY, "No memory" },
106 { LWRES_R_TIMEOUT, "Timeout" },
107 { LWRES_R_NOTFOUND, "Not found" },
108 { LWRES_R_UNEXPECTEDEND, "Unexpected end of input" },
109 { LWRES_R_FAILURE, "Generic failure" },
110 { LWRES_R_IOERROR, "I/O Error" },
111 { LWRES_R_UNEXPECTED, "Unexpected" },
112 { LWRES_R_TRAILINGDATA, "Trailing data" },
113 { LWRES_R_INCOMPLETE, "Incompete" },
114 { LWRES_R_RETRY, "Retry" },
115 { LWRES_R_TYPENOTFOUND, "Type not found" },
116 { LWRES_R_TOOLARGE, "Too large" },
120 static int hf_length = -1;
121 static int hf_version = -1;
122 static int hf_flags = -1;
123 static int hf_serial = -1;
124 static int hf_opcode = -1;
125 static int hf_result = -1;
126 static int hf_recvlen = -1;
127 static int hf_authtype = -1;
128 static int hf_authlen = -1;
130 static int hf_rflags = -1;
131 static int hf_rdclass = -1;
132 static int hf_rdtype = -1;
133 static int hf_namelen = -1;
134 static int hf_req_name = -1;
136 static int hf_ttl = -1;
137 static int hf_nrdatas = -1;
138 static int hf_nsigs = -1;
139 static int hf_realnamelen = -1;
140 static int hf_realname = -1;
143 static int hf_a_record = -1;
144 static int hf_a_rec_len = -1;
145 static int hf_srv_prio = -1;
146 static int hf_srv_weight = -1;
147 static int hf_srv_port = -1;
149 static int hf_adn_flags = -1;
150 static int hf_adn_addrtype = -1;
151 static int hf_adn_namelen = -1;
152 static int hf_adn_name = -1;
154 static int hf_adn_realname = -1;
155 static int hf_adn_aliasname = -1;
157 static int hf_adn_naddrs = -1;
158 static int hf_adn_naliases = -1;
159 static int hf_adn_family = -1;
160 static int hf_adn_addr_len = -1;
161 static int hf_adn_addr_addr = -1;
164 static int ett_lwres = -1;
165 static int ett_rdata_req = -1;
166 static int ett_rdata_resp = -1;
167 static int ett_a_rec = -1;
168 static int ett_a_rec_addr = -1;
169 static int ett_srv_rec = -1;
170 static int ett_srv_rec_item = -1;
171 static int ett_adn_request = -1;
172 static int ett_adn_resp = -1;
173 static int ett_adn_alias = -1;
174 static int ett_adn_addr = -1;
175 static int ett_nba_request = -1;
176 static int ett_nba_resp = -1;
177 static int ett_noop = -1;
179 static int ett_mx_rec = -1;
180 static int ett_mx_rec_item = -1;
182 static int ett_ns_rec = -1;
183 static int ett_ns_rec_item = -1;
187 #ifndef __ETHEREAL_STATIC__
188 G_MODULE_EXPORT const gchar version[] = VERSION;
192 #define LWRES_UDP_PORT 921
194 static guint global_lwres_port = LWRES_UDP_PORT;
195 static guint lwres_port = LWRES_UDP_PORT;
197 void proto_reg_handoff_lwres(void);
200 /* Define the lwres proto */
201 static int proto_lwres = -1;
204 /* Define many many headers for mgcp */
206 static const value_string message_types_values[] = {
215 ip_to_str_buf(const guint8 *ad, gchar *buf)
221 gboolean saw_nonzero;
235 if (saw_nonzero || digit != 0)
248 ip_to_str(const guint8 *ad) {
249 static gchar str[4][16];
252 if (cur == &str[0][0]) {
254 } else if (cur == &str[1][0]) {
256 } else if (cur == &str[2][0]) {
261 ip_to_str_buf(ad, cur);
267 get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
268 char *name, int maxname)
270 int start_offset = offset;
273 int chars_processed = 0;
274 int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
278 const int min_len = 1; /* Minimum length of encoded name (for root) */
279 /* If we're about to return a value (probably negative) which is less
280 * than the minimum length, we're looking at bad data and we're liable
281 * to put the dissector into a loop. Instead we throw an exception */
283 maxname--; /* reserve space for the trailing '\0' */
285 component_len = tvb_get_guint8(tvb, offset);
287 if (component_len == 0)
290 switch (component_len & 0xc0) {
295 /* Not the first component - put in a '.'. */
301 while (component_len > 0) {
303 *np++ = tvb_get_guint8(tvb, offset);
313 /* Extended label (RFC 2673) */
314 switch (component_len & 0x3f) {
317 /* Bitstring label */
324 bit_count = tvb_get_guint8(tvb, offset);
326 label_len = (bit_count - 1) / 8 + 1;
330 print_len = snprintf(np, maxname + 1, "\\[x");
331 if (print_len != -1) {
332 /* Some versions of snprintf return -1 if they'd truncate
335 maxname -= print_len;
337 /* Nothing printed, as there's no room.
338 Suppress all subsequent printing. */
344 print_len = snprintf(np, maxname + 1, "%02x",
345 tvb_get_guint8(tvb, offset));
346 if (print_len != -1) {
347 /* Some versions of snprintf return -1 if they'd truncate
350 maxname -= print_len;
352 /* Nothing printed, as there's no room.
353 Suppress all subsequent printing. */
360 print_len = snprintf(np, maxname + 1, "/%d]", bit_count);
361 if (print_len != -1) {
362 /* Some versions of snprintf return -1 if they'd truncate
365 maxname -= print_len;
367 /* Nothing printed, as there's no room.
368 Suppress all subsequent printing. */
376 strcpy(name, "<Unknown extended label>");
377 /* Parsing will propably fail from here on, since the */
378 /* label length is unknown... */
379 len = offset - start_offset;
381 THROW(ReportedBoundsError);
387 THROW(ReportedBoundsError);
391 indir_offset = dns_data_offset +
392 (((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
396 /* If "len" is negative, we are still working on the original name,
397 not something pointed to by a pointer, and so we should set "len"
398 to the length of the original name. */
400 len = offset - start_offset;
402 /* If we've looked at every character in the message, this pointer
403 will make us look at some character again, which means we're
405 if (chars_processed >= data_size) {
406 strcpy(name, "<Name contains a pointer that loops>");
408 THROW(ReportedBoundsError);
412 offset = indir_offset;
413 break; /* now continue processing from there */
418 /* If "len" is negative, we haven't seen a pointer, and thus haven't
419 set the length, so set it. */
421 len = offset - start_offset;
422 /* Zero-length name means "root server" */
424 strcpy(name, "<Root>");
426 THROW(ReportedBoundsError);
431 static void dissect_getnamebyaddr_request(tvbuff_t* tvb, proto_tree* lwres_tree)
433 guint32 flags,family;
434 guint16 addrlen, slen;
437 proto_item* nba_request_item;
438 proto_tree* nba_request_tree;
440 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
441 family = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
442 addrlen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
443 addr = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH + 10, 4);
444 slen = strlen((char*)ip_to_str(addr));
448 nba_request_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,LWRES_LWPACKET_LENGTH+14,"getnamebyaddr parameters");
449 nba_request_tree = proto_item_add_subtree(nba_request_item, ett_nba_request);
453 proto_tree_add_uint(nba_request_tree,
456 LWRES_LWPACKET_LENGTH,
460 proto_tree_add_uint(nba_request_tree,
463 LWRES_LWPACKET_LENGTH + 4,
467 proto_tree_add_uint(nba_request_tree,
470 LWRES_LWPACKET_LENGTH + 8,
474 proto_tree_add_string(nba_request_tree,
477 LWRES_LWPACKET_LENGTH + 10,
483 static void dissect_getnamebyaddr_response(tvbuff_t* tvb, proto_tree* lwres_tree)
485 guint32 flags,i, offset;
486 guint16 naliases,realnamelen,aliaslen;
491 proto_item* nba_resp_item;
492 proto_tree* nba_resp_tree;
494 proto_item* alias_item;
495 proto_tree* alias_tree;
499 nba_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10,"getnamebyaddr records");
500 nba_resp_tree = proto_item_add_subtree(nba_resp_item, ett_nba_resp);
504 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
505 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
506 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH + 4 + 2);
507 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 4 + 2 + 2, realnamelen, realname);
508 realname[realnamelen]='\0';
510 proto_tree_add_uint(nba_resp_tree,
513 LWRES_LWPACKET_LENGTH,
516 proto_tree_add_uint(nba_resp_tree,
519 LWRES_LWPACKET_LENGTH + 4,
523 proto_tree_add_uint(nba_resp_tree,
526 LWRES_LWPACKET_LENGTH + 6,
530 proto_tree_add_string(nba_resp_tree,
533 LWRES_LWPACKET_LENGTH + 8,
537 offset=LWRES_LWPACKET_LENGTH + 8 + realnamelen;
541 for(i=0; i<naliases; i++)
543 aliaslen = tvb_get_ntohs(tvb, offset);
544 tvb_get_nstringz(tvb, offset + 2, aliaslen, aliasname);
545 aliasname[aliaslen]='\0';
547 alias_item = proto_tree_add_text(nba_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
548 alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
550 proto_tree_add_uint(alias_tree,
557 proto_tree_add_string(alias_tree,
564 offset+=(2 + aliaslen + 1);
569 static void dissect_getaddrsbyname_request(tvbuff_t* tvb, proto_tree* lwres_tree)
571 guint32 flags,addrtype;
575 proto_item* adn_request_item;
576 proto_tree* adn_request_tree;
578 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
579 addrtype = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
580 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
581 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
586 adn_request_item = proto_tree_add_text(lwres_tree,tvb,
587 LWRES_LWPACKET_LENGTH,10+namelen+1,
588 "getaddrbyname parameters");
589 adn_request_tree = proto_item_add_subtree(adn_request_item, ett_adn_request);
595 proto_tree_add_uint(adn_request_tree,
598 LWRES_LWPACKET_LENGTH+0,
602 proto_tree_add_uint(adn_request_tree,
605 LWRES_LWPACKET_LENGTH+4,
609 proto_tree_add_uint(adn_request_tree,
612 LWRES_LWPACKET_LENGTH+8,
616 proto_tree_add_string(adn_request_tree,
619 LWRES_LWPACKET_LENGTH+10,
626 static void dissect_getaddrsbyname_response(tvbuff_t* tvb, proto_tree* lwres_tree)
628 guint32 flags, family ,i, offset;
629 guint16 naliases, naddrs, realnamelen, length, aliaslen;
635 proto_item* adn_resp_item;
636 proto_tree* adn_resp_tree;
637 proto_item* alias_item;
638 proto_tree* alias_tree;
639 proto_item* addr_item;
640 proto_tree* addr_tree;
646 adn_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "getaddrbyname records");
647 adn_resp_tree = proto_item_add_subtree(adn_resp_item, ett_adn_resp);
651 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
652 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
653 naddrs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 6);
654 realnamelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
655 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 10, realnamelen, realname);
656 realname[realnamelen]='\0';
659 proto_tree_add_uint(adn_resp_tree,
662 LWRES_LWPACKET_LENGTH,
666 proto_tree_add_uint(adn_resp_tree,
669 LWRES_LWPACKET_LENGTH + 4,
673 proto_tree_add_uint(adn_resp_tree,
676 LWRES_LWPACKET_LENGTH + 6,
680 proto_tree_add_uint(adn_resp_tree,
683 LWRES_LWPACKET_LENGTH + 8,
687 proto_tree_add_string(adn_resp_tree,
690 LWRES_LWPACKET_LENGTH + 10,
694 offset = LWRES_LWPACKET_LENGTH + 10 + realnamelen + 1;
698 for(i=0; i<naliases; i++)
700 aliaslen = tvb_get_ntohs(tvb, offset);
701 tvb_get_nstringz(tvb, offset + 2, aliaslen, aliasname);
702 aliasname[aliaslen]='\0';
704 alias_item = proto_tree_add_text(adn_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
705 alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
707 proto_tree_add_uint(alias_tree,
714 proto_tree_add_string(alias_tree,
721 offset+=(2 + aliaslen + 1);
727 for(i=0; i < naddrs; i++)
729 family = tvb_get_ntohl(tvb, offset);
730 length = tvb_get_ntohs(tvb, offset + 4);
731 addr = tvb_get_ptr(tvb, offset + 6, 4);
732 slen = strlen((char*)ip_to_str(addr));
734 addr_item = proto_tree_add_text(adn_resp_tree,tvb, offset, 4+2+4, "Address %s",ip_to_str(addr));
735 addr_tree = proto_item_add_subtree(addr_item, ett_adn_addr);
737 proto_tree_add_uint(addr_tree,
744 proto_tree_add_uint(addr_tree,
751 proto_tree_add_string(addr_tree,
765 static void dissect_a_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
770 proto_item* a_rec_item;
771 proto_tree* a_rec_tree;
772 proto_item* addr_item;
773 proto_tree* addr_tree;
777 a_rec_item = proto_tree_add_text(tree,tvb,offset,
778 ((sizeof(guint32) + sizeof(guint16)) * nrec),"A records");
780 a_rec_tree = proto_item_add_subtree(a_rec_item, ett_a_rec);
785 for(i=0; i<nrec; i++)
788 curr = offset + ((sizeof(guint32)+sizeof(guint16)) * i);
790 len = tvb_get_ntohs(tvb,curr);
791 addr = tvb_get_ptr(tvb,curr+2,4);
795 addr_item = proto_tree_add_text(a_rec_tree,tvb, curr, 6,"IP Address");
796 addr_tree = proto_item_add_subtree(addr_item, ett_a_rec_addr);
797 proto_item_set_text(addr_item,"Address %s",ip_to_str(addr));
801 proto_tree_add_uint(addr_tree,
808 proto_tree_add_text(addr_tree,
819 static void dissect_srv_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
822 guint16 len, priority, weight, port, namelen, dlen;
826 proto_item* srv_rec_item, *rec_item;
827 proto_item* srv_rec_tree, *rec_tree;
831 srv_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "SRV records");
832 srv_rec_tree = proto_item_add_subtree(srv_rec_item, ett_srv_rec);
833 proto_item_set_text(srv_rec_item, "SRV records (%d)", nrec);
839 for(i=0; i < nrec; i++)
841 len = tvb_get_ntohs(tvb, curr);
842 priority = tvb_get_ntohs(tvb, curr + 2);
843 weight = tvb_get_ntohs(tvb, curr + 4);
844 port = tvb_get_ntohs(tvb, curr + 6);
846 cmpname = tvb_get_ptr(tvb, curr + 8, namelen);
848 dlen = get_dns_name(tvb, curr + 8, curr, dname, sizeof(dname));
852 rec_item = proto_tree_add_text(srv_rec_tree, tvb, curr, 6," ");
853 rec_tree = proto_item_add_subtree(rec_item, ett_srv_rec_item);
854 proto_item_set_text(rec_item,
855 "SRV record:pri=%d,w=%d,port=%d,dname=%s",
863 proto_tree_add_uint(rec_tree,
870 proto_tree_add_uint(rec_tree,
877 proto_tree_add_uint(rec_tree,
885 proto_tree_add_text(rec_tree,
891 curr+=((sizeof(short)*4) + dlen);
897 static void dissect_mx_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
901 guint16 len, priority, dlen, namelen;
905 proto_item* mx_rec_item, *rec_item;
906 proto_tree* mx_rec_tree, *rec_tree;
911 mx_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "MX records (%d)", nrec);
912 mx_rec_tree = proto_item_add_subtree(mx_rec_item, ett_mx_rec);
918 for(i=0; i < nrec; i++)
920 len = tvb_get_ntohs(tvb, curr);
921 priority = tvb_get_ntohs(tvb, curr + 2);
923 cname = tvb_get_ptr(tvb, curr + 4, 4);
924 dlen = get_dns_name(tvb, curr + 4, curr, dname, sizeof(dname));
927 rec_item = proto_tree_add_text(mx_rec_tree, tvb, curr,6,"MX record: pri=%d,dname=%s",
929 rec_tree = proto_item_add_subtree(rec_item, ett_mx_rec_item);
935 proto_tree_add_uint(rec_tree,
942 proto_tree_add_text(rec_tree,
948 curr+=((sizeof(short)*2) + dlen);
955 static void dissect_ns_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
958 guint16 len, dlen, namelen;
961 proto_item* ns_rec_item, *rec_item;
962 proto_tree* ns_rec_tree, *rec_tree;
966 ns_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "NS record (%d)", nrec);
967 ns_rec_tree = proto_item_add_subtree(ns_rec_item, ett_ns_rec);
975 len = tvb_get_ntohs(tvb, curr);
977 dlen = get_dns_name(tvb, curr + 2, curr, dname, sizeof(dname));
980 rec_item = proto_tree_add_text(ns_rec_tree, tvb, curr,4, "NS record: dname=%s",dname);
981 rec_tree = proto_item_add_subtree(rec_item, ett_ns_rec_item);
986 proto_tree_add_text(rec_tree,
991 curr+=(sizeof(short) + dlen);
998 static void dissect_rdata_request(tvbuff_t* tvb, proto_tree* lwres_tree)
1001 guint16 rdclass, rdtype, namelen;
1004 proto_item* rdata_request_item;
1005 proto_tree* rdata_request_tree;
1007 rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
1008 rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
1009 rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
1010 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+8);
1011 tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
1016 rdata_request_item =
1017 proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,10+namelen+1,"RDATA request parameters");
1018 rdata_request_tree = proto_item_add_subtree(rdata_request_item, ett_rdata_req);
1023 proto_tree_add_uint(rdata_request_tree,
1026 LWRES_LWPACKET_LENGTH+0,
1030 proto_tree_add_uint(rdata_request_tree,
1033 LWRES_LWPACKET_LENGTH+4,
1037 proto_tree_add_uint(rdata_request_tree,
1040 LWRES_LWPACKET_LENGTH+6,
1044 proto_tree_add_uint(rdata_request_tree,
1047 LWRES_LWPACKET_LENGTH+8,
1051 proto_tree_add_string(rdata_request_tree,
1054 LWRES_LWPACKET_LENGTH+10,
1060 static void dissect_rdata_response(tvbuff_t* tvb, proto_tree* lwres_tree)
1062 guint32 rflags, ttl, offset;
1063 guint16 rdclass, rdtype, nrdatas, nsigs, realnamelen;
1064 guint8 realname[120];
1066 proto_item* rdata_resp_item;
1067 proto_tree* rdata_resp_tree;
1069 rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
1070 rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
1071 rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
1072 ttl = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+8);
1073 nrdatas = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+12);
1074 nsigs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+14);
1075 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH+16);
1076 tvb_get_nstringz(tvb,LWRES_LWPACKET_LENGTH+18,realnamelen, realname);
1077 realname[realnamelen]='\0';
1079 offset = LWRES_LWPACKET_LENGTH + 18 + realnamelen + 1;
1083 rdata_resp_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH, 18+realnamelen+1,"RDATA response");
1084 rdata_resp_tree = proto_item_add_subtree(rdata_resp_item, ett_rdata_resp);
1089 proto_tree_add_uint(rdata_resp_tree,
1092 LWRES_LWPACKET_LENGTH+0,
1096 proto_tree_add_uint(rdata_resp_tree,
1099 LWRES_LWPACKET_LENGTH+4,
1103 proto_tree_add_uint(rdata_resp_tree,
1106 LWRES_LWPACKET_LENGTH+6,
1110 proto_tree_add_uint(rdata_resp_tree,
1113 LWRES_LWPACKET_LENGTH+8,
1117 proto_tree_add_uint(rdata_resp_tree,
1120 LWRES_LWPACKET_LENGTH+12,
1124 proto_tree_add_uint(rdata_resp_tree,
1127 LWRES_LWPACKET_LENGTH+14,
1131 proto_tree_add_uint(rdata_resp_tree,
1134 LWRES_LWPACKET_LENGTH+16,
1138 proto_tree_add_string(rdata_resp_tree,
1141 LWRES_LWPACKET_LENGTH+18,
1148 dissect_a_records(tvb,rdata_resp_tree,nrdatas,offset);
1152 dissect_srv_records(tvb,rdata_resp_tree,nrdatas, offset);
1156 dissect_mx_records(tvb,rdata_resp_tree,nrdatas, offset);
1160 dissect_ns_records(tvb,rdata_resp_tree,nrdatas, offset);
1166 static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
1171 proto_item* noop_item;
1172 proto_tree* noop_tree;
1174 datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);
1175 data = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH, datalen);
1179 noop_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "Noop record");
1180 noop_tree = proto_item_add_subtree(noop_item, ett_noop);
1185 proto_tree_add_uint(noop_tree,
1188 LWRES_LWPACKET_LENGTH,
1194 static void dissect_getaddrsbyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1197 dissect_getaddrsbyname_request(tvb, lwres_tree);
1199 dissect_getaddrsbyname_response(tvb, lwres_tree);
1202 static void dissect_getnamebyaddr(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1205 dissect_getnamebyaddr_request(tvb, lwres_tree);
1207 dissect_getnamebyaddr_response(tvb, lwres_tree);
1210 static void dissect_getrdatabyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
1213 dissect_rdata_request(tvb, lwres_tree);
1215 dissect_rdata_response(tvb, lwres_tree);
1219 dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1221 guint16 version, flags, authtype, authlength ;
1222 guint32 length, opcode, result, recvlength, serial;
1223 guint32 message_type;
1225 proto_item* lwres_item;
1226 proto_tree* lwres_tree;
1228 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1229 col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res");
1230 length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET);
1231 version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET);
1232 flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET);
1233 serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET);
1234 opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET);
1235 result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET);
1236 recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET);
1237 authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET);
1238 authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET);
1240 message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1;
1242 if (check_col(pinfo->cinfo, COL_INFO)) {
1243 col_clear(pinfo->cinfo, COL_INFO);
1245 if(flags & LWRES_LWPACKETFLAG_RESPONSE)
1247 col_add_fstr(pinfo->cinfo, COL_INFO,
1248 "%s, opcode=%s, serial=0x%x, result=%s",
1249 val_to_str((guint32)message_type,message_types_values,"unknown"),
1250 val_to_str(opcode, opcode_values, "unknown"),
1252 val_to_str(result,result_values,"unknown"));
1256 col_add_fstr(pinfo->cinfo, COL_INFO,
1257 "%s, opcode=%s, serial=0x%x",
1258 val_to_str((guint32)message_type,message_types_values,"unknown"),
1259 val_to_str(opcode, opcode_values, "unknown"),
1266 lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, FALSE);
1267 lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres);
1272 proto_tree_add_uint(lwres_tree,
1280 proto_tree_add_uint(lwres_tree,
1290 proto_tree_add_uint(lwres_tree,
1297 proto_tree_add_uint(lwres_tree,
1304 proto_tree_add_uint(lwres_tree,
1311 proto_tree_add_uint(lwres_tree,
1318 proto_tree_add_uint(lwres_tree,
1325 proto_tree_add_uint(lwres_tree,
1332 proto_tree_add_uint(lwres_tree,
1343 case LWRES_OPCODE_NOOP:
1344 dissect_noop(tvb, lwres_tree);
1347 case LWRES_OPCODE_GETADDRSBYNAME:
1348 dissect_getaddrsbyname(tvb, lwres_tree, message_type);
1351 case LWRES_OPCODE_GETNAMEBYADDR:
1352 dissect_getnamebyaddr(tvb, lwres_tree, message_type);
1355 case LWRES_OPCODE_GETRDATABYNAME:
1356 dissect_getrdatabyname(tvb, lwres_tree, message_type);
1365 proto_register_lwres(void)
1367 static hf_register_info hf[] = {
1369 { "Length", "lwres.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1370 "lwres length", HFILL }},
1373 { "Version", "lwres.version", FT_UINT16, BASE_DEC, NULL, 0x0,
1374 "lwres legth", HFILL }},
1377 { "Packet Flags", "lwres.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1378 "lwres flags", HFILL }},
1381 { "Serial", "lwres.serial", FT_UINT32, BASE_HEX, NULL, 0x0,
1382 "lwres serial", HFILL }},
1385 { "Operation code", "lwres.opcode", FT_UINT32, BASE_DEC, VALS(opcode_values), 0x0,
1386 "lwres opcode", HFILL }},
1389 { "Result", "lwres.result", FT_UINT32, BASE_DEC, VALS(result_values), 0x0,
1390 "lwres result", HFILL }},
1393 { "Received length", "lwres.recvlen", FT_UINT32, BASE_DEC, NULL, 0x0,
1394 "lwres recvlen", HFILL }},
1397 { "Auth. type", "lwres.authtype", FT_UINT16, BASE_DEC, NULL, 0x0,
1398 "lwres authtype", HFILL }},
1401 { "Auth. length", "lwres.authlen" , FT_UINT16, BASE_DEC, NULL, 0x0,
1402 "lwres authlen", HFILL }},
1405 { "Flags", "lwres.rflags", FT_UINT32, BASE_HEX, NULL, 0x0,
1406 "lwres rflags", HFILL }},
1408 { "Class", "lwres.class", FT_UINT16, BASE_DEC, NULL, 0x0,
1409 "lwres class", HFILL }},
1412 { "Type", "lwres.type", FT_UINT16, BASE_DEC, VALS(t_types), 0x0,
1413 "lwres type" , HFILL }},
1416 { "Name length", "lwres.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1417 "lwres namelen", HFILL }},
1420 { "Domain name" , "lwres.reqdname" , FT_STRING, BASE_DEC, NULL, 0x0,
1421 "lwres reqdname", HFILL }},
1424 { "Time To Live", "lwres.ttl", FT_UINT32, BASE_DEC, NULL, 0x0,
1425 "lwres ttl", HFILL }},
1428 { "Number of rdata records", "lwres.nrdatas", FT_UINT16, BASE_DEC, NULL, 0x0,
1429 "lwres nrdatas" , HFILL }},
1432 { "Number of signature records", "lwres.nsigs", FT_UINT16, BASE_DEC, NULL, 0x0,
1433 "lwres nsigs" , HFILL }},
1436 { "Real name length", "lwres.realnamelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1437 "lwres realnamelen", HFILL }},
1440 { "Real doname name", "lwres.realname", FT_STRING, BASE_DEC, NULL, 0x0,
1441 "lwres realname", HFILL }},
1444 { "IPv4 Address", "lwres.arecord", FT_UINT32, BASE_DEC, NULL, 0x0,
1445 "lwres arecord", HFILL }},
1448 { "Length", "lwres.areclen", FT_UINT16, BASE_DEC, NULL, 0x0,
1449 "lwres areclen", HFILL }},
1452 { "Priority", "lwres.srv.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
1453 "lwres srv prio", HFILL }},
1456 { "Weight", "lwres.srv.weight", FT_UINT16, BASE_DEC, NULL, 0x0,
1457 "lwres srv weight", HFILL }},
1460 { "Port" , "lwres.srv.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1461 "lwres srv port", HFILL }},
1464 { "Flags", "lwres.adn.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
1465 "lwres adn flags", HFILL }},
1468 { "Address type", "lwres.adn.addrtype", FT_UINT32, BASE_DEC, NULL, 0x0,
1469 "lwres adn addrtype", HFILL }},
1472 { "Name length", "lwres.adn.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1473 "lwres adn namelen", HFILL }},
1476 { "Name", "lwres.adn.name", FT_STRING, BASE_DEC, NULL, 0x0,
1477 "lwres adn name", HFILL }},
1480 { "Number of aliases", "lwres.adn.naliases", FT_UINT16, BASE_DEC, NULL, 0x0,
1481 "lwres adn naliases", HFILL }},
1484 { "Number of addresses", "lwres.adn.naddrs", FT_UINT16, BASE_DEC, NULL, 0x0,
1485 "lwres adn naddrs", HFILL }},
1488 { "Real name", "lwres.adn.realname", FT_STRING, BASE_DEC, NULL, 0x0,
1489 "lwres adn realname", HFILL }},
1491 { &hf_adn_aliasname,
1492 { "Alias name", "lwres.adn.aliasname", FT_STRING, BASE_DEC, NULL, 0x0,
1493 "lwres adn aliasname", HFILL }},
1496 { "Address family", "lwres.adn.addr.family", FT_UINT32, BASE_DEC, NULL, 0x0,
1497 "lwres adn addr family", HFILL }},
1500 { "Address length", "lwres.adn.addr.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1501 "lwres adn addr lenght", HFILL }},
1503 { &hf_adn_addr_addr,
1504 { "IP Address", "lwres.adn.addr.addr", FT_STRING, BASE_DEC, NULL, 0x0,
1505 "lwres adn addr addr", HFILL }},
1507 /* Add more fields here */
1510 static gint *ett[] = {
1532 module_t *lwres_module;
1534 proto_lwres = proto_register_protocol("Light Weight DNS RESolver (BIND9)",
1537 proto_register_field_array(proto_lwres, hf, array_length(hf));
1538 proto_register_subtree_array(ett, array_length(ett));
1540 lwres_module = prefs_register_protocol(proto_lwres, proto_reg_handoff_lwres);
1542 prefs_register_uint_preference(lwres_module, "udp.lwres_port",
1543 "lwres listener UDP Port",
1544 "Set the UDP port for lwres daemon"
1545 "(if other than the default of 921)",
1546 10, &global_lwres_port);
1550 /* The registration hand-off routine */
1552 proto_reg_handoff_lwres(void)
1554 static int lwres_prefs_initialized = FALSE;
1555 static dissector_handle_t lwres_handle;
1557 if(!lwres_prefs_initialized) {
1558 lwres_handle = create_dissector_handle(dissect_lwres, proto_lwres);
1559 lwres_prefs_initialized = TRUE;
1562 dissector_delete("udp.port",global_lwres_port, lwres_handle);
1566 lwres_port = global_lwres_port;
1568 dissector_add("udp.port", lwres_port, lwres_handle);
1572 /* Start the functions we need for the plugin stuff */
1574 #ifndef __ETHEREAL_STATIC__
1576 G_MODULE_EXPORT void
1577 plugin_reg_handoff(void){
1578 proto_reg_handoff_lwres();
1581 G_MODULE_EXPORT void
1582 plugin_init(plugin_address_table_t *pat
1583 #ifndef PLUGINS_NEED_ADDRESS_TABLE
1587 /* initialise the table of pointers needed in Win32 DLLs */
1588 plugin_address_table_init(pat);
1589 /* register the new protocol, protocol fields, and subtrees */
1590 if (proto_lwres == -1) { /* execute protocol initialization only once */
1591 proto_register_lwres();
1597 /* End the functions we need for plugin stuff */