Assorted changes from Ronnie Sahlberg:

Add a few small functions to reassemble.c to cope with protocols
	where the total length of defragmented PDUs are specified in the
	first fragment (all previous uses of reassembly has been for
	PDUs where the last fragment is signalled by a flag in the
	header for the last fragment).

	Add a few small functions to reassemble.c to abort-and-delete
	defragmentation of PDUs and also detect IF a PDU is currently
	being defragmented.  (Useful for PDUs where the "unique"
	identifier is rather ununique, or may be reused often enough so
	it can be a problem for Ethereal.)

	Change where NT Cancel presents its Cancelation-to output, and
	makes the three trans secondary requests also output similar
	information.

svn path=/trunk/; revision=4255
This commit is contained in:
Guy Harris 2001-11-24 09:36:40 +00:00
parent 3ee8a76475
commit ac16b7463b
3 changed files with 162 additions and 24 deletions

View File

@ -2,7 +2,7 @@
* Routines for smb packet dissection
* Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
*
* $Id: packet-smb.c,v 1.166 2001/11/21 06:25:58 guy Exp $
* $Id: packet-smb.c,v 1.167 2001/11/24 09:36:39 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -98,6 +98,7 @@ static int hf_smb_uid = -1;
static int hf_smb_mid = -1;
static int hf_smb_response_to = -1;
static int hf_smb_response_in = -1;
static int hf_smb_continuation_to = -1;
static int hf_smb_nt_status = -1;
static int hf_smb_error_class = -1;
static int hf_smb_error_code = -1;
@ -7318,28 +7319,8 @@ dissect_nt_create_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
static int
dissect_nt_cancel_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
{
smb_info_t *si;
guint8 wc;
guint16 bc;
conversation_t *conversation;
conv_tables_t *ct;
smb_saved_info_t *old_si;
si = pinfo->private_data;
conversation = find_conversation(&pinfo->src, &pinfo->dst,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
if(conversation){
ct=conversation_get_proto_data(conversation, proto_smb);
if(ct){
old_si=g_hash_table_lookup(ct->matched, (void *)pinfo->fd->num);
if(old_si){
proto_tree_add_uint(tree, hf_smb_cancel_to, tvb, 0, 0, old_si->frame_req);
} else {
proto_tree_add_text(tree, tvb, 0, 0,
"Cancellation to: <unknown frame>");
}
}
}
WORD_COUNT;
@ -12753,6 +12734,35 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
}
}
}
if(sip && sip->frame_req){
switch(si.cmd){
case SMB_COM_NT_CANCEL:
proto_tree_add_uint(htree, hf_smb_cancel_to,
tvb, 0, 0, sip->frame_req);
break;
case SMB_COM_TRANSACTION_SECONDARY:
case SMB_COM_TRANSACTION2_SECONDARY:
case SMB_COM_NT_TRANSACT_SECONDARY:
proto_tree_add_uint(htree, hf_smb_continuation_to,
tvb, 0, 0, sip->frame_req);
break;
}
} else {
switch(si.cmd){
case SMB_COM_NT_CANCEL:
proto_tree_add_text(htree, tvb, 0, 0,
"Cancellation to: <unknown frame>");
break;
case SMB_COM_TRANSACTION_SECONDARY:
case SMB_COM_TRANSACTION2_SECONDARY:
case SMB_COM_NT_TRANSACT_SECONDARY:
proto_tree_add_text(htree, tvb, 0, 0,
"Continuation to: <unknown frame>");
break;
}
}
} else { /* normal bidirectional request or response */
conversation_t *conversation;
conv_tables_t *ct;
@ -12863,7 +12873,7 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
* frame - if we know the frame number (i.e., it's not 0).
*/
if(si.request){
if (si.cmd != SMB_COM_NT_CANCEL && sip->frame_res != 0)
if (sip->frame_res != 0)
proto_tree_add_uint(htree, hf_smb_response_in, tvb, 0, 0, sip->frame_res);
} else {
if (sip->frame_req != 0)
@ -13023,6 +13033,10 @@ proto_register_smb(void)
{ "Response in", "smb.response_in", FT_UINT32, BASE_DEC,
NULL, 0, "The response to this packet is in this packet", HFILL }},
{ &hf_smb_continuation_to,
{ "Continuation to", "smb.continuation_to", FT_UINT32, BASE_DEC,
NULL, 0, "This packet is a continuation to the packet in this frame", HFILL }},
{ &hf_smb_nt_status,
{ "NT Status", "smb.nt_status", FT_UINT32, BASE_HEX,
VALS(NT_errors), 0, "NT Status code", HFILL }},

View File

@ -1,7 +1,7 @@
/* reassemble.c
* Routines for {fragment,segment} reassembly
*
* $Id: reassemble.c,v 1.4 2001/11/21 01:21:08 guy Exp $
* $Id: reassemble.c,v 1.5 2001/11/24 09:36:40 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -177,6 +177,103 @@ reassemble_init(void)
G_ALLOC_ONLY);
}
/* This function cleans up the stored state and removes the reassembly data and
* (with one exception) all allocated memory for matching reassembly.
*
* The exception is :
* If the PDU was already completely reassembled, then the buffer containing the
* reassembled data WILL NOT be free()d, and the pointer to that buffer will be
* returned.
* Othervise the function will return NULL.
*
* So, if you call fragment_delete and it returns non-NULL, YOU are responsible to
* g_free() that buffer.
*/
unsigned char *
fragment_delete(packet_info *pinfo, guint32 id, GHashTable *fragment_table)
{
fragment_data *fd_head, *fd;
fragment_key key;
unsigned char *data=NULL;
/* create key to search hash with */
key.src = pinfo->src;
key.dst = pinfo->dst;
key.id = id;
fd_head = g_hash_table_lookup(fragment_table, &key);
if(fd_head==NULL){
/* We do not recognize this as a PDU we have seen before. return*/
return NULL;
}
data=fd_head->data;
/* loop over all partial fragments and free any buffers */
for(fd=fd_head->next;fd;){
fragment_data *tmp_fd;
tmp_fd=fd->next;
g_free(fd->data);
g_mem_chunk_free(fragment_data_chunk, fd);
fd=tmp_fd;
}
g_mem_chunk_free(fragment_data_chunk, fd_head);
g_hash_table_remove(fragment_table, &key);
return data;
}
/* This function is used to check if there is partial or completed reassembly state
* matching this packet. I.e. Are there reassembly going on or not for this packet?
*/
fragment_data *
fragment_get(packet_info *pinfo, guint32 id, GHashTable *fragment_table)
{
fragment_data *fd_head;
fragment_key key;
/* create key to search hash with */
key.src = pinfo->src;
key.dst = pinfo->dst;
key.id = id;
fd_head = g_hash_table_lookup(fragment_table, &key);
return fd_head;
}
/* This function can be used to explicitely set the total length (if known)
* for reassembly of a PDU.
* This is useful for reassembly of PDUs where one may have the total length specified
* in the first fragment instead of as for, say, IPv4 where a flag indicates which
* is the last fragment.
*
* Such protocols might fragment_add with a more_frags==TRUE for every fragment
* and just tell the reassembly engine the expected total length of the reassembled data
* using fragment_set_tot_len immediately after doing fragment_add for the first packet.
*/
void
fragment_set_tot_len(packet_info *pinfo, guint32 id, GHashTable *fragment_table,
guint32 tot_len)
{
fragment_data *fd_head;
fragment_key key;
/* create key to search hash with */
key.src = pinfo->src;
key.dst = pinfo->dst;
key.id = id;
fd_head = g_hash_table_lookup(fragment_table, &key);
if(fd_head){
fd_head->datalen = tot_len;
}
return;
}
/*
* This function adds a new fragment to the fragment hash table.
* If this is the first fragment seen for this datagram, a new entry
@ -187,6 +284,7 @@ reassemble_init(void)
*
* Returns a pointer to the head of the fragment data list if we have all the
* fragments, NULL otherwise.
*
*/
fragment_data *
fragment_add(tvbuff_t *tvb, int offset, packet_info *pinfo, guint32 id,

View File

@ -1,7 +1,7 @@
/* reassemble.h
* Declarations of outines for {fragment,segment} reassembly
*
* $Id: reassemble.h,v 1.1 2001/06/08 06:27:16 guy Exp $
* $Id: reassemble.h,v 1.2 2001/11/24 09:36:40 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -75,3 +75,29 @@ void reassemble_init(void);
fragment_data *fragment_add(tvbuff_t *tvb, int offset, packet_info *pinfo,
guint32 id, GHashTable *fragment_table, guint32 frag_offset,
guint32 frag_data_len, gboolean more_frags);
/* to specify how much to reassemble, for fragmentation where last fragment can not be
* identified by flags or such.
*/
void
fragment_set_tot_len(packet_info *pinfo, guint32 id, GHashTable *fragment_table,
guint32 tot_len);
/* This function is used to check if there is partial or completed reassembly state
* matching this packet. I.e. Are there reassembly going on or not for this packet?
*/
fragment_data *
fragment_get(packet_info *pinfo, guint32 id, GHashTable *fragment_table);
/* This will free up all resources and delete reassembly state for this PDU.
* Except if the PDU is completely reassembled, then it would NOT deallocate the
* buffer holding the reassembled data but instead return the pointer to that
* buffer.
*
* So, if you call fragment_delete and it returns non-NULL, YOU are responsible to
* g_free() that buffer.
*/
unsigned char *
fragment_delete(packet_info *pinfo, guint32 id, GHashTable *fragment_table);