epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-lwres.c
blob9daf1b09b7f92e9ffdd8945d7c22805555a1fa17
1 /* packet-lwres.c
2 * Routines for light weight reslover (lwres, part of BIND9) packet disassembly
4 * Copyright (c) 2003 by Oleg Terletsky <oleg.terletsky@comverse.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1999 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/to_str.h>
18 #include <epan/strutil.h>
20 #include "packet-dns.h"
22 void proto_register_lwres(void);
23 void proto_reg_handoff_lwres(void);
25 static dissector_handle_t lwres_handle;
27 #define LWRES_LWPACKET_LENGTH (4 * 5 + 2 * 4)
28 #define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
29 #define LWRES_LWPACKETVERSION_0 0
31 #define LW_LENGTH_OFFSET 0
32 #define LW_VERSION_OFFSET 4
33 #define LW_PKTFLASG_OFFSET 6
34 #define LW_SERIAL_OFFSET 8
35 #define LW_OPCODE_OFFSET 12
36 #define LW_RESULT_OFFSET 16
37 #define LW_RECVLEN_OFFSET 20
38 #define LW_AUTHTYPE_OFFSET 24
39 #define LW_AUTHLEN_OFFSET 26
41 #define LWRES_OPCODE_NOOP 0x00000000U
42 #define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
43 #define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
44 #define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
46 static const value_string opcode_values[] = {
47 { LWRES_OPCODE_NOOP, "Noop" },
48 { LWRES_OPCODE_GETADDRSBYNAME, "getaddrbyname" },
49 { LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr" },
50 { LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname" },
51 { 0, NULL },
55 #define LWRES_R_SUCCESS 0
56 #define LWRES_R_NOMEMORY 1
57 #define LWRES_R_TIMEOUT 2
58 #define LWRES_R_NOTFOUND 3
59 #define LWRES_R_UNEXPECTEDEND 4 /* unexpected end of input */
60 #define LWRES_R_FAILURE 5 /* generic failure */
61 #define LWRES_R_IOERROR 6
62 #define LWRES_R_NOTIMPLEMENTED 7
63 #define LWRES_R_UNEXPECTED 8
64 #define LWRES_R_TRAILINGDATA 9
65 #define LWRES_R_INCOMPLETE 10
66 #define LWRES_R_RETRY 11
67 #define LWRES_R_TYPENOTFOUND 12
68 #define LWRES_R_TOOLARGE 13
70 #define T_A 1
71 #define T_NS 2
72 #define T_MX 15
73 #define T_SRV 33
76 static const value_string t_types[] = {
77 { T_A, "T_A" },
78 { T_NS, "T_NS" },
79 { T_MX, "T_MX" },
80 { T_SRV, "T_SRV" },
81 { 0, NULL },
87 static const value_string result_values[] = {
88 { LWRES_R_SUCCESS, "Success" },
89 { LWRES_R_NOMEMORY, "No memory" },
90 { LWRES_R_TIMEOUT, "Timeout" },
91 { LWRES_R_NOTFOUND, "Not found" },
92 { LWRES_R_UNEXPECTEDEND, "Unexpected end of input" },
93 { LWRES_R_FAILURE, "Generic failure" },
94 { LWRES_R_IOERROR, "I/O Error" },
95 { LWRES_R_NOTIMPLEMENTED, "Not Implemented"},
96 { LWRES_R_UNEXPECTED, "Unexpected" },
97 { LWRES_R_TRAILINGDATA, "Trailing data" },
98 { LWRES_R_INCOMPLETE, "Incomplete" },
99 { LWRES_R_RETRY, "Retry" },
100 { LWRES_R_TYPENOTFOUND, "Type not found" },
101 { LWRES_R_TOOLARGE, "Too large" },
102 { 0, NULL },
105 static int hf_length;
106 static int hf_version;
107 static int hf_flags;
108 static int hf_serial;
109 static int hf_opcode;
110 static int hf_result;
111 static int hf_recvlen;
112 static int hf_authtype;
113 static int hf_authlen;
115 static int hf_rflags;
116 static int hf_rdclass;
117 static int hf_rdtype;
118 static int hf_namelen;
119 static int hf_req_name;
121 static int hf_ttl;
122 static int hf_nrdatas;
123 static int hf_nsigs;
124 static int hf_realnamelen;
125 static int hf_realname;
128 static int hf_a_record;
129 static int hf_a_rec_len;
130 static int hf_srv_prio;
131 static int hf_srv_weight;
132 static int hf_srv_port;
133 static int hf_srv_dname;
135 static int hf_adn_flags;
136 static int hf_adn_addrtype;
137 static int hf_adn_namelen;
138 static int hf_adn_name;
140 static int hf_adn_realname;
141 static int hf_adn_aliasname;
143 static int hf_adn_naddrs;
144 static int hf_adn_naliases;
145 static int hf_adn_family;
146 static int hf_adn_addr_len;
147 static int hf_adn_addr_addr;
149 static int hf_ns_dname;
151 static int ett_lwres;
152 static int ett_rdata_req;
153 static int ett_rdata_resp;
154 static int ett_a_rec;
155 static int ett_a_rec_addr;
156 static int ett_srv_rec;
157 static int ett_srv_rec_item;
158 static int ett_adn_request;
159 static int ett_adn_resp;
160 static int ett_adn_alias;
161 static int ett_adn_addr;
162 static int ett_nba_request;
163 static int ett_nba_resp;
164 static int ett_noop;
166 static int ett_mx_rec;
167 static int ett_mx_rec_item;
169 static int ett_ns_rec;
170 static int ett_ns_rec_item;
174 #define LWRES_UDP_PORT 921 /* Not IANA registered */
176 /* Define the lwres proto */
177 static int proto_lwres;
180 /* Define many many headers for mgcp */
182 static const value_string message_types_values[] = {
183 { 1, "REQUEST " },
184 { 2, "RESPONSE" },
185 { 0, NULL },
188 static void dissect_getnamebyaddr_request(tvbuff_t* tvb, packet_info *pinfo, proto_tree* lwres_tree)
190 uint32_t flags,family;
191 unsigned addrlen, slen;
192 const char* addrs;
194 proto_tree* nba_request_tree;
196 flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
197 family = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
198 addrlen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
199 addrs = tvb_ip_to_str(pinfo->pool, tvb, LWRES_LWPACKET_LENGTH + 10);
200 slen = (int)strlen(addrs);
202 if (lwres_tree == NULL)
203 return;
205 nba_request_tree = proto_tree_add_subtree(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,LWRES_LWPACKET_LENGTH+14,
206 ett_nba_request,NULL,"getnamebyaddr parameters");
208 proto_tree_add_uint(nba_request_tree, hf_adn_flags, tvb,
209 LWRES_LWPACKET_LENGTH, 4, flags);
211 proto_tree_add_uint(nba_request_tree, hf_adn_family, tvb,
212 LWRES_LWPACKET_LENGTH + 4, 4, family);
214 proto_tree_add_uint(nba_request_tree, hf_adn_addr_len, tvb,
215 LWRES_LWPACKET_LENGTH + 8, 2, addrlen);
217 proto_tree_add_string(nba_request_tree, hf_adn_addr_addr, tvb,
218 LWRES_LWPACKET_LENGTH + 10, slen, addrs);
222 static void dissect_getnamebyaddr_response(tvbuff_t* tvb, packet_info *pinfo, proto_tree* lwres_tree)
224 uint32_t i, offset;
225 uint16_t naliases,realnamelen,aliaslen;
226 char *aliasname;
228 proto_tree* nba_resp_tree;
229 proto_tree* alias_tree;
231 if(lwres_tree == NULL)
232 return;
234 nba_resp_tree = proto_tree_add_subtree(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, ett_nba_resp, NULL, "getnamebyaddr records");
236 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
237 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH + 4 + 2);
239 proto_tree_add_item(nba_resp_tree,
240 hf_adn_flags,
241 tvb,
242 LWRES_LWPACKET_LENGTH,
244 ENC_BIG_ENDIAN);
245 proto_tree_add_item(nba_resp_tree,
246 hf_adn_naliases,
247 tvb,
248 LWRES_LWPACKET_LENGTH + 4,
250 ENC_BIG_ENDIAN);
252 proto_tree_add_item(nba_resp_tree,
253 hf_adn_namelen,
254 tvb,
255 LWRES_LWPACKET_LENGTH + 6,
257 ENC_BIG_ENDIAN);
259 proto_tree_add_item(nba_resp_tree,
260 hf_adn_realname,
261 tvb,
262 LWRES_LWPACKET_LENGTH + 8,
263 realnamelen,
264 ENC_ASCII);
266 offset=LWRES_LWPACKET_LENGTH + 8 + realnamelen;
268 if(naliases)
270 for(i=0; i<naliases; i++)
272 aliaslen = tvb_get_ntohs(tvb, offset);
273 aliasname = tvb_get_string_enc(pinfo->pool, tvb, offset + 2, aliaslen, ENC_ASCII);
275 alias_tree = proto_tree_add_subtree_format(nba_resp_tree, tvb, offset, 2 + aliaslen,
276 ett_adn_alias, NULL, "Alias %s",aliasname);
278 proto_tree_add_item(alias_tree,
279 hf_adn_namelen,
280 tvb,
281 offset,
283 ENC_BIG_ENDIAN);
285 proto_tree_add_item(alias_tree,
286 hf_adn_aliasname,
287 tvb,
288 offset + 2,
289 aliaslen,
290 ENC_ASCII);
292 offset+=(2 + aliaslen + 1);
297 static void dissect_getaddrsbyname_request(tvbuff_t* tvb, proto_tree* lwres_tree)
299 uint16_t namelen;
301 proto_tree* adn_request_tree;
303 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
305 if(lwres_tree == NULL)
306 return;
308 adn_request_tree = proto_tree_add_subtree(lwres_tree,tvb,
309 LWRES_LWPACKET_LENGTH,10+namelen+1,
310 ett_adn_request, NULL,
311 "getaddrbyname parameters");
313 proto_tree_add_item(adn_request_tree,
314 hf_adn_flags,
315 tvb,
316 LWRES_LWPACKET_LENGTH+0,
317 sizeof(uint32_t),
318 ENC_BIG_ENDIAN);
320 proto_tree_add_item(adn_request_tree,
321 hf_adn_addrtype,
322 tvb,
323 LWRES_LWPACKET_LENGTH+4,
324 sizeof(uint32_t),
325 ENC_BIG_ENDIAN);
327 proto_tree_add_item(adn_request_tree,
328 hf_adn_namelen,
329 tvb,
330 LWRES_LWPACKET_LENGTH+8,
331 sizeof(uint16_t),
332 ENC_BIG_ENDIAN);
334 proto_tree_add_item(adn_request_tree,
335 hf_adn_name,
336 tvb,
337 LWRES_LWPACKET_LENGTH+10,
338 namelen,
339 ENC_ASCII);
344 static void dissect_getaddrsbyname_response(tvbuff_t* tvb, packet_info *pinfo, proto_tree* lwres_tree)
346 uint32_t family ,i, offset;
347 uint16_t naliases, naddrs, realnamelen, length, aliaslen;
348 const char* addrs;
349 unsigned slen;
350 char *aliasname;
352 proto_tree *adn_resp_tree;
353 proto_tree *alias_tree;
354 proto_tree *addr_tree;
358 if(lwres_tree == NULL)
359 return;
361 adn_resp_tree = proto_tree_add_subtree(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10,
362 ett_adn_resp, NULL, "getaddrbyname records");
364 naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
365 naddrs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 6);
366 realnamelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
369 proto_tree_add_item(adn_resp_tree, hf_adn_flags, tvb,
370 LWRES_LWPACKET_LENGTH, 4, ENC_BIG_ENDIAN);
372 proto_tree_add_item(adn_resp_tree, hf_adn_naliases, tvb,
373 LWRES_LWPACKET_LENGTH + 4, 2, ENC_BIG_ENDIAN);
375 proto_tree_add_item(adn_resp_tree, hf_adn_naddrs, tvb,
376 LWRES_LWPACKET_LENGTH + 6, 2, ENC_BIG_ENDIAN);
378 proto_tree_add_item(adn_resp_tree, hf_adn_namelen, tvb,
379 LWRES_LWPACKET_LENGTH + 8, 2, ENC_BIG_ENDIAN);
381 proto_tree_add_item(adn_resp_tree, hf_adn_realname, tvb,
382 LWRES_LWPACKET_LENGTH + 10, realnamelen, ENC_ASCII);
384 offset = LWRES_LWPACKET_LENGTH + 10 + realnamelen + 1;
386 if(naliases)
388 for(i=0; i<naliases; i++)
390 aliaslen = tvb_get_ntohs(tvb, offset);
391 aliasname = tvb_get_string_enc(pinfo->pool, tvb, offset + 2, aliaslen, ENC_ASCII);
393 alias_tree = proto_tree_add_subtree_format(adn_resp_tree, tvb, offset, 2 + aliaslen,
394 ett_adn_alias, NULL, "Alias %s",aliasname);
396 proto_tree_add_uint(alias_tree, hf_adn_namelen, tvb,
397 offset, 2, aliaslen);
399 proto_tree_add_item(alias_tree, hf_adn_aliasname, tvb,
400 offset + 2, aliaslen, ENC_ASCII);
402 offset+=(2 + aliaslen + 1);
406 if(naddrs)
408 for(i=0; i < naddrs; i++)
410 family = tvb_get_ntohl(tvb, offset);
411 length = tvb_get_ntohs(tvb, offset + 4);
412 addrs = tvb_ip_to_str(pinfo->pool, tvb, offset + 6);
413 slen = (int)strlen(addrs);
415 addr_tree = proto_tree_add_subtree_format(adn_resp_tree,tvb, offset, 4+2+4, ett_adn_addr, NULL, "Address %s", addrs);
417 proto_tree_add_uint(addr_tree, hf_adn_family, tvb,
418 offset, 4, family);
420 proto_tree_add_uint(addr_tree, hf_adn_addr_len, tvb,
421 offset + 4, 2, length);
423 proto_tree_add_string(addr_tree, hf_adn_addr_addr, tvb,
424 offset + 6, slen, addrs);
426 offset+= 4 + 2 + 4;
433 static void dissect_a_records(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree,uint32_t nrec,int offset)
435 uint32_t i, curr;
436 const char* addrs;
437 proto_tree* a_rec_tree;
438 proto_tree* addr_tree;
440 if(tree == NULL)
441 return;
443 a_rec_tree = proto_tree_add_subtree(tree,tvb,offset,
444 (int)((sizeof(uint32_t) + sizeof(uint16_t)) * nrec),
445 ett_a_rec, NULL, "A records");
447 for(i=0; i<nrec; i++)
450 curr = offset + (int)((sizeof(uint32_t)+sizeof(uint16_t)) * i);
452 addrs = tvb_ip_to_str(pinfo->pool, tvb, curr+2);
454 addr_tree = proto_tree_add_subtree_format(a_rec_tree, tvb, curr,
455 6, ett_a_rec_addr, NULL, "Address %s", addrs);
457 proto_tree_add_item(addr_tree, hf_a_rec_len, tvb, curr,
458 sizeof(uint16_t), ENC_BIG_ENDIAN);
460 proto_tree_add_item(addr_tree, hf_a_record, tvb, curr + 2, 4, ENC_BIG_ENDIAN);
465 static void dissect_srv_records(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree,uint32_t nrec,int offset)
467 uint32_t i, curr;
468 uint16_t /*len, namelen,*/ priority, weight, port;
469 int dlen;
470 unsigned used_bytes;
471 const char *dname;
473 proto_item* srv_rec_tree, *rec_tree;
475 if(tree == NULL)
476 return;
478 srv_rec_tree = proto_tree_add_subtree_format(tree, tvb, offset, offset, ett_srv_rec, NULL, "SRV records (%d)", nrec);
480 curr = offset;
482 for(i=0; i < nrec; i++)
484 /*len = tvb_get_ntohs(tvb, curr);*/
485 priority = tvb_get_ntohs(tvb, curr + 2);
486 weight = tvb_get_ntohs(tvb, curr + 4);
487 port = tvb_get_ntohs(tvb, curr + 6);
488 /*namelen = len - 8;*/
490 used_bytes = get_dns_name(tvb, curr + 8, 0, curr + 8, &dname, &dlen);
492 rec_tree = proto_tree_add_subtree_format(srv_rec_tree, tvb, curr, 6,
493 ett_srv_rec_item, NULL,
494 "SRV record:pri=%d,w=%d,port=%d,dname=%s",
495 priority, weight, port, format_text(pinfo->pool, dname, dlen));
497 proto_tree_add_uint(rec_tree,
498 hf_srv_prio,
499 tvb,
500 curr + 2,
502 priority);
504 proto_tree_add_uint(rec_tree,
505 hf_srv_weight,
506 tvb,
507 curr + 4,
509 weight);
511 proto_tree_add_uint(rec_tree,
512 hf_srv_port,
513 tvb,
514 curr + 6,
516 port);
519 proto_tree_add_string(rec_tree,
520 hf_srv_dname,
521 tvb,
522 curr + 8,
523 used_bytes,
524 format_text(pinfo->pool, dname, dlen));
526 curr+=(int)((sizeof(short)*4) + used_bytes);
532 static void dissect_mx_records(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, uint32_t nrec, int offset)
535 unsigned i, curr;
536 unsigned priority;
537 int dlen;
538 unsigned used_bytes;
539 const char *dname;
541 proto_tree* mx_rec_tree, *rec_tree;
544 if(tree == NULL)
545 return;
547 mx_rec_tree = proto_tree_add_subtree_format(tree, tvb, offset, offset, ett_mx_rec, NULL, "MX records (%d)", nrec);
549 curr = offset;
550 for(i=0; i < nrec; i++)
552 /*len = tvb_get_ntohs(tvb, curr);*/
553 priority = tvb_get_ntohs(tvb, curr + 2);
554 /*namelen = len - 4;*/
556 used_bytes = get_dns_name(tvb, curr + 4, 0, curr + 4, &dname, &dlen);
558 rec_tree = proto_tree_add_subtree_format(mx_rec_tree, tvb, curr,6,ett_mx_rec_item,NULL,
559 "MX record: pri=%d,dname=%s", priority,
560 format_text(pinfo->pool, dname, dlen));
563 proto_tree_add_item(rec_tree,
564 hf_srv_prio,
565 tvb,
566 curr + 2,
568 ENC_BIG_ENDIAN);
570 proto_tree_add_string(rec_tree,
571 hf_srv_dname,
572 tvb,
573 curr + 4,
574 used_bytes,
575 format_text(pinfo->pool, dname, dlen));
577 curr+=(int)((sizeof(short)*2) + used_bytes);
584 static void dissect_ns_records(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, uint32_t nrec, int offset)
586 unsigned i, curr;
587 int dlen;
588 const char *dname;
589 unsigned used_bytes;
591 proto_tree* ns_rec_tree, *rec_tree;
593 if(tree == NULL)
594 return;
596 ns_rec_tree = proto_tree_add_subtree_format(tree, tvb, offset, offset, ett_ns_rec, NULL, "NS record (%d)", nrec);
598 curr=offset;
600 for(i=0;i<nrec;i++)
602 /*len = tvb_get_ntohs(tvb, curr);*/
603 /*namelen = len - 2;*/
605 used_bytes = get_dns_name(tvb, curr + 2, 0, curr + 2, &dname, &dlen);
607 rec_tree = proto_tree_add_subtree_format(ns_rec_tree, tvb, curr,4, ett_ns_rec_item, NULL, "NS record: dname=%s",
608 format_text(pinfo->pool, dname, dlen));
610 proto_tree_add_string(rec_tree,
611 hf_ns_dname,
612 tvb,
613 curr + 2,
614 used_bytes,
615 format_text(pinfo->pool, dname, dlen));
616 curr+=(int)(sizeof(short) + used_bytes);
623 static void dissect_rdata_request(tvbuff_t* tvb, proto_tree* lwres_tree)
625 uint16_t namelen;
627 proto_tree* rdata_request_tree;
629 namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+8);
631 if(lwres_tree == NULL)
632 return;
634 rdata_request_tree =
635 proto_tree_add_subtree(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,10+namelen+1,ett_rdata_req,NULL,"RDATA request parameters");
637 proto_tree_add_item(rdata_request_tree,
638 hf_rflags,
639 tvb,
640 LWRES_LWPACKET_LENGTH+0,
641 sizeof(uint32_t),
642 ENC_BIG_ENDIAN);
644 proto_tree_add_item(rdata_request_tree,
645 hf_rdclass,
646 tvb,
647 LWRES_LWPACKET_LENGTH+4,
648 sizeof(uint16_t),
649 ENC_BIG_ENDIAN);
651 proto_tree_add_item(rdata_request_tree,
652 hf_rdtype,
653 tvb,
654 LWRES_LWPACKET_LENGTH+6,
655 sizeof(uint16_t),
656 ENC_BIG_ENDIAN);
658 proto_tree_add_item(rdata_request_tree,
659 hf_namelen,
660 tvb,
661 LWRES_LWPACKET_LENGTH+8,
662 sizeof(uint16_t),
663 ENC_BIG_ENDIAN);
665 proto_tree_add_item(rdata_request_tree,
666 hf_req_name,
667 tvb,
668 LWRES_LWPACKET_LENGTH+10,
669 namelen,
670 ENC_ASCII);
674 static void dissect_rdata_response(tvbuff_t* tvb, packet_info *pinfo, proto_tree* lwres_tree)
676 unsigned offset;
677 unsigned rdtype, nrdatas, realnamelen;
679 proto_tree* rdata_resp_tree;
681 rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
682 nrdatas = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+12);
683 realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH+16);
685 offset = LWRES_LWPACKET_LENGTH + 18 + realnamelen + 1;
687 if(lwres_tree == NULL)
688 return;
690 rdata_resp_tree = proto_tree_add_subtree(lwres_tree,tvb,LWRES_LWPACKET_LENGTH, 18+realnamelen+1,ett_rdata_resp,NULL,"RDATA response");
692 proto_tree_add_item(rdata_resp_tree,
693 hf_rflags,
694 tvb,
695 LWRES_LWPACKET_LENGTH+0,
696 sizeof(uint32_t),
697 ENC_BIG_ENDIAN);
699 proto_tree_add_item(rdata_resp_tree,
700 hf_rdclass,
701 tvb,
702 LWRES_LWPACKET_LENGTH+4,
703 sizeof(uint16_t),
704 ENC_BIG_ENDIAN);
706 proto_tree_add_item(rdata_resp_tree,
707 hf_rdtype,
708 tvb,
709 LWRES_LWPACKET_LENGTH+6,
710 sizeof(uint16_t),
711 ENC_BIG_ENDIAN);
713 proto_tree_add_item(rdata_resp_tree,
714 hf_ttl,
715 tvb,
716 LWRES_LWPACKET_LENGTH+8,
717 sizeof(uint32_t),
718 ENC_BIG_ENDIAN);
720 proto_tree_add_item(rdata_resp_tree,
721 hf_nrdatas,
722 tvb,
723 LWRES_LWPACKET_LENGTH+12,
724 sizeof(uint16_t),
725 ENC_BIG_ENDIAN);
727 proto_tree_add_item(rdata_resp_tree,
728 hf_nsigs,
729 tvb,
730 LWRES_LWPACKET_LENGTH+14,
731 sizeof(uint16_t),
732 ENC_BIG_ENDIAN);
734 proto_tree_add_item(rdata_resp_tree,
735 hf_realnamelen,
736 tvb,
737 LWRES_LWPACKET_LENGTH+16,
738 sizeof(uint16_t),
739 ENC_BIG_ENDIAN);
741 proto_tree_add_item(rdata_resp_tree,
742 hf_realname,
743 tvb,
744 LWRES_LWPACKET_LENGTH+18,
745 realnamelen,
746 ENC_ASCII);
748 switch(rdtype)
750 case T_A:
751 dissect_a_records(tvb,pinfo,rdata_resp_tree,nrdatas,offset);
752 break;
754 case T_SRV:
755 dissect_srv_records(tvb,pinfo,rdata_resp_tree,nrdatas, offset);
756 break;
758 case T_MX:
759 dissect_mx_records(tvb,pinfo,rdata_resp_tree,nrdatas, offset);
760 break;
762 case T_NS:
763 dissect_ns_records(tvb,pinfo,rdata_resp_tree,nrdatas, offset);
764 break;
769 static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
771 uint16_t datalen;
773 proto_tree* noop_tree;
775 datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);
777 if(lwres_tree == NULL)
778 return;
780 noop_tree = proto_tree_add_subtree(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, ett_noop, NULL, "Noop record");
782 proto_tree_add_uint(noop_tree, hf_length, tvb,
783 LWRES_LWPACKET_LENGTH, sizeof(uint16_t), datalen);
785 tvb_ensure_bytes_exist(tvb, LWRES_LWPACKET_LENGTH, datalen);
789 static void dissect_getaddrsbyname(tvbuff_t* tvb, packet_info *pinfo, proto_tree* lwres_tree, int type)
791 if(type == 1)
792 dissect_getaddrsbyname_request(tvb, lwres_tree);
793 else
794 dissect_getaddrsbyname_response(tvb, pinfo, lwres_tree);
797 static void dissect_getnamebyaddr(tvbuff_t* tvb, packet_info *pinfo, proto_tree* lwres_tree, int type)
799 if(type == 1)
800 dissect_getnamebyaddr_request(tvb, pinfo, lwres_tree);
801 else
802 dissect_getnamebyaddr_response(tvb, pinfo, lwres_tree);
805 static void dissect_getrdatabyname(tvbuff_t* tvb, packet_info *pinfo _U_, proto_tree* lwres_tree, int type)
807 if(type == 1)
808 dissect_rdata_request(tvb, lwres_tree);
809 else
810 dissect_rdata_response(tvb, pinfo, lwres_tree);
813 static int
814 dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
816 uint16_t version, flags, authtype, authlength ;
817 uint32_t length, opcode, result, recvlength, serial;
818 uint32_t message_type;
820 proto_item* lwres_item;
821 proto_tree* lwres_tree;
823 col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res");
824 length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET);
825 version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET);
826 flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET);
827 serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET);
828 opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET);
829 result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET);
830 recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET);
831 authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET);
832 authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET);
834 message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1;
836 if(flags & LWRES_LWPACKETFLAG_RESPONSE)
838 col_add_fstr(pinfo->cinfo, COL_INFO,
839 "%s, opcode=%s, serial=0x%x, result=%s",
840 val_to_str_const((uint32_t)message_type,message_types_values,"unknown"),
841 val_to_str_const(opcode, opcode_values, "unknown"),
842 serial,
843 val_to_str_const(result,result_values,"unknown"));
845 else
847 col_add_fstr(pinfo->cinfo, COL_INFO,
848 "%s, opcode=%s, serial=0x%x",
849 val_to_str_const((uint32_t)message_type,message_types_values,"unknown"),
850 val_to_str_const(opcode, opcode_values, "unknown"),
851 serial);
854 if(tree == NULL)
855 return tvb_captured_length(tvb);
857 lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, ENC_NA);
858 lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres);
860 proto_tree_add_uint(lwres_tree,
861 hf_length,
862 tvb,
863 LW_LENGTH_OFFSET,
864 sizeof(uint32_t),
865 length);
868 proto_tree_add_uint(lwres_tree,
869 hf_version,
870 tvb,
871 LW_VERSION_OFFSET,
872 sizeof(uint16_t),
873 version);
878 proto_tree_add_uint(lwres_tree,
879 hf_flags,
880 tvb,
881 LW_PKTFLASG_OFFSET,
882 sizeof(uint16_t),
883 flags);
885 proto_tree_add_uint(lwres_tree,
886 hf_serial,
887 tvb,
888 LW_SERIAL_OFFSET,
889 sizeof(uint32_t),
890 serial);
892 proto_tree_add_uint(lwres_tree,
893 hf_opcode,
894 tvb,
895 LW_OPCODE_OFFSET,
896 sizeof(uint32_t),
897 opcode);
899 proto_tree_add_uint(lwres_tree,
900 hf_result,
901 tvb,
902 LW_RESULT_OFFSET,
903 sizeof(uint32_t),
904 result);
906 proto_tree_add_uint(lwres_tree,
907 hf_recvlen,
908 tvb,
909 LW_RECVLEN_OFFSET,
910 sizeof(uint32_t),
911 recvlength);
913 proto_tree_add_uint(lwres_tree,
914 hf_authtype,
915 tvb,
916 LW_AUTHTYPE_OFFSET,
917 sizeof(uint16_t),
918 authtype);
920 proto_tree_add_uint(lwres_tree,
921 hf_authlen,
922 tvb,
923 LW_AUTHLEN_OFFSET,
924 sizeof(uint16_t),
925 authlength);
927 if(!result)
929 switch(opcode)
931 case LWRES_OPCODE_NOOP:
932 dissect_noop(tvb, lwres_tree);
933 break;
935 case LWRES_OPCODE_GETADDRSBYNAME:
936 dissect_getaddrsbyname(tvb, pinfo, lwres_tree, message_type);
937 break;
939 case LWRES_OPCODE_GETNAMEBYADDR:
940 dissect_getnamebyaddr(tvb, pinfo, lwres_tree, message_type);
941 break;
943 case LWRES_OPCODE_GETRDATABYNAME:
944 dissect_getrdatabyname(tvb, pinfo, lwres_tree, message_type);
945 break;
948 return tvb_captured_length(tvb);
952 void
953 proto_register_lwres(void)
955 static hf_register_info hf[] = {
956 { &hf_length,
957 { "Length", "lwres.length", FT_UINT32, BASE_DEC, NULL, 0x0,
958 "lwres length", HFILL }},
960 { &hf_version,
961 { "Version", "lwres.version", FT_UINT16, BASE_DEC, NULL, 0x0,
962 "lwres version", HFILL }},
964 { &hf_flags,
965 { "Packet Flags", "lwres.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
966 "lwres flags", HFILL }},
968 { &hf_serial,
969 { "Serial", "lwres.serial", FT_UINT32, BASE_HEX, NULL, 0x0,
970 "lwres serial", HFILL }},
972 { &hf_opcode,
973 { "Operation code", "lwres.opcode", FT_UINT32, BASE_DEC, VALS(opcode_values), 0x0,
974 "lwres opcode", HFILL }},
976 { &hf_result,
977 { "Result", "lwres.result", FT_UINT32, BASE_DEC, VALS(result_values), 0x0,
978 "lwres result", HFILL }},
980 { &hf_recvlen,
981 { "Received length", "lwres.recvlen", FT_UINT32, BASE_DEC, NULL, 0x0,
982 "lwres recvlen", HFILL }},
984 { &hf_authtype,
985 { "Auth. type", "lwres.authtype", FT_UINT16, BASE_DEC, NULL, 0x0,
986 "lwres authtype", HFILL }},
988 { &hf_authlen,
989 { "Auth. length", "lwres.authlen", FT_UINT16, BASE_DEC, NULL, 0x0,
990 "lwres authlen", HFILL }},
992 { &hf_rflags,
993 { "Flags", "lwres.rflags", FT_UINT32, BASE_HEX, NULL, 0x0,
994 "lwres rflags", HFILL }},
995 { &hf_rdclass,
996 { "Class", "lwres.class", FT_UINT16, BASE_DEC, NULL, 0x0,
997 "lwres class", HFILL }},
999 { &hf_rdtype,
1000 { "Type", "lwres.type", FT_UINT16, BASE_DEC, VALS(t_types), 0x0,
1001 "lwres type", HFILL }},
1003 { &hf_namelen,
1004 { "Name length", "lwres.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1005 "lwres namelen", HFILL }},
1007 { &hf_req_name,
1008 { "Domain name", "lwres.reqdname", FT_STRING, BASE_NONE, NULL, 0x0,
1009 "lwres reqdname", HFILL }},
1011 { &hf_ttl,
1012 { "Time To Live", "lwres.ttl", FT_UINT32, BASE_DEC, NULL, 0x0,
1013 "lwres ttl", HFILL }},
1015 { &hf_nrdatas,
1016 { "Number of rdata records", "lwres.nrdatas", FT_UINT16, BASE_DEC, NULL, 0x0,
1017 "lwres nrdatas", HFILL }},
1019 { &hf_nsigs,
1020 { "Number of signature records", "lwres.nsigs", FT_UINT16, BASE_DEC, NULL, 0x0,
1021 "lwres nsigs", HFILL }},
1023 { &hf_realnamelen,
1024 { "Real name length", "lwres.realnamelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1025 "lwres realnamelen", HFILL }},
1027 { &hf_realname,
1028 { "Real doname name", "lwres.realname", FT_STRING, BASE_NONE, NULL, 0x0,
1029 "lwres realname", HFILL }},
1031 { &hf_a_record,
1032 { "IPv4 Address", "lwres.arecord", FT_UINT32, BASE_DEC, NULL, 0x0,
1033 "lwres arecord", HFILL }},
1035 { &hf_a_rec_len,
1036 { "Length", "lwres.areclen", FT_UINT16, BASE_DEC, NULL, 0x0,
1037 "lwres areclen", HFILL }},
1039 { &hf_srv_prio,
1040 { "Priority", "lwres.srv.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
1041 "lwres srv prio", HFILL }},
1043 { &hf_srv_weight,
1044 { "Weight", "lwres.srv.weight", FT_UINT16, BASE_DEC, NULL, 0x0,
1045 "lwres srv weight", HFILL }},
1047 { &hf_srv_port,
1048 { "Port", "lwres.srv.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1049 "lwres srv port", HFILL }},
1051 { &hf_srv_dname,
1052 { "DNAME", "lwres.srv.dname", FT_STRING, BASE_NONE, NULL, 0x0,
1053 NULL, HFILL }},
1055 { &hf_adn_flags,
1056 { "Flags", "lwres.adn.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
1057 "lwres adn flags", HFILL }},
1059 { &hf_adn_addrtype,
1060 { "Address type", "lwres.adn.addrtype", FT_UINT32, BASE_DEC, NULL, 0x0,
1061 "lwres adn addrtype", HFILL }},
1063 { &hf_adn_namelen,
1064 { "Name length", "lwres.adn.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1065 "lwres adn namelen", HFILL }},
1067 { &hf_adn_name,
1068 { "Name", "lwres.adn.name", FT_STRING, BASE_NONE, NULL, 0x0,
1069 "lwres adn name", HFILL }},
1071 { &hf_adn_naliases,
1072 { "Number of aliases", "lwres.adn.naliases", FT_UINT16, BASE_DEC, NULL, 0x0,
1073 "lwres adn naliases", HFILL }},
1075 { &hf_adn_naddrs,
1076 { "Number of addresses", "lwres.adn.naddrs", FT_UINT16, BASE_DEC, NULL, 0x0,
1077 "lwres adn naddrs", HFILL }},
1079 { &hf_adn_realname,
1080 { "Real name", "lwres.adn.realname", FT_STRING, BASE_NONE, NULL, 0x0,
1081 "lwres adn realname", HFILL }},
1083 { &hf_adn_aliasname,
1084 { "Alias name", "lwres.adn.aliasname", FT_STRING, BASE_NONE, NULL, 0x0,
1085 "lwres adn aliasname", HFILL }},
1087 { &hf_adn_family,
1088 { "Address family", "lwres.adn.addr.family", FT_UINT32, BASE_DEC, NULL, 0x0,
1089 "lwres adn addr family", HFILL }},
1091 { &hf_adn_addr_len,
1092 { "Address length", "lwres.adn.addr.length", FT_UINT16, BASE_DEC, NULL, 0x0,
1093 "lwres adn addr length", HFILL }},
1095 { &hf_adn_addr_addr,
1096 { "IP Address", "lwres.adn.addr.addr", FT_STRING, BASE_NONE, NULL, 0x0,
1097 "lwres adn addr addr", HFILL }},
1099 { &hf_ns_dname,
1100 { "Name", "lwres.ns.dname", FT_STRING, BASE_NONE, NULL, 0x0,
1101 NULL, HFILL }},
1103 /* Add more fields here */
1106 static int *ett[] = {
1107 &ett_lwres,
1108 &ett_rdata_req,
1109 &ett_rdata_resp,
1110 &ett_a_rec,
1111 &ett_a_rec_addr,
1112 &ett_srv_rec,
1113 &ett_srv_rec_item,
1114 &ett_adn_request,
1115 &ett_adn_resp,
1116 &ett_adn_alias,
1117 &ett_adn_addr,
1118 &ett_nba_request,
1119 &ett_nba_resp,
1120 &ett_mx_rec,
1121 &ett_mx_rec_item,
1122 &ett_ns_rec,
1123 &ett_ns_rec_item,
1124 &ett_noop,
1127 proto_lwres = proto_register_protocol("Light Weight DNS RESolver (BIND9)", "LWRES", "lwres");
1129 proto_register_field_array(proto_lwres, hf, array_length(hf));
1130 proto_register_subtree_array(ett, array_length(ett));
1132 lwres_handle = register_dissector("lwres", dissect_lwres, proto_lwres);
1135 /* The registration hand-off routine */
1136 void
1137 proto_reg_handoff_lwres(void)
1139 dissector_add_uint_with_preference("udp.port", LWRES_UDP_PORT, lwres_handle);
1143 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1145 * Local variables:
1146 * c-basic-offset: 4
1147 * tab-width: 8
1148 * indent-tabs-mode: nil
1149 * End:
1151 * vi: set shiftwidth=4 tabstop=8 expandtab:
1152 * :indentSize=4:tabSize=8:noTabs=true: