epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-ncp.c
blob5ab3c81a94073ccad9438d8d072b76ab9da3b24f
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, packet signature,
6 * & NDS packets by Greg Morris <gmorris@novell.com>
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
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 2000 Gerald Combs
16 * SPDX-License-Identifier: GPL-2.0-or-later
19 /* XXX:
20 ToDo: Find and fix possible memory leak(s):
22 Example:
24 A 40M capture file with mostly NCP frames results
25 in a 400K-800K memory usage increase each time the file is reloaded.
27 (If the NCP dissection is disabled, there is minimal memory usage
28 increase each time the file is reloaded).
32 * On page 86 of
34 * https://www.novell.com/documentation/developer/smscomp/pdfdoc/sms_docs/sms_docs.pdf
36 * it says:
38 * The following table lists the wild cards options that can be used in
39 * the terminal path node.
41 * Value Option Description
42 * 0x2A ASTERISK Regular asterisk
43 * 0x3F QUESTION Regular question mark
44 * 0xAE SPERIOD Special Period-the most significant bit set
45 * 0xAA SASTERISK. Special Asterisk-the most significant bit set.
46 * 0xBF SQUESTION Special Question-with the most significant bit set.
48 * ASTERISK is '*', and QUESTION is '?'; the "special" versions correspond
49 * to the corresponding ASCII character, but with the upper bit set.
51 * They do not indicate what "special" means here. During the painful
52 * process at NetApp of reverse-engineering SMB server wildcard matching;
53 * it turned out that "traditional 8.3 name" matching and "long name"
54 * matching behave differently, and there were separate code points for
55 * "traditional 8.3 name" wildcards and period and "long name" wildcards
56 * and period, so that might be what's involved here.
58 * How should we display them? Show the character in question plus a
59 * Unicode COMBINING OVERLINE (U+0305), so they show up as {period,
60 * asterisk, question mark} with an overline, for example?
62 #include "config.h"
64 #include <epan/packet.h>
65 #include <epan/prefs.h>
66 #include <epan/srt_table.h>
67 #include "packet-ipx.h"
68 #include "packet-tcp.h"
69 #include "packet-ncp-int.h"
70 #include <epan/conversation_table.h>
72 void proto_register_ncp(void);
73 void proto_reg_handoff_ncp(void);
75 static dissector_handle_t ncp_handle;
76 static dissector_handle_t ncp_tcp_handle;
78 int proto_ncp;
79 static int hf_ncp_ip_ver;
80 static int hf_ncp_ip_length;
81 static int hf_ncp_ip_rplybufsize;
82 static int hf_ncp_ip_sig;
83 static int hf_ncp_ip_packetsig;
84 static int hf_ncp_type;
85 static int hf_ncp_seq;
86 static int hf_ncp_connection;
87 static int hf_ncp_task;
88 static int hf_ncp_stream_type;
89 static int hf_ncp_system_flags;
90 static int hf_ncp_system_flags_abt;
91 static int hf_ncp_system_flags_eob;
92 static int hf_ncp_system_flags_sys;
93 static int hf_ncp_system_flags_bsy;
94 static int hf_ncp_system_flags_lst;
95 static int hf_ncp_src_connection;
96 static int hf_ncp_dst_connection;
97 static int hf_ncp_packet_seqno;
98 static int hf_ncp_delay_time;
99 static int hf_ncp_burst_seqno;
100 static int hf_ncp_ack_seqno;
101 static int hf_ncp_burst_len;
102 static int hf_ncp_burst_offset;
103 static int hf_ncp_data_offset;
104 static int hf_ncp_data_bytes;
105 static int hf_ncp_missing_fraglist_count;
106 static int hf_ncp_missing_data_offset;
107 static int hf_ncp_missing_data_count;
108 static int hf_ncp_oplock_flag;
109 static int hf_ncp_oplock_handle;
110 static int hf_ncp_completion_code;
111 static int hf_ncp_connection_status;
112 static int hf_ncp_slot;
113 static int hf_ncp_signature_character;
114 /* static int hf_ncp_fragment_handle; */
115 static int hf_lip_echo_magic;
116 static int hf_lip_echo_payload;
117 static int hf_ncp_burst_command;
118 static int hf_ncp_burst_file_handle;
119 static int hf_ncp_burst_reserved;
121 int ett_ncp;
122 int ett_nds;
123 int ett_nds_segments;
124 int ett_nds_segment;
125 static int ett_ncp_system_flags;
127 static expert_field ei_ncp_oplock_handle;
128 static expert_field ei_ncp_new_server_session;
129 static expert_field ei_ncp_type;
131 static struct novell_tap ncp_tap;
132 static struct ncp_common_header header;
133 static struct ncp_common_header *ncp_hdr;
135 dissector_handle_t nds_data_handle;
137 /* desegmentation of NCP over TCP */
138 static bool ncp_desegment = true;
140 #define TCP_PORT_NCP 524
141 #define UDP_PORT_NCP 524
143 #define NCP_RQST_HDR_LENGTH 7
144 #define NCP_RPLY_HDR_LENGTH 8
146 /* These are the header structures to handle NCP over IP */
147 #define NCPIP_RQST 0x446d6454 /* "DmdT" */
148 #define NCPIP_RPLY 0x744e6350 /* "tNcP" */
150 struct ncp_ip_header {
151 uint32_t signature;
152 uint32_t length;
155 /* This header only appears on NCP over IP request packets */
156 struct ncp_ip_rqhdr {
157 uint32_t version;
158 uint32_t rplybufsize;
161 static const value_string ncp_sigchar_vals[] = {
162 { '?', "Poll inactive station" },
163 { 'Y', "Station is still using the connection" },
164 { '!', "Broadcast message waiting" },
165 { 0, NULL }
168 static const value_string ncp_ip_signature[] = {
169 { NCPIP_RQST, "Demand Transport (Request)" },
170 { NCPIP_RPLY, "Transport is NCP (Reply)" },
171 { 0, NULL }
174 static const value_string burst_command[] = {
175 { 0x01000000, "Burst Read" },
176 { 0x02000000, "Burst Write" },
177 { 0, NULL }
180 /* The information in this module comes from:
181 NetWare LAN Analysis, Second Edition
182 Laura A. Chappell and Dan E. Hakes
183 (c) 1994 Novell, Inc.
184 Novell Press, San Jose.
185 ISBN: 0-7821-1362-1
187 And from the ncpfs source code by Volker Lendecke
189 And:
190 Programmer's Guide to the NetWare Core Protocol
191 Steve Conner & Diane Conner
192 (c) 1996 by Steve Conner & Diane Conner
193 Published by Annabooks, San Diego, California
194 ISBN: 0-929392-31-0
196 And:
198 https://www.novell.com/developer/ndk/netware_core_protocols.html
200 NCP documentation
202 (formerly http:developer.novell.com)
206 static const value_string ncp_type_vals[] = {
207 { NCP_ALLOCATE_SLOT, "Create a service connection" },
208 { NCP_SERVICE_REQUEST, "Service request" },
209 { NCP_SERVICE_REPLY, "Service reply" },
210 { NCP_WATCHDOG, "Watchdog" },
211 { NCP_DEALLOCATE_SLOT, "Destroy service connection" },
212 { NCP_BROADCAST_SLOT, "Server Broadcast" },
213 { NCP_BURST_MODE_XFER, "Burst mode transfer" },
214 { NCP_POSITIVE_ACK, "Request being processed" },
215 { NCP_LIP_ECHO, "Large Internet Packet Echo" },
216 { 0, NULL }
219 static const value_string ncp_oplock_vals[] = {
220 { 0x21, "Message Waiting" },
221 { 0x24, "Clear Op-lock" },
222 { 0, NULL }
225 enum ncp_table_values
227 NCP_NCP_SRT_TABLE_INDEX = 0,
228 NCP_NDS_SRT_TABLE_INDEX,
229 NCP_FUNC_SRT_TABLE_INDEX,
230 NCP_SSS_SRT_TABLE_INDEX,
231 NCP_NMAS_SRT_TABLE_INDEX,
232 NCP_SUB17_SRT_TABLE_INDEX,
233 NCP_SUB21_SRT_TABLE_INDEX,
234 NCP_SUB22_SRT_TABLE_INDEX,
235 NCP_SUB23_SRT_TABLE_INDEX,
236 NCP_SUB32_SRT_TABLE_INDEX,
237 NCP_SUB34_SRT_TABLE_INDEX,
238 NCP_SUB35_SRT_TABLE_INDEX,
239 NCP_SUB36_SRT_TABLE_INDEX,
240 NCP_SUB86_SRT_TABLE_INDEX,
241 NCP_SUB87_SRT_TABLE_INDEX,
242 NCP_SUB89_SRT_TABLE_INDEX,
243 NCP_SUB90_SRT_TABLE_INDEX,
244 NCP_SUB92_SRT_TABLE_INDEX,
245 NCP_SUB94_SRT_TABLE_INDEX,
246 NCP_SUB104_SRT_TABLE_INDEX,
247 NCP_SUB111_SRT_TABLE_INDEX,
248 NCP_SUB114_SRT_TABLE_INDEX,
249 NCP_SUB123_SRT_TABLE_INDEX,
250 NCP_SUB131_SRT_TABLE_INDEX
254 #define NCP_NUM_PROCEDURES 0
256 static const value_string ncp_group_vals[] = {
257 { 0, "Synchronization" },
258 { 1, "Print" },
259 { 2, "File System" },
260 { 3, "Connection" },
261 { 4, "File Server Environment" },
262 { 5, "Message" },
263 { 6, "Bindery" },
264 { 7, "Queue Management System (QMS)" },
265 { 8, "Accounting" },
266 { 9, "Transaction Tracking" },
267 { 10, "AFP" },
268 { 11, "NCP Extension" },
269 { 12, "Extended Attribute" },
270 { 13, "Auditing" },
271 { 14, "Enhanced File System" },
272 { 15, "Migration" },
273 { 16, "Novell Modular Authentication Services (NMAS)" },
274 { 17, "Secret Store Services (SSS)" },
275 { 18, "Packet Burst" },
276 { 19, "Novell Directory Services (NDS)" },
277 { 20, "Time Synchronization" },
278 { 21, "Server Statistics" },
279 { 22, "Remote" },
280 { 0, NULL}
283 WS_DLL_PUBLIC_DEF const value_string sss_verb_enum[] = {
284 { 0x00000000, "Query Server" },
285 { 0x00000001, "Read App Secrets" },
286 { 0x00000002, "Write App Secrets" },
287 { 0x00000003, "Add Secret ID" },
288 { 0x00000004, "Remove Secret ID" },
289 { 0x00000005, "Remove SecretStore" },
290 { 0x00000006, "Enumerate Secret IDs" },
291 { 0x00000007, "Unlock Store" },
292 { 0x00000008, "Set Master Password" },
293 { 0x00000009, "Get Service Information" },
294 { 0x000000ff, "Fragment"},
295 { 0x00000000, NULL}
298 WS_DLL_PUBLIC_DEF const value_string nmas_subverb_enum[] = {
299 { 0, "Fragmented Ping" },
300 { 2, "Client Put Data" },
301 { 4, "Client Get Data" },
302 { 6, "Client Get User NDS Credentials" },
303 { 8, "Login Store Management" },
304 { 10, "Writable Object Check" },
305 { 1242, "Message Handler" },
306 { 0, NULL}
309 WS_DLL_PUBLIC_DEF const value_string ncp_nds_verb_vals[] = {
310 { 1, "Resolve Name" },
311 { 2, "Read Entry Information" },
312 { 3, "Read" },
313 { 4, "Compare" },
314 { 5, "List" },
315 { 6, "Search Entries" },
316 { 7, "Add Entry" },
317 { 8, "Remove Entry" },
318 { 9, "Modify Entry" },
319 { 10, "Modify RDN" },
320 { 11, "Create Attribute" },
321 { 12, "Read Attribute Definition" },
322 { 13, "Remove Attribute Definition" },
323 { 14, "Define Class" },
324 { 15, "Read Class Definition" },
325 { 16, "Modify Class Definition" },
326 { 17, "Remove Class Definition" },
327 { 18, "List Containable Classes" },
328 { 19, "Get Effective Rights" },
329 { 20, "Add Partition" },
330 { 21, "Remove Partition" },
331 { 22, "List Partitions" },
332 { 23, "Split Partition" },
333 { 24, "Join Partitions" },
334 { 25, "Add Replica" },
335 { 26, "Remove Replica" },
336 { 27, "Open Stream" },
337 { 28, "Search Filter" },
338 { 29, "Create Subordinate Reference" },
339 { 30, "Link Replica" },
340 { 31, "Change Replica Type" },
341 { 32, "Start Update Schema" },
342 { 33, "End Update Schema" },
343 { 34, "Update Schema" },
344 { 35, "Start Update Replica" },
345 { 36, "End Update Replica" },
346 { 37, "Update Replica" },
347 { 38, "Synchronize Partition" },
348 { 39, "Synchronize Schema" },
349 { 40, "Read Syntaxes" },
350 { 41, "Get Replica Root ID" },
351 { 42, "Begin Move Entry" },
352 { 43, "Finish Move Entry" },
353 { 44, "Release Moved Entry" },
354 { 45, "Backup Entry" },
355 { 46, "Restore Entry" },
356 { 47, "Save DIB (Obsolete)" },
357 { 48, "Control" },
358 { 49, "Remove Backlink" },
359 { 50, "Close Iteration" },
360 { 51, "Mutate Entry" },
361 { 52, "Audit Skulking" },
362 { 53, "Get Server Address" },
363 { 54, "Set Keys" },
364 { 55, "Change Password" },
365 { 56, "Verify Password" },
366 { 57, "Begin Login" },
367 { 58, "Finish Login" },
368 { 59, "Begin Authentication" },
369 { 60, "Finish Authentication" },
370 { 61, "Logout" },
371 { 62, "Repair Ring (Obsolete)" },
372 { 63, "Repair Timestamps" },
373 { 64, "Create Back Link" },
374 { 65, "Delete External Reference" },
375 { 66, "Rename External Reference" },
376 { 67, "Create Queue Entry Directory" },
377 { 68, "Remove Queue Entry Directory" },
378 { 69, "Merge Entries" },
379 { 70, "Change Tree Name" },
380 { 71, "Partition Entry Count" },
381 { 72, "Check Login Restrictions" },
382 { 73, "Start Join" },
383 { 74, "Low Level Split" },
384 { 75, "Low Level Join" },
385 { 76, "Abort Partition Operation" },
386 { 77, "Get All Servers" },
387 { 78, "Partition Function" },
388 { 79, "Read References" },
389 { 80, "Inspect Entry" },
390 { 81, "Get Remote Entry ID" },
391 { 82, "Change Security" },
392 { 83, "Check Console Operator" },
393 { 84, "Start Move Tree" },
394 { 85, "Move Tree" },
395 { 86, "End Move Tree" },
396 { 87, "Low Level Abort Join" },
397 { 88, "Check Security Equivalence" },
398 { 89, "Merge Tree" },
399 { 90, "Sync External Reference" },
400 { 91, "Resend Entry" },
401 { 92, "New Schema Epoch" },
402 { 93, "Statistics" },
403 { 94, "Ping" },
404 { 95, "Get Bindery Contexts" },
405 { 96, "Monitor Connection" },
406 { 97, "Get DS Statistics" },
407 { 98, "Reset DS Counters" },
408 { 99, "Console" },
409 { 100, "Read Stream" },
410 { 101, "Write Stream" },
411 { 102, "Create Orphan Partition" },
412 { 103, "Remove Orphan Partition" },
413 { 104, "Link Orphan Partition" },
414 { 105, "Set Distributed Reference Link (DRL)" },
415 { 106, "Available" },
416 { 107, "Available" },
417 { 108, "Verify Distributed Reference Link (DRL)" },
418 { 109, "Verify Partition" },
419 { 110, "Iterator" },
420 { 111, "Available" },
421 { 112, "Close Stream" },
422 { 113, "Available" },
423 { 114, "Read Status" },
424 { 115, "Partition Sync Status" },
425 { 116, "Read Reference Data" },
426 { 117, "Write Reference Data" },
427 { 118, "Resource Event" },
428 { 119, "DIB Request (obsolete)" },
429 { 120, "Set Replication Filter" },
430 { 121, "Get Replication Filter" },
431 { 122, "Change Attribute Definition" },
432 { 123, "Schema in Use" },
433 { 124, "Remove Keys" },
434 { 125, "Clone" },
435 { 126, "Multiple Operations Transaction" },
436 { 240, "Ping" },
437 { 255, "EDirectory Call" },
438 { 0, NULL }
441 static void
442 ncpstat_init(struct register_srt* srt _U_, GArray* srt_array)
444 /* Initialize all of the SRT tables with 0 rows. That way we can "filter" the drawing
445 function to only output tables with rows > 0 */
447 init_srt_table("NCP", "Groups", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.group", NULL);
449 /* NDS Verbs */
450 init_srt_table("NDS Verbs", "NDS", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.ndsverb", NULL);
452 /* NCP Functions */
453 init_srt_table("NCP Functions without Subfunctions", "Functions", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func", NULL);
455 /* Secret Store Verbs */
456 init_srt_table("Secret Store Verbs", "SSS", srt_array, NCP_NUM_PROCEDURES, NULL, "sss.subverb", NULL);
458 /* NMAS Verbs */
459 init_srt_table("NMAS Verbs", "NMAS", srt_array, NCP_NUM_PROCEDURES, NULL, "nmas.subverb", NULL);
461 /* NCP Subfunctions */
462 init_srt_table("Subfunctions for NCP 17", "17", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==17 && ncp.subfunc", NULL);
463 init_srt_table("Subfunctions for NCP 21", "21", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==21 && ncp.subfunc", NULL);
464 init_srt_table("Subfunctions for NCP 22", "22", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==22 && ncp.subfunc", NULL);
465 init_srt_table("Subfunctions for NCP 23", "23", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==23 && ncp.subfunc", NULL);
466 init_srt_table("Subfunctions for NCP 32", "32", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==32 && ncp.subfunc", NULL);
467 init_srt_table("Subfunctions for NCP 34", "34", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==34 && ncp.subfunc", NULL);
468 init_srt_table("Subfunctions for NCP 35", "35", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==35 && ncp.subfunc", NULL);
469 init_srt_table("Subfunctions for NCP 36", "36", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==36 && ncp.subfunc", NULL);
470 init_srt_table("Subfunctions for NCP 86", "86", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==86 && ncp.subfunc", NULL);
471 init_srt_table("Subfunctions for NCP 87", "87", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==87 && ncp.subfunc", NULL);
472 init_srt_table("Subfunctions for NCP 89 (Extended NCP's with UTF8 Support)", "89", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==89 && ncp.subfunc", NULL);
473 init_srt_table("Subfunctions for NCP 90", "90", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==90 && ncp.subfunc", NULL);
474 init_srt_table("Subfunctions for NCP 92 (Secret Store Services)", "92", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==92 && ncp.subfunc", NULL);
475 init_srt_table("Subfunctions for NCP 94 (Novell Modular Authentication Services)", "94", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==94 && ncp.subfunc", NULL);
476 init_srt_table("Subfunctions for NCP 104", "104", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==104 && ncp.subfunc", NULL);
477 init_srt_table("Subfunctions for NCP 111", "111", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==111 && ncp.subfunc", NULL);
478 init_srt_table("Subfunctions for NCP 114", "114", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==114 && ncp.subfunc", NULL);
479 init_srt_table("Subfunctions for NCP 123", "123", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==123 && ncp.subfunc", NULL);
480 init_srt_table("Subfunctions for NCP 131", "131", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==131 && ncp.subfunc", NULL);
483 static tap_packet_status
484 ncpstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv, tap_flags_t flags _U_)
486 unsigned i = 0;
487 srt_stat_table *ncp_srt_table;
488 srt_data_t *data = (srt_data_t *)pss;
489 const ncp_req_hash_value *request_val=(const ncp_req_hash_value *)prv;
490 char* tmp_str;
492 /* if we haven't seen the request, just ignore it */
493 if(!request_val || request_val->ncp_rec==0){
494 return TAP_PACKET_DONT_REDRAW;
497 /* By Group */
498 tmp_str = val_to_str_wmem(NULL, request_val->ncp_rec->group, ncp_group_vals, "Unknown(%u)");
499 i = NCP_NCP_SRT_TABLE_INDEX;
500 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
501 init_srt_table_row(ncp_srt_table, request_val->ncp_rec->group, tmp_str);
502 wmem_free(NULL, tmp_str);
503 add_srt_table_data(ncp_srt_table, request_val->ncp_rec->group, &request_val->req_frame_time, pinfo);
504 /* By NCP number without subfunction*/
505 if (request_val->ncp_rec->subfunc==0) {
506 i = NCP_FUNC_SRT_TABLE_INDEX;
507 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
508 init_srt_table_row(ncp_srt_table, request_val->ncp_rec->func, request_val->ncp_rec->name);
509 add_srt_table_data(ncp_srt_table, request_val->ncp_rec->func, &request_val->req_frame_time, pinfo);
511 /* By Subfunction number */
512 if(request_val->ncp_rec->subfunc!=0){
513 if (request_val->ncp_rec->func==17) {
514 i = NCP_SUB17_SRT_TABLE_INDEX;
515 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
516 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
517 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
519 if (request_val->ncp_rec->func==21) {
520 i = NCP_SUB21_SRT_TABLE_INDEX;
521 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
522 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
523 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
525 if (request_val->ncp_rec->func==22) {
526 i = NCP_SUB22_SRT_TABLE_INDEX;
527 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
528 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
529 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
531 if (request_val->ncp_rec->func==23) {
532 i = NCP_SUB23_SRT_TABLE_INDEX;
533 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
534 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
535 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
537 if (request_val->ncp_rec->func==32) {
538 i = NCP_SUB32_SRT_TABLE_INDEX;
539 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
540 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
541 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
543 if (request_val->ncp_rec->func==34) {
544 i = NCP_SUB34_SRT_TABLE_INDEX;
545 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
546 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
547 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
549 if (request_val->ncp_rec->func==35) {
550 i = NCP_SUB35_SRT_TABLE_INDEX;
551 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
552 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
553 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
555 if (request_val->ncp_rec->func==36) {
556 i = NCP_SUB36_SRT_TABLE_INDEX;
557 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
558 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
559 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
561 if (request_val->ncp_rec->func==86) {
562 i = NCP_SUB86_SRT_TABLE_INDEX;
563 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
564 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
565 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
567 if (request_val->ncp_rec->func==87) {
568 i = NCP_SUB87_SRT_TABLE_INDEX;
569 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
570 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
571 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
573 if (request_val->ncp_rec->func==89) {
574 i = NCP_SUB89_SRT_TABLE_INDEX;
575 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
576 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
577 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
579 if (request_val->ncp_rec->func==90) {
580 i = NCP_SUB90_SRT_TABLE_INDEX;
581 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
582 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
583 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
585 if (request_val->ncp_rec->func==92) {
586 i = NCP_SUB92_SRT_TABLE_INDEX;
587 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
588 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
589 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
591 if (request_val->ncp_rec->func==94) {
592 i = NCP_SUB94_SRT_TABLE_INDEX;
593 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
594 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
595 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
597 if (request_val->ncp_rec->func==104) {
598 i = NCP_SUB104_SRT_TABLE_INDEX;
599 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
600 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
601 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
603 if (request_val->ncp_rec->func==111) {
604 i = NCP_SUB111_SRT_TABLE_INDEX;
605 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
606 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
607 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
609 if (request_val->ncp_rec->func==114) {
610 i = NCP_SUB114_SRT_TABLE_INDEX;
611 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
612 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
613 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
615 if (request_val->ncp_rec->func==123) {
616 i = NCP_SUB123_SRT_TABLE_INDEX;
617 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
618 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
619 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
621 if (request_val->ncp_rec->func==131) {
622 i = NCP_SUB131_SRT_TABLE_INDEX;
623 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
624 init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
625 add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
628 /* By NDS verb */
629 if (request_val->ncp_rec->func==0x68) {
630 tmp_str = val_to_str_wmem(NULL, request_val->nds_request_verb, ncp_nds_verb_vals, "Unknown(%u)");
631 i = NCP_NDS_SRT_TABLE_INDEX;
632 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
633 init_srt_table_row(ncp_srt_table, (request_val->nds_request_verb), tmp_str);
634 add_srt_table_data(ncp_srt_table, (request_val->nds_request_verb), &request_val->req_frame_time, pinfo);
635 wmem_free(NULL, tmp_str);
637 if (request_val->ncp_rec->func==0x5c) {
638 tmp_str = val_to_str_wmem(NULL, request_val->req_nds_flags, sss_verb_enum, "Unknown(%u)");
639 i = NCP_SSS_SRT_TABLE_INDEX;
640 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
641 init_srt_table_row(ncp_srt_table, (request_val->req_nds_flags), tmp_str);
642 add_srt_table_data(ncp_srt_table, (request_val->req_nds_flags), &request_val->req_frame_time, pinfo);
643 wmem_free(NULL, tmp_str);
645 if (request_val->ncp_rec->func==0x5e) {
646 tmp_str = val_to_str_wmem(NULL, request_val->req_nds_flags, nmas_subverb_enum, "Unknown(%u)");
647 i = NCP_NMAS_SRT_TABLE_INDEX;
648 ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
649 init_srt_table_row(ncp_srt_table, (request_val->req_nds_flags), tmp_str);
650 add_srt_table_data(ncp_srt_table, (request_val->req_nds_flags), &request_val->req_frame_time, pinfo);
651 wmem_free(NULL, tmp_str);
653 return TAP_PACKET_REDRAW;
657 /* Conversation Struct so we can detect NCP server sessions */
659 typedef struct {
660 conversation_t *conversation;
661 uint32_t nwconnection;
662 uint8_t nwtask;
663 } mncp_rhash_key;
665 /* Store the packet number for the start of the NCP session.
666 * Note sessions are defined as
667 * NCP Connection + NCP Task == Unique NCP server session
668 * It is normal for multiple sessions per connection to exist
669 * These are normally different applications running on multi-tasking
670 * Operating Systems.
672 typedef struct {
673 uint32_t session_start_packet_num;
674 } mncp_rhash_value;
676 static GHashTable *mncp_rhash;
678 /* Hash Functions */
679 static int
680 mncp_equal(const void *v, const void *v2)
682 const mncp_rhash_key *val1 = (const mncp_rhash_key*)v;
683 const mncp_rhash_key *val2 = (const mncp_rhash_key*)v2;
685 if (val1->conversation == val2->conversation && val1->nwconnection == val2->nwconnection && val1->nwtask == val2->nwtask) {
686 return 1;
688 return 0;
691 static unsigned
692 mncp_hash(const void *v)
694 const mncp_rhash_key *mncp_key = (const mncp_rhash_key*)v;
695 return GPOINTER_TO_UINT(mncp_key->conversation)+mncp_key->nwconnection+mncp_key->nwtask;
698 /* Initializes the hash table each time a new
699 * file is loaded or re-loaded in wireshark */
700 static void
701 mncp_init_protocol(void)
703 mncp_rhash = g_hash_table_new(mncp_hash, mncp_equal);
706 static void
707 mncp_cleanup_protocol(void)
709 g_hash_table_destroy(mncp_rhash);
712 static mncp_rhash_value*
713 mncp_hash_insert(conversation_t *conversation, uint32_t nwconnection, uint8_t nwtask, packet_info *pinfo)
715 mncp_rhash_key *key;
716 mncp_rhash_value *value;
718 /* Now remember the request, so we can find it if we later
719 a reply to it. Track by conversation, connection, and task number.
720 in NetWare these values determine each unique session */
721 key = wmem_new(wmem_file_scope(), mncp_rhash_key);
722 key->conversation = conversation;
723 key->nwconnection = nwconnection;
724 key->nwtask = nwtask;
726 value = wmem_new(wmem_file_scope(), mncp_rhash_value);
728 g_hash_table_insert(mncp_rhash, key, value);
730 if (ncp_echo_conn && nwconnection != 65535) {
731 expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nwconnection, nwtask);
732 value->session_start_packet_num = pinfo->num;
735 return value;
738 /* Returns the ncp_rec*, or NULL if not found. */
739 static mncp_rhash_value*
740 mncp_hash_lookup(conversation_t *conversation, uint32_t nwconnection, uint8_t nwtask)
742 mncp_rhash_key key;
744 key.conversation = conversation;
745 key.nwconnection = nwconnection;
746 key.nwtask = nwtask;
748 return (mncp_rhash_value *)g_hash_table_lookup(mncp_rhash, &key);
751 static const char* ncp_conv_get_filter_type(conv_item_t* conv _U_, conv_filter_type_e filter)
753 if ((filter == CONV_FT_SRC_PORT) || (filter == CONV_FT_DST_PORT) || (filter == CONV_FT_ANY_PORT))
754 return "ncp.connection";
756 return CONV_FILTER_INVALID;
759 static ct_dissector_info_t ncp_ct_dissector_info = {&ncp_conv_get_filter_type};
761 static tap_packet_status
762 ncp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
764 conv_hash_t *hash = (conv_hash_t*) pct;
765 hash->flags = flags;
767 const struct ncp_common_header *ncph=(const struct ncp_common_header *)vip;
768 uint32_t connection;
770 connection = (ncph->conn_high * 256)+ncph->conn_low;
771 if (connection < 65535) {
772 add_conversation_table_data(hash, &pinfo->src, &pinfo->dst, connection, connection, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &ncp_ct_dissector_info, CONVERSATION_NCP);
775 return TAP_PACKET_REDRAW;
778 static const char* ncp_endpoint_get_filter_type(endpoint_item_t* endpoint _U_, conv_filter_type_e filter)
780 return ncp_conv_get_filter_type(NULL, filter);
783 static et_dissector_info_t ncp_endpoint_dissector_info = {&ncp_endpoint_get_filter_type};
785 static tap_packet_status
786 ncp_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip _U_, tap_flags_t flags)
788 conv_hash_t *hash = (conv_hash_t*) pit;
789 hash->flags = flags;
791 /*const ncp_common_header *ncphdr=vip;*/
793 /* Take two "add" passes per packet, adding for each direction, ensures that all
794 packets are counted properly (even if address is sending to itself)
795 XXX - this could probably be done more efficiently inside endpoint_table */
796 add_endpoint_table_data(hash, &pinfo->src, 0, true, 1, pinfo->fd->pkt_len, &ncp_endpoint_dissector_info, ENDPOINT_NCP);
797 add_endpoint_table_data(hash, &pinfo->dst, 0, false, 1, pinfo->fd->pkt_len, &ncp_endpoint_dissector_info, ENDPOINT_NCP);
799 return TAP_PACKET_REDRAW;
803 * Burst packet system flags.
805 #define ABT 0x04 /* Abort request */
806 #define BSY 0x08 /* Server Busy */
807 #define EOB 0x10 /* End of burst */
808 #define LST 0x40 /* Include Fragment List */
809 #define SYS 0x80 /* System packet */
811 #define LIP_ECHO_MAGIC_LEN 16
812 static const unsigned char lip_echo_magic[LIP_ECHO_MAGIC_LEN] = {
813 'L', 'I', 'P', ' ', 'E', 'c', 'h', 'o', ' ', 'D', 'a', 't', 'a', ' ', ' ', ' '
816 static void
817 dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
818 bool is_tcp)
820 proto_tree *ncp_tree = NULL;
821 proto_item *ti;
822 struct ncp_ip_header ncpiph;
823 struct ncp_ip_rqhdr ncpiphrq;
824 bool is_lip_echo_allocate_slot = false;
825 uint16_t ncp_burst_seqno, ncp_ack_seqno;
826 uint16_t flags = 0;
827 proto_tree *flags_tree = NULL;
828 int hdr_offset = 0;
829 int commhdr = 0;
830 int offset = 0;
831 int length_remaining;
832 tvbuff_t *next_tvb;
833 uint32_t ncp_burst_command, burst_len, burst_off, burst_file;
834 uint8_t subfunction;
835 uint32_t nw_connection = 0, data_offset;
836 uint16_t data_len = 0;
837 uint16_t missing_fraglist_count = 0;
838 mncp_rhash_value *request_value = NULL;
839 conversation_t *conversation;
841 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NCP");
842 col_clear(pinfo->cinfo, COL_INFO);
844 ncp_hdr = &header;
846 ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, ENC_NA);
847 ncp_tree = proto_item_add_subtree(ti, ett_ncp);
848 if (is_tcp) {
849 if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY)
850 commhdr += 1;
851 /* Get NCPIP Header data */
852 ncpiph.signature = tvb_get_ntohl(tvb, commhdr);
853 proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, commhdr, 4, ncpiph.signature);
854 ncpiph.length = (0x7fffffff & tvb_get_ntohl(tvb, commhdr+4));
855 proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, commhdr+4, 4, ncpiph.length);
856 commhdr += 8;
857 if (ncpiph.signature == NCPIP_RQST) {
858 ncpiphrq.version = tvb_get_ntohl(tvb, commhdr);
859 proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, commhdr, 4, ncpiphrq.version);
860 commhdr += 4;
861 ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, commhdr);
862 proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, commhdr, 4, ncpiphrq.rplybufsize);
863 commhdr += 4;
865 /* Check to see if this is a valid offset, otherwise increment for packet signature */
866 if (try_val_to_str(tvb_get_ntohs(tvb, commhdr), ncp_type_vals)==NULL) {
867 /* Check to see if we have a valid type after packet signature length */
868 if (try_val_to_str(tvb_get_ntohs(tvb, commhdr+8), ncp_type_vals)!=NULL) {
869 proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, commhdr, 8, ENC_NA);
870 commhdr += 8;
873 } else {
874 /* Initialize this structure, we use it below */
875 memset(&ncpiph, 0, sizeof(ncpiph));
878 header.type = tvb_get_ntohs(tvb, commhdr);
879 header.sequence = tvb_get_uint8(tvb, commhdr+2);
880 header.conn_low = tvb_get_uint8(tvb, commhdr+3);
881 header.task = tvb_get_uint8(tvb, commhdr+4);
882 header.conn_high = tvb_get_uint8(tvb, commhdr+5);
883 proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr, 2, header.type);
884 nw_connection = (header.conn_high*256)+header.conn_low;
886 /* Ok, we need to track the conversation so that we can
887 * determine if a new server session is occurring for this
888 * connection.
890 conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
891 CONVERSATION_NCP, (uint32_t) pinfo->srcport, (uint32_t) pinfo->destport,
893 if ((ncpiph.length & 0x80000000) || ncpiph.signature == NCPIP_RPLY) {
894 /* First time through we will record the initial connection and task
895 * values
897 if (!pinfo->fd->visited) {
898 if (conversation != NULL) {
899 /* find the record telling us the
900 * request made that caused this
901 * reply
903 request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
904 /* if for some reason we have no
905 * conversation in our hash, create
906 * one */
907 if (request_value == NULL) {
908 mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
910 } else {
911 /* It's not part of any conversation
912 * - create a new one.
914 conversation = conversation_new(pinfo->num, &pinfo->src,
915 &pinfo->dst, CONVERSATION_NCP, (uint32_t) pinfo->srcport, (uint32_t) pinfo->destport, 0);
916 mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
918 /* If this is a request packet then we
919 * might have a new task
921 if (ncpiph.signature == NCPIP_RPLY) {
922 /* Now on reply packets we have to
923 * use the state of the original
924 * request packet, so look up the
925 * request value and check the task number
927 /*request_value = mncp_hash_lookup(conversation, nw_connection, header.task);*/
929 } else {
930 /* Get request value data */
931 request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
932 if (request_value) {
933 if ((request_value->session_start_packet_num == pinfo->num) && ncp_echo_conn) {
934 expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
938 } else {
939 if (!pinfo->fd->visited) {
940 if (conversation != NULL) {
941 /* find the record telling us the
942 * request made that caused this
943 * reply
945 request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
946 /* if for some reason we have no
947 * conversation in our hash, create
948 * one */
949 if (request_value == NULL) {
950 mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
952 } else {
953 /* It's not part of any conversation
954 * - create a new one.
956 conversation = conversation_new(pinfo->num, &pinfo->src,
957 &pinfo->dst, CONVERSATION_NCP, (uint32_t) pinfo->srcport, (uint32_t) pinfo->destport, 0);
958 mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
960 /* find the record telling us the request
961 * made that caused this reply
963 } else {
964 request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
965 if (request_value) {
966 if ((request_value->session_start_packet_num == pinfo->num) && ncp_echo_conn) {
967 expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
973 tap_queue_packet(ncp_tap.hdr, pinfo, ncp_hdr);
975 col_add_str(pinfo->cinfo, COL_INFO,
976 val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));
979 * Process the packet-type-specific header.
981 switch (header.type) {
983 case NCP_BROADCAST_SLOT: /* Server Broadcast */
984 proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
985 proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
986 proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN);
987 proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, ENC_BIG_ENDIAN);
988 proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, ENC_BIG_ENDIAN);
989 if ((tvb_get_uint8(tvb, commhdr+9)==0x24) && ncp_echo_file) {
990 expert_add_info_format(pinfo, NULL, &ei_ncp_oplock_handle, "Server requesting station to clear oplock on handle - %08x", tvb_get_ntohl(tvb, commhdr+10));
992 break;
994 case NCP_LIP_ECHO: /* Lip Echo Packet */
995 /* Unlike the ones with a packet type of 0x1111, in this one, the
996 packet type field is the first two bytes of "Lip Echo Data"
997 (with "Lip" not capitalized, and with "Echo Data" not followed
998 by blanks) */
999 proto_tree_add_item(ncp_tree, hf_lip_echo_magic, tvb, commhdr, 13, ENC_ASCII);
1000 break;
1002 case NCP_BURST_MODE_XFER: /* Packet Burst Packet */
1004 * XXX - we should keep track of whether there's a burst
1005 * outstanding on a connection and, if not, treat the
1006 * beginning of the data as a burst header.
1008 * The burst header contains:
1010 * 4 bytes of little-endian function number:
1011 * 1 = read, 2 = write;
1013 * 4 bytes of file handle;
1015 * 8 reserved bytes;
1017 * 4 bytes of big-endian file offset;
1019 * 4 bytes of big-endian byte count.
1021 * The data follows for a burst write operation.
1023 * The first packet of a burst read reply contains:
1025 * 4 bytes of little-endian result code:
1026 * 0: No error
1027 * 1: Initial error
1028 * 2: I/O error
1029 * 3: No data read;
1031 * 4 bytes of returned byte count (big-endian?).
1033 * The data follows.
1035 * Each burst of a write request is responded to with a
1036 * burst packet with a 2-byte little-endian result code:
1038 * 0: Write successful
1039 * 4: Write error
1041 flags = tvb_get_uint8(tvb, commhdr + 2);
1043 ti = proto_tree_add_uint(ncp_tree, hf_ncp_system_flags,
1044 tvb, commhdr + 2, 1, flags);
1045 flags_tree = proto_item_add_subtree(ti, ett_ncp_system_flags);
1047 proto_tree_add_item(flags_tree, hf_ncp_system_flags_abt,
1048 tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1049 if (flags & ABT) {
1050 proto_item_append_text(ti, " ABT");
1052 flags&=(~( ABT ));
1054 proto_tree_add_item(flags_tree, hf_ncp_system_flags_bsy,
1055 tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1056 if (flags & BSY) {
1057 proto_item_append_text(ti, " BSY");
1059 flags&=(~( BSY ));
1061 proto_tree_add_item(flags_tree, hf_ncp_system_flags_eob,
1062 tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1063 if (flags & EOB) {
1064 proto_item_append_text(ti, " EOB");
1066 flags&=(~( EOB ));
1068 proto_tree_add_item(flags_tree, hf_ncp_system_flags_lst,
1069 tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1070 if (flags & LST) {
1071 proto_item_append_text(ti, " LST");
1073 flags&=(~( LST ));
1075 proto_tree_add_item(flags_tree, hf_ncp_system_flags_sys,
1076 tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1077 if (flags & SYS) {
1078 proto_item_append_text(ti, " SYS");
1080 flags&=(~( SYS ));
1083 proto_tree_add_item(ncp_tree, hf_ncp_stream_type,
1084 tvb, commhdr + 3, 1, ENC_BIG_ENDIAN);
1085 proto_tree_add_item(ncp_tree, hf_ncp_src_connection,
1086 tvb, commhdr + 4, 4, ENC_BIG_ENDIAN);
1087 proto_tree_add_item(ncp_tree, hf_ncp_dst_connection,
1088 tvb, commhdr + 8, 4, ENC_BIG_ENDIAN);
1089 proto_tree_add_item(ncp_tree, hf_ncp_packet_seqno,
1090 tvb, commhdr + 12, 4, ENC_BIG_ENDIAN);
1091 proto_tree_add_item(ncp_tree, hf_ncp_delay_time,
1092 tvb, commhdr + 16, 4, ENC_BIG_ENDIAN);
1093 ncp_burst_seqno = tvb_get_ntohs(tvb, commhdr+20);
1094 proto_tree_add_item(ncp_tree, hf_ncp_burst_seqno,
1095 tvb, commhdr + 20, 2, ENC_BIG_ENDIAN);
1096 ncp_ack_seqno = tvb_get_ntohs(tvb, commhdr+22);
1097 proto_tree_add_item(ncp_tree, hf_ncp_ack_seqno,
1098 tvb, commhdr + 22, 2, ENC_BIG_ENDIAN);
1099 proto_tree_add_item(ncp_tree, hf_ncp_burst_len,
1100 tvb, commhdr + 24, 4, ENC_BIG_ENDIAN);
1101 data_offset = tvb_get_ntohl(tvb, commhdr + 28);
1102 proto_tree_add_uint(ncp_tree, hf_ncp_data_offset,
1103 tvb, commhdr + 28, 4, data_offset);
1104 data_len = tvb_get_ntohs(tvb, commhdr + 32);
1105 proto_tree_add_uint(ncp_tree, hf_ncp_data_bytes,
1106 tvb, commhdr + 32, 2, data_len);
1107 missing_fraglist_count = tvb_get_ntohs(tvb, commhdr + 34);
1108 proto_tree_add_item(ncp_tree, hf_ncp_missing_fraglist_count,
1109 tvb, commhdr + 34, 2, ENC_BIG_ENDIAN);
1110 offset = commhdr + 36;
1111 if (!(flags & SYS) && ncp_burst_seqno == ncp_ack_seqno &&
1112 data_offset == 0) {
1114 * This is either a Burst Read or Burst Write
1115 * command. The data length includes the burst
1116 * mode header, plus any data in the command
1117 * (there shouldn't be any in a read, but there
1118 * might be some in a write).
1120 if (data_len < 4)
1121 return;
1122 ncp_burst_command = tvb_get_ntohl(tvb, offset);
1123 proto_tree_add_item(ncp_tree, hf_ncp_burst_command,
1124 tvb, offset, 4, ENC_BIG_ENDIAN);
1125 offset += 4;
1126 data_len -= 4;
1128 if (data_len < 4)
1129 return;
1130 burst_file = tvb_get_ntohl(tvb, offset);
1131 proto_tree_add_item(ncp_tree, hf_ncp_burst_file_handle,
1132 tvb, offset, 4, ENC_BIG_ENDIAN);
1133 offset += 4;
1134 data_len -= 4;
1136 if (data_len < 8)
1137 return;
1138 proto_tree_add_item(ncp_tree, hf_ncp_burst_reserved,
1139 tvb, offset, 8, ENC_NA);
1140 offset += 8;
1141 data_len -= 8;
1143 if (data_len < 4)
1144 return;
1145 burst_off = tvb_get_ntohl(tvb, offset);
1146 proto_tree_add_uint(ncp_tree, hf_ncp_burst_offset,
1147 tvb, offset, 4, burst_off);
1148 offset += 4;
1149 data_len -= 4;
1151 if (data_len < 4)
1152 return;
1153 burst_len = tvb_get_ntohl(tvb, offset);
1154 proto_tree_add_uint(ncp_tree, hf_ncp_burst_len,
1155 tvb, offset, 4, burst_len);
1156 offset += 4;
1157 data_len -= 4;
1159 col_add_fstr(pinfo->cinfo, COL_INFO,
1160 "%s %d bytes starting at offset %d in file 0x%08x",
1161 val_to_str(ncp_burst_command,
1162 burst_command, "Unknown (0x%08x)"),
1163 burst_len, burst_off, burst_file);
1164 break;
1165 } else {
1166 if (tvb_get_uint8(tvb, commhdr + 2) & 0x10) {
1167 col_set_str(pinfo->cinfo, COL_INFO, "End of Burst");
1170 break;
1172 case NCP_ALLOCATE_SLOT: /* Allocate Slot Request */
1173 length_remaining = tvb_reported_length_remaining(tvb, commhdr + 4);
1174 if (length_remaining >= LIP_ECHO_MAGIC_LEN &&
1175 tvb_memeql(tvb, commhdr+4, lip_echo_magic, LIP_ECHO_MAGIC_LEN) == 0) {
1176 /* This is a LIP Echo. */
1177 is_lip_echo_allocate_slot = true;
1178 col_set_str(pinfo->cinfo, COL_INFO, "LIP Echo");
1180 /* fall through */
1182 case NCP_POSITIVE_ACK: /* Positive Acknowledgement */
1183 case NCP_SERVICE_REQUEST: /* Server NCP Request */
1184 case NCP_SERVICE_REPLY: /* Server NCP Reply */
1185 case NCP_WATCHDOG: /* Watchdog Packet */
1186 case NCP_DEALLOCATE_SLOT: /* Deallocate Slot Request */
1187 default:
1188 proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
1189 /* XXX - what's at commhdr + 3 in a LIP Echo packet?
1190 commhdr + 4 on is the LIP echo magic number and data. */
1191 if (!is_lip_echo_allocate_slot) {
1192 proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
1193 proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN);
1195 break;
1199 * Process the packet body.
1201 switch (header.type) {
1203 case NCP_ALLOCATE_SLOT: /* Allocate Slot Request */
1204 if (is_lip_echo_allocate_slot) {
1205 length_remaining = tvb_reported_length_remaining(tvb, commhdr + 4);
1206 proto_tree_add_item(ncp_tree, hf_lip_echo_magic, tvb, commhdr + 4, LIP_ECHO_MAGIC_LEN, ENC_ASCII);
1207 if (length_remaining > LIP_ECHO_MAGIC_LEN)
1208 proto_tree_add_item(ncp_tree, hf_lip_echo_payload, tvb, commhdr+4+LIP_ECHO_MAGIC_LEN, length_remaining - LIP_ECHO_MAGIC_LEN, ENC_NA);
1210 next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1211 dissect_ncp_request(next_tvb, pinfo, nw_connection,
1212 header.sequence, header.type, is_lip_echo_allocate_slot, ncp_tree);
1213 break;
1215 case NCP_DEALLOCATE_SLOT: /* Deallocate Slot Request */
1216 next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1217 dissect_ncp_request(next_tvb, pinfo, nw_connection,
1218 header.sequence, header.type, false, ncp_tree);
1219 break;
1221 case NCP_SERVICE_REQUEST: /* Server NCP Request */
1222 case NCP_BROADCAST_SLOT: /* Server Broadcast Packet */
1223 next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1224 if (tvb_get_uint8(tvb, commhdr+6) == 0x68) {
1225 subfunction = tvb_get_uint8(tvb, commhdr+7);
1226 switch (subfunction) {
1228 case 0x02: /* NDS Frag Packet to decode */
1229 dissect_nds_request(next_tvb, pinfo,
1230 nw_connection, header.sequence,
1231 header.type, ncp_tree);
1232 break;
1234 case 0x01: /* NDS Ping */
1235 dissect_ping_req(next_tvb, pinfo,
1236 nw_connection, header.sequence,
1237 header.type, ncp_tree);
1238 break;
1240 default:
1241 dissect_ncp_request(next_tvb, pinfo,
1242 nw_connection, header.sequence,
1243 header.type, false, ncp_tree);
1244 break;
1246 } else {
1247 dissect_ncp_request(next_tvb, pinfo, nw_connection,
1248 header.sequence, header.type, false, ncp_tree);
1250 break;
1252 case NCP_SERVICE_REPLY: /* Server NCP Reply */
1253 next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1254 nds_defrag(next_tvb, pinfo, nw_connection, header.sequence,
1255 header.type, ncp_tree, &ncp_tap);
1256 break;
1258 case NCP_POSITIVE_ACK: /* Positive Acknowledgement */
1260 * XXX - this used to call "nds_defrag()", which would
1261 * clear out "frags". Was that the right thing to
1262 * do?
1264 next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1265 dissect_ncp_reply(next_tvb, pinfo, nw_connection,
1266 header.sequence, header.type, ncp_tree, &ncp_tap);
1267 break;
1269 case NCP_WATCHDOG: /* Watchdog Packet */
1271 * XXX - should the completion code be interpreted as
1272 * it is in "packet-ncp2222.inc"? If so, this
1273 * packet should be handled by "dissect_ncp_reply()".
1275 proto_tree_add_item(ncp_tree, hf_ncp_completion_code,
1276 tvb, commhdr + 6, 1, ENC_LITTLE_ENDIAN);
1277 proto_tree_add_item(ncp_tree, hf_ncp_connection_status,
1278 tvb, commhdr + 7, 1, ENC_LITTLE_ENDIAN);
1279 proto_tree_add_item(ncp_tree, hf_ncp_slot,
1280 tvb, commhdr + 8, 1, ENC_LITTLE_ENDIAN);
1281 proto_tree_add_item(ncp_tree, hf_ncp_signature_character,
1282 tvb, commhdr + 9, 1, ENC_LITTLE_ENDIAN);
1284 * Display the rest of the packet as data.
1286 if (tvb_offset_exists(tvb, commhdr + 10)) {
1287 call_data_dissector(tvb_new_subset_remaining(tvb, commhdr + 10),
1288 pinfo, ncp_tree);
1290 break;
1292 case NCP_BURST_MODE_XFER: /* Packet Burst Packet */
1293 if (flags & SYS) {
1295 * System packet; show missing fragments if there
1296 * are any.
1298 while (missing_fraglist_count != 0) {
1299 proto_tree_add_item(ncp_tree, hf_ncp_missing_data_offset,
1300 tvb, offset, 4, ENC_BIG_ENDIAN);
1301 offset += 4;
1302 proto_tree_add_item(ncp_tree, hf_ncp_missing_data_count,
1303 tvb, offset, 2, ENC_BIG_ENDIAN);
1304 offset += 2;
1305 missing_fraglist_count--;
1307 } else {
1309 * XXX - do this by using -1 and -1 as the length
1310 * arguments to "tvb_new_subset_length_caplen()" and then calling
1311 * "tvb_set_reported_length()"? That'll throw an
1312 * exception if "data_len" goes past the reported
1313 * length of the packet, but that's arguably a
1314 * feature in this case.
1316 length_remaining = tvb_captured_length_remaining(tvb, offset);
1317 if (length_remaining > data_len)
1318 length_remaining = data_len;
1319 if (data_len != 0) {
1320 call_data_dissector(tvb_new_subset_length_caplen(tvb, offset,
1321 length_remaining, data_len),
1322 pinfo, ncp_tree);
1325 break;
1327 case NCP_LIP_ECHO: /* LIP Echo Packet */
1328 proto_tree_add_item(ncp_tree, hf_lip_echo_payload, tvb, commhdr + 13, -1, ENC_NA);
1329 break;
1331 default:
1332 proto_tree_add_expert_format(ncp_tree, pinfo, &ei_ncp_type, tvb, commhdr + 6, -1,
1333 "%s packets not supported yet",
1334 val_to_str(header.type, ncp_type_vals,
1335 "Unknown type (0x%04x)"));
1336 break;
1340 static int
1341 dissect_ncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1343 dissect_ncp_common(tvb, pinfo, tree, false);
1344 return tvb_captured_length(tvb);
1347 static unsigned
1348 get_ncp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1350 uint32_t signature;
1353 * Check the NCP-over-TCP header signature, to make sure it's there.
1354 * If it's not there, we cannot trust the next 4 bytes to be a
1355 * packet length+"has signature" flag, so we just say the length is
1356 * "what remains in the packet".
1358 signature = tvb_get_ntohl(tvb, offset);
1359 if (signature != NCPIP_RQST && signature != NCPIP_RPLY)
1360 return tvb_captured_length_remaining(tvb, offset);
1363 * Get the length of the NCP-over-TCP packet. Strip off the "has
1364 * signature" flag.
1367 return tvb_get_ntohl(tvb, offset + 4) & 0x7fffffff;
1370 static int
1371 dissect_ncp_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1373 dissect_ncp_common(tvb, pinfo, tree, true);
1374 return tvb_captured_length(tvb);
1377 static int
1378 dissect_ncp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1380 tcp_dissect_pdus(tvb, pinfo, tree, ncp_desegment, 8, get_ncp_pdu_len,
1381 dissect_ncp_tcp_pdu, data);
1382 return tvb_captured_length(tvb);
1385 void
1386 proto_register_ncp(void)
1388 static hf_register_info hf[] = {
1389 { &hf_ncp_ip_sig,
1390 { "NCP over IP signature", "ncp.ip.signature",
1391 FT_UINT32, BASE_HEX, VALS(ncp_ip_signature), 0x0,
1392 NULL, HFILL }},
1393 { &hf_ncp_ip_length,
1394 { "NCP over IP length", "ncp.ip.length",
1395 FT_UINT32, BASE_DEC, NULL, 0x0,
1396 NULL, HFILL }},
1397 { &hf_ncp_ip_ver,
1398 { "NCP over IP Version", "ncp.ip.version",
1399 FT_UINT32, BASE_DEC, NULL, 0x0,
1400 NULL, HFILL }},
1401 { &hf_ncp_ip_rplybufsize,
1402 { "NCP over IP Reply Buffer Size", "ncp.ip.replybufsize",
1403 FT_UINT32, BASE_DEC, NULL, 0x0,
1404 NULL, HFILL }},
1405 { &hf_ncp_ip_packetsig,
1406 { "NCP over IP Packet Signature", "ncp.ip.packetsig",
1407 FT_BYTES, BASE_NONE, NULL, 0x0,
1408 NULL, HFILL }},
1409 { &hf_ncp_type,
1410 { "Type", "ncp.type",
1411 FT_UINT16, BASE_HEX, VALS(ncp_type_vals), 0x0,
1412 "NCP message type", HFILL }},
1413 { &hf_ncp_seq,
1414 { "Sequence Number", "ncp.seq",
1415 FT_UINT8, BASE_DEC, NULL, 0x0,
1416 NULL, HFILL }},
1417 { &hf_ncp_connection,
1418 { "Connection Number", "ncp.connection",
1419 FT_UINT16, BASE_DEC, NULL, 0x0,
1420 NULL, HFILL }},
1421 { &hf_ncp_task,
1422 { "Task Number", "ncp.task",
1423 FT_UINT8, BASE_DEC, NULL, 0x0,
1424 NULL, HFILL }},
1425 { &hf_ncp_oplock_flag,
1426 { "Broadcast Message Flag", "ncp.msg_flag",
1427 FT_UINT8, BASE_HEX, VALS(ncp_oplock_vals), 0x0,
1428 NULL, HFILL }},
1429 { &hf_ncp_oplock_handle,
1430 { "File Handle", "ncp.oplock_handle",
1431 FT_UINT32, BASE_HEX, NULL, 0x0,
1432 NULL, HFILL }},
1433 { &hf_ncp_stream_type,
1434 { "Stream Type", "ncp.stream_type",
1435 FT_UINT8, BASE_HEX, NULL, 0x0,
1436 "Type of burst", HFILL }},
1437 { &hf_ncp_system_flags,
1438 { "System Flags", "ncp.system_flags",
1439 FT_UINT8, BASE_HEX, NULL, 0x0,
1440 NULL, HFILL }},
1441 { &hf_ncp_system_flags_abt,
1442 { "ABT", "ncp.system_flags.abt",
1443 FT_BOOLEAN, 8, NULL, ABT,
1444 "Is this an abort request?", HFILL }},
1445 { &hf_ncp_system_flags_eob,
1446 { "EOB", "ncp.system_flags.eob",
1447 FT_BOOLEAN, 8, NULL, EOB,
1448 "Is this the last packet of the burst?", HFILL }},
1449 { &hf_ncp_system_flags_sys,
1450 { "SYS", "ncp.system_flags.sys",
1451 FT_BOOLEAN, 8, NULL, SYS,
1452 "Is this a system packet?", HFILL }},
1453 { &hf_ncp_system_flags_bsy,
1454 { "BSY", "ncp.system_flags.bsy",
1455 FT_BOOLEAN, 8, NULL, BSY,
1456 "Is the server busy?", HFILL }},
1457 { &hf_ncp_system_flags_lst,
1458 { "LST", "ncp.system_flags.lst",
1459 FT_BOOLEAN, 8, NULL, LST,
1460 "Return Fragment List?", HFILL }},
1461 { &hf_ncp_src_connection,
1462 { "Source Connection ID", "ncp.src_connection",
1463 FT_UINT32, BASE_DEC, NULL, 0x0,
1464 "The workstation's connection identification number", HFILL }},
1465 { &hf_ncp_dst_connection,
1466 { "Destination Connection ID", "ncp.dst_connection",
1467 FT_UINT32, BASE_DEC, NULL, 0x0,
1468 "The server's connection identification number", HFILL }},
1469 { &hf_ncp_packet_seqno,
1470 { "Packet Sequence Number", "ncp.packet_seqno",
1471 FT_UINT32, BASE_DEC, NULL, 0x0,
1472 "Sequence number of this packet in a burst", HFILL }},
1473 { &hf_ncp_delay_time,
1474 { "Delay Time", "ncp.delay_time", /* in 100 us increments */
1475 FT_UINT32, BASE_DEC, NULL, 0x0,
1476 "Delay time between consecutive packet sends (100 us increments)", HFILL }},
1477 { &hf_ncp_burst_seqno,
1478 { "Burst Sequence Number", "ncp.burst_seqno",
1479 FT_UINT16, BASE_DEC, NULL, 0x0,
1480 "Sequence number of this packet in the burst", HFILL }},
1481 { &hf_ncp_ack_seqno,
1482 { "ACK Sequence Number", "ncp.ack_seqno",
1483 FT_UINT16, BASE_DEC, NULL, 0x0,
1484 "Next expected burst sequence number", HFILL }},
1485 { &hf_ncp_burst_len,
1486 { "Burst Length", "ncp.burst_len",
1487 FT_UINT32, BASE_DEC, NULL, 0x0,
1488 "Total length of data in this burst", HFILL }},
1489 { &hf_ncp_burst_offset,
1490 { "Burst Offset", "ncp.burst_offset",
1491 FT_UINT32, BASE_DEC, NULL, 0x0,
1492 "Offset of data in the burst", HFILL }},
1493 { &hf_ncp_data_offset,
1494 { "Data Offset", "ncp.data_offset",
1495 FT_UINT32, BASE_DEC, NULL, 0x0,
1496 "Offset of this packet", HFILL }},
1497 { &hf_ncp_data_bytes,
1498 { "Data Bytes", "ncp.data_bytes",
1499 FT_UINT16, BASE_DEC, NULL, 0x0,
1500 "Number of data bytes in this packet", HFILL }},
1501 { &hf_ncp_missing_fraglist_count,
1502 { "Missing Fragment List Count", "ncp.missing_fraglist_count",
1503 FT_UINT16, BASE_DEC, NULL, 0x0,
1504 "Number of missing fragments reported", HFILL }},
1505 { &hf_ncp_missing_data_offset,
1506 { "Missing Data Offset", "ncp.missing_data_offset",
1507 FT_UINT32, BASE_DEC, NULL, 0x0,
1508 "Offset of beginning of missing data", HFILL }},
1509 { &hf_ncp_missing_data_count,
1510 { "Missing Data Count", "ncp.missing_data_count",
1511 FT_UINT16, BASE_DEC, NULL, 0x0,
1512 "Number of bytes of missing data", HFILL }},
1513 { &hf_ncp_completion_code,
1514 { "Completion Code", "ncp.completion_code",
1515 FT_UINT8, BASE_DEC, NULL, 0x0,
1516 NULL, HFILL }},
1517 { &hf_ncp_connection_status,
1518 { "Connection Status", "ncp.connection_status",
1519 FT_UINT8, BASE_DEC, NULL, 0x0,
1520 NULL, HFILL }},
1521 { &hf_ncp_slot,
1522 { "Slot", "ncp.slot",
1523 FT_UINT8, BASE_DEC, NULL, 0x0,
1524 NULL, HFILL }},
1525 { &hf_ncp_signature_character,
1526 { "Signature Character", "ncp.signature_character",
1527 FT_CHAR, BASE_HEX, VALS(ncp_sigchar_vals), 0x0,
1528 NULL, HFILL }},
1529 #if 0
1530 { &hf_ncp_fragment_handle,
1531 { "Fragment Handle", "ncp.fragger_hndl",
1532 FT_UINT16, BASE_HEX, NULL, 0x0,
1533 NULL, HFILL }},
1534 #endif
1535 { &hf_lip_echo_magic,
1536 { "Large Internet Packet Echo Magic String", "ncp.lip_echo.magic_string",
1537 FT_STRING, BASE_NONE, NULL, 0x0,
1538 NULL, HFILL }},
1539 { &hf_lip_echo_payload,
1540 { "Large Internet Packet Echo Payload", "ncp.lip_echo.payload",
1541 FT_BYTES, BASE_NONE, NULL, 0x0,
1542 NULL, HFILL }},
1543 { &hf_ncp_burst_command,
1544 { "Burst Command", "ncp.burst_command",
1545 FT_UINT32, BASE_HEX, VALS(burst_command), 0x0,
1546 "Packet Burst Command", HFILL }},
1547 { &hf_ncp_burst_file_handle,
1548 { "Burst File Handle", "ncp.burst_file_handle",
1549 FT_UINT32, BASE_HEX, NULL, 0x0,
1550 "Packet Burst File Handle", HFILL }},
1551 { &hf_ncp_burst_reserved,
1552 { "Reserved", "ncp.burst_reserved",
1553 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}
1555 static int *ett[] = {
1556 &ett_ncp,
1557 &ett_ncp_system_flags,
1558 &ett_nds,
1559 &ett_nds_segments,
1560 &ett_nds_segment
1562 static ei_register_info ei[] = {
1563 { &ei_ncp_new_server_session, { "ncp.new_server_session", PI_RESPONSE_CODE, PI_CHAT, "Detected New Server Session", EXPFILL }},
1564 { &ei_ncp_oplock_handle, { "ncp.oplock_handle.clear", PI_RESPONSE_CODE, PI_CHAT, "Server requesting station to clear oplock", EXPFILL }},
1565 { &ei_ncp_type, { "ncp.type.unsupported", PI_UNDECODED, PI_NOTE, "Packet type not supported yet", EXPFILL }},
1567 module_t *ncp_module;
1568 expert_module_t* expert_ncp;
1570 proto_ncp = proto_register_protocol("NetWare Core Protocol", "NCP", "ncp");
1572 proto_register_field_array(proto_ncp, hf, array_length(hf));
1573 proto_register_subtree_array(ett, array_length(ett));
1574 expert_ncp = expert_register_protocol(proto_ncp);
1575 expert_register_field_array(expert_ncp, ei, array_length(ei));
1577 ncp_handle = register_dissector("ncp", dissect_ncp, proto_ncp);
1578 ncp_tcp_handle = register_dissector("ncp.tcp", dissect_ncp_tcp, proto_ncp);
1580 ncp_module = prefs_register_protocol(proto_ncp, NULL);
1581 prefs_register_obsolete_preference(ncp_module, "initial_hash_size");
1582 prefs_register_bool_preference(ncp_module, "desegment",
1583 "Reassemble NCP-over-TCP messages spanning multiple TCP segments",
1584 "Whether the NCP dissector should reassemble messages spanning multiple TCP segments."
1585 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1586 &ncp_desegment);
1587 prefs_register_bool_preference(ncp_module, "defragment_nds",
1588 "Reassemble fragmented NDS messages spanning multiple reply packets",
1589 "Whether the NCP dissector should defragment NDS messages spanning multiple reply packets.",
1590 &nds_defragment);
1591 prefs_register_bool_preference(ncp_module, "newstyle",
1592 "Dissect New Netware Information Structure",
1593 "Dissect the NetWare Information Structure as NetWare 5.x or higher or as older NetWare 3.x.",
1594 &ncp_newstyle);
1595 prefs_register_bool_preference(ncp_module, "eid_2_expert",
1596 "Expert: EID to Name lookups?",
1597 "Whether the NCP dissector should echo the NDS Entry ID to name resolves to the expert table.",
1598 &nds_echo_eid);
1599 prefs_register_bool_preference(ncp_module, "connection_2_expert",
1600 "Expert: NCP Connections?",
1601 "Whether the NCP dissector should echo NCP connection information to the expert table.",
1602 &ncp_echo_conn);
1603 prefs_register_bool_preference(ncp_module, "error_2_expert",
1604 "Expert: NCP Errors?",
1605 "Whether the NCP dissector should echo protocol errors to the expert table.",
1606 &ncp_echo_err);
1607 prefs_register_bool_preference(ncp_module, "server_2_expert",
1608 "Expert: Server Information?",
1609 "Whether the NCP dissector should echo server information to the expert table.",
1610 &ncp_echo_server);
1611 prefs_register_bool_preference(ncp_module, "file_2_expert",
1612 "Expert: File Information?",
1613 "Whether the NCP dissector should echo file open/close/oplock information to the expert table.",
1614 &ncp_echo_file);
1615 register_init_routine(&mncp_init_protocol);
1616 register_cleanup_routine(&mncp_cleanup_protocol);
1617 ncp_tap.stat=register_tap("ncp_srt");
1618 ncp_tap.hdr=register_tap("ncp");
1620 register_conversation_table(proto_ncp, false, ncp_conversation_packet, ncp_endpoint_packet);
1621 register_srt_table(proto_ncp, "ncp_srt", 24, ncpstat_packet, ncpstat_init, NULL);
1624 void
1625 proto_reg_handoff_ncp(void)
1627 dissector_add_uint_with_preference("tcp.port", TCP_PORT_NCP, ncp_tcp_handle);
1628 dissector_add_uint("udp.port", UDP_PORT_NCP, ncp_handle);
1629 dissector_add_uint("ipx.packet_type", IPX_PACKET_TYPE_NCP, ncp_handle);
1630 dissector_add_uint("ipx.socket", IPX_SOCKET_NCP, ncp_handle);
1634 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1636 * Local variables:
1637 * c-basic-offset: 4
1638 * tab-width: 8
1639 * indent-tabs-mode: nil
1640 * End:
1642 * vi: set shiftwidth=4 tabstop=8 expandtab:
1643 * :indentSize=4:tabSize=8:noTabs=true: