diff options
Diffstat (limited to 'packet-smb.c')
-rw-r--r-- | packet-smb.c | 1297 |
1 files changed, 425 insertions, 872 deletions
diff --git a/packet-smb.c b/packet-smb.c index 0dcdc779a4..2f406e2b70 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.150 2001/11/16 02:53:11 guy Exp $ + * $Id: packet-smb.c,v 1.151 2001/11/16 07:56:27 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -660,475 +660,44 @@ static const gchar *get_unicode_or_ascii_string(tvbuff_t *tvb, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ static GMemChunk *smb_info_chunk = NULL; static int smb_info_init_count = 200; -static GHashTable *smb_info_table = NULL; -/* - * XXX - MID/PID/UID/TID/command/source/destination are *NOT* unique; - * I have at least one capture with multiple Transaction2 SMB exchanges - * in a row, all with the *same* MID, PID, UID, and TID, and all between - * the *same* machines on the *same* connection. The MID is merely - * intended to distinguish between replies to multiple *in-flight* - * requests; once the reply comes back, an SMB client can reused the - * MID of the request, and, apparently, some clients *do*. - * - * To make this work correctly, you have to include the frame number - * of the matching packet in the hash key, just as is done for the - * transaction hash table. - */ -static gint -smb_info_equal(gconstpointer k1, gconstpointer k2) -{ - smb_info_t *key1 = (smb_info_t *)k1; - smb_info_t *key2 = (smb_info_t *)k2; - gint res; - - /* make sure to always compare mid first since this is most - likely to differ ==> shortcircuiting the expression */ - res= ( (key1->mid==key2->mid) - && (key1->pid==key2->pid) - && (key1->uid==key2->uid) - && (key1->cmd==key2->cmd) - && (key1->tid==key2->tid) - && (ADDRESSES_EQUAL(key1->src, key2->src)) - && (ADDRESSES_EQUAL(key1->dst, key2->dst)) ); - - return res; -} -static guint -smb_info_hash(gconstpointer k) -{ - smb_info_t *key = (smb_info_t *)k; - - /* multiplex id is very likely to differ between calls - it should be sufficient for a good distribution of hash - values. - */ - return key->mid; -} - -static gboolean -free_all_smb_info(gpointer key_arg, gpointer value, gpointer user_data) -{ - smb_info_t *key = (smb_info_t *)key_arg; +/* matched smb_info structures. + For matched smb_info structures we store the smb_info structure twice in the table + using the frame number as the key. + The frame number is guaranteed to be unique but if ever someone makes some change + that will renumber the frames in a capture we are in BIG trouble. + This is not likely though since that would break (among other things) all the + reassembly routines as well. - if((key->src)&&(key->src->data)){ - g_free((gpointer)key->src->data); - key->src->data = NULL; - g_free((gpointer)key->src); - key->src = NULL; - } - - if((key->dst)&&(key->dst->data)){ - g_free((gpointer)key->dst->data); - key->dst->data = NULL; - g_free((gpointer)key->dst); - key->dst = NULL; - } - - return TRUE; -} - -int smb_packet_init_count = 200; - -/* - * This is a hash table matching transaction requests and replies. - * - * Unfortunately, the MID is not a transaction ID in, say, the ONC RPC - * sense; instead, it's a "multiplex ID" used when there's more than one - * request *currently* in flight, to distinguish replies. - * - * This means that the MID and PID don't uniquely identify a request in - * a conversation. - * - * Therefore, we have to use some other value to distinguish between - * requests with the same MID and PID. - * - * On the first pass through the capture, when we first see a request, - * we hash it by conversation, MID, and PID. - * - * When we first see a reply to it, we add it to a new hash table, - * hashing it by conversation, MID, PID, and frame number of the reply. - * - * This works as long as - * - * 1) a client doesn't screw up and have multiple requests outstanding - * with the same MID and PID - * - * and - * - * 2) we don't have, within the same frame, replies to multiple - * requests with the same MID and PID. - * - * 2) should happen only if the server screws up and puts the wrong MID or - * PID into a reply (in which case not only can we not handle this, the - * client can't handle it either) or if the client has screwed up as per - * 1) and the server's dutifully replied to both of the requests with the - * same MID and PID (in which case, again, neither we nor the client can - * handle this). - * - * We don't have to correctly dissect screwups; we just have to keep from - * dumping core on them. - * - * XXX - in addition, we need to keep a hash table of replies, so that we - * can associate continuations with the reply to which they're a continuation. - */ -struct smb_request_key { - guint32 conversation; - guint16 mid; - guint16 pid; - guint32 frame_num; -}; - -static GHashTable *smb_request_hash = NULL; -static GMemChunk *smb_request_keys = NULL; -static GMemChunk *smb_request_vals = NULL; - -/* - * This is a hash table matching continued transation replies and their - * continuations. - * - * It works similarly to the request/reply hash table. - */ -static GHashTable *smb_continuation_hash = NULL; - -static GMemChunk *smb_continuation_vals = NULL; - -/* Hash Functions */ + Oh, yes, the key is really a pointer, but we use it as if it was an integer. + Ugly, yes. Not portable to DEC-20 Yes. But it saves a few bytes. +*/ static gint -smb_equal(gconstpointer v, gconstpointer w) +smb_info_equal_matched(gconstpointer k1, gconstpointer k2) { - struct smb_request_key *v1 = (struct smb_request_key *)v; - struct smb_request_key *v2 = (struct smb_request_key *)w; - -#if defined(DEBUG_SMB_HASH) - printf("Comparing %08X:%u:%u:%u\n and %08X:%u:%u:%u\n", - v1 -> conversation, v1 -> mid, v1 -> pid, v1 -> frame_num, - v2 -> conversation, v2 -> mid, v2 -> pid, v2 -> frame_num); -#endif - - if (v1 -> conversation == v2 -> conversation && - v1 -> mid == v2 -> mid && - v1 -> pid == v2 -> pid && - v1 -> frame_num == v2 -> frame_num) { - - return 1; - - } - - return 0; + register int key1 = (int)k1; + register int key2 = (int)k2; + return key1==key2; } - static guint -smb_hash (gconstpointer v) +smb_info_hash_matched(gconstpointer k) { - struct smb_request_key *key = (struct smb_request_key *)v; - guint val; - - val = (key -> conversation) + (key -> mid) + (key -> pid) + - (key -> frame_num); - -#if defined(DEBUG_SMB_HASH) - printf("SMB Hash calculated as %u\n", val); -#endif - - return val; - + register int key = (int)k; + return key; } - -/* - * Free up any state information we've saved, and re-initialize the - * tables of state information. - */ - -/* - * For a hash table entry, free the address data to which the key refers - * and the fragment data to which the value refers. - * (The actual key and value structures get freed by "reassemble_init()".) - */ static gboolean -free_request_val_data(gpointer key, gpointer value, gpointer user_data) -{ - struct smb_request_val *request_val = value; - - if (request_val->last_transact_command != NULL) - g_free(request_val->last_transact_command); - if (request_val->last_param_descrip != NULL) - g_free(request_val->last_param_descrip); - if (request_val->last_data_descrip != NULL) - g_free(request_val->last_data_descrip); - if (request_val->last_aux_data_descrip != NULL) - g_free(request_val->last_aux_data_descrip); - return TRUE; -} - -static struct smb_request_val * -do_transaction_hashing(conversation_t *conversation, struct smb_info si, - frame_data *fd) -{ - struct smb_request_key request_key, *new_request_key; - struct smb_request_val *request_val = NULL; - gpointer new_request_key_ret, request_val_ret; - - if (si.request) { - /* - * This is a request. - * - * If this is the first time the frame has been seen, check for - * an entry for the request in the hash table. If it's not found, - * insert an entry for it. - * - * If it's the first time it's been seen, then we can't have seen - * the reply yet, so the reply frame number should be 0, for - * "unknown". - */ - if (!fd->flags.visited) { - request_key.conversation = conversation->index; - request_key.mid = si.mid; - request_key.pid = si.pid; - request_key.frame_num = 0; - - request_val = (struct smb_request_val *) g_hash_table_lookup(smb_request_hash, &request_key); - - if (request_val == NULL) { - /* - * Not found. - */ - new_request_key = g_mem_chunk_alloc(smb_request_keys); - new_request_key -> conversation = conversation->index; - new_request_key -> mid = si.mid; - new_request_key -> pid = si.pid; - new_request_key -> frame_num = 0; - - request_val = g_mem_chunk_alloc(smb_request_vals); - request_val -> frame = fd->num; - request_val -> last_transact2_command = -1; /* unknown */ - request_val -> last_transact_command = NULL; - request_val -> last_param_descrip = NULL; - request_val -> last_data_descrip = NULL; - request_val -> last_aux_data_descrip = NULL; - - g_hash_table_insert(smb_request_hash, new_request_key, request_val); - } else { - /* - * This means that we've seen another request in this conversation - * with the same request and reply, and without an intervening - * reply to that first request, and thus won't be using this - * "request_val" structure for that request (as we'd use it only - * for the reply). - * - * Clean out the structure, and set it to refer to this frame. - */ - request_val -> frame = fd->num; - request_val -> last_transact2_command = -1; /* unknown */ - if (request_val -> last_transact_command) - g_free(request_val -> last_transact_command); - request_val -> last_transact_command = NULL; - if (request_val -> last_param_descrip) - g_free(request_val -> last_param_descrip); - request_val -> last_param_descrip = NULL; - if (request_val -> last_data_descrip) - g_free(request_val -> last_data_descrip); - request_val -> last_data_descrip = NULL; - if (request_val -> last_aux_data_descrip) - g_free(request_val -> last_aux_data_descrip); - request_val -> last_aux_data_descrip = NULL; - } - } - } else { - /* - * This is a reply. - */ - if (!fd->flags.visited) { - /* - * This is the first time the frame has been seen; check for - * an entry for a matching request, with an unknown reply frame - * number, in the hash table. - * - * If we find it, re-hash it with this frame's number as the - * reply frame number. - */ - request_key.conversation = conversation->index; - request_key.mid = si.mid; - request_key.pid = si.pid; - request_key.frame_num = 0; - - /* - * Look it up - and, if we find it, get pointers to the key and - * value structures for it. - */ - if (g_hash_table_lookup_extended(smb_request_hash, &request_key, - &new_request_key_ret, - &request_val_ret)) { - new_request_key = new_request_key_ret; - request_val = request_val_ret; - - /* - * We found it. - * Remove the old entry. - */ - g_hash_table_remove(smb_request_hash, &request_key); - - /* - * Now update the key, and put it back into the hash table with - * the new key. - */ - new_request_key->frame_num = fd->num; - g_hash_table_insert(smb_request_hash, new_request_key, request_val); - } - } else { - /* - * This is not the first time the frame has been seen; check for - * an entry for a matching request, with this frame's frame - * number as the reply frame number, in the hash table. - */ - request_key.conversation = conversation->index; - request_key.mid = si.mid; - request_key.pid = si.pid; - request_key.frame_num = fd->num; - - request_val = (struct smb_request_val *) g_hash_table_lookup(smb_request_hash, &request_key); - } - } - - return request_val; -} - -static struct smb_continuation_val * -do_continuation_hashing(conversation_t *conversation, struct smb_info si, - frame_data *fd, guint16 TotalDataCount, - guint16 DataCount, const char **TransactName) +free_all_smb_info_matched(gpointer key_arg, gpointer value, gpointer user_data) { - struct smb_request_key request_key, *new_request_key; - struct smb_continuation_val *continuation_val, *new_continuation_val; - gpointer new_request_key_ret, continuation_val_ret; - - continuation_val = NULL; - if (si.ddisp != 0) { - /* - * This reply isn't the first in the series; there should be a - * reply of which it is a continuation. - */ - if (!fd->flags.visited) { - /* - * This is the first time the frame has been seen; check for - * an entry for a matching continued message, with an unknown - * continuation frame number, in the hash table. - * - * If we find it, re-hash it with this frame's number as the - * continuation frame number. - */ - request_key.conversation = conversation->index; - request_key.mid = si.mid; - request_key.pid = si.pid; - request_key.frame_num = 0; - - /* - * Look it up - and, if we find it, get pointers to the key and - * value structures for it. - */ - if (g_hash_table_lookup_extended(smb_continuation_hash, &request_key, - &new_request_key_ret, - &continuation_val_ret)) { - new_request_key = new_request_key_ret; - continuation_val = continuation_val_ret; - - /* - * We found it. - * Remove the old entry. - */ - g_hash_table_remove(smb_continuation_hash, &request_key); - - /* - * Now update the key, and put it back into the hash table with - * the new key. - */ - new_request_key->frame_num = fd->num; - g_hash_table_insert(smb_continuation_hash, new_request_key, - continuation_val); - } - } else { - /* - * This is not the first time the frame has been seen; check for - * an entry for a matching request, with this frame's frame - * number as the continuation frame number, in the hash table. - */ - request_key.conversation = conversation->index; - request_key.mid = si.mid; - request_key.pid = si.pid; - request_key.frame_num = fd->num; - - continuation_val = (struct smb_continuation_val *) - g_hash_table_lookup(smb_continuation_hash, &request_key); - } - } - - /* - * If we found the entry for the message of which this is a continuation, - * and our caller cares, get the transaction name for that message, as - * it's the transaction name for this message as well. - */ - if (continuation_val != NULL && TransactName != NULL) - *TransactName = continuation_val -> transact_name; - - if (TotalDataCount > DataCount + si.ddisp) { - /* - * This reply isn't the last in the series; there should be a - * continuation for it later in the capture. - * - * If this is the first time the frame has been seen, check for - * an entry for the reply in the hash table. If it's not found, - * insert an entry for it. - * - * If it's the first time it's been seen, then we can't have seen - * the continuation yet, so the continuation frame number should - * be 0, for "unknown". - */ - if (!fd->flags.visited) { - request_key.conversation = conversation->index; - request_key.mid = si.mid; - request_key.pid = si.pid; - request_key.frame_num = 0; - - new_continuation_val = (struct smb_continuation_val *) - g_hash_table_lookup(smb_continuation_hash, &request_key); - - if (new_continuation_val == NULL) { - /* - * Not found. - */ - new_request_key = g_mem_chunk_alloc(smb_request_keys); - new_request_key -> conversation = conversation->index; - new_request_key -> mid = si.mid; - new_request_key -> pid = si.pid; - new_request_key -> frame_num = 0; - - new_continuation_val = g_mem_chunk_alloc(smb_continuation_vals); - new_continuation_val -> frame = fd->num; - if (TransactName != NULL) - new_continuation_val -> transact_name = *TransactName; - else - new_continuation_val -> transact_name = NULL; - - g_hash_table_insert(smb_continuation_hash, new_request_key, - new_continuation_val); - } else { - /* - * This presumably means we never saw the continuation of - * the message we found, and this is a reply to a different - * request; as we never saw the continuation of that message, - * we won't be using this "request_val" structure for that - * message (as we'd use it only for the continuation). - * - * Clean out the structure, and set it to refer to this frame. - */ - new_continuation_val -> frame = fd->num; - } - } - } - - return continuation_val; + return TRUE; } +typedef struct conv_tables { + GHashTable *unmatched; + GHashTable *matched; +} conv_tables_t; +static GMemChunk *conv_tables_chunk = NULL; +static int conv_tables_count = 10; + /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX End of request/response matching functions @@ -7630,17 +7199,24 @@ dissect_nt_cancel_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i smb_info_t *sip; guint8 wc; guint16 bc; + conversation_t *conversation; + conv_tables_t *ct; + smb_info_t *old_si; - /* XXX I think this correct to find the matching request, must test */ sip = pinfo->private_data; - sip->src = &pinfo->src; - sip->dst = &pinfo->dst; - sip = g_hash_table_lookup(smb_info_table, sip); - if(sip){ - proto_tree_add_uint(tree, hf_smb_cancel_to, tvb, 0, 0, sip->frame_req); - } else { - proto_tree_add_text(tree, tvb, 0, 0, - "Cancelation to: <unknown frame>"); + 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->unmatched, (void *)sip->mid); + 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; @@ -7899,13 +7475,11 @@ dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo, proto_item *item = NULL; proto_tree *tree = NULL; smb_info_t *si; - struct smb_request_val *request_val; int fn_len; const char *fn; int old_offset = offset; si = (smb_info_t *)pinfo->private_data; - request_val = si->request_val; if(parent_tree){ item = proto_tree_add_text(parent_tree, tvb, offset, bc, @@ -7993,8 +7567,6 @@ dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo, /* Find First2 information level */ CHECK_BYTE_COUNT_TRANS(2); si->info_level = tvb_get_letohs(tvb, offset); - if (!pinfo->fd->flags.visited) - request_val->last_level = si->info_level; proto_tree_add_uint(tree, hf_smb_ff2_information_level, tvb, offset, 2, si->info_level); COUNT_BYTES_TRANS(2); @@ -8032,8 +7604,6 @@ dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo, /* Find First2 information level */ CHECK_BYTE_COUNT_TRANS(2); si->info_level = tvb_get_letohs(tvb, offset); - if (!pinfo->fd->flags.visited) - request_val->last_level = si->info_level; proto_tree_add_uint(tree, hf_smb_ff2_information_level, tvb, offset, 2, si->info_level); COUNT_BYTES_TRANS(2); @@ -8064,8 +7634,6 @@ dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo, /* level of interest */ CHECK_BYTE_COUNT_TRANS(2); si->info_level = tvb_get_letohs(tvb, offset); - if (!pinfo->fd->flags.visited) - request_val->last_level = si->info_level; proto_tree_add_uint(tree, hf_smb_qfsi_information_level, tvb, offset, 2, si->info_level); COUNT_BYTES_TRANS(2); @@ -8074,8 +7642,6 @@ dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo, /* level of interest */ CHECK_BYTE_COUNT_TRANS(2); si->info_level = tvb_get_letohs(tvb, offset); - if (!pinfo->fd->flags.visited) - request_val->last_level = si->info_level; proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level); COUNT_BYTES_TRANS(2); @@ -8101,8 +7667,6 @@ dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo, /* level of interest */ CHECK_BYTE_COUNT_TRANS(2); si->info_level = tvb_get_letohs(tvb, offset); - if (!pinfo->fd->flags.visited) - request_val->last_level = si->info_level; proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level); COUNT_BYTES_TRANS(2); @@ -8133,8 +7697,6 @@ dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo, /* level of interest */ CHECK_BYTE_COUNT_TRANS(2); si->info_level = tvb_get_letohs(tvb, offset); - if (!pinfo->fd->flags.visited) - request_val->last_level = si->info_level; proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level); COUNT_BYTES_TRANS(2); @@ -8148,8 +7710,6 @@ dissect_transaction2_request_parameters(tvbuff_t *tvb, packet_info *pinfo, /* level of interest */ CHECK_BYTE_COUNT_TRANS(2); si->info_level = tvb_get_letohs(tvb, offset); - if (!pinfo->fd->flags.visited) - request_val->last_level = si->info_level; proto_tree_add_uint(tree, hf_smb_qpi_loi, tvb, offset, 2, si->info_level); COUNT_BYTES_TRANS(2); @@ -9130,8 +8690,6 @@ dissect_transaction2_request_data(tvbuff_t *tvb, packet_info *pinfo, static int dissect_transaction_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree) { - conversation_t *conversation; - struct smb_request_val *request_val; guint8 wc, sc=0; int so=0; guint16 od=0, tf, po=0, pc=0, dc=0, pd, dd=0; @@ -9144,26 +8702,6 @@ dissect_transaction_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, si = (smb_info_t *)pinfo->private_data; - /* - * Find out what conversation this packet is part of. - */ - conversation = find_conversation(&pinfo->src, &pinfo->dst, - pinfo->ptype, pinfo->srcport, pinfo->destport, 0); - - if (conversation == NULL) { - /* - * There isn't one yet; create it. - */ - conversation = conversation_new(&pinfo->src, &pinfo->dst, - pinfo->ptype, pinfo->srcport, pinfo->destport, 0); - } - - si->conversation = conversation; /* Save this */ - - request_val = do_transaction_hashing(conversation, *si, pinfo->fd); - - si->request_val = request_val; /* Save this for later */ - WORD_COUNT; if(wc==8){ @@ -9306,8 +8844,6 @@ dissect_transaction_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, val_to_str(si->subcmd, trans2_cmd_vals, "Unknown (0x%02x)")); } - if (!pinfo->fd->flags.visited) - request_val->last_transact2_command = si->subcmd; break; case 0x25: @@ -10647,8 +10183,6 @@ dissect_transaction2_response_parameters(tvbuff_t *tvb, packet_info *pinfo, prot static int dissect_transaction_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree) { - conversation_t *conversation; - struct smb_request_val *request_val; guint8 sc=0, wc; guint16 od=0, tf, po=0, pc=0, pd, dc=0, dd=0; int so=0; @@ -10659,66 +10193,33 @@ dissect_transaction_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree si = (smb_info_t *)pinfo->private_data; - /* - * Find out what conversation this packet is part of. - */ - conversation = find_conversation(&pinfo->src, &pinfo->dst, - pinfo->ptype, pinfo->srcport, pinfo->destport, 0); - - if (conversation == NULL) { - /* - * There isn't one yet; create it. - */ - conversation = conversation_new(&pinfo->src, &pinfo->dst, - pinfo->ptype, pinfo->srcport, pinfo->destport, 0); - } - - si->conversation = conversation; /* Save this */ - - request_val = do_transaction_hashing(conversation, *si, pinfo->fd); - - si->request_val = request_val; /* Save this for later */ - - if(request_val != NULL){ - switch(si->cmd){ - - case 0x32: - /* transaction2 */ - si->subcmd = request_val->last_transact2_command; - if (si->subcmd != -1) { - proto_tree_add_uint(tree, hf_smb_trans2_subcmd, tvb, 0, 0, si->subcmd); - if (check_col(pinfo->fd, COL_INFO)) { - col_append_fstr(pinfo->fd, COL_INFO, " %s", - val_to_str(si->subcmd, - trans2_cmd_vals, - "<unknown (0x%02x)> ")); - } - } else { - /* - * We didn't manage to extract the subcommand - * from the matching request (perhaps because - * the frame was short), so we don't know what - * type of transaction this is. - */ - proto_tree_add_text(tree, tvb, 0, 0, - "Subcommand: <UNKNOWN> since transaction code wasn't found in request packet"); - if (check_col(pinfo->fd, COL_INFO)) { - col_append_fstr(pinfo->fd, COL_INFO, "<unknown> "); - } + switch(si->cmd){ + case 0x32: + /* transaction2 */ + if (si->subcmd != -1) { + proto_tree_add_uint(tree, hf_smb_trans2_subcmd, tvb, 0, 0, si->subcmd); + if (check_col(pinfo->fd, COL_INFO)) { + col_append_fstr(pinfo->fd, COL_INFO, " %s", + val_to_str(si->subcmd, + trans2_cmd_vals, + "<unknown (0x%02x)>")); + } + } else { + /* + * We didn't manage to extract the subcommand + * from the matching request (perhaps because + * the frame was short), so we don't know what + * type of transaction this is. + * (XXX - Or we didn't even see the matching request + * in the first place.) + */ + proto_tree_add_text(tree, tvb, 0, 0, + "Subcommand: <UNKNOWN> since transaction code wasn't found in request packet"); + if (check_col(pinfo->fd, COL_INFO)) { + col_append_fstr(pinfo->fd, COL_INFO, "<unknown>"); } - break; - } - si->info_level = request_val->last_level; - } else { - /* we have not seen the request yet so we don't know what - subcommand it was */ - proto_tree_add_text(tree, tvb, 0, 0, - "Subcommand: <UNKNOWN> since request packet was not captured"); - if (check_col(pinfo->fd, COL_INFO)) { - col_append_fstr(pinfo->fd, COL_INFO, "<unknown> "); } - si->subcmd = -1; - si->info_level = -1; + break; } WORD_COUNT; @@ -10906,6 +10407,27 @@ dissect_transaction_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +static int +dissect_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree) +{ + guint8 wc; + guint16 bc; + + WORD_COUNT; + + if (wc != 0) + proto_tree_add_text(tree, tvb, offset, wc*2, "Word parameters"); + + BYTE_COUNT; + + if (bc != 0) + proto_tree_add_text(tree, tvb, offset, bc, "Byte parameters"); + + END_OF_SMB + + return offset; +} + typedef struct _smb_function { int (*request)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree); int (*response)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree); @@ -10934,28 +10456,28 @@ smb_function smb_dissector[256] = { /* 0x12 Seek File*/ {dissect_seek_file_request, dissect_seek_file_response}, /* 0x13 Lock And Read*/ {dissect_read_file_request, dissect_lock_and_read_response}, /* 0x14 Write And Unlock*/ {dissect_write_file_request, dissect_write_file_response}, - /* 0x15 */ {NULL, NULL}, - /* 0x16 */ {NULL, NULL}, - /* 0x17 */ {NULL, NULL}, - /* 0x18 */ {NULL, NULL}, - /* 0x19 */ {NULL, NULL}, - /* 0x1a Read Raw*/ {dissect_read_raw_request, NULL}, + /* 0x15 */ {dissect_unknown, dissect_unknown}, + /* 0x16 */ {dissect_unknown, dissect_unknown}, + /* 0x17 */ {dissect_unknown, dissect_unknown}, + /* 0x18 */ {dissect_unknown, dissect_unknown}, + /* 0x19 */ {dissect_unknown, dissect_unknown}, + /* 0x1a Read Raw*/ {dissect_read_raw_request, dissect_unknown}, /* 0x1b Read MPX*/ {dissect_read_mpx_request, dissect_read_mpx_response}, - /* 0x1c */ {NULL, NULL}, + /* 0x1c */ {dissect_unknown, dissect_unknown}, /* 0x1d Write Raw*/ {dissect_write_raw_request, dissect_write_raw_response}, /* 0x1e Write MPX*/ {dissect_write_mpx_request, dissect_write_mpx_response}, - /* 0x1f */ {NULL, NULL}, + /* 0x1f */ {dissect_unknown, dissect_unknown}, - /* 0x20 Write Complete*/ {NULL, dissect_write_and_close_response}, - /* 0x21 */ {NULL, NULL}, + /* 0x20 Write Complete*/ {dissect_unknown, dissect_write_and_close_response}, + /* 0x21 */ {dissect_unknown, dissect_unknown}, /* 0x22 Set Info2*/ {dissect_set_information2_request, dissect_empty}, /* 0x23 Query Info2*/ {dissect_fid, dissect_query_information2_response}, /* 0x24 Locking And X*/ {dissect_locking_andx_request, dissect_locking_andx_response}, /* 0x25 Transaction*/ {dissect_transaction_request, dissect_transaction_response}, - /* 0x26 */ {NULL, NULL}, - /* 0x27 */ {NULL, NULL}, - /* 0x28 */ {NULL, NULL}, - /* 0x29 */ {NULL, NULL}, + /* 0x26 */ {dissect_unknown, dissect_unknown}, + /* 0x27 */ {dissect_unknown, dissect_unknown}, + /* 0x28 */ {dissect_unknown, dissect_unknown}, + /* 0x29 */ {dissect_unknown, dissect_unknown}, /* 0x2a Move File*/ {dissect_move_request, dissect_move_response}, /* 0x2b Echo*/ {dissect_echo_request, dissect_echo_response}, /* 0x2c Write And Close*/ {dissect_write_and_close_request, dissect_write_and_close_response}, @@ -10963,73 +10485,73 @@ smb_function smb_dissector[256] = { /* 0x2e Read And X*/ {dissect_read_andx_request, dissect_read_andx_response}, /* 0x2f Write And X*/ {dissect_write_andx_request, dissect_write_andx_response}, - /* 0x30 */ {NULL, NULL}, - /* 0x31 */ {NULL, NULL}, + /* 0x30 */ {dissect_unknown, dissect_unknown}, + /* 0x31 */ {dissect_unknown, dissect_unknown}, /* 0x32 Transaction2*/ {dissect_transaction_request, dissect_transaction_response}, - /* 0x33 */ {NULL, NULL}, + /* 0x33 */ {dissect_unknown, dissect_unknown}, /* 0x34 Find Close2*/ {dissect_sid, dissect_empty}, - /* 0x35 */ {NULL, NULL}, - /* 0x36 */ {NULL, NULL}, - /* 0x37 */ {NULL, NULL}, - /* 0x38 */ {NULL, NULL}, - /* 0x39 */ {NULL, NULL}, - /* 0x3a */ {NULL, NULL}, - /* 0x3b */ {NULL, NULL}, - /* 0x3c */ {NULL, NULL}, - /* 0x3d */ {NULL, NULL}, - /* 0x3e */ {NULL, NULL}, - /* 0x3f */ {NULL, NULL}, - - /* 0x40 */ {NULL, NULL}, - /* 0x41 */ {NULL, NULL}, - /* 0x42 */ {NULL, NULL}, - /* 0x43 */ {NULL, NULL}, - /* 0x44 */ {NULL, NULL}, - /* 0x45 */ {NULL, NULL}, - /* 0x46 */ {NULL, NULL}, - /* 0x47 */ {NULL, NULL}, - /* 0x48 */ {NULL, NULL}, - /* 0x49 */ {NULL, NULL}, - /* 0x4a */ {NULL, NULL}, - /* 0x4b */ {NULL, NULL}, - /* 0x4c */ {NULL, NULL}, - /* 0x4d */ {NULL, NULL}, - /* 0x4e */ {NULL, NULL}, - /* 0x4f */ {NULL, NULL}, - - /* 0x50 */ {NULL, NULL}, - /* 0x51 */ {NULL, NULL}, - /* 0x52 */ {NULL, NULL}, - /* 0x53 */ {NULL, NULL}, - /* 0x54 */ {NULL, NULL}, - /* 0x55 */ {NULL, NULL}, - /* 0x56 */ {NULL, NULL}, - /* 0x57 */ {NULL, NULL}, - /* 0x58 */ {NULL, NULL}, - /* 0x59 */ {NULL, NULL}, - /* 0x5a */ {NULL, NULL}, - /* 0x5b */ {NULL, NULL}, - /* 0x5c */ {NULL, NULL}, - /* 0x5d */ {NULL, NULL}, - /* 0x5e */ {NULL, NULL}, - /* 0x5f */ {NULL, NULL}, - - /* 0x60 */ {NULL, NULL}, - /* 0x61 */ {NULL, NULL}, - /* 0x62 */ {NULL, NULL}, - /* 0x63 */ {NULL, NULL}, - /* 0x64 */ {NULL, NULL}, - /* 0x65 */ {NULL, NULL}, - /* 0x66 */ {NULL, NULL}, - /* 0x67 */ {NULL, NULL}, - /* 0x68 */ {NULL, NULL}, - /* 0x69 */ {NULL, NULL}, - /* 0x6a */ {NULL, NULL}, - /* 0x6b */ {NULL, NULL}, - /* 0x6c */ {NULL, NULL}, - /* 0x6d */ {NULL, NULL}, - /* 0x6e */ {NULL, NULL}, - /* 0x6f */ {NULL, NULL}, + /* 0x35 */ {dissect_unknown, dissect_unknown}, + /* 0x36 */ {dissect_unknown, dissect_unknown}, + /* 0x37 */ {dissect_unknown, dissect_unknown}, + /* 0x38 */ {dissect_unknown, dissect_unknown}, + /* 0x39 */ {dissect_unknown, dissect_unknown}, + /* 0x3a */ {dissect_unknown, dissect_unknown}, + /* 0x3b */ {dissect_unknown, dissect_unknown}, + /* 0x3c */ {dissect_unknown, dissect_unknown}, + /* 0x3d */ {dissect_unknown, dissect_unknown}, + /* 0x3e */ {dissect_unknown, dissect_unknown}, + /* 0x3f */ {dissect_unknown, dissect_unknown}, + + /* 0x40 */ {dissect_unknown, dissect_unknown}, + /* 0x41 */ {dissect_unknown, dissect_unknown}, + /* 0x42 */ {dissect_unknown, dissect_unknown}, + /* 0x43 */ {dissect_unknown, dissect_unknown}, + /* 0x44 */ {dissect_unknown, dissect_unknown}, + /* 0x45 */ {dissect_unknown, dissect_unknown}, + /* 0x46 */ {dissect_unknown, dissect_unknown}, + /* 0x47 */ {dissect_unknown, dissect_unknown}, + /* 0x48 */ {dissect_unknown, dissect_unknown}, + /* 0x49 */ {dissect_unknown, dissect_unknown}, + /* 0x4a */ {dissect_unknown, dissect_unknown}, + /* 0x4b */ {dissect_unknown, dissect_unknown}, + /* 0x4c */ {dissect_unknown, dissect_unknown}, + /* 0x4d */ {dissect_unknown, dissect_unknown}, + /* 0x4e */ {dissect_unknown, dissect_unknown}, + /* 0x4f */ {dissect_unknown, dissect_unknown}, + + /* 0x50 */ {dissect_unknown, dissect_unknown}, + /* 0x51 */ {dissect_unknown, dissect_unknown}, + /* 0x52 */ {dissect_unknown, dissect_unknown}, + /* 0x53 */ {dissect_unknown, dissect_unknown}, + /* 0x54 */ {dissect_unknown, dissect_unknown}, + /* 0x55 */ {dissect_unknown, dissect_unknown}, + /* 0x56 */ {dissect_unknown, dissect_unknown}, + /* 0x57 */ {dissect_unknown, dissect_unknown}, + /* 0x58 */ {dissect_unknown, dissect_unknown}, + /* 0x59 */ {dissect_unknown, dissect_unknown}, + /* 0x5a */ {dissect_unknown, dissect_unknown}, + /* 0x5b */ {dissect_unknown, dissect_unknown}, + /* 0x5c */ {dissect_unknown, dissect_unknown}, + /* 0x5d */ {dissect_unknown, dissect_unknown}, + /* 0x5e */ {dissect_unknown, dissect_unknown}, + /* 0x5f */ {dissect_unknown, dissect_unknown}, + + /* 0x60 */ {dissect_unknown, dissect_unknown}, + /* 0x61 */ {dissect_unknown, dissect_unknown}, + /* 0x62 */ {dissect_unknown, dissect_unknown}, + /* 0x63 */ {dissect_unknown, dissect_unknown}, + /* 0x64 */ {dissect_unknown, dissect_unknown}, + /* 0x65 */ {dissect_unknown, dissect_unknown}, + /* 0x66 */ {dissect_unknown, dissect_unknown}, + /* 0x67 */ {dissect_unknown, dissect_unknown}, + /* 0x68 */ {dissect_unknown, dissect_unknown}, + /* 0x69 */ {dissect_unknown, dissect_unknown}, + /* 0x6a */ {dissect_unknown, dissect_unknown}, + /* 0x6b */ {dissect_unknown, dissect_unknown}, + /* 0x6c */ {dissect_unknown, dissect_unknown}, + /* 0x6d */ {dissect_unknown, dissect_unknown}, + /* 0x6e */ {dissect_unknown, dissect_unknown}, + /* 0x6f */ {dissect_unknown, dissect_unknown}, /* 0x70 Tree Connect*/ {dissect_tree_connect_request, dissect_tree_connect_response}, /* 0x71 Tree Disconnect*/ {dissect_empty, dissect_empty}, @@ -11037,150 +10559,150 @@ smb_function smb_dissector[256] = { /* 0x73 Session Setup And X*/ {dissect_session_setup_andx_request, dissect_session_setup_andx_response}, /* 0x74 Logoff And X*/ {dissect_empty_andx, dissect_empty_andx}, /* 0x75 Tree Connect And X*/ {dissect_tree_connect_andx_request, dissect_tree_connect_andx_response}, - /* 0x76 */ {NULL, NULL}, - /* 0x77 */ {NULL, NULL}, - /* 0x78 */ {NULL, NULL}, - /* 0x79 */ {NULL, NULL}, - /* 0x7a */ {NULL, NULL}, - /* 0x7b */ {NULL, NULL}, - /* 0x7c */ {NULL, NULL}, - /* 0x7d */ {NULL, NULL}, - /* 0x7e */ {NULL, NULL}, - /* 0x7f */ {NULL, NULL}, + /* 0x76 */ {dissect_unknown, dissect_unknown}, + /* 0x77 */ {dissect_unknown, dissect_unknown}, + /* 0x78 */ {dissect_unknown, dissect_unknown}, + /* 0x79 */ {dissect_unknown, dissect_unknown}, + /* 0x7a */ {dissect_unknown, dissect_unknown}, + /* 0x7b */ {dissect_unknown, dissect_unknown}, + /* 0x7c */ {dissect_unknown, dissect_unknown}, + /* 0x7d */ {dissect_unknown, dissect_unknown}, + /* 0x7e */ {dissect_unknown, dissect_unknown}, + /* 0x7f */ {dissect_unknown, dissect_unknown}, /* 0x80 Query Info Disk*/ {dissect_empty, dissect_query_information_disk_response}, /* 0x81 Search Dir*/ {dissect_search_dir_request, dissect_search_dir_response}, - /* 0x82 */ {NULL, NULL}, - /* 0x83 */ {NULL, NULL}, - /* 0x84 */ {NULL, NULL}, - /* 0x85 */ {NULL, NULL}, - /* 0x86 */ {NULL, NULL}, - /* 0x87 */ {NULL, NULL}, - /* 0x88 */ {NULL, NULL}, - /* 0x89 */ {NULL, NULL}, - /* 0x8a */ {NULL, NULL}, - /* 0x8b */ {NULL, NULL}, - /* 0x8c */ {NULL, NULL}, - /* 0x8d */ {NULL, NULL}, - /* 0x8e */ {NULL, NULL}, - /* 0x8f */ {NULL, NULL}, - - /* 0x90 */ {NULL, NULL}, - /* 0x91 */ {NULL, NULL}, - /* 0x92 */ {NULL, NULL}, - /* 0x93 */ {NULL, NULL}, - /* 0x94 */ {NULL, NULL}, - /* 0x95 */ {NULL, NULL}, - /* 0x96 */ {NULL, NULL}, - /* 0x97 */ {NULL, NULL}, - /* 0x98 */ {NULL, NULL}, - /* 0x99 */ {NULL, NULL}, - /* 0x9a */ {NULL, NULL}, - /* 0x9b */ {NULL, NULL}, - /* 0x9c */ {NULL, NULL}, - /* 0x9d */ {NULL, NULL}, - /* 0x9e */ {NULL, NULL}, - /* 0x9f */ {NULL, NULL}, + /* 0x82 */ {dissect_unknown, dissect_unknown}, + /* 0x83 */ {dissect_unknown, dissect_unknown}, + /* 0x84 */ {dissect_unknown, dissect_unknown}, + /* 0x85 */ {dissect_unknown, dissect_unknown}, + /* 0x86 */ {dissect_unknown, dissect_unknown}, + /* 0x87 */ {dissect_unknown, dissect_unknown}, + /* 0x88 */ {dissect_unknown, dissect_unknown}, + /* 0x89 */ {dissect_unknown, dissect_unknown}, + /* 0x8a */ {dissect_unknown, dissect_unknown}, + /* 0x8b */ {dissect_unknown, dissect_unknown}, + /* 0x8c */ {dissect_unknown, dissect_unknown}, + /* 0x8d */ {dissect_unknown, dissect_unknown}, + /* 0x8e */ {dissect_unknown, dissect_unknown}, + /* 0x8f */ {dissect_unknown, dissect_unknown}, + + /* 0x90 */ {dissect_unknown, dissect_unknown}, + /* 0x91 */ {dissect_unknown, dissect_unknown}, + /* 0x92 */ {dissect_unknown, dissect_unknown}, + /* 0x93 */ {dissect_unknown, dissect_unknown}, + /* 0x94 */ {dissect_unknown, dissect_unknown}, + /* 0x95 */ {dissect_unknown, dissect_unknown}, + /* 0x96 */ {dissect_unknown, dissect_unknown}, + /* 0x97 */ {dissect_unknown, dissect_unknown}, + /* 0x98 */ {dissect_unknown, dissect_unknown}, + /* 0x99 */ {dissect_unknown, dissect_unknown}, + /* 0x9a */ {dissect_unknown, dissect_unknown}, + /* 0x9b */ {dissect_unknown, dissect_unknown}, + /* 0x9c */ {dissect_unknown, dissect_unknown}, + /* 0x9d */ {dissect_unknown, dissect_unknown}, + /* 0x9e */ {dissect_unknown, dissect_unknown}, + /* 0x9f */ {dissect_unknown, dissect_unknown}, /* 0xa0 NT Transaction*/ {dissect_nt_transaction_request, dissect_nt_transaction_response}, /* 0xa1 NT Trans secondary*/ {dissect_nt_transaction_request, dissect_nt_transaction_response}, /* 0xa2 NT CreateAndX*/ {dissect_nt_create_andx_request, dissect_nt_create_andx_response}, - /* 0xa3 */ {NULL, NULL}, - /* 0xa4 NT Cancel*/ {dissect_nt_cancel_request, NULL}, /*no response to this one*/ - /* 0xa5 */ {NULL, NULL}, - /* 0xa6 */ {NULL, NULL}, - /* 0xa7 */ {NULL, NULL}, - /* 0xa8 */ {NULL, NULL}, - /* 0xa9 */ {NULL, NULL}, - /* 0xaa */ {NULL, NULL}, - /* 0xab */ {NULL, NULL}, - /* 0xac */ {NULL, NULL}, - /* 0xad */ {NULL, NULL}, - /* 0xae */ {NULL, NULL}, - /* 0xaf */ {NULL, NULL}, - - /* 0xb0 */ {NULL, NULL}, - /* 0xb1 */ {NULL, NULL}, - /* 0xb2 */ {NULL, NULL}, - /* 0xb3 */ {NULL, NULL}, - /* 0xb4 */ {NULL, NULL}, - /* 0xb5 */ {NULL, NULL}, - /* 0xb6 */ {NULL, NULL}, - /* 0xb7 */ {NULL, NULL}, - /* 0xb8 */ {NULL, NULL}, - /* 0xb9 */ {NULL, NULL}, - /* 0xba */ {NULL, NULL}, - /* 0xbb */ {NULL, NULL}, - /* 0xbc */ {NULL, NULL}, - /* 0xbd */ {NULL, NULL}, - /* 0xbe */ {NULL, NULL}, - /* 0xbf */ {NULL, NULL}, + /* 0xa3 */ {dissect_unknown, dissect_unknown}, + /* 0xa4 NT Cancel*/ {dissect_nt_cancel_request, dissect_unknown}, /*no response to this one*/ + /* 0xa5 */ {dissect_unknown, dissect_unknown}, + /* 0xa6 */ {dissect_unknown, dissect_unknown}, + /* 0xa7 */ {dissect_unknown, dissect_unknown}, + /* 0xa8 */ {dissect_unknown, dissect_unknown}, + /* 0xa9 */ {dissect_unknown, dissect_unknown}, + /* 0xaa */ {dissect_unknown, dissect_unknown}, + /* 0xab */ {dissect_unknown, dissect_unknown}, + /* 0xac */ {dissect_unknown, dissect_unknown}, + /* 0xad */ {dissect_unknown, dissect_unknown}, + /* 0xae */ {dissect_unknown, dissect_unknown}, + /* 0xaf */ {dissect_unknown, dissect_unknown}, + + /* 0xb0 */ {dissect_unknown, dissect_unknown}, + /* 0xb1 */ {dissect_unknown, dissect_unknown}, + /* 0xb2 */ {dissect_unknown, dissect_unknown}, + /* 0xb3 */ {dissect_unknown, dissect_unknown}, + /* 0xb4 */ {dissect_unknown, dissect_unknown}, + /* 0xb5 */ {dissect_unknown, dissect_unknown}, + /* 0xb6 */ {dissect_unknown, dissect_unknown}, + /* 0xb7 */ {dissect_unknown, dissect_unknown}, + /* 0xb8 */ {dissect_unknown, dissect_unknown}, + /* 0xb9 */ {dissect_unknown, dissect_unknown}, + /* 0xba */ {dissect_unknown, dissect_unknown}, + /* 0xbb */ {dissect_unknown, dissect_unknown}, + /* 0xbc */ {dissect_unknown, dissect_unknown}, + /* 0xbd */ {dissect_unknown, dissect_unknown}, + /* 0xbe */ {dissect_unknown, dissect_unknown}, + /* 0xbf */ {dissect_unknown, dissect_unknown}, /* 0xc0 Open Print File*/ {dissect_open_print_file_request, dissect_fid}, /* 0xc1 Write Print File*/ {dissect_write_print_file_request, dissect_empty}, /* 0xc2 Close Print File*/ {dissect_fid, dissect_empty}, /* 0xc3 Get Print Queue*/ {dissect_get_print_queue_request, dissect_get_print_queue_response}, - /* 0xc4 */ {NULL, NULL}, - /* 0xc5 */ {NULL, NULL}, - /* 0xc6 */ {NULL, NULL}, - /* 0xc7 */ {NULL, NULL}, - /* 0xc8 */ {NULL, NULL}, - /* 0xc9 */ {NULL, NULL}, - /* 0xca */ {NULL, NULL}, - /* 0xcb */ {NULL, NULL}, - /* 0xcc */ {NULL, NULL}, - /* 0xcd */ {NULL, NULL}, - /* 0xce */ {NULL, NULL}, - /* 0xcf */ {NULL, NULL}, - - /* 0xd0 */ {NULL, NULL}, - /* 0xd1 */ {NULL, NULL}, - /* 0xd2 */ {NULL, NULL}, - /* 0xd3 */ {NULL, NULL}, - /* 0xd4 */ {NULL, NULL}, - /* 0xd5 */ {NULL, NULL}, - /* 0xd6 */ {NULL, NULL}, - /* 0xd7 */ {NULL, NULL}, - /* 0xd8 */ {NULL, NULL}, - /* 0xd9 */ {NULL, NULL}, - /* 0xda */ {NULL, NULL}, - /* 0xdb */ {NULL, NULL}, - /* 0xdc */ {NULL, NULL}, - /* 0xdd */ {NULL, NULL}, - /* 0xde */ {NULL, NULL}, - /* 0xdf */ {NULL, NULL}, - - /* 0xe0 */ {NULL, NULL}, - /* 0xe1 */ {NULL, NULL}, - /* 0xe2 */ {NULL, NULL}, - /* 0xe3 */ {NULL, NULL}, - /* 0xe4 */ {NULL, NULL}, - /* 0xe5 */ {NULL, NULL}, - /* 0xe6 */ {NULL, NULL}, - /* 0xe7 */ {NULL, NULL}, - /* 0xe8 */ {NULL, NULL}, - /* 0xe9 */ {NULL, NULL}, - /* 0xea */ {NULL, NULL}, - /* 0xeb */ {NULL, NULL}, - /* 0xec */ {NULL, NULL}, - /* 0xed */ {NULL, NULL}, - /* 0xee */ {NULL, NULL}, - /* 0xef */ {NULL, NULL}, - - /* 0xf0 */ {NULL, NULL}, - /* 0xf1 */ {NULL, NULL}, - /* 0xf2 */ {NULL, NULL}, - /* 0xf3 */ {NULL, NULL}, - /* 0xf4 */ {NULL, NULL}, - /* 0xf5 */ {NULL, NULL}, - /* 0xf6 */ {NULL, NULL}, - /* 0xf7 */ {NULL, NULL}, - /* 0xf8 */ {NULL, NULL}, - /* 0xf9 */ {NULL, NULL}, - /* 0xfa */ {NULL, NULL}, - /* 0xfb */ {NULL, NULL}, - /* 0xfc */ {NULL, NULL}, - /* 0xfd */ {NULL, NULL}, - /* 0xfe */ {NULL, NULL}, - /* 0xff */ {NULL, NULL}, + /* 0xc4 */ {dissect_unknown, dissect_unknown}, + /* 0xc5 */ {dissect_unknown, dissect_unknown}, + /* 0xc6 */ {dissect_unknown, dissect_unknown}, + /* 0xc7 */ {dissect_unknown, dissect_unknown}, + /* 0xc8 */ {dissect_unknown, dissect_unknown}, + /* 0xc9 */ {dissect_unknown, dissect_unknown}, + /* 0xca */ {dissect_unknown, dissect_unknown}, + /* 0xcb */ {dissect_unknown, dissect_unknown}, + /* 0xcc */ {dissect_unknown, dissect_unknown}, + /* 0xcd */ {dissect_unknown, dissect_unknown}, + /* 0xce */ {dissect_unknown, dissect_unknown}, + /* 0xcf */ {dissect_unknown, dissect_unknown}, + + /* 0xd0 */ {dissect_unknown, dissect_unknown}, + /* 0xd1 */ {dissect_unknown, dissect_unknown}, + /* 0xd2 */ {dissect_unknown, dissect_unknown}, + /* 0xd3 */ {dissect_unknown, dissect_unknown}, + /* 0xd4 */ {dissect_unknown, dissect_unknown}, + /* 0xd5 */ {dissect_unknown, dissect_unknown}, + /* 0xd6 */ {dissect_unknown, dissect_unknown}, + /* 0xd7 */ {dissect_unknown, dissect_unknown}, + /* 0xd8 */ {dissect_unknown, dissect_unknown}, + /* 0xd9 */ {dissect_unknown, dissect_unknown}, + /* 0xda */ {dissect_unknown, dissect_unknown}, + /* 0xdb */ {dissect_unknown, dissect_unknown}, + /* 0xdc */ {dissect_unknown, dissect_unknown}, + /* 0xdd */ {dissect_unknown, dissect_unknown}, + /* 0xde */ {dissect_unknown, dissect_unknown}, + /* 0xdf */ {dissect_unknown, dissect_unknown}, + + /* 0xe0 */ {dissect_unknown, dissect_unknown}, + /* 0xe1 */ {dissect_unknown, dissect_unknown}, + /* 0xe2 */ {dissect_unknown, dissect_unknown}, + /* 0xe3 */ {dissect_unknown, dissect_unknown}, + /* 0xe4 */ {dissect_unknown, dissect_unknown}, + /* 0xe5 */ {dissect_unknown, dissect_unknown}, + /* 0xe6 */ {dissect_unknown, dissect_unknown}, + /* 0xe7 */ {dissect_unknown, dissect_unknown}, + /* 0xe8 */ {dissect_unknown, dissect_unknown}, + /* 0xe9 */ {dissect_unknown, dissect_unknown}, + /* 0xea */ {dissect_unknown, dissect_unknown}, + /* 0xeb */ {dissect_unknown, dissect_unknown}, + /* 0xec */ {dissect_unknown, dissect_unknown}, + /* 0xed */ {dissect_unknown, dissect_unknown}, + /* 0xee */ {dissect_unknown, dissect_unknown}, + /* 0xef */ {dissect_unknown, dissect_unknown}, + + /* 0xf0 */ {dissect_unknown, dissect_unknown}, + /* 0xf1 */ {dissect_unknown, dissect_unknown}, + /* 0xf2 */ {dissect_unknown, dissect_unknown}, + /* 0xf3 */ {dissect_unknown, dissect_unknown}, + /* 0xf4 */ {dissect_unknown, dissect_unknown}, + /* 0xf5 */ {dissect_unknown, dissect_unknown}, + /* 0xf6 */ {dissect_unknown, dissect_unknown}, + /* 0xf7 */ {dissect_unknown, dissect_unknown}, + /* 0xf8 */ {dissect_unknown, dissect_unknown}, + /* 0xf9 */ {dissect_unknown, dissect_unknown}, + /* 0xfa */ {dissect_unknown, dissect_unknown}, + /* 0xfb */ {dissect_unknown, dissect_unknown}, + /* 0xfc */ {dissect_unknown, dissect_unknown}, + /* 0xfd */ {dissect_unknown, dissect_unknown}, + /* 0xfe */ {dissect_unknown, dissect_unknown}, + /* 0xff */ {dissect_unknown, dissect_unknown}, }; static int @@ -11212,15 +10734,7 @@ dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *top_tree, int dissector = (si->request)? smb_dissector[cmd].request:smb_dissector[cmd].response; - if(dissector){ - offset = (*dissector)(tvb, pinfo, cmd_tree, offset, smb_tree); - } else { - int len = tvb_length_remaining(tvb, offset); - - proto_tree_add_text(cmd_tree, tvb, offset, len, - "Data (%u bytes)", len); - offset += len; - } + offset = (*dissector)(tvb, pinfo, cmd_tree, offset, smb_tree); proto_item_set_len(cmd_item, offset-old_offset); } return offset; @@ -11514,52 +11028,19 @@ static char *decode_smb_name(unsigned char cmd) static void smb_init_protocol(void) { - if (smb_info_table) { - g_hash_table_foreach_remove(smb_info_table, - free_all_smb_info, NULL); - g_hash_table_destroy(smb_info_table); - } - if (smb_request_hash) { - /* - * Remove all entries from the hash table and free all - * strings attached to the keys and values. (The keys - * and values themselves are freed with - * "g_mem_chunk_destroy()" calls below.) - */ - g_hash_table_foreach_remove(smb_request_hash, - free_request_val_data, NULL); - g_hash_table_destroy(smb_request_hash); - } - if (smb_continuation_hash) - g_hash_table_destroy(smb_continuation_hash); - if (smb_request_keys) - g_mem_chunk_destroy(smb_request_keys); - if (smb_request_vals) - g_mem_chunk_destroy(smb_request_vals); - if (smb_continuation_vals) - g_mem_chunk_destroy(smb_continuation_vals); if (smb_info_chunk) g_mem_chunk_destroy(smb_info_chunk); + if (conv_tables_chunk) + g_mem_chunk_destroy(conv_tables_chunk); - smb_info_table = g_hash_table_new(smb_info_hash, smb_info_equal); - smb_request_hash = g_hash_table_new(smb_hash, smb_equal); - smb_continuation_hash = g_hash_table_new(smb_hash, smb_equal); - smb_request_keys = g_mem_chunk_new("smb_request_keys", - sizeof(struct smb_request_key), - smb_packet_init_count * sizeof(struct smb_request_key), - G_ALLOC_AND_FREE); - smb_request_vals = g_mem_chunk_new("smb_request_vals", - sizeof(struct smb_request_val), - smb_packet_init_count * sizeof(struct smb_request_val), - G_ALLOC_AND_FREE); - smb_continuation_vals = g_mem_chunk_new("smb_continuation_vals", - sizeof(struct smb_continuation_val), - smb_packet_init_count * sizeof(struct smb_continuation_val), - G_ALLOC_AND_FREE); smb_info_chunk = g_mem_chunk_new("smb_info_chunk", sizeof(smb_info_t), smb_info_init_count * sizeof(smb_info_t), G_ALLOC_ONLY); + conv_tables_chunk = g_mem_chunk_new("conv_tables_chunk", + sizeof(conv_tables_t), + conv_tables_count * sizeof(conv_tables_t), + G_ALLOC_ONLY); } /* Max string length for displaying Unicode strings. */ @@ -12752,17 +12233,18 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) guint32 nt_status = 0; guint8 errclass = 0; guint16 errcode = 0; - + guint16 uid, pid, tid; top_tree=parent_tree; /* must check that this really is a smb packet */ if (!tvb_bytes_exist(tvb, 0, 4)) - return FALSE; + return FALSE; + if( (tvb_get_guint8(tvb, 0) != 0xff) - || (tvb_get_guint8(tvb, 1) != 'S') - || (tvb_get_guint8(tvb, 2) != 'M') - || (tvb_get_guint8(tvb, 3) != 'B') ){ + || (tvb_get_guint8(tvb, 1) != 'S') + || (tvb_get_guint8(tvb, 2) != 'M') + || (tvb_get_guint8(tvb, 3) != 'B') ){ return FALSE; } @@ -12782,9 +12264,9 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) sip->trans_subcmd = -1; sip->info_level = -1; sip->mid = tvb_get_letohs(tvb, offset+30); - sip->uid = tvb_get_letohs(tvb, offset+28); - sip->pid = tvb_get_letohs(tvb, offset+26); - sip->tid = tvb_get_letohs(tvb, offset+24); + uid = tvb_get_letohs(tvb, offset+28); + pid = tvb_get_letohs(tvb, offset+26); + tid = tvb_get_letohs(tvb, offset+24); flags2 = tvb_get_letohs(tvb, offset+10); if(flags2 & 0x8000){ sip->unicode = TRUE; /* Mark them as Unicode */ @@ -12794,7 +12276,7 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) flags = tvb_get_guint8(tvb, offset+9); sip->request = !(flags&SMB_FLAGS_DIRN); sip->cmd = tvb_get_guint8(tvb, offset+4); - sip->ddisp = 0; + sip->request_val=NULL; if (parent_tree) { item = proto_tree_add_item(parent_tree, proto_smb, tvb, offset, @@ -12810,39 +12292,115 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) proto_tree_add_text(htree, tvb, offset, 4, "Server Component: SMB"); offset += 4; /* Skip the marker */ - /* store smb_info structure so we can retreive it from the reply */ - if(sip->request){ - sip->src = &pinfo->src; - sip->dst = &pinfo->dst; + + if( (sip->request) + && (sip->mid==0) + && (uid==0) + && (pid==0) + && (tid==0) ){ + /* this is a broadcast SMB packet, there will not be a reply. + We dont need to do anything + */ + sip->unidir=FALSE; + } else { + conversation_t *conversation; + conv_tables_t *ct; + smb_info_t *old_si; + gboolean request; + + sip->unidir=TRUE; + request=sip->request; + + /* first we try to find which conversation this packet is + part of + */ + conversation = find_conversation(&pinfo->src, &pinfo->dst, + pinfo->ptype, pinfo->srcport, pinfo->destport, 0); + if(conversation==NULL){ + /* OK this is a new conversation, we must create it + and attach appropriate data (matched and unmatched + table for this conversation) + */ + conversation = conversation_new(&pinfo->src, &pinfo->dst, + pinfo->ptype, pinfo->srcport, pinfo->destport, 0); + ct = g_mem_chunk_alloc(conv_tables_chunk); + ct->matched= g_hash_table_new(smb_info_hash_matched, + smb_info_equal_matched); + ct->unmatched= g_hash_table_new(smb_info_hash_matched, + smb_info_equal_matched); + conversation_add_proto_data(conversation, proto_smb, ct); + } else { + /* this is an old conversation, just get the tables */ + ct=conversation_get_proto_data(conversation, proto_smb); + } if(!pinfo->fd->flags.visited){ - if( (sip->mid==0) - && (sip->uid==0) - && (sip->pid==0) - && (sip->tid==0) ){ - /* this is a broadcast SMB packet, - there will not be a reply. - We dont need to do anything */ - sip->unidir=FALSE; - } else { - sip->unidir=TRUE; + /* first see if we find an unmatched smb "equal" to + the current one + */ + old_si=g_hash_table_lookup(ct->unmatched, + (void *)sip->mid); + if(old_si!=NULL){ + if(request){ + /* ok, we are processing an SMB + request but there was already + another "identical" smb resuest + we had not matched yet. + This must mean that either we have + a retransmission or that the + response to the previous one was + lost and the client has reused + the MID for this conversation. + In either case it's not much more + we can do than forget the old + request and concentrate on the + present one instead. + + XXX - not true for NT Cancel, + where the Cancel request has + the same TID/PID/MID/UID as + the request to be cancelled; + in that case, we should leave + the old request in place. + I'm not sure we can set "sip" + to point to "old_si", however. + */ + g_hash_table_remove(ct->unmatched, (void *)sip->mid); + } else { + /* we have found a response to some request we have seen earlier. + What we do now depends on whether this is the first response + to that request we see (id frame_res==0) or not. + */ + sip=old_si; + + if(sip->frame_res==0){ + /* ok it is the first response we have seen to this packet */ + sip->frame_res = pinfo->fd->num; + g_hash_table_insert(ct->matched, (void *)sip->frame_req, sip); + g_hash_table_insert(ct->matched, (void *)sip->frame_res, sip); + } else { + /* we have already seen another response to this one, but + register it anyway so we see which request it matches + */ + g_hash_table_insert(ct->matched, (void *)pinfo->fd->num, sip); + } + } + } + if(request){ sip = g_mem_chunk_alloc(smb_info_chunk); memcpy(sip, &si, sizeof(smb_info_t)); sip->frame_req = pinfo->fd->num; sip->frame_res = 0; - sip->src=g_malloc(sizeof(address)); - COPY_ADDRESS(sip->src, &pinfo->src); - sip->dst=g_malloc(sizeof(address)); - COPY_ADDRESS(sip->dst, &pinfo->dst); - g_hash_table_insert(smb_info_table, sip, sip); + g_hash_table_insert(ct->unmatched, (void *)sip->mid, sip); + } + } else { + /* we have seen this packet before, just check matching table and if that + fails, just continue using si + */ + old_si=g_hash_table_lookup(ct->matched, (void *)pinfo->fd->num); + if(old_si){ + sip=old_si; } } - } else { - sip->src = &pinfo->dst; - sip->dst = &pinfo->src; - } - sip = g_hash_table_lookup(smb_info_table, sip); - if(!sip){ - sip = &si; } /* need to redo these ones, might have changed if we got a new sip */ sip->request = !(flags&SMB_FLAGS_DIRN); @@ -12857,9 +12415,6 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) proto_tree_add_uint(htree, hf_smb_response_in, tvb, 0, 0, sip->frame_res); } } else { - if(!pinfo->fd->flags.visited){ - sip->frame_res=pinfo->fd->num; - } if(sip->frame_req){ proto_tree_add_uint(htree, hf_smb_response_to, tvb, 0, 0, sip->frame_req); } @@ -12941,18 +12496,15 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) offset += 12; /* TID */ - proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2, - sip->tid); + proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2, tid); offset += 2; /* PID */ - proto_tree_add_uint(htree, hf_smb_pid, tvb, offset, 2, - sip->pid); + proto_tree_add_uint(htree, hf_smb_pid, tvb, offset, 2, pid); offset += 2; /* UID */ - proto_tree_add_uint(htree, hf_smb_uid, tvb, offset, 2, - sip->uid); + proto_tree_add_uint(htree, hf_smb_uid, tvb, offset, 2, uid); offset += 2; /* MID */ @@ -12994,6 +12546,7 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) } } + g_assert(si.request_val==NULL); return TRUE; } |