In the NCP dissector, construct conversations using the source and
authorGuy Harris <guy@alum.mit.edu>
Tue, 18 Apr 2000 04:46:07 +0000 (04:46 -0000)
committerGuy Harris <guy@alum.mit.edu>
Tue, 18 Apr 2000 04:46:07 +0000 (04:46 -0000)
destination network-layer addresses of the servers, and the NCP
connection number, and use the pointer to the conversation and the
request sequence number as the hash key for the table of requests used
to find the request for a given response; this lets it work with
NCP-over-TCP and NCP-over-UDP.

Register the NCP dissector with the UDP dissector in the handoff
registration routine for NCP, just as we do with the TCP dissector.

svn path=/trunk/; revision=1878

packet-ipx.c
packet-ncp.c
packet-udp.c
packet.h

index 01f6cc5a852b2b5fbf3f804d7979a7ec18233581..9812986852b6e44560ab2dd43fddc5431b47f043 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for NetWare's IPX
  * Gilbert Ramirez <gram@xiexie.org>
  *
- * $Id: packet-ipx.c,v 1.55 2000/04/17 00:32:39 guy Exp $
+ * $Id: packet-ipx.c,v 1.56 2000/04/18 04:46:05 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -426,16 +426,6 @@ dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
                        break;
 
                case IPX_PACKET_TYPE_NCP:
-                       /* Is the destination node 00:00:00:00:00:01 ? */
-                       if (pntohl(ipx_dnode) == 0 && pntohs(ipx_dnode + 4) == 1)
-                               nw_server_address = pntohl(ipx_dnet);
-
-                       /* Is the source node 00:00:00:00:00:01 ? */
-                       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;
 
index d0c85c7f3567f6273aa5ae08a6862b887fd34f21..ef215e127f136c038b6b2ca9ef0431afb2d0fff1 100644 (file)
@@ -3,7 +3,7 @@
  * Gilbert Ramirez <gram@xiexie.org>
  * Modified to allow NCP over TCP/IP decodes by James Coe <jammer@cin.net>
  *
- * $Id: packet-ncp.c,v 1.33 2000/04/17 04:00:36 guy Exp $
+ * $Id: packet-ncp.c,v 1.34 2000/04/18 04:46:06 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -41,6 +41,7 @@
 
 #include <glib.h>
 #include "packet.h"
+#include "conversation.h"
 #include "packet-ipx.h"
 #include "packet-ncp.h"
 
@@ -56,15 +57,20 @@ static gint ett_ncp = -1;
 static gint ett_ncp_request_fields = -1;
 static gint ett_ncp_reply_fields = -1;
 
-#define TCP_PORT_NCP                   524
+#define TCP_PORT_NCP           524
+#define UDP_PORT_NCP           524
 
 struct svc_record;
 
 static 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,
+       guint16 nw_connection, guint8 nw_sequence, guint16 nw_ncp_type,
+       proto_tree *ncp_tree, proto_tree *tree);
 
 static 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,
+       guint16 nw_connection, guint8 nw_sequence,
+       proto_tree *ncp_tree, proto_tree *tree);
 
 static struct ncp2222_record *
 ncp2222_find(guint8 func, guint8 subfunc);
@@ -425,42 +431,32 @@ static ncp2222_record ncp2222[] = {
  * (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.
+ * We construct a conversation specified by the client and server
+ * addresses and the connection number; the key representing the unique
+ * NCP request then is composed of the pointer to the conversation
+ * structure, cast to a "guint" (which may throw away the upper 32
+ * bits of the pointer on a P64 platform, but the low-order 32 bits
+ * are more likely to differ between conversations than the upper 32 bits),
+ * and the sequence number.
  *
  * 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;
+       conversation_t  *conversation;
+       guint8          nw_sequence;
 };
 
 struct ncp_request_val {
-       guint32                                 ncp_type;
+       guint32                 ncp_type;
        struct ncp2222_record*  ncp_record;
 };
 
-GHashTable *ncp_request_hash = NULL;
-GMemChunk *ncp_request_keys = NULL;
-GMemChunk *ncp_request_records = NULL;
+static GHashTable *ncp_request_hash = NULL;
+static GMemChunk *ncp_request_keys = NULL;
+static GMemChunk *ncp_request_records = NULL;
 
 /* Hash Functions */
 gint  ncp_equal (gconstpointer v, gconstpointer v2)
@@ -469,14 +465,13 @@ gint  ncp_equal (gconstpointer v, gconstpointer v2)
        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);
+       printf("Comparing %p:%d and %p:%d\n",
+               val1->conversation, val1->nw_sequence,
+               val2->conversation, 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 ) {
+       if (val1->conversation == val2->conversation &&
+           val1->nw_sequence  == val2->nw_sequence ) {
                return 1;
        }
        return 0;
@@ -486,13 +481,10 @@ guint ncp_hash  (gconstpointer 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);
+       printf("hash calculated as %u\n",
+               GPOINTER_TO_UINT(ncp_key->conversation) + ncp_key->nw_sequence);
 #endif
-       return ncp_key->nw_server_address +
-                       ((guint32) ncp_key->nw_connection << 16) +
-                       ncp_key->nw_sequence;
+       return GPOINTER_TO_UINT(ncp_key->conversation) + ncp_key->nw_sequence;
 }
 
 /* Initializes the hash table and the mem_chunk area each time a new
@@ -548,6 +540,9 @@ dissect_ncp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
        struct ncp_ip_header            ncpiph;
        struct ncp_ip_rqhdr             ncpiphrq;
        struct ncp_common_header        header;
+       guint16         nw_connection;
+       guint8          nw_sequence;
+       guint16         nw_ncp_type;
 
        if ( pi.ptype == PT_TCP || pi.ptype == PT_UDP ) {
                ncpiph.signature = pntohl(&pd[offset]);
@@ -612,20 +607,24 @@ dissect_ncp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
 
        /* 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);
+               dissect_ncp_request(pd, offset, fd, nw_connection,
+                               nw_sequence, nw_ncp_type, ncp_tree, tree);
        else if (ncp_hdr_length == 8)
-               dissect_ncp_reply(pd, offset, fd, ncp_tree, tree);
+               dissect_ncp_reply(pd, offset, fd, nw_connection,
+                               nw_sequence, ncp_tree, tree);
        else
                dissect_data(pd, offset, fd, tree);
 }
 
-void
+static void
 dissect_ncp_request(const u_char *pd, int offset, frame_data *fd,
+       guint16 nw_connection, guint8 nw_sequence, guint16 nw_ncp_type,
        proto_tree *ncp_tree, proto_tree *tree) {
 
        struct ncp_request_header       request;
        struct ncp2222_record           *ncp_request;
        gchar                           *description = "";
+       conversation_t                  *conversation;
        struct ncp_request_val          *request_val;
        struct ncp_request_key          *request_key;
        proto_tree                      *field_tree = NULL;
@@ -656,11 +655,25 @@ dissect_ncp_request(const u_char *pd, int offset, frame_data *fd,
 
        if (!fd->flags.visited) {
                /* This is the first time we've looked at this packet.
-                  Remember the request, so we can find it if we later
+                  Keep track of the address and connection whence the request
+                  came, and the address and connection to which the request
+                  is being sent, so that we can match up calls with replies.
+                  (We don't include the sequence number, as we may want
+                  to have all packets over the same connection treated
+                  as being part of a single conversation so that we can
+                  let the user select that conversation to be displayed.) */
+               conversation = find_conversation(&pi.src, &pi.dst,
+                   PT_NCP, nw_connection, nw_connection);
+               if (conversation == NULL) {
+                       /* It's not part of any conversation - create a new one. */
+                       conversation = conversation_new(&pi.src, &pi.dst,
+                           PT_NCP, nw_connection, nw_connection, NULL);
+               }
+
+               /* Now remember the request, so we can find it if we later
                   a reply to it. */
                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->conversation = conversation;
                request_key->nw_sequence = nw_sequence;
 
                request_val = g_mem_chunk_alloc(ncp_request_records);
@@ -669,8 +682,8 @@ dissect_ncp_request(const u_char *pd, int offset, frame_data *fd,
 
                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);
+               printf("Inserted conversation %p sequence %d (val=%p)\n",
+                       conversation, nw_sequence, request_val);
                #endif
        }
 
@@ -703,11 +716,13 @@ dissect_ncp_request(const u_char *pd, int offset, frame_data *fd,
        }
 }
 
-void
+static void
 dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd,
+       guint16 nw_connection, guint8 nw_sequence,
        proto_tree *ncp_tree, proto_tree *tree) {
 
        struct ncp_reply_header         reply;
+       conversation_t                  *conversation;
        struct ncp2222_record           *ncp_request = NULL;
        struct ncp_request_val          *request_val;
        struct ncp_request_key          request_key;
@@ -716,18 +731,28 @@ dissect_ncp_reply(const u_char *pd, int offset, frame_data *fd,
 
        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;
+       /* Find the conversation whence the request would have come. */
 
-       request_val = (struct ncp_request_val*)
-               g_hash_table_lookup(ncp_request_hash, &request_key);
+       conversation = find_conversation(&pi.src, &pi.dst,
+                   PT_NCP, nw_connection, nw_connection);
+       if (conversation != NULL) {
+               /* find the record telling us the request made that caused
+                  this reply */
+               request_key.conversation = conversation;
+               request_key.nw_sequence = nw_sequence;
 
-       #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 defined(DEBUG_NCP_HASH)
+               printf("Looking for conversation %p sequence %u (retval=%p)\n",
+                       conversation, nw_sequence, request_val);
+               #endif
+
+               request_val = (struct ncp_request_val*)
+                       g_hash_table_lookup(ncp_request_hash, &request_key);
+       } else {
+               /* We haven't seen an RPC call for that conversation,
+                  so we can't check for a reply to that call. */
+               request_val = NULL;
+       }
 
        if (request_val)
                ncp_request = request_val->ncp_record;
@@ -1044,4 +1069,5 @@ void
 proto_reg_handoff_ncp(void)
 {
   dissector_add("tcp.port", TCP_PORT_NCP, dissect_ncp);
+  dissector_add("udp.port", UDP_PORT_NCP, dissect_ncp);
 }
index 3eb1a7bf6dc627d0c32e103dae9953d43869acc3..eebfc9fa45f69b34a4194d20a799448f566c9f88 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-udp.c
  * Routines for UDP packet disassembly
  *
- * $Id: packet-udp.c,v 1.67 2000/04/17 02:47:43 guy Exp $
+ * $Id: packet-udp.c,v 1.68 2000/04/18 04:46:07 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -74,7 +74,6 @@ typedef struct _e_udphdr {
 /* UDP Ports -> should go in packet-udp.h */
 
 #define UDP_PORT_TFTP    69
-#define UDP_PORT_NCP    524
 #define UDP_PORT_VINES 573
 
 static dissector_table_t udp_dissector_table;
@@ -129,9 +128,7 @@ decode_udp_ports( const u_char *pd, int offset, frame_data *fd,
 
   /* XXX - we should do these with the subdissector table as well. */
 #define PORT_IS(port)  (uh_sport == port || uh_dport == port)
-  if (PORT_IS(UDP_PORT_NCP))
-    dissect_ncp(pd, offset, fd, tree); /* XXX -- need to handle nw_server_address */
-  else if (PORT_IS(UDP_PORT_VINES)) {
+  if (PORT_IS(UDP_PORT_VINES)) {
     /* FIXME: AFAIK, src and dst port must be the same */
     dissect_vines_frp(pd, offset, fd, tree);
   } else if (PORT_IS(UDP_PORT_TFTP)) {
index 7cbd68878f342c7f7d1675c36920a245dd7cd013..a83c7feb8f01896b35c63172e8364632f5443709 100644 (file)
--- a/packet.h
+++ b/packet.h
@@ -1,7 +1,7 @@
 /* packet.h
  * Definitions for packet disassembly structures and routines
  *
- * $Id: packet.h,v 1.181 2000/04/13 20:39:17 gram Exp $
+ * $Id: packet.h,v 1.182 2000/04/18 04:46:07 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -177,7 +177,8 @@ typedef struct _address {
 typedef enum {
   PT_NONE,             /* no port number */
   PT_TCP,              /* TCP */
-  PT_UDP               /* UDP */
+  PT_UDP,              /* UDP */
+  PT_NCP               /* NCP connection */
 } port_type;
 
 typedef struct _packet_info {