From 1e937e5c0af17b1924220894a8af35f9c77bd391 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Sun, 30 Sep 2001 23:14:43 +0000 Subject: The length of an NBSS message can be bigger than 64K, so make the variable that holds it an "int" rather than a "guint16". Further strengthen the heuristics the NBSS dissector uses to distinguish NBSS messages from continuations of NBSS messages. If an frame contains an NBSS continuation, put the protocol tree item for the continuation data under an NBSS protocol tree item. Have the TCP dissector supply information to subdissectors via a "struct tcpinfo" pointed to by "pinfo->private"; move the urgent pointer value from a global variable into that structure, and add a Boolean flag that indicates whether the data it's handing to a subdissector is reassembled data or not. Make the NBSS dissector check for continuations only in non-reassembled data. Fix the computation, in the TCP dissector, of the offset into the tvbuff handed to the subdissector of the first byte of stuff that needs further reassembly, and fix the computation of the sequence number corresponding to that byte. svn path=/trunk/; revision=3984 --- packet-nbns.c | 182 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 143 insertions(+), 39 deletions(-) (limited to 'packet-nbns.c') diff --git a/packet-nbns.c b/packet-nbns.c index 6df0fc8c38..68f9665c03 100644 --- a/packet-nbns.c +++ b/packet-nbns.c @@ -4,7 +4,7 @@ * Gilbert Ramirez * Much stuff added by Guy Harris * - * $Id: packet-nbns.c,v 1.60 2001/09/29 01:19:00 guy Exp $ + * $Id: packet-nbns.c,v 1.61 2001/09/30 23:14:43 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -40,6 +40,7 @@ #include "packet.h" #include "packet-dns.h" #include "packet-netbios.h" +#include "packet-tcp.h" #include "prefs.h" static int proto_nbns = -1; @@ -1365,7 +1366,7 @@ dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_item *tf; guint8 msg_type; guint8 flags; - guint16 length; + int length; int len; char name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME]; int name_type; @@ -1503,25 +1504,25 @@ dissect_nbss_packet(tvbuff_t *tvb, int offset, packet_info *pinfo, static void dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + struct tcpinfo *tcpinfo = pinfo->private; int offset = 0; - guint8 msg_type; int max_data; + guint8 msg_type; + guint8 flags; + guint32 length; int len; gboolean is_cifs; - static const char zeroes[4] = { 0x00, 0x00, 0x00, 0x00 }; + proto_tree *nbss_tree; + proto_item *ti; if (check_col(pinfo->fd, COL_PROTOCOL)) col_set_str(pinfo->fd, COL_PROTOCOL, "NBSS"); if (check_col(pinfo->fd, COL_INFO)) col_clear(pinfo->fd, COL_INFO); - msg_type = tvb_get_guint8(tvb, offset); + max_data = tvb_length(tvb); - /* - * XXX - we should set this based on both the length remaining - * and "length".... - */ - max_data = tvb_length_remaining(tvb, offset); + msg_type = tvb_get_guint8(tvb, offset); if (pinfo->match_port == TCP_PORT_CIFS) { /* @@ -1537,40 +1538,126 @@ dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) is_cifs = FALSE; } - /* Hmmm, it may be a continuation message ... */ - -#define RJSHACK 1 -#ifdef RJSHACK - if (max_data < 4 || - ((msg_type != SESSION_REQUEST) && - (msg_type != POSITIVE_SESSION_RESPONSE) && - (msg_type != NEGATIVE_SESSION_RESPONSE) && - (msg_type != RETARGET_SESSION_RESPONSE) && - (msg_type != SESSION_KEEP_ALIVE) && - (msg_type != SESSION_MESSAGE)) || - ((msg_type == SESSION_MESSAGE) && - (tvb_memeql(tvb, offset, zeroes, 4) == 0))) { - - /* - * We don't have the first 4 bytes of an NBNS header, or - * the first byte isn't one of the known message types, - * or it looks like a session message with a zero header. - * Assume it's a continuation message. - */ - if (check_col(pinfo->fd, COL_INFO)) { - col_add_fstr(pinfo->fd, COL_INFO, "NBSS Continuation Message"); - } + /* + * This might be a continuation of an earlier message. + * (Yes, that might be true even if we're doing TCP reassembly, + * as the first TCP segment in the capture might start in the + * middle of an NBNS message.) + */ - if (tree) - proto_tree_add_text(tree, tvb, offset, max_data, "Continuation data"); + /* + * If this isn't reassembled data, check to see whether it + * looks like a continuation of a message. + * (If it is reassembled data, it shouldn't be a continuation, + * as reassembly should've gathered the continuations together + * into a message.) + */ + if (!tcpinfo->is_reassembled) { + if (max_data < 4) { + /* + * Not enough data for an NBSS header; assume + * it's a continuation of a message. + * + * XXX - if there's not enough data, we should + * attempt to reassemble the data, if the first byte + * is a valid message type. + */ + goto continuation; + } - return; - } -#endif + /* + * We have enough data for an NBSS header. + * Get the flags and length of the message, + * and see if they're sane. + */ + if (is_cifs) { + flags = 0; + length = tvb_get_ntoh24(tvb, offset + 1); + } else { + flags = tvb_get_guint8(tvb, offset + 1); + length = tvb_get_ntohs(tvb, offset + 2); + if (flags & NBSS_FLAGS_E) + length += 65536; + } + if ((flags & (~NBSS_FLAGS_E)) != 0) { + /* + * A bogus flag was set; assume it's a continuation. + */ + goto continuation; + } + + switch (msg_type) { + + case SESSION_MESSAGE: + /* + * This is variable-length. + * All we know is that it shouldn't be zero. + * (XXX - can we get zero-length messages? + * Not with SMB, but perhaps other NetBIOS-based + * protocols have them.) + */ + if (length == 0) + goto continuation; + break; + case SESSION_REQUEST: + /* + * This is variable-length. + * The names are DNS-encoded 32-byte values; + * we need at least 2 bytes (one for each name; + * actually, we should have more for the first + * name, as there's no name preceding it so + * there should be no compression), and we + * shouldn't have more than 128 bytes (actually, + * we shouldn't have that many). + */ + if (length < 2 || length > 128) + goto continuation; + break; + + case POSITIVE_SESSION_RESPONSE: + /* + * This has no data, so the length must be zero. + */ + if (length != 0) + goto continuation; + break; + + case NEGATIVE_SESSION_RESPONSE: + /* + * This has 1 byte of data. + */ + if (length != 1) + goto continuation; + break; + + case RETARGET_SESSION_RESPONSE: + /* + * This has 6 bytes of data. + */ + if (length != 6) + goto continuation; + break; + + case SESSION_KEEP_ALIVE: + /* + * This has no data, so the length must be zero. + */ + if (length != 0) + goto continuation; + break; + + default: + /* + * Unknown message type; assume it's a continuation. + */ + goto continuation; + } + } + if (check_col(pinfo->fd, COL_INFO)) { col_add_fstr(pinfo->fd, COL_INFO, - val_to_str(msg_type, message_types, "Unknown (%x)")); + val_to_str(msg_type, message_types, "Unknown (%02x)")); } while (max_data > 0) { @@ -1579,6 +1666,23 @@ dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset += len; max_data -= len; } + + return; + +continuation: + /* + * It looks like a continuation. + */ + if (check_col(pinfo->fd, COL_INFO)) + col_add_fstr(pinfo->fd, COL_INFO, "NBSS Continuation Message"); + + if (tree) { + ti = proto_tree_add_item(tree, proto_nbss, tvb, 0, + max_data, FALSE); + nbss_tree = proto_item_add_subtree(ti, ett_nbss); + proto_tree_add_text(nbss_tree, tvb, 0, max_data, + "Continuation data"); + } } void -- cgit v1.2.3