Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-ncp2222.inc
blobc1700b6bf208566d947d69e32b02af0933b4688e
1 #define FAKE_TREE_IS_VISIBLE 1
2 /* fake that the tree is visible so that proto.c will not try to
3  "fake" generation of finfo values/nodes.
4   Thus this means netware dissector is slower than it has to, but it wont crash.
5   once the dissector is refactored to avoid calling fvalue_ functions directly this faking of whether the tree is visible or not can be removed.
6 */
9 /* packet-ncp2222.inc
10  *
11  * Routines for NetWare Core Protocol. This C code gets #include'd
12  * into packet-ncp2222.c, which is generated from ncp2222.py. It's
13  * #include'd instead of being in a separate compilation unit so
14  * that all the data tables in packet-ncp2222.c can remain static.
15  *
16  * Gilbert Ramirez <gram@alumni.rice.edu>
17  * Modified to decode NDS packets by Greg Morris <gmorris@novell.com>
18  *
19  * Portions Copyright (c) Gilbert Ramirez 2000-2002
20  * Portions Copyright (c) Novell, Inc. 2000-2003
21  *
22  * Wireshark - Network traffic analyzer
23  * By Gerald Combs <gerald@wireshark.org>
24  * Copyright 2000 Gerald Combs
25  *
26  * SPDX-License-Identifier: GPL-2.0-or-later
27  */
29 bool nds_defragment  = true;
30 bool nds_echo_eid    = true;
31 bool ncp_echo_err    = true;
32 bool ncp_echo_conn;
33 bool ncp_echo_server = true;
34 bool ncp_echo_file;
35 bool ncp_newstyle    = true;
37 extern dissector_handle_t nds_data_handle;
38 typedef struct {
39     uint32_t    nds_frag_verb;
40     uint32_t    nds_frag_version;
41     uint32_t    nds_frag_flags;
42     uint32_t    nds_frag_prot_flags;
43     uint32_t    nds_length;
44     uint32_t    nds_frag;
45     bool        nds_fragmented;
46     uint8_t     sequence;
47 } frag_info;
49 static frag_info           frags[100];
50 static char    mv_resolve_name_string[128];
52 static const fragment_items nds_frag_items = {
53     &ett_nds_segment,
54     &ett_nds_segments,
55     &hf_nds_segments,
56     &hf_nds_segment,
57     &hf_nds_segment_overlap,
58     &hf_nds_segment_overlap_conflict,
59     &hf_nds_segment_multiple_tails,
60     &hf_nds_segment_too_long_segment,
61     &hf_nds_segment_error,
62     &hf_nds_segment_count,
63     NULL,
64     &hf_nds_reassembled_length,
65     /* Reassembled data field */
66     NULL,
67     "segments"
70 /* Table for reassembly of fragments. */
71 static reassembly_table nds_reassembly_table;
73 #define NDS_TAG_NO_SUCH_ENTRY           0x00000000
74 #define NDS_TAG_LOCAL_ENTRY             0x00000001
75 #define NDS_TAG_REMOTE_ENTRY            0x00000002
76 #define NDS_TAG_ALIAS_ENTRY             0x00000003
77 #define NDS_TAG_REFERRAL_INFORMATION    0x00000004
78 #define NDS_TAG_ENTRY_AND_REFERRALS     0x00000006
80 /* Search objects */
81 #define NDS_SEARCH_ENTRY                         0
82 #define NDS_SEARCH_SUBORDINATES                  1
83 #define NDS_SEARCH_SUBTREE                       2
84 #define NDS_SEARCH_PARTITION                     3
86 /* Search Referral Types */
87 #define NDS_ALIAS_REFERRAL                       0
88 #define NDS_PARTITION_REFERRAL                   1
90 /* Search Filter Types */
91 #define NDS_SEARCH_ITEM                          0
92 #define NDS_SEARCH_OR                            1
93 #define NDS_SEARCH_AND                           2
94 #define NDS_SEARCH_NOT                           3
96 /* Search Operators */
97 #define NDS_SEARCH_EQUAL                         7
98 #define NDS_SEARCH_GREATER_OR_EQUAL              8
99 #define NDS_SEARCH_LESS_OR_EQUAL                 9
100 #define NDS_SEARCH_APPROX                       10
101 #define NDS_SEARCH_PRESENT                      15
102 #define NDS_SEARCH_RDN                          16
103 #define NDS_SEARCH_BASE_CLASS                   17
104 #define NDS_SEARCH_MODIFICATION_GE              18  /* Deprecated, use DS_SEARCH_ENTRY_MTS_GE */
105 #define NDS_SEARCH_VALUE_TIME_GE                19  /* Deprecated, use DS_SEARCH_VALUE_MTS_GE */
106 #define NDS_SEARCH_REFERENCES                   20
107 #define NDS_SEARCH_DN_IN_VALUE                  21
108 #define NDS_SEARCH_SCHEMA_IN_VALUE              22
109 #define NDS_SEARCH_ENTRY_FLAGS                  23
110 #define NDS_SEARCH_ENTRY_HAS_FLAG               24
111 #define NDS_SEARCH_VALUE_FLAGS                  25
112 #define NDS_SEARCH_VALUE_HAS_FLAG               26
113 #define NDS_SEARCH_ATTR_FLAGS                   27
114 #define NDS_SEARCH_ATTR_HAS_FLAG                28
115 #define NDS_SEARCH_EID                          29
117 #define NDS_SEARCH_ENTRY_MTS_GE                 18
118 #define NDS_SEARCH_ENTRY_MTS_G                  30
119 #define NDS_SEARCH_ENTRY_MTS_LE                 31
120 #define NDS_SEARCH_ENTRY_MTS_L                  32
121 #define NDS_SEARCH_ENTRY_MTS_EQ                 33
122 #define NDS_SEARCH_ENTRY_MTS_EQ_APPROX          34
123 #define NDS_SEARCH_VALUE_MTS_GE                 19
124 #define NDS_SEARCH_VALUE_MTS_G                  35
125 #define NDS_SEARCH_VALUE_MTS_LE                 36
126 #define NDS_SEARCH_VALUE_MTS_L                  37
127 #define NDS_SEARCH_VALUE_MTS_EQ                 38
128 #define NDS_SEARCH_VALUE_MTS_EQ_APPROX          39
130 #define NDS_SEARCH_ENTRY_CTS_GE                 40
131 #define NDS_SEARCH_ENTRY_CTS_G                  41
132 #define NDS_SEARCH_ENTRY_CTS_LE                 42
133 #define NDS_SEARCH_ENTRY_CTS_L                  43
134 #define NDS_SEARCH_ENTRY_CTS_EQ                 44
135 #define NDS_SEARCH_ENTRY_CTS_EQ_APPROX          45
136 #define NDS_SEARCH_VALUE_CTS_GE                 46
137 #define NDS_SEARCH_VALUE_CTS_G                  47
138 #define NDS_SEARCH_VALUE_CTS_LE                 48
139 #define NDS_SEARCH_VALUE_CTS_L                  49
140 #define NDS_SEARCH_VALUE_CTS_EQ                 50
141 #define NDS_SEARCH_VALUE_CTS_EQ_APPROX          51
142 #define NDS_SEARCH_EXTENSIBLE                   52
143 #define NDS_SEARCH_ENTRY_SUBCOUNT_GE            53
144 #define NDS_SEARCH_ENTRY_SUBCOUNT_G             54
145 #define NDS_SEARCH_ENTRY_SUBCOUNT_LE            55
146 #define NDS_SEARCH_ENTRY_SUBCOUNT_L             56
147 #define NDS_SEARCH_ENTRY_SUBCOUNT_EQ            57
149 #define DCS_OPS                         0x10000000L
150 #define DCS_MOD_GE_WITH_ATTR            DCS_OPS + NDS_SEARCH_MODIFICATION_GE
151 #define DCS_VALUE_GE_WITH_ATTR          DCS_OPS + NDS_SEARCH_VALUE_TIME_GE
152 #define DCS_MASK                        ~DCS_OPS
154 /* Iterator verbs */
155 #define IT_CLEAR                                 1
156 #define IT_COPY                                  2
157 #define IT_COUNT                                 3
158 #define IT_CREATE                                4
159 #define IT_CURRENT                               5
160 #define IT_DESTROY                               6
161 #define IT_DONE                                  7
162 #define IT_FIRST                                 8
163 #define IT_GETPOSITION                           9
164 #define IT_LAST                                 10
165 #define IT_NEXT                                 11
166 #define IT_PREV                                 12
167 #define IT_POSITION                             13
168 #define IT_POSITION_IT                          14
169 #define IT_SETINDEX                             15
170 #define IT_SETFILTER                            16
171 #define IT_SKIP                                 17
172 #define IT_TYPEDOWN                             18
173 #define IT_ATFIRST                              19
174 #define IT_ATEOF                                20
175 #define IT_GETINDEX                             21
176 #define IT_ISPOSITIONABLE                       22
177 #define IT_ATBOF                                23
178 #define IT_ATLAST                               24
180 /* Iteration information flags */
181 #define DSI_OUTPUT_FIELDS               0x00000001U
182 #define DSI_ENTRY_ID                    0x00000002U
183 #define DSI_ENTRY_FLAGS                 0x00000004U
184 #define DSI_SUBORDINATE_COUNT           0x00000008U
185 #define DSI_MODIFICATION_TIME           0x00000010U
186 #define DSI_MODIFICATION_TIMESTAMP      0x00000020U
187 #define DSI_CREATION_TIMESTAMP          0x00000040U
188 #define DSI_PARTITION_ROOT_ID           0x00000080U
189 #define DSI_PARENT_ID                   0x00000100U
190 #define DSI_REVISION_COUNT              0x00000200U
191 #define DSI_REPLICA_TYPE                0x00000400U
192 #define DSI_BASE_CLASS                  0x00000800U
193 #define DSI_ENTRY_RDN                   0x00001000U
194 #define DSI_ENTRY_DN                    0x00002000U
195 #define DSI_PARTITION_ROOT_DN           0x00004000U
196 #define DSI_PARENT_DN                   0x00008000U
197 #define DSI_PURGE_TIME                  0x00010000U
198 #define DSI_DEREFERENCED_BASE_CLASS     0x00020000U
199 #define DSI_REPLICA_NUMBER              0x00040000U
200 #define DSI_REPLICA_STATE               0x00080000U
201 #define DSI_FEDERATION_BOUNDARY         0x00100000U
202 #define DSI_SCHEMA_BOUNDARY             0x00200000U
203 #define DSI_FEDERATION_BOUNDARY_ID      0x00400000U
204 #define DSI_SCHEMA_BOUNDARY_ID          0x00800000U
205 #define DSI_CUR_SUBCOUNT                0x01000000U
206 #define DSI_LOCAL_ENTRY_FLAGS           0x02000000U
208 static const value_string zensearchenum[] = {
209     { 0, "[Root]" },
210     { 1, "Object Container" },
211     { 2, "Associated Container" },
212     { 3, "Selected Container" },
213     {0, NULL }
216 static const value_string itersearchenum[] = {
217     { NDS_SEARCH_ITEM, "Search Item" },
218     { NDS_SEARCH_OR, "OR" },
219     { NDS_SEARCH_AND, "AND" },
220     { NDS_SEARCH_NOT, "NOT" },
221     { NDS_SEARCH_EQUAL, "Equals" },
222     { NDS_SEARCH_GREATER_OR_EQUAL, "Greater or Equals" },
223     { NDS_SEARCH_LESS_OR_EQUAL, "Less or Equals" },
224     { NDS_SEARCH_APPROX, "Approximately" },
225     { NDS_SEARCH_PRESENT, "Present" },
226     { NDS_SEARCH_RDN, "Relative Distinguished Name" },
227     { NDS_SEARCH_BASE_CLASS, "Base Class" },
228     { NDS_SEARCH_MODIFICATION_GE, "Modification Greater or Equal" },
229     { NDS_SEARCH_VALUE_TIME_GE, "Time Value Greater or Equal" },
230     { NDS_SEARCH_REFERENCES, "References" },
231     { NDS_SEARCH_DN_IN_VALUE, "Designated Name in Value" },
232     { NDS_SEARCH_SCHEMA_IN_VALUE, "Schema in Value" },
233     { NDS_SEARCH_ENTRY_FLAGS, "Entry Flags" },
234     { NDS_SEARCH_ENTRY_HAS_FLAG, "Entry has Flags" },
235     { NDS_SEARCH_VALUE_FLAGS, "Value Flags" },
236     { NDS_SEARCH_VALUE_HAS_FLAG, "Value has Flags" },
237     { NDS_SEARCH_ATTR_FLAGS, "Attribute Flags" },
238     { NDS_SEARCH_ATTR_HAS_FLAG, "Attribute has Flags" },
239     { NDS_SEARCH_EID, "Entry ID" },
240     { NDS_SEARCH_ENTRY_MTS_GE, "Entry Modification Timestamp Greater or Equal" },
241     { NDS_SEARCH_ENTRY_MTS_G, "Entry Modification Timestamp Greater" },
242     { NDS_SEARCH_ENTRY_MTS_LE, "Entry Modification Timestamp Less or Equals" },
243     { NDS_SEARCH_ENTRY_MTS_L, "Entry Modification Timestamp Less" },
244     { NDS_SEARCH_ENTRY_MTS_EQ, "Entry Modification Timestamp Equals" },
245     { NDS_SEARCH_ENTRY_MTS_EQ_APPROX, "Entry Modification Timestamp Equals Approximately" },
246     { NDS_SEARCH_VALUE_MTS_GE, "Value Modification Timestamp Greater or Equal" },
247     { NDS_SEARCH_VALUE_MTS_G, "Value Modification Timestamp Greater" },
248     { NDS_SEARCH_VALUE_MTS_LE, "Value Modification Timestamp Less or Equals" },
249     { NDS_SEARCH_VALUE_MTS_L, "Value Modification Timestamp Less" },
250     { NDS_SEARCH_VALUE_MTS_EQ, "Value Modification Timestamp Equals" },
251     { NDS_SEARCH_VALUE_MTS_EQ_APPROX, "Value Modification Timestamp Equals Approximately" },
252     { NDS_SEARCH_ENTRY_CTS_GE, "Entry Creation Timestamp Greater or Equals" },
253     { NDS_SEARCH_ENTRY_CTS_G, "Entry Creation Timestamp Greater" },
254     { NDS_SEARCH_ENTRY_CTS_LE, "Entry Creation Timestamp Less or Equals" },
255     { NDS_SEARCH_ENTRY_CTS_L, "Entry Creation Timestamp Less" },
256     { NDS_SEARCH_ENTRY_CTS_EQ, "Entry Creation Timestamp Equals" },
257     { NDS_SEARCH_ENTRY_CTS_EQ_APPROX, "Entry Creation Timestamp Equals Approximately" },
258     { NDS_SEARCH_VALUE_CTS_GE, "Value Creation Timestamp Greater or Equals" },
259     { NDS_SEARCH_VALUE_CTS_G, "Value Creation Timestamp Greater" },
260     { NDS_SEARCH_VALUE_CTS_LE, "Value Creation Timestamp Less or Equals" },
261     { NDS_SEARCH_VALUE_CTS_L, "Value Creation Timestamp Less" },
262     { NDS_SEARCH_VALUE_CTS_EQ, "Value Creation Timestamp Equals" },
263     { NDS_SEARCH_VALUE_CTS_EQ_APPROX, "Value Creation Timestamp Equals Approximately" },
264     { NDS_SEARCH_EXTENSIBLE, "Extensible" },
265     { NDS_SEARCH_ENTRY_SUBCOUNT_GE, "Entry SubCount Greater or Equals" },
266     { NDS_SEARCH_ENTRY_SUBCOUNT_G, "Entry SubCount Greater" },
267     { NDS_SEARCH_ENTRY_SUBCOUNT_LE, "Entry SubCount Less or Equals" },
268     { NDS_SEARCH_ENTRY_SUBCOUNT_L, "Entry SubCount Less" },
269     { NDS_SEARCH_ENTRY_SUBCOUNT_EQ, "Entry SubCount Equals" },
270     {0, NULL }
273 static const value_string iterator_subverbs[] = {
274     { IT_CLEAR, "Clear" },
275     { IT_COPY, "Copy" },
276     { IT_COUNT, "Count" },
277     { IT_CREATE, "Create" },
278     { IT_CURRENT, "Current" },
279     { IT_DESTROY, "Destroy" },
280     { IT_DONE, "Done" },
281     { IT_FIRST, "First" },
282     { IT_GETPOSITION, "Get Position" },
283     { IT_LAST, "Last" },
284     { IT_NEXT, "Next" },
285     { IT_PREV, "Previous" },
286     { IT_POSITION, "Position" },
287     { IT_POSITION_IT, "Position Iterator" },
288     { IT_SETINDEX, "Set Index" },
289     { IT_SETFILTER, "Set Filter" },
290     { IT_SKIP, "Skip" },
291     { IT_TYPEDOWN, "Type Down" },
292     { IT_ATFIRST, "At First" },
293     { IT_ATEOF, "At End of File" },
294     { IT_GETINDEX, "Get Index" },
295     { IT_ISPOSITIONABLE, "Is Positionable" },
296     { IT_ATBOF, "At Beginning of File" },
297     { IT_ATLAST, "At Last" },
298     { 0, NULL }
302 static const value_string nds_tuned_tags[] = {
303     { 0, "RDN Hint" },
304     { 1, "RDN History" },
305     {0, NULL }
308 #if 0
309 static const value_string nds_scope_vals[] = {
310     { 0, "Search Scope: 0x0000 - Examine base object only" },
311     { 1, "Search Scope: 0x0001 - Search the immediate subordinates of the base object" },
312     { 2, "Search Scope: 0x0002 - Search the base object and all of its subordinates" },
313     { 3, "Search Scope: 0x0003 - Search the base objects and all objects in its partition (NDS version 8 or higher)" },
314     {0, NULL }
316 #endif
318 static const value_string nds_tuned_item_tags[] = {
319     { 0, "Single Item" },
320     { 1, "Multiple Items" },
321     {0, NULL }
324 static const value_string nds_tags[] = {
325     { NDS_TAG_NO_SUCH_ENTRY,        "No Such Entry" },
326     { NDS_TAG_LOCAL_ENTRY,          "Local Entry" },
327     { NDS_TAG_REMOTE_ENTRY,         "Remote Entry" },
328     { NDS_TAG_ALIAS_ENTRY,          "Alias Entry" },
329     { NDS_TAG_REFERRAL_INFORMATION, "Referral Information" },
330     { NDS_TAG_ENTRY_AND_REFERRALS,  "Entry and Referrals" },
331     { 0, NULL }
334 static const range_string nds_info_type[] = {
335     { 0x00000000, 0x00000000, "Attribute Names Only / " },
336     { 0x00000001, 0x00000001, "Attribute Name & Value / " },
337     { 0x00000002, 0x00000002, "Effective Privileges / " },
338     { 0x00000003, 0x00000003, "Value Information / " },
339     { 0x00000004, 0x00000004, "Abbreviated Value / " },
340     { 0x00000005, 0xFFFFFFFF, "No Info Type Set" },
341     { 0, 0, NULL }
344 static const value_string nds_kind_of_changes[] = {
345     { 0x00000000, "Add Attribute" },
346     { 0x00000001, "Remove Attribute" },
347     { 0x00000002, "Add Value" },
348     { 0x00000003, "Remove Value" },
349     { 0x00000004, "Add Additional Value" },
350     { 0x00000005, "Overwrite Value" },
351     { 0x00000006, "Clear Attribute" },
352     { 0x00000007, "Clear Value" },
353     { 0, NULL }
356 static const value_string es_type[] = {
357     { 0x00000000, "No type is specified" },
358     { 0x00000001, "Unicode string" },
359     { 0x00000002, "Partial name" },
360     { 0x00000003, "Referrals" },
361     { 0x00000004, "Tuned name" },
362     { 0x00000005, "GUID attribute" },
363     { 0x00000006, "Local entry ID" },
364     { 0x00000007, "Number of defined entry specifiers" },
365     { 0, NULL }
368 static const value_string ncp_rights_vals[] = {
369     { 0x00, "No Rights"},
370     { 0x01, "Read"},
371     { 0x02, "Write"},
372     { 0x03, "Read, Write"},
373     { 0x04, "Deny Read"},
374     { 0x05, "Read, Deny Read"},
375     { 0x06, "Write, Deny Read"},
376     { 0x07, "Read, Write, Deny Read"},
377     { 0x08, "Deny Write"},
378     { 0x09, "Read, Deny Write"},
379     { 0x0a, "Write, Deny Write"},
380     { 0x0b, "Read, Write, Deny Write"},
381     { 0x0c, "Deny Read, Deny Write"},
382     { 0x0d, "Read, Deny Read, Deny Write"},
383     { 0x0e, "Write, Deny Read, Deny Write"},
384     { 0x0f, "Read, Write, Deny Read, Deny Write"},
385     { 0x10, "Compatibility"},
386     { 0x11, "Read, Compatibility"},
387     { 0x12, "Write, Compatibility"},
388     { 0x13, "Read, Write, Compatibility"},
389     { 0x14, "Deny Read, Compatibility"},
390     { 0x15, "Read, Deny Read, Compatibility"},
391     { 0x16, "Write, Deny Read, Compatibility"},
392     { 0x17, "Read, Write, Deny Read, Compatibility"},
393     { 0x18, "Deny Write, Compatibility"},
394     { 0x19, "Read, Deny Write, Compatibility"},
395     { 0x1a, "Write, Deny Write, Compatibility"},
396     { 0x1b, "Read, Write, Deny Write, Compatibility"},
397     { 0x1c, "Deny Read, Deny Write, Compatibility"},
398     { 0x1d, "Read, Deny Read, Deny Write, Compatibility"},
399     { 0x1e, "Write, Deny Read, Deny Write, Compatibility"},
400     { 0x1f, "Read, Write, Deny Read, Deny Write, Compatibility"},
401     { 0x40, "File Write Through"},
402     { 0x41, "Read, File Write Through"},
403     { 0x42, "Write, File Write Through"},
404     { 0x43, "Read, Write, File Write Through"},
405     { 0x44, "Deny Read, File Write Through"},
406     { 0x45, "Read, Deny Read, File Write Through"},
407     { 0x46, "Write, Deny Read, File Write Through"},
408     { 0x47, "Read, Write, Deny Read, File Write Through"},
409     { 0x48, "Deny Write, File Write Through"},
410     { 0x49, "Read, Deny Write, File Write Through"},
411     { 0x4a, "Write, Deny Write, File Write Through"},
412     { 0x4b, "Read, Write, Deny Write, File Write Through"},
413     { 0x4c, "Deny Read, Deny Write, File Write Through"},
414     { 0x4d, "Read, Deny Read, Deny Write, File Write Through"},
415     { 0x4e, "Write, Deny Read, Deny Write, File Write Through"},
416     { 0x4f, "Read, Write, Deny Read, Deny Write, File Write Through"},
417     { 0x50, "Compatibility, File Write Through"},
418     { 0x51, "Read, Compatibility, File Write Through"},
419     { 0x52, "Write, Compatibility, File Write Through"},
420     { 0x53, "Read, Write, Compatibility, File Write Through"},
421     { 0x54, "Deny Read, Compatibility, File Write Through"},
422     { 0x55, "Read, Deny Read, Compatibility, File Write Through"},
423     { 0x56, "Write, Deny Read, Compatibility, File Write Through"},
424     { 0x57, "Read, Write, Deny Read, Compatibility, File Write Through"},
425     { 0x58, "Deny Write, Compatibility, File Write Through"},
426     { 0x59, "Read, Deny Write, Compatibility, File Write Through"},
427     { 0x5a, "Write, Deny Write, Compatibility, File Write Through"},
428     { 0x5b, "Read, Write, Deny Write, Compatibility, File Write Through"},
429     { 0x5c, "Deny Read, Deny Write, Compatibility, File Write Through"},
430     { 0x5d, "Read, Deny Read, Deny Write, Compatibility, File Write Through"},
431     { 0x5e, "Write, Deny Read, Deny Write, Compatibility, File Write Through"},
432     { 0x5f, "Read, Write, Deny Read, Deny Write, Compatibility, File Write Through"},
433     { 0,    NULL }
436 static const value_string open_create_mode_vals[] = {
437     { 0x01, "Open"},
438     { 0x02, "Replace"},
439     { 0x03, "Open, Replace"},
440     { 0x08, "Create"},
441     { 0x09, "Open, Create"},
442     { 0x0a, "Replace, Create"},
443     { 0x0b, "Open, Replace, Create"},
444     { 0x20, "64-bit"},
445     { 0x21, "Open, 64-bit"},
446     { 0x22, "Replace, 64-bit"},
447     { 0x23, "Open, Replace, 64-bit"},
448     { 0x28, "Create, 64-bit"},
449     { 0x29, "Open, Create, 64-bit"},
450     { 0x2a, "Replace, Create, 64-bit"},
451     { 0x2b, "Open, Replace, Create, 64-bit"},
452     { 0x40, "Read Only"},
453     { 0x41, "Open, Read Only"},
454     { 0x42, "Replace, Read Only"},
455     { 0x43, "Open, Replace, Read Only"},
456     { 0x48, "Create, Read Only"},
457     { 0x49, "Open, Create, Read Only"},
458     { 0x4a, "Replace, Create, Read Only"},
459     { 0x4b, "Open, Replace, Create, Read Only"},
460     { 0x60, "64-bit, Read Only"},
461     { 0x61, "Open, 64-bit, Read Only"},
462     { 0x62, "Replace, 64-bit, Read Only"},
463     { 0x63, "Open, Replace, 64-bit, Read Only"},
464     { 0x68, "Create, 64-bit, Read Only"},
465     { 0x69, "Open, Create, 64-bit, Read Only"},
466     { 0x6a, "Replace, Create, 64-bit, Read Only"},
467     { 0x6b, "Open, Replace, Create, 64-bit, Read Only"},
468     { 0x80, "Op-Lock"},
469     { 0x81, "Open, Op-Lock"},
470     { 0x82, "Replace, Op-Lock"},
471     { 0x83, "Open, Replace, Op-Lock"},
472     { 0x88, "Create, Op-Lock"},
473     { 0x89, "Open, Create, Op-Lock"},
474     { 0x8a, "Replace, Create, Op-Lock"},
475     { 0x8b, "Open, Replace, Create, Op-Lock"},
476     { 0xa0, "64-bit, Op-Lock"},
477     { 0xa1, "Open, 64-bit, Op-Lock"},
478     { 0xa2, "Replace, 64-bit, Op-Lock"},
479     { 0xa3, "Open, Replace, 64-bit, Op-Lock"},
480     { 0xa8, "Create, 64-bit, Op-Lock"},
481     { 0xa9, "Open, Create, 64-bit, Op-Lock"},
482     { 0xaa, "Replace, Create, 64-bit, Op-Lock"},
483     { 0xab, "Open, Replace, Create, 64-bit, Op-Lock"},
484     { 0xc0, "Read Only, Op-Lock"},
485     { 0xc1, "Open, Read Only, Op-Lock"},
486     { 0xc2, "Replace, Read Only, Op-Lock"},
487     { 0xc3, "Open, Replace, Read Only, Op-Lock"},
488     { 0xc8, "Create, Read Only, Op-Lock"},
489     { 0xc9, "Open, Create, Read Only, Op-Lock"},
490     { 0xca, "Replace, Create, Read Only, Op-Lock"},
491     { 0xcb, "Open, Replace, Create, Read Only, Op-Lock"},
492     { 0xe0, "64-bit, Read Only, Op-Lock"},
493     { 0xe1, "Open, 64-bit, Read Only, Op-Lock"},
494     { 0xe2, "Replace, 64-bit, Read Only, Op-Lock"},
495     { 0xe3, "Open, Replace, 64-bit, Read Only, Op-Lock"},
496     { 0xe8, "Create, 64-bit, Read Only, Op-Lock"},
497     { 0xe9, "Open, Create, 64-bit, Read Only, Op-Lock"},
498     { 0xea, "Replace, Create, 64-bit, Read Only, Op-Lock"},
499     { 0xeb, "Open, Replace, Create, 64-bit, Read Only, Op-Lock"},
500     { 0,    NULL }
503 static const value_string open_create_action_vals[] = {
504     { 0x01, "Opened"},
505     { 0x02, "Created"},
506     { 0x03, "Opened, Created"},
507     { 0x04, "Replaced"},
508     { 0x05, "Opened, Replaced"},
509     { 0x06, "Created, Replaced"},
510     { 0x07, "Opened, Created, Replaced"},
511     { 0x08, "Compressed"},
512     { 0x09, "Opened, Compressed"},
513     { 0x0a, "Created, Compressed"},
514     { 0x0b, "Opened, Created, Compressed"},
515     { 0x0c, "Replaced, Compressed"},
516     { 0x0d, "Opened, Replaced, Compressed"},
517     { 0x0e, "Created, Replaced, Compressed"},
518     { 0x0f, "Opened, Created, Replaced, Compressed"},
519     { 0x80, "Read Only"},
520     { 0x81, "Opened, Read Only"},
521     { 0x82, "Created, Read Only"},
522     { 0x83, "Opened, Created, Read Only"},
523     { 0x84, "Replaced, Read Only"},
524     { 0x85, "Opened, Replaced, Read Only"},
525     { 0x86, "Created, Replaced, Read Only"},
526     { 0x87, "Opened, Created, Replaced, Read Only"},
527     { 0x88, "Compressed, Read Only"},
528     { 0x89, "Opened, Compressed, Read Only"},
529     { 0x8a, "Created, Compressed, Read Only"},
530     { 0x8b, "Opened, Created, Compressed, Read Only"},
531     { 0x8c, "Replaced, Compressed, Read Only"},
532     { 0x8d, "Opened, Replaced, Compressed, Read Only"},
533     { 0x8e, "Created, Replaced, Compressed, Read Only"},
534     { 0x8f, "Opened, Created, Replaced, Compressed, Read Only"},
535     { 0,    NULL }
538 static const value_string access_rights_vals[] = {
539     { 0x0000, "No Rights"},
540     { 0x0001, "Read"},
541     { 0x0002, "Write"},
542     { 0x0003, "Read, Write"},
543     { 0x0004, "Open"},
544     { 0x0005, "Read, Open"},
545     { 0x0006, "Write, Open"},
546     { 0x0007, "Read, Write, Open"},
547     { 0x0008, "Create"},
548     { 0x0009, "Read, Create"},
549     { 0x000a, "Write, Create"},
550     { 0x000b, "Read, Write, Create"},
551     { 0x000c, "Open, Create"},
552     { 0x000d, "Read, Open, Create"},
553     { 0x000e, "Write, Open, Create"},
554     { 0x000f, "Read, Write, Open, Create"},
555     { 0x0010, "Delete"},
556     { 0x0011, "Read, Delete"},
557     { 0x0012, "Write, Delete"},
558     { 0x0013, "Read, Write, Delete"},
559     { 0x0014, "Open, Delete"},
560     { 0x0015, "Read, Open, Delete"},
561     { 0x0016, "Write, Open, Delete"},
562     { 0x0017, "Read, Write, Open, Delete"},
563     { 0x0018, "Create, Delete"},
564     { 0x0019, "Read, Create, Delete"},
565     { 0x001a, "Write, Create, Delete"},
566     { 0x001b, "Read, Write, Create, Delete"},
567     { 0x001c, "Open, Create, Delete"},
568     { 0x001d, "Read, Open, Create, Delete"},
569     { 0x001e, "Write, Open, Create, Delete"},
570     { 0x001f, "Read, Write, Open, Create, Delete"},
571     { 0x0020, "Parental"},
572     { 0x0021, "Read, Parental"},
573     { 0x0022, "Write, Parental"},
574     { 0x0023, "Read, Write, Parental"},
575     { 0x0024, "Open, Parental"},
576     { 0x0025, "Read, Open, Parental"},
577     { 0x0026, "Write, Open, Parental"},
578     { 0x0027, "Read, Write, Open, Parental"},
579     { 0x0028, "Create, Parental"},
580     { 0x0029, "Read, Create, Parental"},
581     { 0x002a, "Write, Create, Parental"},
582     { 0x002b, "Read, Write, Create, Parental"},
583     { 0x002c, "Open, Create, Parental"},
584     { 0x002d, "Read, Open, Create, Parental"},
585     { 0x002e, "Write, Open, Create, Parental"},
586     { 0x002f, "Read, Write, Open, Create, Parental"},
587     { 0x0030, "Delete, Parental"},
588     { 0x0031, "Read, Delete, Parental"},
589     { 0x0032, "Write, Delete, Parental"},
590     { 0x0033, "Read, Write, Delete, Parental"},
591     { 0x0034, "Open, Delete, Parental"},
592     { 0x0035, "Read, Open, Delete, Parental"},
593     { 0x0036, "Write, Open, Delete, Parental"},
594     { 0x0037, "Read, Write, Open, Delete, Parental"},
595     { 0x0038, "Create, Delete, Parental"},
596     { 0x0039, "Read, Create, Delete, Parental"},
597     { 0x003a, "Write, Create, Delete, Parental"},
598     { 0x003b, "Read, Write, Create, Delete, Parental"},
599     { 0x003c, "Open, Create, Delete, Parental"},
600     { 0x003d, "Read, Open, Create, Delete, Parental"},
601     { 0x003e, "Write, Open, Create, Delete, Parental"},
602     { 0x003f, "Read, Write, Open, Create, Delete, Parental"},
603     { 0x0040, "Search"},
604     { 0x0041, "Read, Search"},
605     { 0x0042, "Write, Search"},
606     { 0x0043, "Read, Write, Search"},
607     { 0x0044, "Open, Search"},
608     { 0x0045, "Read, Open, Search"},
609     { 0x0046, "Write, Open, Search"},
610     { 0x0047, "Read, Write, Open, Search"},
611     { 0x0048, "Create, Search"},
612     { 0x0049, "Read, Create, Search"},
613     { 0x004a, "Write, Create, Search"},
614     { 0x004b, "Read, Write, Create, Search"},
615     { 0x004c, "Open, Create, Search"},
616     { 0x004d, "Read, Open, Create, Search"},
617     { 0x004e, "Write, Open, Create, Search"},
618     { 0x004f, "Read, Write, Open, Create, Search"},
619     { 0x0050, "Delete, Search"},
620     { 0x0051, "Read, Delete, Search"},
621     { 0x0052, "Write, Delete, Search"},
622     { 0x0053, "Read, Write, Delete, Search"},
623     { 0x0054, "Open, Delete, Search"},
624     { 0x0055, "Read, Open, Delete, Search"},
625     { 0x0056, "Write, Open, Delete, Search"},
626     { 0x0057, "Read, Write, Open, Delete, Search"},
627     { 0x0058, "Create, Delete, Search"},
628     { 0x0059, "Read, Create, Delete, Search"},
629     { 0x005a, "Write, Create, Delete, Search"},
630     { 0x005b, "Read, Write, Create, Delete, Search"},
631     { 0x005c, "Open, Create, Delete, Search"},
632     { 0x005d, "Read, Open, Create, Delete, Search"},
633     { 0x005e, "Write, Open, Create, Delete, Search"},
634     { 0x005f, "Read, Write, Open, Create, Delete, Search"},
635     { 0x0060, "Parental, Search"},
636     { 0x0061, "Read, Parental, Search"},
637     { 0x0062, "Write, Parental, Search"},
638     { 0x0063, "Read, Write, Parental, Search"},
639     { 0x0064, "Open, Parental, Search"},
640     { 0x0065, "Read, Open, Parental, Search"},
641     { 0x0066, "Write, Open, Parental, Search"},
642     { 0x0067, "Read, Write, Open, Parental, Search"},
643     { 0x0068, "Create, Parental, Search"},
644     { 0x0069, "Read, Create, Parental, Search"},
645     { 0x006a, "Write, Create, Parental, Search"},
646     { 0x006b, "Read, Write, Create, Parental, Search"},
647     { 0x006c, "Open, Create, Parental, Search"},
648     { 0x006d, "Read, Open, Create, Parental, Search"},
649     { 0x006e, "Write, Open, Create, Parental, Search"},
650     { 0x006f, "Read, Write, Open, Create, Parental, Search"},
651     { 0x0070, "Delete, Parental, Search"},
652     { 0x0071, "Read, Delete, Parental, Search"},
653     { 0x0072, "Write, Delete, Parental, Search"},
654     { 0x0073, "Read, Write, Delete, Parental, Search"},
655     { 0x0074, "Open, Delete, Parental, Search"},
656     { 0x0075, "Read, Open, Delete, Parental, Search"},
657     { 0x0076, "Write, Open, Delete, Parental, Search"},
658     { 0x0077, "Read, Write, Open, Delete, Parental, Search"},
659     { 0x0078, "Create, Delete, Parental, Search"},
660     { 0x0079, "Read, Create, Delete, Parental, Search"},
661     { 0x007a, "Write, Create, Delete, Parental, Search"},
662     { 0x007b, "Read, Write, Create, Delete, Parental, Search"},
663     { 0x007c, "Open, Create, Delete, Parental, Search"},
664     { 0x007d, "Read, Open, Create, Delete, Parental, Search"},
665     { 0x007e, "Write, Open, Create, Delete, Parental, Search"},
666     { 0x007f, "Read, Write, Open, Create, Delete, Parental, Search"},
667     { 0x0080, "Modify"},
668     { 0x0081, "Read, Modify"},
669     { 0x0082, "Write, Modify"},
670     { 0x0083, "Read, Write, Modify"},
671     { 0x0084, "Open, Modify"},
672     { 0x0085, "Read, Open, Modify"},
673     { 0x0086, "Write, Open, Modify"},
674     { 0x0087, "Read, Write, Open, Modify"},
675     { 0x0088, "Create, Modify"},
676     { 0x0089, "Read, Create, Modify"},
677     { 0x008a, "Write, Create, Modify"},
678     { 0x008b, "Read, Write, Create, Modify"},
679     { 0x008c, "Open, Create, Modify"},
680     { 0x008d, "Read, Open, Create, Modify"},
681     { 0x008e, "Write, Open, Create, Modify"},
682     { 0x008f, "Read, Write, Open, Create, Modify"},
683     { 0x0090, "Delete, Modify"},
684     { 0x0091, "Read, Delete, Modify"},
685     { 0x0092, "Write, Delete, Modify"},
686     { 0x0093, "Read, Write, Delete, Modify"},
687     { 0x0094, "Open, Delete, Modify"},
688     { 0x0095, "Read, Open, Delete, Modify"},
689     { 0x0096, "Write, Open, Delete, Modify"},
690     { 0x0097, "Read, Write, Open, Delete, Modify"},
691     { 0x0098, "Create, Delete, Modify"},
692     { 0x0099, "Read, Create, Delete, Modify"},
693     { 0x009a, "Write, Create, Delete, Modify"},
694     { 0x009b, "Read, Write, Create, Delete, Modify"},
695     { 0x009c, "Open, Create, Delete, Modify"},
696     { 0x009d, "Read, Open, Create, Delete, Modify"},
697     { 0x009e, "Write, Open, Create, Delete, Modify"},
698     { 0x009f, "Read, Write, Open, Create, Delete, Modify"},
699     { 0x00a0, "Parental, Modify"},
700     { 0x00a1, "Read, Parental, Modify"},
701     { 0x00a2, "Write, Parental, Modify"},
702     { 0x00a3, "Read, Write, Parental, Modify"},
703     { 0x00a4, "Open, Parental, Modify"},
704     { 0x00a5, "Read, Open, Parental, Modify"},
705     { 0x00a6, "Write, Open, Parental, Modify"},
706     { 0x00a7, "Read, Write, Open, Parental, Modify"},
707     { 0x00a8, "Create, Parental, Modify"},
708     { 0x00a9, "Read, Create, Parental, Modify"},
709     { 0x00aa, "Write, Create, Parental, Modify"},
710     { 0x00ab, "Read, Write, Create, Parental, Modify"},
711     { 0x00ac, "Open, Create, Parental, Modify"},
712     { 0x00ad, "Read, Open, Create, Parental, Modify"},
713     { 0x00ae, "Write, Open, Create, Parental, Modify"},
714     { 0x00af, "Read, Write, Open, Create, Parental, Modify"},
715     { 0x00b0, "Delete, Parental, Modify"},
716     { 0x00b1, "Read, Delete, Parental, Modify"},
717     { 0x00b2, "Write, Delete, Parental, Modify"},
718     { 0x00b3, "Read, Write, Delete, Parental, Modify"},
719     { 0x00b4, "Open, Delete, Parental, Modify"},
720     { 0x00b5, "Read, Open, Delete, Parental, Modify"},
721     { 0x00b6, "Write, Open, Delete, Parental, Modify"},
722     { 0x00b7, "Read, Write, Open, Delete, Parental, Modify"},
723     { 0x00b8, "Create, Delete, Parental, Modify"},
724     { 0x00b9, "Read, Create, Delete, Parental, Modify"},
725     { 0x00ba, "Write, Create, Delete, Parental, Modify"},
726     { 0x00bb, "Read, Write, Create, Delete, Parental, Modify"},
727     { 0x00bc, "Open, Create, Delete, Parental, Modify"},
728     { 0x00bd, "Read, Open, Create, Delete, Parental, Modify"},
729     { 0x00be, "Write, Open, Create, Delete, Parental, Modify"},
730     { 0x00bf, "Read, Write, Open, Create, Delete, Parental, Modify"},
731     { 0x00c0, "Search, Modify"},
732     { 0x00c1, "Read, Search, Modify"},
733     { 0x00c2, "Write, Search, Modify"},
734     { 0x00c3, "Read, Write, Search, Modify"},
735     { 0x00c4, "Open, Search, Modify"},
736     { 0x00c5, "Read, Open, Search, Modify"},
737     { 0x00c6, "Write, Open, Search, Modify"},
738     { 0x00c7, "Read, Write, Open, Search, Modify"},
739     { 0x00c8, "Create, Search, Modify"},
740     { 0x00c9, "Read, Create, Search, Modify"},
741     { 0x00ca, "Write, Create, Search, Modify"},
742     { 0x00cb, "Read, Write, Create, Search, Modify"},
743     { 0x00cc, "Open, Create, Search, Modify"},
744     { 0x00cd, "Read, Open, Create, Search, Modify"},
745     { 0x00ce, "Write, Open, Create, Search, Modify"},
746     { 0x00cf, "Read, Write, Open, Create, Search, Modify"},
747     { 0x00d0, "Delete, Search, Modify"},
748     { 0x00d1, "Read, Delete, Search, Modify"},
749     { 0x00d2, "Write, Delete, Search, Modify"},
750     { 0x00d3, "Read, Write, Delete, Search, Modify"},
751     { 0x00d4, "Open, Delete, Search, Modify"},
752     { 0x00d5, "Read, Open, Delete, Search, Modify"},
753     { 0x00d6, "Write, Open, Delete, Search, Modify"},
754     { 0x00d7, "Read, Write, Open, Delete, Search, Modify"},
755     { 0x00d8, "Create, Delete, Search, Modify"},
756     { 0x00d9, "Read, Create, Delete, Search, Modify"},
757     { 0x00da, "Write, Create, Delete, Search, Modify"},
758     { 0x00db, "Read, Write, Create, Delete, Search, Modify"},
759     { 0x00dc, "Open, Create, Delete, Search, Modify"},
760     { 0x00dd, "Read, Open, Create, Delete, Search, Modify"},
761     { 0x00de, "Write, Open, Create, Delete, Search, Modify"},
762     { 0x00df, "Read, Write, Open, Create, Delete, Search, Modify"},
763     { 0x00e0, "Parental, Search, Modify"},
764     { 0x00e1, "Read, Parental, Search, Modify"},
765     { 0x00e2, "Write, Parental, Search, Modify"},
766     { 0x00e3, "Read, Write, Parental, Search, Modify"},
767     { 0x00e4, "Open, Parental, Search, Modify"},
768     { 0x00e5, "Read, Open, Parental, Search, Modify"},
769     { 0x00e6, "Write, Open, Parental, Search, Modify"},
770     { 0x00e7, "Read, Write, Open, Parental, Search, Modify"},
771     { 0x00e8, "Create, Parental, Search, Modify"},
772     { 0x00e9, "Read, Create, Parental, Search, Modify"},
773     { 0x00ea, "Write, Create, Parental, Search, Modify"},
774     { 0x00eb, "Read, Write, Create, Parental, Search, Modify"},
775     { 0x00ec, "Open, Create, Parental, Search, Modify"},
776     { 0x00ed, "Read, Open, Create, Parental, Search, Modify"},
777     { 0x00ee, "Write, Open, Create, Parental, Search, Modify"},
778     { 0x00ef, "Read, Write, Open, Create, Parental, Search, Modify"},
779     { 0x00f0, "Delete, Parental, Search, Modify"},
780     { 0x00f1, "Read, Delete, Parental, Search, Modify"},
781     { 0x00f2, "Write, Delete, Parental, Search, Modify"},
782     { 0x00f3, "Read, Write, Delete, Parental, Search, Modify"},
783     { 0x00f4, "Open, Delete, Parental, Search, Modify"},
784     { 0x00f5, "Read, Open, Delete, Parental, Search, Modify"},
785     { 0x00f6, "Write, Open, Delete, Parental, Search, Modify"},
786     { 0x00f7, "Read, Write, Open, Delete, Parental, Search, Modify"},
787     { 0x00f8, "Create, Delete, Parental, Search, Modify"},
788     { 0x00f9, "Read, Create, Delete, Parental, Search, Modify"},
789     { 0x00fa, "Write, Create, Delete, Parental, Search, Modify"},
790     { 0x00fb, "Read, Write, Create, Delete, Parental, Search, Modify"},
791     { 0x00fc, "Open, Create, Delete, Parental, Search, Modify"},
792     { 0x00fd, "Read, Open, Create, Delete, Parental, Search, Modify"},
793     { 0x00fe, "Write, Open, Create, Delete, Parental, Search, Modify"},
794     { 0x00ff, "Read, Write, Open, Create, Delete, Parental, Search, Modify"},
795     { 0x0100, "Supervisor"},
796     { 0x0101, "Read, Supervisor"},
797     { 0x0102, "Write, Supervisor"},
798     { 0x0103, "Read, Write, Supervisor"},
799     { 0x0104, "Open, Supervisor"},
800     { 0x0105, "Read, Open, Supervisor"},
801     { 0x0106, "Write, Open, Supervisor"},
802     { 0x0107, "Read, Write, Open, Supervisor"},
803     { 0x0108, "Create, Supervisor"},
804     { 0x0109, "Read, Create, Supervisor"},
805     { 0x010a, "Write, Create, Supervisor"},
806     { 0x010b, "Read, Write, Create, Supervisor"},
807     { 0x010c, "Open, Create, Supervisor"},
808     { 0x010d, "Read, Open, Create, Supervisor"},
809     { 0x010e, "Write, Open, Create, Supervisor"},
810     { 0x010f, "Read, Write, Open, Create, Supervisor"},
811     { 0x0110, "Delete, Supervisor"},
812     { 0x0111, "Read, Delete, Supervisor"},
813     { 0x0112, "Write, Delete, Supervisor"},
814     { 0x0113, "Read, Write, Delete, Supervisor"},
815     { 0x0114, "Open, Delete, Supervisor"},
816     { 0x0115, "Read, Open, Delete, Supervisor"},
817     { 0x0116, "Write, Open, Delete, Supervisor"},
818     { 0x0117, "Read, Write, Open, Delete, Supervisor"},
819     { 0x0118, "Create, Delete, Supervisor"},
820     { 0x0119, "Read, Create, Delete, Supervisor"},
821     { 0x011a, "Write, Create, Delete, Supervisor"},
822     { 0x011b, "Read, Write, Create, Delete, Supervisor"},
823     { 0x011c, "Open, Create, Delete, Supervisor"},
824     { 0x011d, "Read, Open, Create, Delete, Supervisor"},
825     { 0x011e, "Write, Open, Create, Delete, Supervisor"},
826     { 0x011f, "Read, Write, Open, Create, Delete, Supervisor"},
827     { 0x0120, "Parental, Supervisor"},
828     { 0x0121, "Read, Parental, Supervisor"},
829     { 0x0122, "Write, Parental, Supervisor"},
830     { 0x0123, "Read, Write, Parental, Supervisor"},
831     { 0x0124, "Open, Parental, Supervisor"},
832     { 0x0125, "Read, Open, Parental, Supervisor"},
833     { 0x0126, "Write, Open, Parental, Supervisor"},
834     { 0x0127, "Read, Write, Open, Parental, Supervisor"},
835     { 0x0128, "Create, Parental, Supervisor"},
836     { 0x0129, "Read, Create, Parental, Supervisor"},
837     { 0x012a, "Write, Create, Parental, Supervisor"},
838     { 0x012b, "Read, Write, Create, Parental, Supervisor"},
839     { 0x012c, "Open, Create, Parental, Supervisor"},
840     { 0x012d, "Read, Open, Create, Parental, Supervisor"},
841     { 0x012e, "Write, Open, Create, Parental, Supervisor"},
842     { 0x012f, "Read, Write, Open, Create, Parental, Supervisor"},
843     { 0x0130, "Delete, Parental, Supervisor"},
844     { 0x0131, "Read, Delete, Parental, Supervisor"},
845     { 0x0132, "Write, Delete, Parental, Supervisor"},
846     { 0x0133, "Read, Write, Delete, Parental, Supervisor"},
847     { 0x0134, "Open, Delete, Parental, Supervisor"},
848     { 0x0135, "Read, Open, Delete, Parental, Supervisor"},
849     { 0x0136, "Write, Open, Delete, Parental, Supervisor"},
850     { 0x0137, "Read, Write, Open, Delete, Parental, Supervisor"},
851     { 0x0138, "Create, Delete, Parental, Supervisor"},
852     { 0x0139, "Read, Create, Delete, Parental, Supervisor"},
853     { 0x013a, "Write, Create, Delete, Parental, Supervisor"},
854     { 0x013b, "Read, Write, Create, Delete, Parental, Supervisor"},
855     { 0x013c, "Open, Create, Delete, Parental, Supervisor"},
856     { 0x013d, "Read, Open, Create, Delete, Parental, Supervisor"},
857     { 0x013e, "Write, Open, Create, Delete, Parental, Supervisor"},
858     { 0x013f, "Read, Write, Open, Create, Delete, Parental, Supervisor"},
859     { 0x0140, "Search, Supervisor"},
860     { 0x0141, "Read, Search, Supervisor"},
861     { 0x0142, "Write, Search, Supervisor"},
862     { 0x0143, "Read, Write, Search, Supervisor"},
863     { 0x0144, "Open, Search, Supervisor"},
864     { 0x0145, "Read, Open, Search, Supervisor"},
865     { 0x0146, "Write, Open, Search, Supervisor"},
866     { 0x0147, "Read, Write, Open, Search, Supervisor"},
867     { 0x0148, "Create, Search, Supervisor"},
868     { 0x0149, "Read, Create, Search, Supervisor"},
869     { 0x014a, "Write, Create, Search, Supervisor"},
870     { 0x014b, "Read, Write, Create, Search, Supervisor"},
871     { 0x014c, "Open, Create, Search, Supervisor"},
872     { 0x014d, "Read, Open, Create, Search, Supervisor"},
873     { 0x014e, "Write, Open, Create, Search, Supervisor"},
874     { 0x014f, "Read, Write, Open, Create, Search, Supervisor"},
875     { 0x0150, "Delete, Search, Supervisor"},
876     { 0x0151, "Read, Delete, Search, Supervisor"},
877     { 0x0152, "Write, Delete, Search, Supervisor"},
878     { 0x0153, "Read, Write, Delete, Search, Supervisor"},
879     { 0x0154, "Open, Delete, Search, Supervisor"},
880     { 0x0155, "Read, Open, Delete, Search, Supervisor"},
881     { 0x0156, "Write, Open, Delete, Search, Supervisor"},
882     { 0x0157, "Read, Write, Open, Delete, Search, Supervisor"},
883     { 0x0158, "Create, Delete, Search, Supervisor"},
884     { 0x0159, "Read, Create, Delete, Search, Supervisor"},
885     { 0x015a, "Write, Create, Delete, Search, Supervisor"},
886     { 0x015b, "Read, Write, Create, Delete, Search, Supervisor"},
887     { 0x015c, "Open, Create, Delete, Search, Supervisor"},
888     { 0x015d, "Read, Open, Create, Delete, Search, Supervisor"},
889     { 0x015e, "Write, Open, Create, Delete, Search, Supervisor"},
890     { 0x015f, "Read, Write, Open, Create, Delete, Search, Supervisor"},
891     { 0x0160, "Parental, Search, Supervisor"},
892     { 0x0161, "Read, Parental, Search, Supervisor"},
893     { 0x0162, "Write, Parental, Search, Supervisor"},
894     { 0x0163, "Read, Write, Parental, Search, Supervisor"},
895     { 0x0164, "Open, Parental, Search, Supervisor"},
896     { 0x0165, "Read, Open, Parental, Search, Supervisor"},
897     { 0x0166, "Write, Open, Parental, Search, Supervisor"},
898     { 0x0167, "Read, Write, Open, Parental, Search, Supervisor"},
899     { 0x0168, "Create, Parental, Search, Supervisor"},
900     { 0x0169, "Read, Create, Parental, Search, Supervisor"},
901     { 0x016a, "Write, Create, Parental, Search, Supervisor"},
902     { 0x016b, "Read, Write, Create, Parental, Search, Supervisor"},
903     { 0x016c, "Open, Create, Parental, Search, Supervisor"},
904     { 0x016d, "Read, Open, Create, Parental, Search, Supervisor"},
905     { 0x016e, "Write, Open, Create, Parental, Search, Supervisor"},
906     { 0x016f, "Read, Write, Open, Create, Parental, Search, Supervisor"},
907     { 0x0170, "Delete, Parental, Search, Supervisor"},
908     { 0x0171, "Read, Delete, Parental, Search, Supervisor"},
909     { 0x0172, "Write, Delete, Parental, Search, Supervisor"},
910     { 0x0173, "Read, Write, Delete, Parental, Search, Supervisor"},
911     { 0x0174, "Open, Delete, Parental, Search, Supervisor"},
912     { 0x0175, "Read, Open, Delete, Parental, Search, Supervisor"},
913     { 0x0176, "Write, Open, Delete, Parental, Search, Supervisor"},
914     { 0x0177, "Read, Write, Open, Delete, Parental, Search, Supervisor"},
915     { 0x0178, "Create, Delete, Parental, Search, Supervisor"},
916     { 0x0179, "Read, Create, Delete, Parental, Search, Supervisor"},
917     { 0x017a, "Write, Create, Delete, Parental, Search, Supervisor"},
918     { 0x017b, "Read, Write, Create, Delete, Parental, Search, Supervisor"},
919     { 0x017c, "Open, Create, Delete, Parental, Search, Supervisor"},
920     { 0x017d, "Read, Open, Create, Delete, Parental, Search, Supervisor"},
921     { 0x017e, "Write, Open, Create, Delete, Parental, Search, Supervisor"},
922     { 0x017f, "Read, Write, Open, Create, Delete, Parental, Search, Supervisor"},
923     { 0x0180, "Modify, Supervisor"},
924     { 0x0181, "Read, Modify, Supervisor"},
925     { 0x0182, "Write, Modify, Supervisor"},
926     { 0x0183, "Read, Write, Modify, Supervisor"},
927     { 0x0184, "Open, Modify, Supervisor"},
928     { 0x0185, "Read, Open, Modify, Supervisor"},
929     { 0x0186, "Write, Open, Modify, Supervisor"},
930     { 0x0187, "Read, Write, Open, Modify, Supervisor"},
931     { 0x0188, "Create, Modify, Supervisor"},
932     { 0x0189, "Read, Create, Modify, Supervisor"},
933     { 0x018a, "Write, Create, Modify, Supervisor"},
934     { 0x018b, "Read, Write, Create, Modify, Supervisor"},
935     { 0x018c, "Open, Create, Modify, Supervisor"},
936     { 0x018d, "Read, Open, Create, Modify, Supervisor"},
937     { 0x018e, "Write, Open, Create, Modify, Supervisor"},
938     { 0x018f, "Read, Write, Open, Create, Modify, Supervisor"},
939     { 0x0190, "Delete, Modify, Supervisor"},
940     { 0x0191, "Read, Delete, Modify, Supervisor"},
941     { 0x0192, "Write, Delete, Modify, Supervisor"},
942     { 0x0193, "Read, Write, Delete, Modify, Supervisor"},
943     { 0x0194, "Open, Delete, Modify, Supervisor"},
944     { 0x0195, "Read, Open, Delete, Modify, Supervisor"},
945     { 0x0196, "Write, Open, Delete, Modify, Supervisor"},
946     { 0x0197, "Read, Write, Open, Delete, Modify, Supervisor"},
947     { 0x0198, "Create, Delete, Modify, Supervisor"},
948     { 0x0199, "Read, Create, Delete, Modify, Supervisor"},
949     { 0x019a, "Write, Create, Delete, Modify, Supervisor"},
950     { 0x019b, "Read, Write, Create, Delete, Modify, Supervisor"},
951     { 0x019c, "Open, Create, Delete, Modify, Supervisor"},
952     { 0x019d, "Read, Open, Create, Delete, Modify, Supervisor"},
953     { 0x019e, "Write, Open, Create, Delete, Modify, Supervisor"},
954     { 0x019f, "Read, Write, Open, Create, Delete, Modify, Supervisor"},
955     { 0x01a0, "Parental, Modify, Supervisor"},
956     { 0x01a1, "Read, Parental, Modify, Supervisor"},
957     { 0x01a2, "Write, Parental, Modify, Supervisor"},
958     { 0x01a3, "Read, Write, Parental, Modify, Supervisor"},
959     { 0x01a4, "Open, Parental, Modify, Supervisor"},
960     { 0x01a5, "Read, Open, Parental, Modify, Supervisor"},
961     { 0x01a6, "Write, Open, Parental, Modify, Supervisor"},
962     { 0x01a7, "Read, Write, Open, Parental, Modify, Supervisor"},
963     { 0x01a8, "Create, Parental, Modify, Supervisor"},
964     { 0x01a9, "Read, Create, Parental, Modify, Supervisor"},
965     { 0x01aa, "Write, Create, Parental, Modify, Supervisor"},
966     { 0x01ab, "Read, Write, Create, Parental, Modify, Supervisor"},
967     { 0x01ac, "Open, Create, Parental, Modify, Supervisor"},
968     { 0x01ad, "Read, Open, Create, Parental, Modify, Supervisor"},
969     { 0x01ae, "Write, Open, Create, Parental, Modify, Supervisor"},
970     { 0x01af, "Read, Write, Open, Create, Parental, Modify, Supervisor"},
971     { 0x01b0, "Delete, Parental, Modify, Supervisor"},
972     { 0x01b1, "Read, Delete, Parental, Modify, Supervisor"},
973     { 0x01b2, "Write, Delete, Parental, Modify, Supervisor"},
974     { 0x01b3, "Read, Write, Delete, Parental, Modify, Supervisor"},
975     { 0x01b4, "Open, Delete, Parental, Modify, Supervisor"},
976     { 0x01b5, "Read, Open, Delete, Parental, Modify, Supervisor"},
977     { 0x01b6, "Write, Open, Delete, Parental, Modify, Supervisor"},
978     { 0x01b7, "Read, Write, Open, Delete, Parental, Modify, Supervisor"},
979     { 0x01b8, "Create, Delete, Parental, Modify, Supervisor"},
980     { 0x01b9, "Read, Create, Delete, Parental, Modify, Supervisor"},
981     { 0x01ba, "Write, Create, Delete, Parental, Modify, Supervisor"},
982     { 0x01bb, "Read, Write, Create, Delete, Parental, Modify, Supervisor"},
983     { 0x01bc, "Open, Create, Delete, Parental, Modify, Supervisor"},
984     { 0x01bd, "Read, Open, Create, Delete, Parental, Modify, Supervisor"},
985     { 0x01be, "Write, Open, Create, Delete, Parental, Modify, Supervisor"},
986     { 0x01bf, "Read, Write, Open, Create, Delete, Parental, Modify, Supervisor"},
987     { 0x01c0, "Search, Modify, Supervisor"},
988     { 0x01c1, "Read, Search, Modify, Supervisor"},
989     { 0x01c2, "Write, Search, Modify, Supervisor"},
990     { 0x01c3, "Read, Write, Search, Modify, Supervisor"},
991     { 0x01c4, "Open, Search, Modify, Supervisor"},
992     { 0x01c5, "Read, Open, Search, Modify, Supervisor"},
993     { 0x01c6, "Write, Open, Search, Modify, Supervisor"},
994     { 0x01c7, "Read, Write, Open, Search, Modify, Supervisor"},
995     { 0x01c8, "Create, Search, Modify, Supervisor"},
996     { 0x01c9, "Read, Create, Search, Modify, Supervisor"},
997     { 0x01ca, "Write, Create, Search, Modify, Supervisor"},
998     { 0x01cb, "Read, Write, Create, Search, Modify, Supervisor"},
999     { 0x01cc, "Open, Create, Search, Modify, Supervisor"},
1000     { 0x01cd, "Read, Open, Create, Search, Modify, Supervisor"},
1001     { 0x01ce, "Write, Open, Create, Search, Modify, Supervisor"},
1002     { 0x01cf, "Read, Write, Open, Create, Search, Modify, Supervisor"},
1003     { 0x01d0, "Delete, Search, Modify, Supervisor"},
1004     { 0x01d1, "Read, Delete, Search, Modify, Supervisor"},
1005     { 0x01d2, "Write, Delete, Search, Modify, Supervisor"},
1006     { 0x01d3, "Read, Write, Delete, Search, Modify, Supervisor"},
1007     { 0x01d4, "Open, Delete, Search, Modify, Supervisor"},
1008     { 0x01d5, "Read, Open, Delete, Search, Modify, Supervisor"},
1009     { 0x01d6, "Write, Open, Delete, Search, Modify, Supervisor"},
1010     { 0x01d7, "Read, Write, Open, Delete, Search, Modify, Supervisor"},
1011     { 0x01d8, "Create, Delete, Search, Modify, Supervisor"},
1012     { 0x01d9, "Read, Create, Delete, Search, Modify, Supervisor"},
1013     { 0x01da, "Write, Create, Delete, Search, Modify, Supervisor"},
1014     { 0x01db, "Read, Write, Create, Delete, Search, Modify, Supervisor"},
1015     { 0x01dc, "Open, Create, Delete, Search, Modify, Supervisor"},
1016     { 0x01dd, "Read, Open, Create, Delete, Search, Modify, Supervisor"},
1017     { 0x01de, "Write, Open, Create, Delete, Search, Modify, Supervisor"},
1018     { 0x01df, "Read, Write, Open, Create, Delete, Search, Modify, Supervisor"},
1019     { 0x01e0, "Parental, Search, Modify, Supervisor"},
1020     { 0x01e1, "Read, Parental, Search, Modify, Supervisor"},
1021     { 0x01e2, "Write, Parental, Search, Modify, Supervisor"},
1022     { 0x01e3, "Read, Write, Parental, Search, Modify, Supervisor"},
1023     { 0x01e4, "Open, Parental, Search, Modify, Supervisor"},
1024     { 0x01e5, "Read, Open, Parental, Search, Modify, Supervisor"},
1025     { 0x01e6, "Write, Open, Parental, Search, Modify, Supervisor"},
1026     { 0x01e7, "Read, Write, Open, Parental, Search, Modify, Supervisor"},
1027     { 0x01e8, "Create, Parental, Search, Modify, Supervisor"},
1028     { 0x01e9, "Read, Create, Parental, Search, Modify, Supervisor"},
1029     { 0x01ea, "Write, Create, Parental, Search, Modify, Supervisor"},
1030     { 0x01eb, "Read, Write, Create, Parental, Search, Modify, Supervisor"},
1031     { 0x01ec, "Open, Create, Parental, Search, Modify, Supervisor"},
1032     { 0x01ed, "Read, Open, Create, Parental, Search, Modify, Supervisor"},
1033     { 0x01ee, "Write, Open, Create, Parental, Search, Modify, Supervisor"},
1034     { 0x01ef, "Read, Write, Open, Create, Parental, Search, Modify, Supervisor"},
1035     { 0x01f0, "Delete, Parental, Search, Modify, Supervisor"},
1036     { 0x01f1, "Read, Delete, Parental, Search, Modify, Supervisor"},
1037     { 0x01f2, "Write, Delete, Parental, Search, Modify, Supervisor"},
1038     { 0x01f3, "Read, Write, Delete, Parental, Search, Modify, Supervisor"},
1039     { 0x01f4, "Open, Delete, Parental, Search, Modify, Supervisor"},
1040     { 0x01f5, "Read, Open, Delete, Parental, Search, Modify, Supervisor"},
1041     { 0x01f6, "Write, Open, Delete, Parental, Search, Modify, Supervisor"},
1042     { 0x01f7, "Read, Write, Open, Delete, Parental, Search, Modify, Supervisor"},
1043     { 0x01f8, "Create, Delete, Parental, Search, Modify, Supervisor"},
1044     { 0x01f9, "Read, Create, Delete, Parental, Search, Modify, Supervisor"},
1045     { 0x01fa, "Write, Create, Delete, Parental, Search, Modify, Supervisor"},
1046     { 0x01fb, "Read, Write, Create, Delete, Parental, Search, Modify, Supervisor"},
1047     { 0x01fc, "Open, Create, Delete, Parental, Search, Modify, Supervisor"},
1048     { 0x01fd, "Read, Open, Create, Delete, Parental, Search, Modify, Supervisor"},
1049     { 0x01fe, "Write, Open, Create, Delete, Parental, Search, Modify, Supervisor"},
1050     { 0x01ff, "Read, Write, Open, Create, Delete, Parental, Search, Modify, Supervisor"},
1051     { 0,    NULL }
1055 static const value_string nds_reply_errors[] = {
1056     { 0xffffffff, "(-1) Insufficient Space" },
1057     { 0xffffff89, "(-119) Buffer too Small" },
1058     { 0xffffff88, "(-120) RR Volume Flag Not Set" },
1059     { 0xffffff87, "(-121) No Items Found" },
1060     { 0xffffff86, "(-122) Connection Already Temporary" },
1061     { 0xffffff85, "(-123) Connection Already Logged In" },
1062     { 0xffffff84, "(-124) Connection Not Authenticated" },
1063     { 0xffffff83, "(-125) Connection Not Logged In" },
1064     { 0xffffff82, "(-126) NCP Boundary Check Failed" },
1065     { 0xffffff81, "(-127) Lock Waiting" },
1066     { 0xffffff80, "(-128) Lock Fail" },
1067     { 0xffffff7f, "(-129) Out of Handles" },
1068     { 0xffffff7e, "(-130) No Open Privilege" },
1069     { 0xffffff7d, "(-131) Hard IO Error" },
1070     { 0xffffff7c, "(-132) No Create Privilege" },
1071     { 0xffffff7b, "(-133) No Create Delete Privilege" },
1072     { 0xffffff7a, "(-134) Create Duplicate When Read Only" },
1073     { 0xffffff79, "(-135) Create File with Invalid Name" },
1074     { 0xffffff78, "(-136) Invalid File Handle" },
1075     { 0xffffff77, "(-137) No Search Privilege"   },
1076     { 0xffffff76, "(-138) No Delete Privilege" },
1077     { 0xffffff75, "(-139) No Rename Privilege" },
1078     { 0xffffff74, "(-140) No Set Privilege" },
1079     { 0xffffff73, "(-141) Some File in Use" },
1080     { 0xffffff72, "(-142) All File in Use" },
1081     { 0xffffff71, "(-143) Some Read Only" },
1082     { 0xffffff70, "(-144) All Read Only" },
1083     { 0xffffff6f, "(-145) Some names Exist" },
1084     { 0xffffff6e, "(-146) All Names Exist" },
1085     { 0xffffff6d, "(-147) No Read Privilege" },
1086     { 0xffffff6c, "(-148) No Write Privilege" },
1087     { 0xffffff6b, "(-149) File Detached" },
1088     { 0xffffff6a, "(-150) No Alloc Space/Target Not a Subdirectory/Insuffficient Memory" },
1089     { 0xffffff69, "(-151) No Spool Space" },
1090     { 0xffffff68, "(-152) Invalid Volume" },
1091     { 0xffffff67, "(-153) Directory Full" },
1092     { 0xffffff66, "(-154) Rename Across Volume" },
1093     { 0xffffff65, "(-155) Bad Directory Handle" },
1094     { 0xffffff64, "(-156) Invalid Path/No Such Extension" },
1095     { 0xffffff63, "(-157) No Directory Handles" },
1096     { 0xffffff62, "(-158) Bad File Name" },
1097     { 0xffffff61, "(-159) Directory Active" },
1098     { 0xffffff60, "(-160) Directory Not Empty" },
1099     { 0xffffff5f, "(-161) Directory IO Error" },
1100     { 0xffffff5e, "(-162) IO Locked" },
1101     { 0xffffff5d, "(-163) Transaction Restarted" },
1102     { 0xffffff5c, "(-164) Rename Directory Invalid" },
1103     { 0xffffff5b, "(-165) Invalid Open/Create Mode" },
1104     { 0xffffff5a, "(-166) Already in Use" },
1105     { 0xffffff59, "(-167) Invalid Resource Tag" },
1106     { 0xffffff58, "(-168) Access Denied" },
1107     { 0xffffff44, "(-188) Login Signing Required" },
1108     { 0xffffff43, "(-189) Login Encryption Required" },
1109     { 0xffffff42, "(-190) Invalid Data Stream" },
1110     { 0xffffff41, "(-191) Invalid Name Space" },
1111     { 0xffffff40, "(-192) No Accounting Privileges" },
1112     { 0xffffff3f, "(-193) No Account Balance" },
1113     { 0xffffff3e, "(-194) Credit Limit Exceeded" },
1114     { 0xffffff3d, "(-195) Too Many Holds" },
1115     { 0xffffff3c, "(-196) Accounting Disabled" },
1116     { 0xffffff3b, "(-197) Intruder Login Lockout" },
1117     { 0xffffff3a, "(-198) No Console Rights" },
1118     { 0xffffff30, "(-208) Queue IO Failure" },
1119     { 0xffffff2f, "(-209) No Queue" },
1120     { 0xffffff2e, "(-210) No Queue Server" },
1121     { 0xffffff2d, "(-211) No Queue Rights" },
1122     { 0xffffff2c, "(-212) Queue Full" },
1123     { 0xffffff2b, "(-213) No Queue Job" },
1124     { 0xffffff2a, "(-214) No Queue Job Rights/Unencrypted Not Allowed" },
1125     { 0xffffff29, "(-215) Queue In Service/Duplicate Password" },
1126     { 0xffffff28, "(-216) Queue Not Active/Password Too Short" },
1127     { 0xffffff27, "(-217) Queue Station Not Server/Maximum Logins Exceeded" },
1128     { 0xffffff26, "(-218) Queue Halted/Bad Login Time" },
1129     { 0xffffff25, "(-219) Queue Maximum Servers/Node Address Violation" },
1130     { 0xffffff24, "(-220) Login Account Expired" },
1131     { 0xffffff22, "(-222) Bad Password" },
1132     { 0xffffff21, "(-223) Password Expired" },
1133     { 0xffffff20, "(-224) No Login Connection Available" },
1134     { 0xffffff18, "(-232) Write to Group Property" },
1135     { 0xffffff17, "(-233) Member Already Exists" },
1136     { 0xffffff16, "(-234) No Such Member" },
1137     { 0xffffff15, "(-235) Property Not Group" },
1138     { 0xffffff14, "(-236) No Such Value Set" },
1139     { 0xffffff13, "(-237) Property Already Exists" },
1140     { 0xffffff12, "(-238) Object Already Exists" },
1141     { 0xffffff11, "(-239) Illegal Name" },
1142     { 0xffffff10, "(-240) Illegal Wildcard" },
1143     { 0xffffff0f, "(-241) Bindery Security" },
1144     { 0xffffff0e, "(-242) No Object Read Rights" },
1145     { 0xffffff0d, "(-243) No Object Rename Rights" },
1146     { 0xffffff0c, "(-244) No Object Delete Rights" },
1147     { 0xffffff0b, "(-245) No Object Create Rights" },
1148     { 0xffffff0a, "(-246) No Property Delete Rights" },
1149     { 0xffffff09, "(-247) No Property Create Rights" },
1150     { 0xffffff08, "(-248) No Property Write Rights" },
1151     { 0xffffff07, "(-249) No Property Read Rights" },
1152     { 0xffffff06, "(-250) Temp Remap" },
1153     { 0xffffff05, "(-251) Unknown Request/No Such Property" },
1154     { 0xffffff04, "(-252) Message Queue Full/Target Already Has Message/No Such Object" },
1155     { 0xffffff03, "(-253) Bad Station Number" },
1156     { 0xffffff02, "(-254) Bindery Locked/Directory Locked/Spool Delete/Trustee not Found/Timeout" },
1157     { 0xffffff01, "(-255) Hard Failure" },
1158     { 0xfffffed3, "(-301) Not Enough Memory" },
1159     { 0xfffffed2, "(-302) Bad Key" },
1160     { 0xfffffed1, "(-303) Bad Context" },
1161     { 0xfffffed0, "(-304) Buffer Full" },
1162     { 0xfffffecf, "(-305) List Empty" },
1163     { 0xfffffece, "(-306) Bad Syntax"   },
1164     { 0xfffffecd, "(-307) Buffer Empty" },
1165     { 0xfffffecc, "(-308) Bad Verb" },
1166     { 0xfffffecb, "(-309) Expected Identifier" },
1167     { 0xfffffeca, "(-310) Expected Equals" },
1168     { 0xfffffec9, "(-311) Attribute Type Expected" },
1169     { 0xfffffec8, "(-312) Attribute Type Not Expected" },
1170     { 0xfffffec7, "(-313) Filter Tree Empty" },
1171     { 0xfffffec6, "(-314) Invalid Object Name" },
1172     { 0xfffffec5, "(-315) Expected RDN Delimiter" },
1173     { 0xfffffec4, "(-316) Too Many Tokens" },
1174     { 0xfffffec3, "(-317) Inconsistent MultiAVA" },
1175     { 0xfffffec2, "(-318) Country Name Too Long" },
1176     { 0xfffffec1, "(-319) Internal Error" },
1177     { 0xfffffec0, "(-320) Can't Add Root" },
1178     { 0xfffffebf, "(-321) Unable to Attach" },
1179     { 0xfffffebe, "(-322) Invalid Iteration Handle" },
1180     { 0xfffffebd, "(-323) Buffer Zero Length" },
1181     { 0xfffffebc, "(-324) Invalid Replica Type" },
1182     { 0xfffffebb, "(-325) Invalid Attribute Syntax" },
1183     { 0xfffffeba, "(-326) Invalid Filter Syntax" },
1184     { 0xfffffeb8, "(-328) Unicode Error during Context Creation" },
1185     { 0xfffffeb7, "(-329) Invalid Union Tag" },
1186     { 0xfffffeb6, "(-330) Invalid Server Response" },
1187     { 0xfffffeb5, "(-331) Null Pointer" },
1188     { 0xfffffeb4, "(-332) No Server Found" },
1189     { 0xfffffeb3, "(-333) No Connection" },
1190     { 0xfffffeb2, "(-334) RDN Too Long" },
1191     { 0xfffffeb1, "(-335) Duplicate Type" },
1192     { 0xfffffeb0, "(-336) Data Store Failure" },
1193     { 0xfffffeaf, "(-337) Not Logged In" },
1194     { 0xfffffeae, "(-338) Invalid Password Characters" },
1195     { 0xfffffead, "(-339) Failed Server Authentication" },
1196     { 0xfffffeac, "(-340) Transport Failed" },
1197     { 0xfffffeab, "(-341) No Such Syntax" },
1198     { 0xfffffeaa, "(-342) Invalid DS Name" },
1199     { 0xfffffea9, "(-343) Attribute Name Too Long" },
1200     { 0xfffffea8, "(-344) Invalid TDS" },
1201     { 0xfffffea7, "(-345) Invalid DS Version" },
1202     { 0xfffffea6, "(-346) Unicode Translation" },
1203     { 0xfffffea5, "(-347) Schema Name Too Long" },
1204     { 0xfffffea4, "(-348) Unicode File Not Found" },
1205     { 0xfffffea3, "(-349) Unicode Already Loaded" },
1206     { 0xfffffea2, "(-350) Not Context Owner" },
1207     { 0xfffffea1, "(-351) Attempt to Authenticate" },
1208     { 0xfffffea0, "(-352) No Writable Replicas" },
1209     { 0xfffffe9f, "(-353) DN Too Long" },
1210     { 0xfffffe9e, "(-354) Rename Not Allowed" },
1211     { 0xfffffe9d, "(-355) Not NDS for NT" },
1212     { 0xfffffe9c, "(-356) NDS for NT - No Domain" },
1213     { 0xfffffe9b, "(-357) NDS for NT - Sync Disabled" },
1214     { 0xfffffe9a, "(-358) Iterator Invalid Handle" },
1215     { 0xfffffe99, "(-359) Iterator Invalid Position" },
1216     { 0xfffffe98, "(-360) Iterator Invalid Search Data" },
1217     { 0xfffffe97, "(-361) Iterator Invalid Scope" },
1218     { 0xfffffda7, "(-601) No Such Entry" },
1219     { 0xfffffda6, "(-602) No Such Value" },
1220     { 0xfffffda5, "(-603) No Such Attribute" },
1221     { 0xfffffda4, "(-604) No Such Class" },
1222     { 0xfffffda3, "(-605) No Such Partition" },
1223     { 0xfffffda2, "(-606) Entry Already Exists" },
1224     { 0xfffffda1, "(-607) Not Effective Class" },
1225     { 0xfffffda0, "(-608) Illegal Attribute" },
1226     { 0xfffffd9f, "(-609) Missing Mandatory" },
1227     { 0xfffffd9e, "(-610) Illegal DS Name" },
1228     { 0xfffffd9d, "(-611) Illegal Containment" },
1229     { 0xfffffd9c, "(-612) Can't Have Multiple Values" },
1230     { 0xfffffd9b, "(-613) Syntax Violation" },
1231     { 0xfffffd9a, "(-614) Duplicate Value" },
1232     { 0xfffffd99, "(-615) Attribute Already Exists" },
1233     { 0xfffffd98, "(-616) Maximum Entries Exist" },
1234     { 0xfffffd97, "(-617) Database Format" },
1235     { 0xfffffd96, "(-618) Inconsistent Database" },
1236     { 0xfffffd95, "(-619) Invalid Comparison" },
1237     { 0xfffffd94, "(-620) Comparison Failed" },
1238     { 0xfffffd93, "(-621) Transaction Tracking Disabled" },
1239     { 0xfffffd92, "(-622) Invalid Transport" },
1240     { 0xfffffd91, "(-623) Syntax Invalid in Name" },
1241     { 0xfffffd90, "(-624) Replica Already Exists" },
1242     { 0xfffffd8f, "(-625) Transport Failure" },
1243     { 0xfffffd8e, "(-626) All Referrals Failed" },
1244     { 0xfffffd8d, "(-627) Can't Remove Naming Value" },
1245     { 0xfffffd8c, "(-628) Object Class Violation" },
1246     { 0xfffffd8b, "(-629) Entry is Not Leaf" },
1247     { 0xfffffd8a, "(-630) Different Tree" },
1248     { 0xfffffd89, "(-631) Illegal Replica Type" },
1249     { 0xfffffd88, "(-632) System Failure" },
1250     { 0xfffffd87, "(-633) Invalid Entry for Root" },
1251     { 0xfffffd86, "(-634) No Referrals" },
1252     { 0xfffffd85, "(-635) Remote Failure" },
1253     { 0xfffffd84, "(-636) Unreachable Server" },
1254     { 0xfffffd83, "(-637) Previous Move in Progress" },
1255     { 0xfffffd82, "(-638) No Character Mapping" },
1256     { 0xfffffd81, "(-639) Incomplete Authentication" },
1257     { 0xfffffd80, "(-640) Invalid Certificate" },
1258     { 0xfffffd7f, "(-641) Invalid Request" },
1259     { 0xfffffd7e, "(-642) Invalid Iteration" },
1260     { 0xfffffd7d, "(-643) Schema is Non-removable" },
1261     { 0xfffffd7c, "(-644) Schema is in Use" },
1262     { 0xfffffd7b, "(-645) Class Already Exists" },
1263     { 0xfffffd7a, "(-646) Bad Naming Attributes" },
1264     { 0xfffffd79, "(-647) Not Root Partition" },
1265     { 0xfffffd78, "(-648) Insufficient Stack" },
1266     { 0xfffffd77, "(-649) Insufficient Buffer" },
1267     { 0xfffffd76, "(-650) Ambiguous Containment" },
1268     { 0xfffffd75, "(-651) Ambiguous Naming" },
1269     { 0xfffffd74, "(-652) Duplicate Mandatory" },
1270     { 0xfffffd73, "(-653) Duplicate Optional" },
1271     { 0xfffffd72, "(-654) Partition Busy" },
1272     { 0xfffffd71, "(-655) Multiple Replicas" },
1273     { 0xfffffd70, "(-656) Crucial Replica" },
1274     { 0xfffffd6f, "(-657) Schema Sync in Progress" },
1275     { 0xfffffd6e, "(-658) Skulk in Progress" },
1276     { 0xfffffd6d, "(-659) Time Not Synchronized" },
1277     { 0xfffffd6c, "(-660) Record in Use" },
1278     { 0xfffffd6b, "(-661) DS Volume Not Mounted" },
1279     { 0xfffffd6a, "(-662) DS Volume IO Failure" },
1280     { 0xfffffd69, "(-663) DS Locked" },
1281     { 0xfffffd68, "(-664) Old Epoch" },
1282     { 0xfffffd67, "(-665) New Epoch" },
1283     { 0xfffffd66, "(-666) Incompatible DS Version" },
1284     { 0xfffffd65, "(-667) Partition Root" },
1285     { 0xfffffd64, "(-668) Entry Not Container" },
1286     { 0xfffffd63, "(-669) Failed Authentication" },
1287     { 0xfffffd62, "(-670) Invalid Context" },
1288     { 0xfffffd61, "(-671) No Such Parent" },
1289     { 0xfffffd60, "(-672) No Access" },
1290     { 0xfffffd5f, "(-673) Replica Not On" },
1291     { 0xfffffd5e, "(-674) Invalid Name Service" },
1292     { 0xfffffd5d, "(-675) Invalid Task" },
1293     { 0xfffffd5c, "(-676) Invalid Connection Handle" },
1294     { 0xfffffd5b, "(-677) Invalid Identity" },
1295     { 0xfffffd5a, "(-678) Duplicate ACL" },
1296     { 0xfffffd59, "(-679) Partition Already Exists" },
1297     { 0xfffffd58, "(-680) Transport Modified" },
1298     { 0xfffffd57, "(-681) Alias of an Alias" },
1299     { 0xfffffd56, "(-682) Auditing Failed" },
1300     { 0xfffffd55, "(-683) Invalid API Version" },
1301     { 0xfffffd54, "(-684) Secure NCP Violation" },
1302     { 0xfffffd53, "(-685) Move in Progress" },
1303     { 0xfffffd52, "(-686) Not a Leaf Partition" },
1304     { 0xfffffd51, "(-687) Cannot Abort" },
1305     { 0xfffffd50, "(-688) Cache Overflow" },
1306     { 0xfffffd4f, "(-689) Invalid Subordinate Count" },
1307     { 0xfffffd4e, "(-690) Invalid RDN" },
1308     { 0xfffffd4d, "(-691) Modification Time Not Current" },
1309     { 0xfffffd4c, "(-692) Incorrect Base Class" },
1310     { 0xfffffd4b, "(-693) Missing Reference" },
1311     { 0xfffffd4a, "(-694) Lost Entry" },
1312     { 0xfffffd49, "(-695) Agent Already Registered" },
1313     { 0xfffffd48, "(-696) DS Loader Busy" },
1314     { 0xfffffd47, "(-697) DS Cannot Reload" },
1315     { 0xfffffd46, "(-698) Replica in Skulk" },
1316     { 0xfffffd45, "(-699) Fatal" },
1317     { 0xfffffd44, "(-700) Obsolete API" },
1318     { 0xfffffd43, "(-701) Synchronization Disabled" },
1319     { 0xfffffd42, "(-702) Invalid Parameter" },
1320     { 0xfffffd41, "(-703) Duplicate Template" },
1321     { 0xfffffd40, "(-704) No Master Replica" },
1322     { 0xfffffd3f, "(-705) Duplicate Containment" },
1323     { 0xfffffd3e, "(-706) Not a Sibling" },
1324     { 0xfffffd3d, "(-707) Invalid Signature" },
1325     { 0xfffffd3c, "(-708) Invalid Response" },
1326     { 0xfffffd3b, "(-709) Insufficient Sockets" },
1327     { 0xfffffd3a, "(-710) Database Read Fail" },
1328     { 0xfffffd39, "(-711) Invalid Code Page" },
1329     { 0xfffffd38, "(-712) Invalid Escape Character" },
1330     { 0xfffffd37, "(-713) Invalid Delimiters" },
1331     { 0xfffffd36, "(-714) Not Implemented" },
1332     { 0xfffffd35, "(-715) Checksum Failure" },
1333     { 0xfffffd34, "(-716) Checksumming Not Supported" },
1334     { 0xfffffd33, "(-717) CRC Failure" },
1335     { 0xfffffd32, "(-718) Invalid Entry Handle" },
1336     { 0xfffffd31, "(-719) Invalid Value Handle" },
1337     { 0xfffffd30, "(-720) Connection Denied" },
1338     { 0xfffffd2f, "(-721) No Such Federation Link" },
1339     { 0xfffffd2e, "(-722) Operetational Schema Mismatch" },
1340     { 0xfffffd2d, "(-723) Stream Not Found" },
1341     { 0xfffffd2c, "(-724) DClient Unavailable" },
1342     { 0xfffffd2b, "(-725) MASV No Access" },
1343     { 0xfffffd2a, "(-726) MASV Invalid Request" },
1344     { 0xfffffd29, "(-727) MASV Failure" },
1345     { 0xfffffd28, "(-728) MASV Already Exists" },
1346     { 0xfffffd27, "(-729) MASV Not Found" },
1347     { 0xfffffd26, "(-730) MASV Bad Range" },
1348     { 0xfffffd25, "(-731) Value Data" },
1349     { 0xfffffd24, "(-732) Database Locked" },
1350     { 0xfffffd21, "(-735) Nothing to Abort" },
1351     { 0xfffffd20, "(-736) End of Stream" },
1352     { 0xfffffd1f, "(-737) No Such Template" },
1353     { 0xfffffd1e, "(-738) SAS Locked" },
1354     { 0xfffffd1d, "(-739) Invalid SAS Version" },
1355     { 0xfffffd1c, "(-740) SAS Already Registered" },
1356     { 0xfffffd1b, "(-741) Name Type Not Supported" },
1357     { 0xfffffd1a, "(-742) Wrong DS Version" },
1358     { 0xfffffd19, "(-743) Invalid Control Function" },
1359     { 0xfffffd18, "(-744) Invalid Control State" },
1360     { 0xfffffd17, "(-745) Cache in Use" },
1361     { 0xfffffd16, "(-746) Zero Creation Time" },
1362     { 0xfffffd15, "(-747) Would Block" },
1363     { 0xfffffd14, "(-748) Connection Timeout" },
1364     { 0xfffffd13, "(-749) Too Many Referrals" },
1365     { 0xfffffd12, "(-750) Operation Cancelled" },
1366     { 0xfffffd11, "(-751) Unknown Target" },
1367     { 0xfffffd10, "(-752) GUID Failure" },
1368     { 0xfffffd0f, "(-753) Incompatible OS" },
1369     { 0xfffffd0e, "(-754) Callback Cancel" },
1370     { 0xfffffd0d, "(-755) Invalid Synchronization Data" },
1371     { 0xfffffd0c, "(-756) Stream Exists" },
1372     { 0xfffffd0b, "(-757) Auxiliary Has Containment" },
1373     { 0xfffffd0a, "(-758) Auxiliary Not Container" },
1374     { 0xfffffd09, "(-759) Auxiliary Not Effective" },
1375     { 0xfffffd08, "(-760) Auxiliary On Alias" },
1376     { 0xfffffd07, "(-761) Have Seen State" },
1377     { 0xfffffd06, "(-762) Verb Locked" },
1378     { 0xfffffd05, "(-763) Verb Exceeds Table Length" },
1379     { 0xfffffd04, "(-764) BOF Hit" },
1380     { 0xfffffd03, "(-765) EOF Hit" },
1381     { 0xfffffd02, "(-766) Incompatible Replica Version" },
1382     { 0xfffffd01, "(-767) Query Timeout" },
1383     { 0xfffffd00, "(-768) Query Maximum Count" },
1384     { 0xfffffcff, "(-769) Duplicate Naming" },
1385     { 0xfffffcfe, "(-770) No Transaction Active" },
1386     { 0xfffffcfd, "(-771) Transaction Active" },
1387     { 0xfffffcfc, "(-772) Illegal Transaction Operation" },
1388     { 0xfffffcfb, "(-773) Iterator Syntax" },
1389     { 0xfffffcfa, "(-774) Repairing DIB" },
1390     { 0xfffffcf9, "(-775) Invalid OID Format" },
1391     { 0xfffffcf8, "(-776) Attempted to perform an NDS operation, and the DS agent on this server is closing" },
1392     { 0xfffffcf7, "(-777) Attempted to modify an object's attribute that is not stored on the sparse replica" },
1393     { 0xfffffcf6, "(-778) VpVector and VpvUser which must be correlated, are out of sync" },
1394     { 0xfffffcf5, "(-779) Error Cannot Go Remote" },
1395     { 0xfffffcf4, "(-780) Request not Supported" },
1396     { 0xfffffcf3, "(-781) Entry Not Local" },
1397     { 0xfffffcf2, "(-782) Root Unreachable" },
1398     { 0xfffffcf1, "(-783) VRDIM Not Initialized" },
1399     { 0xfffffcf0, "(-784) Wait Timeout" },
1400     { 0xfffffcef, "(-785) DIB Error" },
1401     { 0xfffffcee, "(-786) DIB IO Failure" },
1402     { 0xfffffced, "(-787) Illegal Schema Attribute" },
1403     { 0xfffffcec, "(-788) Error Schema Partition" },
1404     { 0xfffffceb, "(-789) Invalid Template" },
1405     { 0xfffffcea, "(-790) Error Opening File" },
1406     { 0xfffffce9, "(-791) Error Direct Opening File" },
1407     { 0xfffffce8, "(-792) Error Creating File" },
1408     { 0xfffffce7, "(-793) Error Direct Creating File" },
1409     { 0xfffffce6, "(-794) Error Reading File" },
1410     { 0xfffffce5, "(-795) Error Direct Reading File" },
1411     { 0xfffffce4, "(-796) Error Writing File" },
1412     { 0xfffffce3, "(-797) Error Direct Writing File" },
1413     { 0xfffffce2, "(-798) Error Positioning in File" },
1414     { 0xfffffce1, "(-799) Error Getting File Size" },
1415     { 0xffffe88f, "(-6001) Error Truncating File" },
1416     { 0xffffe88e, "(-6002) Error Parsing File Name" },
1417     { 0xffffe88d, "(-6003) Error Closing File" },
1418     { 0xffffe88c, "(-6004) Error Getting File Info" },
1419     { 0xffffe88b, "(-6005) Error Expanding File" },
1420     { 0xffffe88a, "(-6006) Error Getting Free Blocks" },
1421     { 0xffffe889, "(-6007) Error Checking File Existence" },
1422     { 0xffffe888, "(-6008) Error Deleting File" },
1423     { 0xffffe887, "(-6009) Error Renaming File" },
1424     { 0xffffe886, "(-6010) Error Initializing IO System" },
1425     { 0xffffe885, "(-6011) Error Flushing File" },
1426     { 0xffffe884, "(-6012) Error Setting Up for Read" },
1427     { 0xffffe883, "(-6013) Error Setting up for Write" },
1428     { 0xffffe882, "(-6014) Error Old View" },
1429     { 0xffffe881, "(-6015) Server in Skulk" },
1430     { 0xffffe880, "(-6016) Error Returning Partial Results" },
1431     { 0xffffe87f, "(-6017) No Such Schema" },
1432     { 0xffffe87e, "(-6018) Serial Number Mismatch" },
1433     { 0xffffe87d, "(-6019) Bad Referral Database Serial Number" },
1434     { 0xffffe87c, "(-6020) Bad Referral Serial Number" },
1435     { 0xffffe87b, "(-6021) Invalid File Sequence" },
1436     { 0xffffe87a, "(-6022) Error Referral Trans Gap" },
1437     { 0xffffe879, "(-6023) Bad Referral File Number" },
1438     { 0xffffe878, "(-6024) Referral File Not Found" },
1439     { 0xffffe877, "(-6025) Error Backup Active" },
1440     { 0xffffe876, "(-6026) Referral Device Full" },
1441     { 0xffffe875, "(-6027) Unsupported Version" },
1442     { 0xffffe874, "(-6028) Error Must Wait Checkpoint" },
1443     { 0xffffe873, "(-6029) Attribute Maintenance in Progress" },
1444     { 0xffffe872, "(-6030) Error Abort Transaction" },
1445     { 0xffff0000, "Ok" },
1446     { 0x0000, "Ok" },
1447     { 0, NULL }
1450 #define NDS_PTYPE_IPX           0x00000000
1451 #define NDS_PTYPE_IP            0x00000001
1452 #define NDS_PTYPE_SDLC          0x00000002
1453 #define NDS_PTYPE_TR_ON_ETH     0x00000003
1454 #define NDS_PTYPE_OSI           0x00000004
1455 #define NDS_PTYPE_APPLETALK     0x00000005
1456 #define NDS_PTYPE_NETBEUI       0x00000006
1457 #define NDS_PTYPE_SOCKETADDRESS 0x00000007
1458 #define NDS_PTYPE_UDP           0x00000008
1459 #define NDS_PTYPE_TCP           0x00000009
1460 #define NDS_PTYPE_UDPv6         0x0000000a
1461 #define NDS_PTYPE_TCPv6         0x0000000b
1462 #define NDS_PTYPE_INTERNAL      0x0000000c
1463 #define NDS_PTYPE_URL           0x0000000d
1464 #define NDS_PTYPE_DNS           0x0000000e
1465 #define NDS_PTYPE_CNT           0x0000000f
1467 static const value_string nds_protocol_type[] = {
1468     { NDS_PTYPE_IPX,           "(IPX Protocol)" },
1469     { NDS_PTYPE_IP,            "(IP Protocol)" },
1470     { NDS_PTYPE_SDLC,          "(SDLC Protocol)" },
1471     { NDS_PTYPE_TR_ON_ETH,     "(TokenRing on Ethernet Protocol)" },
1472     { NDS_PTYPE_OSI,           "(OSI Protocol)" },
1473     { NDS_PTYPE_APPLETALK,     "(AppleTalk Protocol)" },
1474     { NDS_PTYPE_NETBEUI,       "(NetBEUI Protocol)" },
1475     { NDS_PTYPE_SOCKETADDRESS, "(Socket Address Protocol)" },
1476     { NDS_PTYPE_UDP,           "(UDP Protocol)" },
1477     { NDS_PTYPE_TCP,           "(TCP Protocol)" },
1478     { NDS_PTYPE_UDPv6,         "(UDP v6 Protocol)" },
1479     { NDS_PTYPE_TCPv6,         "(TCP v6 Protocol)" },
1480     { NDS_PTYPE_INTERNAL,      "(Internal Protocol)" },
1481     { NDS_PTYPE_URL,           "(URL Protocol)" },
1482     { NDS_PTYPE_DNS,           "(DNS Protocol)" },
1483     { NDS_PTYPE_CNT,           "(Number of protocol types defined)" },
1484     { 0, NULL }
1488 static const value_string nds_syntax[] = {
1489     { 0x00000000, "Unknown Syntax" },
1490     { 0x00000001, "Distinguished Name" },
1491     { 0x00000002, "Case Sensitive Unicode String" },
1492     { 0x00000003, "Non Case Sensitive Unicode String" },
1493     { 0x00000004, "Printable String" },
1494     { 0x00000005, "Numeric String" },
1495     { 0x00000006, "Case Insensitive List" },
1496     { 0x00000007, "Boolean" },
1497     { 0x00000008, "Signed Integer" },
1498     { 0x00000009, "Binary String" },
1499     { 0x0000000a, "Telephone Number" },
1500     { 0x0000000b, "Fax Number" },
1501     { 0x0000000c, "Network Address" },
1502     { 0x0000000d, "Binary String List" },
1503     { 0x0000000e, "Email Address" },
1504     { 0x0000000f, "File System Path" },
1505     { 0x00000010, "Replica Pointer" },
1506     { 0x00000011, "Object ACL" },
1507     { 0x00000012, "Postal Address" },
1508     { 0x00000013, "Time Stamp" },
1509     { 0x00000014, "Class Name" },
1510     { 0x00000015, "Stream" },
1511     { 0x00000016, "Counter" },
1512     { 0x00000017, "Back Link" },
1513     { 0x00000018, "Time" },
1514     { 0x00000019, "Typed Name" },
1515     { 0x0000001a, "Hold" },
1516     { 0x0000001b, "Interval" },
1517     { 0, NULL }
1520 static const value_string name_space_type[] = {
1521     { 0x00000000, "DOS Name Space" },
1522     { 0x00000001, "MAC Name Space" },
1523     { 0x00000002, "NFS Name Space" },
1524     { 0x00000003, "FTAM Name Space" },
1525     { 0x00000004, "OS/2, Long Name Space" },
1526     { 0, NULL }
1530 static const value_string nds_replica_state[] = {
1531     { 0x0000, "On" },
1532     { 0x0001, "New" },
1533     { 0x0002, "Dying" },
1534     { 0x0003, "Locked" },
1535     { 0x0004, "Create Master State 0" },
1536     { 0x0005, "Create Master State 1" },
1537     { 0x0006, "Transition On" },
1538     { 0x0007, "Dead Replica" },
1539     { 0x0008, "Begin Add" },
1540     { 0x000b, "Master Start" },
1541     { 0x000c, "Master Done" },
1542     { 0x0017, "Federated" },
1543     { 0x0030, "Split State 0" },
1544     { 0x0031, "Split State 1" },
1545     { 0x0040, "Join State 0" },
1546     { 0x0041, "Join State 1" },
1547     { 0x0042, "Join State 2" },
1548     { 0x0050, "Move Subtree State 0" },
1549     { 0x0051, "Move Subtree State 1" },
1550     { 0, NULL }
1553 static const value_string nds_replica_type[] = {
1554     { 0x0000, "Master" },
1555     { 0x0001, "Secondary" },
1556     { 0x0002, "Read Only" },
1557     { 0x0003, "Sub Ref" },
1558     { 0, NULL }
1561 static const value_string class_def_type[] = {
1562     { 0x0000, "Return Class Name" },
1563     { 0x0001, "Return Class Name, Flag, and Definition" },
1564     { 0x0002, "Return Class Name, Flag, Definition, and Super Class" },
1565     { 0x0003, "Return Class Name, Flag, and ASN.1 identifier" },
1566     { 0x0004, "Return Class Name, Flag, Definition, Super Class, and ACL" },
1567     { 0x0005, "Return Class Name, Flag, Creation Timestamp, Modification Timestamp, Definition, and ACL" },
1568     { 0, NULL }
1571 static const range_string nds_search_scope[] = {
1572     { 0x0000, 0x0000, "Examine the base object only" },
1573     { 0x0001, 0x0001, "Search the immediate subordinates of the base object" },
1574     { 0x0002, 0x0002, "Search the base object and all its subordinates" },
1575     { 0x0003, 0x0003, "Search the base objects and all objects in its partition (Implemented in NDS 8)" },
1576     { 0x0004, 0xFFFF, "No Search Scope Defined" },
1577     { 0, 0, NULL }
1580 static const value_string nds_verb2b_flag_vals[] = {
1581     { 0, "Request Flags (0x0000) - Retain old object name" },
1582     { 1, "Request Flags (0x0001) - Delete old object name" },
1583     { 0,  NULL }
1586 static const value_string serv_type_vals[] = {
1587     { 0, "NetWare" },
1588     { 1, "OES" },
1589     { 0,  NULL }
1592 static const value_string kernel_type_vals[] = {
1593     { 0, "NetWare" },
1594     { 1, "Linux" },
1595     { 0,  NULL }
1598 static int * const ncp_pingflags1[] = {
1599     &hf_bit1pingflags1,
1600     &hf_bit2pingflags1,
1601     &hf_bit3pingflags1,
1602     &hf_bit4pingflags1,
1603     &hf_bit5pingflags1,
1604     &hf_bit6pingflags1,
1605     &hf_bit7pingflags1,
1606     &hf_bit8pingflags1,
1607     &hf_bit9pingflags1,
1608     &hf_bit10pingflags1,
1609     &hf_bit11pingflags1,
1610     &hf_bit12pingflags1,
1611     &hf_bit13pingflags1,
1612     &hf_bit14pingflags1,
1613     &hf_bit15pingflags1,
1614     &hf_bit16pingflags1,
1615     NULL
1618 static int * const ncp_pingflags2[] = {
1619     &hf_bit1pingflags2,
1620     &hf_bit2pingflags2,
1621     &hf_bit3pingflags2,
1622     &hf_bit4pingflags2,
1623     &hf_bit5pingflags2,
1624     &hf_bit6pingflags2,
1625     &hf_bit7pingflags2,
1626     &hf_bit8pingflags2,
1627     &hf_bit9pingflags2,
1628     &hf_bit10pingflags2,
1629     &hf_bit11pingflags2,
1630     &hf_bit12pingflags2,
1631     &hf_bit13pingflags2,
1632     &hf_bit14pingflags2,
1633     &hf_bit15pingflags2,
1634     &hf_bit16pingflags2,
1635     NULL
1638 static int * const ncp_pingvflags1[] = {
1639     &hf_bit1pingvflags1,
1640     &hf_bit2pingvflags1,
1641     &hf_bit3pingvflags1,
1642     &hf_bit4pingvflags1,
1643     &hf_bit5pingvflags1,
1644     &hf_bit6pingvflags1,
1645     &hf_bit7pingvflags1,
1646     &hf_bit8pingvflags1,
1647     &hf_bit9pingvflags1,
1648     &hf_bit10pingvflags1,
1649     &hf_bit11pingvflags1,
1650     &hf_bit12pingvflags1,
1651     &hf_bit13pingvflags1,
1652     &hf_bit14pingvflags1,
1653     &hf_bit15pingvflags1,
1654     &hf_bit16pingvflags1,
1655     NULL
1658 static int * const ncp_pingpflags1[] = {
1659     &hf_bit1pingpflags1,
1660     &hf_bit2pingpflags1,
1661     &hf_bit3pingpflags1,
1662     &hf_bit4pingpflags1,
1663     &hf_bit5pingpflags1,
1664     &hf_bit6pingpflags1,
1665     &hf_bit7pingpflags1,
1666     &hf_bit8pingpflags1,
1667     &hf_bit9pingpflags1,
1668     &hf_bit10pingpflags1,
1669     &hf_bit11pingpflags1,
1670     &hf_bit12pingpflags1,
1671     &hf_bit13pingpflags1,
1672     &hf_bit14pingpflags1,
1673     &hf_bit15pingpflags1,
1674     &hf_bit16pingpflags1,
1675     NULL
1678 static int * const ndsprotflags[] = {
1679     &hf_ndsprot1flag,
1680     &hf_ndsprot2flag,
1681     &hf_ndsprot3flag,
1682     &hf_ndsprot4flag,
1683     &hf_ndsprot5flag,
1684     &hf_ndsprot6flag,
1685     &hf_ndsprot7flag,
1686     &hf_ndsprot8flag,
1687     &hf_ndsprot9flag,
1688     &hf_ndsprot10flag,
1689     &hf_ndsprot11flag,
1690     &hf_ndsprot12flag,
1691     &hf_ndsprot13flag,
1692     &hf_ndsprot14flag,
1693     &hf_ndsprot15flag,
1694     &hf_ndsprot16flag,
1695     NULL
1698 static int * const ncp_infoflagsl[] = {
1699     &hf_bit1infoflagsl,
1700     &hf_bit2infoflagsl,
1701     &hf_bit3infoflagsl,
1702     &hf_bit4infoflagsl,
1703     &hf_bit5infoflagsl,
1704     &hf_bit6infoflagsl,
1705     &hf_bit7infoflagsl,
1706     &hf_bit8infoflagsl,
1707     &hf_bit9infoflagsl,
1708     &hf_bit10infoflagsl,
1709     &hf_bit11infoflagsl,
1710     &hf_bit12infoflagsl,
1711     &hf_bit13infoflagsl,
1712     &hf_bit14infoflagsl,
1713     &hf_bit15infoflagsl,
1714     &hf_bit16infoflagsl,
1715     NULL
1718 static int * const ncp_infoflagsh[] = {
1719     &hf_bit1infoflagsh,
1720     &hf_bit2infoflagsh,
1721     &hf_bit3infoflagsh,
1722     &hf_bit4infoflagsh,
1723     &hf_bit5infoflagsh,
1724     &hf_bit6infoflagsh,
1725     &hf_bit7infoflagsh,
1726     &hf_bit8infoflagsh,
1727     &hf_bit9infoflagsh,
1728     &hf_bit10infoflagsh,
1729     &hf_bit11infoflagsh,
1730     &hf_bit12infoflagsh,
1731     &hf_bit13infoflagsh,
1732     &hf_bit14infoflagsh,
1733     &hf_bit15infoflagsh,
1734     &hf_bit16infoflagsh,
1735     NULL
1738 static int * const ncp_retinfoflagsh[] = {
1739     &hf_bit1retinfoflagsh,
1740     &hf_bit2retinfoflagsh,
1741     &hf_bit3retinfoflagsh,
1742     &hf_bit4retinfoflagsh,
1743     &hf_bit5retinfoflagsh,
1744     &hf_bit6retinfoflagsh,
1745     &hf_bit7retinfoflagsh,
1746     &hf_bit8retinfoflagsh,
1747     &hf_bit9retinfoflagsh,
1748     &hf_bit10retinfoflagsh,
1749     &hf_bit11retinfoflagsh,
1750     &hf_bit12retinfoflagsh,
1751     &hf_bit13retinfoflagsh,
1752     &hf_bit14retinfoflagsh,
1753     &hf_bit15retinfoflagsh,
1754     &hf_bit16retinfoflagsh,
1755     NULL
1758 static int * const ncp_acflags[] = {
1759     &hf_bit1acflags,
1760     &hf_bit2acflags,
1761     &hf_bit3acflags,
1762     &hf_bit4acflags,
1763     &hf_bit5acflags,
1764     &hf_bit6acflags,
1765     &hf_bit7acflags,
1766     &hf_bit8acflags,
1767     &hf_bit9acflags,
1768     &hf_bit10acflags,
1769     &hf_bit11acflags,
1770     &hf_bit12acflags,
1771     &hf_bit13acflags,
1772     &hf_bit14acflags,
1773     &hf_bit15acflags,
1774     &hf_bit16acflags,
1775     NULL
1778 static int * const ncp_eflags[] = {
1779     &hf_bit1eflags,
1780     &hf_bit2eflags,
1781     &hf_bit3eflags,
1782     &hf_bit4eflags,
1783     &hf_bit5eflags,
1784     &hf_bit6eflags,
1785     &hf_bit7eflags,
1786     &hf_bit8eflags,
1787     &hf_bit9eflags,
1788     &hf_bit10eflags,
1789     &hf_bit11eflags,
1790     &hf_bit12eflags,
1791     &hf_bit13eflags,
1792     &hf_bit14eflags,
1793     &hf_bit15eflags,
1794     &hf_bit16eflags,
1795     NULL
1798 static int * const ncp_cflags[] = {
1799     &hf_bit1cflags,
1800     &hf_bit2cflags,
1801     &hf_bit3cflags,
1802     &hf_bit4cflags,
1803     &hf_bit5cflags,
1804     &hf_bit6cflags,
1805     &hf_bit7cflags,
1806     &hf_bit8cflags,
1807     &hf_bit9cflags,
1808     &hf_bit10cflags,
1809     &hf_bit11cflags,
1810     &hf_bit12cflags,
1811     &hf_bit13cflags,
1812     &hf_bit14cflags,
1813     &hf_bit15cflags,
1814     &hf_bit16cflags,
1815     NULL
1818 static int * const ncp_lflags[] = {
1819     &hf_bit1lflags,
1820     &hf_bit2lflags,
1821     &hf_bit3lflags,
1822     &hf_bit4lflags,
1823     &hf_bit5lflags,
1824     &hf_bit6lflags,
1825     &hf_bit7lflags,
1826     &hf_bit8lflags,
1827     &hf_bit9lflags,
1828     &hf_bit10lflags,
1829     &hf_bit11lflags,
1830     &hf_bit12lflags,
1831     &hf_bit13lflags,
1832     &hf_bit14lflags,
1833     &hf_bit15lflags,
1834     &hf_bit16lflags,
1835     NULL
1838 static int * const ncp_nflags[] = {
1839     &hf_bit1nflags,
1840     &hf_bit2nflags,
1841     &hf_bit3nflags,
1842     &hf_bit4nflags,
1843     &hf_bit5nflags,
1844     &hf_bit6nflags,
1845     &hf_bit7nflags,
1846     &hf_bit8nflags,
1847     &hf_bit9nflags,
1848     &hf_bit10nflags,
1849     &hf_bit11nflags,
1850     &hf_bit12nflags,
1851     &hf_bit13nflags,
1852     &hf_bit14nflags,
1853     &hf_bit15nflags,
1854     &hf_bit16nflags,
1855     NULL
1858 static int * const ncp_rflags[] = {
1859     &hf_bit1rflags,
1860     &hf_bit2rflags,
1861     &hf_bit3rflags,
1862     &hf_bit4rflags,
1863     &hf_bit5rflags,
1864     &hf_bit6rflags,
1865     &hf_bit7rflags,
1866     &hf_bit8rflags,
1867     &hf_bit9rflags,
1868     &hf_bit10rflags,
1869     &hf_bit11rflags,
1870     &hf_bit12rflags,
1871     &hf_bit13rflags,
1872     &hf_bit14rflags,
1873     &hf_bit15rflags,
1874     &hf_bit16rflags,
1875     NULL
1878 static int * const ncp_outflags[] = {
1879     &hf_bit1outflags,
1880     &hf_bit2outflags,
1881     &hf_bit3outflags,
1882     &hf_bit4outflags,
1883     &hf_bit5outflags,
1884     &hf_bit6outflags,
1885     &hf_bit7outflags,
1886     &hf_bit8outflags,
1887     &hf_bit9outflags,
1888     &hf_bit10outflags,
1889     &hf_bit11outflags,
1890     &hf_bit12outflags,
1891     &hf_bit13outflags,
1892     &hf_bit14outflags,
1893     &hf_bit15outflags,
1894     &hf_bit16outflags,
1895     NULL
1898 static int * const ncp_siflags[] = {
1899     &hf_bit1siflags,
1900     &hf_bit2siflags,
1901     &hf_bit3siflags,
1902     &hf_bit4siflags,
1903     &hf_bit5siflags,
1904     &hf_bit6siflags,
1905     &hf_bit7siflags,
1906     &hf_bit8siflags,
1907     &hf_bit9siflags,
1908     &hf_bit10siflags,
1909     &hf_bit11siflags,
1910     &hf_bit12siflags,
1911     &hf_bit13siflags,
1912     &hf_bit14siflags,
1913     &hf_bit15siflags,
1914     &hf_bit16siflags,
1915     NULL
1918 static int * const ncp_vflags[] = {
1919     &hf_bit1vflags,
1920     &hf_bit2vflags,
1921     &hf_bit3vflags,
1922     &hf_bit4vflags,
1923     &hf_bit5vflags,
1924     &hf_bit6vflags,
1925     &hf_bit7vflags,
1926     &hf_bit8vflags,
1927     &hf_bit9vflags,
1928     &hf_bit10vflags,
1929     &hf_bit11vflags,
1930     &hf_bit12vflags,
1931     &hf_bit13vflags,
1932     &hf_bit14vflags,
1933     &hf_bit15vflags,
1934     &hf_bit16vflags,
1935     NULL
1938 static int * const nds_bitflags[] = {
1939     &hf_nds_bit1,
1940     &hf_nds_bit2,
1941     &hf_nds_bit3,
1942     &hf_nds_bit4,
1943     &hf_nds_bit5,
1944     &hf_nds_bit6,
1945     &hf_nds_bit7,
1946     &hf_nds_bit8,
1947     &hf_nds_bit9,
1948     &hf_nds_bit10,
1949     &hf_nds_bit11,
1950     &hf_nds_bit12,
1951     &hf_nds_bit13,
1952     &hf_nds_bit14,
1953     &hf_nds_bit15,
1954     &hf_nds_bit16,
1955     NULL
1958 static int * const ncp_l1flagsl[] = {
1959     &hf_bit1l1flagsl,
1960     &hf_bit2l1flagsl,
1961     &hf_bit3l1flagsl,
1962     &hf_bit4l1flagsl,
1963     &hf_bit5l1flagsl,
1964     &hf_bit6l1flagsl,
1965     &hf_bit7l1flagsl,
1966     &hf_bit8l1flagsl,
1967     &hf_bit9l1flagsl,
1968     &hf_bit10l1flagsl,
1969     &hf_bit11l1flagsl,
1970     &hf_bit12l1flagsl,
1971     &hf_bit13l1flagsl,
1972     &hf_bit14l1flagsl,
1973     &hf_bit15l1flagsl,
1974     &hf_bit16l1flagsl,
1975     NULL
1978 static int * const ncp_l1flagsh[] = {
1979     &hf_bit1l1flagsh,
1980     &hf_bit2l1flagsh,
1981     &hf_bit3l1flagsh,
1982     &hf_bit4l1flagsh,
1983     &hf_bit5l1flagsh,
1984     &hf_bit6l1flagsh,
1985     &hf_bit7l1flagsh,
1986     &hf_bit8l1flagsh,
1987     &hf_bit9l1flagsh,
1988     &hf_bit10l1flagsh,
1989     &hf_bit11l1flagsh,
1990     &hf_bit12l1flagsh,
1991     &hf_bit13l1flagsh,
1992     &hf_bit14l1flagsh,
1993     &hf_bit15l1flagsh,
1994     &hf_bit16l1flagsh,
1995     NULL
1998 static void
1999 process_ptvc_record(ptvcursor_t *ptvc, packet_info *pinfo, const ptvc_record *rec,
2000                     bool *req_cond_results, bool really_decode,
2001                     const ncp_record *ncp_rec, bool request);
2003 /* NCP packets come in request/reply pairs. The request packets tell the type
2004  * of NCP request and give a sequence ID. The response, unfortunately, only
2005  * identifies itself via the sequence ID; you have to know what type of NCP
2006  * request the request packet contained in order to successfully parse the NCP
2007  * response. A global method for doing this does not exist in wireshark yet
2008  * (NFS also requires it), so for now the NCP section will keep its own hash
2009  * table keeping track of NCP packet types.
2011  * We construct a conversation specified by the client and server
2012  * addresses and the connection number; the key representing the unique
2013  * NCP request then is composed of the pointer to the conversation
2014  * structure, cast to a "uint" (which may throw away the upper 32
2015  * bits of the pointer on a P64 platform, but the low-order 32 bits
2016  * are more likely to differ between conversations than the upper 32 bits),
2017  * and the sequence number.
2019  * The value stored in the hash table is the ncp_req_hash_value pointer. This
2020  * struct tells us the NCP type and gives the ncp2222_record pointer, if
2021  * ncp_type == 0x2222.
2022  */
2023 typedef struct {
2024     conversation_t  *conversation;
2025     uint32_t          nw_sequence_long;
2026 } ncp_req_hash_key;
2029 typedef struct {
2030     uint32_t         nw_eid;
2031 } ncp_req_eid_hash_key;
2034  * XXX - should the object_name be a pointer, initialized to null,
2035  * and set to a wmem-allocated copy of the full string?
2036  */
2037 typedef struct {
2038     ncp_req_eid_hash_key    *nds_eid;
2039     char                    object_name[256];
2040 } ncp_req_eid_hash_value;
2042 static wmem_map_t *ncp_req_hash;
2043 static wmem_map_t *ncp_req_eid_hash;
2045 static uint32_t check_offset_addition(uint32_t offset, uint32_t value, proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb)
2047     if (offset > UINT32_MAX - value) {
2048         proto_tree_add_expert_format(tree, pinfo, &ei_ncp_value_too_large, tvb, 0, 0, "Offset value too large: %u", value);
2049         THROW(ReportedBoundsError);
2050     }
2051     return offset + value;
2054 /* Hash Functions */
2055 static gboolean
2056 ncp_equal(const void *v, const void *v2)
2058     const ncp_req_hash_key *val1 = (const ncp_req_hash_key*)v;
2059     const ncp_req_hash_key *val2 = (const ncp_req_hash_key*)v2;
2061     if (val1->conversation == val2->conversation &&
2062         val1->nw_sequence_long  == val2->nw_sequence_long ) {
2063         return TRUE;
2064     }
2065     return FALSE;
2068 static gboolean
2069 ncp_eid_equal(const void *v, const void *v2)
2071     const ncp_req_eid_hash_key *val1 = (const ncp_req_eid_hash_key*)v;
2072     const ncp_req_eid_hash_key *val2 = (const ncp_req_eid_hash_key*)v2;
2074     if (val1->nw_eid == val2->nw_eid ) {
2075         return TRUE;
2076     }
2077     return FALSE;
2080 static unsigned
2081 ncp_hash(const void *v)
2083     const ncp_req_hash_key *ncp_key = (const ncp_req_hash_key*)v;
2084     return GPOINTER_TO_UINT(ncp_key->conversation) + ncp_key->nw_sequence_long;
2087 static unsigned
2088 ncp_eid_hash(const void *v)
2090     const ncp_req_eid_hash_key *ncp_eid_key = (const ncp_req_eid_hash_key*)v;
2091     return GPOINTER_TO_UINT(ncp_eid_key->nw_eid);
2094 static void
2095 ncp_init_protocol(void)
2097     int i;
2099     for (i = 0; i < 99; i++) {
2100         frags[i].nds_frag = 0xfffffff0;
2101     }
2104 /* NCP sequence numbers are from 0 - 255. After reaching 255 the
2105  * sequence number wraps back to 0. Change nw_sequence to nw_sequence_long
2106  * and use upper bits to make sequence numbers unique. This way
2107  * future attempts to locate initiating packet will succeed.
2108  */
2109 static ncp_req_hash_value*
2110 ncp_hash_insert(conversation_t *conversation, uint8_t nw_sequence,
2111                 const ncp_record *ncp_rec, uint32_t pkt_num)
2113     ncp_req_hash_key    *request_key;
2114     ncp_req_hash_value  *request_value;
2116     /* Now remember the request, so we can find it if we later
2117        a reply to it. */
2118     request_key = wmem_new(wmem_file_scope(), ncp_req_hash_key);
2119     request_key->conversation = conversation;
2120     /* Make sequence number unique */
2121     request_key->nw_sequence_long = (0x10000 + ((pkt_num/16)<<16)) | nw_sequence;
2123     request_value = wmem_new0(wmem_file_scope(), ncp_req_hash_value);
2124     request_value->ncp_rec = ncp_rec;
2125     request_value->req_cond_results = NULL;
2126     request_value->req_nds_flags = 0;
2127     request_value->nds_request_verb = 0;
2128     request_value->nds_version = 0;
2129     (void) g_strlcpy(request_value->object_name, "", 256);
2130     request_value->nds_frag = true;
2132     wmem_map_insert(ncp_req_hash, request_key, request_value);
2134     return request_value;
2137 static ncp_req_eid_hash_value*
2138 ncp_eid_hash_insert(uint32_t nw_eid)
2140     ncp_req_eid_hash_key    *request_eid_key;
2141     ncp_req_eid_hash_value  *request_eid_value;
2143     /* Now remember the request, so we can find it if we later
2144        a reply to it. */
2145     request_eid_key = wmem_new(wmem_file_scope(), ncp_req_eid_hash_key);
2146     request_eid_key->nw_eid = nw_eid;
2148     request_eid_value = wmem_new0(wmem_file_scope(), ncp_req_eid_hash_value);
2149     (void) g_strlcpy(request_eid_value->object_name, "", 256);
2151     wmem_map_insert(ncp_req_eid_hash, request_eid_key, request_eid_value);
2153     return request_eid_value;
2156 /* Returns the ncp_rec*, or NULL if not found. */
2157 static ncp_req_hash_value*
2158 ncp_hash_lookup(conversation_t *conversation, uint8_t nw_sequence, uint32_t pkt_num)
2160     ncp_req_hash_key  request_key;
2161     ncp_req_hash_value *temp_value;
2163     request_key.conversation = conversation;
2164     /* Find unique sequence number */
2165     request_key.nw_sequence_long = (0x10000+((pkt_num/16)<<16)) | nw_sequence;
2167     /* Since masking of sequence number utilizes the packet number as
2168      * part of it's algorythm it is possible for a packet to sit right
2169      * on the boundary and fail. (depending on number of packets in trace)
2170      * Loop through all the previous sequence numbers in the hash to see
2171      * if the original request packet can be found.
2172      */
2173     temp_value = (ncp_req_hash_value *)wmem_map_lookup(ncp_req_hash, &request_key);
2174     while(!temp_value)
2175     {
2176        request_key.nw_sequence_long = request_key.nw_sequence_long-0x10000;
2177        if((request_key.nw_sequence_long & 0xffff0000) == 0){
2178             break;
2179        }
2180        temp_value = (ncp_req_hash_value *)wmem_map_lookup(ncp_req_hash, &request_key);
2181     }
2182     return temp_value;
2185 /* Returns the value_rec* for needed EID, or NULL if not found. */
2186 static ncp_req_eid_hash_value*
2187 ncp_eid_hash_lookup(conversation_t *conversation _U_, uint32_t nw_eid)
2189     ncp_req_eid_hash_key  request_eid_key;
2191     request_eid_key.nw_eid = nw_eid;
2193     return (ncp_req_eid_hash_value *)wmem_map_lookup(ncp_req_eid_hash, &request_eid_key);
2196 /* Does NCP func require a subfunction code? */
2197 static bool
2198 ncp_requires_subfunc(uint8_t func)
2200     const uint8_t *ncp_func_requirement = ncp_func_requires_subfunc;
2202     while (*ncp_func_requirement != 0) {
2203         if (*ncp_func_requirement == func) {
2204             return true;
2205         }
2206         ncp_func_requirement++;
2207     }
2208     return false;
2211 /* Does the NCP func have a length parameter? */
2212 static bool
2213 ncp_has_length_parameter(uint8_t func)
2215     const uint8_t *ncp_func_requirement = ncp_func_has_no_length_parameter;
2217     while (*ncp_func_requirement != 0) {
2218         if (*ncp_func_requirement == func) {
2219             return false;
2220         }
2221         ncp_func_requirement++;
2222     }
2223     return true;
2227 /* Return a ncp_record* based on func and possibly subfunc */
2228 static const ncp_record *
2229 ncp_record_find(uint8_t func, uint8_t subfunc)
2231     const ncp_record *ncp_rec = ncp_packets;
2233     while(ncp_rec->func != 0 || ncp_rec->subfunc != 0 ||
2234           ncp_rec->name != NULL ) {
2235         if (ncp_rec->func == func) {
2236             if (ncp_rec->has_subfunc) {
2237                 if (ncp_rec->subfunc == subfunc) {
2238                     return ncp_rec;
2239                 }
2240             }
2241             else {
2242                 return ncp_rec;
2243             }
2244         }
2245         ncp_rec++;
2246     }
2247     return NULL;
2250 #define NW_UNI_MAX 1024
2252 #define VTYPE_NONE                       0  /* no value */
2253 #define VTYPE_UINT8                      1
2254 #define VTYPE_UINT16                     2
2255 #define VTYPE_UINT32                     3
2256 #define VTYPE_STRING                     4
2257 #define VTYPE_BITFIELD                   5
2258 #define VTYPE_MULTIVALUE_UINT32          6
2259 #define VTYPE_BYTES                      7
2260 #define VTYPE_BOOLEAN                    8
2261 #define VTYPE_ITEM                       9
2263 #define MVTYPE_ATTR_REQUEST              1
2264 #define MVTYPE_ATTR_REPLY                2
2265 #define MVTYPE_ATTR_REQUEST2             3
2266 #define MVTYPE_READ_CLASS_REQ            4
2267 #define MVTYPE_READ_REPLICAS             5
2268 #define MVTYPE_MODIFY_ATTR_REQUEST       6
2269 #define MVTYPE_ADDR_REFERRAL_REQUEST     7
2270 #define MVTYPE_ADDR_REFERRAL_REPLY       8
2271 #define MVTYPE_LOC_ADDR_REFERRAL_REPLY   9
2272 #define MVTYPE_PROC_ENTRY_SPECIFIERS    10
2273 #define MVTYPE_PRINT_TIMESTAMP          11
2274 #define MVTYPE_LIST_PARTITIONS          12
2275 #define MVTYPE_CLASS_NAMES              13
2276 #define MVTYPE_MODIFY_CLASS             14
2277 #define MVTYPE_ADD_ATTR_REQUEST         15
2278 #define MVTYPE_PROCESS_TAGS             16
2279 #define MVTYPE_PROCESS_ITERATOR         17
2281 typedef struct {
2282     uint8_t         vtype;
2283     uint32_t        vvalue;
2284     const char*     vstring;
2285     const char*     vdesc;
2286     uint32_t        vlength;
2287     uint32_t        voffset;
2288     uint32_t        hfname;
2289     const char*     bit1;
2290     uint32_t        bit1hfname;
2291     const char*     bit2;
2292     uint32_t        bit2hfname;
2293     const char*     bit3;
2294     uint32_t        bit3hfname;
2295     const char*     bit4;
2296     uint32_t        bit4hfname;
2297     const char*     bit5;
2298     uint32_t        bit5hfname;
2299     const char*     bit6;
2300     uint32_t        bit6hfname;
2301     const char*     bit7;
2302     uint32_t        bit7hfname;
2303     const char*     bit8;
2304     uint32_t        bit8hfname;
2305     const char*     bit9;
2306     uint32_t        bit9hfname;
2307     const char*     bit10;
2308     uint32_t        bit10hfname;
2309     const char*     bit11;
2310     uint32_t        bit11hfname;
2311     const char*     bit12;
2312     uint32_t        bit12hfname;
2313     const char*     bit13;
2314     uint32_t        bit13hfname;
2315     const char*     bit14;
2316     uint32_t        bit14hfname;
2317     const char*     bit15;
2318     uint32_t        bit15hfname;
2319     const char*     bit16;
2320     uint32_t        bit16hfname;
2321     uint8_t         mvtype;
2322     uint32_t        vflags;
2323     uint32_t        nds_version;
2324     uint32_t        pflags; /* NDS Protocol Flags */
2325 } nds_val;
2327 static proto_item*
2328 add_ptvc_field(packet_info* pinfo, ptvcursor_t *ptvc, const ptvc_record *rec, bool request, bool repeat, unsigned* ret_value)
2330     header_field_info* hinfo = proto_registrar_get_nth(*rec->hf_ptr);
2332     if (!repeat && request && rec->req_info_str)
2333         col_set_str(pinfo->cinfo, COL_INFO, "C ");
2335     /* We may want integer values regardless of whether or not the value is displayed in INFO column */
2336     if (FT_IS_UINT(hinfo->type) || FT_IS_INT(hinfo->type)) {
2337         uint32_t value32 = 0;
2338         uint64_t value64 = 0;
2340         switch(rec->length)
2341         {
2342         case 1:
2343             value32 = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2344             *ret_value = value32;
2345             break;
2346         case 2:
2347             value32 = tvb_get_uint16(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2348             *ret_value = value32;
2349             break;
2350         case 3:
2351             value32 = tvb_get_uint24(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2352             *ret_value = value32;
2353             break;
2354         case 4:
2355             value32 = tvb_get_uint32(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2356             *ret_value = value32;
2357             break;
2358         case 5:
2359             value64 = tvb_get_uint40(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2360             break;
2361         case 6:
2362             value64 = tvb_get_uint48(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2363             break;
2364         case 7:
2365             value64 = tvb_get_uint56(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2366             break;
2367         case 8:
2368             value64 = tvb_get_uint64(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2369             break;
2370         default:
2371             DISSECTOR_ASSERT(false);
2372             break;
2373         }
2375         if (request && rec->req_info_str) {
2376             if (rec->length <= 4) {
2377                 col_append_fstr(pinfo->cinfo, COL_INFO,
2378                         (const char*)(repeat ? rec->req_info_str->repeat_string : rec->req_info_str->first_string),
2379                         value32);
2380             } else {
2381                 col_append_fstr(pinfo->cinfo, COL_INFO,
2382                         (const char*)(repeat ? rec->req_info_str->repeat_string : rec->req_info_str->first_string),
2383                         value64);
2385             }
2386         }
2387     } else if (request && rec->req_info_str) {
2388         if (hinfo->type == FT_STRING) {
2389             col_append_fstr(pinfo->cinfo, COL_INFO,
2390                                 (const char*)(repeat ? rec->req_info_str->repeat_string : rec->req_info_str->first_string),
2391                                  tvb_get_string_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2392                                      ptvcursor_current_offset(ptvc), rec->length, ENC_ASCII));
2393         } else if (hinfo->type == FT_STRINGZ) {
2394             int length;
2395             col_append_fstr(pinfo->cinfo, COL_INFO,
2396                                 (const char*)(repeat ? rec->req_info_str->repeat_string : rec->req_info_str->first_string),
2397                                 tvb_get_stringz_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2398                                     ptvcursor_current_offset(ptvc), &length, ENC_ASCII));
2399         } else if (hinfo->type == FT_UINT_STRING) {
2400             uint32_t length = 0;
2402             switch(rec->length)
2403             {
2404             case 1:
2405                 length = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2406                 break;
2407             case 2:
2408                 length = tvb_get_uint16(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2409                 break;
2410             case 3:
2411                 length = tvb_get_uint24(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2412                 break;
2413             case 4:
2414                 length = tvb_get_uint32(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc), rec->endianness);
2415                 break;
2416             default:
2417                 DISSECTOR_ASSERT(false);
2418                 break;
2419             }
2421             col_append_fstr(pinfo->cinfo, COL_INFO,
2422                                 (const char*)(repeat ? rec->req_info_str->repeat_string : rec->req_info_str->first_string),
2423                                 tvb_get_string_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2424                                     ptvcursor_current_offset(ptvc)+rec->length, length, ENC_ASCII));
2425         } else if (hinfo->type == FT_BYTES) {
2426             col_append_fstr(pinfo->cinfo, COL_INFO,
2427                                 (const char*)(repeat ? rec->req_info_str->repeat_string : rec->req_info_str->first_string),
2428                                 tvb_bytes_to_str(pinfo->pool, ptvcursor_tvbuff(ptvc),
2429                                     ptvcursor_current_offset(ptvc), rec->length));
2430         }
2431     }
2433     return ptvcursor_add(ptvc, *rec->hf_ptr,
2434                       rec->length,
2435                       rec->endianness);
2439  * XXX - are these just DOS-format dates and times?
2441  * Should we put code to understand various date and time formats (UNIX,
2442  * DOS, SMB weird mutant UNIX, NT, Mac, etc. into libwireshark, and have
2443  * the "display" member of an HF_ABSOLUTE_TIME field specify whether
2444  * it's DOS date/DOS time, DOS time/DOS date, NT time, UNIX time_t,
2445  * UNIX "struct timeval", NFSv3/NFSv4 seconds/nanoseconds, Mac, etc.?
2447  * What about hijacking the "bitmask" field to specify the precision of
2448  * the time stamp, or putting a combination of precision and format
2449  * into the "display" member?
2451  * What about relative times?  Should they have units (seconds, milliseconds,
2452  * microseconds, nanoseconds, etc.), precision, and format in there?
2453  */
2454 static void
2455 padd_date( char *result, uint32_t date_value )
2457     snprintf(result, ITEM_LABEL_LENGTH, "%04u/%02u/%02u",
2458                 ((date_value & 0xfe00) >> 9) + 1980,
2459                 (date_value & 0x01e0) >> 5,
2460                 date_value & 0x001f);
2463 static void
2464 padd_time( char *result, uint32_t time_value )
2466     snprintf(result, ITEM_LABEL_LENGTH, "%02u:%02u:%02u",
2467                 ((time_value & 0xf800) >> 11),
2468                 ((time_value & 0x07e0) >> 5),
2469                 (time_value & 0x001f) * 2);
2472 /* Add a value for a ptvc_record, and process the sub-ptvc_record
2473  * that it points to. */
2474 static void
2475 process_bitfield_sub_ptvc_record(ptvcursor_t *ptvc, const ptvc_record *rec,
2476                                  bool really_decode)
2478     proto_item          *item;
2479     proto_tree          *sub_tree;
2480     const ptvc_record   *sub_rec;
2481     int                 current_offset;
2482     int                 ett;
2483     ptvcursor_t         *sub_ptvc;
2485     if (really_decode) {
2486         /* Save the current offset */
2487         current_offset = ptvcursor_current_offset(ptvc);
2489         /* Add the item */
2490         item = ptvcursor_add(ptvc, *rec->hf_ptr, rec->length,
2491                              rec->endianness);
2493         ett = *rec->sub_ptvc_rec->ett;
2495         /* Make a new protocol sub-tree */
2496         sub_tree = proto_item_add_subtree(item, ett);
2498         /* Make a new ptvcursor */
2499         sub_ptvc = ptvcursor_new(wmem_packet_scope(), sub_tree, ptvcursor_tvbuff(ptvc),
2500                                  current_offset);
2502         /* Use it */
2503         sub_rec = rec->sub_ptvc_rec->ptvc_rec;
2504         while(sub_rec->hf_ptr != NULL) {
2505             DISSECTOR_ASSERT(!sub_rec->sub_ptvc_rec);
2506             ptvcursor_add_no_advance(sub_ptvc, *sub_rec->hf_ptr,
2507                                      sub_rec->length,
2508                                      sub_rec->endianness);
2509             sub_rec++;
2510         }
2512         /* Free it. */
2513         ptvcursor_free(sub_ptvc);
2514     }
2515     else {
2516         DISSECTOR_ASSERT(rec->length > 0 &&
2517                          proto_registrar_get_nth(*rec->hf_ptr)->type != FT_UINT_STRING);
2518         ptvcursor_advance(ptvc, rec->length);
2519     }
2522 /* Process a sub-ptvc_record that points to a "struct" ptvc_record. */
2523 static void
2524 process_struct_sub_ptvc_record(ptvcursor_t *ptvc, packet_info *pinfo, const ptvc_record *rec,
2525                                bool *req_cond_results, bool really_decode,
2526                                const ncp_record *ncp_rec, bool request)
2528     const ptvc_record   *sub_rec;
2529     int                 ett;
2530     proto_tree          *old_tree=NULL, *new_tree;
2531     proto_item          *item=NULL;
2532     int                 offset=0;
2534     /* Create a sub-proto_tree? */
2535     if (rec->sub_ptvc_rec->descr) {
2536         ett = *rec->sub_ptvc_rec->ett;
2537         old_tree = ptvcursor_tree(ptvc);
2538         offset = ptvcursor_current_offset(ptvc);
2539         new_tree = proto_tree_add_subtree(old_tree, ptvcursor_tvbuff(ptvc), offset, -1,
2540                                           ett, &item, rec->sub_ptvc_rec->descr);
2541         ptvcursor_set_tree(ptvc, new_tree);
2542     }
2544     /* Get the ptvc_record for the struct and call our caller
2545      * to process it. */
2546     sub_rec = rec->sub_ptvc_rec->ptvc_rec;
2547     process_ptvc_record(ptvc, pinfo, sub_rec, req_cond_results, really_decode, ncp_rec, request);
2549     /* Re-set the tree */
2550     if (rec->sub_ptvc_rec->descr) {
2551         if (ptvcursor_current_offset(ptvc) <= offset)
2552             THROW(ReportedBoundsError);
2554         proto_item_set_len(item, ptvcursor_current_offset(ptvc) - offset);
2555         ptvcursor_set_tree(ptvc, old_tree);
2556     }
2559 /* Run through the table of ptvc_record's and add info to the tree. This
2560  * is the work-horse of process_ptvc_record(). */
2561 static void
2562 _process_ptvc_record(ptvcursor_t *ptvc, packet_info *pinfo, const ptvc_record *rec,
2563                      bool *req_cond_results, bool really_decode,
2564                      const ncp_record *ncp_rec, bool request)
2566     unsigned    i, repeat_count, repeat_value;
2568     if (rec->sub_ptvc_rec) {
2569         /* Repeat this? */
2570         if (rec->repeat_index >= NO_REPEAT) {
2571             if (rec->hf_ptr == PTVC_STRUCT) {
2572                 process_struct_sub_ptvc_record(ptvc, pinfo, rec,
2573                                                req_cond_results, really_decode,
2574                                                ncp_rec, request);
2575             }
2576             else {
2577                 process_bitfield_sub_ptvc_record(ptvc, rec,
2578                                                  really_decode);
2579             }
2580         }
2581         else {
2582             repeat_count = repeat_vars[rec->repeat_index];
2583             for (i = 0; i < repeat_count; i++ ) {
2584                 if (rec->hf_ptr == PTVC_STRUCT) {
2585                     process_struct_sub_ptvc_record(ptvc, pinfo, rec,
2586                                                    req_cond_results, really_decode,
2587                                                    ncp_rec, request);
2588                 }
2589                 else {
2590                     process_bitfield_sub_ptvc_record(ptvc, rec,
2591                                                      really_decode);
2592                 }
2593             }
2594         }
2595     }
2596     else {
2597         /* If we can't repeat this field, we might use it
2598          * to set a 'var'. */
2599         if (rec->repeat_index == NO_REPEAT) {
2600             if (really_decode) {
2601                 repeat_value = 0;
2602                 add_ptvc_field(pinfo, ptvc, rec, request, false, &repeat_value);
2604                 /* Set the value as a 'var' ? */
2605                 if (rec->var_index != NO_VAR) {
2606                     repeat_vars[rec->var_index] = repeat_value;
2607                 }
2608             }
2609             else {
2610                 /* If we don't decode the field, we
2611                  * better not use the value to set a var.
2612                  * Actually, we could, as long as we don't
2613                  * *use* that var; for now keep this assert in
2614                  * place. */
2615                 DISSECTOR_ASSERT(rec->var_index == NO_VAR);
2617                 /* This had better not be variable-length,
2618                  * either. */
2619                 DISSECTOR_ASSERT(rec->length > 0 &&
2620                                  proto_registrar_get_nth(*rec->hf_ptr)->type != FT_UINT_STRING);
2621                 ptvcursor_advance(ptvc, rec->length);
2622             }
2623         }
2624         else {
2625             /* We do repeat this field. */
2626             repeat_count = repeat_vars[rec->repeat_index];
2627             if (really_decode) {
2628                 for (i = 0; i < repeat_count; i++ ) {
2629                     add_ptvc_field(pinfo, ptvc, rec, request, i != 0, &repeat_value);
2630                 }
2631             }
2632             else {
2633                 for (i = 0; i < repeat_count; i++ ) {
2634                     DISSECTOR_ASSERT(rec->length > 0 &&
2635                                      proto_registrar_get_nth(*rec->hf_ptr)->type != FT_UINT_STRING);
2636                     ptvcursor_advance(ptvc, rec->length);
2637                 }
2638             }
2639         }
2640     }
2643 /* Run through the table of ptvc_record's and add info to the tree.
2644  * Honor a request condition result. */
2645 static void
2646 process_ptvc_record(ptvcursor_t *ptvc, packet_info *pinfo, const ptvc_record *rec,
2647                     bool *req_cond_results, bool really_decode,
2648                     const ncp_record *ncp_rec, bool request)
2650     bool decode;
2651     ptvcursor_t *expert_ptvc;
2652     proto_tree* expert_tree = ptvcursor_tree(ptvc);
2653     tvbuff_t* expert_tvb = ptvcursor_tvbuff(ptvc);
2654     int expert_offset = ptvcursor_current_offset(ptvc);
2656     while(rec->hf_ptr != NULL) {
2657         decode = really_decode;
2658         /* If we're supposed to decode, check the request condition
2659          * results to see if we should override this and *not* decode. */
2660         if (decode && req_cond_results) {
2661             if (rec->req_cond_index != NO_REQ_COND) {
2662                 if (req_cond_results[rec->req_cond_index] == false) {
2663                     decode = false;
2664                 }
2665             }
2666         }
2667         if (decode || ncp_rec->req_cond_size_type == REQ_COND_SIZE_CONSTANT) {
2668             _process_ptvc_record(ptvc, pinfo, rec, req_cond_results, decode, ncp_rec, request);
2669         }
2670         rec++;
2671     }
2673     /* Collect any potential expert info that would have been collected over
2674        these records */
2675     if (ncp_rec->expert_handler_func)
2676     {
2677         expert_ptvc = ptvcursor_new(pinfo->pool, expert_tree, expert_tvb, expert_offset);
2678         ncp_rec->expert_handler_func(expert_ptvc, pinfo, ncp_rec, request);
2679         ptvcursor_free(expert_ptvc);
2680     }
2685 /* Clear the repeat_vars array. */
2686 static void
2687 clear_repeat_vars(void)
2689     unsigned i;
2691     for (i = 0 ; i < NUM_REPEAT_VARS; i++ ) {
2692         repeat_vars[i] = 0;
2693     }
2697 /* Given an error_equivalency table and a completion code, return
2698  * the string representing the error. */
2699 static const char*
2700 ncp_error_string(const error_equivalency *errors, uint8_t completion_code)
2703     while (errors->ncp_error_index != -1) {
2704         if (errors->error_in_packet == completion_code) {
2705             return ncp_errors[errors->ncp_error_index];
2706         }
2707         errors++;
2708     }
2710     return "Unknown Error Code";
2713 static const ncp_record ncp1111_request =
2714 { 0x1, 0x00, NO_SUBFUNC, "Create Connection Service", NCP_GROUP_CONNECTION,
2715   NULL, NULL, ncp_0x2_errors, NULL, NO_REQ_COND_SIZE, NULL };
2717 static const ncp_record ncp5555_request =
2718 { 0x5, 0x00, NO_SUBFUNC, "Destroy Connection Service", NCP_GROUP_CONNECTION,
2719   NULL, NULL, ncp_0x2_errors, NULL, NO_REQ_COND_SIZE, NULL };
2721 static const ncp_record ncpbbbb_request =
2722 { 0xb, 0x00, NO_SUBFUNC, "Server Broadcast Message", NCP_GROUP_CONNECTION,
2723   NULL, NULL, ncp_0x2_errors, NULL, NO_REQ_COND_SIZE, NULL };
2725 static const ncp_record ncplip_echo =
2726 { 0x1f, 0x00, NO_SUBFUNC, "LIP Echo Packet", NCP_GROUP_CONNECTION,
2727   NULL, NULL, ncp_0x2_errors, NULL, NO_REQ_COND_SIZE, NULL };
2729 /* Wrapper around proto_tree_free() */
2730 static void free_proto_tree(void *tree)
2732     if (tree) {
2733         proto_tree_free((proto_tree*) tree);
2734     }
2737 static uint32_t
2738 align_4(tvbuff_t *tvb, uint32_t aoffset)
2740     if(tvb_captured_length_remaining(tvb, aoffset) > 4 )
2741     {
2742         return (aoffset%4);
2743     }
2744     return 0;
2748  * XXX - should we just use regular string functions, or proto_item_
2749  * functions, with ENC_UTF_16|ENC_LITTLE_ENDIAN (or ENC_UCS_2, if
2750  * they don't support full UTF-16)?
2751  */
2752 static const char *
2753 get_string(tvbuff_t* tvb, unsigned offset, unsigned str_length)
2755     char *dest_buf;
2756     int i;
2757     uint16_t c_char;
2758     int length_remaining = 0;
2759     int max_length = (str_length < NW_UNI_MAX) ? str_length : NW_UNI_MAX;
2761     length_remaining = tvb_captured_length_remaining(tvb, offset);
2762     if((int)str_length > length_remaining)
2763     {
2764         THROW(ReportedBoundsError);
2765     }
2767     if(str_length == 0)
2768     {
2769         return "";
2770     }
2772     dest_buf = (char *)wmem_alloc(wmem_packet_scope(), max_length + 1);
2773     dest_buf[0] = '\0';
2775     for ( i = 0; i < (int)str_length; i++ )
2776     {
2777         c_char = tvb_get_uint8(tvb, offset );
2778         if (c_char<0x20 || c_char>0x7e)
2779         {
2780             if (c_char != 0x00)
2781             {
2782                 c_char = '.';
2783                 dest_buf[i] = c_char & 0xff;
2784             }
2785             else
2786             {
2787                 i--;
2788                 str_length--;
2789             }
2790         }
2791         else
2792         {
2793             dest_buf[i] = c_char & 0xff;
2794         }
2795         offset++;
2796         length_remaining--;
2798         if(length_remaining==1)
2799         {
2800             dest_buf[i+1] = '\0';
2801             return dest_buf;
2802         }
2803         if (i >= 1023) { /* Don't process beyond the size of our variable */
2804             break;       /* If string is too long just return the first 1K. */
2805         }
2806     }
2807     if (i < 0) {
2808         i = 0;
2809     }
2810     dest_buf[i] = '\0';
2811     return dest_buf;
2814 /* Echo the NDS EID and name for NCP 22,51 replies to expert tap */
2815 static void ncp1633_reply_expert_func(ptvcursor_t *ptvc, packet_info *pinfo, const ncp_record *ncp_rec _U_, bool request)
2817     if (nds_echo_eid && !request) {
2818         uint32_t object_id;
2819         uint8_t volume_name_len;
2820         uint8_t*  volume_name;
2822         object_id = tvb_get_letohl(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc)+126);
2823         ptvcursor_advance(ptvc, 134);
2824         volume_name_len = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2825         ptvcursor_advance(ptvc, 1);
2826         volume_name = tvb_get_string_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2827                                 ptvcursor_current_offset(ptvc), volume_name_len, ENC_ASCII);
2829         expert_add_info_format(pinfo, NULL, &ei_ncp_eid,
2830                                     "EID (%08x) = %s", object_id, volume_name);
2831     }
2834 /* The following allows for specific NCP server info to be echoed to the expert tap. */
2835 static void ncp1711_reply_expert_func(ptvcursor_t *ptvc, packet_info *pinfo, const ncp_record *ncp_rec _U_, bool request)
2837     if (ncp_echo_server && !request) {
2838         uint8_t* fsname;
2839         uint8_t maj_ver, min_ver, os_lang, serv_type, kernel;
2840         uint16_t prod_rev;
2842         fsname = tvb_get_string_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2843                                 ptvcursor_current_offset(ptvc), 48, ENC_ASCII);
2844         ptvcursor_advance(ptvc, 48);
2845         maj_ver = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2846         ptvcursor_advance(ptvc, 1);
2847         min_ver = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2848         ptvcursor_advance(ptvc, 25); /* Skip unimportant fields */
2849         prod_rev = tvb_get_ntohs(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2850         ptvcursor_advance(ptvc, 2);
2851         os_lang = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2852         ptvcursor_advance(ptvc, 2);
2853         serv_type = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2854         ptvcursor_advance(ptvc, 1);
2855         kernel = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2856         ptvcursor_advance(ptvc, 1);
2858         expert_add_info_format(pinfo, NULL, &ei_ncp_server, "Server %s, version %d.%d, support pack %d, language %d, server type %s, kernel %s", fsname,
2859                                 maj_ver, min_ver, prod_rev, os_lang, val_to_str(serv_type & 0x01, serv_type_vals, "Unknown: %d"),
2860                                 val_to_str(kernel & 0x01, kernel_type_vals, "Unknown: %d") );
2861     }
2864 /* The following allows for Update file handle rights echoed to expert tap. */
2865 static void ncp42_request_expert_func(ptvcursor_t *ptvc, packet_info *pinfo, const ncp_record *ncp_rec _U_, bool request)
2867     if (ncp_echo_file && request) {
2868         char* filehandle = tvb_bytes_to_str(pinfo->pool, ptvcursor_tvbuff(ptvc),
2869                                                 ptvcursor_current_offset(ptvc)+1, 6);
2871         expert_add_info_format(pinfo, NULL, &ei_ncp_file_handle, "Close file handle %s", filehandle);
2872     }
2875 /* The following allows for oplock level 1 file opens echoed to expert tap. */
2876 static void file_rights_expert_func(ptvcursor_t *ptvc, packet_info *pinfo, const ncp_record *ncp_rec, bool request)
2878     if (ncp_echo_file) {
2879         if (request) {
2880             uint8_t oaction = 0, path_count = 0;
2881             uint16_t rights = 0;
2882             uint8_t* filename = "";
2884             if (ncp_rec->func == 87) {
2885                 switch(ncp_rec->subfunc)
2886                 {
2887                 case 1:
2888                 case 32:
2889                     oaction = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc)+1);
2890                     ptvcursor_advance(ptvc, 12);
2891                     rights = tvb_get_ntohs(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2892                     ptvcursor_advance(ptvc, 8);
2893                     path_count = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2894                     ptvcursor_advance(ptvc, 1);
2895                     filename = tvb_get_string_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2896                                 ptvcursor_current_offset(ptvc), path_count, ENC_ASCII);
2897                     break;
2898                 case 33:
2899                 case 30:
2900                     oaction = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc)+2);
2901                     ptvcursor_advance(ptvc, 16);
2902                     rights = tvb_get_ntohs(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2903                     ptvcursor_advance(ptvc, 8);
2904                     path_count = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2905                     ptvcursor_advance(ptvc, 1);
2906                     filename = tvb_get_string_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2907                                     ptvcursor_current_offset(ptvc), path_count, ENC_ASCII);
2908                     break;
2909                 }
2910             } else if (ncp_rec->func == 89) {
2911                 switch(ncp_rec->subfunc)
2912                 {
2913                 case 1:
2914                 case 32:
2915                     oaction = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc)+1);
2916                     ptvcursor_advance(ptvc, 12);
2917                     rights = tvb_get_ntohs(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2918                     ptvcursor_advance(ptvc, 14);
2919                     path_count = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2920                     ptvcursor_advance(ptvc, 1);
2921                     filename = tvb_get_string_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2922                                     ptvcursor_current_offset(ptvc), path_count, ENC_ASCII);
2923                     break;
2924                 case 33:
2925                 case 30:
2926                     oaction = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc)+2);
2927                     ptvcursor_advance(ptvc, 16);
2928                     rights = tvb_get_ntohs(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2929                     ptvcursor_advance(ptvc, 14);
2930                     path_count = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2931                     ptvcursor_advance(ptvc, 1);
2932                     filename = tvb_get_string_enc(pinfo->pool, ptvcursor_tvbuff(ptvc),
2933                                     ptvcursor_current_offset(ptvc), path_count, ENC_ASCII);
2934                     break;
2935                 }
2936             }
2938             expert_add_info_format(pinfo, NULL, &ei_ncp_file_rights,
2939                                 "Op-lock open, mode %s for filename %s with rights %s",
2940                                 val_to_str(oaction & 0xeb, open_create_mode_vals, "Unknown: %d"),
2941                                 filename,
2942                                 val_to_str(rights & 0x5f, ncp_rights_vals, "Unknown: %d"));
2943         } else {
2944             if ((ncp_rec->func == 89 || ncp_rec->func == 87) && (ncp_rec->subfunc == 32 || ncp_rec->subfunc == 1)) {
2945                 uint8_t oaction, oplockflg;
2946                 char* filehandle;
2948                 filehandle = tvb_bytes_to_str(pinfo->pool, ptvcursor_tvbuff(ptvc),
2949                                                 ptvcursor_current_offset(ptvc), 4);
2950                 ptvcursor_advance(ptvc, 4);
2951                 oaction = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2953                 if (ncp_rec->subfunc == 1) {
2954                     expert_add_info_format(pinfo, NULL, &ei_ncp_file_handle, "%s - File handle %s",
2955                                            val_to_str(oaction & 0x8f, open_create_action_vals, "Unknown: %d"),
2956                                            filehandle);
2957                 }
2958                 else
2959                 {
2960                     ptvcursor_advance(ptvc, 1);
2961                     oplockflg = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2962                     expert_add_info_format(pinfo, NULL, &ei_ncp_file_handle, "%s - File handle %s, %s",
2963                                            val_to_str(oaction & 0x8f, open_create_action_vals, "Unknown: %d"),
2964                                            filehandle,
2965                                            val_to_str(oplockflg, ncp_o_c_ret_flags_vals, "Unknown: %d"));
2966                 }
2967             }
2968         }
2969     }
2972 /* The following allows for oplock ack's and level 2 request echoed to expert tap. */
2973 static void ncp5722_request_expert_func(ptvcursor_t *ptvc, packet_info *pinfo, const ncp_record *ncp_rec _U_, bool request)
2975     if (ncp_echo_file && request) {
2976         uint32_t filehandle;
2977         uint8_t cc_function;
2979         filehandle = tvb_get_ntohl(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2980         ptvcursor_advance(ptvc, 4);
2981         cc_function = tvb_get_uint8(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
2983         expert_add_info_format(pinfo, NULL, &ei_ncp_op_lock_handle, "Op-lock on handle %08x - %s", filehandle,
2984                                 val_to_str(cc_function, ncp_cc_function_vals, "Unknown: %d"));
2985     }
2988 /* The following allows for Update file handle rights echoed to expert tap. */
2989 static void ncp572c_expert_func(ptvcursor_t *ptvc, packet_info *pinfo, const ncp_record *ncp_rec _U_, bool request)
2991     if (ncp_echo_file) {
2992         char* filehandle;
2994         if (request) {
2995             uint16_t access_rights, new_rights;
2997             access_rights = tvb_get_ntohs(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc)+8);
2998             ptvcursor_advance(ptvc, 10);
2999             new_rights = tvb_get_ntohs(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc));
3000             ptvcursor_advance(ptvc, 2);
3001             filehandle = tvb_bytes_to_str(pinfo->pool, ptvcursor_tvbuff(ptvc),
3002                                                     ptvcursor_current_offset(ptvc), 4);
3004             expert_add_info_format(pinfo, NULL, &ei_ncp_file_rights_change, "Change handle %s rights from:(%s) to:(%s)",
3005                                    filehandle,
3006                                    val_to_str(access_rights & 0x1ff, access_rights_vals, "Unknown: %d"),
3007                                    val_to_str(new_rights & 0x1ff, access_rights_vals, "Unknown: %d"));
3009         } else {
3010             uint32_t rights;
3012             filehandle = tvb_bytes_to_str(pinfo->pool, ptvcursor_tvbuff(ptvc),
3013                                                     ptvcursor_current_offset(ptvc), 4);
3014             ptvcursor_advance(ptvc, 4);
3015             rights = tvb_get_ntohl(ptvcursor_tvbuff(ptvc), ptvcursor_current_offset(ptvc)+8);
3017             expert_add_info_format(pinfo, NULL, &ei_ncp_effective_rights, "Handle %s effective rights:(%s)", filehandle,
3018                                     val_to_str(rights & 0x1ff, access_rights_vals, "Unknown: %d"));
3019         }
3020     }
3023 static void
3024 print_nds_values(proto_tree *vtree, packet_info* pinfo, tvbuff_t *tvb, uint32_t syntax_type, nds_val *vvalues)
3026     uint32_t        value1 = 0;
3027     uint32_t        value2 = 0;
3028     uint32_t        value3 = 0;
3029     uint32_t        value4 = 0;
3030     uint32_t        value5 = 0;
3031     uint32_t        voffset = 0, oldvoffset;
3032     uint32_t        icounter;
3033     uint32_t        number_of_values = 0;
3034     uint32_t        number_of_items = 0;
3035     uint32_t        r;
3036     proto_item      *vitem;
3037     proto_tree      *nvtree;
3038     proto_item      *aditem;
3039     proto_tree      *adtree;
3040     const char      *valuestr = NULL;
3041     int             length_remaining;
3042     nstime_t        ns;
3043     bool            entry_rights = false;
3045     voffset = vvalues->voffset;
3046 #if 0
3047     if(tvb_get_uint8(tvb, voffset) == 0x00)
3048     {
3049         voffset = voffset+2;
3050     }
3051 #endif
3053     number_of_values = tvb_get_letohl(tvb, voffset);
3055     vitem = proto_tree_add_uint_format(vtree, hf_nds_uint32value, tvb, voffset,
3056                                        4, number_of_values, "Number of Values: %u", number_of_values);
3058     nvtree = proto_item_add_subtree(vitem, ett_nds);
3060     oldvoffset = voffset;
3061     voffset = voffset + 4;
3063     for (icounter = 1 ; icounter <= number_of_values; icounter++ )
3064     {
3065         if (oldvoffset >= voffset) {
3066             proto_tree_add_expert_format(nvtree, pinfo, &ei_ncp_invalid_offset, tvb, 0, 0, "Invalid offset: %u", voffset);
3067             THROW(ReportedBoundsError);
3068         }
3069         oldvoffset = voffset;
3070         switch(syntax_type)
3071         {
3072         case 0x00000006:        /* Case Insensitive List */
3073         case 0x00000012:        /* Postal Address */
3074             voffset += align_4(tvb, voffset);
3075             voffset = voffset+4;
3076             number_of_items = tvb_get_letohl(tvb, voffset);
3077             voffset = voffset+4;
3078             for (r=1; r<=number_of_items; r++)
3079             {
3080                 value1 = tvb_get_letohl(tvb, voffset);
3081                 voffset = voffset + 4;
3082                 vvalues->vstring = get_string(tvb, voffset, value1);
3083                 proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3084                                       value1, vvalues->vstring);
3085                 voffset = check_offset_addition(voffset, value1, nvtree, pinfo, tvb);
3086                 voffset += align_4(tvb, voffset);
3087             }
3088             break;
3089         case 0x00000007:        /* Boolean */
3090             voffset+=4;                            /* this is always just a parameter count of 1, so ignore */
3091             value1 = tvb_get_uint8(tvb, voffset); /* Boolean value */
3092             if (value1==0)
3093             {
3094                 vvalues->vstring = "False";
3095             }
3096             else
3097             {
3098                 vvalues->vstring = "True";
3099             }
3100             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3101                                   1, vvalues->vstring);
3102             voffset=voffset+1;
3103             voffset += align_4(tvb, voffset);
3104             break;
3105         case 0x00000009:        /* Binary String */
3106             value1 = tvb_get_letohl(tvb, voffset); /* length of field */
3107             length_remaining = tvb_captured_length_remaining(tvb, voffset);
3108             if(length_remaining == -1 || value1 > (uint32_t) length_remaining)
3109             {
3110                 break;
3111             }
3112             voffset += 4;
3113             proto_tree_add_item(nvtree, hf_value_bytes, tvb, voffset, value1, ENC_NA);
3114             voffset += value1;
3115             voffset += (value1%2);
3116             break;
3117         case 0x0000000d:        /* Binary String List */
3118             value1 = tvb_get_letohl(tvb, voffset); /* Overall length of field list */
3119             length_remaining = tvb_captured_length_remaining(tvb, voffset);
3120             if(length_remaining == -1 || value1 > (uint32_t) length_remaining)
3121             {
3122                 break;
3123             }
3124             voffset += 4;
3125             tvb_ensure_bytes_exist(tvb, voffset, value1);
3126             number_of_items = tvb_get_letohl(tvb, voffset);
3127             voffset = voffset+4;
3128             for (r=1; r<=number_of_items; r++)
3129             {
3130                 value1 = tvb_get_letohl(tvb, voffset); /* length of field */
3131                 length_remaining = tvb_captured_length_remaining(tvb, voffset);
3132                 if(length_remaining == -1 || value1 > (uint32_t) length_remaining)
3133                 {
3134                     break;
3135                 }
3136                 voffset += 4;
3137                 proto_tree_add_item(nvtree, hf_value_bytes, tvb, voffset, value1, ENC_NA);
3138                 voffset += value1;
3139                 voffset += (value1%2);
3140             }
3141             break;
3142         case 0x00000015:        /* Stream */
3143             value1 = tvb_get_letohl(tvb, voffset); /* length of field */
3144             length_remaining = tvb_captured_length_remaining(tvb, voffset);
3145             if(length_remaining == -1 || value1 > (uint32_t) length_remaining)
3146             {
3147                 break;
3148             }
3149             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset, 4, value1, "No value, Open stream file for data.");
3150             voffset += 4;
3151             voffset += value1;
3152             voffset += (value1%2);
3153             break;
3154         case 0x00000008:        /* Signed Integer */
3155         case 0x00000016:        /* Counter */
3156         case 0x0000001b:        /* Interval */
3157             value1 = tvb_get_letohl(tvb, voffset); /* length of field */
3158             voffset = voffset+4;
3159             value2 = tvb_get_letohl(tvb, voffset); /* Value */
3160             if (strcmp(vvalues->vstring, "zendmSearchType")==0) {
3161                 proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3162                                            value1, value2,
3163                                            "Value (%d) = %s", value2,
3164                                            val_to_str(value2, zensearchenum, "Unknown: %d"));
3165             }
3166             else
3167             {
3168                 proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3169                                            value1, value2, "Value %d", value2);
3170             }
3171             voffset = voffset+4;
3172             break;
3173         case 0x0000000b:        /* Fax Number */
3174             value1 = tvb_get_letohl(tvb, voffset); /* length of field */
3175             voffset = voffset+4;
3176             vvalues->vstring = get_string(tvb, voffset, value1);
3177             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3178                                   value1, vvalues->vstring);
3179             voffset = check_offset_addition(voffset, value1, nvtree, pinfo, tvb);
3180             voffset += align_4(tvb, voffset);
3181             break;
3182         case 0x0000000c:        /* Network Address */
3183             value1 = tvb_get_letohl(tvb, voffset); /* length of field */
3184             voffset = voffset + 4;
3185             value2 = tvb_get_letohl(tvb, voffset); /* type of Protocol */
3186             valuestr = val_to_str_const(value2, nds_protocol_type, "(Undefined Protocol)");
3187             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3188                                        value1, value2, valuestr, value2);
3189             voffset = voffset+4;
3190             value3 = tvb_get_letohl(tvb, voffset); /* length of address */
3191             voffset = voffset+4;
3192             switch (value2)
3193             {
3194             case NDS_PTYPE_IPX:
3195                 proto_tree_add_item(nvtree, hf_nds_net, tvb, voffset, 4, ENC_BIG_ENDIAN);
3196                 proto_tree_add_item(nvtree, hf_nds_node, tvb, voffset+4, 6, ENC_NA);
3197                 proto_tree_add_item(nvtree, hf_nds_socket, tvb, voffset+10, 2, ENC_BIG_ENDIAN);
3198                 break;
3199             case NDS_PTYPE_IP:
3200                 if (value3 > 4) {
3201                     proto_tree_add_item(nvtree, hf_nds_port, tvb, voffset, 2, ENC_BIG_ENDIAN);
3202                     voffset += 2;
3203                 }
3204                 proto_tree_add_item(nvtree, hf_add_ref_ip, tvb, voffset, 4, ENC_BIG_ENDIAN);
3205                 break;
3206             case NDS_PTYPE_UDP:
3207                 if (value3 > 4) {
3208                     proto_tree_add_item(nvtree, hf_nds_port, tvb, voffset, 2, ENC_BIG_ENDIAN);
3209                     voffset += 2;
3210                 }
3211                 proto_tree_add_item(nvtree, hf_add_ref_udp, tvb, voffset, 4, ENC_BIG_ENDIAN);
3212                 break;
3213             case NDS_PTYPE_TCP:
3214                 proto_tree_add_item(nvtree, hf_nds_port, tvb, voffset, 2, ENC_BIG_ENDIAN);
3215                 proto_tree_add_item(nvtree, hf_add_ref_tcp, tvb, voffset+2, 4, ENC_BIG_ENDIAN);
3216                 break;
3217             case NDS_PTYPE_URL:
3218             case NDS_PTYPE_DNS:
3219                 vvalues->vstring = get_string(tvb, voffset, value3);
3220                 proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3221                                       value3, vvalues->vstring);
3222                 break;
3223             default:
3224                 break;
3225             }
3226             voffset = check_offset_addition(voffset, value3, nvtree, pinfo, tvb);
3227             voffset += align_4(tvb, voffset);
3228             break;
3229         case 0x0000000f:        /* File System Path */
3230             /*value1 = tvb_get_letohl(tvb, voffset);*/ /* length of field */
3231             voffset = voffset + 4;
3232             value2 = tvb_get_letohl(tvb, voffset); /* Name Space */
3233             valuestr = val_to_str_const(value2, name_space_type, "Unknown Name Space");
3234             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3235                                   4, valuestr);
3236             voffset = voffset+4;
3237             value3 = tvb_get_letohl(tvb, voffset); /* Length of Volume name */
3238             voffset = voffset+4;
3239             vvalues->vstring = get_string(tvb, voffset, value3);
3240             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3241                                   value3, vvalues->vstring);
3242             voffset = check_offset_addition(voffset, value3, nvtree, pinfo, tvb);
3243             voffset += align_4(tvb, voffset);
3244             value4 = tvb_get_letohl(tvb, voffset); /* Length of Path name */
3245             voffset = voffset+4;
3246             vvalues->vstring = get_string(tvb, voffset, value4);
3247             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3248                                   value4, vvalues->vstring);
3249             voffset = check_offset_addition(voffset, value4, nvtree, pinfo, tvb);
3250             voffset += align_4(tvb, voffset);
3251             break;
3252         case 0x00000010:        /* Replica Pointer */
3253             /*value1 = tvb_get_letohl(tvb, voffset);*/ /* length of field */
3254             voffset = voffset + 4;
3255             value2 = tvb_get_letohl(tvb, voffset); /* Length of Server name */
3256             voffset = voffset+4;
3257             vvalues->vstring = get_string(tvb, voffset, value2);
3258             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3259                                   value2, vvalues->vstring);
3260             voffset = check_offset_addition(voffset, value2, nvtree, pinfo, tvb);
3261             voffset += align_4(tvb, voffset);
3262             proto_tree_add_item(nvtree, hf_replica_type, tvb, voffset, 2, ENC_LITTLE_ENDIAN);
3263             voffset = voffset+2;
3264             proto_tree_add_item(nvtree, hf_replica_state, tvb, voffset, 2, ENC_LITTLE_ENDIAN);
3265             voffset = voffset+2;
3266             proto_tree_add_item(nvtree, hf_replica_number, tvb, voffset, 4, ENC_LITTLE_ENDIAN);
3267             voffset = voffset+4;
3268             if((vvalues->pflags & 0x8000) | (vvalues->pflags & 0x4000))
3269             {
3270                 /* If this request flag is set then this is a server. Server structures
3271                  * include the RootID as part of the replica data. */
3272                 proto_tree_add_item(nvtree, hf_nds_partition_root_id, tvb, voffset, 4, ENC_BIG_ENDIAN);
3273                 voffset += 4;
3274             }
3275             number_of_items = tvb_get_letohl(tvb, voffset);  /* Number of Addresses */
3276             aditem = proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3277                                                 4, number_of_items, "Number of Addresses: %u", number_of_items);
3279             adtree = proto_item_add_subtree(aditem, ett_nds);
3280             voffset = voffset+4;
3281             for (r=1; r <= number_of_items; r++)
3282             {
3283                 /* Trap for end of packet */
3284                 if(tvb_captured_length_remaining(tvb, voffset)<12)
3285                 {
3286                     THROW(ReportedBoundsError);
3287                 }
3288                 voffset += align_4(tvb, voffset);
3289                 value4 = tvb_get_letohl(tvb, voffset); /* type of Protocol */
3290                 valuestr = val_to_str_const(value4, nds_protocol_type, "(Undefined Protocol)");
3291                 proto_tree_add_uint_format(adtree, hf_nds_uint32value, tvb, voffset,
3292                                            4, value4, valuestr, value4);
3293                 voffset = voffset+4;
3294                 value5 = tvb_get_letohl(tvb, voffset); /* length of address */
3295                 voffset = voffset+4;
3296                 switch (value4)
3297                 {
3298                 case NDS_PTYPE_IPX:
3299                     proto_tree_add_item(adtree, hf_nds_net, tvb, voffset, 4, ENC_BIG_ENDIAN);
3300                     proto_tree_add_item(adtree, hf_nds_node, tvb, voffset+4, 6, ENC_NA);
3301                     proto_tree_add_item(adtree, hf_nds_socket, tvb, voffset+10, 2, ENC_BIG_ENDIAN);
3302                     break;
3303                 case NDS_PTYPE_IP:
3304                     proto_tree_add_item(adtree, hf_nds_port, tvb, voffset, 2, ENC_BIG_ENDIAN);
3305                     proto_tree_add_item(adtree, hf_add_ref_ip, tvb, voffset+2, 4, ENC_BIG_ENDIAN);
3306                     break;
3307                 case NDS_PTYPE_UDP:
3308                     proto_tree_add_item(adtree, hf_nds_port, tvb, voffset, 2, ENC_BIG_ENDIAN);
3309                     proto_tree_add_item(adtree, hf_add_ref_udp, tvb, voffset+2, 4, ENC_BIG_ENDIAN);
3310                     break;
3311                 case NDS_PTYPE_TCP:
3312                     proto_tree_add_item(adtree, hf_nds_port, tvb, voffset, 2, ENC_BIG_ENDIAN);
3313                     proto_tree_add_item(adtree, hf_add_ref_tcp, tvb, voffset+2, 4, ENC_BIG_ENDIAN);
3314                     break;
3315                 case NDS_PTYPE_URL:
3316                 case NDS_PTYPE_DNS:
3317                     vvalues->vstring = get_string(tvb, voffset, value5);
3318                     proto_tree_add_string(adtree, hf_value_string, tvb, voffset,
3319                                           value5, vvalues->vstring);
3320                     break;
3321                 default:
3322                     break;
3323                 }
3324                 voffset = check_offset_addition(voffset, value5, adtree, pinfo, tvb);
3325             }
3326             voffset += align_4(tvb, voffset);
3327             break;
3328         case 0x00000011:        /* Object ACL */
3329             /*value1 = tvb_get_letohl(tvb, voffset);*/ /* Length of Field */
3330             voffset = voffset + 4;
3331             value2 = tvb_get_letohl(tvb, voffset);
3332             voffset = voffset + 4;
3333             vvalues->vstring = get_string(tvb, voffset, value2); /* Unicode String */
3334             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3335                                   value2, vvalues->vstring);
3336             if (strcmp(vvalues->vstring, "[Entry Rights]")) {
3337                 entry_rights=true;
3338             }
3339             else
3340             {
3341                 entry_rights=false;
3342             }
3343             voffset = check_offset_addition(voffset, value2, nvtree, pinfo, tvb);
3344             voffset += align_4(tvb, voffset);
3345             value3 = tvb_get_letohl(tvb, voffset);
3346             voffset = voffset + 4;
3347             vvalues->vstring = get_string(tvb, voffset, value3); /* Unicode Subject Name */
3348             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3349                                   value3, vvalues->vstring);
3350             voffset = check_offset_addition(voffset, value3, nvtree, pinfo, tvb);
3351             voffset += align_4(tvb, voffset);
3352             /* Entry or Attribute Privileges */
3353             if (entry_rights) {
3354                 /* if Entries then use these bits */
3355                 static int * const entries[] = {
3356                     &hf_nds_compare_attributes,
3357                     &hf_nds_read_attribute,
3358                     &hf_nds_write_add_delete_attribute,
3359                     &hf_nds_add_delete_self,
3360                     &hf_nds_privilege_not_defined,
3361                     &hf_nds_supervisor,
3362                     &hf_nds_inheritance_control,
3363                     &hf_bit8vflags,
3364                     &hf_bit9vflags,
3365                     &hf_bit10vflags,
3366                     &hf_bit11vflags,
3367                     &hf_bit12vflags,
3368                     &hf_bit13vflags,
3369                     &hf_bit14vflags,
3370                     &hf_bit15vflags,
3371                     &hf_bit16vflags,
3372                     NULL
3373                 };
3375                 proto_tree_add_bitmask(nvtree, tvb, voffset, hf_nds_privileges, ett_ncp, entries, ENC_LITTLE_ENDIAN);
3376             }
3377             else
3378             {
3379                 /* if attribute rights then do these bits */
3380                 static int * const rights[] = {
3381                     &hf_nds_browse_entry,
3382                     &hf_nds_add_entry,
3383                     &hf_nds_delete_entry,
3384                     &hf_nds_rename_entry,
3385                     &hf_nds_supervisor_entry,
3386                     &hf_nds_entry_privilege_not_defined,
3387                     &hf_nds_inheritance_control,
3388                     &hf_bit8vflags,
3389                     &hf_bit9vflags,
3390                     &hf_bit10vflags,
3391                     &hf_bit11vflags,
3392                     &hf_bit12vflags,
3393                     &hf_bit13vflags,
3394                     &hf_bit14vflags,
3395                     &hf_bit15vflags,
3396                     &hf_bit16vflags,
3397                     NULL
3398                 };
3400                 proto_tree_add_bitmask(nvtree, tvb, voffset, hf_nds_privileges, ett_ncp, rights, ENC_LITTLE_ENDIAN);
3401             }
3402             voffset = voffset+4;
3403             voffset += align_4(tvb, voffset);
3404             break;
3405         case 0x00000013:        /* Time Stamp */
3406             value1 = tvb_get_letohl(tvb, voffset);         /* Seconds */
3407             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3408                                        4, value1, "Length of Record: %u", value1);
3409             voffset = voffset+4;
3410             ns.secs = tvb_get_letohl(tvb, voffset);
3411             ns.nsecs = 0;
3412             proto_tree_add_time_format(nvtree, hf_nds_ds_time, tvb, voffset, 4,
3413                 &ns, "Timestamp: %s", abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
3414             voffset = voffset + 4;
3415             proto_tree_add_item(nvtree, hf_nds_rnum, tvb, voffset, 2, ENC_LITTLE_ENDIAN);
3416             voffset = voffset+2;
3417             proto_tree_add_item(nvtree, hf_nds_revent, tvb, voffset, 2, ENC_LITTLE_ENDIAN);
3418             voffset = voffset+2;
3419             voffset += align_4(tvb, voffset);
3420             break;
3421         case 0x00000017:        /* Back Link */
3422             value1 = tvb_get_letohl(tvb, voffset);         /* Length */
3423             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3424                                        4, value1, "Length of Record %08x", value1);
3425             voffset = voffset+4;
3426             value2 = tvb_get_letohl(tvb, voffset);         /* Remote ID */
3427             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3428                                        4, value2, "Remote ID %08x", value2);
3429             voffset = voffset+4;
3430             value3 = tvb_get_letohl(tvb, voffset);         /* Length of string */
3431             voffset = voffset+4;
3432             vvalues->vstring = get_string(tvb, voffset, value3);
3433             proto_tree_add_string_format(nvtree, hf_value_string, tvb, voffset,
3434                                          value3, vvalues->vstring,
3435                                          "Server Distinguished Name - %s", vvalues->vstring);
3436             voffset = voffset+value3;
3437             voffset += align_4(tvb, voffset);
3438             break;
3439         case 0x00000018:        /* Time */
3440             voffset += 4; /* This is the length of the time data no need to decode, always 4 bytes */
3441             ns.secs = tvb_get_letohl(tvb, voffset);
3442             ns.nsecs = 0;
3443             proto_tree_add_time_format(nvtree, hf_nds_ds_time, tvb, voffset, 4,
3444                 &ns, "Time: %s", abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
3445             voffset = voffset + 4;
3446             break;
3447         case 0x00000019:        /* Typed Name */
3448             value1 = tvb_get_letohl(tvb, voffset);         /* Length */
3449             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3450                                        4, value1, "Length of Record %08x", value1);
3451             voffset = voffset+4;
3452             value2 = tvb_get_letohl(tvb, voffset);         /* Level */
3453             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3454                                        4, value2, "Level %d", value2);
3455             voffset = voffset+4;
3456             value3 = tvb_get_letohl(tvb, voffset);         /* Interval */
3457             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3458                                        4, value3, "Interval %d", value3);
3459             voffset = voffset+4;
3460             value4 = tvb_get_letohl(tvb, voffset);         /* Distinguished Name */
3461             voffset = voffset+4;
3462             vvalues->vstring = get_string(tvb, voffset, value4);
3463             proto_tree_add_string_format(nvtree, hf_value_string, tvb, voffset,
3464                                          value4, vvalues->vstring,
3465                                          "Distinguished Name - %s", vvalues->vstring);
3466             voffset = voffset+value4;
3467             voffset += align_4(tvb, voffset);
3468             break;
3469         case 0x0000001a:        /* Hold */
3470             value1 = tvb_get_letohl(tvb, voffset);         /* Length */
3471             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3472                                        4, value1, "Length of Record %08x", value1);
3473             voffset = voffset+4;
3474             value2 = tvb_get_letohl(tvb, voffset);         /* Amount */
3475             proto_tree_add_uint_format(nvtree, hf_nds_uint32value, tvb, voffset,
3476                                        4, value2, "Amount %d", value2);
3477             voffset = voffset+4;
3478             value3 = tvb_get_letohl(tvb, voffset);         /* Subject */
3479             voffset = voffset+4;
3480             vvalues->vstring = get_string(tvb, voffset, value3);
3481             proto_tree_add_string_format(nvtree, hf_value_string, tvb, voffset,
3482                                          value3, vvalues->vstring,
3483                                          "Subject - %s", vvalues->vstring);
3484             voffset = voffset+value3;
3485             voffset += align_4(tvb, voffset);
3486             break;
3487         case 0x00000001:        /* Distinguished Name */
3488         case 0x00000002:        /* Case Sensitive Unicode String */
3489         case 0x00000003:        /* Non Case Sensitive Unicode String */
3490         case 0x00000004:        /* Printable String */
3491         case 0x00000005:        /* Numeric String */
3492         case 0x0000000a:        /* Telephone Number */
3493         case 0x0000000e:        /* Email Address */
3494         case 0x00000014:        /* Class Name */
3495         default:
3496             value1 = tvb_get_letohl(tvb, voffset);
3497             voffset = voffset + 4;
3498             if (strcmp(vvalues->vstring, "zendmSearchOrder")==0) {
3499                 vvalues->vstring = get_string(tvb, voffset, value1);
3500                 if (strcmp(vvalues->vstring, "0")==0) {
3501                     vvalues->vstring = "Value (0) = Object";
3502                 }
3503                 else if (strcmp(vvalues->vstring, "1")==0) {
3504                     vvalues->vstring = "Value (1) = Group";
3505                 }
3506                 else if (strcmp(vvalues->vstring, "2")==0) {
3507                     vvalues->vstring = "Value (2) = Container";
3508                 }
3509                 else if (strcmp(vvalues->vstring, "01")==0) {
3510                     vvalues->vstring = "Value (01) = Object, Group";
3511                 }
3512                 else if (strcmp(vvalues->vstring, "02")==0) {
3513                     vvalues->vstring = "Value (02) = Object, Container";
3514                 }
3515                 else if (strcmp(vvalues->vstring, "10")==0) {
3516                     vvalues->vstring = "Value (10) = Group, Object";
3517                 }
3518                 else if (strcmp(vvalues->vstring, "12")==0) {
3519                     vvalues->vstring = "Value (12) = Group, Container";
3520                 }
3521                 else if (strcmp(vvalues->vstring, "20")==0) {
3522                     vvalues->vstring = "Value (20) = Container, Object";
3523                 }
3524                 else if (strcmp(vvalues->vstring, "21")==0) {
3525                     vvalues->vstring = "Value (21) = Container, Group";
3526                 }
3527                 else if (strcmp(vvalues->vstring, "012")==0) {
3528                     vvalues->vstring = "Value (012) = Object, Group, Container";
3529                 }
3530                 else if (strcmp(vvalues->vstring, "021")==0) {
3531                     vvalues->vstring = "Value (021) = Object, Container, Group";
3532                 }
3533                 else if (strcmp(vvalues->vstring, "102")==0) {
3534                     vvalues->vstring = "Value (102) = Group, Object, Container";
3535                 }
3536                 else if (strcmp(vvalues->vstring, "120")==0) {
3537                     vvalues->vstring = "Value (120) = Group, Container, Object";
3538                 }
3539                 else if (strcmp(vvalues->vstring, "201")==0) {
3540                     vvalues->vstring = "Value (201) = Container, Object, Group";
3541                 }
3542                 else if (strcmp(vvalues->vstring, "210")==0) {
3543                     vvalues->vstring = "Value (210) = Container, Group, Object";
3544                 }
3545             }
3546             else
3547             {
3548                 vvalues->vstring = get_string(tvb, voffset, value1);
3549             }
3550             proto_tree_add_string(nvtree, hf_value_string, tvb, voffset,
3551                                   value1, vvalues->vstring);
3552             voffset = voffset + value1;
3553             voffset += align_4(tvb, voffset);
3554             break;
3555         }
3556         voffset += align_4(tvb, voffset);
3557     }
3558     vvalues->voffset=voffset;
3559     return;
3562 static uint32_t
3563 print_es_type(proto_tree *estree, tvbuff_t *tvb, nds_val *values, uint32_t vtype, uint32_t ioffset)
3565     uint32_t        value1;
3566     uint32_t        value2;
3567     uint32_t        value3;
3568     uint32_t        value4;
3569     uint32_t        value5;
3570     uint32_t        number_of_referrals;
3571     uint32_t        r;
3572     uint32_t        i;
3573     proto_tree      *nestree;
3574     proto_item      *nesitem;
3575     proto_tree      *sub1tree;
3576     proto_item      *sub1item;
3577     proto_tree      *sub2tree;
3578     const char      *vstring="";
3579     nstime_t        ns;
3581     switch (vtype)
3582     {
3583     case 0: /* No Specifier Type */
3584         /* ES Type */
3585         proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
3586                             4, ENC_LITTLE_ENDIAN);
3587         ioffset = ioffset + 4;
3588         break;
3589     case 1: /* Unicode String */
3590         value1 = tvb_get_letohl(tvb, ioffset);   /* Delimiter Set */
3591         ioffset = ioffset + 4;
3592         values->vstring = get_string(tvb, ioffset, value1);
3593         proto_tree_add_string_format(estree, hf_mv_string, tvb, ioffset,
3594                                      value1, values->vstring, "Delimiter ->%s", values->vstring);
3595         ioffset=ioffset + value1;
3596         ioffset += align_4(tvb, ioffset);
3597         value2 = tvb_get_letohl(tvb, ioffset);
3598         ioffset = ioffset + 4;
3599         values->vstring = get_string(tvb, ioffset, value2);
3600         proto_tree_add_string(estree, hf_mv_string, tvb, ioffset,
3601                               value2, values->vstring);
3602         values->voffset = check_offset_addition(ioffset, value2, estree, NULL, tvb);
3603         ioffset = values->voffset;
3604         ioffset += align_4(tvb, ioffset);
3605         break;
3606     case 2: /* Based */
3607         value1 = tvb_get_letohl(tvb, ioffset);   /* ES Type */
3608         vstring = val_to_str_const(value1, es_type, "No ES Type Found");
3609         nesitem = proto_tree_add_string_format(estree, hf_es_type, tvb, ioffset,
3610                                                4, vstring, "Base Context Type - %s", vstring);
3611         nestree = proto_item_add_subtree(nesitem, ett_nds);
3612         ioffset = ioffset + 4;
3613         switch (value1)
3614         {
3615         case 0: /* No Specifier Type */
3616             /* ES Type */
3617             proto_tree_add_item(nestree, hf_es_value, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
3618             ioffset = ioffset + 4;
3619             break;
3620         case 1: /* Unicode String */
3621             value2 = tvb_get_letohl(tvb, ioffset);   /* Delimiter Set */
3622             ioffset = ioffset + 4;
3623             values->vstring = get_string(tvb, ioffset, value2);
3624             proto_tree_add_string_format(nestree, hf_mv_string, tvb, ioffset,
3625                                          value2, values->vstring, "Delimiter ->%s", values->vstring);
3626             ioffset = check_offset_addition(ioffset, value2, nestree, NULL, tvb);
3627             ioffset += align_4(tvb, ioffset);
3628             value3 = tvb_get_letohl(tvb, ioffset);
3629             ioffset = ioffset + 4;
3630             values->vstring = get_string(tvb, ioffset, value3);
3631             proto_tree_add_string(nestree, hf_mv_string, tvb, ioffset,
3632                                   value3, values->vstring);
3633             values->voffset=ioffset + value3;
3634             ioffset = values->voffset;
3635             ioffset += align_4(tvb, ioffset);
3636             break;
3637         case 2: /* Based */
3638             break;
3639         case 3: /* Hinted */
3640             break;
3641         case 4: /* Tuned */
3642             value2 = tvb_get_letohl(tvb, ioffset);   /* Count */
3643             proto_tree_add_item(nestree, hf_es_rdn_count, tvb, ioffset,
3644                                 4, ENC_LITTLE_ENDIAN);
3645             ioffset = ioffset + 4;
3646             for (r = 1 ; r <= value2; r++ )
3647             {
3648                 ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
3649                 ns.nsecs = 0;
3650                 proto_tree_add_time_format(nestree, hf_es_seconds, tvb, ioffset,
3651                                            4, &ns, "Timestamp: %s",
3652                                            abs_time_secs_to_str(wmem_packet_scope(), ns.secs, ABSOLUTE_TIME_LOCAL, true));
3653                 ioffset = ioffset + 4;
3654                 proto_tree_add_item(nestree, hf_nds_replica_num, tvb, ioffset,
3655                                     2, ENC_LITTLE_ENDIAN);
3656                 ioffset = ioffset + 2;
3657                 proto_tree_add_item(nestree, hf_nds_event_num, tvb, ioffset,
3658                                     2, ENC_LITTLE_ENDIAN);
3659                 ioffset = ioffset + 2;
3660             }
3661             value4 = tvb_get_letohl(tvb, ioffset);   /* Delimiter Set */
3662             ioffset = ioffset + 4;
3663             values->vstring = get_string(tvb, ioffset, value4);
3664             proto_tree_add_string(nestree, hf_mv_string, tvb, ioffset,
3665                                   value4, values->vstring);
3666             ioffset=ioffset + value4;
3667             ioffset += align_4(tvb, ioffset);
3668             value5 = tvb_get_letohl(tvb, ioffset);   /* RDN */
3669             ioffset = ioffset + 4;
3670             values->vstring = get_string(tvb, ioffset, value5);
3671             proto_tree_add_string(nestree, hf_rdn_string, tvb, ioffset,
3672                                   value5, values->vstring);
3673             ioffset=ioffset + value5;
3674             ioffset += align_4(tvb, ioffset);
3675             break;
3676         case 5: /* GUID */
3677         case 6: /* ID32 */
3678         case 7: /* Count */
3679         default:
3680             /* ES Type */
3681             /* XXX: nestree rather than estree ?? */
3682             proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
3683                                 4, ENC_LITTLE_ENDIAN);
3684             ioffset = ioffset + 4;
3685             break;
3686         }
3687         value1 = tvb_get_letohl(tvb, ioffset);   /* ES Type */
3688         vstring = val_to_str_const(value1, es_type, "No ES Type Found");
3689         nesitem = proto_tree_add_string_format(estree, hf_es_type, tvb, ioffset,
3690                                                4, vstring, "Object Name Type - %s", vstring);
3691         nestree = proto_item_add_subtree(nesitem, ett_nds);
3692         ioffset = ioffset + 4;
3693         switch (value1)
3694         {
3695         case 0: /* No Specifier Type */
3696             /* ES Type */
3697             proto_tree_add_item(nestree, hf_es_value, tvb, ioffset,
3698                                 4, ENC_LITTLE_ENDIAN);
3699             ioffset = ioffset + 4;
3700             break;
3701         case 1: /* Unicode String */
3702             value2 = tvb_get_letohl(tvb, ioffset);   /* Delimiter Set */
3703             ioffset = ioffset + 4;
3704             values->vstring = get_string(tvb, ioffset, value2);
3705             proto_tree_add_string_format(nestree, hf_mv_string, tvb, ioffset,
3706                                          value2, values->vstring, "Delimiter ->%s", values->vstring);
3707             ioffset = check_offset_addition(ioffset, value2, nestree, NULL, tvb);
3708             ioffset += align_4(tvb, ioffset);
3709             value3 = tvb_get_letohl(tvb, ioffset);
3710             ioffset = ioffset + 4;
3711             values->vstring = get_string(tvb, ioffset, value3);
3712             proto_tree_add_string(nestree, hf_mv_string, tvb, ioffset,
3713                                   value3, values->vstring);
3714             values->voffset=ioffset + value3;
3715             ioffset = values->voffset;
3716             ioffset += align_4(tvb, ioffset);
3717             break;
3718         case 2: /* Based */
3719             break;
3720         case 3: /* Hinted */
3721             break;
3722         case 4: /* Tuned */
3723             /* Count */
3724             proto_tree_add_item_ret_uint(nestree, hf_es_rdn_count, tvb, ioffset,
3725                                 4, ENC_LITTLE_ENDIAN, &value2);
3726             ioffset = ioffset + 4;
3727             for (r = 1 ; r <= value2; r++ )
3728             {
3729                 ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
3730                 ns.nsecs = 0;
3731                 proto_tree_add_time_format(nestree, hf_es_seconds, tvb, ioffset,
3732                                            4, &ns, "Timestamp: %s",
3733                                            abs_time_secs_to_str(wmem_packet_scope(), ns.secs, ABSOLUTE_TIME_LOCAL, true));
3734                 ioffset = ioffset + 4;
3735                 proto_tree_add_item(nestree, hf_nds_replica_num, tvb, ioffset,
3736                                     2, ENC_LITTLE_ENDIAN);
3737                 ioffset = ioffset + 2;
3738                 proto_tree_add_item(nestree, hf_nds_event_num, tvb, ioffset,
3739                                     2, ENC_LITTLE_ENDIAN);
3740                 ioffset = ioffset + 2;
3741             }
3742             value4 = tvb_get_letohl(tvb, ioffset);   /* Delimiter Set */
3743             ioffset = ioffset + 4;
3744             values->vstring = get_string(tvb, ioffset, value4);
3745             proto_tree_add_string(nestree, hf_mv_string, tvb, ioffset,
3746                                   value4, values->vstring);
3747             ioffset=ioffset + value4;
3748             ioffset += align_4(tvb, ioffset);
3749             value5 = tvb_get_letohl(tvb, ioffset);   /* RDN */
3750             ioffset = ioffset + 4;
3751             values->vstring = get_string(tvb, ioffset, value5);
3752             proto_tree_add_string(nestree, hf_rdn_string, tvb, ioffset,
3753                                   value5, values->vstring);
3754             ioffset=ioffset + value5;
3755             ioffset += align_4(tvb, ioffset);
3756             break;
3757         case 5: /* GUID */
3758         case 6: /* ID32 */
3759         case 7: /* Count */
3760         default:
3761             /* ES Type */
3762             /* XXX: nestree rather than estree ?? */
3763             proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
3764                                 4, ENC_LITTLE_ENDIAN);
3765             ioffset = ioffset + 4;
3766             break;
3767         }
3768         break;
3769     case 3: /* Hinted */
3770         number_of_referrals = tvb_get_letohl(tvb, ioffset);
3772         for (r = 1 ; r <= number_of_referrals; r++ )
3773         {
3774             sub1item = proto_tree_add_uint_format(estree, hf_referral_record, tvb, 6, 0,
3775                                                   r, "NDS Referral Record #%u", r);
3776             sub1tree = proto_item_add_subtree(sub1item, ett_nds);
3778             proto_tree_add_item_ret_uint(sub1tree, hf_referral_addcount, tvb, ioffset, 4, ENC_LITTLE_ENDIAN, &value1);
3780             ioffset = ioffset + 4;
3781             for (i = 1 ; i <= value1; i++ )
3782             {
3783                 value2 = tvb_get_letohl(tvb, ioffset);
3784                 values->vstring = val_to_str_const(value2, nds_protocol_type, "(Undefined Protocol)");
3785                 proto_tree_add_uint_format(sub1tree, hf_nds_uint32value, tvb, ioffset,
3786                                            4, value2, vstring, value2);
3787                 ioffset = ioffset+4;
3788                 value3 = tvb_get_letohl(tvb, ioffset);
3789                 ioffset = ioffset+4;
3790                 switch (value2)
3791                 {
3792                 case NDS_PTYPE_IPX:
3793                     proto_tree_add_item(sub1tree, hf_nds_net, tvb, ioffset, 4, ENC_BIG_ENDIAN);
3794                     proto_tree_add_item(sub1tree, hf_nds_node, tvb, ioffset+4, 6, ENC_NA);
3795                     proto_tree_add_item(sub1tree, hf_nds_socket, tvb, ioffset+10, 2, ENC_BIG_ENDIAN);
3796                     break;
3797                 case NDS_PTYPE_IP:
3798                     proto_tree_add_item(sub1tree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
3799                     proto_tree_add_item(sub1tree, hf_add_ref_ip, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
3800                     break;
3801                 case NDS_PTYPE_UDP:
3802                     proto_tree_add_item(sub1tree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
3803                     proto_tree_add_item(sub1tree, hf_add_ref_udp, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
3804                     break;
3805                 case NDS_PTYPE_TCP:
3806                     proto_tree_add_item(sub1tree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
3807                     proto_tree_add_item(sub1tree, hf_add_ref_tcp, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
3808                     break;
3809                 case NDS_PTYPE_URL:
3810                 case NDS_PTYPE_DNS:
3811                     values->vstring = get_string(tvb, ioffset, value3);
3812                     proto_tree_add_string(sub1tree, hf_value_string, tvb, ioffset,
3813                                           value3, values->vstring);
3814                     break;
3815                 default:
3816                     break;
3817                 }
3818                 ioffset = check_offset_addition(ioffset, value3, sub1tree, NULL, tvb);
3819                 ioffset += align_4(tvb, ioffset);
3820             }
3822         }
3823         value1 = tvb_get_letohl(tvb, ioffset);   /* ES Type */
3824         vstring = val_to_str_const(value1, es_type, "No ES Type Found");
3825         nesitem = proto_tree_add_string_format(estree, hf_es_type, tvb, ioffset,
3826                                                4, vstring, "Object Name Type - %s", vstring);
3827         nestree = proto_item_add_subtree(nesitem, ett_nds);
3828         ioffset = ioffset + 4;
3829         switch (value1)
3830         {
3831         case 0: /* No Specifier Type */
3832             /* ES Type */
3833             proto_tree_add_item(nestree, hf_es_value, tvb, ioffset,
3834                                 4, ENC_LITTLE_ENDIAN);
3835             ioffset = ioffset + 4;
3836             break;
3837         case 1: /* Unicode String */
3838             value2 = tvb_get_letohl(tvb, ioffset);   /* Delimiter Set */
3839             ioffset = ioffset + 4;
3840             values->vstring = get_string(tvb, ioffset, value2);
3841             proto_tree_add_string_format(nestree, hf_mv_string, tvb, ioffset,
3842                                          value2, values->vstring, "Delimiter ->%s", values->vstring);
3843             ioffset = check_offset_addition(ioffset, value2, nestree, NULL, tvb);
3844             ioffset += align_4(tvb, ioffset);
3845             value3 = tvb_get_letohl(tvb, ioffset);
3846             ioffset = ioffset + 4;
3847             values->vstring = get_string(tvb, ioffset, value3);
3848             proto_tree_add_string(nestree, hf_mv_string, tvb, ioffset,
3849                                   value3, values->vstring);
3850             values->voffset=check_offset_addition(ioffset, value3, nestree, NULL, tvb);
3851             ioffset = values->voffset;
3852             ioffset += align_4(tvb, ioffset);
3853             break;
3854         case 2: /* Based */
3855             break;
3856         case 3: /* Hinted */
3857             break;
3858         case 4: /* Tuned */
3859             /* Count */
3860             proto_tree_add_item_ret_uint(nestree, hf_es_rdn_count, tvb, ioffset,
3861                                 4, ENC_LITTLE_ENDIAN, &value2);
3862             ioffset = ioffset + 4;
3863             for (r = 1 ; r <= value2; r++ )
3864             {
3865                 ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
3866                 ns.nsecs = 0;
3867                 proto_tree_add_time_format(nestree, hf_es_seconds, tvb, ioffset,
3868                                            4, &ns, "Timestamp: %s",
3869                                            abs_time_secs_to_str(wmem_packet_scope(), ns.secs, ABSOLUTE_TIME_LOCAL, true));
3870                 ioffset = ioffset + 4;
3871                 proto_tree_add_item(nestree, hf_nds_replica_num, tvb, ioffset,
3872                                     2, ENC_LITTLE_ENDIAN);
3873                 ioffset = ioffset + 2;
3874                 proto_tree_add_item(nestree, hf_nds_event_num, tvb, ioffset,
3875                                     2, ENC_LITTLE_ENDIAN);
3876                 ioffset = ioffset + 2;
3877             }
3878             value4 = tvb_get_letohl(tvb, ioffset);   /* Delimiter Set */
3879             ioffset = ioffset + 4;
3880             values->vstring = get_string(tvb, ioffset, value4);
3881             proto_tree_add_string(nestree, hf_mv_string, tvb, ioffset,
3882                                   value4, values->vstring);
3883             ioffset = check_offset_addition(ioffset, value4, nestree, NULL, tvb);
3884             ioffset += align_4(tvb, ioffset);
3885             value5 = tvb_get_letohl(tvb, ioffset);   /* RDN */
3886             ioffset = ioffset + 4;
3887             values->vstring = get_string(tvb, ioffset, value5);
3888             proto_tree_add_string(nestree, hf_rdn_string, tvb, ioffset,
3889                                   value5, values->vstring);
3890             ioffset = check_offset_addition(ioffset, value5, nestree, NULL, tvb);
3891             ioffset += align_4(tvb, ioffset);
3892             break;
3893         case 5: /* GUID */
3894         case 6: /* ID32 */
3895         case 7: /* Count */
3896         default:
3897             /* ES Type */
3898             /* XXX: nestree rather than estree ?? */
3899             proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
3900                                 4, ENC_LITTLE_ENDIAN);
3901             ioffset = ioffset + 4;
3902             break;
3903         }
3904         break;
3905     case 4: /* Tuned */
3906         value1 = tvb_get_letohl(tvb, ioffset);
3907         sub1item = proto_tree_add_uint_format(estree, hf_es_rdn_count, tvb, ioffset,
3908                                               4, value1, "Number of RDN Items %u", value1);
3909         sub1tree = proto_item_add_subtree(sub1item, ett_nds);
3910         ioffset = ioffset + 4;
3911         for (r = 1 ; r <= value1; r++ )
3912         {
3913             sub2tree = proto_tree_add_subtree_format(sub1tree, tvb, ioffset, 10, ett_nds, NULL, "Item %u", r);
3915             ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
3916             ns.nsecs = 0;
3917             proto_tree_add_time_format(sub2tree, hf_es_seconds, tvb, ioffset,
3918                                        4, &ns, "Timestamp: %s",
3919                                        abs_time_secs_to_str(wmem_packet_scope(), ns.secs, ABSOLUTE_TIME_LOCAL, true));
3920             ioffset = ioffset + 4;
3921             proto_tree_add_item(sub2tree, hf_nds_replica_num, tvb, ioffset,
3922                                 2, ENC_LITTLE_ENDIAN);
3923             ioffset = ioffset + 2;
3924             proto_tree_add_item(sub2tree, hf_nds_event_num, tvb, ioffset,
3925                                 2, ENC_LITTLE_ENDIAN);
3926             ioffset = ioffset + 2;
3927         }
3928         value3 = tvb_get_letohl(tvb, ioffset);   /* Delimiter Set */
3929         ioffset = ioffset + 4;
3930         values->vstring = get_string(tvb, ioffset, value3);
3931         proto_tree_add_string(sub1tree, hf_mv_string, tvb, ioffset,
3932                               value3, values->vstring);
3933         ioffset = check_offset_addition(ioffset, value3, sub1tree, NULL, tvb);
3934         ioffset += align_4(tvb, ioffset);
3935         value4 = tvb_get_letohl(tvb, ioffset);   /* RDN */
3936         ioffset = ioffset + 4;
3937         values->vstring = get_string(tvb, ioffset, value4);
3938         proto_tree_add_string(sub1tree, hf_rdn_string, tvb, ioffset,
3939                               value4, values->vstring);
3940         ioffset=check_offset_addition(ioffset, value4, sub1tree, NULL, tvb);
3941         ioffset += align_4(tvb, ioffset);
3942         break;
3943     case 5: /* GUID */
3944     case 6: /* ID32 */
3945     case 7: /* Count */
3946     default:
3947         /* ES Type */
3948         proto_tree_add_item(estree, hf_es_value, tvb, ioffset,
3949                             4, ENC_LITTLE_ENDIAN);
3950         ioffset = ioffset + 4;
3951         break;
3952     }
3953     return ioffset;
3957 static void process_set_filter(proto_tree* , tvbuff_t*, packet_info*, nds_val*);
3959 static void
3960 process_search_expression(proto_tree *it_tree, tvbuff_t *tvb, nds_val *values)
3962     uint32_t    search_tag, ioffset;
3963     const char *search_string;
3965     ioffset = values->voffset;
3966     search_tag = tvb_get_letohl(tvb, ioffset); /* Get next search operation tag */
3967     search_string = val_to_str_const(search_tag, itersearchenum, "(No Search Operation Type Found!)");
3968     proto_tree_add_uint_format(it_tree, hf_iter_search, tvb, ioffset, 4,
3969                                search_tag, "Search Operation Type: %d, (0x%04x), %s",
3970                                search_tag, search_tag, search_string);
3971     ioffset += 4;
3972     switch (search_tag)
3973     {
3974     case NDS_SEARCH_EQUAL:
3975     case NDS_SEARCH_GREATER_OR_EQUAL:
3976     case NDS_SEARCH_LESS_OR_EQUAL:
3977     case NDS_SEARCH_APPROX:
3978     case NDS_SEARCH_ATTR_FLAGS:
3979     case NDS_SEARCH_ATTR_HAS_FLAG:
3980         /* start of DCWPutAttribute */
3981         values->vvalue = tvb_get_letohl(tvb, ioffset);
3982         ioffset = ioffset + 4;
3983         values->vstring = get_string(tvb, ioffset, values->vvalue);
3984         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
3985                               values->vvalue, values->vstring);
3986         ioffset += values->vvalue;
3987         /* end of DCWPutAttribute */
3989         ioffset += align_4(tvb, ioffset);
3991         /* start of DCWPutValue */
3992         proto_tree_add_item(it_tree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
3993         ioffset = ioffset + 4;
3994         values->vvalue = tvb_get_letohl(tvb, ioffset);
3995         ioffset = ioffset + 4;
3996         values->vstring = get_string(tvb, ioffset, values->vvalue);
3997         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
3998                               values->vvalue, values->vstring);
3999         ioffset += values->vvalue;
4000         /* end of DCWPutValue */
4002         break;
4003     case NDS_SEARCH_PRESENT:
4004         /* start of DCWPutAttribute */
4005         values->vvalue = tvb_get_letohl(tvb, ioffset);
4006         ioffset = ioffset + 4;
4007         values->vstring = get_string(tvb, ioffset, values->vvalue);
4008         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4009                               values->vvalue, values->vstring);
4010         ioffset = check_offset_addition(ioffset, values->vvalue, it_tree, NULL, tvb);
4011         /* end of DCWPutAttribute */
4012         break;
4014     case NDS_SEARCH_RDN:
4015         /* print the relative distinguished name. This includes context info... */
4016 #if 0
4017         if (err = DCWPutRDN(context, cur, limit, item->data))
4018             return err;
4019 #endif
4021         values->vvalue = tvb_get_letohl(tvb, ioffset);
4022         ioffset = ioffset + 4;
4023         values->vstring = get_string(tvb, ioffset, values->vvalue);
4024         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4025                               values->vvalue, values->vstring);
4026         ioffset += values->vvalue;
4027         break;
4028     case NDS_SEARCH_BASE_CLASS:
4029     case NDS_SEARCH_ENTRY_FLAGS:
4030     case NDS_SEARCH_ENTRY_HAS_FLAG:
4031     case NDS_SEARCH_VALUE_FLAGS:
4032     case NDS_SEARCH_VALUE_HAS_FLAG:
4033         /* start of DCWPutValue */
4034 #if 0
4035         proto_tree_add_item(it_tree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4036         ioffset = ioffset + 4;
4037 #endif
4038         values->vvalue = tvb_get_letohl(tvb, ioffset);
4039         ioffset = ioffset + 4;
4040         values->vstring = get_string(tvb, ioffset, values->vvalue);
4041         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4042                               values->vvalue, values->vstring);
4043         ioffset += values->vvalue;
4044         /* end of DCWPutValue */
4045         break;
4046     case DCS_VALUE_GE_WITH_ATTR:        /* Deprecated, use DS_SEARCH_VALUE_MTS_GE */
4047     case NDS_SEARCH_VALUE_MTS_GE:
4048     case NDS_SEARCH_VALUE_MTS_G:
4049     case NDS_SEARCH_VALUE_MTS_LE:
4050     case NDS_SEARCH_VALUE_MTS_L:
4051     case NDS_SEARCH_VALUE_MTS_EQ:
4052     case NDS_SEARCH_VALUE_MTS_EQ_APPROX:
4053     case NDS_SEARCH_VALUE_CTS_GE:
4054     case NDS_SEARCH_VALUE_CTS_G:
4055     case NDS_SEARCH_VALUE_CTS_LE:
4056     case NDS_SEARCH_VALUE_CTS_L:
4057     case NDS_SEARCH_VALUE_CTS_EQ:
4058     case NDS_SEARCH_VALUE_CTS_EQ_APPROX:
4059         /* start of DCWPutAttribute */
4060         values->vvalue = tvb_get_letohl(tvb, ioffset);
4061         ioffset = ioffset + 4;
4062         values->vstring = get_string(tvb, ioffset, values->vvalue);
4063         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4064                               values->vvalue, values->vstring);
4065         ioffset += values->vvalue;
4066         /* end of DCWPutAttribute */
4068         ioffset += align_4(tvb, ioffset);
4070         /* start of DCWPutValue */
4071         proto_tree_add_item(it_tree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4072         ioffset = ioffset + 4;
4073         values->vvalue = tvb_get_letohl(tvb, ioffset);
4074         ioffset = ioffset + 4;
4075         values->vstring = get_string(tvb, ioffset, values->vvalue);
4076         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4077                               values->vvalue, values->vstring);
4078         ioffset += values->vvalue;
4079         /* end of DCWPutValue */
4080         break;
4081     case DCS_MOD_GE_WITH_ATTR:        /* Deprecated, use DS_SEARCH_ENTRY_MTS */
4082     case NDS_SEARCH_ENTRY_MTS_GE:
4083     case NDS_SEARCH_ENTRY_MTS_G:
4084     case NDS_SEARCH_ENTRY_MTS_LE:
4085     case NDS_SEARCH_ENTRY_MTS_L:
4086     case NDS_SEARCH_ENTRY_MTS_EQ:
4087     case NDS_SEARCH_ENTRY_MTS_EQ_APPROX:
4088     case NDS_SEARCH_ENTRY_CTS_GE:
4089     case NDS_SEARCH_ENTRY_CTS_G:
4090     case NDS_SEARCH_ENTRY_CTS_LE:
4091     case NDS_SEARCH_ENTRY_CTS_L:
4092     case NDS_SEARCH_ENTRY_CTS_EQ:
4093     case NDS_SEARCH_ENTRY_CTS_EQ_APPROX:
4094         /* start of DCWPutAttribute */
4095         values->vvalue = tvb_get_letohl(tvb, ioffset);
4096         ioffset = ioffset + 4;
4097         values->vstring = get_string(tvb, ioffset, values->vvalue);
4098         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4099                               values->vvalue, values->vstring);
4100         ioffset += values->vvalue;
4101         /* end of DCWPutAttribute */
4103         ioffset += align_4(tvb, ioffset);
4105         /* start of DCWPutValue */
4106         proto_tree_add_item(it_tree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4107         ioffset = ioffset + 4;
4108         values->vvalue = tvb_get_letohl(tvb, ioffset);
4109         ioffset = ioffset + 4;
4110         values->vstring = get_string(tvb, ioffset, values->vvalue);
4111         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4112                               values->vvalue, values->vstring);
4113         ioffset += values->vvalue;
4114         /* end of DCWPutValue */
4116         break;
4117     case NDS_SEARCH_EID:
4118     case NDS_SEARCH_ENTRY_SUBCOUNT_GE:
4119     case NDS_SEARCH_ENTRY_SUBCOUNT_G:
4120     case NDS_SEARCH_ENTRY_SUBCOUNT_LE:
4121     case NDS_SEARCH_ENTRY_SUBCOUNT_L:
4122     case NDS_SEARCH_ENTRY_SUBCOUNT_EQ:
4123         /* start of DCWPutValue */
4124         proto_tree_add_item(it_tree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4125         ioffset = ioffset + 4;
4126         values->vvalue = tvb_get_letohl(tvb, ioffset);
4127         ioffset = ioffset + 4;
4128         values->vstring = get_string(tvb, ioffset, values->vvalue);
4129         proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4130                               values->vvalue, values->vstring);
4131         ioffset += values->vvalue;
4132         /* end of DCWPutValue */
4134         break;
4136     default: /* Unknown Iteration search Item type */
4137         if (tvb_captured_length_remaining(tvb, ioffset) < 4) {
4138                 THROW(ReportedBoundsError);
4139         }
4140         break;
4141     }
4142     ioffset += align_4(tvb, ioffset);
4143     values->voffset = ioffset;
4144     return;
4147 static void
4148 process_search_subexpression(proto_tree *it_tree, tvbuff_t *tvb, packet_info *pinfo, nds_val *values)
4150     proto_tree  *it_subtree, *it_subtree1;
4151     proto_item  *it_subitem;
4152     uint32_t    i, ioffset, number_of_items;
4154     ioffset = values->voffset;
4155     if (values->vvalue != NDS_SEARCH_NOT) {
4156         number_of_items = tvb_get_letohl(tvb, ioffset);
4157         it_subitem = proto_tree_add_item(it_tree, hf_this_count, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4158         it_subtree = proto_item_add_subtree(it_subitem, ett_nds);
4159         ioffset += 4;
4160         for (i = 0; i < number_of_items; i++)
4161         {
4162             it_subtree1 = proto_tree_add_subtree_format(it_subtree, tvb, ioffset, -1, ett_nds, NULL, "Item #: %u", i+1);
4164             values->voffset = ioffset;
4165             process_set_filter(it_subtree1, tvb, pinfo, values);
4166             ioffset = values->voffset;
4168             if (tvb_captured_length_remaining(tvb, ioffset) < 4) {
4169                 THROW(ReportedBoundsError);
4170                 break;
4171             }
4173         }
4174     }
4175     values->voffset = ioffset;
4176     return;
4179 static void
4180 process_search_match(proto_tree *it_tree, tvbuff_t *tvb, nds_val *values)
4182     uint32_t    ioffset;
4184     ioffset = values->voffset;
4186     values->vvalue = tvb_get_letohl(tvb, ioffset);
4187     ioffset += 4;
4188     proto_tree_add_item(it_tree, hf_nds_oid, tvb, ioffset, values->vvalue, ENC_NA);
4189     ioffset += values->vvalue;
4191     ioffset += align_4(tvb, ioffset);
4193     proto_tree_add_item(it_tree, hf_iter_ans, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4194     ioffset += 4;
4196     ioffset += align_4(tvb, ioffset);
4198     /* start of DCWPutAttribute */
4199     values->vvalue = tvb_get_letohl(tvb, ioffset);
4200     ioffset = ioffset + 4;
4201     values->vstring = get_string(tvb, ioffset, values->vvalue);
4202     proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4203             values->vvalue, values->vstring);
4204     ioffset = check_offset_addition(ioffset, values->vvalue, it_tree, NULL, tvb);
4205     /* end of DCWPutAttribute */
4207     ioffset += align_4(tvb, ioffset);
4209     /* start of DCWPutValue */
4210     proto_tree_add_item(it_tree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4211     ioffset = ioffset + 4;
4212     values->vvalue = tvb_get_letohl(tvb, ioffset);
4213     ioffset = ioffset + 4;
4214     values->vstring = get_string(tvb, ioffset, values->vvalue);
4215     proto_tree_add_string(it_tree, hf_mv_string, tvb, ioffset,
4216                           values->vvalue, values->vstring);
4217     ioffset += values->vvalue;
4218     /* end of DCWPutValue */
4220     ioffset += align_4(tvb, ioffset);
4222     values->voffset = ioffset;
4223     return;
4226 static void
4227 process_set_filter(proto_tree *it_tree, tvbuff_t *tvb, packet_info *pinfo, nds_val *values)
4229     uint32_t    search_tag, ioffset = values->voffset;
4230     const char *search_string;
4232     search_tag = tvb_get_letohl(tvb, ioffset);
4233     search_string = val_to_str_const(search_tag, itersearchenum, "(No Search Tag Found)");
4234     proto_tree_add_uint_format(it_tree, hf_iter_search, tvb, ioffset, 4,
4235         search_tag, "Type of Search: Tag = %d, (0x%04x), %s",
4236         search_tag, search_tag, search_string);
4237     ioffset += 4;
4238     values->voffset = ioffset;
4240     switch (search_tag)
4241     {
4242     case NDS_SEARCH_ITEM:
4243         /* DCWPutSearchExp */
4244         process_search_expression(it_tree, tvb, values);
4245         break;
4247     case NDS_SEARCH_EXTENSIBLE:
4248 #if 0
4249         err = DCWPutSearchExtMatch(context, syncFormat, cur, limit, sexp->u.extMatch);
4250 #endif
4251         process_search_match(it_tree, tvb, values);
4252         break;
4254     case NDS_SEARCH_OR:
4255     case NDS_SEARCH_AND:
4256     case NDS_SEARCH_NOT:
4257         /* DCWPutSearchSubExp = process_search_subexpression */
4258         process_search_subexpression(it_tree, tvb, pinfo, values);
4259         break;
4260     default: /* Unknown Iteration search type */
4261         if (tvb_captured_length_remaining(tvb, ioffset) < 4) {
4262             THROW(ReportedBoundsError);
4263         }
4264         break;
4265     }
4266     /*ioffset = values->voffset;*/
4267     return;
4271  * XXX - what if DSI_OUTPUT_FIELDS *isn't* set in the flags?
4272  * If so, then there *aren't* any flags in which it *could* be
4273  * set.
4275  * This is processing entries in a response to a request that
4276  * probably contained a list of requested flags; if *that* list
4277  * doesn't have DSI_OUTPUT_FIELDS set, perhaps we should
4278  * assume that field isn't present in the response, and that
4279  * the flags in the request indicate what's in the response.
4281  * Either that, or report an error with an expert info, and
4282  * give up on trying to parse the response.
4283  */
4284 static void
4285 process_entry_info(proto_tree *it_tree, tvbuff_t *tvb, nds_val *values)
4287     uint32_t    iter_flags, ioffset = values->voffset;
4288     nstime_t    ns;
4290     values->vstring = NULL;
4291     ioffset += align_4(tvb, ioffset);
4292     iter_flags = tvb_get_letohl(tvb, ioffset);
4295     if (iter_flags & DSI_OUTPUT_FIELDS) { /* Output Flags */
4296         proto_tree_add_bitmask(it_tree, tvb, ioffset, hf_retinfoflagsl, ett_ncp, ncp_infoflagsl, ENC_LITTLE_ENDIAN);
4297         ioffset = ioffset+2;
4298         proto_tree_add_bitmask(it_tree, tvb, ioffset, hf_retinfoflagsh, ett_ncp, ncp_retinfoflagsh, ENC_LITTLE_ENDIAN);
4299         ioffset = ioffset+2;
4300     }
4301     if (iter_flags & DSI_ENTRY_ID) { /* Entry ID */
4302         values->vvalue = tvb_get_letohl(tvb, ioffset);
4303         proto_tree_add_uint_format(it_tree, hf_nds_eid, tvb, ioffset,
4304                 4, values->vvalue, "Entry ID 0x%08x", values->vvalue);
4305         ioffset = ioffset + 4;
4306     }
4307     if (iter_flags & DSI_ENTRY_FLAGS) { /* Entry Flags */
4308         proto_tree_add_bitmask(it_tree, tvb, ioffset, hf_eflags, ett_ncp, ncp_eflags, ENC_LITTLE_ENDIAN);
4309         ioffset = ioffset+4;
4310     }
4311     if (iter_flags & DSI_SUBORDINATE_COUNT) { /* Subordinate Count */
4312         proto_tree_add_item(it_tree, hf_sub_count, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4313         ioffset += 4;
4314     }
4315     if (iter_flags & DSI_MODIFICATION_TIME) { /* Modification Time */
4316         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
4317         ns.nsecs = 0;
4318         proto_tree_add_time_format(it_tree, hf_es_seconds, tvb, ioffset,
4319                 4, &ns, "Modification Time: %s",
4320                 abs_time_secs_to_str(wmem_packet_scope(), ns.secs, ABSOLUTE_TIME_LOCAL, true));
4321         ioffset = ioffset + 4;
4322     }
4323     if (iter_flags & DSI_MODIFICATION_TIMESTAMP) { /* Modification Timestamp */
4324         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
4325         ns.nsecs = 0;
4326         proto_tree_add_time_format(it_tree, hf_es_seconds, tvb, ioffset,
4327                 4, &ns, "Modification Timestamp: %s",
4328                 abs_time_secs_to_str(wmem_packet_scope(), ns.secs, ABSOLUTE_TIME_LOCAL, true));
4329         ioffset = ioffset + 4;
4330         proto_tree_add_item(it_tree, hf_nds_replica_num, tvb, ioffset,
4331                 2, ENC_LITTLE_ENDIAN);
4332         ioffset = ioffset + 2;
4333         proto_tree_add_item(it_tree, hf_nds_event_num, tvb, ioffset,
4334                 2, ENC_LITTLE_ENDIAN);
4335         ioffset = ioffset + 2;
4336     }
4337     if (iter_flags & DSI_CREATION_TIMESTAMP) { /* Creation Timestamp */
4338         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
4339         ns.nsecs = 0;
4340         proto_tree_add_time_format(it_tree, hf_es_seconds, tvb, ioffset,
4341                 4, &ns, "Creation Timestamp: %s",
4342                 abs_time_secs_to_str(wmem_packet_scope(), ns.secs, ABSOLUTE_TIME_LOCAL, true));
4343         ioffset = ioffset + 4;
4344         proto_tree_add_item(it_tree, hf_nds_replica_num, tvb, ioffset,
4345                 2, ENC_LITTLE_ENDIAN);
4346         ioffset = ioffset + 2;
4347         proto_tree_add_item(it_tree, hf_nds_event_num, tvb, ioffset,
4348                 2, ENC_LITTLE_ENDIAN);
4349         ioffset = ioffset + 2;
4350     }
4351     if (iter_flags & DSI_PARTITION_ROOT_ID) { /* Partition Root ID */
4352         values->vvalue = tvb_get_letohl(tvb, ioffset);
4353         proto_tree_add_uint_format(it_tree, hf_nds_local_partition, tvb, ioffset,
4354                 4, values->vvalue, "Partition Root ID %08x", values->vvalue);
4355         ioffset = ioffset + 4;
4356     }
4357     if (iter_flags & DSI_PARENT_ID) { /* Parent ID */
4358         values->vvalue = tvb_get_letohl(tvb, ioffset);
4359         proto_tree_add_uint_format(it_tree, hf_nds_local_partition, tvb, ioffset,
4360                 4, values->vvalue, "Parent ID %08x", values->vvalue);
4361         ioffset = ioffset + 4;
4362     }
4363     if (iter_flags & DSI_REVISION_COUNT) { /* Revision Count */
4364         values->vvalue = tvb_get_letohl(tvb, ioffset);
4365         proto_tree_add_uint_format(it_tree, hf_nds_local_partition, tvb, ioffset,
4366                 4, values->vvalue, "Revision count %08x", values->vvalue);
4367         ioffset = ioffset + 4;
4368     }
4369     if (iter_flags & DSI_REPLICA_TYPE) { /* Replica Type */
4370         values->vvalue = tvb_get_letohl(tvb, ioffset) & 0x00ff;
4371         proto_tree_add_uint(it_tree, hf_replica_type, tvb, ioffset, 4, values->vvalue);
4372         values->vvalue = tvb_get_letohl(tvb, ioffset) & 0xff00;
4373         proto_tree_add_uint(it_tree, hf_replica_state, tvb, ioffset, 4, values->vvalue);
4374         ioffset = ioffset + 4;
4375     }
4376     if (iter_flags & DSI_BASE_CLASS) { /* Base Class */
4377         values->vvalue = tvb_get_letohl(tvb, ioffset);         /* Length of string */
4378         ioffset = ioffset+4;
4379         values->vstring = get_string(tvb, ioffset, values->vvalue);
4380         proto_tree_add_string_format(it_tree, hf_value_string, tvb, ioffset,
4381                 values->vvalue, values->vstring,
4382                 "Base Class: - %s", values->vstring);
4383         ioffset = check_offset_addition(ioffset, values->vvalue, it_tree, NULL, tvb);
4384         ioffset += align_4(tvb, ioffset);
4385     }
4386     if (iter_flags & DSI_ENTRY_RDN) { /* Relative Distinguished Name */
4387         values->vvalue = tvb_get_letohl(tvb, ioffset);         /* Length of string */
4388         ioffset = ioffset+4;
4389         values->vstring = get_string(tvb, ioffset, values->vvalue);
4390         proto_tree_add_string_format(it_tree, hf_value_string, tvb, ioffset,
4391                  values->vvalue, values->vstring,
4392                  "Relative Distinguished Name - %s", values->vstring);
4393         ioffset = check_offset_addition(ioffset, values->vvalue, it_tree, NULL, tvb);
4394         ioffset += align_4(tvb, ioffset);
4395     }
4396     if (iter_flags & DSI_ENTRY_DN) { /* Distinguished Name */
4397         values->vvalue = tvb_get_letohl(tvb, ioffset);         /* Length of string */
4398         ioffset = ioffset+4;
4399         values->vstring = get_string(tvb, ioffset, values->vvalue);
4400         proto_tree_add_string_format(it_tree, hf_value_string, tvb, ioffset,
4401                  values->vvalue, values->vstring,
4402                  "Distinguished Name - %s", values->vstring);
4403         ioffset = check_offset_addition(ioffset, values->vvalue, it_tree, NULL, tvb);
4404         ioffset += align_4(tvb, ioffset);
4405     }
4406     if (iter_flags & DSI_PARTITION_ROOT_DN) { /* Root Distinguished Name */
4407         values->vvalue = tvb_get_letohl(tvb, ioffset);         /* Length of string */
4408         ioffset = ioffset+4;
4409         values->vstring = get_string(tvb, ioffset, values->vvalue);
4410         proto_tree_add_string_format(it_tree, hf_value_string, tvb, ioffset,
4411                  values->vvalue, values->vstring,
4412                  "Root Distinguished Name - %s", values->vstring);
4413         ioffset = check_offset_addition(ioffset, values->vvalue, it_tree, NULL, tvb);
4414         ioffset += align_4(tvb, ioffset);
4415     }
4416     if (iter_flags & DSI_PARENT_DN) { /* Parent Distinguished Name */
4417         values->vvalue = tvb_get_letohl(tvb, ioffset);         /* Length of string */
4418         ioffset = ioffset+4;
4419         values->vstring = get_string(tvb, ioffset, values->vvalue);
4420         proto_tree_add_string_format(it_tree, hf_value_string, tvb, ioffset,
4421                  values->vvalue, values->vstring,
4422                  "Parent Distinguished Name - %s", values->vstring);
4423         ioffset = check_offset_addition(ioffset, values->vvalue, it_tree, NULL, tvb);
4424         ioffset += align_4(tvb, ioffset);
4425     }
4426     if (iter_flags & DSI_PURGE_TIME) { /* Purge Time */
4427         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
4428         ns.nsecs = 0;
4429         proto_tree_add_time(it_tree, hf_nds_purge, tvb, ioffset, 4, &ns);
4430         ioffset = ioffset + 4;
4431     }
4432     if (iter_flags & DSI_DEREFERENCED_BASE_CLASS) { /* Dereference Base Class */
4433         values->vvalue = tvb_get_letohl(tvb, ioffset);
4434         ioffset = ioffset + 4;
4435         values->vstring = get_string(tvb, ioffset, values->vvalue);
4436         proto_tree_add_string(it_tree, hf_deref_base, tvb, ioffset,
4437                 values->vvalue, values->vstring);
4438         ioffset = check_offset_addition(ioffset, values->vvalue, it_tree, NULL, tvb);
4439     }
4440     if (iter_flags & DSI_REPLICA_NUMBER) { /* Replica Number */
4441         proto_tree_add_item_ret_uint(it_tree, hf_replica_number, tvb, ioffset,
4442                  4, ENC_LITTLE_ENDIAN, &values->vvalue);
4443         ioffset = ioffset+4;
4444     }
4445     if (iter_flags & DSI_REPLICA_STATE) { /* Replica State */
4446         values->vvalue = tvb_get_letohl(tvb, ioffset) & 0xff00;
4447         values->vstring = val_to_str_const(values->vvalue, nds_replica_state, "No Replica State Found");
4448         proto_tree_add_uint(it_tree, hf_replica_state, tvb, ioffset, 4, values->vvalue);
4449         ioffset = ioffset + 2;
4450     }
4451     if (iter_flags & DSI_FEDERATION_BOUNDARY) { /* Federation Boundary */
4452         values->vvalue = tvb_get_letohl(tvb, ioffset);
4453         proto_tree_add_uint_format(it_tree, hf_nds_uint32value, tvb, ioffset,
4454                 4, values->vvalue, "Federation Boundary %d", values->vvalue);
4455         ioffset = ioffset+4;
4456     }
4457     if (iter_flags & DSI_SCHEMA_BOUNDARY) { /* Schema Boundary */
4458         values->vvalue = tvb_get_letohl(tvb, ioffset);
4459         proto_tree_add_uint_format(it_tree, hf_nds_uint32value, tvb, ioffset,
4460                 4, values->vvalue, "Schema Boundary %d", values->vvalue);
4461         ioffset = ioffset+4;
4462     }
4463     if (iter_flags & DSI_FEDERATION_BOUNDARY_ID) { /* Federation Boundary ID */
4464         values->vvalue = tvb_get_letohl(tvb, ioffset);
4465         proto_tree_add_uint_format(it_tree, hf_nds_uint32value, tvb, ioffset,
4466                 4, values->vvalue, "Federation Boundary ID %d", values->vvalue);
4467         ioffset = ioffset+4;
4468     }
4469     if (iter_flags & DSI_SCHEMA_BOUNDARY_ID) { /* Schema Boundary ID*/
4470         values->vvalue = tvb_get_letohl(tvb, ioffset);
4471         proto_tree_add_uint_format(it_tree, hf_nds_uint32value, tvb, ioffset,
4472                 4, values->vvalue, "Schema Boundary ID %d", values->vvalue);
4473         ioffset = ioffset+4;
4474     }
4475     if (iter_flags & DSI_CUR_SUBCOUNT) { /* Current Subcount */
4476         values->vvalue = tvb_get_letohl(tvb, ioffset);
4477         proto_tree_add_uint_format(it_tree, hf_nds_uint32value, tvb, ioffset,
4478                 4, values->vvalue, "Current Subcount %d", values->vvalue);
4479         ioffset = ioffset+4;
4480     }
4481     if (iter_flags & DSI_LOCAL_ENTRY_FLAGS) { /* Local Entry Flags */
4482         proto_tree_add_bitmask(it_tree, tvb, ioffset, hf_eflags, ett_ncp, ncp_eflags, ENC_LITTLE_ENDIAN);
4483         ioffset = ioffset+4;
4484     }
4485     values->voffset = ioffset;
4486     return;
4489 static void
4490 dissect_nds_iterator(proto_tree *it_tree, tvbuff_t *tvb, packet_info *pinfo, uint32_t it_verb, uint32_t request_flags, uint32_t ioffset, bool request_reply)
4492     uint32_t    rcode, i, number_of_items, number_to_get;
4493     const char  *error_string;
4494     nds_val     values;
4495     proto_tree  *it_subtree, *it_subtree1;
4496     proto_item  *it_subitem;
4497     proto_item  *expert_item;
4499     values.vtype = 0;
4500     values.vvalue = 0;
4501     values.vlength = 0;
4502     values.voffset = 0;
4503     values.hfname = 0;
4504     values.vdesc = "";
4505     values.vstring = NULL;
4506     values.mvtype = 0;
4507     values.vflags = 0;
4510     while (true) {
4511         it_subitem = proto_tree_add_uint(it_tree, hf_ncp_nds_iterverb, tvb, ioffset-4, 4, it_verb);
4513         it_subtree = proto_item_add_subtree(it_subitem, ett_nds);
4515         if (request_reply) { /* Request packets */
4516             switch (it_verb) {
4517             case IT_ATFIRST:
4518             case IT_ATEOF:
4519             case IT_ATLAST:
4520             case IT_ATBOF:
4521             case IT_CLEAR:
4522             case IT_COPY:
4523                 break;
4524             case IT_COUNT:
4525                 proto_tree_add_item(it_subtree, hf_timelimit, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4526                 ioffset += 4;
4527                 proto_tree_add_item(it_subtree, hf_max_entries, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4528                 ioffset += 4;
4529                 proto_tree_add_item(it_subtree, hf_move_position, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4530                 ioffset += 4;
4531                 break;
4532             case IT_CREATE:
4533             case IT_CURRENT:
4534             case IT_DESTROY:
4535             case IT_DONE:
4536                 break;
4537             case IT_FIRST:
4538                 proto_tree_add_item(it_subtree, hf_timelimit, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4539                 ioffset += 4;
4540                 break;
4541             case IT_GETPOSITION:
4542             case IT_ISPOSITIONABLE:
4543                 break;
4544             case IT_LAST:
4545                 proto_tree_add_item(it_subtree, hf_timelimit, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4546                 ioffset += 4;
4547                 break;
4548             case IT_NEXT:
4549             case IT_PREV:
4550                 proto_tree_add_item(it_subtree, hf_timelimit, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4551                 ioffset += 4;
4552                 proto_tree_add_item(it_subtree, hf_num_to_get, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4553                 ioffset += 4;
4554                 break;
4555             case IT_POSITION:
4556                 proto_tree_add_item(it_subtree, hf_iter_position, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4557                 ioffset += 4;
4558                 proto_tree_add_item(it_subtree, hf_timelimit, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4559                 ioffset += 4;
4560                 break;
4561             case IT_POSITION_IT:
4562                 proto_tree_add_item(it_subtree, hf_iter_other, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4563                 ioffset += 4;
4564                 break;
4565             case IT_SETINDEX:
4566                 proto_tree_add_item(it_subtree, hf_nds_number_of_items, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4567                 number_of_items = tvb_get_letohl(tvb, ioffset);
4568                 ioffset += 4;
4569                 for (i=0; i < number_of_items; i++) {
4570                     /* Process the attribute tag */
4571 #if 0
4572                     proto_tree_add_item(it_subtree, hf_nds_tag_string, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4573 #endif
4574                     proto_tree_add_item(it_subtree, hf_iter_index, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4575                     ioffset = ioffset + 4;
4577                     /* start of DCWPutAttribute */
4578 #if 0
4579                     values.vvalue = tvb_get_letohl(tvb, ioffset);
4580                     ioffset = ioffset + 4;
4581                     values.vstring = get_string(tvb, ioffset, values.vvalue);
4582                     proto_tree_add_string(it_subtree, hf_mv_string, tvb, ioffset,
4583                             values.vvalue, values.vstring);
4584                     ioffset = check_offset_addition(ioffset, values.vvalue, it_subtree, pinfo, tvb);
4585 #endif
4586                     /* end of DCWPutAttribute */
4588 #if 0
4589                     ioffset += align_4(tvb, ioffset);
4590 #endif
4591                     if (tvb_captured_length_remaining(tvb, ioffset) < 4) {
4592                         THROW(ReportedBoundsError);
4593                         return;
4594                     }
4595                 }
4596                 break;
4597             case IT_SETFILTER:
4599                 values.voffset = ioffset;
4601                 /* DCWPutSearchExp  = process_set_filter() */
4602                 process_set_filter(it_subtree, tvb, pinfo, &values);
4604                 ioffset = values.voffset;
4605                 ioffset += align_4(tvb, ioffset);
4606                 break;
4607             case IT_SKIP:
4608                 proto_tree_add_item(it_subtree, hf_timelimit, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4609                 ioffset += 4;
4610                 proto_tree_add_item(it_subtree, hf_num_to_skip, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4611                 ioffset += 4;
4612                 break;
4613             case IT_TYPEDOWN:
4614                 proto_tree_add_item(it_subtree, hf_num_to_get, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4615                 number_to_get = tvb_get_letohl(tvb, ioffset);
4616                 ioffset += 4;
4617                 if (number_to_get == 0) {
4618                     proto_tree_add_item(it_tree, hf_nds_tag_string, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4619                     ioffset = ioffset + 4;
4621                 }
4622                 values.vvalue = tvb_get_letohl(tvb, ioffset);
4623                 ioffset = ioffset + 4;
4624                 values.vstring = get_string(tvb, ioffset, values.vvalue);
4625                 proto_tree_add_string(it_subtree, hf_mv_string, tvb, ioffset,
4626                         values.vvalue, values.vstring);
4627                 ioffset = check_offset_addition(ioffset, values.vvalue, it_subtree, pinfo, tvb);
4628                 ioffset += align_4(tvb, ioffset);
4629                 break;
4630             default:
4631                 if (tvb_captured_length_remaining(tvb, ioffset) < 4) {
4632                     THROW(ReportedBoundsError);
4633                 }
4634                 return;
4635             }
4636         }
4637         else    /* Reply Packets */
4638         {                                           /* All replies include a completion code first */
4639             expert_item = proto_tree_add_item_ret_uint(it_subtree, hf_iter_verb_completion_code, tvb, ioffset,
4640                     4, ENC_LITTLE_ENDIAN, &rcode);
4641             error_string = val_to_str_const(rcode, nds_reply_errors, "Unknown Interation Verb Completion Code");
4643             if (rcode != 0 && ncp_echo_err) {
4644                 expert_add_info_format(pinfo, expert_item, &ei_iter_verb_completion_code, "Iteration Verb Error: 0x%08x %s", rcode, error_string);
4645             }
4646             ioffset += 4;
4648             switch (it_verb) {
4649             case IT_ATFIRST:
4650             case IT_ATEOF:
4651             case IT_ATLAST:
4652             case IT_ATBOF:
4653                 proto_tree_add_item(it_subtree, hf_iter_ans, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4654                 ioffset += 4;
4655                 break;
4656             case IT_CLEAR:
4657                 break;
4658             case IT_COPY:
4659                 proto_tree_add_item(it_subtree, hf_iter_copy, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4660                 ioffset += 4;
4661                 break;
4662             case IT_COUNT:
4663                 proto_tree_add_item(it_subtree, hf_this_count, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4664                 ioffset += 4;
4665                 break;
4666             case IT_CREATE:
4667                 proto_tree_add_item(it_subtree, hf_nds_iterator, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4668                 ioffset += 4;
4669                 break;
4670             case IT_CURRENT:
4671             case IT_NEXT:
4672             case IT_PREV:
4673             case IT_FIRST:
4674             case IT_LAST:
4675                 proto_tree_add_item(it_subtree, hf_nds_info_type, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4676                 ioffset = ioffset + 4;
4677                 proto_tree_add_item(it_subtree, hf_data_size, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4678                 ioffset += 4;
4679                 number_of_items = tvb_get_letohl(tvb, ioffset);
4680                 proto_tree_add_item(it_subtree, hf_this_count, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4681                 ioffset += 4;
4682                 for (i = 0; i < number_of_items; i++)
4683                 {
4684                     it_subtree1 = proto_tree_add_subtree_format(it_subtree, tvb, ioffset, -1, ett_nds, NULL, "Item #: %u", i+1);
4686                     ioffset += align_4(tvb, ioffset);
4688                     /* Start WGetAndBufferEntryInfo = process_entry_info() */
4689                     values.voffset = ioffset;
4690                     /*
4691                      * XXX - each entry also may contain a set of flags
4692                      * indicating what values are(?) present; which
4693                      * should be used?
4694                      */
4695                     values.vflags = request_flags;
4696                     process_entry_info(it_subtree1, tvb, &values);
4697                     ioffset = values.voffset;
4698                     /* End WGetAndBufferEntryInfo */
4700                     ioffset += align_4(tvb, ioffset);
4702                     /* WGetReadBuffer - This seems to be a count and then size field (2 * uint32_t) */
4703                     /* For now we will just skip this offset. NEED TO ADD LOGIC TO HANDLE */
4704                     ioffset += 8;
4706                     if (tvb_captured_length_remaining(tvb, ioffset) < 4) {
4707                         break;
4708                     }
4709                 }
4710                 break;
4711             case IT_DESTROY:
4712             case IT_DONE:
4713                 break;
4714             case IT_GETPOSITION:
4715                 proto_tree_add_item(it_subtree, hf_iter_position, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4716                 ioffset += 4;
4717                 break;
4718             case IT_ISPOSITIONABLE:
4719                 proto_tree_add_item(it_subtree, hf_positionable, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4720                 ioffset += 4;
4721                 break;
4722             case IT_POSITION:
4723             case IT_POSITION_IT:
4724             case IT_SETFILTER:
4725             case IT_TYPEDOWN:
4726                 break;
4727             case IT_SETINDEX:
4728                 proto_tree_add_item(it_subtree, hf_iter_index, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4729                 ioffset += 4;
4730                 break;
4731             case IT_SKIP:
4732                 proto_tree_add_item(it_subtree, hf_num_skipped, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4733                 ioffset += 4;
4734                 break;
4735             default:
4736                 if (tvb_captured_length_remaining(tvb, ioffset) < 4) {
4737                     THROW(ReportedBoundsError);
4738                 }
4739                 return;
4740             }
4741         }
4742         it_verb = tvb_get_letohl(tvb, ioffset);
4743         ioffset += 4;
4744         if (it_verb == IT_DONE || tvb_captured_length_remaining(tvb, ioffset) < 4) {
4745             proto_tree_add_uint(it_tree, hf_ncp_nds_iterverb, tvb, ioffset-4, 4, it_verb);
4746             break;
4747         }
4748     }
4749     return;
4753 static void
4754 process_multivalues(proto_tree *ncp_tree, tvbuff_t *tvb, packet_info *pinfo, nds_val *values)
4756     uint32_t        i;
4757     uint32_t        r;
4758     uint32_t        ioffset = 0, oldioffset;
4759     uint32_t        value1 = 0;
4760     uint32_t        value2 = 0;
4761     uint8_t         value3 = 0;
4762     uint32_t        value4 = 0;
4763     int             value5 = 0;
4764     uint32_t        value6 = 0;
4765     uint32_t        value7 = 0;
4766     const char      *valuestr = "";
4767     proto_tree      *ntree;
4768     proto_tree      *atree;
4769     proto_item      *nitem;
4770     proto_item      *aitem;
4771     uint32_t        number_of_referrals = 0;
4772     proto_tree      *estree;
4773     proto_item      *esitem;
4774     uint32_t        bvalue=0;
4775     nds_val         temp_values;
4776     proto_tree      *sub1tree;
4777     proto_item      *sub1item;
4778     proto_tree      *sub2tree;
4779     proto_item      *sub2item;
4780     int             length_remaining;
4781     nstime_t        ns;
4783     mv_resolve_name_string[0] = '\0';
4784     values->vstring = "";
4786     /* Is the value passed a string or UINT32? */
4787     /* XXX - this should just be an FT_NONE to cover the entire item */
4788     if(values->mvtype != MVTYPE_LIST_PARTITIONS && values->mvtype != MVTYPE_PROCESS_TAGS)
4789     {
4790         nitem = proto_tree_add_uint_format(ncp_tree, values->hfname, tvb, values->voffset+ioffset,
4791                                            values->vlength, values->vvalue, values->vdesc, values->vvalue);
4792     }
4793     else
4794     {
4795         nitem = proto_tree_add_string_format(ncp_tree, values->hfname, tvb, values->voffset+ioffset,
4796                                              values->vlength, values->vdesc, "%s", values->vdesc);
4797     }
4798     ioffset = (values->voffset+4);
4800     ntree = proto_item_add_subtree(nitem, ett_nds);
4802     switch (values->mvtype)
4803     {
4804     case MVTYPE_ATTR_REQUEST:   /* Attribute Request */
4805         for (i = 1 ; i <= values->vvalue; i++ )
4806         {
4807             ioffset += align_4(tvb, ioffset);
4808             value1 = tvb_get_letohl(tvb, ioffset);
4809             ioffset = ioffset + 4;
4810             values->vstring = get_string(tvb, ioffset, value1);
4811             proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
4812                                   value1, values->vstring);
4813             ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
4814         }
4815         break;
4817     case MVTYPE_ATTR_REPLY:     /* Attribute Reply */
4818         switch(values->vflags)
4819         {
4820         case 0:
4821             for (i = 1 ; i <= values->vvalue; i++ )
4822             {
4823                 ioffset += align_4(tvb, ioffset);
4824                 value1 = tvb_get_letohl(tvb, ioffset);
4825                 ioffset = ioffset + 4;
4826                 values->vstring = get_string(tvb, ioffset, value1);
4827                 proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
4828                                       value1, values->vstring);
4829                 ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
4830             }
4831             break;
4832         case 1:
4833             for (i = 1 ; i <= values->vvalue; i++ )
4834             {
4835                 uint32_t syntax;
4837                 proto_tree_add_item_ret_uint(ntree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN, &syntax);
4838                 ioffset = ioffset + 4;
4839                 value2 = tvb_get_letohl(tvb, ioffset);
4840                 ioffset = ioffset + 4;
4841                 values->vstring = get_string(tvb, ioffset, value2);
4842                 proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
4843                                       value2, values->vstring);
4844                 ioffset += value2;
4845                 ioffset += align_4(tvb, ioffset);
4846                 values->voffset = ioffset;
4848                 print_nds_values(ntree, pinfo, tvb, syntax, values);
4849                 ioffset = values->voffset;
4850             }
4851             break;
4852         case 2:
4853             for (i = 1 ; i <= values->vvalue; i++ )
4854             {
4855                 proto_tree_add_item(ntree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4856                 ioffset = ioffset + 4;
4857                 value2 = tvb_get_letohl(tvb, ioffset);
4858                 ioffset = ioffset + 4;
4859                 values->vstring = get_string(tvb, ioffset, value2);
4860                 proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
4861                                       value2, values->vstring);
4862                 values->voffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
4863                 ioffset += value2;
4864                 ioffset += align_4(tvb, ioffset);
4865                 value3 = tvb_get_letohl(tvb, ioffset);
4867                 proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset, 4,
4868                                            value3, "Number of Values - %u", value3);
4870                 ioffset = ioffset + 4;
4871                 for (r = 1 ; r <= value3; r++ )
4872                 {
4873                     ioffset += 4;   /* Length = 4 */
4874                     proto_tree_add_item(ntree, hf_nds_privileges, tvb, ioffset,
4875                                         values->vlength, ENC_LITTLE_ENDIAN);
4877                     ioffset = ioffset+4;
4878                 }
4879             }
4880             break;
4881         case 3:
4882             for (i = 1 ; i <= values->vvalue; i++ )
4883             {
4884                 proto_tree_add_item(ntree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4885                 ioffset = ioffset + 4;
4886                 value2 = tvb_get_letohl(tvb, ioffset);
4887                 ioffset = ioffset + 4;
4888                 values->vstring = get_string(tvb, ioffset, value2);
4889                 proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
4890                                       value2, values->vstring);
4891                 ioffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
4892                 ioffset += align_4(tvb, ioffset);
4893                 value3 = tvb_get_letohl(tvb, ioffset);
4895                 aitem = proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset, 4,
4896                                                    value3, "Number of Values - %u", value3);
4898                 atree = proto_item_add_subtree(aitem, ett_nds);
4900                 ioffset = ioffset + 4;
4901                 for (r = 1 ; r <= value3; r++ )
4902                 {
4903                     ioffset += align_4(tvb, ioffset);
4904                     proto_tree_add_bitmask(atree, tvb, ioffset, hf_vflags, ett_ncp, ncp_vflags, ENC_LITTLE_ENDIAN);
4905                     ioffset = ioffset + 4;
4906                     ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
4907                     ns.nsecs = 0;
4908                     proto_tree_add_time_format(atree, hf_es_seconds, tvb, ioffset,
4909                                                4, &ns, "Timestamp: %s",
4910                                                abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
4911                     ioffset = ioffset + 4;
4912                     proto_tree_add_item(atree, hf_nds_replica_num, tvb, ioffset,
4913                                         2, ENC_LITTLE_ENDIAN);
4914                     ioffset = ioffset + 2;
4915                     proto_tree_add_item(atree, hf_nds_event_num, tvb, ioffset,
4916                                         2, ENC_LITTLE_ENDIAN);
4917                     ioffset = ioffset + 2;
4918                     value5 = tvb_get_letohl(tvb, ioffset); /* length of field */
4919                     if(value5 > tvb_captured_length_remaining(tvb, ioffset))
4920                     {
4921                         break;
4922                     }
4923                     ioffset += 4;
4924                     proto_tree_add_item(atree, hf_value_bytes, tvb, ioffset, value5, ENC_NA);
4925                     ioffset += value5;
4926                     ioffset += (value5%2);
4927                 }
4928             }
4929             break;
4930         case 4:
4931             for (i = 1 ; i <= values->vvalue; i++ )
4932             {
4933                 proto_tree_add_item(ntree, hf_nds_syntax, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
4934                 ioffset = ioffset + 4;
4935                 value2 = tvb_get_letohl(tvb, ioffset);
4936                 ioffset = ioffset + 4;
4937                 values->vstring = get_string(tvb, ioffset, value2);
4938                 proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
4939                                       value2, values->vstring);
4940                 ioffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
4941                 value3 = tvb_get_letohl(tvb, ioffset);
4943                 proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset, 4,
4944                                            value3, "Number of Values - %u", value3);
4946                 ioffset = ioffset + 4;
4947                 for (r = 1 ; r <= value3; r++ )
4948                 {
4949                     ioffset += align_4(tvb, ioffset);
4950                     proto_tree_add_bitmask(ntree, tvb, ioffset, hf_vflags, ett_ncp, ncp_vflags, ENC_LITTLE_ENDIAN);
4951                     ioffset = ioffset + 4;
4952                     ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
4953                     ns.nsecs = 0;
4954                     proto_tree_add_time_format(ntree, hf_es_seconds, tvb, ioffset,
4955                                                4, &ns, "Creation Time: %s",
4956                                                abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
4957                     ioffset = ioffset + 4;
4958                     proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
4959                                         2, ENC_LITTLE_ENDIAN);
4960                     ioffset = ioffset + 2;
4961                     proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
4962                                         2, ENC_LITTLE_ENDIAN);
4963                     ioffset = ioffset + 2;
4964                     proto_tree_add_item(ntree, hf_nds_value_len, tvb, ioffset,
4965                                         4, ENC_LITTLE_ENDIAN);
4966                     ioffset = ioffset + 4;
4967                 }
4968             }
4969             break;
4970         default:
4971             break;
4972         }
4973         break;
4975     case MVTYPE_ATTR_REQUEST2:    /* Attribute Request */
4976         oldioffset = 0;
4977         for (i = 1 ; i <= values->vvalue; i++ )
4978         {
4979             if (oldioffset >= ioffset) {
4980                 proto_tree_add_expert_format(ntree, pinfo, &ei_ncp_invalid_offset, tvb, 0, 0, "Invalid offset: %u", ioffset);
4981                 THROW(ReportedBoundsError);
4982             }
4983             oldioffset = ioffset;
4984             ioffset += align_4(tvb, ioffset);
4985             value1 = tvb_get_letohl(tvb, ioffset);
4986             proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset,
4987                                        4, value1, "Value %d", value1);
4988             ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
4989         }
4990         break;
4992     case MVTYPE_ADD_ATTR_REQUEST: /* Add Attribute Request */
4993         for (i = 1 ; i <= values->vvalue; i++ )
4994         {
4995             value1 = tvb_get_letohl(tvb, ioffset);
4996             ioffset = ioffset + 4;
4997             values->vstring = get_string(tvb, ioffset, value1);
4998             proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
4999                                   value1, values->vstring);
5000             ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5001             ioffset += align_4(tvb, ioffset);
5002             values->voffset = ioffset;
5003             print_nds_values(ntree, pinfo, tvb, 9, values);
5004             ioffset = values->voffset;
5005         }
5006         break;
5008     case MVTYPE_READ_CLASS_REQ:   /* Read Class Request */
5009         for (i = 1 ; i <= values->vvalue; i++ )
5010         {
5011             ioffset += align_4(tvb, ioffset);
5012             value1 = tvb_get_letohl(tvb, ioffset);
5013             ioffset = ioffset + 4;
5014             values->vstring = get_string(tvb, ioffset, value1);
5015             proto_tree_add_string(ntree, hf_nds_base, tvb, ioffset,
5016                                   value1, values->vstring);
5017             values->mvtype = MVTYPE_ATTR_REQUEST;
5018             ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5019         }
5020         break;
5022     case MVTYPE_READ_REPLICAS:    /* Read Replicas */
5023         for (i = 1 ; i <= values->vvalue; i++ )
5024         {
5025             bvalue = 0x00000001;
5027             for (r = 0 ; r < 9; r++ )
5028             {
5029                 if (values->vflags & bvalue)
5030                 {
5031                     // Note: these do not all apear to be DSI_ flags
5032                     switch(bvalue)
5033                     {
5034                     case 0x00000001:                /*p3values.bit1 = "Output Flags"*/
5035                         proto_tree_add_bitmask(ntree, tvb, ioffset, hf_outflags, ett_ncp, ncp_outflags, ENC_LITTLE_ENDIAN);
5036                         ioffset = ioffset + 4;
5037                         break;
5038                     case 0x00000002:                /*p3values.bit2 = "Entry ID"*/
5039                         value1 = tvb_get_letohl(tvb, ioffset);
5040                         proto_tree_add_uint_format(ntree, hf_nds_eid, tvb, ioffset,
5041                                                    4, value1, "Entry ID %08x", value1);
5042                         ioffset = ioffset + 4;
5043                         break;
5044                     case 0x00000004:                /*p3values.bit3 = "Replica State"*/
5045                         proto_tree_add_item_ret_uint(ntree, hf_replica_state, tvb, ioffset,
5046                                               4, ENC_LITTLE_ENDIAN, &value1);
5047                         ioffset = ioffset + 4;
5048                         break;
5049                     case 0x0000008:                 /*p3values.bit4 = "Modification Timestamp"*/
5050                         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5051                         ns.nsecs = 0;
5052                         proto_tree_add_time_format(ntree, hf_es_seconds, tvb, ioffset,
5053                                                    4, &ns, "Modification Timestamp: %s",
5054                                                    abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
5055                         ioffset = ioffset + 4;
5056                         proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
5057                                             2, ENC_LITTLE_ENDIAN);
5058                         ioffset = ioffset + 2;
5059                         proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
5060                                             2, ENC_LITTLE_ENDIAN);
5061                         ioffset = ioffset + 2;
5062                         break;
5063                     case 0x00000010:                /*p3values.bit5 = "Purge Time"*/
5064                         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5065                         ns.nsecs = 0;
5066                         proto_tree_add_time(ntree, hf_nds_purge, tvb, ioffset, 4, &ns);
5067                         ioffset = ioffset + 4;
5068                         break;
5069                     case 0x00000020:                /*p3values.bit6 = "Local Partition ID"*/
5070                         proto_tree_add_item(ntree, hf_nds_local_partition, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
5071                         ioffset = ioffset + 4;
5072                         break;
5073                     case 0x00000040:                /*p3values.bit7 = "Distinguished Name"*/
5074                         value1 = tvb_get_letohl(tvb, ioffset);
5075                         ioffset = ioffset + 4;
5076                         temp_values.vstring = get_string(tvb, ioffset, value1);
5077                         proto_tree_add_string(ntree, hf_nds_name, tvb, ioffset,
5078                                               value1, temp_values.vstring);
5079                         ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5080                         break;
5081                     case 0x00000080:                /*p3values.bit8 = "Replica Type & State"*/
5082                         value1 = tvb_get_letohl(tvb, ioffset);
5083                         value2 = value1 & 0x00ff;
5084                         proto_tree_add_uint(ntree, hf_replica_type, tvb, ioffset, 4, value2);
5085                         value3 = value1 & 0xff00;
5086                         proto_tree_add_uint(ntree, hf_replica_state, tvb, ioffset, 4, value3);
5087                         ioffset = ioffset + 4;
5088                         break;
5089                     case 0x00000100:                /*p3values.bit9 = "Partition Busy"*/
5090                         value1 = tvb_get_letohs(tvb, ioffset);
5091                         proto_tree_add_boolean(ntree, hf_partition_busy, tvb, ioffset, 4, value1);
5092                         ioffset += 4;
5093                         break;
5094                     default:
5095                         break;
5096                     }
5097                 }
5098                 bvalue = bvalue*2;
5099                 ioffset += align_4(tvb, ioffset);
5100                 if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5101                 {
5102                     break;
5103                 }
5104             }
5105             if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5106             {
5107                 break;
5108             }
5109         }
5110         break;
5112     case MVTYPE_MODIFY_ATTR_REQUEST: /* Modify Attribute Request */
5113         for (i = 0 ; i < values->vvalue; i++ )
5114         {
5115             ioffset += align_4(tvb, ioffset);
5116             value1 = tvb_get_letohl(tvb, ioffset);
5117             valuestr = val_to_str_const(value1, nds_kind_of_changes, "(Kind Change Not Found)");
5118             proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset,
5119                                        values->vlength, value1, valuestr, value1);
5120             ioffset = ioffset+4;
5121             value2 = tvb_get_letohl(tvb, ioffset);
5122             ioffset = ioffset + 4;
5123             temp_values.vstring = get_string(tvb, ioffset, value2);   /* Name of Attribute */
5124             proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
5125                                   value2, temp_values.vstring);
5126             ioffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
5127             ioffset += align_4(tvb, ioffset);
5128             if(value1 != 1 && value1 != 6)
5129             {
5130                 values->voffset = ioffset;
5131                 /* XX: Is values.vstring set properly at this point ?? */
5132                 print_nds_values(ntree, pinfo, tvb, 9, values);
5133                 ioffset = values->voffset;
5134             }
5135         }
5136         break;
5138     case MVTYPE_ADDR_REFERRAL_REQUEST: /* Address Referral Request */
5139         for (i = 0 ; i < values->vvalue; i++ )
5140         {
5141             value1 = tvb_get_letohl(tvb, ioffset);
5142             valuestr = val_to_str_const(value1, nds_protocol_type, "(Undefined Protocol)");
5143             proto_tree_add_uint_format(ntree, hf_nds_uint32value, tvb, ioffset,
5144                                        values->vlength, value1, valuestr, value1);
5145             ioffset = ioffset+4;
5146         }
5147         break;
5149     case MVTYPE_ADDR_REFERRAL_REPLY: /* Address Referral Reply */
5150         number_of_referrals = values->vvalue;
5152         for (r = 1 ; r <= number_of_referrals; r++ )
5153         {
5154             aitem = proto_tree_add_uint_format(ntree, hf_referral_record, tvb, 6, 0,
5155                                                r, "NDS Referral Record #%u", r);
5156             atree = proto_item_add_subtree(aitem, ett_nds);
5158             proto_tree_add_item_ret_uint(atree, hf_referral_addcount, tvb, ioffset, 4, ENC_LITTLE_ENDIAN, &value1);
5160             ioffset = ioffset + 4;
5161             for (i = 1 ; i <= value1; i++ )
5162             {
5163                 value2 = tvb_get_letohl(tvb, ioffset);
5164                 valuestr = val_to_str_const(value2, nds_protocol_type, "(Undefined Protocol)");
5165                 proto_tree_add_uint_format(atree, hf_nds_uint32value, tvb, ioffset,
5166                                            values->vlength, value2, valuestr, value2);
5167                 ioffset = ioffset+4;
5168                 value3 = tvb_get_letohl(tvb, ioffset);
5169                 ioffset = ioffset+4;
5170                 switch (value2)
5171                 {
5172                 case NDS_PTYPE_IPX:
5173                     proto_tree_add_item(atree, hf_nds_net, tvb, ioffset, 4, ENC_BIG_ENDIAN);
5174                     proto_tree_add_item(atree, hf_nds_node, tvb, ioffset+4, 6, ENC_NA);
5175                     proto_tree_add_item(atree, hf_nds_socket, tvb, ioffset+10, 2, ENC_BIG_ENDIAN);
5176                     break;
5177                 case NDS_PTYPE_IP:
5178                     proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
5179                     proto_tree_add_item(atree, hf_add_ref_ip, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
5180                     break;
5181                 case NDS_PTYPE_UDP:
5182                     proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
5183                     proto_tree_add_item(atree, hf_add_ref_udp, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
5184                     break;
5185                 case NDS_PTYPE_TCP:
5186                     proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
5187                     proto_tree_add_item(atree, hf_add_ref_tcp, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
5188                     break;
5189                 case NDS_PTYPE_URL:
5190                 case NDS_PTYPE_DNS:
5191                     values->vstring = get_string(tvb, ioffset, value3);
5192                     proto_tree_add_string(atree, hf_value_string, tvb, ioffset,
5193                                           value3, values->vstring);
5194                     break;
5195                 default:
5196                     break;
5197                 }
5198                 ioffset = check_offset_addition(ioffset, value3, atree, pinfo, tvb);
5199                 ioffset += align_4(tvb, ioffset);
5200             }
5202         }
5203         break;
5205     case MVTYPE_LOC_ADDR_REFERRAL_REPLY: /* Local Address Referral Reply */
5206         number_of_referrals = values->vvalue;
5208         for (r = 1 ; r <= number_of_referrals; r++ )
5209         {
5210             aitem = proto_tree_add_uint_format(ntree, hf_referral_record, tvb, 6, 0,
5211                                                r, "NDS Referral Record #%u", r);
5212             atree = proto_item_add_subtree(aitem, ett_nds);
5214             value2 = tvb_get_letohl(tvb, ioffset);
5215             valuestr = val_to_str_const(value2, nds_protocol_type, "(Undefined Protocol)");
5216             proto_tree_add_uint_format(atree, hf_nds_uint32value, tvb, ioffset,
5217                                        values->vlength, value2, valuestr, value2);
5218             ioffset = ioffset+4;
5219             value3 = tvb_get_letohl(tvb, ioffset);
5220             ioffset = ioffset+4;
5222             switch (value2)
5223             {
5224             case NDS_PTYPE_IPX:
5225                 proto_tree_add_item(atree, hf_nds_net, tvb, ioffset, 4, ENC_BIG_ENDIAN);
5226                 proto_tree_add_item(atree, hf_nds_node, tvb, ioffset+4, 6, ENC_NA);
5227                 proto_tree_add_item(atree, hf_nds_socket, tvb, ioffset+10, 2, ENC_BIG_ENDIAN);
5228                 break;
5229             case NDS_PTYPE_IP:
5230                 proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
5231                 proto_tree_add_item(atree, hf_add_ref_ip, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
5232                 break;
5233             case NDS_PTYPE_UDP:
5234                 proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
5235                 proto_tree_add_item(atree, hf_add_ref_udp, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
5236                 break;
5237             case NDS_PTYPE_TCP:
5238                 proto_tree_add_item(atree, hf_nds_port, tvb, ioffset, 2, ENC_BIG_ENDIAN);
5239                 proto_tree_add_item(atree, hf_add_ref_tcp, tvb, ioffset+2, 4, ENC_BIG_ENDIAN);
5240                 break;
5241             case NDS_PTYPE_URL:
5242             case NDS_PTYPE_DNS:
5243                 values->vstring = get_string(tvb, ioffset, value3);
5244                 proto_tree_add_string(atree, hf_value_string, tvb, ioffset,
5245                                       value3, values->vstring);
5246                 break;
5247             default:
5248                 break;
5249             }
5250             ioffset = check_offset_addition(ioffset, value3, atree, pinfo, tvb);
5251             ioffset += align_4(tvb, ioffset);
5252         }
5253         break;
5255     case MVTYPE_PROC_ENTRY_SPECIFIERS: /* Process Entry Specifiers */
5256         value2 = tvb_get_letohl(tvb, ioffset);   /* ES Type */
5257         values->vstring = val_to_str_const(value2, es_type, "No ES Type Found");
5258         esitem = proto_tree_add_string_format(ntree, hf_es_type, tvb, ioffset,
5259                                               4, values->vstring, "Output Entry Specifier - %s", values->vstring);
5260         estree = proto_item_add_subtree(esitem, ett_nds);
5261         ioffset = ioffset + 4;
5262         ioffset = print_es_type(estree, tvb, values, value2, ioffset);
5263         value3 = tvb_get_letohl(tvb, ioffset);   /* ES Type */
5264         values->vstring = val_to_str_const(value3, es_type, "No ES Type Found");
5265         esitem = proto_tree_add_string_format(ntree, hf_es_type, tvb, ioffset,
5266                                               4, values->vstring, "Input Entry Specifier - %s", values->vstring);
5267         estree = proto_item_add_subtree(esitem, ett_nds);
5268         ioffset = ioffset + 4;
5269         ioffset = print_es_type(estree, tvb, values, value3, ioffset);
5270         /* values.vstring is being overwritten. So store the resolve name to a global value */
5271         (void) g_strlcpy(mv_resolve_name_string, values->vstring, 128);
5272         value4 = tvb_get_letohl(tvb, ioffset);
5273         aitem = proto_tree_add_uint_format(ntree, hf_referral_record, tvb, ioffset, 4,
5274                                            value4, "Referral Protocols - %u", value4);
5275         atree = proto_item_add_subtree(aitem, ett_nds);
5276         ioffset += 4;
5277         for (i = 0 ; i < value4; i++ )
5278         {
5279             value5 = tvb_get_letohl(tvb, ioffset);
5280             valuestr = val_to_str_const(value5, nds_protocol_type, "(Undefined Protocol)");
5281             proto_tree_add_string_format(atree, hf_value_string, tvb, ioffset,
5282                                          4, valuestr, "Protocol -> %s", valuestr);
5283             ioffset = ioffset+4;
5284         }
5285         value6 = tvb_get_letohl(tvb, ioffset);
5286         aitem = proto_tree_add_uint_format(ntree, hf_referral_record, tvb, ioffset, 4,
5287                                            value6, "Tree Walking Protocols - %u", value6);
5288         atree = proto_item_add_subtree(aitem, ett_nds);
5289         ioffset += 4;
5290         for (i = 0 ; i < value6; i++ )
5291         {
5292             value7 = tvb_get_letohl(tvb, ioffset);
5293             valuestr = val_to_str_const(value7, nds_protocol_type, "(Undefined Protocol)");
5294             proto_tree_add_string_format(atree, hf_value_string, tvb, ioffset,
5295                                          4, valuestr, "Protocol -> %s", valuestr);
5296             ioffset = ioffset+4;
5297         }
5298         values->vstring = " ";
5299         break;
5301     case MVTYPE_PRINT_TIMESTAMP:  /* Print Timestamp */
5302         proto_tree_add_item(ncp_tree, hf_nds_replica_num, tvb, ioffset,
5303                             2, ENC_LITTLE_ENDIAN);
5304         ioffset = ioffset + 2;
5305         proto_tree_add_item(ncp_tree, hf_nds_event_num, tvb, ioffset,
5306                             2, ENC_LITTLE_ENDIAN);
5307         ioffset = ioffset + 2;
5308         /* fall through */
5310     case MVTYPE_LIST_PARTITIONS:  /* List Partitions */
5311         number_of_referrals = values->vvalue;
5312         /* A bad packet could put us in a tight loop so trap for anything
5313          * over 256 referrals.
5314          */
5315         if (number_of_referrals > 256) {
5316             proto_tree_add_expert_format(ntree, pinfo, &ei_ncp_invalid_offset, tvb, 0, 0, "Bad referral at offset: %u", ioffset);
5317             THROW(ReportedBoundsError);
5318             break;
5319         }
5320         for (i = 0; i < number_of_referrals; i++)
5321         {
5322             /*
5323              * XXX - should we just call process_entry_info() here?
5324              */
5325             bvalue = 0x00000001;
5327             /*
5328              * If the caller didn't request DSI_OUTPUT_FIELDS,
5329              * assume the presence bits aren't present, so we
5330              * can't fetch them; use the fields the caller
5331              * requested, instead.
5332              *
5333              * XXX - or should we treat that as an error, and report
5334              * it with an expert info?
5335              */
5336             uint32_t output_fields;
5338             if (values->vflags & DSI_OUTPUT_FIELDS)
5339                 output_fields = tvb_get_letohl(tvb, ioffset);
5340             else
5341                 output_fields = values->vflags;
5342             for (r = 0 ; r < 32; r++ )
5343             {
5344                 /*oldioffset = ioffset;*/
5345                 if (output_fields & bvalue)
5346                 {
5347                     switch(bvalue)
5348                     {
5349                     case DSI_OUTPUT_FIELDS:           /* Information Flags */
5350                         /*
5351                          * XXX - if this bit isn't set, report an error,
5352                          * because if it's not set, the field containing
5353                          * the bits, including this bit, isn't present!
5354                          * (Computer bursts into flames at that point.)
5355                          */
5356                         proto_tree_add_bitmask(ntree, tvb, ioffset, hf_infoflagsl, ett_ncp, ncp_infoflagsl, ENC_LITTLE_ENDIAN);
5357                         ioffset += 2;
5358                         proto_tree_add_bitmask(ntree, tvb, ioffset, hf_infoflagsh, ett_ncp, ncp_infoflagsh, ENC_LITTLE_ENDIAN);
5359                         ioffset += 2;
5360                         break;
5361                     case DSI_ENTRY_ID:                /* Entry ID */
5362                         value1 = tvb_get_letohl(tvb, ioffset);
5363                         proto_tree_add_uint_format(ntree, hf_nds_eid, tvb, ioffset,
5364                                                    4, value1, "Entry ID %08x", value1);
5365                         ioffset = ioffset + 4;
5366                         break;
5367                     case DSI_ENTRY_FLAGS:             /* Entry Flags */
5368                         proto_tree_add_bitmask(ntree, tvb, ioffset, hf_eflags, ett_ncp, ncp_eflags, ENC_LITTLE_ENDIAN);
5369                         ioffset = ioffset+4;
5370                         break;
5371                     case DSI_SUBORDINATE_COUNT:       /* Subordinate Count */
5372                         value1 = tvb_get_letohl(tvb, ioffset);
5373                         proto_tree_add_uint_format(ntree, hf_sub_count, tvb, ioffset,
5374                                                    4, value1, "Subordinate Count %u", value1);
5375                         ioffset = ioffset + 4;
5376                         break;
5377                     case DSI_MODIFICATION_TIME:       /* Modification Time */
5378                         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5379                         ns.nsecs = 0;
5380                         proto_tree_add_time_format(ntree, hf_es_seconds, tvb, ioffset,
5381                                                    4, &ns, "Modification Time: %s",
5382                                                    abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
5383                         ioffset = ioffset + 4;
5384                         break;
5385                     case DSI_MODIFICATION_TIMESTAMP:  /* Modification Timestamp */
5386                         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5387                         ns.nsecs = 0;
5388                         proto_tree_add_time_format(ntree, hf_es_seconds, tvb, ioffset,
5389                                                    4, &ns, "Modification Timestamp: %s",
5390                                                    abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
5391                         ioffset = ioffset + 4;
5392                         proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
5393                                             2, ENC_LITTLE_ENDIAN);
5394                         ioffset = ioffset + 2;
5395                         proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
5396                                             2, ENC_LITTLE_ENDIAN);
5397                         ioffset = ioffset + 2;
5398                         break;
5399                     case DSI_CREATION_TIMESTAMP:      /* Creation Timestamp */
5400                         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5401                         ns.nsecs = 0;
5402                         proto_tree_add_time_format(ntree, hf_es_seconds, tvb, ioffset,
5403                                                    4, &ns, "Creation Timestamp: %s",
5404                                                    abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
5405                         ioffset = ioffset + 4;
5406                         proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
5407                                             2, ENC_LITTLE_ENDIAN);
5408                         ioffset = ioffset + 2;
5409                         proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
5410                                             2, ENC_LITTLE_ENDIAN);
5411                         ioffset = ioffset + 2;
5412                         break;
5413                     case DSI_PARTITION_ROOT_ID:       /* Partition Root ID */
5414                         value1 = tvb_get_letohl(tvb, ioffset);
5415                         proto_tree_add_uint_format(ntree, hf_nds_partition_root_id, tvb, ioffset,
5416                                                    4, value1, "Partition Root ID %08x", value1);
5417                         ioffset = ioffset + 4;
5418                         break;
5419                     case DSI_PARENT_ID:               /* Parent ID */
5420                         proto_tree_add_item(ntree, hf_nds_parent, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
5421                         ioffset = ioffset + 4;
5422                         break;
5423                     case DSI_REVISION_COUNT:          /* Revision Count */
5424                         proto_tree_add_item(ntree, hf_nds_revision, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
5425                         ioffset = ioffset + 4;
5426                         break;
5427                     case DSI_REPLICA_TYPE:           /* Replica Type & State */
5428                         value1 = tvb_get_letohl(tvb, ioffset);
5429                         value2 = value1 & 0x00ff;
5430                         proto_tree_add_uint(ntree, hf_replica_type, tvb, ioffset, 4, value2);
5431                         value3 = value1 & 0xff00;
5432                         proto_tree_add_uint(ntree, hf_replica_state, tvb, ioffset, 4, value3);
5433                         ioffset = ioffset + 4;
5434                         break;
5435                     case DSI_BASE_CLASS:              /* Base Class */
5436                         value1 = tvb_get_letohl(tvb, ioffset);
5437                         ioffset = ioffset + 4;
5438                         temp_values.vstring = get_string(tvb, ioffset, value1);
5439                         proto_tree_add_string(ntree, hf_nds_base, tvb, ioffset,
5440                                               value1, temp_values.vstring);
5441                         ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5442                         break;
5443                     case DSI_ENTRY_RDN:               /* Relative Distinguished Name */
5444                         value1 = tvb_get_letohl(tvb, ioffset);
5445                         ioffset = ioffset + 4;
5446                         temp_values.vstring = get_string(tvb, ioffset, value1);
5447                         proto_tree_add_string(ntree, hf_nds_relative_dn, tvb, ioffset,
5448                                               value1, temp_values.vstring);
5449                         ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5450                         break;
5451                     case DSI_ENTRY_DN:                /* Distinguished Name */
5452                         value1 = tvb_get_letohl(tvb, ioffset);
5453                         ioffset = ioffset + 4;
5454                         temp_values.vstring = get_string(tvb, ioffset, value1);
5455                         proto_tree_add_string(ntree, hf_nds_name, tvb, ioffset,
5456                                               value1, temp_values.vstring);
5457                         ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5458                         break;
5459                     case DSI_PARTITION_ROOT_DN:       /* Root Distinguished Name */
5460                         value1 = tvb_get_letohl(tvb, ioffset);
5461                         ioffset = ioffset + 4;
5462                         temp_values.vstring = get_string(tvb, ioffset, value1);
5463                         proto_tree_add_string(ntree, hf_nds_name, tvb, ioffset,
5464                                               value1, temp_values.vstring);
5465                         ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5466                         break;
5467                     case DSI_PARENT_DN:               /* Parent Distinguished Name */
5468                         value1 = tvb_get_letohl(tvb, ioffset);
5469                         ioffset = ioffset + 4;
5470                         temp_values.vstring = get_string(tvb, ioffset, value1);
5471                         proto_tree_add_string(ntree, hf_nds_name, tvb, ioffset,
5472                                               value1, temp_values.vstring);
5473                         ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5474                         break;
5475                     case DSI_PURGE_TIME:              /* Purge Time */
5476                         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5477                         ns.nsecs = 0;
5478                         proto_tree_add_time_format(ntree, hf_es_seconds, tvb, ioffset,
5479                                                    4, &ns, "Purge Time: %s",
5480                                                    abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
5481                         ioffset = ioffset + 4;
5482                         break;
5483                     case DSI_DEREFERENCED_BASE_CLASS: /* Dereference Base Class */
5484                         value1 = tvb_get_letohl(tvb, ioffset);
5485                         ioffset = ioffset + 4;
5486                         temp_values.vstring = get_string(tvb, ioffset, value1);
5487                         proto_tree_add_string(ntree, hf_deref_base, tvb, ioffset,
5488                                               value1, temp_values.vstring);
5489                         ioffset = check_offset_addition(ioffset, value1, ntree, pinfo, tvb);
5490                         break;
5491                     default:
5492                         break;
5494                     }
5495                     ioffset += align_4(tvb, ioffset);
5496                 }
5497                 bvalue = bvalue*2;
5498                 /* We could loop forever so check to see if bvalue has wrapped to 0.
5499                  * if so then just abort loop.
5500                  */
5501                 if (bvalue==0) {
5502                     break;
5503                 }
5504                 if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5505                 {
5506                     break;
5507                 }
5508             }
5509             if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5510             {
5511                 break;
5512             }
5513         }
5514         break;
5516     case MVTYPE_CLASS_NAMES:      /* Class Names */
5517         /*
5518          * Section 5.15 "Information Types for Class Definitions"
5519          * of Novell eDirectory Core Services says
5520          *
5521          *    DS_CLASS_DEF_NAMES     0 Returns only the class names.
5522          *
5523          *    DS_CLASS_DEFS          1 Returns class names, class flags,
5524          *                             and class definitions (super classes,
5525          *                             containment classes, naming attributes,
5526          *                             mandatory attributes, and optional
5527          *                             attributes).
5528          *
5529          *    DS_EXPANDED_CLASS_DEFS 2 Returns class names, class flags,
5530          *                             class definitions, and class
5531          *                             definitions of the super classes.
5532          *
5533          *    DS_INFO_CLASS_DEFS     3 Returns class names, class flags,
5534          *                             and ASN.1 identifiers.
5535          *
5536          *    DS_FULL_CLASS_DEFS     4 Returns class names, class flags,
5537          *                             class definitions, class definitions
5538          *                             of the super classes, and default
5539          *                             ACLs.
5540          *
5541          * Some version of the Linux ncpfs appears to define
5542          * DS_FULL_CLASS_DEFS_AND_TIMESTAMPS as 5.
5543          *
5544          * Those appear to be the values from earlier in the packet,
5545          * passed to us as values->vflags.
5546          */
5547         number_of_referrals = values->vvalue;
5548         for (i = 0; i < number_of_referrals; i++)
5549         {
5550             ioffset += align_4(tvb, ioffset);
5551             value1 = tvb_get_letohl(tvb, ioffset);
5552             ioffset = ioffset + 4;
5553             temp_values.vstring = get_string(tvb, ioffset, value1);
5554             sub1item = proto_tree_add_string(ntree, hf_nds_base_class, tvb, ioffset,
5555                                              value1, temp_values.vstring);
5556             sub1tree = proto_item_add_subtree(sub1item, ett_nds);
5557             ioffset = check_offset_addition(ioffset, value1, sub1tree, pinfo, tvb);
5558             ioffset += align_4(tvb, ioffset);
5559             if(values->vflags != 0)
5560             {
5561                 /* Not just the class names; give the class flags. */
5562                 proto_tree_add_bitmask(sub1tree, tvb, ioffset, hf_cflags, ett_ncp, ncp_cflags, ENC_LITTLE_ENDIAN);
5563                 ioffset = ioffset+4;
5564                 if(values->vflags != 5)
5565                 {
5566                     /*
5567                      * XXX - where is it stated that all DS_ values other
5568                      * than 0 and 5 include an ASN.1 ID?  And should it
5569                      * be displayed as FT_OID?
5570                      */
5571                     value1 = tvb_get_letohl(tvb, ioffset); /* length of field */
5572                     length_remaining = tvb_captured_length_remaining(tvb, ioffset);
5573                     if(length_remaining == -1 || value1 > (uint32_t) length_remaining)
5574                     {
5575                         break;
5576                     }
5577                     ioffset += 4;
5578                     proto_tree_add_item(sub1tree, hf_nds_asn1, tvb, ioffset, value1, ENC_NA);
5579                     ioffset += value1;
5580                     ioffset += (value1%2);
5581                 }
5582                 if(values->vflags == 1 || values->vflags == 2 || values->vflags == 4)
5583                 {
5584                     /*
5585                      * Everything except DS_INFO_CLASS_DEFS and 5;
5586                      * What comes next is class definitions, so that's
5587                      * what we show here.
5588                      */
5589                     value1 = tvb_get_letohl(tvb, ioffset);  /* Super Classes */
5590                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5591                                                           4, value1, "Super Classes %u", value1);
5592                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5593                     ioffset = ioffset + 4;
5594                     for (r = 0; r < value1; r++)
5595                     {
5596                         value2 = tvb_get_letohl(tvb, ioffset);
5597                         ioffset = ioffset + 4;
5598                         temp_values.vstring = get_string(tvb, ioffset, value2);
5599                         proto_tree_add_string(sub2tree, hf_nds_super, tvb, ioffset,
5600                                               value2, temp_values.vstring);
5601                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5602                         ioffset += align_4(tvb, ioffset);
5603                     }
5604                     value1 = tvb_get_letohl(tvb, ioffset);  /* Containment Classes */
5605                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5606                                                           4, value1, "Containment Classes %u", value1);
5607                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5608                     ioffset = ioffset + 4;
5609                     for (r = 0; r < value1; r++)
5610                     {
5611                         value2 = tvb_get_letohl(tvb, ioffset);
5612                         ioffset = ioffset + 4;
5613                         temp_values.vstring = get_string(tvb, ioffset, value2);
5614                         proto_tree_add_string(sub2tree, hf_nds_base_class, tvb, ioffset,
5615                                               value2, temp_values.vstring);
5616                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5617                         ioffset += align_4(tvb, ioffset);
5618                     }
5619                     value1 = tvb_get_letohl(tvb, ioffset);  /* Naming Attributes */
5620                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5621                                                           4, value1, "Naming Attributes %u", value1);
5622                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5623                     ioffset = ioffset + 4;
5624                     for (r = 0; r < value1; r++)
5625                     {
5626                         value2 = tvb_get_letohl(tvb, ioffset);
5627                         ioffset = ioffset + 4;
5628                         temp_values.vstring = get_string(tvb, ioffset, value2);
5629                         proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
5630                                               value2, temp_values.vstring);
5631                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5632                         ioffset += align_4(tvb, ioffset);
5633                     }
5634                     value1 = tvb_get_letohl(tvb, ioffset);  /* Mandatory Attributes */
5635                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5636                                                           4, value1, "Mandatory Attributes %u", value1);
5637                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5638                     ioffset = ioffset + 4;
5639                     for (r = 0; r < value1; r++)
5640                     {
5641                         value2 = tvb_get_letohl(tvb, ioffset);
5642                         ioffset = ioffset + 4;
5643                         temp_values.vstring = get_string(tvb, ioffset, value2);
5644                         proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
5645                                               value2, temp_values.vstring);
5646                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5647                         ioffset += align_4(tvb, ioffset);
5648                     }
5649                     value1 = tvb_get_letohl(tvb, ioffset);  /* Optional Attributes */
5650                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5651                                                           4, value1, "Optional Attributes %u", value1);
5652                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5653                     ioffset = ioffset + 4;
5654                     for (r = 0; r < value1; r++)
5655                     {
5656                         ioffset += align_4(tvb, ioffset);
5657                         value2 = tvb_get_letohl(tvb, ioffset);
5658                         ioffset = ioffset + 4;
5659                         temp_values.vstring = get_string(tvb, ioffset, value2);
5660                         proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
5661                                               value2, temp_values.vstring);
5662                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5663                         if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5664                         {
5665                             break;
5666                         }
5667                     }
5668                 }
5669                 if(values->vflags == 4)   /* ACLs */
5670                 {
5671                     /*
5672                      * If the NDS documentation is to be believed, this
5673                      * is DS_FULL_CLASS_DEFS (4), which is the class definitions
5674                      * done above, class definitions of the super classes
5675                      * (which we don't seem to be seeing), and default ACLs
5676                      * (which is as described above, *not* just one 32-bit
5677                      * number).
5678                      *
5679                      * DS_EXPANDED_CLASS_DEFS (2) also has the class
5680                      * definitions of the super classes.
5681                      *
5682                      * Perhaps *neither* of them have the class definitions
5683                      * of the super classes immediately after the class
5684                      * definitions, which is why we aren't checking for 2,
5685                      * but we shouldn't be doing this for 4, either.
5686                      * (Do the super classes *follow* the ACLs?  Or do
5687                      * the descriptions of those DS_ values describe
5688                      * *API* behavior, so that DS_EXPANDED_CLASS_DEFS
5689                      * including "class definitions of the super classes"
5690                      * means that the "class definitions" section includes,
5691                      * for each of the super classes listed in a class's
5692                      * description, a class definition entry for that
5693                      * class, i.e. it's an enumeration that returns
5694                      * not only the requested classes, but all their
5695                      * super classes, all the way up to the root of
5696                      * the class hierarchy?  (Note that a single reply
5697                      * to NDS Read Class Definitions" doesn't necessarily
5698                      * contain *all* the classes - subsequent reads may
5699                      * read more of them.)
5700                      *
5701                      * XXX - the ACL permission bits are probably described
5702                      * by section 5.18 "eDirectory Access Control Rights"
5703                      * of Novell eDirectory Core Services.
5704                      */
5705                     value1 = tvb_get_letohl(tvb, ioffset);  /* ACL entries */
5706                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5707                                                           4, value1, "ACL Entries %u", value1);
5708                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5709                     ioffset = ioffset + 4;
5710                     for (r = 0; r < value1; r++)
5711                     {
5712                         value2 = tvb_get_letohl(tvb, ioffset);
5713                         ioffset = ioffset + 4;
5714                         temp_values.vstring = get_string(tvb, ioffset, value2);
5715                         proto_tree_add_string(sub2tree, hf_nds_acl_protected_attribute, tvb, ioffset,
5716                                               value2, temp_values.vstring);
5717                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5718                         ioffset += align_4(tvb, ioffset);
5720                         value2 = tvb_get_letohl(tvb, ioffset);
5721                         ioffset = ioffset + 4;
5722                         temp_values.vstring = get_string(tvb, ioffset, value2);
5723                         proto_tree_add_string(sub2tree, hf_nds_acl_subject, tvb, ioffset,
5724                                               value2, temp_values.vstring);
5725                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5726                         ioffset += align_4(tvb, ioffset);
5728                         proto_tree_add_item(sub2tree, hf_nds_acl_privileges, tvb, ioffset,
5729                                             4, ENC_LITTLE_ENDIAN);
5730                         ioffset = ioffset + 4;
5731                     }
5732                 }
5733                 if(values->vflags == 5)   /* Time stamps and Base Class definitions  */
5734                 {
5735                     /*
5736                      * XXX - and what's this?  I *do* see time stamps,
5737                      * followed by a bunch of other stuff, so maybe
5738                      * it is, in fact, DS_FULL_CLASS_DEFS_AND_TIMESTAMPS.
5739                      *
5740                      * But what's the stuff after it?  Is it, in fact,
5741                      * present in replies?  Or does it again mean
5742                      * "walk up the class hierarchy", so that the
5743                      * class hierarchy is linearized, as per the above?
5744                      *
5745                      * BTW, is this the universe's way of saying that
5746                      * maybe this should be divided into a bunch of
5747                      * subroutines, called from here, rather than
5748                      * what appears to be a bit of inheritance by
5749                      * copy and paste?
5750                      */
5751                     ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5752                     ns.nsecs = 0;
5753                     proto_tree_add_time_format(sub1tree, hf_es_seconds, tvb, ioffset,
5754                                                4, &ns, "Creation Timestamp: %s",
5755                                                abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
5756                     ioffset = ioffset + 4;
5757                     proto_tree_add_item(sub1tree, hf_nds_replica_num, tvb, ioffset,
5758                                         2, ENC_LITTLE_ENDIAN);
5759                     ioffset = ioffset + 2;
5760                     proto_tree_add_item(sub1tree, hf_nds_event_num, tvb, ioffset,
5761                                         2, ENC_LITTLE_ENDIAN);
5762                     ioffset = ioffset + 2;
5763                     ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5764                     ns.nsecs = 0;
5765                     proto_tree_add_time_format(sub1tree, hf_es_seconds, tvb, ioffset,
5766                                                4, &ns, "Modification Timestamp: %s",
5767                                                abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
5768                     ioffset = ioffset + 4;
5769                     proto_tree_add_item(sub1tree, hf_nds_replica_num, tvb, ioffset,
5770                                         2, ENC_LITTLE_ENDIAN);
5771                     ioffset = ioffset + 2;
5772                     proto_tree_add_item(sub1tree, hf_nds_event_num, tvb, ioffset,
5773                                         2, ENC_LITTLE_ENDIAN);
5774                     ioffset = ioffset + 2;
5775                     /* Class Definition */
5776                     /* XXX - is this really there? */
5777                     value1 = tvb_get_letohl(tvb, ioffset);  /* Super Classes */
5778                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5779                                                           4, value1, "Super Classes %u", value1);
5780                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5781                     ioffset = ioffset + 4;
5782                     for (r = 0; r < value1; r++)
5783                     {
5784                         value2 = tvb_get_letohl(tvb, ioffset);
5785                         ioffset = ioffset + 4;
5786                         temp_values.vstring = get_string(tvb, ioffset, value2);
5787                         proto_tree_add_string(sub2tree, hf_nds_super, tvb, ioffset,
5788                                               value2, temp_values.vstring);
5789                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5790                         ioffset += align_4(tvb, ioffset);
5791                     }
5792                     value1 = tvb_get_letohl(tvb, ioffset);  /* Containment Classes */
5793                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5794                                                           4, value1, "Containment Classes %u", value1);
5795                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5796                     ioffset = ioffset + 4;
5797                     for (r = 0; r < value1; r++)
5798                     {
5799                         value2 = tvb_get_letohl(tvb, ioffset);
5800                         ioffset = ioffset + 4;
5801                         temp_values.vstring = get_string(tvb, ioffset, value2);
5802                         proto_tree_add_string(sub2tree, hf_nds_base_class, tvb, ioffset,
5803                                               value2, temp_values.vstring);
5804                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5805                         ioffset += align_4(tvb, ioffset);
5806                     }
5807                     value1 = tvb_get_letohl(tvb, ioffset);  /* Naming Attributes */
5808                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5809                                                           4, value1, "Naming Attributes %u", value1);
5810                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5811                     ioffset = ioffset + 4;
5812                     for (r = 0; r < value1; r++)
5813                     {
5814                         value2 = tvb_get_letohl(tvb, ioffset);
5815                         ioffset = ioffset + 4;
5816                         temp_values.vstring = get_string(tvb, ioffset, value2);
5817                         proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
5818                                               value2, temp_values.vstring);
5819                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5820                         ioffset += align_4(tvb, ioffset);
5821                     }
5822                     value1 = tvb_get_letohl(tvb, ioffset);  /* Mandatory Attributes */
5823                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5824                                                           4, value1, "Mandatory Attributes %u", value1);
5825                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5826                     ioffset = ioffset + 4;
5827                     for (r = 0; r < value1; r++)
5828                     {
5829                         value2 = tvb_get_letohl(tvb, ioffset);
5830                         ioffset = ioffset + 4;
5831                         temp_values.vstring = get_string(tvb, ioffset, value2);
5832                         proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
5833                                               value2, temp_values.vstring);
5834                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5835                         ioffset += align_4(tvb, ioffset);
5836                     }
5837                     value1 = tvb_get_letohl(tvb, ioffset);  /* Optional Attributes */
5838                     sub2item = proto_tree_add_uint_format(sub1tree, hf_nds_number_of_items, tvb, ioffset,
5839                                                           4, value1, "Optional Attributes %u", value1);
5840                     sub2tree = proto_item_add_subtree(sub2item, ett_nds);
5841                     ioffset = ioffset + 4;
5842                     for (r = 0; r < value1; r++)
5843                     {
5844                         value2 = tvb_get_letohl(tvb, ioffset);
5845                         ioffset = ioffset + 4;
5846                         temp_values.vstring = get_string(tvb, ioffset, value2);
5847                         proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
5848                                               value2, temp_values.vstring);
5849                         ioffset = check_offset_addition(ioffset, value2, sub2tree, pinfo, tvb);
5850                         ioffset += align_4(tvb, ioffset);
5851                     }
5852                     value1 = tvb_get_letohl(tvb, ioffset);    /* Default ACL */
5853                     proto_tree_add_uint_format(sub1tree, hf_nds_eid, tvb, ioffset,
5854                                                4, value1, "Default ACL %08x", value1);
5855                     ioffset = ioffset + 4;
5856                     if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5857                     {
5858                         break;
5859                     }
5860                 }
5861             }
5862         }
5863         break;
5865     case MVTYPE_MODIFY_CLASS:     /* Modify Class */
5866         for (i = 1 ; i <= values->vvalue; i++ )   /* Attribute Names to add*/
5867         {
5868             ioffset += align_4(tvb, ioffset);
5869             value1 = tvb_get_letohl(tvb, ioffset);
5870             ioffset = ioffset + 4;
5871             values->vstring = get_string(tvb, ioffset, value1);
5872             proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
5873                                   value1, values->vstring);
5874             ioffset = ioffset + value1;
5875         }
5876         if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5877         {
5878             break;
5879         }
5880         ioffset += align_4(tvb, ioffset);
5881         proto_tree_add_item_ret_uint(ntree, hf_nds_att_del, tvb, ioffset, 4, ENC_LITTLE_ENDIAN, &value1);
5882         ioffset = ioffset + 4;
5883         for (i = 1 ; i <= value1; i++ )   /* Attribute Names to delete*/
5884         {
5885             ioffset += align_4(tvb, ioffset);
5886             value2 = tvb_get_letohl(tvb, ioffset);
5887             ioffset = ioffset + 4;
5888             values->vstring = get_string(tvb, ioffset, value2);
5889             proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
5890                                   value2, values->vstring);
5891             ioffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
5892         }
5893         if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5894         {
5895             break;
5896         }
5897         ioffset += align_4(tvb, ioffset);
5898         proto_tree_add_item_ret_uint(ntree, hf_nds_acl_add, tvb, ioffset, 4, ENC_LITTLE_ENDIAN, &value1);
5899         ioffset = ioffset + 4;
5900         for (i = 1 ; i <= value1; i++ )   /* ACL templates to add*/
5901         {
5902             ioffset += align_4(tvb, ioffset);
5903             value2 = tvb_get_letohl(tvb, ioffset);  /* Attribute Name */
5904             ioffset = ioffset + 4;
5905             values->vstring = get_string(tvb, ioffset, value2);
5906             proto_tree_add_string(ntree, hf_nds_attribute_dn, tvb, ioffset,
5907                                   value2, values->vstring);
5908             ioffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
5909             ioffset += align_4(tvb, ioffset);
5910             value2 = tvb_get_letohl(tvb, ioffset);  /* DN of Trustee */
5911             ioffset = ioffset + 4;
5912             values->vstring = get_string(tvb, ioffset, value2);
5913             proto_tree_add_string(ntree, hf_nds_trustee_dn, tvb, ioffset,
5914                                   value2, values->vstring);
5915             ioffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
5916             ioffset += align_4(tvb, ioffset);
5917             proto_tree_add_item(ntree, hf_nds_privileges, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
5918             ioffset = ioffset + 4;
5919         }
5920         if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
5921         {
5922             break;
5923         }
5924         ioffset += align_4(tvb, ioffset);
5925         proto_tree_add_item_ret_uint(ntree, hf_nds_acl_del, tvb, ioffset,
5926                                    4, ENC_LITTLE_ENDIAN, &value1);
5927         ioffset = ioffset + 4;
5928         for (i = 1 ; i <= value1; i++ )   /* ACL templates to delete*/
5929         {
5930             ioffset += align_4(tvb, ioffset);
5931             value2 = tvb_get_letohl(tvb, ioffset);  /* Attribute Name */
5932             ioffset = ioffset + 4;
5933             values->vstring = get_string(tvb, ioffset, value2);
5934             proto_tree_add_string(ntree, hf_nds_attribute_dn, tvb, ioffset,
5935                                   value2, values->vstring);
5936             ioffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
5937             ioffset += align_4(tvb, ioffset);
5938             value2 = tvb_get_letohl(tvb, ioffset);  /* DN of Trustee */
5939             ioffset = ioffset + 4;
5940             values->vstring = get_string(tvb, ioffset, value2);
5941             proto_tree_add_string(ntree, hf_nds_trustee_dn, tvb, ioffset,
5942                                   value2, values->vstring);
5943             ioffset = check_offset_addition(ioffset, value2, ntree, pinfo, tvb);
5944             ioffset += align_4(tvb, ioffset);
5945             value1 = tvb_get_letohl(tvb, ioffset);  /* Privileges */
5946             proto_tree_add_item(ntree, hf_nds_privileges, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
5947             ioffset = ioffset + 4;
5948         }
5949         break;
5951     case MVTYPE_PROCESS_TAGS: /* Process tags and paths depending on name type returned. */
5952         switch (values->vflags) {
5954         case 8:  /* Tuned Name */
5955             proto_tree_add_item(ntree, hf_nds_tune_mark, tvb, ioffset, 2, ENC_BIG_ENDIAN);
5956             ioffset += 2;
5957             value1 = tvb_get_letohs(tvb, ioffset);
5958             valuestr = val_to_str_const(value1, nds_tuned_tags, "(Undefined Tuned Name Tag)");
5959             proto_tree_add_string_format(ntree, hf_value_string, tvb, ioffset,
5960                                          2, valuestr, "Tuned Name Tag -> %s", valuestr);
5961             ioffset += 2;
5962             ioffset += align_4(tvb, ioffset);
5963             if (value1 == 0) { /* RDN Hint - really just returns the dist name + timestamp info */
5964                 value2 = tvb_get_letohl(tvb, ioffset);  /* Distinguished Name Len, String[len]*/
5965                 ioffset = ioffset + 4;
5966                 values->vstring = get_string(tvb, ioffset, value2);
5967                 proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
5968                                       value2, values->vstring);
5969                 ioffset += value2;
5970                 ioffset += align_4(tvb, ioffset);
5971                 ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
5972                 ns.nsecs = 0;
5973                 proto_tree_add_time_format(ntree, hf_es_seconds, tvb, ioffset,
5974                                            4, &ns, "Creation Timestamp: %s",
5975                                            abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
5976                 ioffset += 4;
5977                 proto_tree_add_item(ntree, hf_nds_replica_num, tvb, ioffset,
5978                                     2, ENC_LITTLE_ENDIAN);
5979                 ioffset = ioffset + 2;
5980                 proto_tree_add_item(ntree, hf_nds_event_num, tvb, ioffset,
5981                                     2, ENC_LITTLE_ENDIAN);
5982                 ioffset = ioffset + 2;
5983             }
5984             else /* Process the full RDN history including ancestors */
5985             {
5986                 value1 = tvb_get_letohl(tvb, ioffset);
5987                 sub1item = proto_tree_add_uint_format(ntree, hf_nds_acl_del, tvb, ioffset,
5988                                                       4, value1, "Number of RDN Items %u", value1);
5989                 sub1tree = proto_item_add_subtree(sub1item, ett_nds);
5990                 ioffset = ioffset + 4;
5991                 for (i=1; i <= value1; i++) {
5992                     sub2tree = proto_tree_add_subtree_format(sub1tree, tvb, ioffset, 0, ett_nds, NULL, "Item %u", i);
5993                     ioffset += align_4(tvb, ioffset);
5995                     value5 = tvb_get_letohl(tvb, ioffset);
5996                     valuestr = val_to_str_const(value5, nds_tuned_item_tags, "(Undefined Tuned Name Tag)");
5997                     if (value5 == 0) { /* Items are timestamp + Distinguished name (0 value == one entry)*/
5998                         proto_tree_add_string_format(sub2tree, hf_value_string, tvb, ioffset,
5999                                                      4, valuestr, "Item Tag -> %s", valuestr);
6000                         ioffset += 4;
6001                         ns.secs = tvb_get_letohl(tvb, ioffset);   /* Seconds */
6002                         ns.nsecs = 0;
6003                         proto_tree_add_time_format(sub2tree, hf_es_seconds, tvb, ioffset,
6004                                                    4, &ns, "Timestamp: %s",
6005                                                    abs_time_secs_to_str(pinfo->pool, ns.secs, ABSOLUTE_TIME_LOCAL, true));
6006                         ioffset += 4;
6007                         proto_tree_add_item(sub2tree, hf_nds_replica_num, tvb, ioffset,
6008                                             2, ENC_LITTLE_ENDIAN);
6009                         ioffset = ioffset + 2;
6010                         proto_tree_add_item(sub2tree, hf_nds_event_num, tvb, ioffset,
6011                                             2, ENC_LITTLE_ENDIAN);
6012                         ioffset = ioffset + 2;
6013                         value2 = tvb_get_letohl(tvb, ioffset);  /* Distinguished Name Len, String[len]*/
6014                         ioffset = ioffset + 4;
6015                         values->vstring = get_string(tvb, ioffset, value2);
6016                         proto_tree_add_string(sub2tree, hf_mv_string, tvb, ioffset,
6017                                               value2, values->vstring);
6018                         ioffset += value2;
6019                     }
6020                     /* XXX: What if "multiple items" ?                 */
6021                     /*      What if "Undefined ... " ?                 */
6022                     /*      For now: we'll just keep on walking...     */
6023                     /*      Presumably we'll get a ReportedBoundsError */
6024                     /*       pretty quickly.                           */
6025                     else   /* Undefined or "multiple items" ... */
6026                     {
6027                         ioffset += 4;
6028                     }
6029                 } /* for */
6030             } /* else */
6031             values->voffset=ioffset;
6032             break;
6033         default: /* All other name types are just a string */
6034             values->vstring = get_string(tvb, ioffset, values->vlength);
6035             proto_tree_add_string(ntree, hf_mv_string, tvb, ioffset,
6036                                   values->vlength, values->vstring);
6037             values->voffset=ioffset + values->vlength;
6038             /*ioffset = values->voffset;
6039             ioffset += align_4(tvb, ioffset);*/
6040             break;
6041         } /* switch (values->vflags) */
6042         break;
6044     case MVTYPE_PROCESS_ITERATOR: /* Process Iterator subverbs. */
6045         proto_tree_add_item(ntree, hf_nds_info_type, tvb, ioffset, 4, ENC_LITTLE_ENDIAN);
6046         ioffset += 4;
6047         value5 = tvb_get_letohl(tvb, ioffset);
6048         proto_tree_add_bitmask(ncp_tree, tvb, ioffset, hf_infoflagsl, ett_ncp, ncp_infoflagsl, ENC_LITTLE_ENDIAN);
6049         ioffset += 2;
6050         proto_tree_add_bitmask(ncp_tree, tvb, ioffset, hf_infoflagsh, ett_ncp, ncp_infoflagsh, ENC_LITTLE_ENDIAN);
6051         ioffset += 2;
6052         proto_tree_add_item(ntree, hf_nds_time_filter, tvb, ioffset, 4, ENC_BIG_ENDIAN);
6053         ioffset += 4;
6054         proto_tree_add_item(ntree, hf_nds_all_attr, tvb, ioffset, 4, ENC_BIG_ENDIAN);
6055         ioffset += 4;
6056         value2 = tvb_get_letohl(tvb, ioffset);
6057         sub1item = proto_tree_add_uint_format(ntree, hf_nds_number_of_items, tvb, ioffset,
6058                                               4, value2, "Number of Attributes %u", value2);
6059         sub1tree = proto_item_add_subtree(sub1item, ett_nds);
6060         ioffset += 4;
6061         for (i=1; i<=value2; i++) {
6062             sub2tree = proto_tree_add_subtree_format(sub1tree, tvb, ioffset, 0, ett_nds, NULL, "Attribute %u", i);
6063             ioffset += align_4(tvb, ioffset);
6064             value3 = tvb_get_letohl(tvb, ioffset);  /* Attribute Name */
6065             ioffset = ioffset + 4;
6066             values->vstring = get_string(tvb, ioffset, value3);
6067             proto_tree_add_string(sub2tree, hf_nds_attribute_dn, tvb, ioffset,
6068                                   value3, values->vstring);
6069             ioffset = ioffset + value3;
6071             if(tvb_captured_length_remaining(tvb, ioffset) < 4 )
6072             {
6073                 break;
6074             }
6075         }
6076         ioffset += align_4(tvb, ioffset);
6077         value4 = tvb_get_letohl(tvb, ioffset);
6078         values->vstring = val_to_str_const(value4, iterator_subverbs, "(No Iteration Verb Found)");
6079         ioffset += 4;
6080         dissect_nds_iterator(ntree, tvb, pinfo, value4, value5, ioffset, true);
6082         values->vstring = wmem_strdup_printf(pinfo->pool, "(%s)", values->vstring);
6083         break;
6085     default:
6086         break;
6087     }
6090 static void
6091 dissect_ncp_89_6_request(tvbuff_t *tvb, proto_tree *volatile ncp_tree, uint32_t offset)
6093     uint32_t string_len, datatype, count, i;
6095     datatype = tvb_get_letohl(tvb, offset);
6096     proto_tree_add_item(ncp_tree, hf_ncp_data_type_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
6097     offset += 1;
6098     proto_tree_add_item(ncp_tree, hf_ncp_reserved5, tvb, offset, 5, ENC_NA);
6099     offset += 5;
6100     count = tvb_get_uint8(tvb, offset);
6101     proto_tree_add_item(ncp_tree, hf_ncp_path_count, tvb, offset, 1, ENC_LITTLE_ENDIAN);
6102     offset += 1;
6103     for (i=0; i < count; i++) {
6104         if (datatype == 0) {
6105             string_len = (tvb_get_uint8(tvb, offset))+1;
6106             proto_tree_add_item(ncp_tree, hf_ncp_directory_path, tvb, offset+1, string_len-1, ENC_ASCII|ENC_NA);
6107         }
6108         else
6109         {
6110             string_len = (tvb_get_letohs(tvb, offset))+2;
6111             proto_tree_add_item(ncp_tree, hf_ncp_directory_path, tvb, offset+2, string_len-2, ENC_ASCII|ENC_NA);
6112         }
6113         offset += string_len;
6114         if(tvb_captured_length_remaining(tvb, offset) < 4 )
6115         {
6116             break;
6117         }
6118     }
6122 static void
6123 dissect_ncp_123_11_reply(tvbuff_t *tvb, proto_tree *volatile ncp_tree, ncp_req_hash_value *request_value)
6125     int string_len, loffset;
6127     loffset = 76;
6128     if (request_value->length == 7) {
6129         /* Undocumented, if request value length is 7 then the reply is offset by 8 bytes.
6130          * Unknown what these 8 bytes represent */
6131         loffset += 8;
6132     }
6133     string_len = tvb_get_uint8(tvb, loffset);
6134     proto_tree_add_item(ncp_tree, hf_ncp_file_name_12, tvb, loffset+1, string_len, ENC_ASCII|ENC_NA);
6135     loffset += string_len+1;
6136     string_len = tvb_get_uint8(tvb, loffset);
6137     proto_tree_add_item(ncp_tree, hf_ncp_name12, tvb, loffset+1, string_len, ENC_ASCII|ENC_NA);
6138     loffset += string_len+1;
6139     string_len = tvb_get_uint8(tvb, loffset);
6140     proto_tree_add_item(ncp_tree, hf_ncp_copyright, tvb, loffset+1, string_len, ENC_ASCII|ENC_NA);
6143 static void
6144 dissect_ncp_123_17_reply(tvbuff_t *tvb, packet_info* pinfo, proto_tree *volatile ncp_tree)
6146     proto_tree              *atree;
6147     proto_item              *aitem;
6148     uint32_t loffset, number_of_items, addr_type;
6149     uint16_t x;
6151     number_of_items = tvb_get_letohl(tvb, 36);
6152     proto_tree_add_item(ncp_tree, hf_ncp_items_in_packet, tvb, 36, 4, ENC_LITTLE_ENDIAN);
6153     loffset = 40;
6154     for (x = 1; x <= number_of_items; x++)
6155     {
6156         atree = proto_tree_add_subtree_format(ncp_tree, tvb, loffset, -1, ett_ncp, &aitem, "Network Address - %u", x);
6158         addr_type = tvb_get_uint8(tvb, loffset);
6159         proto_tree_add_item(atree, hf_ncp_transport_type, tvb, loffset, 1, ENC_LITTLE_ENDIAN);
6160         /* The address type is one byte of a 4 byte value. The next 4 bytes are
6161          * the length of the address. Since we already know the length based upon
6162          * the type of address, we can skip this value. So set the offset accourdingly */
6163         loffset += 8;
6165         switch (addr_type)
6166         {
6167         case 1:
6168             proto_tree_add_item(atree, hf_nds_net, tvb, loffset, 4, ENC_BIG_ENDIAN);
6169             proto_tree_add_item(atree, hf_nds_node, tvb, loffset+4, 6, ENC_NA);
6170             proto_tree_add_item(atree, hf_nds_socket, tvb, loffset+10, 2, ENC_BIG_ENDIAN);
6171             loffset += 12;
6172             break;
6173         case 5:
6174             proto_tree_add_item(atree, hf_nds_port, tvb, loffset, 2, ENC_BIG_ENDIAN);
6175             proto_tree_add_item(atree, hf_add_ref_udp, tvb, loffset+2, 4, ENC_BIG_ENDIAN);
6176             loffset += 6;
6177             break;
6178         case 6:
6179             proto_tree_add_item(atree, hf_nds_port, tvb, loffset, 2, ENC_BIG_ENDIAN);
6180             proto_tree_add_item(atree, hf_add_ref_tcp, tvb, loffset+2, 4, ENC_BIG_ENDIAN);
6181             loffset += 6;
6182             break;
6183         default:
6184             expert_add_info(pinfo, aitem, &ei_ncp_address_type);
6185             /* unknown type so read the length field and then
6186              * just skip the record and move on to the next */
6187             loffset += tvb_get_letohl(tvb, loffset - 4);
6188             break;
6189         }
6190         proto_item_set_end(aitem, tvb, loffset);
6191         if(tvb_captured_length_remaining(tvb, loffset) < 4 )
6192         {
6193             break;
6194         }
6195     }
6198 static void
6199 dissect_ncp_87_72_reply(tvbuff_t *tvb, proto_tree *volatile ncp_tree)
6201     proto_tree_add_item(ncp_tree, hf_ncp_bytes_actually_trans_64, tvb, tvb_captured_length_remaining(tvb, 0)-4, 4, ENC_BIG_ENDIAN);
6204 static void
6205 dissect_ncp_23_26_reply(tvbuff_t *tvb, proto_tree *volatile ncp_tree)
6207     /* For an IP-only server, the 4-byte IP address is placed into the 4-byte NetworkAddress
6208      * field of the NetworkAddressStruct, while the NetworkNodeAddress and NetworkSocket
6209      * fields are left blank. */
6210     if (tvb_get_letohl(tvb, 12)==0) {
6211         /* IP Address */
6212         proto_tree_add_item(ncp_tree, hf_ncp_ip_address, tvb, 8, 4, ENC_BIG_ENDIAN);
6213     }
6214     else
6215     {
6216         /* IPX Address */
6217         proto_tree_add_item(ncp_tree, hf_nds_net, tvb, 8, 4, ENC_BIG_ENDIAN);
6218         proto_tree_add_item(ncp_tree, hf_nds_node, tvb, 12, 6, ENC_NA);
6219         proto_tree_add_item(ncp_tree, hf_nds_socket, tvb, 18, 2, ENC_BIG_ENDIAN);
6220     }
6221     proto_tree_add_item(ncp_tree, hf_ncp_connection_type, tvb, 20, 1, ENC_NA);
6225  * XXX - this actually handles both 89 3 and 89 20.
6226  * It should also probably handle 87 3 and 87 20.
6227  */
6228 static void
6229 dissect_ncp_8x20req(tvbuff_t *tvb, proto_tree *volatile ncp_tree, uint32_t offset, unsigned func)
6231     uint32_t string_len, str_length, buffer_offset;
6232     int i;
6233     uint8_t c_char;
6234     wmem_strbuf_t *string_buf;
6235     int length_remaining = 0;
6237     length_remaining = tvb_captured_length_remaining(tvb, offset);
6238     /*
6239      * XXX - the Novell documentation for function code 89 (0x59) says
6240      * that the length is 1 byte if the data format byte is 0 for ASCII
6241      * and 2 bytes if the data format byte is 1 for UTF-8.
6242      *
6243      * The documentation for function code 87 (0x57) says it's always
6244      * 1 byte - and that there's no data format byte.
6245      */
6246     if (func == 0x57)
6247     {
6248         string_len = tvb_get_uint8(tvb, offset);
6249         str_length = tvb_get_uint8(tvb, offset);
6250     }
6251     else
6252     {
6253         string_len = tvb_get_letohs(tvb, offset);
6254         str_length = tvb_get_letohs(tvb, offset);
6255     }
6257     if((int)str_length > length_remaining)
6258     {
6259         THROW(ReportedBoundsError);
6260     }
6262     string_buf = wmem_strbuf_new(wmem_packet_scope(), NULL);
6263     offset++;
6264     buffer_offset = offset;
6266     /*
6267      * XXX - should this treat ASCII and UTF-8 differently?
6268      */
6269     for ( i = 0; i <= (int)str_length; i++ )
6270     {
6271         c_char = tvb_get_uint8(tvb, buffer_offset );
6272         if (c_char<0x20 || c_char>0x7e)
6273         {
6274             /* Not printable ASCII */
6275             if (c_char == 0xff)
6276             {
6277                 /*
6278                  * 0xff is not a valid ASCII character and is not
6279                  * part of a valid UTF-8 octet sequence.
6280                  *
6281                  * What is the significance of 0xbf, 0xaa, and 0xae
6282                  * here?
6283                  *
6284                  * Will these show up in UTF-8 strings?
6285                  */
6286                 buffer_offset++;
6287                 length_remaining--;
6288                 c_char = tvb_get_uint8(tvb, buffer_offset);
6289                 if (c_char == '?')
6290                 {
6291                     wmem_strbuf_append_c(string_buf, '?');
6292                     proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "Wildcard Question");
6293                 }
6294                 else if (c_char == '*')
6295                 {
6296                     wmem_strbuf_append_c(string_buf, '*');
6297                     proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "Wildcard Asterisk");
6298                 }
6299                 else if (c_char == 0xbf)
6300                 {
6301                     /*
6302                      * For what it's worth, in ISO 8859-1, 0xbf is a
6303                      * Spanish-style upside-down question mark.
6304                      */
6305                     wmem_strbuf_append_c(string_buf, '?');
6306                     proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "DOS Wildcard Question");
6307                 }
6308                 else if (c_char == 0xaa)
6309                 {
6310                     /*
6311                      * But, in 8859-1, this is a feminine ordinal indicator
6312                      * (underlined subscripted "a").
6313                      */
6314                     c_char = '*';
6315                     wmem_strbuf_append_c(string_buf, c_char);
6316                     proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "DOS Wildcard Asterisk");
6317                 }
6318                 else if (c_char == 0xae)
6319                 {
6320                     /*
6321                      * And this is a registered trademark symbol.
6322                      */
6323                     wmem_strbuf_append_c(string_buf, '.');
6324                     proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "DOS Wildcard Period");
6325                 }
6326                 else
6327                 {
6328                     wmem_strbuf_append_c(string_buf, '.');
6329                 }
6330             }
6331             else if (c_char == 0xef)
6332             {
6333                 /*
6334                  * XXX - if these 3-character sequences are considered
6335                  * as UTF-8 sequences, they map to characters in the
6336                  * private use range from f87b to f87f.
6337                  *
6338                  * Is that what's happening here?
6339                  *
6340                  * If so, will these show up in ASCII strings?
6341                  */
6342                 buffer_offset++;
6343                 length_remaining--;
6344                 c_char = tvb_get_uint8(tvb, buffer_offset);
6345                 if (c_char == 0xa3)
6346                 {
6347                     buffer_offset++;
6348                     length_remaining--;
6349                     c_char = tvb_get_uint8(tvb, buffer_offset);
6350                     if (c_char == 0xbb)
6351                     {
6352                         wmem_strbuf_append_c(string_buf, '?');
6353                         proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "Wildcard Question");
6354                     }
6355                     else if (c_char == 0xbc)
6356                     {
6357                         wmem_strbuf_append_c(string_buf, '*');
6358                         proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "Wildcard Asterisk");
6359                     }
6360                     else if (c_char == 0xbd)
6361                     {
6362                         c_char = '?';
6363                         wmem_strbuf_append_c(string_buf, c_char);
6364                         proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "DOS Wildcard Question");
6365                     }
6366                     else if (c_char == 0xbe)
6367                     {
6368                         wmem_strbuf_append_c(string_buf, '*');
6369                         proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "DOS Wildcard Asterisk");
6370                     }
6371                     else if (c_char == 0xbf)
6372                     {
6373                         wmem_strbuf_append_c(string_buf, '.');
6374                         proto_tree_add_uint_format_value(ncp_tree, hf_search_modifier, tvb, buffer_offset-1, 2, c_char, "DOS Wildcard Period");
6375                     }
6376                 }
6377             }
6378             else
6379             {
6380                 if (c_char != 0x00)
6381                 {
6382                     wmem_strbuf_append_c(string_buf, '.');
6383                 }
6384                 else
6385                 {
6386                     i--;
6387                     str_length--;
6388                     offset++;
6389                 }
6390             }
6391         }
6392         else
6393         {
6394             /* printable ASCII */
6395             wmem_strbuf_append_c(string_buf, c_char);
6396         }
6397         buffer_offset++;
6398         length_remaining--;
6400         if(length_remaining==1)
6401         {
6402             break;
6403         }
6404         if (i >= 1023) { /* Don't process beyond the size of our variable */
6405             break;       /* If string is too long just return the first 1K. */
6406         }
6407     }
6409     proto_tree_add_string(ncp_tree, hf_search_pattern, tvb, offset, string_len, wmem_strbuf_get_str(string_buf));
6412 static void
6413 dissect_ncp_8x20reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *volatile ncp_tree,
6414                       const ncp_record *ncp_rec, ncp_req_hash_value *request_value)
6416     uint16_t            x;
6417     uint32_t            loffset, number_of_items, str_length;
6418     ptvcursor_t         *ptvc = NULL;
6419     proto_tree          *atree, *btree;
6420     proto_item          *aitem, *bitem;
6422     if ((request_value->req_mask ==0) & (request_value->req_mask_ext == 0))
6423     {
6424         return;
6425     }
6426     atree = proto_tree_add_subtree(ncp_tree, tvb, 8, 9, ett_ncp, &aitem, "Search Sequence");
6428     proto_tree_add_item(atree, hf_ncp_volume_number, tvb, 8, 1, ENC_LITTLE_ENDIAN);
6429     proto_tree_add_item(atree, hf_ncp_directory_entry_number, tvb, 9, 4, ENC_LITTLE_ENDIAN);
6430     proto_tree_add_item(atree, hf_ncp_sequence_number, tvb, 13, 4, ENC_LITTLE_ENDIAN);
6432     proto_tree_add_item(ncp_tree, hf_ncp_more_flag, tvb, 17, 1, ENC_LITTLE_ENDIAN);
6433     number_of_items = tvb_get_letohs(tvb, 18);
6434     proto_tree_add_item(ncp_tree, hf_ncp_info_count, tvb, 18, 2, ENC_LITTLE_ENDIAN);
6435     loffset = 20;
6436     for (x = 1; x <= number_of_items; x++ )
6437     {
6438         atree = proto_tree_add_subtree_format(ncp_tree, tvb, loffset, -1, ett_ncp, &aitem, "Information Item %u", x);
6440         /* Data Stream Space Allocated */
6441         if (request_value->req_mask & 0x0002) {
6442             proto_tree_add_item(atree, hf_ncp_data_stream_space_alloc, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6443             loffset += 4;
6444         }
6445         else
6446         {
6447             if ((request_value->req_mask_ext & 0x8000)==false) {
6448                 loffset += 4;
6449             }
6450         }
6451         /* Attributes */
6452         if (request_value->req_mask & 0x0004) {
6453             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Attributes");
6455             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6456             process_ptvc_record(ptvc, pinfo, ptvc_struct_attributes_struct,
6457                     NULL, true, ncp_rec, false);
6458             ptvcursor_free(ptvc);
6459             loffset += 6;
6460             proto_item_set_end(bitem, tvb, loffset);
6461         }
6462         else
6463         {
6464             if ((request_value->req_mask_ext & 0x8000)==false) {
6465                 loffset += 6;
6466             }
6467         }
6468         /* Data Stream Size */
6469         if (request_value->req_mask & 0x0008) {
6470             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Data Stream Size");
6472             proto_tree_add_item(btree, hf_ncp_data_stream_size, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6473             loffset += 4;
6474             proto_item_set_end(bitem, tvb, loffset);
6475         }
6476         else
6477         {
6478             if ((request_value->req_mask_ext & 0x8000)==false) {
6479                 loffset += 4;
6480             }
6481         }
6482         /* Total Stream Size */
6483         if (request_value->req_mask & 0x0010) {
6484             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Total Stream Size");
6486             proto_tree_add_item(btree, hf_ncp_ttl_ds_disk_space_alloc, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6487             proto_tree_add_item(btree, hf_ncp_number_of_data_streams, tvb, loffset+4, 2, ENC_LITTLE_ENDIAN);
6488             loffset += 6;
6489             proto_item_set_end(bitem, tvb, loffset);
6490         }
6491         else
6492         {
6493             if ((request_value->req_mask_ext & 0x8000)==false) {
6494                 loffset += 6;
6495             }
6496         }
6497         /* Extended Attributes oldstyle location*/
6498         if (request_value->req_mask & 0x0020 && !ncp_newstyle) {
6499             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Extended Attributes");
6500             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6501             process_ptvc_record(ptvc, pinfo, ptvc_struct_ea_info_struct,
6502                     NULL, true, ncp_rec, false);
6503             ptvcursor_free(ptvc);
6504             loffset += 12;
6505             proto_item_set_end(bitem, tvb, loffset);
6506         }
6507         else
6508         {
6509             if ((request_value->req_mask_ext & 0x8000)==false && !ncp_newstyle) {
6510                 loffset += 12;
6511             }
6512         }
6513         /* Extended Attributes new style location*/
6514         if (request_value->req_mask & 0x0020 && ncp_newstyle) {
6515             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Extended Attributes");
6517             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6518             process_ptvc_record(ptvc, pinfo, ptvc_struct_ea_info_struct,
6519                     NULL, true, ncp_rec, false);
6520             ptvcursor_free(ptvc);
6521             loffset += 12;
6522             proto_item_set_end(bitem, tvb, loffset);
6523         }
6524         else
6525         {
6526             if ((request_value->req_mask_ext & 0x8000)==false && ncp_newstyle) {
6527                 loffset += 12;
6528             }
6529         }
6530         /* Archive Information */
6531         if (request_value->req_mask & 0x0040) {
6532             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Archive");
6533             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6534             process_ptvc_record(ptvc, pinfo, ptvc_struct_archive_info_struct,
6535                     NULL, true, ncp_rec, false);
6536             ptvcursor_free(ptvc);
6537             loffset += 8;
6538             proto_item_set_end(bitem, tvb, loffset);
6539         }
6540         else
6541         {
6542             if ((request_value->req_mask_ext & 0x8000)==false) {
6543                 loffset += 8;
6544             }
6545         }
6546         /* Modification Information */
6547         if (request_value->req_mask & 0x0080) {
6548             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Modification");
6550             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6551             process_ptvc_record(ptvc, pinfo, ptvc_struct_modify_info_struct,
6552                     NULL, true, ncp_rec, false);
6553             ptvcursor_free(ptvc);
6554             loffset += 10;
6555             proto_item_set_end(bitem, tvb, loffset);
6556         }
6557         else
6558         {
6559             if ((request_value->req_mask_ext & 0x8000)==false) {
6560                 loffset += 10;
6561             }
6562         }
6563         /* Creation Information old style location */
6564         if (request_value->req_mask & 0x0100 && !ncp_newstyle) {
6565             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Creation");
6566             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6567             process_ptvc_record(ptvc, pinfo, ptvc_struct_creation_info_struct,
6568                     NULL, true, ncp_rec, false);
6569             ptvcursor_free(ptvc);
6570             loffset += 8;
6571             proto_item_set_end(bitem, tvb, loffset);
6572         }
6573         else
6574         {
6575             if ((request_value->req_mask_ext & 0x8000)==false && !ncp_newstyle) {
6576                 loffset += 8;
6577             }
6578         }
6579         /* Creation Information new style location */
6580         if (request_value->req_mask & 0x0100 && ncp_newstyle) {
6581             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Creation");
6582             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6583             process_ptvc_record(ptvc, pinfo, ptvc_struct_creation_info_struct,
6584                     NULL, true, ncp_rec, false);
6585             ptvcursor_free(ptvc);
6586             loffset += 8;
6587             proto_item_set_end(bitem, tvb, loffset);
6588         }
6589         else
6590         {
6591             if ((request_value->req_mask_ext & 0x8000)==false && ncp_newstyle) {
6592                 loffset += 8;
6593             }
6594         }
6595         /* Name Space Information */
6596         if (request_value->req_mask & 0x0200) {
6597             proto_tree_add_item(atree, hf_ncp_creator_name_space_number, tvb, loffset, 1, ENC_LITTLE_ENDIAN);
6598             loffset += 4;
6599         }
6600         else
6601         {
6602             if ((request_value->req_mask_ext & 0x8000)==false) {
6603                 loffset += 4;
6604             }
6605         }
6606         /* Directory Entry */
6607         if (request_value->req_mask & 0x0400) {
6608             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Directory Entry");
6609             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6610             process_ptvc_record(ptvc, pinfo, ptvc_struct_dir_entry_struct,
6611                     NULL, true, ncp_rec, false);
6612             ptvcursor_free(ptvc);
6613             loffset += 12;
6614             proto_item_set_end(bitem, tvb, loffset);
6615         }
6616         else
6617         {
6618             if ((request_value->req_mask_ext & 0x8000)==false) {
6619                 loffset += 12;
6620             }
6621         }
6622         /* Rights Information */
6623         if (request_value->req_mask & 0x0800) {
6624             ptvc = ptvcursor_new(pinfo->pool, atree, tvb, loffset);
6625             process_ptvc_record(ptvc, pinfo, ptvc_struct_rights_info_struct,
6626                     NULL, true, ncp_rec, false);
6627             ptvcursor_free(ptvc);
6628             loffset += 2;
6629         }
6630         else
6631         {
6632             if ((request_value->req_mask_ext & 0x8000)==false) {
6633                 loffset += 2;
6634             }
6635         }
6636         /* Return ID Information */
6637         if (request_value->req_mask & 0x1000) {
6638             proto_tree_add_item(atree, hf_ncp_curr_ref_id, tvb, loffset, 2, ENC_LITTLE_ENDIAN);
6639             loffset += 2;
6640         }
6641         /* Return Name Space Attributes Information */
6642         if (request_value->req_mask & 0x2000) {
6643             proto_tree_add_item(atree, hf_ncp_attr_def_32, tvb, loffset, 1, ENC_LITTLE_ENDIAN);
6644             loffset += 4;
6645         }
6646         /* Return Actual Information */
6647         if (request_value->req_mask & 0x4000) {
6648             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Actual");
6650             proto_tree_add_item(btree, hf_ncp_data_stream_num_long, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6651             proto_tree_add_item(btree, hf_ncp_data_stream_fat_blks, tvb, loffset+4, 4, ENC_LITTLE_ENDIAN);
6652             loffset += 8;
6653             proto_item_set_end(bitem, tvb, loffset);
6654         }
6655         /* Return Logical Information */
6656         if (request_value->req_mask & 0x8000) {
6657             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Logical");
6658             proto_tree_add_item(btree, hf_ncp_number_of_data_streams_long, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6659             number_of_items = tvb_get_letohs(tvb, loffset);
6660             loffset += 4;
6661             for (x = 1; x <= number_of_items; x++ )
6662             {
6663                 proto_tree_add_item(btree, hf_ncp_data_stream_num_long, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6664                 proto_tree_add_item(btree, hf_ncp_data_stream_size, tvb, loffset+4, 4, ENC_LITTLE_ENDIAN);
6665                 loffset += 8;
6666             }
6667             proto_item_set_end(bitem, tvb, loffset);
6668         }
6669         /* Last Update */
6670         if (request_value->req_mask_ext & 0x0001 && ncp_newstyle) {
6671             proto_tree_add_item(atree, hf_ncp_sec_rel_to_y2k, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6672             loffset += 4;
6673         }
6674         /* Dos Name */
6675         if (request_value->req_mask_ext & 0x0002 && ncp_newstyle) {
6676             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "DOS Name");
6678             if (ncp_rec->func == 0x57) {
6679                 str_length = tvb_get_uint8(tvb, loffset);
6680                 loffset += 1;
6681             }
6682             else
6683             {
6684                 str_length = tvb_get_letohs(tvb, loffset);
6685                 loffset += 2;
6686             }
6687             proto_tree_add_item(btree, hf_ncp_file_name_12, tvb, loffset, str_length, ENC_ASCII|ENC_NA);
6688             loffset += str_length;
6689             proto_item_set_end(bitem, tvb, loffset);
6690         }
6691         /* Flush Time */
6692         if (request_value->req_mask_ext & 0x0004 && ncp_newstyle) {
6693             ptvc = ptvcursor_new(pinfo->pool, atree, tvb, loffset);
6694             process_ptvc_record(ptvc, pinfo, ptvc_struct_flush_time_struct,
6695                     NULL, true, ncp_rec, false);
6696             ptvcursor_free(ptvc);
6697             loffset += 4;
6698         }
6699         /* Parental */
6700         if (request_value->req_mask_ext & 0x0008 && ncp_newstyle) {
6701             proto_tree_add_item(atree, hf_ncp_parent_base_id, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6702             loffset += 4;
6703         }
6704         /* MAC finder */
6705         if (request_value->req_mask_ext & 0x0010 && ncp_newstyle) {
6706             proto_tree_add_item(atree, hf_ncp_mac_finder_info, tvb, loffset, 32, ENC_NA);
6707             loffset += 32;
6708         }
6709         /* Sibling */
6710         if (request_value->req_mask_ext & 0x0020 && ncp_newstyle) {
6711             proto_tree_add_item(atree, hf_ncp_sibling_count, tvb, loffset, 4, ENC_LITTLE_ENDIAN);
6712             loffset += 4;
6713         }
6714         /* Effective */
6715         if (request_value->req_mask_ext & 0x0040 && ncp_newstyle) {
6716             proto_tree_add_item(atree, hf_ncp_effective_rights, tvb, loffset, 1, ENC_LITTLE_ENDIAN);
6717             loffset += 4;
6718         }
6719         /* MAC Date */
6720         if (request_value->req_mask_ext & 0x0080 && ncp_newstyle) {
6721             btree = proto_tree_add_subtree(atree, tvb, loffset, -1, ett_ncp, &bitem, "Mac Date");
6723             ptvc = ptvcursor_new(pinfo->pool, btree, tvb, loffset);
6724             process_ptvc_record(ptvc, pinfo, ptvc_struct_mac_time_struct,
6725                     NULL, true, ncp_rec, false);
6726             ptvcursor_free(ptvc);
6727             loffset += 8;
6728             proto_item_set_end(bitem, tvb, loffset);
6729         }
6730         /* Last Access */
6731         if (request_value->req_mask_ext & 0x0100 && ncp_newstyle) {
6732             ptvc = ptvcursor_new(pinfo->pool, atree, tvb, loffset);
6733             process_ptvc_record(ptvc, pinfo, ptvc_struct_last_access_time_struct,
6734                     NULL, true, ncp_rec, false);
6735             ptvcursor_free(ptvc);
6736             loffset += 2;
6737         }
6738         /* 64 bit file sizes */
6739         if (request_value->req_mask_ext & 0x0400 && ncp_newstyle) {
6740             proto_tree_add_item(atree, hf_ncp_f_size_64bit, tvb, loffset, 8, ENC_LITTLE_ENDIAN);
6741             loffset += 8;
6742         }
6743         /* We always return the file name */
6744         if (ncp_rec->func == 0x57) {
6745             str_length = tvb_get_uint8(tvb, loffset);
6746             loffset += 1;
6747         }
6748         else
6749         {
6750             str_length = tvb_get_letohs(tvb, loffset);
6751             loffset += 2;
6752         }
6753         proto_tree_add_item(atree, hf_ncp_file_name_12, tvb, loffset, str_length, ENC_UTF_8);
6754         loffset += str_length;
6756         proto_item_set_end(aitem, tvb, loffset);
6758         if(tvb_captured_length_remaining(tvb, loffset) < 4 )
6759         {
6760                 break;
6761         }
6762     }
6765 static void
6766 dissect_ncp_123_62_reply(tvbuff_t *tvb, proto_tree *volatile ncp_tree)
6768     uint8_t cmd_type;
6769     const char * param_string;
6770     int ret_len;
6772     cmd_type = tvb_get_uint8(tvb, 8+16);
6773     param_string = (const char *)tvb_get_stringz_enc(wmem_packet_scope(), tvb, 8+24, &ret_len, ENC_ASCII);
6775     switch (cmd_type) {
6776     case 0:   /* { 0x00, "Numeric Value" }, */
6777     case 2:   /* { 0x02, "Ticks Value" },   */
6778     case 4:   /* { 0x04, "Time Value" },    */
6779     case 6:   /* { 0x06, "Trigger Value" }, */
6780     case 7:   /* { 0x07, "Numeric Value" }, */
6781         proto_tree_add_item(ncp_tree, hf_srvr_param_number, tvb, 37+(int)strlen(param_string), 4, ENC_LITTLE_ENDIAN);
6782         break;
6783     case 1:   /* { 0x01, "Boolean Value" }, */
6784         proto_tree_add_item(ncp_tree, hf_srvr_param_boolean, tvb, 37+(int)strlen(param_string), 1, ENC_LITTLE_ENDIAN);
6785         break;
6786     case 5:   /* { 0x05, "String Value" },  */
6787         proto_tree_add_item(ncp_tree, hf_srvr_param_string, tvb, 37+(int)strlen(param_string), -1, ENC_ASCII|ENC_NA);
6788         break;
6789     default:
6790         break;
6791     }
6795  * Defrag logic
6797  * NDS fragment not being set to 0xffffffff indicates we are inside or at the
6798  * beginning of a fragment. But when the end of the fragment
6799  * is encounterd the flag is set to 0xffffffff. So we must mark what the
6800  * frame number is of the end fragment so that we will be
6801  * able to redissect if the user clicks on the packet
6802  * or resorts/filters the trace.
6804  * Once we are certain that we are in a fragment sequence
6805  * then we can just process each fragment in this conversation
6806  * until we reach the fragment == 0xffffffff packet.
6808  * We will be able to easily determine if a conversation is a fragment
6809  * with the exception of the last packet in the fragment. So remember
6810  * the last fragment packet number.
6812  * Also the NDS dissection requires the values of NDS Verb, Version, and Flags.
6813  * Without these values being remembered from the first request packet then
6814  * we will be unable to dissect the reply packet. For this reason we remember
6815  * these values on the first fragment and then populate the values in the final
6816  * fragment. We only do this on the first dissection.
6817  */
6818 void
6819 nds_defrag(tvbuff_t *tvb, packet_info *pinfo, uint32_t nw_connection, uint8_t sequence, uint16_t type, proto_tree *tree, struct novell_tap *ncp_tap)
6821     int                 i, frag_count=0;
6822     uint32_t            tid = 1;
6823     tvbuff_t            *frag_tvb = NULL;
6824     fragment_head       *fd_head;
6825     ncp_req_hash_value  *request_value = NULL;
6826     conversation_t      *conversation;
6827     uint32_t            nds_frag;
6829     for (i = 0; i < 99; i++) {
6830         if (!frags[i].nds_fragmented)
6831         {
6832             frags[i].nds_frag = 0xfffffff0;
6833         }
6834     }
6835     /* Check to see if defragmentation is enabeled in the dissector */
6836     if (!nds_defragment) {
6837         dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
6838         return;
6839     }
6840     /* Has this already been dissected? */
6841     if (!pinfo->fd->visited) {
6842         /* Find the conversation whence the request would have come. */
6843         conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
6844                                          CONVERSATION_NCP, nw_connection, nw_connection, 0);
6845         if (conversation != NULL) {
6846             /* find the record telling us the request made that caused
6847                this reply */
6848             request_value = ncp_hash_lookup(conversation, sequence, pinfo->num);
6849             if (!request_value) {
6850                 dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
6851                 return;
6852             }
6853             p_add_proto_data(wmem_file_scope(), pinfo, proto_ncp, 0, (void*) request_value);
6854         }
6855         /* else... we haven't seen an NCP Request for that conversation and sequence. */
6856         else
6857             {
6858                 dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
6859                 return;
6860             }
6861     }
6862     else {
6863         request_value = (ncp_req_hash_value *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ncp, 0);
6864         if (!request_value) {
6865                 dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
6866                 return;
6867         }
6868     }
6869     /* Validate that this is an NDS packet */
6870     /* If this isn't an NDS packet then just return */
6871     if (!request_value->ncp_rec ||
6872         request_value->ncp_rec->func!=104 || request_value->ncp_rec->subfunc!=2) {
6873         dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
6874         return;
6875     }
6876     /* Check to see if there is at least enough packet info to get the fragment flag */
6877     if (tvb_reported_length_remaining(tvb, 12) < 4) {
6878         dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
6879         return;
6880     }
6881     /* Get the fragment flag */
6882     nds_frag = tvb_get_letohl(tvb, 12);
6884     /* Now we need to find if this is a new fragment or already one defined. */
6885     /* We currently limit the maximum number of simultaneous fragments to 100. */
6886     for (i=0; i<100; i++)
6887     {
6888         if (frags[i].nds_frag == nds_frag || frags[i].nds_frag == 0xfffffff0)
6889         {
6890             if (frags[i].nds_frag == 0xfffffff0)
6891                 {
6892                     frags[i].nds_length = 0;
6893                     frags[i].nds_frag = nds_frag;
6894                     frags[i].nds_fragmented = true;
6895                     frags[i].sequence = 0;
6896                 }
6897             break;
6898         }
6899     }
6900     if (i > 99)
6901         return;
6903     frag_count = i;
6905     /* is this the end of an existing fragment or just another reply */
6906     if (nds_frag == 0xffffffff && request_value->nds_frag_num == 0xffffffff)
6907     {
6908         dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
6909         return;
6910     }
6912     /* Now we process the fragments */
6913     if (request_value->nds_frag || (request_value->nds_end_frag == pinfo->num))
6914     {
6915         unsigned len;
6917         /* Check to see of this is a fragment. If so then mark as a fragment. */
6918         if (frags[frag_count].nds_frag==0xffffffff) {
6919             request_value->nds_frag = false;
6920             /* nds_length of 0 means start of fragment */
6921             frags[frag_count].nds_length = 0;
6922         }
6923         else
6924         {
6925             if (frags[frag_count].nds_length == 0)
6926             {
6927                 frags[frag_count].nds_length = tvb_get_letohl(tvb, 0);
6928             }
6929         }
6930         /*
6931          * Fragment
6932          *
6933          */
6934         tid = (pinfo->srcport+pinfo->destport);
6935         len = tvb_reported_length(tvb);
6936         if (len > 0 && tvb_bytes_exist(tvb, 0, len))
6937         {
6938             if (frags[frag_count].nds_length > len)
6939             {
6940                 /* This is the first fragment so remember the verb, version, and flags. */
6941                 frags[frag_count].nds_frag_verb = request_value->nds_request_verb;
6942                 frags[frag_count].nds_frag_version = request_value->nds_version;
6943                 frags[frag_count].nds_frag_flags = request_value->req_nds_flags;
6944                 frags[frag_count].nds_frag_prot_flags = request_value->req_nds_prot_flags;
6945                 fd_head = fragment_add_seq_next(&nds_reassembly_table, tvb, 0, pinfo, tid, NULL, len, request_value->nds_frag);
6946                 frags[frag_count].sequence = sequence;
6947                 frags[frag_count].nds_length = 1;
6948             }
6949             else
6950             {
6951                 /* Subsequent fragments should be offset by 16 since we do not need */
6952                 /* the additional fragment handle and size fields in our composite data */
6953                 /* Also do not add retransmitted packets, just mark and return */
6954                 if (!pinfo->fd->visited)
6955                 {
6956                     if (sequence != frags[frag_count].sequence) {
6957                         fd_head = fragment_add_seq_next(&nds_reassembly_table, tvb, 16, pinfo, tid, NULL, len-16, request_value->nds_frag);
6958                         frags[frag_count].sequence = sequence;
6959                     }
6960                     else
6961                     {
6962                         col_add_fstr(pinfo->cinfo, COL_INFO, "[Retransmitted NDS Fragment 0x%08x]", frags[frag_count].nds_frag);
6963                         return;
6964                     }
6965                 }
6966                 else
6967                 {
6968                     fd_head = fragment_add_seq_next(&nds_reassembly_table, tvb, 16, pinfo, tid, NULL, len-16, request_value->nds_frag);
6969                     frags[frag_count].sequence = sequence;
6970                 }
6971             }
6972             if (fd_head != NULL)
6973             {
6974                 /* Is this the last fragment? nds_frag will indicate */
6975                 if (fd_head->next != NULL && !request_value->nds_frag)
6976                 {
6977                     frag_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
6978                     add_new_data_source(pinfo,
6979                                         frag_tvb,
6980                                         "Reassembled NDS");
6981                     /* Show all fragments. */
6982                     if (tree)
6983                     {
6984                         proto_item *frag_tree_item;
6985                         show_fragment_seq_tree(fd_head,
6986                                                &nds_frag_items,
6987                                                tree, pinfo,
6988                                                frag_tvb, &frag_tree_item);
6989                         tid++;
6990                     }
6992                     if (!pinfo->fd->visited)
6993                     {
6994                         /* Now we need to find the original fragment number. */
6995                         /* Get the fragment flag */
6996                         nds_frag = tvb_get_letohl(frag_tvb, 12);
6997                         for (i=0; i<100; i++)
6998                         {
6999                             if (frags[i].nds_frag == nds_frag)
7000                             {
7001                                 break;
7002                             }
7003                         }
7004                         if (i > 99)
7005                             return;
7006                         if (frags[i].nds_frag == 0xffffffff)
7007                         {
7008                             /* Error can't find fragment */
7009                             /*DISSECTOR_ASSERT(0);*/
7010                         }
7011                         frag_count = i;
7012                         /* Remember this fragment information so we can dissect.
7013                          * Only do this on the first dissection. After the first
7014                          * dissection we will just read the memory values.
7015                          */
7016                         request_value->nds_end_frag = pinfo->num;
7017                         request_value->nds_request_verb = frags[frag_count].nds_frag_verb;
7018                         request_value->nds_version = frags[frag_count].nds_frag_version;
7019                         request_value->req_nds_flags = frags[frag_count].nds_frag_flags;
7020                         request_value->req_nds_prot_flags = frags[frag_count].nds_frag_prot_flags;
7021                     }
7023                 }
7024                 else
7025                 {
7026                     /* This is either a beginning or middle fragment on second dissection */
7027                     frag_tvb = tvb_new_subset_remaining(tvb, 0);
7028                     if (request_value->nds_frag)
7029                     {
7030                       col_add_fstr(pinfo->cinfo, COL_INFO, "[NDS Fragment 0x%08x]", frags[frag_count].nds_frag);
7031                     }
7032                 }
7033             }
7034             else
7035             {
7036                 /* Fragment from first pass of dissection */
7037                 if (request_value->nds_frag)
7038                 {
7039                    col_add_fstr(pinfo->cinfo, COL_INFO, "[NDS Fragment 0x%08x]", frags[frag_count].nds_frag);
7040                 }
7042                 frag_tvb = NULL;
7043             }
7044         }
7045         else
7046         {
7047             /*
7048              * There are no bytes so Dissect this
7049              */
7050             frag_tvb = tvb_new_subset_remaining(tvb, 0);
7051         }
7052         if (frag_tvb == NULL)
7053         {
7054             /* This is a fragment packet */
7055             frag_tvb = tvb_new_subset_remaining(tvb, 0);
7056             nds_data_handle = find_dissector("data");
7057             call_dissector(nds_data_handle, frag_tvb, pinfo, tree);
7058         }
7059         else
7060         {
7061             /* This is the end fragment so dissect */
7062             if (!request_value->nds_frag) {
7063                 frags[frag_count].nds_length = 0;
7064                 dissect_ncp_reply(frag_tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
7065             }
7066         }
7067     }
7068     else
7069     {
7070         /* This is not any fragment packet */
7071         request_value->nds_frag = false;
7072         /* Trap for retransmitted end fragment */
7073         if (request_value->nds_end_frag < pinfo->num) {
7074             col_add_fstr(pinfo->cinfo, COL_INFO, "[Retransmitted end of NDS Fragment 0x%08x, see packet #%d for details.]", request_value->nds_frag_num, request_value->nds_end_frag);
7075         }
7076         else
7077         {
7078             dissect_ncp_reply(tvb, pinfo, nw_connection, sequence, type, tree, ncp_tap);
7079         }
7080     }
7083 static bool ncp2222_dfilters_compiled;
7085 static void
7086 ncp2222_compile_dfilters(void)
7088     int i;
7089     df_error_t *df_err;
7091     for (i = 0; i < NUM_REQ_CONDS; i++) {
7092         if (!dfilter_compile((const char*)req_conds[i].dfilter_text,
7093                              &req_conds[i].dfilter, &df_err)) {
7094             g_error("NCP dissector failed to compile dfilter \"%s\": %s\n",
7095                       req_conds[i].dfilter_text, df_err->msg);
7096             df_error_free(&df_err);
7097             ws_assert_not_reached();
7098         }
7099     }
7102 void
7103 dissect_ncp_request(tvbuff_t *tvb, packet_info *pinfo,
7104                 uint32_t nw_connection, uint8_t sequence,
7105                 uint16_t type, bool is_lip_echo_allocate_slot,
7106                 proto_tree *volatile ncp_tree)
7108     volatile uint8_t        func=0;
7109     volatile uint8_t        subfunc = 0;
7110     bool                    requires_subfunc = false;
7111     bool                    has_length = false;
7112     ncp_req_hash_value      *volatile request_value = NULL;
7113     const ncp_record        *volatile ncp_rec = NULL;
7114     conversation_t          *conversation;
7115     ptvcursor_t             *volatile ptvc = NULL;
7116     proto_tree              *temp_tree = NULL;
7117     volatile bool           run_req_cond = false;
7118     volatile unsigned long  exception_code;
7119     const char              *volatile message;
7120     proto_item              *ti;
7123     /* We're dissecting an ncp2222 request; Compile the dfilters (if not yet done). */
7124     /* XXX: We do this here rather than at "post-registration" (as previouly done)  */
7125     /*      so compiling over 100 dfilters is done only if needed (thus avoiding    */
7126     /*      compiling the dfilters each time Wireshark is started.                  */
7127     if (! ncp2222_dfilters_compiled) {
7128         ncp2222_compile_dfilters();
7129         ncp2222_dfilters_compiled = true;
7130     }
7132     /* Determine which ncp_record to use. */
7133     switch (type) {
7134     case NCP_ALLOCATE_SLOT:
7135         if (is_lip_echo_allocate_slot) {
7136             ncp_rec = &ncplip_echo;
7137         } else {
7138             ncp_rec = &ncp1111_request;
7139             if (ncp_echo_conn) {
7140                 expert_add_info(pinfo, NULL, &ei_ncp_connection_request);
7141             }
7142         }
7143         break;
7144     case NCP_SERVICE_REQUEST:
7145         func = tvb_get_uint8(tvb, 6);
7146         requires_subfunc = ncp_requires_subfunc(func);
7147         has_length = ncp_has_length_parameter(func);
7148         if (requires_subfunc) {
7149             if (has_length) {
7150                 subfunc = tvb_get_uint8(tvb, 9);
7151             }
7152             else {
7153                 subfunc = tvb_get_uint8(tvb, 7);
7154             }
7155         }
7156         ncp_rec = ncp_record_find(func, subfunc);
7157         break;
7158     case NCP_DEALLOCATE_SLOT:
7159         ncp_rec = &ncp5555_request;
7160         if (ncp_echo_conn) {
7161             expert_add_info_format(pinfo, NULL, &ei_ncp_destroy_connection, "Destroy Connection %u Request", nw_connection);
7162         }
7163         break;
7164     case NCP_BROADCAST_SLOT:
7165         ncp_rec = &ncpbbbb_request;
7166         break;
7167     case NCP_LIP_ECHO:
7168         ncp_rec = &ncplip_echo;
7169         break;
7170     default:
7171         ncp_rec = NULL;
7172         break;
7173     }
7175     /* Fill in the INFO column. */
7176     if (ncp_rec) {
7177         col_add_fstr(pinfo->cinfo, COL_INFO, "C %s", ncp_rec->name);
7178     }
7179     else {
7180         if (requires_subfunc) {
7181             col_add_fstr(pinfo->cinfo, COL_INFO,
7182                             "C Unknown Function %u %u (0x%02X/0x%02x)",
7183                             func, subfunc, func, subfunc);
7184             return;
7185         }
7186         else {
7187             col_add_fstr(pinfo->cinfo, COL_INFO,
7188                             "C Unknown Function %u (0x%02x)",
7189                             func, func);
7190             return;
7191         }
7192     }
7194     if (!pinfo->fd->visited) {
7195         /* This is the first time we've looked at this packet.
7196            Keep track of the address and connection whence the request
7197            came, and the address and connection to which the request
7198            is being sent, so that we can match up calls with replies.
7199            (We don't include the sequence number, as we may want
7200            to have all packets over the same connection treated
7201            as being part of a single conversation so that we can
7202            let the user select that conversation to be displayed.) */
7203         conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
7204                                          CONVERSATION_NCP, nw_connection, nw_connection, 0);
7206         if (conversation == NULL) {
7207             /* It's not part of any conversation - create a new one. */
7208             conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst,
7209                                             CONVERSATION_NCP, nw_connection, nw_connection, 0);
7210         }
7211         request_value = ncp_hash_insert(conversation, sequence, ncp_rec, pinfo->num);
7212         request_value->req_frame_num = pinfo->num;
7213         request_value->req_frame_time = pinfo->abs_ts;
7215         /* If this is the first time we're examining the packet,
7216          * check to see if this NCP type uses a "request condition".
7217          * If so, we have to build a proto_tree because request conditions
7218          * use display filters to work, and without a proto_tree,
7219          * display filters can't possibly work. */
7220         if (ncp_rec) {
7221             if (ncp_rec->req_cond_indexes) {
7222                 run_req_cond = true;
7223             }
7224         }
7225     }
7227     /* If we have to handle a request condition, or have to
7228        add to the Info column, we need to construct a protocol
7229        tree.  If we already have a proto_tree, then wonderful.
7230        If we don't, we need to build one. */
7231     if (run_req_cond && !ncp_tree) {
7232         temp_tree = proto_tree_create_root(pinfo);
7233         proto_tree_set_visible(temp_tree, false);
7234         ti = proto_tree_add_item(temp_tree, proto_ncp, tvb, 0, -1, ENC_NA);
7235         ncp_tree = proto_item_add_subtree(ti, ett_ncp);
7236     }
7238     if (ncp_tree) {
7239         /* If the dissection throws an exception, be sure to free
7240          * the temporary proto_tree that was created. Because of the
7241          * way the CLEANUP_PUSH macro works, we can't put it in an 'if'
7242          * block; it has to be in the same scope as the terminating
7243          * CLEANUP_POP or CLEANUP_POP_AND_ALLOC. So, we always
7244          * call CLEANUP_POP and friends, but the value of temp_tree is
7245          * NULL if no cleanup is needed, and non-null if cleanup is needed. */
7246         CLEANUP_PUSH_PFX(xx,free_proto_tree, temp_tree);
7248 #ifdef FAKE_TREE_IS_VISIBLE
7249         PTREE_DATA(ncp_tree)->visible=1;
7250 #endif
7252         /* Before the dissection, if we're saving data for a request
7253          * condition, we have to prime the proto tree using the
7254          * dfilter information */
7255         if (run_req_cond) {
7256             const int *needed;
7257             dfilter_t *dfilter;
7259             needed = ncp_rec->req_cond_indexes;
7261             while (*needed != -1) {
7262                 dfilter = req_conds[*needed].dfilter;
7263                 /* Prime the proto_tree with "interesting fields". */
7264                 dfilter_prime_proto_tree(dfilter, ncp_tree);
7265                 needed++;
7266             }
7267         }
7269         switch (type) {
7270         case NCP_BROADCAST_SLOT:
7271             ; /* nothing */
7272             break;
7274         case NCP_SERVICE_REQUEST:
7275             proto_tree_add_uint_format_value(ncp_tree, hf_ncp_func, tvb, 6, 1,
7276                                        func, "%u (0x%02X), %s",
7277                                        func, func, ncp_rec ? ncp_rec->name : "Unknown");
7278             break;
7280         default:
7281             ; /* nothing */
7282             break;
7283         }
7284         if (request_value) {
7285             request_value->length = 0;
7286         }
7287         if (requires_subfunc) {
7288             if (has_length) {
7289                 if (request_value && func==123) {
7290                     request_value->length = tvb_get_ntohs(tvb, 7);
7291                 }
7292                 proto_tree_add_item(ncp_tree, hf_ncp_length, tvb, 7,
7293                                     2, ENC_BIG_ENDIAN);
7294                 proto_tree_add_uint(ncp_tree, hf_ncp_subfunc, tvb, 9, 1, subfunc);
7295                 ptvc = ptvcursor_new(pinfo->pool, ncp_tree, tvb, 10);
7296             }
7297             else {
7298                 proto_tree_add_uint(ncp_tree, hf_ncp_subfunc, tvb, 7, 1, subfunc);
7299                 ptvc = ptvcursor_new(pinfo->pool, ncp_tree, tvb, 8);
7300             }
7301         }
7302         else {
7303             ptvc = ptvcursor_new(pinfo->pool, ncp_tree, tvb, 7);
7304         }
7306         /* The group is not part of the packet, but it's useful
7307          * information to display anyway. Put it in the tree for filtering and tap use*/
7308         if (ncp_rec) {
7309             ti = proto_tree_add_uint_format_value(ncp_tree, hf_ncp_group, tvb, 0, 0, ncp_rec->group, "%s", ncp_groups[ncp_rec->group]);
7310             proto_item_set_generated(ti);
7311         }
7313         exception_code = 0;
7314         message = NULL;
7315         if (ncp_rec && ncp_rec->request_ptvc) {
7316             clear_repeat_vars();
7317             /*
7318              * We need to remember the results even if we
7319              * throw an exception dissecting this request,
7320              * so that we can properly dissect the reply.
7321              * We catch any exceptions thrown when
7322              * dissecting the request, and re-throw them
7323              * after saving the results of any conditional
7324              * tests.
7325              */
7326             TRY {
7327                 process_ptvc_record(ptvc, pinfo, ncp_rec->request_ptvc, NULL, true, ncp_rec, true);
7328             } CATCH_ALL {
7329                 exception_code = EXCEPT_CODE;
7330                 message = GET_MESSAGE;
7331             }
7332             ENDTRY;
7333         }
7334         ptvcursor_free(ptvc);
7336         /* Now that the dissection is done, do we need to run
7337          * some display filters on the resulting tree in order
7338          * to save results for "request conditions" ? */
7339         if (run_req_cond) {
7340             const int   *needed;
7341             bool        *results;
7342             dfilter_t   *dfilter;
7344             results = (bool *)wmem_alloc0(wmem_file_scope(), sizeof(bool)*NUM_REQ_CONDS);
7345             needed = ncp_rec->req_cond_indexes;
7347             while (*needed != -1) {
7348                 /* ncp_tree is not a root proto_tree, but
7349                  * dfilters will still work on it. */
7350                 dfilter = req_conds[*needed].dfilter;
7351                 results[*needed] = dfilter_apply(dfilter, ncp_tree);
7352                 needed++;
7353             }
7355             /* Save the results so the reply packet dissection
7356              * get to them. */
7357             request_value->req_cond_results = results;
7358         }
7360         if (!request_value)
7361         {
7362              conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
7363                                                  CONVERSATION_NCP, nw_connection, nw_connection, 0);
7364              if (conversation != NULL) {
7365                  /* find the record telling us the request made that caused
7366                     this reply */
7367                  request_value = ncp_hash_lookup(conversation, sequence, pinfo->num);
7368               }
7369         }
7370         /* SecretStore packets are dessected in packet-ncp-sss.c */
7371         if (func == 0x5c && ncp_tree) {
7372             dissect_sss_request(tvb, pinfo, ncp_tree, request_value);
7373         }
7374         /* NMAS packets are dessected in packet-ncp-nmas.c */
7375         if (func == 0x5e && ncp_tree) {
7376             dissect_nmas_request(tvb, pinfo, ncp_tree, request_value);
7377         }
7379         /* Store NCP request specific flags for manual dissection */
7380         if ((func == 0x57 || func == 0x59) && subfunc == 0x14 && ncp_tree && request_value) {
7381             request_value->req_mask = tvb_get_letohs(tvb, 8+4);
7382             request_value->req_mask_ext = tvb_get_letohs(tvb, 8+6);
7383         }
7384         /* NCP function 89/6 passes either ASCII or UTF8 data */
7385         /* Decode manually since it is not possible to SREC the request */
7386         /* packets from the python code */
7387         if (func == 0x59 && subfunc == 0x6) {
7388             dissect_ncp_89_6_request(tvb, ncp_tree, 22);
7389         }
7390         /*
7391          * Need to parse for Novell specific wildcard values in Search
7392          * Pattern, decode this ncp (89)/20 and (89)/03 req manually here.
7393          *
7394          * XXX - do 0x57/87 and 0x59/89 both have this?  87 doesn't
7395          * appear to have the ASCII/UTF-8 data type field.
7396          */
7397         if (ncp_rec->func == 0x59 && (ncp_rec->subfunc == 0x14 || ncp_rec->subfunc == 0x03)) {
7398             if (ncp_rec->subfunc == 0x03)
7399             {
7400                  dissect_ncp_8x20req(tvb, ncp_tree, 26, ncp_rec->func);
7401             }
7402 /*if (ncp_rec->func == 0x57)
7404             dissect_ncp_8x20req(tvb, ncp_tree, 27, ncp_rec->func);
7406             else
7407             {
7408                 dissect_ncp_8x20req(tvb, ncp_tree, 28, ncp_rec->func);
7409             }
7410         }
7411         /* Free the temporary proto_tree */
7412         CLEANUP_CALL_AND_POP_PFX(xx);
7414         /* Re-throw any exception. */
7415         if (exception_code != 0)
7416             THROW_MESSAGE(exception_code, message);
7417     }
7420 static void
7421 dissect_nds_ping_reply(tvbuff_t *tvb, packet_info *pinfo _U_,
7422                        proto_tree *ncp_tree, ncp_req_hash_value *request_value)
7424     uint8_t    ping_version;
7425     uint32_t   nds_string_len;
7426     uint32_t   nds_offset;
7427     uint32_t   bvalue;
7428     uint32_t   nds_flags;
7429     int        i;
7430     nstime_t   ns;
7432     ping_version = tvb_get_uint8(tvb, 8);
7433     proto_tree_add_item(ncp_tree, hf_ping_version, tvb, 8, 1, ENC_NA);
7434     if (ping_version == 9) {
7435         nds_string_len = tvb_get_ntohl(tvb, 9);
7436         nds_offset = nds_string_len+16;
7437         proto_tree_add_item(ncp_tree, hf_nds_tree_name, tvb, 16, nds_string_len, ENC_ASCII|ENC_NA);
7438         proto_tree_add_item(ncp_tree, hf_nds_reply_depth, tvb, nds_offset, 4, ENC_BIG_ENDIAN);
7439         proto_tree_add_item(ncp_tree, hf_nds_reply_rev, tvb, (nds_offset+4), 4, ENC_BIG_ENDIAN);
7440         proto_tree_add_item(ncp_tree, hf_nds_reply_flags, tvb, (nds_offset+8), 4, ENC_LITTLE_ENDIAN);
7441     }
7442     else {
7443         nds_offset = 12;
7444         nds_flags = request_value->req_nds_flags;
7445         bvalue = 0x00000001;
7447         for (i = 0 ; i < 32; i++ ) {
7448             if (nds_flags & bvalue)
7449             {
7450                 switch(bvalue)
7451                 {
7452                 case 0x00000001:   /* Supported Fields */
7453                     proto_tree_add_bitmask(ncp_tree, tvb, nds_offset, hf_pingflags1, ett_ncp, ncp_pingflags1, ENC_LITTLE_ENDIAN);
7454                     nds_offset += 2;
7455                     proto_tree_add_bitmask(ncp_tree, tvb, nds_offset, hf_pingflags2, ett_ncp, ncp_pingflags2, ENC_LITTLE_ENDIAN);
7456                     nds_offset += 2;
7457                     break;
7458                 case 0x00000002:
7459                     proto_tree_add_item(ncp_tree, hf_nds_reply_depth, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7460                     nds_offset += 4;
7461                     break;
7462                 case 0x00000004:
7463                     proto_tree_add_item(ncp_tree, hf_nds_reply_rev, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7464                     nds_offset += 4;
7465                     break;
7466                 case 0x00000008:
7467                     proto_tree_add_bitmask(ncp_tree, tvb, nds_offset, hf_pingpflags1, ett_ncp, ncp_pingpflags1, ENC_LITTLE_ENDIAN);
7468                     nds_offset += 4;
7469                     break;
7470                 case 0x00000010:
7471                     proto_tree_add_bitmask(ncp_tree, tvb, nds_offset, hf_pingvflags1, ett_ncp, ncp_pingvflags1, ENC_LITTLE_ENDIAN);
7472                     nds_offset += 4;
7473                     break;
7474                 case 0x00000020:
7475                     proto_tree_add_item(ncp_tree, hf_nds_letter_ver, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7476                     nds_offset += 4;
7477                     break;
7478                 case 0x00000040:
7479                     proto_tree_add_item(ncp_tree, hf_nds_os_majver, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7480                     nds_offset += 4;
7481                     proto_tree_add_item(ncp_tree, hf_nds_os_minver, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7482                     nds_offset += 4;
7483                     proto_tree_add_item(ncp_tree, hf_ncp_os_revision, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7484                     nds_offset += 4;
7485                     break;
7486                 case 0x00000100:
7487                     proto_tree_add_item(ncp_tree, hf_nds_lic_flags, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7488                     nds_offset += 4;
7489                     break;
7490                 case 0x00000200:
7491                     ns.secs = tvb_get_letohl(tvb, nds_offset);
7492                     ns.nsecs = 0;
7493                     proto_tree_add_time(ncp_tree, hf_nds_ds_time, tvb, nds_offset, 4, &ns);
7494                     nds_offset += 4;
7495                     break;
7496                 case 0x00000400:
7497                     ns.secs = tvb_get_letohl(tvb, nds_offset);
7498                     ns.nsecs = 0;
7499                     proto_tree_add_time(ncp_tree, hf_nds_svr_time, tvb, nds_offset, 4, &ns);
7500                     nds_offset += 4;
7501                     break;
7502                 case 0x00000800:
7503                     ns.secs = tvb_get_letohl(tvb, nds_offset);
7504                     ns.nsecs = 0;
7505                     proto_tree_add_time(ncp_tree, hf_nds_crt_time, tvb, nds_offset, 4, &ns);
7506                     nds_offset += 4;
7507                     break;
7508                 case 0x00010000:
7509                     if(tvb_get_uint8(tvb, nds_offset) == 0x00)
7510                     {
7511                         nds_offset += 2;
7512                     }
7513                     nds_string_len = tvb_get_letohl(tvb, nds_offset);
7514                     nds_offset += 4;
7515                     proto_tree_add_item(ncp_tree, hf_sap_name, tvb, nds_offset, nds_string_len, ENC_ASCII|ENC_NA);
7516                     nds_offset += nds_string_len;
7517                     nds_offset += align_4(tvb, nds_offset);
7518                     break;
7519                 case 0x00020000:
7520                     if(tvb_get_uint8(tvb, nds_offset) == 0x00)
7521                     {
7522                         nds_offset += 2;
7523                     }
7524                     nds_string_len = tvb_get_letohl(tvb, nds_offset);
7525                     nds_offset += 4;
7526                     proto_tree_add_item(ncp_tree, hf_nds_tree_name, tvb, nds_offset, nds_string_len, ENC_ASCII|ENC_NA);
7527                     nds_offset += nds_string_len;
7528                     nds_offset += align_4(tvb, nds_offset);
7529                     break;
7530                 case 0x00040000:
7531                     if(tvb_get_uint8(tvb, nds_offset) == 0x00)
7532                     {
7533                         nds_offset += 2;
7534                     }
7535                     nds_string_len = tvb_get_letohl(tvb, nds_offset);
7536                     nds_offset += 4;
7537                     proto_tree_add_item(ncp_tree, hf_os_name, tvb, nds_offset, nds_string_len, ENC_ASCII|ENC_NA);
7538                     nds_offset += nds_string_len;
7539                     nds_offset += align_4(tvb, nds_offset);
7540                     break;
7541                 case 0x00080000:
7542                     if(tvb_get_uint8(tvb, nds_offset) == 0x00)
7543                     {
7544                         nds_offset += 2;
7545                     }
7546                     nds_string_len = tvb_get_letohl(tvb, nds_offset);
7547                     nds_offset += 4;
7548                     proto_tree_add_item(ncp_tree, hf_hardware_name, tvb, nds_offset, nds_string_len, ENC_ASCII|ENC_NA);
7549                     nds_offset += nds_string_len;
7550                     nds_offset += align_4(tvb, nds_offset);
7551                     break;
7552                 case 0x00100000:
7553                     if(tvb_get_uint8(tvb, nds_offset) == 0x00)
7554                     {
7555                         nds_offset += 2;
7556                     }
7557                     nds_string_len = tvb_get_letohl(tvb, nds_offset);
7558                     nds_offset += 4;
7559                     proto_tree_add_item(ncp_tree, hf_vendor_name, tvb, nds_offset, nds_string_len, ENC_ASCII|ENC_NA);
7560                     nds_offset += nds_string_len;
7561                     nds_offset += align_4(tvb, nds_offset);
7562                     break;
7563                 default:
7564                     break;
7565                 }
7566             }
7567             bvalue = bvalue*2;
7568         }
7569     }
7572 static void
7573 dissect_nds_reply(tvbuff_t *tvb, packet_info *pinfo,
7574                   proto_tree *ncp_tree, uint32_t nds_error_code,
7575                   const char *nds_error_string, ncp_req_hash_value *request_value,
7576                   conversation_t *conversation)
7578     uint32_t                        nds_offset;
7579     proto_item                      *expert_item;
7580     const char                      *verb_string;
7581     bool                            resolve_eid=false;
7582     uint32_t                        global_eid=0;
7583     bool                            add_eid = false;
7584     char                            *global_object_name = NULL;
7585     ncp_req_eid_hash_value          *request_eid_value = NULL;
7586     nds_val                         temp_value;
7587     uint32_t                        class_def_type_val;
7589     nds_offset = 8;
7591     proto_tree_add_item(ncp_tree, hf_ncp_fragment_size, tvb, nds_offset,
7592                         4, ENC_LITTLE_ENDIAN);
7593     nds_offset += 4;
7594     proto_tree_add_item(ncp_tree, hf_ncp_fragment_handle, tvb, nds_offset,
7595                         4, ENC_LITTLE_ENDIAN);
7596     nds_offset += 4;
7597     /*
7598      * Is the possibly-reassembled reply large enough to have a completion
7599      * code?  (We can't check the fragment size as this might just be the
7600      * last fragment.)
7601      */
7602     if (tvb_reported_length_remaining(tvb, nds_offset) >= 4)
7603     {
7604         /* Yes - process the completion code. */
7605         expert_item = proto_tree_add_uint_format(ncp_tree, hf_nds_reply_error, tvb, nds_offset,
7606                                                  4, nds_error_code, "NDS Completion Code: 0x%08x, %s",
7607                                                  nds_error_code, nds_error_string);
7609         if (nds_error_code != 0 && ncp_echo_err) {
7610             expert_add_info_format(pinfo, expert_item, &ei_nds_reply_error, "NDS Error: 0x%08x %s", nds_error_code, nds_error_string);
7611         }
7612     }
7614     if ((request_value == NULL) || (nds_error_code != 0))
7615         return;
7617     nds_offset = 20;
7618     verb_string = val_to_str_const(request_value->nds_request_verb,
7619                                     ncp_nds_verb_vals, "Continuation Fragment");
7620     if(request_value->req_nds_prot_flags & 0x4000)
7621     {
7622         /* CRC is included in the NDS header so justify the offset */
7623         proto_tree_add_item(ncp_tree, hf_nds_crc, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7624         nds_offset += 4;
7625     }
7627     if(request_value->nds_request_verb != 0)
7628     {
7629         proto_tree_add_uint_format_value(ncp_tree,
7630                                     hf_ncp_nds_verb, tvb, 6, 0,
7631                                     request_value->nds_request_verb,
7632                                     "%d, %s",
7633                                     request_value->nds_request_verb, verb_string);
7634     }
7636     memset(&temp_value, 0, sizeof(temp_value));
7637     switch (request_value->nds_request_verb)
7638     {
7639     case 0x01:
7640         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_tag_string, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN, &temp_value.vvalue);
7641         nds_offset += 4;
7643         switch(temp_value.vvalue)
7644         {
7645         case NDS_TAG_NO_SUCH_ENTRY:
7646             break;
7647         case NDS_TAG_LOCAL_ENTRY:
7648             proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN, &global_eid);
7649             add_eid = true;
7650             resolve_eid = true;
7651             global_object_name = request_value->object_name;
7652             nds_offset += 4;
7654             temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7655             temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7656             temp_value.vdesc = "Referral Records: %u";
7657             temp_value.vlength = 4;
7658             temp_value.voffset = nds_offset;
7659             temp_value.hfname = hf_nds_referrals;
7660             temp_value.mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
7661             process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7662             break;
7663         case NDS_TAG_REMOTE_ENTRY:
7664             nds_offset += 4;   /* UINT32 reserved field */
7665             proto_tree_add_item(ncp_tree, hf_nds_eid, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7666             nds_offset += 4;
7667             temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7668             temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7669             temp_value.vdesc = "Referral Records: %u";
7670             temp_value.vlength = 4;
7671             temp_value.voffset = nds_offset;
7672             temp_value.hfname = hf_nds_referrals;
7673             temp_value.mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
7674             process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7675             break;
7676         case NDS_TAG_ALIAS_ENTRY:
7677             temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7678             if (temp_value.vvalue == 0x00)
7679                 break;
7681             temp_value.vstring =(const char*)tvb_get_string_enc(pinfo->pool, tvb, nds_offset+4, temp_value.vvalue, ENC_UTF_16|ENC_LITTLE_ENDIAN);
7682             proto_tree_add_string_format(ncp_tree, hf_nds_name, tvb, nds_offset, 4+temp_value.vvalue, temp_value.vstring, "Alias Name: %s", temp_value.vstring);
7683             break;
7684         case NDS_TAG_REFERRAL_INFORMATION:
7685             temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7686             proto_tree_add_uint_format(ncp_tree, hf_nds_eid, tvb, nds_offset, 4, temp_value.vvalue, "Distance Object is From Root: 0x%08x", temp_value.vvalue);
7687             nds_offset += 4;
7689             temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7690             temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7691             temp_value.vdesc = "Referral Records: %u";
7692             temp_value.vlength = 4;
7693             temp_value.voffset = nds_offset;
7694             temp_value.hfname = hf_nds_referrals;
7695             temp_value.mvtype = MVTYPE_ADDR_REFERRAL_REPLY;
7696             process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7697             break;
7698         case NDS_TAG_ENTRY_AND_REFERRALS:
7699             proto_tree_add_item(ncp_tree, hf_nds_result_flags, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7700             nds_offset += 4;
7701             proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN, &global_eid);
7702             add_eid = true;
7703             resolve_eid = true;
7704             global_object_name = request_value->object_name;
7705             nds_offset += 4;
7707             temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7708             temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7709             temp_value.vdesc = "Referral Records: %u";
7710             temp_value.vlength = 4;
7711             temp_value.voffset = nds_offset;
7712             temp_value.hfname = hf_nds_referrals;
7713             temp_value.mvtype = MVTYPE_ADDR_REFERRAL_REPLY;
7714             process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7715             break;
7716         default:
7717             break;
7718         }
7719         break;
7720     case 0x02:
7721         nds_offset -= 4;
7722         temp_value.vvalue = 1;
7723         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7724         temp_value.vdesc = "Entry Information";
7725         temp_value.vlength = 0;
7726         temp_value.voffset = nds_offset;
7727         temp_value.hfname = hf_nds_name;
7728         temp_value.mvtype = MVTYPE_LIST_PARTITIONS;
7729         temp_value.vflags = request_value->req_nds_flags;
7730         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7731         break;
7732     case 0x03:
7733         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7734         nds_offset += 4;
7735         proto_tree_add_item(ncp_tree, hf_nds_info_type, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7736         nds_offset += 4;
7738         temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7739         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7740         temp_value.vdesc = "Number of Attributes: %u";
7741         temp_value.vlength = 4;
7742         temp_value.voffset = nds_offset;
7743         temp_value.hfname = hf_nds_attr;
7744         temp_value.mvtype = MVTYPE_ATTR_REPLY;
7745         temp_value.vflags = request_value->req_nds_flags;
7746         temp_value.nds_version = request_value->nds_version;
7747         temp_value.pflags = request_value->req_nds_prot_flags;
7748         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7749         break;
7750     case 0x04:
7751         temp_value.vvalue = tvb_get_uint8(tvb, nds_offset);
7752         if (temp_value.vvalue == 0)
7753         {
7754             proto_tree_add_uint_format_value(ncp_tree, hf_nds_compare_results, tvb, nds_offset, 1, temp_value.vvalue, "Did Not Match");
7755         }
7756         else
7757         {
7758             proto_tree_add_uint_format_value(ncp_tree, hf_nds_compare_results, tvb, nds_offset, 1, temp_value.vvalue, "Matched");
7759         }
7760         break;
7761     case 0x05:
7762         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7763         nds_offset += 4;
7765         temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7766         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7767         temp_value.vdesc = "Entry Information";
7768         temp_value.vlength = 0;
7769         temp_value.voffset = nds_offset;
7770         temp_value.hfname = hf_nds_name;
7771         temp_value.mvtype = MVTYPE_LIST_PARTITIONS;
7772         temp_value.vflags = request_value->req_nds_flags;
7773         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7774         break;
7775     case 0x06:
7776     case 0x07:
7777     case 0x08:
7778     case 0x09:
7779     case 0x0a:
7780     case 0x0b:
7781     case 0x0c:
7782     case 0x0d:
7783     case 0x0e:
7784         break;
7785     case 0x0f:
7786         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7787         nds_offset += 4;
7788         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_class_def_type, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN, &class_def_type_val);
7789         nds_offset += 4;
7791         temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7792         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7793         temp_value.vdesc = "Class Definitions %u";
7794         temp_value.vlength = 0;
7795         temp_value.voffset = nds_offset;
7796         temp_value.hfname = hf_nds_classes;
7797         temp_value.mvtype = MVTYPE_CLASS_NAMES;
7798         temp_value.vflags = class_def_type_val;
7799         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7800         break;
7801     case 0x10:
7802     case 0x11:
7803         break;
7804     case 0x12:
7805         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7806         nds_offset += 4;
7808         temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7809         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7810         temp_value.vdesc = "Classes: %u";
7811         temp_value.vlength = 4;
7812         temp_value.voffset = nds_offset;
7813         temp_value.mvtype = MVTYPE_READ_CLASS_REQ;
7814         temp_value.hfname= hf_nds_classes;
7815         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7816         break;
7817     case 0x13:
7818         proto_tree_add_item(ncp_tree, hf_nds_privileges, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7819         break;
7820     case 0x14:
7821     case 0x15:
7822         break;
7823     case 0x16:
7824         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7825         nds_offset += 4;
7827         temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7828         if (temp_value.vvalue == 0)
7829             break;
7831         temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, nds_offset+4, temp_value.vvalue, ENC_UTF_16|ENC_LITTLE_ENDIAN);
7832         proto_tree_add_string_format(ncp_tree, hf_nds_name, tvb, nds_offset, 4+temp_value.vvalue, temp_value.vstring, "Server Distinguished Name: %s", temp_value.vstring);
7833         nds_offset += 4+temp_value.vvalue;
7834         nds_offset += align_4(tvb, nds_offset);
7836         temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7837         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7838         temp_value.vdesc = "Replicas: %u";
7839         temp_value.vlength = 4;
7840         temp_value.voffset = nds_offset;
7841         temp_value.hfname = hf_nds_replicas;
7842         temp_value.mvtype = MVTYPE_READ_REPLICAS;
7843         temp_value.bit1 = "Output Flags";
7844         temp_value.bit2 = "Entry ID";
7845         temp_value.bit3 = "Replica State";
7846         temp_value.bit4 = "Modification Timestamp";
7847         temp_value.bit5 = "Purge Time";
7848         temp_value.bit6 = "Local Partition ID";
7849         temp_value.bit7 = "Distinguished Name";
7850         temp_value.bit8 = "Replica Type";
7851         temp_value.bit9 = "Partition Busy";
7852         temp_value.vflags = request_value->req_nds_flags;
7853         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7854         break;
7855     case 0x17:
7856     case 0x18:
7857     case 0x19:
7858     case 0x1a:
7859         break;
7860     case 0x1b:
7861         proto_tree_add_item(ncp_tree, hf_nds_file_handle, tvb, nds_offset, 4, ENC_BIG_ENDIAN);
7862         nds_offset += 4;
7863         proto_tree_add_item(ncp_tree, hf_nds_file_size, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7864         break;
7865     case 0x1c:
7866     case 0x1d:
7867     case 0x1e:
7868     case 0x1f:
7869     case 0x20:
7870     case 0x21:
7871     case 0x22:
7872     case 0x23:
7873     case 0x24:
7874     case 0x25:
7875     case 0x26:
7876     case 0x27:
7877     case 0x28:
7878     case 0x29:
7879     case 0x2a:
7880     case 0x2b:
7881     case 0x2c:
7882     case 0x2d:
7883     case 0x2e:
7884     case 0x2f:
7885     case 0x30:
7886     case 0x31:
7887     case 0x32:
7888     case 0x33:
7889     case 0x34:
7890         break;
7891     case 0x35:
7892         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7893         temp_value.vdesc = "Server Name";
7894         temp_value.mvtype = MVTYPE_PROCESS_TAGS;
7895         temp_value.vflags = request_value->req_nds_flags;
7896         temp_value.hfname = hf_nds_svr_dst_name;
7897         temp_value.vlength = tvb_get_letohl(tvb, nds_offset);
7898         if (temp_value.vlength == 0x00)
7899             break;
7901         temp_value.voffset = nds_offset;
7902         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7903         nds_offset += temp_value.vlength + 4;
7904         nds_offset += align_4(tvb, nds_offset);
7906         temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7907         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
7908         temp_value.vdesc = "Referral Records: %u";
7909         temp_value.vlength = 4;
7910         temp_value.voffset = nds_offset;
7911         temp_value.hfname = hf_nds_referrals;
7912         temp_value.mvtype = MVTYPE_LOC_ADDR_REFERRAL_REPLY;
7913         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
7914         break;
7915     case 0x36:
7916     case 0x37:
7917     case 0x38:
7918         break;
7919     case 0x39:
7920         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN, &global_eid);
7921         add_eid = true;
7922         resolve_eid = true;
7923         global_object_name = request_value->object_name;
7924         break;
7925     case 0x3a:
7926     case 0x3b:
7927     case 0x3c:
7928     case 0x3d:
7929     case 0x3e:
7930     case 0x3f:
7931     case 0x40:
7932     case 0x41:
7933     case 0x42:
7934     case 0x43:
7935     case 0x44:
7936     case 0x45:
7937     case 0x46:
7938     case 0x47:
7939     case 0x48:
7940     case 0x49:
7941     case 0x4a:
7942     case 0x4b:
7943     case 0x4c:
7944     case 0x4d:
7945         break;
7946     case 0x6e:
7947         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN);
7948         nds_offset += 4;
7949         expert_item = proto_tree_add_item_ret_uint(ncp_tree, hf_iter_completion_code, tvb, nds_offset, 4, ENC_LITTLE_ENDIAN, &temp_value.vvalue);
7950         nds_offset += 4;
7952         if (temp_value.vvalue != 0 && ncp_echo_err) {
7953             expert_add_info_format(pinfo, expert_item, &ei_nds_iteration, "NDS Iteration Error: 0x%08x %s",
7954                                     temp_value.vvalue, val_to_str(temp_value.vvalue, nds_reply_errors, "Unknown: %d"));
7955         }
7956         temp_value.vvalue = tvb_get_letohl(tvb, nds_offset);
7957         temp_value.vtype = VTYPE_ITEM;
7958         temp_value.vlength = 4;
7959         temp_value.voffset = nds_offset;
7960         temp_value.mvtype = MVTYPE_PROCESS_ITERATOR;
7961         temp_value.hfname = hf_ncp_nds_iterverb;
7962         dissect_nds_iterator(ncp_tree, tvb, pinfo, temp_value.vvalue, 0, nds_offset, false);
7963         break;
7964     default:
7965         break;
7966     }
7967     /* NDS Entry ID's (EID) is identified in the reply
7968         * packet of an NDS resolve name. We need to store
7969         * this EID and its associated name into our hash
7970         * so that we can resolve the name for other NDS
7971         * requests. */
7972     if (!pinfo->fd->visited) {
7973         if(add_eid)
7974         {
7975             request_eid_value = ncp_eid_hash_lookup(conversation, global_eid);
7976             if (!request_eid_value) {
7977                 request_eid_value = ncp_eid_hash_insert(global_eid);
7978                 if (global_object_name != NULL)
7979                     (void) g_strlcpy(request_eid_value->object_name, global_object_name, 256);
7980                 else
7981                     request_eid_value->object_name[0] = '\0';
7982             }
7983         }
7984     }
7985     /* Echo EID data to expert Chat window */
7986     if (add_eid && nds_echo_eid) {
7987         expert_add_info_format(pinfo, NULL, &ei_ncp_eid,
7988                                 "EID (%08x) = %s", global_eid, global_object_name);
7989     }
7990     /* For NDS requests with just an EID, resolve name
7991         * from hash table. */
7992     if(resolve_eid)
7993     {
7994         request_eid_value = ncp_eid_hash_lookup(conversation, global_eid);
7995         if (request_eid_value) {
7996             proto_tree_add_string_format(ncp_tree,
7997                                             hf_nds_name, tvb, 6, 0,
7998                                             request_eid_value->object_name,
7999                                             "NDS Name for EID - %s",
8000                                             request_eid_value->object_name);
8001         }
8002     }
8005 void
8006 dissect_ncp_reply(tvbuff_t *tvb, packet_info *pinfo,
8007                   uint32_t nw_connection, uint8_t sequence, uint16_t type,
8008                   proto_tree *ncp_tree, struct novell_tap *ncp_tap)
8010     conversation_t      *conversation = NULL;
8011     ncp_req_hash_value  *request_value = NULL;
8012     const ncp_record    *ncp_rec = NULL;
8013     bool                *req_cond_results;
8014     uint8_t              completion_code=0;
8015     ptvcursor_t         *ptvc = NULL;
8016     const char          *error_string;
8017     uint32_t             nds_error_code = 0;
8018     /*uint32_t             nds_reply_buffer = 0;*/
8019     const char          *nds_error_string = NULL;
8020     /*uint32_t             nds_frag=0;*/
8021     proto_item          *expert_item;
8022     uint8_t              conn_stat;
8025 #ifdef FAKE_TREE_IS_VISIBLE
8026     if (ncp_tree) {
8027         PTREE_DATA(ncp_tree)->visible=1;
8028     }
8029 #endif
8031     if (!pinfo->fd->visited) {
8032         /* Find the conversation whence the request would have come. */
8033         conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
8034                                          CONVERSATION_NCP, nw_connection, nw_connection, 0);
8035         if (conversation != NULL) {
8036             /* find the record telling us the request made that caused
8037                this reply */
8038             request_value = ncp_hash_lookup(conversation, sequence, pinfo->num);
8039             if (request_value) {
8040                 ncp_rec = request_value->ncp_rec;
8041             }
8042             p_add_proto_data(wmem_file_scope(), pinfo, proto_ncp, 0, (void*) request_value);
8043         }
8044         /* else... we haven't seen an NCP Request for that conversation
8045            and sequence.
8046            Create Service request packets do not contain nw_connection.
8047            The initial value is set to 65535 or 0. The reply packet has the
8048            valid connection. So, we can't find the request packet in
8049            our conversation list. To trap for this we can just perform
8050            the search again with 65535 to see if we can locate the
8051            proper request packet. */
8052         else {
8053             conversation = find_conversation(pinfo->num,
8054                                              &pinfo->src, &pinfo->dst, CONVERSATION_NCP, 65535, 65535, 0);
8055             if (conversation != NULL) {
8056                 /* find the record telling us the request made
8057                    that caused this reply */
8058                 request_value = ncp_hash_lookup(conversation,
8059                                                 sequence, pinfo->num);
8060                 if (request_value) {
8061                     ncp_rec = request_value->ncp_rec;
8062                 }
8063                 p_add_proto_data(wmem_file_scope(), pinfo, proto_ncp, 0,
8064                                  (void*) request_value);
8065             }
8066             else {
8067                 conversation = find_conversation(pinfo->num,
8068                                                  &pinfo->src, &pinfo->dst, CONVERSATION_NCP, 0, 0, 0);
8069                 if (conversation != NULL) {
8070                     /* find the record telling us the request made
8071                        that caused this reply */
8072                     request_value = ncp_hash_lookup(conversation,
8073                                                     sequence, pinfo->num);
8074                     if (request_value) {
8075                         ncp_rec = request_value->ncp_rec;
8076                     }
8077                     p_add_proto_data(wmem_file_scope(), pinfo, proto_ncp, 0,
8078                                      (void*) request_value);
8079                 }
8080                 /* else... we haven't seen an NCP Request for that
8081                    conversation and sequence. */
8082             }
8083         }
8084     }
8085     else {
8086         /*request_value = p_get_proto_data(wmem_file_scope(), pinfo, proto_ncp);*/
8087         conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
8088                                          CONVERSATION_NCP, nw_connection, nw_connection, 0);
8089         if (conversation != NULL) {
8091              request_value = ncp_hash_lookup(conversation,
8092                                sequence, pinfo->num);
8093         }
8094         if (request_value) {
8095             ncp_rec = request_value->ncp_rec;
8096         }
8097     }
8099     /*
8100      * Tap the packet before the dissectors are called so we
8101      * still get the tap listener called even if there is an
8102      * exception.
8103      */
8104     tap_queue_packet(ncp_tap->stat, pinfo, request_value);
8106     if (ncp_rec && ncp_rec->func==0x68 &&
8107         (ncp_rec->subfunc==0x02 || ncp_rec->subfunc==0x01)) {
8108         col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDS");
8109     }
8111     /* A completion code of 0 always means OK. Non-zero means failure,
8112      * but each non-zero value has a different meaning. And the same value
8113      * can have different meanings, depending on the ncp.func (and ncp.subfunc)
8114      * value. */
8115     completion_code = tvb_get_uint8(tvb, 6);
8116     if (completion_code == 0) {
8117         if(type == NCP_POSITIVE_ACK)
8118         {
8119             error_string = "Server Busy, Request Being Processed";
8120         }
8121         else
8122         {
8123             error_string = "OK";
8124         }
8125     } else {
8126         if (ncp_rec && ncp_rec->errors) {
8127             error_string = ncp_error_string(ncp_rec->errors, completion_code);
8128         }
8129         else {
8130             error_string = "Original Request Packet not Found";
8131         }
8132     }
8133     if (type == NCP_SERVICE_REPLY && ncp_rec && ncp_rec->func==0x68 &&
8134         ncp_rec->subfunc==0x02 && (tvb_reported_length_remaining(tvb, 8) >= 8))
8135     {
8136         uint32_t nds_offset;
8138         nds_offset = 8;
8139         /*nds_reply_buffer = tvb_get_letohl(tvb, nds_offset);*/
8140         nds_offset += 4;
8141         /*nds_frag = tvb_get_letohl(tvb, nds_offset);*/
8142         nds_offset += 4;
8143         /*
8144          * Is the possibly-reassembled reply large enough to have
8145          * a completion code?  (We can't check the fragment size
8146          * as this might just be the last fragment.)
8147          */
8148         if (tvb_reported_length_remaining(tvb, nds_offset) >= 4)
8149         {
8150             /* Yes - process the completion code. */
8151             nds_error_code = tvb_get_letohl(tvb, nds_offset);
8152             nds_error_string = val_to_str_const(nds_error_code, nds_reply_errors, "NDS Error - No Definition Found");
8153         }
8154     }
8155     col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
8156                     type == NCP_SERVICE_REPLY ? "R" : "ACK",
8157                     nds_error_string ? nds_error_string : error_string);
8159     if (ncp_tree) {
8161         if (request_value) {
8162             nstime_t ns;
8164             proto_tree_add_uint(ncp_tree, hf_ncp_req_frame_num, tvb, 0, 0,
8165                                 request_value->req_frame_num);
8166             nstime_delta(&ns, &pinfo->abs_ts, &request_value->req_frame_time);
8167             proto_tree_add_time(ncp_tree, hf_ncp_req_frame_time, tvb, 0, 0, &ns);
8168         }
8170         /* Put the func (and maybe subfunc) from the request packet
8171          * in the proto tree, but hidden. That way filters on ncp.func
8172          * or ncp.subfunc will find both the requests and the replies.
8173          */
8174         if (ncp_rec) {
8175             proto_tree_add_uint_format_value(ncp_tree, hf_ncp_func, tvb, 6, 0,
8176                                        ncp_rec->func, "%u (0x%02X), %s",
8177                                        ncp_rec->func, ncp_rec->func, ncp_rec->name);
8178             if (ncp_requires_subfunc(ncp_rec->func)) {
8179                 proto_tree_add_uint(ncp_tree, hf_ncp_subfunc, tvb, 6, 0, ncp_rec->subfunc);
8180             }
8181         }
8182     }
8184     expert_item = proto_tree_add_uint_format_value(ncp_tree, hf_ncp_completion_code, tvb, 6, 1,
8185                                              completion_code, "%d (0x89%02x), %s",
8186                                              completion_code, completion_code, error_string);
8187     if ((completion_code != 0 || type == NCP_POSITIVE_ACK) && ncp_echo_err) {
8188         expert_add_info_format(pinfo, expert_item, &ei_ncp_completion_code,
8189                                "Error: %d (0x89%02x) %s", completion_code,
8190                                completion_code, error_string);
8191     }
8193     conn_stat = tvb_get_uint8(tvb, 7);
8194     expert_item = proto_tree_add_item(ncp_tree, hf_ncp_connection_status, tvb,
8195                                       7, 1, ENC_NA);
8196     if (conn_stat != 0 && conn_stat != 0x40 ) {
8197         col_set_str(pinfo->cinfo, COL_INFO,
8198                     "Error: Bad Connection Status");
8199         if (ncp_echo_err) {
8200             expert_add_info(pinfo, expert_item, &ei_ncp_connection_status);
8201         }
8202         return;
8203     }
8204     /*
8205      * Unless this is a successful reply, that's all there
8206      * is to parse.
8207      */
8208     if (type != NCP_SERVICE_REPLY || completion_code != 0)
8209         return;
8211     if (ncp_rec) {
8212         /* Dissect SSS Reply packets */
8213         if (ncp_rec->func == 0x5c && request_value)
8214         {
8215             dissect_sss_reply(tvb, pinfo, ncp_tree, ncp_rec->subfunc, request_value);
8216         }
8217         /* Dissect NMAS Reply packets */
8218         if (ncp_rec->func == 0x5e && request_value)
8219         {
8220             dissect_nmas_reply(tvb, pinfo, ncp_tree, ncp_rec->func, ncp_rec->subfunc, request_value);
8221         }
8222         /* Dissect NDS Ping packets */
8223         if (ncp_rec->func == 0x68 && ncp_rec->subfunc == 0x01)
8224         {
8225             dissect_nds_ping_reply(tvb, pinfo, ncp_tree,
8226                                    request_value);
8227         }
8228         /* Dissect NDS Reply packets */
8229         if (ncp_rec->func == 0x68 && ncp_rec->subfunc == 0x02)
8230         {
8231             dissect_nds_reply(tvb, pinfo, ncp_tree, nds_error_code,
8232                               nds_error_string, request_value, conversation);
8233         }
8234         /* Due to lack of group repeat fields in reply structure, decode this ncp 87/20 reply manually here. */
8235         if ((ncp_rec->func == 0x57 || ncp_rec->func == 0x59) && ncp_rec->subfunc == 0x14) {
8236             dissect_ncp_8x20reply(tvb, pinfo, ncp_tree, ncp_rec, request_value);
8237         }
8238         if (ncp_rec->func == 5 && ncp_echo_conn) {
8239             expert_add_info(pinfo, NULL, &ei_ncp_connection_destroyed);
8240         }
8241         if (ncp_rec->reply_ptvc) {
8242             /* If we're not building a protocol tree, quit;
8243              * "process_ptvc_record()" assumes we're building
8244              * a protocol tree, and we don't support putting
8245              * stuff in the Info column in replies, and no
8246              * state information is currently updated for
8247              * replies by "process_ptvc_record()", so we
8248              * can't, and don't have a reason to, dissect
8249              * any further if we're not building a protocol
8250              * tree. */
8251             if (!ncp_tree)
8252                 return;
8254             /* If a non-zero completion code was found, it is
8255              * legal to not have any fields, even if the packet
8256              * type is defined as having fields.
8257              *
8258              * XXX - we already know that the completion code
8259              * is 0, as we checked it above.  Is there any
8260              * reason why we'd want to do a full dissection
8261              * if the completion code isn't 0? */
8262             if (completion_code != 0 && tvb_captured_length(tvb) == 8) {
8263                 return;
8264             }
8266             /* Any request condition results? */
8267             if (request_value) {
8268                 req_cond_results = request_value->req_cond_results;
8269             }
8270             else {
8271                 req_cond_results = NULL;
8272             }
8273             clear_repeat_vars();
8274             ptvc = ptvcursor_new(pinfo->pool, ncp_tree, tvb, 8);
8275             process_ptvc_record(ptvc, pinfo, ncp_rec->reply_ptvc,
8276                                 req_cond_results, true, ncp_rec, false);
8277             ptvcursor_free(ptvc);
8279             /* Process ncp 123/17 address records manually to format correctly. */
8280             if (ncp_rec->func == 0x7b && ncp_rec->subfunc == 0x11) {
8281                 dissect_ncp_123_17_reply(tvb, pinfo, ncp_tree);
8282             }
8283             /* Process ncp 123/11 NLM names manually to format correctly. */
8284             if (ncp_rec->func == 0x7b && ncp_rec->subfunc == 0x0b && request_value) {
8285                 dissect_ncp_123_11_reply(tvb, ncp_tree, request_value);
8286             }
8287             /* Process ncp 123/62 server set parameter values manually to format correctly. */
8288             if (ncp_rec->func == 0x7b && ncp_rec->subfunc == 0x3e) {
8289                 dissect_ncp_123_62_reply(tvb, ncp_tree);
8290             }
8291             /* Process ncp 23/26 address records manually to format correctly. */
8292             if (ncp_rec->func == 0x17 && ncp_rec->subfunc == 0x1a) {
8293                 dissect_ncp_23_26_reply(tvb, ncp_tree);
8294             }
8295             /* Process ncp 87/72 bytes transferred value. */
8296             if (ncp_rec->func == 0x57 && ncp_rec->subfunc == 0x48) {
8297                 dissect_ncp_87_72_reply(tvb, ncp_tree);
8298             }
8300         }
8301     } else {
8302         if (tvb_reported_length(tvb) > 8) {
8303             expert_item = proto_tree_add_item(ncp_tree, hf_no_request_record_found, tvb, 8, -1, ENC_NA);
8304             if (ncp_echo_err) {
8305                 expert_add_info(pinfo, expert_item, &ei_ncp_no_request_record_found);
8306             }
8307         }
8308     }
8311 void
8312 dissect_nds_request(tvbuff_t *tvb, packet_info *pinfo,
8313                     uint32_t nw_connection, uint8_t sequence,
8314                     uint16_t type, proto_tree *ncp_tree)
8316     uint8_t                  func, subfunc;
8317     ncp_req_hash_value      *request_value = NULL;
8318     ncp_req_eid_hash_value  *request_eid_value = NULL;
8319     const ncp_record        *ncp_rec = NULL;
8320     conversation_t          *conversation;
8321     ptvcursor_t             *ptvc = NULL;
8322     proto_tree              *temp_tree = NULL;
8323     bool                     run_req_cond = false;
8324     uint8_t                  nds_verb = 0;
8325     const char              *verb_string = "";
8326     uint32_t                 nds_frag = 0;
8327     uint8_t                  nds_version = 0;
8328     uint32_t                 foffset = 0;
8329     const char*              global_object_name = NULL;
8330     uint32_t                 global_eid=0;
8331     bool                     resolve_eid=false;
8332     uint32_t                 global_flags;
8333     uint32_t                 version, value1;
8334     nds_val                  temp_value;
8336     func = tvb_get_uint8(tvb, 6);
8337     subfunc = tvb_get_uint8(tvb, 7);
8339     ncp_rec = ncp_record_find(func, subfunc);
8340     if (ncp_rec) {
8341         col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDS");
8342     } else {
8343         col_add_fstr(pinfo->cinfo, COL_INFO,
8344                         "C Unknown Function %d (0x%02x)",
8345                         func, func);
8346     }
8348     /* Check to see if this is a fragment packet */
8349     nds_frag = tvb_get_letohl(tvb, 8);
8351     /* Keep track of the address and connection whence the request
8352        came, and the address and connection to which the request
8353        is being sent, so that we can match up calls with replies.
8354        (We don't include the sequence number, as we may want
8355        to have all packets over the same connection treated
8356        as being part of a single conversation so that we can
8357        let the user select that conversation to be displayed.) */
8359     conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
8360                                      CONVERSATION_NCP, nw_connection, nw_connection, 0);
8361     if (conversation == NULL) {
8362         /* It's not part of any conversation - create a new one. */
8363         conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst,
8364                                         CONVERSATION_NCP, nw_connection, nw_connection, 0);
8365     }
8367     if (!pinfo->fd->visited) {
8368         request_value = ncp_hash_insert(conversation, sequence, ncp_rec, pinfo->num);
8369         request_value->req_frame_num = pinfo->num;
8370         request_value->req_frame_time=pinfo->abs_ts;
8372         /* If this is the first time we're examining the packet,
8373          * check to see if this NCP type uses a "request condition".
8374          * If so, we have to build a proto_tree because request conditions
8375          * use display filters to work, and without a proto_tree,
8376          * display filters can't possibly work. If we already have
8377          * a proto_tree, then wonderful. If we don't, we need to build
8378          * one. */
8379         if (ncp_rec && !ncp_tree) {
8380             run_req_cond = true;
8381         }
8382         /* Keep track of the Fragment number in the request for defrag logic */
8383         request_value->nds_frag_num = nds_frag;
8384     }
8386     /* If we have to handle a request condition, or have to
8387        add to the Info column, we need to construct a protocol
8388        tree.  If we already have a proto_tree, then wonderful.
8389        If we don't, we need to build one. */
8390     if (run_req_cond && !ncp_tree) {
8391         proto_item *ti;
8393         temp_tree = proto_tree_create_root(pinfo);
8394         proto_tree_set_visible(temp_tree, false);
8395         ti = proto_tree_add_item(temp_tree, proto_ncp, tvb, 0, -1, ENC_NA);
8396         ncp_tree = proto_item_add_subtree(ti, ett_ncp);
8397     }
8399     /* Get NDS Verb */
8400     if (nds_frag == 0xffffffff) {
8401         /* First fragment or only fragment. */
8402         nds_verb = tvb_get_uint8(tvb, 24);
8403         if (nds_verb == 0xfe)
8404         {
8405             nds_version = nds_verb;
8406             nds_verb = tvb_get_uint8(tvb, 32);
8407             foffset = 36;
8408         }
8409         else
8410         {
8411             nds_version = 0;
8412             foffset = 28;
8413         }
8414         if (type == NCP_SERVICE_REQUEST) {
8415             proto_tree_add_item(ncp_tree, hf_nds_buffer_size, tvb, foffset,
8416                                 4, ENC_LITTLE_ENDIAN);
8417             if (!pinfo->fd->visited) {
8418                 /*
8419                  * Should we just do a lookup above, so that we use
8420                  * the value we created and added on the first pass,
8421                  * and fetch that value on the next pass?
8422                  */
8423                 request_value = ncp_hash_lookup(conversation, sequence, pinfo->num);
8424                 if (request_value != NULL) {
8425                     request_value->nds_request_verb = nds_verb;
8426                     request_value->nds_version = nds_version;
8427                 }
8428             }
8429         }
8430         foffset = foffset+4;
8431         verb_string = val_to_str_const(nds_verb, ncp_nds_verb_vals,
8432                                        "Continuation Fragment");
8434         if (ncp_rec)
8435             col_add_fstr(pinfo->cinfo, COL_INFO, "C NDS %s", verb_string);
8436     } else {
8437         if (ncp_rec)
8438             col_add_fstr(pinfo->cinfo, COL_INFO, "C Continue NDS Fragment 0x%08x", nds_frag);
8439     }
8441     if (ncp_tree) {
8442         /* If the dissection throws an exception, be sure to free
8443          * the temporary proto_tree that was created. Because of the
8444          * way the CLEANUP_PUSH macro works, we can't put it in an 'if'
8445          * block; it has to be in the same scope as the terminating
8446          * CLEANUP_POP or CLEANUP_POP_AND_ALLOC. So, we always
8447          * call CLEANUP_POP and friends, but the value of temp_tree is
8448          * NULL if no cleanup is needed, and non-null if cleanup is needed.
8449          */
8450         CLEANUP_PUSH(free_proto_tree, temp_tree);
8452 #ifdef FAKE_TREE_IS_VISIBLE
8453         PTREE_DATA(ncp_tree)->visible=1;
8454 #endif
8456         if (type == NCP_SERVICE_REQUEST) {
8457             memset(&temp_value, 0, sizeof(temp_value));
8458             request_value = ncp_hash_lookup(conversation, sequence, pinfo->num);
8460             if (ncp_rec && ncp_rec->request_ptvc)
8461             {
8462                 ptvc = ptvcursor_new(pinfo->pool, ncp_tree, tvb, 7);
8463                 clear_repeat_vars();
8464                 process_ptvc_record(ptvc, pinfo, ncp_rec->request_ptvc, NULL, true, ncp_rec, true);
8465                 ptvcursor_free(ptvc);
8466             }
8467             if (ncp_tree) {
8468                 proto_tree_add_uint_format_value(ncp_tree, hf_ncp_func, tvb, 6, 1,
8469                                            func, "%d (0x%02X), %s",
8470                                            func, func, ncp_rec ? ncp_rec->name : "Unknown");
8472                 proto_tree_add_uint(ncp_tree, hf_ncp_subfunc, tvb, 7, 1, subfunc);
8474                 proto_tree_add_uint(ncp_tree, hf_ncp_fragment_handle, tvb, 8, 4,
8475                                     nds_frag);
8476             }
8478             if (nds_frag == 0xffffffff) {
8479                 uint32_t nds_prot_flags;
8481                 if (ncp_tree) {
8482                     proto_tree_add_item(ncp_tree, hf_ncp_fragment_size, tvb, 12, 4, ENC_LITTLE_ENDIAN);
8484                     proto_tree_add_item(ncp_tree, hf_ncp_message_size, tvb, 16, 4, ENC_LITTLE_ENDIAN);
8485                 }
8486                 nds_prot_flags=tvb_get_letohs(tvb, 22);
8487                 if (!pinfo->fd->visited) {
8488                     if (request_value)
8489                         request_value->req_nds_prot_flags = nds_prot_flags;
8490                 }
8491                 if (ncp_tree) {
8492                     proto_tree_add_bitmask(ncp_tree, tvb, 22, hf_ncp_nds_flag, ett_ncp, ndsprotflags, ENC_LITTLE_ENDIAN);
8494                     if (nds_version == 0) {
8495                         proto_tree_add_uint_format_value(ncp_tree, hf_ncp_nds_verb, tvb, 24, 4,
8496                                                 nds_verb, "%d, (0x%02x), %s",
8497                                                 nds_verb, nds_verb, verb_string);
8498                     }
8499                     else {
8500                         proto_tree_add_uint_format_value(ncp_tree, hf_ncp_nds_verb, tvb, 32, 4,
8501                                                 nds_verb, "%d, (0x%02x), %s",
8502                                                 nds_verb, nds_verb, verb_string);
8503                     }
8504                 }
8506                 switch(nds_verb) {
8508                 case 0x01:
8509                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
8510                     foffset += 4;
8511                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_nds_nflags, ett_ncp, ncp_nflags, ENC_LITTLE_ENDIAN);
8512                     foffset += 4;
8514                     if (version == 0 || version == 1)
8515                     {
8516                         proto_tree_add_item(ncp_tree, hf_nds_scope, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8517                         foffset += 4;
8518                         value1 = tvb_get_letohl(tvb, foffset);
8519                         if (value1 == 0)
8520                             break;
8522                         global_object_name = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8523                         proto_tree_add_string(ncp_tree, hf_nds_name, tvb, foffset, 4+value1, global_object_name);
8524                         col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", global_object_name);
8525                         if (!pinfo->fd->visited) {
8526                             if (request_value)
8527                                 (void) g_strlcpy(request_value->object_name, global_object_name, 256);
8528                         }
8529                         foffset += 4+value1;
8530                         foffset += align_4(tvb, foffset);
8532                         temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8533                         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
8534                         temp_value.vdesc = "Communications Transports: %u";
8535                         temp_value.vlength = 4;
8536                         temp_value.hfname= hf_nds_comm_trans;
8537                         temp_value.voffset = foffset;
8538                         temp_value.mvtype = MVTYPE_ADDR_REFERRAL_REQUEST;
8539                         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8540                         foffset = foffset + (temp_value.vvalue * 4) + 4;
8542                         temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8543                         temp_value.vdesc = "Tree Walker Transport Type: %u";
8544                         temp_value.hfname= hf_nds_tree_trans;
8545                         temp_value.voffset = foffset;
8546                         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8547                     }
8548                     else
8549                     {
8550                         proto_tree_add_item(ncp_tree, hf_min_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8551                         foffset += 4;
8553                         temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8554                         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
8555                         temp_value.vdesc = "Number of Versions to Include: %u";
8556                         temp_value.vlength = 4;
8557                         temp_value.mvtype = MVTYPE_ATTR_REQUEST2;
8558                         temp_value.voffset = foffset;
8559                         temp_value.hfname= hf_nds_ver_include;
8560                         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8561                         foffset += (temp_value.vvalue * 4) + 4;
8563                         temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8564                         temp_value.vdesc = "Number of Versions to Exclude: %u";
8565                         temp_value.hfname= hf_nds_ver_exclude;
8566                         temp_value.voffset = foffset;
8567                         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8568                         foffset += (temp_value.vvalue * 4) + 4;
8570                         proto_tree_add_item(ncp_tree, hf_nds_dn_output_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8571                         foffset += 4;
8572                         proto_tree_add_item(ncp_tree, hf_nds_nested_output_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8573                         foffset += 4;
8575                         value1 = tvb_get_letohl(tvb, foffset);
8576                         global_object_name = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8577                         proto_tree_add_string(ncp_tree, hf_nds_output_delimiter, tvb, foffset, 4+value1, global_object_name);
8578                         col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", global_object_name);
8579                         if (!pinfo->fd->visited) {
8580                             if (request_value)
8581                                 (void) g_strlcpy(request_value->object_name, global_object_name, 256);
8582                         }
8583                         foffset += 4+value1;
8584                         foffset += align_4(tvb, foffset);
8586                         temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8587                         temp_value.vdesc = "Size of Entry Specifier: %u";
8588                         temp_value.mvtype = MVTYPE_PROC_ENTRY_SPECIFIERS;
8589                         temp_value.hfname= hf_nds_output_entry_specifier;
8590                         temp_value.voffset = foffset;
8591                         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8592                     }
8593                     break;
8594                 case 0x02:
8595                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
8596                     foffset += 4;
8597                     switch(version)
8598                     {
8599                     case 0:
8600                         proto_tree_add_item(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8601                         break;
8602                     case 1:
8603                         proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_nds_rflags, ett_ncp, ncp_rflags, ENC_LITTLE_ENDIAN);
8604                         value1 = tvb_get_letohl(tvb, foffset);
8606                         if ((value1 & 0xf000) == 0xc000)
8607                         {
8608                             proto_tree_add_string(ncp_tree, hf_nds_name_type, tvb, 0, 0, "Partial");
8609                         }
8610                         else
8611                         {
8612                             proto_tree_add_string(ncp_tree, hf_nds_name_type, tvb, 0, 0, "Full");
8613                         }
8614                         foffset += 4;
8616                         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8617                         resolve_eid = true;
8618                         break;
8619                     case 2:
8620                         proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_nds_rflags, ett_ncp, ncp_rflags, ENC_LITTLE_ENDIAN);
8621                         value1 = tvb_get_letohl(tvb, foffset);
8622                         if ((value1 & 0xf000) == 0xc000)
8623                         {
8624                             proto_tree_add_string(ncp_tree, hf_nds_name_type, tvb, 0, 0, "Return Partition Name");
8625                         }
8626                         else
8627                         {
8628                             proto_tree_add_string(ncp_tree, hf_nds_name_type, tvb, 0, 0, "Return Full Name");
8629                         }
8630                         foffset += 4;
8631                         proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_retinfoflagsl, ett_ncp, ncp_infoflagsl, ENC_LITTLE_ENDIAN);
8632                         global_flags = tvb_get_letohl(tvb, foffset);
8633                         if (!pinfo->fd->visited) {
8634                             if (request_value)
8635                                 request_value->req_nds_flags = global_flags;
8636                         }
8637                         foffset += 2;
8638                         proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_retinfoflagsh, ett_ncp, ncp_infoflagsh, ENC_LITTLE_ENDIAN);
8639                         foffset += 2;
8641                         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8642                         resolve_eid = true;
8643                         break;
8644                     default:
8645                         break;
8646                     }
8647                     break;
8649                 case 0x03:
8650                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
8651                     foffset += 4;
8653                     if (version == 0)
8654                     {
8655                         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8656                         foffset += 4;
8657                         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8658                         resolve_eid = true;
8659                         foffset += 4;
8660                         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_info_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_flags);
8661                         col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", rval_to_str_const(global_flags, nds_info_type, "No Info Type Set"));
8662                         if (!pinfo->fd->visited) {
8663                             if (request_value)
8664                                 request_value->req_nds_flags = global_flags;
8665                         }
8667                         foffset += 4;
8668                         proto_tree_add_item(ncp_tree, hf_nds_all_attr, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8669                         foffset += 4;
8671                         temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8672                         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
8673                         temp_value.vdesc = "Attributes: %u";
8674                         temp_value.vlength = 4;
8675                         temp_value.voffset = foffset;
8676                         temp_value.mvtype = MVTYPE_ATTR_REQUEST;
8677                         temp_value.hfname= hf_nds_attr;
8678                         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8679                         col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", temp_value.vstring);
8680                     }
8681                     else
8682                     {
8683                         proto_tree_add_item(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8684                         foffset += 4;
8685                         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8686                         foffset += 4;
8687                         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8688                         resolve_eid = true;
8689                         foffset += 4;
8690                         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_info_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_flags);
8691                         col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", rval_to_str_const(global_flags, nds_info_type, "No Info Type Set"));
8692                         if (!pinfo->fd->visited) {
8693                             if (request_value)
8694                                 request_value->req_nds_flags = global_flags;
8695                         }
8696                         foffset += 4;
8697                         proto_tree_add_item(ncp_tree, hf_nds_all_attr, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8698                         foffset += 4;
8700                         temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8701                         temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
8702                         temp_value.vdesc = "Attributes: %u";
8703                         temp_value.vlength = 4;
8704                         temp_value.voffset = foffset;
8705                         temp_value.mvtype = MVTYPE_ATTR_REQUEST;
8706                         temp_value.hfname= hf_nds_attr;
8707                         process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8708                         col_append_fstr(pinfo->cinfo, COL_INFO, " %s", temp_value.vstring);
8709                    }
8710                    break;
8711                 case 0x04:
8712                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
8713                     foffset += 4;
8715                     if (version == 1)
8716                     {
8717                         /* Version 1 specifies for this offset value to always be a value of 1*/
8718                         /* No need to display to user */
8719                         foffset += 4;
8720                     }
8722                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8723                     resolve_eid = true;
8724                     foffset += 4;
8726                     foffset += 4;       /* Attribute Count = 1 */
8728                     value1 = tvb_get_letohl(tvb, foffset);
8729                     if (value1 == 0)
8730                         break;
8732                     global_object_name = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8733                     proto_tree_add_string_format(ncp_tree, hf_nds_name, tvb, foffset, 4+value1, global_object_name, "Attribute Name Being Compared: %s", global_object_name);
8734                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", global_object_name);
8735                     if (!pinfo->fd->visited) {
8736                         if (request_value)
8737                             (void) g_strlcpy(request_value->object_name, global_object_name, 256);
8738                     }
8739                     foffset += 4+value1;
8740                     foffset += align_4(tvb, foffset);
8742                     foffset += 4;       /* Attribute Count = 1 */
8744                     value1 = tvb_get_letohl(tvb, foffset);
8745                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8746                     proto_tree_add_string_format(ncp_tree, hf_value_string, tvb, foffset, 4+value1, temp_value.vstring, "Attribute Value: %s", temp_value.vstring);
8747                     col_append_fstr(pinfo->cinfo, COL_INFO, " %s", temp_value.vstring);
8748                     break;
8749                 case 0x05:
8750                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
8751                     foffset += 4;
8752                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_nds_rflags, ett_ncp, ncp_lflags, ENC_LITTLE_ENDIAN);
8753                     foffset += 2;
8754                     /*
8755                      * XXX - what are the two bytes following the rflags?
8756                      * Or is it a 4-byte field?
8757                      */
8758                     foffset += 2;
8759                     proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8760                     foffset += 4;
8761                     proto_tree_add_item(ncp_tree, hf_nds_parent, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8762                     foffset += 4;
8763                     if (tvb_reported_length_remaining(tvb, foffset) == 0) {
8764                         /*
8765                          * Some requests appear to stop here.
8766                          *
8767                          * XXX - we test for version == 0 later; do all
8768                          * version 0 requests stop here, rather than
8769                          * after the name filter, or do some stop here
8770                          * and some stop there?  If the latter, is there
8771                          * some other way of determining whether the
8772                          * request stops here?
8773                          */
8774                         if (!pinfo->fd->visited) {
8775                             /*
8776                              * This appears to be the set of fields
8777                              * provided in responses to requests that
8778                              * stop before providing a list of requested
8779                              * fields.
8780                              *
8781                              * XXX - is the last entry really the Relative
8782                              * Distinguished Name?  In the captures I've
8783                              * seen with short requests, it begins with
8784                              * "CN=", unlike the captures I've seen with
8785                              * long requests, where it doesn't have that
8786                              * prefix.
8787                              */
8788                             if (request_value)
8789                                 request_value->req_nds_flags =
8790                                     DSI_ENTRY_ID|DSI_ENTRY_FLAGS|DSI_SUBORDINATE_COUNT|DSI_MODIFICATION_TIME|DSI_BASE_CLASS|DSI_ENTRY_RDN;
8791                         }
8792                         break;
8793                     }
8795                     if (!pinfo->fd->visited) {
8796                         if (request_value)
8797                             request_value->req_nds_flags = tvb_get_letohl(tvb, foffset);
8798                     }
8799                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_retinfoflagsl, ett_ncp, ncp_infoflagsl, ENC_LITTLE_ENDIAN);
8800                     foffset += 2;
8801                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_retinfoflagsh, ett_ncp, ncp_infoflagsh, ENC_LITTLE_ENDIAN);
8802                     foffset += 2;
8804                     value1 = tvb_get_letohl(tvb, foffset);
8805                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8806                     proto_tree_add_string(ncp_tree, hf_nds_name_filter, tvb, foffset, 4+value1, temp_value.vstring);
8807                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", temp_value.vstring);
8808                     foffset += 4+value1;
8809                     if (version == 0)
8810                         break;
8812                     foffset += align_4(tvb, foffset);
8814                     value1 = tvb_get_letohl(tvb, foffset);
8815                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8816                     proto_tree_add_string(ncp_tree, hf_nds_class_filter, tvb, foffset, 4+value1, temp_value.vstring);
8817                     col_append_fstr(pinfo->cinfo, COL_INFO, " %s", temp_value.vstring);
8818                     foffset += 4+value1;
8819                     if (version == 1)
8820                         break;
8822                     foffset += align_4(tvb, foffset);
8824                     temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8825                     temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
8826                     temp_value.vdesc = "Seconds: %u";
8827                     temp_value.vlength = 4;
8828                     temp_value.mvtype = MVTYPE_PRINT_TIMESTAMP;
8829                     temp_value.hfname= hf_nds_time_filter;
8830                     temp_value.voffset = foffset;
8831                     process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8832                     break;
8833                 case 0x06:
8834                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
8835                     foffset += 4;
8836                     proto_tree_add_item(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8837                     foffset += 4;
8838                     proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8839                     foffset += 4;
8840                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8841                     resolve_eid = false;
8842                     foffset += 4;
8843                     proto_tree_add_item(ncp_tree, hf_nds_search_scope, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8844                     foffset += 4;
8845                     proto_tree_add_item(ncp_tree, hf_nds_num_objects, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8846                     foffset += 4;
8847                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_siflags, ett_ncp, ncp_siflags, ENC_LITTLE_ENDIAN);
8848                     foffset += 4;
8850                     if (version != 2)
8851                     {
8852                         proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_retinfoflagsl, ett_ncp, ncp_infoflagsl, ENC_LITTLE_ENDIAN);
8853                         foffset += 2;
8854                         proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_retinfoflagsh, ett_ncp, ncp_infoflagsh, ENC_LITTLE_ENDIAN);
8855                     }
8856                     break;
8857                 case 0x07:
8858                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
8859                     foffset += 4;
8860                     proto_tree_add_item(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8861                     foffset += 4;
8862                     if (version != 0)
8863                     {
8864                         proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8865                         foffset += 4;
8866                     }
8868                     global_eid = tvb_get_letohl(tvb, foffset);
8869                     proto_tree_add_uint_format(ncp_tree, hf_nds_eid, tvb, foffset, 4, global_eid, "Parent Entry ID: 0x%08x", global_eid);
8870                     resolve_eid = false;
8871                     foffset += 4;
8873                     value1 = tvb_get_letohl(tvb, foffset);
8874                     if (value1 == 0)
8875                         break;
8876                     global_object_name = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8877                     proto_tree_add_string(ncp_tree, hf_nds_relative_dn, tvb, foffset, 4+value1, global_object_name);
8878                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", global_object_name);
8879                     if (!pinfo->fd->visited) {
8880                         if (request_value)
8881                             (void) g_strlcpy(request_value->object_name, global_object_name, 256);
8882                     }
8883                     foffset += 4+value1;
8884                     foffset += align_4(tvb, foffset);
8886                     temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8887                     temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
8888                     temp_value.vstring = "";
8889                     temp_value.vdesc = "Attributes: %u";
8890                     temp_value.vlength = 4;
8891                     temp_value.voffset = foffset;
8892                     temp_value.mvtype = MVTYPE_ADD_ATTR_REQUEST;
8893                     temp_value.hfname= hf_nds_attr;
8894                     process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8895                     break;
8896                 case 0x08:
8897                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8898                     foffset += 4;
8899                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8900                     resolve_eid = true;
8901                     break;
8903                 case 0x09:
8904                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
8905                     foffset += 4;
8907                     if (version != 0)
8908                     {
8909                         proto_tree_add_item(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8910                         foffset += 4;
8911                     }
8913                     proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8914                     foffset += 4;
8915                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8916                     resolve_eid = true;
8917                     foffset += 4;
8919                     temp_value.vvalue = tvb_get_letohl(tvb, foffset);
8920                     temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
8921                     temp_value.vstring = "";
8922                     temp_value.vdesc = "Number of Attributes to Change %u";
8923                     temp_value.vlength = 4;
8924                     temp_value.mvtype = MVTYPE_MODIFY_ATTR_REQUEST;
8925                     temp_value.hfname= hf_nds_number_of_changes;
8926                     temp_value.voffset = foffset;
8927                     process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
8928                     break;
8929                 case 0x0a:
8930                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8931                     foffset += 4;
8933                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
8934                     resolve_eid = true;
8935                     foffset += 4;
8937                     proto_tree_add_item(ncp_tree, hf_nds_keep, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8938                     foffset += 4;
8939                     foffset += align_4(tvb, foffset);
8941                     value1 = tvb_get_letohl(tvb, foffset);
8942                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8943                     proto_tree_add_string(ncp_tree, hf_nds_new_rdn, tvb, foffset, 4+value1, temp_value.vstring);
8944                     break;
8946                 case 0x0b:
8947                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8948                     foffset += 4;
8949                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_nds_acflags, ett_ncp, ncp_acflags, ENC_LITTLE_ENDIAN);
8950                     foffset += 4;
8952                     value1 = tvb_get_letohl(tvb, foffset);
8953                     if (value1 == 0)
8954                         break;
8955                     global_object_name = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8956                     proto_tree_add_string_format(ncp_tree, hf_nds_relative_dn, tvb, foffset, 4+value1, global_object_name, "Attribute Name: %s", global_object_name);
8957                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", global_object_name);
8958                     if (!pinfo->fd->visited) {
8959                         if (request_value)
8960                             (void) g_strlcpy(request_value->object_name, global_object_name, 256);
8961                     }
8962                     foffset += 4+value1;
8963                     foffset += align_4(tvb, foffset);
8965                     proto_tree_add_item(ncp_tree, hf_nds_syntax, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8966                     foffset += 4;
8967                     proto_tree_add_item(ncp_tree, hf_nds_lower, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8968                     foffset += 4;
8969                     proto_tree_add_item(ncp_tree, hf_nds_upper, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8970                     foffset += 4;
8971                     value1 = tvb_get_letohl(tvb, foffset);
8972                     foffset += 4;
8973                     proto_tree_add_item(ncp_tree, hf_nds_asn1, tvb, foffset, value1, ENC_NA);
8974                     break;
8975                 case 0x0c: /* Not Defined */
8976                     break;
8977                 case 0x0d:
8978                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8979                     foffset += 4;
8981                     value1 = tvb_get_letohl(tvb, foffset);
8982                     if (value1 == 0)
8983                         break;
8985                     global_object_name = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
8986                     proto_tree_add_string(ncp_tree, hf_nds_attribute_dn, tvb, foffset, 4+value1, global_object_name);
8987                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", global_object_name);
8988                     if (!pinfo->fd->visited) {
8989                         if (request_value)
8990                             (void) g_strlcpy(request_value->object_name, global_object_name, 256);
8991                     }
8992                     break;
8993                 case 0x0e: /* Not Defined */
8994                     break;
8995                 case 0x0f:
8996                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8997                     foffset += 4;
8998                     proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
8999                     foffset += 4;
9000                     proto_tree_add_item(ncp_tree, hf_nds_class_def_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9001                     foffset += 4;
9002                     value1 = tvb_get_letohl(tvb, foffset);
9003                     if (value1 == 0)
9004                     {
9005                         proto_tree_add_uint_format_value(ncp_tree, hf_nds_return_all_classes, tvb, foffset, 4, value1, "Do Not Return All Classes");
9006                     }
9007                     else
9008                     {
9009                         proto_tree_add_uint_format_value(ncp_tree, hf_nds_return_all_classes, tvb, foffset, 4, value1, "Return All Classes");
9010                     }
9011                     foffset += 4;
9012                     foffset += align_4(tvb, foffset);
9014                     temp_value.vvalue = tvb_get_letohl(tvb, foffset);
9015                     temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
9016                     temp_value.vdesc = "Classes: %u";
9017                     temp_value.vlength = 4;
9018                     temp_value.mvtype = MVTYPE_READ_CLASS_REQ;
9019                     temp_value.hfname= hf_nds_classes;
9020                     temp_value.voffset = foffset;
9021                     process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
9022                     break;
9023                 case 0x10:
9024                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
9025                     foffset += 4;
9027                     value1 = tvb_get_letohl(tvb, foffset);
9028                     if (value1 == 0)
9029                         break;
9031                     global_object_name = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9032                     proto_tree_add_string_format(ncp_tree, hf_nds_base_class, tvb, foffset, 4+value1, global_object_name, "Class Name: %s", global_object_name);
9033                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", global_object_name);
9034                     if (!pinfo->fd->visited) {
9035                         if (request_value)
9036                             (void) g_strlcpy(request_value->object_name, global_object_name, 256);
9037                     }
9038                     foffset += 4+value1;
9039                     foffset += align_4(tvb, foffset);
9041                     temp_value.vvalue = tvb_get_letohl(tvb, foffset);
9042                     temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
9043                     temp_value.vdesc = "Number of Attributes to Add: %u";
9044                     temp_value.vlength = 4;
9045                     temp_value.voffset = foffset;
9046                     temp_value.mvtype = MVTYPE_MODIFY_CLASS;
9047                     temp_value.hfname= hf_nds_att_add;
9048                     break;
9049                 case 0x11:
9050                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9051                     foffset += 4;
9053                     value1 = tvb_get_letohl(tvb, foffset);
9054                     if (value1 == 0)
9055                         break;
9057                     global_object_name = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9058                     proto_tree_add_string_format(ncp_tree, hf_nds_base, tvb, foffset, 4+value1, global_object_name, "Class Name: %s", global_object_name);
9059                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", global_object_name);
9060                     if (!pinfo->fd->visited) {
9061                         if (request_value)
9062                             (void) g_strlcpy(request_value->object_name, global_object_name, 256);
9063                     }
9064                     break;
9065                 case 0x12:
9066                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9067                     foffset += 4;
9068                     proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9069                     foffset += 4;
9070                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
9071                     resolve_eid = true;
9072                     break;
9073                 case 0x13:
9074                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
9075                     foffset += 4;
9076                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
9077                     resolve_eid = true;
9078                     foffset += 4;
9080                     value1 = tvb_get_letohl(tvb, foffset);
9081                     if (value1 == 0)
9082                         break;
9084                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9085                     proto_tree_add_string_format(ncp_tree, hf_nds_name, tvb, foffset, 4+value1, temp_value.vstring, "Trustee Name: %s", temp_value.vstring);
9086                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", temp_value.vstring);
9087                     foffset += 4+value1;
9088                     foffset += align_4(tvb, foffset);
9090                     value1 = tvb_get_letohl(tvb, foffset);
9091                     if (value1 == 0)
9092                         break;
9094                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9095                     proto_tree_add_string_format(ncp_tree, hf_nds_name, tvb, foffset, 4+value1, temp_value.vstring, "Attribute to be Checked: %s", temp_value.vstring);
9096                     foffset += 4+value1;
9097                     foffset += align_4(tvb, foffset);
9099                     if(version != 0)
9100                     {
9101                         value1 = tvb_get_letohl(tvb, foffset);
9102                         if (value1 == 0)
9103                             break;
9105                         temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9106                         proto_tree_add_string_format(ncp_tree, hf_nds_name, tvb, foffset, 4+value1, temp_value.vstring, "Security Equivalence: %s", temp_value.vstring);
9107                         col_append_fstr(pinfo->cinfo, COL_INFO, " %s", temp_value.vstring);
9108                     }
9109                     break;
9110                 case 0x14: /* Not Defined */
9111                 case 0x15:
9112                     break;
9113                 case 0x16:
9114                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
9115                     foffset += 4;
9116                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_nds_rflags, ett_ncp, nds_bitflags, ENC_LITTLE_ENDIAN);
9117                     foffset += 2;
9118                     proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9119                     foffset += 4;
9121                     if(version == 0)
9122                     {
9123                         global_flags = 0x000000c0;
9124                         if (!pinfo->fd->visited) {
9125                             if (request_value)
9126                                 request_value->req_nds_flags = global_flags;
9127                         }
9128                         break;
9129                     }
9131                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_l1flagsl, ett_ncp, ncp_l1flagsl, ENC_LITTLE_ENDIAN);
9132                     global_flags = tvb_get_letohs(tvb, foffset);
9133                     if (!pinfo->fd->visited) {
9134                         if (request_value)
9135                             request_value->req_nds_flags = global_flags;
9136                     }
9137                     foffset += 2;
9138                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_l1flagsh, ett_ncp, ncp_l1flagsh, ENC_LITTLE_ENDIAN);
9139                     foffset += 2;
9141                     if(version == 1)
9142                         break;
9144                     proto_tree_add_item(ncp_tree, hf_nds_partition_root_id, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9145                     break;
9146                 case 0x17:
9147                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9148                     foffset += 4;
9149                     value1 = tvb_get_letohl(tvb, foffset);
9150                     proto_tree_add_uint_format(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, value1, "Flags: 0x%08x", value1);
9151                     foffset += 4;
9152                     proto_tree_add_item(ncp_tree, hf_nds_new_part_id, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9153                     break;
9154                 case 0x18:
9155                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9156                     foffset += 4;
9157                     value1 = tvb_get_letohl(tvb, foffset);
9158                     proto_tree_add_uint_format(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, value1, "Flags: 0x%08x", value1);
9159                     foffset += 4;
9160                     proto_tree_add_item(ncp_tree, hf_nds_child_part_id, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9161                     break;
9162                 case 0x19:
9163                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9164                     foffset += 4;
9165                     value1 = tvb_get_letohl(tvb, foffset);
9166                     proto_tree_add_uint_format(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, value1, "Flags: 0x%08x", value1);
9167                     foffset += 4;
9168                     proto_tree_add_item(ncp_tree, hf_nds_master_part_id, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9169                     foffset += 4;
9170                     proto_tree_add_item(ncp_tree, hf_replica_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9171                     foffset += 4;
9173                     value1 = tvb_get_letohl(tvb, foffset);
9174                     if (value1 == 0)
9175                         break;
9177                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9178                     proto_tree_add_string(ncp_tree, hf_nds_target_name, tvb, foffset, 4+value1, temp_value.vstring);
9179                     break;
9180                 case 0x1a: /* Not Defined */
9181                     break;
9182                 case 0x1b:
9183                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9184                     foffset += 4;
9185                     proto_tree_add_item(ncp_tree, hf_nds_stream_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9186                     foffset += 4;
9187                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
9188                     resolve_eid = true;
9189                     foffset += 4;
9191                     value1 = tvb_get_letohl(tvb, foffset);
9192                     if (value1 == 0)
9193                         break;
9195                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9196                     proto_tree_add_string(ncp_tree, hf_nds_stream_name, tvb, foffset, 4+value1, temp_value.vstring);
9197                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", temp_value.vstring);
9198                     break;
9199                 case 0x1c: /* Not Defined */
9200                 case 0x1d:
9201                 case 0x1e:
9202                 case 0x1f:
9203                 case 0x20:
9204                 case 0x21:
9205                 case 0x22:
9206                 case 0x23:
9207                 case 0x24:
9208                 case 0x25:
9209                     break;
9210                 case 0x26:
9211                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &version);
9212                     foffset += 4;
9213                     value1 = tvb_get_letohl(tvb, foffset);
9214                     proto_tree_add_uint_format(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, value1, "Flags: 0x%08x", value1);
9215                     foffset += 4;
9216                     proto_tree_add_item(ncp_tree, hf_nds_time_delay, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9217                     foffset += 4;
9219                     if(version == 0)
9220                     {
9221                         value1 = tvb_get_letohl(tvb, foffset);
9222                         if (value1 == 0)
9223                             break;
9225                         temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9226                         proto_tree_add_string(ncp_tree, hf_nds_root_name, tvb, foffset, 4+value1, temp_value.vstring);
9227                         col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", temp_value.vstring);
9228                     }
9229                     else
9230                     {
9231                         global_eid = tvb_get_letohl(tvb, foffset);
9232                         proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
9233                         resolve_eid = true;
9234                     }
9235                     break;
9236                 case 0x27: /* Not Defined */
9237                 case 0x28:
9238                 case 0x29:
9239                     break;
9240                 case 0x2a:
9241                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9242                     foffset += 4;
9243                     value1 = tvb_get_letohl(tvb, foffset);
9244                     proto_tree_add_uint_format(ncp_tree, hf_nds_req_flags, tvb, foffset, 4, value1, "Flags: 0x%08x", value1);
9245                     foffset += 4;
9246                     global_eid = tvb_get_letohl(tvb, foffset);
9247                     proto_tree_add_uint_format(ncp_tree, hf_nds_ver, tvb, foffset, 4, global_eid, "Destination Parent Entry ID: 0x%08x", global_eid);
9248                     resolve_eid = true;
9249                     foffset += 4;
9251                     value1 = tvb_get_letohl(tvb, foffset);
9252                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9253                     proto_tree_add_string(ncp_tree, hf_nds_new_rdn, tvb, foffset, 4+value1, temp_value.vstring);
9254                     foffset += (4+value1);
9255                     foffset += align_4(tvb, foffset);
9257                     value1 = tvb_get_letohl(tvb, foffset);
9258                     if (value1 == 0)
9259                         break;
9260                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9261                     proto_tree_add_string(ncp_tree, hf_nds_target_name, tvb, foffset, 4+value1, temp_value.vstring);
9262                     break;
9263                 case 0x2b:
9264                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9265                     foffset += 4;
9266                     proto_tree_add_item(ncp_tree, hf_nds_verb2b_req_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9267                     foffset += 4;
9268                     global_eid = tvb_get_letohl(tvb, foffset);
9269                     proto_tree_add_uint_format(ncp_tree, hf_nds_ver, tvb, foffset, 4, global_eid, "Source Entry ID: 0x%08x", global_eid);
9270                     resolve_eid = true;
9271                     foffset += 4;
9272                     value1 = tvb_get_letohl(tvb, foffset);
9273                     proto_tree_add_uint_format(ncp_tree, hf_nds_ver, tvb, foffset, 4, value1, "Destination Parent Entry ID: 0x%08x", value1);
9274                     foffset += 4;
9275                     value1 = tvb_get_letohl(tvb, foffset);
9276                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9277                     proto_tree_add_string(ncp_tree, hf_nds_new_rdn, tvb, foffset, 4+value1, temp_value.vstring);
9278                     foffset += (4+value1);
9279                     foffset += align_4(tvb, foffset);
9280                     value1 = tvb_get_letohl(tvb, foffset);
9281                     if (value1 == 0)
9282                         break;
9283                     temp_value.vstring = (const char*)tvb_get_string_enc(pinfo->pool, tvb, foffset+4, value1, ENC_UTF_16|ENC_LITTLE_ENDIAN);
9284                     proto_tree_add_string(ncp_tree, hf_nds_target_name, tvb, foffset, 4+value1, temp_value.vstring);
9285                     break;
9286                 case 0x2c: /* Not Defined */
9287                 case 0x2d:
9288                 case 0x2e:
9289                 case 0x2f:
9290                 case 0x30:
9291                 case 0x31:
9292                     break;
9293                 case 0x32:
9294                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9295                     foffset += 4;
9296                     proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9297                     foffset += 4;
9298                     value1 = tvb_get_letohl(tvb, foffset);
9299                     temp_value.vstring = val_to_str_const(value1, ncp_nds_verb_vals, "(No Verb Found)");
9300                     proto_tree_add_string_format(ncp_tree, hf_mv_string, tvb, foffset, 4+value1, temp_value.vstring, "NDS Verb: %s", temp_value.vstring);
9301                 break;
9302                 case 0x33: /* Not Defined */
9303                 case 0x34:
9304                     break;
9305                 case 0x35:
9306                     if (nds_version != 0)
9307                     {
9308                         proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9309                         foffset += 4;
9310                         proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_nds_rflags, ett_ncp, ncp_rflags, ENC_LITTLE_ENDIAN);
9311                         global_flags = tvb_get_letohl(tvb, foffset);
9312                         if (!pinfo->fd->visited) {
9313                             if (request_value)
9314                                 request_value->req_nds_flags = global_flags;
9315                         }
9316                     }
9317                     break;
9318                 case 0x36: /* Not Defined */
9319                 case 0x37:
9320                 case 0x38:
9321                     break;
9322                 case 0x39:
9323                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9324                     foffset += 4;
9325                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
9326                     resolve_eid = true;
9327                     break;
9328                 case 0x3a:
9329                     proto_tree_add_item(ncp_tree, hf_nds_buffer_size, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9330                     foffset += 4;
9331                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9332                     foffset += 4;
9333                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
9334                     resolve_eid = true;
9335                     break;
9336                 case 0x3b:
9337                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9338                     foffset += 4;
9339                     proto_tree_add_item_ret_uint(ncp_tree, hf_nds_eid, tvb, foffset, 4, ENC_LITTLE_ENDIAN, &global_eid);
9340                     resolve_eid = true;
9341                     break;
9342                 case 0x3c: /* Not Defined */
9343                 case 0x3d:
9344                 case 0x3e:
9345                 case 0x3f:
9346                 case 0x40:
9347                 case 0x41:
9348                 case 0x42:
9349                 case 0x43:
9350                 case 0x44:
9351                 case 0x45:
9352                 case 0x46:
9353                 case 0x47:
9354                 case 0x48:
9355                 case 0x49:
9356                 case 0x4a:
9357                 case 0x4b:
9358                 case 0x4c:
9359                 case 0x4d:
9360                     break;
9361                 case 0x6e:
9362                     proto_tree_add_item(ncp_tree, hf_nds_ver, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9363                     foffset += 4;
9364                     proto_tree_add_bitmask(ncp_tree, tvb, foffset, hf_nds_rflags, ett_ncp, ncp_rflags, ENC_LITTLE_ENDIAN);
9365                     global_flags = tvb_get_letohl(tvb, foffset);
9366                     if (!pinfo->fd->visited) {
9367                         if (request_value)
9368                             request_value->req_nds_flags = global_flags;
9369                     }
9370                     foffset += 4;
9371                     proto_tree_add_item(ncp_tree, hf_nds_iteration, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9372                     foffset += 4;
9373                     global_eid = tvb_get_letohl(tvb, foffset);
9374                     proto_tree_add_uint_format(ncp_tree, hf_nds_eid, tvb, foffset, 4, global_eid, "Base Entry ID: 0x%08x", global_eid);
9375                     resolve_eid = true;
9376                     foffset += 4;
9377                     proto_tree_add_item(ncp_tree, hf_nds_scope, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
9378                     foffset += 4;
9380                     temp_value.vvalue = tvb_get_letohl(tvb, foffset);
9381                     temp_value.vtype = VTYPE_MULTIVALUE_UINT32;
9382                     temp_value.vdesc = "Iterator: 0x%08x";
9383                     temp_value.vlength = 4;
9384                     temp_value.voffset = foffset;
9385                     temp_value.hfname= hf_nds_iterator;
9386                     temp_value.mvtype = MVTYPE_PROCESS_ITERATOR;
9387                     process_multivalues(ncp_tree, tvb, pinfo, &temp_value);
9388                     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", temp_value.vstring);
9389                     break;
9390                 default: /* Not Defined */
9391                     break;
9392                 }
9393             }
9395             /* For NDS requests with just an EID, resolve name from hash table. */
9396             request_eid_value = ncp_eid_hash_lookup(conversation, global_eid);
9397             if(resolve_eid) {
9398                 if (request_eid_value) {
9399                     col_append_fstr(pinfo->cinfo, COL_INFO, ", Object Name - %s", request_eid_value->object_name);
9400                 }
9401             }
9402         }
9404         /* Free the temporary proto_tree */
9405         CLEANUP_CALL_AND_POP;
9406     }
9410  * XXX - this duplicates stuff in "dissect_ncp_request()"; could
9411  * "dissect_ncp_request()" not just call "dissect_ping_req()" if
9412  * the operation is an NCP ping, and "dissect_ping_req()" just dissect
9413  * ping portion?
9414  */
9415 void
9416 dissect_ping_req(tvbuff_t *tvb, packet_info *pinfo,
9417                  uint32_t nw_connection, uint8_t sequence,
9418                  uint16_t type, proto_tree *ncp_tree)
9420     uint8_t              func, subfunc = 0;
9421     ncp_req_hash_value  *request_value = NULL;
9422     const ncp_record    *ncp_rec = NULL;
9423     conversation_t      *conversation;
9424     ptvcursor_t         *ptvc = NULL;
9425     proto_tree          *temp_tree = NULL;
9426     int                  length_remaining = 0;
9427     uint32_t             nds_flags;
9428     uint32_t             ping_version;
9430 #ifdef FAKE_TREE_IS_VISIBLE
9431     if (ncp_tree) {
9432         PTREE_DATA(ncp_tree)->visible=1;
9433     }
9434 #endif
9436     func = tvb_get_uint8(tvb, 6);
9437     subfunc = tvb_get_uint8(tvb, 7);
9439     ncp_rec = ncp_record_find(func, subfunc);
9441     /* Fill in the INFO column. */
9442     if (ncp_rec)
9443     {
9444         col_set_str(pinfo->cinfo, COL_PROTOCOL, "NDS");
9446         col_set_str(pinfo->cinfo, COL_INFO, "C Ping for NDS");
9448     }
9449     if (!pinfo->fd->visited)
9450     {
9452         /* This is the first time we've looked at this packet.
9453            Keep track of the address and connection whence the request
9454            came, and the address and connection to which the request
9455            is being sent, so that we can match up calls with replies.
9456            (We don't include the sequence number, as we may want
9457            to have all packets over the same connection treated
9458            as being part of a single conversation so that we can
9459            let the user select that conversation to be displayed.) */
9461         conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
9462                                          CONVERSATION_NCP, nw_connection, nw_connection, 0);
9464         if (conversation == NULL)
9465         {
9466             /* It's not part of any conversation - create a new one. */
9467             conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst,
9468                                             CONVERSATION_NCP, nw_connection, nw_connection, 0);
9469         }
9471         request_value = ncp_hash_insert(conversation, sequence, ncp_rec, pinfo->num);
9472         request_value->req_frame_num = pinfo->num;
9473         request_value->req_frame_time=pinfo->abs_ts;
9475         /* If this is the first time we're examining the packet,
9476          * check to see if this NCP type uses a "request condition".
9477          * If so, we have to build a proto_tree because request conditions
9478          * use display filters to work, and without a proto_tree,
9479          * display filters can't possibly work. If we already have
9480          * a proto_tree, then wonderful. If we don't, we need to build
9481          * one. */
9482         if (ncp_rec && !ncp_tree) {
9483             proto_item *ti;
9485             temp_tree = proto_tree_create_root(pinfo);
9486             proto_tree_set_visible(temp_tree, false);
9487             ti = proto_tree_add_item(temp_tree, proto_ncp, tvb, 0, -1, ENC_NA);
9488             ncp_tree = proto_item_add_subtree(ti, ett_ncp);
9489         }
9490     }
9492     if (ncp_tree) {
9493         /* If the dissection throws an exception, be sure to free
9494          * the temporary proto_tree that was created. Because of the
9495          * way the CLEANUP_PUSH macro works, we can't put it in an 'if'
9496          * block; it has to be in the same scope as the terminating
9497          * CLEANUP_POP or CLEANUP_POP_AND_ALLOC. So, we always
9498          * call CLEANUP_POP and friends, but the value of temp_tree is
9499          * NULL if no cleanup is needed, and non-null if cleanup is needed.
9500          */
9501         CLEANUP_PUSH(free_proto_tree, temp_tree);
9503         switch (type) {
9505         case NCP_BROADCAST_SLOT:
9506             ; /* nothing */
9507             break;
9509         case NCP_SERVICE_REQUEST:
9510             proto_tree_add_uint_format_value(ncp_tree, hf_ncp_func, tvb, 6, 1,
9511                                        func, "%u (0x%02X), %s",
9512                                        func, func, ncp_rec ? ncp_rec->name : "Unknown");
9514             proto_tree_add_uint(ncp_tree, hf_ncp_subfunc, tvb, 7, 1, subfunc);
9516             length_remaining = tvb_reported_length_remaining(tvb, 8);
9518             if (length_remaining >= 8) {
9519                 proto_item *pi;
9521                 ping_version = tvb_get_letohl(tvb, 8);
9522                 proto_tree_add_uint(ncp_tree, hf_nds_ping_version, tvb, 8,
9523                                     4, ping_version);
9524                 nds_flags = tvb_get_letohl(tvb, 12);
9525                 if (request_value){
9526                     request_value->nds_request_verb = 0xf0;
9527                     request_value->req_nds_flags = nds_flags;
9528                 }
9530                 pi = proto_tree_add_uint(ncp_tree, hf_ncp_nds_verb, tvb, 0, 0, 240);
9531                 proto_item_set_hidden(pi);
9533                 proto_tree_add_bitmask(ncp_tree, tvb, 12, hf_pingflags1, ett_ncp, ncp_pingflags1, ENC_LITTLE_ENDIAN);
9534                 proto_tree_add_bitmask(ncp_tree, tvb, 14, hf_pingflags2, ett_ncp, ncp_pingflags2, ENC_LITTLE_ENDIAN);
9535             }
9536             break;
9538         default:
9539             ; /* nothing */
9540             break;
9541         }
9542         ptvc = ptvcursor_new(pinfo->pool, ncp_tree, tvb, 7);
9543         if (ncp_rec && ncp_rec->request_ptvc) {
9544             clear_repeat_vars();
9545             process_ptvc_record(ptvc, pinfo, ncp_rec->request_ptvc, NULL, true, ncp_rec, true);
9546         }
9547         ptvcursor_free(ptvc);
9549         /* Free the temporary proto_tree */
9550         CLEANUP_CALL_AND_POP;
9551     }
9555  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
9557  * Local variables:
9558  * c-basic-offset: 4
9559  * tab-width: 4
9560  * indent-tabs-mode: nil
9561  * End:
9563  * vi: set shiftwidth=4 tabstop=4 expandtab filetype=c:
9564  * :indentSize=4:tabSize=4:noTabs=true:
9565  */