Use "address_to_str_buf()" to generate column data for non-resolved
[obnox/wireshark/wip.git] / packet-ncp.c
1 /* packet-ncp.c
2  * Routines for NetWare Core Protocol
3  * Gilbert Ramirez <gram@alumni.rice.edu>
4  * Modified to allow NCP over TCP/IP decodes by James Coe <jammer@cin.net>
5  * Modified to decode server op-lock
6  * & NDS packets by Greg Morris <gmorris@novell.com>
7  *
8  * Portions Copyright (c) by Gilbert Ramirez 2000-2002
9  * Portions Copyright (c) by James Coe 2000-2002
10  * Portions Copyright (c) Novell, Inc. 2000-2003
11  *
12  * $Id: packet-ncp.c,v 1.73 2003/08/25 22:14:07 guy Exp $
13  *
14  * Ethereal - Network traffic analyzer
15  * By Gerald Combs <gerald@ethereal.com>
16  * Copyright 2000 Gerald Combs
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif
40
41 #ifdef HAVE_NETINET_IN_H
42 # include <netinet/in.h>
43 #endif
44
45 #include <string.h>
46 #include <glib.h>
47 #include <epan/packet.h>
48 #include <epan/conversation.h>
49 #include "prefs.h"
50 #include "packet-ipx.h"
51 #include "packet-tcp.h"
52 #include "packet-ncp-int.h"
53 #include "reassemble.h"
54
55 gboolean is_signed = FALSE;
56 int proto_ncp = -1;
57 static int hf_ncp_ip_ver = -1;
58 static int hf_ncp_ip_length = -1;
59 static int hf_ncp_ip_rplybufsize = -1;
60 static int hf_ncp_ip_sig = -1;
61 static int hf_ncp_ip_packetsig = -1;
62 static int hf_ncp_type = -1;
63 static int hf_ncp_seq = -1;
64 static int hf_ncp_connection = -1;
65 static int hf_ncp_task = -1;
66 static int hf_ncp_stream_type = -1;
67 static int hf_ncp_system_flags = -1;
68 static int hf_ncp_system_flags_abt = -1;
69 static int hf_ncp_system_flags_eob = -1;
70 static int hf_ncp_system_flags_sys = -1;
71 static int hf_ncp_src_connection = -1;
72 static int hf_ncp_dst_connection = -1;
73 static int hf_ncp_packet_seqno = -1;
74 static int hf_ncp_delay_time = -1;
75 static int hf_ncp_burst_seqno = -1;
76 static int hf_ncp_ack_seqno = -1;
77 static int hf_ncp_burst_len = -1;
78 static int hf_ncp_data_offset = -1;
79 static int hf_ncp_data_bytes = -1;
80 static int hf_ncp_missing_fraglist_count = -1;
81 static int hf_ncp_missing_data_offset = -1;
82 static int hf_ncp_missing_data_count = -1;
83 static int hf_ncp_oplock_flag = -1;
84 static int hf_ncp_oplock_handle = -1;
85 static int hf_ncp_completion_code = -1;
86 static int hf_ncp_connection_status = -1;
87 static int hf_ncp_slot = -1;
88 static int hf_ncp_control_code = -1;
89 static int hf_ncp_fragment_handle = -1;
90 static int hf_lip_echo = -1;
91
92 gint ett_ncp = -1;
93 gint ett_nds = -1;
94 gint ett_nds_segments = -1;
95 gint ett_nds_segment = -1;
96 static gint ett_ncp_system_flags = -1;
97
98
99 /* Tables for reassembly of fragments. */ 
100 GHashTable *nds_fragment_table = NULL;
101 GHashTable *nds_reassembled_table = NULL;
102 dissector_handle_t nds_data_handle;
103
104 /* desegmentation of NCP over TCP */
105 static gboolean ncp_desegment = TRUE;
106
107 static dissector_handle_t data_handle;
108
109 #define TCP_PORT_NCP            524
110 #define UDP_PORT_NCP            524
111
112 #define NCP_RQST_HDR_LENGTH     7
113 #define NCP_RPLY_HDR_LENGTH     8
114
115
116 /* Hash functions */
117 gint  ncp_equal (gconstpointer v, gconstpointer v2);
118 guint ncp_hash  (gconstpointer v);
119
120 /* These are the header structures to handle NCP over IP */
121 #define NCPIP_RQST      0x446d6454      /* "DmdT" */
122 #define NCPIP_RPLY      0x744e6350      /* "tNcP" */
123
124 struct ncp_ip_header {
125         guint32 signature;
126         guint32 length;
127 };
128
129 /* This header only appears on NCP over IP request packets */
130 struct ncp_ip_rqhdr {
131         guint32 version;
132         guint32 rplybufsize;
133 };
134
135 static const value_string ncp_ip_signature[] = {
136         { NCPIP_RQST, "Demand Transport (Request)" },
137         { NCPIP_RPLY, "Transport is NCP (Reply)" },
138         { 0, NULL },
139 };
140
141 /* The information in this module comes from:
142         NetWare LAN Analysis, Second Edition
143         Laura A. Chappell and Dan E. Hakes
144         (c) 1994 Novell, Inc.
145         Novell Press, San Jose.
146         ISBN: 0-7821-1362-1
147
148   And from the ncpfs source code by Volker Lendecke
149
150   And:
151         Programmer's Guide to the NetWare Core Protocol
152         Steve Conner & Diane Conner
153         (c) 1996 by Steve Conner & Diane Conner
154         Published by Annabooks, San Diego, California
155         ISBN: 0-929392-31-0
156         
157  And:
158     http:developer.novell.com
159     NCP documentation        
160
161 */
162
163 /*
164  * Every NCP packet has this common header (except for burst packets).
165  */
166 struct ncp_common_header {
167         guint16 type;
168         guint8  sequence;
169         guint8  conn_low;
170         guint8  task;
171         guint8  conn_high; /* type=0x5555 doesn't have this */
172 };
173
174
175 static value_string ncp_type_vals[] = {
176         { NCP_ALLOCATE_SLOT,    "Create a service connection" },
177         { NCP_SERVICE_REQUEST,  "Service request" },
178         { NCP_SERVICE_REPLY,    "Service reply" },
179         { NCP_WATCHDOG,         "Watchdog" },
180         { NCP_DEALLOCATE_SLOT,  "Destroy service connection" },
181     { NCP_BROADCAST_SLOT,   "Server Broadcast" },
182         { NCP_BURST_MODE_XFER,  "Burst mode transfer" },
183         { NCP_POSITIVE_ACK,     "Request being processed" },
184     { NCP_LIP_ECHO, "Large Internet Packet Echo" },
185         { 0,                    NULL }
186 };
187
188
189 /*
190  * Burst packet system flags.
191  */
192 #define ABT     0x04            /* Abort request */
193 #define EOB     0x10            /* End of burst */
194 #define SYS     0x80            /* System packet */
195
196 static void
197 dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
198     gboolean is_tcp)
199 {
200         proto_tree                      *ncp_tree = NULL;
201         proto_item                      *ti;
202         struct ncp_ip_header            ncpiph;
203         struct ncp_ip_rqhdr             ncpiphrq;
204         struct ncp_common_header        header;
205         guint16                         nw_connection;
206         guint16                         flags = 0;
207         char                            flags_str[1+3+1+3+1+3+1+1];
208         char                            *sep;
209         proto_tree                      *flags_tree = NULL;
210         guint16                         data_len = 0;
211         guint16                         missing_fraglist_count = 0;
212         int                             hdr_offset = 0;
213         int                             commhdr;
214         int                             offset;
215         gint                            length_remaining;
216         tvbuff_t                        *next_tvb;
217         guint32                         testvar = 0;
218         guint8                          subfunction;
219
220         if (check_col(pinfo->cinfo, COL_PROTOCOL))
221                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NCP");
222         if (check_col(pinfo->cinfo, COL_INFO))
223                 col_clear(pinfo->cinfo, COL_INFO);
224
225     hdr_offset = 0;
226
227         if (is_tcp) {
228         if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY) 
229         {
230             hdr_offset += 1;
231         }
232                 ncpiph.signature        = tvb_get_ntohl(tvb, hdr_offset);
233                 ncpiph.length           = tvb_get_ntohl(tvb, hdr_offset+4);
234                 hdr_offset += 8;
235                 if ( ncpiph.signature == NCPIP_RQST ) {
236                         ncpiphrq.version        = tvb_get_ntohl(tvb, hdr_offset);
237                         hdr_offset += 4;
238                         ncpiphrq.rplybufsize    = tvb_get_ntohl(tvb, hdr_offset);
239                         hdr_offset += 4;
240                 }
241                 if (ncpiph.length & 0x80000000 || ncpiph.signature == NCPIP_RPLY) 
242         {
243             if (!pinfo->fd->flags.visited)
244             {
245                         /*
246                          * This appears to indicate that this packet
247                          * is signed; the signature is 8 bytes long.
248                          *
249                          * XXX - that bit does *not* appear to be set
250                          * in signed replies, and we can't dissect the
251                          * reply enough to find the matching request
252                          * without knowing whether the reply is
253                          * signed.
254                          *
255                          * XXX - what about NCP-over-IPX signed
256                          * messages?
257                          */
258                 if (ncpiph.signature == NCPIP_RQST) {
259                     is_signed = TRUE;
260                     hdr_offset += 8;
261                     ncpiph.length &= 0x7fffffff;
262                 }
263                 else
264                 {
265                     if (is_signed) 
266                     {
267                         hdr_offset += 8;
268                         ncpiph.length &= 0x7fffffff;
269                     }
270                     else
271                     {
272                         is_signed = FALSE;
273                     }
274                 }
275             }
276             else
277             {
278                 if(is_signed)
279                 {
280                     hdr_offset += 8;
281                     ncpiph.length &= 0x7fffffff;
282                 }
283             }
284                 }
285         else
286         {
287             is_signed = FALSE;
288         }
289         }
290
291         /* Record the offset where the NCP common header starts */
292         commhdr = hdr_offset;
293
294         header.type                 = tvb_get_ntohs(tvb, commhdr);
295         header.sequence         = tvb_get_guint8(tvb, commhdr+2);
296         header.conn_low         = tvb_get_guint8(tvb, commhdr+3);
297         header.conn_high        = tvb_get_guint8(tvb, commhdr+5);
298
299         if (check_col(pinfo->cinfo, COL_INFO)) {
300             col_add_fstr(pinfo->cinfo, COL_INFO,
301                     "%s",
302                     val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));
303
304         }
305
306         nw_connection = (header.conn_high << 16) + header.conn_low;
307
308         if (tree) {
309                 ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, FALSE);
310                 ncp_tree = proto_item_add_subtree(ti, ett_ncp);
311
312                 if (is_tcp) {
313                         proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, 0, 4, ncpiph.signature);
314                         proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, 4, 4, ncpiph.length);
315                         if (ncpiph.signature == NCPIP_RQST) {
316                                 proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, 8, 4, ncpiphrq.version);
317                                 proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, 12, 4, ncpiphrq.rplybufsize);
318                 if (is_signed)
319                     proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, 16, 8, FALSE);
320                         }
321             else
322             {
323                 if (is_signed)
324                     proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, 8, 8, FALSE);
325             }
326                 }
327                 proto_tree_add_uint(ncp_tree, hf_ncp_type,      tvb, commhdr + 0, 2, header.type);
328         }
329
330
331         /*
332          * Process the packet-type-specific header.
333          */
334         switch (header.type) {
335
336         case NCP_BROADCAST_SLOT:    /* Server Broadcast */
337                 proto_tree_add_uint(ncp_tree, hf_ncp_seq,       tvb, commhdr + 2, 1, header.sequence);
338                 proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
339                 proto_tree_add_item(ncp_tree, hf_ncp_task,      tvb, commhdr + 4, 1, FALSE);
340                 proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, FALSE);
341                 proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, FALSE);
342                 break;
343
344         case NCP_LIP_ECHO:    /* Lip Echo Packet */
345                 proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr, 13, FALSE);
346                 break;
347
348         case NCP_BURST_MODE_XFER:       /* Packet Burst Packet */
349                 /*
350                  * XXX - we should keep track of whether there's a burst
351                  * outstanding on a connection and, if not, treat the
352                  * beginning of the data as a burst header.
353                  *
354                  * The burst header contains:
355                  *
356                  *      4 bytes of little-endian function number:
357                  *          1 = read, 2 = write;
358                  *
359                  *      4 bytes of file handle;
360                  *
361                  *      8 reserved bytes;
362                  *
363                  *      4 bytes of big-endian file offset;
364                  *
365                  *      4 bytes of big-endian byte count.
366                  *
367                  * The data follows for a burst write operation.
368                  *
369                  * The first packet of a burst read reply contains:
370                  *
371                  *      4 bytes of little-endian result code:
372                  *         0: No error
373                  *         1: Initial error
374                  *         2: I/O error
375                  *         3: No data read;
376                  *
377                  *      4 bytes of returned byte count (big-endian?).
378                  *
379                  * The data follows.
380                  *
381                  * Each burst of a write request is responded to with a
382                  * burst packet with a 2-byte little-endian result code:
383                  *
384                  *      0: Write successful
385                  *      4: Write error
386                  */
387                 flags = tvb_get_guint8(tvb, commhdr + 2);
388                 strcpy(flags_str, "");
389                 sep = " (";
390                 if (flags & ABT) {
391                         strcat(flags_str, sep);
392                         strcat(flags_str, "ABT");
393                         sep = ",";
394                 }
395                 if (flags & EOB) {
396                         strcat(flags_str, sep);
397                         strcat(flags_str, "EOB");
398                         sep = ",";
399                 }
400                 if (flags & SYS) {
401                         strcat(flags_str, sep);
402                         strcat(flags_str, "SYS");
403                 }
404                 if (flags_str[0] != '\0')
405                         strcat(flags_str, ")");
406                 ti = proto_tree_add_uint_format(ncp_tree, hf_ncp_system_flags,
407                     tvb, commhdr + 2, 1, flags, "Flags: 0x%04x%s", flags,
408                     flags_str);
409                 flags_tree = proto_item_add_subtree(ti, ett_ncp_system_flags);
410                 proto_tree_add_item(flags_tree, hf_ncp_system_flags_abt,
411                     tvb, commhdr + 2, 1, FALSE);
412                 proto_tree_add_item(flags_tree, hf_ncp_system_flags_eob,
413                     tvb, commhdr + 2, 1, FALSE);
414                 proto_tree_add_item(flags_tree, hf_ncp_system_flags_sys,
415                     tvb, commhdr + 2, 1, FALSE);
416
417                 proto_tree_add_item(ncp_tree, hf_ncp_stream_type,
418                     tvb, commhdr + 3, 1, FALSE);
419                 proto_tree_add_item(ncp_tree, hf_ncp_src_connection,
420                     tvb, commhdr + 4, 4, FALSE);
421                 proto_tree_add_item(ncp_tree, hf_ncp_dst_connection,
422                     tvb, commhdr + 8, 4, FALSE);
423                 proto_tree_add_item(ncp_tree, hf_ncp_packet_seqno,
424                     tvb, commhdr + 12, 4, FALSE);
425                 proto_tree_add_item(ncp_tree, hf_ncp_delay_time,
426                     tvb, commhdr + 16, 4, FALSE);
427                 proto_tree_add_item(ncp_tree, hf_ncp_burst_seqno,
428                     tvb, commhdr + 20, 2, FALSE);
429                 proto_tree_add_item(ncp_tree, hf_ncp_ack_seqno,
430                     tvb, commhdr + 22, 2, FALSE);
431                 proto_tree_add_item(ncp_tree, hf_ncp_burst_len,
432                     tvb, commhdr + 24, 4, FALSE);
433                 proto_tree_add_item(ncp_tree, hf_ncp_data_offset,
434                     tvb, commhdr + 28, 4, FALSE);
435                 data_len = tvb_get_ntohs(tvb, commhdr + 32);
436                 proto_tree_add_uint(ncp_tree, hf_ncp_data_bytes,
437                     tvb, commhdr + 32, 2, data_len);
438                 missing_fraglist_count = tvb_get_ntohs(tvb, commhdr + 34);
439                 proto_tree_add_item(ncp_tree, hf_ncp_missing_fraglist_count,
440                     tvb, commhdr + 34, 2, FALSE);
441                 break;
442
443         case NCP_ALLOCATE_SLOT:         /* Allocate Slot Request */
444                 length_remaining = tvb_length_remaining(tvb, commhdr + 4);
445                 if (length_remaining > 4) { 
446                         testvar = tvb_get_ntohl(tvb, commhdr+4);
447                         if (testvar == 0x4c495020) {
448                                 proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr+4, 13, FALSE);
449                                 break;
450                         }
451                 }
452                 /* otherwise fall through */
453     
454         case NCP_POSITIVE_ACK:          /* Positive Acknowledgement */
455         case NCP_SERVICE_REQUEST:       /* Server NCP Request */
456         case NCP_SERVICE_REPLY:         /* Server NCP Reply */
457         case NCP_WATCHDOG:              /* Watchdog Packet */
458         case NCP_DEALLOCATE_SLOT:       /* Deallocate Slot Request */
459         default:
460                 proto_tree_add_uint(ncp_tree, hf_ncp_seq,       tvb, commhdr + 2, 1, header.sequence);
461                 proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
462                 proto_tree_add_item(ncp_tree, hf_ncp_task,      tvb, commhdr + 4, 1, FALSE);
463                 break;
464         }
465
466         /*
467          * Process the packet body.
468          */
469         switch (header.type) {
470
471         case NCP_DEALLOCATE_SLOT:       /* Deallocate Slot Request */
472                 proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
473                     "Destroy Service Connection");
474                 break;
475         case NCP_ALLOCATE_SLOT:         /* Allocate Slot Request */
476                 length_remaining = tvb_length_remaining(tvb, commhdr + 4);
477                 if (length_remaining > 4) {
478                         testvar = tvb_get_ntohl(tvb, commhdr+4);
479                         if (testvar == 0x4c495020) {
480                                 proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
481                                     "Lip Echo Packet");
482                                 /*break;*/
483                         }
484                 }
485
486         case NCP_SERVICE_REQUEST:       /* Server NCP Request */
487         case NCP_BROADCAST_SLOT:        /* Server Broadcast Packet */
488                 next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
489                 if (tvb_get_guint8(tvb, commhdr+6) == 0x68) {
490                         subfunction = tvb_get_guint8(tvb, commhdr+7);
491                         switch (subfunction) {
492
493                         case 0x02:      /* NDS Frag Packet to decode */
494                                 dissect_nds_request(next_tvb, pinfo,
495                                     nw_connection, header.sequence,
496                                     header.type, ncp_tree);
497                                 break;
498
499                         case 0x01:      /* NDS Ping */
500                                 dissect_ping_req(next_tvb, pinfo,
501                                     nw_connection, header.sequence,
502                                     header.type, ncp_tree);
503                                 break;
504
505                         default:
506                                 dissect_ncp_request(next_tvb, pinfo,
507                                     nw_connection, header.sequence,
508                                     header.type, ncp_tree);
509                                 break;
510                          }
511                 } else {
512                         dissect_ncp_request(next_tvb, pinfo, nw_connection,
513                             header.sequence, header.type, ncp_tree);
514                 }
515                 break;
516
517         case NCP_SERVICE_REPLY:         /* Server NCP Reply */
518         case NCP_POSITIVE_ACK:          /* Positive Acknowledgement */
519                 next_tvb = tvb_new_subset(tvb, hdr_offset, -1, -1);
520         nds_defrag(next_tvb, pinfo, nw_connection, header.sequence, header.type, ncp_tree);
521                 break;
522
523         case NCP_WATCHDOG:              /* Watchdog Packet */
524                 /*
525                  * XXX - should the completion code be interpreted as
526                  * it is in "packet-ncp2222.inc"?  If so, this
527                  * packet should be handled by "dissect_ncp_reply()".
528                  */
529                 proto_tree_add_item(ncp_tree, hf_ncp_completion_code,
530                     tvb, commhdr + 6, 1, TRUE);
531                 proto_tree_add_item(ncp_tree, hf_ncp_connection_status,
532                     tvb, commhdr + 7, 1, TRUE);
533                 proto_tree_add_item(ncp_tree, hf_ncp_slot,
534                     tvb, commhdr + 8, 1, TRUE);
535                 proto_tree_add_item(ncp_tree, hf_ncp_control_code,
536                     tvb, commhdr + 9, 1, TRUE);
537                 /*
538                  * Display the rest of the packet as data.
539                  */
540                 if (tvb_offset_exists(tvb, commhdr + 10)) {
541                         call_dissector(data_handle,
542                             tvb_new_subset(tvb, commhdr + 10, -1, -1),
543                             pinfo, ncp_tree);
544                 }
545                 break;
546
547         case NCP_BURST_MODE_XFER:       /* Packet Burst Packet */
548                 if (flags & SYS) {
549                         /*
550                          * System packet; show missing fragments if there
551                          * are any.
552                          */
553                         offset = commhdr + 36;
554                         while (missing_fraglist_count != 0) {
555                                 proto_tree_add_item(ncp_tree, hf_ncp_missing_data_offset,
556                                     tvb, offset, 4, FALSE);
557                                 proto_tree_add_item(ncp_tree, hf_ncp_missing_data_count,
558                                     tvb, offset, 2, FALSE);
559                                 missing_fraglist_count--;
560                         }
561                 } else {
562                         /*
563                          * XXX - do this by using -1 and -1 as the length
564                          * arguments to "tvb_new_subset()" and then calling
565                          * "tvb_set_reported_length()"?  That'll throw an
566                          * exception if "data_len" goes past the reported
567                          * length of the packet, but that's arguably a
568                          * feature in this case.
569                          */
570                         length_remaining = tvb_length_remaining(tvb, commhdr + 36);
571                         if (length_remaining > data_len)
572                                 length_remaining = data_len;
573                         if (data_len != 0) {
574                                 call_dissector(data_handle,
575                                     tvb_new_subset(tvb, commhdr + 36,
576                                         length_remaining, data_len),
577                                     pinfo, ncp_tree);
578                         }
579                 }
580                 break;
581
582         case NCP_LIP_ECHO:              /* LIP Echo Packet */
583                 proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
584                     "Lip Echo Packet");
585                 break;
586
587         default:
588                 if (tree) {
589                     proto_tree_add_text(ncp_tree, tvb, commhdr + 6, -1,
590                             "%s packets not supported yet",
591                             val_to_str(header.type, ncp_type_vals,
592                                 "Unknown type (0x%04x)"));
593                 }
594                 break;
595         }
596 }
597
598 static void
599 dissect_ncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
600 {
601         dissect_ncp_common(tvb, pinfo, tree, FALSE);
602 }
603
604 static guint
605 get_ncp_pdu_len(tvbuff_t *tvb, int offset)
606 {
607   guint32 signature;
608
609   /*
610    * Check the NCP-over-TCP header signature, to make sure it's there.
611    * If it's not there, we cannot trust the next 4 bytes to be a
612    * packet length+"has signature" flag, so we just say the length is
613    * "what remains in the packet".
614    */
615   /*if (tvb_get_guint8(tvb, offset)==0xff) 
616   {
617       offset += 1;
618   }*/
619   signature = tvb_get_ntohl(tvb, offset);
620   if (signature != NCPIP_RQST && signature != NCPIP_RPLY)
621     return tvb_length_remaining(tvb, offset);
622
623   /*
624    * Get the length of the NCP-over-TCP packet.  Strip off the "has
625    * signature" flag.
626    */
627
628   return tvb_get_ntohl(tvb, offset + 4) & 0x7fffffff;
629 }
630
631 static void
632 dissect_ncp_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
633 {
634   dissect_ncp_common(tvb, pinfo, tree, TRUE);
635 }
636
637 static void
638 dissect_ncp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
639 {
640   tcp_dissect_pdus(tvb, pinfo, tree, ncp_desegment, 8, get_ncp_pdu_len,
641         dissect_ncp_tcp_pdu);
642 }
643
644 void
645 proto_register_ncp(void)
646 {
647
648   static hf_register_info hf[] = {
649     { &hf_ncp_ip_sig,
650       { "NCP over IP signature",        "ncp.ip.signature",
651         FT_UINT32, BASE_HEX, VALS(ncp_ip_signature), 0x0,
652         "", HFILL }},
653     { &hf_ncp_ip_length,
654       { "NCP over IP length",           "ncp.ip.length",
655         FT_UINT32, BASE_DEC, NULL, 0x0,
656         "", HFILL }},
657     { &hf_ncp_ip_ver,
658       { "NCP over IP Version",          "ncp.ip.version",
659         FT_UINT32, BASE_DEC, NULL, 0x0,
660         "", HFILL }},
661     { &hf_ncp_ip_rplybufsize,
662       { "NCP over IP Reply Buffer Size",        "ncp.ip.replybufsize",
663         FT_UINT32, BASE_DEC, NULL, 0x0,
664         "", HFILL }},
665     { &hf_ncp_ip_packetsig,
666       { "NCP over IP Packet Signature", "ncp.ip.packetsig",
667         FT_BYTES, BASE_NONE, NULL, 0x0,
668         "", HFILL }},
669     { &hf_ncp_type,
670       { "Type",                 "ncp.type",
671         FT_UINT16, BASE_HEX, VALS(ncp_type_vals), 0x0,
672         "NCP message type", HFILL }},
673     { &hf_ncp_seq,
674       { "Sequence Number",      "ncp.seq",
675         FT_UINT8, BASE_DEC, NULL, 0x0,
676         "", HFILL }},
677     { &hf_ncp_connection,
678       { "Connection Number",    "ncp.connection",
679         FT_UINT16, BASE_DEC, NULL, 0x0,
680         "", HFILL }},
681     { &hf_ncp_task,
682       { "Task Number",          "ncp.task",
683         FT_UINT8, BASE_DEC, NULL, 0x0,
684         "", HFILL }},
685     { &hf_ncp_oplock_flag,
686       { "Oplock Flag",    "ncp.oplock_flag",
687         FT_UINT8, BASE_HEX, NULL, 0x0,
688         "", HFILL }},
689     { &hf_ncp_oplock_handle,
690       { "File Handle",    "ncp.oplock_handle",
691         FT_UINT16, BASE_HEX, NULL, 0x0,
692         "", HFILL }},
693     { &hf_ncp_stream_type,
694       { "Stream Type",          "ncp.stream_type",
695         FT_UINT8, BASE_HEX, NULL, 0x0,
696         "Type of burst", HFILL }},
697     { &hf_ncp_system_flags,
698       { "System Flags",         "ncp.system_flags",
699         FT_UINT8, BASE_HEX, NULL, 0x0,
700         "", HFILL }},
701     { &hf_ncp_system_flags_abt,
702       { "ABT",          "ncp.system_flags.abt",
703         FT_BOOLEAN, 8, NULL, ABT,
704         "Is this an abort request?", HFILL }},
705     { &hf_ncp_system_flags_eob,
706       { "EOB",          "ncp.system_flags.eob",
707         FT_BOOLEAN, 8, NULL, EOB,
708         "Is this the last packet of the burst?", HFILL }},
709     { &hf_ncp_system_flags_sys,
710       { "SYS",          "ncp.system_flags.sys",
711         FT_BOOLEAN, 8, NULL, SYS,
712         "Is this a system packet?", HFILL }},
713     { &hf_ncp_src_connection,
714       { "Source Connection ID",    "ncp.src_connection",
715         FT_UINT32, BASE_DEC, NULL, 0x0,
716         "The workstation's connection identification number", HFILL }},
717     { &hf_ncp_dst_connection,
718       { "Destination Connection ID",    "ncp.dst_connection",
719         FT_UINT32, BASE_DEC, NULL, 0x0,
720         "The server's connection identification number", HFILL }},
721     { &hf_ncp_packet_seqno,
722       { "Packet Sequence Number",    "ncp.packet_seqno",
723         FT_UINT32, BASE_DEC, NULL, 0x0,
724         "Sequence number of this packet in a burst", HFILL }},
725     { &hf_ncp_delay_time,
726       { "Delay Time",    "ncp.delay_time",      /* in 100 us increments */
727         FT_UINT32, BASE_DEC, NULL, 0x0,
728         "Delay time between consecutive packet sends (100 us increments)", HFILL }},
729     { &hf_ncp_burst_seqno,
730       { "Burst Sequence Number",    "ncp.burst_seqno",
731         FT_UINT16, BASE_DEC, NULL, 0x0,
732         "Sequence number of this packet in the burst", HFILL }},
733     { &hf_ncp_ack_seqno,
734       { "ACK Sequence Number",    "ncp.ack_seqno",
735         FT_UINT16, BASE_DEC, NULL, 0x0,
736         "Next expected burst sequence number", HFILL }},
737     { &hf_ncp_burst_len,
738       { "Burst Length",    "ncp.burst_len",
739         FT_UINT32, BASE_DEC, NULL, 0x0,
740         "Total length of data in this burst", HFILL }},
741     { &hf_ncp_data_offset,
742       { "Data Offset",    "ncp.data_offset",
743         FT_UINT32, BASE_DEC, NULL, 0x0,
744         "Offset of this packet in the burst", HFILL }},
745     { &hf_ncp_data_bytes,
746       { "Data Bytes",    "ncp.data_bytes",
747         FT_UINT16, BASE_DEC, NULL, 0x0,
748         "Number of data bytes in this packet", HFILL }},
749     { &hf_ncp_missing_fraglist_count,
750       { "Missing Fragment List Count",    "ncp.missing_fraglist_count",
751         FT_UINT16, BASE_DEC, NULL, 0x0,
752         "Number of missing fragments reported", HFILL }},
753     { &hf_ncp_missing_data_offset,
754       { "Missing Data Offset",    "ncp.missing_data_offset",
755         FT_UINT32, BASE_DEC, NULL, 0x0,
756         "Offset of beginning of missing data", HFILL }},
757     { &hf_ncp_missing_data_count,
758       { "Missing Data Count",    "ncp.missing_data_count",
759         FT_UINT16, BASE_DEC, NULL, 0x0,
760         "Number of bytes of missing data", HFILL }},
761     { &hf_ncp_completion_code,
762       { "Completion Code",    "ncp.completion_code",
763         FT_UINT8, BASE_DEC, NULL, 0x0,
764         "", HFILL }},
765     { &hf_ncp_connection_status,
766       { "Connection Status",    "ncp.connection_status",
767         FT_UINT8, BASE_DEC, NULL, 0x0,
768         "", HFILL }},
769     { &hf_ncp_slot,
770       { "Slot",    "ncp.slot",
771         FT_UINT8, BASE_DEC, NULL, 0x0,
772         "", HFILL }},
773     { &hf_ncp_control_code,
774       { "Control Code",    "ncp.control_code",
775         FT_UINT8, BASE_DEC, NULL, 0x0,
776         "", HFILL }},
777     { &hf_ncp_fragment_handle,
778       { "Fragment Handle",    "ncp.fragger_hndl",
779     FT_UINT16, BASE_HEX, NULL, 0x0,
780     "", HFILL }},
781     { &hf_lip_echo,
782       { "Large Internet Packet Echo",    "ncp.lip_echo",
783     FT_STRING, BASE_NONE, NULL, 0x0,
784     "", HFILL }},
785   
786   };
787   static gint *ett[] = {
788     &ett_ncp,
789     &ett_ncp_system_flags,
790     &ett_nds,
791         &ett_nds_segments,
792         &ett_nds_segment,
793   };
794   module_t *ncp_module;
795
796   proto_ncp = proto_register_protocol("NetWare Core Protocol", "NCP", "ncp");
797   proto_register_field_array(proto_ncp, hf, array_length(hf));
798   proto_register_subtree_array(ett, array_length(ett));
799
800   ncp_module = prefs_register_protocol(proto_ncp, NULL);
801   prefs_register_obsolete_preference(ncp_module, "initial_hash_size");
802   prefs_register_bool_preference(ncp_module, "desegment",
803     "Desegment all NCP-over-TCP messages spanning multiple segments",
804     "Whether the NCP dissector should desegment all messages spanning multiple TCP segments",
805     &ncp_desegment);
806   prefs_register_bool_preference(ncp_module, "defragment_nds",
807     "Defragment all NDS messages spanning multiple packets",
808     "Whether the NCP dissector should defragment all NDS messages spanning multiple packets",
809     &nds_defragment);
810 }
811
812 void
813 proto_reg_handoff_ncp(void)
814 {
815   dissector_handle_t ncp_handle;
816   dissector_handle_t ncp_tcp_handle;
817
818   ncp_handle = create_dissector_handle(dissect_ncp, proto_ncp);
819   ncp_tcp_handle = create_dissector_handle(dissect_ncp_tcp, proto_ncp);
820   dissector_add("tcp.port", TCP_PORT_NCP, ncp_tcp_handle);
821   dissector_add("udp.port", UDP_PORT_NCP, ncp_handle);
822   dissector_add("ipx.packet_type", IPX_PACKET_TYPE_NCP, ncp_handle);
823   dissector_add("ipx.socket", IPX_SOCKET_NCP, ncp_handle);
824
825   data_handle = find_dissector("data");
826 }
827
828