aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2001-11-24 09:36:40 +0000
committerGuy Harris <guy@alum.mit.edu>2001-11-24 09:36:40 +0000
commitac16b7463b8e57f4bd54f9c7f16b7ea62a4e2298 (patch)
tree473c58448667764dc58b451bc517a6f1376d5027
parent3ee8a764759e9cc77488980c5e231b5a7f2fda12 (diff)
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
-rw-r--r--packet-smb.c58
-rw-r--r--reassemble.c100
-rw-r--r--reassemble.h28
3 files changed, 162 insertions, 24 deletions
diff --git a/packet-smb.c b/packet-smb.c
index 3321cb9b1a..2b36cef825 100644
--- a/packet-smb.c
+++ b/packet-smb.c
@@ -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 }},
diff --git a/reassemble.c b/reassemble.c
index 45cb0daebf..5af1495417 100644
--- a/reassemble.c
+++ b/reassemble.c
@@ -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,
diff --git a/reassemble.h b/reassemble.h
index 8b96e72d1a..3d3faba8ec 100644
--- a/reassemble.h
+++ b/reassemble.h
@@ -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);
+
+