aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>1999-03-20 04:38:57 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>1999-03-20 04:38:57 +0000
commitca662881cb3a7c74b219aabb25642974dddb2c28 (patch)
treef5da08dbcd76b9b09319dc4d755f5e2bdcff68ee
parent71b4a3f7c8f7bdd7f98a5c38a531b5def774a5a6 (diff)
downloadwireshark-ca662881cb3a7c74b219aabb25642974dddb2c28.tar.gz
wireshark-ca662881cb3a7c74b219aabb25642974dddb2c28.tar.bz2
wireshark-ca662881cb3a7c74b219aabb25642974dddb2c28.zip
Re-wrote the NCP module in accordance with how NCP is really organized.
NCP is still not decoded much, but the infrastructure for doing so is now in place, including a hashtable to record the NCP type of each request so that we now how to parse the response. svn path=/trunk/; revision=215
-rw-r--r--file.c8
-rw-r--r--packet-ipx.c73
-rw-r--r--packet-ncp.c503
-rw-r--r--packet-ncp.h310
4 files changed, 394 insertions, 500 deletions
diff --git a/file.c b/file.c
index b080c37d32..1a1095059b 100644
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
- * $Id: file.c,v 1.20 1999/03/01 18:57:01 gram Exp $
+ * $Id: file.c,v 1.21 1999/03/20 04:38:57 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -62,6 +62,8 @@
#include "file.h"
#include "util.h"
+#include "packet-ncp.h"
+
extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
extern guint file_ctx;
@@ -237,7 +239,9 @@ load_cap_file(char *fname, capture_file *cf) {
int err;
close_cap_file(cf, info_bar, file_ctx);
-
+
+ ncp_init_protocol();
+
if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
name_ptr = fname;
else
diff --git a/packet-ipx.c b/packet-ipx.c
index a3e7055994..8e0c2861e7 100644
--- a/packet-ipx.c
+++ b/packet-ipx.c
@@ -2,7 +2,7 @@
* Routines for NetWare's IPX
* Gilbert Ramirez <gram@verdict.uthscsa.edu>
*
- * $Id: packet-ipx.c,v 1.16 1999/03/05 06:09:39 gram Exp $
+ * $Id: packet-ipx.c,v 1.17 1999/03/20 04:38:56 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@unicom.net>
@@ -39,6 +39,7 @@
#include "ethereal.h"
#include "packet.h"
#include "packet-ipx.h"
+#include "packet-ncp.h"
/* The information in this module (IPX, SPX, NCP) comes from:
NetWare LAN Analysis, Second Edition
@@ -183,59 +184,68 @@ void
dissect_ipx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
GtkWidget *ipx_tree, *ti;
- u_char ipx_type;
+ guint8 ipx_type, ipx_hops;
+ guint16 ipx_checksum, ipx_length;
+ guint8 *ipx_snode, *ipx_dnode, *ipx_snet, *ipx_dnet;
- char *dnet, *snet;
- guint16 dsocket, ssocket;
+ gchar *str_dnet, *str_snet;
+ guint16 ipx_dsocket, ipx_ssocket;
void (*dissect) (const u_char *, int, frame_data *, GtkTree *);
/* Calculate here for use in pinfo and in tree */
- dnet = ipxnet_to_string((guint8*)&pd[offset+6]);
- snet = ipxnet_to_string((guint8*)&pd[offset+18]);
- dsocket = pntohs(&pd[offset+16]);
- ssocket = pntohs(&pd[offset+28]);
+ ipx_dnet = (guint8*)&pd[offset+6];
+ ipx_snet = (guint8*)&pd[offset+18];
+ str_dnet = ipxnet_to_string(ipx_dnet);
+ str_snet = ipxnet_to_string(ipx_snet);
+ ipx_dsocket = pntohs(&pd[offset+16]);
+ ipx_ssocket = pntohs(&pd[offset+28]);
+ ipx_dnode = (guint8*)&pd[offset+10];
+ ipx_snode = (guint8*)&pd[offset+22];
+ ipx_type = pd[offset+5];
if (check_col(fd, COL_RES_DL_DST))
col_add_str(fd, COL_RES_DL_DST,
- ipx_addr_to_str(pntohl(&pd[offset+6]),
- (guint8*)&pd[offset+10]));
+ ipx_addr_to_str(pntohl(ipx_dnet), ipx_dnode));
if (check_col(fd, COL_RES_DL_SRC))
col_add_str(fd, COL_RES_DL_SRC,
- ipx_addr_to_str(pntohl(&pd[offset+18]),
- (guint8*)&pd[offset+22]));
+ ipx_addr_to_str(pntohl(ipx_snet), ipx_snode));
+
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "IPX");
if (check_col(fd, COL_INFO))
- col_add_fstr(fd, COL_INFO, "%s (0x%04X)", port_text(dsocket), dsocket);
-
- ipx_type = pd[offset+5];
+ col_add_fstr(fd, COL_INFO, "%s (0x%04X)", port_text(ipx_dsocket),
+ ipx_dsocket);
if (tree) {
+ ipx_checksum = pntohs(&pd[offset]);
+ ipx_length = pntohs(&pd[offset+2]);
+ ipx_hops = pd[offset+4];
+
ti = add_item_to_tree(GTK_WIDGET(tree), offset, 30,
"Internetwork Packet Exchange");
ipx_tree = gtk_tree_new();
add_subtree(ti, ipx_tree, ETT_IPX);
add_item_to_tree(ipx_tree, offset, 2, "Checksum: 0x%04x",
- (pd[offset] << 8) | pd[offset+1]);
+ ipx_checksum);
add_item_to_tree(ipx_tree, offset+2, 2, "Length: %d bytes",
- (pd[offset+2] << 8) | pd[offset+3]);
+ ipx_length);
add_item_to_tree(ipx_tree, offset+4, 1, "Transport Control: %d hops",
- pd[offset+4]);
+ ipx_hops);
add_item_to_tree(ipx_tree, offset+5, 1, "Packet Type: %s",
ipx_packet_type(ipx_type));
add_item_to_tree(ipx_tree, offset+6, 4, "Destination Network: %s",
- dnet);
+ str_dnet);
add_item_to_tree(ipx_tree, offset+10, 6, "Destination Node: %s",
- ether_to_str((guint8*)&pd[offset+10]));
- /*dsocket = ntohs(*((guint16*)&pd[offset+16]));*/
+ ether_to_str(ipx_dnode));
add_item_to_tree(ipx_tree, offset+16, 2,
- "Destination Socket: %s (0x%04X)", port_text(dsocket), dsocket);
+ "Destination Socket: %s (0x%04X)", port_text(ipx_dsocket),
+ ipx_dsocket);
add_item_to_tree(ipx_tree, offset+18, 4, "Source Network: %s",
- snet);
+ str_snet);
add_item_to_tree(ipx_tree, offset+22, 6, "Source Node: %s",
- ether_to_str((guint8*)&pd[offset+22]));
+ ether_to_str(ipx_snode));
add_item_to_tree(ipx_tree, offset+28, 2,
- "Source Socket: %s (0x%04X)", port_text(ssocket), ssocket);
+ "Source Socket: %s (0x%04X)", port_text(ipx_ssocket), ipx_ssocket);
}
offset += 30;
@@ -245,11 +255,18 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
break;
case 17: /* NCP */
+ if (pntohl(ipx_dnode) == 0 && pntohs(ipx_dnode + 4) == 1)
+ nw_server_address = pntohl(ipx_dnet);
+ else if (pntohl(ipx_snode) == 0 && pntohs(ipx_snode + 4) == 1)
+ nw_server_address = pntohl(ipx_snet);
+ else
+ nw_server_address = 0;
+
dissect_ncp(pd, offset, fd, tree);
break;
case 20: /* NetBIOS */
- if (dsocket == 0x0455) {
+ if (ipx_dsocket == 0x0455) {
dissect_nbipx_ns(pd, offset, fd, tree);
break;
}
@@ -257,12 +274,12 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
case 0: /* IPX, fall through to default */
default:
- dissect = port_func(dsocket);
+ dissect = port_func(ipx_dsocket);
if (dissect) {
dissect(pd, offset, fd, tree);
}
else {
- dissect = port_func(ssocket);
+ dissect = port_func(ipx_ssocket);
if (dissect) {
dissect(pd, offset, fd, tree);
}
diff --git a/packet-ncp.c b/packet-ncp.c
index 8c62a446fe..811b9772c8 100644
--- a/packet-ncp.c
+++ b/packet-ncp.c
@@ -2,7 +2,7 @@
* Routines for NetWare Core Protocol
* Gilbert Ramirez <gram@verdict.uthscsa.edu>
*
- * $Id: packet-ncp.c,v 1.8 1999/03/01 18:28:11 gram Exp $
+ * $Id: packet-ncp.c,v 1.9 1999/03/20 04:38:57 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@unicom.net>
@@ -29,7 +29,7 @@
#endif
#include <gtk/gtk.h>
-
+#include <glib.h>
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
@@ -45,6 +45,25 @@
#include "packet-ipx.h"
#include "packet-ncp.h"
+static void
+dissect_ncp_request(const u_char *pd, int offset, frame_data *fd, GtkWidget *ncp_tree, GtkTree *tree);
+
+static void
+dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd, GtkWidget *ncp_tree, GtkTree *tree);
+
+static struct ncp2222_record *
+ncp2222_find(guint8 func, guint8 subfunc);
+
+struct svc_record;
+
+static int
+svc_record_byte_count(struct svc_record *sr);
+
+/* Hash functions */
+gint ncp_equal (const gpointer v, const gpointer v2);
+guint ncp_hash (const gpointer v);
+
+
/* The information in this module comes from:
NetWare LAN Analysis, Second Edition
Laura A. Chappell and Dan E. Hakes
@@ -53,12 +72,47 @@
ISBN: 0-7821-1362-1
And from the ncpfs source code by Volker Lendecke
+
+ And:
+ Programmer's Guide to the NetWare Core Protocol
+ Steve Conner & Diane Conner
+ (c) 1996 by Steve Conner & Diane Conner
+ Published by Annabooks, San Diego, California
+ ISBN: 0-929392-31-0
+
*/
+struct ncp_common_header {
+ guint16 type;
+ guint8 sequence;
+ guint8 conn_low;
+ guint8 task;
+ guint8 conn_high;
+};
+struct ncp_request_header {
+ guint16 type;
+ guint8 sequence;
+ guint8 conn_low;
+ guint8 task;
+ guint8 conn_high;
+ guint8 function;
+ guint16 length;
+ guint8 subfunc;
+};
+
+struct ncp_reply_header {
+ guint16 type;
+ guint8 sequence;
+ guint8 conn_low;
+ guint8 task;
+ guint8 conn_high;
+ guint8 completion_code;
+ guint8 connection_state;
+};
static value_string request_reply_values[] = {
- { 0x1111, "Create a service connection" },
+ { 0x1111, "Create a service connection" },
{ 0x2222, "Service request" },
{ 0x3333, "Service reply" },
{ 0x5555, "Destroy service connection" },
@@ -67,158 +121,228 @@ static value_string request_reply_values[] = {
{ 0x0000, NULL }
};
+enum ntype { nend, nbyte, nhex, nbelong, nbeshort, ndata, nbytevar,
+ ndatetime, nasciiz };
+
+typedef struct svc_record {
+ enum ntype type;
+ guint8 length;
+ gchar *description;
+} svc_record;
+
+typedef struct ncp2222_record {
+ guint8 func;
+ guint8 subfunc;
+ guint8 submask;
+ 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;
+} ncp2222_record;
+
+/* Service Queue Job REQUEST */
+static svc_record ncp_17_7C_C[] = {
+ { nbelong, 4, "The queue the job resides in" },
+ { nbeshort, 2, "Job Type" },
+ { nend, 0, NULL }
+};
+/* Service Queue Job REPLY */
+static svc_record ncp_17_7C_R[] = {
+ { nbelong, 4, "Client station number" },
+ { 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" },
+ { nbelong, 4, "Job Number" },
+ { nbeshort, 2, "Job Type" },
+ { nbeshort, 2, "Job Position" },
+ { nbeshort, 2, "Current status of job" },
+ { nasciiz, 14, "Name of file" },
+ { nbelong, 4, "File handle" },
+ { nbelong, 4, "Client station number" },
+ { nbelong, 4, "Task number" },
+ { nbelong, 4, "Job server" },
+ { nend, 0, NULL }
+};
-static value_string ncp2222_func[] = {
- { 17, "Print and Queue Services" },
- { 21, "Message Services" },
- { 22, "File and Directory Services" },
- { 23, "Binding and Rights Services" },
- { 34, "Transaction Tacking Services" },
- { 35, "Apple File Services" },
- { 72, "File Services" }, /* guess */
- { 86, "Extended Attributes Services" },
- { 87, "File and Directory Services" },
- { 88, "Auditing Services" },
- { 104, "Netware Directory Services" },
- { 123, "Netware 4.x Statistical Information Services" },
- { 0, NULL }
+/* Read from a file REQUEST */
+static svc_record ncp_48_00_C[] = {
+ { nbyte, 1, "Unknown" },
+ { nhex, 6, "File Handle" },
+ { nbelong, 4, "Byte offset within file" },
+ { nbeshort, 2, "Maximum data bytes to return" },
+ { nend, 0, NULL }
+};
+/* RESPONSE */
+static svc_record ncp_48_00_R[] = {
+ { nbeshort, 2, "Data bytes returned" },
+ { nbytevar, 1, "Padding" },
+ { ndata, 0, NULL }
};
-static char*
-ncp2222_subfunc(u_short func, u_short subfunc) {
- value_string *info_ptr = NULL;
-
- /* Accounting Services */
- static value_string ncp_23[] = {
- { 150, "Get Current Account Status" },
- { 151, "Submit Account Charge" },
- { 152, "Submit Account Hold" },
- { 153, "Submit Account Note" },
- { 0, NULL }
- };
-
- /* Apple File Services */
- static value_string ncp_35[] = {
- { 1, "AFP Create Directory" },
- { 2, "AFP Create File" },
- { 3, "AFP Delete" },
- { 4, "AFP Get Entry ID from Name" },
- { 5, "AFP Get File Information" },
- { 6, "AFP Get Entry ID From NetWare Handle" },
- { 7, "AFP Rename" },
- { 8, "AFP Open File Fork" },
- { 9, "AFP Set File Information" },
- { 10, "AFP Scan File Information" },
- { 11, "AFP 2.0 Alloc Temporary Directory Handle" },
- { 12, "AFP Get Entry ID from Name Path" },
- { 13, "AFP 2.0 Create Directory" },
- { 14, "AFP 2.0 Create File" },
-/* ??? { 15, "AFP 2.0 Delete File" }, just guessing */
- { 16, "AFP 2.0 Set File Information" },
- { 17, "AFP 2.0 Scan File Information" },
- { 18, "AFP Get DOS Name from Entry ID" },
- { 19, "AFP Get Macintosh Info on Deleted File" },
- { 0, NULL }
- };
-
- /* File services */ /* guess */
- static value_string ncp_72[] = {
- { 0xbb, "Read" },
- { 0, NULL }
- };
-
- /* Auditing Services */
- static value_string ncp_88[] = {
- { 1, "Query Volume Audit Status" },
- { 2, "Add Audit Property" },
- { 3, "Add Auditor Access" },
-
- { 0, NULL }
- };
-
- switch (func) {
- case 23:
- info_ptr = ncp_23;
- break;
- case 35:
- info_ptr = ncp_35;
- break;
- case 72:
- info_ptr = ncp_72;
- break;
- case 88:
- info_ptr = ncp_88;
- break;
- default:
- return "Unknown function";
- }
+#define SUBFUNC 0xff
+#define NOSUB 0x00
- return val_to_str(subfunc, info_ptr, "Unknown");
+static ncp2222_record ncp2222[] = {
+
+{ 0x17, 0x7C, SUBFUNC, "Service Queue Job",
+ ncp_17_7C_C, "", -1, -1, -1,
+ ncp_17_7C_R, "", -1, -1, -1
+},
+
+{ 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
+},
+
+{ 0x00, 0x00, NOSUB, NULL,
+ NULL, NULL, -1, -1, -1,
+ NULL, NULL, -1, -1, -1
+}
+
+};
+
+/* NCP packets come in request/reply pairs. The request packets tell the type
+ * of NCP request and give a sequence ID. The response, unfortunately, only
+ * identifies itself via the sequence ID; you have to know what type of NCP
+ * request the request packet contained in order to successfully parse the NCP
+ * response. A global method for doing this does not exist in ethereal yet
+ * (NFS also requires it), so for now the NCP section will keep its own hash
+ * table keeping track of NCP packet types.
+ *
+ * The key representing the unique NCP request is composed of 3 variables:
+ *
+ * ServerIPXNetwork.Connection.SequenceNumber
+ * 4 bytes 2 bytes 1 byte
+ * guint32 guint16 guint8 (all are host order)
+ *
+ * This assumes that all NCP connection is between a client and server.
+ * Servers can be identified by having a 00:00:00:00:00:01 IPX Node address.
+ * We have to let the IPX layer pass us the ServerIPXNetwork via a global
+ * variable (nw_server_address). In the future, if we decode NCP over TCP/UDP,
+ * then nw_server_address will represent the IP address of the server, which
+ * conveniently, is also 4 bytes long.
+ *
+ * The value stored in the hash table is the ncp_request_val pointer. This
+ * struct tells us the NCP type and gives the ncp2222_record pointer, if
+ * ncp_type == 0x2222.
+ */
+guint32 nw_server_address = 0; /* set by IPX layer */
+guint16 nw_connection = 0; /* set by dissect_ncp */
+guint8 nw_sequence = 0; /* set by dissect_ncp */
+guint16 nw_ncp_type = 0; /* set by dissect_ncp */
+
+struct ncp_request_key {
+ guint32 nw_server_address;
+ guint16 nw_connection;
+ guint8 nw_sequence;
+};
+
+struct ncp_request_val {
+ guint32 ncp_type;
+ struct ncp2222_record* ncp_record;
+};
+
+GHashTable *ncp_request_hash = NULL;
+GMemChunk *ncp_request_records = NULL;
+
+/* Hash Functions */
+gint ncp_equal (const gpointer v, const gpointer v2)
+{
+ return memcmp(v, v2, 7);
}
+guint ncp_hash (const gpointer v)
+{
+ struct ncp_request_key *ncp_key = (struct ncp_request_key*)v;
+
+ return ncp_key->nw_server_address +
+ ((guint32) ncp_key->nw_connection << 16) +
+ ncp_key->nw_sequence;
+}
void
-ncp_read(GtkWidget *tree, const u_char *pd, int offset)
+ncp_init_protocol(void)
+{
+ if (ncp_request_hash)
+ g_hash_table_destroy(ncp_request_hash);
+ if (ncp_request_records)
+ g_mem_chunk_destroy(ncp_request_records);
+
+ ncp_request_hash = g_hash_table_new(ncp_hash, ncp_equal);
+ 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);
+}
+
+static struct ncp2222_record *
+ncp2222_find(guint8 func, guint8 subfunc)
{
- struct ncp_read_header header;
+ struct ncp2222_record *ncp_record, *retval = NULL;
- memcpy(header.handle, &pd[offset], 6);
- header.offset = pntohl(&pd[offset+6]);
- header.bytes = pntohs(&pd[offset+10]);
+ ncp_record = ncp2222;
- add_item_to_tree(tree, offset, 6,
- "File Handle: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X ",
- header.handle[0], header.handle[1], header.handle[2],
- header.handle[3], header.handle[4], header.handle[5]);
-
- add_item_to_tree(tree, offset+6, 4,
- "Starting Offset: %d", header.offset);
+ while(ncp_record->func != 0) {
+ if (ncp_record->func == func &&
+ ncp_record->subfunc == (subfunc & ncp_record->submask)) {
+ retval = ncp_record;
+ break;
+ }
+ ncp_record++;
+ }
- add_item_to_tree(tree, offset+10, 2,
- "Bytes to Read: %d", header.bytes);
+ return retval;
+}
+static int
+svc_record_byte_count(svc_record *sr)
+{
+ svc_record *rec = sr;
+ int byte_count = 0;
+
+ while (rec->type != nend && rec->type != ndata) {
+ byte_count += rec->length;
+ rec++;
+ }
+
+ return byte_count;
}
void
dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
- GtkWidget *ncp_tree, *ti;
- guint16 ncp_type;
- int ncp_hdr;
+ GtkWidget *ncp_tree = NULL, *ti;
+ int ncp_hdr_length = 0;
struct ncp_common_header header;
- struct ncp_request_header request;
- struct ncp_reply_header reply;
- char *ncp_type_text[] = { "Unknown",
- "Request", "Reply" };
-
- ncp_type = pntohs(&pd[offset]);
- header.type = ncp_type;
- header.sequence = pd[offset+2];
- header.conn_low = pd[offset+3];
- header.task = pd[offset+4];
- header.conn_high = pd[offset+5];
-
- if (ncp_type == 0x1111 || ncp_type == 0x2222 || ncp_type == 0x5555 ||
- ncp_type == 0x7777) {
- ncp_hdr = 7;
- request.function = pd[offset+6];
- }
- else if (ncp_type == 0x3333 || ncp_type == 0x9999) {
- ncp_hdr = 8;
- reply.completion_code = pd[offset+6];
- reply.connection_state = pd[offset+7];
+
+ memcpy(&header, &pd[offset], sizeof(header));
+ header.type = ntohs(header.type);
+
+ if (header.type == 0x1111 ||
+ header.type == 0x2222 ||
+ header.type == 0x5555 ||
+ header.type == 0x7777) {
+ ncp_hdr_length = 7;
}
- else {
- ncp_hdr = 6; /* in order to get ncp_type_text[0] */
+ else if (header.type == 0x3333 || header.type == 0x9999) {
+ ncp_hdr_length = 8;
}
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "NCP");
- if (check_col(fd, COL_INFO))
- /* I take advantage of the ncp_hdr length to use as an index into
- * ncp_type_text[]. Ugly hack, but quick. */
- col_add_fstr(fd, COL_INFO, "%s", ncp_type_text[ncp_hdr - 6]);
-
+ nw_connection = (header.conn_high << 16) + header.conn_low;
+ nw_sequence = header.sequence;
+ nw_ncp_type = header.type;
if (tree) {
ti = add_item_to_tree(GTK_WIDGET(tree), offset, END_OF_FRAME,
@@ -227,52 +351,105 @@ dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
add_subtree(ti, ncp_tree, ETT_NCP);
add_item_to_tree(ncp_tree, offset, 2,
- "Type: %s", val_to_str( header.type, request_reply_values,
- "Unknown (%04X)"));
+ "Type: %s", val_to_str( header.type,
+ request_reply_values, "Unknown (%04X)"));
add_item_to_tree(ncp_tree, offset+2, 1,
"Sequence Number: %d", header.sequence);
- add_item_to_tree(ncp_tree, offset+3, 1,
- "Connection Number Low: %d", header.conn_low);
+ add_item_to_tree(ncp_tree, offset+3, 3,
+ "Connection Number: %d", nw_connection);
add_item_to_tree(ncp_tree, offset+4, 1,
"Task Number: %d", header.task);
+ }
- add_item_to_tree(ncp_tree, offset+5, 1,
- "Connection Number High: %d", header.conn_high);
+ /* Note how I use ncp_tree *and* tree in my args for ncp request/reply */
+ if (ncp_hdr_length == 7)
+ dissect_ncp_request(pd, offset, fd, ncp_tree, tree);
+ else if (ncp_hdr_length == 8)
+ dissect_ncp_reply(pd, offset, fd, ncp_tree, tree);
+ else
+ dissect_data(pd, offset, fd, tree);
+}
- if (ncp_hdr == 8) {
- add_item_to_tree(ncp_tree, offset+6, 1,
- "Completion Code: %d", reply.completion_code);
+void
+dissect_ncp_request(const u_char *pd, int offset, frame_data *fd, GtkWidget *ncp_tree, GtkTree *tree) {
- add_item_to_tree(ncp_tree, offset+7, 1,
- "Connection Status: %d", reply.connection_state);
- }
- else {
- add_item_to_tree(ncp_tree, offset+6, 1,
- "Function Code: %s (%d)",
- val_to_str(request.function, ncp2222_func, "Unknown"),
- request.function);
- }
+ struct ncp_request_header request;
+ struct ncp2222_record *ncp_request;
+ gchar *description = "Unknown";
+ struct ncp_request_val *request_val;
+ struct ncp_request_key request_key;
- offset += ncp_hdr;
+ /*memcpy(&request, &pd[offset], sizeof(request));*/
+ request.function = pd[offset+6];
+ request.subfunc = pd[offset+9];
- if (ncp_type == 0x2222) {
- /* my offset is different now */
- add_item_to_tree(ncp_tree, offset, 1,
- "Subfunction Code: %s (%d)",
- ncp2222_subfunc(pd[offset-1], pd[offset]), pd[offset]);
+ ncp_request = ncp2222_find(request.function, request.subfunc);
- if (request.function == 0x48) {
- ncp_read(ncp_tree, pd, offset+1);
- }
- else {
- dissect_data(pd, offset, fd, tree);
- }
- }
- else {
+ if (ncp_request)
+ description = ncp_request->funcname;
+
+ if (check_col(fd, COL_INFO))
+ col_add_fstr(fd, COL_INFO, "C %s", description);
+
+ if (ncp_tree) {
+ add_item_to_tree(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);
}
}
+ else { /* ! tree */
+ 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);
+ }
+
+}
+
+void
+dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd, GtkWidget *ncp_tree, GtkTree *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";
+
+ memcpy(&reply, &pd[offset], sizeof(reply));
+
+ /* find the record telling us the request made that caused this reply */
+ request_key.nw_server_address = nw_server_address;
+ request_key.nw_connection = nw_connection;
+ request_key.nw_sequence = nw_sequence;
+
+ request_val = (struct ncp_request_val*)
+ g_hash_table_lookup(ncp_request_hash, &request_key);
+
+ if (request_val)
+ ncp_request = request_val->ncp_record;
+
+ if (ncp_request)
+ description = ncp_request->funcname;
+
+ if (check_col(fd, COL_INFO))
+ col_add_fstr(fd, COL_INFO, "R %s", description);
+
+ if (ncp_tree) {
+ add_item_to_tree(ncp_tree, offset+6, 1,
+ "Completion Code: %d", reply.completion_code);
+
+ add_item_to_tree(ncp_tree, offset+7, 1,
+ "Connection Status: %d", reply.connection_state);
+ offset += 8;
+ dissect_data(pd, offset, fd, tree);
+ }
+
}
diff --git a/packet-ncp.h b/packet-ncp.h
index 59a52f5b10..837f7bf6a0 100644
--- a/packet-ncp.h
+++ b/packet-ncp.h
@@ -2,7 +2,7 @@
* Routines for NetWare Core Protocol
* Gilbert Ramirez <gram@verdict.uthscsa.edu>
*
- * $Id: packet-ncp.h,v 1.4 1998/11/18 03:01:34 gerald Exp $
+ * $Id: packet-ncp.h,v 1.5 1999/03/20 04:38:57 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@unicom.net>
@@ -24,312 +24,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*
- * ncp.h
- *
- * Copyright (C) 1995 by Volker Lendecke
- *
- */
-
-#define NCP_PTYPE (0x11)
-#define NCP_PORT (0x0451)
-
-#define NCP_ALLOC_SLOT_REQUEST (0x1111)
-#define NCP_REQUEST (0x2222)
-#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
-
-struct ncp_common_header {
- guint16 type ;
- guint8 sequence ;
- guint8 conn_low ;
- guint8 task ;
- guint8 conn_high ;
-};
-struct ncp_request_header {
-/* guint16 type ;
- guint8 sequence ;
- guint8 conn_low ;
- guint8 task ;
- guint8 conn_high ;*/
- guint8 function ;
-/* guint8 data[0] ;*/
-};
-
-#define NCP_REPLY (0x3333)
-#define NCP_POSITIVE_ACK (0x9999)
-
-struct ncp_reply_header {
-/* guint16 type ;
- guint8 sequence ;
- guint8 conn_low ;
- guint8 task ;
- guint8 conn_high ;*/
- guint8 completion_code ;
- guint8 connection_state ;
-/* guint8 data[0] ;*/
-};
-
-
-#define NCP_BINDERY_USER (0x0001)
-#define NCP_BINDERY_UGROUP (0x0002)
-#define NCP_BINDERY_PQUEUE (0x0003)
-#define NCP_BINDERY_FSERVER (0x0004)
-#define NCP_BINDERY_NAME_LEN (48)
-struct ncp_bindery_object {
- guint32 object_id;
- guint16 object_type;
- guint8 object_name[NCP_BINDERY_NAME_LEN];
- guint8 object_flags;
- guint8 object_security;
- guint8 object_has_prop;
-};
-
-struct nw_property {
- guint8 value[128];
- guint8 more_flag;
- guint8 property_flag;
-};
-
-struct prop_net_address {
- guint32 network ;
- guint8 node[IPX_NODE_LEN] ;
- guint16 port ;
-};
-
-#define NCP_VOLNAME_LEN (16)
-#define NCP_NUMBER_OF_VOLUMES (64)
-struct ncp_volume_info {
- guint32 total_blocks;
- guint32 free_blocks;
- guint32 purgeable_blocks;
- guint32 not_yet_purgeable_blocks;
- guint32 total_dir_entries;
- guint32 available_dir_entries;
- guint8 sectors_per_block;
- char volume_name[NCP_VOLNAME_LEN+1];
-};
-
-struct ncp_filesearch_info {
- guint8 volume_number;
- guint16 directory_id;
- guint16 sequence_no;
- guint8 access_rights;
-};
-
-#define NCP_MAX_FILENAME 14
-
-/* these define the attribute byte as seen by NCP */
-#define aRONLY (1L<<0)
-#define aHIDDEN (1L<<1)
-#define aSYSTEM (1L<<2)
-#define aEXECUTE (1L<<3)
-#define aDIR (1L<<4)
-#define aARCH (1L<<5)
-
-#define AR_READ (0x01)
-#define AR_WRITE (0x02)
-#define AR_EXCLUSIVE (0x20)
-
-#define NCP_FILE_ID_LEN 6
-struct ncp_file_info {
- guint8 file_id[NCP_FILE_ID_LEN];
- char file_name[NCP_MAX_FILENAME+1];
- guint8 file_attributes;
- guint8 file_mode;
- guint32 file_length;
- guint16 creation_date;
- guint16 access_date;
- guint16 update_date;
- guint16 update_time;
-};
-
-/* Defines for Name Spaces */
-#define NW_NS_DOS 0
-#define NW_NS_MAC 1
-#define NW_NS_NFS 2
-#define NW_NS_FTAM 3
-#define NW_NS_OS2 4
-
-/* Defines for ReturnInformationMask */
-#define RIM_NAME (0x0001L)
-#define RIM_SPACE_ALLOCATED (0x0002L)
-#define RIM_ATTRIBUTES (0x0004L)
-#define RIM_DATA_SIZE (0x0008L)
-#define RIM_TOTAL_SIZE (0x0010L)
-#define RIM_EXT_ATTR_INFO (0x0020L)
-#define RIM_ARCHIVE (0x0040L)
-#define RIM_MODIFY (0x0080L)
-#define RIM_CREATION (0x0100L)
-#define RIM_OWNING_NAMESPACE (0x0200L)
-#define RIM_DIRECTORY (0x0400L)
-#define RIM_RIGHTS (0x0800L)
-#define RIM_ALL (0x0FFFL)
-#define RIM_COMPRESSED_INFO (0x80000000L)
-
-/* open/create modes */
-#define OC_MODE_OPEN 0x01
-#define OC_MODE_TRUNCATE 0x02
-#define OC_MODE_REPLACE 0x02
-#define OC_MODE_CREATE 0x08
-
-/* open/create results */
-#define OC_ACTION_NONE 0x00
-#define OC_ACTION_OPEN 0x01
-#define OC_ACTION_CREATE 0x02
-#define OC_ACTION_TRUNCATE 0x04
-#define OC_ACTION_REPLACE 0x04
-
-/* access rights attributes */
-#ifndef AR_READ_ONLY
-#define AR_READ_ONLY 0x0001
-#define AR_WRITE_ONLY 0x0002
-#define AR_DENY_READ 0x0004
-#define AR_DENY_WRITE 0x0008
-#define AR_COMPATIBILITY 0x0010
-#define AR_WRITE_THROUGH 0x0040
-#define AR_OPEN_COMPRESSED 0x0100
-#endif
-
-struct nw_info_struct
-{
- guint32 spaceAlloc ;
- guint32 attributes ;
- guint16 flags ;
- guint32 dataStreamSize ;
- guint32 totalStreamSize ;
- guint16 numberOfStreams ;
- guint16 creationTime ;
- guint16 creationDate ;
- guint32 creatorID ;
- guint16 modifyTime ;
- guint16 modifyDate ;
- guint32 modifierID ;
- guint16 lastAccessDate ;
- guint16 archiveTime ;
- guint16 archiveDate ;
- guint32 archiverID ;
- guint16 inheritedRightsMask ;
- guint32 dirEntNum ;
- guint32 DosDirNum ;
- guint32 volNumber ;
- guint32 EADataSize ;
- guint32 EAKeyCount ;
- guint32 EAKeySize ;
- guint32 NSCreator ;
- guint8 nameLen ;
- guint8 entryName[256] ;
-};
-
-/* modify mask - use with MODIFY_DOS_INFO structure */
-#define DM_ATTRIBUTES (0x0002L)
-#define DM_CREATE_DATE (0x0004L)
-#define DM_CREATE_TIME (0x0008L)
-#define DM_CREATOR_ID (0x0010L)
-#define DM_ARCHIVE_DATE (0x0020L)
-#define DM_ARCHIVE_TIME (0x0040L)
-#define DM_ARCHIVER_ID (0x0080L)
-#define DM_MODIFY_DATE (0x0100L)
-#define DM_MODIFY_TIME (0x0200L)
-#define DM_MODIFIER_ID (0x0400L)
-#define DM_LAST_ACCESS_DATE (0x0800L)
-#define DM_INHERITED_RIGHTS_MASK (0x1000L)
-#define DM_MAXIMUM_SPACE (0x2000L)
-
-struct nw_modify_dos_info
-{
- guint32 attributes ;
- guint16 creationDate ;
- guint16 creationTime ;
- guint32 creatorID ;
- guint16 modifyDate ;
- guint16 modifyTime ;
- guint32 modifierID ;
- guint16 archiveDate ;
- guint16 archiveTime ;
- guint32 archiverID ;
- guint16 lastAccessDate ;
- guint16 inheritanceGrantMask ;
- guint16 inheritanceRevokeMask ;
- guint32 maximumSpace ;
-};
-
-struct nw_file_info {
- struct nw_info_struct i;
- int opened;
- int access;
- guint32 server_file_handle ;
- guint8 open_create_action ;
- guint8 file_handle[6] ;
-};
-
-struct nw_search_sequence {
- guint8 volNumber ;
- guint32 dirBase ;
- guint32 sequence ;
-};
-
-struct nw_queue_job_entry {
- guint16 InUse ;
- guint32 prev ;
- guint32 next ;
- guint32 ClientStation ;
- guint32 ClientTask ;
- guint32 ClientObjectID ;
- guint32 TargetServerID ;
- guint8 TargetExecTime[6] ;
- guint8 JobEntryTime[6] ;
- guint32 JobNumber ;
- guint16 JobType ;
- guint16 JobPosition ;
- guint16 JobControlFlags ;
- guint8 FileNameLen ;
- char JobFileName[13] ;
- guint32 JobFileHandle ;
- guint32 ServerStation ;
- guint32 ServerTaskNumber ;
- guint32 ServerObjectID ;
- char JobTextDescription[50] ;
- char ClientRecordArea[152] ;
-};
-
-struct queue_job {
- struct nw_queue_job_entry j;
- guint8 file_handle[6];
-};
-
-#define QJE_OPER_HOLD 0x80
-#define QJE_USER_HOLD 0x40
-#define QJE_ENTRYOPEN 0x20
-#define QJE_SERV_RESTART 0x10
-#define QJE_SERV_AUTO 0x08
-
-/* ClientRecordArea for print jobs */
-#define KEEP_ON 0x0400
-#define NO_FORM_FEED 0x0800
-#define NOTIFICATION 0x1000
-#define DELETE_FILE 0x2000
-#define EXPAND_TABS 0x4000
-#define PRINT_BANNER 0x8000
+extern guint32 nw_server_address;
-struct print_job_record {
- guint8 Version ;
- guint8 TabSize ;
- guint16 Copies ;
- guint16 CtrlFlags ;
- guint16 Lines ;
- guint16 Rows ;
- char FormName[16] ;
- guint8 Reserved[6] ;
- char BannerName[13] ;
- char FnameBanner[13] ;
- char FnameHeader[14] ;
- char Path[80] ;
-};
+void ncp_init_protocol(void);
-/* ethereal additions */
-struct ncp_read_header {
- guint8 handle[6];
- guint32 offset;
- guint16 bytes;
-};