Fixed some serious bugs in the NCP hash routines. I also simplified

the NCP field table structure so that it is easier to add new request/reply
types. I even added a new type myself. There's still more work to be done;
so for now ignore the warnings that gcc emits.

svn path=/trunk/; revision=287
This commit is contained in:
Gilbert Ramirez 1999-05-13 16:42:43 +00:00
parent 7d152d2237
commit 124c7bc994
2 changed files with 174 additions and 44 deletions

View File

@ -2,7 +2,7 @@
* Routines for NetWare Core Protocol
* Gilbert Ramirez <gram@verdict.uthscsa.edu>
*
* $Id: packet-ncp.c,v 1.11 1999/05/10 20:51:36 gram Exp $
* $Id: packet-ncp.c,v 1.12 1999/05/13 16:42:43 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@unicom.net>
@ -24,6 +24,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#undef DEBUG_NCP_HASH
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@ -41,6 +43,8 @@
#include "packet-ipx.h"
#include "packet-ncp.h"
struct svc_record;
static void
dissect_ncp_request(const u_char *pd, int offset, frame_data *fd, proto_tree *ncp_tree, proto_tree *tree);
@ -50,7 +54,9 @@ dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *ncp_
static struct ncp2222_record *
ncp2222_find(guint8 func, guint8 subfunc);
struct svc_record;
static void
parse_ncp_svc_fields(const u_char *pd, proto_tree *ncp_tree, int offset,
struct svc_record *svc);
static int
svc_record_byte_count(struct svc_record *sr);
@ -78,6 +84,7 @@ guint ncp_hash (const gpointer v);
*/
/* Every NCP packet has this common header */
struct ncp_common_header {
guint16 type;
guint8 sequence;
@ -85,6 +92,8 @@ struct ncp_common_header {
guint8 task;
guint8 conn_high;
};
/* NCP request packets */
struct ncp_request_header {
guint16 type;
guint8 sequence;
@ -96,6 +105,7 @@ struct ncp_request_header {
guint8 subfunc;
};
/* NCP reply packets */
struct ncp_reply_header {
guint16 type;
guint8 sequence;
@ -117,9 +127,20 @@ static value_string request_reply_values[] = {
{ 0x0000, NULL }
};
enum ntype { nend, nbyte, nhex, nbelong, nbeshort, ndata, nbytevar,
ndatetime, nasciiz };
/* These are the field types in an NCP packet */
enum ntype {
nend, /* end of the NCP field list */
nbyte, /* one byte of data */
nhex,
nbelong, /* 4-byte big-endian long int */
nbeshort, /* 2-byte big-endian short int */
ndata, /* unstructured data */
nbytevar, /* a variable number of bytes */
ndatetime, /* date-time stamp */
nasciiz /* null-terminated string of ASCII characters */
};
/* Information on the NCP field */
typedef struct svc_record {
enum ntype type;
guint8 length;
@ -133,16 +154,9 @@ typedef struct ncp2222_record {
gchar *funcname;
svc_record *req;
gchar *req_summ;
guint8 req_summ_var1;
guint8 req_summ_var2;
guint8 req_summ_var3;
svc_record *rep;
gchar *rep_summ;
guint8 rep_summ_var1;
guint8 rep_summ_var2;
guint8 rep_summ_var3;
void* special_handler;
} ncp2222_record;
/* Service Queue Job REQUEST */
@ -157,8 +171,8 @@ static svc_record ncp_17_7C_R[] = {
{ nbelong, 4, "Task Number" },
{ nbelong, 4, "User" },
{ nbelong, 4, "Server specifed to service queue entry" },
{ ndatetime,6, "Earliest time to execute" },
{ ndatetime,6, "When job entered queue" },
{ ndatetime, 6, "Earliest time to execute" },
{ ndatetime, 6, "When job entered queue" },
{ nbelong, 4, "Job Number" },
{ nbeshort, 2, "Job Type" },
{ nbeshort, 2, "Job Position" },
@ -171,6 +185,17 @@ static svc_record ncp_17_7C_R[] = {
{ nend, 0, NULL }
};
/* Negotiate Buffer Size REQUEST */
static svc_record ncp_21_00_C[] = {
{ nbeshort, 2, "Caller's maximum packet size: %d bytes" },
{ nend, 0, NULL }
};
/* RESPONSE */
static svc_record ncp_21_00_R[] = {
{ nbeshort, 2, "Packet size decided upon by file server: %d" },
{ nend, 0, NULL }
};
/* Read from a file REQUEST */
static svc_record ncp_48_00_C[] = {
{ nbyte, 1, "Unknown" },
@ -192,18 +217,19 @@ static svc_record ncp_48_00_R[] = {
static ncp2222_record ncp2222[] = {
{ 0x17, 0x7C, SUBFUNC, "Service Queue Job",
ncp_17_7C_C, "", -1, -1, -1,
ncp_17_7C_R, "", -1, -1, -1
ncp_17_7C_C, ncp_17_7C_R, NULL
},
{ 0x21, 0x00, NOSUB, "Negotiate Buffer Size",
ncp_21_00_C, ncp_21_00_R, NULL
},
{ 0x48, 0x00, NOSUB, "Read from a file",
ncp_48_00_C, "F=%s Read %d at %d", 1, 2, 3,
ncp_48_00_R, "%d bytes read", 0, -1, -1
ncp_48_00_C, ncp_48_00_R, NULL
},
{ 0x00, 0x00, NOSUB, NULL,
NULL, NULL, -1, -1, -1,
NULL, NULL, -1, -1, -1
NULL, NULL, NULL
}
};
@ -250,35 +276,64 @@ struct ncp_request_val {
};
GHashTable *ncp_request_hash = NULL;
GMemChunk *ncp_request_keys = NULL;
GMemChunk *ncp_request_records = NULL;
/* Hash Functions */
gint ncp_equal (const gpointer v, const gpointer v2)
{
return memcmp(v, v2, 7);
struct ncp_request_key *val1 = (struct ncp_request_key*)v;
struct ncp_request_key *val2 = (struct ncp_request_key*)v2;
#if defined(DEBUG_NCP_HASH)
printf("Comparing %08X:%d:%d and %08X:%d:%d\n",
val1->nw_server_address, val1->nw_connection, val1->nw_sequence,
val2->nw_server_address, val2->nw_connection, val2->nw_sequence);
#endif
if (val1->nw_server_address == val2->nw_server_address &&
val1->nw_connection == val2->nw_connection &&
val1->nw_sequence == val2->nw_sequence ) {
return 1;
}
return 0;
}
guint ncp_hash (const gpointer v)
{
struct ncp_request_key *ncp_key = (struct ncp_request_key*)v;
#if defined(DEBUG_NCP_HASH)
printf("hash calculated as %d\n", ncp_key->nw_server_address +
((guint32) ncp_key->nw_connection << 16) +
ncp_key->nw_sequence);
#endif
return ncp_key->nw_server_address +
((guint32) ncp_key->nw_connection << 16) +
ncp_key->nw_sequence;
}
/* Initializes the hash table and the mem_chunk area each time a new
* file is loaded or re-loaded in ethereal */
void
ncp_init_protocol(void)
{
#if defined(DEBUG_NCP_HASH)
printf("Initializing NCP hashtable and mem_chunk area\n");
#endif
if (ncp_request_hash)
g_hash_table_destroy(ncp_request_hash);
if (ncp_request_keys)
g_mem_chunk_destroy(ncp_request_keys);
if (ncp_request_records)
g_mem_chunk_destroy(ncp_request_records);
ncp_request_hash = g_hash_table_new(ncp_hash, ncp_equal);
ncp_request_keys = g_mem_chunk_new("ncp_request_keys",
sizeof(struct ncp_request_key),
100 * sizeof(struct ncp_request_key), G_ALLOC_AND_FREE);
ncp_request_records = g_mem_chunk_new("ncp_request_records",
sizeof(struct ncp_request_val), 50 * sizeof(struct ncp_request_val),
G_ALLOC_AND_FREE);
sizeof(struct ncp_request_val),
100 * sizeof(struct ncp_request_val), G_ALLOC_AND_FREE);
}
static struct ncp2222_record *
@ -300,6 +355,7 @@ ncp2222_find(guint8 func, guint8 subfunc)
return retval;
}
/* How many bytes of NCP data to expect in the packet */
static int
svc_record_byte_count(svc_record *sr)
{
@ -338,6 +394,7 @@ dissect_ncp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "NCP");
nw_connection = (header.conn_high << 16) + header.conn_low;
nw_sequence = header.sequence;
nw_ncp_type = header.type;
@ -372,13 +429,17 @@ dissect_ncp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree,
}
void
dissect_ncp_request(const u_char *pd, int offset, frame_data *fd, proto_tree *ncp_tree, proto_tree *tree) {
dissect_ncp_request(const u_char *pd, int offset, frame_data *fd,
proto_tree *ncp_tree, proto_tree *tree) {
struct ncp_request_header request;
struct ncp2222_record *ncp_request;
gchar *description = "Unknown";
gchar *description = "";
struct ncp_request_val *request_val;
struct ncp_request_key request_key;
struct ncp_request_key *request_key;
proto_tree *field_tree = NULL;
proto_item *ti = NULL;
int max_data;
/*memcpy(&request, &pd[offset], sizeof(request));*/
request.function = pd[offset+6];
@ -389,37 +450,65 @@ dissect_ncp_request(const u_char *pd, int offset, frame_data *fd, proto_tree *nc
if (ncp_request)
description = ncp_request->funcname;
if (check_col(fd, COL_INFO))
col_add_fstr(fd, COL_INFO, "C %s", description);
if (check_col(fd, COL_INFO)) {
if (description[0]) {
col_add_fstr(fd, COL_INFO, "C %s", description);
}
else {
col_add_fstr(fd, COL_INFO, "C 2222/%02X%02X",
request.function, request.subfunc);
}
}
if (ncp_tree) {
proto_tree_add_item(ncp_tree, offset+6, 1, "Function Code: 0x%02X (%s)",
proto_tree_add_item(ncp_tree, offset+6, 1,
"Function Code: 0x%02X (%s)",
request.function, description);
if (ncp_request) {
offset += 10 + svc_record_byte_count(ncp_request->req);
dissect_data(pd, offset, fd, tree);
if (ncp_request) {
max_data = svc_record_byte_count(ncp_request->req);
if (max_data > 0) {
ti = proto_tree_add_item(ncp_tree, offset+7, END_OF_FRAME,
"NCP Request Packet");
field_tree = proto_tree_new();
proto_item_add_subtree(ti, field_tree, ETT_NCP_REQUEST_FIELDS);
parse_ncp_svc_fields(pd, field_tree, offset+7, ncp_request->req);
}
}
}
else { /* ! tree */
request_key = g_mem_chunk_alloc(ncp_request_keys);
request_key->nw_server_address = nw_server_address;
request_key->nw_connection = nw_connection;
request_key->nw_sequence = nw_sequence;
request_val = g_mem_chunk_alloc(ncp_request_records);
request_val->ncp_type = nw_ncp_type;
request_val->ncp_record = ncp2222_find(request.function, request.subfunc);
request_key.nw_server_address = nw_server_address;
request_key.nw_connection = nw_connection;
request_key.nw_sequence = nw_sequence;
g_hash_table_insert(ncp_request_hash, &request_key, request_val);
g_hash_table_insert(ncp_request_hash, request_key, request_val);
#if defined(DEBUG_NCP_HASH)
printf("Inserted server %08X connection %d sequence %d (val=%08X)\n",
nw_server_address, nw_connection, nw_sequence, request_val);
#endif
}
}
void
dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *ncp_tree, proto_tree *tree) {
dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd,
proto_tree *ncp_tree, proto_tree *tree) {
struct ncp_reply_header reply;
struct ncp2222_record *ncp_request = NULL;
struct ncp_request_val *request_val;
struct ncp_request_key request_key;
gchar *description = "Unknown";
gchar *description = "Unknown";
proto_tree *field_tree = NULL;
proto_item *ti = NULL;
int max_data;
memcpy(&reply, &pd[offset], sizeof(reply));
@ -429,7 +518,12 @@ dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *ncp_
request_key.nw_sequence = nw_sequence;
request_val = (struct ncp_request_val*)
g_hash_table_lookup(ncp_request_hash, &request_key);
g_hash_table_lookup(ncp_request_hash, &request_key);
#if defined(DEBUG_NCP_HASH)
printf("Looking for server %08X connection %d sequence %d (retval=%08X)\n",
nw_server_address, nw_connection, nw_sequence, request_val);
#endif
if (request_val)
ncp_request = request_val->ncp_record;
@ -446,8 +540,42 @@ dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *ncp_
proto_tree_add_item(ncp_tree, offset+7, 1,
"Connection Status: %d", reply.connection_state);
offset += 8;
dissect_data(pd, offset, fd, tree);
if (ncp_request) {
max_data = svc_record_byte_count(ncp_request->req);
if (max_data > 0) {
ti = proto_tree_add_item(ncp_tree, offset+8, END_OF_FRAME,
"NCP Reply Packet");
field_tree = proto_tree_new();
proto_item_add_subtree(ti, field_tree, ETT_NCP_REPLY_FIELDS);
parse_ncp_svc_fields(pd, field_tree, offset+8, ncp_request->req);
}
}
}
}
/* Populates the protocol tree with information about the svc_record fields */
static void
parse_ncp_svc_fields(const u_char *pd, proto_tree *ncp_tree, int offset,
struct svc_record *svc)
{
struct svc_record *rec = svc;
int field_offset = offset;
while (rec->type != nend) {
switch(rec->type) {
case nbeshort:
proto_tree_add_item(ncp_tree, field_offset,
rec->length, rec->description, pntohs(&pd[field_offset]));
break;
/* default:
nothing */
}
field_offset += rec->length;
rec++;
}
}

View File

@ -1,7 +1,7 @@
/* packet.h
* Definitions for packet disassembly structures and routines
*
* $Id: packet.h,v 1.55 1999/05/12 05:56:42 gram Exp $
* $Id: packet.h,v 1.56 1999/05/13 16:42:43 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -166,6 +166,8 @@ enum {
ETT_IPX,
ETT_SPX,
ETT_NCP,
ETT_NCP_REQUEST_FIELDS,
ETT_NCP_REPLY_FIELDS,
ETT_DNS,
ETT_DNS_FLAGS,
ETT_DNS_QRY,