Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-ncp.c
Line
Count
Source (jump to first uncovered line)
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>
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
 * Wireshark - Network traffic analyzer
13
 * By Gerald Combs <gerald@wireshark.org>
14
 * Copyright 2000 Gerald Combs
15
 *
16
 * SPDX-License-Identifier: GPL-2.0-or-later
17
 */
18
19
/* XXX:
20
   ToDo: Find and fix possible memory leak(s):
21
22
   Example:
23
24
   A 40M capture file with mostly NCP frames results
25
   in a 400K-800K memory usage increase each time the file is reloaded.
26
27
   (If the NCP dissection is disabled, there is minimal memory usage
28
   increase each time the file is reloaded).
29
*/
30
31
/*
32
 * On page 86 of
33
 *
34
 *   https://www.novell.com/documentation/developer/smscomp/pdfdoc/sms_docs/sms_docs.pdf
35
 *
36
 * it says:
37
 *
38
 * The following table lists the wild cards options that can be used in
39
 * the terminal path node.
40
 *
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.
47
 *
48
 * ASTERISK is '*', and QUESTION is '?'; the "special" versions correspond
49
 * to the corresponding ASCII character, but with the upper bit set.
50
 *
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.
57
 *
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?
61
 */
62
#include "config.h"
63
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>
71
72
void proto_register_ncp(void);
73
void proto_reg_handoff_ncp(void);
74
75
static dissector_handle_t ncp_handle;
76
static dissector_handle_t ncp_tcp_handle;
77
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;
120
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;
126
127
static expert_field ei_ncp_oplock_handle;
128
static expert_field ei_ncp_new_server_session;
129
static expert_field ei_ncp_type;
130
131
static struct novell_tap ncp_tap;
132
static struct ncp_common_header     header;
133
static struct ncp_common_header    *ncp_hdr;
134
135
dissector_handle_t nds_data_handle;
136
137
/* desegmentation of NCP over TCP */
138
static bool ncp_desegment = true;
139
140
14
#define TCP_PORT_NCP            524
141
14
#define UDP_PORT_NCP            524
142
143
#define NCP_RQST_HDR_LENGTH     7
144
#define NCP_RPLY_HDR_LENGTH     8
145
146
/* These are the header structures to handle NCP over IP */
147
15
#define NCPIP_RQST      0x446d6454      /* "DmdT" */
148
135
#define NCPIP_RPLY      0x744e6350      /* "tNcP" */
149
150
struct ncp_ip_header {
151
    uint32_t signature;
152
    uint32_t length;
153
};
154
155
/* This header only appears on NCP over IP request packets */
156
struct ncp_ip_rqhdr {
157
    uint32_t version;
158
    uint32_t rplybufsize;
159
};
160
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 }
166
};
167
168
static const value_string ncp_ip_signature[] = {
169
    { NCPIP_RQST, "Demand Transport (Request)" },
170
    { NCPIP_RPLY, "Transport is NCP (Reply)" },
171
    { 0, NULL }
172
};
173
174
static const value_string burst_command[] = {
175
    { 0x01000000, "Burst Read" },
176
    { 0x02000000, "Burst Write" },
177
    { 0, NULL }
178
};
179
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
186
187
   And from the ncpfs source code by Volker Lendecke
188
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
195
196
   And:
197
198
   https://www.novell.com/developer/ndk/netware_core_protocols.html
199
200
   NCP documentation
201
202
   (formerly http:developer.novell.com)
203
204
*/
205
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 }
217
};
218
219
static const value_string ncp_oplock_vals[] = {
220
    { 0x21, "Message Waiting" },
221
    { 0x24, "Clear Op-lock" },
222
    { 0, NULL }
223
};
224
225
enum ncp_table_values
226
{
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
251
252
};
253
254
0
#define NCP_NUM_PROCEDURES     0
255
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}
281
};
282
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}
296
};
297
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}
307
};
308
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 }
439
};
440
441
static void
442
ncpstat_init(struct register_srt* srt _U_, GArray* srt_array)
443
0
{
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 */
446
447
0
    init_srt_table("NCP", "Groups", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.group", NULL);
448
449
    /* NDS Verbs */
450
0
    init_srt_table("NDS Verbs", "NDS", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.ndsverb", NULL);
451
452
    /* NCP Functions */
453
0
    init_srt_table("NCP Functions without Subfunctions", "Functions", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func", NULL);
454
455
    /* Secret Store Verbs */
456
0
    init_srt_table("Secret Store Verbs", "SSS", srt_array, NCP_NUM_PROCEDURES, NULL, "sss.subverb", NULL);
457
458
    /* NMAS Verbs */
459
0
    init_srt_table("NMAS Verbs", "NMAS", srt_array, NCP_NUM_PROCEDURES, NULL, "nmas.subverb", NULL);
460
461
    /* NCP Subfunctions */
462
0
    init_srt_table("Subfunctions for NCP 17", "17", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==17 && ncp.subfunc", NULL);
463
0
    init_srt_table("Subfunctions for NCP 21", "21", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==21 && ncp.subfunc", NULL);
464
0
    init_srt_table("Subfunctions for NCP 22", "22", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==22 && ncp.subfunc", NULL);
465
0
    init_srt_table("Subfunctions for NCP 23", "23", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==23 && ncp.subfunc", NULL);
466
0
    init_srt_table("Subfunctions for NCP 32", "32", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==32 && ncp.subfunc", NULL);
467
0
    init_srt_table("Subfunctions for NCP 34", "34", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==34 && ncp.subfunc", NULL);
468
0
    init_srt_table("Subfunctions for NCP 35", "35", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==35 && ncp.subfunc", NULL);
469
0
    init_srt_table("Subfunctions for NCP 36", "36", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==36 && ncp.subfunc", NULL);
470
0
    init_srt_table("Subfunctions for NCP 86", "86", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==86 && ncp.subfunc", NULL);
471
0
    init_srt_table("Subfunctions for NCP 87", "87", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==87 && ncp.subfunc", NULL);
472
0
    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
0
    init_srt_table("Subfunctions for NCP 90", "90", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==90 && ncp.subfunc", NULL);
474
0
    init_srt_table("Subfunctions for NCP 92 (Secret Store Services)", "92", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==92 && ncp.subfunc", NULL);
475
0
    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
0
    init_srt_table("Subfunctions for NCP 104", "104", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==104 && ncp.subfunc", NULL);
477
0
    init_srt_table("Subfunctions for NCP 111", "111", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==111 && ncp.subfunc", NULL);
478
0
    init_srt_table("Subfunctions for NCP 114", "114", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==114 && ncp.subfunc", NULL);
479
0
    init_srt_table("Subfunctions for NCP 123", "123", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==123 && ncp.subfunc", NULL);
480
0
    init_srt_table("Subfunctions for NCP 131", "131", srt_array, NCP_NUM_PROCEDURES, NULL, "ncp.func==131 && ncp.subfunc", NULL);
481
0
}
482
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_)
485
0
{
486
0
    unsigned i = 0;
487
0
    srt_stat_table *ncp_srt_table;
488
0
    srt_data_t *data = (srt_data_t *)pss;
489
0
    const ncp_req_hash_value *request_val=(const ncp_req_hash_value *)prv;
490
0
    char* tmp_str;
491
492
    /* if we haven't seen the request, just ignore it */
493
0
    if(!request_val || request_val->ncp_rec==0){
494
0
        return TAP_PACKET_DONT_REDRAW;
495
0
    }
496
497
    /* By Group */
498
0
    tmp_str = val_to_str_wmem(NULL, request_val->ncp_rec->group, ncp_group_vals, "Unknown(%u)");
499
0
    i = NCP_NCP_SRT_TABLE_INDEX;
500
0
    ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
501
0
    init_srt_table_row(ncp_srt_table, request_val->ncp_rec->group, tmp_str);
502
0
    wmem_free(NULL, tmp_str);
503
0
    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
0
    if (request_val->ncp_rec->subfunc==0) {
506
0
        i = NCP_FUNC_SRT_TABLE_INDEX;
507
0
        ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
508
0
        init_srt_table_row(ncp_srt_table, request_val->ncp_rec->func, request_val->ncp_rec->name);
509
0
        add_srt_table_data(ncp_srt_table, request_val->ncp_rec->func, &request_val->req_frame_time, pinfo);
510
0
    }
511
    /* By Subfunction number */
512
0
    if(request_val->ncp_rec->subfunc!=0){
513
0
        if (request_val->ncp_rec->func==17) {
514
0
            i = NCP_SUB17_SRT_TABLE_INDEX;
515
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
516
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
517
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
518
0
        }
519
0
        if (request_val->ncp_rec->func==21) {
520
0
            i = NCP_SUB21_SRT_TABLE_INDEX;
521
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
522
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
523
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
524
0
        }
525
0
        if (request_val->ncp_rec->func==22) {
526
0
            i = NCP_SUB22_SRT_TABLE_INDEX;
527
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
528
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
529
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
530
0
        }
531
0
        if (request_val->ncp_rec->func==23) {
532
0
            i = NCP_SUB23_SRT_TABLE_INDEX;
533
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
534
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
535
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
536
0
        }
537
0
        if (request_val->ncp_rec->func==32) {
538
0
            i = NCP_SUB32_SRT_TABLE_INDEX;
539
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
540
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
541
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
542
0
        }
543
0
        if (request_val->ncp_rec->func==34) {
544
0
            i = NCP_SUB34_SRT_TABLE_INDEX;
545
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
546
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
547
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
548
0
        }
549
0
        if (request_val->ncp_rec->func==35) {
550
0
            i = NCP_SUB35_SRT_TABLE_INDEX;
551
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
552
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
553
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
554
0
        }
555
0
        if (request_val->ncp_rec->func==36) {
556
0
            i = NCP_SUB36_SRT_TABLE_INDEX;
557
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
558
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
559
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
560
0
        }
561
0
        if (request_val->ncp_rec->func==86) {
562
0
            i = NCP_SUB86_SRT_TABLE_INDEX;
563
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
564
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
565
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
566
0
        }
567
0
        if (request_val->ncp_rec->func==87) {
568
0
            i = NCP_SUB87_SRT_TABLE_INDEX;
569
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
570
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
571
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
572
0
        }
573
0
        if (request_val->ncp_rec->func==89) {
574
0
            i = NCP_SUB89_SRT_TABLE_INDEX;
575
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
576
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
577
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
578
0
        }
579
0
        if (request_val->ncp_rec->func==90) {
580
0
            i = NCP_SUB90_SRT_TABLE_INDEX;
581
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
582
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
583
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
584
0
        }
585
0
        if (request_val->ncp_rec->func==92) {
586
0
            i = NCP_SUB92_SRT_TABLE_INDEX;
587
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
588
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
589
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
590
0
        }
591
0
        if (request_val->ncp_rec->func==94) {
592
0
            i = NCP_SUB94_SRT_TABLE_INDEX;
593
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
594
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
595
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
596
0
        }
597
0
        if (request_val->ncp_rec->func==104) {
598
0
            i = NCP_SUB104_SRT_TABLE_INDEX;
599
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
600
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
601
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
602
0
        }
603
0
        if (request_val->ncp_rec->func==111) {
604
0
            i = NCP_SUB111_SRT_TABLE_INDEX;
605
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
606
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
607
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
608
0
        }
609
0
        if (request_val->ncp_rec->func==114) {
610
0
            i = NCP_SUB114_SRT_TABLE_INDEX;
611
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
612
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
613
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
614
0
        }
615
0
        if (request_val->ncp_rec->func==123) {
616
0
            i = NCP_SUB123_SRT_TABLE_INDEX;
617
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
618
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
619
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
620
0
        }
621
0
        if (request_val->ncp_rec->func==131) {
622
0
            i = NCP_SUB131_SRT_TABLE_INDEX;
623
0
            ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
624
0
            init_srt_table_row(ncp_srt_table, (request_val->ncp_rec->subfunc), request_val->ncp_rec->name);
625
0
            add_srt_table_data(ncp_srt_table, (request_val->ncp_rec->subfunc), &request_val->req_frame_time, pinfo);
626
0
        }
627
0
    }
628
    /* By NDS verb */
629
0
    if (request_val->ncp_rec->func==0x68) {
630
0
        tmp_str = val_to_str_wmem(NULL, request_val->nds_request_verb, ncp_nds_verb_vals, "Unknown(%u)");
631
0
        i = NCP_NDS_SRT_TABLE_INDEX;
632
0
        ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
633
0
        init_srt_table_row(ncp_srt_table, (request_val->nds_request_verb), tmp_str);
634
0
        add_srt_table_data(ncp_srt_table, (request_val->nds_request_verb), &request_val->req_frame_time, pinfo);
635
0
        wmem_free(NULL, tmp_str);
636
0
    }
637
0
    if (request_val->ncp_rec->func==0x5c) {
638
0
        tmp_str = val_to_str_wmem(NULL, request_val->req_nds_flags, sss_verb_enum, "Unknown(%u)");
639
0
        i = NCP_SSS_SRT_TABLE_INDEX;
640
0
        ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
641
0
        init_srt_table_row(ncp_srt_table, (request_val->req_nds_flags), tmp_str);
642
0
        add_srt_table_data(ncp_srt_table, (request_val->req_nds_flags), &request_val->req_frame_time, pinfo);
643
0
        wmem_free(NULL, tmp_str);
644
0
    }
645
0
    if (request_val->ncp_rec->func==0x5e) {
646
0
        tmp_str = val_to_str_wmem(NULL, request_val->req_nds_flags, nmas_subverb_enum, "Unknown(%u)");
647
0
        i = NCP_NMAS_SRT_TABLE_INDEX;
648
0
        ncp_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
649
0
        init_srt_table_row(ncp_srt_table, (request_val->req_nds_flags), tmp_str);
650
0
        add_srt_table_data(ncp_srt_table, (request_val->req_nds_flags), &request_val->req_frame_time, pinfo);
651
0
        wmem_free(NULL, tmp_str);
652
0
    }
653
0
    return TAP_PACKET_REDRAW;
654
0
}
655
656
657
/* Conversation Struct so we can detect NCP server sessions */
658
659
typedef struct {
660
    conversation_t *conversation;
661
    uint32_t        nwconnection;
662
    uint8_t         nwtask;
663
} mncp_rhash_key;
664
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.
671
 */
672
typedef struct {
673
    uint32_t session_start_packet_num;
674
} mncp_rhash_value;
675
676
static GHashTable *mncp_rhash;
677
678
/* Hash Functions */
679
static int
680
mncp_equal(const void *v, const void *v2)
681
72
{
682
72
    const mncp_rhash_key *val1 = (const mncp_rhash_key*)v;
683
72
    const mncp_rhash_key *val2 = (const mncp_rhash_key*)v2;
684
685
72
    if (val1->conversation == val2->conversation && val1->nwconnection == val2->nwconnection && val1->nwtask == val2->nwtask) {
686
72
        return 1;
687
72
    }
688
0
    return 0;
689
72
}
690
691
static unsigned
692
mncp_hash(const void *v)
693
151
{
694
151
    const mncp_rhash_key *mncp_key = (const mncp_rhash_key*)v;
695
151
    return GPOINTER_TO_UINT(mncp_key->conversation)+mncp_key->nwconnection+mncp_key->nwtask;
696
151
}
697
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)
702
14
{
703
14
    mncp_rhash = g_hash_table_new(mncp_hash, mncp_equal);
704
14
}
705
706
static void
707
mncp_cleanup_protocol(void)
708
0
{
709
0
    g_hash_table_destroy(mncp_rhash);
710
0
}
711
712
static mncp_rhash_value*
713
mncp_hash_insert(conversation_t *conversation, uint32_t nwconnection, uint8_t nwtask, packet_info *pinfo)
714
57
{
715
57
    mncp_rhash_key      *key;
716
57
    mncp_rhash_value    *value;
717
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
57
    key = wmem_new(wmem_file_scope(), mncp_rhash_key);
722
57
    key->conversation = conversation;
723
57
    key->nwconnection = nwconnection;
724
57
    key->nwtask = nwtask;
725
726
57
    value = wmem_new(wmem_file_scope(), mncp_rhash_value);
727
728
57
    g_hash_table_insert(mncp_rhash, key, value);
729
730
57
    if (ncp_echo_conn && nwconnection != 65535) {
731
0
        expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nwconnection, nwtask);
732
0
        value->session_start_packet_num = pinfo->num;
733
0
    }
734
735
57
    return value;
736
57
}
737
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)
741
94
{
742
94
    mncp_rhash_key        key;
743
744
94
    key.conversation = conversation;
745
94
    key.nwconnection = nwconnection;
746
94
    key.nwtask = nwtask;
747
748
94
    return (mncp_rhash_value *)g_hash_table_lookup(mncp_rhash, &key);
749
94
}
750
751
static const char* ncp_conv_get_filter_type(conv_item_t* conv _U_, conv_filter_type_e filter)
752
0
{
753
0
    if ((filter == CONV_FT_SRC_PORT) || (filter == CONV_FT_DST_PORT) || (filter == CONV_FT_ANY_PORT))
754
0
        return "ncp.connection";
755
756
0
    return CONV_FILTER_INVALID;
757
0
}
758
759
static ct_dissector_info_t ncp_ct_dissector_info = {&ncp_conv_get_filter_type};
760
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)
763
0
{
764
0
    conv_hash_t *hash = (conv_hash_t*) pct;
765
0
    hash->flags = flags;
766
767
0
    const struct ncp_common_header *ncph=(const struct ncp_common_header *)vip;
768
0
    uint32_t connection;
769
770
0
    connection = (ncph->conn_high * 256)+ncph->conn_low;
771
0
    if (connection < 65535) {
772
0
        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);
773
0
    }
774
775
0
    return TAP_PACKET_REDRAW;
776
0
}
777
778
static const char* ncp_endpoint_get_filter_type(endpoint_item_t* endpoint _U_, conv_filter_type_e filter)
779
0
{
780
0
    return ncp_conv_get_filter_type(NULL, filter);
781
0
}
782
783
static et_dissector_info_t ncp_endpoint_dissector_info = {&ncp_endpoint_get_filter_type};
784
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)
787
0
{
788
0
    conv_hash_t *hash = (conv_hash_t*) pit;
789
0
    hash->flags = flags;
790
791
    /*const ncp_common_header *ncphdr=vip;*/
792
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
0
    add_endpoint_table_data(hash, &pinfo->src, 0, true, 1, pinfo->fd->pkt_len, &ncp_endpoint_dissector_info, ENDPOINT_NCP);
797
0
    add_endpoint_table_data(hash, &pinfo->dst, 0, false, 1, pinfo->fd->pkt_len, &ncp_endpoint_dissector_info, ENDPOINT_NCP);
798
799
0
    return TAP_PACKET_REDRAW;
800
0
}
801
802
/*
803
 * Burst packet system flags.
804
 */
805
14
#define ABT 0x04        /* Abort request */
806
14
#define BSY 0x08        /* Server Busy */
807
14
#define EOB 0x10        /* End of burst */
808
14
#define LST 0x40        /* Include Fragment List */
809
14
#define SYS 0x80        /* System packet */
810
811
3
#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', ' ', ' ', ' '
814
};
815
816
static void
817
dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
818
    bool is_tcp)
819
129
{
820
129
    proto_tree            *ncp_tree = NULL;
821
129
    proto_item            *ti;
822
129
    struct ncp_ip_header  ncpiph;
823
129
    struct ncp_ip_rqhdr   ncpiphrq;
824
129
    bool                  is_lip_echo_allocate_slot = false;
825
129
    uint16_t              ncp_burst_seqno, ncp_ack_seqno;
826
129
    uint16_t              flags = 0;
827
129
    proto_tree            *flags_tree = NULL;
828
129
    int                   hdr_offset = 0;
829
129
    int                   commhdr = 0;
830
129
    int                   offset = 0;
831
129
    int                   length_remaining;
832
129
    tvbuff_t              *next_tvb;
833
129
    uint32_t              ncp_burst_command, burst_len, burst_off, burst_file;
834
129
    uint8_t               subfunction;
835
129
    uint32_t              nw_connection = 0, data_offset;
836
129
    uint16_t              data_len = 0;
837
129
    uint16_t              missing_fraglist_count = 0;
838
129
    mncp_rhash_value      *request_value = NULL;
839
129
    conversation_t        *conversation;
840
841
129
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NCP");
842
129
    col_clear(pinfo->cinfo, COL_INFO);
843
844
129
    ncp_hdr = &header;
845
846
129
    ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, ENC_NA);
847
129
    ncp_tree = proto_item_add_subtree(ti, ett_ncp);
848
129
    if (is_tcp) {
849
3
        if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY)
850
3
            commhdr += 1;
851
        /* Get NCPIP Header data */
852
3
        ncpiph.signature = tvb_get_ntohl(tvb, commhdr);
853
3
        proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, commhdr, 4, ncpiph.signature);
854
3
        ncpiph.length = (0x7fffffff & tvb_get_ntohl(tvb, commhdr+4));
855
3
        proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, commhdr+4, 4, ncpiph.length);
856
3
        commhdr += 8;
857
3
        if (ncpiph.signature == NCPIP_RQST) {
858
0
            ncpiphrq.version = tvb_get_ntohl(tvb, commhdr);
859
0
            proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, commhdr, 4, ncpiphrq.version);
860
0
            commhdr += 4;
861
0
            ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, commhdr);
862
0
            proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, commhdr, 4, ncpiphrq.rplybufsize);
863
0
            commhdr += 4;
864
0
        }
865
        /* Check to see if this is a valid offset, otherwise increment for packet signature */
866
3
        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
3
            if (try_val_to_str(tvb_get_ntohs(tvb, commhdr+8), ncp_type_vals)!=NULL) {
869
0
                proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, commhdr, 8, ENC_NA);
870
0
                commhdr += 8;
871
0
            }
872
3
        }
873
126
    } else {
874
        /* Initialize this structure, we use it below */
875
126
        memset(&ncpiph, 0, sizeof(ncpiph));
876
126
    }
877
878
129
    header.type         = tvb_get_ntohs(tvb, commhdr);
879
129
    header.sequence     = tvb_get_uint8(tvb, commhdr+2);
880
129
    header.conn_low     = tvb_get_uint8(tvb, commhdr+3);
881
129
    header.task         = tvb_get_uint8(tvb, commhdr+4);
882
129
    header.conn_high    = tvb_get_uint8(tvb, commhdr+5);
883
129
    proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr, 2, header.type);
884
129
    nw_connection = (header.conn_high*256)+header.conn_low;
885
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.
889
     */
890
129
    conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
891
129
        CONVERSATION_NCP, (uint32_t) pinfo->srcport, (uint32_t) pinfo->destport,
892
129
        0);
893
129
    if ((ncpiph.length & 0x80000000) || ncpiph.signature == NCPIP_RPLY) {
894
        /* First time through we will record the initial connection and task
895
         * values
896
         */
897
0
        if (!pinfo->fd->visited) {
898
0
            if (conversation != NULL) {
899
                /* find the record telling us the
900
                 * request made that caused this
901
                 * reply
902
                 */
903
0
                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
0
                if (request_value == NULL) {
908
0
                    mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
909
0
                }
910
0
            } else {
911
                /* It's not part of any conversation
912
                 * - create a new one.
913
                 */
914
0
                conversation = conversation_new(pinfo->num, &pinfo->src,
915
0
                    &pinfo->dst, CONVERSATION_NCP, (uint32_t) pinfo->srcport, (uint32_t) pinfo->destport, 0);
916
0
                mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
917
0
            }
918
            /* If this is a request packet then we
919
             * might have a new task
920
             */
921
0
            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
926
                 */
927
                /*request_value = mncp_hash_lookup(conversation, nw_connection, header.task);*/
928
0
            }
929
0
        } else {
930
            /* Get request value data */
931
0
            request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
932
0
            if (request_value) {
933
0
                if ((request_value->session_start_packet_num == pinfo->num) && ncp_echo_conn) {
934
0
                    expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
935
0
                }
936
0
            }
937
0
        }
938
129
    } else {
939
129
        if (!pinfo->fd->visited) {
940
129
            if (conversation != NULL) {
941
                /* find the record telling us the
942
                 * request made that caused this
943
                 * reply
944
                 */
945
94
                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
94
                if (request_value == NULL) {
950
22
                    mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
951
22
                }
952
94
            } else {
953
                /* It's not part of any conversation
954
                 * - create a new one.
955
                 */
956
35
                conversation = conversation_new(pinfo->num, &pinfo->src,
957
35
                    &pinfo->dst, CONVERSATION_NCP, (uint32_t) pinfo->srcport, (uint32_t) pinfo->destport, 0);
958
35
                mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
959
35
            }
960
            /* find the record telling us the request
961
             * made that caused this reply
962
             */
963
129
        } else {
964
0
            request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
965
0
            if (request_value) {
966
0
                if ((request_value->session_start_packet_num == pinfo->num) && ncp_echo_conn) {
967
0
                    expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
968
0
                }
969
0
            }
970
0
        }
971
129
    }
972
973
129
    tap_queue_packet(ncp_tap.hdr, pinfo, ncp_hdr);
974
975
129
    col_add_str(pinfo->cinfo, COL_INFO,
976
129
        val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));
977
978
    /*
979
     * Process the packet-type-specific header.
980
     */
981
129
    switch (header.type) {
982
983
0
    case NCP_BROADCAST_SLOT:    /* Server Broadcast */
984
0
        proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
985
0
        proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
986
0
        proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN);
987
0
        proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, ENC_BIG_ENDIAN);
988
0
        proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, ENC_BIG_ENDIAN);
989
0
        if ((tvb_get_uint8(tvb, commhdr+9)==0x24) && ncp_echo_file) {
990
0
            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));
991
0
        }
992
0
        break;
993
994
0
    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
0
        proto_tree_add_item(ncp_tree, hf_lip_echo_magic, tvb, commhdr, 13, ENC_ASCII);
1000
0
        break;
1001
1002
0
    case NCP_BURST_MODE_XFER:    /* Packet Burst Packet */
1003
        /*
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.
1007
         *
1008
         * The burst header contains:
1009
         *
1010
         *    4 bytes of little-endian function number:
1011
         *        1 = read, 2 = write;
1012
         *
1013
         *    4 bytes of file handle;
1014
         *
1015
         *    8 reserved bytes;
1016
         *
1017
         *    4 bytes of big-endian file offset;
1018
         *
1019
         *    4 bytes of big-endian byte count.
1020
         *
1021
         * The data follows for a burst write operation.
1022
         *
1023
         * The first packet of a burst read reply contains:
1024
         *
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;
1030
         *
1031
         *    4 bytes of returned byte count (big-endian?).
1032
         *
1033
         * The data follows.
1034
         *
1035
         * Each burst of a write request is responded to with a
1036
         * burst packet with a 2-byte little-endian result code:
1037
         *
1038
         *    0: Write successful
1039
         *    4: Write error
1040
         */
1041
0
        flags = tvb_get_uint8(tvb, commhdr + 2);
1042
1043
0
        ti = proto_tree_add_uint(ncp_tree, hf_ncp_system_flags,
1044
0
            tvb, commhdr + 2, 1, flags);
1045
0
        flags_tree = proto_item_add_subtree(ti, ett_ncp_system_flags);
1046
1047
0
        proto_tree_add_item(flags_tree, hf_ncp_system_flags_abt,
1048
0
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1049
0
        if (flags & ABT) {
1050
0
            proto_item_append_text(ti, "  ABT");
1051
0
        }
1052
0
        flags&=(~( ABT ));
1053
1054
0
        proto_tree_add_item(flags_tree, hf_ncp_system_flags_bsy,
1055
0
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1056
0
        if (flags & BSY) {
1057
0
            proto_item_append_text(ti, "  BSY");
1058
0
        }
1059
0
        flags&=(~( BSY ));
1060
1061
0
        proto_tree_add_item(flags_tree, hf_ncp_system_flags_eob,
1062
0
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1063
0
        if (flags & EOB) {
1064
0
            proto_item_append_text(ti, "  EOB");
1065
0
        }
1066
0
        flags&=(~( EOB ));
1067
1068
0
        proto_tree_add_item(flags_tree, hf_ncp_system_flags_lst,
1069
0
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1070
0
        if (flags & LST) {
1071
0
            proto_item_append_text(ti, "  LST");
1072
0
        }
1073
0
        flags&=(~( LST ));
1074
1075
0
        proto_tree_add_item(flags_tree, hf_ncp_system_flags_sys,
1076
0
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
1077
0
        if (flags & SYS) {
1078
0
            proto_item_append_text(ti, "  SYS");
1079
0
        }
1080
0
        flags&=(~( SYS ));
1081
1082
1083
0
        proto_tree_add_item(ncp_tree, hf_ncp_stream_type,
1084
0
            tvb, commhdr + 3, 1, ENC_BIG_ENDIAN);
1085
0
        proto_tree_add_item(ncp_tree, hf_ncp_src_connection,
1086
0
            tvb, commhdr + 4, 4, ENC_BIG_ENDIAN);
1087
0
        proto_tree_add_item(ncp_tree, hf_ncp_dst_connection,
1088
0
            tvb, commhdr + 8, 4, ENC_BIG_ENDIAN);
1089
0
        proto_tree_add_item(ncp_tree, hf_ncp_packet_seqno,
1090
0
            tvb, commhdr + 12, 4, ENC_BIG_ENDIAN);
1091
0
        proto_tree_add_item(ncp_tree, hf_ncp_delay_time,
1092
0
            tvb, commhdr + 16, 4, ENC_BIG_ENDIAN);
1093
0
        ncp_burst_seqno = tvb_get_ntohs(tvb, commhdr+20);
1094
0
        proto_tree_add_item(ncp_tree, hf_ncp_burst_seqno,
1095
0
            tvb, commhdr + 20, 2, ENC_BIG_ENDIAN);
1096
0
        ncp_ack_seqno = tvb_get_ntohs(tvb, commhdr+22);
1097
0
        proto_tree_add_item(ncp_tree, hf_ncp_ack_seqno,
1098
0
            tvb, commhdr + 22, 2, ENC_BIG_ENDIAN);
1099
0
        proto_tree_add_item(ncp_tree, hf_ncp_burst_len,
1100
0
            tvb, commhdr + 24, 4, ENC_BIG_ENDIAN);
1101
0
        data_offset = tvb_get_ntohl(tvb, commhdr + 28);
1102
0
        proto_tree_add_uint(ncp_tree, hf_ncp_data_offset,
1103
0
            tvb, commhdr + 28, 4, data_offset);
1104
0
        data_len = tvb_get_ntohs(tvb, commhdr + 32);
1105
0
        proto_tree_add_uint(ncp_tree, hf_ncp_data_bytes,
1106
0
            tvb, commhdr + 32, 2, data_len);
1107
0
        missing_fraglist_count = tvb_get_ntohs(tvb, commhdr + 34);
1108
0
        proto_tree_add_item(ncp_tree, hf_ncp_missing_fraglist_count,
1109
0
            tvb, commhdr + 34, 2, ENC_BIG_ENDIAN);
1110
0
        offset = commhdr + 36;
1111
0
        if (!(flags & SYS) && ncp_burst_seqno == ncp_ack_seqno &&
1112
0
            data_offset == 0) {
1113
            /*
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).
1119
             */
1120
0
            if (data_len < 4)
1121
0
                return;
1122
0
            ncp_burst_command = tvb_get_ntohl(tvb, offset);
1123
0
            proto_tree_add_item(ncp_tree, hf_ncp_burst_command,
1124
0
                tvb, offset, 4, ENC_BIG_ENDIAN);
1125
0
            offset += 4;
1126
0
            data_len -= 4;
1127
1128
0
            if (data_len < 4)
1129
0
                return;
1130
0
            burst_file = tvb_get_ntohl(tvb, offset);
1131
0
            proto_tree_add_item(ncp_tree, hf_ncp_burst_file_handle,
1132
0
                tvb, offset, 4, ENC_BIG_ENDIAN);
1133
0
            offset += 4;
1134
0
            data_len -= 4;
1135
1136
0
            if (data_len < 8)
1137
0
                return;
1138
0
            proto_tree_add_item(ncp_tree, hf_ncp_burst_reserved,
1139
0
                tvb, offset, 8, ENC_NA);
1140
0
            offset += 8;
1141
0
            data_len -= 8;
1142
1143
0
            if (data_len < 4)
1144
0
                return;
1145
0
            burst_off = tvb_get_ntohl(tvb, offset);
1146
0
            proto_tree_add_uint(ncp_tree, hf_ncp_burst_offset,
1147
0
                tvb, offset, 4, burst_off);
1148
0
            offset += 4;
1149
0
            data_len -= 4;
1150
1151
0
            if (data_len < 4)
1152
0
                return;
1153
0
            burst_len = tvb_get_ntohl(tvb, offset);
1154
0
            proto_tree_add_uint(ncp_tree, hf_ncp_burst_len,
1155
0
                tvb, offset, 4, burst_len);
1156
0
            offset += 4;
1157
0
            data_len -= 4;
1158
1159
0
            col_add_fstr(pinfo->cinfo, COL_INFO,
1160
0
                "%s %d bytes starting at offset %d in file 0x%08x",
1161
0
                val_to_str(ncp_burst_command,
1162
0
                    burst_command, "Unknown (0x%08x)"),
1163
0
                    burst_len, burst_off, burst_file);
1164
0
            break;
1165
0
        } else {
1166
0
            if (tvb_get_uint8(tvb, commhdr + 2) & 0x10) {
1167
0
                col_set_str(pinfo->cinfo, COL_INFO, "End of Burst");
1168
0
            }
1169
0
        }
1170
0
        break;
1171
1172
1
    case NCP_ALLOCATE_SLOT:        /* Allocate Slot Request */
1173
1
        length_remaining = tvb_reported_length_remaining(tvb, commhdr + 4);
1174
1
        if (length_remaining >= LIP_ECHO_MAGIC_LEN &&
1175
1
            tvb_memeql(tvb, commhdr+4, lip_echo_magic, LIP_ECHO_MAGIC_LEN) == 0) {
1176
            /* This is a LIP Echo. */
1177
0
            is_lip_echo_allocate_slot = true;
1178
0
            col_set_str(pinfo->cinfo, COL_INFO, "LIP Echo");
1179
0
        }
1180
        /* fall through */
1181
1182
1
    case NCP_POSITIVE_ACK:        /* Positive Acknowledgement */
1183
97
    case NCP_SERVICE_REQUEST:    /* Server NCP Request */
1184
97
    case NCP_SERVICE_REPLY:        /* Server NCP Reply */
1185
97
    case NCP_WATCHDOG:        /* Watchdog Packet */
1186
97
    case NCP_DEALLOCATE_SLOT:    /* Deallocate Slot Request */
1187
129
    default:
1188
129
        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
129
        if (!is_lip_echo_allocate_slot) {
1192
129
            proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
1193
129
            proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN);
1194
129
        }
1195
129
        break;
1196
129
    }
1197
1198
    /*
1199
     * Process the packet body.
1200
     */
1201
129
    switch (header.type) {
1202
1203
1
    case NCP_ALLOCATE_SLOT:        /* Allocate Slot Request */
1204
1
        if (is_lip_echo_allocate_slot) {
1205
0
            length_remaining = tvb_reported_length_remaining(tvb, commhdr + 4);
1206
0
            proto_tree_add_item(ncp_tree, hf_lip_echo_magic, tvb, commhdr + 4, LIP_ECHO_MAGIC_LEN, ENC_ASCII);
1207
0
            if (length_remaining > LIP_ECHO_MAGIC_LEN)
1208
0
                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);
1209
0
        }
1210
1
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1211
1
        dissect_ncp_request(next_tvb, pinfo, nw_connection,
1212
1
            header.sequence, header.type, is_lip_echo_allocate_slot, ncp_tree);
1213
1
        break;
1214
1215
0
    case NCP_DEALLOCATE_SLOT:    /* Deallocate Slot Request */
1216
0
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1217
0
        dissect_ncp_request(next_tvb, pinfo, nw_connection,
1218
0
            header.sequence, header.type, false, ncp_tree);
1219
0
        break;
1220
1221
96
    case NCP_SERVICE_REQUEST:    /* Server NCP Request */
1222
96
    case NCP_BROADCAST_SLOT:    /* Server Broadcast Packet */
1223
96
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1224
96
        if (tvb_get_uint8(tvb, commhdr+6) == 0x68) {
1225
47
            subfunction = tvb_get_uint8(tvb, commhdr+7);
1226
47
            switch (subfunction) {
1227
1228
47
            case 0x02:    /* NDS Frag Packet to decode */
1229
47
                dissect_nds_request(next_tvb, pinfo,
1230
47
                    nw_connection, header.sequence,
1231
47
                    header.type, ncp_tree);
1232
47
                break;
1233
1234
0
            case 0x01:    /* NDS Ping */
1235
0
                dissect_ping_req(next_tvb, pinfo,
1236
0
                    nw_connection, header.sequence,
1237
0
                    header.type, ncp_tree);
1238
0
                break;
1239
1240
0
            default:
1241
0
                dissect_ncp_request(next_tvb, pinfo,
1242
0
                    nw_connection, header.sequence,
1243
0
                    header.type, false, ncp_tree);
1244
0
                break;
1245
47
             }
1246
49
        } else {
1247
49
            dissect_ncp_request(next_tvb, pinfo, nw_connection,
1248
49
                header.sequence, header.type, false, ncp_tree);
1249
49
        }
1250
57
        break;
1251
1252
57
    case NCP_SERVICE_REPLY:        /* Server NCP Reply */
1253
0
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1254
0
        nds_defrag(next_tvb, pinfo, nw_connection, header.sequence,
1255
0
            header.type, ncp_tree, &ncp_tap);
1256
0
        break;
1257
1258
0
    case NCP_POSITIVE_ACK:        /* Positive Acknowledgement */
1259
        /*
1260
         * XXX - this used to call "nds_defrag()", which would
1261
         * clear out "frags".  Was that the right thing to
1262
         * do?
1263
         */
1264
0
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
1265
0
        dissect_ncp_reply(next_tvb, pinfo, nw_connection,
1266
0
            header.sequence, header.type, ncp_tree, &ncp_tap);
1267
0
        break;
1268
1269
0
    case NCP_WATCHDOG:        /* Watchdog Packet */
1270
        /*
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()".
1274
         */
1275
0
        proto_tree_add_item(ncp_tree, hf_ncp_completion_code,
1276
0
            tvb, commhdr + 6, 1, ENC_LITTLE_ENDIAN);
1277
0
        proto_tree_add_item(ncp_tree, hf_ncp_connection_status,
1278
0
            tvb, commhdr + 7, 1, ENC_LITTLE_ENDIAN);
1279
0
        proto_tree_add_item(ncp_tree, hf_ncp_slot,
1280
0
            tvb, commhdr + 8, 1, ENC_LITTLE_ENDIAN);
1281
0
        proto_tree_add_item(ncp_tree, hf_ncp_signature_character,
1282
0
            tvb, commhdr + 9, 1, ENC_LITTLE_ENDIAN);
1283
        /*
1284
         * Display the rest of the packet as data.
1285
         */
1286
0
        if (tvb_offset_exists(tvb, commhdr + 10)) {
1287
0
            call_data_dissector(tvb_new_subset_remaining(tvb, commhdr + 10),
1288
0
                pinfo, ncp_tree);
1289
0
        }
1290
0
        break;
1291
1292
0
    case NCP_BURST_MODE_XFER:    /* Packet Burst Packet */
1293
0
        if (flags & SYS) {
1294
            /*
1295
             * System packet; show missing fragments if there
1296
             * are any.
1297
             */
1298
0
            while (missing_fraglist_count != 0) {
1299
0
                proto_tree_add_item(ncp_tree, hf_ncp_missing_data_offset,
1300
0
                    tvb, offset, 4, ENC_BIG_ENDIAN);
1301
0
                offset += 4;
1302
0
                proto_tree_add_item(ncp_tree, hf_ncp_missing_data_count,
1303
0
                    tvb, offset, 2, ENC_BIG_ENDIAN);
1304
0
                offset += 2;
1305
0
                missing_fraglist_count--;
1306
0
            }
1307
0
        } else {
1308
            /*
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.
1315
             */
1316
0
            length_remaining = tvb_captured_length_remaining(tvb, offset);
1317
0
            if (length_remaining > data_len)
1318
0
                length_remaining = data_len;
1319
0
            if (data_len != 0) {
1320
0
                call_data_dissector(tvb_new_subset_length_caplen(tvb, offset,
1321
0
                    length_remaining, data_len),
1322
0
                    pinfo, ncp_tree);
1323
0
            }
1324
0
        }
1325
0
        break;
1326
1327
0
    case NCP_LIP_ECHO:        /* LIP Echo Packet */
1328
0
        proto_tree_add_item(ncp_tree, hf_lip_echo_payload, tvb, commhdr + 13, -1, ENC_NA);
1329
0
        break;
1330
1331
32
    default:
1332
32
        proto_tree_add_expert_format(ncp_tree, pinfo, &ei_ncp_type, tvb, commhdr + 6, -1,
1333
32
            "%s packets not supported yet",
1334
32
            val_to_str(header.type, ncp_type_vals,
1335
32
                "Unknown type (0x%04x)"));
1336
32
        break;
1337
129
    }
1338
129
}
1339
1340
static int
1341
dissect_ncp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1342
126
{
1343
126
    dissect_ncp_common(tvb, pinfo, tree, false);
1344
126
    return tvb_captured_length(tvb);
1345
126
}
1346
1347
static unsigned
1348
get_ncp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1349
3
{
1350
3
    uint32_t signature;
1351
1352
    /*
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".
1357
     */
1358
3
    signature = tvb_get_ntohl(tvb, offset);
1359
3
    if (signature != NCPIP_RQST && signature != NCPIP_RPLY)
1360
3
        return tvb_captured_length_remaining(tvb, offset);
1361
1362
    /*
1363
     * Get the length of the NCP-over-TCP packet.  Strip off the "has
1364
     * signature" flag.
1365
     */
1366
1367
0
    return tvb_get_ntohl(tvb, offset + 4) & 0x7fffffff;
1368
3
}
1369
1370
static int
1371
dissect_ncp_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1372
3
{
1373
3
    dissect_ncp_common(tvb, pinfo, tree, true);
1374
3
    return tvb_captured_length(tvb);
1375
3
}
1376
1377
static int
1378
dissect_ncp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1379
3
{
1380
3
    tcp_dissect_pdus(tvb, pinfo, tree, ncp_desegment, 8, get_ncp_pdu_len,
1381
3
                     dissect_ncp_tcp_pdu, data);
1382
3
    return tvb_captured_length(tvb);
1383
3
}
1384
1385
void
1386
proto_register_ncp(void)
1387
14
{
1388
14
    static hf_register_info hf[] = {
1389
14
        { &hf_ncp_ip_sig,
1390
14
          { "NCP over IP signature",            "ncp.ip.signature",
1391
14
            FT_UINT32, BASE_HEX, VALS(ncp_ip_signature), 0x0,
1392
14
            NULL, HFILL }},
1393
14
        { &hf_ncp_ip_length,
1394
14
          { "NCP over IP length",               "ncp.ip.length",
1395
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1396
14
            NULL, HFILL }},
1397
14
        { &hf_ncp_ip_ver,
1398
14
          { "NCP over IP Version",              "ncp.ip.version",
1399
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1400
14
            NULL, HFILL }},
1401
14
        { &hf_ncp_ip_rplybufsize,
1402
14
          { "NCP over IP Reply Buffer Size",    "ncp.ip.replybufsize",
1403
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1404
14
            NULL, HFILL }},
1405
14
        { &hf_ncp_ip_packetsig,
1406
14
          { "NCP over IP Packet Signature",     "ncp.ip.packetsig",
1407
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
1408
14
            NULL, HFILL }},
1409
14
        { &hf_ncp_type,
1410
14
          { "Type",                             "ncp.type",
1411
14
            FT_UINT16, BASE_HEX, VALS(ncp_type_vals), 0x0,
1412
14
            "NCP message type", HFILL }},
1413
14
        { &hf_ncp_seq,
1414
14
          { "Sequence Number",                  "ncp.seq",
1415
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
1416
14
            NULL, HFILL }},
1417
14
        { &hf_ncp_connection,
1418
14
          { "Connection Number",                "ncp.connection",
1419
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
1420
14
            NULL, HFILL }},
1421
14
        { &hf_ncp_task,
1422
14
          { "Task Number",                      "ncp.task",
1423
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
1424
14
            NULL, HFILL }},
1425
14
        { &hf_ncp_oplock_flag,
1426
14
          { "Broadcast Message Flag",           "ncp.msg_flag",
1427
14
            FT_UINT8, BASE_HEX, VALS(ncp_oplock_vals), 0x0,
1428
14
            NULL, HFILL }},
1429
14
        { &hf_ncp_oplock_handle,
1430
14
          { "File Handle",                      "ncp.oplock_handle",
1431
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
1432
14
            NULL, HFILL }},
1433
14
        { &hf_ncp_stream_type,
1434
14
          { "Stream Type",                      "ncp.stream_type",
1435
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1436
14
            "Type of burst", HFILL }},
1437
14
        { &hf_ncp_system_flags,
1438
14
          { "System Flags",                     "ncp.system_flags",
1439
14
            FT_UINT8, BASE_HEX, NULL, 0x0,
1440
14
            NULL, HFILL }},
1441
14
        { &hf_ncp_system_flags_abt,
1442
14
          { "ABT",                              "ncp.system_flags.abt",
1443
14
            FT_BOOLEAN, 8, NULL, ABT,
1444
14
            "Is this an abort request?", HFILL }},
1445
14
        { &hf_ncp_system_flags_eob,
1446
14
          { "EOB",                              "ncp.system_flags.eob",
1447
14
            FT_BOOLEAN, 8, NULL, EOB,
1448
14
            "Is this the last packet of the burst?", HFILL }},
1449
14
        { &hf_ncp_system_flags_sys,
1450
14
          { "SYS",                              "ncp.system_flags.sys",
1451
14
            FT_BOOLEAN, 8, NULL, SYS,
1452
14
            "Is this a system packet?", HFILL }},
1453
14
        { &hf_ncp_system_flags_bsy,
1454
14
          { "BSY",                              "ncp.system_flags.bsy",
1455
14
            FT_BOOLEAN, 8, NULL, BSY,
1456
14
            "Is the server busy?", HFILL }},
1457
14
        { &hf_ncp_system_flags_lst,
1458
14
          { "LST",                              "ncp.system_flags.lst",
1459
14
            FT_BOOLEAN, 8, NULL, LST,
1460
14
            "Return Fragment List?", HFILL }},
1461
14
        { &hf_ncp_src_connection,
1462
14
          { "Source Connection ID",             "ncp.src_connection",
1463
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1464
14
            "The workstation's connection identification number", HFILL }},
1465
14
        { &hf_ncp_dst_connection,
1466
14
          { "Destination Connection ID",        "ncp.dst_connection",
1467
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1468
14
            "The server's connection identification number", HFILL }},
1469
14
        { &hf_ncp_packet_seqno,
1470
14
          { "Packet Sequence Number",           "ncp.packet_seqno",
1471
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1472
14
            "Sequence number of this packet in a burst", HFILL }},
1473
14
        { &hf_ncp_delay_time,
1474
14
          { "Delay Time",                       "ncp.delay_time",       /* in 100 us increments */
1475
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1476
14
            "Delay time between consecutive packet sends (100 us increments)", HFILL }},
1477
14
        { &hf_ncp_burst_seqno,
1478
14
          { "Burst Sequence Number",            "ncp.burst_seqno",
1479
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
1480
14
            "Sequence number of this packet in the burst", HFILL }},
1481
14
        { &hf_ncp_ack_seqno,
1482
14
          { "ACK Sequence Number",              "ncp.ack_seqno",
1483
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
1484
14
            "Next expected burst sequence number", HFILL }},
1485
14
        { &hf_ncp_burst_len,
1486
14
          { "Burst Length",                     "ncp.burst_len",
1487
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1488
14
            "Total length of data in this burst", HFILL }},
1489
14
        { &hf_ncp_burst_offset,
1490
14
          { "Burst Offset",                     "ncp.burst_offset",
1491
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1492
14
            "Offset of data in the burst", HFILL }},
1493
14
        { &hf_ncp_data_offset,
1494
14
          { "Data Offset",                      "ncp.data_offset",
1495
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1496
14
            "Offset of this packet", HFILL }},
1497
14
        { &hf_ncp_data_bytes,
1498
14
          { "Data Bytes",                       "ncp.data_bytes",
1499
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
1500
14
            "Number of data bytes in this packet", HFILL }},
1501
14
        { &hf_ncp_missing_fraglist_count,
1502
14
          { "Missing Fragment List Count",      "ncp.missing_fraglist_count",
1503
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
1504
14
            "Number of missing fragments reported", HFILL }},
1505
14
        { &hf_ncp_missing_data_offset,
1506
14
          { "Missing Data Offset",              "ncp.missing_data_offset",
1507
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
1508
14
            "Offset of beginning of missing data", HFILL }},
1509
14
        { &hf_ncp_missing_data_count,
1510
14
          { "Missing Data Count",               "ncp.missing_data_count",
1511
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
1512
14
            "Number of bytes of missing data", HFILL }},
1513
14
        { &hf_ncp_completion_code,
1514
14
          { "Completion Code",                  "ncp.completion_code",
1515
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
1516
14
            NULL, HFILL }},
1517
14
        { &hf_ncp_connection_status,
1518
14
          { "Connection Status",                "ncp.connection_status",
1519
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
1520
14
            NULL, HFILL }},
1521
14
        { &hf_ncp_slot,
1522
14
          { "Slot",                             "ncp.slot",
1523
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
1524
14
            NULL, HFILL }},
1525
14
        { &hf_ncp_signature_character,
1526
14
          { "Signature Character",              "ncp.signature_character",
1527
14
            FT_CHAR, BASE_HEX, VALS(ncp_sigchar_vals), 0x0,
1528
14
            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
14
        { &hf_lip_echo_magic,
1536
14
          { "Large Internet Packet Echo Magic String",  "ncp.lip_echo.magic_string",
1537
14
            FT_STRING, BASE_NONE, NULL, 0x0,
1538
14
            NULL, HFILL }},
1539
14
        { &hf_lip_echo_payload,
1540
14
          { "Large Internet Packet Echo Payload",  "ncp.lip_echo.payload",
1541
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
1542
14
            NULL, HFILL }},
1543
14
        { &hf_ncp_burst_command,
1544
14
          { "Burst Command",                    "ncp.burst_command",
1545
14
            FT_UINT32, BASE_HEX, VALS(burst_command), 0x0,
1546
14
            "Packet Burst Command", HFILL }},
1547
14
        { &hf_ncp_burst_file_handle,
1548
14
          { "Burst File Handle",                "ncp.burst_file_handle",
1549
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
1550
14
            "Packet Burst File Handle", HFILL }},
1551
14
        { &hf_ncp_burst_reserved,
1552
14
          { "Reserved",                         "ncp.burst_reserved",
1553
14
            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}
1554
14
    };
1555
14
    static int *ett[] = {
1556
14
        &ett_ncp,
1557
14
        &ett_ncp_system_flags,
1558
14
        &ett_nds,
1559
14
        &ett_nds_segments,
1560
14
        &ett_nds_segment
1561
14
    };
1562
14
    static ei_register_info ei[] = {
1563
14
        { &ei_ncp_new_server_session, { "ncp.new_server_session", PI_RESPONSE_CODE, PI_CHAT, "Detected New Server Session", EXPFILL }},
1564
14
        { &ei_ncp_oplock_handle, { "ncp.oplock_handle.clear", PI_RESPONSE_CODE, PI_CHAT, "Server requesting station to clear oplock", EXPFILL }},
1565
14
        { &ei_ncp_type, { "ncp.type.unsupported", PI_UNDECODED, PI_NOTE, "Packet type not supported yet", EXPFILL }},
1566
14
    };
1567
14
    module_t *ncp_module;
1568
14
    expert_module_t* expert_ncp;
1569
1570
14
    proto_ncp = proto_register_protocol("NetWare Core Protocol", "NCP", "ncp");
1571
1572
14
    proto_register_field_array(proto_ncp, hf, array_length(hf));
1573
14
    proto_register_subtree_array(ett, array_length(ett));
1574
14
    expert_ncp = expert_register_protocol(proto_ncp);
1575
14
    expert_register_field_array(expert_ncp, ei, array_length(ei));
1576
1577
14
    ncp_handle = register_dissector("ncp", dissect_ncp, proto_ncp);
1578
14
    ncp_tcp_handle = register_dissector("ncp.tcp", dissect_ncp_tcp, proto_ncp);
1579
1580
14
    ncp_module = prefs_register_protocol(proto_ncp, NULL);
1581
14
    prefs_register_obsolete_preference(ncp_module, "initial_hash_size");
1582
14
    prefs_register_bool_preference(ncp_module, "desegment",
1583
14
                                   "Reassemble NCP-over-TCP messages spanning multiple TCP segments",
1584
14
                                   "Whether the NCP dissector should reassemble messages spanning multiple TCP segments."
1585
14
                                   " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1586
14
                                   &ncp_desegment);
1587
14
    prefs_register_bool_preference(ncp_module, "defragment_nds",
1588
14
                                   "Reassemble fragmented NDS messages spanning multiple reply packets",
1589
14
                                   "Whether the NCP dissector should defragment NDS messages spanning multiple reply packets.",
1590
14
                                   &nds_defragment);
1591
14
    prefs_register_bool_preference(ncp_module, "newstyle",
1592
14
                                   "Dissect New Netware Information Structure",
1593
14
                                   "Dissect the NetWare Information Structure as NetWare 5.x or higher or as older NetWare 3.x.",
1594
14
                                   &ncp_newstyle);
1595
14
    prefs_register_bool_preference(ncp_module, "eid_2_expert",
1596
14
                                   "Expert: EID to Name lookups?",
1597
14
                                   "Whether the NCP dissector should echo the NDS Entry ID to name resolves to the expert table.",
1598
14
                                   &nds_echo_eid);
1599
14
    prefs_register_bool_preference(ncp_module, "connection_2_expert",
1600
14
                                   "Expert: NCP Connections?",
1601
14
                                   "Whether the NCP dissector should echo NCP connection information to the expert table.",
1602
14
                                   &ncp_echo_conn);
1603
14
    prefs_register_bool_preference(ncp_module, "error_2_expert",
1604
14
                                   "Expert: NCP Errors?",
1605
14
                                   "Whether the NCP dissector should echo protocol errors to the expert table.",
1606
14
                                   &ncp_echo_err);
1607
14
    prefs_register_bool_preference(ncp_module, "server_2_expert",
1608
14
                                   "Expert: Server Information?",
1609
14
                                   "Whether the NCP dissector should echo server information to the expert table.",
1610
14
                                   &ncp_echo_server);
1611
14
    prefs_register_bool_preference(ncp_module, "file_2_expert",
1612
14
                                   "Expert: File Information?",
1613
14
                                   "Whether the NCP dissector should echo file open/close/oplock information to the expert table.",
1614
14
                                   &ncp_echo_file);
1615
14
    register_init_routine(&mncp_init_protocol);
1616
14
    register_cleanup_routine(&mncp_cleanup_protocol);
1617
14
    ncp_tap.stat=register_tap("ncp_srt");
1618
14
    ncp_tap.hdr=register_tap("ncp");
1619
1620
14
    register_conversation_table(proto_ncp, false, ncp_conversation_packet, ncp_endpoint_packet);
1621
14
    register_srt_table(proto_ncp, "ncp_srt", 24, ncpstat_packet, ncpstat_init, NULL);
1622
14
}
1623
1624
void
1625
proto_reg_handoff_ncp(void)
1626
14
{
1627
14
    dissector_add_uint_with_preference("tcp.port", TCP_PORT_NCP, ncp_tcp_handle);
1628
14
    dissector_add_uint("udp.port", UDP_PORT_NCP, ncp_handle);
1629
14
    dissector_add_uint("ipx.packet_type", IPX_PACKET_TYPE_NCP, ncp_handle);
1630
14
    dissector_add_uint("ipx.socket", IPX_SOCKET_NCP, ncp_handle);
1631
14
}
1632
1633
/*
1634
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1635
 *
1636
 * Local variables:
1637
 * c-basic-offset: 4
1638
 * tab-width: 8
1639
 * indent-tabs-mode: nil
1640
 * End:
1641
 *
1642
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1643
 * :indentSize=4:tabSize=8:noTabs=true:
1644
 */
1645