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