pinfo->private_data was a quite subptimal idea
[obnox/wireshark/wip.git] / epan / dissectors / packet-smb-pipe.c
1 /*
2 XXX  Fixme : shouldnt show [malformed frame] for long packets
3 */
4
5 /* packet-smb-pipe.c
6  * Routines for SMB named pipe packet dissection
7  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
8  * significant rewrite to tvbuffify the dissector, Ronnie Sahlberg and
9  * Guy Harris 2001
10  *
11  * $Id$
12  *
13  * Ethereal - Network traffic analyzer
14  * By Gerald Combs <gerald@ethereal.com>
15  * Copyright 1998 Gerald Combs
16  *
17  * Copied from packet-pop.c
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <stdio.h>
39
40 #include <time.h>
41 #include <string.h>
42 #include <glib.h>
43 #include <ctype.h>
44 #include <epan/packet.h>
45 #include "smb.h"
46 #include "packet-smb-pipe.h"
47 #include "packet-smb-browse.h"
48 #include "packet-smb-common.h"
49 #include "packet-windows-common.h"
50 #include "packet-dcerpc.h"
51 #include <epan/reassemble.h>
52
53 static int proto_smb_pipe = -1;
54 static int hf_pipe_function = -1;
55 static int hf_pipe_priority = -1;
56 static int hf_pipe_peek_available = -1;
57 static int hf_pipe_peek_remaining = -1;
58 static int hf_pipe_peek_status = -1;
59 static int hf_pipe_getinfo_info_level = -1;
60 static int hf_pipe_getinfo_output_buffer_size = -1;
61 static int hf_pipe_getinfo_input_buffer_size = -1;
62 static int hf_pipe_getinfo_maximum_instances = -1;
63 static int hf_pipe_getinfo_current_instances = -1;
64 static int hf_pipe_getinfo_pipe_name_length = -1;
65 static int hf_pipe_getinfo_pipe_name = -1;
66 static int hf_pipe_write_raw_bytes_written = -1;
67 static int hf_pipe_fragments = -1;
68 static int hf_pipe_fragment = -1;
69 static int hf_pipe_fragment_overlap = -1;
70 static int hf_pipe_fragment_overlap_conflict = -1;
71 static int hf_pipe_fragment_multiple_tails = -1;
72 static int hf_pipe_fragment_too_long_fragment = -1;
73 static int hf_pipe_fragment_error = -1;
74 static int hf_pipe_reassembled_in = -1;
75
76 static gint ett_smb_pipe = -1;
77 static gint ett_smb_pipe_fragment = -1;
78 static gint ett_smb_pipe_fragments = -1;
79
80 static const fragment_items smb_pipe_frag_items = {
81         &ett_smb_pipe_fragment,
82         &ett_smb_pipe_fragments,
83         &hf_pipe_fragments,
84         &hf_pipe_fragment,
85         &hf_pipe_fragment_overlap,
86         &hf_pipe_fragment_overlap_conflict,
87         &hf_pipe_fragment_multiple_tails,
88         &hf_pipe_fragment_too_long_fragment,
89         &hf_pipe_fragment_error,
90         NULL,
91         "fragments"
92 };
93
94 static int proto_smb_lanman = -1;
95 static int hf_function_code = -1;
96 static int hf_param_desc = -1;
97 static int hf_return_desc = -1;
98 static int hf_aux_data_desc = -1;
99 static int hf_detail_level = -1;
100 static int hf_recv_buf_len = -1;
101 static int hf_send_buf_len = -1;
102 static int hf_continuation_from = -1;
103 static int hf_status = -1;
104 static int hf_convert = -1;
105 static int hf_ecount = -1;
106 static int hf_acount = -1;
107 static int hf_share_name = -1;
108 static int hf_share_type = -1;
109 static int hf_share_comment = -1;
110 static int hf_share_permissions = -1;
111 static int hf_share_max_uses = -1;
112 static int hf_share_current_uses = -1;
113 static int hf_share_path = -1;
114 static int hf_share_password = -1;
115 static int hf_server_name = -1;
116 static int hf_server_major = -1;
117 static int hf_server_minor = -1;
118 static int hf_server_comment = -1;
119 static int hf_abytes = -1;
120 static int hf_current_time = -1;
121 static int hf_msecs = -1;
122 static int hf_hour = -1;
123 static int hf_minute = -1;
124 static int hf_second = -1;
125 static int hf_hundredths = -1;
126 static int hf_tzoffset = -1;
127 static int hf_timeinterval = -1;
128 static int hf_day = -1;
129 static int hf_month = -1;
130 static int hf_year = -1;
131 static int hf_weekday = -1;
132 static int hf_enumeration_domain = -1;
133 static int hf_last_entry = -1;
134 static int hf_computer_name = -1;
135 static int hf_user_name = -1;
136 static int hf_group_name = -1;
137 static int hf_workstation_domain = -1;
138 static int hf_workstation_major = -1;
139 static int hf_workstation_minor = -1;
140 static int hf_logon_domain = -1;
141 static int hf_other_domains = -1;
142 static int hf_password = -1;
143 static int hf_workstation_name = -1;
144 static int hf_ustruct_size = -1;
145 static int hf_logon_code = -1;
146 static int hf_privilege_level = -1;
147 static int hf_operator_privileges = -1;
148 static int hf_num_logons = -1;
149 static int hf_bad_pw_count = -1;
150 static int hf_last_logon = -1;
151 static int hf_last_logoff = -1;
152 static int hf_logoff_time = -1;
153 static int hf_kickoff_time = -1;
154 static int hf_password_age = -1;
155 static int hf_password_can_change = -1;
156 static int hf_password_must_change = -1;
157 static int hf_script_path = -1;
158 static int hf_logoff_code = -1;
159 static int hf_duration = -1;
160 static int hf_comment = -1;
161 static int hf_user_comment = -1;
162 static int hf_full_name = -1;
163 static int hf_homedir = -1;
164 static int hf_parameters = -1;
165 static int hf_logon_server = -1;
166 static int hf_country_code = -1;
167 static int hf_workstations = -1;
168 static int hf_max_storage = -1;
169 static int hf_units_per_week = -1;
170 static int hf_logon_hours = -1;
171 static int hf_code_page = -1;
172 static int hf_new_password = -1;
173 static int hf_old_password = -1;
174 static int hf_reserved = -1;
175
176 static gint ett_lanman = -1;
177 static gint ett_lanman_unknown_entries = -1;
178 static gint ett_lanman_unknown_entry = -1;
179 static gint ett_lanman_shares = -1;
180 static gint ett_lanman_share = -1;
181 static gint ett_lanman_groups = -1;
182 static gint ett_lanman_servers = -1;
183 static gint ett_lanman_server = -1;
184
185 static dissector_handle_t data_handle;
186
187 /*
188  * See
189  *
190  *      ftp://ftp.microsoft.com/developr/drg/CIFS/cifsrap2.txt
191  *
192  * among other documents.
193  */
194
195 static const value_string status_vals[] = {
196         {0,     "Success"},
197         {5,     "User has insufficient privilege"},
198         {65,    "Network access is denied"},
199         {86,    "The specified password is invalid"},
200         {SMBE_moredata, "Additional data is available"},
201         {2114,  "Service is not running on the remote computer"},
202         {2123,  "Supplied buffer is too small"},
203         {2141,  "Server is not configured for transactions (IPC$ not shared)"},
204         {2212,  "An error occurred while loading or running the logon script"},
205         {2214,  "The logon was not validated by any server"},
206         {2217,  "The logon server is running an older software version"},
207         {2221,  "The user name was not found"},
208         {2226,  "Operation not permitted on Backup Domain Controller"},
209         {2240,  "The user is not allowed to logon from this computer"},
210         {2241,  "The user is not allowed to logon at this time"},
211         {2242,  "The user password has expired"},
212         {2243,  "The password cannot be changed"},
213         {2246,  "The password is too short"},
214         {0,     NULL}
215 };
216
217 static const value_string privilege_vals[] = {
218         {0, "Guest"},
219         {1, "User"},
220         {2, "Administrator"},
221         {0, NULL}
222 };
223
224 static const value_string op_privilege_vals[] = {
225         {0, "Print operator"},
226         {1, "Communications operator"},
227         {2, "Server operator"},
228         {3, "Accounts operator"},
229         {0, NULL}
230 };
231
232 static const value_string weekday_vals[] = {
233         {0, "Sunday"},
234         {1, "Monday"},
235         {2, "Tuesday"},
236         {3, "Wednesday"},
237         {4, "Thursday"},
238         {5, "Friday"},
239         {6, "Saturday"},
240         {0, NULL}
241 };
242
243 static int
244 add_word_param(tvbuff_t *tvb, int offset, int count _U_,
245     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
246 {
247         guint16 WParam;
248
249         if (hf_index != -1)
250                 proto_tree_add_item(tree, hf_index, tvb, offset, 2, TRUE);
251         else {
252                 WParam = tvb_get_letohs(tvb, offset);
253                 proto_tree_add_text(tree, tvb, offset, 2,
254                     "Word Param: %u (0x%04X)", WParam, WParam);
255         }
256         offset += 2;
257         return offset;
258 }
259
260 static int
261 add_dword_param(tvbuff_t *tvb, int offset, int count _U_,
262     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
263 {
264         guint32 LParam;
265
266         if (hf_index != -1)
267                 proto_tree_add_item(tree, hf_index, tvb, offset, 4, TRUE);
268         else {
269                 LParam = tvb_get_letohl(tvb, offset);
270                 proto_tree_add_text(tree, tvb, offset, 4,
271                     "Doubleword Param: %u (0x%08X)", LParam, LParam);
272         }
273         offset += 4;
274         return offset;
275 }
276
277 static int
278 add_byte_param(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
279     proto_tree *tree, int convert _U_, int hf_index)
280 {
281         guint8 BParam;
282
283         if (hf_index != -1)
284                 proto_tree_add_item(tree, hf_index, tvb, offset, count, TRUE);
285         else {
286                 if (count == 1) {
287                         BParam = tvb_get_guint8(tvb, offset);
288                         proto_tree_add_text(tree, tvb, offset, count,
289                             "Byte Param: %u (0x%02X)",
290                             BParam, BParam);
291                 } else {
292                         proto_tree_add_text(tree, tvb, offset, count,
293                             "Byte Param: %s",
294                             tvb_bytes_to_str(tvb, offset, count));
295                 }
296         }
297         offset += count;
298         return offset;
299 }
300
301 static int
302 add_pad_param(tvbuff_t *tvb _U_, int offset, int count, packet_info *pinfo _U_,
303     proto_tree *tree _U_, int convert _U_, int hf_index _U_)
304 {
305         /*
306          * This is for parameters that have descriptor entries but that
307          * are, in practice, just padding.
308          */
309         offset += count;
310         return offset;
311 }
312
313 static void
314 add_null_pointer_param(tvbuff_t *tvb, int offset, int count _U_,
315     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
316 {
317         if (hf_index != -1) {
318                 proto_tree_add_text(tree, tvb, offset, 0,
319                   "%s (Null pointer)",
320                   proto_registrar_get_name(hf_index));
321         } else {
322                 proto_tree_add_text(tree, tvb, offset, 0,
323                     "String Param (Null pointer)");
324         }
325 }
326
327 static int
328 add_string_param(tvbuff_t *tvb, int offset, int count _U_,
329     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
330 {
331         guint string_len;
332
333         string_len = tvb_strsize(tvb, offset);
334         if (hf_index != -1) {
335                 proto_tree_add_item(tree, hf_index, tvb, offset, string_len,
336                     TRUE);
337         } else {
338                 proto_tree_add_text(tree, tvb, offset, string_len,
339                     "String Param: %s",
340                     tvb_format_text(tvb, offset, string_len));
341         }
342         offset += string_len;
343         return offset;
344 }
345
346 static const char *
347 get_stringz_pointer_value(tvbuff_t *tvb, int offset, int convert, int *cptrp,
348     int *lenp)
349 {
350         int cptr;
351         gint string_len;
352
353         /* pointer to string */
354         cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
355         *cptrp = cptr;
356
357         /* string */
358         if (tvb_offset_exists(tvb, cptr) &&
359             (string_len = tvb_strnlen(tvb, cptr, -1)) != -1) {
360                 string_len++;   /* include the terminating '\0' */
361                 *lenp = string_len;
362                 return tvb_format_text(tvb, cptr, string_len - 1);
363         } else
364                 return NULL;
365 }
366
367 static int
368 add_stringz_pointer_param(tvbuff_t *tvb, int offset, int count _U_,
369     packet_info *pinfo _U_, proto_tree *tree, int convert, int hf_index)
370 {
371         int cptr;
372         const char *string;
373         gint string_len;
374
375         string = get_stringz_pointer_value(tvb, offset, convert, &cptr,
376             &string_len);
377         offset += 4;
378
379         /* string */
380         if (string != NULL) {
381                 if (hf_index != -1) {
382                         proto_tree_add_item(tree, hf_index, tvb, cptr,
383                             string_len, TRUE);
384                 } else {
385                         proto_tree_add_text(tree, tvb, cptr, string_len,
386                             "String Param: %s", string);
387                 }
388         } else {
389                 if (hf_index != -1) {
390                         proto_tree_add_text(tree, tvb, 0, 0,
391                             "%s: <String goes past end of frame>",
392                             proto_registrar_get_name(hf_index));
393                 } else {
394                         proto_tree_add_text(tree, tvb, 0, 0,
395                             "String Param: <String goes past end of frame>");
396                 }
397         }
398
399         return offset;
400 }
401
402 static int
403 add_bytes_pointer_param(tvbuff_t *tvb, int offset, int count,
404     packet_info *pinfo _U_, proto_tree *tree, int convert, int hf_index)
405 {
406         int cptr;
407
408         /* pointer to byte array */
409         cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
410         offset += 4;
411
412         /* bytes */
413         if (tvb_bytes_exist(tvb, cptr, count)) {
414                 if (hf_index != -1) {
415                         proto_tree_add_item(tree, hf_index, tvb, cptr,
416                             count, TRUE);
417                 } else {
418                         proto_tree_add_text(tree, tvb, cptr, count,
419                             "Byte Param: %s",
420                             tvb_bytes_to_str(tvb, cptr, count));
421                 }
422         } else {
423                 if (hf_index != -1) {
424                         proto_tree_add_text(tree, tvb, 0, 0,
425                             "%s: <Bytes go past end of frame>",
426                             proto_registrar_get_name(hf_index));
427                 } else {
428                         proto_tree_add_text(tree, tvb, 0, 0,
429                             "Byte Param: <Bytes goes past end of frame>");
430                 }
431         }
432
433         return offset;
434 }
435
436 static int
437 add_detail_level(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo,
438     proto_tree *tree, int convert _U_, int hf_index)
439 {
440         struct smb_info *smb_info = pinfo->private_data;
441         smb_transact_info_t *trp = smb_info->sip->extra_info;
442         guint16 level;
443
444         level = tvb_get_letohs(tvb, offset);
445         if (!pinfo->fd->flags.visited)
446                 trp->info_level = level;        /* remember this for the response */
447         proto_tree_add_uint(tree, hf_index, tvb, offset, 2, level);
448         offset += 2;
449         return offset;
450 }
451
452 static int
453 add_max_uses(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
454     proto_tree *tree, int convert _U_, int hf_index)
455 {
456         guint16 WParam;
457
458         WParam = tvb_get_letohs(tvb, offset);
459         if (WParam == 0xffff) { /* -1 */
460                 proto_tree_add_uint_format(tree, hf_index, tvb,
461                     offset, 2, WParam,
462                     "%s: No limit",
463                     proto_registrar_get_name(hf_index));
464         } else {
465                 proto_tree_add_uint(tree, hf_index, tvb,
466                             offset, 2, WParam);
467         }
468         offset += 2;
469         return offset;
470 }
471
472 static int
473 add_server_type(tvbuff_t *tvb, int offset, int count _U_,
474     packet_info *pinfo, proto_tree *tree, int convert _U_, int hf_index _U_)
475 {
476         offset = dissect_smb_server_type_flags(
477                 tvb, offset, pinfo, tree, NULL, FALSE);
478         return offset;
479 }
480
481 static int
482 add_server_type_info(tvbuff_t *tvb, int offset, int count _U_,
483     packet_info *pinfo, proto_tree *tree, int convert _U_, int hf_index _U_)
484 {
485         offset = dissect_smb_server_type_flags(
486                 tvb, offset, pinfo, tree, NULL, TRUE);
487         return offset;
488 }
489
490 static int
491 add_reltime(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
492     proto_tree *tree, int convert _U_, int hf_index)
493 {
494         nstime_t nstime;
495
496         nstime.secs = tvb_get_letohl(tvb, offset);
497         nstime.nsecs = 0;
498         proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
499             &nstime, "%s: %s", proto_registrar_get_name(hf_index),
500             time_secs_to_str(nstime.secs));
501         offset += 4;
502         return offset;
503 }
504
505 /*
506  * Sigh.  These are for handling Microsoft's annoying almost-UNIX-time-but-
507  * it's-local-time-not-UTC time.
508  */
509 static int
510 add_abstime_common(tvbuff_t *tvb, int offset, proto_tree *tree, int hf_index,
511     const char *absent_name)
512 {
513         nstime_t nstime;
514         struct tm *tmp;
515
516         nstime.secs = tvb_get_letohl(tvb, offset);
517         nstime.nsecs = 0;
518         /*
519          * Sigh.  Sometimes it appears that -1 means "unknown", and
520          * sometimes it appears that 0 means "unknown", for the last
521          * logoff date/time.
522          */
523         if (nstime.secs == -1 || nstime.secs == 0) {
524                 proto_tree_add_time_format(tree, hf_index, tvb, offset, 4,
525                     &nstime, "%s: %s", proto_registrar_get_name(hf_index),
526                     absent_name);
527         } else {
528                 /*
529                  * Run it through "gmtime()" to break it down, and then
530                  * run it through "mktime()" to put it back together
531                  * as UTC.
532                  */
533                 tmp = gmtime(&nstime.secs);
534                 tmp->tm_isdst = -1;     /* we don't know if it's DST or not */
535                 nstime.secs = mktime(tmp);
536                 proto_tree_add_time(tree, hf_index, tvb, offset, 4,
537                     &nstime);
538         }
539         offset += 4;
540         return offset;
541 }
542
543 static int
544 add_abstime_absent_never(tvbuff_t *tvb, int offset, int count _U_,
545     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
546 {
547         return add_abstime_common(tvb, offset, tree, hf_index, "Never");
548 }
549
550 static int
551 add_abstime_absent_unknown(tvbuff_t *tvb, int offset, int count _U_,
552     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
553 {
554         return add_abstime_common(tvb, offset, tree, hf_index, "Unknown");
555 }
556
557 static int
558 add_nlogons(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
559     proto_tree *tree, int convert _U_, int hf_index)
560 {
561         guint16 nlogons;
562
563         nlogons = tvb_get_letohs(tvb, offset);
564         if (nlogons == 0xffff)  /* -1 */
565                 proto_tree_add_uint_format(tree, hf_index, tvb, offset, 2,
566                     nlogons, "%s: Unknown",
567                     proto_registrar_get_name(hf_index));
568         else
569                 proto_tree_add_uint(tree, hf_index, tvb, offset, 2,
570                     nlogons);
571         offset += 2;
572         return offset;
573 }
574
575 static int
576 add_max_storage(tvbuff_t *tvb, int offset, int count _U_,
577     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
578 {
579         guint32 max_storage;
580
581         max_storage = tvb_get_letohl(tvb, offset);
582         if (max_storage == 0xffffffff)
583                 proto_tree_add_uint_format(tree, hf_index, tvb, offset, 4,
584                     max_storage, "%s: No limit",
585                     proto_registrar_get_name(hf_index));
586         else
587                 proto_tree_add_uint(tree, hf_index, tvb, offset, 4,
588                     max_storage);
589         offset += 4;
590         return offset;
591 }
592
593 static int
594 add_logon_hours(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
595     proto_tree *tree, int convert, int hf_index)
596 {
597         int cptr;
598
599         /* pointer to byte array */
600         cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
601         offset += 4;
602
603         /* bytes */
604         if (tvb_bytes_exist(tvb, cptr, count)) {
605                 if (count == 21) {
606                         /*
607                          * The logon hours should be exactly 21 bytes long.
608                          *
609                          * XXX - should actually carve up the bits;
610                          * we need the units per week to do that, though.
611                          */
612                         proto_tree_add_item(tree, hf_index, tvb, cptr, count,
613                             TRUE);
614                 } else {
615                         proto_tree_add_bytes_format(tree, hf_index, tvb,
616                             cptr, count, tvb_get_ptr(tvb, cptr, count),
617                             "%s: %s (wrong length, should be 21, is %d",
618                             proto_registrar_get_name(hf_index),
619                             tvb_bytes_to_str(tvb, cptr, count), count);
620                 }
621         } else {
622                 proto_tree_add_text(tree, tvb, 0, 0,
623                     "%s: <Bytes go past end of frame>",
624                     proto_registrar_get_name(hf_index));
625         }
626
627         return offset;
628 }
629
630 static int
631 add_tzoffset(tvbuff_t *tvb, int offset, int count _U_, packet_info *pinfo _U_,
632     proto_tree *tree, int convert _U_, int hf_index)
633 {
634         gint16 tzoffset;
635
636         tzoffset = tvb_get_letohs(tvb, offset);
637         if (tzoffset < 0) {
638                 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
639                     tzoffset, "%s: %s east of UTC",
640                     proto_registrar_get_name(hf_index),
641                     time_secs_to_str(-tzoffset*60));
642         } else if (tzoffset > 0) {
643                 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
644                     tzoffset, "%s: %s west of UTC",
645                     proto_registrar_get_name(hf_index),
646                     time_secs_to_str(tzoffset*60));
647         } else {
648                 proto_tree_add_int_format(tree, hf_tzoffset, tvb, offset, 2,
649                     tzoffset, "%s: at UTC",
650                     proto_registrar_get_name(hf_index));
651         }
652         offset += 2;
653         return offset;
654 }
655
656 static int
657 add_timeinterval(tvbuff_t *tvb, int offset, int count _U_,
658     packet_info *pinfo _U_, proto_tree *tree, int convert _U_, int hf_index)
659 {
660         guint16 timeinterval;
661
662         timeinterval = tvb_get_letohs(tvb, offset);
663         proto_tree_add_uint_format(tree, hf_timeinterval, tvb, offset, 2,
664            timeinterval, "%s: %f seconds", proto_registrar_get_name(hf_index),
665            timeinterval*.0001);
666         offset += 2;
667         return offset;
668 }
669
670 static int
671 add_logon_args(tvbuff_t *tvb, int offset, int count, packet_info *pinfo _U_,
672     proto_tree *tree, int convert _U_, int hf_index _U_)
673 {
674         if (count != 54) {
675                 proto_tree_add_text(tree, tvb, offset, count,
676                    "Bogus NetWkstaUserLogon parameters: length is %d, should be 54",
677                    count);
678                 offset += count;
679                 return offset;
680         }
681
682         /* user name */
683         proto_tree_add_item(tree, hf_user_name, tvb, offset, 21, TRUE);
684         offset += 21;
685
686         /* pad1 */
687         offset += 1;
688
689         /* password */
690         proto_tree_add_item(tree, hf_password, tvb, offset, 15, TRUE);
691         offset += 15;
692
693         /* pad2 */
694         offset += 1;
695
696         /* workstation name */
697         proto_tree_add_item(tree, hf_workstation_name, tvb, offset, 16, TRUE);
698         offset += 16;
699         return offset;
700 }
701
702 /*
703  * The following data structure describes the Remote API requests we
704  * understand.
705  *
706  * Simply fill in the number and parameter information.
707  * Try to keep them in order.
708  *
709  * We will extend this data structure as we try to decode more.
710  */
711
712 /*
713  * This is a pointer to a function to process an item.
714  */
715 typedef int     (*item_func)(tvbuff_t *, int, int, packet_info *, proto_tree *,
716                              int, int);
717
718 /*
719  * Type of an item; determines what parameter strings are valid for
720  * the item.
721  */
722 typedef enum {
723         PARAM_NONE,     /* for the end-of-list stopper */
724         PARAM_WORD,     /* 'W' or 'h' - 16-bit word */
725         PARAM_DWORD,    /* 'D' or 'i' - 32-bit word */
726         PARAM_BYTES,    /* 'B' or 'b' or 'g' or 'O' - one or more bytes */
727         PARAM_STRINGZ   /* 'z' or 'O' - null-terminated string */
728 } param_type_t;
729
730 /*
731  * This structure describes an item; "hf_index" points to the index
732  * for the field corresponding to that item, "func" points to the
733  * function to use to add that item to the tree, and "type" is the
734  * type that the item is supposed to have.
735  */
736 typedef struct {
737         int             *hf_index;
738         item_func       func;
739         param_type_t    type;
740 } item_t;
741
742 /*
743  * This structure describes a list of items; each list of items
744  * has a corresponding detail level.
745  */
746 typedef struct {
747         int             level;
748         const item_t    *item_list;
749 } item_list_t;
750
751 struct lanman_desc {
752         int             lanman_num;
753         const item_t    *req;
754         proto_item      *(*req_data_item)(tvbuff_t *, packet_info *,
755                                           proto_tree *, int);
756         gint            *ett_req_data;
757         const item_t    *req_data;
758         const item_t    *req_aux_data;
759         const item_t    *resp;
760         const gchar     *resp_data_entry_list_label;
761         gint            *ett_data_entry_list;
762         proto_item      *(*resp_data_element_item)(tvbuff_t *, proto_tree *,
763                                                    int);
764         gint            *ett_resp_data_element_item;
765         const item_list_t *resp_data_list;
766         const item_t    *resp_aux_data;
767 };
768
769 static int no_hf = -1;  /* for padding crap */
770
771 static const item_t lm_params_req_netshareenum[] = {
772         { &hf_detail_level, add_detail_level, PARAM_WORD },
773         { &hf_recv_buf_len, add_word_param, PARAM_WORD },
774         { NULL, NULL, PARAM_NONE }
775 };
776
777 static const item_t lm_params_resp_netshareenum[] = {
778         { &hf_acount, add_word_param, PARAM_WORD },
779         { NULL, NULL, PARAM_NONE }
780 };
781
782 /*
783  * Create a subtree for a share.
784  */
785 static proto_item *
786 netshareenum_share_entry(tvbuff_t *tvb, proto_tree *tree, int offset)
787 {
788         if (tree) {
789                 return proto_tree_add_text(tree, tvb, offset, -1,
790                     "Share %.13s", tvb_get_ptr(tvb, offset, 13));
791         } else
792                 return NULL;
793 }
794
795 static const item_t lm_null[] = {
796         { NULL, NULL, PARAM_NONE }
797 };
798
799 static const item_list_t lm_null_list[] = {
800         { -1, lm_null }
801 };
802
803 static const item_t lm_data_resp_netshareenum_1[] = {
804         { &hf_share_name, add_byte_param, PARAM_BYTES },
805         { &no_hf, add_pad_param, PARAM_BYTES },
806         { &hf_share_type, add_word_param, PARAM_WORD },
807         { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
808         { NULL, NULL, PARAM_NONE }
809 };
810
811 static const item_list_t lm_data_resp_netshareenum[] = {
812         { 1, lm_data_resp_netshareenum_1 },
813         { -1, lm_null }
814 };
815
816 static const item_t lm_params_req_netsharegetinfo[] = {
817         { &hf_share_name, add_string_param, PARAM_STRINGZ },
818         { &hf_detail_level, add_detail_level, PARAM_WORD },
819         { NULL, NULL, PARAM_NONE }
820 };
821
822 static const item_t lm_params_resp_netsharegetinfo[] = {
823         { &hf_abytes, add_word_param, PARAM_WORD },
824         { NULL, NULL, PARAM_NONE }
825 };
826
827 static const item_t lm_data_resp_netsharegetinfo_0[] = {
828         { &hf_share_name, add_byte_param, PARAM_BYTES },
829         { NULL, NULL, PARAM_NONE }
830 };
831
832 static const item_t lm_data_resp_netsharegetinfo_1[] = {
833         { &hf_share_name, add_byte_param, PARAM_BYTES },
834         { &no_hf, add_pad_param, PARAM_BYTES },
835         { &hf_share_type, add_word_param, PARAM_WORD },
836         { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
837         { NULL, NULL, PARAM_NONE }
838 };
839
840 static const item_t lm_data_resp_netsharegetinfo_2[] = {
841         { &hf_share_name, add_byte_param, PARAM_BYTES },
842         { &no_hf, add_pad_param, PARAM_BYTES },
843         { &hf_share_type, add_word_param, PARAM_WORD },
844         { &hf_share_comment, add_stringz_pointer_param, PARAM_STRINGZ },
845         { &hf_share_permissions, add_word_param, PARAM_WORD }, /* XXX - do as bit fields */
846         { &hf_share_max_uses, add_max_uses, PARAM_WORD },
847         { &hf_share_current_uses, add_word_param, PARAM_WORD },
848         { &hf_share_path, add_stringz_pointer_param, PARAM_STRINGZ },
849         { &hf_share_password, add_byte_param, PARAM_BYTES },
850         { NULL, NULL, PARAM_NONE }
851 };
852
853 static const item_list_t lm_data_resp_netsharegetinfo[] = {
854         { 0, lm_data_resp_netsharegetinfo_0 },
855         { 1, lm_data_resp_netsharegetinfo_1 },
856         { 2, lm_data_resp_netsharegetinfo_2 },
857         { -1, lm_null }
858 };
859
860 static const item_t lm_params_req_netservergetinfo[] = {
861         { &hf_detail_level, add_detail_level, PARAM_WORD },
862         { NULL, NULL, PARAM_NONE }
863 };
864
865 static const item_t lm_params_resp_netservergetinfo[] = {
866         { &hf_abytes, add_word_param, PARAM_WORD },
867         { NULL, NULL, PARAM_NONE }
868 };
869
870 static const item_t lm_data_serverinfo_0[] = {
871         { &hf_server_name, add_byte_param, PARAM_BYTES },
872         { NULL, NULL, PARAM_NONE }
873 };
874
875 static const item_t lm_data_serverinfo_1[] = {
876         { &hf_server_name, add_byte_param, PARAM_BYTES },
877         { &hf_server_major, add_byte_param, PARAM_BYTES },
878         { &hf_server_minor, add_byte_param, PARAM_BYTES },
879         { &no_hf, add_server_type, PARAM_DWORD },
880         { &hf_server_comment, add_stringz_pointer_param, PARAM_STRINGZ },
881         { NULL, NULL, PARAM_NONE }
882 };
883
884 static const item_list_t lm_data_serverinfo[] = {
885         { 0, lm_data_serverinfo_0 },
886         { 1, lm_data_serverinfo_1 },
887         { -1, lm_null }
888 };
889
890 static const item_t lm_params_req_netusergetinfo[] = {
891         { &hf_user_name, add_string_param, PARAM_STRINGZ },
892         { &hf_detail_level, add_detail_level, PARAM_WORD },
893         { NULL, NULL, PARAM_NONE }
894 };
895
896 static const item_t lm_params_resp_netusergetinfo[] = {
897         { &hf_abytes, add_word_param, PARAM_WORD },
898         { NULL, NULL, PARAM_NONE }
899 };
900
901 static const item_t lm_data_resp_netusergetinfo_11[] = {
902         { &hf_user_name, add_byte_param, PARAM_BYTES },
903         { &no_hf, add_pad_param, PARAM_BYTES },
904         { &hf_comment, add_stringz_pointer_param, PARAM_STRINGZ },
905         { &hf_user_comment, add_stringz_pointer_param, PARAM_STRINGZ },
906         { &hf_full_name, add_stringz_pointer_param, PARAM_STRINGZ },
907         { &hf_privilege_level, add_word_param, PARAM_WORD },
908         { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
909         { &hf_password_age, add_reltime, PARAM_DWORD },
910         { &hf_homedir, add_stringz_pointer_param, PARAM_STRINGZ },
911         { &hf_parameters, add_stringz_pointer_param, PARAM_STRINGZ },
912         { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
913         { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
914         { &hf_bad_pw_count, add_word_param, PARAM_WORD },
915         { &hf_num_logons, add_nlogons, PARAM_WORD },
916         { &hf_logon_server, add_stringz_pointer_param, PARAM_STRINGZ },
917         { &hf_country_code, add_word_param, PARAM_WORD },
918         { &hf_workstations, add_stringz_pointer_param, PARAM_STRINGZ },
919         { &hf_max_storage, add_max_storage, PARAM_DWORD },
920         { &hf_units_per_week, add_word_param, PARAM_WORD },
921         { &hf_logon_hours, add_logon_hours, PARAM_BYTES },
922         { &hf_code_page, add_word_param, PARAM_WORD },
923         { NULL, NULL, PARAM_NONE }
924 };
925
926 static const item_list_t lm_data_resp_netusergetinfo[] = {
927         { 11, lm_data_resp_netusergetinfo_11 },
928         { -1, lm_null }
929 };
930
931 static const item_t lm_params_req_netusergetgroups[] = {
932         { &hf_user_name, add_string_param, PARAM_STRINGZ },
933         { &hf_detail_level, add_detail_level, PARAM_WORD },
934         { NULL, NULL, PARAM_NONE }
935 };
936
937 static const item_t lm_params_resp_netusergetgroups[] = {
938         { &hf_abytes, add_word_param, PARAM_WORD },
939         { NULL, NULL, PARAM_NONE }
940 };
941
942 static const item_t lm_data_resp_netusergetgroups_0[] = {
943         { &hf_group_name, add_byte_param, PARAM_BYTES },
944         { NULL, NULL, PARAM_NONE }
945 };
946
947 static const item_list_t lm_data_resp_netusergetgroups[] = {
948         { 0, lm_data_resp_netusergetgroups_0 },
949         { -1, lm_null }
950 };
951
952 /*
953  * Has no detail level; make it the default.
954  */
955 static const item_t lm_data_resp_netremotetod_nolevel[] = {
956         { &hf_current_time, add_abstime_absent_unknown, PARAM_DWORD },
957         { &hf_msecs, add_dword_param, PARAM_DWORD },
958         { &hf_hour, add_byte_param, PARAM_BYTES },
959         { &hf_minute, add_byte_param, PARAM_BYTES },
960         { &hf_second, add_byte_param, PARAM_BYTES },
961         { &hf_hundredths, add_byte_param, PARAM_BYTES },
962         { &hf_tzoffset, add_tzoffset, PARAM_WORD },
963         { &hf_timeinterval, add_timeinterval, PARAM_WORD },
964         { &hf_day, add_byte_param, PARAM_BYTES },
965         { &hf_month, add_byte_param, PARAM_BYTES },
966         { &hf_year, add_word_param, PARAM_WORD },
967         { &hf_weekday, add_byte_param, PARAM_BYTES },
968         { NULL, NULL, PARAM_NONE }
969 };
970
971 static const item_list_t lm_data_resp_netremotetod[] = {
972         { -1, lm_data_resp_netremotetod_nolevel },
973 };
974
975 static const item_t lm_params_req_netserverenum2[] = {
976         { &hf_detail_level, add_detail_level, PARAM_WORD },
977         { &no_hf, add_server_type_info, PARAM_DWORD },
978         { &hf_enumeration_domain, add_string_param, PARAM_STRINGZ },
979         { NULL, NULL, PARAM_NONE }
980 };
981
982 /*
983  * Create a subtree for a server.
984  */
985 static proto_item *
986 netserverenum2_server_entry(tvbuff_t *tvb, proto_tree *tree, int offset)
987 {
988         if (tree) {
989                 return proto_tree_add_text(tree, tvb, offset, -1,
990                             "Server %.16s", tvb_get_ptr(tvb, offset, 16));
991         } else
992                 return NULL;
993 }
994
995 static const item_t lm_params_resp_netserverenum2[] = {
996         { &hf_acount, add_word_param, PARAM_WORD },
997         { NULL, NULL, PARAM_NONE }
998 };
999
1000
1001 static const item_t lm_params_req_netserverenum3[] = {
1002         { &hf_detail_level, add_detail_level, PARAM_WORD },
1003         { &no_hf, add_server_type_info, PARAM_DWORD },
1004         { &hf_enumeration_domain, add_string_param, PARAM_STRINGZ },
1005         { &hf_last_entry, add_string_param, PARAM_STRINGZ },
1006         { NULL, NULL, PARAM_NONE }
1007 };
1008
1009
1010 static const item_t lm_params_req_netwkstagetinfo[] = {
1011         { &hf_detail_level, add_detail_level, PARAM_WORD },
1012         { NULL, NULL, PARAM_NONE }
1013 };
1014
1015 static const item_t lm_params_resp_netwkstagetinfo[] = {
1016         { &hf_abytes, add_word_param, PARAM_WORD },
1017         { NULL, NULL, PARAM_NONE }
1018 };
1019
1020 static const item_t lm_data_resp_netwkstagetinfo_10[] = {
1021         { &hf_computer_name, add_stringz_pointer_param, PARAM_STRINGZ },
1022         { &hf_user_name, add_stringz_pointer_param, PARAM_STRINGZ },
1023         { &hf_workstation_domain, add_stringz_pointer_param, PARAM_STRINGZ },
1024         { &hf_workstation_major, add_byte_param, PARAM_BYTES },
1025         { &hf_workstation_minor, add_byte_param, PARAM_BYTES },
1026         { &hf_logon_domain, add_stringz_pointer_param, PARAM_STRINGZ },
1027         { &hf_other_domains, add_stringz_pointer_param, PARAM_STRINGZ },
1028         { NULL, NULL, PARAM_NONE }
1029 };
1030
1031 static const item_list_t lm_data_resp_netwkstagetinfo[] = {
1032         { 10, lm_data_resp_netwkstagetinfo_10 },
1033         { -1, lm_null }
1034 };
1035
1036 static const item_t lm_params_req_netwkstauserlogon[] = {
1037         { &no_hf, add_stringz_pointer_param, PARAM_STRINGZ },
1038         { &no_hf, add_stringz_pointer_param, PARAM_STRINGZ },
1039         { &hf_detail_level, add_detail_level, PARAM_WORD },
1040         { &no_hf, add_logon_args, PARAM_BYTES },
1041         { &hf_ustruct_size, add_word_param, PARAM_WORD },
1042         { NULL, NULL, PARAM_NONE }
1043 };
1044
1045 static const item_t lm_params_resp_netwkstauserlogon[] = {
1046         { &hf_abytes, add_word_param, PARAM_WORD },
1047         { NULL, NULL, PARAM_NONE }
1048 };
1049
1050 static const item_t lm_data_resp_netwkstauserlogon_1[] = {
1051         { &hf_logon_code, add_word_param, PARAM_WORD },
1052         { &hf_user_name, add_byte_param, PARAM_BYTES },
1053         { &no_hf, add_pad_param, PARAM_BYTES },
1054         { &hf_privilege_level, add_word_param, PARAM_WORD },
1055         { &hf_operator_privileges, add_dword_param, PARAM_DWORD },
1056         { &hf_num_logons, add_nlogons, PARAM_WORD },
1057         { &hf_bad_pw_count, add_word_param, PARAM_WORD },
1058         { &hf_last_logon, add_abstime_absent_unknown, PARAM_DWORD },
1059         { &hf_last_logoff, add_abstime_absent_unknown, PARAM_DWORD },
1060         { &hf_logoff_time, add_abstime_absent_never, PARAM_DWORD },
1061         { &hf_kickoff_time, add_abstime_absent_never, PARAM_DWORD },
1062         { &hf_password_age, add_reltime, PARAM_DWORD },
1063         { &hf_password_can_change, add_abstime_absent_never, PARAM_DWORD },
1064         { &hf_password_must_change, add_abstime_absent_never, PARAM_DWORD },
1065         { &hf_server_name, add_stringz_pointer_param, PARAM_STRINGZ },
1066         { &hf_logon_domain, add_stringz_pointer_param, PARAM_STRINGZ },
1067         { &hf_script_path, add_stringz_pointer_param, PARAM_STRINGZ },
1068         { &hf_reserved, add_dword_param, PARAM_DWORD },
1069         { NULL, NULL, PARAM_NONE }
1070 };
1071
1072 static const item_list_t lm_data_resp_netwkstauserlogon[] = {
1073         { 1, lm_data_resp_netwkstauserlogon_1 },
1074         { -1, lm_null }
1075 };
1076
1077 static const item_t lm_params_req_netwkstauserlogoff[] = {
1078         { &hf_user_name, add_byte_param, PARAM_BYTES },
1079         { &no_hf, add_pad_param, PARAM_BYTES },
1080         { &hf_workstation_name, add_byte_param, PARAM_BYTES },
1081         { NULL, NULL, PARAM_NONE }
1082 };
1083
1084 static const item_t lm_params_resp_netwkstauserlogoff[] = {
1085         { &hf_abytes, add_word_param, PARAM_WORD },
1086         { NULL, NULL, PARAM_NONE }
1087 };
1088
1089 static const item_t lm_data_resp_netwkstauserlogoff_1[] = {
1090         { &hf_logoff_code, add_word_param, PARAM_WORD },
1091         { &hf_duration, add_reltime, PARAM_DWORD },
1092         { &hf_num_logons, add_nlogons, PARAM_WORD },
1093         { NULL, NULL, PARAM_NONE }
1094 };
1095
1096 static const item_list_t lm_data_resp_netwkstauserlogoff[] = {
1097         { 1, lm_data_resp_netwkstauserlogoff_1 },
1098         { -1, lm_null }
1099 };
1100
1101 static const item_t lm_params_req_samoemchangepassword[] = {
1102         { &hf_user_name, add_string_param, PARAM_STRINGZ },
1103         { NULL, NULL, PARAM_NONE }
1104 };
1105
1106 static const item_t lm_data_req_samoemchangepassword[] = {
1107         { &hf_new_password, add_byte_param, PARAM_BYTES },
1108         { &hf_old_password, add_byte_param, PARAM_BYTES },
1109         { NULL, NULL, PARAM_NONE }
1110 };
1111
1112 #define API_NetShareEnum                0
1113 #define API_NetShareGetInfo             1
1114 #define API_NetShareSetInfo             2
1115 #define API_NetShareAdd                 3
1116 #define API_NetShareDel                 4
1117 #define API_NetShareCheck               5
1118 #define API_NetSessionEnum              6
1119 #define API_NetSessionGetInfo           7
1120 #define API_NetSessionDel               8
1121 #define API_WconnectionEnum             9
1122 #define API_NetFileEnum                 10
1123 #define API_NetFileGetInfo              11
1124 #define API_NetFileClose                12
1125 #define API_NetServerGetInfo            13
1126 #define API_NetServerSetInfo            14
1127 #define API_NetServerDiskEnum           15
1128 #define API_NetServerAdminCommand       16
1129 #define API_NetAuditOpen                17
1130 #define API_NetAuditClear               18
1131 #define API_NetErrorLogOpen             19
1132 #define API_NetErrorLogClear            20
1133 #define API_NetCharDevEnum              21
1134 #define API_NetCharDevGetInfo           22
1135 #define API_NetCharDevControl           23
1136 #define API_NetCharDevQEnum             24
1137 #define API_NetCharDevQGetInfo          25
1138 #define API_NetCharDevQSetInfo          26
1139 #define API_NetCharDevQPurge            27
1140 #define API_NetCharDevQPurgeSelf        28
1141 #define API_NetMessageNameEnum          29
1142 #define API_NetMessageNameGetInfo       30
1143 #define API_NetMessageNameAdd           31
1144 #define API_NetMessageNameDel           32
1145 #define API_NetMessageNameFwd           33
1146 #define API_NetMessageNameUnFwd         34
1147 #define API_NetMessageBufferSend        35
1148 #define API_NetMessageFileSend          36
1149 #define API_NetMessageLogFileSet        37
1150 #define API_NetMessageLogFileGet        38
1151 #define API_NetServiceEnum              39
1152 #define API_NetServiceInstall           40
1153 #define API_NetServiceControl           41
1154 #define API_NetAccessEnum               42
1155 #define API_NetAccessGetInfo            43
1156 #define API_NetAccessSetInfo            44
1157 #define API_NetAccessAdd                45
1158 #define API_NetAccessDel                46
1159 #define API_NetGroupEnum                47
1160 #define API_NetGroupAdd                 48
1161 #define API_NetGroupDel                 49
1162 #define API_NetGroupAddUser             50
1163 #define API_NetGroupDelUser             51
1164 #define API_NetGroupGetUsers            52
1165 #define API_NetUserEnum                 53
1166 #define API_NetUserAdd                  54
1167 #define API_NetUserDel                  55
1168 #define API_NetUserGetInfo              56
1169 #define API_NetUserSetInfo              57
1170 #define API_NetUserPasswordSet          58
1171 #define API_NetUserGetGroups            59
1172 /*This line and number replaced a Dead Entry for 60 */
1173 /*This line and number replaced a Dead Entry for 61 */
1174 #define API_NetWkstaSetUID              62
1175 #define API_NetWkstaGetInfo             63
1176 #define API_NetWkstaSetInfo             64
1177 #define API_NetUseEnum                  65
1178 #define API_NetUseAdd                   66
1179 #define API_NetUseDel                   67
1180 #define API_NetUseGetInfo               68
1181 #define API_WPrintQEnum                 69
1182 #define API_WPrintQGetInfo              70
1183 #define API_WPrintQSetInfo              71
1184 #define API_WPrintQAdd                  72
1185 #define API_WPrintQDel                  73
1186 #define API_WPrintQPause                74
1187 #define API_WPrintQContinue             75
1188 #define API_WPrintJobEnum               76
1189 #define API_WPrintJobGetInfo            77
1190 #define API_WPrintJobSetInfo_OLD        78
1191 /* This line and number replaced a Dead Entry for 79 */
1192 /* This line and number replaced a Dead Entry for 80 */
1193 #define API_WPrintJobDel                81
1194 #define API_WPrintJobPause              82
1195 #define API_WPrintJobContinue           83
1196 #define API_WPrintDestEnum              84
1197 #define API_WPrintDestGetInfo           85
1198 #define API_WPrintDestControl           86
1199 #define API_NetProfileSave              87
1200 #define API_NetProfileLoad              88
1201 #define API_NetStatisticsGet            89
1202 #define API_NetStatisticsClear          90
1203 #define API_NetRemoteTOD                91
1204 #define API_WNetBiosEnum                92
1205 #define API_WNetBiosGetInfo             93
1206 #define API_NetServerEnum               94
1207 #define API_I_NetServerEnum             95
1208 #define API_NetServiceGetInfo           96
1209 /* This line and number replaced a Dead Entry for 97 */
1210 /* This line and number replaced a Dead Entry for 98 */
1211 /* This line and number replaced a Dead Entry for 99 */
1212 /* This line and number replaced a Dead Entry for 100 */
1213 /* This line and number replaced a Dead Entry for 101 */
1214 /* This line and number replaced a Dead Entry for 102 */
1215 #define API_WPrintQPurge                103
1216 #define API_NetServerEnum2              104
1217 #define API_NetAccessGetUserPerms       105
1218 #define API_NetGroupGetInfo             106
1219 #define API_NetGroupSetInfo             107
1220 #define API_NetGroupSetUsers            108
1221 #define API_NetUserSetGroups            109
1222 #define API_NetUserModalsGet            110
1223 #define API_NetUserModalsSet            111
1224 #define API_NetFileEnum2                112
1225 #define API_NetUserAdd2                 113
1226 #define API_NetUserSetInfo2             114
1227 #define API_NetUserPasswordSet2         115
1228 #define API_I_NetServerEnum2            116
1229 #define API_NetConfigGet2               117
1230 #define API_NetConfigGetAll2            118
1231 #define API_NetGetDCName                119
1232 #define API_NetHandleGetInfo            120
1233 #define API_NetHandleSetInfo            121
1234 #define API_NetStatisticsGet2           122
1235 #define API_WBuildGetInfo               123
1236 #define API_NetFileGetInfo2             124
1237 #define API_NetFileClose2               125
1238 #define API_NetServerReqChallenge       126
1239 #define API_NetServerAuthenticate       127
1240 #define API_NetServerPasswordSet        128
1241 #define API_WNetAccountDeltas           129
1242 #define API_WNetAccountSync             130
1243 #define API_NetUserEnum2                131
1244 #define API_NetWkstaUserLogon           132
1245 #define API_NetWkstaUserLogoff          133
1246 #define API_NetLogonEnum                134
1247 #define API_NetErrorLogRead             135
1248 #define API_I_NetPathType               136
1249 #define API_I_NetPathCanonicalize       137
1250 #define API_I_NetPathCompare            138
1251 #define API_I_NetNameValidate           139
1252 #define API_I_NetNameCanonicalize       140
1253 #define API_I_NetNameCompare            141
1254 #define API_NetAuditRead                142
1255 #define API_WPrintDestAdd               143
1256 #define API_WPrintDestSetInfo           144
1257 #define API_WPrintDestDel               145
1258 #define API_NetUserValidate2            146
1259 #define API_WPrintJobSetInfo            147
1260 #define API_TI_NetServerDiskEnum        148
1261 #define API_TI_NetServerDiskGetInfo     149
1262 #define API_TI_FTVerifyMirror           150
1263 #define API_TI_FTAbortVerify            151
1264 #define API_TI_FTGetInfo                152
1265 #define API_TI_FTSetInfo                153
1266 #define API_TI_FTLockDisk               154
1267 #define API_TI_FTFixError               155
1268 #define API_TI_FTAbortFix               156
1269 #define API_TI_FTDiagnoseError          157
1270 #define API_TI_FTGetDriveStats          158
1271 /* This line and number replaced a Dead Entry for 159 */
1272 #define API_TI_FTErrorGetInfo           160
1273 /* This line and number replaced a Dead Entry for 161 */
1274 /* This line and number replaced a Dead Entry for 162 */
1275 #define API_NetAccessCheck              163
1276 #define API_NetAlertRaise               164
1277 #define API_NetAlertStart               165
1278 #define API_NetAlertStop                166
1279 #define API_NetAuditWrite               167
1280 #define API_NetIRemoteAPI               168
1281 #define API_NetServiceStatus            169
1282 #define API_I_NetServerRegister         170
1283 #define API_I_NetServerDeregister       171
1284 #define API_I_NetSessionEntryMake       172
1285 #define API_I_NetSessionEntryClear      173
1286 #define API_I_NetSessionEntryGetInfo    174
1287 #define API_I_NetSessionEntrySetInfo    175
1288 #define API_I_NetConnectionEntryMake    176
1289 #define API_I_NetConnectionEntryClear   177
1290 #define API_I_NetConnectionEntrySetInfo 178
1291 #define API_I_NetConnectionEntryGetInfo 179
1292 #define API_I_NetFileEntryMake          180
1293 #define API_I_NetFileEntryClear         181
1294 #define API_I_NetFileEntrySetInfo       182
1295 #define API_I_NetFileEntryGetInfo       183
1296 #define API_AltSrvMessageBufferSend     184
1297 #define API_AltSrvMessageFileSend       185
1298 #define API_wI_NetRplWkstaEnum          186
1299 #define API_wI_NetRplWkstaGetInfo       187
1300 #define API_wI_NetRplWkstaSetInfo       188
1301 #define API_wI_NetRplWkstaAdd           189
1302 #define API_wI_NetRplWkstaDel           190
1303 #define API_wI_NetRplProfileEnum        191
1304 #define API_wI_NetRplProfileGetInfo     192
1305 #define API_wI_NetRplProfileSetInfo     193
1306 #define API_wI_NetRplProfileAdd         194
1307 #define API_wI_NetRplProfileDel         195
1308 #define API_wI_NetRplProfileClone       196
1309 #define API_wI_NetRplBaseProfileEnum    197
1310 /* This line and number replaced a Dead Entry for 198 */
1311 /* This line and number replaced a Dead Entry for 199 */
1312 /* This line and number replaced a Dead Entry for 200 */
1313 #define API_WIServerSetInfo             201
1314 /* This line and number replaced a Dead Entry for 202 */
1315 /* This line and number replaced a Dead Entry for 203 */
1316 /* This line and number replaced a Dead Entry for 204 */
1317 #define API_WPrintDriverEnum            205
1318 #define API_WPrintQProcessorEnum        206
1319 #define API_WPrintPortEnum              207
1320 #define API_WNetWriteUpdateLog          208
1321 #define API_WNetAccountUpdate           209
1322 #define API_WNetAccountConfirmUpdate    210
1323 #define API_NetConfigSet                211
1324 #define API_WAccountsReplicate          212
1325 /* 213 is used by WfW */
1326 #define API_SamOEMChgPasswordUser2_P    214
1327 #define API_NetServerEnum3              215
1328 /* XXX - what about 216 through 249? */
1329 #define API_WPrintDriverGetInfo         250
1330 #define API_WPrintDriverSetInfo         251
1331 #define API_NetAliasAdd                 252
1332 #define API_NetAliasDel                 253
1333 #define API_NetAliasGetInfo             254
1334 #define API_NetAliasSetInfo             255
1335 #define API_NetAliasEnum                256
1336 #define API_NetUserGetLogonAsn          257
1337 #define API_NetUserSetLogonAsn          258
1338 #define API_NetUserGetAppSel            259
1339 #define API_NetUserSetAppSel            260
1340 #define API_NetAppAdd                   261
1341 #define API_NetAppDel                   262
1342 #define API_NetAppGetInfo               263
1343 #define API_NetAppSetInfo               264
1344 #define API_NetAppEnum                  265
1345 #define API_NetUserDCDBInit             266
1346 #define API_NetDASDAdd                  267
1347 #define API_NetDASDDel                  268
1348 #define API_NetDASDGetInfo              269
1349 #define API_NetDASDSetInfo              270
1350 #define API_NetDASDEnum                 271
1351 #define API_NetDASDCheck                272
1352 #define API_NetDASDCtl                  273
1353 #define API_NetUserRemoteLogonCheck     274
1354 #define API_NetUserPasswordSet3         275
1355 #define API_NetCreateRIPLMachine        276
1356 #define API_NetDeleteRIPLMachine        277
1357 #define API_NetGetRIPLMachineInfo       278
1358 #define API_NetSetRIPLMachineInfo       279
1359 #define API_NetEnumRIPLMachine          280
1360 #define API_I_ShareAdd                  281
1361 #define API_I_AliasEnum                 282
1362 #define API_NetAccessApply              283
1363 #define API_WPrt16Query                 284
1364 #define API_WPrt16Set                   285
1365 #define API_NetUserDel100               286
1366 #define API_NetUserRemoteLogonCheck2    287
1367 #define API_WRemoteTODSet               294
1368 #define API_WPrintJobMoveAll            295
1369 #define API_W16AppParmAdd               296
1370 #define API_W16AppParmDel               297
1371 #define API_W16AppParmGet               298
1372 #define API_W16AppParmSet               299
1373 #define API_W16RIPLMachineCreate        300
1374 #define API_W16RIPLMachineGetInfo       301
1375 #define API_W16RIPLMachineSetInfo       302
1376 #define API_W16RIPLMachineEnum          303
1377 #define API_W16RIPLMachineListParmEnum  304
1378 #define API_W16RIPLMachClassGetInfo     305
1379 #define API_W16RIPLMachClassEnum        306
1380 #define API_W16RIPLMachClassCreate      307
1381 #define API_W16RIPLMachClassSetInfo     308
1382 #define API_W16RIPLMachClassDelete      309
1383 #define API_W16RIPLMachClassLPEnum      310
1384 #define API_W16RIPLMachineDelete        311
1385 #define API_W16WSLevelGetInfo           312
1386 #define API_NetServerNameAdd            313
1387 #define API_NetServerNameDel            314
1388 #define API_NetServerNameEnum           315
1389 #define API_I_WDASDEnum                 316
1390 #define API_I_WDASDEnumTerminate        317
1391 #define API_I_WDASDSetInfo2             318
1392
1393 static const struct lanman_desc lmd[] = {
1394         { API_NetShareEnum,
1395           lm_params_req_netshareenum,
1396           NULL,
1397           NULL,
1398           lm_null,
1399           lm_null,
1400           lm_params_resp_netshareenum,
1401           "Available Shares",
1402           &ett_lanman_shares,
1403           netshareenum_share_entry,
1404           &ett_lanman_share,
1405           lm_data_resp_netshareenum,
1406           lm_null },
1407
1408         { API_NetShareGetInfo,
1409           lm_params_req_netsharegetinfo,
1410           NULL,
1411           NULL,
1412           lm_null,
1413           lm_null,
1414           lm_params_resp_netsharegetinfo,
1415           NULL,
1416           NULL,
1417           NULL,
1418           NULL,
1419           lm_data_resp_netsharegetinfo,
1420           lm_null },
1421
1422         { API_NetServerGetInfo,
1423           lm_params_req_netservergetinfo,
1424           NULL,
1425           NULL,
1426           lm_null,
1427           lm_null,
1428           lm_params_resp_netservergetinfo,
1429           NULL,
1430           NULL,
1431           NULL,
1432           NULL,
1433           lm_data_serverinfo,
1434           lm_null },
1435
1436         { API_NetUserGetInfo,
1437           lm_params_req_netusergetinfo,
1438           NULL,
1439           NULL,
1440           lm_null,
1441           lm_null,
1442           lm_params_resp_netusergetinfo,
1443           NULL,
1444           NULL,
1445           NULL,
1446           NULL,
1447           lm_data_resp_netusergetinfo,
1448           lm_null },
1449
1450         { API_NetUserGetGroups,
1451           lm_params_req_netusergetgroups,
1452           NULL,
1453           NULL,
1454           lm_null,
1455           lm_null,
1456           lm_params_resp_netusergetgroups,
1457           "Groups",
1458           &ett_lanman_groups,
1459           NULL,
1460           NULL,
1461           lm_data_resp_netusergetgroups,
1462           lm_null },
1463
1464         { API_NetRemoteTOD,
1465           lm_null,
1466           NULL,
1467           NULL,
1468           lm_null,
1469           lm_null,
1470           lm_null,
1471           NULL,
1472           NULL,
1473           NULL,
1474           NULL,
1475           lm_data_resp_netremotetod,
1476           lm_null },
1477
1478         { API_NetServerEnum2,
1479           lm_params_req_netserverenum2,
1480           NULL,
1481           NULL,
1482           lm_null,
1483           lm_null,
1484           lm_params_resp_netserverenum2,
1485           "Servers",
1486           &ett_lanman_servers,
1487           netserverenum2_server_entry,
1488           &ett_lanman_server,
1489           lm_data_serverinfo,
1490           lm_null },
1491
1492         { API_NetWkstaGetInfo,
1493           lm_params_req_netwkstagetinfo,
1494           NULL,
1495           NULL,
1496           lm_null,
1497           lm_null,
1498           lm_params_resp_netwkstagetinfo,
1499           NULL,
1500           NULL,
1501           NULL,
1502           NULL,
1503           lm_data_resp_netwkstagetinfo,
1504           lm_null },
1505
1506         { API_NetWkstaUserLogon,
1507           lm_params_req_netwkstauserlogon,
1508           NULL,
1509           NULL,
1510           lm_null,
1511           lm_null,
1512           lm_params_resp_netwkstauserlogon,
1513           NULL,
1514           NULL,
1515           NULL,
1516           NULL,
1517           lm_data_resp_netwkstauserlogon,
1518           lm_null },
1519
1520         { API_NetWkstaUserLogoff,
1521           lm_params_req_netwkstauserlogoff,
1522           NULL,
1523           NULL,
1524           lm_null,
1525           lm_null,
1526           lm_params_resp_netwkstauserlogoff,
1527           NULL,
1528           NULL,
1529           NULL,
1530           NULL,
1531           lm_data_resp_netwkstauserlogoff,
1532           lm_null },
1533
1534         { API_SamOEMChgPasswordUser2_P,
1535           lm_params_req_samoemchangepassword,
1536           NULL,
1537           NULL,
1538           lm_data_req_samoemchangepassword,
1539           lm_null,
1540           lm_null,
1541           NULL,
1542           NULL,
1543           NULL,
1544           NULL,
1545           lm_null_list,
1546           lm_null },
1547
1548         { API_NetServerEnum3,
1549           lm_params_req_netserverenum3,
1550           NULL,
1551           NULL,
1552           lm_null,
1553           lm_null,
1554           lm_params_resp_netserverenum2,
1555           "Servers",
1556           &ett_lanman_servers,
1557           netserverenum2_server_entry,
1558           &ett_lanman_server,
1559           lm_data_serverinfo,
1560           lm_null },
1561
1562         { -1,
1563           lm_null,
1564           NULL,
1565           NULL,
1566           lm_null,
1567           lm_null,
1568           lm_null,
1569           NULL,
1570           NULL,
1571           NULL,
1572           &ett_lanman_unknown_entry,
1573           lm_null_list,
1574           lm_null }
1575 };
1576
1577 static const struct lanman_desc *
1578 find_lanman(int lanman_num)
1579 {
1580         int i;
1581
1582         for (i = 0; lmd[i].lanman_num != -1; i++) {
1583                 if (lmd[i].lanman_num == lanman_num)
1584                         break;
1585         }
1586         return &lmd[i];
1587 }
1588
1589 static const guchar *
1590 get_count(const guchar *desc, int *countp)
1591 {
1592         int count = 0;
1593         guchar c;
1594
1595         if (!isdigit(*desc)) {
1596                 *countp = 1;    /* no count was supplied */
1597                 return desc;
1598         }
1599
1600         while ((c = *desc) != '\0' && isdigit(c)) {
1601                 count = (count * 10) + c - '0';
1602                 desc++;
1603         }
1604
1605         *countp = count;        /* XXX - what if it's 0? */
1606         return desc;
1607 }
1608
1609 static int
1610 dissect_request_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
1611     proto_tree *tree, const guchar *desc, const item_t *items,
1612     gboolean *has_data_p)
1613 {
1614         guint c;
1615         guint16 WParam;
1616         guint32 LParam;
1617         guint string_len;
1618         int count;
1619
1620         *has_data_p = FALSE;
1621         while ((c = *desc++) != '\0') {
1622                 switch (c) {
1623
1624                 case 'W':
1625                         /*
1626                          * A 16-bit word value in the request.
1627                          */
1628                         if (items->func == NULL) {
1629                                 /*
1630                                  * We've run out of items in the table;
1631                                  * fall back on the default.
1632                                  */
1633                                 offset = add_word_param(tvb, offset, 0, pinfo,
1634                                     tree, 0, -1);
1635                         } else if (items->type != PARAM_WORD) {
1636                                 /*
1637                                  * Descriptor character is 'W', but this
1638                                  * isn't a word parameter.
1639                                  */
1640                                 WParam = tvb_get_letohs(tvb, offset);
1641                                 proto_tree_add_text(tree, tvb, offset, 2,
1642                                     "%s: Value is %u (0x%04X), type is wrong (W)",
1643                                     (*items->hf_index == -1) ?
1644                                       "Word Param" :
1645                                       proto_registrar_get_name(*items->hf_index),
1646                                     WParam, WParam);
1647                                 offset += 2;
1648                                 items++;
1649                         } else {
1650                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1651                                     tree, 0, *items->hf_index);
1652                                 items++;
1653                         }
1654                         break;
1655
1656                 case 'D':
1657                         /*
1658                          * A 32-bit doubleword value in the request.
1659                          */
1660                         if (items->func == NULL) {
1661                                 /*
1662                                  * We've run out of items in the table;
1663                                  * fall back on the default.
1664                                  */
1665                                 offset = add_dword_param(tvb, offset, 0, pinfo,
1666                                     tree, 0, -1);
1667                         } else if (items->type != PARAM_DWORD) {
1668                                 /*
1669                                  * Descriptor character is 'D', but this
1670                                  * isn't a doubleword parameter.
1671                                  */
1672                                 LParam = tvb_get_letohl(tvb, offset);
1673                                 proto_tree_add_text(tree, tvb, offset, 2,
1674                                     "%s: Value is %u (0x%08X), type is wrong (D)",
1675                                     (*items->hf_index == -1) ?
1676                                       "Doubleword Param" :
1677                                       proto_registrar_get_name(*items->hf_index),
1678                                     LParam, LParam);
1679                                 offset += 4;
1680                                 items++;
1681                         } else {
1682                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1683                                     tree, 0, *items->hf_index);
1684                                 items++;
1685                         }
1686                         break;
1687
1688                 case 'b':
1689                         /*
1690                          * A byte or multi-byte value in the request.
1691                          */
1692                         desc = get_count(desc, &count);
1693                         if (items->func == NULL) {
1694                                 /*
1695                                  * We've run out of items in the table;
1696                                  * fall back on the default.
1697                                  */
1698                                 offset = add_byte_param(tvb, offset, count,
1699                                     pinfo, tree, 0, -1);
1700                         } else if (items->type != PARAM_BYTES) {
1701                                 /*
1702                                  * Descriptor character is 'b', but this
1703                                  * isn't a byte/bytes parameter.
1704                                  */
1705                                 proto_tree_add_text(tree, tvb, offset, count,
1706                                     "%s: Value is %s, type is wrong (b)",
1707                                     (*items->hf_index == -1) ?
1708                                       "Byte Param" :
1709                                       proto_registrar_get_name(*items->hf_index),
1710                                     tvb_bytes_to_str(tvb, offset, count));
1711                                 offset += count;
1712                                 items++;
1713                         } else {
1714                                 offset = (*items->func)(tvb, offset, count,
1715                                     pinfo, tree, 0, *items->hf_index);
1716                                 items++;
1717                         }
1718                         break;
1719
1720                 case 'O':
1721                         /*
1722                          * A null pointer.
1723                          */
1724                         if (items->func == NULL) {
1725                                 /*
1726                                  * We've run out of items in the table;
1727                                  * fall back on the default.
1728                                  */
1729                                 add_null_pointer_param(tvb, offset, 0,
1730                                     pinfo, tree, 0, -1);
1731                         } else {
1732                                 /*
1733                                  * If "*items->hf_index" is -1, this is
1734                                  * a reserved must-be-null field; don't
1735                                  * clutter the protocol tree by putting
1736                                  * it in.
1737                                  */
1738                                 if (*items->hf_index != -1) {
1739                                         add_null_pointer_param(tvb,
1740                                             offset, 0, pinfo, tree, 0,
1741                                             *items->hf_index);
1742                                 }
1743                                 items++;
1744                         }
1745                         break;
1746
1747                 case 'z':
1748                         /*
1749                          * A null-terminated ASCII string.
1750                          */
1751                         if (items->func == NULL) {
1752                                 /*
1753                                  * We've run out of items in the table;
1754                                  * fall back on the default.
1755                                  */
1756                                 offset = add_string_param(tvb, offset, 0,
1757                                     pinfo, tree, 0, -1);
1758                         } else if (items->type != PARAM_STRINGZ) {
1759                                 /*
1760                                  * Descriptor character is 'z', but this
1761                                  * isn't a string parameter.
1762                                  */
1763                                 string_len = tvb_strsize(tvb, offset);
1764                                 proto_tree_add_text(tree, tvb, offset, string_len,
1765                                     "%s: Value is %s, type is wrong (z)",
1766                                     (*items->hf_index == -1) ?
1767                                       "String Param" :
1768                                       proto_registrar_get_name(*items->hf_index),
1769                                     tvb_format_text(tvb, offset, string_len));
1770                                 offset += string_len;
1771                                 items++;
1772                         } else {
1773                                 offset = (*items->func)(tvb, offset, 0,
1774                                     pinfo, tree, 0, *items->hf_index);
1775                                 items++;
1776                         }
1777                         break;
1778
1779                 case 'F':
1780                         /*
1781                          * One or more pad bytes.
1782                          */
1783                         desc = get_count(desc, &count);
1784                         proto_tree_add_text(tree, tvb, offset, count,
1785                             "%s", "Padding");
1786                         offset += count;
1787                         break;
1788
1789                 case 'L':
1790                         /*
1791                          * 16-bit receive buffer length.
1792                          */
1793                         proto_tree_add_item(tree, hf_recv_buf_len, tvb,
1794                             offset, 2, TRUE);
1795                         offset += 2;
1796                         break;
1797
1798                 case 's':
1799                         /*
1800                          * 32-bit send buffer offset.
1801                          * This appears not to be sent over the wire.
1802                          */
1803                         *has_data_p = TRUE;
1804                         break;
1805
1806                 case 'T':
1807                         /*
1808                          * 16-bit send buffer length.
1809                          */
1810                         proto_tree_add_item(tree, hf_send_buf_len, tvb,
1811                             offset, 2, TRUE);
1812                         offset += 2;
1813                         break;
1814
1815                 default:
1816                         break;
1817                 }
1818         }
1819         return offset;
1820 }
1821
1822 static int
1823 dissect_response_parameters(tvbuff_t *tvb, int offset, packet_info *pinfo,
1824     proto_tree *tree, const guchar *desc, const item_t *items,
1825     gboolean *has_data_p, gboolean *has_ent_count_p, guint16 *ent_count_p)
1826 {
1827         guint c;
1828         guint16 WParam;
1829         guint32 LParam;
1830         int count;
1831
1832         *has_data_p = FALSE;
1833         *has_ent_count_p = FALSE;
1834         while ((c = *desc++) != '\0') {
1835                 switch (c) {
1836
1837                 case 'r':
1838                         /*
1839                          * 32-bit receive buffer offset.
1840                          */
1841                         *has_data_p = TRUE;
1842                         break;
1843
1844                 case 'g':
1845                         /*
1846                          * A byte or series of bytes is returned.
1847                          */
1848                         desc = get_count(desc, &count);
1849                         if (items->func == NULL) {
1850                                 /*
1851                                  * We've run out of items in the table;
1852                                  * fall back on the default.
1853                                  */
1854                                 offset = add_byte_param(tvb, offset, count,
1855                                     pinfo, tree, 0, -1);
1856                         } else if (items->type != PARAM_BYTES) {
1857                                 /*
1858                                  * Descriptor character is 'b', but this
1859                                  * isn't a byte/bytes parameter.
1860                                  */
1861                                 proto_tree_add_text(tree, tvb, offset, count,
1862                                     "%s: Value is %s, type is wrong (g)",
1863                                     (*items->hf_index == -1) ?
1864                                       "Byte Param" :
1865                                       proto_registrar_get_name(*items->hf_index),
1866                                     tvb_bytes_to_str(tvb, offset, count));
1867                                 offset += count;
1868                                 items++;
1869                         } else {
1870                                 offset = (*items->func)(tvb, offset, count,
1871                                     pinfo, tree, 0, *items->hf_index);
1872                                 items++;
1873                         }
1874                         break;
1875
1876                 case 'h':
1877                         /*
1878                          * A 16-bit word is received.
1879                          */
1880                         if (items->func == NULL) {
1881                                 /*
1882                                  * We've run out of items in the table;
1883                                  * fall back on the default.
1884                                  */
1885                                 offset = add_word_param(tvb, offset, 0, pinfo,
1886                                     tree, 0, -1);
1887                         } else if (items->type != PARAM_WORD) {
1888                                 /*
1889                                  * Descriptor character is 'h', but this
1890                                  * isn't a word parameter.
1891                                  */
1892                                 WParam = tvb_get_letohs(tvb, offset);
1893                                 proto_tree_add_text(tree, tvb, offset, 2,
1894                                     "%s: Value is %u (0x%04X), type is wrong (W)",
1895                                     (*items->hf_index == -1) ?
1896                                       "Word Param" :
1897                                       proto_registrar_get_name(*items->hf_index),
1898                                     WParam, WParam);
1899                                 offset += 2;
1900                                 items++;
1901                         } else {
1902                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1903                                     tree, 0, *items->hf_index);
1904                                 items++;
1905                         }
1906                         break;
1907
1908                 case 'i':
1909                         /*
1910                          * A 32-bit doubleword is received.
1911                          */
1912                         if (items->func == NULL) {
1913                                 /*
1914                                  * We've run out of items in the table;
1915                                  * fall back on the default.
1916                                  */
1917                                 offset = add_dword_param(tvb, offset, 0, pinfo,
1918                                     tree, 0, -1);
1919                         } else if (items->type != PARAM_DWORD) {
1920                                 /*
1921                                  * Descriptor character is 'i', but this
1922                                  * isn't a doubleword parameter.
1923                                  */
1924                                 LParam = tvb_get_letohl(tvb, offset);
1925                                 proto_tree_add_text(tree, tvb, offset, 2,
1926                                     "%s: Value is %u (0x%08X), type is wrong (i)",
1927                                     (*items->hf_index == -1) ?
1928                                       "Doubleword Param" :
1929                                       proto_registrar_get_name(*items->hf_index),
1930                                     LParam, LParam);
1931                                 offset += 4;
1932                                 items++;
1933                         } else {
1934                                 offset = (*items->func)(tvb, offset, 0, pinfo,
1935                                     tree, 0, *items->hf_index);
1936                                 items++;
1937                         }
1938                         break;
1939
1940                 case 'e':
1941                         /*
1942                          * A 16-bit entry count is returned.
1943                          */
1944                         WParam = tvb_get_letohs(tvb, offset);
1945                         proto_tree_add_uint(tree, hf_ecount, tvb, offset, 2,
1946                             WParam);
1947                         offset += 2;
1948                         *has_ent_count_p = TRUE;
1949                         *ent_count_p = WParam;  /* Save this for later retrieval */
1950                         break;
1951
1952                 default:
1953                         break;
1954                 }
1955         }
1956         return offset;
1957 }
1958
1959 static int
1960 dissect_transact_data(tvbuff_t *tvb, int offset, int convert,
1961     packet_info *pinfo, proto_tree *tree, const guchar *desc,
1962     const item_t *items, guint16 *aux_count_p)
1963 {
1964         guint c;
1965         guint16 WParam;
1966         guint32 LParam;
1967         int count;
1968         int cptr;
1969         const char *string;
1970         gint string_len;
1971
1972         if (aux_count_p != NULL)
1973                 *aux_count_p = 0;
1974
1975         while ((c = *desc++) != '\0') {
1976                 switch (c) {
1977
1978                 case 'W':
1979                         /*
1980                          * A 16-bit word value.
1981                          * XXX - handle the count?
1982                          */
1983                         desc = get_count(desc, &count);
1984                         if (items->func == NULL) {
1985                                 /*
1986                                  * We've run out of items in the table;
1987                                  * fall back on the default.
1988                                  */
1989                                 offset = add_word_param(tvb, offset, 0, pinfo,
1990                                     tree, convert, -1);
1991                         } else if (items->type != PARAM_WORD) {
1992                                 /*
1993                                  * Descriptor character is 'W', but this
1994                                  * isn't a word parameter.
1995                                  */
1996                                 WParam = tvb_get_letohs(tvb, offset);
1997                                 proto_tree_add_text(tree, tvb, offset, 2,
1998                                     "%s: Value is %u (0x%04X), type is wrong (W)",
1999                                     (*items->hf_index == -1) ?
2000                                       "Word Param" :
2001                                       proto_registrar_get_name(*items->hf_index),
2002                                     WParam, WParam);
2003                                 offset += 2;
2004                                 items++;
2005                         } else {
2006                                 offset = (*items->func)(tvb, offset, 0, pinfo,
2007                                     tree, convert, *items->hf_index);
2008                                 items++;
2009                         }
2010                         break;
2011
2012                 case 'D':
2013                         /*
2014                          * A 32-bit doubleword value.
2015                          * XXX - handle the count?
2016                          */
2017                         desc = get_count(desc, &count);
2018                         if (items->func == NULL) {
2019                                 /*
2020                                  * We've run out of items in the table;
2021                                  * fall back on the default.
2022                                  */
2023                                 offset = add_dword_param(tvb, offset, 0, pinfo,
2024                                     tree, convert, -1);
2025                         } else if (items->type != PARAM_DWORD) {
2026                                 /*
2027                                  * Descriptor character is 'D', but this
2028                                  * isn't a doubleword parameter.
2029                                  */
2030                                 LParam = tvb_get_letohl(tvb, offset);
2031                                 proto_tree_add_text(tree, tvb, offset, 2,
2032                                     "%s: Value is %u (0x%08X), type is wrong (D)",
2033                                     (*items->hf_index == -1) ?
2034                                       "Doubleword Param" :
2035                                       proto_registrar_get_name(*items->hf_index),
2036                                     LParam, LParam);
2037                                 offset += 4;
2038                                 items++;
2039                         } else {
2040                                 offset = (*items->func)(tvb, offset, 0, pinfo,
2041                                     tree, convert, *items->hf_index);
2042                                 items++;
2043                         }
2044                         break;
2045
2046                 case 'B':
2047                         /*
2048                          * A byte or multi-byte value.
2049                          */
2050                         desc = get_count(desc, &count);
2051                         if (items->func == NULL) {
2052                                 /*
2053                                  * We've run out of items in the table;
2054                                  * fall back on the default.
2055                                  */
2056                                 offset = add_byte_param(tvb, offset, count,
2057                                     pinfo, tree, convert, -1);
2058                         } else if (items->type != PARAM_BYTES) {
2059                                 /*
2060                                  * Descriptor character is 'B', but this
2061                                  * isn't a byte/bytes parameter.
2062                                  */
2063                                 proto_tree_add_text(tree, tvb, offset, count,
2064                                     "%s: Value is %s, type is wrong (B)",
2065                                     (*items->hf_index == -1) ?
2066                                       "Byte Param" :
2067                                       proto_registrar_get_name(*items->hf_index),
2068                                     tvb_bytes_to_str(tvb, offset, count));
2069                                 offset += count;
2070                                 items++;
2071                         } else {
2072                                 offset = (*items->func)(tvb, offset, count,
2073                                     pinfo, tree, convert, *items->hf_index);
2074                                 items++;
2075                         }
2076                         break;
2077
2078                 case 'O':
2079                         /*
2080                          * A null pointer.
2081                          */
2082                         if (items->func == NULL) {
2083                                 /*
2084                                  * We've run out of items in the table;
2085                                  * fall back on the default.
2086                                  */
2087                                 add_null_pointer_param(tvb, offset, 0,
2088                                     pinfo, tree, convert, -1);
2089                         } else {
2090                                 /*
2091                                  * If "*items->hf_index" is -1, this is
2092                                  * a reserved must-be-null field; don't
2093                                  * clutter the protocol tree by putting
2094                                  * it in.
2095                                  */
2096                                 if (*items->hf_index != -1) {
2097                                         add_null_pointer_param(tvb,
2098                                             offset, 0, pinfo, tree, convert,
2099                                             *items->hf_index);
2100                                 }
2101                                 items++;
2102                         }
2103                         break;
2104
2105                 case 'z':
2106                         /*
2107                          * A pointer to a null-terminated ASCII string.
2108                          */
2109                         if (items->func == NULL) {
2110                                 /*
2111                                  * We've run out of items in the table;
2112                                  * fall back on the default.
2113                                  */
2114                                 offset = add_stringz_pointer_param(tvb, offset,
2115                                     0, pinfo, tree, convert, -1);
2116                         } else if (items->type != PARAM_STRINGZ) {
2117                                 /*
2118                                  * Descriptor character is 'z', but this
2119                                  * isn't a string parameter.
2120                                  */
2121                                 string = get_stringz_pointer_value(tvb, offset,
2122                                     convert, &cptr, &string_len);
2123                                 offset += 4;
2124                                 proto_tree_add_text(tree, tvb, cptr, string_len,
2125                                     "%s: Value is %s, type is wrong (z)",
2126                                     (*items->hf_index == -1) ?
2127                                       "String Param" :
2128                                       proto_registrar_get_name(*items->hf_index),
2129                                     string);
2130                                 items++;
2131                         } else {
2132                                 offset = (*items->func)(tvb, offset, 0,
2133                                     pinfo, tree, convert, *items->hf_index);
2134                                 items++;
2135                         }
2136                         break;
2137
2138                 case 'b':
2139                         /*
2140                          * A pointer to a byte or multi-byte value.
2141                          */
2142                         desc = get_count(desc, &count);
2143                         if (items->func == NULL) {
2144                                 /*
2145                                  * We've run out of items in the table;
2146                                  * fall back on the default.
2147                                  */
2148                                 offset = add_bytes_pointer_param(tvb, offset,
2149                                     count, pinfo, tree, convert, -1);
2150                         } else if (items->type != PARAM_BYTES) {
2151                                 /*
2152                                  * Descriptor character is 'b', but this
2153                                  * isn't a byte/bytes parameter.
2154                                  */
2155                                 cptr = (tvb_get_letohl(tvb, offset)&0xffff)-convert;
2156                                 offset += 4;
2157                                 proto_tree_add_text(tree, tvb, offset, count,
2158                                     "%s: Value is %s, type is wrong (b)",
2159                                     (*items->hf_index == -1) ?
2160                                       "Byte Param" :
2161                                       proto_registrar_get_name(*items->hf_index),
2162                                     tvb_bytes_to_str(tvb, cptr, count));
2163                                 items++;
2164                         } else {
2165                                 offset = (*items->func)(tvb, offset, count,
2166                                     pinfo, tree, convert, *items->hf_index);
2167                                 items++;
2168                         }
2169                         break;
2170
2171                 case 'N':
2172                         /*
2173                          * 16-bit auxiliary data structure count.
2174                          * XXX - hf_acount?
2175                          */
2176                         WParam = tvb_get_letohs(tvb, offset);
2177                         proto_tree_add_text(tree, tvb, offset, 2,
2178                             "%s: %u (0x%04X)",
2179                             "Auxiliary data structure count",
2180                             WParam, WParam);
2181                         offset += 2;
2182                         if (aux_count_p != NULL)
2183                                 *aux_count_p = WParam;  /* Save this for later retrieval */
2184                         break;
2185
2186                 default:
2187                         break;
2188                 }
2189         }
2190         return offset;
2191 }
2192
2193 static const value_string commands[] = {
2194         {API_NetShareEnum,                      "NetShareEnum"},
2195         {API_NetShareGetInfo,                   "NetShareGetInfo"},
2196         {API_NetShareSetInfo,                   "NetShareSetInfo"},
2197         {API_NetShareAdd,                       "NetShareAdd"},
2198         {API_NetShareDel,                       "NetShareDel"},
2199         {API_NetShareCheck,                     "NetShareCheck"},
2200         {API_NetSessionEnum,                    "NetSessionEnum"},
2201         {API_NetSessionGetInfo,                 "NetSessionGetInfo"},
2202         {API_NetSessionDel,                     "NetSessionDel"},
2203         {API_WconnectionEnum,                   "NetConnectionEnum"},
2204         {API_NetFileEnum,                       "NetFileEnum"},
2205         {API_NetFileGetInfo,                    "NetFileGetInfo"},
2206         {API_NetFileClose,                      "NetFileClose"},
2207         {API_NetServerGetInfo,                  "NetServerGetInfo"},
2208         {API_NetServerSetInfo,                  "NetServerSetInfo"},
2209         {API_NetServerDiskEnum,                 "NetServerDiskEnum"},
2210         {API_NetServerAdminCommand,             "NetServerAdminCommand"},
2211         {API_NetAuditOpen,                      "NetAuditOpen"},
2212         {API_NetAuditClear,                     "NetAuditClear"},
2213         {API_NetErrorLogOpen,                   "NetErrorLogOpen"},
2214         {API_NetErrorLogClear,                  "NetErrorLogClear"},
2215         {API_NetCharDevEnum,                    "NetCharDevEnum"},
2216         {API_NetCharDevGetInfo,                 "NetCharDevGetInfo"},
2217         {API_NetCharDevControl,                 "NetCharDevControl"},
2218         {API_NetCharDevQEnum,                   "NetCharDevQEnum"},
2219         {API_NetCharDevQGetInfo,                "NetCharDevQGetInfo"},
2220         {API_NetCharDevQSetInfo,                "NetCharDevQSetInfo"},
2221         {API_NetCharDevQPurge,                  "NetCharDevQPurge"},
2222         {API_NetCharDevQPurgeSelf,              "NetCharDevQPurgeSelf"},
2223         {API_NetMessageNameEnum,                "NetMessageNameEnum"},
2224         {API_NetMessageNameGetInfo,             "NetMessageNameGetInfo"},
2225         {API_NetMessageNameAdd,                 "NetMessageNameAdd"},
2226         {API_NetMessageNameDel,                 "NetMessageNameDel"},
2227         {API_NetMessageNameFwd,                 "NetMessageNameFwd"},
2228         {API_NetMessageNameUnFwd,               "NetMessageNameUnFwd"},
2229         {API_NetMessageBufferSend,              "NetMessageBufferSend"},
2230         {API_NetMessageFileSend,                "NetMessageFileSend"},
2231         {API_NetMessageLogFileSet,              "NetMessageLogFileSet"},
2232         {API_NetMessageLogFileGet,              "NetMessageLogFileGet"},
2233         {API_NetServiceEnum,                    "NetServiceEnum"},
2234         {API_NetServiceInstall,                 "NetServiceInstall"},
2235         {API_NetServiceControl,                 "NetServiceControl"},
2236         {API_NetAccessEnum,                     "NetAccessEnum"},
2237         {API_NetAccessGetInfo,                  "NetAccessGetInfo"},
2238         {API_NetAccessSetInfo,                  "NetAccessSetInfo"},
2239         {API_NetAccessAdd,                      "NetAccessAdd"},
2240         {API_NetAccessDel,                      "NetAccessDel"},
2241         {API_NetGroupEnum,                      "NetGroupEnum"},
2242         {API_NetGroupAdd,                       "NetGroupAdd"},
2243         {API_NetGroupDel,                       "NetGroupDel"},
2244         {API_NetGroupAddUser,                   "NetGroupAddUser"},
2245         {API_NetGroupDelUser,                   "NetGroupDelUser"},
2246         {API_NetGroupGetUsers,                  "NetGroupGetUsers"},
2247         {API_NetUserEnum,                       "NetUserEnum"},
2248         {API_NetUserAdd,                        "NetUserAdd"},
2249         {API_NetUserDel,                        "NetUserDel"},
2250         {API_NetUserGetInfo,                    "NetUserGetInfo"},
2251         {API_NetUserSetInfo,                    "NetUserSetInfo"},
2252         {API_NetUserPasswordSet,                "NetUserPasswordSet"},
2253         {API_NetUserGetGroups,                  "NetUserGetGroups"},
2254         {API_NetWkstaSetUID,                    "NetWkstaSetUID"},
2255         {API_NetWkstaGetInfo,                   "NetWkstaGetInfo"},
2256         {API_NetWkstaSetInfo,                   "NetWkstaSetInfo"},
2257         {API_NetUseEnum,                        "NetUseEnum"},
2258         {API_NetUseAdd,                         "NetUseAdd"},
2259         {API_NetUseDel,                         "NetUseDel"},
2260         {API_NetUseGetInfo,                     "NetUseGetInfo"},
2261         {API_WPrintQEnum,                       "WPrintQEnum"},
2262         {API_WPrintQGetInfo,                    "WPrintQGetInfo"},
2263         {API_WPrintQSetInfo,                    "WPrintQSetInfo"},
2264         {API_WPrintQAdd,                        "WPrintQAdd"},
2265         {API_WPrintQDel,                        "WPrintQDel"},
2266         {API_WPrintQPause,                      "WPrintQPause"},
2267         {API_WPrintQContinue,                   "WPrintQContinue"},
2268         {API_WPrintJobEnum,                     "WPrintJobEnum"},
2269         {API_WPrintJobGetInfo,                  "WPrintJobGetInfo"},
2270         {API_WPrintJobSetInfo_OLD,              "WPrintJobSetInfo_OLD"},
2271         {API_WPrintJobDel,                      "WPrintJobDel"},
2272         {API_WPrintJobPause,                    "WPrintJobPause"},
2273         {API_WPrintJobContinue,                 "WPrintJobContinue"},
2274         {API_WPrintDestEnum,                    "WPrintDestEnum"},
2275         {API_WPrintDestGetInfo,                 "WPrintDestGetInfo"},
2276         {API_WPrintDestControl,                 "WPrintDestControl"},
2277         {API_NetProfileSave,                    "NetProfileSave"},
2278         {API_NetProfileLoad,                    "NetProfileLoad"},
2279         {API_NetStatisticsGet,                  "NetStatisticsGet"},
2280         {API_NetStatisticsClear,                "NetStatisticsClear"},
2281         {API_NetRemoteTOD,                      "NetRemoteTOD"},
2282         {API_WNetBiosEnum,                      "WNetBiosEnum"},
2283         {API_WNetBiosGetInfo,                   "WNetBiosGetInfo"},
2284         {API_NetServerEnum,                     "NetServerEnum"},
2285         {API_I_NetServerEnum,                   "I_NetServerEnum"},
2286         {API_NetServiceGetInfo,                 "NetServiceGetInfo"},
2287         {API_WPrintQPurge,                      "WPrintQPurge"},
2288         {API_NetServerEnum2,                    "NetServerEnum2"},
2289         {API_NetAccessGetUserPerms,             "NetAccessGetUserPerms"},
2290         {API_NetGroupGetInfo,                   "NetGroupGetInfo"},
2291         {API_NetGroupSetInfo,                   "NetGroupSetInfo"},
2292         {API_NetGroupSetUsers,                  "NetGroupSetUsers"},
2293         {API_NetUserSetGroups,                  "NetUserSetGroups"},
2294         {API_NetUserModalsGet,                  "NetUserModalsGet"},
2295         {API_NetUserModalsSet,                  "NetUserModalsSet"},
2296         {API_NetFileEnum2,                      "NetFileEnum2"},
2297         {API_NetUserAdd2,                       "NetUserAdd2"},
2298         {API_NetUserSetInfo2,                   "NetUserSetInfo2"},
2299         {API_NetUserPasswordSet2,               "SetUserPassword"},
2300         {API_I_NetServerEnum2,                  "I_NetServerEnum2"},
2301         {API_NetConfigGet2,                     "NetConfigGet2"},
2302         {API_NetConfigGetAll2,                  "NetConfigGetAll2"},
2303         {API_NetGetDCName,                      "NetGetDCName"},
2304         {API_NetHandleGetInfo,                  "NetHandleGetInfo"},
2305         {API_NetHandleSetInfo,                  "NetHandleSetInfo"},
2306         {API_NetStatisticsGet2,                 "NetStatisticsGet2"},
2307         {API_WBuildGetInfo,                     "WBuildGetInfo"},
2308         {API_NetFileGetInfo2,                   "NetFileGetInfo2"},
2309         {API_NetFileClose2,                     "NetFileClose2"},
2310         {API_NetServerReqChallenge,             "NetServerReqChallenge"},
2311         {API_NetServerAuthenticate,             "NetServerAuthenticate"},
2312         {API_NetServerPasswordSet,              "NetServerPasswordSet"},
2313         {API_WNetAccountDeltas,                 "WNetAccountDeltas"},
2314         {API_WNetAccountSync,                   "WNetAccountSync"},
2315         {API_NetUserEnum2,                      "NetUserEnum2"},
2316         {API_NetWkstaUserLogon,                 "NetWkstaUserLogon"},
2317         {API_NetWkstaUserLogoff,                "NetWkstaUserLogoff"},
2318         {API_NetLogonEnum,                      "NetLogonEnum"},
2319         {API_NetErrorLogRead,                   "NetErrorLogRead"},
2320         {API_I_NetPathType,                     "I_NetPathType"},
2321         {API_I_NetPathCanonicalize,             "I_NetPathCanonicalize"},
2322         {API_I_NetPathCompare,                  "I_NetPathCompare"},
2323         {API_I_NetNameValidate,                 "I_NetNameValidate"},
2324         {API_I_NetNameCanonicalize,             "I_NetNameCanonicalize"},
2325         {API_I_NetNameCompare,                  "I_NetNameCompare"},
2326         {API_NetAuditRead,                      "NetAuditRead"},
2327         {API_WPrintDestAdd,                     "WPrintDestAdd"},
2328         {API_WPrintDestSetInfo,                 "WPrintDestSetInfo"},
2329         {API_WPrintDestDel,                     "WPrintDestDel"},
2330         {API_NetUserValidate2,                  "NetUserValidate2"},
2331         {API_WPrintJobSetInfo,                  "WPrintJobSetInfo"},
2332         {API_TI_NetServerDiskEnum,              "TI_NetServerDiskEnum"},
2333         {API_TI_NetServerDiskGetInfo,           "TI_NetServerDiskGetInfo"},
2334         {API_TI_FTVerifyMirror,                 "TI_FTVerifyMirror"},
2335         {API_TI_FTAbortVerify,                  "TI_FTAbortVerify"},
2336         {API_TI_FTGetInfo,                      "TI_FTGetInfo"},
2337         {API_TI_FTSetInfo,                      "TI_FTSetInfo"},
2338         {API_TI_FTLockDisk,                     "TI_FTLockDisk"},
2339         {API_TI_FTFixError,                     "TI_FTFixError"},
2340         {API_TI_FTAbortFix,                     "TI_FTAbortFix"},
2341         {API_TI_FTDiagnoseError,                "TI_FTDiagnoseError"},
2342         {API_TI_FTGetDriveStats,                "TI_FTGetDriveStats"},
2343         {API_TI_FTErrorGetInfo,                 "TI_FTErrorGetInfo"},
2344         {API_NetAccessCheck,                    "NetAccessCheck"},
2345         {API_NetAlertRaise,                     "NetAlertRaise"},
2346         {API_NetAlertStart,                     "NetAlertStart"},
2347         {API_NetAlertStop,                      "NetAlertStop"},
2348         {API_NetAuditWrite,                     "NetAuditWrite"},
2349         {API_NetIRemoteAPI,                     "NetIRemoteAPI"},
2350         {API_NetServiceStatus,                  "NetServiceStatus"},
2351         {API_I_NetServerRegister,               "I_NetServerRegister"},
2352         {API_I_NetServerDeregister,             "I_NetServerDeregister"},
2353         {API_I_NetSessionEntryMake,             "I_NetSessionEntryMake"},
2354         {API_I_NetSessionEntryClear,            "I_NetSessionEntryClear"},
2355         {API_I_NetSessionEntryGetInfo,          "I_NetSessionEntryGetInfo"},
2356         {API_I_NetSessionEntrySetInfo,          "I_NetSessionEntrySetInfo"},
2357         {API_I_NetConnectionEntryMake,          "I_NetConnectionEntryMake"},
2358         {API_I_NetConnectionEntryClear,         "I_NetConnectionEntryClear"},
2359         {API_I_NetConnectionEntrySetInfo,       "I_NetConnectionEntrySetInfo"},
2360         {API_I_NetConnectionEntryGetInfo,       "I_NetConnectionEntryGetInfo"},
2361         {API_I_NetFileEntryMake,                "I_NetFileEntryMake"},
2362         {API_I_NetFileEntryClear,               "I_NetFileEntryClear"},
2363         {API_I_NetFileEntrySetInfo,             "I_NetFileEntrySetInfo"},
2364         {API_I_NetFileEntryGetInfo,             "I_NetFileEntryGetInfo"},
2365         {API_AltSrvMessageBufferSend,           "AltSrvMessageBufferSend"},
2366         {API_AltSrvMessageFileSend,             "AltSrvMessageFileSend"},
2367         {API_wI_NetRplWkstaEnum,                "wI_NetRplWkstaEnum"},
2368         {API_wI_NetRplWkstaGetInfo,             "wI_NetRplWkstaGetInfo"},
2369         {API_wI_NetRplWkstaSetInfo,             "wI_NetRplWkstaSetInfo"},
2370         {API_wI_NetRplWkstaAdd,                 "wI_NetRplWkstaAdd"},
2371         {API_wI_NetRplWkstaDel,                 "wI_NetRplWkstaDel"},
2372         {API_wI_NetRplProfileEnum,              "wI_NetRplProfileEnum"},
2373         {API_wI_NetRplProfileGetInfo,           "wI_NetRplProfileGetInfo"},
2374         {API_wI_NetRplProfileSetInfo,           "wI_NetRplProfileSetInfo"},
2375         {API_wI_NetRplProfileAdd,               "wI_NetRplProfileAdd"},
2376         {API_wI_NetRplProfileDel,               "wI_NetRplProfileDel"},
2377         {API_wI_NetRplProfileClone,             "wI_NetRplProfileClone"},
2378         {API_wI_NetRplBaseProfileEnum,          "wI_NetRplBaseProfileEnum"},
2379         {API_WIServerSetInfo,                   "WIServerSetInfo"},
2380         {API_WPrintDriverEnum,                  "WPrintDriverEnum"},
2381         {API_WPrintQProcessorEnum,              "WPrintQProcessorEnum"},
2382         {API_WPrintPortEnum,                    "WPrintPortEnum"},
2383         {API_WNetWriteUpdateLog,                "WNetWriteUpdateLog"},
2384         {API_WNetAccountUpdate,                 "WNetAccountUpdate"},
2385         {API_WNetAccountConfirmUpdate,          "WNetAccountConfirmUpdate"},
2386         {API_NetConfigSet,                      "NetConfigSet"},
2387         {API_WAccountsReplicate,                "WAccountsReplicate"},
2388         {API_SamOEMChgPasswordUser2_P,          "SamOEMChangePassword"},
2389         {API_NetServerEnum3,                    "NetServerEnum3"},
2390         {API_WPrintDriverGetInfo,               "WPrintDriverGetInfo"},
2391         {API_WPrintDriverSetInfo,               "WPrintDriverSetInfo"},
2392         {API_NetAliasAdd,                       "NetAliasAdd"},
2393         {API_NetAliasDel,                       "NetAliasDel"},
2394         {API_NetAliasGetInfo,                   "NetAliasGetInfo"},
2395         {API_NetAliasSetInfo,                   "NetAliasSetInfo"},
2396         {API_NetAliasEnum,                      "NetAliasEnum"},
2397         {API_NetUserGetLogonAsn,                "NetUserGetLogonAsn"},
2398         {API_NetUserSetLogonAsn,                "NetUserSetLogonAsn"},
2399         {API_NetUserGetAppSel,                  "NetUserGetAppSel"},
2400         {API_NetUserSetAppSel,                  "NetUserSetAppSel"},
2401         {API_NetAppAdd,                         "NetAppAdd"},
2402         {API_NetAppDel,                         "NetAppDel"},
2403         {API_NetAppGetInfo,                     "NetAppGetInfo"},
2404         {API_NetAppSetInfo,                     "NetAppSetInfo"},
2405         {API_NetAppEnum,                        "NetAppEnum"},
2406         {API_NetUserDCDBInit,                   "NetUserDCDBInit"},
2407         {API_NetDASDAdd,                        "NetDASDAdd"},
2408         {API_NetDASDDel,                        "NetDASDDel"},
2409         {API_NetDASDGetInfo,                    "NetDASDGetInfo"},
2410         {API_NetDASDSetInfo,                    "NetDASDSetInfo"},
2411         {API_NetDASDEnum,                       "NetDASDEnum"},
2412         {API_NetDASDCheck,                      "NetDASDCheck"},
2413         {API_NetDASDCtl,                        "NetDASDCtl"},
2414         {API_NetUserRemoteLogonCheck,           "NetUserRemoteLogonCheck"},
2415         {API_NetUserPasswordSet3,               "NetUserPasswordSet3"},
2416         {API_NetCreateRIPLMachine,              "NetCreateRIPLMachine"},
2417         {API_NetDeleteRIPLMachine,              "NetDeleteRIPLMachine"},
2418         {API_NetGetRIPLMachineInfo,             "NetGetRIPLMachineInfo"},
2419         {API_NetSetRIPLMachineInfo,             "NetSetRIPLMachineInfo"},
2420         {API_NetEnumRIPLMachine,                "NetEnumRIPLMachine"},
2421         {API_I_ShareAdd,                        "I_ShareAdd"},
2422         {API_I_AliasEnum,                       "I_AliasEnum"},
2423         {API_NetAccessApply,                    "NetAccessApply"},
2424         {API_WPrt16Query,                       "WPrt16Query"},
2425         {API_WPrt16Set,                         "WPrt16Set"},
2426         {API_NetUserDel100,                     "NetUserDel100"},
2427         {API_NetUserRemoteLogonCheck2,          "NetUserRemoteLogonCheck2"},
2428         {API_WRemoteTODSet,                     "WRemoteTODSet"},
2429         {API_WPrintJobMoveAll,                  "WPrintJobMoveAll"},
2430         {API_W16AppParmAdd,                     "W16AppParmAdd"},
2431         {API_W16AppParmDel,                     "W16AppParmDel"},
2432         {API_W16AppParmGet,                     "W16AppParmGet"},
2433         {API_W16AppParmSet,                     "W16AppParmSet"},
2434         {API_W16RIPLMachineCreate,              "W16RIPLMachineCreate"},
2435         {API_W16RIPLMachineGetInfo,             "W16RIPLMachineGetInfo"},
2436         {API_W16RIPLMachineSetInfo,             "W16RIPLMachineSetInfo"},
2437         {API_W16RIPLMachineEnum,                "W16RIPLMachineEnum"},
2438         {API_W16RIPLMachineListParmEnum,        "W16RIPLMachineListParmEnum"},
2439         {API_W16RIPLMachClassGetInfo,           "W16RIPLMachClassGetInfo"},
2440         {API_W16RIPLMachClassEnum,              "W16RIPLMachClassEnum"},
2441         {API_W16RIPLMachClassCreate,            "W16RIPLMachClassCreate"},
2442         {API_W16RIPLMachClassSetInfo,           "W16RIPLMachClassSetInfo"},
2443         {API_W16RIPLMachClassDelete,            "W16RIPLMachClassDelete"},
2444         {API_W16RIPLMachClassLPEnum,            "W16RIPLMachClassLPEnum"},
2445         {API_W16RIPLMachineDelete,              "W16RIPLMachineDelete"},
2446         {API_W16WSLevelGetInfo,                 "W16WSLevelGetInfo"},
2447         {API_NetServerNameAdd,                  "NetServerNameAdd"},
2448         {API_NetServerNameDel,                  "NetServerNameDel"},
2449         {API_NetServerNameEnum,                 "NetServerNameEnum"},
2450         {API_I_WDASDEnum,                       "I_WDASDEnum"},
2451         {API_I_WDASDEnumTerminate,              "I_WDASDEnumTerminate"},
2452         {API_I_WDASDSetInfo2,                   "I_WDASDSetInfo2"},
2453         {0,                                     NULL}
2454 };
2455
2456 static void
2457 dissect_response_data(tvbuff_t *tvb, packet_info *pinfo, int convert,
2458     proto_tree *tree, struct smb_info *smb_info,
2459     const struct lanman_desc *lanman, gboolean has_ent_count,
2460     guint16 ent_count)
2461 {
2462         smb_transact_info_t *trp = smb_info->sip->extra_info;
2463         const item_list_t *resp_data_list;
2464         int offset, start_offset;
2465         const char *label;
2466         gint ett;
2467         const item_t *resp_data;
2468         proto_item *data_item;
2469         proto_tree *data_tree;
2470         proto_item *entry_item;
2471         proto_tree *entry_tree;
2472         guint i, j;
2473         guint16 aux_count;
2474
2475         /*
2476          * Find the item table for the matching request's detail level.
2477          */
2478         for (resp_data_list = lanman->resp_data_list;
2479             resp_data_list->level != -1; resp_data_list++) {
2480                 if (resp_data_list->level == trp->info_level)
2481                         break;
2482         }
2483         resp_data = resp_data_list->item_list;
2484
2485         offset = 0;
2486         if (has_ent_count) {
2487                 /*
2488                  * The data is a list of entries; create a protocol tree item
2489                  * for it.
2490                  */
2491                 if (tree) {
2492                         label = lanman->resp_data_entry_list_label;
2493                         if (label == NULL)
2494                                 label = "Entries";
2495                         if (lanman->ett_data_entry_list != NULL)
2496                                 ett = *lanman->ett_data_entry_list;
2497                         else
2498                                 ett = ett_lanman_unknown_entries;
2499                         data_item = proto_tree_add_text(tree, tvb, offset, -1,
2500                             label);
2501                         data_tree = proto_item_add_subtree(data_item, ett);
2502                 } else {
2503                         data_item = NULL;
2504                         data_tree = NULL;
2505                 }
2506         } else {
2507                 /*
2508                  * Just leave it at the top level.
2509                  */
2510                 data_item = NULL;
2511                 data_tree = tree;
2512         }
2513
2514         if (trp->data_descrip == NULL) {
2515                 /*
2516                  * This could happen if we only dissected
2517                  * part of the request to which this is a
2518                  * reply, e.g. if the request was split
2519                  * across TCP segments and we weren't doing
2520                  * TCP desegmentation, or if we had a snapshot
2521                  * length that was too short.
2522                  *
2523                  * We can't dissect the data; just show it as raw data or,
2524                  * if we've already created a top-level item, note that
2525                  * no descriptor is available.
2526                  */
2527                 if (has_ent_count) {
2528                         if (data_item != NULL) {
2529                                 proto_item_append_text(data_item,
2530                                     " (No descriptor available)");
2531                         }
2532                 } else {
2533                         proto_tree_add_text(data_tree, tvb, offset, -1,
2534                             "Data (no descriptor available)");
2535                 }
2536                 offset += tvb_length_remaining(tvb, offset);
2537         } else {
2538                 /*
2539                  * If we have an entry count, show all the entries,
2540                  * with each one having a protocol tree item.
2541                  *
2542                  * Otherwise, we just show one returned item, with
2543                  * no protocol tree item.
2544                  */
2545                 if (!has_ent_count)
2546                         ent_count = 1;
2547                 for (i = 0; i < ent_count; i++) {
2548                         start_offset = offset;
2549                         if (has_ent_count &&
2550                             lanman->resp_data_element_item != NULL) {
2551                                 /*
2552                                  * Create a protocol tree item for the
2553                                  * entry.
2554                                  */
2555                                 entry_item =
2556                                     (*lanman->resp_data_element_item)
2557                                       (tvb, data_tree, offset);
2558                                 entry_tree = proto_item_add_subtree(
2559                                     entry_item,
2560                                     *lanman->ett_resp_data_element_item);
2561                         } else {
2562                                 /*
2563                                  * Just leave it at the current
2564                                  * level.
2565                                  */
2566                                 entry_item = NULL;
2567                                 entry_tree = data_tree;
2568                         }
2569
2570                         offset = dissect_transact_data(tvb, offset,
2571                             convert, pinfo, entry_tree,
2572                             trp->data_descrip, resp_data, &aux_count);
2573
2574                         /* auxiliary data */
2575                         if (trp->aux_data_descrip != NULL) {
2576                                 for (j = 0; j < aux_count; j++) {
2577                                         offset = dissect_transact_data(
2578                                             tvb, offset, convert,
2579                                             pinfo, entry_tree,
2580                                             trp->data_descrip,
2581                                             lanman->resp_aux_data, NULL);
2582                                 }
2583                         }
2584
2585                         if (entry_item != NULL) {
2586                                 /*
2587                                  * Set the length of the protocol tree
2588                                  * item for the entry.
2589                                  */
2590                                 proto_item_set_len(entry_item,
2591                                     offset - start_offset);
2592                         }
2593                 }
2594         }
2595
2596         if (data_item != NULL) {
2597                 /*
2598                  * Set the length of the protocol tree item
2599                  * for the data.
2600                  */
2601                 proto_item_set_len(data_item, offset);
2602         }
2603 }
2604
2605 static gboolean
2606 dissect_pipe_lanman(tvbuff_t *pd_tvb, tvbuff_t *p_tvb, tvbuff_t *d_tvb,
2607                     packet_info *pinfo, proto_tree *parent_tree)
2608 {
2609         smb_info_t *smb_info = pinfo->private_data;
2610         smb_transact_info_t *trp = smb_info->sip->extra_info;
2611         int offset = 0, start_offset;
2612         guint16 cmd;
2613         guint16 status;
2614         int convert;
2615         const struct lanman_desc *lanman;
2616         proto_item *item = NULL;
2617         proto_tree *tree = NULL;
2618         guint descriptor_len;
2619         const gchar *param_descrip, *data_descrip, *aux_data_descrip = NULL;
2620         gboolean has_data;
2621         gboolean has_ent_count;
2622         guint16 ent_count, aux_count;
2623         guint i;
2624         proto_item *data_item;
2625         proto_tree *data_tree;
2626
2627         if (!proto_is_protocol_enabled(find_protocol_by_id(proto_smb_lanman)))
2628                 return FALSE;
2629         if (smb_info->request && p_tvb == NULL) {
2630                 /*
2631                  * Requests must have parameters.
2632                  */
2633                 return FALSE;
2634         }
2635         pinfo->current_proto = "LANMAN";
2636
2637         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
2638                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LANMAN");
2639         }
2640
2641         if (parent_tree) {
2642                 item = proto_tree_add_item(parent_tree, proto_smb_lanman,
2643                         pd_tvb, 0, -1, FALSE);
2644                 tree = proto_item_add_subtree(item, ett_lanman);
2645         }
2646
2647         if (smb_info->request) { /* this is a request */
2648                 /* function code */
2649                 cmd = tvb_get_letohs(p_tvb, offset);
2650                 if (check_col(pinfo->cinfo, COL_INFO)) {
2651                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s Request", val_to_str(cmd, commands, "Unknown Command (%u)"));
2652                 }
2653                 proto_tree_add_uint(tree, hf_function_code, p_tvb, offset, 2,
2654                     cmd);
2655                 offset += 2;
2656
2657                 /*
2658                  * If we haven't already done so, save the function code in
2659                  * the structure we were handed, so that it's available to
2660                  * the code parsing the reply, and initialize the detail
2661                  * level to -1, meaning "unknown".
2662                  */
2663                 if (!pinfo->fd->flags.visited) {
2664                         trp->lanman_cmd = cmd;
2665                         trp->info_level = -1;
2666                         trp->param_descrip=NULL;
2667                         trp->data_descrip=NULL;
2668                         trp->aux_data_descrip=NULL;
2669                 }
2670
2671                 /* parameter descriptor */
2672                 descriptor_len = tvb_strsize(p_tvb, offset);
2673                 proto_tree_add_item(tree, hf_param_desc, p_tvb, offset,
2674                     descriptor_len, TRUE);
2675                 param_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
2676                 if (!pinfo->fd->flags.visited) {
2677                         /*
2678                          * Save the parameter descriptor for future use.
2679                          */
2680                         g_assert(trp->param_descrip == NULL);
2681                         trp->param_descrip = g_strdup(param_descrip);
2682                 }
2683                 offset += descriptor_len;
2684
2685                 /* return descriptor */
2686                 descriptor_len = tvb_strsize(p_tvb, offset);
2687                 proto_tree_add_item(tree, hf_return_desc, p_tvb, offset,
2688                     descriptor_len, TRUE);
2689                 data_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
2690                 if (!pinfo->fd->flags.visited) {
2691                         /*
2692                          * Save the return descriptor for future use.
2693                          */
2694                         g_assert(trp->data_descrip == NULL);
2695                         trp->data_descrip = g_strdup(data_descrip);
2696                 }
2697                 offset += descriptor_len;
2698
2699                 lanman = find_lanman(cmd);
2700
2701                 /* request parameters */
2702                 start_offset = offset;
2703                 offset = dissect_request_parameters(p_tvb, offset, pinfo, tree,
2704                     param_descrip, lanman->req, &has_data);
2705
2706                 /* auxiliary data descriptor */
2707                 if (tvb_reported_length_remaining(p_tvb, offset) > 0){
2708                         /*
2709                          * There are more parameters left, so the next
2710                          * item is the auxiliary data descriptor.
2711                          */
2712                         descriptor_len = tvb_strsize(p_tvb, offset);
2713                         proto_tree_add_item(tree, hf_aux_data_desc, p_tvb, offset,
2714                             descriptor_len, TRUE);
2715                         aux_data_descrip = tvb_get_ptr(p_tvb, offset, descriptor_len);
2716                         if (!pinfo->fd->flags.visited) {
2717                                 /*
2718                                  * Save the auxiliary data descriptor for
2719                                  * future use.
2720                                  */
2721                                 g_assert(trp->aux_data_descrip == NULL);
2722                                 trp->aux_data_descrip =
2723                                     g_strdup(aux_data_descrip);
2724                         }
2725                         offset += descriptor_len;
2726                 }
2727
2728                 /* reset offset, we now start dissecting the data area */
2729                 offset = 0;
2730                 if (has_data && d_tvb && tvb_reported_length(d_tvb) != 0) {
2731                         /*
2732                          * There's a send buffer item in the descriptor
2733                          * string, and the data count in the transaction
2734                          * is non-zero, so there's data to dissect.
2735                          */
2736
2737                         if (lanman->req_data_item != NULL) {
2738                                 /*
2739                                  * Create a protocol tree item for the data.
2740                                  */
2741                                 data_item = (*lanman->req_data_item)(d_tvb,
2742                                     pinfo, tree, offset);
2743                                 data_tree = proto_item_add_subtree(data_item,
2744                                     *lanman->ett_req_data);
2745                         } else {
2746                                 /*
2747                                  * Just leave it at the top level.
2748                                  */
2749                                 data_item = NULL;
2750                                 data_tree = tree;
2751                         }
2752
2753                         /* data */
2754                         offset = dissect_transact_data(d_tvb, offset, -1,
2755                             pinfo, data_tree, data_descrip, lanman->req_data,
2756                             &aux_count);        /* XXX - what about strings? */
2757
2758                         /* auxiliary data */
2759                         if (aux_data_descrip != NULL) {
2760                                 for (i = 0; i < aux_count; i++) {
2761                                         offset = dissect_transact_data(d_tvb,
2762                                             offset, -1, pinfo, data_tree,
2763                                             aux_data_descrip,
2764                                             lanman->req_aux_data, NULL);
2765                                 }
2766                         }
2767
2768                         if (data_item != NULL) {
2769                                 /*
2770                                  * Set the length of the protocol tree item
2771                                  * for the data.
2772                                  */
2773                                 proto_item_set_len(data_item, offset);
2774                         }
2775                 }
2776         } else {
2777                 /*
2778                  * This is a response.
2779                  * Have we seen the request to which it's a response?
2780                  */
2781                 if (trp == NULL)
2782                         return FALSE;   /* no - can't dissect it */
2783
2784                 /* ok we have seen this one before */
2785
2786                 /* if it looks like an interim response, update COL_INFO and return */
2787                 if( ( (p_tvb==NULL) || (tvb_reported_length(p_tvb)==0) )
2788                 &&  ( (d_tvb==NULL) || (tvb_reported_length(d_tvb)==0) ) ){
2789                         /* command */
2790                         if (check_col(pinfo->cinfo, COL_INFO)) {
2791                                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Interim Response",
2792                                              val_to_str(trp->lanman_cmd, commands, "Unknown Command (%u)"));
2793                         }
2794                         proto_tree_add_uint(tree, hf_function_code, p_tvb, 0, 0, trp->lanman_cmd);
2795                         return TRUE;
2796                 }
2797
2798                 /* command */
2799                 if (check_col(pinfo->cinfo, COL_INFO)) {
2800                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s Response",
2801                                      val_to_str(trp->lanman_cmd, commands, "Unknown Command (%u)"));
2802                 }
2803                 proto_tree_add_uint(tree, hf_function_code, p_tvb, 0, 0,
2804                     trp->lanman_cmd);
2805
2806                 lanman = find_lanman(trp->lanman_cmd);
2807
2808                 /* response parameters */
2809
2810                 /* status */
2811                 status = tvb_get_letohs(p_tvb, offset);
2812                 proto_tree_add_uint(tree, hf_status, p_tvb, offset, 2, status);
2813                 offset += 2;
2814
2815                 /* convert */
2816                 convert = tvb_get_letohs(p_tvb, offset);
2817                 proto_tree_add_uint(tree, hf_convert, p_tvb, offset, 2, convert);
2818                 offset += 2;
2819
2820                 if (trp->param_descrip == NULL) {
2821                         /*
2822                          * This could happen if we only dissected
2823                          * part of the request to which this is a
2824                          * reply, e.g. if the request was split
2825                          * across TCP segments and we weren't doing
2826                          * TCP desegmentation, or if we had a snapshot
2827                          * length that was too short.
2828                          *
2829                          * We can't dissect the parameters; just show them
2830                          * as raw data.
2831                          */
2832                         proto_tree_add_text(tree, p_tvb, offset, -1,
2833                             "Parameters (no descriptor available)");
2834
2835                         /*
2836                          * We don't know whether we have a receive buffer,
2837                          * as we don't have the descriptor; just show what
2838                          * bytes purport to be data.
2839                          */
2840                         if (d_tvb && tvb_reported_length(d_tvb) > 0) {
2841                                 proto_tree_add_text(tree, d_tvb, 0, -1,
2842                                     "Data (no descriptor available)");
2843                         }
2844                 } else {
2845                         /* rest of the parameters */
2846