diff options
author | Gilbert Ramirez <gram@alumni.rice.edu> | 1999-03-20 04:38:57 +0000 |
---|---|---|
committer | Gilbert Ramirez <gram@alumni.rice.edu> | 1999-03-20 04:38:57 +0000 |
commit | ca662881cb3a7c74b219aabb25642974dddb2c28 (patch) | |
tree | f5da08dbcd76b9b09319dc4d755f5e2bdcff68ee | |
parent | 71b4a3f7c8f7bdd7f98a5c38a531b5def774a5a6 (diff) | |
download | wireshark-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.c | 8 | ||||
-rw-r--r-- | packet-ipx.c | 73 | ||||
-rw-r--r-- | packet-ncp.c | 503 | ||||
-rw-r--r-- | packet-ncp.h | 310 |
4 files changed, 394 insertions, 500 deletions
@@ -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; -}; |