* Add -Wall to CFLAGS if we're running gcc.
[obnox/wireshark/wip.git] / packet-ncp.c
index b8a6a1c714bd1ca0c834b3469aaf0ee814906d8d..e014eba868676b36ae06c09c0fb7d13a7cacbb48 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for NetWare Core Protocol
  * Gilbert Ramirez <gram@verdict.uthscsa.edu>
  *
- * $Id: packet-ncp.c,v 1.1 1998/09/23 05:25:11 gram Exp $
+ * $Id: packet-ncp.c,v 1.7 1998/11/17 04:28:59 gerald Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@unicom.net>
@@ -29,7 +29,6 @@
 #endif
 
 #include <gtk/gtk.h>
-#include <pcap.h>
 
 #include <stdio.h>
 
@@ -43,6 +42,8 @@
 
 #include "ethereal.h"
 #include "packet.h"
+#include "packet-ipx.h"
+#include "packet-ncp.h"
 
 /* The information in this module comes from:
        NetWare LAN Analysis, Second Edition
 */
 
 
-struct req_info {
-       u_short req;
-       char    *text;
-};
 
+static value_string request_reply_values[] = {
+       { 0x1111,       "Create a service connection" },
+       { 0x2222, "Service request" },
+       { 0x3333, "Service reply" },
+       { 0x5555, "Destroy service connection" },
+       { 0x7777, "Burst mode transfer" },
+       { 0x9999, "Request being processed" },
+       { 0x0000, NULL }
+};
 
-/* ================================================================= */
-/* NCP                                                               */
-/* ================================================================= */
-static char*
-req_text(u_short req) {
-       int i=0;
-
-       static struct req_info  reqs[] = {
-               { 0x1111,       "Create a service connection" },
-               { 0x2222, "Service request" },
-               { 0x3333, "Service reply" },
-               { 0x5555, "Destroy service connection" },
-               { 0x7777, "Burst mode transfer" },
-               { 0x9999, "Request being processed" },
-               { 0x0000, NULL }
-       };
 
-       while (reqs[i].text != NULL) {
-               if (reqs[i].req == req) {
-                       return reqs[i].text;
-               }
-               i++;
-       }
-       return "Unknown";
-}
-
-static char*
-ncp2222_func(u_short func) {
-       int i=0;
-
-       static struct req_info  ncp[] = {
-               { 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" },
-               { 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 }
-       };
-
-       while (ncp[i].text != NULL) {
-               if (ncp[i].req == func) {
-                       return ncp[i].text;
-               }
-               i++;
-       }
-       return "Unknown";
-}
+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 }
+};
 
 static char*
 ncp2222_subfunc(u_short func, u_short subfunc) {
-       int i=0;
-       struct req_info *info_ptr = NULL;
+       value_string    *info_ptr = NULL;
 
        /* Accounting Services */
-       static struct req_info  ncp_23[] = {
+       static value_string     ncp_23[] = {
                { 150,  "Get Current Account Status" },
                { 151,  "Submit Account Charge" },
                { 152,  "Submit Account Hold" },
@@ -130,7 +98,7 @@ ncp2222_subfunc(u_short func, u_short subfunc) {
        };
 
        /* Apple File Services */
-       static struct req_info  ncp_35[] = {
+       static value_string     ncp_35[] = {
                { 1,    "AFP Create Directory" },
                { 2,    "AFP Create File" },
                { 3,    "AFP Delete" },
@@ -153,8 +121,14 @@ ncp2222_subfunc(u_short func, u_short subfunc) {
                { 0,    NULL }
        };
 
+       /* File services */ /* guess */
+       static value_string ncp_72[] = {
+               { 0xbb, "Read" },
+               { 0,    NULL }
+       };
+
        /* Auditing Services */
-       static struct req_info  ncp_88[] = {
+       static value_string     ncp_88[] = {
                { 1,    "Query Volume Audit Status" },
                { 2,    "Add Audit Property" },
                { 3,    "Add Auditor Access" },
@@ -169,94 +143,136 @@ ncp2222_subfunc(u_short func, u_short subfunc) {
                case 35:
                        info_ptr = ncp_35;
                        break;
+               case 72:
+                       info_ptr = ncp_72;
+                       break;
                case 88:
                        info_ptr = ncp_88;
                        break;
                default:
-                       return "Unkown function";
+                       return "Unknown function";
        }
 
-
-       while (info_ptr[i].text != NULL) {
-               if (info_ptr[i].req == subfunc) {
-                       printf("subfunc=%s\n", info_ptr[i].text);
-                       return info_ptr[i].text;
-               }
-               i++;
-       }
-       return "Unknown";
+       return val_to_str(subfunc, info_ptr, "Unknown");
 }
 
 
+void
+ncp_read(GtkWidget *tree, const u_char *pd, int offset)
+{
+       struct ncp_read_header header;
+
+       memcpy(header.handle, &pd[offset], 6);
+       header.offset = pntohl(&pd[offset+6]);
+       header.bytes = pntohs(&pd[offset+10]);
+
+       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);
+
+       add_item_to_tree(tree, offset+10,    2,
+                       "Bytes to Read: %d", header.bytes);
+
+}
+
 void
 dissect_ncp(const u_char *pd, int offset, frame_data *fd, GtkTree *tree) {
 
        GtkWidget       *ncp_tree, *ti;
        guint16         ncp_type;
        int                     ncp_hdr;
-
-       if (fd->win_info[0]) {
-               strcpy(fd->win_info[3], "NCP");
-               strcpy(fd->win_info[4], "NCP");
-       }
+       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 = 6;
+               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];
        }
        else {
-               ncp_hdr = 1; /* ? */
+               ncp_hdr = 6; /* in order to get ncp_type_text[0] */
        }
 
+       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]);
+
+
        if (tree) {
-               ti = add_item_to_tree(GTK_WIDGET(tree), offset, ncp_hdr,
+               ti = add_item_to_tree(GTK_WIDGET(tree), offset, END_OF_FRAME,
                        "NetWare Core Protocol");
                ncp_tree = gtk_tree_new();
                add_subtree(ti, ncp_tree, ETT_NCP);
 
                add_item_to_tree(ncp_tree, offset,      2,
-                       "Type: %s", req_text( pntohs( &pd[offset] ) ) );
+                       "Type: %s", val_to_str( header.type, request_reply_values,
+                                       "Unknown (%04X)"));
 
                add_item_to_tree(ncp_tree, offset+2,    1,
-                       "Sequence Number: %d", pd[offset+2]);
+                       "Sequence Number: %d", header.sequence);
 
                add_item_to_tree(ncp_tree, offset+3,    1,
-                       "Connection Number Low: %d", pd[offset+3]);
+                       "Connection Number Low: %d", header.conn_low);
 
                add_item_to_tree(ncp_tree, offset+4,    1,
-                       "Task Number: %d", pd[offset+4]);
+                       "Task Number: %d", header.task);
 
                add_item_to_tree(ncp_tree, offset+5,    1,
-                       "Connection Number High: %d", pd[offset+5]);
+                       "Connection Number High: %d", header.conn_high);
 
                if (ncp_hdr == 8) {
                        add_item_to_tree(ncp_tree, offset+6,    1,
-                               "Completion Code: %d", pd[offset+6]);
+                               "Completion Code: %d", reply.completion_code);
 
                        add_item_to_tree(ncp_tree, offset+7,    1,
-                               "Connection Status: %d", pd[offset+7]);
+                               "Connection Status: %d", reply.connection_state);
+               }
+               else {
+                       add_item_to_tree(ncp_tree, offset+6,            1,
+                               "Function Code: %s (%d)",
+                               match_strval(request.function, ncp2222_func),
+                               request.function);
                }
 
                offset += ncp_hdr;
 
                if (ncp_type == 0x2222) {
                        /* my offset is different now */
-                       add_item_to_tree(ncp_tree, offset,              1,
-                               "Function Code: %s (%d)",
-                               ncp2222_func(pd[offset]), pd[offset]);
-
-                       add_item_to_tree(ncp_tree, offset+2,    1,
+                       add_item_to_tree(ncp_tree, offset,      1,
                                "Subfunction Code: %s (%d)",
-                               ncp2222_subfunc(pd[offset], pd[offset+2]), pd[offset+2]);
-
-                       offset += 3;
+                               ncp2222_subfunc(pd[offset-1], pd[offset]), pd[offset]);
+
+                       if (request.function == 0x48) {
+                               ncp_read(ncp_tree, pd, offset+1);
+                       }
+                       else {
+                               dissect_data(pd, offset, fd, tree);
+                       }
+               }
+               else {
+                       dissect_data(pd, offset, fd, tree);
                }
-
-               dissect_data(pd, offset, fd, tree);
        }
 }