/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 | | |