MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-lwres.c
blobac1903c4c2d23e2285536ccf281685706c39d0f7
1 /* packet-lwres.c
2 * Routines for light weight reslover (lwres, part of BIND9) packet disassembly
4 * $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <string.h>
31 #include <glib.h>
33 #include <epan/packet.h>
34 #include <epan/prefs.h>
35 #include "packet-dns.h"
37 #define LWRES_LWPACKET_LENGTH (4 * 5 + 2 * 4)
38 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
39 #define LWRES_LWPACKETVERSION_0 0
41 #define LW_LENGTH_OFFSET 0
42 #define LW_VERSION_OFFSET 4
43 #define LW_PKTFLASG_OFFSET 6
44 #define LW_SERIAL_OFFSET 8
45 #define LW_OPCODE_OFFSET 12
46 #define LW_RESULT_OFFSET 16
47 #define LW_RECVLEN_OFFSET 20
48 #define LW_AUTHTYPE_OFFSET 24
49 #define LW_AUTHLEN_OFFSET 26
51 #define LWRES_OPCODE_NOOP 0x00000000U
52 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
53 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
54 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
56 static const value_string opcode_values[] = {
57 { LWRES_OPCODE_NOOP, "Noop" },
58 { LWRES_OPCODE_GETADDRSBYNAME, "getaddrbyname" },
59 { LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr" },
60 { LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname" },
61 { 0, NULL },
65 #define LWRES_R_SUCCESS 0
66 #define LWRES_R_NOMEMORY 1
67 #define LWRES_R_TIMEOUT 2
68 #define LWRES_R_NOTFOUND 3
69 #define LWRES_R_UNEXPECTEDEND 4 /* unexpected end of input */
70 #define LWRES_R_FAILURE 5 /* generic failure */
71 #define LWRES_R_IOERROR 6
72 #define LWRES_R_NOTIMPLEMENTED 7
73 #define LWRES_R_UNEXPECTED 8
74 #define LWRES_R_TRAILINGDATA 9
75 #define LWRES_R_INCOMPLETE 10
76 #define LWRES_R_RETRY 11
77 #define LWRES_R_TYPENOTFOUND 12
78 #define LWRES_R_TOOLARGE 13
80 #define T_A 1
81 #define T_NS 2
82 #define T_MX 15
83 #define T_SRV 33
86 static const value_string t_types[] = {
87 { T_A, "T_A" },
88 { T_NS, "T_NS" },
89 { T_MX, "T_MX" },
90 { T_SRV, "T_SRV" },
91 { 0, NULL },
97 static const value_string result_values[] = {
98 { LWRES_R_SUCCESS, "Success" },
99 { LWRES_R_NOMEMORY, "No memory" },
100 { LWRES_R_TIMEOUT, "Timeout" },
101 { LWRES_R_NOTFOUND, "Not found" },
102 { LWRES_R_UNEXPECTEDEND, "Unexpected end of input" },
103 { LWRES_R_FAILURE, "Generic failure" },
104 { LWRES_R_IOERROR, "I/O Error" },
105 { LWRES_R_UNEXPECTED, "Unexpected" },
106 { LWRES_R_TRAILINGDATA, "Trailing data" },
107 { LWRES_R_INCOMPLETE, "Incomplete" },
108 { LWRES_R_RETRY, "Retry" },
109 { LWRES_R_TYPENOTFOUND, "Type not found" },
110 { LWRES_R_TOOLARGE, "Too large" },
111 { 0, NULL },
114 static int hf_length = -1;
115 static int hf_version = -1;
116 static int hf_flags = -1;
117 static int hf_serial = -1;
118 static int hf_opcode = -1;
119 static int hf_result = -1;
120 static int hf_recvlen = -1;
121 static int hf_authtype = -1;
122 static int hf_authlen = -1;
124 static int hf_rflags = -1;
125 static int hf_rdclass = -1;
126 static int hf_rdtype = -1;
127 static int hf_namelen = -1;
128 static int hf_req_name = -1;
130 static int hf_ttl = -1;
131 static int hf_nrdatas = -1;
132 static int hf_nsigs = -1;
133 static int hf_realnamelen = -1;
134 static int hf_realname = -1;
137 /* static int hf_a_record = -1; */
138 static int hf_a_rec_len = -1;
139 static int hf_srv_prio = -1;
140 static int hf_srv_weight = -1;
141 static int hf_srv_port = -1;
143 static int hf_adn_flags = -1;
144 static int hf_adn_addrtype = -1;
145 static int hf_adn_namelen = -1;
146 static int hf_adn_name = -1;
148 static int hf_adn_realname = -1;
149 static int hf_adn_aliasname = -1;
151 static int hf_adn_naddrs = -1;
152 static int hf_adn_naliases = -1;
153 static int hf_adn_family = -1;
154 static int hf_adn_addr_len = -1;
155 static int hf_adn_addr_addr = -1;
158 static int ett_lwres = -1;
159 static int ett_rdata_req = -1;
160 static int ett_rdata_resp = -1;
161 static int ett_a_rec = -1;
162 static int ett_a_rec_addr = -1;
163 static int ett_srv_rec = -1;
164 static int ett_srv_rec_item = -1;
165 static int ett_adn_request = -1;
166 static int ett_adn_resp = -1;
167 static int ett_adn_alias = -1;
168 static int ett_adn_addr = -1;
169 static int ett_nba_request = -1;
170 static int ett_nba_resp = -1;
171 static int ett_noop = -1;
173 static int ett_mx_rec = -1;
174 static int ett_mx_rec_item = -1;
176 static int ett_ns_rec = -1;
177 static int ett_ns_rec_item = -1;
181 #define LWRES_UDP_PORT 921
183 static guint global_lwres_port = LWRES_UDP_PORT;
185 void proto_reg_handoff_lwres(void);
188 /* Define the lwres proto */
189 static int proto_lwres = -1;
192 /* Define many many headers for mgcp */
194 static const value_string message_types_values[] = {
195 { 1, "REQUEST " },
196 { 2, "RESPONSE" },
197 { 0, NULL },
200 static void dissect_getnamebyaddr_request(tvbuff_t* tvb, proto_tree* lwres_tree)
202 guint32 flags,family;
203 guint16 addrlen, slen;
204 const char* addrs;
206 proto_item* nba_request_item;
207 proto_tree* nba_request_tree;
209 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
210 family = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
211 addrlen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
212 addrs = tvb_ip_to_str(tvb, LWRES_LWPACKET_LENGTH + 10);
213 slen = (int)strlen(addrs);
215 if(lwres_tree)
217 nba_request_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,LWRES_LWPACKET_LENGTH+14,"getnamebyaddr parameters");
218 nba_request_tree = proto_item_add_subtree(nba_request_item, ett_nba_request);
220 else return;
222 proto_tree_add_uint(nba_request_tree, hf_adn_flags, tvb,
223 LWRES_LWPACKET_LENGTH, 4, flags);
225 proto_tree_add_uint(nba_request_tree, hf_adn_family, tvb,
226 LWRES_LWPACKET_LENGTH + 4, 4, family);
228 proto_tree_add_uint(nba_request_tree, hf_adn_addr_len, tvb,
229 LWRES_LWPACKET_LENGTH + 8, 2, addrlen);
231 proto_tree_add_string(nba_request_tree, hf_adn_addr_addr, tvb,
232 LWRES_LWPACKET_LENGTH + 10, slen, addrs);
236 static void dissect_getnamebyaddr_response(tvbuff_t* tvb, proto_tree* lwres_tree)
238 guint32 i, offset;
239 guint16 naliases,realnamelen,aliaslen;
240 gchar *aliasname;
243 proto_item* nba_resp_item;
244 proto_tree* nba_resp_tree;
246 proto_item* alias_item;
247 proto_tree* alias_tree;
249 if(lwres_tree)
251 nba_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10,"getnamebyaddr records");
252 nba_resp_tree = proto_item_add_subtree(nba_resp_item, ett_nba_resp);
254 else return;
256 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
257 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH + 4 + 2);
259 proto_tree_add_item(nba_resp_tree,
260 hf_adn_flags,
261 tvb,
262 LWRES_LWPACKET_LENGTH,
264 ENC_BIG_ENDIAN);
265 proto_tree_add_item(nba_resp_tree,
266 hf_adn_naliases,
267 tvb,
268 LWRES_LWPACKET_LENGTH + 4,
270 ENC_BIG_ENDIAN);
272 proto_tree_add_item(nba_resp_tree,
273 hf_adn_namelen,
274 tvb,
275 LWRES_LWPACKET_LENGTH + 6,
277 ENC_BIG_ENDIAN);
279 proto_tree_add_item(nba_resp_tree,
280 hf_adn_realname,
281 tvb,
282 LWRES_LWPACKET_LENGTH + 8,
283 realnamelen,
284 ENC_ASCII|ENC_NA);
286 offset=LWRES_LWPACKET_LENGTH + 8 + realnamelen;
288 if(naliases)
290 for(i=0; i<naliases; i++)
292 aliaslen = tvb_get_ntohs(tvb, offset);
293 aliasname = tvb_get_string(wmem_packet_scope(), tvb, offset + 2, aliaslen);
295 alias_item = proto_tree_add_text(nba_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
296 alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
298 proto_tree_add_item(alias_tree,
299 hf_adn_namelen,
300 tvb,
301 offset,
303 ENC_BIG_ENDIAN);
305 proto_tree_add_item(alias_tree,
306 hf_adn_aliasname,
307 tvb,
308 offset + 2,
309 aliaslen,
310 ENC_ASCII|ENC_NA);
312 offset+=(2 + aliaslen + 1);
317 static void dissect_getaddrsbyname_request(tvbuff_t* tvb, proto_tree* lwres_tree)
319 guint16 namelen;
321 proto_item* adn_request_item;
322 proto_tree* adn_request_tree;
324 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
326 if(lwres_tree)
328 adn_request_item = proto_tree_add_text(lwres_tree,tvb,
329 LWRES_LWPACKET_LENGTH,10+namelen+1,
330 "getaddrbyname parameters");
331 adn_request_tree = proto_item_add_subtree(adn_request_item, ett_adn_request);
333 else
334 return;
337 proto_tree_add_item(adn_request_tree,
338 hf_adn_flags,
339 tvb,
340 LWRES_LWPACKET_LENGTH+0,
341 sizeof(guint32),
342 ENC_BIG_ENDIAN);
344 proto_tree_add_item(adn_request_tree,
345 hf_adn_addrtype,
346 tvb,
347 LWRES_LWPACKET_LENGTH+4,
348 sizeof(guint32),
349 ENC_BIG_ENDIAN);
351 proto_tree_add_item(adn_request_tree,
352 hf_adn_namelen,
353 tvb,
354 LWRES_LWPACKET_LENGTH+8,
355 sizeof(guint16),
356 ENC_BIG_ENDIAN);
358 proto_tree_add_item(adn_request_tree,
359 hf_adn_name,
360 tvb,
361 LWRES_LWPACKET_LENGTH+10,
362 namelen,
363 ENC_ASCII|ENC_NA);
368 static void dissect_getaddrsbyname_response(tvbuff_t* tvb, proto_tree* lwres_tree)
370 guint32 family ,i, offset;
371 guint16 naliases, naddrs, realnamelen, length, aliaslen;
372 const gchar* addrs;
373 guint slen;
374 gchar *aliasname;
376 proto_item *adn_resp_item;
377 proto_tree *adn_resp_tree;
378 proto_item *alias_item;
379 proto_tree *alias_tree;
380 proto_item *addr_item;
381 proto_tree *addr_tree;
385 if(lwres_tree)
387 adn_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "getaddrbyname records");
388 adn_resp_tree = proto_item_add_subtree(adn_resp_item, ett_adn_resp);
390 else return;
392 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
393 naddrs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 6);
394 realnamelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
397 proto_tree_add_item(adn_resp_tree, hf_adn_flags, tvb,
398 LWRES_LWPACKET_LENGTH, 4, ENC_BIG_ENDIAN);
400 proto_tree_add_item(adn_resp_tree, hf_adn_naliases, tvb,
401 LWRES_LWPACKET_LENGTH + 4, 2, ENC_BIG_ENDIAN);
403 proto_tree_add_item(adn_resp_tree, hf_adn_naddrs, tvb,
404 LWRES_LWPACKET_LENGTH + 6, 2, ENC_BIG_ENDIAN);
406 proto_tree_add_item(adn_resp_tree, hf_adn_namelen, tvb,
407 LWRES_LWPACKET_LENGTH + 8, 2, ENC_BIG_ENDIAN);
409 proto_tree_add_item(adn_resp_tree, hf_adn_realname, tvb,
410 LWRES_LWPACKET_LENGTH + 10, realnamelen, ENC_ASCII|ENC_NA);
412 offset = LWRES_LWPACKET_LENGTH + 10 + realnamelen + 1;
414 if(naliases)
416 for(i=0; i<naliases; i++)
418 aliaslen = tvb_get_ntohs(tvb, offset);
419 aliasname = tvb_get_string(wmem_packet_scope(), tvb, offset + 2, aliaslen);
421 alias_item = proto_tree_add_text(adn_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
422 alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
424 proto_tree_add_uint(alias_tree, hf_adn_namelen, tvb,
425 offset, 2, aliaslen);
427 proto_tree_add_item(alias_tree, hf_adn_aliasname, tvb,
428 offset + 2, aliaslen, ENC_ASCII|ENC_NA);
430 offset+=(2 + aliaslen + 1);
434 if(naddrs)
436 for(i=0; i < naddrs; i++)
438 family = tvb_get_ntohl(tvb, offset);
439 length = tvb_get_ntohs(tvb, offset + 4);
440 addrs = tvb_ip_to_str(tvb, offset + 6);
441 slen = (int)strlen(addrs);
443 addr_item = proto_tree_add_text(adn_resp_tree,tvb, offset, 4+2+4, "Address %s", addrs);
444 addr_tree = proto_item_add_subtree(addr_item, ett_adn_addr);
446 proto_tree_add_uint(addr_tree, hf_adn_family, tvb,
447 offset, 4, family);
449 proto_tree_add_uint(addr_tree, hf_adn_addr_len, tvb,
450 offset + 4, 2, length);
452 proto_tree_add_string(addr_tree, hf_adn_addr_addr, tvb,
453 offset + 6, slen, addrs);
455 offset+= 4 + 2 + 4;
462 static void dissect_a_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
464 guint32 i, curr;
465 const gchar* addrs;
466 guint16 len;
467 proto_item* a_rec_item;
468 proto_tree* a_rec_tree;
469 proto_item* addr_item;
470 proto_tree* addr_tree;
472 if(tree)
474 a_rec_item = proto_tree_add_text(tree,tvb,offset,
475 (int)((sizeof(guint32) + sizeof(guint16)) * nrec),"A records");
477 a_rec_tree = proto_item_add_subtree(a_rec_item, ett_a_rec);
479 else
480 return;
482 for(i=0; i<nrec; i++)
485 curr = offset + (int)((sizeof(guint32)+sizeof(guint16)) * i);
487 len = tvb_get_ntohs(tvb,curr);
489 addrs = tvb_ip_to_str(tvb, curr+2);
490 if(a_rec_tree)
492 addr_item = proto_tree_add_text(a_rec_tree, tvb, curr,
493 6, "Address %s", addrs);
494 addr_tree = proto_item_add_subtree(addr_item, ett_a_rec_addr);
496 else return;
498 proto_tree_add_uint(addr_tree, hf_a_rec_len, tvb, curr,
499 sizeof(guint16), len);
501 proto_tree_add_text(addr_tree, tvb, curr + 2, 4, "Addr: %s",
502 addrs);
508 static void dissect_srv_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
510 guint32 i, curr;
511 guint16 /*len, namelen,*/ priority, weight, port, dlen;
512 const guchar *dname;
514 proto_item* srv_rec_item, *rec_item;
515 proto_item* srv_rec_tree, *rec_tree;
517 if(tree)
519 srv_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "SRV records");
520 srv_rec_tree = proto_item_add_subtree(srv_rec_item, ett_srv_rec);
521 proto_item_set_text(srv_rec_item, "SRV records (%d)", nrec);
523 else return;
525 curr = offset;
527 for(i=0; i < nrec; i++)
529 /*len = tvb_get_ntohs(tvb, curr);*/
530 priority = tvb_get_ntohs(tvb, curr + 2);
531 weight = tvb_get_ntohs(tvb, curr + 4);
532 port = tvb_get_ntohs(tvb, curr + 6);
533 /*namelen = len - 8;*/
535 dlen = get_dns_name(tvb, curr + 8, 0, curr + 8, &dname);
537 if(srv_rec_tree)
539 rec_item = proto_tree_add_text(srv_rec_tree, tvb, curr, 6," ");
540 rec_tree = proto_item_add_subtree(rec_item, ett_srv_rec_item);
541 proto_item_set_text(rec_item,
542 "SRV record:pri=%d,w=%d,port=%d,dname=%s",
543 priority,
544 weight,
545 port,
546 dname);
548 else return;
550 proto_tree_add_uint(rec_tree,
551 hf_srv_prio,
552 tvb,
553 curr + 2,
555 priority);
557 proto_tree_add_uint(rec_tree,
558 hf_srv_weight,
559 tvb,
560 curr + 4,
562 weight);
564 proto_tree_add_uint(rec_tree,
565 hf_srv_port,
566 tvb,
567 curr + 6,
569 port);
572 proto_tree_add_text(rec_tree,
573 tvb,
574 curr + 8,
575 dlen,
576 "DNAME: %s", dname);
578 curr+=(int)((sizeof(short)*4) + dlen);
584 static void dissect_mx_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
587 guint i, curr;
588 guint /*len, namelen,*/ priority, dlen;
589 const guchar *dname;
591 proto_item* mx_rec_item, *rec_item;
592 proto_tree* mx_rec_tree, *rec_tree;
595 if(tree)
597 mx_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "MX records (%d)", nrec);
598 mx_rec_tree = proto_item_add_subtree(mx_rec_item, ett_mx_rec);
600 else
601 return;
603 curr = offset;
604 for(i=0; i < nrec; i++)
606 /*len = tvb_get_ntohs(tvb, curr);*/
607 priority = tvb_get_ntohs(tvb, curr + 2);
608 /*namelen = len - 4;*/
610 dlen = get_dns_name(tvb, curr + 4, 0, curr + 4, &dname);
611 if(mx_rec_tree)
613 rec_item = proto_tree_add_text(mx_rec_tree, tvb, curr,6,"MX record: pri=%d,dname=%s",
614 priority,dname);
615 rec_tree = proto_item_add_subtree(rec_item, ett_mx_rec_item);
617 else
618 return;
621 proto_tree_add_uint(rec_tree,
622 hf_srv_prio,
623 tvb,
624 curr + 2,
626 priority);
628 proto_tree_add_text(rec_tree,
629 tvb,
630 curr + 4,
631 dlen,
632 "name: %s", dname);
634 curr+=(int)((sizeof(short)*2) + dlen);
641 static void dissect_ns_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
643 guint i, curr;
644 guint /*len, namelen,*/ dlen;
645 const guchar *dname;
647 proto_item* ns_rec_item, *rec_item;
648 proto_tree* ns_rec_tree, *rec_tree;
650 if(tree)
652 ns_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "NS record (%d)", nrec);
653 ns_rec_tree = proto_item_add_subtree(ns_rec_item, ett_ns_rec);
655 else
656 return;
657 curr=offset;
659 for(i=0;i<nrec;i++)
661 /*len = tvb_get_ntohs(tvb, curr);*/
662 /*namelen = len - 2;*/
664 dlen = get_dns_name(tvb, curr + 2, 0, curr + 2, &dname);
665 if(ns_rec_tree)
667 rec_item = proto_tree_add_text(ns_rec_tree, tvb, curr,4, "NS record: dname=%s",dname);
668 rec_tree = proto_item_add_subtree(rec_item, ett_ns_rec_item);
670 else
671 return;
673 proto_tree_add_text(rec_tree,
674 tvb,
675 curr + 2,
676 dlen,
677 "Name: %s", dname);
678 curr+=(int)(sizeof(short) + dlen);
685 static void dissect_rdata_request(tvbuff_t* tvb, proto_tree* lwres_tree)
687 guint16 namelen;
689 proto_item* rdata_request_item;
690 proto_tree* rdata_request_tree;
692 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+8);
694 if(lwres_tree)
696 rdata_request_item =
697 proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,10+namelen+1,"RDATA request parameters");
698 rdata_request_tree = proto_item_add_subtree(rdata_request_item, ett_rdata_req);
700 else
701 return;
703 proto_tree_add_item(rdata_request_tree,
704 hf_rflags,
705 tvb,
706 LWRES_LWPACKET_LENGTH+0,
707 sizeof(guint32),
708 ENC_BIG_ENDIAN);
710 proto_tree_add_item(rdata_request_tree,
711 hf_rdclass,
712 tvb,
713 LWRES_LWPACKET_LENGTH+4,
714 sizeof(guint16),
715 ENC_BIG_ENDIAN);
717 proto_tree_add_item(rdata_request_tree,
718 hf_rdtype,
719 tvb,
720 LWRES_LWPACKET_LENGTH+6,
721 sizeof(guint16),
722 ENC_BIG_ENDIAN);
724 proto_tree_add_item(rdata_request_tree,
725 hf_namelen,
726 tvb,
727 LWRES_LWPACKET_LENGTH+8,
728 sizeof(guint16),
729 ENC_BIG_ENDIAN);
731 proto_tree_add_item(rdata_request_tree,
732 hf_req_name,
733 tvb,
734 LWRES_LWPACKET_LENGTH+10,
735 namelen,
736 ENC_ASCII|ENC_NA);
740 static void dissect_rdata_response(tvbuff_t* tvb, proto_tree* lwres_tree)
742 guint offset;
743 guint rdtype, nrdatas, realnamelen;
745 proto_item* rdata_resp_item;
746 proto_tree* rdata_resp_tree;
748 rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
749 nrdatas = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+12);
750 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH+16);
752 offset = LWRES_LWPACKET_LENGTH + 18 + realnamelen + 1;
754 if(lwres_tree)
756 rdata_resp_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH, 18+realnamelen+1,"RDATA response");
757 rdata_resp_tree = proto_item_add_subtree(rdata_resp_item, ett_rdata_resp);
759 else
760 return;
762 proto_tree_add_item(rdata_resp_tree,
763 hf_rflags,
764 tvb,
765 LWRES_LWPACKET_LENGTH+0,
766 sizeof(guint32),
767 ENC_BIG_ENDIAN);
769 proto_tree_add_item(rdata_resp_tree,
770 hf_rdclass,
771 tvb,
772 LWRES_LWPACKET_LENGTH+4,
773 sizeof(guint16),
774 ENC_BIG_ENDIAN);
776 proto_tree_add_item(rdata_resp_tree,
777 hf_rdtype,
778 tvb,
779 LWRES_LWPACKET_LENGTH+6,
780 sizeof(guint16),
781 ENC_BIG_ENDIAN);
783 proto_tree_add_item(rdata_resp_tree,
784 hf_ttl,
785 tvb,
786 LWRES_LWPACKET_LENGTH+8,
787 sizeof(guint32),
788 ENC_BIG_ENDIAN);
790 proto_tree_add_item(rdata_resp_tree,
791 hf_nrdatas,
792 tvb,
793 LWRES_LWPACKET_LENGTH+12,
794 sizeof(guint16),
795 ENC_BIG_ENDIAN);
797 proto_tree_add_item(rdata_resp_tree,
798 hf_nsigs,
799 tvb,
800 LWRES_LWPACKET_LENGTH+14,
801 sizeof(guint16),
802 ENC_BIG_ENDIAN);
804 proto_tree_add_item(rdata_resp_tree,
805 hf_realnamelen,
806 tvb,
807 LWRES_LWPACKET_LENGTH+16,
808 sizeof(guint16),
809 ENC_BIG_ENDIAN);
811 proto_tree_add_item(rdata_resp_tree,
812 hf_realname,
813 tvb,
814 LWRES_LWPACKET_LENGTH+18,
815 realnamelen,
816 ENC_ASCII|ENC_NA);
818 switch(rdtype)
820 case T_A:
821 dissect_a_records(tvb,rdata_resp_tree,nrdatas,offset);
822 break;
824 case T_SRV:
825 dissect_srv_records(tvb,rdata_resp_tree,nrdatas, offset);
826 break;
828 case T_MX:
829 dissect_mx_records(tvb,rdata_resp_tree,nrdatas, offset);
830 break;
832 case T_NS:
833 dissect_ns_records(tvb,rdata_resp_tree,nrdatas, offset);
834 break;
839 static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
841 guint16 datalen;
843 proto_item* noop_item;
844 proto_tree* noop_tree;
846 datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);
848 if(lwres_tree)
850 noop_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "Noop record");
851 noop_tree = proto_item_add_subtree(noop_item, ett_noop);
853 else
854 return;
856 proto_tree_add_uint(noop_tree, hf_length, tvb,
857 LWRES_LWPACKET_LENGTH, sizeof(guint16), datalen);
859 tvb_ensure_bytes_exist(tvb, LWRES_LWPACKET_LENGTH, datalen);
863 static void dissect_getaddrsbyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
865 if(type == 1)
866 dissect_getaddrsbyname_request(tvb, lwres_tree);
867 else
868 dissect_getaddrsbyname_response(tvb, lwres_tree);
871 static void dissect_getnamebyaddr(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
873 if(type == 1)
874 dissect_getnamebyaddr_request(tvb, lwres_tree);
875 else
876 dissect_getnamebyaddr_response(tvb, lwres_tree);
879 static void dissect_getrdatabyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
881 if(type == 1)
882 dissect_rdata_request(tvb, lwres_tree);
883 else
884 dissect_rdata_response(tvb, lwres_tree);
887 static void
888 dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
890 guint16 version, flags, authtype, authlength ;
891 guint32 length, opcode, result, recvlength, serial;
892 guint32 message_type;
894 proto_item* lwres_item;
895 proto_tree* lwres_tree;
897 col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res");
898 length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET);
899 version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET);
900 flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET);
901 serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET);
902 opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET);
903 result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET);
904 recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET);
905 authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET);
906 authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET);
908 message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1;
910 if(flags & LWRES_LWPACKETFLAG_RESPONSE)
912 col_add_fstr(pinfo->cinfo, COL_INFO,
913 "%s, opcode=%s, serial=0x%x, result=%s",
914 val_to_str_const((guint32)message_type,message_types_values,"unknown"),
915 val_to_str_const(opcode, opcode_values, "unknown"),
916 serial,
917 val_to_str_const(result,result_values,"unknown"));
919 else
921 col_add_fstr(pinfo->cinfo, COL_INFO,
922 "%s, opcode=%s, serial=0x%x",
923 val_to_str_const((guint32)message_type,message_types_values,"unknown"),
924 val_to_str_const(opcode, opcode_values, "unknown"),
925 serial);
928 if(tree)
930 lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, ENC_NA);
931 lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres);
933 else return;
936 proto_tree_add_uint(lwres_tree,
937 hf_length,
938 tvb,
939 LW_LENGTH_OFFSET,
940 sizeof(guint32),
941 length);
944 proto_tree_add_uint(lwres_tree,
945 hf_version,
946 tvb,
947 LW_VERSION_OFFSET,
948 sizeof(guint16),
949 version);
954 proto_tree_add_uint(lwres_tree,
955 hf_flags,
956 tvb,
957 LW_PKTFLASG_OFFSET,
958 sizeof(guint16),
959 flags);
961 proto_tree_add_uint(lwres_tree,
962 hf_serial,
963 tvb,
964 LW_SERIAL_OFFSET,
965 sizeof(guint32),
966 serial);
968 proto_tree_add_uint(lwres_tree,
969 hf_opcode,
970 tvb,
971 LW_OPCODE_OFFSET,
972 sizeof(guint32),
973 opcode);
975 proto_tree_add_uint(lwres_tree,
976 hf_result,
977 tvb,
978 LW_RESULT_OFFSET,
979 sizeof(guint32),
980 result);
982 proto_tree_add_uint(lwres_tree,
983 hf_recvlen,
984 tvb,
985 LW_RECVLEN_OFFSET,
986 sizeof(guint32),
987 recvlength);
989 proto_tree_add_uint(lwres_tree,
990 hf_authtype,
991 tvb,
992 LW_AUTHTYPE_OFFSET,
993 sizeof(guint16),
994 authtype);
996 proto_tree_add_uint(lwres_tree,
997 hf_authlen,
998 tvb,
999 LW_AUTHLEN_OFFSET,
1000 sizeof(guint16),
1001 authlength);
1003 if(!result)
1005 switch(opcode)
1007 case LWRES_OPCODE_NOOP:
1008 dissect_noop(tvb, lwres_tree);
1009 break;
1011 case LWRES_OPCODE_GETADDRSBYNAME:
1012 dissect_getaddrsbyname(tvb, lwres_tree, message_type);
1013 break;
1015 case LWRES_OPCODE_GETNAMEBYADDR:
1016 dissect_getnamebyaddr(tvb, lwres_tree, message_type);
1017 break;
1019 case LWRES_OPCODE_GETRDATABYNAME:
1020 dissect_getrdatabyname(tvb, lwres_tree, message_type);
1021 break;
1027 void
1028 proto_register_lwres(void)
1030 static hf_register_info hf[] = {
1031 { &hf_length,
1032 { "Length", "lwres.length", FT_UINT32, BASE_DEC, NULL, 0x0,
1033 "lwres length", HFILL }},
1035 { &hf_version,
1036 { "Version", "lwres.version", FT_UINT16, BASE_DEC, NULL, 0x0,
1037 "lwres version", HFILL }},
1039 { &hf_flags,
1040 { "Packet Flags", "lwres.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
1041 "lwres flags", HFILL }},
1043 { &hf_serial,
1044 { "Serial", "lwres.serial", FT_UINT32, BASE_HEX, NULL, 0x0,
1045 "lwres serial", HFILL }},
1047 { &hf_opcode,
1048 { "Operation code", "lwres.opcode", FT_UINT32, BASE_DEC, VALS(opcode_values), 0x0,
1049 "lwres opcode", HFILL }},
1051 { &hf_result,
1052 { "Result", "lwres.result", FT_UINT32, BASE_DEC, VALS(result_values), 0x0,
1053 "lwres result", HFILL }},
1055 { &hf_recvlen,
1056 { "Received length", "lwres.recvlen", FT_UINT32, BASE_DEC, NULL, 0x0,
1057 "lwres recvlen", HFILL }},
1059 { &hf_authtype,
1060 { "Auth. type", "lwres.authtype", FT_UINT16, BASE_DEC, NULL, 0x0,
1061 "lwres authtype", HFILL }},
1063 { &hf_authlen,
1064 { "Auth. length", "lwres.authlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1065 "lwres authlen", HFILL }},
1067 { &hf_rflags,
1068 { "Flags", "lwres.rflags", FT_UINT32, BASE_HEX, NULL, 0x0,
1069 "lwres rflags", HFILL }},
1070 { &hf_rdclass,
1071 { "Class", "lwres.class", FT_UINT16, BASE_DEC, NULL, 0x0,
1072 "lwres class", HFILL }},
1074 { &hf_rdtype,
1075 { "Type", "lwres.type", FT_UINT16, BASE_DEC, VALS(t_types), 0x0,
1076 "lwres type", HFILL }},
1078 { &hf_namelen,
1079 { "Name length", "lwres.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1080 "lwres namelen", HFILL }},
1082 { &hf_req_name,
1083 { "Domain name", "lwres.reqdname", FT_STRING, BASE_NONE, NULL, 0x0,
1084 "lwres reqdname", HFILL }},
1086 { &hf_ttl,
1087 { "Time To Live", "lwres.ttl", FT_UINT32, BASE_DEC, NULL, 0x0,
1088 "lwres ttl", HFILL }},
1090 { &hf_nrdatas,
1091 { "Number of rdata records", "lwres.nrdatas", FT_UINT16, BASE_DEC, NULL, 0x0,
1092 "lwres nrdatas", HFILL }},
1094 { &hf_nsigs,
1095 { "Number of signature records", "lwres.nsigs", FT_UINT16, BASE_DEC, NULL, 0x0,
1096 "lwres nsigs", HFILL }},
1098 { &hf_realnamelen,
1099 { "Real name length", "lwres.realnamelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1100 "lwres realnamelen", HFILL }},
1102 { &hf_realname,
1103 { "Real doname name", "lwres.realname", FT_STRING, BASE_NONE, NULL, 0x0,
1104 "lwres realname", HFILL }},
1106 #if 0
1107 { &hf_a_record,
1108 { "IPv4 Address", "lwres.arecord", FT_UINT32, BASE_DEC, NULL, 0x0,
1109 "lwres arecord", HFILL }},
1110 #endif
1112 { &hf_a_rec_len,
1113 { "Length", "lwres.areclen", FT_UINT16, BASE_DEC, NULL, 0x0,
1114 "lwres areclen", HFILL }},
1116 { &hf_srv_prio,
1117 { "Priority", "lwres.srv.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
1118 "lwres srv prio", HFILL }},
1120 { &hf_srv_weight,
1121 { "Weight", "lwres.srv.weight", FT_UINT16, BASE_DEC, NULL, 0x0,
1122 "lwres srv weight", HFILL }},
1124 { &hf_srv_port,
1125 { "Port" , "lwres.srv.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1126 "lwres srv port", HFILL }},
1128 { &hf_adn_flags,
1129 { "Flags", "lwres.adn.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
1130 "lwres adn flags", HFILL }},
1132 { &hf_adn_addrtype,
1133 { "Address type", "lwres.adn.addrtype", FT_UINT32, BASE_DEC, NULL, 0x0,
1134 "lwres adn addrtype", HFILL }},
1136 { &hf_adn_namelen,
1137 { "Name length", "lwres.adn.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1138 "lwres adn namelen", HFILL }},
1140 { &hf_adn_name,
1141 { "Name", "lwres.adn.name", FT_STRING, BASE_NONE, NULL, 0x0,
1142 "lwres adn name", HFILL }},
1144 { &hf_adn_naliases,
1145 { "Number of aliases", "lwres.adn.naliases", FT_UINT16, BASE_DEC, NULL, 0x0,
1146 "lwres adn naliases", HFILL }},
1148 { &hf_adn_naddrs,
1149 { "Number of addresses", "lwres.adn.naddrs", FT_UINT16, BASE_DEC, NULL, 0x0,
1150 "lwres adn naddrs", HFILL }},
1152 { &hf_adn_realname,
1153 { "Real name", "lwres.adn.realname", FT_STRING, BASE_NONE, NULL, 0x0,
1154 "lwres adn realname", HFILL }},
1156 { &hf_adn_aliasname,
1157 { "Alias name", "lwres.adn.aliasname", FT_STRING, BASE_NONE, NULL, 0x0,
1158 "lwres adn aliasname", HFILL }},
1160 { &hf_adn_family,
1161 { "Address family", "lwres.adn.addr.family", FT_UINT32, BASE_DEC, NULL, 0x0,
1162 "lwres adn addr family", HFILL }},
1164 { &hf_adn_addr_len,
1165 { "Address length", "lwres.adn.addr.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1166 "lwres adn addr length", HFILL }},
1168 { &hf_adn_addr_addr,
1169 { "IP Address", "lwres.adn.addr.addr", FT_STRING, BASE_NONE, NULL, 0x0,
1170 "lwres adn addr addr", HFILL }},
1172 /* Add more fields here */
1175 static gint *ett[] = {
1176 &ett_lwres,
1177 &ett_rdata_req,
1178 &ett_rdata_resp,
1179 &ett_a_rec,
1180 &ett_a_rec_addr,
1181 &ett_srv_rec,
1182 &ett_srv_rec_item,
1183 &ett_adn_request,
1184 &ett_adn_resp,
1185 &ett_adn_alias,
1186 &ett_adn_addr,
1187 &ett_nba_request,
1188 &ett_nba_resp,
1189 &ett_mx_rec,
1190 &ett_mx_rec_item,
1191 &ett_ns_rec,
1192 &ett_ns_rec_item,
1193 &ett_noop,
1197 module_t *lwres_module;
1199 proto_lwres = proto_register_protocol("Light Weight DNS RESolver (BIND9)",
1200 "LWRES", "lwres");
1202 proto_register_field_array(proto_lwres, hf, array_length(hf));
1203 proto_register_subtree_array(ett, array_length(ett));
1205 lwres_module = prefs_register_protocol(proto_lwres, proto_reg_handoff_lwres);
1207 prefs_register_uint_preference(lwres_module, "udp.lwres_port",
1208 "lwres listener UDP Port",
1209 "Set the UDP port for lwres daemon"
1210 "(if other than the default of 921)",
1211 10, &global_lwres_port);
1215 /* The registration hand-off routine */
1216 void
1217 proto_reg_handoff_lwres(void)
1219 static gboolean lwres_prefs_initialized = FALSE;
1220 static dissector_handle_t lwres_handle;
1221 static guint lwres_port;
1223 if(!lwres_prefs_initialized) {
1224 lwres_handle = create_dissector_handle(dissect_lwres, proto_lwres);
1225 lwres_prefs_initialized = TRUE;
1227 else {
1228 dissector_delete_uint("udp.port", lwres_port, lwres_handle);
1231 dissector_add_uint("udp.port", global_lwres_port, lwres_handle);
1232 lwres_port = global_lwres_port;