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