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