Tag NetBIOS Name Service-over-UDP packets as "NBNS (UDP)".
Give a detailed display of the innards of NBNS-over-UDP packets. Export some stuff from the DNS decoder for the use of the NBNS decoder (NBNS is DNS-like). Give a more detailed display of the innards of DNS packets as well. Fix a couple of minor NBNS bugs. svn path=/trunk/; revision=55
This commit is contained in:
parent
b3da21d812
commit
022967513b
|
@ -1,6 +1,6 @@
|
|||
/* ethereal.c
|
||||
*
|
||||
* $Id: ethereal.c,v 1.5 1998/10/12 01:40:47 gerald Exp $
|
||||
* $Id: ethereal.c,v 1.6 1998/10/14 19:34:57 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@zing.org>
|
||||
|
@ -520,7 +520,7 @@ main(int argc, char *argv[])
|
|||
col_width = gdk_string_width(pl_style->font, "00:00:00:00:00:00") + 2;
|
||||
gtk_clist_set_column_width(GTK_CLIST(packet_list), COL_SOURCE, col_width);
|
||||
gtk_clist_set_column_width(GTK_CLIST(packet_list), COL_DESTINATION, col_width);
|
||||
col_width = gdk_string_width(pl_style->font, "AppleTalk") + 2;
|
||||
col_width = gdk_string_width(pl_style->font, "NBNS (UDP)") + 2;
|
||||
gtk_clist_set_column_width(GTK_CLIST(packet_list), COL_PROTOCOL, col_width);
|
||||
gtk_widget_set_usize(packet_list, -1, pl_size);
|
||||
gtk_paned_add1(GTK_PANED(u_pane), packet_list);
|
||||
|
|
238
packet-dns.c
238
packet-dns.c
|
@ -1,7 +1,7 @@
|
|||
/* packet-dns.c
|
||||
* Routines for DNS packet disassembly
|
||||
*
|
||||
* $Id: packet-dns.c,v 1.4 1998/09/27 22:12:28 gerald Exp $
|
||||
* $Id: packet-dns.c,v 1.5 1998/10/14 19:34:58 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@zing.org>
|
||||
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "ethereal.h"
|
||||
#include "packet.h"
|
||||
#include "packet-dns.h"
|
||||
|
||||
|
||||
/* DNS structs and definitions */
|
||||
|
@ -56,8 +57,6 @@ typedef struct _e_dns {
|
|||
guint16 dns_add;
|
||||
} e_dns;
|
||||
|
||||
#define MAXDNAME 1025 /* maximum domain name */
|
||||
|
||||
/* type values */
|
||||
#define T_A 1 /* host address */
|
||||
#define T_NS 2 /* authoritative server */
|
||||
|
@ -71,8 +70,6 @@ typedef struct _e_dns {
|
|||
#define T_AAAA 28 /* IP6 Address */
|
||||
|
||||
|
||||
static const u_char *dns_data_ptr;
|
||||
|
||||
static char *
|
||||
dns_type_name (int type)
|
||||
{
|
||||
|
@ -116,7 +113,7 @@ dns_type_name (int type)
|
|||
}
|
||||
|
||||
|
||||
static char *
|
||||
char *
|
||||
dns_class_name(int class)
|
||||
{
|
||||
char *class_name;
|
||||
|
@ -171,7 +168,8 @@ copy_one_name_component(const u_char *dataptr, char *nameptr)
|
|||
|
||||
|
||||
static int
|
||||
copy_name_component_rec(const u_char *dataptr, char *nameptr, int *real_string_len)
|
||||
copy_name_component_rec(const u_char *dns_data_ptr, const u_char *dataptr,
|
||||
char *nameptr, int *real_string_len)
|
||||
{
|
||||
int len = 0;
|
||||
int str_len;
|
||||
|
@ -182,7 +180,7 @@ copy_name_component_rec(const u_char *dataptr, char *nameptr, int *real_string_l
|
|||
compress = 1;
|
||||
offset = get_compressed_name_offset(dataptr);
|
||||
dataptr = dns_data_ptr + offset;
|
||||
copy_name_component_rec(dataptr, nameptr, &str_len);
|
||||
copy_name_component_rec(dns_data_ptr, dataptr, nameptr, &str_len);
|
||||
*real_string_len += str_len;
|
||||
nameptr += str_len;
|
||||
len = 2;
|
||||
|
@ -202,7 +200,7 @@ copy_name_component_rec(const u_char *dataptr, char *nameptr, int *real_string_l
|
|||
|
||||
if (*dataptr > 0) {
|
||||
*nameptr++ = '.';
|
||||
len += copy_name_component_rec(dataptr, nameptr, &str_len);
|
||||
len += copy_name_component_rec(dns_data_ptr, dataptr, nameptr, &str_len);
|
||||
*real_string_len += str_len;
|
||||
return len;
|
||||
}
|
||||
|
@ -211,24 +209,27 @@ copy_name_component_rec(const u_char *dataptr, char *nameptr, int *real_string_l
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
get_dns_name(const u_char *pd, int offset, char *nameptr, int maxname)
|
||||
int
|
||||
get_dns_name(const u_char *dns_data_ptr, const u_char *pd, int offset,
|
||||
char *nameptr, int maxname)
|
||||
{
|
||||
int len;
|
||||
const u_char *dataptr = pd + offset;
|
||||
int str_len = 0;
|
||||
|
||||
memset (nameptr, 0, maxname);
|
||||
len = copy_name_component_rec(dataptr, nameptr, &str_len);
|
||||
len = copy_name_component_rec(dns_data_ptr, dataptr, nameptr, &str_len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
get_dns_name_type_class (const u_char *pd,
|
||||
get_dns_name_type_class (const u_char *dns_data_ptr,
|
||||
const u_char *pd,
|
||||
int offset,
|
||||
char *name_ret,
|
||||
char *name_ret,
|
||||
int *name_len_ret,
|
||||
int *type_ret,
|
||||
int *class_ret)
|
||||
{
|
||||
|
@ -239,19 +240,20 @@ get_dns_name_type_class (const u_char *pd,
|
|||
char name[MAXDNAME];
|
||||
const u_char *pd_save;
|
||||
|
||||
name_len = get_dns_name(pd, offset, name, sizeof(name));
|
||||
name_len = get_dns_name(dns_data_ptr, pd, offset, name, sizeof(name));
|
||||
pd += offset;
|
||||
pd_save = pd;
|
||||
pd += name_len;
|
||||
|
||||
type = (*pd << 8) | *(pd + 1);
|
||||
type = pntohs(pd);
|
||||
pd += 2;
|
||||
class = (*pd << 8) | *(pd + 1);
|
||||
class = pntohs(pd);
|
||||
pd += 2;
|
||||
|
||||
strcpy (name_ret, name);
|
||||
*type_ret = type;
|
||||
*class_ret = class;
|
||||
*name_len_ret = name_len;
|
||||
|
||||
len = pd - pd_save;
|
||||
return len;
|
||||
|
@ -259,114 +261,141 @@ get_dns_name_type_class (const u_char *pd,
|
|||
|
||||
|
||||
static int
|
||||
dissect_dns_query(const u_char *pd, int offset, GtkWidget *dns_tree)
|
||||
{
|
||||
int len;
|
||||
char name[MAXDNAME];
|
||||
int type;
|
||||
int class;
|
||||
char *class_name;
|
||||
char *type_name;
|
||||
|
||||
len = get_dns_name_type_class (pd, offset, name, &type, &class);
|
||||
|
||||
type_name = dns_type_name(type);
|
||||
class_name = dns_class_name(class);
|
||||
|
||||
add_item_to_tree(dns_tree, offset, len, "%s: type %s, class %s",
|
||||
name, type_name, class_name );
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dissect_dns_answer(const u_char *pd, int offset, GtkWidget *dns_tree)
|
||||
dissect_dns_query(const u_char *dns_data_ptr, const u_char *pd, int offset,
|
||||
GtkWidget *dns_tree)
|
||||
{
|
||||
int len;
|
||||
char name[MAXDNAME];
|
||||
int name_len;
|
||||
int type;
|
||||
int class;
|
||||
char *class_name;
|
||||
char *type_name;
|
||||
const u_char *dptr;
|
||||
const u_char *data_start;
|
||||
const u_char *res_ptr;
|
||||
u_int ttl;
|
||||
u_short data_len;
|
||||
|
||||
data_start = dptr = pd + offset;
|
||||
|
||||
len = get_dns_name_type_class (pd, offset, name, &type, &class);
|
||||
len = get_dns_name_type_class(dns_data_ptr, pd, offset, name, &name_len,
|
||||
&type, &class);
|
||||
dptr += len;
|
||||
|
||||
/* this works regardless of the alignment */
|
||||
ttl = (*dptr << 24) | *(dptr + 1) << 16 | *(dptr + 2) << 8 | *(dptr + 3);
|
||||
dptr += 4;
|
||||
data_len = (*dptr << 8) | *(dptr + 1);
|
||||
dptr += 2;
|
||||
add_item_to_tree(dns_tree, offset, name_len, "Name: %s", name);
|
||||
offset += name_len;
|
||||
|
||||
type_name = dns_type_name(type);
|
||||
add_item_to_tree(dns_tree, offset, 2, "Type: %s", type_name);
|
||||
offset += 2;
|
||||
|
||||
class_name = dns_class_name(class);
|
||||
add_item_to_tree(dns_tree, offset, 2, "Class: %s", class_name);
|
||||
offset += 2;
|
||||
|
||||
return dptr - data_start;
|
||||
}
|
||||
|
||||
|
||||
GtkWidget *
|
||||
add_rr_to_tree(GtkWidget *trr, int rr_type, int offset, const char *name,
|
||||
int namelen, const char *type_name, const char *class_name, u_int ttl,
|
||||
u_short data_len)
|
||||
{
|
||||
GtkWidget *rr_tree;
|
||||
|
||||
rr_tree = gtk_tree_new();
|
||||
add_subtree(trr, rr_tree, rr_type);
|
||||
add_item_to_tree(rr_tree, offset, namelen, "Name: %s", name);
|
||||
offset += namelen;
|
||||
add_item_to_tree(rr_tree, offset, 2, "Type: %s", type_name);
|
||||
offset += 2;
|
||||
add_item_to_tree(rr_tree, offset, 2, "Class: %s", class_name);
|
||||
offset += 2;
|
||||
add_item_to_tree(rr_tree, offset, 4, "Time to live: %u", ttl);
|
||||
offset += 4;
|
||||
add_item_to_tree(rr_tree, offset, 2, "Data length: %u", data_len);
|
||||
return rr_tree;
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_dns_answer(const u_char *dns_data_ptr, const u_char *pd, int offset,
|
||||
GtkWidget *dns_tree)
|
||||
{
|
||||
int len;
|
||||
char name[MAXDNAME];
|
||||
int name_len;
|
||||
int type;
|
||||
int class;
|
||||
char *class_name;
|
||||
char *type_name;
|
||||
const u_char *dptr;
|
||||
const u_char *data_start;
|
||||
u_int ttl;
|
||||
u_short data_len;
|
||||
GtkWidget *rr_tree, *trr;
|
||||
|
||||
data_start = dptr = pd + offset;
|
||||
|
||||
len = get_dns_name_type_class(dns_data_ptr, pd, offset, name, &name_len,
|
||||
&type, &class);
|
||||
dptr += len;
|
||||
|
||||
type_name = dns_type_name(type);
|
||||
class_name = dns_class_name(class);
|
||||
res_ptr = dptr;
|
||||
|
||||
/* skip the resource data */
|
||||
dptr += data_len;
|
||||
|
||||
len = dptr - data_start;
|
||||
|
||||
ttl = pntohl(dptr);
|
||||
dptr += 4;
|
||||
|
||||
data_len = pntohs(dptr);
|
||||
dptr += 2;
|
||||
|
||||
switch (type) {
|
||||
case T_A: /* "A" record */
|
||||
add_item_to_tree(dns_tree, offset, len,
|
||||
trr = add_item_to_tree(dns_tree, offset, (dptr - data_start) + data_len,
|
||||
"%s: type %s, class %s, addr %d.%d.%d.%d",
|
||||
name, type_name, class_name,
|
||||
*res_ptr, *(res_ptr+1), *(res_ptr+2), *(res_ptr+3));
|
||||
*dptr, *(dptr+1), *(dptr+2), *(dptr+3));
|
||||
rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len, type_name,
|
||||
class_name, ttl, data_len);
|
||||
offset += (dptr - data_start);
|
||||
add_item_to_tree(rr_tree, offset, 4, "Addr: %d.%d.%d.%d",
|
||||
*dptr, *(dptr+1), *(dptr+2), *(dptr+3));
|
||||
break;
|
||||
|
||||
case T_NS: /* "NS" record */
|
||||
{
|
||||
char ns_name[MAXDNAME];
|
||||
int ns_name_len;
|
||||
|
||||
get_dns_name(res_ptr, 0, ns_name, sizeof(ns_name));
|
||||
add_item_to_tree(dns_tree, offset, len,
|
||||
"%s: %s, type %s, class %s",
|
||||
name, ns_name, type_name, class_name);
|
||||
|
||||
ns_name_len = get_dns_name(dns_data_ptr, dptr, 0, ns_name, sizeof(ns_name));
|
||||
trr = add_item_to_tree(dns_tree, offset, (dptr - data_start) + data_len,
|
||||
"%s: type %s, class %s, ns %s",
|
||||
name, type_name, class_name, ns_name);
|
||||
rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len,
|
||||
type_name, class_name, ttl, data_len);
|
||||
offset += (dptr - data_start);
|
||||
add_item_to_tree(rr_tree, offset, ns_name_len, "Name server: %s", ns_name);
|
||||
}
|
||||
break;
|
||||
|
||||
/* TODO: parse more record types */
|
||||
|
||||
default:
|
||||
add_item_to_tree(dns_tree, offset, len, "%s: type %s, class %s",
|
||||
default:
|
||||
trr = add_item_to_tree(dns_tree, offset, (dptr - data_start) + data_len,
|
||||
"%s: type %s, class %s",
|
||||
name, type_name, class_name);
|
||||
rr_tree = add_rr_to_tree(trr, ETT_DNS_RR, offset, name, name_len, type_name,
|
||||
class_name, ttl, data_len);
|
||||
offset += (dptr - data_start);
|
||||
add_item_to_tree(rr_tree, offset, data_len, "Data");
|
||||
}
|
||||
|
||||
return len;
|
||||
dptr += data_len;
|
||||
|
||||
return dptr - data_start;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dissect_answer_records(int count, const u_char *pd, int cur_off,
|
||||
GtkWidget *dns_tree, char *name)
|
||||
{
|
||||
int start_off;
|
||||
GtkWidget *qatree, *ti;
|
||||
|
||||
qatree = gtk_tree_new();
|
||||
start_off = cur_off;
|
||||
|
||||
while (count-- > 0)
|
||||
cur_off += dissect_dns_answer(pd, cur_off, qatree);
|
||||
ti = add_item_to_tree(GTK_WIDGET(dns_tree), start_off, cur_off - start_off, name);
|
||||
add_subtree(ti, qatree, ETT_DNS_ANS);
|
||||
|
||||
return cur_off - start_off;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dissect_query_records(int count, const u_char *pd,
|
||||
dissect_query_records(const u_char *dns_data_ptr, int count, const u_char *pd,
|
||||
int cur_off, GtkWidget *dns_tree)
|
||||
{
|
||||
int start_off;
|
||||
|
@ -376,7 +405,7 @@ dissect_query_records(int count, const u_char *pd,
|
|||
start_off = cur_off;
|
||||
|
||||
while (count-- > 0)
|
||||
cur_off += dissect_dns_query(pd, cur_off, qatree);
|
||||
cur_off += dissect_dns_query(dns_data_ptr, pd, cur_off, qatree);
|
||||
ti = add_item_to_tree(GTK_WIDGET(dns_tree),
|
||||
start_off, cur_off - start_off, "Queries");
|
||||
add_subtree(ti, qatree, ETT_DNS_QRY);
|
||||
|
@ -386,8 +415,29 @@ dissect_query_records(int count, const u_char *pd,
|
|||
|
||||
|
||||
|
||||
static int
|
||||
dissect_answer_records(const u_char *dns_data_ptr, int count,
|
||||
const u_char *pd, int cur_off, GtkWidget *dns_tree,
|
||||
char *name)
|
||||
{
|
||||
int start_off;
|
||||
GtkWidget *qatree, *ti;
|
||||
|
||||
qatree = gtk_tree_new();
|
||||
start_off = cur_off;
|
||||
|
||||
while (count-- > 0)
|
||||
cur_off += dissect_dns_answer(dns_data_ptr, pd, cur_off, qatree);
|
||||
ti = add_item_to_tree(GTK_WIDGET(dns_tree), start_off, cur_off - start_off, name);
|
||||
add_subtree(ti, qatree, ETT_DNS_ANS);
|
||||
|
||||
return cur_off - start_off;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dissect_dns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
|
||||
const u_char *dns_data_ptr;
|
||||
e_dns *dh;
|
||||
GtkWidget *dns_tree, *ti;
|
||||
guint16 id, flags, quest, ans, auth, add;
|
||||
|
@ -430,17 +480,19 @@ dissect_dns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
|
|||
cur_off = offset + 12;
|
||||
|
||||
if (quest > 0)
|
||||
cur_off += dissect_query_records(quest, pd, cur_off, dns_tree);
|
||||
cur_off += dissect_query_records(dns_data_ptr, quest, pd, cur_off,
|
||||
dns_tree);
|
||||
|
||||
if (ans > 0)
|
||||
cur_off += dissect_answer_records(ans, pd, cur_off, dns_tree, "Answers");
|
||||
cur_off += dissect_answer_records(dns_data_ptr, ans, pd, cur_off,
|
||||
dns_tree, "Answers");
|
||||
|
||||
if (auth > 0)
|
||||
cur_off += dissect_answer_records(auth, pd, cur_off, dns_tree,
|
||||
"Authoritative nameservers");
|
||||
cur_off += dissect_answer_records(dns_data_ptr, auth, pd, cur_off,
|
||||
dns_tree, "Authoritative nameservers");
|
||||
|
||||
if (add > 0)
|
||||
cur_off += dissect_answer_records(add, pd, cur_off, dns_tree,
|
||||
"Additional records");
|
||||
cur_off += dissect_answer_records(dns_data_ptr, add, pd, cur_off,
|
||||
dns_tree, "Additional records");
|
||||
}
|
||||
}
|
||||
|
|
705
packet-nbns.c
705
packet-nbns.c
|
@ -1,8 +1,9 @@
|
|||
/* packet-nbns.c
|
||||
* Routines for NetBIOS Name Service packet disassembly
|
||||
* Gilbert Ramirez <gram@verdict.uthscsa.edu>
|
||||
* Much stuff added by Guy Harris <guy@netapp.com>
|
||||
*
|
||||
* $Id: packet-nbns.c,v 1.1 1998/10/14 04:09:11 gram Exp $
|
||||
* $Id: packet-nbns.c,v 1.2 1998/10/14 19:34:59 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@zing.org>
|
||||
|
@ -44,6 +45,7 @@
|
|||
|
||||
#include "ethereal.h"
|
||||
#include "packet.h"
|
||||
#include "packet-dns.h"
|
||||
|
||||
/* Packet structure taken from RFC 1002. See also RFC 1001.
|
||||
* The Samba source code, specifically nmblib.c, also helps a lot. */
|
||||
|
@ -67,36 +69,638 @@ struct nbns_header {
|
|||
guint16 arcount;
|
||||
};
|
||||
|
||||
/* type values */
|
||||
#define T_NB 32 /* NetBIOS name service RR */
|
||||
#define T_NBSTAT 33 /* NetBIOS node status RR */
|
||||
|
||||
|
||||
static char *
|
||||
nbns_type_name (int type)
|
||||
{
|
||||
switch (type) {
|
||||
case T_NB:
|
||||
return "NB";
|
||||
case T_NBSTAT:
|
||||
return "NBSTAT";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/* "Canonicalize" a 16-character NetBIOS name by:
|
||||
*
|
||||
* removing and saving the last byte;
|
||||
*
|
||||
* stripping trailing blanks;
|
||||
*
|
||||
* appending the trailing byte, as a hex number, in square brackets. */
|
||||
static char *
|
||||
canonicalize_netbios_name(char *nbname)
|
||||
{
|
||||
char *pnbname;
|
||||
u_char lastchar;
|
||||
|
||||
/* Get the last character of the name, as it's a special number
|
||||
* indicating the type of the name, rather than part of the name
|
||||
* *per se*. */
|
||||
pnbname = nbname + 15; /* point to the 16th character */
|
||||
lastchar = *(unsigned char *)pnbname;
|
||||
|
||||
/* Now strip off any trailing blanks used to pad it to
|
||||
* 16 bytes. */
|
||||
while (pnbname > &nbname[0]) {
|
||||
if (*(pnbname - 1) != ' ')
|
||||
break; /* found non-blank character */
|
||||
pnbname--; /* blank - skip over it */
|
||||
}
|
||||
|
||||
/* Replace the last character with its hex value, in square
|
||||
* brackets, to make it easier to tell what it is. */
|
||||
sprintf(pnbname, "[%02X]", lastchar);
|
||||
pnbname += 4;
|
||||
return pnbname;
|
||||
}
|
||||
|
||||
static int
|
||||
get_nbns_name_type_class(const u_char *nbns_data_ptr, const u_char *pd,
|
||||
int offset, char *name_ret, int *name_len_ret, int *type_ret,
|
||||
int *class_ret)
|
||||
{
|
||||
int len;
|
||||
int name_len;
|
||||
int type;
|
||||
int class;
|
||||
char name[MAXDNAME];
|
||||
char nbname[MAXDNAME+4]; /* 4 for [<last char>] */
|
||||
char *pname, *pnbname, cname, cnbname;
|
||||
const u_char *pd_save;
|
||||
|
||||
name_len = get_dns_name(nbns_data_ptr, pd, offset, name, sizeof(name));
|
||||
pd += offset;
|
||||
pd_save = pd;
|
||||
pd += name_len;
|
||||
|
||||
type = pntohs(pd);
|
||||
pd += 2;
|
||||
class = pntohs(pd);
|
||||
pd += 2;
|
||||
|
||||
/* OK, now undo the first-level encoding. */
|
||||
pname = &name[0];
|
||||
pnbname = &nbname[0];
|
||||
for (;;) {
|
||||
/* Every two characters of the first level-encoded name
|
||||
* turn into one character in the decoded name. */
|
||||
cname = *pname;
|
||||
if (cname == '\0')
|
||||
break; /* no more characters */
|
||||
if (cname == '.')
|
||||
break; /* scope ID follows */
|
||||
if (cname < 'A' || cname > 'Z') {
|
||||
/* Not legal. */
|
||||
strcpy(nbname,
|
||||
"Illegal NetBIOS name (character not between A and Z in first-level encoding)");
|
||||
goto bad;
|
||||
}
|
||||
cname -= 'A';
|
||||
cnbname = cname << 4;
|
||||
pname++;
|
||||
|
||||
cname = *pname;
|
||||
if (cname == '\0' || cname == '.') {
|
||||
/* No more characters in the name - but we're in
|
||||
* the middle of a pair. Not legal. */
|
||||
strcpy(nbname,
|
||||
"Illegal NetBIOS name (odd number of bytes)");
|
||||
goto bad;
|
||||
}
|
||||
if (cname < 'A' || cname > 'Z') {
|
||||
/* Not legal. */
|
||||
strcpy(nbname,
|
||||
"Illegal NetBIOS name (character not between A and Z in first-level encoding)");
|
||||
goto bad;
|
||||
}
|
||||
cname -= 'A';
|
||||
cnbname |= cname;
|
||||
pname++;
|
||||
|
||||
/* Store the character. */
|
||||
*pnbname++ = cnbname;
|
||||
}
|
||||
|
||||
/* NetBIOS names are supposed to be exactly 16 bytes long. */
|
||||
if (pnbname - nbname == 16) {
|
||||
/* This one is; canonicalize its name. */
|
||||
pnbname = canonicalize_netbios_name(nbname);
|
||||
} else {
|
||||
sprintf(nbname, "Illegal NetBIOS name (%d bytes long)",
|
||||
pnbname - nbname);
|
||||
goto bad;
|
||||
}
|
||||
if (cname == '.') {
|
||||
/* We have a scope ID, starting at "pname"; append that to
|
||||
* the decoded host name. */
|
||||
strcpy(pnbname, pname);
|
||||
} else {
|
||||
/* Terminate the decoded host name. */
|
||||
*pnbname = '\0';
|
||||
}
|
||||
|
||||
bad:
|
||||
strcpy (name_ret, nbname);
|
||||
*type_ret = type;
|
||||
*class_ret = class;
|
||||
*name_len_ret = name_len;
|
||||
|
||||
len = pd - pd_save;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dissect_nbns_query(const u_char *nbns_data_ptr, const u_char *pd, int offset,
|
||||
GtkWidget *nbns_tree)
|
||||
{
|
||||
int len;
|
||||
char name[MAXDNAME];
|
||||
int name_len;
|
||||
int type;
|
||||
int class;
|
||||
char *class_name;
|
||||
char *type_name;
|
||||
const u_char *dptr;
|
||||
const u_char *data_start;
|
||||
|
||||
data_start = dptr = pd + offset;
|
||||
|
||||
len = get_nbns_name_type_class(nbns_data_ptr, pd, offset, name,
|
||||
&name_len, &type, &class);
|
||||
dptr += len;
|
||||
|
||||
add_item_to_tree(nbns_tree, offset, name_len, "Name: %s", name);
|
||||
offset += name_len;
|
||||
|
||||
type_name = nbns_type_name(type);
|
||||
add_item_to_tree(nbns_tree, offset, 2, "Type: %s", type_name);
|
||||
offset += 2;
|
||||
|
||||
class_name = dns_class_name(class);
|
||||
add_item_to_tree(nbns_tree, offset, 2, "Class: %s", class_name);
|
||||
offset += 2;
|
||||
|
||||
return dptr - data_start;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dissect_nbns_answer(const u_char *nbns_data_ptr, const u_char *pd, int offset,
|
||||
GtkWidget *nbns_tree, int opcode)
|
||||
{
|
||||
int len;
|
||||
char name[MAXDNAME];
|
||||
int name_len;
|
||||
int type;
|
||||
int class;
|
||||
char *class_name;
|
||||
char *type_name;
|
||||
const u_char *dptr;
|
||||
const u_char *data_start;
|
||||
u_int ttl;
|
||||
u_short data_len;
|
||||
u_short flags;
|
||||
GtkWidget *rr_tree, *trr;
|
||||
|
||||
data_start = dptr = pd + offset;
|
||||
|
||||
len = get_nbns_name_type_class(nbns_data_ptr, pd, offset, name,
|
||||
&name_len, &type, &class);
|
||||
dptr += len;
|
||||
|
||||
type_name = nbns_type_name(type);
|
||||
class_name = dns_class_name(class);
|
||||
|
||||
ttl = pntohl(dptr);
|
||||
dptr += 4;
|
||||
|
||||
data_len = pntohs(dptr);
|
||||
dptr += 2;
|
||||
|
||||
switch (type) {
|
||||
case T_NB: /* "NB" record */
|
||||
trr = add_item_to_tree(nbns_tree, offset,
|
||||
(dptr - data_start) + data_len,
|
||||
"%s: type %s, class %s",
|
||||
name, type_name, class_name);
|
||||
rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
|
||||
name_len, type_name, class_name, ttl, data_len);
|
||||
offset += (dptr - data_start);
|
||||
while (data_len > 0) {
|
||||
if (opcode == 0x7) {
|
||||
/* WACK response. This doesn't contain the
|
||||
* same type of RR data as other T_NB
|
||||
* responses. */
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
flags = pntohs(dptr);
|
||||
dptr += 2;
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Flags: 0x%x", flags);
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
} else {
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
flags = pntohs(dptr);
|
||||
dptr += 2;
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Flags: 0x%x", flags);
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 4) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 4,
|
||||
"Addr: %d.%d.%d.%d",
|
||||
*dptr, *(dptr+1), *(dptr+2), *(dptr+3));
|
||||
dptr += 4;
|
||||
offset += 4;
|
||||
data_len -= 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case T_NBSTAT: /* "NBSTAT" record */
|
||||
{
|
||||
u_int num_names;
|
||||
char nbname[16+4+1]; /* 4 for [<last char>] */
|
||||
u_short name_flags;
|
||||
|
||||
trr = add_item_to_tree(nbns_tree, offset,
|
||||
(dptr - data_start) + data_len,
|
||||
"%s: type %s, class %s",
|
||||
name, type_name, class_name);
|
||||
rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
|
||||
name_len, type_name, class_name, ttl, data_len);
|
||||
offset += (dptr - data_start);
|
||||
if (data_len < 1) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
num_names = *dptr;
|
||||
dptr += 1;
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of names: %u", num_names);
|
||||
offset += 1;
|
||||
|
||||
while (num_names != 0) {
|
||||
if (data_len < 16) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
goto out;
|
||||
}
|
||||
memcpy(nbname, dptr, 16);
|
||||
dptr += 16;
|
||||
canonicalize_netbios_name(nbname);
|
||||
add_item_to_tree(rr_tree, offset, 16,
|
||||
"Name: %s", nbname);
|
||||
offset += 16;
|
||||
data_len -= 16;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
goto out;
|
||||
}
|
||||
name_flags = pntohs(dptr);
|
||||
dptr += 2;
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Name flags: 0x%x", name_flags);
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
num_names--;
|
||||
}
|
||||
|
||||
if (data_len < 6) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 6,
|
||||
"Unit ID: %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
*dptr, *(dptr + 1), *(dptr + 2),
|
||||
*(dptr + 3), *(dptr + 4), *(dptr + 5));
|
||||
dptr += 6;
|
||||
offset += 6;
|
||||
data_len -= 6;
|
||||
|
||||
if (data_len < 1) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 1,
|
||||
"Jumpers: 0x%x", *dptr);
|
||||
dptr += 1;
|
||||
offset += 1;
|
||||
data_len -= 1;
|
||||
|
||||
if (data_len < 1) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 1,
|
||||
"Test result: 0x%x", *dptr);
|
||||
dptr += 1;
|
||||
offset += 1;
|
||||
data_len -= 1;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Version number: 0x%x", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Period of statistics: 0x%x", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of CRCs: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of alignment errors: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of collisions: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of send aborts: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 4) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 4,
|
||||
"Number of good sends: %u", pntohl(dptr));
|
||||
dptr += 4;
|
||||
offset += 4;
|
||||
data_len -= 4;
|
||||
|
||||
if (data_len < 4) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 4,
|
||||
"Number of good receives: %u", pntohl(dptr));
|
||||
dptr += 4;
|
||||
offset += 4;
|
||||
data_len -= 4;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of retransmits: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of no resource conditions: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of command blocks: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Number of pending sessions: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Max number of pending sessions: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Max total sessions possible: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
|
||||
if (data_len < 2) {
|
||||
add_item_to_tree(rr_tree, offset,
|
||||
data_len, "(incomplete entry)");
|
||||
break;
|
||||
}
|
||||
add_item_to_tree(rr_tree, offset, 2,
|
||||
"Session data packet size: %u", pntohs(dptr));
|
||||
dptr += 2;
|
||||
offset += 2;
|
||||
data_len -= 2;
|
||||
}
|
||||
out:
|
||||
break;
|
||||
|
||||
default:
|
||||
trr = add_item_to_tree(nbns_tree, offset,
|
||||
(dptr - data_start) + data_len,
|
||||
"%s: type %s, class %s",
|
||||
name, type_name, class_name);
|
||||
rr_tree = add_rr_to_tree(trr, ETT_NBNS_RR, offset, name,
|
||||
name_len, type_name, class_name, ttl, data_len);
|
||||
offset += (dptr - data_start);
|
||||
add_item_to_tree(rr_tree, offset, data_len, "Data");
|
||||
break;
|
||||
}
|
||||
dptr += data_len;
|
||||
|
||||
return dptr - data_start;
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_query_records(const u_char *nbns_data_ptr, int count, const u_char *pd,
|
||||
int cur_off, GtkWidget *nbns_tree)
|
||||
{
|
||||
int start_off;
|
||||
GtkWidget *qatree, *ti;
|
||||
|
||||
qatree = gtk_tree_new();
|
||||
start_off = cur_off;
|
||||
|
||||
while (count-- > 0)
|
||||
cur_off += dissect_nbns_query(nbns_data_ptr, pd, cur_off, qatree);
|
||||
ti = add_item_to_tree(GTK_WIDGET(nbns_tree),
|
||||
start_off, cur_off - start_off, "Queries");
|
||||
add_subtree(ti, qatree, ETT_NBNS_QRY);
|
||||
|
||||
return cur_off - start_off;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
dissect_answer_records(const u_char *nbns_data_ptr, int count,
|
||||
const u_char *pd, int cur_off, GtkWidget *nbns_tree, int opcode, char *name)
|
||||
{
|
||||
int start_off;
|
||||
GtkWidget *qatree, *ti;
|
||||
|
||||
qatree = gtk_tree_new();
|
||||
start_off = cur_off;
|
||||
|
||||
while (count-- > 0)
|
||||
cur_off += dissect_nbns_answer(nbns_data_ptr, pd, cur_off,
|
||||
qatree, opcode);
|
||||
ti = add_item_to_tree(GTK_WIDGET(nbns_tree), start_off, cur_off - start_off, name);
|
||||
add_subtree(ti, qatree, ETT_NBNS_ANS);
|
||||
|
||||
return cur_off - start_off;
|
||||
}
|
||||
|
||||
void
|
||||
dissect_nbns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
|
||||
{
|
||||
GtkWidget *nbns_tree, *ti;
|
||||
GtkWidget *nbns_tree, *ti;
|
||||
struct nbns_header header;
|
||||
int nm_flags;
|
||||
int nm_flags;
|
||||
const u_char *nbns_data_ptr;
|
||||
int cur_off;
|
||||
|
||||
char *opcode[] = {
|
||||
"Query",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown operation (1)",
|
||||
"Unknown operation (2)",
|
||||
"Unknown operation (3)",
|
||||
"Unknown operation (4)",
|
||||
"Registration",
|
||||
"Release",
|
||||
"Wait and Acknowledge",
|
||||
"Refresh"
|
||||
"Refresh(altcode)"
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Unknown",
|
||||
"Refresh",
|
||||
"Refresh(altcode)",
|
||||
"Unknown operation (10)",
|
||||
"Unknown operation (11)",
|
||||
"Unknown operation (12)",
|
||||
"Unknown operation (13)",
|
||||
"Unknown operation (14)",
|
||||
"Multi-Homed Registration",
|
||||
};
|
||||
|
||||
nbns_data_ptr = &pd[offset];
|
||||
|
||||
/* This is taken from samba/source/nmlib.c, parse_nmb() */
|
||||
header.name_tran_id = pntohs(&pd[offset]);
|
||||
header.opcode = (pd[offset+2] >> 3) & 0xf;
|
||||
header.r = (pd[offset+2] >> 7) & 1;
|
||||
|
||||
nm_flags = ((pd[offset+2] & 0x7) << 4) + (pd[offset+3] >> 4);
|
||||
header.nm_flags.bcast = (nm_flags & 1) ? 1 : 0;
|
||||
header.nm_flags.recursion_available = (nm_flags & 8) ? 1 : 0;
|
||||
header.nm_flags.recursion_desired = (nm_flags & 0x10) ? 1 : 0;
|
||||
header.nm_flags.trunc = (nm_flags & 0x20) ? 1 : 0;
|
||||
header.nm_flags.authoritative = (nm_flags & 0x40) ? 1 : 0;
|
||||
|
||||
header.rcode = pd[offset+3] & 0xf;
|
||||
header.qdcount = pntohs(&pd[offset+4]);
|
||||
header.ancount = pntohs(&pd[offset+6]);
|
||||
header.nscount = pntohs(&pd[offset+8]);
|
||||
header.arcount = pntohs(&pd[offset+10]);
|
||||
|
||||
if (fd->win_info[COL_NUM]) {
|
||||
/*strcpy(fd->win_info[COL_PROTOCOL], "NBNS (UDP)");*/
|
||||
strcpy(fd->win_info[COL_PROTOCOL], "NBNS");
|
||||
strcpy(fd->win_info[COL_INFO], "NetBIOS Name Service");
|
||||
strcpy(fd->win_info[COL_PROTOCOL], "NBNS (UDP)");
|
||||
if (header.opcode <= 15) {
|
||||
sprintf(fd->win_info[COL_INFO], "%s %s",
|
||||
opcode[header.opcode], header.r ? "reply" : "request");
|
||||
} else {
|
||||
sprintf(fd->win_info[COL_INFO], "Unknown operation (%d) %s",
|
||||
header.opcode, header.r ? "reply" : "request");
|
||||
}
|
||||
}
|
||||
|
||||
if (tree) {
|
||||
|
@ -105,27 +709,9 @@ dissect_nbns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
|
|||
nbns_tree = gtk_tree_new();
|
||||
add_subtree(ti, nbns_tree, ETT_NBNS);
|
||||
|
||||
/* This is taken from samba/source/nmlib.c, parse_nmb() */
|
||||
header.name_tran_id = pntohs(&pd[offset]);
|
||||
header.opcode = (pd[offset+2] >> 3) & 0xf;
|
||||
header.r = (pd[offset+2] >> 7) & 1;
|
||||
|
||||
nm_flags = ((pd[offset+2] & 0x7) << 4) + (pd[offset+3] >> 4);
|
||||
header.nm_flags.bcast = (nm_flags & 1) ? 1 : 0;
|
||||
header.nm_flags.recursion_available = (nm_flags & 8) ? 1 : 0;
|
||||
header.nm_flags.recursion_desired = (nm_flags & 0x10) ? 1 : 0;
|
||||
header.nm_flags.trunc = (nm_flags & 0x20) ? 1 : 0;
|
||||
header.nm_flags.authoritative = (nm_flags & 0x40) ? 1 : 0;
|
||||
|
||||
header.rcode = pd[offset+3] & 0xf;
|
||||
header.qdcount = pletohs(&pd[offset+4]);
|
||||
header.ancount = pletohs(&pd[offset+6]);
|
||||
header.nscount = pletohs(&pd[offset+8]);
|
||||
header.arcount = pletohs(&pd[offset+10]);
|
||||
|
||||
add_item_to_tree(nbns_tree, offset, 2, "Transaction ID: 0x%04X",
|
||||
add_item_to_tree(nbns_tree, offset, 2, "Transaction ID: 0x%04X",
|
||||
header.name_tran_id);
|
||||
add_item_to_tree(nbns_tree, offset + 2, 1, "Type: %s",
|
||||
add_item_to_tree(nbns_tree, offset + 2, 1, "Type: %s",
|
||||
header.r == 0 ? "Request" : "Response" );
|
||||
|
||||
if (header.opcode <= 15) {
|
||||
|
@ -136,22 +722,35 @@ dissect_nbns(const u_char *pd, int offset, frame_data *fd, GtkTree *tree)
|
|||
add_item_to_tree(nbns_tree, offset + 2, 1, "Operation: Unknown (%d)",
|
||||
header.opcode);
|
||||
}
|
||||
add_item_to_tree(nbns_tree, offset + 4, 2, "Questions: %d",
|
||||
header.qdcount);
|
||||
add_item_to_tree(nbns_tree, offset + 6, 2, "Answer RRs: %d",
|
||||
header.ancount);
|
||||
add_item_to_tree(nbns_tree, offset + 8, 2, "Authority RRs: %d",
|
||||
header.nscount);
|
||||
add_item_to_tree(nbns_tree, offset + 10, 2, "Additional RRs: %d",
|
||||
header.arcount);
|
||||
|
||||
/* add_item_to_tree(nbns_tree, offset+2, 2, */
|
||||
cur_off = offset + 12;
|
||||
|
||||
if (header.qdcount > 0)
|
||||
cur_off += dissect_query_records(nbns_data_ptr,
|
||||
header.qdcount, pd, cur_off, nbns_tree);
|
||||
|
||||
if (header.ancount > 0)
|
||||
cur_off += dissect_answer_records(nbns_data_ptr,
|
||||
header.ancount, pd, cur_off, nbns_tree,
|
||||
header.opcode, "Answers");
|
||||
|
||||
if (header.nscount > 0)
|
||||
cur_off += dissect_answer_records(nbns_data_ptr,
|
||||
header.nscount, pd, cur_off, nbns_tree,
|
||||
header.opcode,
|
||||
"Authoritative nameservers");
|
||||
|
||||
if (header.arcount > 0)
|
||||
cur_off += dissect_answer_records(nbns_data_ptr,
|
||||
header.arcount, pd, cur_off, nbns_tree,
|
||||
header.opcode, "Additional records");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
6
packet.h
6
packet.h
|
@ -1,7 +1,7 @@
|
|||
/* packet.h
|
||||
* Definitions for packet disassembly structures and routines
|
||||
*
|
||||
* $Id: packet.h,v 1.16 1998/10/14 05:18:32 gram Exp $
|
||||
* $Id: packet.h,v 1.17 1998/10/14 19:35:00 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@zing.org>
|
||||
|
@ -405,6 +405,7 @@ enum {
|
|||
ETT_DNS,
|
||||
ETT_DNS_ANS,
|
||||
ETT_DNS_QRY,
|
||||
ETT_DNS_RR,
|
||||
ETT_RIP,
|
||||
ETT_RIP_VEC,
|
||||
ETT_OSPF,
|
||||
|
@ -427,6 +428,9 @@ enum {
|
|||
ETT_IPXSAP,
|
||||
ETT_IPXSAP_SERVER,
|
||||
ETT_NBNS,
|
||||
ETT_NBNS_ANS,
|
||||
ETT_NBNS_QRY,
|
||||
ETT_NBNS_RR,
|
||||
ETT_NBIPX,
|
||||
NUM_TREE_TYPES /* last item number plus one */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue