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