Complete the dissection of NetWkstaSetInfo, wheeee, this is fun, plonk.
[obnox/wireshark/wip.git] / packet-smb-pipe.c
1 /*
2 XXX  Fixme : shouldnt show [malformed frame] for long packets
3 */
4
5 /* packet-smb-pipe.c
6  * Routines for SMB named pipe packet dissection
7  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
8  * significant rewrite to tvbuffify the dissector, Ronnie Sahlberg and
9  * Guy Harris 2001
10  *
11  * $Id: packet-smb-pipe.c,v 1.94 2003/04/20 11:36:15 guy Exp $
12  *
13  * Ethereal - Network traffic analyzer
14  * By Gerald Combs <gerald@ethereal.com>
15  * Copyright 1998 Gerald Combs
16  *
17  * Copied from packet-pop.c
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <stdio.h>
39
40 #include <time.h>
41 #include <string.h>
42 #include <glib.h>
43 #include <ctype.h>
44 #include <epan/packet.h>
45 #include <epan/conversation.h>
46 #include "smb.h"
47 #include "packet-smb-pipe.h"
48 #include "packet-smb-browse.h"
49 #include "packet-smb-common.h"
50 #include "packet-dcerpc.h"
51 #include "reassemble.h"
52
53 static int proto_smb_pipe = -1;
54 static int hf_pipe_function = -1;
55 static int hf_pipe_priority = -1;
56 static int hf_pipe_peek_available = -1;
57 static int hf_pipe_peek_remaining = -1;
58 static int hf_pipe_peek_status = -1;
59 static int hf_pipe_getinfo_info_level = -1;
60 static int hf_pipe_getinfo_output_buffer_size = -1;
61 static int hf_pipe_getinfo_input_buffer_size = -1;
62 static int hf_pipe_getinfo_maximum_instances = -1;
63 static int hf_pipe_getinfo_current_instances = -1;
64 static int hf_pipe_getinfo_pipe_name_length = -1;
65 static int hf_pipe_getinfo_pipe_name = -1;
66 static int hf_pipe_write_raw_bytes_written = -1;
67 static int hf_pipe_fragments = -1;
68 static int hf_pipe_fragment = -1;
69 static int hf_pipe_fragment_overlap = -1;
70 static int hf_pipe_fragment_overlap_conflict = -1;
71 static int hf_pipe_fragment_multiple_tails = -1;
72 static int hf_pipe_fragment_too_long_fragment = -1;
73 static int hf_pipe_fragment_error = -1;
74 static int hf_pipe_reassembled_in = -1;
75
76 static gint ett_smb_pipe = -1;
77 static gint ett_smb_pipe_fragment = -1;
78 static gint ett_smb_pipe_fragments = -1;
79
80 static const fragment_items smb_pipe_frag_items = {
81         &ett_smb_pipe_fragment,
82         &ett_smb_pipe_fragments,
83         &hf_pipe_fragments,
84         &hf_pipe_fragment,
85         &hf_pipe_fragment_overlap,
86         &hf_pipe_fragment_overlap_conflict,
87         &hf_pipe_fragment_multiple_tails,
88         &hf_pipe_fragment_too_long_fragment,
89         &hf_pipe_fragment_error,
90         NULL,
91         "fragments"
92 };
93
94 static int proto_smb_lanman = -1;
95 static int hf_function_code = -1;
96 static int hf_param_desc = -1;
97 static int hf_return_desc = -1;
98 static int hf_aux_data_desc = -1;
99 static int hf_detail_level = -1;
100 static int hf_recv_buf_len = -1;
101 static int hf_send_buf_len = -1;
102 static int hf_continuation_from = -1;
103 static int hf_status = -1;
104 static int hf_convert = -1;
105 static int hf_ecount = -1;
106 static int hf_acount = -1;
107 static int hf_share_name = -1;
108 static int hf_share_type = -1;
109 static int hf_share_comment = -1;
110 static int hf_share_permissions = -1;
111 static int hf_share_max_uses = -1;
112 static int hf_share_current_uses = -1;
113 static int hf_share_path = -1;
114 static int hf_share_password = -1;
115 static int hf_server_name = -1;
116 static int hf_server_major = -1;
117 static int hf_server_minor = -1;
118 static int hf_server_comment = -1;
119 static int hf_abytes = -1;
120 static int hf_current_time = -1;
121 static int hf_msecs = -1;
122 static int hf_hour = -1;
123 static int hf_minute = -1;
124 static int hf_second = -1;
125 static int hf_hundredths = -1;
126 static int hf_tzoffset = -1;
127 static int hf_timeinterval = -1;
128 static int hf_day = -1;
129 static int hf_month = -1;
130 static int hf_year = -1;
131 static int hf_weekday = -1;
132 static int hf_enumeration_domain = -1;
133 static int hf_computer_name = -1;
134 static int hf_user_name = -1;
135 static int hf_group_name = -1;
136 static int hf_workstation_domain = -1;
137 static int hf_workstation_major = -1;
138 static int hf_workstation_minor = -1;
139 static int hf_logon_domain = -1;
140 static int hf_other_domains = -1;
141 static int hf_password = -1;
142 static int hf_workstation_name = -1;
143 static int hf_ustruct_size = -1;
144 static int hf_logon_code = -1;
145 static int hf_privilege_level = -1;
146 static int hf_operator_privileges = -1;
147 static int hf_num_logons = -1;
148 static int hf_bad_pw_count = -1;
149 static int hf_last_logon = -1;
150 static int hf_last_logoff = -1;
151 static int hf_logoff_time = -1;
152 static int hf_kickoff_time = -1;
153 static int hf_password_age = -1;
154 static int hf_password_can_change = -1;
155 static int hf_password_must_change = -1;
156 static int hf_script_path = -1;
157 static int hf_logoff_code = -1;
158 static int hf_duration = -1;
159 static int hf_comment = -1;
160 static int hf_user_comment = -1;
161 static int hf_full_name = -1;
162 static int hf_homedir = -1;
163 static int hf_parameters = -1;
164 static int hf_logon_server = -1;
165 static int hf_country_code = -1;
166 static int hf_workstations = -1;
167 static int hf_max_storage = -1;
168 static int hf_units_per_week = -1;
169 static int hf_logon_hours = -1;
170 static int hf_code_page = -1;
171 static int hf_new_password = -1;
172 static int hf_old_password = -1;
173 static int hf_reserved = -1;
174
175 static gint ett_lanman = -1;
176 static gint ett_lanman_unknown_entries = -1;
177 static gint ett_lanman_unknown_entry = -1;
178 static gint ett_lanman_shares = -1;
179 static gint ett_lanman_share = -1;
180 static gint ett_lanman_groups = -1;
181 static gint ett_lanman_servers = -1;
182 static gint ett_lanman_server = -1;
183
184 static dissector_handle_t data_handle;
185
186 /*
187  * See
188  *
189  *      ftp://ftp.microsoft.com/developr/drg/CIFS/cifsrap2.txt
190  *
191  * among other documents.
192  */
193
194 static const value_string status_vals[] = {
195         {0,     "Success"},
196         {5,     "User has insufficient privilege"},
197         {65,    "Network access is denied"},
198         {86,    "The specified password is invalid"},
199         {SMBE_moredata, "Additional data is available"},
200         {2114,  "Service is not running on the remote computer"},
201         {2123,  "Supplied buffer is too small"},
202         {2141,  "Server is not configured for transactions (IPC$ not shared)"},
203         {2212,  "An error occurred while loading or running the logon script"},
204         {2214,  "The logon was not validated by any server"},
205         {2217,  "The logon server is running an older software version"},
206         {2221,  "The user name was not found"},
207         {2226,  "Operation not permitted on Backup Domain Controller"},
208         {2240,  "The user is not allowed to logon from this computer"},
209         {2241,  "The user is not allowed to logon at this time"},
210         {2242,  "The user password has expired"},
211         {2243,  "The password cannot be changed"},
212         {2246,  "The password is too short"},
213         {0,     NULL}
214 };
215
216 static const value_string privilege_vals[] = {
217         {0, "Guest"},
218         {1, "User"},
219         {2, "Administrator"},
220         {0, NULL}
221 };
222
223 static const value_string op_privilege_vals[] = {
224         {0, "Print operator"},
225         {1, "Communications operator"},
226         {2, "Server operator"},
227         {3, "Accounts operator"},
228         {0, NULL}
229 };
230
231 static const value_string weekday_vals[] = {
232         {0, "Sunday"},
233         {1, "Monday"},
234         {2, "Tuesday"},
235         {3, "Wednesday"},
236         {4, "Thursday"},
237         {5, "Friday"},
238         {6, "Saturday"},
239         {0, NULL}
240 };
241
242 static int
243 add_word_param(tvbuff_t *tvb, int offset, int count _U_,
244     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
245 {
246         guint16 WParam;
247
248         if (hf_index != -1)
249                 proto_tree_add_item(tree, hf_index, tvb, offset, 2, TRUE);
250         else {
251                 WParam = tvb_get_letohs(tvb, offset);
252                 proto_tree_add_text(tree, tvb, offset, 2,
253                     "Word Param: %u (0x%04X)", WParam, WParam);
254         }
255         offset += 2;
256         return offset;
257 }
258
259 static int
260 add_dword_param(tvbuff_t *tvb, int offset, int count _U_,
261     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
262 {
263         guint32 LParam;
264
265         if (hf_index != -1)
266                 proto_tree_add_item(tree, hf_index, tvb, offset, 4, TRUE);
267         else {
268                 LParam = tvb_get_letohl(tvb, offset);
269                 proto_tree_add_text(tree, tvb, offset, 4,
270                     "Doubleword Param: %u (0x%08X)", LParam, LParam);
271         }
272         offset += 4;
273         return offset;
274 }
275
276 static int
277 add_byte_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
278     proto_tree *tree, int convert _U_, int hf_index)
279 {
280         guint8 BParam;
281
282         if (hf_index != -1)
283                 proto_tree_add_item(tree, hf_index, tvb, offset, count, TRUE);
284         else {
285                 if (count == 1) {
286                         BParam = tvb_get_guint8(tvb, offset);
287                         proto_tree_add_text(tree, tvb, offset, count,
288                             "Byte Param: %u (0x%02X)",
289                             BParam, BParam);
290                 } else {
291                         proto_tree_add_text(tree, tvb, offset, count,
292                             "Byte Param: %s",
293                             tvb_bytes_to_str(tvb, offset, count));
294                 }
295         }
296         offset += count;
297         return offset;
298 }
299
300 static int
301 add_pad_param(tvbuff_t *tvb _U_, int offset, int count, packet_info *pinfo _U_,
302     proto_tree *tree _U_, int convert _U_, int hf_index _U_)
303 {
304         /*
305          * This is for parameters that have descriptor entries but that
306          * are, in practice, just padding.
307          */
308         offset += count;
309         return offset;
310 }
311
312 static void
313 add_null_pointer_param(tvbuff_t *tvb, int offset, int count _U_,
314     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
315 {
316         if (hf_index != -1) {
317                 proto_tree_add_text(tree, tvb, offset, 0,
318                   "%s (Null pointer)",
319                   proto_registrar_get_name(hf_index));
320         } else {
321                 proto_tree_add_text(tree, tvb, offset, 0,
322                     "String Param (Null pointer)");
323         }
324 }
325
326 static int
327 add_string_param(tvbuff_t *tvb, int offset, int count _U_,
328     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
329 {
330         guint string_len;
331
332         string_len = tvb_strsize(tvb, offset);
333         if (hf_index != -1) {
334                 proto_tree_add_item(tree, hf_index, tvb, offset, string_len,
335                     TRUE);
336         } else {
337                 proto_tree_add_text(tree, tvb, offset, string_len,
338                     "String Param: %s",
339                     tvb_format_text(tvb, offset, string_len));
340         }
341         offset += string_len;
342         return offset;
343 }
344
345 static const char *
346 get_stringz_pointer_value(tvbuff_t *tvb, int offset, int convert, int *cptrp,
347     int *lenp)
348 {
349         int cptr;
350         gint string_len;
351
352         /* pointer to string */
353         cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
354         *cptrp = cptr;
355
356         /* string */
357         if (tvb_offset_exists(tvb, cptr) &&
358             (string_len = tvb_strnlen(tvb, cptr, -1)) != -1) {
359                 string_len++;   /* include the terminating '\0' */
360                 *lenp = string_len;
361                 return tvb_format_text(tvb, cptr, string_len - 1);
362         } else
363                 return NULL;
364 }
365
366 static int
367 add_stringz_pointer_param(tvbuff_t *tvb, int offset, int count _U_,
368     packet_info *pinfo _U_, proto_tree *tree, int convert, int hf_index)
369 {
370         int cptr;
371         const char *string;
372         gint string_len;
373
374         string = get_stringz_pointer_value(tvb, offset, convert, &cptr,
375             &string_len);
376         offset += 4;
377
378         /* string */
379         if (string != NULL) {
380                 if (hf_index != -1) {
381                         proto_tree_add_item(tree, hf_index, tvb, cptr,
382                             string_len, TRUE);
383                 } else {
384                         proto_tree_add_text(tree, tvb, cptr, string_len,
385                             "String Param: %s", string);
386                 }
387         } else {
388                 if (hf_index != -1) {
389                         proto_tree_add_text(tree, tvb, 0, 0,
390                             "%s: <String goes past end of frame>",
391                             proto_registrar_get_name(hf_index));
392                 } else {
393                         proto_tree_add_text(tree, tvb, 0, 0,
394                             "String Param: <String goes past end of frame>");
395                 }
396         }
397
398         return offset;
399 }
400
401 static int
402 add_bytes_pointer_param(tvbuff_t *tvb, int offset, int count,
403     packet_info *pinfo _U_, proto_tree *tree, int convert, int hf_index)
404 {
405         int cptr;
406
407         /* pointer to byte array */
408         cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
409         offset += 4;
410
411         /* bytes */
412         if (tvb_bytes_exist(tvb, cptr, count)) {
413                 if (hf_index != -1) {
414                         proto_tree_add_item(tree, hf_index, tvb, cptr,
415                             count, TRUE);
416                 } else {
417                         proto_tree_add_text(tree, tvb, cptr, count,
418                             "Byte Param: %s",
419                             tvb_bytes_to_str(tvb, cptr, count));
420                 }
421         } else {
422                 if (hf_index != -1) {
423                         proto_tree_add_text(tree, tvb, 0, 0,
424                             "%s: <Bytes go past end of frame>",
425                             proto_registrar_get_name(hf_index));
426                 } else {
427                         proto_tree_add_text(tree, tvb, 0, 0,
428                             "Byte Param: <Bytes goes past end of frame>");
429                 }
430         }
431
432         return offset;
433 }
434
435 static int
436 add_detail_level(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo,
437     proto_tree *tree, int convert _U_, int hf_index)
438 {
439         struct smb_info *smb_info = pinfo->private_data;
440         smb_transact_info_t *trp = smb_info->sip->extra_info;
441         guint16 level;
442
443         level = tvb_get_letohs(tvb, offset);
444         if (!pinfo->fd->flags.visited)
445                 trp->info_level = level;        /* remember this for the response */
446         proto_tree_add_uint(tree, hf_index, tvb, offset, 2, level);
447         offset += 2;
448         return offset;
449 }
450
451 static int
452 add_max_uses(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
453     proto_tree *tree, int convert _U_, int hf_index)
454 {
455         guint16 WParam;
456
457         WParam = tvb_get_letohs(tvb, offset);
458         if (WParam == 0xffff) { /* -1 */
459                 proto_tree_add_uint_format(tree, hf_index, tvb,
460                     offset, 2, WParam,
461                     "%s: No limit",
462                     proto_registrar_get_name(hf_index));
463         } else {
464                 proto_tree_add_uint(tree, hf_index, tvb,
465                             offset, 2, WParam);
466         }
467         offset += 2;
468         return offset;
469 }
470
471 static int
472 add_server_type(tvbuff_t *tvb, int offset, int count _U_,
473     packet_info *pinfo, proto_tree *tree, int convert _U_, int hf_index _U_)
474 {
475         offset = dissect_smb_server_type_flags(
476                 tvb, offset, pinfo, tree, NULL, FALSE);
477         return offset;
478 }
479
480 static int
481 add_server_type_info(tvbuff_t *tvb, int offset, int count _U_,
482     packet_info *pinfo, proto_tree *tree, int convert _U_, int hf_index _U_)
483 {
484         offset = dissect_smb_server_type_flags(
485                 tvb, offset, pinfo, tree, NULL, TRUE);
486         return offset;
487 }
488
489 static int
490 add_reltime(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
491     proto_tree *tree, int convert _U_, int hf_index)
492 {
493         nstime_t nstime;
494
495         nstime.secs = tvb_get_letohl(tvb, offset);
496         nstime.nsecs = 0;
497         proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
498             &nstime, "%s: %s", proto_registrar_get_name(hf_index),
499             time_secs_to_str(nstime.secs));
500         offset += 4;
501         return offset;
502 }
503
504 /*
505  * Sigh.  These are for handling Microsoft's annoying almost-UNIX-time-but-
506  * it's-local-time-not-UTC time.
507  */
508 static int
509 add_abstime_common(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_index,
510     const char *absent_name)
511 {
512         nstime_t nstime;
513         struct tm *tmp;
514
515         nstime.secs = tvb_get_letohl(tvb, offset);
516         nstime.nsecs = 0;
517         /*
518          * Sigh.  Sometimes it appears that -1 means "unknown", and
519          * sometimes it appears that 0 means "unknown", for the last
520          * logoff date/time.
521          */
522         if (nstime.secs == -1 || nstime.secs == 0) {
523                 proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
524                     &nstime, "%s: %s", proto_registrar_get_name(hf_index),
525                     absent_name);
526         } else {
527                 /*
528                  * Run it through "gmtime()" to break it down, and then
529                  * run it through "mktime()" to put it back together
530                  * as UTC.
531                  */
532                 tmp = gmtime(&nstime.secs);
533                 tmp->tm_isdst = -1;     /* we don't know if it's DST or not */
534                 nstime.secs = mktime(tmp);
535                 proto_tree_add_time(tree, hf_index, tvb, offset, 4,
536                     &nstime);
537         }
538         offset += 4;
539         return offset;
540 }
541
542 static int
543 add_abstime_absent_never(tvbuff_t *tvb, int offset, int count _U_,
544     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
545 {
546         return add_abstime_common(tvb, offset, tree, hf_index, "Never");
547 }
548
549 static int
550 add_abstime_absent_unknown(tvbuff_t *tvb, int offset, int count _U_,
551     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
552 {
553         return add_abstime_common(tvb, offset, tree, hf_index, "Unknown");
554 }
555
556 static int
557 add_nlogons(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
558     proto_tree *tree, int convert _U_, int hf_index)
559 {
560         guint16 nlogons;
561
562         nlogons = tvb_get_letohs(tvb, offset);
563         if (nlogons == 0xffff)  /* -1 */
564                 proto_tree_add_uint_format(tree, hf_index, tvb, offset, 2,
565                     nlogons, "%s: Unknown",
566                     proto_registrar_get_name(hf_index));
567         else
568                 proto_tree_add_uint(tree, hf_index, tvb, offset, 2,
569                     nlogons);
570         offset += 2;
571         return offset;
572 }
573
574 static int
575 add_max_storage(tvbuff_t *tvb, int offset, int count _U_,
576     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
577 {
578         guint32 max_storage;
579
580         max_storage = tvb_get_letohl(tvb, offset);
581         if (max_storage == 0xffffffff)
582                 proto_tree_add_uint_format(tree, hf_index, tvb, offset, 4,
583                     max_storage, "%s: No limit",
584                     proto_registrar_get_name(hf_index));
585         else
586                 proto_tree_add_uint(tree, hf_index, tvb, offset, 4,
587                     max_storage);
588         offset += 4;
589         return offset;
590 }
591
592 static int
593 add_logon_hours(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
594     proto_tree *tree, int convert, int hf_index)
595 {
596         int cptr;
597
598         /* pointer to byte array */
599         cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
600         offset += 4;
601
602         /* bytes */
603         if (tvb_bytes_exist(tvb, cptr, count)) {
604                 if (count == 21) {
605                         /*
606                          * The logon hours should be exactly 21 bytes long.
607                          *
608                          * XXX - should actually carve up the bits;
609                          * we need the units per week to do that, though.
610                          */
611                         proto_tree_add_item(tree, hf_index, tvb, cptr, count,
612                             TRUE);
613                 } else {
614                         proto_tree_add_bytes_format(tree, hf_index, tvb,
615                             cptr, count, tvb_get_ptr(tvb, cptr, count),
616                             "%s: %s (wrong length, should be 21, is %d",
617                             proto_registrar_get_name(hf_index),
618                             tvb_bytes_to_str(tvb, cptr, count), count);
619                 }
620         } else {
621                 proto_tree_add_text(tree, tvb, 0, 0,
622                     "%s: <Bytes go past end of frame>",
623                     proto_registrar_get_name(hf_index));
624         }
625
626         return offset;
627 }
628
629 static int
630 add_tzoffset(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
631     proto_tree *tree, int convert _U_, int hf_index)
632 {
633         gint16 tzoffset;
634
635         tzoffset = tvb_get_letohs(tvb, offset);
636         if (tzoffset < 0) {
637                 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
638                     tzoffset, "%s: %s east of UTC",
639                     proto_registrar_get_name(hf_index),
640                     time_secs_to_str(-tzoffset*60));
641         } else if (tzoffset > 0) {
642                 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
643                     tzoffset, "%s: %s west of UTC",
644                     proto_registrar_get_name(hf_index),
645                     time_secs_to_str(tzoffset*60));
646         } else {
647                 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
648                     tzoffset, "%s: at UTC",
649                     proto_registrar_get_name(hf_index));
650         }
651         offset += 2;
652         return offset;
653 }
654
655 static int
656 add_timeinterval(tvbuff_t *tvb, int offset, int count _U_,
657     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
658 {
659         guint16 timeinterval;
660
661         timeinterval = tvb_get_letohs(tvb, offset);
662         proto_tree_add_uint_format(tree, hf_timeinterval, tvb, offset, 2,
663            timeinterval, "%s: %f seconds", proto_registrar_get_name(hf_index),
664            timeinterval*.0001);
665         offset += 2;
666         return offset;
667 }
668
669 static int
670 add_logon_args(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
671     proto_tree *tree, int convert _U_, int hf_index _U_)
672 {
673         if (count != 54) {
674                 proto_tree_add_text(tree, tvb, offset, count,
675                    "Bogus NetWkstaUserLogon parameters: length is %d, should be 54",
676                    count);
677                 offset += count;
678                 return offset;
679         }
680
681         /* user name */
682         proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
683         offset += 21;
684
685         /* pad1 */
686         offset += 1;
687
688         /* password */
689         proto_tree_add_item(tree, hf_password, tvb, offset, 15, TRUE);
690         offset += 15;
691
692         /* pad2 */
693         offset += 1;
694
695         /* workstation name */
696         proto_tree_add_item(tree, hf_workstation_name, tvb, offset, 16, TRUE);
697         offset += 16;
698         return offset;
699 }
700
701 /*
702  * The following data structure describes the Remote API requests we
703  * understand.
704  *
705  * Simply fill in the number and parameter information.
706  * Try to keep them in order.
707  *
708  * We will extend this data structure as we try to decode more.
709  */
710
711 /*
712  * This is a pointer to a function to process an item.
713  */
714 typedef int     (*item_func)(tvbuff_t *, int, int, packet_info *, proto_tree *,
715                              int, int);
716
717 /*
718  * Type of an item; determines what parameter strings are valid for
719  * the item.
720  */
721 typedef enum {
722         PARAM_NONE,     /* for the end-of-list stopper */
723         PARAM_WORD,     /* 'W' or 'h' - 16-bit word */
724         PARAM_DWORD,    /* 'D' or 'i' - 32-bit word */
725         PARAM_BYTES,    /* 'B' or 'b' or 'g' or 'O' - one or more bytes */
726         PARAM_STRINGZ,  /* 'z' or 'O' - null-terminated string */
727 } param_type_t;
728
729 /*
730  * This structure describes an item; "hf_index" points to the index
731  * for the field corresponding to that item, "func" points to the
732  * function to use to add that item to the tree, and "type" is the
733  * type that the item is supposed to have.
734  */
735 typedef struct {
736         int             *hf_index;
737         item_func       func;
738         param_type_t    type;
739 } item_t;
740
741 /*
742  * This structure describes a list of items; each list of items
743  * has a corresponding detail level.
744  */
745 typedef struct {
746         int             level;
747         const item_t    *item_list;
748 } item_list_t;
749
750 struct lanman_desc {
751         int             lanman_num;
752         const item_t    *req;
753         proto_item      *(*req_data_item)(tvbuff_t *, packet_info *,
754                                           proto_tree *, int);
755         gint            *ett_req_data;
756         const item_t    *req_data;
757         const item_t    *req_aux_data;
758         const item_t    *resp;
759         const gchar     *resp_data_entry_list_label;
760         gint            *ett_data_entry_list;
761         proto_item      *(*resp_data_element_item)(tvbuff_t *, proto_tree *,
762                                                    int);
763         gint            *ett_resp_data_element_item;
764         const item_list_t *resp_data_list;
765         const item_t    *resp_aux_data;
766 };
767
768 static int no_hf = -1;  /* for padding crap */
769
770 static const item_t lm_params_req_netshareenum[] = {
771         { &hf_detail_level, add_detail_level, PARAM_WORD },
772         { &hf_recv_buf_len, add_word_param, PARAM_WORD },
773         { NULL, NULL, PARAM_NONE }
774 };
775
776 static const item_t lm_params_resp_netshareenum[] = {
777         { &hf_acount, add_word_param, PARAM_WORD },
778         { NULL, NULL, PARAM_NONE }
779 };
780
781 /*
782  * Create a subtree for a share.
783  */
784 static proto_item *
785 netshareenum_share_entry(tvbuff_t *tvb, proto_tree *tree, int offset)
786 {
787         if (tree) {
788                 return proto_tree_add_text(tree, tvb, offset, -1,
789                     "Share %.13s", tvb_get_ptr(tvb, offset, 13));
790         } else
791                 return NULL;
792 }
793
794 static const item_t lm_null[] = {
795         { NULL, NULL, PARAM_NONE }
796 };
797
798 static const item_list_t lm_null_list[] = {
799         { -1, lm_null }
800 };
801
802 static const item_t lm_data_resp_netshareenum_1[] = {
803         { &hf_share_name, add_byte_param, PARAM_BYTES },
804         { &no_hf, add_pad_param, PARAM_BYTES },
805         { &hf_share_type, add_word_param, PARAM_WORD },
806         { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
807         { NULL, NULL, PARAM_NONE }
808 };
809
810 static const item_list_t lm_data_resp_netshareenum[] = {
811         { 1, lm_data_resp_netshareenum_1 },
812         { -1, lm_null }
813 };
814
815 static const item_t lm_params_req_netsharegetinfo[] = {
816         { &hf_share_name, add_string_param, PARAM_STRINGZ },
817         { &hf_detail_level, add_detail_level, PARAM_WORD },
818         { NULL, NULL, PARAM_NONE }
819 };
820
821 static const item_t lm_params_resp_netsharegetinfo[] = {
822         { &hf_abytes, add_word_param, PARAM_WORD },
823         { NULL, NULL, PARAM_NONE }
824 };
825
826 static const item_t lm_data_resp_netsharegetinfo_0[] = {
827         { &hf_share_name, add_byte_param, PARAM_BYTES },
828         { NULL, NULL, PARAM_NONE }
829 };
830
831 static const item_t lm_data_resp_netsharegetinfo_1[] = {
832         { &hf_share_name, add_byte_param, PARAM_BYTES },
833         { &no_hf, add_pad_param, PARAM_BYTES },
834         { &hf_share_type, add_word_param, PARAM_WORD },
835         { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
836         { NULL, NULL, PARAM_NONE }
837 };
838
839 static const item_t lm_data_resp_netsharegetinfo_2[] = {
840         { &hf_share_name, add_byte_param, PARAM_BYTES },
841         { &no_hf, add_pad_param, PARAM_BYTES },
842         { &hf_share_type, add_word_param, PARAM_WORD },
843         { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
844         { &hf_share_permissions, add_word_param, PARAM_WORD }, /* XXX - do as bit fields */
845         { &hf_share_max_uses, add_max_uses, PARAM_WORD },
846         { &hf_share_current_uses, add_word_param, PARAM_WORD },
847         { &hf_share_path, add_stringz_pointer_param, PARAM_STRINGZ },
848         { &hf_share_password, add_byte_param, PARAM_BYTES },
849         { NULL, NULL, PARAM_NONE }
850 };
851
852 static const item_list_t lm_data_resp_netsharegetinfo[] = {
853         { 0, lm_data_resp_netsharegetinfo_0 },
854         { 1, lm_data_resp_netsharegetinfo_1 },
855         { 2, lm_data_resp_netsharegetinfo_2 },
856         { -1, lm_null }
857 };
858
859 static const item_t lm_params_req_netservergetinfo[] = {
860         { &hf_detail_level, add_detail_level, PARAM_WORD },
861         { NULL, NULL, PARAM_NONE }
862 };
863
864 static const item_t lm_params_resp_netservergetinfo[] = {
865         { &hf_abytes, add_word_param, PARAM_WORD },
866         { NULL, NULL, PARAM_NONE }
867 };
868
869 static const item_t lm_data_serverinfo_0[] = {
870         { &hf_server_name, add_byte_param, PARAM_BYTES },
871         { NULL, NULL, PARAM_NONE }
872 };
873
874 static const item_t lm_data_serverinfo_1[] = {
875         { &hf_server_name, add_byte_param, PARAM_BYTES },
876         { &hf_server_major, add_byte_param, PARAM_BYTES },
877         { &hf_server_minor, add_byte_param, PARAM_BYTES },
878         { &no_hf, add_server_type, PARAM_DWORD },
879         { &hf_server_comment, add_stringz_pointer_param, PARAM_STRINGZ },
880         { NULL, NULL, PARAM_NONE }
881 };
882
883 static const item_list_t lm_data_serverinfo[] = {
884         { 0, lm_data_serverinfo_0 },
885         { 1, lm_data_serverinfo_1 },
886         { -1, lm_null }
887 };
888
889 static const item_t lm_params_req_netusergetinfo[] = {
890         { &hf_user_name, add_string_param, PARAM_STRINGZ },
891         { &hf_detail_level, add_detail_level, PARAM_WORD },
892         { NULL, NULL, PARAM_NONE }
893 };
894
895 static const item_t lm_params_resp_netusergetinfo[] = {
896         { &hf_abytes, add_word_param, PARAM_WORD },
897         { NULL, NULL, PARAM_NONE }
898 };
899
900 static const item_t lm_data_resp_netusergetinfo_11[] = {
901         { &hf_user_name, add_byte_param, PARAM_BYTES },
902         { &no_hf, add_pad_param, PARAM_BYTES },
903         { &hf_comment, add_stringz_pointer_param, PARAM_STRINGZ },
904         { &hf_user_comment, add_stringz_pointer_param, PARAM_STRINGZ },
905         { &hf_full_name, add_stringz_pointer_param, PARAM_STRINGZ },
906         { &hf_privilege_level, add_word_param, PARAM_WORD },
907         { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
908         { &hf_password_age, add_reltime, PARAM_DWORD },
909         { &hf_homedir, add_stringz_pointer_param, PARAM_STRINGZ },
910         { &hf_parameters, add_stringz_pointer_param, PARAM_STRINGZ },
911         { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
912         { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
913         { &hf_bad_pw_count, add_word_param, PARAM_WORD },
914         { &hf_num_logons, add_nlogons, PARAM_WORD },
915         { &hf_logon_server, add_stringz_pointer_param, PARAM_STRINGZ },
916         { &hf_country_code, add_word_param, PARAM_WORD },
917         { &hf_workstations, add_stringz_pointer_param, PARAM_STRINGZ },
918         { &hf_max_storage, add_max_storage, PARAM_DWORD },
919         { &hf_units_per_week, add_word_param, PARAM_WORD },
920         { &hf_logon_hours, add_logon_hours, PARAM_BYTES },
921         { &hf_code_page, add_word_param, PARAM_WORD },
922         { NULL, NULL, PARAM_NONE }
923 };
924
925 static const item_list_t lm_data_resp_netusergetinfo[] = {
926         { 11, lm_data_resp_netusergetinfo_11 },
927         { -1, lm_null }
928 };
929
930 static const item_t lm_params_req_netusergetgroups[] = {
931         { &hf_user_name, add_string_param, PARAM_STRINGZ },
932         { &hf_detail_level, add_detail_level, PARAM_WORD },
933         { NULL, NULL, PARAM_NONE }
934 };
935
936 static const item_t lm_params_resp_netusergetgroups[] = {
937         { &hf_abytes, add_word_param, PARAM_WORD },
938         { NULL, NULL, PARAM_NONE }
939 };
940
941 static const item_t lm_data_resp_netusergetgroups_0[] = {
942         { &hf_group_name, add_byte_param, PARAM_BYTES },
943         { NULL, NULL, PARAM_NONE }
944 };
945
946 static const item_list_t lm_data_resp_netusergetgroups[] = {
947         { 0, lm_data_resp_netusergetgroups_0 },
948         { -1, lm_null }
949 };
950
951 /*
952  * Has no detail level; make it the default.
953  */
954 static const item_t lm_data_resp_netremotetod_nolevel[] = {
955         { &hf_current_time, add_abstime_absent_unknown, PARAM_DWORD },
956         { &hf_msecs, add_dword_param, PARAM_DWORD },
957         { &hf_hour, add_byte_param, PARAM_BYTES },
958         { &hf_minute, add_byte_param, PARAM_BYTES },
959         { &hf_second, add_byte_param, PARAM_BYTES },
960         { &hf_hundredths, add_byte_param, PARAM_BYTES },
961         { &hf_tzoffset, add_tzoffset, PARAM_WORD },
962         { &hf_timeinterval, add_timeinterval, PARAM_WORD },
963         { &hf_day, add_byte_param, PARAM_BYTES },
964         { &hf_month, add_byte_param, PARAM_BYTES },
965         { &hf_year, add_word_param, PARAM_WORD },
966         { &hf_weekday, add_byte_param, PARAM_BYTES },
967         { NULL, NULL, PARAM_NONE }
968 };
969
970 static const item_list_t lm_data_resp_netremotetod[] = {
971         { -1, lm_data_resp_netremotetod_nolevel },
972 };
973
974 static const item_t lm_params_req_netserverenum2[] = {
975         { &hf_detail_level, add_detail_level, PARAM_WORD },
976         { &no_hf, add_server_type_info, PARAM_DWORD },
977         { &hf_enumeration_domain, add_string_param, PARAM_STRINGZ },
978         { NULL, NULL, PARAM_NONE }
979 };
980
981 /*
982  * Create a subtree for a server.
983  */
984 static proto_item *
985 netserverenum2_server_entry(tvbuff_t *tvb, proto_tree *tree, int offset)
986 {
987         if (tree) {
988                 return proto_tree_add_text(tree, tvb, offset, -1,
989                             "Server %.16s", tvb_get_ptr(tvb, offset, 16));
990         } else
991                 return NULL;
992 }
993
994 static const item_t lm_params_resp_netserverenum2[] = {
995         { &hf_acount, add_word_param, PARAM_WORD },
996         { NULL, NULL, PARAM_NONE }
997 };
998
999 static const item_t lm_params_req_netwkstagetinfo[] = {
1000         { &hf_detail_level, add_detail_level, PARAM_WORD },
1001         { NULL, NULL, PARAM_NONE }
1002 };
1003
1004 static const item_t lm_params_resp_netwkstagetinfo[] = {
1005         { &hf_abytes, add_word_param, PARAM_WORD },
1006         { NULL, NULL, PARAM_NONE }
1007 };
1008
1009 static const item_t lm_data_resp_netwkstagetinfo_10[] = {
1010         { &hf_computer_name, add_stringz_pointer_param, PARAM_STRINGZ },
1011         { &hf_user_name, add_stringz_pointer_param, PARAM_STRINGZ },
1012         { &hf_workstation_domain, add_stringz_pointer_param, PARAM_STRINGZ },
1013         { &hf_workstation_major, add_byte_param, PARAM_BYTES },
1014         { &hf_workstation_minor, add_byte_param, PARAM_BYTES },
1015         { &hf_logon_domain, add_stringz_pointer_param, PARAM_STRINGZ },
1016         { &hf_other_domains, add_stringz_pointer_param, PARAM_STRINGZ },
1017         { NULL, NULL, PARAM_NONE }
1018 };
1019
1020 static const item_list_t lm_data_resp_netwkstagetinfo[] = {
1021         { 10, lm_data_resp_netwkstagetinfo_10 },
1022         { -1, lm_null }
1023 };
1024
1025 static const item_t lm_params_req_netwkstauserlogon[] = {
1026         { &no_hf, add_stringz_pointer_param, PARAM_STRINGZ },
1027         { &no_hf, add_stringz_pointer_param, PARAM_STRINGZ },
1028         { &hf_detail_level, add_detail_level, PARAM_WORD },
1029         { &no_hf, add_logon_args, PARAM_BYTES },
1030         { &hf_ustruct_size, add_word_param, PARAM_WORD },
1031         { NULL, NULL, PARAM_NONE }
1032 };
1033
1034 static const item_t lm_params_resp_netwkstauserlogon[] = {
1035         { &hf_abytes, add_word_param, PARAM_WORD },
1036         { NULL, NULL, PARAM_NONE }
1037 };
1038
1039 static const item_t lm_data_resp_netwkstauserlogon_1[] = {
1040         { &hf_logon_code, add_word_param, PARAM_WORD },
1041         { &hf_user_name, add_byte_param, PARAM_BYTES },
1042         { &no_hf, add_pad_param, PARAM_BYTES },
1043         { &hf_privilege_level, add_word_param, PARAM_WORD },
1044         { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
1045         { &hf_num_logons, add_nlogons, PARAM_WORD },
1046         { &hf_bad_pw_count, add_word_param, PARAM_WORD },
1047         { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
1048         { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
1049         { &hf_logoff_time, add_abstime_absent_never, PARAM_DWORD },
1050         { &hf_kickoff_time, add_abstime_absent_never, PARAM_DWORD },
1051         { &hf_password_age, add_reltime, PARAM_DWORD },
1052         { &hf_password_can_change, add_abstime_absent_never, PARAM_DWORD },
1053         { &hf_password_must_change, add_abstime_absent_never, PARAM_DWORD },
1054         { &hf_server_name, add_stringz_pointer_param, PARAM_STRINGZ },
1055         { &hf_logon_domain, add_stringz_pointer_param, PARAM_STRINGZ },
1056         { &hf_script_path, add_stringz_pointer_param, PARAM_STRINGZ },
1057         { &hf_reserved, add_dword_param, PARAM_DWORD },
1058         { NULL, NULL, PARAM_NONE }
1059 };
1060
1061 static const item_list_t lm_data_resp_netwkstauserlogon[] = {
1062         { 1, lm_data_resp_netwkstauserlogon_1 },
1063         { -1, lm_null }
1064 };
1065
1066 static const item_t lm_params_req_netwkstauserlogoff[] = {
1067         { &hf_user_name, add_byte_param, PARAM_BYTES },
1068         { &no_hf, add_pad_param, PARAM_BYTES },
1069         { &hf_workstation_name, add_byte_param, PARAM_BYTES },
1070         { NULL, NULL, PARAM_NONE }
1071 };
1072
1073 static const item_t lm_params_resp_netwkstauserlogoff[] = {
1074         { &hf_abytes, add_word_param, PARAM_WORD },
1075         { NULL, NULL, PARAM_NONE }
1076 };
1077
1078 static const item_t lm_data_resp_netwkstauserlogoff_1[] = {
1079         { &hf_logoff_code, add_word_param, PARAM_WORD },
1080         { &hf_duration, add_reltime, PARAM_DWORD },
1081         { &hf_num_logons, add_nlogons, PARAM_WORD },
1082         { NULL, NULL, PARAM_NONE }
1083 };
1084
1085 static const item_list_t lm_data_resp_netwkstauserlogoff[] = {
1086         { 1, lm_data_resp_netwkstauserlogoff_1 },
1087         { -1, lm_null }
1088 };
1089
1090 static const item_t lm_params_req_samoemchangepassword[] = {
1091         { &hf_user_name, add_string_param, PARAM_STRINGZ },
1092         { NULL, NULL, PARAM_NONE }
1093 };
1094
1095 static const item_t lm_data_req_samoemchangepassword[] = {
1096         { &hf_new_password, add_byte_param, PARAM_BYTES },
1097         { &hf_old_password, add_byte_param, PARAM_BYTES },
1098         { NULL, NULL, PARAM_NONE }
1099 };
1100
1101 #define API_NetShareEnum                0
1102 #define API_NetShareGetInfo             1
1103 #define API_NetShareSetInfo             2
1104 #define API_NetShareAdd                 3
1105 #define API_NetShareDel                 4
1106 #define API_NetShareCheck               5
1107 #define API_NetSessionEnum              6
1108 #define API_NetSessionGetInfo           7
1109 #define API_NetSessionDel               8
1110 #define API_WconnectionEnum             9
1111 #define API_NetFileEnum                 10
1112 #define API_NetFileGetInfo              11
1113 #define API_NetFileClose                12
1114 #define API_NetServerGetInfo            13
1115 #define API_NetServerSetInfo            14
1116 #define API_NetServerDiskEnum           15
1117 #define API_NetServerAdminCommand       16
1118 #define API_NetAuditOpen                17
1119 #define API_NetAuditClear               18
1120 #define API_NetErrorLogOpen             19
1121 #define API_NetErrorLogClear            20
1122 #define API_NetCharDevEnum              21
1123 #define API_NetCharDevGetInfo           22
1124 #define API_NetCharDevControl           23
1125 #define API_NetCharDevQEnum             24
1126 #define API_NetCharDevQGetInfo          25
1127 #define API_NetCharDevQSetInfo          26
1128 #define API_NetCharDevQPurge            27
1129 #define API_NetCharDevQPurgeSelf        28
1130 #define API_NetMessageNameEnum          29
1131 #define API_NetMessageNameGetInfo       30
1132 #define API_NetMessageNameAdd           31
1133 #define API_NetMessageNameDel           32
1134 #define API_NetMessageNameFwd           33
1135 #define API_NetMessageNameUnFwd         34
1136 #define API_NetMessageBufferSend        35
1137 #define API_NetMessageFileSend          36
1138 #define API_NetMessageLogFileSet        37
1139 #define API_NetMessageLogFileGet        38
1140 #define API_NetServiceEnum              39
1141 #define API_NetServiceInstall           40
1142 #define API_NetServiceControl           41
1143 #define API_NetAccessEnum               42
1144 #define API_NetAccessGetInfo            43
1145 #define API_NetAccessSetInfo            44
1146 #define API_NetAccessAdd                45
1147 #define API_NetAccessDel                46
1148 #define API_NetGroupEnum                47
1149 #define API_NetGroupAdd                 48
1150 #define API_NetGroupDel                 49
1151 #define API_NetGroupAddUser             50
1152 #define API_NetGroupDelUser             51
1153 #define API_NetGroupGetUsers            52
1154 #define API_NetUserEnum                 53
1155 #define API_NetUserAdd                  54
1156 #define API_NetUserDel                  55
1157 #define API_NetUserGetInfo              56
1158 #define API_NetUserSetInfo              57
1159 #define API_NetUserPasswordSet          58
1160 #define API_NetUserGetGroups            59
1161 /*This line and number replaced a Dead Entry for 60 */
1162 /*This line and number replaced a Dead Entry for 61 */
1163 #define API_NetWkstaSetUID              62
1164 #define API_NetWkstaGetInfo             63
1165 #define API_NetWkstaSetInfo             64
1166 #define API_NetUseEnum                  65
1167 #define API_NetUseAdd                   66
1168 #define API_NetUseDel                   67
1169 #define API_NetUseGetInfo               68
1170 #define API_WPrintQEnum                 69
1171 #define API_WPrintQGetInfo              70
1172 #define API_WPrintQSetInfo              71
1173 #define API_WPrintQAdd                  72
1174 #define API_WPrintQDel                  73
1175 #define API_WPrintQPause                74
1176 #define API_WPrintQContinue             75
1177 #define API_WPrintJobEnum               76
1178 #define API_WPrintJobGetInfo            77
1179 #define API_WPrintJobSetInfo_OLD        78
1180 /* This line and number replaced a Dead Entry for 79 */
1181 /* This line and number replaced a Dead Entry for 80 */
1182 #define API_WPrintJobDel                81
1183 #define API_WPrintJobPause              82
1184 #define API_WPrintJobContinue           83
1185 #define API_WPrintDestEnum              84
1186 #define API_WPrintDestGetInfo           85
1187 #define API_WPrintDestControl           86
1188 #define API_NetProfileSave              87
1189 #define API_NetProfileLoad              88
1190 #define API_NetStatisticsGet            89
1191 #define API_NetStatisticsClear          90
1192 #define API_NetRemoteTOD                91
1193 #define API_WNetBiosEnum                92
1194 #define API_WNetBiosGetInfo             93
1195 #define API_NetServerEnum               94
1196 #define API_I_NetServerEnum             95
1197 #define API_NetServiceGetInfo           96
1198 /* This line and number replaced a Dead Entry for 97 */
1199 /* This line and number replaced a Dead Entry for 98 */
1200 /* This line and number replaced a Dead Entry for 99 */
1201 /* This line and number replaced a Dead Entry for 100 */
1202 /* This line and number replaced a Dead Entry for 101 */
1203 /* This line and number replaced a Dead Entry for 102 */
1204 #define API_WPrintQPurge                103
1205 #define API_NetServerEnum2              104
1206 #define API_NetAccessGetUserPerms       105
1207 #define API_NetGroupGetInfo             106
1208 #define API_NetGroupSetInfo             107
1209 #define API_NetGroupSetUsers            108
1210 #define API_NetUserSetGroups            109
1211 #define API_NetUserModalsGet            110
1212 #define API_NetUserModalsSet            111
1213 #define API_NetFileEnum2                112
1214 #define API_NetUserAdd2                 113
1215 #define API_NetUserSetInfo2             114
1216 #define API_NetUserPasswordSet2         115
1217 #define API_I_NetServerEnum2            116
1218 #define API_NetConfigGet2               117
1219 #define API_NetConfigGetAll2            118
1220 #define API_NetGetDCName                119
1221 #define API_NetHandleGetInfo            120
1222 #define API_NetHandleSetInfo            121
1223 #define API_NetStatisticsGet2           122
1224 #define API_WBuildGetInfo               123
1225 #define API_NetFileGetInfo2             124
1226 #define API_NetFileClose2               125
1227 #define API_NetServerReqChallenge       126
1228 #define API_NetServerAuthenticate       127
1229 #define API_NetServerPasswordSet        128
1230 #define API_WNetAccountDeltas           129
1231 #define API_WNetAccountSync             130
1232 #define API_NetUserEnum2                131
1233 #define API_NetWkstaUserLogon           132
1234 #define API_NetWkstaUserLogoff          133
1235 #define API_NetLogonEnum                134
1236 #define API_NetErrorLogRead             135
1237 #define API_I_NetPathType               136
1238 #define API_I_NetPathCanonicalize       137
1239 #define API_I_NetPathCompare            138
1240 #define API_I_NetNameValidate           139
1241 #define API_I_NetNameCanonicalize       140
1242 #define API_I_NetNameCompare            141
1243 #define API_NetAuditRead                142
1244 #define API_WPrintDestAdd               143
1245 #define API_WPrintDestSetInfo           144
1246 #define API_WPrintDestDel               145
1247 #define API_NetUserValidate2            146
1248 #define API_WPrintJobSetInfo            147
1249 #define API_TI_NetServerDiskEnum        148
1250 #define API_TI_NetServerDiskGetInfo     149
1251 #define API_TI_FTVerifyMirror           150
1252 #define API_TI_FTAbortVerify            151
1253 #define API_TI_FTGetInfo                152
1254 #define API_TI_FTSetInfo                153
1255 #define API_TI_FTLockDisk               154
1256 #define API_TI_FTFixError               155
1257 #define API_TI_FTAbortFix               156
1258 #define API_TI_FTDiagnoseError          157
1259 #define API_TI_FTGetDriveStats          158
1260 /* This line and number replaced a Dead Entry for 159 */
1261 #define API_TI_FTErrorGetInfo           160
1262 /* This line and number replaced a Dead Entry for 161 */
1263 /* This line and number replaced a Dead Entry for 162 */
1264 #define API_NetAccessCheck              163
1265 #define API_NetAlertRaise               164
1266 #define API_NetAlertStart               165
1267 #define API_NetAlertStop                166
1268 #define API_NetAuditWrite               167
1269 #define API_NetIRemoteAPI               168
1270 #define API_NetServiceStatus            169
1271 #define API_I_NetServerRegister         170
1272 #define API_I_NetServerDeregister       171
1273 #define API_I_NetSessionEntryMake       172
1274 #define API_I_NetSessionEntryClear      173
1275 #define API_I_NetSessionEntryGetInfo    174
1276 #define API_I_NetSessionEntrySetInfo    175
1277 #define API_I_NetConnectionEntryMake    176
1278 #define API_I_NetConnectionEntryClear   177
1279 #define API_I_NetConnectionEntrySetInfo 178
1280 #define API_I_NetConnectionEntryGetInfo 179
1281 #define API_I_NetFileEntryMake          180
1282 #define API_I_NetFileEntryClear         181
1283 #define API_I_NetFileEntrySetInfo       182
1284 #define API_I_NetFileEntryGetInfo       183
1285 #define API_AltSrvMessageBufferSend     184
1286 #define API_AltSrvMessageFileSend       185
1287 #define API_wI_NetRplWkstaEnum          186
1288 #define API_wI_NetRplWkstaGetInfo       187
1289 #define API_wI_NetRplWkstaSetInfo       188
1290 #define API_wI_NetRplWkstaAdd           189
1291 #define API_wI_NetRplWkstaDel           190
1292 #define API_wI_NetRplProfileEnum        191
1293 #define API_wI_NetRplProfileGetInfo     192
1294 #define API_wI_NetRplProfileSetInfo     193
1295 #define API_wI_NetRplProfileAdd         194
1296 #define API_wI_NetRplProfileDel         195
1297 #define API_wI_NetRplProfileClone       196
1298 #define API_wI_NetRplBaseProfileEnum    197
1299 /* This line and number replaced a Dead Entry for 198 */
1300 /* This line and number replaced a Dead Entry for 199 */
1301 /* This line and number replaced a Dead Entry for 200 */
1302 #define API_WIServerSetInfo             201
1303 /* This line and number replaced a Dead Entry for 202 */
1304 /* This line and number replaced a Dead Entry for 203 */
1305 /* This line and number replaced a Dead Entry for 204 */
1306 #define API_WPrintDriverEnum            205
1307 #define API_WPrintQProcessorEnum        206
1308 #define API_WPrintPortEnum              207
1309 #define API_WNetWriteUpdateLog          208
1310 #define API_WNetAccountUpdate           209
1311 #define API_WNetAccountConfirmUpdate    210
1312 #define API_NetConfigSet                211
1313 #define API_WAccountsReplicate          212
1314 /* 213 is used by WfW */
1315 #define API_SamOEMChgPasswordUser2_P    214
1316 #define API_NetServerEnum3              215
1317 /* XXX - what about 216 through 249? */
1318 #define API_WPrintDriverGetInfo         250
1319 #define API_WPrintDriverSetInfo         251
1320 #define API_NetAliasAdd                 252
1321 #define API_NetAliasDel                 253
1322 #define API_NetAliasGetInfo             254
1323 #define API_NetAliasSetInfo             255
1324 #define API_NetAliasEnum                256
1325 #define API_NetUserGetLogonAsn          257
1326 #define API_NetUserSetLogonAsn          258
1327 #define API_NetUserGetAppSel            259
1328 #define API_NetUserSetAppSel            260
1329 #define API_NetAppAdd                   261
1330 #define API_NetAppDel                   262
1331 #define API_NetAppGetInfo               263
1332 #define API_NetAppSetInfo               264
1333 #define API_NetAppEnum                  265
1334 #define API_NetUserDCDBInit             266
1335 #define API_NetDASDAdd                  267
1336 #define API_NetDASDDel                  268
1337 #define API_NetDASDGetInfo              269
1338 #define API_NetDASDSetInfo              270
1339 #define API_NetDASDEnum                 271
1340 #define API_NetDASDCheck                272
1341 #define API_NetDASDCtl                  273
1342 #define API_NetUserRemoteLogonCheck     274
1343 #define API_NetUserPasswordSet3         275
1344 #define API_NetCreateRIPLMachine        276
1345 #define API_NetDeleteRIPLMachine        277
1346 #define API_NetGetRIPLMachineInfo       278
1347 #define API_NetSetRIPLMachineInfo       279
1348 #define API_NetEnumRIPLMachine          280
1349 #define API_I_ShareAdd                  281
1350 #define API_I_AliasEnum                 282
1351 #define API_NetAccessApply              283
1352 #define API_WPrt16Query                 284
1353 #define API_WPrt16Set                   285
1354 #define API_NetUserDel100               286
1355 #define API_NetUserRemoteLogonCheck2    287
1356 #define API_WRemoteTODSet               294
1357 #define API_WPrintJobMoveAll            295
1358 #define API_W16AppParmAdd               296
1359 #define API_W16AppParmDel               297
1360 #define API_W16AppParmGet               298
1361 #define API_W16AppParmSet               299
1362 #define API_W16RIPLMachineCreate        300
1363 #define API_W16RIPLMachineGetInfo       301
1364 #define API_W16RIPLMachineSetInfo       302
1365 #define API_W16RIPLMachineEnum          303
1366 #define API_W16RIPLMachineListParmEnum  304
1367 #define API_W16RIPLMachClassGetInfo     305
1368 #define API_W16RIPLMachClassEnum        306
1369 #define API_W16RIPLMachClassCreate      307
1370 #define API_W16RIPLMachClassSetInfo     308
1371 #define API_W16RIPLMachClassDelete      309
1372 #define API_W16RIPLMachClassLPEnum      310
1373 #define API_W16RIPLMachineDelete        311
1374 #define API_W16WSLevelGetInfo           312
1375 #define API_NetServerNameAdd            313
1376 #define API_NetServerNameDel            314
1377 #define API_NetServerNameEnum           315
1378 #define API_I_WDASDEnum                 316
1379 #define API_I_WDASDEnumTerminate        317
1380 #define API_I_WDASDSetInfo2             318
1381
1382 static const struct lanman_desc lmd[] = {
1383         { API_NetShareEnum,
1384           lm_params_req_netshareenum,
1385           NULL,
1386           NULL,
1387           lm_null,
1388           lm_null,
1389           lm_params_resp_netshareenum,
1390           "Available Shares",
1391           &ett_lanman_shares,
1392           netshareenum_share_entry,
1393           &ett_lanman_share,
1394           lm_data_resp_netshareenum,
1395           lm_null },
1396
1397         { API_NetShareGetInfo,
1398           lm_params_req_netsharegetinfo,
1399           NULL,
1400           NULL,
1401           lm_null,
1402           lm_null,
1403           lm_params_resp_netsharegetinfo,
1404           NULL,
1405           NULL,
1406           NULL,
1407           NULL,
1408           lm_data_resp_netsharegetinfo,
1409           lm_null },
1410
1411         { API_NetServerGetInfo,
1412           lm_params_req_netservergetinfo,
1413           NULL,
1414           NULL,
1415           lm_null,
1416           lm_null,
1417           lm_params_resp_netservergetinfo,
1418           NULL,
1419           NULL,
1420           NULL,
1421           NULL,
1422           lm_data_serverinfo,
1423           lm_null },
1424
1425         { API_NetUserGetInfo,
1426           lm_params_req_netusergetinfo,
1427           NULL,
1428           NULL,
1429           lm_null,
1430           lm_null,
1431           lm_params_resp_netusergetinfo,
1432           NULL,
1433           NULL,
1434           NULL,
1435           NULL,
1436           lm_data_resp_netusergetinfo,
1437           lm_null },
1438
1439         { API_NetUserGetGroups,
1440           lm_params_req_netusergetgroups,
1441           NULL,
1442           NULL,
1443           lm_null,
1444           lm_null,
1445           lm_params_resp_netusergetgroups,
1446           "Groups",
1447           &ett_lanman_groups,
1448           NULL,
1449           NULL,
1450           lm_data_resp_netusergetgroups,
1451           lm_null },
1452
1453         { API_NetRemoteTOD,
1454           lm_null,
1455           NULL,
1456           NULL,
1457           lm_null,
1458           lm_null,
1459           lm_null,
1460           NULL,
1461           NULL,
1462           NULL,
1463           NULL,
1464           lm_data_resp_netremotetod,
1465           lm_null },
1466
1467         { API_NetServerEnum2,
1468           lm_params_req_netserverenum2,
1469           NULL,
1470           NULL,
1471           lm_null,
1472           lm_null,
1473           lm_params_resp_netserverenum2,
1474           "Servers",
1475           &ett_lanman_servers,
1476           netserverenum2_server_entry,
1477           &ett_lanman_server,
1478           lm_data_serverinfo,
1479           lm_null },
1480
1481         { API_NetWkstaGetInfo,
1482           lm_params_req_netwkstagetinfo,
1483           NULL,
1484           NULL,
1485           lm_null,
1486           lm_null,
1487           lm_params_resp_netwkstagetinfo,
1488           NULL,
1489           NULL,
1490           NULL,
1491           NULL,
1492           lm_data_resp_netwkstagetinfo,
1493           lm_null },
1494
1495         { API_NetWkstaUserLogon,
1496           lm_params_req_netwkstauserlogon,
1497           NULL,
1498           NULL,
1499           lm_null,
1500           lm_null,
1501           lm_params_resp_netwkstauserlogon,
1502           NULL,
1503           NULL,
1504           NULL,
1505           NULL,
1506           lm_data_resp_netwkstauserlogon,
1507           lm_null },
1508
1509         { API_NetWkstaUserLogoff,
1510           lm_params_req_netwkstauserlogoff,
1511           NULL,
1512           NULL,
1513           lm_null,
1514           lm_null,
1515           lm_params_resp_netwkstauserlogoff,
1516           NULL,
1517           NULL,
1518           NULL,
1519           NULL,
1520           lm_data_resp_netwkstauserlogoff,
1521           lm_null },
1522
1523         { API_SamOEMChgPasswordUser2_P,
1524           lm_params_req_samoemchangepassword,
1525           NULL,
1526           NULL,
1527           lm_data_req_samoemchangepassword,
1528           lm_null,
1529           lm_null,
1530           NULL,
1531           NULL,
1532           NULL,
1533           NULL,
1534           lm_null_list,
1535           lm_null },
1536
1537         { -1,
1538           lm_null,
1539           NULL,
1540           NULL,
1541           lm_null,
1542           lm_null,
1543           lm_null,
1544           NULL,
1545           NULL,
1546           NULL,
1547           &ett_lanman_unknown_entry,
1548           lm_null_list,
1549           lm_null }
1550 };
1551
1552 static const struct lanman_desc *
1553 find_lanman(int lanman_num)
1554 {
1555         int i;
1556
1557         for (i = 0; lmd[i].lanman_num != -1; i++) {
1558                 if (lmd[i].lanman_num == lanman_num)
1559                         break;
1560         }
1561         return &lmd[i];
1562 }
1563
1564 static const guchar *
1565 get_count(const guchar *desc, int *countp)
1566 {
1567         int count = 0;
1568         guchar c;
1569
1570         if (!isdigit(*desc)) {
1571                 *countp = 1;    /* no count was supplied */
1572                 return desc;
1573         }
1574
1575         while ((c = *desc) != '\0' && isdigit(c)) {
1576                 count = (count * 10) + c - '0';
1577                 desc++;
1578         }
1579
1580         *countp = count;        /* XXX - what if it's 0? */
1581         return desc;
1582 }
1583
1584 static int
1585 dissect_request_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
1586     proto_tree *tree, const guchar *desc, const item_t *items,
1587     gboolean *has_data_p)
1588 {
1589         guint c;
1590         guint16 WParam;
1591         guint32 LParam;
1592         guint string_len;
1593         int count;
1594
1595         *has_data_p = FALSE;
1596         while ((c = *desc++) != '\0') {
1597                 switch (c) {
1598
1599                 case 'W':
1600                         /*
1601                          * A 16-bit word value in the request.
1602                          */
1603                         if (items->func == NULL) {
1604                                 /*
1605                                  * We've run out of items in the table;
1606                                  * fall back on the default.
1607                                  */
1608                                 offset = add_word_param(tvb, offset, 0, pinfo,
1609                                     tree, 0, -1);
1610                         } else if (items->type != PARAM_WORD) {
1611                                 /*
1612                                  * Descriptor character is 'W', but this
1613                                  * isn't a word parameter.
1614                                  */
1615                                 WParam = tvb_get_letohs(tvb, offset);
1616                                 proto_tree_add_text(tree, tvb, offset, 2,
1617                                     "%s: Value is %u (0x%04X), type is wrong (W)",
1618                                     (*items->hf_index == -1) ?
1619                                       "Word Param" :
1620                                       proto_registrar_get_name(*items->hf_index),
1621                                     WParam, WParam);
1622                                 offset += 2;
1623                                 items++;
1624                         } else {
1625                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1626                                     tree, 0, *items->hf_index);
1627                                 items++;
1628                         }
1629                         break;
1630
1631                 case 'D':
1632                         /*
1633                          * A 32-bit doubleword value in the request.
1634                          */
1635                         if (items->func == NULL) {
1636                                 /*
1637                                  * We've run out of items in the table;
1638                                  * fall back on the default.
1639                                  */
1640                                 offset = add_dword_param(tvb, offset, 0, pinfo,
1641                                     tree, 0, -1);
1642                         } else if (items->type != PARAM_DWORD) {
1643                                 /*
1644                                  * Descriptor character is 'D', but this
1645                                  * isn't a doubleword parameter.
1646                                  */
1647                                 LParam = tvb_get_letohl(tvb, offset);
1648                                 proto_tree_add_text(tree, tvb, offset, 2,
1649                                     "%s: Value is %u (0x%08X), type is wrong (D)",
1650                                     (*items->hf_index == -1) ?
1651                                       "Doubleword Param" :
1652                                       proto_registrar_get_name(*items->hf_index),
1653                                     LParam, LParam);
1654                                 offset += 4;
1655                                 items++;
1656                         } else {
1657                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1658                                     tree, 0, *items->hf_index);
1659                                 items++;
1660                         }
1661                         break;
1662
1663                 case 'b':
1664                         /*
1665                          * A byte or multi-byte value in the request.
1666                          */
1667                         desc = get_count(desc, &count);
1668                         if (items->func == NULL) {
1669                                 /*
1670                                  * We've run out of items in the table;
1671                                  * fall back on the default.
1672                                  */
1673                                 offset = add_byte_param(tvb, offset, count,
1674                                     pinfo, tree, 0, -1);
1675                         } else if (items->type != PARAM_BYTES) {
1676                                 /*
1677                                  * Descriptor character is 'b', but this
1678                                  * isn't a byte/bytes parameter.
1679                                  */
1680                                 proto_tree_add_text(tree, tvb, offset, count,
1681                                     "%s: Value is %s, type is wrong (b)",
1682                                     (*items->hf_index == -1) ?
1683                                       "Byte Param" :
1684                                       proto_registrar_get_name(*items->hf_index),
1685                                     tvb_bytes_to_str(tvb, offset, count));
1686                                 offset += count;
1687                                 items++;
1688                         } else {
1689                                 offset = (*items->func)(tvb, offset, count,
1690                                     pinfo, tree, 0, *items->hf_index);
1691                                 items++;
1692                         }
1693                         break;
1694
1695                 case 'O':
1696                         /*
1697                          * A null pointer.
1698                          */
1699                         if (items->func == NULL) {
1700                                 /*
1701                                  * We've run out of items in the table;
1702                                  * fall back on the default.
1703                                  */
1704                                 add_null_pointer_param(tvb, offset, 0,
1705                                     pinfo, tree, 0, -1);
1706                         } else {
1707                                 /*
1708                                  * If "*items->hf_index" is -1, this is
1709                                  * a reserved must-be-null field; don't
1710                                  * clutter the protocol tree by putting
1711                                  * it in.
1712                                  */
1713                                 if (*items->hf_index != -1) {
1714                                         add_null_pointer_param(tvb,
1715                                             offset, 0, pinfo, tree, 0,
1716                                             *items->hf_index);
1717                                 }
1718                                 items++;
1719                         }
1720                         break;
1721
1722                 case 'z':
1723                         /*
1724                          * A null-terminated ASCII string.
1725                          */
1726                         if (items->func == NULL) {
1727                                 /*
1728                                  * We've run out of items in the table;
1729                                  * fall back on the default.
1730                                  */
1731                                 offset = add_string_param(tvb, offset, 0,
1732                                     pinfo, tree, 0, -1);
1733                         } else if (items->type != PARAM_STRINGZ) {
1734                                 /*
1735                                  * Descriptor character is 'z', but this
1736                                  * isn't a string parameter.
1737                                  */
1738                                 string_len = tvb_strsize(tvb, offset);
1739                                 proto_tree_add_text(tree, tvb, offset, string_len,
1740                                     "%s: Value is %s, type is wrong (z)",
1741                                     (*items->hf_index == -1) ?
1742                                       "String Param" :
1743                                       proto_registrar_get_name(*items->hf_index),
1744                                     tvb_format_text(tvb, offset, string_len));
1745                                 offset += string_len;
1746                                 items++;
1747                         } else {
1748                                 offset = (*items->func)(tvb, offset, 0,
1749                                     pinfo, tree, 0, *items->hf_index);
1750                                 items++;
1751                         }
1752                         break;
1753
1754                 case 'F':
1755                         /*
1756                          * One or more pad bytes.
1757                          */
1758                         desc = get_count(desc, &count);
1759                         proto_tree_add_text(tree, tvb, offset, count,
1760                             "%s", "Padding");
1761                         offset += count;
1762                         break;
1763
1764                 case 'L':
1765                         /*
1766                          * 16-bit receive buffer length.
1767                          */
1768                         proto_tree_add_item(tree, hf_recv_buf_len, tvb,
1769                             offset, 2, TRUE);
1770                         offset += 2;
1771                         break;
1772
1773                 case 's':
1774                         /*
1775                          * 32-bit send buffer offset.
1776                          * This appears not to be sent over the wire.
1777                          */
1778                         *has_data_p = TRUE;
1779                         break;
1780
1781                 case 'T':
1782                         /*
1783                          * 16-bit send buffer length.
1784                          */
1785                         proto_tree_add_item(tree, hf_send_buf_len, tvb,
1786                             offset, 2, TRUE);
1787                         offset += 2;
1788                         break;
1789
1790                 default:
1791                         break;
1792                 }
1793         }
1794         return offset;
1795 }
1796
1797 static int
1798 dissect_response_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
1799     proto_tree *tree, const guchar *desc, const item_t *items,
1800     gboolean *has_data_p, gboolean *has_ent_count_p, guint16 *ent_count_p)
1801 {
1802         guint c;
1803         guint16 WParam;
1804         guint32 LParam;
1805         int count;
1806
1807         *has_data_p = FALSE;
1808         *has_ent_count_p = FALSE;
1809         while ((c = *desc++) != '\0') {
1810                 switch (c) {
1811
1812                 case 'r':
1813                         /*
1814                          * 32-bit receive buffer offset.
1815                          */
1816                         *has_data_p = TRUE;
1817                         break;
1818
1819                 case 'g':
1820                         /*
1821                          * A byte or series of bytes is returned.
1822                          */
1823                         desc = get_count(desc, &count);
1824                         if (items->func == NULL) {
1825                                 /*
1826                                  * We've run out of items in the table;
1827                                  * fall back on the default.
1828                                  */
1829                                 offset = add_byte_param(tvb, offset, count,
1830                                     pinfo, tree, 0, -1);
1831                         } else if (items->type != PARAM_BYTES) {
1832                                 /*
1833                                  * Descriptor character is 'b', but this
1834                                  * isn't a byte/bytes parameter.
1835                                  */
1836                                 proto_tree_add_text(tree, tvb, offset, count,
1837                                     "%s: Value is %s, type is wrong (g)",
1838                                     (*items->hf_index == -1) ?
1839                                       "Byte Param" :
1840                                       proto_registrar_get_name(*items->hf_index),
1841                                     tvb_bytes_to_str(tvb, offset, count));
1842                                 offset += count;
1843                                 items++;
1844                         } else {
1845                                 offset = (*items->func)(tvb, offset, count,
1846                                     pinfo, tree, 0, *items->hf_index);
1847                                 items++;
1848                         }
1849                         break;
1850
1851                 case 'h':
1852                         /*
1853                          * A 16-bit word is received.
1854                          */
1855                         if (items->func == NULL) {
1856                                 /*
1857                                  * We've run out of items in the table;
1858                                  * fall back on the default.
1859                                  */
1860                                 offset = add_word_param(tvb, offset, 0, pinfo,
1861                                     tree, 0, -1);
1862                         } else if (items->type != PARAM_WORD) {
1863                                 /*
1864                                  * Descriptor character is 'h', but this
1865                                  * isn't a word parameter.
1866                                  */
1867                                 WParam = tvb_get_letohs(tvb, offset);
1868                                 proto_tree_add_text(tree, tvb, offset, 2,
1869                                     "%s: Value is %u (0x%04X), type is wrong (W)",
1870                                     (*items->hf_index == -1) ?
1871                                       "Word Param" :
1872                                       proto_registrar_get_name(*items->hf_index),
1873                                     WParam, WParam);
1874                                 offset += 2;
1875                                 items++;
1876                         } else {
1877                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1878                                     tree, 0, *items->hf_index);
1879                                 items++;
1880                         }
1881                         break;
1882
1883                 case 'i':
1884                         /*
1885                          * A 32-bit doubleword is received.
1886                          */
1887                         if (items->func == NULL) {
1888                                 /*
1889                                  * We've run out of items in the table;
1890                                  * fall back on the default.
1891                                  */
1892                                 offset = add_dword_param(tvb, offset, 0, pinfo,
1893                                     tree, 0, -1);
1894                         } else if (items->type != PARAM_DWORD) {
1895                                 /*
1896                                  * Descriptor character is 'i', but this
1897                                  * isn't a doubleword parameter.
1898                                  */
1899                                 LParam = tvb_get_letohl(tvb, offset);
1900                                 proto_tree_add_text(tree, tvb, offset, 2,
1901                                     "%s: Value is %u (0x%08X), type is wrong (i)",
1902                                     (*items->hf_index == -1) ?
1903                                       "Doubleword Param" :
1904                                       proto_registrar_get_name(*items->hf_index),
1905                                     LParam, LParam);
1906                                 offset += 4;
1907                                 items++;
1908                         } else {
1909                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1910                                     tree, 0, *items->hf_index);
1911                                 items++;
1912                         }
1913                         break;
1914
1915                 case 'e':
1916                         /*
1917                          * A 16-bit entry count is returned.
1918                          */
1919                         WParam = tvb_get_letohs(tvb, offset);
1920                         proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2,
1921                             WParam);
1922                         offset += 2;
1923                         *has_ent_count_p = TRUE;
1924                         *ent_count_p = WParam;  /* Save this for later retrieval */
1925                         break;
1926
1927                 default:
1928                         break;
1929                 }
1930         }
1931         return offset;
1932 }
1933
1934 static int
1935 dissect_transact_data(tvbuff_t *tvb, int offset, int convert,
1936     packet_info *pinfo, proto_tree *tree, const guchar *desc,
1937     const item_t *items, guint16 *aux_count_p)
1938 {
1939         guint c;
1940         guint16 WParam;
1941         guint32 LParam;
1942         int count;
1943         int cptr;
1944         const char *string;
1945         gint string_len;
1946
1947         if (aux_count_p != NULL)
1948                 *aux_count_p = 0;
1949
1950         while ((c = *desc++) != '\0') {
1951                 switch (c) {
1952
1953                 case 'W':
1954                         /*
1955                          * A 16-bit word value.
1956                          * XXX - handle the count?
1957                          */
1958                         desc = get_count(desc, &count);
1959                         if (items->func == NULL) {
1960                                 /*
1961                                  * We've run out of items in the table;
1962                                  * fall back on the default.
1963                                  */
1964                                 offset = add_word_param(tvb, offset, 0, pinfo,
1965                                     tree, convert, -1);
1966                         } else if (items->type != PARAM_WORD) {
1967                                 /*
1968                                  * Descriptor character is 'W', but this
1969                                  * isn't a word parameter.
1970                                  */
1971                                 WParam = tvb_get_letohs(tvb, offset);
1972                                 proto_tree_add_text(tree, tvb, offset, 2,
1973                                     "%s: Value is %u (0x%04X), type is wrong (W)",
1974                                     (*items->hf_index == -1) ?
1975                                       "Word Param" :
1976                                       proto_registrar_get_name(*items->hf_index),
1977                                     WParam, WParam);
1978                                 offset += 2;
1979                                 items++;
1980                         } else {
1981                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1982                                     tree, convert, *items->hf_index);
1983                                 items++;
1984                         }
1985                         break;
1986
1987                 case 'D':
1988                         /*
1989                          * A 32-bit doubleword value.
1990                          * XXX - handle the count?
1991                          */
1992                         desc = get_count(desc, &count);
1993                         if (items->func == NULL) {
1994                                 /*
1995                                  * We've run out of items in the table;
1996                                  * fall back on the default.
1997                                  */
1998                                 offset = add_dword_param(tvb, offset, 0, pinfo,
1999                                     tree, convert, -1);
2000                         } else if (items->type != PARAM_DWORD) {
2001                                 /*
2002                                  * Descriptor character is 'D', but this
2003                                  * isn't a doubleword parameter.
2004                                  */
2005                                 LParam = tvb_get_letohl(tvb, offset);
2006                                 proto_tree_add_text(tree, tvb, offset, 2,
2007                                     "%s: Value is %u (0x%08X), type is wrong (D)",
2008                                     (*items->hf_index == -1) ?
2009                                       "Doubleword Param" :
2010                                       proto_registrar_get_name(*items->hf_index),
2011                                     LParam, LParam);
2012                                 offset += 4;
2013                                 items++;
2014                         } else {
2015                                 offset = (*items->func)(tvb, offset, 0, pinfo,
2016                                     tree, convert, *items->hf_index);
2017                                 items++;
2018                         }
2019                         break;
2020
2021                 case 'B':
2022                         /*
2023                          * A byte or multi-byte value.
2024                          */
2025                         desc = get_count(desc, &count);
2026                         if (items->func == NULL) {
2027                                 /*
2028                                  * We've run out of items in the table;
2029                                  * fall back on the default.
2030                                  */
2031                                 offset = add_byte_param(tvb, offset, count,
2032                                     pinfo, tree, convert, -1);
2033                         } else if (items->type != PARAM_BYTES) {
2034                                 /*
2035                                  * Descriptor character is 'B', but this
2036                                  * isn't a byte/bytes parameter.
2037                                  */
2038                                 proto_tree_add_text(tree, tvb, offset, count,
2039                                     "%s: Value is %s, type is wrong (B)",
2040                                     (*items->hf_index == -1) ?
2041                                       "Byte Param" :
2042                                       proto_registrar_get_name(*items->hf_index),
2043                                     tvb_bytes_to_str(tvb, offset, count));
2044                                 offset += count;
2045                                 items++;
2046                         } else {
2047                                 offset = (*items->func)(tvb, offset, count,
2048                                     pinfo, tree, convert, *items->hf_index);
2049                                 items++;
2050                         }
2051                         break;
2052
2053                 case 'O':
2054                         /*
2055                          * A null pointer.
2056                          */
2057                         if (items->func == NULL) {
2058                                 /*
2059                                  * We've run out of items in the table;
2060                                  * fall back on the default.
2061                                  */
2062                                 add_null_pointer_param(tvb, offset, 0,
2063                                     pinfo, tree, convert, -1);
2064                         } else {
2065                                 /*
2066                                  * If "*items->hf_index" is -1, this is
2067                                  * a reserved must-be-null field; don't
2068                                  * clutter the protocol tree by putting
2069                                  * it in.
2070                                  */
2071                                 if (*items->hf_index != -1) {
2072                                         add_null_pointer_param(tvb,
2073                                             offset, 0, pinfo, tree, convert,
2074                                             *items->hf_index);
2075                                 }
2076                                 items++;
2077                         }
2078                         break;
2079
2080                 case 'z':
2081                         /*
2082                          * A pointer to a null-terminated ASCII string.
2083                          */
2084                         if (items->func == NULL) {
2085                                 /*
2086                                  * We've run out of items in the table;
2087                                  * fall back on the default.
2088                                  */
2089                                 offset = add_stringz_pointer_param(tvb, offset,
2090                                     0, pinfo, tree, convert, -1);
2091                         } else if (items->type != PARAM_STRINGZ) {
2092                                 /*
2093                                  * Descriptor character is 'z', but this
2094                                  * isn't a string parameter.
2095                                  */
2096                                 string = get_stringz_pointer_value(tvb, offset,
2097                                     convert, &cptr, &string_len);
2098                                 offset += 4;
2099                                 proto_tree_add_text(tree, tvb, cptr, string_len,
2100                                     "%s: Value is %s, type is wrong (z)",
2101                                     (*items->hf_index == -1) ?
2102                                       "String Param" :
2103                                       proto_registrar_get_name(*items->hf_index),
2104                                     string);
2105                                 items++;
2106                         } else {
2107                                 offset = (*items->func)(tvb, offset, 0,
2108                                     pinfo, tree, convert, *items->hf_index);
2109                                 items++;
2110                         }
2111                         break;
2112
2113                 case 'b':
2114                         /*
2115                          * A pointer to a byte or multi-byte value.
2116                          */
2117                         desc = get_count(desc, &count);
2118                         if (items->func == NULL) {
2119                                 /*
2120                                  * We've run out of items in the table;
2121                                  * fall back on the default.
2122                                  */
2123                                 offset = add_bytes_pointer_param(tvb, offset,
2124                                     count, pinfo, tree, convert, -1);
2125                         } else if (items->type != PARAM_BYTES) {
2126                                 /*
2127                                  * Descriptor character is 'b', but this
2128                                  * isn't a byte/bytes parameter.
2129                                  */
2130                                 cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
2131                                 offset += 4;
2132                                 proto_tree_add_text(tree, tvb, offset, count,
2133                                     "%s: Value is %s, type is wrong (b)",
2134                                     (*items->hf_index == -1) ?
2135                                       "Byte Param" :
2136                                       proto_registrar_get_name(*items->hf_index),
2137                                     tvb_bytes_to_str(tvb, cptr, count));
2138                                 items++;
2139                         } else {
2140                                 offset = (*items->func)(tvb, offset, count,
2141                                     pinfo, tree, convert, *items->hf_index);
2142                                 items++;
2143                         }
2144                         break;
2145
2146                 case 'N':
2147                         /*
2148                          * 16-bit auxiliary data structure count.
2149                          * XXX - hf_acount?
2150                          */
2151                         WParam = tvb_get_letohs(tvb, offset);
2152                         proto_tree_add_text(tree, tvb, offset, 2,
2153                             "%s: %u (0x%04X)",
2154                             "Auxiliary data structure count",
2155                             WParam, WParam);
2156                         offset += 2;
2157                         if (aux_count_p != NULL)
2158                                 *aux_count_p = WParam;  /* Save this for later retrieval */
2159                         break;
2160
2161                 default:
2162                         break;
2163                 }
2164         }
2165         return offset;
2166 }
2167
2168 static const value_string commands[] = {
2169         {API_NetShareEnum,                      "NetShareEnum"},
2170         {API_NetShareGetInfo,                   "NetShareGetInfo"},
2171         {API_NetShareSetInfo,                   "NetShareSetInfo"},
2172         {API_NetShareAdd,                       "NetShareAdd"},
2173         {API_NetShareDel,                       "NetShareDel"},
2174         {API_NetShareCheck,                     "NetShareCheck"},
2175         {API_NetSessionEnum,                    "NetSessionEnum"},
2176         {API_NetSessionGetInfo,                 "NetSessionGetInfo"},
2177         {API_NetSessionDel,                     "NetSessionDel"},
2178         {API_WconnectionEnum,                   "NetConnectionEnum"},
2179         {API_NetFileEnum,                       "NetFileEnum"},
2180         {API_NetFileGetInfo,                    "NetFileGetInfo"},
2181         {API_NetFileClose,                      "NetFileClose"},
2182         {API_NetServerGetInfo,                  "NetServerGetInfo"},
2183         {API_NetServerSetInfo,                  "NetServerSetInfo"},
2184         {API_NetServerDiskEnum,                 "NetServerDiskEnum"},
2185         {API_NetServerAdminCommand,             "NetServerAdminCommand"},
2186         {API_NetAuditOpen,                      "NetAuditOpen"},
2187         {API_NetAuditClear,                     "NetAuditClear"},
2188         {API_NetErrorLogOpen,                   "NetErrorLogOpen"},
2189         {API_NetErrorLogClear,                  "NetErrorLogClear"},
2190         {API_NetCharDevEnum,                    "NetCharDevEnum"},
2191         {API_NetCharDevGetInfo,                 "NetCharDevGetInfo"},
2192         {API_NetCharDevControl,                 "NetCharDevControl"},
2193         {API_NetCharDevQEnum,                   "NetCharDevQEnum"},
2194         {API_NetCharDevQGetInfo,                "NetCharDevQGetInfo"},
2195         {API_NetCharDevQSetInfo,                "NetCharDevQSetInfo"},
2196         {API_NetCharDevQPurge,                  "NetCharDevQPurge"},
2197         {API_NetCharDevQPurgeSelf,              "NetCharDevQPurgeSelf"},
2198         {API_NetMessageNameEnum,                "NetMessageNameEnum"},
2199         {API_NetMessageNameGetInfo,             "NetMessageNameGetInfo"},
2200         {API_NetMessageNameAdd,                 "NetMessageNameAdd"},
2201         {API_NetMessageNameDel,                 "NetMessageNameDel"},
2202         {API_NetMessageNameFwd,                 "NetMessageNameFwd"},
2203         {API_NetMessageNameUnFwd,               "NetMessageNameUnFwd"},
2204         {API_NetMessageBufferSend,              "NetMessageBufferSend"},
2205         {API_NetMessageFileSend,                "NetMessageFileSend"},
2206         {API_NetMessageLogFileSet,              "NetMessageLogFileSet"},
2207         {API_NetMessageLogFileGet,              "NetMessageLogFileGet"},
2208         {API_NetServiceEnum,                    "NetServiceEnum"},
2209         {API_NetServiceInstall,                 "NetServiceInstall"},
2210         {API_NetServiceControl,                 "NetServiceControl"},
2211         {API_NetAccessEnum,                     "NetAccessEnum"},
2212         {API_NetAccessGetInfo,                  "NetAccessGetInfo"},
2213         {API_NetAccessSetInfo,                  "NetAccessSetInfo"},
2214         {API_NetAccessAdd,                      "NetAccessAdd"},
2215         {API_NetAccessDel,                      "NetAccessDel"},
2216         {API_NetGroupEnum,                      "NetGroupEnum"},
2217         {API_NetGroupAdd,                       "NetGroupAdd"},
2218         {API_NetGroupDel,                       "NetGroupDel"},
2219         {API_NetGroupAddUser,                   "NetGroupAddUser"},
2220         {API_NetGroupDelUser,                   "NetGroupDelUser"},
2221         {API_NetGroupGetUsers,                  "NetGroupGetUsers"},
2222         {API_NetUserEnum,                       "NetUserEnum"},
2223         {API_NetUserAdd,                        "NetUserAdd"},
2224         {API_NetUserDel,                        "NetUserDel"},
2225         {API_NetUserGetInfo,                    "NetUserGetInfo"},
2226         {API_NetUserSetInfo,                    "NetUserSetInfo"},
2227         {API_NetUserPasswordSet,                "NetUserPasswordSet"},
2228         {API_NetUserGetGroups,                  "NetUserGetGroups"},
2229         {API_NetWkstaSetUID,                    "NetWkstaSetUID"},
2230         {API_NetWkstaGetInfo,                   "NetWkstaGetInfo"},
2231         {API_NetWkstaSetInfo,                   "NetWkstaSetInfo"},
2232         {API_NetUseEnum,                        "NetUseEnum"},
2233         {API_NetUseAdd,                         "NetUseAdd"},
2234         {API_NetUseDel,                         "NetUseDel"},
2235         {API_NetUseGetInfo,                     "NetUseGetInfo"},
2236         {API_WPrintQEnum,                       "WPrintQEnum"},
2237         {API_WPrintQGetInfo,                    "WPrintQGetInfo"},
2238         {API_WPrintQSetInfo,                    "WPrintQSetInfo"},
2239         {API_WPrintQAdd,                        "WPrintQAdd"},
2240         {API_WPrintQDel,                        "WPrintQDel"},
2241         {API_WPrintQPause,                      "WPrintQPause"},
2242         {API_WPrintQContinue,                   "WPrintQContinue"},
2243         {API_WPrintJobEnum,                     "WPrintJobEnum"},
2244         {API_WPrintJobGetInfo,                  "WPrintJobGetInfo"},
2245         {API_WPrintJobSetInfo_OLD,              "WPrintJobSetInfo_OLD"},
2246         {API_WPrintJobDel,                      "WPrintJobDel"},
2247         {API_WPrintJobPause,                    "WPrintJobPause"},
2248         {API_WPrintJobContinue,                 "WPrintJobContinue"},
2249         {API_WPrintDestEnum,                    "WPrintDestEnum"},
2250         {API_WPrintDestGetInfo,                 "WPrintDestGetInfo"},
2251         {API_WPrintDestControl,                 "WPrintDestControl"},
2252         {API_NetProfileSave,                    "NetProfileSave"},
2253         {API_NetProfileLoad,                    "NetProfileLoad"},
2254         {API_NetStatisticsGet,                  "NetStatisticsGet"},
2255         {API_NetStatisticsClear,                "NetStatisticsClear"},
2256         {API_NetRemoteTOD,                      "NetRemoteTOD"},
2257         {API_WNetBiosEnum,                      "WNetBiosEnum"},
2258         {API_WNetBiosGetInfo,                   "WNetBiosGetInfo"},
2259         {API_NetServerEnum,                     "NetServerEnum"},
2260         {API_I_NetServerEnum,                   "I_NetServerEnum"},
2261         {API_NetServiceGetInfo,                 "NetServiceGetInfo"},
2262         {API_WPrintQPurge,                      "WPrintQPurge"},
2263         {API_NetServerEnum2,                    "NetServerEnum2"},
2264         {API_NetAccessGetUserPerms,             "NetAccessGetUserPerms"},
2265         {API_NetGroupGetInfo,                   "NetGroupGetInfo"},
2266         {API_NetGroupSetInfo,                   "NetGroupSetInfo"},
2267         {API_NetGroupSetUsers,                  "NetGroupSetUsers"},
2268         {API_NetUserSetGroups,                  "NetUserSetGroups"},
2269         {API_NetUserModalsGet,                  "NetUserModalsGet"},
2270         {API_NetUserModalsSet,                  "NetUserModalsSet"},
2271         {API_NetFileEnum2,                      "NetFileEnum2"},
2272         {API_NetUserAdd2,                       "NetUserAdd2"},
2273         {API_NetUserSetInfo2,                   "NetUserSetInfo2"},
2274         {API_NetUserPasswordSet2,               "SetUserPassword"},
2275         {API_I_NetServerEnum2,                  "I_NetServerEnum2"},
2276         {API_NetConfigGet2,                     "NetConfigGet2"},
2277         {API_NetConfigGetAll2,                  "NetConfigGetAll2"},
2278         {API_NetGetDCName,                      "NetGetDCName"},
2279         {API_NetHandleGetInfo,                  "NetHandleGetInfo"},
2280         {API_NetHandleSetInfo,                  "NetHandleSetInfo"},
2281         {API_NetStatisticsGet2,                 "NetStatisticsGet2"},
2282         {API_WBuildGetInfo,                     "WBuildGetInfo"},
2283         {API_NetFileGetInfo2,                   "NetFileGetInfo2"},
2284         {API_NetFileClose2,                     "NetFileClose2"},
2285         {API_NetServerReqChallenge,             "NetServerReqChallenge"},
2286         {API_NetServerAuthenticate,             "NetServerAuthenticate"},
2287         {API_NetServerPasswordSet,              "NetServerPasswordSet"},
2288         {API_WNetAccountDeltas,                 "WNetAccountDeltas"},
2289         {API_WNetAccountSync,                   "WNetAccountSync"},
2290         {API_NetUserEnum2,                      "NetUserEnum2"},
2291         {API_NetWkstaUserLogon,                 "NetWkstaUserLogon"},
2292         {API_NetWkstaUserLogoff,                "NetWkstaUserLogoff"},
2293         {API_NetLogonEnum,                      "NetLogonEnum"},
2294         {API_NetErrorLogRead,                   "NetErrorLogRead"},
2295         {API_I_NetPathType,                     "I_NetPathType"},
2296         {API_I_NetPathCanonicalize,             "I_NetPathCanonicalize"},
2297         {API_I_NetPathCompare,                  "I_NetPathCompare"},
2298         {API_I_NetNameValidate,                 "I_NetNameValidate"},
2299         {API_I_NetNameCanonicalize,             "I_NetNameCanonicalize"},
2300         {API_I_NetNameCompare,                  "I_NetNameCompare"},
2301         {API_NetAuditRead,                      "NetAuditRead"},
2302         {API_WPrintDestAdd,                     "WPrintDestAdd"},
2303         {API_WPrintDestSetInfo,                 "WPrintDestSetInfo"},
2304         {API_WPrintDestDel,                     "WPrintDestDel"},
2305         {API_NetUserValidate2,                  "NetUserValidate2"},
2306         {API_WPrintJobSetInfo,                  "WPrintJobSetInfo"},
2307         {API_TI_NetServerDiskEnum,              "TI_NetServerDiskEnum"},
2308         {API_TI_NetServerDiskGetInfo,           "TI_NetServerDiskGetInfo"},
2309         {API_TI_FTVerifyMirror,                 "TI_FTVerifyMirror"},
2310         {API_TI_FTAbortVerify,                  "TI_FTAbortVerify"},
2311         {API_TI_FTGetInfo,                      "TI_FTGetInfo"},
2312         {API_TI_FTSetInfo,                      "TI_FTSetInfo"},
2313         {API_TI_FTLockDisk,                     "TI_FTLockDisk"},
2314         {API_TI_FTFixError,                     "TI_FTFixError"},
2315         {API_TI_FTAbortFix,                     "TI_FTAbortFix"},
2316         {API_TI_FTDiagnoseError,                "TI_FTDiagnoseError"},
2317         {API_TI_FTGetDriveStats,                "TI_FTGetDriveStats"},
2318         {API_TI_FTErrorGetInfo,                 "TI_FTErrorGetInfo"},
2319         {API_NetAccessCheck,                    "NetAccessCheck"},
2320         {API_NetAlertRaise,                     "NetAlertRaise"},
2321         {API_NetAlertStart,                     "NetAlertStart"},
2322         {API_NetAlertStop,                      "NetAlertStop"},
2323         {API_NetAuditWrite,                     "NetAuditWrite"},
2324         {API_NetIRemoteAPI,                     "NetIRemoteAPI"},
2325         {API_NetServiceStatus,                  "NetServiceStatus"},
2326         {API_I_NetServerRegister,               "I_NetServerRegister"},
2327         {API_I_NetServerDeregister,             "I_NetServerDeregister"},
2328         {API_I_NetSessionEntryMake,             "I_NetSessionEntryMake"},
2329         {API_I_NetSessionEntryClear,            "I_NetSessionEntryClear"},
2330         {API_I_NetSessionEntryGetInfo,          "I_NetSessionEntryGetInfo"},
2331         {API_I_NetSessionEntrySetInfo,          "I_NetSessionEntrySetInfo"},
2332         {API_I_NetConnectionEntryMake,          "I_NetConnectionEntryMake"},
2333         {API_I_NetConnectionEntryClear,         "I_NetConnectionEntryClear"},
2334         {API_I_NetConnectionEntrySetInfo,       "I_NetConnectionEntrySetInfo"},
2335         {API_I_NetConnectionEntryGetInfo,       "I_NetConnectionEntryGetInfo"},
2336         {API_I_NetFileEntryMake,                "I_NetFileEntryMake"},
2337         {API_I_NetFileEntryClear,               "I_NetFileEntryClear"},
2338         {API_I_NetFileEntrySetInfo,             "I_NetFileEntrySetInfo"},
2339         {API_I_NetFileEntryGetInfo,             "I_NetFileEntryGetInfo"},
2340         {API_AltSrvMessageBufferSend,           "AltSrvMessageBufferSend"},
2341         {API_AltSrvMessageFileSend,             "AltSrvMessageFileSend"},
2342         {API_wI_NetRplWkstaEnum,                "wI_NetRplWkstaEnum"},
2343         {API_wI_NetRplWkstaGetInfo,             "wI_NetRplWkstaGetInfo"},
2344         {API_wI_NetRplWkstaSetInfo,             "wI_NetRplWkstaSetInfo"},
2345         {API_wI_NetRplWkstaAdd,                 "wI_NetRplWkstaAdd"},
2346         {API_wI_NetRplWkstaDel,                 "wI_NetRplWkstaDel"},
2347         {API_wI_NetRplProfileEnum,              "wI_NetRplProfileEnum"},
2348         {API_wI_NetRplProfileGetInfo,           "wI_NetRplProfileGetInfo"},
2349         {API_wI_NetRplProfileSetInfo,           "wI_NetRplProfileSetInfo"},
2350         {API_wI_NetRplProfileAdd,               "wI_NetRplProfileAdd"},
2351         {API_wI_NetRplProfileDel,               "wI_NetRplProfileDel"},
2352         {API_wI_NetRplProfileClone,             "wI_NetRplProfileClone"},
2353         {API_wI_NetRplBaseProfileEnum,          "wI_NetRplBaseProfileEnum"},
2354         {API_WIServerSetInfo,                   "WIServerSetInfo"},
2355         {API_WPrintDriverEnum,                  "WPrintDriverEnum"},
2356         {API_WPrintQProcessorEnum,              "WPrintQProcessorEnum"},
2357         {API_WPrintPortEnum,                    "WPrintPortEnum"},
2358         {API_WNetWriteUpdateLog,                "WNetWriteUpdateLog"},
2359         {API_WNetAccountUpdate,                 "WNetAccountUpdate"},
2360         {API_WNetAccountConfirmUpdate,          "WNetAccountConfirmUpdate"},
2361         {API_NetConfigSet,                      "NetConfigSet"},
2362         {API_WAccountsReplicate,                "WAccountsReplicate"},
2363         {API_SamOEMChgPasswordUser2_P,          "SamOEMChangePassword"},
2364         {API_NetServerEnum3,                    "NetServerEnum3"},
2365         {API_WPrintDriverGetInfo,               "WPrintDriverGetInfo"},
2366         {API_WPrintDriverSetInfo,               "WPrintDriverSetInfo"},
2367         {API_NetAliasAdd,                       "NetAliasAdd"},
2368         {API_NetAliasDel,                       "NetAliasDel"},
2369         {API_NetAliasGetInfo,                   "NetAliasGetInfo"},
2370         {API_NetAliasSetInfo,                   "NetAliasSetInfo"},
2371         {API_NetAliasEnum,                      "NetAliasEnum"},
2372         {API_NetUserGetLogonAsn,                "NetUserGetLogonAsn"},
2373         {API_NetUserSetLogonAsn,                "NetUserSetLogonAsn"},
2374         {API_NetUserGetAppSel,                  "NetUserGetAppSel"},
2375         {API_NetUserSetAppSel,                  "NetUserSetAppSel"},
2376         {API_NetAppAdd,                         "NetAppAdd"},
2377         {API_NetAppDel,                         "NetAppDel"},
2378         {API_NetAppGetInfo,                     "NetAppGetInfo"},
2379         {API_NetAppSetInfo,                     "NetAppSetInfo"},
2380         {API_NetAppEnum,                        "NetAppEnum"},
2381         {API_NetUserDCDBInit,                   "NetUserDCDBInit"},
2382         {API_NetDASDAdd,                        "NetDASDAdd"},
2383         {API_NetDASDDel,                        "NetDASDDel"},
2384         {API_NetDASDGetInfo,                    "NetDASDGetInfo"},
2385         {API_NetDASDSetInfo,                    "NetDASDSetInfo"},
2386         {API_NetDASDEnum,                       "NetDASDEnum"},
2387         {API_NetDASDCheck,                      "NetDASDCheck"},
2388         {API_NetDASDCtl,                        "NetDASDCtl"},
2389         {API_NetUserRemoteLogonCheck,           "NetUserRemoteLogonCheck"},
2390         {API_NetUserPasswordSet3,               "NetUserPasswordSet3"},
2391         {API_NetCreateRIPLMachine,              "NetCreateRIPLMachine"},
2392         {API_NetDeleteRIPLMachine,              "NetDeleteRIPLMachine"},
2393         {API_NetGetRIPLMachineInfo,             "NetGetRIPLMachineInfo"},
2394         {API_NetSetRIPLMachineInfo,             "NetSetRIPLMachineInfo"},
2395         {API_NetEnumRIPLMachine,                "NetEnumRIPLMachine"},
2396         {API_I_ShareAdd,                        "I_ShareAdd"},
2397         {API_I_AliasEnum,                       "I_AliasEnum"},
2398         {API_NetAccessApply,                    "NetAccessApply"},
2399         {API_WPrt16Query,                       "WPrt16Query"},
2400         {API_WPrt16Set,                         "WPrt16Set"},
2401         {API_NetUserDel100,                     "NetUserDel100"},
2402         {API_NetUserRemoteLogonCheck2,          "NetUserRemoteLogonCheck2"},
2403         {API_WRemoteTODSet,                     "WRemoteTODSet"},
2404         {API_WPrintJobMoveAll,                  "WPrintJobMoveAll"},
2405         {API_W16AppParmAdd,                     "W16AppParmAdd"},
2406         {API_W16AppParmDel,                     "W16AppParmDel"},
2407         {API_W16AppParmGet,                     "W16AppParmGet"},
2408         {API_W16AppParmSet,                     "W16AppParmSet"},
2409         {API_W16RIPLMachineCreate,              "W16RIPLMachineCreate"},
2410         {API_W16RIPLMachineGetInfo,             "W16RIPLMachineGetInfo"},
2411         {API_W16RIPLMachineSetInfo,             "W16RIPLMachineSetInfo"},
2412         {API_W16RIPLMachineEnum,                "W16RIPLMachineEnum"},
2413         {API_W16RIPLMachineListParmEnum,        "W16RIPLMachineListParmEnum"},
2414         {API_W16RIPLMachClassGetInfo,           "W16RIPLMachClassGetInfo"},
2415         {API_W16RIPLMachClassEnum,              "W16RIPLMachClassEnum"},
2416         {API_W16RIPLMachClassCreate,            "W16RIPLMachClassCreate"},
2417         {API_W16RIPLMachClassSetInfo,           "W16RIPLMachClassSetInfo"},
2418         {API_W16RIPLMachClassDelete,            "W16RIPLMachClassDelete"},
2419         {API_W16RIPLMachClassLPEnum,            "W16RIPLMachClassLPEnum"},
2420         {API_W16RIPLMachineDelete,              "W16RIPLMachineDelete"},
2421         {API_W16WSLevelGetInfo,                 "W16WSLevelGetInfo"},
2422         {API_NetServerNameAdd,                  "NetServerNameAdd"},
2423         {API_NetServerNameDel,                  "NetServerNameDel"},
2424         {API_NetServerNameEnum,                 "NetServerNameEnum"},
2425         {API_I_WDASDEnum,                       "I_WDASDEnum"},
2426         {API_I_WDASDEnumTerminate,              "I_WDASDEnumTerminate"},
2427         {API_I_WDASDSetInfo2,                   "I_WDASDSetInfo2"},
2428         {0,                                     NULL}
2429 };
2430
2431 static void
2432 dissect_response_data(tvbuff_t *tvb, packet_info *pinfo, int convert,
2433     proto_tree *tree, struct smb_info *smb_info,
2434     const struct lanman_desc *lanman, gboolean has_ent_count,
2435     guint16 ent_count)
2436 {
2437         smb_transact_info_t *trp = smb_info->sip->extra_info;
2438         const item_list_t *resp_data_list;
2439         int offset, start_offset;
2440         const char *label;
2441         gint ett;
2442         const item_t *resp_data;
2443         proto_item *data_item;
2444         proto_tree *data_tree;
2445         proto_item *entry_item;
2446         proto_tree *entry_tree;
2447         guint i, j;
2448         guint16 aux_count;
2449
2450         /*
2451          * Find the item table for the matching request's detail level.
2452          */
2453         for (resp_data_list = lanman->resp_data_list;
2454             resp_data_list->level != -1; resp_data_list++) {
2455                 if (resp_data_list->level == trp->info_level)
2456                         break;
2457         }
2458         resp_data = resp_data_list->item_list;
2459
2460         offset = 0;
2461         if (has_ent_count) {
2462                 /*
2463                  * The data is a list of entries; create a protocol tree item
2464                  * for it.
2465                  */
2466                 if (tree) {
2467                         label = lanman->resp_data_entry_list_label;
2468                         if (label == NULL)
2469                                 label = "Entries";
2470                         if (lanman->ett_data_entry_list != NULL)
2471                                 ett = *lanman->ett_data_entry_list;
2472                         else
2473                                 ett = ett_lanman_unknown_entries;
2474                         data_item = proto_tree_add_text(tree, tvb, offset, -1,
2475                             label);
2476                         data_tree = proto_item_add_subtree(data_item, ett);
2477                 } else {
2478                         data_item = NULL;
2479                         data_tree = NULL;
2480                 }
2481         } else {
2482                 /*
2483                  * Just leave it at the top level.
2484                  */
2485                 data_item = NULL;
2486                 data_tree = tree;
2487         }
2488
2489         if (trp->data_descrip == NULL) {
2490                 /*
2491                  * This could happen if we only dissected
2492                  * part of the request to which this is a
2493                  * reply, e.g. if the request was split
2494                  * across TCP segments and we weren't doing
2495                  * TCP desegmentation, or if we had a snapshot
2496                  * length that was too short.
2497                  *
2498                  * We can't dissect the data; just show it as raw data or,
2499                  * if we've already created a top-level item, note that
2500                  * no descriptor is available.
2501                  */
2502                 if (has_ent_count) {
2503                         if (data_item != NULL) {
2504                                 proto_item_append_text(data_item,
2505                                     " (No descriptor available)");
2506                         }
2507                 } else {
2508                         proto_tree_add_text(data_tree, tvb, offset, -1,
2509                             "Data (no descriptor available)");
2510                 }
2511                 offset += tvb_length_remaining(tvb, offset);
2512         } else {
2513                 /*
2514                  * If we have an entry count, show all the entries,
2515                  * with each one having a protocol tree item.
2516                  *
2517                  * Otherwise, we just show one returned item, with
2518                  * no protocol tree item.
2519                  */
2520                 if (!has_ent_count)
2521                         ent_count = 1;
2522                 for (i = 0; i < ent_count; i++) {
2523                         start_offset = offset;
2524                         if (has_ent_count &&
2525                             lanman->resp_data_element_item != NULL) {
2526                                 /*
2527                                  * Create a protocol tree item for the
2528                                  * entry.
2529                                  */
2530                                 entry_item =
2531                                     (*lanman->resp_data_element_item)
2532                                       (tvb, data_tree, offset);
2533                                 entry_tree = proto_item_add_subtree(
2534                                     entry_item,
2535                                     *lanman->ett_resp_data_element_item);
2536                         } else {
2537                                 /*
2538                                  * Just leave it at the current
2539                                  * level.
2540                                  */
2541                                 entry_item = NULL;
2542                                 entry_tree = data_tree;
2543                         }
2544
2545                         offset = dissect_transact_data(tvb, offset,
2546                             convert, pinfo, entry_tree,
2547                             trp->data_descrip, resp_data, &aux_count);
2548
2549                         /* auxiliary data */
2550                         if (trp->aux_data_descrip != NULL) {
2551                                 for (j = 0; j < aux_count; j++) {
2552                                         offset = dissect_transact_data(
2553                                             tvb, offset, convert,
2554                                             pinfo, entry_tree,
2555                                             trp->data_descrip,
2556                                             lanman->resp_aux_data, NULL);
2557                                 }
2558                         }
2559
2560                         if (entry_item != NULL) {
2561                                 /*
2562                                  * Set the length of the protocol tree
2563                                  * item for the entry.
2564                                  */
2565                                 proto_item_set_len(entry_item,
2566                                     offset - start_offset);
2567                         }
2568                 }
2569         }
2570
2571         if (data_item != NULL) {
2572                 /*
2573                  * Set the length of the protocol tree item
2574                  * for the data.
2575                  */
2576                 proto_item_set_len(data_item, offset);
2577         }
2578 }
2579
2580 static gboolean
2581 dissect_pipe_lanman(tvbuff_t *pd_tvb, tvbuff_t *p_tvb, tvbuff_t *d_tvb,
2582                     packet_info *pinfo, proto_tree *parent_tree)
2583 {
2584         smb_info_t *smb_info = pinfo->private_data;
2585         smb_transact_info_t *trp = smb_info->sip->extra_info;
2586         int offset = 0, start_offset;
2587         guint16 cmd;
2588         guint16 status;
2589         int convert;
2590         const struct lanman_desc *lanman;
2591         proto_item *item = NULL;
2592         proto_tree *tree = NULL;
2593         guint descriptor_len;
2594         const gchar *param_descrip, *data_descrip, *aux_data_descrip = NULL;
2595         gboolean has_data;
2596         gboolean has_ent_count;
2597         guint16 ent_count, aux_count;
2598         guint i;
2599         proto_item *data_item;
2600         proto_tree *data_tree;
2601
2602         if (!proto_is_protocol_enabled(proto_smb_lanman))
2603                 return FALSE;
2604         if (smb_info->request && p_tvb == NULL) {
2605                 /*
2606                  * Requests must have parameters.
2607                  */
2608                 return FALSE;
2609         }
2610         pinfo->current_proto = "LANMAN";
2611
2612         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2613                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LANMAN");
2614         }
2615
2616         if (parent_tree) {
2617                 item = proto_tree_add_item(parent_tree, proto_smb_lanman,
2618                         pd_tvb, 0, -1, FALSE);
2619                 tree = proto_item_add_subtree(item, ett_lanman);
2620         }
2621
2622         if (smb_info->request) { /* this is a request */
2623                 /* function code */
2624                 cmd = tvb_get_letohs(p_tvb, offset);
2625                 if (check_col(pinfo->cinfo, COL_INFO)) {
2626                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s Request", val_to_str(cmd, commands, "Unknown Command (%u)"));
2627                 }
2628                 proto_tree_add_uint(tree, hf_function_code, p_tvb, offset, 2,
2629                     cmd);
2630                 offset += 2;
2631
2632                 /*
2633                  * If we haven't already done so, save the function code in
2634                  * the structure we were handed, so that it's available to
2635                  * the code parsing the reply, and initialize the detail
2636                  * level to -1, meaning "unknown".
2637                  */
2638                 if (!pinfo->fd->flags.visited) {
2639                         trp->lanman_cmd = cmd;
2640                         trp->info_level = -1;
2641                         trp->param_descrip=NULL;
2642                         trp->data_descrip=NULL;
2643                         trp->aux_data_descrip=NULL;
2644                 }
2645
2646                 /* parameter descriptor */
2647                 descriptor_len = tvb_strsize(p_tvb, offset);
2648                 proto_tree_add_item(tree, hf_param_desc, p_tvb, offset,
2649                     descriptor_len, TRUE);
2650                 param_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
2651                 if (!pinfo->fd->flags.visited) {
2652                         /*
2653                          * Save the parameter descriptor for future use.
2654                          */
2655                         g_assert(trp->param_descrip == NULL);
2656                         trp->param_descrip = g_strdup(param_descrip);
2657                 }
2658                 offset += descriptor_len;
2659
2660                 /* return descriptor */
2661                 descriptor_len = tvb_strsize(p_tvb, offset);
2662                 proto_tree_add_item(tree, hf_return_desc, p_tvb, offset,
2663                     descriptor_len, TRUE);
2664                 data_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
2665                 if (!pinfo->fd->flags.visited) {
2666                         /*
2667                          * Save the return descriptor for future use.
2668                          */
2669                         g_assert(trp->data_descrip == NULL);
2670                         trp->data_descrip = g_strdup(data_descrip);
2671                 }
2672                 offset += descriptor_len;
2673
2674                 lanman = find_lanman(cmd);
2675
2676                 /* request parameters */
2677                 start_offset = offset;
2678                 offset = dissect_request_parameters(p_tvb, offset, pinfo, tree,
2679                     param_descrip, lanman->req, &has_data);
2680
2681                 /* auxiliary data descriptor */
2682                 if (tvb_reported_length_remaining(p_tvb, offset) > 0){
2683                         /*
2684                          * There are more parameters left, so the next
2685                          * item is the auxiliary data descriptor.
2686                          */
2687                         descriptor_len = tvb_strsize(p_tvb, offset);
2688                         proto_tree_add_item(tree, hf_aux_data_desc, p_tvb, offset,
2689                             descriptor_len, TRUE);
2690                         aux_data_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
2691                         if (!pinfo->fd->flags.visited) {
2692                                 /*
2693                                  * Save the auxiliary data descriptor for
2694                                  * future use.
2695                                  */
2696                                 g_assert(trp->aux_data_descrip == NULL);
2697                                 trp->aux_data_descrip =
2698                                     g_strdup(aux_data_descrip);
2699                         }
2700                         offset += descriptor_len;
2701                 }
2702
2703                 /* reset offset, we now start dissecting the data area */
2704                 offset = 0;
2705                 if (has_data && d_tvb && tvb_reported_length(d_tvb) != 0) {
2706                         /*
2707                          * There's a send buffer item in the descriptor
2708                          * string, and the data count in the transaction
2709                          * is non-zero, so there's data to dissect.
2710                          */
2711
2712                         if (lanman->req_data_item != NULL) {
2713                                 /*
2714                                  * Create a protocol tree item for the data.
2715                                  */
2716                                 data_item = (*lanman->req_data_item)(d_tvb,
2717                                     pinfo, tree, offset);
2718                                 data_tree = proto_item_add_subtree(data_item,
2719                                     *lanman->ett_req_data);
2720                         } else {
2721                                 /*
2722                                  * Just leave it at the top level.
2723                                  */
2724                                 data_item = NULL;
2725                                 data_tree = tree;
2726                         }
2727
2728                         /* data */
2729                         offset = dissect_transact_data(d_tvb, offset, -1,
2730                             pinfo, data_tree, data_descrip, lanman->req_data,
2731                             &aux_count);        /* XXX - what about strings? */
2732
2733                         /* auxiliary data */
2734                         if (aux_data_descrip != NULL) {
2735                                 for (i = 0; i < aux_count; i++) {
2736                                         offset = dissect_transact_data(d_tvb,
2737                                             offset, -1, pinfo, data_tree,
2738                                             aux_data_descrip,
2739                                             lanman->req_aux_data, NULL);
2740                                 }
2741                         }
2742
2743                         if (data_item != NULL) {
2744                                 /*
2745                                  * Set the length of the protocol tree item
2746                                  * for the data.
2747                                  */
2748                                 proto_item_set_len(data_item, offset);
2749                         }
2750                 }
2751         } else {
2752                 /*
2753                  * This is a response.
2754                  * Have we seen the request to which it's a response?
2755                  */
2756                 if (trp == NULL)
2757                         return FALSE;   /* no - can't dissect it */
2758
2759                 /* ok we have seen this one before */
2760
2761                 /* if it looks like an interim response, update COL_INFO and return */
2762                 if( ( (p_tvb==NULL) || (tvb_reported_length(p_tvb)==0) )
2763                 &&  ( (d_tvb==NULL) || (tvb_reported_length(d_tvb)==0) ) ){
2764                         /* command */
2765                         if (check_col(pinfo->cinfo, COL_INFO)) {
2766                                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Interim Response",
2767                                              val_to_str(trp->lanman_cmd, commands, "Unknown Command (%u)"));
2768                         }
2769                         proto_tree_add_uint(tree, hf_function_code, p_tvb, 0, 0, trp->lanman_cmd);
2770                         return TRUE;
2771                 }
2772
2773                 /* command */
2774                 if (check_col(pinfo->cinfo, COL_INFO)) {
2775                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s Response",
2776                                      val_to_str(trp->lanman_cmd, commands, "Unknown Command (%u)"));
2777                 }
2778                 proto_tree_add_uint(tree, hf_function_code, p_tvb, 0, 0,
2779                     trp->lanman_cmd);
2780
2781                 lanman = find_lanman(trp->lanman_cmd);
2782
2783                 /* response parameters */
2784
2785                 /* status */
2786                 status = tvb_get_letohs(p_tvb, offset);
2787                 proto_tree_add_uint(tree, hf_status, p_tvb, offset, 2, status);
2788                 offset += 2;
2789
2790                 /* convert */
2791                 convert = tvb_get_letohs(p_tvb, offset);
2792                 proto_tree_add_uint(tree, hf_convert, p_tvb, offset, 2, convert);
2793                 offset += 2;
2794
2795                 if (trp->param_descrip == NULL) {
2796                         /*
2797                          * This could happen if we only dissected
2798                          * part of the request to which this is a
2799                          * reply, e.g. if the request was split
2800                          * across TCP segments and we weren't doing
2801                          * TCP desegmentation, or if we had a snapshot
2802                          * length that was too short.
2803                          *
2804                          * We can't dissect the parameters; just show them
2805                          * as raw data.
2806                          */
2807                         proto_tree_add_text(tree, p_tvb, offset, -1,
2808                             "Parameters (no descriptor available)");
2809
2810                         /*
2811                          * We don't know whether we have a receive buffer,
2812                          * as we don't have the descriptor; just show what
2813                          * bytes purport to be data.
2814                          */
2815                         if (d_tvb && tvb_reported_length(d_tvb) > 0) {
2816                                 proto_tree_add_text(tree, d_tvb, 0, -1,
2817                                     "Data (no descriptor available)");
2818                         }
2819                 } else {
2820                         /* rest of the parameters */
2821                         offset = dissect_response_parameters(p_tvb, offset,
2822                             pinfo, tree, trp->param_descrip, lanman->resp,
2823                             &has_data, &has_ent_count, &ent_count);
2824
2825                         /* reset offset, we now start dissecting the data area */
2826                         offset = 0;
2827                         /* data */
2828                         if (d_tvb && tvb_reported_length(d_tvb) > 0) {
2829                                 /*
2830                                  * Well, there are bytes that purport to
2831                                  * be data, at least.
2832                                  */
2833                                 if (has_data) {
2834                                         /*
2835                                          * There's a receive buffer item
2836                                          * in the descriptor string, so
2837                                          * dissect it as response data.
2838                                          */
2839                                         dissect_response_data(d_tvb, pinfo,
2840                                             convert, tree, smb_info, lanman,
2841                                             has_ent_count, ent_count);
2842                                 } else {
2843                                         /*
2844                                          * There's no receive buffer item,
2845                                          * but we do have data, so just
2846                                          * show what bytes are data.
2847                                          */
2848                                         proto_tree_add_text(tree, d_tvb, 0, -1,
2849                                             "Data (no receive buffer)");
2850                                 }
2851                         }
2852                 }
2853         }
2854
2855         return TRUE;
2856 }
2857
2858 void
2859 proto_register_pipe_lanman(void)
2860 {
2861         static hf_register_info hf[] = {
2862                 { &hf_function_code,
2863                         { "Function Code", "lanman.function_code", FT_UINT16, BASE_DEC,
2864                         VALS(commands), 0, "LANMAN Function Code/Command", HFILL }},
2865
2866                 { &hf_param_desc,
2867                         { "Parameter Descriptor", "lanman.param_desc", FT_STRING, BASE_NONE,
2868                         NULL, 0, "LANMAN Parameter Descriptor", HFILL }},
2869
2870                 { &hf_return_desc,
2871                         { "Return Descriptor", "lanman.ret_desc", FT_STRING, BASE_NONE,
2872                         NULL, 0, "LANMAN Return Descriptor", HFILL }},
2873
2874                 { &hf_aux_data_desc,
2875                         { "Auxiliary Data Descriptor", "lanman.aux_data_desc", FT_STRING, BASE_NONE,
2876                         NULL, 0, "LANMAN Auxiliary Data Descriptor", HFILL }},
2877
2878                 { &hf_detail_level,
2879                         { "Detail Level", "lanman.level", FT_UINT16, BASE_DEC,
2880                         NULL, 0, "LANMAN Detail Level", HFILL }},
2881
2882                 { &hf_recv_buf_len,
2883                         { "Receive Buffer Length", "lanman.recv_buf_len", FT_UINT16, BASE_DEC,
2884                         NULL, 0, "LANMAN Receive Buffer Length", HFILL }},
2885
2886                 { &hf_send_buf_len,
2887                         { "Send Buffer Length", "lanman.send_buf_len", FT_UINT16, BASE_DEC,
2888                         NULL, 0, "LANMAN Send Buffer Length", HFILL }},
2889
2890                 { &hf_continuation_from,
2891                         { "Continuation from message in frame", "lanman.continuation_from", FT_UINT32, BASE_DEC,
2892                         NULL, 0, "This is a LANMAN continuation from the message in the frame in question", HFILL }},
2893
2894                 { &hf_status,
2895                         { "Status", "lanman.status", FT_UINT16, BASE_DEC,
2896                         VALS(status_vals), 0, "LANMAN Return status", HFILL }},
2897
2898                 { &hf_convert,
2899                         { "Convert", "lanman.convert", FT_UINT16, BASE_DEC,
2900                         NULL, 0, "LANMAN Convert", HFILL }},
2901
2902                 { &hf_ecount,
2903                         { "Entry Count", "lanman.entry_count", FT_UINT16, BASE_DEC,
2904                         NULL, 0, "LANMAN Number of Entries", HFILL }},
2905
2906                 { &hf_acount,
2907                         { "Available Entries", "lanman.available_count", FT_UINT16, BASE_DEC,
2908                         NULL, 0, "LANMAN Number of Available Entries", HFILL }},
2909
2910                 { &hf_share_name,
2911                         { "Share Name", "lanman.share.name", FT_STRING, BASE_NONE,
2912                         NULL, 0, "LANMAN Name of Share", HFILL }},
2913
2914                 { &hf_share_type,
2915                         { "Share Type", "lanman.share.type", FT_UINT16, BASE_DEC,
2916                         VALS(share_type_vals), 0, "LANMAN Type of Share", HFILL }},
2917
2918                 { &hf_share_comment,
2919                         { "Share Comment", "lanman.share.comment", FT_STRING, BASE_NONE,
2920                         NULL, 0, "LANMAN Share Comment", HFILL }},
2921
2922                 { &hf_share_permissions,
2923                         { "Share Permissions", "lanman.share.permissions", FT_UINT16, BASE_DEC,
2924                         NULL, 0, "LANMAN Permissions on share", HFILL }},
2925
2926                 { &hf_share_max_uses,
2927                         { "Share Max Uses", "lanman.share.max_uses", FT_UINT16, BASE_DEC,
2928                         NULL, 0, "LANMAN Max connections allowed to share", HFILL }},
2929
2930                 { &hf_share_current_uses,
2931                         { "Share Current Uses", "lanman.share.current_uses", FT_UINT16, BASE_DEC,
2932                         NULL, 0, "LANMAN Current connections to share", HFILL }},
2933
2934                 { &hf_share_path,
2935                         { "Share Path", "lanman.share.path", FT_STRING, BASE_NONE,
2936                         NULL, 0, "LANMAN Share Path", HFILL }},
2937
2938                 { &hf_share_password,
2939                         { "Share Password", "lanman.share.password", FT_STRING, BASE_NONE,
2940                         NULL, 0, "LANMAN Share Password", HFILL }},
2941
2942                 { &hf_server_name,
2943                         { "Server Name", "lanman.server.name", FT_STRING, BASE_NONE,
2944                         NULL, 0, "LANMAN Name of Server", HFILL }},
2945
2946                 { &hf_server_major,
2947                         { "Major Version", "lanman.server.major", FT_UINT8, BASE_DEC,
2948                         NULL, 0, "LANMAN Server Major Version", HFILL }},
2949
2950                 { &hf_server_minor,
2951                         { "Minor Version", "lanman.server.minor", FT_UINT8, BASE_DEC,
2952                         NULL, 0, "LANMAN Server Minor Version", HFILL }},
2953
2954                 { &hf_server_comment,
2955                         { "Server Comment", "lanman.server.comment", FT_STRING, BASE_NONE,
2956                         NULL, 0, "LANMAN Server Comment", HFILL }},
2957
2958                 { &hf_abytes,
2959                         { "Available Bytes", "lanman.available_bytes", FT_UINT16, BASE_DEC,
2960                         NULL, 0, "LANMAN Number of Available Bytes", HFILL }},
2961
2962                 { &hf_current_time,
2963                         { "Current Date/Time", "lanman.current_time", FT_ABSOLUTE_TIME, BASE_NONE,
2964                         NULL, 0, "LANMAN Current date and time, in seconds since 00:00:00, January 1, 1970", HFILL }},
2965
2966                 { &hf_msecs,
2967                         { "Milliseconds", "lanman.msecs", FT_UINT32, BASE_DEC,
2968                         NULL, 0, "LANMAN Milliseconds since arbitrary time in the past (typically boot time)", HFILL }},
2969
2970                 { &hf_hour,
2971                         { "Hour", "lanman.hour", FT_UINT8, BASE_DEC,
2972                         NULL, 0, "LANMAN Current hour", HFILL }},
2973
2974                 { &hf_minute,
2975                         { "Minute", "lanman.minute", FT_UINT8, BASE_DEC,
2976                         NULL, 0, "LANMAN Current minute", HFILL }},
2977
2978                 { &hf_second,
2979                         { "Second", "lanman.second", FT_UINT8, BASE_DEC,
2980                         NULL, 0, "LANMAN Current second", HFILL }},
2981
2982                 { &hf_hundredths,
2983                         { "Hundredths of a second", "lanman.hundredths", FT_UINT8, BASE_DEC,
2984                         NULL, 0, "LANMAN Current hundredths of a second", HFILL }},
2985
2986                 { &hf_tzoffset,
2987                         { "Time Zone Offset", "lanman.tzoffset", FT_INT16, BASE_DEC,
2988                         NULL, 0, "LANMAN Offset of time zone from GMT, in minutes", HFILL }},
2989
2990                 { &hf_timeinterval,
2991                         { "Time Interval", "lanman.timeinterval", FT_UINT16, BASE_DEC,
2992                         NULL, 0, "LANMAN .0001 second units per clock tick", HFILL }},
2993
2994                 { &hf_day,
2995                         { "Day", "lanman.day", FT_UINT8, BASE_DEC,
2996                         NULL, 0, "LANMAN Current day", HFILL }},
2997
2998                 { &hf_month,
2999                         { "Month", "lanman.month", FT_UINT8, BASE_DEC,
3000                         NULL, 0, "LANMAN Current month", HFILL }},
3001
3002                 { &hf_year,
3003                         { "Year", "lanman.year", FT_UINT16, BASE_DEC,
3004                         NULL, 0, "LANMAN Current year", HFILL }},
3005
3006                 { &hf_weekday,
3007                         { "Weekday", "lanman.weekday", FT_UINT8, BASE_DEC,
3008                         VALS(weekday_vals), 0, "LANMAN Current day of the week", HFILL }},
3009
3010                 { &hf_enumeration_domain,
3011                         { "Enumeration Domain", "lanman.enumeration_domain", FT_STRING, BASE_NONE,
3012                         NULL, 0, "LANMAN Domain in which to enumerate servers", HFILL }},
3013
3014                 { &hf_computer_name,
3015                         { "Computer Name", "lanman.computer_name", FT_STRING, BASE_NONE,
3016                         NULL, 0, "LANMAN Computer Name", HFILL }},
3017
3018                 { &hf_user_name,
3019                         { "User Name", "lanman.user_name", FT_STRING, BASE_NONE,
3020                         NULL, 0, "LANMAN User Name", HFILL }},
3021
3022                 { &hf_group_name,
3023                         { "Group Name", "lanman.group_name", FT_STRING, BASE_NONE,
3024                         NULL, 0, "LANMAN Group Name", HFILL }},
3025
3026                 { &hf_workstation_domain,
3027                         { "Workstation Domain", "lanman.workstation_domain", FT_STRING, BASE_NONE,
3028                         NULL, 0, "LANMAN Workstation Domain", HFILL }},
3029
3030                 { &hf_workstation_major,
3031                         { "Workstation Major Version", "lanman.workstation_major", FT_UINT8, BASE_DEC,
3032                         NULL, 0, "LANMAN Workstation Major Version", HFILL }},
3033
3034                 { &hf_workstation_minor,
3035                         { "Workstation Minor Version", "lanman.workstation_minor", FT_UINT8, BASE_DEC,
3036                         NULL, 0, "LANMAN Workstation Minor Version", HFILL }},
3037
3038                 { &hf_logon_domain,
3039                         { "Logon Domain", "lanman.logon_domain", FT_STRING, BASE_NONE,
3040                         NULL, 0, "LANMAN Logon Domain", HFILL }},
3041
3042                 { &hf_other_domains,
3043                         { "Other Domains", "lanman.other_domains", FT_STRING, BASE_NONE,
3044                         NULL, 0, "LANMAN Other Domains", HFILL }},
3045
3046                 { &hf_password,
3047                         { "Password", "lanman.password", FT_STRING, BASE_NONE,
3048                         NULL, 0, "LANMAN Password", HFILL }},
3049
3050                 { &hf_workstation_name,
3051                         { "Workstation Name", "lanman.workstation_name", FT_STRING, BASE_NONE,
3052                         NULL, 0, "LANMAN Workstation Name", HFILL }},
3053
3054                 { &hf_ustruct_size,
3055                         { "Length of UStruct", "lanman.ustruct_size", FT_UINT16, BASE_DEC,
3056                         NULL, 0, "LANMAN UStruct Length", HFILL }},
3057
3058                 { &hf_logon_code,
3059                         { "Logon Code", "lanman.logon_code", FT_UINT16, BASE_DEC,
3060                         VALS(status_vals), 0, "LANMAN Logon Code", HFILL }},
3061
3062                 { &hf_privilege_level,
3063                         { "Privilege Level", "lanman.privilege_level", FT_UINT16, BASE_DEC,
3064                         VALS(privilege_vals), 0, "LANMAN Privilege Level", HFILL }},
3065
3066                 { &hf_operator_privileges,
3067                         { "Operator Privileges", "lanman.operator_privileges", FT_UINT32, BASE_DEC,
3068                         VALS(op_privilege_vals), 0, "LANMAN Operator Privileges", HFILL }},
3069
3070                 { &hf_num_logons,
3071                         { "Number of Logons", "lanman.num_logons", FT_UINT16, BASE_DEC,
3072                         NULL, 0, "LANMAN Number of Logons", HFILL }},
3073
3074                 { &hf_bad_pw_count,
3075                         { "Bad Password Count", "lanman.bad_pw_count", FT_UINT16, BASE_DEC,
3076                         NULL, 0, "LANMAN Number of incorrect passwords entered since last successful login", HFILL }},
3077
3078                 { &hf_last_logon,
3079                         { "Last Logon Date/Time", "lanman.last_logon", FT_ABSOLUTE_TIME, BASE_NONE,
3080                         NULL, 0, "LANMAN Date and time of last logon", HFILL }},
3081
3082                 { &hf_last_logoff,
3083                         { "Last Logoff Date/Time", "lanman.last_logoff", FT_ABSOLUTE_TIME, BASE_NONE,
3084                         NULL, 0, "LANMAN Date and time of last logoff", HFILL }},
3085
3086                 { &hf_logoff_time,
3087                         { "Logoff Date/Time", "lanman.logoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
3088                         NULL, 0, "LANMAN Date and time when user should log off", HFILL }},
3089
3090                 { &hf_kickoff_time,
3091                         { "Kickoff Date/Time", "lanman.kickoff_time", FT_ABSOLUTE_TIME, BASE_NONE,
3092                         NULL, 0, "LANMAN Date and time when user will be logged off", HFILL }},
3093
3094                 { &hf_password_age,
3095                         { "Password Age", "lanman.password_age", FT_RELATIVE_TIME, BASE_NONE,
3096                         NULL, 0, "LANMAN Time since user last changed his/her password", HFILL }},
3097
3098                 { &hf_password_can_change,
3099                         { "Password Can Change", "lanman.password_can_change", FT_ABSOLUTE_TIME, BASE_NONE,
3100                         NULL, 0, "LANMAN Date and time when user can change their password", HFILL }},
3101
3102                 { &hf_password_must_change,
3103                         { "Password Must Change", "lanman.password_must_change", FT_ABSOLUTE_TIME, BASE_NONE,
3104                         NULL, 0, "LANMAN Date and time when user must change their password", HFILL }},
3105
3106                 { &hf_script_path,
3107                         { "Script Path", "lanman.script_path", FT_STRING, BASE_NONE,
3108                         NULL, 0, "LANMAN Pathname of user's logon script", HFILL }},
3109
3110                 { &hf_logoff_code,
3111                         { "Logoff Code", "lanman.logoff_code", FT_UINT16, BASE_DEC,
3112                         VALS(status_vals), 0, "LANMAN Logoff Code", HFILL }},
3113
3114                 { &hf_duration,
3115                         { "Duration of Session", "lanman.duration", FT_RELATIVE_TIME, BASE_NONE,
3116                         NULL, 0, "LANMAN Number of seconds the user was logged on", HFILL }},
3117
3118                 { &hf_comment,
3119                         { "Comment", "lanman.comment", FT_STRING, BASE_NONE,
3120                         NULL, 0, "LANMAN Comment", HFILL }},
3121
3122                 { &hf_user_comment,
3123                         { "User Comment", "lanman.user_comment", FT_STRING, BASE_NONE,
3124                         NULL, 0, "LANMAN User Comment", HFILL }},
3125
3126                 { &hf_full_name,
3127                         { "Full Name", "lanman.full_name", FT_STRING, BASE_NONE,
3128                         NULL, 0, "LANMAN Full Name", HFILL }},
3129
3130                 { &hf_homedir,
3131                         { "Home Directory", "lanman.homedir", FT_STRING, BASE_NONE,
3132                         NULL, 0, "LANMAN Home Directory", HFILL }},
3133
3134                 { &hf_parameters,
3135                         { "Parameters", "lanman.parameters", FT_STRING, BASE_NONE,
3136                         NULL, 0, "LANMAN Parameters", HFILL }},
3137
3138                 { &hf_logon_server,
3139                         { "Logon Server", "lanman.logon_server", FT_STRING, BASE_NONE,
3140                         NULL, 0, "LANMAN Logon Server", HFILL }},
3141
3142                 /* XXX - we should have a value_string table for this */
3143                 { &hf_country_code,
3144                         { "Country Code", "lanman.country_code", FT_UINT16, BASE_DEC,
3145                         VALS(ms_country_codes), 0, "LANMAN Country Code", HFILL }},
3146
3147                 { &hf_workstations,
3148                         { "Workstations", "lanman.workstations", FT_STRING, BASE_NONE,
3149                         NULL, 0, "LANMAN Workstations", HFILL }},
3150
3151                 { &hf_max_storage,
3152                         { "Max Storage", "lanman.max_storage", FT_UINT32, BASE_DEC,
3153                         NULL, 0, "LANMAN Max Storage", HFILL }},
3154
3155                 { &hf_units_per_week,
3156                         { "Units Per Week", "lanman.units_per_week", FT_UINT16, BASE_DEC,
3157                         NULL, 0, "LANMAN Units Per Week", HFILL }},
3158
3159                 { &hf_logon_hours,
3160                         { "Logon Hours", "lanman.logon_hours", FT_BYTES, BASE_NONE,
3161                         NULL, 0, "LANMAN Logon Hours", HFILL }},
3162
3163                 /* XXX - we should have a value_string table for this */
3164                 { &hf_code_page,
3165                         { "Code Page", "lanman.code_page", FT_UINT16, BASE_DEC,
3166                         NULL, 0, "LANMAN Code Page", HFILL }},
3167
3168                 { &hf_new_password,
3169                         { "New Password", "lanman.new_password", FT_BYTES, BASE_HEX,
3170                         NULL, 0, "LANMAN New Password (encrypted)", HFILL }},
3171
3172                 { &hf_old_password,
3173                         { "Old Password", "lanman.old_password", FT_BYTES, BASE_HEX,
3174                         NULL, 0, "LANMAN Old Password (encrypted)", HFILL }},
3175
3176                 { &hf_reserved,
3177                         { "Reserved", "lanman.reserved", FT_UINT32, BASE_HEX,
3178                         NULL, 0, "LANMAN Reserved", HFILL }},
3179
3180         };
3181         static gint *ett[] = {
3182                 &ett_lanman,
3183                 &ett_lanman_unknown_entries,
3184                 &ett_lanman_unknown_entry,
3185                 &ett_lanman_servers,
3186                 &ett_lanman_server,
3187                 &ett_lanman_groups,
3188                 &ett_lanman_shares,
3189                 &ett_lanman_share,
3190         };
3191
3192         proto_smb_lanman = proto_register_protocol(
3193                 "Microsoft Windows Lanman Remote API Protocol", "LANMAN", "lanman");
3194         proto_register_field_array(proto_smb_lanman, hf, array_length(hf));
3195         proto_register_subtree_array(ett, array_length(ett));
3196 }
3197
3198 static heur_dissector_list_t smb_transact_heur_subdissector_list;
3199
3200 static GHashTable *dcerpc_fragment_table = NULL;
3201
3202 static void
3203 smb_dcerpc_reassembly_init(void)
3204 {
3205         fragment_table_init(&dcerpc_fragment_table);
3206 }
3207
3208 gboolean
3209 dissect_pipe_dcerpc(tvbuff_t *d_tvb, packet_info *pinfo, proto_tree *parent_tree,
3210     proto_tree *tree, guint32 fid)
3211 {
3212         dcerpc_private_info dcerpc_priv;
3213         smb_info_t *smb_priv = (smb_info_t *)pinfo->private_data;
3214         gboolean result=0;
3215         gboolean save_fragmented;
3216         guint reported_len;
3217         guint32 hash_key;
3218         gpointer hash_value;
3219         fragment_data *fd_head;
3220         tvbuff_t *new_tvb;
3221         guint32 frame;
3222
3223         dcerpc_priv.transport_type = DCERPC_TRANSPORT_SMB;
3224         dcerpc_priv.data.smb.fid = fid;
3225
3226         pinfo->private_data = &dcerpc_priv;
3227
3228
3229         /*
3230          * Offer desegmentation service to DCERPC if we have all the
3231          * data.  Otherwise, reassembly is (probably) impossible.
3232          */
3233         pinfo->can_desegment=0;
3234         pinfo->desegment_offset = 0;
3235         pinfo->desegment_len = 0;
3236         reported_len = tvb_reported_length(d_tvb);
3237         if(smb_dcerpc_reassembly && tvb_bytes_exist(d_tvb, 0, reported_len)){
3238                 pinfo->can_desegment=2;
3239         }
3240
3241         save_fragmented = pinfo->fragmented;
3242
3243
3244         /* if we are not offering desegmentation, just try the heuristics
3245            and bail out
3246         */
3247         if(!pinfo->can_desegment){
3248                 result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
3249                 goto clean_up_and_exit;
3250         }
3251
3252
3253         /* below this line, we know we are doing reassembly */
3254         
3255
3256         /* this is a new packet, see if we are already reassembling this
3257            pdu and if not, check if the dissector wants us
3258            to reassemble it
3259         */
3260         if((!pinfo->fd->flags.visited) && smb_priv->sip){
3261                 /*
3262                  * Check if we are already reassembling this PDU or not;
3263                  * we check for an in-progress reassembly for this FID
3264                  * in this direction (the direction is indicated by the
3265                  * SMB request/reply flag - data from client to server
3266                  * is carried in requests, data from server to client
3267                  * is carried in replies).
3268                  *
3269                  * We know that the FID is only 16 bits long, so we put
3270                  * the direction in bit 17.
3271                  */
3272                 hash_key = fid;
3273                 if (smb_priv->request)
3274                         hash_key |= 0x10000;
3275                 hash_value = g_hash_table_lookup(smb_priv->ct->dcerpc_fid_to_frame, (void *)hash_key);
3276                 if(!hash_value){
3277                         /* this is a new pdu. check if the dissector wants us
3278                            to reassemble it or if we already got the full pdu
3279                            in this tvb.
3280                         */
3281
3282                         /*
3283                          * First, just check if it looks like dcerpc or not.
3284                          *
3285                          * XXX - this assumes that the dissector is idempotent,
3286                          * as it's doing a "trial" dissection building no
3287                          * tree; that's not necessarily the case.
3288                          */
3289                         result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, NULL);
3290                         
3291                         /* no this didnt look like something we know */
3292                         if(!result){
3293                                 goto clean_up_and_exit;
3294                         }
3295
3296                         /* did the subdissector want us to reassemble any
3297                            more data ?
3298                         */
3299                         if(pinfo->desegment_len){
3300                                 fragment_add(d_tvb, 0, pinfo, pinfo->fd->num,
3301                                         dcerpc_fragment_table,
3302                                         0, reported_len, TRUE);
3303                                 fragment_set_tot_len(pinfo, pinfo->fd->num,
3304                                         dcerpc_fragment_table,
3305                                         pinfo->desegment_len+reported_len);
3306                                 /* we also need to store this fid value so we 
3307                                    know for the next Write/Read/Trans call
3308                                    to this fid that we are doing reassembly
3309
3310                                    we know this entry does not exist already
3311                                    from the code above
3312                                 */
3313                                 g_hash_table_insert(smb_priv->ct->dcerpc_fid_to_frame, (void *)hash_key,(void *)pinfo->fd->num);
3314
3315                                 /* store the frame to hash_key value so we can
3316                                    find this pdu later */
3317                                 g_hash_table_insert(smb_priv->ct->dcerpc_frame_to_dcerpc_pdu, (void *)pinfo->fd->num,(void *)pinfo->fd->num);
3318
3319                                 goto clean_up_and_exit;
3320                         }
3321
3322                         /* guess we have the full pdu in this tvb then,
3323                            just dissect it and continue.
3324                         */
3325                         result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
3326                         goto clean_up_and_exit;
3327                 }
3328
3329                 /* ok this seems to be a new fragment to add to an existing
3330                    reassembly 
3331                 */
3332                 frame = GPOINTER_TO_UINT(hash_value);
3333
3334                 /* find the existing reassembly structure */
3335                 fd_head=fragment_get(pinfo, frame, dcerpc_fragment_table);
3336                 /* if we got here, there MUST be a reassembly structure */
3337                 g_assert(fd_head);
3338                 /* skip to last segment in the existing reassembly structure
3339                    and add this fragment there
3340
3341                    XXX we might add code here to use any offset values
3342                    we might pick up from the Read/Write calls instead of
3343                    assuming we always get them in the correct order
3344                 */
3345                 while(fd_head->next){
3346                         fd_head=fd_head->next;
3347                 }
3348                 fd_head=fragment_add(d_tvb, 0, pinfo,
3349                         frame, dcerpc_fragment_table,
3350                         fd_head->offset+fd_head->len,
3351                         reported_len, TRUE);
3352                 /* store the frame to hash_key value so we can
3353                    find this pdu later */
3354                 g_hash_table_insert(smb_priv->ct->dcerpc_frame_to_dcerpc_pdu, (void *)pinfo->fd->num,(void *)frame);
3355
3356                 /* if we completed reassembly */
3357                 if(fd_head){
3358                         g_hash_table_remove(smb_priv->ct->dcerpc_fid_to_frame, (void *)hash_key);
3359                         new_tvb = tvb_new_real_data(fd_head->data,
3360                                   fd_head->datalen, fd_head->datalen);
3361                         tvb_set_child_real_data_tvbuff(d_tvb, new_tvb);
3362                         add_new_data_source(pinfo, new_tvb,
3363                                   "DCERPC over SMB");
3364                         pinfo->fragmented=FALSE;
3365
3366                         d_tvb=new_tvb;
3367
3368                         /* list what segments we have */
3369                         show_fragment_tree(fd_head, &smb_pipe_frag_items,
3370                             tree, pinfo, d_tvb);
3371
3372                         /* dissect the full PDU */
3373                         result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
3374                 }
3375                 goto clean_up_and_exit;
3376         }
3377
3378
3379         /* this is not a new packet so just see if we have already
3380            seen this fragment and if so if we were able to reassemble it
3381            or not.
3382         */
3383         hash_value = g_hash_table_lookup(smb_priv->ct->dcerpc_frame_to_dcerpc_pdu, (void *)pinfo->fd->num);
3384         if(!hash_value){
3385                 /* we didnt find it, try any of the heurisitc dissectors
3386                    and bail out 
3387                 */
3388                 result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
3389                 goto clean_up_and_exit;
3390         }
3391         fd_head=fragment_get(pinfo, (guint32)hash_value, dcerpc_fragment_table);
3392         if(!fd_head){
3393                 /* we didnt find it, try any of the heurisitc dissectors
3394                    and bail out 
3395                 */
3396                 result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
3397                 goto clean_up_and_exit;
3398         }
3399         if(!fd_head->flags&FD_DEFRAGMENTED){
3400                 /* we dont have a fully reassembled frame */
3401                 result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
3402                 goto clean_up_and_exit;
3403         }
3404
3405         /* it is reassembled but it was reassembled in a different frame */
3406         if(pinfo->fd->num!=fd_head->reassembled_in){
3407                 proto_tree_add_uint(parent_tree, hf_pipe_reassembled_in, d_tvb, 0, 0, fd_head->reassembled_in);
3408                 goto clean_up_and_exit;
3409         }
3410
3411
3412         /* display the reassembled pdu */
3413         new_tvb = tvb_new_real_data(fd_head->data,
3414                   fd_head->datalen, fd_head->datalen);
3415         tvb_set_child_real_data_tvbuff(d_tvb, new_tvb);
3416         add_new_data_source(pinfo, new_tvb,
3417                   "DCERPC over SMB");
3418         pinfo->fragmented=FALSE;
3419
3420         d_tvb=new_tvb;
3421
3422         /* list what segments we have */
3423         show_fragment_tree(fd_head, &smb_pipe_frag_items,
3424                     tree, pinfo, d_tvb);
3425
3426         /* dissect the full PDU */
3427         result = dissector_try_heuristic(smb_transact_heur_subdissector_list, d_tvb, pinfo, parent_tree);
3428         
3429
3430
3431 clean_up_and_exit:
3432         /* clear out the variables */
3433         pinfo->private_data = smb_priv;
3434         pinfo->can_desegment=0;
3435         pinfo->desegment_offset = 0;
3436         pinfo->desegment_len = 0;
3437
3438         if (!result)
3439                 call_dissector(data_handle, d_tvb, pinfo, parent_tree);
3440
3441         pinfo->fragmented = save_fragmented;
3442         return TRUE;
3443 }
3444
3445 void
3446 proto_register_pipe_dcerpc(void)
3447 {
3448         register_heur_dissector_list("smb_transact", &smb_transact_heur_subdissector_list);
3449         register_init_routine(smb_dcerpc_reassembly_init);
3450 }
3451
3452 #define CALL_NAMED_PIPE         0x54
3453 #define WAIT_NAMED_PIPE         0x53
3454 #define PEEK_NAMED_PIPE         0x23
3455 #define Q_NM_P_HAND_STATE       0x21
3456 #define SET_NM_P_HAND_STATE     0x01
3457 #define Q_NM_PIPE_INFO          0x22
3458 #define TRANSACT_NM_PIPE        0x26
3459 #define RAW_READ_NM_PIPE        0x11
3460 #define RAW_WRITE_NM_PIPE       0x31
3461
3462 static const value_string functions[] = {
3463         {CALL_NAMED_PIPE,       "CallNamedPipe"},
3464         {WAIT_NAMED_PIPE,       "WaitNamedPipe"},
3465         {PEEK_NAMED_PIPE,       "PeekNamedPipe"},
3466         {Q_NM_P_HAND_STATE,     "QNmPHandState"},
3467         {SET_NM_P_HAND_STATE,   "SetNmPHandState"},
3468         {Q_NM_PIPE_INFO,        "QNmPipeInfo"},
3469         {TRANSACT_NM_PIPE,      "TransactNmPipe"},
3470         {RAW_READ_NM_PIPE,      "RawReadNmPipe"},
3471         {RAW_WRITE_NM_PIPE,     "RawWriteNmPipe"},
3472         {0,                     NULL}
3473 };
3474
3475 static const value_string pipe_status[] = {
3476         {1,     "Disconnected by server"},
3477         {2,     "Listening"},
3478         {3,     "Connection to server is OK"},
3479         {4,     "Server end of pipe is closed"},
3480         {0,     NULL}
3481 };
3482
3483 #define PIPE_LANMAN     1
3484 #define PIPE_DCERPC     2
3485
3486 /* decode the SMB pipe protocol
3487    for requests
3488     pipe is the name of the pipe, e.g. LANMAN
3489     smb_info->trans_subcmd is set to the symbolic constant matching the mailslot name
3490   for responses
3491     pipe is NULL
3492     smb_info->trans_subcmd gives us which pipe this response is for
3493 */
3494 gboolean
3495 dissect_pipe_smb(tvbuff_t *sp_tvb, tvbuff_t *s_tvb, tvbuff_t *pd_tvb,
3496                  tvbuff_t *p_tvb, tvbuff_t *d_tvb, const char *pipe,
3497                  packet_info *pinfo, proto_tree *tree)
3498 {
3499         smb_info_t *smb_info;
3500         smb_transact_info_t *tri;
3501         guint sp_len;
3502         proto_item *pipe_item = NULL;
3503         proto_tree *pipe_tree = NULL;
3504         int offset;
3505         int trans_subcmd;
3506         int function;
3507         int fid = -1;
3508         guint16 info_level;
3509
3510         if (!proto_is_protocol_enabled(proto_smb_pipe))
3511                 return FALSE;
3512         pinfo->current_proto = "SMB Pipe";
3513
3514         smb_info = pinfo->private_data;
3515
3516         /*
3517          * Set the columns.
3518          */
3519         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
3520                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMB Pipe");
3521         }
3522         if (check_col(pinfo->cinfo, COL_INFO)) {
3523                 col_set_str(pinfo->cinfo, COL_INFO,
3524                     smb_info->request ? "Request" : "Response");
3525         }
3526
3527         if (smb_info->sip != NULL)
3528                 tri = smb_info->sip->extra_info;
3529         else
3530                 tri = NULL;
3531
3532         /*
3533          * Set up a subtree for the pipe protocol.  (It might not contain
3534          * anything.)
3535          */
3536         if (sp_tvb != NULL)
3537                 sp_len = tvb_length(sp_tvb);
3538         else
3539                 sp_len = 0;
3540         if (tree) {
3541                 pipe_item = proto_tree_add_item(tree, proto_smb_pipe,
3542                     sp_tvb, 0, sp_len, FALSE);
3543                 pipe_tree = proto_item_add_subtree(pipe_item, ett_smb_pipe);
3544         }
3545         offset = 0;
3546
3547         /*
3548          * Do we have any setup words at all?
3549          */
3550         if (s_tvb != NULL && tvb_length(s_tvb) != 0) {
3551                 /*
3552                  * Yes.  The first of them is the function.
3553                  */
3554                 function = tvb_get_letohs(s_tvb, offset);
3555                 proto_tree_add_uint(pipe_tree, hf_pipe_function, s_tvb,
3556                     offset, 2, function);
3557                 offset += 2;
3558                 if (check_col(pinfo->cinfo, COL_INFO)) {
3559                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
3560                             val_to_str(function, functions, "Unknown function (0x%04x)"),
3561                             smb_info->request ? "Request" : "Response");
3562                 }
3563                 if (tri != NULL)
3564                         tri->function = function;
3565
3566                 /*
3567                  * The second of them depends on the function.
3568                  */
3569                 switch (function) {
3570
3571                 case CALL_NAMED_PIPE:
3572                 case WAIT_NAMED_PIPE:
3573                         /*
3574                          * It's a priority.
3575                          */
3576                         proto_tree_add_item(pipe_tree, hf_pipe_priority, s_tvb,
3577                             offset, 2, TRUE);
3578                         break;
3579
3580                 case PEEK_NAMED_PIPE:
3581                 case Q_NM_P_HAND_STATE:
3582                 case SET_NM_P_HAND_STATE:
3583                 case Q_NM_PIPE_INFO:
3584                 case TRANSACT_NM_PIPE:
3585                 case RAW_READ_NM_PIPE:
3586                 case RAW_WRITE_NM_PIPE:
3587                         /*
3588                          * It's a FID.
3589                          */
3590                         fid = tvb_get_letohs(s_tvb, 2);
3591                         add_fid(s_tvb, pinfo, pipe_tree, offset, 2, fid);
3592                         if (tri != NULL)
3593                                 tri->fid = fid;
3594                         break;
3595
3596                 default:
3597                         /*
3598                          * It's something unknown.
3599                          * XXX - put it into the tree?
3600                          */
3601                         break;
3602                 }
3603                 offset += 2;
3604         } else {
3605                 /*
3606                  * This is either a response or a pipe transaction with
3607                  * no setup information.
3608                  *
3609                  * In the former case, we can get that information from
3610                  * the matching request, if we saw it.
3611                  *
3612                  * In the latter case, there is no function or FID.
3613                  */
3614                 if (tri != NULL && tri->function != -1) {
3615                         function = tri->function;
3616                         proto_tree_add_uint(pipe_tree, hf_pipe_function, NULL,
3617                             0, 0, function);
3618                         if (check_col(pinfo->cinfo, COL_INFO)) {
3619                                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
3620                                     val_to_str(function, functions, "Unknown function (0x%04x)"),
3621                                     smb_info->request ? "Request" : "Response");
3622                         }
3623                         fid = tri->fid;
3624                         if (fid != -1)
3625                                 add_fid(NULL, pinfo, pipe_tree, 0, 0, fid);
3626                 } else {
3627                         function = -1;
3628                         fid = -1;
3629                 }
3630         }
3631
3632         /*
3633          * XXX - put the byte count and the pipe name into the tree as well;
3634          * that requires us to fetch a possibly-Unicode string.
3635          */
3636
3637         if(smb_info->request){
3638                 if(strncmp(pipe,"LANMAN",6) == 0){
3639                         trans_subcmd=PIPE_LANMAN;
3640                 } else {
3641                         /* assume it is DCERPC */
3642                         trans_subcmd=PIPE_DCERPC;
3643                 }
3644
3645                 if (!pinfo->fd->flags.visited)
3646                         tri->trans_subcmd = trans_subcmd;
3647         } else
3648                 trans_subcmd = tri->trans_subcmd;
3649
3650         if (tri == NULL) {
3651                 /*
3652                  * We don't know what type of pipe transaction this
3653                  * was, so indicate that we didn't dissect it.
3654                  */
3655                 return FALSE;
3656         }
3657
3658         switch (function) {
3659
3660         case CALL_NAMED_PIPE:
3661         case TRANSACT_NM_PIPE:
3662                 switch(trans_subcmd){
3663
3664                 case PIPE_LANMAN:
3665                         return dissect_pipe_lanman(pd_tvb, p_tvb, d_tvb, pinfo,
3666                             tree);
3667                         break;
3668
3669                 case PIPE_DCERPC:
3670                         /*
3671                          * Only dissect this if we know the FID.
3672                          */
3673                         if (fid != -1) {
3674                                 if (d_tvb == NULL)
3675                                         return FALSE;
3676                                 return dissect_pipe_dcerpc(d_tvb, pinfo, tree,
3677                                     pipe_tree, fid);
3678                         }
3679                         break;
3680                 }
3681                 break;
3682
3683         case -1:
3684                 /*
3685                  * We don't know the function; we dissect only LANMAN
3686                  * pipe messages, not RPC pipe messages, in that case.
3687                  */
3688                 switch(trans_subcmd){
3689                 case PIPE_LANMAN:
3690                         return dissect_pipe_lanman(pd_tvb, p_tvb, d_tvb, pinfo,
3691                             tree);
3692                         break;
3693                 }
3694                 break;
3695
3696         case WAIT_NAMED_PIPE:
3697                 break;
3698
3699         case PEEK_NAMED_PIPE:
3700                 /*
3701                  * Request contains no parameters or data.
3702                  */
3703                 if (!smb_info->request) {
3704                         if (p_tvb == NULL)
3705                                 return FALSE;
3706                         offset = 0;
3707                         proto_tree_add_item(pipe_tree, hf_pipe_peek_available,
3708                             p_tvb, offset, 2, TRUE);
3709                         offset += 2;
3710                         proto_tree_add_item(pipe_tree, hf_pipe_peek_remaining,
3711                             p_tvb, offset, 2, TRUE);
3712                         offset += 2;
3713                         proto_tree_add_item(pipe_tree, hf_pipe_peek_status,
3714                             p_tvb, offset, 2, TRUE);
3715                         offset += 2;
3716                 }
3717                 break;
3718
3719         case Q_NM_P_HAND_STATE:
3720                 /*
3721                  * Request contains no parameters or data.
3722                  */
3723                 if (!smb_info->request) {
3724                         if (p_tvb == NULL)
3725                                 return FALSE;
3726                         offset = dissect_ipc_state(p_tvb, pipe_tree, 0, FALSE);
3727                 }
3728                 break;
3729
3730         case SET_NM_P_HAND_STATE:
3731                 /*
3732                  * Response contains no parameters or data.
3733                  */
3734                 if (smb_info->request) {
3735                         if (p_tvb == NULL)
3736                                 return FALSE;
3737                         offset = dissect_ipc_state(p_tvb, pipe_tree, 0, TRUE);
3738                 }
3739                 break;
3740
3741         case Q_NM_PIPE_INFO:
3742                 offset = 0;
3743                 if (smb_info->request) {
3744                         if (p_tvb == NULL)
3745                                 return FALSE;
3746
3747                         /*
3748                          * Request contains an information level.
3749                          */
3750                         info_level = tvb_get_letohs(p_tvb, offset);
3751                         proto_tree_add_uint(pipe_tree, hf_pipe_getinfo_info_level,
3752                             p_tvb, offset, 2, info_level);
3753                         offset += 2;
3754                         if (!pinfo->fd->flags.visited)
3755                                 tri->info_level = info_level;
3756                 } else {
3757                         guint8 pipe_namelen;
3758
3759                         if (d_tvb == NULL)
3760                                 return FALSE;
3761
3762                         switch (tri->info_level) {
3763
3764                         case 1:
3765                                 proto_tree_add_item(pipe_tree,
3766                                     hf_pipe_getinfo_output_buffer_size,
3767                                     d_tvb, offset, 2, TRUE);
3768                                 offset += 2;
3769                                 proto_tree_add_item(pipe_tree,
3770                                     hf_pipe_getinfo_input_buffer_size,
3771                                     d_tvb, offset, 2, TRUE);
3772                                 offset += 2;
3773                                 proto_tree_add_item(pipe_tree,
3774                                     hf_pipe_getinfo_maximum_instances,
3775                                     d_tvb, offset, 1, TRUE);
3776                                 offset += 1;
3777                                 proto_tree_add_item(pipe_tree,
3778                                     hf_pipe_getinfo_current_instances,
3779                                     d_tvb, offset, 1, TRUE);
3780                                 offset += 1;
3781                                 pipe_namelen = tvb_get_guint8(d_tvb, offset);
3782                                 proto_tree_add_uint(pipe_tree,
3783                                     hf_pipe_getinfo_pipe_name_length,
3784                                     d_tvb, offset, 1, pipe_namelen);
3785                                 offset += 1;
3786                                 /* XXX - can this be Unicode? */
3787                                 proto_tree_add_item(pipe_tree,
3788                                     hf_pipe_getinfo_pipe_name,
3789                                     d_tvb, offset, pipe_namelen, TRUE);
3790                                 break;
3791                         }
3792                 }
3793                 break;
3794
3795         case RAW_READ_NM_PIPE:
3796                 /*
3797                  * Request contains no parameters or data.
3798                  */
3799                 if (!smb_info->request) {
3800                         if (d_tvb == NULL)
3801                                 return FALSE;
3802
3803                         offset = dissect_file_data(d_tvb, pipe_tree, 0,
3804                             tvb_reported_length(d_tvb),
3805                             tvb_reported_length(d_tvb));
3806                 }
3807                 break;
3808
3809         case RAW_WRITE_NM_PIPE:
3810                 offset = 0;
3811                 if (smb_info->request) {
3812                         if (d_tvb == NULL)
3813                                 return FALSE;
3814
3815                         offset = dissect_file_data(d_tvb, pipe_tree,
3816                             offset, tvb_reported_length(d_tvb),
3817                             tvb_reported_length(d_tvb));
3818                 } else {
3819                         if (p_tvb == NULL)
3820                                 return FALSE;
3821                         proto_tree_add_item(pipe_tree,
3822                             hf_pipe_write_raw_bytes_written,
3823                             p_tvb, offset, 2, TRUE);
3824                         offset += 2;
3825                 }
3826                 break;
3827         }
3828         return TRUE;
3829 }
3830
3831 void
3832 proto_register_smb_pipe(void)
3833 {
3834         static hf_register_info hf[] = {
3835                 { &hf_pipe_function,
3836                         { "Function", "pipe.function", FT_UINT16, BASE_HEX,
3837                         VALS(functions), 0, "SMB Pipe Function Code", HFILL }},
3838                 { &hf_pipe_priority,
3839                         { "Priority", "pipe.priority", FT_UINT16, BASE_DEC,
3840                         NULL, 0, "SMB Pipe Priority", HFILL }},
3841                 { &hf_pipe_peek_available,
3842                         { "Available Bytes", "pipe.peek.available_bytes", FT_UINT16, BASE_DEC,
3843                         NULL, 0, "Total number of bytes available to be read from the pipe", HFILL }},
3844                 { &hf_pipe_peek_remaining,
3845                         { "Bytes Remaining", "pipe.peek.remaining_bytes", FT_UINT16, BASE_DEC,
3846                         NULL, 0, "Total number of bytes remaining in the message at the head of the pipe", HFILL }},
3847                 { &hf_pipe_peek_status,
3848                         { "Pipe Status", "pipe.peek.status", FT_UINT16, BASE_DEC,
3849                         VALS(pipe_status), 0, "Pipe status", HFILL }},
3850                 { &hf_pipe_getinfo_info_level,
3851                         { "Information Level", "pipe.getinfo.info_level", FT_UINT16, BASE_DEC,
3852                         NULL, 0, "Information level of information to return", HFILL }},
3853                 { &hf_pipe_getinfo_output_buffer_size,
3854                         { "Output Buffer Size", "pipe.getinfo.output_buffer_size", FT_UINT16, BASE_DEC,
3855                         NULL, 0, "Actual size of buffer for outgoing (server) I/O", HFILL }},
3856                 { &hf_pipe_getinfo_input_buffer_size,
3857                         { "Input Buffer Size", "pipe.getinfo.input_buffer_size", FT_UINT16, BASE_DEC,
3858                         NULL, 0, "Actual size of buffer for incoming (client) I/O", HFILL }},
3859                 { &hf_pipe_getinfo_maximum_instances,
3860                         { "Maximum Instances", "pipe.getinfo.maximum_instances", FT_UINT8, BASE_DEC,
3861                         NULL, 0, "Maximum allowed number of instances", HFILL }},
3862                 { &hf_pipe_getinfo_current_instances,
3863                         { "Current Instances", "pipe.getinfo.current_instances", FT_UINT8, BASE_DEC,
3864                         NULL, 0, "Current number of instances", HFILL }},
3865                 { &hf_pipe_getinfo_pipe_name_length,
3866                         { "Pipe Name Length", "pipe.getinfo.pipe_name_length", FT_UINT8, BASE_DEC,
3867                         NULL, 0, "Length of pipe name", HFILL }},
3868                 { &hf_pipe_getinfo_pipe_name,
3869                         { "Pipe Name", "pipe.getinfo.pipe_name", FT_STRING, BASE_NONE,
3870                         NULL, 0, "Name of pipe", HFILL }},
3871                 { &hf_pipe_write_raw_bytes_written,
3872                         { "Bytes Written", "pipe.write_raw.bytes_written", FT_UINT16, BASE_DEC,
3873                         NULL, 0, "Number of bytes written to the pipe", HFILL }},
3874                 { &hf_pipe_fragment_overlap,
3875                         { "Fragment overlap",   "pipe.fragment.overlap", FT_BOOLEAN, BASE_NONE,
3876                         NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
3877                 { &hf_pipe_fragment_overlap_conflict,
3878                         { "Conflicting data in fragment overlap",       "pipe.fragment.overlap.conflict", FT_BOOLEAN,
3879                         BASE_NONE, NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
3880                 { &hf_pipe_fragment_multiple_tails,
3881                         { "Multiple tail fragments found",      "pipe.fragment.multipletails", FT_BOOLEAN,
3882                         BASE_NONE, NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
3883                 { &hf_pipe_fragment_too_long_fragment,
3884                         { "Fragment too long",  "pipe.fragment.toolongfragment", FT_BOOLEAN,
3885                         BASE_NONE, NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
3886                 { &hf_pipe_fragment_error,
3887                         { "Defragmentation error", "pipe.fragment.error", FT_FRAMENUM,
3888                         BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
3889                 { &hf_pipe_fragment,
3890                         { "Fragment", "pipe.fragment", FT_FRAMENUM,
3891                         BASE_NONE, NULL, 0x0, "Pipe Fragment", HFILL }},
3892                 { &hf_pipe_fragments,
3893                         { "Fragments", "pipe.fragments", FT_NONE,
3894                         BASE_NONE, NULL, 0x0, "Pipe Fragments", HFILL }},
3895                 { &hf_pipe_reassembled_in,
3896                         { "This PDU is reassembled in", "pipe.reassembled_in", FT_FRAMENUM,
3897                         BASE_NONE, NULL, 0x0, "The DCE/RPC PDU is completely reassembled in this frame", HFILL }},
3898         };
3899         static gint *ett[] = {
3900                 &ett_smb_pipe,
3901                 &ett_smb_pipe_fragment,
3902                 &ett_smb_pipe_fragments,
3903         };
3904
3905         proto_smb_pipe = proto_register_protocol(
3906                 "SMB Pipe Protocol", "SMB Pipe", "pipe");
3907
3908         proto_register_field_array(proto_smb_pipe, hf, array_length(hf));
3909         proto_register_subtree_array(ett, array_length(ett));
3910 }
3911
3912 void
3913 proto_reg_handoff_smb_pipe(void)
3914 {
3915         data_handle = find_dissector("data");
3916 }