forked from osmocom/wireshark
caf80bbb74
svn path=/trunk/; revision=27888
1511 lines
36 KiB
C
1511 lines
36 KiB
C
/* packet-lwres.c
|
|
* Routines for light weight reslover (lwres, part of BIND9) packet disassembly
|
|
*
|
|
* $Id$
|
|
*
|
|
* Copyright (c) 2003 by Oleg Terletsky <oleg.terletsky@comverse.com>
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1999 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
#include <epan/packet.h>
|
|
#include <epan/prefs.h>
|
|
|
|
#define LWRES_LWPACKET_LENGTH (4 * 5 + 2 * 4)
|
|
#define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
|
|
#define LWRES_LWPACKETVERSION_0 0
|
|
|
|
#define LW_LENGTH_OFFSET 0
|
|
#define LW_VERSION_OFFSET 4
|
|
#define LW_PKTFLASG_OFFSET 6
|
|
#define LW_SERIAL_OFFSET 8
|
|
#define LW_OPCODE_OFFSET 12
|
|
#define LW_RESULT_OFFSET 16
|
|
#define LW_RECVLEN_OFFSET 20
|
|
#define LW_AUTHTYPE_OFFSET 24
|
|
#define LW_AUTHLEN_OFFSET 26
|
|
|
|
|
|
#define LWRES_OPCODE_NOOP 0x00000000U
|
|
#define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
|
|
#define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
|
|
#define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
|
|
|
|
static const value_string opcode_values[] = {
|
|
{ LWRES_OPCODE_NOOP, "Noop" },
|
|
{ LWRES_OPCODE_GETADDRSBYNAME, "getaddrbyname" },
|
|
{ LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr" },
|
|
{ LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
|
|
#define LWRES_R_SUCCESS 0
|
|
#define LWRES_R_NOMEMORY 1
|
|
#define LWRES_R_TIMEOUT 2
|
|
#define LWRES_R_NOTFOUND 3
|
|
#define LWRES_R_UNEXPECTEDEND 4 /* unexpected end of input */
|
|
#define LWRES_R_FAILURE 5 /* generic failure */
|
|
#define LWRES_R_IOERROR 6
|
|
#define LWRES_R_NOTIMPLEMENTED 7
|
|
#define LWRES_R_UNEXPECTED 8
|
|
#define LWRES_R_TRAILINGDATA 9
|
|
#define LWRES_R_INCOMPLETE 10
|
|
#define LWRES_R_RETRY 11
|
|
#define LWRES_R_TYPENOTFOUND 12
|
|
#define LWRES_R_TOOLARGE 13
|
|
|
|
#define T_A 1
|
|
#define T_NS 2
|
|
#define T_MX 15
|
|
#define T_SRV 33
|
|
|
|
|
|
static const value_string t_types[] = {
|
|
{ T_A, "T_A" },
|
|
{ T_NS, "T_NS" },
|
|
{ T_MX, "T_MX" },
|
|
{ T_SRV, "T_SRV" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
|
|
|
|
|
|
static const value_string result_values[] = {
|
|
{ LWRES_R_SUCCESS, "Success" },
|
|
{ LWRES_R_NOMEMORY, "No memory" },
|
|
{ LWRES_R_TIMEOUT, "Timeout" },
|
|
{ LWRES_R_NOTFOUND, "Not found" },
|
|
{ LWRES_R_UNEXPECTEDEND, "Unexpected end of input" },
|
|
{ LWRES_R_FAILURE, "Generic failure" },
|
|
{ LWRES_R_IOERROR, "I/O Error" },
|
|
{ LWRES_R_UNEXPECTED, "Unexpected" },
|
|
{ LWRES_R_TRAILINGDATA, "Trailing data" },
|
|
{ LWRES_R_INCOMPLETE, "Incomplete" },
|
|
{ LWRES_R_RETRY, "Retry" },
|
|
{ LWRES_R_TYPENOTFOUND, "Type not found" },
|
|
{ LWRES_R_TOOLARGE, "Too large" },
|
|
{ 0, NULL },
|
|
};
|
|
|
|
static int hf_length = -1;
|
|
static int hf_version = -1;
|
|
static int hf_flags = -1;
|
|
static int hf_serial = -1;
|
|
static int hf_opcode = -1;
|
|
static int hf_result = -1;
|
|
static int hf_recvlen = -1;
|
|
static int hf_authtype = -1;
|
|
static int hf_authlen = -1;
|
|
|
|
static int hf_rflags = -1;
|
|
static int hf_rdclass = -1;
|
|
static int hf_rdtype = -1;
|
|
static int hf_namelen = -1;
|
|
static int hf_req_name = -1;
|
|
|
|
static int hf_ttl = -1;
|
|
static int hf_nrdatas = -1;
|
|
static int hf_nsigs = -1;
|
|
static int hf_realnamelen = -1;
|
|
static int hf_realname = -1;
|
|
|
|
|
|
static int hf_a_record = -1;
|
|
static int hf_a_rec_len = -1;
|
|
static int hf_srv_prio = -1;
|
|
static int hf_srv_weight = -1;
|
|
static int hf_srv_port = -1;
|
|
|
|
static int hf_adn_flags = -1;
|
|
static int hf_adn_addrtype = -1;
|
|
static int hf_adn_namelen = -1;
|
|
static int hf_adn_name = -1;
|
|
|
|
static int hf_adn_realname = -1;
|
|
static int hf_adn_aliasname = -1;
|
|
|
|
static int hf_adn_naddrs = -1;
|
|
static int hf_adn_naliases = -1;
|
|
static int hf_adn_family = -1;
|
|
static int hf_adn_addr_len = -1;
|
|
static int hf_adn_addr_addr = -1;
|
|
|
|
|
|
static int ett_lwres = -1;
|
|
static int ett_rdata_req = -1;
|
|
static int ett_rdata_resp = -1;
|
|
static int ett_a_rec = -1;
|
|
static int ett_a_rec_addr = -1;
|
|
static int ett_srv_rec = -1;
|
|
static int ett_srv_rec_item = -1;
|
|
static int ett_adn_request = -1;
|
|
static int ett_adn_resp = -1;
|
|
static int ett_adn_alias = -1;
|
|
static int ett_adn_addr = -1;
|
|
static int ett_nba_request = -1;
|
|
static int ett_nba_resp = -1;
|
|
static int ett_noop = -1;
|
|
|
|
static int ett_mx_rec = -1;
|
|
static int ett_mx_rec_item = -1;
|
|
|
|
static int ett_ns_rec = -1;
|
|
static int ett_ns_rec_item = -1;
|
|
|
|
|
|
|
|
#define LWRES_UDP_PORT 921
|
|
|
|
static guint global_lwres_port = LWRES_UDP_PORT;
|
|
|
|
void proto_reg_handoff_lwres(void);
|
|
|
|
|
|
/* Define the lwres proto */
|
|
static int proto_lwres = -1;
|
|
|
|
|
|
/* Define many many headers for mgcp */
|
|
|
|
static const value_string message_types_values[] = {
|
|
{ 1, "REQUEST " },
|
|
{ 2, "RESPONSE" },
|
|
{ 0 , NULL },
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
lwres_get_dns_name(tvbuff_t *tvb, int offset, int dns_data_offset,
|
|
char *name, int maxname)
|
|
{
|
|
int start_offset = offset;
|
|
char *np = name;
|
|
int len = -1;
|
|
int chars_processed = 0;
|
|
int data_size = tvb_reported_length_remaining(tvb, dns_data_offset);
|
|
int component_len;
|
|
int indir_offset;
|
|
|
|
const int min_len = 1; /* Minimum length of encoded name (for root) */
|
|
/* If we're about to return a value (probably negative) which is less
|
|
* than the minimum length, we're looking at bad data and we're liable
|
|
* to put the dissector into a loop. Instead we throw an exception */
|
|
|
|
maxname--; /* reserve space for the trailing '\0' */
|
|
for (;;) {
|
|
component_len = tvb_get_guint8(tvb, offset);
|
|
offset++;
|
|
if (component_len == 0)
|
|
break;
|
|
chars_processed++;
|
|
switch (component_len & 0xc0) {
|
|
|
|
case 0x00:
|
|
/* Label */
|
|
if (np != name) {
|
|
/* Not the first component - put in a '.'. */
|
|
if (maxname > 0) {
|
|
*np++ = '.';
|
|
maxname--;
|
|
}
|
|
}
|
|
while (component_len > 0) {
|
|
if (maxname > 0) {
|
|
*np++ = tvb_get_guint8(tvb, offset);
|
|
maxname--;
|
|
}
|
|
component_len--;
|
|
offset++;
|
|
chars_processed++;
|
|
}
|
|
break;
|
|
|
|
case 0x40:
|
|
/* Extended label (RFC 2673) */
|
|
switch (component_len & 0x3f) {
|
|
|
|
case 0x01:
|
|
/* Bitstring label */
|
|
{
|
|
int bit_count;
|
|
int label_len;
|
|
int print_len;
|
|
|
|
|
|
bit_count = tvb_get_guint8(tvb, offset);
|
|
offset++;
|
|
label_len = (bit_count - 1) / 8 + 1;
|
|
|
|
|
|
if (maxname > 0) {
|
|
print_len = g_snprintf(np, maxname + 1, "\\[x");
|
|
if (print_len != -1 && print_len < maxname + 1) {
|
|
/* Some versions of g_snprintf return -1 if they'd truncate
|
|
the output. */
|
|
np += print_len;
|
|
maxname -= print_len;
|
|
} else {
|
|
/* Nothing printed, as there's no room.
|
|
Suppress all subsequent printing. */
|
|
maxname = 0;
|
|
}
|
|
}
|
|
while(label_len--) {
|
|
if (maxname > 0) {
|
|
print_len = g_snprintf(np, maxname + 1, "%02x",
|
|
tvb_get_guint8(tvb, offset));
|
|
if (print_len != -1 && print_len < maxname + 1) {
|
|
/* Some versions of g_snprintf return -1 if they'd truncate
|
|
the output. */
|
|
np += print_len;
|
|
maxname -= print_len;
|
|
} else {
|
|
/* Nothing printed, as there's no room.
|
|
Suppress all subsequent printing. */
|
|
maxname = 0;
|
|
}
|
|
}
|
|
offset++;
|
|
}
|
|
if (maxname > 0) {
|
|
print_len = g_snprintf(np, maxname + 1, "/%d]", bit_count);
|
|
if (print_len != -1 && print_len < maxname + 1) {
|
|
/* Some versions of g_snprintf return -1 if they'd truncate
|
|
the output. */
|
|
np += print_len;
|
|
maxname -= print_len;
|
|
} else {
|
|
/* Nothing printed, as there's no room.
|
|
Suppress all subsequent printing. */
|
|
maxname = 0;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
g_strlcpy(name, "<Unknown extended label>", maxname);
|
|
/* Parsing will propably fail from here on, since the */
|
|
/* label length is unknown... */
|
|
len = offset - start_offset;
|
|
if (len < min_len)
|
|
THROW(ReportedBoundsError);
|
|
return len;
|
|
}
|
|
break;
|
|
|
|
case 0x80:
|
|
THROW(ReportedBoundsError);
|
|
|
|
case 0xc0:
|
|
/* Pointer. */
|
|
indir_offset = dns_data_offset +
|
|
(((component_len & ~0xc0) << 8) | tvb_get_guint8(tvb, offset));
|
|
offset++;
|
|
chars_processed++;
|
|
|
|
/* If "len" is negative, we are still working on the original name,
|
|
not something pointed to by a pointer, and so we should set "len"
|
|
to the length of the original name. */
|
|
if (len < 0)
|
|
len = offset - start_offset;
|
|
|
|
/* If we've looked at every character in the message, this pointer
|
|
will make us look at some character again, which means we're
|
|
looping. */
|
|
if (chars_processed >= data_size) {
|
|
g_strlcpy(name, "<Name contains a pointer that loops>", maxname);
|
|
if (len < min_len)
|
|
THROW(ReportedBoundsError);
|
|
return len;
|
|
}
|
|
|
|
offset = indir_offset;
|
|
break; /* now continue processing from there */
|
|
}
|
|
}
|
|
|
|
*np = '\0';
|
|
/* If "len" is negative, we haven't seen a pointer, and thus haven't
|
|
set the length, so set it. */
|
|
if (len < 0)
|
|
len = offset - start_offset;
|
|
/* Zero-length name means "root server" */
|
|
if (*name == '\0')
|
|
g_strlcpy(name, "<Root>", maxname);
|
|
if (len < min_len)
|
|
THROW(ReportedBoundsError);
|
|
return len;
|
|
}
|
|
|
|
|
|
static void dissect_getnamebyaddr_request(tvbuff_t* tvb, proto_tree* lwres_tree)
|
|
{
|
|
guint32 flags,family;
|
|
guint16 addrlen, slen;
|
|
const guint8* addr;
|
|
|
|
proto_item* nba_request_item;
|
|
proto_tree* nba_request_tree;
|
|
|
|
flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
|
|
family = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
|
|
addrlen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
|
|
addr = tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH + 10, 4);
|
|
slen = (int)strlen(ip_to_str(addr));
|
|
|
|
if(lwres_tree)
|
|
{
|
|
nba_request_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,LWRES_LWPACKET_LENGTH+14,"getnamebyaddr parameters");
|
|
nba_request_tree = proto_item_add_subtree(nba_request_item, ett_nba_request);
|
|
}
|
|
else return;
|
|
|
|
proto_tree_add_uint(nba_request_tree,
|
|
hf_adn_flags,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH,
|
|
4,
|
|
flags);
|
|
|
|
proto_tree_add_uint(nba_request_tree,
|
|
hf_adn_family,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 4,
|
|
4,
|
|
family);
|
|
|
|
proto_tree_add_uint(nba_request_tree,
|
|
hf_adn_addr_len,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 8,
|
|
2,
|
|
addrlen);
|
|
|
|
proto_tree_add_string(nba_request_tree,
|
|
hf_adn_addr_addr,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 10,
|
|
slen,
|
|
ip_to_str(addr));
|
|
|
|
}
|
|
|
|
static void dissect_getnamebyaddr_response(tvbuff_t* tvb, proto_tree* lwres_tree)
|
|
{
|
|
guint32 flags,i, offset;
|
|
guint16 naliases,realnamelen,aliaslen;
|
|
char aliasname[120];
|
|
char realname[120];
|
|
|
|
|
|
proto_item* nba_resp_item;
|
|
proto_tree* nba_resp_tree;
|
|
|
|
proto_item* alias_item;
|
|
proto_tree* alias_tree;
|
|
|
|
if(lwres_tree)
|
|
{
|
|
nba_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10,"getnamebyaddr records");
|
|
nba_resp_tree = proto_item_add_subtree(nba_resp_item, ett_nba_resp);
|
|
}
|
|
else return;
|
|
|
|
flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
|
|
naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
|
|
realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH + 4 + 2);
|
|
tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 4 + 2 + 2, realnamelen, (guint8*)realname);
|
|
realname[realnamelen]='\0';
|
|
|
|
proto_tree_add_uint(nba_resp_tree,
|
|
hf_adn_flags,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH,
|
|
4,
|
|
flags);
|
|
proto_tree_add_uint(nba_resp_tree,
|
|
hf_adn_naliases,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 4,
|
|
2,
|
|
naliases);
|
|
|
|
proto_tree_add_uint(nba_resp_tree,
|
|
hf_adn_namelen,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 6,
|
|
2,
|
|
realnamelen);
|
|
|
|
proto_tree_add_string(nba_resp_tree,
|
|
hf_adn_realname,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 8,
|
|
realnamelen,
|
|
realname);
|
|
|
|
offset=LWRES_LWPACKET_LENGTH + 8 + realnamelen;
|
|
|
|
if(naliases)
|
|
{
|
|
for(i=0; i<naliases; i++)
|
|
{
|
|
aliaslen = tvb_get_ntohs(tvb, offset);
|
|
tvb_get_nstringz(tvb, offset + 2, aliaslen, (guint8*)aliasname);
|
|
aliasname[aliaslen]='\0';
|
|
|
|
alias_item = proto_tree_add_text(nba_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
|
|
alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
|
|
|
|
proto_tree_add_uint(alias_tree,
|
|
hf_adn_namelen,
|
|
tvb,
|
|
offset,
|
|
2,
|
|
aliaslen);
|
|
|
|
proto_tree_add_string(alias_tree,
|
|
hf_adn_aliasname,
|
|
tvb,
|
|
offset + 2,
|
|
aliaslen,
|
|
aliasname);
|
|
|
|
offset+=(2 + aliaslen + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void dissect_getaddrsbyname_request(tvbuff_t* tvb, proto_tree* lwres_tree)
|
|
{
|
|
guint32 flags,addrtype;
|
|
guint16 namelen;
|
|
guint8 name[120];
|
|
|
|
proto_item* adn_request_item;
|
|
proto_tree* adn_request_tree;
|
|
|
|
flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
|
|
addrtype = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH + 4);
|
|
namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
|
|
tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
|
|
name[namelen]='\0';
|
|
|
|
if(lwres_tree)
|
|
{
|
|
adn_request_item = proto_tree_add_text(lwres_tree,tvb,
|
|
LWRES_LWPACKET_LENGTH,10+namelen+1,
|
|
"getaddrbyname parameters");
|
|
adn_request_tree = proto_item_add_subtree(adn_request_item, ett_adn_request);
|
|
}
|
|
else
|
|
return;
|
|
|
|
|
|
proto_tree_add_uint(adn_request_tree,
|
|
hf_adn_flags,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+0,
|
|
sizeof(guint32),
|
|
flags);
|
|
|
|
proto_tree_add_uint(adn_request_tree,
|
|
hf_adn_addrtype,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+4,
|
|
sizeof(guint32),
|
|
addrtype);
|
|
|
|
proto_tree_add_uint(adn_request_tree,
|
|
hf_adn_namelen,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+8,
|
|
sizeof(guint16),
|
|
namelen);
|
|
|
|
proto_tree_add_string(adn_request_tree,
|
|
hf_adn_name,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+10,
|
|
namelen,
|
|
(gchar*)name);
|
|
|
|
}
|
|
|
|
|
|
static void dissect_getaddrsbyname_response(tvbuff_t* tvb, proto_tree* lwres_tree)
|
|
{
|
|
guint32 flags, family ,i, offset;
|
|
guint16 naliases, naddrs, realnamelen, length, aliaslen;
|
|
const gchar* addr;
|
|
guint slen;
|
|
char realname[120];
|
|
char aliasname[120];
|
|
|
|
proto_item* adn_resp_item;
|
|
proto_tree* adn_resp_tree;
|
|
proto_item* alias_item;
|
|
proto_tree* alias_tree;
|
|
proto_item* addr_item;
|
|
proto_tree* addr_tree;
|
|
|
|
|
|
|
|
if(lwres_tree)
|
|
{
|
|
adn_resp_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "getaddrbyname records");
|
|
adn_resp_tree = proto_item_add_subtree(adn_resp_item, ett_adn_resp);
|
|
}
|
|
else return;
|
|
|
|
flags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH);
|
|
naliases = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 4);
|
|
naddrs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 6);
|
|
realnamelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH + 8);
|
|
tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH + 10, realnamelen, (guint8*)realname);
|
|
realname[realnamelen]='\0';
|
|
|
|
|
|
proto_tree_add_uint(adn_resp_tree,
|
|
hf_adn_flags,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH,
|
|
4,
|
|
flags);
|
|
|
|
proto_tree_add_uint(adn_resp_tree,
|
|
hf_adn_naliases,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 4,
|
|
2,
|
|
naliases);
|
|
|
|
proto_tree_add_uint(adn_resp_tree,
|
|
hf_adn_naddrs,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 6,
|
|
2,
|
|
naddrs);
|
|
|
|
proto_tree_add_uint(adn_resp_tree,
|
|
hf_adn_namelen,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 8,
|
|
2,
|
|
realnamelen);
|
|
|
|
proto_tree_add_string(adn_resp_tree,
|
|
hf_adn_realname,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH + 10,
|
|
realnamelen,
|
|
realname);
|
|
|
|
offset = LWRES_LWPACKET_LENGTH + 10 + realnamelen + 1;
|
|
|
|
if(naliases)
|
|
{
|
|
for(i=0; i<naliases; i++)
|
|
{
|
|
aliaslen = tvb_get_ntohs(tvb, offset);
|
|
tvb_get_nstringz(tvb, offset + 2, aliaslen, (guint8*)aliasname);
|
|
aliasname[aliaslen]='\0';
|
|
|
|
alias_item = proto_tree_add_text(adn_resp_tree, tvb, offset, 2 + aliaslen, "Alias %s",aliasname);
|
|
alias_tree = proto_item_add_subtree(alias_item, ett_adn_alias);
|
|
|
|
proto_tree_add_uint(alias_tree,
|
|
hf_adn_namelen,
|
|
tvb,
|
|
offset,
|
|
2,
|
|
aliaslen);
|
|
|
|
proto_tree_add_string(alias_tree,
|
|
hf_adn_aliasname,
|
|
tvb,
|
|
offset + 2,
|
|
aliaslen,
|
|
aliasname);
|
|
|
|
offset+=(2 + aliaslen + 1);
|
|
}
|
|
}
|
|
|
|
if(naddrs)
|
|
{
|
|
for(i=0; i < naddrs; i++)
|
|
{
|
|
family = tvb_get_ntohl(tvb, offset);
|
|
length = tvb_get_ntohs(tvb, offset + 4);
|
|
addr = (gchar*)tvb_get_ptr(tvb, offset + 6, 4);
|
|
slen = (int)strlen((char*)ip_to_str((guint8*)addr));
|
|
|
|
addr_item = proto_tree_add_text(adn_resp_tree,tvb, offset, 4+2+4, "Address %s",ip_to_str((guint8*)addr));
|
|
addr_tree = proto_item_add_subtree(addr_item, ett_adn_addr);
|
|
|
|
proto_tree_add_uint(addr_tree,
|
|
hf_adn_family,
|
|
tvb,
|
|
offset,
|
|
4,
|
|
family);
|
|
|
|
proto_tree_add_uint(addr_tree,
|
|
hf_adn_addr_len,
|
|
tvb,
|
|
offset + 4,
|
|
2,
|
|
length);
|
|
|
|
proto_tree_add_string(addr_tree,
|
|
hf_adn_addr_addr,
|
|
tvb,
|
|
offset + 6,
|
|
slen,
|
|
ip_to_str((guint8*)addr));
|
|
|
|
offset+= 4 + 2 + 4;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
static void dissect_a_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
|
|
{
|
|
guint32 i, curr;
|
|
const gchar* addr;
|
|
guint16 len;
|
|
proto_item* a_rec_item;
|
|
proto_tree* a_rec_tree;
|
|
proto_item* addr_item;
|
|
proto_tree* addr_tree;
|
|
|
|
if(tree)
|
|
{
|
|
a_rec_item = proto_tree_add_text(tree,tvb,offset,
|
|
((sizeof(guint32) + sizeof(guint16)) * nrec),"A records");
|
|
|
|
a_rec_tree = proto_item_add_subtree(a_rec_item, ett_a_rec);
|
|
}
|
|
else
|
|
return;
|
|
|
|
for(i=0; i<nrec; i++)
|
|
{
|
|
|
|
curr = offset + ((sizeof(guint32)+sizeof(guint16)) * i);
|
|
|
|
len = tvb_get_ntohs(tvb,curr);
|
|
addr = (gchar*)tvb_get_ptr(tvb,curr+2,4);
|
|
|
|
if(a_rec_tree)
|
|
{
|
|
addr_item = proto_tree_add_text(a_rec_tree,tvb, curr, 6,"IP Address");
|
|
addr_tree = proto_item_add_subtree(addr_item, ett_a_rec_addr);
|
|
proto_item_set_text(addr_item,"Address %s",ip_to_str((guint8*)addr));
|
|
}
|
|
else return;
|
|
|
|
proto_tree_add_uint(addr_tree,
|
|
hf_a_rec_len,
|
|
tvb,
|
|
curr,
|
|
sizeof(guint16),
|
|
len);
|
|
|
|
proto_tree_add_text(addr_tree,
|
|
tvb,
|
|
curr + 2,
|
|
4,
|
|
"Addr: %s",
|
|
ip_to_str((guint8*)addr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void dissect_srv_records(tvbuff_t* tvb, proto_tree* tree,guint32 nrec,int offset)
|
|
{
|
|
guint32 i, curr;
|
|
guint16 len, priority, weight, port, namelen, dlen;
|
|
const char *cmpname;
|
|
guint8 dname[120];
|
|
|
|
proto_item* srv_rec_item, *rec_item;
|
|
proto_item* srv_rec_tree, *rec_tree;
|
|
|
|
if(tree)
|
|
{
|
|
srv_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "SRV records");
|
|
srv_rec_tree = proto_item_add_subtree(srv_rec_item, ett_srv_rec);
|
|
proto_item_set_text(srv_rec_item, "SRV records (%d)", nrec);
|
|
}
|
|
else return;
|
|
|
|
curr = offset;
|
|
|
|
for(i=0; i < nrec; i++)
|
|
{
|
|
len = tvb_get_ntohs(tvb, curr);
|
|
priority = tvb_get_ntohs(tvb, curr + 2);
|
|
weight = tvb_get_ntohs(tvb, curr + 4);
|
|
port = tvb_get_ntohs(tvb, curr + 6);
|
|
namelen = len - 8;
|
|
cmpname = (char*)tvb_get_ptr(tvb, curr + 8, namelen);
|
|
|
|
dlen = lwres_get_dns_name(tvb, curr + 8, curr, (gchar*)dname, sizeof(dname));
|
|
|
|
if(srv_rec_tree)
|
|
{
|
|
rec_item = proto_tree_add_text(srv_rec_tree, tvb, curr, 6," ");
|
|
rec_tree = proto_item_add_subtree(rec_item, ett_srv_rec_item);
|
|
proto_item_set_text(rec_item,
|
|
"SRV record:pri=%d,w=%d,port=%d,dname=%s",
|
|
priority,
|
|
weight,
|
|
port,
|
|
dname);
|
|
}
|
|
else return;
|
|
|
|
proto_tree_add_uint(rec_tree,
|
|
hf_srv_prio,
|
|
tvb,
|
|
curr + 2,
|
|
2,
|
|
priority);
|
|
|
|
proto_tree_add_uint(rec_tree,
|
|
hf_srv_weight,
|
|
tvb,
|
|
curr + 4,
|
|
2,
|
|
weight);
|
|
|
|
proto_tree_add_uint(rec_tree,
|
|
hf_srv_port,
|
|
tvb,
|
|
curr + 6,
|
|
2,
|
|
port);
|
|
|
|
|
|
proto_tree_add_text(rec_tree,
|
|
tvb,
|
|
curr + 8,
|
|
dlen,
|
|
"DNAME: %s", dname);
|
|
|
|
curr+=((sizeof(short)*4) + dlen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void dissect_mx_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
|
|
{
|
|
|
|
guint32 i, curr;
|
|
guint16 len, priority, dlen, namelen;
|
|
const char* cname;
|
|
guint8 dname[120];
|
|
|
|
proto_item* mx_rec_item, *rec_item;
|
|
proto_tree* mx_rec_tree, *rec_tree;
|
|
|
|
|
|
if(tree)
|
|
{
|
|
mx_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "MX records (%d)", nrec);
|
|
mx_rec_tree = proto_item_add_subtree(mx_rec_item, ett_mx_rec);
|
|
}
|
|
else
|
|
return;
|
|
|
|
curr = offset;
|
|
for(i=0; i < nrec; i++)
|
|
{
|
|
len = tvb_get_ntohs(tvb, curr);
|
|
priority = tvb_get_ntohs(tvb, curr + 2);
|
|
namelen = len - 4;
|
|
cname = (char*)tvb_get_ptr(tvb, curr + 4, 4);
|
|
dlen = lwres_get_dns_name(tvb, curr + 4, curr, (gchar*)dname, sizeof(dname));
|
|
if(mx_rec_tree)
|
|
{
|
|
rec_item = proto_tree_add_text(mx_rec_tree, tvb, curr,6,"MX record: pri=%d,dname=%s",
|
|
priority,dname);
|
|
rec_tree = proto_item_add_subtree(rec_item, ett_mx_rec_item);
|
|
}
|
|
else
|
|
return;
|
|
|
|
|
|
proto_tree_add_uint(rec_tree,
|
|
hf_srv_prio,
|
|
tvb,
|
|
curr + 2,
|
|
2,
|
|
priority);
|
|
|
|
proto_tree_add_text(rec_tree,
|
|
tvb,
|
|
curr + 4,
|
|
dlen,
|
|
"name: %s", dname);
|
|
|
|
curr+=((sizeof(short)*2) + dlen);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void dissect_ns_records(tvbuff_t* tvb, proto_tree* tree, guint32 nrec, int offset)
|
|
{
|
|
guint32 i, curr;
|
|
guint16 len, dlen, namelen;
|
|
guint8 dname[120];
|
|
|
|
proto_item* ns_rec_item, *rec_item;
|
|
proto_tree* ns_rec_tree, *rec_tree;
|
|
|
|
if(tree)
|
|
{
|
|
ns_rec_item = proto_tree_add_text(tree, tvb, offset, offset, "NS record (%d)", nrec);
|
|
ns_rec_tree = proto_item_add_subtree(ns_rec_item, ett_ns_rec);
|
|
}
|
|
else
|
|
return;
|
|
curr=offset;
|
|
|
|
for(i=0;i<nrec;i++)
|
|
{
|
|
len = tvb_get_ntohs(tvb, curr);
|
|
namelen = len - 2;
|
|
dlen = lwres_get_dns_name(tvb, curr + 2, curr, (char*)dname, sizeof(dname));
|
|
if(ns_rec_tree)
|
|
{
|
|
rec_item = proto_tree_add_text(ns_rec_tree, tvb, curr,4, "NS record: dname=%s",dname);
|
|
rec_tree = proto_item_add_subtree(rec_item, ett_ns_rec_item);
|
|
}
|
|
else
|
|
return;
|
|
|
|
proto_tree_add_text(rec_tree,
|
|
tvb,
|
|
curr + 2,
|
|
dlen,
|
|
"Name: %s", dname);
|
|
curr+=(sizeof(short) + dlen);
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
static void dissect_rdata_request(tvbuff_t* tvb, proto_tree* lwres_tree)
|
|
{
|
|
guint32 rflags;
|
|
guint16 rdclass, rdtype, namelen;
|
|
guint8 name[120];
|
|
|
|
proto_item* rdata_request_item;
|
|
proto_tree* rdata_request_tree;
|
|
|
|
rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
|
|
rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
|
|
rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
|
|
namelen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+8);
|
|
tvb_get_nstringz(tvb, LWRES_LWPACKET_LENGTH+10, namelen, name);
|
|
name[namelen]='\0';
|
|
|
|
if(lwres_tree)
|
|
{
|
|
rdata_request_item =
|
|
proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH,10+namelen+1,"RDATA request parameters");
|
|
rdata_request_tree = proto_item_add_subtree(rdata_request_item, ett_rdata_req);
|
|
}
|
|
else
|
|
return;
|
|
|
|
proto_tree_add_uint(rdata_request_tree,
|
|
hf_rflags,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+0,
|
|
sizeof(guint32),
|
|
rflags);
|
|
|
|
proto_tree_add_uint(rdata_request_tree,
|
|
hf_rdclass,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+4,
|
|
sizeof(guint16),
|
|
rdclass);
|
|
|
|
proto_tree_add_uint(rdata_request_tree,
|
|
hf_rdtype,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+6,
|
|
sizeof(guint16),
|
|
rdtype);
|
|
|
|
proto_tree_add_uint(rdata_request_tree,
|
|
hf_namelen,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+8,
|
|
sizeof(guint16),
|
|
namelen);
|
|
|
|
proto_tree_add_string(rdata_request_tree,
|
|
hf_req_name,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+10,
|
|
namelen,
|
|
(char*)name);
|
|
|
|
}
|
|
|
|
static void dissect_rdata_response(tvbuff_t* tvb, proto_tree* lwres_tree)
|
|
{
|
|
guint32 rflags, ttl, offset;
|
|
guint16 rdclass, rdtype, nrdatas, nsigs, realnamelen;
|
|
guint8 realname[120];
|
|
|
|
proto_item* rdata_resp_item;
|
|
proto_tree* rdata_resp_tree;
|
|
|
|
rflags = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+0);
|
|
rdclass = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+4);
|
|
rdtype = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+6);
|
|
ttl = tvb_get_ntohl(tvb, LWRES_LWPACKET_LENGTH+8);
|
|
nrdatas = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+12);
|
|
nsigs = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH+14);
|
|
realnamelen = tvb_get_ntohs(tvb,LWRES_LWPACKET_LENGTH+16);
|
|
tvb_get_nstringz(tvb,LWRES_LWPACKET_LENGTH+18,realnamelen, realname);
|
|
realname[realnamelen]='\0';
|
|
|
|
offset = LWRES_LWPACKET_LENGTH + 18 + realnamelen + 1;
|
|
|
|
if(lwres_tree)
|
|
{
|
|
rdata_resp_item = proto_tree_add_text(lwres_tree,tvb,LWRES_LWPACKET_LENGTH, 18+realnamelen+1,"RDATA response");
|
|
rdata_resp_tree = proto_item_add_subtree(rdata_resp_item, ett_rdata_resp);
|
|
}
|
|
else
|
|
return;
|
|
|
|
proto_tree_add_uint(rdata_resp_tree,
|
|
hf_rflags,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+0,
|
|
sizeof(guint32),
|
|
rflags);
|
|
|
|
proto_tree_add_uint(rdata_resp_tree,
|
|
hf_rdclass,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+4,
|
|
sizeof(guint16),
|
|
rdclass);
|
|
|
|
proto_tree_add_uint(rdata_resp_tree,
|
|
hf_rdtype,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+6,
|
|
sizeof(guint16),
|
|
rdtype);
|
|
|
|
proto_tree_add_uint(rdata_resp_tree,
|
|
hf_ttl,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+8,
|
|
sizeof(guint32),
|
|
ttl);
|
|
|
|
proto_tree_add_uint(rdata_resp_tree,
|
|
hf_nrdatas,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+12,
|
|
sizeof(guint16),
|
|
nrdatas);
|
|
|
|
proto_tree_add_uint(rdata_resp_tree,
|
|
hf_nsigs,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+14,
|
|
sizeof(guint16),
|
|
nsigs);
|
|
|
|
proto_tree_add_uint(rdata_resp_tree,
|
|
hf_realnamelen,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+16,
|
|
sizeof(guint16),
|
|
realnamelen);
|
|
|
|
proto_tree_add_string(rdata_resp_tree,
|
|
hf_realname,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH+18,
|
|
realnamelen,
|
|
(char*)realname);
|
|
|
|
switch(rdtype)
|
|
{
|
|
case T_A:
|
|
dissect_a_records(tvb,rdata_resp_tree,nrdatas,offset);
|
|
break;
|
|
|
|
case T_SRV:
|
|
dissect_srv_records(tvb,rdata_resp_tree,nrdatas, offset);
|
|
break;
|
|
|
|
case T_MX:
|
|
dissect_mx_records(tvb,rdata_resp_tree,nrdatas, offset);
|
|
break;
|
|
|
|
case T_NS:
|
|
dissect_ns_records(tvb,rdata_resp_tree,nrdatas, offset);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
|
|
{
|
|
guint16 datalen;
|
|
const char* data;
|
|
|
|
proto_item* noop_item;
|
|
proto_tree* noop_tree;
|
|
|
|
datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);
|
|
data = (char*)tvb_get_ptr(tvb, LWRES_LWPACKET_LENGTH, datalen);
|
|
|
|
if(lwres_tree)
|
|
{
|
|
noop_item = proto_tree_add_text(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, "Noop record");
|
|
noop_tree = proto_item_add_subtree(noop_item, ett_noop);
|
|
}
|
|
else
|
|
return;
|
|
|
|
proto_tree_add_uint(noop_tree,
|
|
hf_length,
|
|
tvb,
|
|
LWRES_LWPACKET_LENGTH,
|
|
sizeof(guint16),
|
|
datalen);
|
|
|
|
}
|
|
|
|
static void dissect_getaddrsbyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
|
|
{
|
|
if(type == 1)
|
|
dissect_getaddrsbyname_request(tvb, lwres_tree);
|
|
else
|
|
dissect_getaddrsbyname_response(tvb, lwres_tree);
|
|
}
|
|
|
|
static void dissect_getnamebyaddr(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
|
|
{
|
|
if(type == 1)
|
|
dissect_getnamebyaddr_request(tvb, lwres_tree);
|
|
else
|
|
dissect_getnamebyaddr_response(tvb, lwres_tree);
|
|
}
|
|
|
|
static void dissect_getrdatabyname(tvbuff_t* tvb, proto_tree* lwres_tree, int type)
|
|
{
|
|
if(type == 1)
|
|
dissect_rdata_request(tvb, lwres_tree);
|
|
else
|
|
dissect_rdata_response(tvb, lwres_tree);
|
|
}
|
|
|
|
static void
|
|
dissect_lwres(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
{
|
|
guint16 version, flags, authtype, authlength ;
|
|
guint32 length, opcode, result, recvlength, serial;
|
|
guint32 message_type;
|
|
|
|
proto_item* lwres_item;
|
|
proto_tree* lwres_tree;
|
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "lw_res");
|
|
length = tvb_get_ntohl(tvb, LW_LENGTH_OFFSET);
|
|
version = tvb_get_ntohs(tvb, LW_VERSION_OFFSET);
|
|
flags = tvb_get_ntohs(tvb, LW_PKTFLASG_OFFSET);
|
|
serial = tvb_get_ntohl(tvb, LW_SERIAL_OFFSET);
|
|
opcode = tvb_get_ntohl(tvb,LW_OPCODE_OFFSET);
|
|
result = tvb_get_ntohl(tvb, LW_RESULT_OFFSET);
|
|
recvlength = tvb_get_ntohl(tvb, LW_RECVLEN_OFFSET);
|
|
authtype = tvb_get_ntohs(tvb, LW_AUTHTYPE_OFFSET);
|
|
authlength = tvb_get_ntohs(tvb, LW_AUTHLEN_OFFSET);
|
|
|
|
message_type = (flags & LWRES_LWPACKETFLAG_RESPONSE) ? 2 : 1;
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) {
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
|
|
|
if(flags & LWRES_LWPACKETFLAG_RESPONSE)
|
|
{
|
|
col_add_fstr(pinfo->cinfo, COL_INFO,
|
|
"%s, opcode=%s, serial=0x%x, result=%s",
|
|
val_to_str((guint32)message_type,message_types_values,"unknown"),
|
|
val_to_str(opcode, opcode_values, "unknown"),
|
|
serial,
|
|
val_to_str(result,result_values,"unknown"));
|
|
}
|
|
else
|
|
{
|
|
col_add_fstr(pinfo->cinfo, COL_INFO,
|
|
"%s, opcode=%s, serial=0x%x",
|
|
val_to_str((guint32)message_type,message_types_values,"unknown"),
|
|
val_to_str(opcode, opcode_values, "unknown"),
|
|
serial);
|
|
}
|
|
}
|
|
|
|
if(tree)
|
|
{
|
|
lwres_item = proto_tree_add_item(tree,proto_lwres, tvb,0, -1, FALSE);
|
|
lwres_tree = proto_item_add_subtree(lwres_item, ett_lwres);
|
|
}
|
|
else return;
|
|
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_length,
|
|
tvb,
|
|
LW_LENGTH_OFFSET,
|
|
sizeof(guint32),
|
|
length);
|
|
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_version,
|
|
tvb,
|
|
LW_VERSION_OFFSET,
|
|
sizeof(guint16),
|
|
version);
|
|
|
|
|
|
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_flags,
|
|
tvb,
|
|
LW_PKTFLASG_OFFSET,
|
|
sizeof(guint16),
|
|
flags);
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_serial,
|
|
tvb,
|
|
LW_SERIAL_OFFSET,
|
|
sizeof(guint32),
|
|
serial);
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_opcode,
|
|
tvb,
|
|
LW_OPCODE_OFFSET,
|
|
sizeof(guint32),
|
|
opcode);
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_result,
|
|
tvb,
|
|
LW_RESULT_OFFSET,
|
|
sizeof(guint32),
|
|
result);
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_recvlen,
|
|
tvb,
|
|
LW_RECVLEN_OFFSET,
|
|
sizeof(guint32),
|
|
recvlength);
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_authtype,
|
|
tvb,
|
|
LW_AUTHTYPE_OFFSET,
|
|
sizeof(guint16),
|
|
authtype);
|
|
|
|
proto_tree_add_uint(lwres_tree,
|
|
hf_authlen,
|
|
tvb,
|
|
LW_AUTHLEN_OFFSET,
|
|
sizeof(guint16),
|
|
authlength);
|
|
|
|
if(!result)
|
|
{
|
|
switch(opcode)
|
|
{
|
|
case LWRES_OPCODE_NOOP:
|
|
dissect_noop(tvb, lwres_tree);
|
|
break;
|
|
|
|
case LWRES_OPCODE_GETADDRSBYNAME:
|
|
dissect_getaddrsbyname(tvb, lwres_tree, message_type);
|
|
break;
|
|
|
|
case LWRES_OPCODE_GETNAMEBYADDR:
|
|
dissect_getnamebyaddr(tvb, lwres_tree, message_type);
|
|
break;
|
|
|
|
case LWRES_OPCODE_GETRDATABYNAME:
|
|
dissect_getrdatabyname(tvb, lwres_tree, message_type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
proto_register_lwres(void)
|
|
{
|
|
static hf_register_info hf[] = {
|
|
{ &hf_length,
|
|
{ "Length", "lwres.length", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
"lwres length", HFILL }},
|
|
|
|
{ &hf_version,
|
|
{ "Version", "lwres.version", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres version", HFILL }},
|
|
|
|
{ &hf_flags,
|
|
{ "Packet Flags", "lwres.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
|
|
"lwres flags", HFILL }},
|
|
|
|
{ &hf_serial,
|
|
{ "Serial", "lwres.serial", FT_UINT32, BASE_HEX, NULL, 0x0,
|
|
"lwres serial", HFILL }},
|
|
|
|
{ &hf_opcode,
|
|
{ "Operation code", "lwres.opcode", FT_UINT32, BASE_DEC, VALS(opcode_values), 0x0,
|
|
"lwres opcode", HFILL }},
|
|
|
|
{ &hf_result,
|
|
{ "Result", "lwres.result", FT_UINT32, BASE_DEC, VALS(result_values), 0x0,
|
|
"lwres result", HFILL }},
|
|
|
|
{ &hf_recvlen,
|
|
{ "Received length", "lwres.recvlen", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
"lwres recvlen", HFILL }},
|
|
|
|
{ &hf_authtype,
|
|
{ "Auth. type", "lwres.authtype", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres authtype", HFILL }},
|
|
|
|
{ &hf_authlen,
|
|
{ "Auth. length", "lwres.authlen" , FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres authlen", HFILL }},
|
|
|
|
{ &hf_rflags,
|
|
{ "Flags", "lwres.rflags", FT_UINT32, BASE_HEX, NULL, 0x0,
|
|
"lwres rflags", HFILL }},
|
|
{ &hf_rdclass,
|
|
{ "Class", "lwres.class", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres class", HFILL }},
|
|
|
|
{ &hf_rdtype,
|
|
{ "Type", "lwres.type", FT_UINT16, BASE_DEC, VALS(t_types), 0x0,
|
|
"lwres type" , HFILL }},
|
|
|
|
{ &hf_namelen,
|
|
{ "Name length", "lwres.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres namelen", HFILL }},
|
|
|
|
{ &hf_req_name,
|
|
{ "Domain name" , "lwres.reqdname" , FT_STRING, BASE_DEC, NULL, 0x0,
|
|
"lwres reqdname", HFILL }},
|
|
|
|
{ &hf_ttl,
|
|
{ "Time To Live", "lwres.ttl", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
"lwres ttl", HFILL }},
|
|
|
|
{ &hf_nrdatas,
|
|
{ "Number of rdata records", "lwres.nrdatas", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres nrdatas" , HFILL }},
|
|
|
|
{ &hf_nsigs,
|
|
{ "Number of signature records", "lwres.nsigs", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres nsigs" , HFILL }},
|
|
|
|
{ &hf_realnamelen,
|
|
{ "Real name length", "lwres.realnamelen", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres realnamelen", HFILL }},
|
|
|
|
{ &hf_realname,
|
|
{ "Real doname name", "lwres.realname", FT_STRING, BASE_DEC, NULL, 0x0,
|
|
"lwres realname", HFILL }},
|
|
|
|
{ &hf_a_record,
|
|
{ "IPv4 Address", "lwres.arecord", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
"lwres arecord", HFILL }},
|
|
|
|
{ &hf_a_rec_len,
|
|
{ "Length", "lwres.areclen", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres areclen", HFILL }},
|
|
|
|
{ &hf_srv_prio,
|
|
{ "Priority", "lwres.srv.priority", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres srv prio", HFILL }},
|
|
|
|
{ &hf_srv_weight,
|
|
{ "Weight", "lwres.srv.weight", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres srv weight", HFILL }},
|
|
|
|
{ &hf_srv_port,
|
|
{ "Port" , "lwres.srv.port", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres srv port", HFILL }},
|
|
|
|
{ &hf_adn_flags,
|
|
{ "Flags", "lwres.adn.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
|
|
"lwres adn flags", HFILL }},
|
|
|
|
{ &hf_adn_addrtype,
|
|
{ "Address type", "lwres.adn.addrtype", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
"lwres adn addrtype", HFILL }},
|
|
|
|
{ &hf_adn_namelen,
|
|
{ "Name length", "lwres.adn.namelen", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres adn namelen", HFILL }},
|
|
|
|
{ &hf_adn_name,
|
|
{ "Name", "lwres.adn.name", FT_STRING, BASE_DEC, NULL, 0x0,
|
|
"lwres adn name", HFILL }},
|
|
|
|
{ &hf_adn_naliases,
|
|
{ "Number of aliases", "lwres.adn.naliases", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres adn naliases", HFILL }},
|
|
|
|
{ &hf_adn_naddrs,
|
|
{ "Number of addresses", "lwres.adn.naddrs", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres adn naddrs", HFILL }},
|
|
|
|
{ &hf_adn_realname,
|
|
{ "Real name", "lwres.adn.realname", FT_STRING, BASE_DEC, NULL, 0x0,
|
|
"lwres adn realname", HFILL }},
|
|
|
|
{ &hf_adn_aliasname,
|
|
{ "Alias name", "lwres.adn.aliasname", FT_STRING, BASE_DEC, NULL, 0x0,
|
|
"lwres adn aliasname", HFILL }},
|
|
|
|
{ &hf_adn_family,
|
|
{ "Address family", "lwres.adn.addr.family", FT_UINT32, BASE_DEC, NULL, 0x0,
|
|
"lwres adn addr family", HFILL }},
|
|
|
|
{ &hf_adn_addr_len,
|
|
{ "Address length", "lwres.adn.addr.length", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
"lwres adn addr length", HFILL }},
|
|
|
|
{ &hf_adn_addr_addr,
|
|
{ "IP Address", "lwres.adn.addr.addr", FT_STRING, BASE_DEC, NULL, 0x0,
|
|
"lwres adn addr addr", HFILL }},
|
|
|
|
/* Add more fields here */
|
|
};
|
|
|
|
static gint *ett[] = {
|
|
&ett_lwres,
|
|
&ett_rdata_req,
|
|
&ett_rdata_resp,
|
|
&ett_a_rec,
|
|
&ett_a_rec_addr,
|
|
&ett_srv_rec,
|
|
&ett_srv_rec_item,
|
|
&ett_adn_request,
|
|
&ett_adn_resp,
|
|
&ett_adn_alias,
|
|
&ett_adn_addr,
|
|
&ett_nba_request,
|
|
&ett_nba_resp,
|
|
&ett_mx_rec,
|
|
&ett_mx_rec_item,
|
|
&ett_ns_rec,
|
|
&ett_ns_rec_item,
|
|
&ett_noop,
|
|
};
|
|
|
|
|
|
module_t *lwres_module;
|
|
|
|
proto_lwres = proto_register_protocol("Light Weight DNS RESolver (BIND9)",
|
|
"LWRES", "lwres");
|
|
|
|
proto_register_field_array(proto_lwres, hf, array_length(hf));
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
lwres_module = prefs_register_protocol(proto_lwres, proto_reg_handoff_lwres);
|
|
|
|
prefs_register_uint_preference(lwres_module, "udp.lwres_port",
|
|
"lwres listener UDP Port",
|
|
"Set the UDP port for lwres daemon"
|
|
"(if other than the default of 921)",
|
|
10, &global_lwres_port);
|
|
|
|
}
|
|
|
|
/* The registration hand-off routine */
|
|
void
|
|
proto_reg_handoff_lwres(void)
|
|
{
|
|
static gboolean lwres_prefs_initialized = FALSE;
|
|
static dissector_handle_t lwres_handle;
|
|
static guint lwres_port;
|
|
|
|
if(!lwres_prefs_initialized) {
|
|
lwres_handle = create_dissector_handle(dissect_lwres, proto_lwres);
|
|
lwres_prefs_initialized = TRUE;
|
|
}
|
|
else {
|
|
dissector_delete("udp.port", lwres_port, lwres_handle);
|
|
}
|
|
|
|
dissector_add("udp.port", global_lwres_port, lwres_handle);
|
|
lwres_port = global_lwres_port;
|
|
|
|
}
|