aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ncp.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-ncp.c')
-rw-r--r--epan/dissectors/packet-ncp.c343
1 files changed, 172 insertions, 171 deletions
diff --git a/epan/dissectors/packet-ncp.c b/epan/dissectors/packet-ncp.c
index 21e272a64e..908a87f00e 100644
--- a/epan/dissectors/packet-ncp.c
+++ b/epan/dissectors/packet-ncp.c
@@ -186,14 +186,29 @@ static value_string ncp_type_vals[] = {
{ 0, NULL }
};
-/* Conversation Struct so we can store whether the conversation is using Packet Signature */
+static value_string ncp_oplock_vals[] = {
+ { 0x21, "Message Waiting" },
+ { 0x24, "Clear Op-lock" },
+ { 0, NULL }
+};
+
+/* Conversation Struct so we can detect NCP server sessions */
typedef struct {
conversation_t *conversation;
+ guint32 nwconnection;
+ guint8 nwtask;
} mncp_rhash_key;
+/* Store the packet number for the start of the NCP session.
+ * Note sessions are defined as
+ * NCP Connection + NCP Task == Unique NCP server session
+ * It is normal for multiple sessions per connection to exist
+ * These are normally different applications running on multi-tasking
+ * Operating Systems.
+ */
typedef struct {
- gboolean packet_signature;
+ guint32 session_start_packet_num;
} mncp_rhash_value;
static GHashTable *mncp_rhash = NULL;
@@ -205,7 +220,7 @@ mncp_equal(gconstpointer v, gconstpointer v2)
const mncp_rhash_key *val1 = (const mncp_rhash_key*)v;
const mncp_rhash_key *val2 = (const mncp_rhash_key*)v2;
- if (val1->conversation == val2->conversation ) {
+ if (val1->conversation == val2->conversation && val1->nwconnection == val2->nwconnection && val1->nwtask == val2->nwtask) {
return 1;
}
return 0;
@@ -215,7 +230,7 @@ static guint
mncp_hash(gconstpointer v)
{
const mncp_rhash_key *mncp_key = (const mncp_rhash_key*)v;
- return GPOINTER_TO_UINT(mncp_key->conversation);
+ return GPOINTER_TO_UINT(mncp_key->conversation)+mncp_key->nwconnection+mncp_key->nwtask;
}
/* Initializes the hash table and the mem_chunk area each time a new
@@ -238,31 +253,40 @@ mncp_postseq_cleanup(void)
}
static mncp_rhash_value*
-mncp_hash_insert(conversation_t *conversation)
+mncp_hash_insert(conversation_t *conversation, guint32 nwconnection, guint8 nwtask, packet_info *pinfo)
{
mncp_rhash_key *key;
mncp_rhash_value *value;
/* Now remember the request, so we can find it if we later
- a reply to it. */
+ a reply to it. Track by conversation, connection, and task number.
+ in NetWare these values determine each unique session */
key = se_alloc(sizeof(mncp_rhash_key));
key->conversation = conversation;
+ key->nwconnection = nwconnection;
+ key->nwtask = nwtask;
value = se_alloc(sizeof(mncp_rhash_value));
- value->packet_signature = FALSE;
g_hash_table_insert(mncp_rhash, key, value);
+
+ if (ncp_echo_conn && nwconnection != 65535) {
+ expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_CHAT, "Detected New Server Session. Connection %d, Task %d", nwconnection, nwtask);
+ value->session_start_packet_num = pinfo->fd->num;
+ }
return value;
}
/* Returns the ncp_rec*, or NULL if not found. */
static mncp_rhash_value*
-mncp_hash_lookup(conversation_t *conversation)
+mncp_hash_lookup(conversation_t *conversation, guint32 nwconnection, guint8 nwtask)
{
mncp_rhash_key key;
key.conversation = conversation;
+ key.nwconnection = nwconnection;
+ key.nwtask = nwtask;
return g_hash_table_lookup(mncp_rhash, &key);
}
@@ -288,13 +312,13 @@ dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint16 flags = 0;
proto_tree *flags_tree = NULL;
int hdr_offset = 0;
- int commhdr;
+ int commhdr = 0;
int offset = 0;
gint length_remaining;
tvbuff_t *next_tvb;
guint32 testvar = 0, ncp_burst_command, burst_len, burst_off, burst_file;
guint8 subfunction;
- guint32 nw_connection, data_offset;
+ guint32 nw_connection = 0, data_offset;
guint16 data_len = 0;
guint16 missing_fraglist_count = 0;
mncp_rhash_value *request_value = NULL;
@@ -307,139 +331,130 @@ dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
hdr_offset = 0;
ncp_hdr = &header;
- if (is_tcp) {
- if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY)
- hdr_offset += 1;
- ncpiph.signature = tvb_get_ntohl(tvb, hdr_offset);
- ncpiph.length = tvb_get_ntohl(tvb, hdr_offset+4);
- hdr_offset += 8;
- if (ncpiph.signature == NCPIP_RQST) {
- ncpiphrq.version = tvb_get_ntohl(tvb, hdr_offset);
- hdr_offset += 4;
- ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, hdr_offset);
- hdr_offset += 4;
- }
- /* Ok, we need to track the conversation so that we can
- * determine if packet signature is occuring for this
- * connection. We will store the conversation the first
- * time and that state of packet signature will be stored
- * later in our logic. This way when we dissect reply
- * packets we will be able to determine if we need
- * to also dissect with a signature.
- */
- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
- PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport,
- 0);
- if ((ncpiph.length & 0x80000000) ||
- ncpiph.signature == NCPIP_RPLY) {
- /* First time through we will store packet signature
- * state
- */
- if (!pinfo->fd->flags.visited) {
- if (conversation != NULL) {
- /* find the record telling us the
- * request made that caused this
- * reply
- */
- request_value =
- mncp_hash_lookup(conversation);
- /* if for some reason we have no
- * conversation in our hash, create
- * one */
- if (request_value == NULL) {
- request_value =
- mncp_hash_insert(conversation);
- }
- } else {
- /* It's not part of any conversation
- * - create a new one.
- */
- conversation = conversation_new(pinfo->fd->num, &pinfo->src,
- &pinfo->dst, PT_NCP,
- (guint32) pinfo->srcport,
- (guint32) pinfo->destport, 0);
- request_value =
- mncp_hash_insert(conversation);
- }
- /* If this is a request packet then we know
- * that we have a signature
- */
- if (ncpiph.signature == NCPIP_RQST) {
- hdr_offset += 8;
- ncpiph.length &= 0x7fffffff;
- request_value->packet_signature=TRUE;
- } else {
- /* Now on reply packets we have to
- * use the state of the original
- * request packet, so look up the
- * request value and check the state
- * of packet signature
- */
- request_value =
- mncp_hash_lookup(conversation);
- if (request_value->packet_signature) {
- hdr_offset += 8;
- ncpiph.length &= 0x7fffffff;
- /* XXX - it already *is* TRUE */
- request_value->packet_signature=TRUE;
- } else {
- /* XXX - it already *is* FALSE */
- request_value->packet_signature=FALSE;
- }
- }
- } else {
- /* Get request value data */
- request_value = mncp_hash_lookup(conversation);
- if (request_value->packet_signature) {
- hdr_offset += 8;
- ncpiph.length &= 0x7fffffff;
- }
- }
- } else {
- if (!pinfo->fd->flags.visited) {
- if (conversation != NULL) {
- /* find the record telling us the
- * request made that caused this
- * reply
- */
- request_value =
- mncp_hash_lookup(conversation);
- /* if for some reason we have no
- * conversation in our hash, create
- * one */
- if (request_value == NULL) {
- request_value =
- mncp_hash_insert(conversation);
- }
- } else {
- /* It's not part of any conversation
- * - create a new one.
- */
- conversation = conversation_new(pinfo->fd->num, &pinfo->src,
- &pinfo->dst, PT_NCP,
- (guint32) pinfo->srcport,
- (guint32) pinfo->destport, 0);
- request_value =
- mncp_hash_insert(conversation);
- }
- /* find the record telling us the request
- * made that caused this reply
- */
- request_value->packet_signature=FALSE;
- } else {
- request_value = mncp_hash_lookup(conversation);
- }
- }
+ commhdr = hdr_offset;
+
+ ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, FALSE);
+ ncp_tree = proto_item_add_subtree(ti, ett_ncp);
+ if (is_tcp) {
+ if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY)
+ commhdr += 1;
+ /* Get NCPIP Header data */
+ ncpiph.signature = tvb_get_ntohl(tvb, commhdr);
+ proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, commhdr, 4, ncpiph.signature);
+ ncpiph.length = (0x7fffffff & tvb_get_ntohl(tvb, commhdr+4));
+ proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, commhdr+4, 4, ncpiph.length);
+ commhdr += 8;
+ if (ncpiph.signature == NCPIP_RQST) {
+ ncpiphrq.version = tvb_get_ntohl(tvb, commhdr);
+ proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, commhdr, 4, ncpiphrq.version);
+ commhdr += 4;
+ ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, commhdr);
+ proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, commhdr, 4, ncpiphrq.rplybufsize);
+ commhdr += 4;
+ }
+ /* Check to see if this is a valid offset, otherwise increment for packet signature */
+ if (match_strval(tvb_get_ntohs(tvb, commhdr), ncp_type_vals)==NULL) {
+ proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, commhdr, 8, FALSE);
+ commhdr += 8;
+ }
+ }
+ header.type = tvb_get_ntohs(tvb, commhdr);
+ header.sequence = tvb_get_guint8(tvb, commhdr+2);
+ header.conn_low = tvb_get_guint8(tvb, commhdr+3);
+ header.task = tvb_get_guint8(tvb, commhdr+4);
+ header.conn_high = tvb_get_guint8(tvb, commhdr+5);
+ proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr, 2, header.type);
+ nw_connection = (header.conn_high*256)+header.conn_low;
+
+ /* Ok, we need to track the conversation so that we can
+ * determine if a new server session is occuring for this
+ * connection.
+ */
+ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+ PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport,
+ 0);
+ if ((ncpiph.length & 0x80000000) || ncpiph.signature == NCPIP_RPLY) {
+ /* First time through we will record the initial connection and task
+ * values
+ */
+ if (!pinfo->fd->flags.visited) {
+ if (conversation != NULL) {
+ /* find the record telling us the
+ * request made that caused this
+ * reply
+ */
+ request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
+ /* if for some reason we have no
+ * conversation in our hash, create
+ * one */
+ if (request_value == NULL) {
+ request_value = mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
+ }
+ } else {
+ /* It's not part of any conversation
+ * - create a new one.
+ */
+ conversation = conversation_new(pinfo->fd->num, &pinfo->src,
+ &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
+ request_value = mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
+ }
+ /* If this is a request packet then we
+ * might have a new task
+ */
+ if (ncpiph.signature == NCPIP_RPLY) {
+ /* Now on reply packets we have to
+ * use the state of the original
+ * request packet, so look up the
+ * request value and check the task number
+ */
+ request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
+ }
+ } else {
+ /* Get request value data */
+ request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
+ if (request_value) {
+ if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn)
+ {
+ expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_CHAT, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
+ }
+ }
+ }
+ } else {
+ if (!pinfo->fd->flags.visited) {
+ if (conversation != NULL) {
+ /* find the record telling us the
+ * request made that caused this
+ * reply
+ */
+ request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
+ /* if for some reason we have no
+ * conversation in our hash, create
+ * one */
+ if (request_value == NULL) {
+ request_value = mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
+ }
+ } else {
+ /* It's not part of any conversation
+ * - create a new one.
+ */
+ conversation = conversation_new(pinfo->fd->num, &pinfo->src,
+ &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
+ request_value = mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
+ }
+ /* find the record telling us the request
+ * made that caused this reply
+ */
+ } else {
+ request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
+ if (request_value) {
+ if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn)
+ {
+ expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_CHAT, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
+ }
+ }
+ }
}
- /* Record the offset where the NCP common header starts */
- commhdr = hdr_offset;
-
- header.type = tvb_get_ntohs(tvb, commhdr);
- header.sequence = tvb_get_guint8(tvb, commhdr+2);
- header.conn_low = tvb_get_guint8(tvb, commhdr+3);
- header.conn_high = tvb_get_guint8(tvb, commhdr+5);
-
tap_queue_packet(ncp_tap.hdr, pinfo, ncp_hdr);
if (check_col(pinfo->cinfo, COL_INFO)) {
@@ -448,28 +463,6 @@ dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));
}
- nw_connection = (header.conn_high*256)+header.conn_low;
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, FALSE);
- ncp_tree = proto_item_add_subtree(ti, ett_ncp);
-
- if (is_tcp) {
- proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, 0, 4, ncpiph.signature);
- proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, 4, 4, ncpiph.length);
- if (ncpiph.signature == NCPIP_RQST) {
- proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, 8, 4, ncpiphrq.version);
- proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, 12, 4, ncpiphrq.rplybufsize);
- if (request_value->packet_signature==TRUE)
- proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, 16, 8, FALSE);
- } else {
- if (request_value->packet_signature==TRUE)
- proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, 8, 8, FALSE);
- }
- }
- proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr + 0, 2, header.type);
- }
-
/*
* Process the packet-type-specific header.
*/
@@ -479,8 +472,12 @@ dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, FALSE);
- proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, FALSE);
+ proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, tvb_get_guint8(tvb, commhdr+9));
proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, FALSE);
+ if ((tvb_get_guint8(tvb, commhdr+9)==0x24) && ncp_echo_file)
+ {
+ expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_CHAT, "Server requesting station to clear oplock on handle - %08x", tvb_get_ntohl(tvb, commhdr+10));
+ }
break;
case NCP_LIP_ECHO: /* Lip Echo Packet */
@@ -700,20 +697,20 @@ dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/*break;*/
}
}
- next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
+ next_tvb = tvb_new_subset(tvb, commhdr, -1, -1);
dissect_ncp_request(next_tvb, pinfo, nw_connection,
header.sequence, header.type, ncp_tree);
break;
case NCP_DEALLOCATE_SLOT: /* Deallocate Slot Request */
- next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
+ next_tvb = tvb_new_subset(tvb, commhdr, -1, -1);
dissect_ncp_request(next_tvb, pinfo, nw_connection,
header.sequence, header.type, ncp_tree);
break;
case NCP_SERVICE_REQUEST: /* Server NCP Request */
case NCP_BROADCAST_SLOT: /* Server Broadcast Packet */
- next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
+ next_tvb = tvb_new_subset(tvb, commhdr, -1, -1);
if (tvb_get_guint8(tvb, commhdr+6) == 0x68) {
subfunction = tvb_get_guint8(tvb, commhdr+7);
switch (subfunction) {
@@ -743,7 +740,7 @@ dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
break;
case NCP_SERVICE_REPLY: /* Server NCP Reply */
- next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
+ next_tvb = tvb_new_subset(tvb, commhdr, -1, -1);
nds_defrag(next_tvb, pinfo, nw_connection, header.sequence,
header.type, ncp_tree, &ncp_tap);
break;
@@ -754,7 +751,7 @@ dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
* clear out "frags". Was that the right thing to
* do?
*/
- next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
+ next_tvb = tvb_new_subset(tvb, commhdr, -1, -1);
dissect_ncp_reply(next_tvb, pinfo, nw_connection,
header.sequence, header.type, ncp_tree, &ncp_tap);
break;
@@ -922,8 +919,8 @@ proto_register_ncp(void)
FT_UINT8, BASE_DEC, NULL, 0x0,
"", HFILL }},
{ &hf_ncp_oplock_flag,
- { "Oplock Flag", "ncp.oplock_flag",
- FT_UINT8, BASE_HEX, NULL, 0x0,
+ { "Broadcast Message Flag", "ncp.msg_flag",
+ FT_UINT8, BASE_HEX, VALS(ncp_oplock_vals), 0x0,
"", HFILL }},
{ &hf_ncp_oplock_handle,
{ "File Handle", "ncp.oplock_handle",
@@ -1086,6 +1083,10 @@ proto_register_ncp(void)
"Expert: Server Information?",
"Whether the NCP dissector should echo server information to the expert table.",
&ncp_echo_server);
+ prefs_register_bool_preference(ncp_module, "file_2_expert",
+ "Expert: File Information?",
+ "Whether the NCP dissector should echo file information to the expert table.",
+ &ncp_echo_file);
register_init_routine(&mncp_init_protocol);
ncp_tap.stat=register_tap("ncp_srt");
ncp_tap.hdr=register_tap("ncp_hdr");