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